Missing validation: push descriptor updates don't trigger image layout mismatch errors
zeux opened this issue · comments
I have an application where a compute shader uses an image descriptor. The application has two modes: using regular descriptor sets (vkUpdateDescriptorSetWithTemplate + vkCmdBindDescriptorSets) and using push descriptors (vkCmdPushDescriptorSetWithTemplateKHR).
In this application, the image layout transition from UNDEFINED (initial state) to GENERAL (expected state in dispatch) is mistakenly omitted.
When using push descriptors, validation layers are silent. When using regular descriptors, they correctly flag this error:
ERROR: Validation Error: [ UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout ] Object 0: handle = 0x20590c19120, type = VK_OBJECT_TYPE_COMMAND_BUFFER; | MessageID = 0x4dae5635 | Submitted command buffer expects VkImage 0xfd77e40000000041[] (subresource: aspectMask 0x1 array layer 0, mip level 0) to be in layout VK_IMAGE_LAYOUT_GENERAL--instead, current layout is VK_IMAGE_LAYOUT_UNDEFINED.
When using regular descriptors, the following call sequence happens:
> VkLayer_khronos_validation.dll!cvdescriptorset::ImageSamplerDescriptor::UpdateDrawState(ValidationStateTracker * dev_data, CMD_BUFFER_STATE * cb_node) Line 1668 C++
VkLayer_khronos_validation.dll!cvdescriptorset::DescriptorSet::UpdateDrawState(ValidationStateTracker * device_data, CMD_BUFFER_STATE * cb_node, const PIPELINE_STATE * pipe, const std::map<unsigned int,enum descriptor_req,std::less<unsigned int>,std::allocator<std::pair<unsigned int const ,enum descriptor_req>>> & binding_req_map) Line 1274 C++
VkLayer_khronos_validation.dll!ValidationStateTracker::UpdateDrawState(CMD_BUFFER_STATE * cb_state, const VkPipelineBindPoint bind_point) Line 701 C++
VkLayer_khronos_validation.dll!ValidationStateTracker::UpdateStateCmdDrawDispatchType(CMD_BUFFER_STATE * cb_state, VkPipelineBindPoint bind_point) Line 4760 C++
VkLayer_khronos_validation.dll!vulkan_layer_chassis::CmdDispatch(VkCommandBuffer_T * commandBuffer, unsigned int groupCountX, unsigned int groupCountY, unsigned int groupCountZ) Line 3312 C++
niagara.exe!main::__l48::<lambda>(VkPipeline_T * pipeline, unsigned int timestamp, const char * phase) Line 949 C++
Inside ImageSamplerDescriptor::UpdateDrawState
, CallSetImageViewInitialLayoutCallback
(I think?) records the initial layout, which is then used in the command buffer validation code to validate the image layouts.
However, when using push descriptors, ValidationStateTracker::UpdateDrawState
doesn't call cvdescriptorset::DescriptorSet::UpdateDrawState
because of the following check (state_tracker.cpp:659):
if (!descriptor_set->IsPushDescriptor()) {
As a result, the error is not emitted.
Fixed with #1904
Thanks!