Skip to content

Commit

Permalink
SPIRV KHR BDA Tests added to vk_shader_debug_zoo
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Zorro666 committed Jan 17, 2024
1 parent 932d1b1 commit b23e9f6
Show file tree
Hide file tree
Showing 2 changed files with 266 additions and 4 deletions.
10 changes: 10 additions & 0 deletions util/test/demos/test_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
260 changes: 256 additions & 4 deletions util/test/demos/vk/vk_shader_debug_zoo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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 "
Expand Down Expand Up @@ -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 +
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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++)
Expand Down Expand Up @@ -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)
{
Expand All @@ -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;

Expand All @@ -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;

Expand Down Expand Up @@ -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()
Expand All @@ -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");
Expand All @@ -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");

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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<VkDescriptorSet> descSets = {descset0};

Expand All @@ -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,
Expand Down Expand Up @@ -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;
}
};
Expand Down

0 comments on commit b23e9f6

Please sign in to comment.