vulkan: improve render pass performance

Before this patch some common patterns would lead to very suboptimal
render passes.
Consider the following code:
```lua
local canvas = love.graphics.newCanvas(...)

function love.draw()
    love.graphics.setCanvas(canvas)
    love.graphics.clear(...)
    love.graphics.draw(...)
    love.graphics.setCanvas()

    love.graphics.draw(canvas)
end
```
This would lead to the following rendering:
1) render pass on main window with loadOp=load, followed by an immediate
    call to vkCmdClearAttachments
2) render pass on canvas with loadOp=load, followed by an immediate call
    to vkCmdClearAttachments
3) render pass on main window with loadOp=load

This patch changes the behaviour to the more performant
(and equivalent) version:
1) render pass on canvas with loadOp=clear
2) render pass on main window with loadOp=clear

This is especially helpful on mobile devices, where creating render
passes is an expensive operation.
This commit is contained in:
niki
2023-02-11 20:06:19 +01:00
parent 9f452474c7
commit 094d6e39d1
2 changed files with 241 additions and 136 deletions
+29 -6
View File
@@ -46,27 +46,43 @@ namespace graphics
namespace vulkan
{
struct RenderPassAttachment
struct ColorAttachment
{
VkFormat format = VK_FORMAT_UNDEFINED;
bool discard = true;
VkAttachmentLoadOp loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
VkSampleCountFlagBits msaaSamples = VK_SAMPLE_COUNT_1_BIT;
bool operator==(const RenderPassAttachment &attachment) const
bool operator==(const ColorAttachment&attachment) const
{
return format == attachment.format &&
discard == attachment.discard &&
loadOp == attachment.loadOp &&
msaaSamples == attachment.msaaSamples;
}
};
struct DepthStencilAttachment
{
VkFormat format = VK_FORMAT_UNDEFINED;
VkAttachmentLoadOp depthLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
VkAttachmentLoadOp stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
VkSampleCountFlagBits msaaSamples = VK_SAMPLE_COUNT_1_BIT;
bool operator==(const DepthStencilAttachment &attachment) const
{
return format == attachment.format &&
depthLoadOp == attachment.depthLoadOp &&
stencilLoadOp == attachment.stencilLoadOp &&
msaaSamples == attachment.msaaSamples;
}
};
struct RenderPassConfiguration
{
std::vector<RenderPassAttachment> colorAttachments;
std::vector<ColorAttachment> colorAttachments;
struct StaticRenderPassConfiguration
{
RenderPassAttachment depthAttachment;
DepthStencilAttachment depthStencilAttachment;
bool resolve = false;
} staticData;
@@ -216,6 +232,7 @@ struct RenderpassState
{
bool active = false;
VkRenderPassBeginInfo beginInfo{};
bool isWindow = false;
bool useConfigurations = false;
RenderPassConfiguration renderPassConfiguration{};
FramebufferConfiguration framebufferConfiguration{};
@@ -225,6 +242,12 @@ struct RenderpassState
float width = 0.0f;
float height = 0.0f;
VkSampleCountFlagBits msaa = VK_SAMPLE_COUNT_1_BIT;
std::vector<VkClearValue> clearColors;
bool windowClearRequested = false;
OptionalColorD mainWindowClearColorValue;
OptionalDouble mainWindowClearDepthValue;
OptionalInt mainWindowClearStencilValue;
};
struct ScreenshotReadbackBuffer