Skip to content

Commit

Permalink
Vulkan: Reduce the amount of redundant stencil parameter sets
Browse files Browse the repository at this point in the history
  • Loading branch information
hrydgard committed Aug 12, 2019
1 parent cf06b4a commit ddb5208
Showing 1 changed file with 22 additions and 6 deletions.
28 changes: 22 additions & 6 deletions ext/native/thin3d/VulkanQueueRunner.cpp
Expand Up @@ -869,9 +869,11 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c


auto &commands = step.commands; auto &commands = step.commands;


// TODO: Dynamic state commands (SetViewport, SetScissor, SetBlendConstants, SetStencil*) are only // We can do a little bit of state tracking here to eliminate some calls into the driver.
// valid when a pipeline is bound with those as dynamic state. So we need to add some state tracking here // The stencil ones are very commonly mostly redundant so let's eliminate them where possible.
// for this to be correct. This is a bit of a pain but also will let us eliminate redundant calls. int lastStencilWriteMask = -1;
int lastStencilCompareMask = -1;
int lastStencilReference = -1;


for (const auto &c : commands) { for (const auto &c : commands) {
switch (c.cmd) { switch (c.cmd) {
Expand All @@ -882,6 +884,10 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
if (c.pipeline.pipeline != lastPipeline) { if (c.pipeline.pipeline != lastPipeline) {
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, c.pipeline.pipeline); vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, c.pipeline.pipeline);
lastPipeline = c.pipeline.pipeline; lastPipeline = c.pipeline.pipeline;
// Reset dynamic state so it gets refreshed with the new pipeline.
lastStencilWriteMask = -1;
lastStencilCompareMask = -1;
lastStencilReference = -1;
} }
break; break;


Expand All @@ -902,9 +908,18 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
break; break;


case VKRRenderCommand::STENCIL: case VKRRenderCommand::STENCIL:
vkCmdSetStencilWriteMask(cmd, VK_STENCIL_FRONT_AND_BACK, c.stencil.stencilWriteMask); if (lastStencilReference != c.stencil.stencilWriteMask) {
vkCmdSetStencilCompareMask(cmd, VK_STENCIL_FRONT_AND_BACK, c.stencil.stencilCompareMask); lastStencilReference = (int)c.stencil.stencilWriteMask;
vkCmdSetStencilReference(cmd, VK_STENCIL_FRONT_AND_BACK, c.stencil.stencilRef); vkCmdSetStencilWriteMask(cmd, VK_STENCIL_FRONT_AND_BACK, c.stencil.stencilWriteMask);
}
if (lastStencilCompareMask != c.stencil.stencilCompareMask) {
lastStencilCompareMask = c.stencil.stencilCompareMask;
vkCmdSetStencilCompareMask(cmd, VK_STENCIL_FRONT_AND_BACK, c.stencil.stencilCompareMask);
}
if (lastStencilReference != c.stencil.stencilRef) {
lastStencilReference = c.stencil.stencilRef;
vkCmdSetStencilReference(cmd, VK_STENCIL_FRONT_AND_BACK, c.stencil.stencilRef);
}
break; break;


case VKRRenderCommand::DRAW_INDEXED: case VKRRenderCommand::DRAW_INDEXED:
Expand All @@ -924,6 +939,7 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c


case VKRRenderCommand::CLEAR: case VKRRenderCommand::CLEAR:
{ {
// If we get here, we failed to merge a clear into a render pass load op. This is bad for perf.
int numAttachments = 0; int numAttachments = 0;
VkClearRect rc{}; VkClearRect rc{};
rc.baseArrayLayer = 0; rc.baseArrayLayer = 0;
Expand Down

0 comments on commit ddb5208

Please sign in to comment.