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_convert_irrlicht_mesh;
bool m_texture_compression; bool m_texture_compression;
std::unordered_set<std::string> m_ondemand_load_texture_paths; std::unordered_set<std::string> m_ondemand_load_texture_paths;
float m_render_scale;
}; };
void setVideoDriver(irr::video::IVideoDriver* driver); void setVideoDriver(irr::video::IVideoDriver* driver);

View File

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

View File

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

View File

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

View File

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

View File

@ -498,7 +498,8 @@ GEVulkanDriver::GEVulkanDriver(const SIrrlichtCreationParameters& params,
: CNullDriver(io, core::dimension2d<u32>(0, 0)), : CNullDriver(io, core::dimension2d<u32>(0, 0)),
m_params(params), m_irrlicht_device(device), m_params(params), m_irrlicht_device(device),
m_depth_texture(NULL), m_mesh_texture_descriptor(NULL), 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_vk.reset(new VK());
m_physical_device = VK_NULL_HANDLE; m_physical_device = VK_NULL_HANDLE;
@ -663,6 +664,11 @@ void GEVulkanDriver::destroyVulkan()
m_depth_texture->drop(); m_depth_texture->drop();
m_depth_texture = NULL; m_depth_texture = NULL;
} }
if (m_rtt_texture)
{
m_rtt_texture->drop();
m_rtt_texture = NULL;
}
if (m_white_texture) if (m_white_texture)
{ {
m_white_texture->drop(); m_white_texture->drop();
@ -1260,6 +1266,16 @@ found_mode:
m_depth_texture = new GEVulkanDepthTexture(this, m_depth_texture = new GEVulkanDepthTexture(this,
core::dimension2du(m_swap_chain_extent.width, core::dimension2du(m_swap_chain_extent.width,
m_swap_chain_extent.height)); 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 } // createSwapChain
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -1595,6 +1611,14 @@ bool GEVulkanDriver::beginScene(bool backBuffer, bool zBuffer, SColor color,
m_clear_color = color; m_clear_color = color;
PrimitivesDrawn = m_rtt_polycount; PrimitivesDrawn = m_rtt_polycount;
m_rtt_polycount = 0; 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; return true;
} // beginScene } // beginScene
@ -2107,9 +2131,9 @@ void GEVulkanDriver::getRotatedRect2D(VkRect2D* rect)
} // getRotatedRect2D } // 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; return;
VkRect2D rect; VkRect2D rect;
@ -2165,6 +2189,11 @@ void GEVulkanDriver::destroySwapChainRelated(bool handle_surface)
m_depth_texture->drop(); m_depth_texture->drop();
m_depth_texture = NULL; m_depth_texture = NULL;
} }
if (m_rtt_texture)
{
m_rtt_texture->drop();
m_rtt_texture = NULL;
}
for (VkFramebuffer& framebuffer : m_vk->swap_chain_framebuffers) for (VkFramebuffer& framebuffer : m_vk->swap_chain_framebuffers)
vkDestroyFramebuffer(m_vk->device, framebuffer, NULL); vkDestroyFramebuffer(m_vk->device, framebuffer, NULL);
m_vk->swap_chain_framebuffers.clear(); m_vk->swap_chain_framebuffers.clear();
@ -2247,13 +2276,24 @@ void GEVulkanDriver::buildCommandBuffers()
VkRenderPassBeginInfo render_pass_info = {}; VkRenderPassBeginInfo render_pass_info = {};
render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_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.clearValueCount = (uint32_t)(clear_values.size());
render_pass_info.pClearValues = &clear_values[0]; 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 = {}; VkCommandBufferBeginInfo begin_info = {};
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_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); p.second->render(this, p.first);
PrimitivesDrawn += p.second->getPolyCount(); 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(); GEVulkan2dRenderer::render();
vkCmdEndRenderPass(getCurrentCommandBuffer()); vkCmdEndRenderPass(getCurrentCommandBuffer());
@ -2319,7 +2371,8 @@ ITexture* GEVulkanDriver::addRenderTargetTexture(const core::dimension2d<u32>& s
const io::path& name, const ECOLOR_FORMAT format, const io::path& name, const ECOLOR_FORMAT format,
const bool useStencil) const bool useStencil)
{ {
GEVulkanFBOTexture* rtt = new GEVulkanFBOTexture(size, true/*create_depth*/); GEVulkanFBOTexture* rtt = new GEVulkanFBOTexture(this, size,
true/*create_depth*/);
rtt->createRTT(); rtt->createRTT();
return rtt; return rtt;
} // addRenderTargetTexture } // addRenderTargetTexture
@ -2329,9 +2382,21 @@ bool GEVulkanDriver::setRenderTarget(video::ITexture* texture,
bool clearBackBuffer, bool clearZBuffer, bool clearBackBuffer, bool clearZBuffer,
SColor color) SColor color)
{ {
m_rtt_texture = dynamic_cast<GEVulkanFBOTexture*>(texture); GEVulkanFBOTexture* new_rtt = dynamic_cast<GEVulkanFBOTexture*>(texture);
if (m_rtt_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_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; return true;
} // setRenderTarget } // setRenderTarget

View File

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

View File

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

View File

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