diff options
| -rw-r--r-- | include/vk-api.hpp | 6 | ||||
| -rw-r--r-- | include/vk-renderer.hpp | 2 | ||||
| -rw-r--r-- | include/vulkan-loader.hpp | 1 | ||||
| -rw-r--r-- | src/utils.cpp | 4 | ||||
| -rw-r--r-- | src/vk-api.cpp | 74 | ||||
| -rw-r--r-- | src/vk-renderer.cpp | 35 |
6 files changed, 98 insertions, 24 deletions
diff --git a/include/vk-api.hpp b/include/vk-api.hpp index 099f4de..ed8ff65 100644 --- a/include/vk-api.hpp +++ b/include/vk-api.hpp @@ -22,14 +22,18 @@ struct ComputePipeline { struct Image { VkImage handle; VkImageView view; + VmaAllocation alloc; VkImageSubresourceRange subresource_range; VkFormat format; + VkExtent3D size; }; struct Swapchain { size_t image_count; std::vector<Image> images; VkSwapchainKHR handle; + VkSurfaceFormatKHR surface_format; + VkExtent2D extent; }; class window; @@ -90,6 +94,8 @@ class vkapi { void run_compute_pipeline(VkCommandBuffer command_buffer, ComputePipeline pipeline, VkDescriptorSet set, size_t group_count_x, size_t group_count_y, size_t group_count_z); + void blit_full(VkCommandBuffer command_buffer, Image src_image, Image dst_image); + void end_record(VkCommandBuffer command_buffer); VkResult submit(VkCommandBuffer command_buffer, VkSemaphore wait_semaphore, VkSemaphore signal_semaphore, VkFence submission_fence); diff --git a/include/vk-renderer.hpp b/include/vk-renderer.hpp index f16adf5..1180d0a 100644 --- a/include/vk-renderer.hpp +++ b/include/vk-renderer.hpp @@ -29,6 +29,8 @@ class vkrenderer { uint64_t frame_index = 0; + Image accumulation_image; + std::vector<VkCommandBuffer> command_buffers; std::vector<VkDescriptorSet> compute_shader_sets; diff --git a/include/vulkan-loader.hpp b/include/vulkan-loader.hpp index 3e01132..d6773f3 100644 --- a/include/vulkan-loader.hpp +++ b/include/vulkan-loader.hpp @@ -84,6 +84,7 @@ X(vkCmdBindDescriptorSets) \ X(vkCmdCopyBuffer) \ X(vkCmdCopyImage) \ + X(vkCmdBlitImage) \ X(vkCmdCopyBufferToImage) \ X(vkCmdDraw) \ X(vkCmdDrawIndexed) \ diff --git a/src/utils.cpp b/src/utils.cpp index 3416714..00745dc 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -93,8 +93,8 @@ struct input_data create_inputs(uint32_t width, uint32_t height) { // Image dimensions const float aspect_ratio = (float)width / (float) height; - const uint32_t samples_per_pixel = 1; - const uint32_t max_depth = 2; + const uint32_t samples_per_pixel = 10; + const uint32_t max_depth = 5; const vec3 camera_position{ 13.0, 2.0, 3.0 }; const vec3 camera_target{ 0.0, 0.0, 0.0 }; diff --git a/src/vk-api.cpp b/src/vk-api.cpp index 6144c9e..2ecd06f 100644 --- a/src/vk-api.cpp +++ b/src/vk-api.cpp @@ -73,6 +73,8 @@ void vkapi::destroy_buffer(Buffer& buffer) { Image vkapi::create_image(VkExtent3D size, VkFormat format, VkImageUsageFlags usages) { Image image; + image.size = size; + image.subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; image.subresource_range.baseMipLevel = 0; image.subresource_range.levelCount = 1; @@ -96,7 +98,10 @@ Image vkapi::create_image(VkExtent3D size, VkFormat format, VkImageUsageFlags us img_create_info.pQueueFamilyIndices = nullptr; img_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - vkCreateImage(context.device, &img_create_info, VK_NULL_HANDLE, &image.handle); + VmaAllocationCreateInfo alloc_create_info = {}; + alloc_create_info.usage = VMA_MEMORY_USAGE_GPU_ONLY; + + vmaCreateImage(context.allocator, &img_create_info, &alloc_create_info, &image.handle, &image.alloc, nullptr); VkImageViewCreateInfo image_view_create_info = {}; image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; @@ -113,7 +118,7 @@ Image vkapi::create_image(VkExtent3D size, VkFormat format, VkImageUsageFlags us }; image_view_create_info.subresourceRange = image.subresource_range; - vkCreateImage(context.device, &img_create_info, VK_NULL_HANDLE, &image.handle); + VKRESULT(vkCreateImageView(context.device, &image_view_create_info, VK_NULL_HANDLE, &image.view)) return std::move(image); } @@ -360,18 +365,18 @@ Swapchain vkapi::create_swapchain(VkSurfaceKHR surface, size_t min_image_count, VkSurfaceCapabilitiesKHR caps; VKRESULT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(context.physical_device, surface, &caps)) - VkExtent2D wantedExtent = caps.currentExtent; + swapchain.extent = caps.currentExtent; - if (wantedExtent.width < caps.minImageExtent.width) { - wantedExtent.width = caps.minImageExtent.width; - } else if (wantedExtent.width > caps.maxImageExtent.width) { - wantedExtent.width = caps.maxImageExtent.width; + if (swapchain.extent.width < caps.minImageExtent.width) { + swapchain.extent.width = caps.minImageExtent.width; + } else if (swapchain.extent.width > caps.maxImageExtent.width) { + swapchain.extent.width = caps.maxImageExtent.width; } - if (wantedExtent.height < caps.minImageExtent.height) { - wantedExtent.height = caps.minImageExtent.height; - } else if (wantedExtent.height > caps.maxImageExtent.height) { - wantedExtent.height = caps.maxImageExtent.height; + if (swapchain.extent.height < caps.minImageExtent.height) { + swapchain.extent.height = caps.minImageExtent.height; + } else if (swapchain.extent.height > caps.maxImageExtent.height) { + swapchain.extent.height = caps.maxImageExtent.height; } uint32_t supported_formats_count = 0; @@ -386,7 +391,7 @@ Swapchain vkapi::create_swapchain(VkSurfaceKHR surface, size_t min_image_count, std::vector<VkPresentModeKHR> supported_present_modes { supported_present_modes_count }; VKRESULT(vkGetPhysicalDeviceSurfacePresentModesKHR(context.physical_device, surface, &supported_present_modes_count, supported_present_modes.data())) - VkSurfaceFormatKHR surface_format = supported_formats[0]; + swapchain.surface_format = supported_formats[0]; VkSwapchainKHR old_swapchain_handle = (old_swapchain != std::nullopt) ? old_swapchain.value().handle : VK_NULL_HANDLE; VkSwapchainCreateInfoKHR create_info = {}; @@ -395,9 +400,9 @@ Swapchain vkapi::create_swapchain(VkSurfaceKHR surface, size_t min_image_count, create_info.flags = 0; create_info.surface = surface; create_info.minImageCount = min_image_count; - create_info.imageFormat = surface_format.format; - create_info.imageColorSpace = surface_format.colorSpace; - create_info.imageExtent = wantedExtent; + create_info.imageFormat = swapchain.surface_format.format; + create_info.imageColorSpace = swapchain.surface_format.colorSpace; + create_info.imageExtent = swapchain.extent; create_info.imageArrayLayers = 1; create_info.imageUsage = usages; create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; @@ -430,8 +435,15 @@ Swapchain vkapi::create_swapchain(VkSurfaceKHR surface, size_t min_image_count, image_subresource_range.baseArrayLayer = 0; image_subresource_range.layerCount = 1; + VkExtent3D image_size = { + .width = swapchain.extent.width, + .height = swapchain.extent.height, + .depth = 1, + }; + for (size_t image_index = 0; image_index < swapchain.image_count; image_index++) { swapchain.images[image_index].handle = images[image_index]; + swapchain.images[image_index].size = image_size; swapchain.images[image_index].subresource_range = image_subresource_range; VkImageViewCreateInfo image_view_create_info = {}; @@ -440,7 +452,7 @@ Swapchain vkapi::create_swapchain(VkSurfaceKHR surface, size_t min_image_count, image_view_create_info.flags = 0; image_view_create_info.image = swapchain.images[image_index].handle; image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - image_view_create_info.format = surface_format.format; + image_view_create_info.format = swapchain.surface_format.format; image_view_create_info.components = { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, @@ -529,7 +541,6 @@ void vkapi::image_barrier(VkCommandBuffer command_buffer, VkImageLayout src_layo undefined_to_general_barrier.image = image.handle; undefined_to_general_barrier.subresourceRange = image.subresource_range; - // api.image_barrier(cmd_buffer, src_stage, dst_stage, image); vkCmdPipelineBarrier( command_buffer, src_stage, @@ -552,6 +563,35 @@ void vkapi::run_compute_pipeline(VkCommandBuffer command_buffer, ComputePipeline vkCmdDispatch(command_buffer, group_count_x, group_count_y, group_count_z); } +void vkapi::blit_full(VkCommandBuffer command_buffer, Image src_image, Image dst_image) { + VkImageSubresourceLayers images_subres_layers { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1, + }; + + VkOffset3D start_offset { + .x = 0, + .y = 0, + .z = 0, + }; + VkOffset3D end_offset { + .x = (int32_t)src_image.size.width, + .y = (int32_t)src_image.size.height, + .z = (int32_t)src_image.size.depth, + }; + + VkImageBlit blit_region { + .srcSubresource = images_subres_layers, + .srcOffsets = { start_offset, end_offset }, + .dstSubresource = images_subres_layers, + .dstOffsets = { start_offset, end_offset }, + }; + + vkCmdBlitImage(command_buffer, src_image.handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_image.handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit_region, VK_FILTER_NEAREST); +} + void vkapi::end_record(VkCommandBuffer command_buffer) { VKRESULT(vkEndCommandBuffer(command_buffer)) } diff --git a/src/vk-renderer.cpp b/src/vk-renderer.cpp index 93f319d..2054ae3 100644 --- a/src/vk-renderer.cpp +++ b/src/vk-renderer.cpp @@ -16,7 +16,9 @@ vkrenderer::vkrenderer(window& wnd, const input_data& inputs) { swapchain = api.create_swapchain( platform_surface, min_swapchain_image_count, - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT, + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | + VK_IMAGE_USAGE_STORAGE_BIT | + VK_IMAGE_USAGE_TRANSFER_DST_BIT, std::nullopt ); @@ -43,6 +45,13 @@ vkrenderer::vkrenderer(window& wnd, const input_data& inputs) { compute_shader_sets = api.create_descriptor_sets(compute_pipeline.descriptor_set_layout, swapchain.image_count); + VkExtent3D image_size = { + .width = swapchain.extent.width, + .height = swapchain.extent.height, + .depth = 1, + }; + accumulation_image = api.create_image(image_size, swapchain.surface_format.format, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); + submission_fences = api.create_fences(swapchain.image_count); execution_semaphores = api.create_semaphores(swapchain.image_count); acquire_semaphores = api.create_semaphores(swapchain.image_count); @@ -52,7 +61,7 @@ vkrenderer::vkrenderer(window& wnd, const input_data& inputs) { for (size_t index = 0; index < swapchain.image_count; index++) { api.update_descriptor_set_buffer(compute_shader_sets[index], bindings[0], compute_shader_buffer); - api.update_descriptor_set_image(compute_shader_sets[index], bindings[1], swapchain.images[index].view); + api.update_descriptor_set_image(compute_shader_sets[index], bindings[1], accumulation_image.view); } } @@ -84,9 +93,18 @@ void vkrenderer::compute(uint32_t width, uint32_t height) { auto cmd_buf = command_buffers[frame_index]; api.start_record(cmd_buf); - api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, VK_ACCESS_SHADER_WRITE_BIT, swapchain.images[swapchain_image_index]); + + api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, VK_ACCESS_SHADER_WRITE_BIT, accumulation_image); api.run_compute_pipeline(cmd_buf, compute_pipeline, compute_shader_sets[swapchain_image_index], width / 8, height / 8, 1); - api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, swapchain.images[swapchain_image_index]); + + api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, accumulation_image); + + api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, swapchain.images[swapchain_image_index]); + + api.blit_full(cmd_buf, accumulation_image, swapchain.images[swapchain_image_index]); + + api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, swapchain.images[swapchain_image_index]); + api.end_record(cmd_buf); api.submit(cmd_buf, acquire_semaphores[frame_index], execution_semaphores[frame_index], submission_fences[frame_index]); @@ -107,6 +125,13 @@ void vkrenderer::recreate_swapchain() { std::optional<Swapchain> { swapchain } ); + VkExtent3D image_size = { + .width = swapchain.extent.width, + .height = swapchain.extent.height, + .depth = 1, + }; + accumulation_image = api.create_image(image_size, swapchain.surface_format.format, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); + VkDescriptorSetLayoutBinding binding { .binding = 1, .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, @@ -116,7 +141,7 @@ void vkrenderer::recreate_swapchain() { }; for (size_t index = 0; index < swapchain.image_count; index++) { - api.update_descriptor_set_image(compute_shader_sets[index], binding, swapchain.images[index].view); + api.update_descriptor_set_image(compute_shader_sets[index], binding, accumulation_image.view); } } |
