mirror of
https://github.com/mirkobrombin/raven.git
synced 2026-10-28 21:25:06 +00:00
185 lines
13 KiB
C
185 lines
13 KiB
C
#include <vulkan/vulkan.h>
|
|
#include "vulkan_compute_spirv.h"
|
|
|
|
static VkPhysicalDevice physical[16];
|
|
static VkExtensionProperties offered[256];
|
|
|
|
unsigned int raven_entry(void)
|
|
{
|
|
const char *extensions[] = {"VK_KHR_maintenance1", "VK_KHR_create_renderpass2",
|
|
"VK_KHR_imageless_framebuffer", "VK_KHR_descriptor_update_template", "VK_KHR_push_descriptor"};
|
|
VkApplicationInfo application = {VK_STRUCTURE_TYPE_APPLICATION_INFO, 0, "Vulkan extension fixture", 1, 0, 0, VK_API_VERSION_1_2};
|
|
VkInstanceCreateInfo instance_info = {VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 0, 0, &application};
|
|
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, offered) != VK_SUCCESS) return 2;
|
|
for (uint32_t e = 0; e < sizeof extensions / sizeof extensions[0]; ++e) {
|
|
uint32_t found = 0;
|
|
for (uint32_t i = 0; i < count; ++i) {
|
|
uint32_t j = 0;
|
|
while (extensions[e][j] && extensions[e][j] == offered[i].extensionName[j]) ++j;
|
|
if (!extensions[e][j] && !offered[i].extensionName[j]) found = offered[i].specVersion;
|
|
}
|
|
if (!found) return 3 + e;
|
|
}
|
|
VkPhysicalDeviceImagelessFramebufferFeatures imageless = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES};
|
|
VkPhysicalDeviceFeatures2 features = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, &imageless};
|
|
vkGetPhysicalDeviceFeatures2(physical[0], &features);
|
|
if (!imageless.imagelessFramebuffer) return 7;
|
|
float priority = 1;
|
|
VkDeviceQueueCreateInfo queue_info = {VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 0, 0, 0, 1, &priority};
|
|
VkDeviceCreateInfo device_info = {VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, &imageless, 0, 1, &queue_info, 0, 0,
|
|
sizeof extensions / sizeof extensions[0], extensions, 0};
|
|
VkDevice device = VK_NULL_HANDLE;
|
|
if (vkCreateDevice(physical[0], &device_info, 0, &device) != VK_SUCCESS) return 8;
|
|
PFN_vkTrimCommandPoolKHR trim = (PFN_vkTrimCommandPoolKHR)vkGetDeviceProcAddr(device, "vkTrimCommandPoolKHR");
|
|
PFN_vkCreateRenderPass2KHR create_pass = (PFN_vkCreateRenderPass2KHR)vkGetDeviceProcAddr(device, "vkCreateRenderPass2KHR");
|
|
PFN_vkCmdBeginRenderPass2KHR begin_pass = (PFN_vkCmdBeginRenderPass2KHR)vkGetDeviceProcAddr(device, "vkCmdBeginRenderPass2KHR");
|
|
PFN_vkCmdNextSubpass2KHR next_pass = (PFN_vkCmdNextSubpass2KHR)vkGetDeviceProcAddr(device, "vkCmdNextSubpass2KHR");
|
|
PFN_vkCmdEndRenderPass2KHR end_pass = (PFN_vkCmdEndRenderPass2KHR)vkGetDeviceProcAddr(device, "vkCmdEndRenderPass2KHR");
|
|
PFN_vkCreateDescriptorUpdateTemplateKHR create_template = (PFN_vkCreateDescriptorUpdateTemplateKHR)vkGetDeviceProcAddr(device, "vkCreateDescriptorUpdateTemplateKHR");
|
|
PFN_vkUpdateDescriptorSetWithTemplateKHR update_template = (PFN_vkUpdateDescriptorSetWithTemplateKHR)vkGetDeviceProcAddr(device, "vkUpdateDescriptorSetWithTemplateKHR");
|
|
PFN_vkDestroyDescriptorUpdateTemplateKHR destroy_template = (PFN_vkDestroyDescriptorUpdateTemplateKHR)vkGetDeviceProcAddr(device, "vkDestroyDescriptorUpdateTemplateKHR");
|
|
if (!trim || !create_pass || !begin_pass || !next_pass || !end_pass || !create_template || !update_template || !destroy_template) return 9;
|
|
VkBufferCreateInfo buffer_info = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 0, 0, 8192,
|
|
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_SHARING_MODE_EXCLUSIVE};
|
|
VkBuffer buffer = VK_NULL_HANDLE;
|
|
if (vkCreateBuffer(device, &buffer_info, 0, &buffer) != VK_SUCCESS) return 10;
|
|
VkMemoryRequirements requirements;
|
|
VkPhysicalDeviceMemoryProperties memory_properties;
|
|
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 11;
|
|
VkMemoryAllocateInfo allocation = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 0, requirements.size, memory_type};
|
|
VkDeviceMemory memory = VK_NULL_HANDLE;
|
|
uint32_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 12;
|
|
for (uint32_t i = 0; i < 64; ++i) { data[i] = i + 10; data[1024 + 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, 0, 2, bindings};
|
|
VkDescriptorSetLayout set_layout = VK_NULL_HANDLE;
|
|
if (vkCreateDescriptorSetLayout(device, &set_info, 0, &set_layout) != VK_SUCCESS) return 13;
|
|
VkDescriptorPoolSize pool_size = {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2};
|
|
VkDescriptorPoolCreateInfo descriptor_pool_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, 0, 0, 1, 1, &pool_size};
|
|
VkDescriptorPool descriptor_pool = VK_NULL_HANDLE;
|
|
VkDescriptorSet set = VK_NULL_HANDLE;
|
|
if (vkCreateDescriptorPool(device, &descriptor_pool_info, 0, &descriptor_pool) != VK_SUCCESS) return 14;
|
|
VkDescriptorSetAllocateInfo set_allocate = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 0, descriptor_pool, 1, &set_layout};
|
|
if (vkAllocateDescriptorSets(device, &set_allocate, &set) != VK_SUCCESS) return 15;
|
|
VkDescriptorBufferInfo buffers[2] = {{buffer, 0, 256}, {buffer, 4096, 256}};
|
|
VkDescriptorUpdateTemplateEntry entries[2] = {{0, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, sizeof buffers[0]},
|
|
{1, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, sizeof buffers[0], sizeof buffers[0]}};
|
|
VkDescriptorUpdateTemplateCreateInfo template_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO, 0, 0, 2, entries,
|
|
VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET, set_layout};
|
|
VkDescriptorUpdateTemplate descriptor_template = VK_NULL_HANDLE;
|
|
if (create_template(device, &template_info, 0, &descriptor_template) != VK_SUCCESS) return 16;
|
|
update_template(device, set, descriptor_template, buffers);
|
|
VkPushConstantRange push_range = {VK_SHADER_STAGE_COMPUTE_BIT, 0, 4};
|
|
VkPipelineLayoutCreateInfo layout_info = {VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 0, 0, 1, &set_layout, 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 17;
|
|
VkComputePipelineCreateInfo pipeline_info = {VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, 0, 0,
|
|
{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 18;
|
|
VkSubpassDescription2 subpasses[2] = {{VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, 0, 0, VK_PIPELINE_BIND_POINT_GRAPHICS},
|
|
{VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, 0, 0, VK_PIPELINE_BIND_POINT_GRAPHICS}};
|
|
VkRenderPassCreateInfo2 pass_info = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2, 0, 0, 0, 0, 2, subpasses};
|
|
VkRenderPass pass = VK_NULL_HANDLE;
|
|
if (create_pass(device, &pass_info, 0, &pass) != VK_SUCCESS) return 19;
|
|
VkFramebufferCreateInfo framebuffer_info = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, 0, VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT,
|
|
pass, 0, 0, 16, 16, 1};
|
|
VkFramebuffer framebuffer = VK_NULL_HANDLE;
|
|
if (vkCreateFramebuffer(device, &framebuffer_info, 0, &framebuffer) != VK_SUCCESS) return 20;
|
|
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 21;
|
|
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 22;
|
|
VkRenderPassBeginInfo pass_begin = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 0, pass, framebuffer, {{0, 0}, {16, 16}}};
|
|
VkSubpassBeginInfo subpass_begin = {VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO, 0, VK_SUBPASS_CONTENTS_INLINE};
|
|
VkSubpassEndInfo subpass_end = {VK_STRUCTURE_TYPE_SUBPASS_END_INFO};
|
|
begin_pass(command, &pass_begin, &subpass_begin);
|
|
next_pass(command, &subpass_begin, &subpass_end);
|
|
end_pass(command, &subpass_end);
|
|
vkCmdBindPipeline(command, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
|
|
vkCmdBindDescriptorSets(command, VK_PIPELINE_BIND_POINT_COMPUTE, layout, 0, 1, &set, 0, 0);
|
|
uint32_t scale = 3;
|
|
vkCmdPushConstants(command, layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, 4, &scale);
|
|
vkCmdDispatch(command, 1, 1, 1);
|
|
VkMemoryBarrier barrier = {VK_STRUCTURE_TYPE_MEMORY_BARRIER, 0, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT};
|
|
vkCmdPipelineBarrier(command, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 1, &barrier, 0, 0, 0, 0);
|
|
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 23;
|
|
for (uint32_t i = 0; i < 64; ++i)
|
|
if (data[1024 + i] != (i + 10) * scale + i) return 24;
|
|
PFN_vkCmdPushDescriptorSetWithTemplateKHR push_template = (PFN_vkCmdPushDescriptorSetWithTemplateKHR)
|
|
vkGetDeviceProcAddr(device, "vkCmdPushDescriptorSetWithTemplateKHR");
|
|
if (!push_template) return 25;
|
|
set_info.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
|
|
VkDescriptorSetLayout push_set_layout = VK_NULL_HANDLE;
|
|
VkPipelineLayout push_layout = VK_NULL_HANDLE;
|
|
VkPipeline push_pipeline = VK_NULL_HANDLE;
|
|
VkDescriptorUpdateTemplate push_update = VK_NULL_HANDLE;
|
|
if (vkCreateDescriptorSetLayout(device, &set_info, 0, &push_set_layout) != VK_SUCCESS) return 26;
|
|
layout_info.pSetLayouts = &push_set_layout;
|
|
if (vkCreatePipelineLayout(device, &layout_info, 0, &push_layout) != VK_SUCCESS) return 27;
|
|
template_info.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR;
|
|
template_info.descriptorSetLayout = VK_NULL_HANDLE;
|
|
template_info.pipelineBindPoint = VK_PIPELINE_BIND_POINT_COMPUTE;
|
|
template_info.pipelineLayout = push_layout;
|
|
template_info.set = 0;
|
|
pipeline_info.layout = push_layout;
|
|
if (create_template(device, &template_info, 0, &push_update) != VK_SUCCESS ||
|
|
vkCreateComputePipelines(device, VK_NULL_HANDLE, 1, &pipeline_info, 0, &push_pipeline) != VK_SUCCESS) return 28;
|
|
for (uint32_t i = 0; i < 64; ++i) data[1024 + i] = 0xdeadbeef;
|
|
if (vkResetCommandPool(device, pool, 0) != VK_SUCCESS || vkBeginCommandBuffer(command, &begin) != VK_SUCCESS) return 29;
|
|
vkCmdBindPipeline(command, VK_PIPELINE_BIND_POINT_COMPUTE, push_pipeline);
|
|
push_template(command, push_update, push_layout, 0, buffers);
|
|
scale = 5;
|
|
vkCmdPushConstants(command, push_layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, 4, &scale);
|
|
vkCmdDispatch(command, 1, 1, 1);
|
|
vkCmdPipelineBarrier(command, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 1, &barrier, 0, 0, 0, 0);
|
|
if (vkEndCommandBuffer(command) != VK_SUCCESS || vkQueueSubmit(queue, 1, &submit, VK_NULL_HANDLE) != VK_SUCCESS ||
|
|
vkQueueWaitIdle(queue) != VK_SUCCESS) return 30;
|
|
for (uint32_t i = 0; i < 64; ++i)
|
|
if (data[1024 + i] != (i + 10) * scale + i) return 31;
|
|
vkDestroyPipeline(device, push_pipeline, 0);
|
|
destroy_template(device, push_update, 0);
|
|
vkDestroyPipelineLayout(device, push_layout, 0);
|
|
vkDestroyDescriptorSetLayout(device, push_set_layout, 0);
|
|
vkFreeCommandBuffers(device, pool, 1, &command);
|
|
trim(device, pool, 0);
|
|
vkDestroyCommandPool(device, pool, 0);
|
|
vkDestroyFramebuffer(device, framebuffer, 0);
|
|
vkDestroyRenderPass(device, pass, 0);
|
|
vkDestroyPipeline(device, pipeline, 0);
|
|
vkDestroyShaderModule(device, shader, 0);
|
|
vkDestroyPipelineLayout(device, layout, 0);
|
|
destroy_template(device, descriptor_template, 0);
|
|
vkDestroyDescriptorPool(device, descriptor_pool, 0);
|
|
vkDestroyDescriptorSetLayout(device, set_layout, 0);
|
|
vkUnmapMemory(device, memory);
|
|
vkDestroyBuffer(device, buffer, 0);
|
|
vkFreeMemory(device, memory, 0);
|
|
vkDestroyDevice(device, 0);
|
|
vkDestroyInstance(instance, 0);
|
|
return 0;
|
|
}
|