Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't replace shaders for incomplete pipeline libraries #3307

Merged
merged 1 commit into from
May 10, 2024

Conversation

w-pearson
Copy link
Contributor

Description

Before, when replacing shaders, RenderDoc would treat these incomplete pipeline libraries as if they were complete pipelines, and thus attempt to create pipelines with incomplete data, producing several validation errors and on some devices crashes.

For instance, a pipeline library that only contains a vertex or fragment shader but not input assembly state would use invalid input assembly state (specifically, VulkanShaderCache::MakeGraphicsPipelineInfo would use the topology value from VulkanCreationInfo::Pipeline, which is set to VK_PRIMITIVE_TOPOLOGY_MAX_ENUM (0x7fffffff) if the pipeline has no input assembly state by VulkanCreationInfo::Pipeline::Init).

Additionally, those pipeline libraries were treated as complete graphics pipelines, not libraries, as VulkanShaderCache::MakeGraphicsPipelineInfo removes VK_PIPELINE_CREATE_LIBRARY_BIT_KHR and no
VkGraphicsPipelineLibraryCreateInfoEXT was added to the pNext chain.

RenderDoc already merges the pipeline libraries into complete graphics pipelines, so there is no reason to recreate the libraries with modified shaders.

This change removes the following validation warnings after replacing a shader that draws a teapot on the graphics_pipeline_library Khronos sample:

RDOC 047012: [16:04:20]          vk_core.cpp(4738) - Warning - [VUID-VkPipelineInputAssemblyStateCreateInfo-topology-parameter] Validation Error: [ VUID-VkPipelineInputAssemblyStateCreateInfo-topology-parameter ] | MessageID = 0xb85b1e9b | vkCreateGraphicsPipelines(): pCreateInfos[0].pInputAssemblyState->topology (2147483647) does not fall within the begin..end range of the VkPrimitiveTopology enumeration tokens and is not an extension added token. The Vulkan spec states: topology must be a valid VkPrimitiveTopology value (https://vulkan.lunarg.com/doc/view/1.3.280.0/windows/1.3-extensions/vkspec.html#VUID-VkPipelineInputAssemblyStateCreateInfo-topology-parameter)
RDOC 047012: [16:04:20]          vk_core.cpp(4738) - Warning - [VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135] Validation Error: [ VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135 ] | MessageID = 0x405fe816 | vkCreateGraphicsPipelines(): pCreateInfos[0].pViewportState->viewportCount can't be 0 unless VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT is used. The Vulkan spec states: If the graphics pipeline is being created with VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT set then viewportCount must be 0, otherwise viewportCount must be greater than 0 (https://vulkan.lunarg.com/doc/view/1.3.280.0/windows/1.3-extensions/vkspec.html#VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135)
RDOC 047012: [16:04:20]          vk_core.cpp(4738) - Warning - [VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136] Validation Error: [ VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136 ] | MessageID = 0x6a5d7d30 | vkCreateGraphicsPipelines(): pCreateInfos[0].pViewportState->scissorCount can't be 0 unless VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT is used. The Vulkan spec states: If the graphics pipeline is being created with VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT set then scissorCount must be 0, otherwise scissorCount must be greater than 0 (https://vulkan.lunarg.com/doc/view/1.3.280.0/windows/1.3-extensions/vkspec.html#VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136)
RDOC 047012: [16:04:20]          vk_core.cpp(4738) - Warning - [VUID-VkGraphicsPipelineCreateInfo-pStages-06896] Validation Error: [ VUID-VkGraphicsPipelineCreateInfo-pStages-06896 ] | MessageID = 0x8ca1caba | vkCreateGraphicsPipelines(): pCreateInfos[0] contains pre-raster state, but stages (VK_SHADER_STAGE_FRAGMENT_BIT) does not contain any pre-raster shaders. The Vulkan spec states: If the pipeline requires pre-rasterization shader state, all elements of pStages must have a stage set to a shader stage which participates in fragment shader state or pre-rasterization shader state (https://vulkan.lunarg.com/doc/view/1.3.280.0/windows/1.3-extensions/vkspec.html#VUID-VkGraphicsPipelineCreateInfo-pStages-06896)
RDOC 047012: [16:04:20]          vk_core.cpp(4738) - Warning - [VUID-VkGraphicsPipelineCreateInfo-stage-02096] Validation Error: [ VUID-VkGraphicsPipelineCreateInfo-stage-02096 ] | MessageID = 0x733290e1 | vkCreateGraphicsPipelines(): pCreateInfos[0] no stage in pStages contains a Vertex Shader or Mesh Shader. The Vulkan spec states: If the pipeline requires pre-rasterization shader state the stage member of one element of pStages must be VK_SHADER_STAGE_VERTEX_BIT or VK_SHADER_STAGE_MESH_BIT_EXT (https://vulkan.lunarg.com/doc/view/1.3.280.0/windows/1.3-extensions/vkspec.html#VUID-VkGraphicsPipelineCreateInfo-stage-02096)
RDOC 047012: [16:04:20]          vk_core.cpp(4738) - Warning - [VUID-VkGraphicsPipelineCreateInfo-renderPass-07609] Validation Error: [ VUID-VkGraphicsPipelineCreateInfo-renderPass-07609 ] | MessageID = 0x583c7182 | vkCreateGraphicsPipelines(): pCreateInfos[0].pColorBlendState->attachmentCount (0) is different than VkRenderPass 0x972ee40000000265[] pSubpasses[0].colorAttachmentCount (1). The Vulkan spec states: If renderPass is not VK_NULL_HANDLE, and the pipeline is being created with fragment output interface state, and the pColorBlendState pointer is not NULL, and the subpass uses color attachments, the attachmentCount member of pColorBlendState must be equal to the colorAttachmentCount used to create subpass (https://vulkan.lunarg.com/doc/view/1.3.280.0/windows/1.3-extensions/vkspec.html#VUID-VkGraphicsPipelineCreateInfo-renderPass-07609)

The Vulkan spec is a bit ambiguous about whether a topology of VK_PRIMITIVE_TOPOLOGY_MAX_ENUM is ever legal. A pipeline library without VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT passes VUID-VkGraphicsPipelineCreateInfo-dynamicPrimitiveTopologyUnrestricted-09031 so pInputAssemblyState can be null, but if it is not null then VUID-VkGraphicsPipelineCreateInfo-pInputAssemblyState-09032 says it needs to be valid. But the members section says that pInputAssemblyState "is ignored if the pipeline includes a mesh shader stage", not just "can be null". The description section says that members being null "is optional so the application can still use a valid pointer if it needs to set the pNext or flags fields to specify state for other extensions".

In practice, as of Vulkan SDK 1.3.280.0, it seems like the validation layers do not care about invalid topologies in pInputAssemblyState for a pipeline library without the vertex input interface bit or for pipelines containing mesh shaders (tested with the mesh_shading Khronos sample). I didn't try to test the extended_dynamic_state3 case as none of the Khronos samples use dynamicPrimitiveTopologyUnrestricted. Even with this PR, renderdoc does still create a pipeline with an invalid topology when editing a shader in a pipeline with mesh shaders, but the validation layers don't care; I suspect the same thing happens with extended_dynamic_state3.

An alternative implementation of this PR that re-created pipeline libraries with the appropriate flags would also pass the validation layers, but is more awkward to implement (especially since prior to Vulkan 1.3.260, VkGraphicsPipelineLibraryCreateInfoEXT::pNext was a non-const pointer, which means const_cast is needed for inserting it to the pNext chain). Another alternative option would be to only set pInputAssemblyState if the original pInputAssemblyState was non-null, but that is quite messy when applied to the other fields too.

Before, RenderDoc would treat these incomplete pipeline libraries as if
they were complete pipelines, and thus attempt to create pipelines with
incomplete data, producing several validation errors and on some devices
crashes.

For instance, a pipeline library that only contains a vertex or fragment
shader but not input assembly state would use invalid input assembly
state (specifically, VulkanShaderCache::MakeGraphicsPipelineInfo would
use the topology value from VulkanCreationInfo::Pipeline, which is set
to VK_PRIMITIVE_TOPOLOGY_MAX_ENUM (0x7fffffff) if the pipeline has no
input assembly state by VulkanCreationInfo::Pipeline::Init).

Additionally, those pipeline libraries were treated as complete graphics
pipelines, not libraries, as VulkanShaderCache::MakeGraphicsPipelineInfo
removes VK_PIPELINE_CREATE_LIBRARY_BIT_KHR and no
VkGraphicsPipelineLibraryCreateInfoEXT was added to the pNext chain.

RenderDoc already merges the pipeline libraries into complete graphics
pipelines, so there is no reason to recreate the libraries with modified
shaders.
@baldurk
Copy link
Owner

baldurk commented May 10, 2024

Good catch, indeed by the time we get to replaying we've "baked" down any libraries into their final PSOs so patching the shaders in these component libraries is not necessary.

Even with this PR, renderdoc does still create a pipeline with an invalid topology when editing a shader in a pipeline with mesh shaders, but the validation layers don't care; I suspect the same thing happens with extended_dynamic_state3.

This should be covered by the VU you quoted which states that input assembly is ignored entirely if mesh shaders are present. Unfortunately the vulkan convention is that pointers that aren't used can be garbage not just can be NULL, so implementations and validation can't even read from it to see what the topology is. I think VUID-VkGraphicsPipelineCreateInfo-pInputAssemblyState-09032 probably isn't properly accounting for mesh shaders and I don't think it was intended to require a non-NULL pointer.

@baldurk baldurk merged commit 3b2bb46 into baldurk:v1.x May 10, 2024
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants