Browse Source

Add a second compute shader stage.

master
Amber 2 years ago
parent
commit
0d34595a35
  1. 2
      meson.build
  2. 10
      src/compute_simple.comp
  3. 12
      src/compute_simple2.comp
  4. 144
      src/vlk_compute.c

2
meson.build

@ -4,7 +4,7 @@ deps = [dependency('glfw3'), dependency('vulkan'), dependency('dl'), dependency( @@ -4,7 +4,7 @@ deps = [dependency('glfw3'), dependency('vulkan'), dependency('dl'), dependency(
glslc = find_program('glslc')
shaders = ['src/vertex_simple.vert', 'src/fragment_simple.frag', 'src/compute_simple.comp']
shaders = ['src/vertex_simple.vert', 'src/fragment_simple.frag', 'src/compute_simple.comp', 'src/compute_simple2.comp']
foreach shader : shaders
out = (shader.split('.')[-2] + '.spv').split('/')[-1]

10
src/compute_simple.comp

@ -3,14 +3,10 @@ @@ -3,14 +3,10 @@
layout(local_size_x_id = 1) in;
layout(binding = 0) uniform Input {
layout(binding = 0) buffer Data {
uint num;
} in_vals;
layout(binding = 1) buffer Output {
uint num;
} out_vals;
} vals;
void main() {
out_vals.num = in_vals.num;
vals.num = 15;
}

12
src/compute_simple2.comp

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
#version 450
#extension GL_EXT_debug_printf : enable
layout(local_size_x_id = 1) in;
layout(binding = 0) buffer Data {
uint num;
} vals;
void main() {
vals.num = vals.num * 2;
}

144
src/vlk_compute.c

@ -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);

Loading…
Cancel
Save