From 60fe43b78c44c239019ade576016613000d622f8 Mon Sep 17 00:00:00 2001 From: spencer-lunarg Date: Fri, 17 Apr 2026 16:06:06 +0200 Subject: [PATCH] tests: Add Heap with Mesh shading --- layers/core_checks/cc_drawdispatch.cpp | 12 +- tests/unit/debug_printf.cpp | 208 ++++++++++++++++++------- 2 files changed, 160 insertions(+), 60 deletions(-) diff --git a/layers/core_checks/cc_drawdispatch.cpp b/layers/core_checks/cc_drawdispatch.cpp index 4d7240a6e48..50bce4b9b1c 100644 --- a/layers/core_checks/cc_drawdispatch.cpp +++ b/layers/core_checks/cc_drawdispatch.cpp @@ -155,12 +155,12 @@ bool CoreChecks::ValidateVTGShaderStages(const LastBound& last_bound_state, cons if (last_bound_state.pipeline_state && last_bound_state.pipeline_state->active_shaders & (VK_SHADER_STAGE_TASK_BIT_EXT | VK_SHADER_STAGE_MESH_BIT_EXT)) { - skip |= LogError( - CreateActionVuid(loc.function, vvl::ActionVUID::INVALID_MESH_SHADER_STAGES_06481), - last_bound_state.cb_state.GetObjectList(VK_PIPELINE_BIND_POINT_GRAPHICS), loc, - "The bound graphics pipeline must not have been created with " - "VK_SHADER_STAGE_TASK_BIT_EXT or VK_SHADER_STAGE_MESH_BIT_EXT. Active shader stages on the bound pipeline are %s.", - string_VkShaderStageFlags(last_bound_state.pipeline_state->active_shaders).c_str()); + skip |= LogError(CreateActionVuid(loc.function, vvl::ActionVUID::INVALID_MESH_SHADER_STAGES_06481), + last_bound_state.cb_state.GetObjectList(VK_PIPELINE_BIND_POINT_GRAPHICS), loc, + "The bound graphics pipeline must not have been created with " + "VK_SHADER_STAGE_TASK_BIT_EXT or VK_SHADER_STAGE_MESH_BIT_EXT (you need to use something like " + "vkCmdDrawMeshTasksEXT instead).\nActive shader stages on the bound pipeline are %s.", + string_VkShaderStageFlags(last_bound_state.pipeline_state->active_shaders).c_str()); } return skip; } diff --git a/tests/unit/debug_printf.cpp b/tests/unit/debug_printf.cpp index c6cdb18192b..cdbb5a8ce63 100644 --- a/tests/unit/debug_printf.cpp +++ b/tests/unit/debug_printf.cpp @@ -5779,18 +5779,12 @@ TEST_F(NegativeDebugPrintf, DescriptorHeap) { vkt::device_address); const auto descriptor_heap_ptr = static_cast(descriptor_heap.Memory().Map()); - VkHostAddressRangeEXT descriptor_host; - descriptor_host.address = descriptor_heap_ptr; - descriptor_host.size = static_cast(heap_props.bufferDescriptorSize); - - VkDeviceAddressRangeEXT device_range; - device_range.address = buffer_data.Address(); - device_range.size = 16; + VkHostAddressRangeEXT descriptor_host{descriptor_heap_ptr, static_cast(heap_props.bufferDescriptorSize)}; + VkDeviceAddressRangeEXT device_range = buffer_data.AddressRange(); VkResourceDescriptorInfoEXT descriptor_info = vku::InitStructHelper(); descriptor_info.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; descriptor_info.data.pAddressRange = &device_range; - vk::WriteResourceDescriptorsEXT(*m_device, 1u, &descriptor_info, &descriptor_host); const char* cs_source = R"glsl( @@ -5896,18 +5890,12 @@ TEST_F(NegativeDebugPrintf, DescriptorHeapGraphics) { vkt::device_address); const auto descriptor_heap_ptr = static_cast(descriptor_heap.Memory().Map()); - VkHostAddressRangeEXT descriptor_host; - descriptor_host.address = descriptor_heap_ptr; - descriptor_host.size = static_cast(heap_props.bufferDescriptorSize); - - VkDeviceAddressRangeEXT device_range; - device_range.address = buffer_data.Address(); - device_range.size = 16; + VkHostAddressRangeEXT descriptor_host{descriptor_heap_ptr, static_cast(heap_props.bufferDescriptorSize)}; + VkDeviceAddressRangeEXT device_range = buffer_data.AddressRange(); VkResourceDescriptorInfoEXT descriptor_info = vku::InitStructHelper(); descriptor_info.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; descriptor_info.data.pAddressRange = &device_range; - vk::WriteResourceDescriptorsEXT(*m_device, 1u, &descriptor_info, &descriptor_host); const char* vs_source = R"glsl( @@ -6005,13 +5993,8 @@ TEST_F(NegativeDebugPrintf, DescriptorHeapUntypedPointers) { vkt::device_address); const auto descriptor_heap_ptr = static_cast(descriptor_heap.Memory().Map()); - VkHostAddressRangeEXT descriptor_host; - descriptor_host.address = descriptor_heap_ptr; - descriptor_host.size = static_cast(heap_props.bufferDescriptorSize); - - VkDeviceAddressRangeEXT device_range; - device_range.address = buffer_data.Address(); - device_range.size = size; + VkHostAddressRangeEXT descriptor_host{descriptor_heap_ptr, static_cast(heap_props.bufferDescriptorSize)}; + VkDeviceAddressRangeEXT device_range{buffer_data.Address(), size}; VkResourceDescriptorInfoEXT descriptor_info = vku::InitStructHelper(); descriptor_info.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; @@ -6093,18 +6076,12 @@ TEST_F(NegativeDebugPrintf, DescriptorHeapGPL) { vkt::device_address); const auto descriptor_heap_ptr = static_cast(descriptor_heap.Memory().Map()); - VkHostAddressRangeEXT descriptor_host; - descriptor_host.address = descriptor_heap_ptr; - descriptor_host.size = static_cast(heap_props.bufferDescriptorSize); - - VkDeviceAddressRangeEXT device_range; - device_range.address = buffer_data.Address(); - device_range.size = 16; + VkHostAddressRangeEXT descriptor_host{descriptor_heap_ptr, static_cast(heap_props.bufferDescriptorSize)}; + VkDeviceAddressRangeEXT device_range = buffer_data.AddressRange(); VkResourceDescriptorInfoEXT descriptor_info = vku::InitStructHelper(); descriptor_info.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; descriptor_info.data.pAddressRange = &device_range; - vk::WriteResourceDescriptorsEXT(*m_device, 1u, &descriptor_info, &descriptor_host); const char* vs_source = R"glsl( @@ -6232,18 +6209,12 @@ TEST_F(NegativeDebugPrintf, DescriptorHeapShaderObjects) { vkt::device_address); const auto descriptor_heap_ptr = static_cast(descriptor_heap.Memory().Map()); - VkHostAddressRangeEXT descriptor_host; - descriptor_host.address = descriptor_heap_ptr; - descriptor_host.size = static_cast(heap_props.bufferDescriptorSize); - - VkDeviceAddressRangeEXT device_range; - device_range.address = buffer_data.Address(); - device_range.size = 16; + VkHostAddressRangeEXT descriptor_host{descriptor_heap_ptr, static_cast(heap_props.bufferDescriptorSize)}; + VkDeviceAddressRangeEXT device_range = buffer_data.AddressRange(); VkResourceDescriptorInfoEXT descriptor_info = vku::InitStructHelper(); descriptor_info.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; descriptor_info.data.pAddressRange = &device_range; - vk::WriteResourceDescriptorsEXT(*m_device, 1u, &descriptor_info, &descriptor_host); const char* cs_source = R"glsl( @@ -6379,18 +6350,12 @@ TEST_F(NegativeDebugPrintf, DeviceLocalHeap) { vkt::Buffer copy_src(*m_device, resource_heap_size_app, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, kHostVisibleMemProps); const auto descriptor_heap_ptr = static_cast(copy_src.Memory().Map()); - VkHostAddressRangeEXT descriptor_host; - descriptor_host.address = descriptor_heap_ptr; - descriptor_host.size = static_cast(heap_props.bufferDescriptorSize); - - VkDeviceAddressRangeEXT device_range; - device_range.address = buffer_data.Address(); - device_range.size = 16; + VkHostAddressRangeEXT descriptor_host{descriptor_heap_ptr, static_cast(heap_props.bufferDescriptorSize)}; + VkDeviceAddressRangeEXT device_range = buffer_data.AddressRange(); VkResourceDescriptorInfoEXT descriptor_info = vku::InitStructHelper(); descriptor_info.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; descriptor_info.data.pAddressRange = &device_range; - vk::WriteResourceDescriptorsEXT(*m_device, 1u, &descriptor_info, &descriptor_host); const char* cs_source = R"glsl( @@ -6502,13 +6467,8 @@ TEST_F(NegativeDebugPrintf, DeviceLocalHeapGraphics) { vkt::Buffer copy_src(*m_device, resource_heap_size_app, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, kHostVisibleMemProps); const auto descriptor_heap_ptr = static_cast(copy_src.Memory().Map()); - VkHostAddressRangeEXT descriptor_host; - descriptor_host.address = descriptor_heap_ptr; - descriptor_host.size = static_cast(heap_props.bufferDescriptorSize); - - VkDeviceAddressRangeEXT device_range; - device_range.address = buffer_data.Address(); - device_range.size = 16; + VkHostAddressRangeEXT descriptor_host{descriptor_heap_ptr, static_cast(heap_props.bufferDescriptorSize)}; + VkDeviceAddressRangeEXT device_range = buffer_data.AddressRange(); VkResourceDescriptorInfoEXT descriptor_info = vku::InitStructHelper(); descriptor_info.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; @@ -6599,6 +6559,146 @@ TEST_F(NegativeDebugPrintf, DeviceLocalHeapGraphics) { m_errorMonitor->VerifyFound(); } +TEST_F(NegativeDebugPrintf, DeviceLocalHeapMesh) { + SetTargetApiVersion(VK_API_VERSION_1_3); + AddRequiredExtensions(VK_EXT_DESCRIPTOR_HEAP_EXTENSION_NAME); + AddRequiredExtensions(VK_EXT_MESH_SHADER_EXTENSION_NAME); + AddRequiredFeature(vkt::Feature::descriptorHeap); + AddRequiredFeature(vkt::Feature::bufferDeviceAddress); + AddRequiredFeature(vkt::Feature::vertexPipelineStoresAndAtomics); + AddRequiredFeature(vkt::Feature::synchronization2); + AddRequiredFeature(vkt::Feature::maintenance4); + AddRequiredFeature(vkt::Feature::taskShader); + AddRequiredFeature(vkt::Feature::meshShader); + RETURN_IF_SKIP(InitDebugPrintfFramework()); + RETURN_IF_SKIP(InitState()); + InitRenderTarget(); + + VkPhysicalDeviceDescriptorHeapPropertiesEXT heap_props = vku::InitStructHelper(); + GetPhysicalDeviceProperties2(heap_props); + + vkt::Buffer buffer_data(*m_device, 16, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, vkt::device_address); + uint32_t* data = (uint32_t*)buffer_data.Memory().Map(); + data[0] = 8; + data[1] = 12; + data[2] = 1; + + VkDeviceSize resource_heap_size_app = Align(heap_props.bufferDescriptorSize, heap_props.bufferDescriptorAlignment); + resource_heap_size_app = Align(resource_heap_size_app, heap_props.imageDescriptorAlignment); + const VkDeviceSize resource_heap_size_driver = resource_heap_size_app + heap_props.minResourceHeapReservedRange; + + VkMemoryAllocateFlagsInfo allocate_flag_info = vku::InitStructHelper(); + allocate_flag_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT; + vkt::Buffer descriptor_heap( + *m_device, resource_heap_size_driver, + VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &allocate_flag_info); + + vkt::Buffer copy_src(*m_device, resource_heap_size_app, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, kHostVisibleMemProps); + const auto descriptor_heap_ptr = static_cast(copy_src.Memory().Map()); + + VkHostAddressRangeEXT descriptor_host{descriptor_heap_ptr, static_cast(heap_props.bufferDescriptorSize)}; + VkDeviceAddressRangeEXT device_range = buffer_data.AddressRange(); + + VkResourceDescriptorInfoEXT descriptor_info = vku::InitStructHelper(); + descriptor_info.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptor_info.data.pAddressRange = &device_range; + vk::WriteResourceDescriptorsEXT(*m_device, 1u, &descriptor_info, &descriptor_host); + + const char* task_source = R"glsl( + #version 460 + #extension GL_EXT_mesh_shader : require + #extension GL_EXT_debug_printf : enable + layout (local_size_x=1, local_size_y=1, local_size_z=1) in; + void main() { + EmitMeshTasksEXT(1u, 1u, 1u); + } + )glsl"; + + const char* mesh_source = R"glsl( + #version 460 + #extension GL_EXT_mesh_shader : require + #extension GL_EXT_debug_printf : enable + layout(max_vertices = 3, max_primitives=1) out; + layout(triangles) out; + layout (set = 0, binding = 0) buffer SSBO_0 { + uint a; + uint b; + uint c; + }; + void main() { + c = a + b; + debugPrintfEXT("c == %u\n", c); + } + )glsl"; + + VkDescriptorSetAndBindingMappingEXT mapping = vku::InitStructHelper(); + mapping.descriptorSet = 0; + mapping.firstBinding = 0; + mapping.bindingCount = 1; + mapping.resourceMask = VK_SPIRV_RESOURCE_TYPE_ALL_EXT; + mapping.source = VK_DESCRIPTOR_MAPPING_SOURCE_HEAP_WITH_CONSTANT_OFFSET_EXT; + mapping.sourceData.constantOffset.heapOffset = 0; + mapping.sourceData.constantOffset.heapArrayStride = 0; + + VkShaderDescriptorSetAndBindingMappingInfoEXT mapping_info = vku::InitStructHelper(); + mapping_info.mappingCount = 1u; + mapping_info.pMappings = &mapping; + + VkShaderObj ts_module = VkShaderObj(*m_device, task_source, VK_SHADER_STAGE_TASK_BIT_EXT, SPV_ENV_VULKAN_1_3); + VkShaderObj ms_module = VkShaderObj(*m_device, mesh_source, VK_SHADER_STAGE_MESH_BIT_EXT, SPV_ENV_VULKAN_1_3); + VkShaderObj fs_module = VkShaderObj(*m_device, kFragmentMinimalGlsl, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_3); + + VkPipelineCreateFlags2CreateInfoKHR pipeline_create_flags_2_create_info = vku::InitStructHelper(); + pipeline_create_flags_2_create_info.flags = VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT; + + VkPipelineShaderStageCreateInfo stages[3] = {ts_module.GetStageCreateInfo(), ms_module.GetStageCreateInfo(), + fs_module.GetStageCreateInfo()}; + stages[0].pNext = &mapping_info; // unused + stages[1].pNext = &mapping_info; + + CreatePipelineHelper pipe(*this, &pipeline_create_flags_2_create_info); + pipe.gp_ci_.layout = VK_NULL_HANDLE; + pipe.gp_ci_.stageCount = 3; + pipe.gp_ci_.pStages = stages; + pipe.CreateGraphicsPipeline(false); + + VkBindHeapInfoEXT bind_resource_info = vku::InitStructHelper(); + bind_resource_info.heapRange.address = descriptor_heap.Address(); + bind_resource_info.heapRange.size = resource_heap_size_driver; + bind_resource_info.reservedRangeOffset = resource_heap_size_app; + bind_resource_info.reservedRangeSize = heap_props.minResourceHeapReservedRange; + + VkBufferCopy copy_region; + copy_region.srcOffset = 0u; + copy_region.dstOffset = 0u; + copy_region.size = resource_heap_size_app; + + VkMemoryBarrier2 memory_barrier = vku::InitStructHelper(); + memory_barrier.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT; + memory_barrier.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT; + memory_barrier.dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + memory_barrier.dstAccessMask = VK_ACCESS_2_RESOURCE_HEAP_READ_BIT_EXT | VK_ACCESS_2_SAMPLER_HEAP_READ_BIT_EXT; + + VkDependencyInfo dependency_info = vku::InitStructHelper(); + dependency_info.memoryBarrierCount = 1u; + dependency_info.pMemoryBarriers = &memory_barrier; + + m_command_buffer.Begin(); + vk::CmdCopyBuffer(m_command_buffer, copy_src, descriptor_heap, 1u, ©_region); + vk::CmdPipelineBarrier2(m_command_buffer, &dependency_info); + vk::CmdBindResourceHeapEXT(m_command_buffer, &bind_resource_info); + m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); + vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); + vk::CmdDrawMeshTasksEXT(m_command_buffer, 1, 1, 1); + m_command_buffer.EndRenderPass(); + m_command_buffer.End(); + + m_errorMonitor->SetDesiredInfo("c == 20"); + m_default_queue->SubmitAndWait(m_command_buffer); + m_errorMonitor->VerifyFound(); +} + void NegativeDebugPrintf::CoopMat2CallbackTest(const char* shader_source, const char* message) { AddRequiredExtensions(VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME); AddRequiredExtensions(VK_NV_COOPERATIVE_MATRIX_2_EXTENSION_NAME);