Skip to content

Commit 6e8ac1c

Browse files
committed
Compute Shaders
1 parent 90d15eb commit 6e8ac1c

8 files changed

Lines changed: 133 additions & 5 deletions

File tree

shaders/compile.bat

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ glslc.exe -fshader-stage=frag model_frag.glsl -o model_frag.spv
99
glslc.exe -fshader-stage=vert postprocess_vert.glsl -o postprocess_vert.spv
1010
glslc.exe -fshader-stage=frag postprocess_frag.glsl -o postprocess_frag.spv
1111
glslc.exe -fshader-stage=vert gaussian_vert.glsl -o gaussian_vert.spv
12-
glslc.exe -fshader-stage=frag gaussian_frag.glsl -o gaussian_frag.spv
12+
glslc.exe -fshader-stage=frag gaussian_frag.glsl -o gaussian_frag.spv
13+
glslc.exe -fshader-stage=comp compute_comp.glsl -o compute_comp.spv

shaders/compile.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ glslc -fshader-stage=frag model_frag.glsl -o model_frag.spv
1010
glslc -fshader-stage=vert postprocess_vert.glsl -o postprocess_vert.spv
1111
glslc -fshader-stage=frag postprocess_frag.glsl -o postprocess_frag.spv
1212
glslc -fshader-stage=vert gaussian_vert.glsl -o gaussian_vert.spv
13-
glslc -fshader-stage=frag gaussian_frag.glsl -o gaussian_frag.spv
13+
glslc -fshader-stage=frag gaussian_frag.glsl -o gaussian_frag.spv
14+
glslc -fshader-stage=comp compute_comp.glsl -o compute_comp.spv

shaders/compute_comp.glsl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#version 460
2+
3+
layout(set = 0, binding = 0, rgba8) uniform writeonly image2D destinationImage;
4+
5+
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
6+
void main() {
7+
ivec2 destinationIUV = ivec2(gl_GlobalInvocationID.xy);
8+
vec4 rgba = vec4(1.0, 0.0, 1.0, 1.0);
9+
imageStore(destinationImage, destinationIUV, rgba);
10+
}

shaders/compute_comp.spv

980 Bytes
Binary file not shown.

src/main.cpp

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ VkRenderPass gaussRenderPass;
6363
VkRenderPass gaussRenderPassFinal;
6464
VkSampler linearSampler;
6565

66+
VulkanPipeline computePipeline;
67+
VkDescriptorSetLayout computeDescriptorSetLayout;
68+
VkDescriptorSet computeDescriptorSets[FRAMES_IN_FLIGHT];
69+
6670
VkQueryPool timestampQueryPools[FRAMES_IN_FLIGHT];
6771

6872
VkDescriptorPool imguiDescriptorPool;
@@ -224,7 +228,7 @@ void initApplication(SDL_Window* window) {
224228
context = initVulkan(instanceExtensionCount, enabledInstanceExtensions, ARRAY_COUNT(enabledDeviceExtensions), enabledDeviceExtensions);
225229

226230
SDL_Vulkan_CreateSurface(window, context->instance, &surface);
227-
swapchain = createSwapchain(context, surface, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
231+
swapchain = createSwapchain(context, surface, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT);
228232

229233
recreateRenderPass();
230234

@@ -313,9 +317,10 @@ void initApplication(SDL_Window* window) {
313317
VkDescriptorPoolSize poolSizes[] = {
314318
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, FRAMES_IN_FLIGHT},
315319
{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, FRAMES_IN_FLIGHT},
320+
{VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, FRAMES_IN_FLIGHT},
316321
};
317322
VkDescriptorPoolCreateInfo createInfo = {VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO};
318-
createInfo.maxSets = FRAMES_IN_FLIGHT;
323+
createInfo.maxSets = FRAMES_IN_FLIGHT * 2;
319324
createInfo.poolSizeCount = ARRAY_COUNT(poolSizes);
320325
createInfo.pPoolSizes = poolSizes;
321326
VKA(vkCreateDescriptorPool(context->device, &createInfo, 0, &modelDescriptorPool));
@@ -558,6 +563,24 @@ void initApplication(SDL_Window* window) {
558563
VKA(vkDeviceWaitIdle(context->device));
559564
ImGui_ImplVulkan_DestroyFontUploadObjects();
560565
}
566+
567+
{
568+
VkDescriptorSetLayoutBinding bindings[] = {
569+
{0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT, 0},
570+
};
571+
VkDescriptorSetLayoutCreateInfo createInfo = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO};
572+
createInfo.bindingCount = ARRAY_COUNT(bindings);
573+
createInfo.pBindings = bindings;
574+
VK(vkCreateDescriptorSetLayout(context->device, &createInfo, 0, &computeDescriptorSetLayout));
575+
}
576+
for(uint32_t i = 0; i < FRAMES_IN_FLIGHT; ++i) {
577+
VkDescriptorSetAllocateInfo allocateInfo = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO};
578+
allocateInfo.descriptorPool = modelDescriptorPool;
579+
allocateInfo.descriptorSetCount = 1;
580+
allocateInfo.pSetLayouts = &computeDescriptorSetLayout;
581+
VKA(vkAllocateDescriptorSets(context->device, &allocateInfo, &computeDescriptorSets[i]));
582+
}
583+
computePipeline = createComputePipeline(context, "../shaders/compute_comp.spv", 1, &computeDescriptorSetLayout, 0, 0);
561584
}
562585

563586
void recreateSwapchain() {
@@ -571,7 +594,7 @@ void recreateSwapchain() {
571594

572595

573596
VKA(vkDeviceWaitIdle(context->device));
574-
swapchain = createSwapchain(context, surface, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &oldSwapchain);
597+
swapchain = createSwapchain(context, surface, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT, &oldSwapchain);
575598

576599
destroySwapchain(context, &oldSwapchain);
577600
recreateRenderPass();
@@ -747,6 +770,46 @@ void renderApplication() {
747770

748771
VK(vkCmdWriteTimestamp(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, timestampQueryPools[frameIndex], 1));
749772

773+
{ // Swapchain Attachment Output -> Compute Write
774+
VkImageSubresourceRange subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
775+
VkImageMemoryBarrier imageBarrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER};
776+
imageBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
777+
imageBarrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
778+
imageBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
779+
imageBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
780+
imageBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
781+
imageBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
782+
imageBarrier.image = swapchain.images[imageIndex];
783+
imageBarrier.subresourceRange = subresourceRange;
784+
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, 0, 0, 0, 1, &imageBarrier);
785+
}
786+
787+
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline.pipeline);
788+
imageInfo = {0, swapchain.imageViews[imageIndex], VK_IMAGE_LAYOUT_GENERAL};
789+
descriptorWrite = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET};
790+
descriptorWrite.dstSet = computeDescriptorSets[frameIndex];
791+
descriptorWrite.dstBinding = 0;
792+
descriptorWrite.descriptorCount = 1;
793+
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
794+
descriptorWrite.pImageInfo = &imageInfo;
795+
vkUpdateDescriptorSets(context->device, 1, &descriptorWrite, 0, 0);
796+
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline.pipelineLayout, 0, 1, &computeDescriptorSets[frameIndex], 0, 0);
797+
vkCmdDispatch(commandBuffer, (swapchain.width + 7) / 8, (swapchain.height + 7) / 8, 1);
798+
799+
{ // Swapchain Compute Write -> Present
800+
VkImageSubresourceRange subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
801+
VkImageMemoryBarrier imageBarrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER};
802+
imageBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
803+
imageBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
804+
imageBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
805+
imageBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
806+
imageBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
807+
imageBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
808+
imageBarrier.image = swapchain.images[imageIndex];
809+
imageBarrier.subresourceRange = subresourceRange;
810+
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0, 0, 0, 1, &imageBarrier);
811+
}
812+
750813
VKA(vkEndCommandBuffer(commandBuffer));
751814
}
752815

@@ -802,6 +865,7 @@ void shutdownApplication() {
802865
VK(vkDestroyDescriptorSetLayout(context->device, spriteDescriptorLayout, 0));
803866
VK(vkDestroyDescriptorPool(context->device, gaussDescriptorPool, 0));
804867
VK(vkDestroyDescriptorSetLayout(context->device, gaussDescriptorSetLayout, 0));
868+
VK(vkDestroyDescriptorSetLayout(context->device, computeDescriptorSetLayout, 0));
805869
destroyBuffer(context, &spriteVertexBuffer);
806870
destroyBuffer(context, &spriteIndexBuffer);
807871
destroyImage(context, &image);
@@ -819,6 +883,7 @@ void shutdownApplication() {
819883
destroyPipeline(context, &modelPipeline);
820884
destroyPipeline(context, &gaussPipelineHorizontal);
821885
destroyPipeline(context, &gaussPipelineVertical);
886+
destroyPipeline(context, &computePipeline);
822887

823888
vkDestroySampler(context->device, sampler, 0);
824889
vkDestroySampler(context->device, linearSampler, 0);

src/vulkan_base/vulkan_base.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,6 @@ void destroyImage(VulkanContext* context, VulkanImage* image);
7575

7676
VulkanPipeline createPipeline(VulkanContext* context, const char* vertexShaderFilename, const char* fragmentShaderFilename, VkRenderPass renderPass, uint32_t width, uint32_t height,
7777
VkVertexInputAttributeDescription* attributes, uint32_t numAttributes, VkVertexInputBindingDescription* binding, uint32_t numSetLayouts, VkDescriptorSetLayout* setLayouts, VkPushConstantRange* pushConstant, uint32_t subpassIndex = 0, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT, VkSpecializationInfo* specializationInfo = 0);
78+
VulkanPipeline createComputePipeline(VulkanContext* context, const char* shaderFilename,
79+
uint32_t numSetLayouts, VkDescriptorSetLayout* setLayouts, VkPushConstantRange* pushConstant, VkSpecializationInfo* specializationInfo);
7880
void destroyPipeline(VulkanContext* context, VulkanPipeline* pipeline);

src/vulkan_base/vulkan_pipeline.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,43 @@ VulkanPipeline createPipeline(VulkanContext* context, const char* vertexShaderFi
131131
return result;
132132
}
133133

134+
VulkanPipeline createComputePipeline(VulkanContext* context, const char* shaderFilename,
135+
uint32_t numSetLayouts, VkDescriptorSetLayout* setLayouts, VkPushConstantRange* pushConstant, VkSpecializationInfo* specializationInfo) {
136+
VkShaderModule shaderModule = createShaderModule(context, shaderFilename);
137+
VkPipelineShaderStageCreateInfo shaderStage;
138+
shaderStage = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO };
139+
shaderStage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
140+
shaderStage.module = shaderModule;
141+
shaderStage.pName = "main";
142+
shaderStage.pSpecializationInfo = specializationInfo;
143+
144+
VkPipelineLayout pipelineLayout;
145+
{
146+
VkPipelineLayoutCreateInfo createInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
147+
createInfo.setLayoutCount = numSetLayouts;
148+
createInfo.pSetLayouts = setLayouts;
149+
createInfo.pushConstantRangeCount = pushConstant ? 1 : 0;
150+
createInfo.pPushConstantRanges = pushConstant;
151+
VKA(vkCreatePipelineLayout(context->device, &createInfo, 0, &pipelineLayout));
152+
}
153+
154+
VkPipeline pipeline;
155+
{
156+
VkComputePipelineCreateInfo createInfo = {VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO};
157+
createInfo.stage = shaderStage;
158+
createInfo.layout = pipelineLayout;
159+
VKA(vkCreateComputePipelines(context->device, 0, 1, &createInfo, 0, &pipeline));
160+
}
161+
162+
// Module can be destroyed after pipeline creation
163+
VK(vkDestroyShaderModule(context->device, shaderModule, 0));
164+
165+
VulkanPipeline result = {};
166+
result.pipeline = pipeline;
167+
result.pipelineLayout = pipelineLayout;
168+
return result;
169+
}
170+
134171
void destroyPipeline(VulkanContext* context, VulkanPipeline* pipeline) {
135172
VK(vkDestroyPipeline(context->device, pipeline->pipeline, 0));
136173
VK(vkDestroyPipelineLayout(context->device, pipeline->pipelineLayout, 0));

src/vulkan_base/vulkan_swapchain.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,18 @@ VulkanSwapchain createSwapchain(VulkanContext* context, VkSurfaceKHR surface, Vk
2323
// First available format should be a sensible default in most cases
2424
VkFormat format = availableFormats[0].format;
2525
VkColorSpaceKHR colorSpace = availableFormats[0].colorSpace;
26+
for(uint32_t i = 0; i < numFormats; ++i) {
27+
format = availableFormats[i].format;
28+
colorSpace = availableFormats[i].colorSpace;
29+
30+
VkImageFormatProperties formatProperties;
31+
VkResult formatResult = vkGetPhysicalDeviceImageFormatProperties(context->physicalDevice, format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage, 0, &formatProperties);
32+
if(formatResult == VK_ERROR_FORMAT_NOT_SUPPORTED) {
33+
LOG_ERROR("Swapchain format does not support requested usage flags");
34+
} else {
35+
break;
36+
}
37+
}
2638

2739
VkSurfaceCapabilitiesKHR surfaceCapabilities;
2840
VKA(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(context->physicalDevice, surface, &surfaceCapabilities));

0 commit comments

Comments
 (0)