diff --git a/layers/gpu/cmd_validation/gpuav_cmd_validation_common.cpp b/layers/gpu/cmd_validation/gpuav_cmd_validation_common.cpp index fdd536911c9..e184644fa1a 100644 --- a/layers/gpu/cmd_validation/gpuav_cmd_validation_common.cpp +++ b/layers/gpu/cmd_validation/gpuav_cmd_validation_common.cpp @@ -64,14 +64,14 @@ void RestorablePipelineState::Create(vvl::CommandBuffer &cb_state, VkPipelineBin push_constants_data_ = cb_state.push_constant_data_chunks; descriptor_sets_.reserve(last_bound.per_set.size()); - for (std::size_t i = 0; i < last_bound.per_set.size(); i++) { - const auto &bound_descriptor_set = last_bound.per_set[i].bound_descriptor_set; + for (std::size_t set_i = 0; set_i < last_bound.per_set.size(); set_i++) { + const auto &bound_descriptor_set = last_bound.per_set[set_i].bound_descriptor_set; if (bound_descriptor_set) { - descriptor_sets_.emplace_back(bound_descriptor_set->VkHandle(), static_cast(i)); + descriptor_sets_.emplace_back(bound_descriptor_set->VkHandle(), static_cast(set_i)); if (bound_descriptor_set->IsPushDescriptor()) { - push_descriptor_set_index_ = static_cast(i); + push_descriptor_set_index_ = static_cast(set_i); } - dynamic_offsets_.push_back(last_bound.per_set[i].dynamicOffsets); + dynamic_offsets_.push_back(last_bound.per_set[set_i].dynamicOffsets); } } diff --git a/layers/gpu/core/gpuav.h b/layers/gpu/core/gpuav.h index edc547aa5cb..8942c5f7d02 100644 --- a/layers/gpu/core/gpuav.h +++ b/layers/gpu/core/gpuav.h @@ -147,59 +147,114 @@ class Validator : public gpu::GpuShaderInstrumentor { const RecordObject& record_obj) final; void PreCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance, const RecordObject& record_obj) final; + void PostCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, + uint32_t firstInstance, const RecordObject& record_obj) final; void PreCallRecordCmdDrawMultiEXT(VkCommandBuffer commandBuffer, uint32_t drawCount, const VkMultiDrawInfoEXT* pVertexInfo, uint32_t instanceCount, uint32_t firstInstance, uint32_t stride, const RecordObject& record_obj) final; + void PostCallRecordCmdDrawMultiEXT(VkCommandBuffer commandBuffer, uint32_t drawCount, const VkMultiDrawInfoEXT* pVertexInfo, + uint32_t instanceCount, uint32_t firstInstance, uint32_t stride, + const RecordObject& record_obj) final; void PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance, const RecordObject& record_obj) final; + void PostCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, + uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance, + const RecordObject& record_obj) final; void PreCallRecordCmdDrawMultiIndexedEXT(VkCommandBuffer commandBuffer, uint32_t drawCount, const VkMultiDrawIndexedInfoEXT* pIndexInfo, uint32_t instanceCount, uint32_t firstInstance, uint32_t stride, const int32_t* pVertexOffset, const RecordObject& record_obj) final; + void PostCallRecordCmdDrawMultiIndexedEXT(VkCommandBuffer commandBuffer, uint32_t drawCount, + const VkMultiDrawIndexedInfoEXT* pIndexInfo, uint32_t instanceCount, + uint32_t firstInstance, uint32_t stride, const int32_t* pVertexOffset, + const RecordObject& record_obj) final; void PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride, const RecordObject& record_obj) final; + void PostCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, + uint32_t stride, const RecordObject& record_obj) final; void PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride, const RecordObject& record_obj) final; + void PostCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, + uint32_t stride, const RecordObject& record_obj) final; void PreCallRecordCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, const RecordObject& record_obj) final; + void PostCallRecordCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, + VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, + uint32_t stride, const RecordObject& record_obj) final; void PreCallRecordCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, const RecordObject& record_obj) final; + void PostCallRecordCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, + VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, + uint32_t stride, const RecordObject& record_obj) final; void PreCallRecordCmdDrawIndirectByteCountEXT(VkCommandBuffer commandBuffer, uint32_t instanceCount, uint32_t firstInstance, VkBuffer counterBuffer, VkDeviceSize counterBufferOffset, uint32_t counterOffset, uint32_t vertexStride, const RecordObject& record_obj) final; + void PostCallRecordCmdDrawIndirectByteCountEXT(VkCommandBuffer commandBuffer, uint32_t instanceCount, uint32_t firstInstance, + VkBuffer counterBuffer, VkDeviceSize counterBufferOffset, uint32_t counterOffset, + uint32_t vertexStride, const RecordObject& record_obj) final; void PreCallRecordCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, const RecordObject& record_obj) final; + void PostCallRecordCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, + VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, + uint32_t stride, const RecordObject& record_obj) final; void PreCallRecordCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, const RecordObject& record_obj) final; + void PostCallRecordCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, + VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, + uint32_t stride, const RecordObject& record_obj) final; void PreCallRecordCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask, const RecordObject& record_obj) final; + void PostCallRecordCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask, + const RecordObject& record_obj) final; void PreCallRecordCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride, const RecordObject& record_obj) final; + void PostCallRecordCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, + uint32_t drawCount, uint32_t stride, const RecordObject& record_obj) final; void PreCallRecordCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, const RecordObject& record_obj) final; + void PostCallRecordCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, + VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, + uint32_t stride, const RecordObject& record_obj) final; void PreCallRecordCmdDrawMeshTasksEXT(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, const RecordObject& record_obj) final; + void PostCallRecordCmdDrawMeshTasksEXT(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, + uint32_t groupCountZ, const RecordObject& record_obj) final; void PreCallRecordCmdDrawMeshTasksIndirectEXT(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride, const RecordObject& record_obj) final; + void PostCallRecordCmdDrawMeshTasksIndirectEXT(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, + uint32_t drawCount, uint32_t stride, const RecordObject& record_obj) final; void PreCallRecordCmdDrawMeshTasksIndirectCountEXT(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, const RecordObject& record_obj) final; + void PostCallRecordCmdDrawMeshTasksIndirectCountEXT(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, + VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, + uint32_t stride, const RecordObject& record_obj) final; void PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z, const RecordObject& record_obj) final; + void PostCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z, + const RecordObject& record_obj) final; void PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, const RecordObject& record_obj) final; + void PostCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, + const RecordObject& record_obj) final; void PreCallRecordCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, const RecordObject& record_obj) final; + void PostCallRecordCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, + uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, + const RecordObject& record_obj) final; void PreCallRecordCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, const RecordObject& record_obj) final; + void PostCallRecordCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, + uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, + const RecordObject& record_obj) final; void PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, @@ -207,20 +262,42 @@ class Validator : public gpu::GpuShaderInstrumentor { VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer, VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride, uint32_t width, uint32_t height, uint32_t depth, const RecordObject& record_obj) final; + void PostCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, + VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, + VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, + VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset, + VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer, + VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride, + uint32_t width, uint32_t height, uint32_t depth, const RecordObject& record_obj) final; + void PreCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer, const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, uint32_t width, uint32_t height, uint32_t depth, const RecordObject& record_obj) final; + void PostCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer, + const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, uint32_t width, + uint32_t height, uint32_t depth, const RecordObject& record_obj) final; void PreCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer, const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, VkDeviceAddress indirectDeviceAddress, const RecordObject& record_obj) final; + void PostCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer, + const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, + const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, + VkDeviceAddress indirectDeviceAddress, const RecordObject& record_obj) final; void PreCallRecordCmdTraceRaysIndirect2KHR(VkCommandBuffer commandBuffer, VkDeviceAddress indirectDeviceAddress, const RecordObject& record_obj) final; + void PostCallRecordCmdTraceRaysIndirect2KHR(VkCommandBuffer commandBuffer, VkDeviceAddress indirectDeviceAddress, + const RecordObject& record_obj) final; void PostCallRecordGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pPhysicalDeviceProperties2, diff --git a/layers/gpu/core/gpuav_record.cpp b/layers/gpu/core/gpuav_record.cpp index 743bc77ca2f..8e93896d947 100644 --- a/layers/gpu/core/gpuav_record.cpp +++ b/layers/gpu/core/gpuav_record.cpp @@ -307,7 +307,20 @@ void Validator::PreCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t ver return; } - SetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); + PreCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); +} + +void Validator::PostCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, + uint32_t firstVertex, uint32_t firstInstance, const RecordObject &record_obj) { + BaseClass::PostCallRecordCmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance, record_obj); + + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; + } + + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); } void Validator::PreCallRecordCmdDrawMultiEXT(VkCommandBuffer commandBuffer, uint32_t drawCount, @@ -322,9 +335,22 @@ void Validator::PreCallRecordCmdDrawMultiEXT(VkCommandBuffer commandBuffer, uint return; } - for (uint32_t i = 0; i < drawCount; i++) { - SetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); + PreCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); +} + +void Validator::PostCallRecordCmdDrawMultiEXT(VkCommandBuffer commandBuffer, uint32_t drawCount, + const VkMultiDrawInfoEXT *pVertexInfo, uint32_t instanceCount, uint32_t firstInstance, + uint32_t stride, const RecordObject &record_obj) { + BaseClass::PostCallRecordCmdDrawMultiEXT(commandBuffer, drawCount, pVertexInfo, instanceCount, firstInstance, stride, + record_obj); + + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; } + + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); } void Validator::PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, @@ -337,7 +363,20 @@ void Validator::PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint3 InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); return; } - SetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); + PreCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); +} + +void Validator::PostCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, + uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance, + const RecordObject &record_obj) { + BaseClass::PostCallRecordCmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance, + record_obj); + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; + } + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); } void Validator::PreCallRecordCmdDrawMultiIndexedEXT(VkCommandBuffer commandBuffer, uint32_t drawCount, @@ -353,10 +392,25 @@ void Validator::PreCallRecordCmdDrawMultiIndexedEXT(VkCommandBuffer commandBuffe } for (uint32_t i = 0; i < drawCount; i++) { // #ARNO_TODO calling Setup drawCount times seems weird... - SetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); + PreCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); } } +void Validator::PostCallRecordCmdDrawMultiIndexedEXT(VkCommandBuffer commandBuffer, uint32_t drawCount, + const VkMultiDrawIndexedInfoEXT *pIndexInfo, uint32_t instanceCount, + uint32_t firstInstance, uint32_t stride, const int32_t *pVertexOffset, + const RecordObject &record_obj) { + BaseClass::PostCallRecordCmdDrawMultiIndexedEXT(commandBuffer, drawCount, pIndexInfo, instanceCount, firstInstance, stride, + pVertexOffset, record_obj); + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; + } + + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); +} + void Validator::PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride, const RecordObject &record_obj) { BaseClass::PreCallRecordCmdDrawIndirect(commandBuffer, buffer, offset, count, stride, record_obj); @@ -368,7 +422,20 @@ void Validator::PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBu } InsertIndirectDrawValidation(*this, record_obj.location, *cb_state, buffer, offset, count, VK_NULL_HANDLE, 0, stride); - SetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); + PreCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); +} + +void Validator::PostCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, + uint32_t stride, const RecordObject &record_obj) { + BaseClass::PostCallRecordCmdDrawIndirect(commandBuffer, buffer, offset, count, stride, record_obj); + + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; + } + + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); } void Validator::PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, @@ -382,7 +449,20 @@ void Validator::PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffe } InsertIndirectDrawValidation(*this, record_obj.location, *cb_state, buffer, offset, count, VK_NULL_HANDLE, 0, stride); - SetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); + PreCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); +} + +void Validator::PostCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, + uint32_t count, uint32_t stride, const RecordObject &record_obj) { + BaseClass::PostCallRecordCmdDrawIndexedIndirect(commandBuffer, buffer, offset, count, stride, record_obj); + + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; + } + + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); } void Validator::PreCallRecordCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, @@ -392,6 +472,13 @@ void Validator::PreCallRecordCmdDrawIndirectCountKHR(VkCommandBuffer commandBuff record_obj); } +void Validator::PostCallRecordCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, + VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, + uint32_t stride, const RecordObject &record_obj) { + PostCallRecordCmdDrawIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride, + record_obj); +} + void Validator::PreCallRecordCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, const RecordObject &record_obj) { @@ -405,7 +492,22 @@ void Validator::PreCallRecordCmdDrawIndirectCount(VkCommandBuffer commandBuffer, } InsertIndirectDrawValidation(*this, record_obj.location, *cb_state, buffer, offset, maxDrawCount, countBuffer, countBufferOffset, stride); - SetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); + PreCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); +} + +void Validator::PostCallRecordCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, + VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, + uint32_t stride, const RecordObject &record_obj) { + BaseClass::PostCallRecordCmdDrawIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, + stride, record_obj); + + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; + } + + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); } void Validator::PreCallRecordCmdDrawIndirectByteCountEXT(VkCommandBuffer commandBuffer, uint32_t instanceCount, @@ -419,7 +521,21 @@ void Validator::PreCallRecordCmdDrawIndirectByteCountEXT(VkCommandBuffer command InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); return; } - SetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); + PreCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); +} + +void Validator::PostCallRecordCmdDrawIndirectByteCountEXT(VkCommandBuffer commandBuffer, uint32_t instanceCount, + uint32_t firstInstance, VkBuffer counterBuffer, + VkDeviceSize counterBufferOffset, uint32_t counterOffset, + uint32_t vertexStride, const RecordObject &record_obj) { + BaseClass::PostCallRecordCmdDrawIndirectByteCountEXT(commandBuffer, instanceCount, firstInstance, counterBuffer, + counterBufferOffset, counterOffset, vertexStride, record_obj); + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; + } + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); } void Validator::PreCallRecordCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, @@ -430,6 +546,14 @@ void Validator::PreCallRecordCmdDrawIndexedIndirectCountKHR(VkCommandBuffer comm record_obj); } +void Validator::PostCallRecordCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, + VkBuffer countBuffer, VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, uint32_t stride, + const RecordObject &record_obj) { + PostCallRecordCmdDrawIndexedIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride, + record_obj); +} + void Validator::PreCallRecordCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, const RecordObject &record_obj) { @@ -443,7 +567,22 @@ void Validator::PreCallRecordCmdDrawIndexedIndirectCount(VkCommandBuffer command } InsertIndirectDrawValidation(*this, record_obj.location, *cb_state, buffer, offset, maxDrawCount, countBuffer, countBufferOffset, stride); - SetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); + PreCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); +} + +void Validator::PostCallRecordCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, + VkBuffer countBuffer, VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, uint32_t stride, const RecordObject &record_obj) { + BaseClass::PostCallRecordCmdDrawIndexedIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset, + maxDrawCount, stride, record_obj); + + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; + } + + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); } void Validator::PreCallRecordCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask, @@ -454,7 +593,18 @@ void Validator::PreCallRecordCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, u InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); return; } - SetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); + PreCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); +} + +void Validator::PostCallRecordCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask, + const RecordObject &record_obj) { + ValidationStateTracker::PostCallRecordCmdDrawMeshTasksNV(commandBuffer, taskCount, firstTask, record_obj); + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; + } + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); } void Validator::PreCallRecordCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, @@ -467,7 +617,19 @@ void Validator::PreCallRecordCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandB return; } InsertIndirectDrawValidation(*this, record_obj.location, *cb_state, buffer, offset, drawCount, VK_NULL_HANDLE, 0, stride); - SetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); + PreCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); +} + +void Validator::PostCallRecordCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, + uint32_t drawCount, uint32_t stride, const RecordObject &record_obj) { + BaseClass::PostCallRecordCmdDrawMeshTasksIndirectNV(commandBuffer, buffer, offset, drawCount, stride, record_obj); + + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; + } + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); } void Validator::PreCallRecordCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, @@ -484,7 +646,23 @@ void Validator::PreCallRecordCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer com } InsertIndirectDrawValidation(*this, record_obj.location, *cb_state, buffer, offset, maxDrawCount, countBuffer, countBufferOffset, stride); - SetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); + PreCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); +} + +void Validator::PostCallRecordCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, + VkBuffer countBuffer, VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, uint32_t stride, + const RecordObject &record_obj) { + BaseClass::PostCallRecordCmdDrawMeshTasksIndirectCountNV(commandBuffer, buffer, offset, countBuffer, countBufferOffset, + maxDrawCount, stride, record_obj); + + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; + } + + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); } void Validator::PreCallRecordCmdDrawMeshTasksEXT(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, @@ -495,7 +673,18 @@ void Validator::PreCallRecordCmdDrawMeshTasksEXT(VkCommandBuffer commandBuffer, InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); return; } - SetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); + PreCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); +} + +void Validator::PostCallRecordCmdDrawMeshTasksEXT(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, + uint32_t groupCountZ, const RecordObject &record_obj) { + BaseClass::PostCallRecordCmdDrawMeshTasksEXT(commandBuffer, groupCountX, groupCountY, groupCountZ, record_obj); + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; + } + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); } void Validator::PreCallRecordCmdDrawMeshTasksIndirectEXT(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, @@ -508,7 +697,19 @@ void Validator::PreCallRecordCmdDrawMeshTasksIndirectEXT(VkCommandBuffer command return; } InsertIndirectDrawValidation(*this, record_obj.location, *cb_state, buffer, offset, drawCount, VK_NULL_HANDLE, 0, stride); - SetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); + PreCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); +} + +void Validator::PostCallRecordCmdDrawMeshTasksIndirectEXT(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, + uint32_t drawCount, uint32_t stride, const RecordObject &record_obj) { + BaseClass::PostCallRecordCmdDrawMeshTasksIndirectEXT(commandBuffer, buffer, offset, drawCount, stride, record_obj); + + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; + } + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); } void Validator::PreCallRecordCmdDrawMeshTasksIndirectCountEXT(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, @@ -525,7 +726,23 @@ void Validator::PreCallRecordCmdDrawMeshTasksIndirectCountEXT(VkCommandBuffer co } InsertIndirectDrawValidation(*this, record_obj.location, *cb_state, buffer, offset, maxDrawCount, countBuffer, countBufferOffset, stride); - SetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); + PreCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); +} + +void Validator::PostCallRecordCmdDrawMeshTasksIndirectCountEXT(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, + VkBuffer countBuffer, VkDeviceSize countBufferOffset, + uint32_t maxDrawCount, uint32_t stride, + const RecordObject &record_obj) { + BaseClass::PostCallRecordCmdDrawMeshTasksIndirectCountEXT(commandBuffer, buffer, offset, countBuffer, countBufferOffset, + maxDrawCount, stride, record_obj); + + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; + } + + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, record_obj.location); } void Validator::PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z, @@ -537,7 +754,19 @@ void Validator::PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); return; } - SetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_COMPUTE, record_obj.location); + PreCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_COMPUTE, record_obj.location); +} + +void Validator::PostCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z, + const RecordObject &record_obj) { + BaseClass::PostCallRecordCmdDispatch(commandBuffer, x, y, z, record_obj); + + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; + } + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_COMPUTE, record_obj.location); } void Validator::PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, @@ -550,7 +779,20 @@ void Validator::PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, return; } InsertIndirectDispatchValidation(*this, record_obj.location, *cb_state, buffer, offset); - SetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_COMPUTE, record_obj.location); + PreCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_COMPUTE, record_obj.location); +} + +void Validator::PostCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, + const RecordObject &record_obj) { + BaseClass::PostCallRecordCmdDispatchIndirect(commandBuffer, buffer, offset, record_obj); + + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; + } + + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_COMPUTE, record_obj.location); } void Validator::PreCallRecordCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, @@ -564,7 +806,21 @@ void Validator::PreCallRecordCmdDispatchBase(VkCommandBuffer commandBuffer, uint InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); return; } - SetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_COMPUTE, record_obj.location); + PreCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_COMPUTE, record_obj.location); +} + +void Validator::PostCallRecordCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, + uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, + const RecordObject &record_obj) { + BaseClass::PostCallRecordCmdDispatchBase(commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, + groupCountZ, record_obj); + + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; + } + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_COMPUTE, record_obj.location); } void Validator::PreCallRecordCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, @@ -574,6 +830,20 @@ void Validator::PreCallRecordCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, u record_obj); } +void Validator::PostCallRecordCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, + uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, + uint32_t groupCountZ, const RecordObject &record_obj) { + BaseClass::PostCallRecordCmdDispatchBaseKHR(commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, + groupCountZ, record_obj); + + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; + } + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_COMPUTE, record_obj.location); +} + void Validator::PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, @@ -592,7 +862,28 @@ void Validator::PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuf InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); return; } - SetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, record_obj.location); + PreCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, record_obj.location); +} + +void Validator::PostCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, + VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, + VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, + VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset, + VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer, + VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride, + uint32_t width, uint32_t height, uint32_t depth, const RecordObject &record_obj) { + BaseClass::PostCallRecordCmdTraceRaysNV(commandBuffer, raygenShaderBindingTableBuffer, raygenShaderBindingOffset, + missShaderBindingTableBuffer, missShaderBindingOffset, missShaderBindingStride, + hitShaderBindingTableBuffer, hitShaderBindingOffset, hitShaderBindingStride, + callableShaderBindingTableBuffer, callableShaderBindingOffset, + callableShaderBindingStride, width, height, depth, record_obj); + + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; + } + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, record_obj.location); } void Validator::PreCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer, @@ -609,7 +900,24 @@ void Validator::PreCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer, InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); return; } - SetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, record_obj.location); + PreCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, record_obj.location); +} + +void Validator::PostCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer, + const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable, + const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable, + const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable, + const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable, uint32_t width, + uint32_t height, uint32_t depth, const RecordObject &record_obj) { + BaseClass::PostCallRecordCmdTraceRaysKHR(commandBuffer, pRaygenShaderBindingTable, pMissShaderBindingTable, + pHitShaderBindingTable, pCallableShaderBindingTable, width, height, depth, record_obj); + + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; + } + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, record_obj.location); } void Validator::PreCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer, @@ -628,7 +936,25 @@ void Validator::PreCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuff return; } InsertIndirectTraceRaysValidation(*this, record_obj.location, *cb_state, indirectDeviceAddress); - SetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, record_obj.location); + PreCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, record_obj.location); +} + +void Validator::PostCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer, + const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable, + const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable, + const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable, + const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable, + VkDeviceAddress indirectDeviceAddress, const RecordObject &record_obj) { + BaseClass::PostCallRecordCmdTraceRaysIndirectKHR(commandBuffer, pRaygenShaderBindingTable, pMissShaderBindingTable, + pHitShaderBindingTable, pCallableShaderBindingTable, indirectDeviceAddress, + record_obj); + + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; + } + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, record_obj.location); } void Validator::PreCallRecordCmdTraceRaysIndirect2KHR(VkCommandBuffer commandBuffer, VkDeviceAddress indirectDeviceAddress, @@ -640,7 +966,19 @@ void Validator::PreCallRecordCmdTraceRaysIndirect2KHR(VkCommandBuffer commandBuf InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); return; } - SetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, record_obj.location); + PreCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, record_obj.location); +} + +void Validator::PostCallRecordCmdTraceRaysIndirect2KHR(VkCommandBuffer commandBuffer, VkDeviceAddress indirectDeviceAddress, + const RecordObject &record_obj) { + BaseClass::PostCallRecordCmdTraceRaysIndirect2KHR(commandBuffer, indirectDeviceAddress, record_obj); + + auto cb_state = GetWrite(commandBuffer); + if (!cb_state) { + InternalError(commandBuffer, record_obj.location, "Unrecognized command buffer."); + return; + } + PostCallSetupShaderInstrumentationResources(*this, *cb_state, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, record_obj.location); } } // namespace gpuav diff --git a/layers/gpu/instrumentation/gpu_shader_instrumentor.h b/layers/gpu/instrumentation/gpu_shader_instrumentor.h index ac9d89415b6..84067470022 100644 --- a/layers/gpu/instrumentation/gpu_shader_instrumentor.h +++ b/layers/gpu/instrumentation/gpu_shader_instrumentor.h @@ -225,6 +225,8 @@ class GpuShaderInstrumentor : public ValidationStateTracker { std::atomic unique_shader_module_id_ = 1; // zero represents no shader module found // The descriptor slot we will be injecting our error buffer into uint32_t desc_set_bind_index_ = 0; + // This is a layout used to "pad" a pipeline layout to fill in any gaps to the selected bind index + VkDescriptorSetLayout dummy_desc_layout_ = VK_NULL_HANDLE; VmaAllocator vma_allocator_ = {}; VmaPool output_buffer_pool_ = VK_NULL_HANDLE; std::unique_ptr desc_set_manager_; @@ -239,8 +241,6 @@ class GpuShaderInstrumentor : public ValidationStateTracker { private: void Cleanup(); - // This is a layout used to "pad" a pipeline layout to fill in any gaps to the selected bind index - VkDescriptorSetLayout dummy_desc_layout_ = VK_NULL_HANDLE; // These are objects used to inject our descriptor set into the command buffer VkDescriptorSetLayout debug_desc_layout_ = VK_NULL_HANDLE; VkPipelineLayout debug_pipeline_layout_ = VK_NULL_HANDLE; diff --git a/layers/gpu/instrumentation/gpuav_instrumentation.cpp b/layers/gpu/instrumentation/gpuav_instrumentation.cpp index 47151934cca..8f1dcd69581 100644 --- a/layers/gpu/instrumentation/gpuav_instrumentation.cpp +++ b/layers/gpu/instrumentation/gpuav_instrumentation.cpp @@ -25,8 +25,34 @@ namespace gpuav { -void SetupShaderInstrumentationResources(Validator &gpuav, CommandBuffer &cb_state, VkPipelineBindPoint bind_point, - const Location &loc) { +static std::shared_ptr GetInstrumentionDescSetBindingPipelineLayout(Validator &gpuav, + LvlBindPoint lv_bind_point, + CommandBuffer &cb_state, + const LastBound &last_bound) { + // If GPL is used, it's possible the pipeline layout used at pipeline creation time is null. If CmdBindDescriptorSets has + // not been called yet (i.e., state.pipeline_null), then fall back to the layout associated with pre-raster state, + // or the last specified pipeline layout in vkCmdPushConstantRanges. + // PipelineLayoutState should be used for the purposes of determining the number of sets in the layout, but this layout + // may be a "pseudo layout" used to represent the union of pre-raster and fragment shader layouts, and therefore have a + // null handle. + std::shared_ptr inst_desc_set_binding_pipe_layout_state; + if (last_bound.pipeline_state && !last_bound.pipeline_state->PipelineLayoutState()->Destroyed() && + last_bound.pipeline_state->PipelineLayoutState()->VkHandle() != VK_NULL_HANDLE) { + inst_desc_set_binding_pipe_layout_state = last_bound.pipeline_state->PipelineLayoutState(); + } else if (last_bound.pipeline_state && !last_bound.pipeline_state->PreRasterPipelineLayoutState()->Destroyed()) { + inst_desc_set_binding_pipe_layout_state = last_bound.pipeline_state->PreRasterPipelineLayoutState(); + } else if (last_bound.desc_set_pipeline_layout) { + inst_desc_set_binding_pipe_layout_state = gpuav.Get(last_bound.desc_set_pipeline_layout); + } else if (cb_state.push_constant_latest_used_layout[lv_bind_point] != VK_NULL_HANDLE) { + inst_desc_set_binding_pipe_layout_state = + gpuav.Get(cb_state.push_constant_latest_used_layout[lv_bind_point]); + } + + return inst_desc_set_binding_pipe_layout_state; +} + +void PreCallSetupShaderInstrumentationResources(Validator &gpuav, CommandBuffer &cb_state, VkPipelineBindPoint bind_point, + const Location &loc) { if (!gpuav.gpuav_settings.shader_instrumentation_enabled) { return; } @@ -36,9 +62,8 @@ void SetupShaderInstrumentationResources(Validator &gpuav, CommandBuffer &cb_sta const auto lv_bind_point = ConvertToLvlBindPoint(bind_point); auto const &last_bound = cb_state.lastBound[lv_bind_point]; - const auto *pipeline_state = last_bound.pipeline_state; - if (!pipeline_state && !last_bound.HasShaderObjects()) { + if (!last_bound.pipeline_state && !last_bound.HasShaderObjects()) { gpuav.InternalError(cb_state.VkHandle(), loc, "Neither pipeline state nor shader object states were found."); return; } @@ -151,23 +176,8 @@ void SetupShaderInstrumentationResources(Validator &gpuav, CommandBuffer &cb_sta DispatchUpdateDescriptorSets(gpuav.device, static_cast(desc_writes.size()), desc_writes.data(), 0, nullptr); } - auto pipeline_layout = pipeline_state ? pipeline_state->PipelineLayoutState() - : gpuav.Get(last_bound.desc_set_pipeline_layout); - // If GPL is used, it's possible the pipeline layout used at pipeline creation time is null. If CmdBindDescriptorSets has - // not been called yet (i.e., state.pipeline_null), then fall back to the layout associated with pre-raster state, - // or the last specified pipeline layout in vkCmdPushConstantRanges. - // PipelineLayoutState should be used for the purposes of determining the number of sets in the layout, but this layout - // may be a "pseudo layout" used to represent the union of pre-raster and fragment shader layouts, and therefore have a - // null handle. - VkPipelineLayout pipeline_layout_handle = VK_NULL_HANDLE; - if (last_bound.desc_set_pipeline_layout) { - pipeline_layout_handle = last_bound.desc_set_pipeline_layout; - } else if (pipeline_state && !pipeline_state->PreRasterPipelineLayoutState()->Destroyed()) { - pipeline_layout_handle = pipeline_state->PreRasterPipelineLayoutState()->VkHandle(); - } else if (cb_state.push_constant_latest_used_layout[lv_bind_point] != VK_NULL_HANDLE) { - pipeline_layout_handle = cb_state.push_constant_latest_used_layout[lv_bind_point]; - pipeline_layout = gpuav.Get(pipeline_layout_handle); - } + const std::shared_ptr inst_desc_set_binding_pipe_layout_state = + GetInstrumentionDescSetBindingPipelineLayout(gpuav, lv_bind_point, cb_state, last_bound); uint32_t operation_index = 0; if (bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) @@ -182,14 +192,15 @@ void SetupShaderInstrumentationResources(Validator &gpuav, CommandBuffer &cb_sta const uint32_t error_logger_i = static_cast(cb_state.per_command_error_loggers.size()); const std::array dynamic_offsets = { {operation_index * gpuav.indices_buffer_alignment_, error_logger_i * gpuav.indices_buffer_alignment_}}; - if (pipeline_layout && pipeline_layout_handle != VK_NULL_HANDLE) { - // If we were unable to use the layout because it overlaps with the instrumented set, don't dispatch anything or we will - // disturb the original bound set - if (pipeline_layout->set_layouts.size() <= gpuav.desc_set_bind_index_) { - DispatchCmdBindDescriptorSets(cb_state.VkHandle(), bind_point, pipeline_layout_handle, gpuav.desc_set_bind_index_, 1, - &instrumentation_desc_set, static_cast(dynamic_offsets.size()), - dynamic_offsets.data()); + if (inst_desc_set_binding_pipe_layout_state) { + if (inst_desc_set_binding_pipe_layout_state->set_layouts.size() <= gpuav.desc_set_bind_index_) { + DispatchCmdBindDescriptorSets(cb_state.VkHandle(), bind_point, inst_desc_set_binding_pipe_layout_state->VkHandle(), + gpuav.desc_set_bind_index_, 1, &instrumentation_desc_set, + static_cast(dynamic_offsets.size()), dynamic_offsets.data()); } else { + // #ARNO_TODO should never get there. We should just early abort this function is shaders were not instrumented. + // If we were unable to use the layout because it overlaps with the instrumented set, don't dispatch anything or we will + // disturb the original bound set // Cannot setup instrumentation descriptor set, abort for this command return; } @@ -201,21 +212,16 @@ void SetupShaderInstrumentationResources(Validator &gpuav, CommandBuffer &cb_sta dynamic_offsets.data()); } - if (pipeline_state && pipeline_layout_handle == VK_NULL_HANDLE) { - gpuav.InternalError(cb_state.Handle(), loc, "Unable to find pipeline layout to bind debug descriptor set"); - return; - } - // It is possible to have no descriptor sets bound, for example if using push constants. const uint32_t desc_binding_index = !cb_state.di_input_buffer_list.empty() ? uint32_t(cb_state.di_input_buffer_list.size()) - 1 : vvl::kU32Max; const bool uses_robustness = (gpuav.enabled_features.robustBufferAccess || gpuav.enabled_features.robustBufferAccess2 || - (pipeline_state && pipeline_state->uses_pipeline_robustness)); + (last_bound.pipeline_state && last_bound.pipeline_state->uses_pipeline_robustness)); CommandBuffer::ErrorLoggerFunc error_logger = [loc, desc_binding_index, desc_binding_list = &cb_state.di_input_buffer_list, cb_state_handle = cb_state.VkHandle(), bind_point, operation_index, - uses_shader_object = pipeline_state == nullptr, + uses_shader_object = last_bound.pipeline_state == nullptr, uses_robustness](Validator &gpuav, const uint32_t *error_record, const LogObjectList &objlist) { bool skip = false; @@ -230,6 +236,60 @@ void SetupShaderInstrumentationResources(Validator &gpuav, CommandBuffer &cb_sta cb_state.per_command_error_loggers.emplace_back(error_logger); } +void PostCallSetupShaderInstrumentationResources(Validator &gpuav, CommandBuffer &cb_state, VkPipelineBindPoint bind_point, + const Location &loc) { + if (!gpuav.gpuav_settings.shader_instrumentation_enabled) { + return; + } + + assert(bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS || bind_point == VK_PIPELINE_BIND_POINT_COMPUTE || + bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR); + + const LvlBindPoint lv_bind_point = ConvertToLvlBindPoint(bind_point); + const LastBound &last_bound = cb_state.lastBound[lv_bind_point]; + + if (!last_bound.pipeline_state && !last_bound.HasShaderObjects()) { + gpuav.InternalError(cb_state.VkHandle(), loc, "Neither pipeline state nor shader object states were found."); + return; + } + + const std::shared_ptr instrumentation_desc_set_binding_pipe_layout_state = + GetInstrumentionDescSetBindingPipelineLayout(gpuav, lv_bind_point, cb_state, last_bound); + + // Only need to rebind application desc sets if they have been disturbed by GPU-AV binding its instrumentation desc set. + // - Can happen if the pipeline layout used to bind instrumentation descriptor set is not compatible with the one used by the + // app to bind the last/all the last desc set. This pipeline layout is referred to as "last_bound_desc_set_pipe_layout_state" + // hereinafter. + // => We create this incompatibility when we add our empty descriptor set. + // See PositiveGpuAVDescriptorIndexing.SharedPipelineLayoutSubsetGraphics + // How to solve: + // - Take pipeline layout we used to bind the instrumentation desc set + // - Look if the empty descriptor sets we added see their bindings overlap with last_bound_desc_set_pipe_layout_state + // - If so, re-bind app supplied descriptor sets at those spots + + std::shared_ptr last_bound_desc_set_pipe_layout_state; + if (last_bound.desc_set_pipeline_layout) { + last_bound_desc_set_pipe_layout_state = gpuav.Get(last_bound.desc_set_pipeline_layout); + } + + if (instrumentation_desc_set_binding_pipe_layout_state && last_bound_desc_set_pipe_layout_state) { + if (instrumentation_desc_set_binding_pipe_layout_state->set_layouts.size() < + last_bound_desc_set_pipe_layout_state->set_layouts.size()) { + const size_t bindings_count = last_bound_desc_set_pipe_layout_state->set_layouts.size() - + instrumentation_desc_set_binding_pipe_layout_state->set_layouts.size(); + for (size_t set_i = 0; set_i < bindings_count; ++set_i) { + const uint32_t last_bound_set_i = + static_cast(set_i + instrumentation_desc_set_binding_pipe_layout_state->set_layouts.size()); + VkDescriptorSet desc_set = last_bound.per_set[last_bound_set_i].bound_descriptor_set->VkHandle(); + const std::vector &dynamic_offset = last_bound.per_set[last_bound_set_i].dynamicOffsets; + const uint32_t dynamic_offset_count = static_cast(dynamic_offset.size()); + DispatchCmdBindDescriptorSets(cb_state.VkHandle(), bind_point, last_bound_desc_set_pipe_layout_state->VkHandle(), + last_bound_set_i, 1, &desc_set, dynamic_offset_count, dynamic_offset.data()); + } + } + } +} + bool LogMessageInstBindlessDescriptor(Validator &gpuav, const uint32_t *error_record, std::string &out_error_msg, std::string &out_vuid_msg, const std::vector &descriptor_sets, const Location &loc, bool uses_shader_object, bool &out_oob_access) { diff --git a/layers/gpu/instrumentation/gpuav_instrumentation.h b/layers/gpu/instrumentation/gpuav_instrumentation.h index 4f3b3728e29..214ba8d4a73 100644 --- a/layers/gpu/instrumentation/gpuav_instrumentation.h +++ b/layers/gpu/instrumentation/gpuav_instrumentation.h @@ -23,8 +23,11 @@ namespace gpuav { struct DescSetState; -void SetupShaderInstrumentationResources(Validator& gpuav, CommandBuffer& cmd_buffer, VkPipelineBindPoint bind_point, - const Location& loc); +void PreCallSetupShaderInstrumentationResources(Validator& gpuav, CommandBuffer& cb_state, VkPipelineBindPoint bind_point, + const Location& loc); + +void PostCallSetupShaderInstrumentationResources(Validator& gpuav, CommandBuffer& cb_statee, VkPipelineBindPoint bind_point, + const Location& loc); // Return true iff a error has been found bool LogInstrumentationError(Validator& gpuav, VkCommandBuffer cmd_buffer, const LogObjectList& objlist, uint32_t operation_index, diff --git a/tests/unit/gpu_av_descriptor_indexing_positive.cpp b/tests/unit/gpu_av_descriptor_indexing_positive.cpp index a544e8bac76..7bae5ece069 100644 --- a/tests/unit/gpu_av_descriptor_indexing_positive.cpp +++ b/tests/unit/gpu_av_descriptor_indexing_positive.cpp @@ -1031,4 +1031,483 @@ TEST_F(PositiveGpuAVDescriptorIndexing, PartialBoundDescriptorSSBO) { m_default_queue->Submit(*m_commandBuffer); m_default_queue->Wait(); -} \ No newline at end of file +} + +TEST_F(PositiveGpuAVDescriptorIndexing, SharedPipelineLayoutSubsetCompute) { + TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/8377"); + RETURN_IF_SKIP(InitGpuVUDescriptorIndexing()); + + VkDescriptorBindingFlags binding_flags = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT; + VkDescriptorSetLayoutBindingFlagsCreateInfo flags_create_info = vku::InitStructHelper(); + flags_create_info.bindingCount = 1; + flags_create_info.pBindingFlags = &binding_flags; + + const VkDescriptorSetLayoutBinding binding{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}; + vkt::DescriptorSetLayout dsl2(*m_device, binding, VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT, + &flags_create_info); + vkt::DescriptorSetLayout dsl1(*m_device, binding, VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT, + &flags_create_info); + VkDescriptorSetLayout set_layouts[2] = {dsl1.handle(), dsl2.handle()}; + + VkPipelineLayoutCreateInfo pipeline_layout_ci = vku::InitStructHelper(); + pipeline_layout_ci.pSetLayouts = set_layouts; + + pipeline_layout_ci.setLayoutCount = 1; + const vkt::PipelineLayout pipeline_layout_1(*m_device, pipeline_layout_ci); + pipeline_layout_ci.setLayoutCount = 2; + const vkt::PipelineLayout pipeline_layout_2(*m_device, pipeline_layout_ci); + + char const *source_1 = R"glsl( + #version 450 + layout(set = 0, binding = 0) buffer foo_0 { int a; int b;}; + void main() { + a = b; + } + )glsl"; + char const *source_2 = R"glsl( + #version 450 + layout(set = 0, binding = 0) buffer foo_0 { int a; }; + layout(set = 1, binding = 0) buffer foo_1 { int b; }; + void main() { + a = b; + } + )glsl"; + + CreateComputePipelineHelper pipe1(*this); + pipe1.cs_ = std::make_unique(this, source_1, VK_SHADER_STAGE_COMPUTE_BIT); + pipe1.cp_ci_.layout = pipeline_layout_1.handle(); + pipe1.CreateComputePipeline(); + + CreateComputePipelineHelper pipe2(*this); + pipe2.cs_ = std::make_unique(this, source_2, VK_SHADER_STAGE_COMPUTE_BIT); + pipe2.cp_ci_.layout = pipeline_layout_2.handle(); + pipe2.CreateComputePipeline(); + + VkDescriptorPoolSize pool_size = {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2}; + VkDescriptorPoolCreateInfo ds_pool_ci = vku::InitStructHelper(); + ds_pool_ci.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT; + ds_pool_ci.maxSets = 2; + ds_pool_ci.poolSizeCount = 1; + ds_pool_ci.pPoolSizes = &pool_size; + vkt::DescriptorPool pool(*m_device, ds_pool_ci); + + VkDescriptorSetAllocateInfo allocate_info = vku::InitStructHelper(); + allocate_info.descriptorPool = pool.handle(); + allocate_info.descriptorSetCount = 2; + allocate_info.pSetLayouts = set_layouts; + + VkDescriptorSet descriptor_sets[2]; + vk::AllocateDescriptorSets(device(), &allocate_info, descriptor_sets); + + vkt::Buffer buffer(*m_device, 32, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); + VkDescriptorBufferInfo buffer_info = {buffer.handle(), 0, VK_WHOLE_SIZE}; + + VkWriteDescriptorSet descriptor_writes[2]; + descriptor_writes[0] = vku::InitStructHelper(); + descriptor_writes[0].dstSet = descriptor_sets[0]; + descriptor_writes[0].dstBinding = 0; + descriptor_writes[0].descriptorCount = 1; + descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptor_writes[0].pBufferInfo = &buffer_info; + descriptor_writes[1] = vku::InitStructHelper(); + descriptor_writes[1].dstSet = descriptor_sets[1]; + descriptor_writes[1].dstBinding = 0; + descriptor_writes[1].descriptorCount = 1; + descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptor_writes[1].pBufferInfo = &buffer_info; + vk::UpdateDescriptorSets(device(), 2, descriptor_writes, 0, nullptr); + + VkCommandBufferBeginInfo begin_info = vku::InitStructHelper(); + m_commandBuffer->begin(&begin_info); + + vk::CmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout_2.handle(), 0, 2, + descriptor_sets, 0, nullptr); + + vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_COMPUTE, pipe2.Handle()); + vk::CmdDispatch(m_commandBuffer->handle(), 1, 1, 1); + + vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_COMPUTE, pipe1.Handle()); + vk::CmdDispatch(m_commandBuffer->handle(), 1, 1, 1); + + vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_COMPUTE, pipe2.Handle()); + vk::CmdDispatch(m_commandBuffer->handle(), 1, 1, 1); + + m_commandBuffer->end(); + m_default_queue->Submit(*m_commandBuffer); + m_default_queue->Wait(); +} + +TEST_F(PositiveGpuAVDescriptorIndexing, SharedPipelineLayoutSubsetGraphics) { + TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/8377"); + RETURN_IF_SKIP(InitGpuVUDescriptorIndexing()); + InitRenderTarget(); + + // Create 2 pipeline layouts. Pipeline layout 2 starts the same as pipeline layout 1, with one descriptor set, + // but one more descriptor set is added to it, for a total of 2. + // Hence, it is valid to bind all descriptor slots from pipeline layout 2, + // but use a pipeline create with pipeline layout 1 for rendering. + // BUT, + // since GPU-AV adds empty descriptor sets to pipeline layouts before adding the + // instrumentation descriptor set, it creates an incompatibility between pipeline + // layout 1 and 2 at the binding index 1: pipeline layout 1 has one empty descriptor set, + // and pipeline layout 2 as an application defined descriptor set. + // GPU-AV has to take care of this incompatibility, by picking the right pipeline layout to + // bind its instrumentation descriptor set to, and by correctly restoring disturbed application + // defined descriptor set bindings. + + VkDescriptorBindingFlags binding_flags = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT; + VkDescriptorSetLayoutBindingFlagsCreateInfo flags_create_info = vku::InitStructHelper(); + flags_create_info.bindingCount = 1; + flags_create_info.pBindingFlags = &binding_flags; + + const VkDescriptorSetLayoutBinding binding{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}; + + vkt::DescriptorSetLayout dsl_1(*m_device, binding, VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT, + &flags_create_info); + + std::array set_layouts = {dsl_1.handle(), dsl_1.handle()}; + + VkPipelineLayoutCreateInfo pipeline_layout_ci = vku::InitStructHelper(); + pipeline_layout_ci.pSetLayouts = set_layouts.data(); + + pipeline_layout_ci.setLayoutCount = 1; + const vkt::PipelineLayout pipeline_layout_1(*m_device, pipeline_layout_ci); + pipeline_layout_ci.setLayoutCount = 2; + const vkt::PipelineLayout pipeline_layout_2(*m_device, pipeline_layout_ci); + + char const *vs_source_1 = R"glsl( + #version 450 + layout(set = 0, binding = 0) buffer foo_0 { int a; int b;}; + void main() { + a = b; + } + )glsl"; + char const *vs_source_2 = R"glsl( + #version 450 + layout(set = 0, binding = 0) buffer foo_0 { int a; }; + layout(set = 1, binding = 0) buffer foo_1 { int b; }; + void main() { + a = b; + } + )glsl"; + VkShaderObj vs_1(this, vs_source_1, VK_SHADER_STAGE_VERTEX_BIT); + VkShaderObj vs_2(this, vs_source_2, VK_SHADER_STAGE_VERTEX_BIT); + + CreatePipelineHelper pipe_1(*this); + pipe_1.shader_stages_ = {vs_1.GetStageCreateInfo(), pipe_1.fs_->GetStageCreateInfo()}; + pipe_1.gp_ci_.layout = pipeline_layout_1.handle(); + pipe_1.CreateGraphicsPipeline(); + + CreatePipelineHelper pipe_2(*this); + pipe_2.shader_stages_ = {vs_2.GetStageCreateInfo(), pipe_2.fs_->GetStageCreateInfo()}; + pipe_2.gp_ci_.layout = pipeline_layout_2.handle(); + pipe_2.CreateGraphicsPipeline(); + + VkDescriptorPoolSize pool_size = {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2}; + VkDescriptorPoolCreateInfo ds_pool_ci = vku::InitStructHelper(); + ds_pool_ci.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT; + ds_pool_ci.maxSets = 2; + ds_pool_ci.poolSizeCount = 1; + ds_pool_ci.pPoolSizes = &pool_size; + vkt::DescriptorPool pool(*m_device, ds_pool_ci); + + VkDescriptorSetAllocateInfo allocate_info = vku::InitStructHelper(); + allocate_info.descriptorPool = pool.handle(); + allocate_info.descriptorSetCount = 2; + allocate_info.pSetLayouts = set_layouts.data(); + + std::array descriptor_sets{}; + vk::AllocateDescriptorSets(device(), &allocate_info, descriptor_sets.data()); + + vkt::Buffer buffer(*m_device, 32, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); + VkDescriptorBufferInfo buffer_info = {buffer.handle(), 0, VK_WHOLE_SIZE}; + + VkWriteDescriptorSet descriptor_writes[2]; + descriptor_writes[0] = vku::InitStructHelper(); + descriptor_writes[0].dstSet = descriptor_sets[0]; + descriptor_writes[0].dstBinding = 0; + descriptor_writes[0].descriptorCount = 1; + descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptor_writes[0].pBufferInfo = &buffer_info; + descriptor_writes[1] = vku::InitStructHelper(); + descriptor_writes[1].dstSet = descriptor_sets[1]; + descriptor_writes[1].dstBinding = 0; + descriptor_writes[1].descriptorCount = 1; + descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptor_writes[1].pBufferInfo = &buffer_info; + vk::UpdateDescriptorSets(device(), 2, descriptor_writes, 0, nullptr); + + VkCommandBufferBeginInfo begin_info = vku::InitStructHelper(); + m_commandBuffer->begin(&begin_info); + m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); + + vk::CmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout_2.handle(), 0, 2, + descriptor_sets.data(), 0, nullptr); + + vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_2.Handle()); + vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); + + vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_1.Handle()); + vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); + + vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_2.Handle()); + vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); + + m_commandBuffer->EndRenderPass(); + m_commandBuffer->end(); + m_default_queue->Submit(*m_commandBuffer); + m_default_queue->Wait(); +} + +TEST_F(PositiveGpuAVDescriptorIndexing, SharedPipelineLayoutSubsetGraphicsGPL) { + TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/8377"); + + AddRequiredExtensions(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME); + AddRequiredFeature(vkt::Feature::graphicsPipelineLibrary); + RETURN_IF_SKIP(InitGpuVUDescriptorIndexing()); + InitRenderTarget(); + + // Create 2 pipeline layouts. Pipeline layout 2 starts the same as pipeline layout 1, with one descriptor set, + // but one more descriptor set is added to it, for a total of 2. + // Hence, it is valid to bind all descriptor slots from pipeline layout 2, + // but use a pipeline create with pipeline layout 1 for rendering. + // BUT, + // since GPU-AV adds empty descriptor sets to pipeline layouts before adding the + // instrumentation descriptor set, it creates an incompatibility between pipeline + // layout 1 and 2 at the binding index 1: pipeline layout 1 has one empty descriptor set, + // and pipeline layout 2 as an application defined descriptor set. + // GPU-AV has to take care of this incompatibility, by picking the right pipeline layout to + // bind its instrumentation descriptor set to, and by correctly restoring disturbed application + // defined descriptor set bindings. + + VkDescriptorBindingFlags binding_flags = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT; + VkDescriptorSetLayoutBindingFlagsCreateInfo flags_create_info = vku::InitStructHelper(); + flags_create_info.bindingCount = 1; + flags_create_info.pBindingFlags = &binding_flags; + + const VkDescriptorSetLayoutBinding binding{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}; + + vkt::DescriptorSetLayout dsl_1(*m_device, binding, VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT, + &flags_create_info); + + std::array set_layouts = {dsl_1.handle(), dsl_1.handle()}; + + VkPipelineLayoutCreateInfo pipeline_layout_ci = vku::InitStructHelper(); + pipeline_layout_ci.pSetLayouts = set_layouts.data(); + + pipeline_layout_ci.setLayoutCount = 1; + const vkt::PipelineLayout pipeline_layout_1(*m_device, pipeline_layout_ci); + pipeline_layout_ci.setLayoutCount = 2; + const vkt::PipelineLayout pipeline_layout_2(*m_device, pipeline_layout_ci); + + char const *vs_source_1 = R"glsl( + #version 450 + layout(set = 0, binding = 0) buffer foo_0 { int a; int b;}; + void main() { + a = b; + } + )glsl"; + char const *vs_source_2 = R"glsl( + #version 450 + layout(set = 0, binding = 0) buffer foo_0 { int a; }; + layout(set = 1, binding = 0) buffer foo_1 { int b; }; + void main() { + a = b; + } + )glsl"; + + vkt::SimpleGPL pipe_1(*this, pipeline_layout_1.handle(), vs_source_1); + + vkt::SimpleGPL pipe_2(*this, pipeline_layout_2.handle(), vs_source_2); + + VkDescriptorPoolSize pool_size = {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2}; + VkDescriptorPoolCreateInfo ds_pool_ci = vku::InitStructHelper(); + ds_pool_ci.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT; + ds_pool_ci.maxSets = 2; + ds_pool_ci.poolSizeCount = 1; + ds_pool_ci.pPoolSizes = &pool_size; + vkt::DescriptorPool pool(*m_device, ds_pool_ci); + + VkDescriptorSetAllocateInfo allocate_info = vku::InitStructHelper(); + allocate_info.descriptorPool = pool.handle(); + allocate_info.descriptorSetCount = 2; + allocate_info.pSetLayouts = set_layouts.data(); + + std::array descriptor_sets{}; + vk::AllocateDescriptorSets(device(), &allocate_info, descriptor_sets.data()); + + vkt::Buffer buffer(*m_device, 32, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); + VkDescriptorBufferInfo buffer_info = {buffer.handle(), 0, VK_WHOLE_SIZE}; + + VkWriteDescriptorSet descriptor_writes[2]; + descriptor_writes[0] = vku::InitStructHelper(); + descriptor_writes[0].dstSet = descriptor_sets[0]; + descriptor_writes[0].dstBinding = 0; + descriptor_writes[0].descriptorCount = 1; + descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptor_writes[0].pBufferInfo = &buffer_info; + descriptor_writes[1] = vku::InitStructHelper(); + descriptor_writes[1].dstSet = descriptor_sets[1]; + descriptor_writes[1].dstBinding = 0; + descriptor_writes[1].descriptorCount = 1; + descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptor_writes[1].pBufferInfo = &buffer_info; + vk::UpdateDescriptorSets(device(), 2, descriptor_writes, 0, nullptr); + + VkCommandBufferBeginInfo begin_info = vku::InitStructHelper(); + m_commandBuffer->begin(&begin_info); + m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo); + + vk::CmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout_2.handle(), 0, 2, + descriptor_sets.data(), 0, nullptr); + + vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_2.Handle()); + vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); + + vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_1.Handle()); + vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); + + vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_2.Handle()); + vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); + + m_commandBuffer->EndRenderPass(); + m_commandBuffer->end(); + m_default_queue->Submit(*m_commandBuffer); + m_default_queue->Wait(); +} + +TEST_F(PositiveGpuAVDescriptorIndexing, SharedPipelineLayoutSubsetGraphicsShaderObject) { + TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/8377"); + AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); + AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME); + AddRequiredFeature(vkt::Feature::dynamicRendering); + AddRequiredFeature(vkt::Feature::shaderObject); + RETURN_IF_SKIP(InitGpuVUDescriptorIndexing()); + InitDynamicRenderTarget(); + + // Create 2 pipeline layouts. Pipeline layout 2 starts the same as pipeline layout 1, with one descriptor set, + // but one more descriptor set is added to it, for a total of 2. + // Hence, it is valid to bind all descriptor slots from pipeline layout 2, + // but use a pipeline create with pipeline layout 1 for rendering. + // BUT, + // since GPU-AV adds empty descriptor sets to pipeline layouts before adding the + // instrumentation descriptor set, it creates an incompatibility between pipeline + // layout 1 and 2 at the binding index 1: pipeline layout 1 has one empty descriptor set, + // and pipeline layout 2 as an application defined descriptor set. + // GPU-AV has to take care of this incompatibility, by picking the right pipeline layout to + // bind its instrumentation descriptor set to, and by correctly restoring disturbed application + // defined descriptor set bindings. + + VkDescriptorBindingFlags binding_flags = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT; + VkDescriptorSetLayoutBindingFlagsCreateInfo flags_create_info = vku::InitStructHelper(); + flags_create_info.bindingCount = 1; + flags_create_info.pBindingFlags = &binding_flags; + + const VkDescriptorSetLayoutBinding binding{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}; + + vkt::DescriptorSetLayout dsl_1(*m_device, binding, VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT, + &flags_create_info); + + std::array set_layouts = {dsl_1.handle(), dsl_1.handle()}; + + VkPipelineLayoutCreateInfo pipeline_layout_ci = vku::InitStructHelper(); + pipeline_layout_ci.pSetLayouts = set_layouts.data(); + + pipeline_layout_ci.setLayoutCount = 1; + const vkt::PipelineLayout pipeline_layout_1(*m_device, pipeline_layout_ci); + pipeline_layout_ci.setLayoutCount = 2; + const vkt::PipelineLayout pipeline_layout_2(*m_device, pipeline_layout_ci); + + char const *vs_source_1 = R"glsl( + #version 450 + layout(set = 0, binding = 0) buffer foo_0 { int a; int b;}; + void main() { + a = b; + } + )glsl"; + const std::vector vs_spv_1 = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, vs_source_1); + char const *vs_source_2 = R"glsl( + #version 450 + layout(set = 0, binding = 0) buffer foo_0 { int a; }; + layout(set = 1, binding = 0) buffer foo_1 { int b; }; + void main() { + a = b; + } + )glsl"; + const std::vector vs_spv_2 = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, vs_source_2); + + VkShaderCreateInfoEXT shader_obj_ci = vku::InitStructHelper(); + shader_obj_ci.stage = VK_SHADER_STAGE_VERTEX_BIT; + shader_obj_ci.codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT; + shader_obj_ci.codeSize = vs_spv_1.size() * sizeof(uint32_t); + shader_obj_ci.pCode = vs_spv_1.data(); + shader_obj_ci.pName = "main"; + shader_obj_ci.setLayoutCount = 1u; + shader_obj_ci.pSetLayouts = set_layouts.data(); + vkt::Shader vs_1(*m_device, shader_obj_ci); + shader_obj_ci.codeSize = vs_spv_2.size() * sizeof(uint32_t); + shader_obj_ci.pCode = vs_spv_2.data(); + shader_obj_ci.setLayoutCount = 2u; + vkt::Shader vs_2(*m_device, shader_obj_ci); + + const VkShaderStageFlagBits stages[] = {VK_SHADER_STAGE_VERTEX_BIT}; + const VkShaderEXT shaders_1[] = {vs_1.handle()}; + const VkShaderEXT shaders_2[] = {vs_2.handle()}; + + VkDescriptorPoolSize pool_size = {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2}; + VkDescriptorPoolCreateInfo ds_pool_ci = vku::InitStructHelper(); + ds_pool_ci.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT; + ds_pool_ci.maxSets = 2; + ds_pool_ci.poolSizeCount = 1; + ds_pool_ci.pPoolSizes = &pool_size; + vkt::DescriptorPool pool(*m_device, ds_pool_ci); + + VkDescriptorSetAllocateInfo allocate_info = vku::InitStructHelper(); + allocate_info.descriptorPool = pool.handle(); + allocate_info.descriptorSetCount = 2; + allocate_info.pSetLayouts = set_layouts.data(); + + std::array descriptor_sets{}; + vk::AllocateDescriptorSets(device(), &allocate_info, descriptor_sets.data()); + + vkt::Buffer buffer(*m_device, 32, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); + VkDescriptorBufferInfo buffer_info = {buffer.handle(), 0, VK_WHOLE_SIZE}; + + VkWriteDescriptorSet descriptor_writes[2]; + descriptor_writes[0] = vku::InitStructHelper(); + descriptor_writes[0].dstSet = descriptor_sets[0]; + descriptor_writes[0].dstBinding = 0; + descriptor_writes[0].descriptorCount = 1; + descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptor_writes[0].pBufferInfo = &buffer_info; + descriptor_writes[1] = vku::InitStructHelper(); + descriptor_writes[1].dstSet = descriptor_sets[1]; + descriptor_writes[1].dstBinding = 0; + descriptor_writes[1].descriptorCount = 1; + descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptor_writes[1].pBufferInfo = &buffer_info; + vk::UpdateDescriptorSets(device(), 2, descriptor_writes, 0, nullptr); + + VkCommandBufferBeginInfo begin_info = vku::InitStructHelper(); + m_commandBuffer->begin(&begin_info); + m_commandBuffer->BeginRenderingColor(GetDynamicRenderTarget(), GetRenderTargetArea()); + + vk::CmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout_2.handle(), 0, 2, + descriptor_sets.data(), 0, nullptr); + + vk::CmdBindShadersEXT(m_commandBuffer->handle(), 1u, stages, shaders_2); + SetDefaultDynamicStatesAll(m_commandBuffer->handle()); + + vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); + + vk::CmdBindShadersEXT(m_commandBuffer->handle(), 1u, stages, shaders_1); + vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); + + vk::CmdBindShadersEXT(m_commandBuffer->handle(), 1u, stages, shaders_2); + vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0); + + m_commandBuffer->EndRendering(); + m_commandBuffer->end(); + m_default_queue->Submit(*m_commandBuffer); + m_default_queue->Wait(); +} diff --git a/tests/unit/gpu_av_positive.cpp b/tests/unit/gpu_av_positive.cpp index e7abbf23989..ca9d9320b46 100644 --- a/tests/unit/gpu_av_positive.cpp +++ b/tests/unit/gpu_av_positive.cpp @@ -1730,3 +1730,80 @@ TEST_F(PositiveGpuAV, PipelineLayoutMixing) { m_default_queue->Submit(*m_commandBuffer); m_default_queue->Wait(); } + +TEST_F(PositiveGpuAV, SharedPipelineLayoutSubset) { + TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/8377"); + RETURN_IF_SKIP(InitGpuAvFramework()); + RETURN_IF_SKIP(InitState()); + + const VkDescriptorSetLayoutBinding binding{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}; + vkt::DescriptorSetLayout dsl1(*m_device, binding); + vkt::DescriptorSetLayout dsl2(*m_device, binding); + VkDescriptorSetLayout set_layouts[2] = {dsl1.handle(), dsl2.handle()}; + + VkPipelineLayoutCreateInfo pipeline_layout_ci = vku::InitStructHelper(); + pipeline_layout_ci.pSetLayouts = set_layouts; + + pipeline_layout_ci.setLayoutCount = 1; + const vkt::PipelineLayout pipeline_layout_1(*m_device, pipeline_layout_ci); + pipeline_layout_ci.setLayoutCount = 2; + const vkt::PipelineLayout pipeline_layout_2(*m_device, pipeline_layout_ci); + + char const *cs_source = R"glsl( + #version 450 + layout(set = 0, binding = 0) buffer foo_0 { int a; int b;}; + void main() { + a = b; + } + )glsl"; + CreateComputePipelineHelper pipe(*this); + pipe.cs_ = std::make_unique(this, cs_source, VK_SHADER_STAGE_COMPUTE_BIT); + pipe.cp_ci_.layout = pipeline_layout_1.handle(); + pipe.CreateComputePipeline(); + + VkDescriptorPoolSize pool_size = {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2}; + VkDescriptorPoolCreateInfo ds_pool_ci = vku::InitStructHelper(); + ds_pool_ci.maxSets = 2; + ds_pool_ci.poolSizeCount = 1; + ds_pool_ci.pPoolSizes = &pool_size; + vkt::DescriptorPool pool(*m_device, ds_pool_ci); + + VkDescriptorSetAllocateInfo allocate_info = vku::InitStructHelper(); + allocate_info.descriptorPool = pool.handle(); + allocate_info.descriptorSetCount = 2; + allocate_info.pSetLayouts = set_layouts; + + VkDescriptorSet descriptor_sets[2]; + vk::AllocateDescriptorSets(device(), &allocate_info, descriptor_sets); + + vkt::Buffer buffer(*m_device, 32, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); + VkDescriptorBufferInfo buffer_info = {buffer.handle(), 0, VK_WHOLE_SIZE}; + + VkWriteDescriptorSet descriptor_writes[2]; + descriptor_writes[0] = vku::InitStructHelper(); + descriptor_writes[0].dstSet = descriptor_sets[0]; + descriptor_writes[0].dstBinding = 0; + descriptor_writes[0].descriptorCount = 1; + descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptor_writes[0].pBufferInfo = &buffer_info; + descriptor_writes[1] = vku::InitStructHelper(); + descriptor_writes[1].dstSet = descriptor_sets[1]; + descriptor_writes[1].dstBinding = 0; + descriptor_writes[1].descriptorCount = 1; + descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptor_writes[1].pBufferInfo = &buffer_info; + vk::UpdateDescriptorSets(device(), 2, descriptor_writes, 0, nullptr); + + VkCommandBufferBeginInfo begin_info = vku::InitStructHelper(); + m_commandBuffer->begin(&begin_info); + + vk::CmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout_2.handle(), 0, 2, + descriptor_sets, 0, nullptr); + + vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_COMPUTE, pipe.Handle()); + vk::CmdDispatch(m_commandBuffer->handle(), 1, 1, 1); + + m_commandBuffer->end(); + m_default_queue->Submit(*m_commandBuffer); + m_default_queue->Wait(); +} \ No newline at end of file