mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-11-07 22:43:49 +00:00
Work around NV issue with dynamic state setting & rebinding pipeline
This commit is contained in:
5 files changed
+55
-1
No files matched your search
@@ -1057,6 +1057,17 @@ VkDriverInfo::VkDriverInfo(const VkPhysicalDeviceProperties &physProps,
|
||||
RDCLOG("Enabling NV texel fetch workaround - update to a newer driver for fix");
|
||||
texelFetchBrokenDriver = true;
|
||||
}
|
||||
|
||||
// this isn't exactly when the root problem started happening, but it is when it started
|
||||
// happening in a way that was easy to notice. In this version NV applied a optimisation
|
||||
// to not re-set static pipeline state when a renderpass was begun, which was previously
|
||||
// hiding the issue by conservatively re-setting the state.
|
||||
if(Major() > 532)
|
||||
{
|
||||
if(active)
|
||||
RDCLOG("Enabling NV workaround for static pipeline force-bind to preserve state");
|
||||
nvidiaStaticPipelineRebindStates = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(driverProps.driverID == VK_DRIVER_ID_AMD_PROPRIETARY ||
|
||||
|
||||
@@ -285,6 +285,13 @@ public:
|
||||
// on Intel, occlusion queries are broken unless the shader has some effects. When we don't want
|
||||
// it to have visible effects during pixel history we have to insert some manual side-effects
|
||||
bool IntelBrokenOcclusionQueries() const { return intelBrokenOcclusionQueries; }
|
||||
// on NV binding a static pipeline does not re-set static state which may have been perturbed by
|
||||
// dynamic state setting, if the previous bound pipeline was identical.
|
||||
// to work around this, whenever we are setting state and we do not have a pipeline to bind, we
|
||||
// bind a dummy pipeline to ensure the pipeline always changes when we are setting dynamic state.
|
||||
// If we do have a pipeline to bind, we should never be perturbing dynamic state in between static
|
||||
// pipeline binds.
|
||||
bool NVStaticPipelineRebindStates() const { return nvidiaStaticPipelineRebindStates; }
|
||||
private:
|
||||
GPUVendor m_Vendor;
|
||||
|
||||
@@ -299,6 +306,7 @@ private:
|
||||
bool qualcommDrefNon2DCompileCrash = false;
|
||||
bool qualcommLineWidthCrash = false;
|
||||
bool intelBrokenOcclusionQueries = false;
|
||||
bool nvidiaStaticPipelineRebindStates = false;
|
||||
};
|
||||
|
||||
enum
|
||||
|
||||
@@ -98,7 +98,8 @@ static void create(WrappedVulkan *driver, const char *objName, const int line,
|
||||
}
|
||||
|
||||
pipeLayoutInfo.pSetLayouts = &setLayout;
|
||||
pipeLayoutInfo.setLayoutCount = 1;
|
||||
if(setLayout != VK_NULL_HANDLE)
|
||||
pipeLayoutInfo.setLayoutCount = 1;
|
||||
|
||||
VkResult vkr = driver->vkCreatePipelineLayout(driver->GetDev(), &pipeLayoutInfo, NULL, pipeLayout);
|
||||
if(vkr != VK_SUCCESS)
|
||||
@@ -708,6 +709,28 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver)
|
||||
|
||||
if(RenderDoc::Inst().IsReplayApp())
|
||||
{
|
||||
CREATE_OBJECT(m_DummyPipelineLayout, VK_NULL_HANDLE, 0);
|
||||
|
||||
ConciseGraphicsPipeline dummyPipeInfo = {
|
||||
VK_NULL_HANDLE,
|
||||
m_DummyPipelineLayout,
|
||||
shaderCache->GetBuiltinModule(BuiltinShader::BlitVS),
|
||||
shaderCache->GetBuiltinModule(BuiltinShader::FixedColFS),
|
||||
{},
|
||||
VK_SAMPLE_COUNT_1_BIT,
|
||||
false, // sampleRateShading
|
||||
false, // depthEnable
|
||||
false, // stencilEnable
|
||||
VK_STENCIL_OP_REPLACE,
|
||||
false, // colourOutput
|
||||
false, // blendEnable
|
||||
VK_BLEND_FACTOR_ONE,
|
||||
VK_BLEND_FACTOR_ZERO,
|
||||
0x0, // writeMask
|
||||
};
|
||||
|
||||
CREATE_OBJECT(m_DummyPipeline, dummyPipeInfo);
|
||||
|
||||
VkDescriptorPoolSize descPoolTypes[] = {
|
||||
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, ARRAY_COUNT(m_DiscardSet)},
|
||||
};
|
||||
@@ -803,6 +826,9 @@ VulkanDebugManager::~VulkanDebugManager()
|
||||
m_pDriver->vkDestroyPipeline(dev, m_MS2BufferPipe, NULL);
|
||||
m_pDriver->vkDestroyPipeline(dev, m_DepthMS2BufferPipe, NULL);
|
||||
|
||||
m_pDriver->vkDestroyPipelineLayout(dev, m_DummyPipelineLayout, NULL);
|
||||
m_pDriver->vkDestroyPipeline(dev, m_DummyPipeline, NULL);
|
||||
|
||||
m_pDriver->vkDestroyDescriptorPool(dev, m_DiscardPool, NULL);
|
||||
m_pDriver->vkDestroyPipelineLayout(dev, m_DiscardLayout, NULL);
|
||||
m_pDriver->vkDestroyDescriptorSetLayout(dev, m_DiscardSetLayout, NULL);
|
||||
|
||||
@@ -80,6 +80,7 @@ public:
|
||||
VkDeviceMemory GetReadbackMemory() { return m_ReadbackWindow.mem; }
|
||||
VkPipelineCache GetPipelineCache() { return m_PipelineCache; }
|
||||
VkPipeline GetCustomPipeline() { return m_Custom.TexPipeline; }
|
||||
VkPipeline GetDummyPipeline() { return m_DummyPipeline; }
|
||||
VkImage GetCustomTexture() { return m_Custom.TexImg; }
|
||||
VkFramebuffer GetCustomFramebuffer() { return m_Custom.TexFB; }
|
||||
VkRenderPass GetCustomRenderpass() { return m_Custom.TexRP; }
|
||||
@@ -145,6 +146,10 @@ private:
|
||||
VkImage m_DummyStencilImage = {VK_NULL_HANDLE};
|
||||
VkImageView m_DummyStencilView = {VK_NULL_HANDLE};
|
||||
|
||||
// dummy pipeline
|
||||
VkPipelineLayout m_DummyPipelineLayout;
|
||||
VkPipeline m_DummyPipeline;
|
||||
|
||||
// one per depth/stencil output format, per sample count
|
||||
VkPipeline m_DepthArray2MSPipe[7][4] = {{VK_NULL_HANDLE}};
|
||||
|
||||
|
||||
@@ -326,6 +326,10 @@ void VulkanRenderState::BindPipeline(WrappedVulkan *vk, VkCommandBuffer cmd,
|
||||
}
|
||||
else if(binding == BindInitial)
|
||||
{
|
||||
if(vk->GetDriverInfo().NVStaticPipelineRebindStates())
|
||||
ObjDisp(cmd)->CmdBindPipeline(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
Unwrap(vk->GetDebugManager()->GetDummyPipeline()));
|
||||
|
||||
// if we're setting up a partial command buffer, bind all dynamic state we have. This will
|
||||
// then get overridden, but we need it in case a pipeline expects to inherit some dynamic
|
||||
// state from earlier in the command buffer but there's no pipeline bound yet.
|
||||
|
||||
Reference in new issue
Block a user