Files
raven/testdata/native_cpu/descriptor_buffer_client.c

136 lines
9.3 KiB
C

#include <vulkan/vulkan.h>
#include "vulkan_compute_spirv.h"
static VkExtensionProperties extensions[256];
static VkPhysicalDevice physical[16];
unsigned int raven_entry(void)
{
VkApplicationInfo application = {VK_STRUCTURE_TYPE_APPLICATION_INFO, 0, "Descriptor buffer fixture", 1, 0, 0, VK_API_VERSION_1_3};
VkInstanceCreateInfo instance_info = {VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 0, 0, &application, 0, 0, 0, 0};
VkInstance instance = VK_NULL_HANDLE;
uint32_t count = 16;
if (vkCreateInstance(&instance_info, 0, &instance) != VK_SUCCESS ||
vkEnumeratePhysicalDevices(instance, &count, physical) != VK_SUCCESS || !count)
return 1;
count = 256;
if (vkEnumerateDeviceExtensionProperties(physical[0], 0, &count, extensions) != VK_SUCCESS)
return 2;
uint32_t offered = 0;
const char *extension = "VK_EXT_descriptor_buffer";
for (uint32_t i = 0; i < count; ++i) {
uint32_t j = 0;
while (extension[j] && extension[j] == extensions[i].extensionName[j]) ++j;
if (!extension[j] && !extensions[i].extensionName[j]) offered = 1;
}
if (!offered) return 3;
VkPhysicalDeviceDescriptorBufferFeaturesEXT descriptor_features = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT};
VkPhysicalDeviceVulkan12Features features12 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, &descriptor_features};
VkPhysicalDeviceFeatures2 features = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, &features12};
vkGetPhysicalDeviceFeatures2(physical[0], &features);
if (!descriptor_features.descriptorBuffer || !features12.bufferDeviceAddress) return 4;
VkPhysicalDeviceDescriptorBufferPropertiesEXT descriptor_properties = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT};
VkPhysicalDeviceProperties2 properties = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, &descriptor_properties};
vkGetPhysicalDeviceProperties2(physical[0], &properties);
float priority = 1.0f;
VkDeviceQueueCreateInfo queue_info = {VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 0, 0, 0, 1, &priority};
VkPhysicalDeviceBufferDeviceAddressFeatures address_features = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES, 0, VK_TRUE};
VkPhysicalDeviceDescriptorBufferFeaturesEXT enabled = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT, &address_features, VK_TRUE};
VkDeviceCreateInfo device_info = {VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, &enabled, 0, 1, &queue_info, 0, 0, 1, &extension, 0};
VkDevice device = VK_NULL_HANDLE;
if (vkCreateDevice(physical[0], &device_info, 0, &device) != VK_SUCCESS) return 5;
const char *commands[] = {"vkGetDescriptorEXT", "vkGetDescriptorSetLayoutSizeEXT", "vkGetDescriptorSetLayoutBindingOffsetEXT",
"vkCmdBindDescriptorBuffersEXT", "vkCmdSetDescriptorBufferOffsetsEXT", "vkCmdBindDescriptorBufferEmbeddedSamplersEXT",
"vkGetBufferOpaqueCaptureDescriptorDataEXT", "vkGetImageOpaqueCaptureDescriptorDataEXT",
"vkGetImageViewOpaqueCaptureDescriptorDataEXT", "vkGetSamplerOpaqueCaptureDescriptorDataEXT"};
for (uint32_t i = 0; i < sizeof commands / sizeof commands[0]; ++i)
if (!vkGetDeviceProcAddr(device, commands[i])) return 6;
VkBufferCreateInfo buffer_info = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 0, 0, 8192,
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT,
VK_SHARING_MODE_EXCLUSIVE, 0, 0};
VkBuffer buffer = VK_NULL_HANDLE;
VkMemoryRequirements requirements;
VkPhysicalDeviceMemoryProperties memory_properties;
if (vkCreateBuffer(device, &buffer_info, 0, &buffer) != VK_SUCCESS) return 7;
vkGetBufferMemoryRequirements(device, buffer, &requirements);
vkGetPhysicalDeviceMemoryProperties(physical[0], &memory_properties);
uint32_t memory_type = UINT32_MAX;
for (uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i)
if ((requirements.memoryTypeBits & (1u << i)) && (memory_properties.memoryTypes[i].propertyFlags &
(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) ==
(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) { memory_type = i; break; }
if (memory_type == UINT32_MAX) return 8;
VkMemoryAllocateFlagsInfo flags = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO, 0, VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, 0};
VkMemoryAllocateInfo allocation = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, &flags, requirements.size, memory_type};
VkDeviceMemory memory = VK_NULL_HANDLE;
uint8_t *data = 0;
if (vkAllocateMemory(device, &allocation, 0, &memory) != VK_SUCCESS || vkBindBufferMemory(device, buffer, memory, 0) != VK_SUCCESS ||
vkMapMemory(device, memory, 0, VK_WHOLE_SIZE, 0, (void **)&data) != VK_SUCCESS) return 9;
VkBufferDeviceAddressInfo address_info = {VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, 0, buffer};
VkDeviceAddress address = vkGetBufferDeviceAddress(device, &address_info);
if (!address) return 10;
uint32_t *input = (uint32_t *)(data + 4096), *output = (uint32_t *)(data + 4352);
for (uint32_t i = 0; i < 64; ++i) { input[i] = i + 10; output[i] = 0xdeadbeef; }
VkDescriptorSetLayoutBinding bindings[2] = {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, 0},
{1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, 0}};
VkDescriptorSetLayoutCreateInfo set_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, 0,
VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT, 2, bindings};
VkDescriptorSetLayout set = VK_NULL_HANDLE;
if (vkCreateDescriptorSetLayout(device, &set_info, 0, &set) != VK_SUCCESS) return 11;
VkDeviceSize size = 0, offsets[2] = {0, 0};
vkGetDescriptorSetLayoutSizeEXT(device, set, &size);
vkGetDescriptorSetLayoutBindingOffsetEXT(device, set, 0, &offsets[0]);
vkGetDescriptorSetLayoutBindingOffsetEXT(device, set, 1, &offsets[1]);
if (!size || size > 4096 || !descriptor_properties.storageBufferDescriptorSize) return 12;
for (uint32_t i = 0; i < 2; ++i) {
VkDescriptorAddressInfoEXT source = {VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT, 0, address + 4096 + i * 256, 256, VK_FORMAT_UNDEFINED};
VkDescriptorGetInfoEXT get = {VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT, 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER};
get.data.accelerationStructure = UINT64_MAX;
get.data.pStorageBuffer = &source;
if (offsets[i] + descriptor_properties.storageBufferDescriptorSize > size) return 13;
vkGetDescriptorEXT(device, &get, descriptor_properties.storageBufferDescriptorSize, data + offsets[i]);
}
VkPushConstantRange push_range = {VK_SHADER_STAGE_COMPUTE_BIT, 0, 4};
VkPipelineLayoutCreateInfo layout_info = {VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 0, 0, 1, &set, 1, &push_range};
VkPipelineLayout layout = VK_NULL_HANDLE;
VkShaderModuleCreateInfo shader_info = {VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, 0, 0, sizeof compute_words, compute_words};
VkShaderModule shader = VK_NULL_HANDLE;
if (vkCreatePipelineLayout(device, &layout_info, 0, &layout) != VK_SUCCESS || vkCreateShaderModule(device, &shader_info, 0, &shader) != VK_SUCCESS) return 14;
VkComputePipelineCreateInfo pipeline_info = {VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, 0, VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT,
{VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 0, 0, VK_SHADER_STAGE_COMPUTE_BIT, shader, "main", 0}, layout, VK_NULL_HANDLE, -1};
VkPipeline pipeline = VK_NULL_HANDLE;
if (vkCreateComputePipelines(device, VK_NULL_HANDLE, 1, &pipeline_info, 0, &pipeline) != VK_SUCCESS) return 15;
VkCommandPoolCreateInfo pool_info = {VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, 0, 0, 0};
VkCommandPool pool = VK_NULL_HANDLE;
if (vkCreateCommandPool(device, &pool_info, 0, &pool) != VK_SUCCESS) return 16;
VkCommandBufferAllocateInfo command_info = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 0, pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
VkCommandBuffer command = VK_NULL_HANDLE;
VkCommandBufferBeginInfo begin = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, 0};
if (vkAllocateCommandBuffers(device, &command_info, &command) != VK_SUCCESS || vkBeginCommandBuffer(command, &begin) != VK_SUCCESS) return 17;
vkCmdBindPipeline(command, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
VkDescriptorBufferBindingInfoEXT binding = {VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT, 0, address, VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT};
vkCmdBindDescriptorBuffersEXT(command, 1, &binding);
uint32_t buffer_index = 0, scale = 3;
VkDeviceSize offset = 0;
vkCmdSetDescriptorBufferOffsetsEXT(command, VK_PIPELINE_BIND_POINT_COMPUTE, layout, 0, 1, &buffer_index, &offset);
vkCmdPushConstants(command, layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, 4, &scale);
vkCmdDispatch(command, 1, 1, 1);
VkQueue queue = VK_NULL_HANDLE;
vkGetDeviceQueue(device, 0, 0, &queue);
VkSubmitInfo submit = {VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, 0, 0, 0, 1, &command, 0, 0};
if (vkEndCommandBuffer(command) != VK_SUCCESS || vkQueueSubmit(queue, 1, &submit, VK_NULL_HANDLE) != VK_SUCCESS || vkQueueWaitIdle(queue) != VK_SUCCESS) return 18;
for (uint32_t i = 0; i < 64; ++i)
if (output[i] != (i + 10) * scale + i) return 19;
vkDestroyCommandPool(device, pool, 0);
vkDestroyPipeline(device, pipeline, 0);
vkDestroyShaderModule(device, shader, 0);
vkDestroyPipelineLayout(device, layout, 0);
vkDestroyDescriptorSetLayout(device, set, 0);
vkUnmapMemory(device, memory);
vkDestroyBuffer(device, buffer, 0);
vkFreeMemory(device, memory, 0);
vkDestroyDevice(device, 0);
vkDestroyInstance(instance, 0);
return 0;
}