From 1a0aba5a41c7af5715a4b6d1405af12944a55c87 Mon Sep 17 00:00:00 2001 From: ladevieq Date: Sat, 16 Jan 2021 22:56:25 +0100 Subject: Rendering loop --- include/vk-renderer.hpp | 59 ++++++------ src/main.cpp | 33 ++++--- src/vk-renderer.cpp | 234 +++++++++++++++++++++++++++--------------------- 3 files changed, 178 insertions(+), 148 deletions(-) diff --git a/include/vk-renderer.hpp b/include/vk-renderer.hpp index c2344c9..580ca72 100644 --- a/include/vk-renderer.hpp +++ b/include/vk-renderer.hpp @@ -32,9 +32,9 @@ struct input_data { class vkrenderer { public: - vkrenderer(window& wnd); + vkrenderer(window& wnd, const input_data& inputs); - void compute(const input_data& inputs, size_t width, size_t height); + void compute(size_t width, size_t height); private: void create_instance(); @@ -51,11 +51,11 @@ class vkrenderer { void create_memory_allocator(); - void create_command_buffer(); + void create_command_buffers(); void create_descriptor_set(); - void create_fence(); + void create_fences(); void create_semaphores(); @@ -63,39 +63,40 @@ class vkrenderer { void select_compute_queue(); - void fill_descriptor_set(const input_data& data); + void update_sets(const input_data& data); - uint32_t compute_queue_index; + uint32_t compute_queue_index; + uint64_t frame_index = 0; - VkInstance instance; - VkPhysicalDevice physical_device; - VkDevice device; - VkQueue compute_queue; + VkInstance instance; + VkPhysicalDevice physical_device; + VkDevice device; + VkQueue compute_queue; - VmaAllocator allocator; - VkBuffer compute_shader_buffer; + VmaAllocator allocator; + VkBuffer compute_shader_buffer; - VkCommandPool command_pool; - VkCommandBuffer command_buffer; + VkCommandPool command_pool; + std::vector command_buffers; - VkDescriptorPool descriptor_pool; - VkDescriptorSet compute_shader_set; + VkDescriptorPool descriptor_pool; + std::vector compute_shader_sets; - VkDescriptorSetLayout compute_shader_layout; - VkPipelineLayout compute_pipeline_layout; - VkPipeline compute_pipeline; + VkDescriptorSetLayout compute_shader_layout; + VkPipelineLayout compute_pipeline_layout; + VkPipeline compute_pipeline; - VkFence submission_fence; - VkSemaphore execution_semaphore; - VkSemaphore acquire_semaphore; + std::vector submission_fences; + std::vector execution_semaphores; + std::vector acquire_semaphores; - VkSurfaceFormatKHR surface_format; - VkSurfaceKHR platform_surface; - VkSwapchainKHR swapchain; - size_t swapchain_images_count = 3; - std::vector swapchain_images; - std::vectorswapchain_images_views; - uint32_t current_image_index; + VkSurfaceFormatKHR surface_format; + VkSurfaceKHR platform_surface; + VkSwapchainKHR swapchain; + size_t swapchain_images_count = 3; + std::vector swapchain_images; + std::vector swapchain_images_views; + uint32_t current_image_index; struct input_data* mapped_data; }; diff --git a/src/main.cpp b/src/main.cpp index 08004d9..0a357f8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -107,11 +107,8 @@ int main() { const uint32_t width = 400; const uint32_t height = width / aspect_ratio; - window wnd { width , height }; - vkrenderer renderer { wnd }; - - const uint32_t samples_per_pixel = 25; - const uint32_t max_depth = 25; + const uint32_t samples_per_pixel = 1; + const uint32_t max_depth = 50; const vec3 camera_position{ 13.0, 2.0, 3.0 }; const vec3 camera_target{ 0.0, 0.0, 0.0 }; @@ -152,22 +149,24 @@ int main() { // World hittable objects random_scene(inputs.spheres); - // To start a frame capture, call StartFrameCapture. - // You can specify NULL, NULL for the device to capture on if you have only one device and - // either no windows at all or only one window, and it will capture from that device. - // See the documentation below for a longer explanation - if(rdoc_api) rdoc_api->StartFrameCapture(NULL, NULL); + window wnd { width , height }; + vkrenderer renderer { wnd, inputs }; - auto start = std::chrono::high_resolution_clock::now(); - renderer.compute(inputs, width, height); - auto end = std::chrono::high_resolution_clock::now(); + while(wnd.isOpen) { + // To start a frame capture, call StartFrameCapture. + // You can specify NULL, NULL for the device to capture on if you have only one device and + // either no windows at all or only one window, and it will capture from that device. + // See the documentation below for a longer explanation + if(rdoc_api) rdoc_api->StartFrameCapture(NULL, NULL); - std::cerr << "Image generation took " << std::chrono::duration_cast(end - start).count() << "ms" << std::endl; + auto start = std::chrono::high_resolution_clock::now(); + renderer.compute(width, height); + auto end = std::chrono::high_resolution_clock::now(); - // stop the capture - if(rdoc_api) rdoc_api->EndFrameCapture(NULL, NULL); + std::cerr << "Image generation took " << std::chrono::duration_cast(end - start).count() << "ms" << std::endl; - while(wnd.isOpen) { + // stop the capture + if(rdoc_api) rdoc_api->EndFrameCapture(NULL, NULL); } //------------------------- diff --git a/src/vk-renderer.cpp b/src/vk-renderer.cpp index a733d49..5e7178a 100644 --- a/src/vk-renderer.cpp +++ b/src/vk-renderer.cpp @@ -19,7 +19,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(VkDebugUtilsMessageSeverityFlagBits return VK_FALSE; } -vkrenderer::vkrenderer(window& wnd) { +vkrenderer::vkrenderer(window& wnd, const input_data& inputs) { load_vulkan(); create_instance(); @@ -28,16 +28,19 @@ vkrenderer::vkrenderer(window& wnd) { create_swapchain(wnd); create_pipeline(); create_memory_allocator(); - create_command_buffer(); + create_command_buffers(); create_descriptor_set(); - create_fence(); + create_fences(); create_semaphores(); + + update_sets(inputs); } -void vkrenderer::compute(const input_data& inputs, size_t width, size_t height) { - VKRESULT(vkAcquireNextImageKHR(device, swapchain, UINT64_MAX, acquire_semaphore, VK_NULL_HANDLE, ¤t_image_index)) +void vkrenderer::compute(size_t width, size_t height) { + VKRESULT(vkWaitForFences(device, 1, &submission_fences[frame_index], VK_TRUE, UINT64_MAX)) + VKRESULT(vkResetFences(device, 1, &submission_fences[frame_index])) - fill_descriptor_set(inputs); + VKRESULT(vkAcquireNextImageKHR(device, swapchain, UINT64_MAX, acquire_semaphores[frame_index], VK_NULL_HANDLE, ¤t_image_index)) VkCommandBufferBeginInfo cmd_buf_begin_info = {}; cmd_buf_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; @@ -45,7 +48,7 @@ void vkrenderer::compute(const input_data& inputs, size_t width, size_t height) cmd_buf_begin_info.flags = 0; cmd_buf_begin_info.pInheritanceInfo = nullptr; - vkBeginCommandBuffer(command_buffer, &cmd_buf_begin_info); + vkBeginCommandBuffer(command_buffers[frame_index], &cmd_buf_begin_info); VkImageSubresourceRange image_subresource_range = {}; image_subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; @@ -54,20 +57,20 @@ void vkrenderer::compute(const input_data& inputs, size_t width, size_t height) image_subresource_range.baseArrayLayer = 0; image_subresource_range.layerCount = 1; - VkImageMemoryBarrier image_memory_barrier = {}; - image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - image_memory_barrier.pNext = nullptr; - image_memory_barrier.srcAccessMask = 0; - image_memory_barrier.dstAccessMask = 0; - image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_memory_barrier.image = swapchain_images[current_image_index]; - image_memory_barrier.subresourceRange = image_subresource_range; + VkImageMemoryBarrier undefined_to_general_barrier = {}; + undefined_to_general_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + undefined_to_general_barrier.pNext = nullptr; + undefined_to_general_barrier.srcAccessMask = 0; + undefined_to_general_barrier.dstAccessMask = 0; + undefined_to_general_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + undefined_to_general_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; + undefined_to_general_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + undefined_to_general_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + undefined_to_general_barrier.image = swapchain_images[current_image_index]; + undefined_to_general_barrier.subresourceRange = image_subresource_range; vkCmdPipelineBarrier( - command_buffer, + command_buffers[frame_index], VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, @@ -76,20 +79,31 @@ void vkrenderer::compute(const input_data& inputs, size_t width, size_t height) 0, nullptr, 1, - &image_memory_barrier + &undefined_to_general_barrier ); - vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute_pipeline_layout, 0, 1, &compute_shader_set, 0, nullptr); + vkCmdBindDescriptorSets(command_buffers[frame_index], VK_PIPELINE_BIND_POINT_COMPUTE, compute_pipeline_layout, 0, 1, &compute_shader_sets[current_image_index], 0, nullptr); - vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute_pipeline); + vkCmdBindPipeline(command_buffers[frame_index], VK_PIPELINE_BIND_POINT_COMPUTE, compute_pipeline); - vkCmdDispatch(command_buffer, width / 8, height / 8, 1); + vkCmdDispatch(command_buffers[frame_index], width / 8, height / 8, 1); - image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + VkImageMemoryBarrier general_to_present_barrier = {}; + general_to_present_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + general_to_present_barrier.pNext = nullptr; + general_to_present_barrier.srcAccessMask = 0; + general_to_present_barrier.dstAccessMask = 0; + general_to_present_barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; + general_to_present_barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + general_to_present_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + general_to_present_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + general_to_present_barrier.image = swapchain_images[current_image_index]; + general_to_present_barrier.subresourceRange = image_subresource_range; + // image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; + // image_memory_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; vkCmdPipelineBarrier( - command_buffer, + command_buffers[frame_index], VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, @@ -98,10 +112,10 @@ void vkrenderer::compute(const input_data& inputs, size_t width, size_t height) 0, nullptr, 1, - &image_memory_barrier + &general_to_present_barrier ); - VKRESULT(vkEndCommandBuffer(command_buffer)) + VKRESULT(vkEndCommandBuffer(command_buffers[frame_index])) VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; @@ -109,20 +123,20 @@ void vkrenderer::compute(const input_data& inputs, size_t width, size_t height) submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submit_info.pNext = nullptr; submit_info.waitSemaphoreCount = 1; - submit_info.pWaitSemaphores = &acquire_semaphore; + submit_info.pWaitSemaphores = &acquire_semaphores[frame_index]; submit_info.pWaitDstStageMask = &wait_stage; - submit_info.signalSemaphoreCount = 0; - submit_info.pSignalSemaphores = nullptr; + submit_info.signalSemaphoreCount = 1; + submit_info.pSignalSemaphores = &execution_semaphores[frame_index]; submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer; + submit_info.pCommandBuffers = &command_buffers[frame_index]; - VKRESULT(vkQueueSubmit(compute_queue, 1, &submit_info, submission_fence)) + VKRESULT(vkQueueSubmit(compute_queue, 1, &submit_info, submission_fences[frame_index])) VkPresentInfoKHR present_info = {}; present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; present_info.pNext = nullptr; - present_info.waitSemaphoreCount = 0; - present_info.pWaitSemaphores = 0; + present_info.waitSemaphoreCount = 1; + present_info.pWaitSemaphores = &execution_semaphores[frame_index]; present_info.swapchainCount = 1; present_info.pSwapchains = &swapchain; present_info.pImageIndices = ¤t_image_index; @@ -130,7 +144,9 @@ void vkrenderer::compute(const input_data& inputs, size_t width, size_t height) VKRESULT(vkQueuePresentKHR(compute_queue, &present_info)) - VKRESULT(vkWaitForFences(device, 1, &submission_fence, VK_TRUE, UINT64_MAX)) + VKRESULT(vkWaitForFences(device, 1, &submission_fences[frame_index], VK_TRUE, UINT64_MAX)) + + frame_index = ++frame_index % swapchain_images_count; } @@ -421,7 +437,7 @@ void vkrenderer::create_memory_allocator() { vmaCreateAllocator(&allocator_info, &allocator); } -void vkrenderer::create_command_buffer() { +void vkrenderer::create_command_buffers() { VkCommandPoolCreateInfo cmd_pool_create_info = {}; cmd_pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; cmd_pool_create_info.pNext = nullptr; @@ -435,19 +451,20 @@ void vkrenderer::create_command_buffer() { cmd_buf_allocate_info.pNext = nullptr; cmd_buf_allocate_info.commandPool = command_pool; cmd_buf_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - cmd_buf_allocate_info.commandBufferCount = 1; + cmd_buf_allocate_info.commandBufferCount = swapchain_images_count; - vkAllocateCommandBuffers(device, &cmd_buf_allocate_info, &command_buffer); + command_buffers = std::vector { swapchain_images_count }; + vkAllocateCommandBuffers(device, &cmd_buf_allocate_info, command_buffers.data()); } void vkrenderer::create_descriptor_set() { std::vector descriptor_pools_sizes = { { .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - .descriptorCount = 1, + .descriptorCount = (uint32_t)swapchain_images_count, }, { .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, - .descriptorCount = 1, + .descriptorCount = (uint32_t)swapchain_images_count, } }; @@ -455,39 +472,54 @@ void vkrenderer::create_descriptor_set() { descriptor_pool_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; descriptor_pool_create_info.pNext = nullptr; descriptor_pool_create_info.flags = 0; - descriptor_pool_create_info.maxSets = 1; + descriptor_pool_create_info.maxSets = swapchain_images_count; descriptor_pool_create_info.poolSizeCount = descriptor_pools_sizes.size(); descriptor_pool_create_info.pPoolSizes = descriptor_pools_sizes.data(); VKRESULT(vkCreateDescriptorPool(device, &descriptor_pool_create_info, nullptr, &descriptor_pool)) + std::vector sets_layouts = { swapchain_images_count, compute_shader_layout }; + VkDescriptorSetAllocateInfo descriptor_set_allocate_info = {}; descriptor_set_allocate_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; descriptor_set_allocate_info.pNext = nullptr; descriptor_set_allocate_info.descriptorPool = descriptor_pool; - descriptor_set_allocate_info.descriptorSetCount = 1; - descriptor_set_allocate_info.pSetLayouts = &compute_shader_layout; + descriptor_set_allocate_info.descriptorSetCount = sets_layouts.size(); + descriptor_set_allocate_info.pSetLayouts = sets_layouts.data(); - vkAllocateDescriptorSets(device, &descriptor_set_allocate_info, &compute_shader_set); + compute_shader_sets = std::vector { swapchain_images_count }; + vkAllocateDescriptorSets(device, &descriptor_set_allocate_info, compute_shader_sets.data()); } -void vkrenderer::create_fence() { - VkFenceCreateInfo create_info = {}; - create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - create_info.pNext = nullptr; - create_info.flags = 0; - - VKRESULT(vkCreateFence(device, &create_info, nullptr, &submission_fence)) +void vkrenderer::create_fences() { + for (size_t fence_index = 0; fence_index < swapchain_images_count; fence_index++) { + VkFence submission_fence; + VkFenceCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + create_info.pNext = nullptr; + create_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; + + VKRESULT(vkCreateFence(device, &create_info, nullptr, &submission_fence)) + + submission_fences.push_back(submission_fence); + } } void vkrenderer::create_semaphores() { - VkSemaphoreCreateInfo create_info = {}; - create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - create_info.pNext = nullptr; - create_info.flags = 0; - - VKRESULT(vkCreateSemaphore(device, &create_info, nullptr, &execution_semaphore)) - VKRESULT(vkCreateSemaphore(device, &create_info, nullptr, &acquire_semaphore)) + for (size_t semaphore_index = 0; semaphore_index < swapchain_images_count; semaphore_index++) { + VkSemaphore execution_semaphore; + VkSemaphore acquire_semaphore; + VkSemaphoreCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + create_info.pNext = nullptr; + create_info.flags = 0; + + VKRESULT(vkCreateSemaphore(device, &create_info, nullptr, &execution_semaphore)) + VKRESULT(vkCreateSemaphore(device, &create_info, nullptr, &acquire_semaphore)) + + execution_semaphores.push_back(execution_semaphore); + acquire_semaphores.push_back(acquire_semaphore); + } } void vkrenderer::select_physical_device() { @@ -523,9 +555,10 @@ void vkrenderer::select_compute_queue() { exit(1); } -void vkrenderer::fill_descriptor_set(const input_data& inputs) { +void vkrenderer::update_sets(const input_data& inputs) { // Create and fill input data buffer - VkBufferCreateInfo buffer_info = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; + VkBufferCreateInfo buffer_info = { }; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; buffer_info.size = sizeof(inputs); buffer_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; @@ -538,47 +571,44 @@ void vkrenderer::fill_descriptor_set(const input_data& inputs) { vmaMapMemory(allocator, allocation, (void**) &mapped_data); std::memcpy(mapped_data, &inputs, sizeof(inputs)); - // Update uniform buffer descriptor - VkDescriptorBufferInfo descriptor_buf_info = {}; - descriptor_buf_info.buffer = compute_shader_buffer; - descriptor_buf_info.offset = 0; - descriptor_buf_info.range = VK_WHOLE_SIZE; - - VkWriteDescriptorSet write_buffer_descriptor = {}; - write_buffer_descriptor.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write_buffer_descriptor.pNext = nullptr; - write_buffer_descriptor.dstSet = compute_shader_set; - write_buffer_descriptor.dstBinding = 0; - write_buffer_descriptor.dstArrayElement = 0; - write_buffer_descriptor.descriptorCount = 1; - write_buffer_descriptor.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - write_buffer_descriptor.pImageInfo = VK_NULL_HANDLE; - write_buffer_descriptor.pBufferInfo = &descriptor_buf_info; - write_buffer_descriptor.pTexelBufferView = VK_NULL_HANDLE; - - - // Update storage image descriptor - VkDescriptorImageInfo descriptor_image_info = {}; - descriptor_image_info.sampler = VK_NULL_HANDLE; - descriptor_image_info.imageView = swapchain_images_views[current_image_index]; - descriptor_image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - - VkWriteDescriptorSet write_image_descriptor = {}; - write_image_descriptor.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write_image_descriptor.pNext = nullptr; - write_image_descriptor.dstSet = compute_shader_set; - write_image_descriptor.dstBinding = 1; - write_image_descriptor.dstArrayElement = 0; - write_image_descriptor.descriptorCount = 1; - write_image_descriptor.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - write_image_descriptor.pImageInfo = &descriptor_image_info; - write_image_descriptor.pBufferInfo = VK_NULL_HANDLE; - write_image_descriptor.pTexelBufferView = VK_NULL_HANDLE; - - std::vector write_descriptors { - write_buffer_descriptor, - write_image_descriptor, - }; + std::vector descriptors_buf_info { swapchain_images_count }; + std::vector descriptors_image_info { swapchain_images_count }; + std::vector write_descriptors { swapchain_images_count * 2 }; + + for (size_t set_index = 0; set_index < swapchain_images_count; set_index++) { + // Update uniform buffer descriptor + descriptors_buf_info[set_index].buffer = compute_shader_buffer; + descriptors_buf_info[set_index].offset = 0; + descriptors_buf_info[set_index].range = VK_WHOLE_SIZE; + + write_descriptors[set_index * 2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_descriptors[set_index * 2].pNext = nullptr; + write_descriptors[set_index * 2].dstSet = compute_shader_sets[set_index]; + write_descriptors[set_index * 2].dstBinding = 0; + write_descriptors[set_index * 2].dstArrayElement = 0; + write_descriptors[set_index * 2].descriptorCount = 1; + write_descriptors[set_index * 2].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + write_descriptors[set_index * 2].pImageInfo = VK_NULL_HANDLE; + write_descriptors[set_index * 2].pBufferInfo = &descriptors_buf_info[set_index]; + write_descriptors[set_index * 2].pTexelBufferView = VK_NULL_HANDLE; + + + // Update storage image descriptor + descriptors_image_info[set_index].sampler = VK_NULL_HANDLE; + descriptors_image_info[set_index].imageView = swapchain_images_views[set_index]; + descriptors_image_info[set_index].imageLayout = VK_IMAGE_LAYOUT_GENERAL; + + write_descriptors[set_index * 2 + 1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_descriptors[set_index * 2 + 1].pNext = nullptr; + write_descriptors[set_index * 2 + 1].dstSet = compute_shader_sets[set_index]; + write_descriptors[set_index * 2 + 1].dstBinding = 1; + write_descriptors[set_index * 2 + 1].dstArrayElement = 0; + write_descriptors[set_index * 2 + 1].descriptorCount = 1; + write_descriptors[set_index * 2 + 1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + write_descriptors[set_index * 2 + 1].pImageInfo = &descriptors_image_info[set_index]; + write_descriptors[set_index * 2 + 1].pBufferInfo = VK_NULL_HANDLE; + write_descriptors[set_index * 2 + 1].pTexelBufferView = VK_NULL_HANDLE; + } vkUpdateDescriptorSets(device, write_descriptors.size(), write_descriptors.data(), 0, nullptr); } -- cgit v1.3