VulkanSceneGraph
VulkanSceneGraph copied to clipboard
vkCmdPushConstants() in MatrixStack::record() can sometimes cause Vulkan validation-error VUID-01795
Describe the bug
TLDR: Minimal repro code https://github.com/drywolf/vsg-View-vkCmdPushConstants-bug (see vsg-View-PushConst-bug-minimal.cpp)
Some context:
- in our VulkanSceneGraph production code, we are rendering off-screen (without a vsg::Window)
- our renderer uses just one single vsg::CommandGraph to record/submit all of our Vulkan drawing/commands
- we are using multiple vsg::RenderGraphs that are children to this vsg::CommandGraph
- some of the vsg::RenderGraphs are rendering 3D scenes/geometry
- these passes are making use of vsg::View/vsg::Camera/vsg::MatrixTransform/etc.
- (very similar to the code in vsgExamples / vsgXchange-assimp)
- and some other vsg::RenderGraphs are simply rendering a Fullscreen triangle/a Fullscreen GLSL shader
- each of those passes is using its own individual vsg::Framebuffer+ vsg::Image attachments
- typically the fullscreen-shaders are reading from a GLSL
sampler2D
and are writing to the bound vsg::Image attachments - (e.g. for doing color-effects on previously rendered RGBA images of a scene)
The Bug:
Recently we have found that under some circumstances in our app, we are getting VUID-vkCmdPushConstants-offset-01795 Vulkan validation-errors. It took some debugging into the VulkanSceneGraph code itself to figure out what was causing it. We are rendering Fullscreen-Passes using pretty much the exact same VSG mechanisms & C++ classes that are otherwise used for the 3D scene rendering. Because of that, when VSG encounters our Fullscreen-Passes, it also calls the following code:
-
void RecordTraversal::apply(const Command& command)
(source)
As long as our Fullscreen-Shaders did not use any Push-Constants, the check for if (pipeline == 0 || stageFlags == 0)
prevented the vkCmdPushConstants()
call for the projection & model-view matrices from happening.
But recently we added a Fullscreen-Pass that was using Push-Constants to pass a single vsg::vec4
to the fullscreen-shader.
In this case we started seeing the VUID-vkCmdPushConstants-offset-01795
validation error.
VUID-vkCmdPushConstants-offset-01795(ERROR / SPEC): msgNum: 666667206 - Validation Error: [ VUID-vkCmdPushConstants-offset-01795 ] Object 0: handle = 0x1ea94cfd920, type = VK_OBJECT_TYPE_COMMAND_BUFFER; | MessageID = 0x27bc88c6 | vkCmdPushConstants(): VK_SHADER_STAGE_FRAGMENT_BIT, VkPushConstantRange in VkPipelineLayout 0x84c0580000000017[] overlapping offset = 0 and size = 64, do not contain VK_SHADER_STAGE_FRAGMENT_BIT. The Vulkan spec states: For each byte in the range specified by offset and size and for each shader stage in stageFlags, there must be a push constant range in layout that includes that byte and that stage (https://vulkan.lunarg.com/doc/view/1.3.250.0/windows/1.3-extensions/vkspec.html#VUID-vkCmdPushConstants-offset-01795)
Objects: 1
[0] 0x1ea94cfd920, type: 6, name: NULL
VUID-vkCmdPushConstants-offset-01795(ERROR / SPEC): msgNum: 666667206 - Validation Error: [ VUID-vkCmdPushConstants-offset-01795 ] Object 0: handle = 0x1ea94cfd920, type = VK_OBJECT_TYPE_COMMAND_BUFFER; | MessageID = 0x27bc88c6 | vkCmdPushConstants(): VK_SHADER_STAGE_FRAGMENT_BIT, VkPushConstantRange in VkPipelineLayout 0x84c0580000000017[] overlapping offset = 64 and size = 64, do not contain VK_SHADER_STAGE_FRAGMENT_BIT. The Vulkan spec states: For each byte in the range specified by offset and size and for each shader stage in stageFlags, there must be a push constant range in layout that includes that byte and that stage (https://vulkan.lunarg.com/doc/view/1.3.250.0/windows/1.3-extensions/vkspec.html#VUID-vkCmdPushConstants-offset-01795)
Objects: 1
[0] 0x1ea94cfd920, type: 6, name: NULL
PS: the vsg::Commands
overload of void RecordTraversal::apply()
is calling into exactly the same function-callstack as shown above.
(it can lead to the exact same problem)
To Reproduce
Steps to reproduce the behavior:
- clone the GIT repo containing the bug-repro code
- https://github.com/drywolf/vsg-View-vkCmdPushConstants-bug
- configure and build the code
- see the README.md and/or
BugScenario
code invsg-View-PushConst-bug.cpp
- run the
vsg-View-PushConst-bug.exe
executable - see Vulkan validation errors
VUID-01795
in console- also in some scenarios you will experience a crash
Expected behavior
- the
vkCmdPushConstants()
inMatrixStack::record()
should only be called when actively requested/configured- in other words: the 2x
mat4
push-constants that are used specifically only for the VSG pbr/phong/flat shaders, should only be set when one of these shader-sets is currently active
- in other words: the 2x
- how this ought to be configured/controlled from the C++ code needs to be discussed ?!
- could be set per ShaderSet (as mentioned above)
- but could also be set per StateGroup, per RenderPass/RenderGraph, PipelineLayout, ... ?!