|
|
|
@ -51,14 +51,11 @@ typedef struct ApplicationState {
@@ -51,14 +51,11 @@ typedef struct ApplicationState {
|
|
|
|
|
VkDescriptorPool descriptor_pool; |
|
|
|
|
VkDescriptorSet descriptor_sets; |
|
|
|
|
VkPipelineLayout pipeline_layout; |
|
|
|
|
VkPipeline pipeline; |
|
|
|
|
VkPipeline pipeline[2]; |
|
|
|
|
|
|
|
|
|
VkBuffer input_buffer; |
|
|
|
|
VkDeviceMemory input_buffer_memory; |
|
|
|
|
|
|
|
|
|
VkBuffer output_buffer; |
|
|
|
|
VkDeviceMemory output_buffer_memory; |
|
|
|
|
|
|
|
|
|
VkFence compute_done; |
|
|
|
|
} compute; |
|
|
|
|
} ApplicationState; |
|
|
|
@ -397,16 +394,10 @@ void create_descriptor_set_layout(ApplicationState* state) {
@@ -397,16 +394,10 @@ void create_descriptor_set_layout(ApplicationState* state) {
|
|
|
|
|
VkDescriptorSetLayoutBinding input_binding = {0}; |
|
|
|
|
input_binding.binding = 0; |
|
|
|
|
input_binding.descriptorCount = 1; |
|
|
|
|
input_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; |
|
|
|
|
input_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; |
|
|
|
|
input_binding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; |
|
|
|
|
|
|
|
|
|
VkDescriptorSetLayoutBinding output_binding = {0}; |
|
|
|
|
output_binding.binding = 1; |
|
|
|
|
output_binding.descriptorCount = 1; |
|
|
|
|
output_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; |
|
|
|
|
output_binding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; |
|
|
|
|
|
|
|
|
|
VkDescriptorSetLayoutBinding bindings[2] = {input_binding, output_binding}; |
|
|
|
|
VkDescriptorSetLayoutBinding bindings[1] = {input_binding}; |
|
|
|
|
|
|
|
|
|
VkDescriptorSetLayoutCreateInfo layout_info = {0}; |
|
|
|
|
layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; |
|
|
|
@ -455,58 +446,79 @@ VkShaderModule create_shader_module(ApplicationState* state, const char* code, s
@@ -455,58 +446,79 @@ VkShaderModule create_shader_module(ApplicationState* state, const char* code, s
|
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void create_compute_pipeline(ApplicationState* state) { |
|
|
|
|
VkShaderModule compute_shader_module; |
|
|
|
|
size_t compute_shader_size; |
|
|
|
|
char* compute_shader = load_file("./compute_simple.spv", &compute_shader_size); |
|
|
|
|
|
|
|
|
|
compute_shader_module = create_shader_module(state, compute_shader, compute_shader_size); |
|
|
|
|
|
|
|
|
|
VkPipelineShaderStageCreateInfo compute_shader_stage_info = {0}; |
|
|
|
|
compute_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; |
|
|
|
|
compute_shader_stage_info.stage = VK_SHADER_STAGE_COMPUTE_BIT; |
|
|
|
|
compute_shader_stage_info.module = compute_shader_module; |
|
|
|
|
compute_shader_stage_info.pName = "main"; |
|
|
|
|
|
|
|
|
|
VkPipelineLayoutCreateInfo pipeline_layout_create_info = {0}; |
|
|
|
|
pipeline_layout_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; |
|
|
|
|
pipeline_layout_create_info.setLayoutCount = 1; |
|
|
|
|
pipeline_layout_create_info.pSetLayouts = &state->compute.descriptor_set_layout; |
|
|
|
|
pipeline_layout_create_info.pushConstantRangeCount = 0; |
|
|
|
|
pipeline_layout_create_info.pPushConstantRanges = NULL; |
|
|
|
|
|
|
|
|
|
if (vkCreatePipelineLayout(state->device, &pipeline_layout_create_info, NULL, &state->compute.pipeline_layout) != VK_SUCCESS) { |
|
|
|
|
void create_compute_pipelines(ApplicationState* state) { |
|
|
|
|
VkShaderModule compute_shader_module0; |
|
|
|
|
VkShaderModule compute_shader_module1; |
|
|
|
|
size_t compute_shader_size0; |
|
|
|
|
size_t compute_shader_size1; |
|
|
|
|
char* compute_shader0 = load_file("./compute_simple.spv", &compute_shader_size0); |
|
|
|
|
char* compute_shader1 = load_file("./compute_simple2.spv", &compute_shader_size1); |
|
|
|
|
|
|
|
|
|
compute_shader_module0 = create_shader_module(state, compute_shader0, compute_shader_size0); |
|
|
|
|
compute_shader_module1 = create_shader_module(state, compute_shader1, compute_shader_size1); |
|
|
|
|
|
|
|
|
|
VkPipelineShaderStageCreateInfo compute_shader_stage_info0 = {0}; |
|
|
|
|
compute_shader_stage_info0.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; |
|
|
|
|
compute_shader_stage_info0.stage = VK_SHADER_STAGE_COMPUTE_BIT; |
|
|
|
|
compute_shader_stage_info0.module = compute_shader_module0; |
|
|
|
|
compute_shader_stage_info0.pName = "main"; |
|
|
|
|
|
|
|
|
|
VkPipelineShaderStageCreateInfo compute_shader_stage_info1 = {0}; |
|
|
|
|
compute_shader_stage_info1.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; |
|
|
|
|
compute_shader_stage_info1.stage = VK_SHADER_STAGE_COMPUTE_BIT; |
|
|
|
|
compute_shader_stage_info1.module = compute_shader_module1; |
|
|
|
|
compute_shader_stage_info1.pName = "main"; |
|
|
|
|
|
|
|
|
|
VkPipelineLayoutCreateInfo pipeline_layout_create_info0 = {0}; |
|
|
|
|
pipeline_layout_create_info0.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; |
|
|
|
|
pipeline_layout_create_info0.setLayoutCount = 1; |
|
|
|
|
pipeline_layout_create_info0.pSetLayouts = &state->compute.descriptor_set_layout; |
|
|
|
|
pipeline_layout_create_info0.pushConstantRangeCount = 0; |
|
|
|
|
pipeline_layout_create_info0.pPushConstantRanges = NULL; |
|
|
|
|
|
|
|
|
|
if (vkCreatePipelineLayout(state->device, &pipeline_layout_create_info0, NULL, &state->compute.pipeline_layout) != VK_SUCCESS) { |
|
|
|
|
printf("failed to create pipeline layout"); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
printf("created pipeline layout\n"); |
|
|
|
|
|
|
|
|
|
VkComputePipelineCreateInfo create_info = {0}; |
|
|
|
|
create_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; |
|
|
|
|
create_info.layout = state->compute.pipeline_layout; |
|
|
|
|
create_info.basePipelineHandle = VK_NULL_HANDLE; |
|
|
|
|
create_info.stage = compute_shader_stage_info; |
|
|
|
|
create_info.flags = 0; |
|
|
|
|
VkComputePipelineCreateInfo create_info0 = {0}; |
|
|
|
|
create_info0.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; |
|
|
|
|
create_info0.layout = state->compute.pipeline_layout; |
|
|
|
|
create_info0.basePipelineHandle = VK_NULL_HANDLE; |
|
|
|
|
create_info0.stage = compute_shader_stage_info0; |
|
|
|
|
create_info0.flags = 0; |
|
|
|
|
|
|
|
|
|
VkComputePipelineCreateInfo create_info1 = {0}; |
|
|
|
|
create_info1.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; |
|
|
|
|
create_info1.layout = state->compute.pipeline_layout; |
|
|
|
|
create_info1.basePipelineHandle = VK_NULL_HANDLE; |
|
|
|
|
create_info1.stage = compute_shader_stage_info1; |
|
|
|
|
create_info1.flags = 0; |
|
|
|
|
|
|
|
|
|
if (vkCreateComputePipelines(state->device, VK_NULL_HANDLE, 1, &create_info0, NULL, &state->compute.pipeline[0]) != VK_SUCCESS) { |
|
|
|
|
printf("failed to create compute pipeline\n"); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (vkCreateComputePipelines(state->device, VK_NULL_HANDLE, 1, &create_info, NULL, &state->compute.pipeline) != VK_SUCCESS) { |
|
|
|
|
if (vkCreateComputePipelines(state->device, VK_NULL_HANDLE, 1, &create_info1, NULL, &state->compute.pipeline[1]) != VK_SUCCESS) { |
|
|
|
|
printf("failed to create compute pipeline\n"); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
printf("created compute pipeline\n"); |
|
|
|
|
|
|
|
|
|
vkDestroyShaderModule(state->device, compute_shader_module, NULL); |
|
|
|
|
vkDestroyShaderModule(state->device, compute_shader_module0, NULL); |
|
|
|
|
vkDestroyShaderModule(state->device, compute_shader_module1, NULL); |
|
|
|
|
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void create_descriptor_pool(ApplicationState* state) { |
|
|
|
|
VkDescriptorPoolSize pool_size[2] = {0}; |
|
|
|
|
pool_size[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; |
|
|
|
|
VkDescriptorPoolSize pool_size[1] = {0}; |
|
|
|
|
pool_size[0].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; |
|
|
|
|
pool_size[0].descriptorCount = 1; |
|
|
|
|
pool_size[1].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; |
|
|
|
|
pool_size[1].descriptorCount = 1; |
|
|
|
|
|
|
|
|
|
VkDescriptorPoolCreateInfo pool_info = {0}; |
|
|
|
|
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; |
|
|
|
@ -534,42 +546,26 @@ void create_descriptor_sets(ApplicationState* state) {
@@ -534,42 +546,26 @@ void create_descriptor_sets(ApplicationState* state) {
|
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
create_buffer(state, sizeof(uint32_t), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, |
|
|
|
|
&state->compute.input_buffer, &state->compute.input_buffer_memory); |
|
|
|
|
create_buffer(state, sizeof(uint32_t), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, |
|
|
|
|
&state->compute.output_buffer, &state->compute.output_buffer_memory); |
|
|
|
|
&state->compute.input_buffer, &state->compute.input_buffer_memory); |
|
|
|
|
|
|
|
|
|
VkDescriptorBufferInfo in_buffer_info = {0}; |
|
|
|
|
VkDescriptorBufferInfo out_buffer_info = {0}; |
|
|
|
|
|
|
|
|
|
in_buffer_info.buffer = state->compute.input_buffer; |
|
|
|
|
in_buffer_info.range = sizeof(uint32_t); |
|
|
|
|
|
|
|
|
|
out_buffer_info.buffer = state->compute.output_buffer; |
|
|
|
|
out_buffer_info.range = sizeof(uint32_t); |
|
|
|
|
|
|
|
|
|
VkWriteDescriptorSet descriptor_writes[2] = {0}; |
|
|
|
|
VkWriteDescriptorSet descriptor_writes[1] = {0}; |
|
|
|
|
|
|
|
|
|
descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; |
|
|
|
|
descriptor_writes[0].dstSet = state->compute.descriptor_sets; |
|
|
|
|
descriptor_writes[0].dstBinding = 0; |
|
|
|
|
descriptor_writes[0].dstArrayElement = 0; |
|
|
|
|
descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; |
|
|
|
|
descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; |
|
|
|
|
descriptor_writes[0].descriptorCount = 1; |
|
|
|
|
descriptor_writes[0].pBufferInfo = &in_buffer_info; |
|
|
|
|
descriptor_writes[0].pImageInfo = NULL; |
|
|
|
|
descriptor_writes[0].pTexelBufferView = NULL; |
|
|
|
|
|
|
|
|
|
descriptor_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; |
|
|
|
|
descriptor_writes[1].dstSet = state->compute.descriptor_sets; |
|
|
|
|
descriptor_writes[1].dstBinding = 1; |
|
|
|
|
descriptor_writes[1].dstArrayElement = 0; |
|
|
|
|
descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; |
|
|
|
|
descriptor_writes[1].descriptorCount = 1; |
|
|
|
|
descriptor_writes[1].pBufferInfo = &out_buffer_info; |
|
|
|
|
descriptor_writes[1].pImageInfo = NULL; |
|
|
|
|
descriptor_writes[1].pTexelBufferView = NULL; |
|
|
|
|
|
|
|
|
|
vkUpdateDescriptorSets(state->device, ARRSIZE(descriptor_writes), descriptor_writes, 0, NULL); |
|
|
|
|
|
|
|
|
|
printf("allocated and written descriptor sets\n"); |
|
|
|
@ -595,7 +591,7 @@ void init_vulkan(ApplicationState* state) {
@@ -595,7 +591,7 @@ void init_vulkan(ApplicationState* state) {
|
|
|
|
|
pick_physical_device(state); |
|
|
|
|
create_logical_device(state); |
|
|
|
|
create_descriptor_set_layout(state); |
|
|
|
|
create_compute_pipeline(state); |
|
|
|
|
create_compute_pipelines(state); |
|
|
|
|
create_descriptor_pool(state); |
|
|
|
|
create_descriptor_sets(state); |
|
|
|
|
setup_compute_queues(state); |
|
|
|
@ -607,12 +603,11 @@ void terminate(ApplicationState* state) {
@@ -607,12 +603,11 @@ void terminate(ApplicationState* state) {
|
|
|
|
|
// vkDestroyCommandPool(state->device, state->compute.command_pool, NULL);
|
|
|
|
|
|
|
|
|
|
vkFreeMemory(state->device, state->compute.input_buffer_memory, NULL); |
|
|
|
|
vkFreeMemory(state->device, state->compute.output_buffer_memory, NULL); |
|
|
|
|
vkDestroyBuffer(state->device, state->compute.input_buffer, NULL); |
|
|
|
|
vkDestroyBuffer(state->device, state->compute.output_buffer, NULL); |
|
|
|
|
|
|
|
|
|
vkDestroyDescriptorPool(state->device, state->compute.descriptor_pool, NULL); |
|
|
|
|
vkDestroyPipeline(state->device, state->compute.pipeline, NULL); |
|
|
|
|
vkDestroyPipeline(state->device, state->compute.pipeline[0], NULL); |
|
|
|
|
vkDestroyPipeline(state->device, state->compute.pipeline[1], NULL); |
|
|
|
|
vkDestroyPipelineLayout(state->device, state->compute.pipeline_layout, NULL); |
|
|
|
|
vkDestroyDescriptorSetLayout(state->device, state->compute.descriptor_set_layout, NULL); |
|
|
|
|
vkDestroyCommandPool(state->device, state->compute.command_pool, NULL); |
|
|
|
@ -634,10 +629,18 @@ int main() {
@@ -634,10 +629,18 @@ int main() {
|
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
vkCmdBindPipeline(state.compute.command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, state.compute.pipeline); |
|
|
|
|
vkCmdBindPipeline(state.compute.command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, state.compute.pipeline[0]); |
|
|
|
|
vkCmdBindDescriptorSets(state.compute.command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, |
|
|
|
|
state.compute.pipeline_layout, 0, 1, &state.compute.descriptor_sets, 0, NULL); |
|
|
|
|
vkCmdDispatch(state.compute.command_buffer, 1, 1, 1); |
|
|
|
|
vkCmdBindPipeline(state.compute.command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, state.compute.pipeline[1]); |
|
|
|
|
struct VkMemoryBarrier barrier = {0}; |
|
|
|
|
barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; |
|
|
|
|
barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; |
|
|
|
|
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; |
|
|
|
|
vkCmdPipelineBarrier(state.compute.command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, |
|
|
|
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &barrier, 0, NULL, 0, NULL); |
|
|
|
|
vkCmdDispatch(state.compute.command_buffer, 1, 1, 1); |
|
|
|
|
|
|
|
|
|
printf("start recording command buffer\n"); |
|
|
|
|
|
|
|
|
@ -667,10 +670,7 @@ int main() {
@@ -667,10 +670,7 @@ int main() {
|
|
|
|
|
vkWaitForFences(state.device, 1, &state.compute.compute_done, VK_TRUE, UINT64_MAX); |
|
|
|
|
vkQueueWaitIdle(state.compute.queue); |
|
|
|
|
|
|
|
|
|
vkMapMemory(state.device, state.compute.output_buffer_memory, 0, sizeof(uint32_t), 0, (void**)&data); |
|
|
|
|
printf("submit complete, result: %X\n", *data); |
|
|
|
|
vkUnmapMemory(state.device, state.compute.output_buffer_memory); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
terminate(&state); |
|
|
|
|
|
|
|
|
|