From b23e9f6b3729421255e6c017d1465828da6d2497 Mon Sep 17 00:00:00 2001 From: Jake Turner Date: Thu, 4 Jan 2024 15:47:40 +0000 Subject: [PATCH] SPIRV KHR BDA Tests added to vk_shader_debug_zoo Load buffer address from push constants as a uvec2 and bitcast to a pointer Load vec4 from the buffer address pointer Bitcast uint2 address to a pointer and load from the pointer OpPtrAccessChain : float[] : ArrayStride 4 OpPtrAccessChain : float[] : ArrayStride 8 OpPtrAccessChain : float[] : ArrayStride 12 Convert u64 address to a pointer and load from the pointer Convert u64 address to a pointer and back to a u64 address, load from the address Arithmetic on a u64 address then convert u64 address to a pointer and load from the pointer Generate a u64 address using arithmetic on two u32 values and load from the address --- util/test/demos/test_common.h | 10 + util/test/demos/vk/vk_shader_debug_zoo.cpp | 260 ++++++++++++++++++++- 2 files changed, 266 insertions(+), 4 deletions(-) diff --git a/util/test/demos/test_common.h b/util/test/demos/test_common.h index cb40ed541..5952e76e3 100644 --- a/util/test/demos/test_common.h +++ b/util/test/demos/test_common.h @@ -158,6 +158,16 @@ struct Vec4u uint32_t x, y, z, w; }; +struct Vec2u +{ + Vec2u(uint32_t X = 0, uint32_t Y = 0) + { + x = X; + y = Y; + } + uint32_t x, y; +}; + struct DefaultA2V { Vec3f pos; diff --git a/util/test/demos/vk/vk_shader_debug_zoo.cpp b/util/test/demos/vk/vk_shader_debug_zoo.cpp index 15c52c3e4..6ec35b604 100644 --- a/util/test/demos/vk/vk_shader_debug_zoo.cpp +++ b/util/test/demos/vk/vk_shader_debug_zoo.cpp @@ -39,6 +39,20 @@ RD_TEST(VK_Shader_Debug_Zoo, VulkanGraphicsTest) Vec2f uv; }; + struct PushData + { + Vec4i push; + Vec2u bda_uvec2; + uint32_t bda_hi; + uint32_t bda_lo; + uint64_t bda_u64; + }; + + struct BDA_Data + { + float f32[8]; + }; + std::string v2f = R"EOSHADER( @@ -2941,6 +2955,91 @@ OpBranch %_bottomlabel "%_break_{0} = OpLabel\n", intTypes[i], caseLiterals[i])}); } + + // test buffer device address + if(bdaFeatures.bufferDeviceAddress) + { + // bitcast uint2 address to pointer + append_tests({ + R"EOTEST( +%_ptr_addr_bda_data_struct = OpAccessChain %ptr_PushConstant_uint2 %push_data %int_1 +%_addr_bda_data_struct = OpLoad %uint2 %_ptr_addr_bda_data_struct +%_ptr_bda_data_struct = OpBitcast %ptr_PhysicalStorageBuffer_bda_data_struct %_addr_bda_data_struct +%_ptr_first = OpAccessChain %ptr_PhysicalStorageBuffer_bda_data_struct_first %_ptr_bda_data_struct %int_0 +%_out_float4 = OpLoad %float4 %_ptr_first Aligned 16 +)EOTEST", + // OpPtrAccessChain : float[] : ArrayStride 4 + R"EOTEST( +%_ptr_addr_bda_data_struct = OpAccessChain %ptr_PushConstant_uint2 %push_data %int_1 +%_addr_bda_data_struct = OpLoad %uint2 %_ptr_addr_bda_data_struct +%_ptr_bda_data_struct = OpBitcast %ptr_PhysicalStorageBuffer_bda_data_struct_f32_4 %_addr_bda_data_struct +%_ptr_f32 = OpPtrAccessChain %ptr_PhysicalStorageBuffer_f32 %_ptr_bda_data_struct %int_dyn_1 +%_out_float = OpLoad %float %_ptr_f32 Aligned 16 +)EOTEST", + // OpPtrAccessChain : float[] : ArrayStride 8 + R"EOTEST( +%_ptr_addr_bda_data_struct = OpAccessChain %ptr_PushConstant_uint2 %push_data %int_1 +%_addr_bda_data_struct = OpLoad %uint2 %_ptr_addr_bda_data_struct +%_ptr_bda_data_struct = OpBitcast %ptr_PhysicalStorageBuffer_bda_data_struct_f32_8 %_addr_bda_data_struct +%_ptr_f32 = OpPtrAccessChain %ptr_PhysicalStorageBuffer_f32 %_ptr_bda_data_struct %int_dyn_1 +%_out_float = OpLoad %float %_ptr_f32 Aligned 16 +)EOTEST", + // OpPtrAccessChain : float[] : ArrayStride 12 + R"EOTEST( +%_ptr_addr_bda_data_struct = OpAccessChain %ptr_PushConstant_uint2 %push_data %int_1 +%_addr_bda_data_struct = OpLoad %uint2 %_ptr_addr_bda_data_struct +%_ptr_bda_data_struct = OpBitcast %ptr_PhysicalStorageBuffer_bda_data_struct_f32_12 %_addr_bda_data_struct +%_ptr_f32 = OpPtrAccessChain %ptr_PhysicalStorageBuffer_f32 %_ptr_bda_data_struct %int_dyn_1 +%_out_float = OpLoad %float %_ptr_f32 Aligned 16 +)EOTEST", + }); + if(features.shaderInt64) + { + append_tests({ + // Convert u64 address to pointer + R"EOTEST( +%_ptr_addr_bda_data_struct = OpAccessChain %ptr_PushConstant_u64 %push_data %int_4 +%_addr_bda_data_struct = OpLoad %u64 %_ptr_addr_bda_data_struct +%_ptr_bda_data_struct = OpConvertUToPtr %ptr_PhysicalStorageBuffer_bda_data_struct %_addr_bda_data_struct +%_ptr_first = OpAccessChain %ptr_PhysicalStorageBuffer_bda_data_struct_first %_ptr_bda_data_struct %int_1 +%_out_float4 = OpLoad %float4 %_ptr_first Aligned 16 +)EOTEST", + // Convert u64 address to pointer back to u64 address + R"EOTEST( +%_ptr_addr_bda_data_struct = OpAccessChain %ptr_PushConstant_u64 %push_data %int_4 +%_addr = OpLoad %u64 %_ptr_addr_bda_data_struct +%_addr_bda_data_struct = OpIAdd %u64 %_addr %u64_dyn_8 +%_ptr_bda_data_struct = OpConvertUToPtr %ptr_PhysicalStorageBuffer_bda_data_struct %_addr_bda_data_struct +%_out_u64 = OpConvertPtrToU %u64 %_ptr_bda_data_struct +)EOTEST", + // arithmetic on u64 address then convert u64 address to pointer + R"EOTEST( +%_ptr_addr_bda_data_struct = OpAccessChain %ptr_PushConstant_u64 %push_data %int_4 +%_addr = OpLoad %u64 %_ptr_addr_bda_data_struct +%_addr2 = OpIAdd %u64 %_addr %u64_dyn_1023 +%_addr3 = OpISub %u64 %_addr2 %u64_dyn_1023 +%_addr_bda_data_struct = OpIAdd %u64 %_addr3 %u64_dyn_16 +%_ptr_bda_data_struct = OpConvertUToPtr %ptr_PhysicalStorageBuffer_bda_data_struct %_addr_bda_data_struct +%_ptr_first = OpInBoundsAccessChain %ptr_PhysicalStorageBuffer_bda_data_struct_first %_ptr_bda_data_struct %int_0 +%_out_float4 = OpLoad %float4 %_ptr_first Aligned 16 +)EOTEST", + // form u64 address by arithmetic from two u32 values + R"EOTEST( +%_ptr_addr_bda_data_struct_hi = OpAccessChain %ptr_PushConstant_uint %push_data %int_2 +%_addr_bda_data_struct_hi = OpLoad %uint %_ptr_addr_bda_data_struct_hi +%_ptr_addr_bda_data_struct_lo = OpAccessChain %ptr_PushConstant_uint %push_data %int_3 +%_addr_bda_data_struct_lo = OpLoad %uint %_ptr_addr_bda_data_struct_lo +%_addr_u64_hi = OpUConvert %u64 %_addr_bda_data_struct_hi +%_addr_u64_lo = OpUConvert %u64 %_addr_bda_data_struct_lo +%_addr_u64 = OpShiftLeftLogical %u64 %_addr_u64_hi %uint_32 +%_addr_bda_data_struct = OpIAdd %u64 %_addr_u64 %_addr_u64_lo +%_ptr_bda_data_struct = OpConvertUToPtr %ptr_PhysicalStorageBuffer_bda_data_struct %_addr_bda_data_struct +%_ptr_first = OpAccessChain %ptr_PhysicalStorageBuffer_bda_data_struct_first %_ptr_bda_data_struct %int_0 +%_out_float4 = OpLoad %float4 %_ptr_first Aligned 16 +)EOTEST", + }); + } + } } std::string make_pixel_asm() @@ -3436,6 +3535,58 @@ OpBranch %_bottomlabel capabilities += "OpCapability Int16\n"; } + if(bdaFeatures.bufferDeviceAddress) + { + capabilities += "OpCapability PhysicalStorageBufferAddresses\n"; + spv_extensions += R"EOSHADER( + OpExtension "SPV_KHR_physical_storage_buffer" +)EOSHADER"; + + typesConstants += "%pushdata_struct = OpTypeStruct %int4 %uint2 %uint %uint"; + if(features.shaderInt64) + typesConstants += " %u64\n"; + else + typesConstants += " %uint2\n"; + + typesConstants += R"EOSHADER( +%ptr_PushConstant_pushdata_struct = OpTypePointer PushConstant %pushdata_struct +%push_data = OpVariable %ptr_PushConstant_pushdata_struct PushConstant + +%ptr_PushConstant_uint = OpTypePointer PushConstant %uint +%ptr_PushConstant_uint2 = OpTypePointer PushConstant %uint2 + )EOSHADER"; + + if(features.shaderInt64) + typesConstants += "%ptr_PushConstant_u64 = OpTypePointer PushConstant %u64\n"; + + typesConstants += "%bda_data_struct = OpTypeStruct %float4 %float4"; + + typesConstants += R"EOSHADER( +%ptr_PhysicalStorageBuffer_bda_data_struct = OpTypePointer PhysicalStorageBuffer %bda_data_struct +%ptr_PhysicalStorageBuffer_bda_data_struct_first = OpTypePointer PhysicalStorageBuffer %float4 +%ptr_PhysicalStorageBuffer_bda_data_struct_f32_4 = OpTypePointer PhysicalStorageBuffer %float +%ptr_PhysicalStorageBuffer_bda_data_struct_f32_8 = OpTypePointer PhysicalStorageBuffer %float +%ptr_PhysicalStorageBuffer_bda_data_struct_f32_12 = OpTypePointer PhysicalStorageBuffer %float +%ptr_PhysicalStorageBuffer_f32 = OpTypePointer PhysicalStorageBuffer %float + )EOSHADER"; + + decorations += R"EOSHADER( +OpDecorate %ptr_PhysicalStorageBuffer_bda_data_struct_f32_4 ArrayStride 4 +OpDecorate %ptr_PhysicalStorageBuffer_bda_data_struct_f32_8 ArrayStride 8 +OpDecorate %ptr_PhysicalStorageBuffer_bda_data_struct_f32_12 ArrayStride 12 +OpDecorate %pushdata_struct Block +OpMemberDecorate %pushdata_struct 0 Offset 16 ; int4 data +OpMemberDecorate %pushdata_struct 1 Offset 32 ; uint2 bda_uvec2 +OpMemberDecorate %pushdata_struct 2 Offset 40 ; uint bda_hi +OpMemberDecorate %pushdata_struct 3 Offset 44 ; uint bda_lo +OpMemberDecorate %pushdata_struct 4 Offset 48 ; uint64_t bda_u64 + +OpDecorate %bda_data_struct Block +OpMemberDecorate %bda_data_struct 0 Offset 0 ; float f32[0..3] +OpMemberDecorate %bda_data_struct 1 Offset 16 ; float f32[4..7] +)EOSHADER"; + } + std::string cbuffer = "%cbuffer_struct = OpTypeStruct %float4 %float4 %float4 %float4 %float4 %float4 %float4 " " %float4 %float4 %float4 %float4 %float4 %uint %uint %uint " @@ -3582,9 +3733,13 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource )EOSHADER"; + std::string memory_model = + (bdaFeatures.bufferDeviceAddress) ? "PhysicalStorageBuffer64" : "Logical"; std::string ret = capabilities + spv_extensions + extinstimport + R"EOSHADER( - OpMemoryModel Logical GLSL450 + OpMemoryModel )EOSHADER" + + memory_model + " GLSL450\n" + + R"EOSHADER( OpEntryPoint Fragment %main "main" %flatData %linearData %Color %gl_FragCoord )EOSHADER" + executionmodes + spv_debug + decorations + typesConstants + functions + @@ -3639,6 +3794,13 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource if(features.shaderFloat64) ret += "%zerof64 = OpFConvert %double %zerof\n"; + if(features.shaderInt64) + { + ret += + "%_temp = OpCompositeConstruct %uint2 %zerou %zerou\n" + "%zerou64 = OpBitcast %u64 %_temp\n"; + } + // generate dynamic versions of the constants for(float f : float_constants) { @@ -3669,6 +3831,9 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource for(uint32_t u : uint_constants) ret += fmt::format("%uint_dyn_{0} = OpIAdd %uint %zerou %uint_{0}\n", u); + for(uint64_t u : u64_constants) + ret += fmt::format("%u64_dyn_{0} = OpIAdd %u64 %zerou64 %u64_{0}\n", u); + ret += "\n"; for(size_t i = 0; i < 32; i++) @@ -3717,6 +3882,9 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource VkPhysicalDeviceFloat16Int8FeaturesKHR float16Int8Features = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR, }; + VkPhysicalDeviceBufferDeviceAddressFeaturesEXT bdaFeatures = { + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR, + }; void Prepare(int argc, char **argv) { @@ -3734,6 +3902,9 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource // dependencies of VK_KHR_8bit_storage optDevExts.push_back(VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME); + // add BDA extension + optDevExts.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); + // we require this to pixel shader debug anyway, so we might as well require it for all tests. features.fragmentStoresAndAtomics = VK_TRUE; @@ -3753,6 +3924,8 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource VK_KHR_8BIT_STORAGE_EXTENSION_NAME) != devExts.end(); const bool float16int8 = std::find(devExts.begin(), devExts.end(), VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME) != devExts.end(); + const bool bda = std::find(devExts.begin(), devExts.end(), + VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) != devExts.end(); vk_version = 0x10; @@ -3858,6 +4031,13 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource float16Int8Features.pNext = (void *)devInfoNext; devInfoNext = &float16Int8Features; } + + if(bda) + { + getPhysFeatures2(&bdaFeatures); + bdaFeatures.pNext = (void *)devInfoNext; + devInfoNext = &bdaFeatures; + } } int main() @@ -3876,6 +4056,8 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource VK_KHR_8BIT_STORAGE_EXTENSION_NAME) != devExts.end(); const bool float16int8 = std::find(devExts.begin(), devExts.end(), VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME) != devExts.end(); + const bool bda = std::find(devExts.begin(), devExts.end(), + VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) != devExts.end(); if(storage16) TEST_LOG("Running tests on 16-bit storage"); @@ -3886,6 +4068,9 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource if(float16int8) TEST_LOG("Running tests on half and int8 arithmetic"); + if(bda) + TEST_LOG("Running tests on buffer device address"); + if(features.shaderFloat64) TEST_LOG("Running tests on doubles"); @@ -4032,7 +4217,7 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource VkPipelineLayout layout = createPipelineLayout(vkh::PipelineLayoutCreateInfo( setLayouts, { - vkh::PushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, 16, sizeof(Vec4i)), + vkh::PushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, 16, sizeof(PushData)), })); // calculate number of tests, wrapping each row at 256 @@ -4384,6 +4569,59 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource VK_BUFFER_USAGE_TRANSFER_DST_BIT), VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY})); + VkBuffer bda_data_buffer; + VkDeviceMemory bda_deviceMem; + byte *bda_base_gpuptr = NULL; + if(bda) + { + vkh::BufferCreateInfo bda_buffer_info(sizeof(BDA_Data), + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR); + VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO}; + VkMemoryAllocateFlagsInfo memAllocFlags = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO}; + + memAllocFlags.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; + memAllocInfo.pNext = &memAllocFlags; + + const VkPhysicalDeviceMemoryProperties *memProps = NULL; + vmaGetMemoryProperties(allocator, &memProps); + + vkCreateBuffer(device, bda_buffer_info, NULL, &bda_data_buffer); + + VkMemoryRequirements mrq; + vkGetBufferMemoryRequirements(device, bda_data_buffer, &mrq); + memAllocInfo.allocationSize = mrq.size; + for(uint32_t i = 0; i < memProps->memoryTypeCount; i++) + { + if((mrq.memoryTypeBits & (1u << i)) && + (memProps->memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) + { + memAllocInfo.memoryTypeIndex = i; + break; + } + } + vkAllocateMemory(device, &memAllocInfo, NULL, &bda_deviceMem); + vkBindBufferMemory(device, bda_data_buffer, bda_deviceMem, 0); + + VkBufferDeviceAddressInfoKHR bda_info = {VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR}; + bda_info.buffer = bda_data_buffer; + + VkDeviceAddress bda_Addr = vkGetBufferDeviceAddressKHR(device, &bda_info); + bda_base_gpuptr = (byte *)bda_Addr; // not a valid cpu pointer + + byte *bda_base_cpuptr = NULL; + vkMapMemory(device, bda_deviceMem, 0, mrq.size, 0, (void **)&bda_base_cpuptr); + + BDA_Data *bda_data_cpu = (BDA_Data *)bda_base_cpuptr; + bda_data_cpu->f32[0] = 0.1f; + bda_data_cpu->f32[1] = 0.2f; + bda_data_cpu->f32[2] = 0.3f; + bda_data_cpu->f32[3] = 0.8f; + bda_data_cpu->f32[4] = 0.3f; + bda_data_cpu->f32[5] = 0.2f; + bda_data_cpu->f32[6] = 0.1f; + bda_data_cpu->f32[7] = 0.9f; + } + AllocatedImage store_image( this, vkh::ImageCreateInfo(128, 128, 0, VK_FORMAT_R32G32B32A32_SFLOAT, @@ -4627,7 +4865,14 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource vkCmdSetScissor(cmd, 0, 1, &s); vkh::cmdBindVertexBuffers(cmd, 0, {vb.buffer}, {0}); - Vec4i push = Vec4i(101, 103, 107, 109); + BDA_Data *bda_gpuptr = (BDA_Data *)bda_base_gpuptr; + + PushData pushData; + pushData.push = Vec4i(101, 103, 107, 109); + pushData.bda_uvec2 = *(Vec2u *)(&bda_gpuptr); + pushData.bda_hi = (uint64_t)bda_gpuptr >> 32; + pushData.bda_lo = (uint64_t)bda_gpuptr & 0xFFFFFFFF; + pushData.bda_u64 = *(uint64_t *)(&bda_gpuptr); std::vector descSets = {descset0}; @@ -4639,7 +4884,7 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource vkh::cmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descSets, {0, sizeof(Vec4f) * 16}); - vkCmdPushConstants(cmd, layout, VK_SHADER_STAGE_FRAGMENT_BIT, 16, sizeof(Vec4i), &push); + vkCmdPushConstants(cmd, layout, VK_SHADER_STAGE_FRAGMENT_BIT, 16, sizeof(PushData), &pushData); vkCmdBeginRenderPass(cmd, vkh::RenderPassBeginInfo(renderPass, framebuffer, s, @@ -4742,7 +4987,14 @@ OpMemberDecorate %cbuffer_struct 17 Offset 216 ; double doublePackSource Present(); } + CHECK_VKR(vkDeviceWaitIdle(device)); + if(bda) + { + vkDestroyBuffer(device, bda_data_buffer, NULL); + vkUnmapMemory(device, bda_deviceMem); + vkFreeMemory(device, bda_deviceMem, NULL); + } return 0; } };