Add render scale support in vulkan

This commit is contained in:
Benau 2022-08-27 12:49:17 +08:00
parent 97e5064535
commit d31281cb6f
9 changed files with 105 additions and 23 deletions

View File

@ -17,6 +17,7 @@ bool m_disable_npot_texture;
bool m_convert_irrlicht_mesh;
bool m_texture_compression;
std::unordered_set<std::string> m_ondemand_load_texture_paths;
float m_render_scale;
};
void setVideoDriver(irr::video::IVideoDriver* driver);

View File

@ -324,7 +324,7 @@ namespace GE
video::ITexture* getTransparentTexture() const
{ return m_transparent_texture; }
void getRotatedRect2D(VkRect2D* rect);
void getRotatedViewport(VkViewport* vp);
void getRotatedViewport(VkViewport* vp, bool handle_rtt);
const core::matrix4& getPreRotationMatrix()
{ return m_pre_rotation_matrix; }
virtual void pauseRendering();
@ -353,6 +353,8 @@ namespace GE
GEVulkanTextureDescriptor* getMeshTextureDescriptor() const
{ return m_mesh_texture_descriptor; }
GEVulkanFBOTexture* getRTTTexture() const { return m_rtt_texture; }
GEVulkanFBOTexture* getSeparateRTTTexture() const
{ return m_separate_rtt_texture; }
void handleDeletedTextures();
void addRTTPolyCount(unsigned count) { m_rtt_polycount += count; }
private:
@ -493,6 +495,8 @@ namespace GE
GEVulkanDepthTexture* m_depth_texture;
GEVulkanTextureDescriptor* m_mesh_texture_descriptor;
GEVulkanFBOTexture* m_rtt_texture;
GEVulkanFBOTexture* m_prev_rtt_texture;
GEVulkanFBOTexture* m_separate_rtt_texture;
u32 m_rtt_polycount;
void createInstance(SDL_Window* window);

View File

@ -6,7 +6,14 @@
namespace GE
{
irr::video::IVideoDriver* g_driver = NULL;
GEConfig g_config = {};
GEConfig g_config =
{
false,
false,
false,
{},
1.0f
};
std::string g_shader_folder = "";
std::chrono::steady_clock::time_point g_mono_start =
std::chrono::steady_clock::now();

View File

@ -309,7 +309,7 @@ void GEVulkan2dRenderer::render()
vp.height = g_vk->getViewPort().getHeight();
vp.minDepth = 0;
vp.maxDepth = 1.0f;
g_vk->getRotatedViewport(&vp);
g_vk->getRotatedViewport(&vp, false/*handle_rtt*/);
vkCmdSetViewport(g_vk->getCurrentCommandBuffer(), 0, 1, &vp);
if (GEVulkanFeatures::supportsBindTexturesAtOnce())

View File

@ -959,13 +959,16 @@ void GEVulkanDrawCall::render(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam,
}
VkViewport vp;
vp.x = cam->getViewPort().UpperLeftCorner.X;
vp.y = cam->getViewPort().UpperLeftCorner.Y;
vp.width = cam->getViewPort().getWidth();
vp.height = cam->getViewPort().getHeight();
float scale = getGEConfig()->m_render_scale;
if (vk->getSeparateRTTTexture())
scale = 1.0f;
vp.x = cam->getViewPort().UpperLeftCorner.X * scale;
vp.y = cam->getViewPort().UpperLeftCorner.Y * scale;
vp.width = cam->getViewPort().getWidth() * scale;
vp.height = cam->getViewPort().getHeight() * scale;
vp.minDepth = 0;
vp.maxDepth = 1.0f;
vk->getRotatedViewport(&vp);
vk->getRotatedViewport(&vp, true/*handle_rtt*/);
vkCmdSetViewport(cmd, 0, 1, &vp);
VkRect2D scissor;

View File

@ -498,7 +498,8 @@ GEVulkanDriver::GEVulkanDriver(const SIrrlichtCreationParameters& params,
: CNullDriver(io, core::dimension2d<u32>(0, 0)),
m_params(params), m_irrlicht_device(device),
m_depth_texture(NULL), m_mesh_texture_descriptor(NULL),
m_rtt_texture(NULL), m_rtt_polycount(0)
m_rtt_texture(NULL), m_prev_rtt_texture(NULL),
m_separate_rtt_texture(NULL), m_rtt_polycount(0)
{
m_vk.reset(new VK());
m_physical_device = VK_NULL_HANDLE;
@ -663,6 +664,11 @@ void GEVulkanDriver::destroyVulkan()
m_depth_texture->drop();
m_depth_texture = NULL;
}
if (m_rtt_texture)
{
m_rtt_texture->drop();
m_rtt_texture = NULL;
}
if (m_white_texture)
{
m_white_texture->drop();
@ -1260,6 +1266,16 @@ found_mode:
m_depth_texture = new GEVulkanDepthTexture(this,
core::dimension2du(m_swap_chain_extent.width,
m_swap_chain_extent.height));
const float scale = getGEConfig()->m_render_scale;
if (scale != 1.0f)
{
core::dimension2du screen_size = ScreenSize;
screen_size.Width *= scale;
screen_size.Height *= scale;
m_rtt_texture = new GEVulkanFBOTexture(this, screen_size,
true/*create_depth*/);
m_rtt_texture->createRTT();
}
} // createSwapChain
// ----------------------------------------------------------------------------
@ -1595,6 +1611,14 @@ bool GEVulkanDriver::beginScene(bool backBuffer, bool zBuffer, SColor color,
m_clear_color = color;
PrimitivesDrawn = m_rtt_polycount;
m_rtt_polycount = 0;
if (m_rtt_texture)
{
draw2DImage(m_rtt_texture,core::recti(0, 0,
ScreenSize.Width, ScreenSize.Height),
core::recti(0, 0,
m_rtt_texture->getSize().Width, m_rtt_texture->getSize().Height));
}
return true;
} // beginScene
@ -2107,9 +2131,9 @@ void GEVulkanDriver::getRotatedRect2D(VkRect2D* rect)
} // getRotatedRect2D
// ----------------------------------------------------------------------------
void GEVulkanDriver::getRotatedViewport(VkViewport* vp)
void GEVulkanDriver::getRotatedViewport(VkViewport* vp, bool handle_rtt)
{
if (m_rtt_texture)
if (handle_rtt && m_rtt_texture)
return;
VkRect2D rect;
@ -2165,6 +2189,11 @@ void GEVulkanDriver::destroySwapChainRelated(bool handle_surface)
m_depth_texture->drop();
m_depth_texture = NULL;
}
if (m_rtt_texture)
{
m_rtt_texture->drop();
m_rtt_texture = NULL;
}
for (VkFramebuffer& framebuffer : m_vk->swap_chain_framebuffers)
vkDestroyFramebuffer(m_vk->device, framebuffer, NULL);
m_vk->swap_chain_framebuffers.clear();
@ -2247,13 +2276,24 @@ void GEVulkanDriver::buildCommandBuffers()
VkRenderPassBeginInfo render_pass_info = {};
render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
render_pass_info.renderPass = getRenderPass();
render_pass_info.framebuffer =
getSwapChainFramebuffers()[getCurrentImageIndex()];
render_pass_info.renderArea.offset = {0, 0};
render_pass_info.renderArea.extent = getSwapChainExtent();
render_pass_info.clearValueCount = (uint32_t)(clear_values.size());
render_pass_info.pClearValues = &clear_values[0];
render_pass_info.renderArea.offset = {0, 0};
if (m_rtt_texture)
{
render_pass_info.renderPass = m_rtt_texture->getRTTRenderPass();
render_pass_info.framebuffer = m_rtt_texture->getRTTFramebuffer();
render_pass_info.renderArea.extent = { m_rtt_texture->getSize().Width,
m_rtt_texture->getSize().Height };
}
else
{
render_pass_info.renderPass = getRenderPass();
render_pass_info.framebuffer =
getSwapChainFramebuffers()[getCurrentImageIndex()];
render_pass_info.renderArea.extent = getSwapChainExtent();
}
VkCommandBufferBeginInfo begin_info = {};
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
@ -2280,6 +2320,18 @@ void GEVulkanDriver::buildCommandBuffers()
p.second->render(this, p.first);
PrimitivesDrawn += p.second->getPolyCount();
}
if (m_rtt_texture)
{
vkCmdEndRenderPass(getCurrentCommandBuffer());
render_pass_info.renderPass = getRenderPass();
render_pass_info.framebuffer =
getSwapChainFramebuffers()[getCurrentImageIndex()];
render_pass_info.renderArea.extent = getSwapChainExtent();
vkCmdBeginRenderPass(getCurrentCommandBuffer(), &render_pass_info,
VK_SUBPASS_CONTENTS_INLINE);
}
GEVulkan2dRenderer::render();
vkCmdEndRenderPass(getCurrentCommandBuffer());
@ -2319,7 +2371,8 @@ ITexture* GEVulkanDriver::addRenderTargetTexture(const core::dimension2d<u32>& s
const io::path& name, const ECOLOR_FORMAT format,
const bool useStencil)
{
GEVulkanFBOTexture* rtt = new GEVulkanFBOTexture(size, true/*create_depth*/);
GEVulkanFBOTexture* rtt = new GEVulkanFBOTexture(this, size,
true/*create_depth*/);
rtt->createRTT();
return rtt;
} // addRenderTargetTexture
@ -2329,9 +2382,21 @@ bool GEVulkanDriver::setRenderTarget(video::ITexture* texture,
bool clearBackBuffer, bool clearZBuffer,
SColor color)
{
m_rtt_texture = dynamic_cast<GEVulkanFBOTexture*>(texture);
if (m_rtt_texture)
GEVulkanFBOTexture* new_rtt = dynamic_cast<GEVulkanFBOTexture*>(texture);
if (m_separate_rtt_texture == new_rtt)
return true;
m_separate_rtt_texture = new_rtt;
if (m_separate_rtt_texture)
{
m_rtt_clear_color = color;
m_prev_rtt_texture = m_rtt_texture;
m_rtt_texture = m_separate_rtt_texture;
}
else
{
m_rtt_texture = m_prev_rtt_texture;
m_prev_rtt_texture = NULL;
}
return true;
} // setRenderTarget

View File

@ -9,11 +9,12 @@
namespace GE
{
GEVulkanFBOTexture::GEVulkanFBOTexture(const core::dimension2d<u32>& size,
GEVulkanFBOTexture::GEVulkanFBOTexture(GEVulkanDriver* vk,
const core::dimension2d<u32>& size,
bool create_depth)
: GEVulkanTexture()
{
m_vk = getVKDriver();
m_vk = vk;
m_vulkan_device = m_vk->getDevice();
m_image = VK_NULL_HANDLE;
m_vma_allocation = VK_NULL_HANDLE;

View File

@ -16,7 +16,8 @@ private:
VkFramebuffer m_rtt_frame_buffer;
public:
// ------------------------------------------------------------------------
GEVulkanFBOTexture(const core::dimension2d<u32>& size, bool create_depth);
GEVulkanFBOTexture(GEVulkanDriver* vk, const core::dimension2d<u32>& size,
bool create_depth);
// ------------------------------------------------------------------------
virtual ~GEVulkanFBOTexture();
// ------------------------------------------------------------------------

View File

@ -214,7 +214,7 @@ void GEVulkanSceneManager::drawAll(irr::u32 flags)
{
drawAllInternal();
GEVulkanDriver* vk = static_cast<GEVulkanDriver*>(getVideoDriver());
GEVulkanFBOTexture* rtt = vk->getRTTTexture();
GEVulkanFBOTexture* rtt = vk->getSeparateRTTTexture();
if (!rtt)
return;