From 11de490e9415458205373f96da50c10864d4a049 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Thu, 28 Mar 2024 16:33:55 +0900 Subject: [PATCH] Vulkan compute: combine all minmax calls This commit combines the minmax execution via Vulkan compute. The previous implementation executed compute in vulkan_minmax with a new command buffer each time. This implementation combines all required executions of compute in vulkan_minmax in a single command buffer and uses a pipeline to ensure the enqueued compute calls stay in order. --- src/blue_noise.cpp | 307 +++++++++++++++++++++++++++---------- src/blue_noise.hpp | 4 +- src/blue_noise_minmax.glsl | 2 + 3 files changed, 227 insertions(+), 86 deletions(-) diff --git a/src/blue_noise.cpp b/src/blue_noise.cpp index 7024a5d..85a8bf2 100644 --- a/src/blue_noise.cpp +++ b/src/blue_noise.cpp @@ -195,7 +195,7 @@ std::vector dither::internal::blue_noise_vulkan_impl( VkBuffer pbp_buf, VkPipeline pipeline, VkPipelineLayout pipeline_layout, VkDescriptorSet descriptor_set, VkBuffer filter_out_buf, VkPipeline minmax_pipeline, VkPipelineLayout minmax_pipeline_layout, - VkDescriptorSet minmax_descriptor_set, VkBuffer max_in_buf, + std::array minmax_desc_sets, VkBuffer max_in_buf, VkBuffer min_in_buf, VkBuffer max_out_buf, VkBuffer min_out_buf, VkBuffer state_buf, const int width, const int height) { const int size = width * height; @@ -318,11 +318,11 @@ std::vector dither::internal::blue_noise_vulkan_impl( } int min, max; - auto vulkan_minmax_opt = vulkan_minmax( - device, phys_device, command_buffer, command_pool, queue, - minmax_pipeline, minmax_pipeline_layout, minmax_descriptor_set, - max_in_buf, min_in_buf, max_out_buf, min_out_buf, state_buf, size, - filter_mapped_float, pbp); + auto vulkan_minmax_opt = + vulkan_minmax(device, phys_device, command_buffer, command_pool, queue, + minmax_pipeline, minmax_pipeline_layout, minmax_desc_sets, + max_in_buf, min_in_buf, max_out_buf, min_out_buf, + state_buf, size, filter_mapped_float, pbp); if (!vulkan_minmax_opt.has_value()) { std::cerr << "Vulkan: vulkan_minmax returned nullopt!\n"; return {}; @@ -352,11 +352,11 @@ std::vector dither::internal::blue_noise_vulkan_impl( // get second buffer's min int second_min; - vulkan_minmax_opt = vulkan_minmax( - device, phys_device, command_buffer, command_pool, queue, - minmax_pipeline, minmax_pipeline_layout, minmax_descriptor_set, - max_in_buf, min_in_buf, max_out_buf, min_out_buf, state_buf, size, - filter_mapped_float, pbp); + vulkan_minmax_opt = + vulkan_minmax(device, phys_device, command_buffer, command_pool, queue, + minmax_pipeline, minmax_pipeline_layout, minmax_desc_sets, + max_in_buf, min_in_buf, max_out_buf, min_out_buf, + state_buf, size, filter_mapped_float, pbp); if (!vulkan_minmax_opt.has_value()) { std::cerr << "Vulkan: vulkan_minmax returned nullopt!\n"; return {}; @@ -439,11 +439,11 @@ std::vector dither::internal::blue_noise_vulkan_impl( pbp_mapped_int, staging_pbp_buffer, staging_pbp_buffer_mem, staging_filter_buffer_mem, staging_filter_buffer); - auto vulkan_minmax_opt = vulkan_minmax( - device, phys_device, command_buffer, command_pool, queue, - minmax_pipeline, minmax_pipeline_layout, minmax_descriptor_set, - max_in_buf, min_in_buf, max_out_buf, min_out_buf, state_buf, size, - filter_mapped_float, pbp); + auto vulkan_minmax_opt = + vulkan_minmax(device, phys_device, command_buffer, command_pool, + queue, minmax_pipeline, minmax_pipeline_layout, + minmax_desc_sets, max_in_buf, min_in_buf, max_out_buf, + min_out_buf, state_buf, size, filter_mapped_float, pbp); if (!vulkan_minmax_opt.has_value()) { std::cerr << "Vulkan: vulkan_minmax returned nullopt!\n"; return {}; @@ -475,11 +475,11 @@ std::vector dither::internal::blue_noise_vulkan_impl( size, pbp, reversed_pbp, global_size, pbp_mapped_int, staging_pbp_buffer, staging_pbp_buffer_mem, staging_filter_buffer_mem, staging_filter_buffer); - auto vulkan_minmax_opt = vulkan_minmax( - device, phys_device, command_buffer, command_pool, queue, - minmax_pipeline, minmax_pipeline_layout, minmax_descriptor_set, - max_in_buf, min_in_buf, max_out_buf, min_out_buf, state_buf, size, - filter_mapped_float, pbp); + auto vulkan_minmax_opt = + vulkan_minmax(device, phys_device, command_buffer, command_pool, queue, + minmax_pipeline, minmax_pipeline_layout, minmax_desc_sets, + max_in_buf, min_in_buf, max_out_buf, min_out_buf, + state_buf, size, filter_mapped_float, pbp); if (!vulkan_minmax_opt.has_value()) { std::cerr << "Vulkan: vulkan_minmax returned nullopt!\n"; return {}; @@ -521,11 +521,11 @@ std::vector dither::internal::blue_noise_vulkan_impl( size, pbp, reversed_pbp, global_size, pbp_mapped_int, staging_pbp_buffer, staging_pbp_buffer_mem, staging_filter_buffer_mem, staging_filter_buffer); - auto vulkan_minmax_opt = vulkan_minmax( - device, phys_device, command_buffer, command_pool, queue, - minmax_pipeline, minmax_pipeline_layout, minmax_descriptor_set, - max_in_buf, min_in_buf, max_out_buf, min_out_buf, state_buf, size, - filter_mapped_float, pbp); + auto vulkan_minmax_opt = + vulkan_minmax(device, phys_device, command_buffer, command_pool, queue, + minmax_pipeline, minmax_pipeline_layout, minmax_desc_sets, + max_in_buf, min_in_buf, max_out_buf, min_out_buf, + state_buf, size, filter_mapped_float, pbp); if (!vulkan_minmax_opt.has_value()) { std::cerr << "Vulkan: vulkan_minmax returned nullopt!\n"; return {}; @@ -573,7 +573,7 @@ std::optional> dither::internal::vulkan_minmax( VkDevice device, VkPhysicalDevice phys_dev, VkCommandBuffer command_buffer, VkCommandPool command_pool, VkQueue queue, VkPipeline minmax_pipeline, VkPipelineLayout minmax_pipeline_layout, - VkDescriptorSet minmax_descriptor_set, VkBuffer max_in_buf, + std::array minmax_desc_sets, VkBuffer max_in_buf, VkBuffer min_in_buf, VkBuffer max_out_buf, VkBuffer min_out_buf, VkBuffer state_buf, const int size, const float *const filter_mapped, std::vector pbp) { @@ -666,25 +666,94 @@ std::optional> dither::internal::vulkan_minmax( int current_size = size; int next_size; - while (current_size > 1) { - next_size = (current_size + 1) / 2; - vkResetCommandBuffer(command_buffer, 0); - + bool swap = false; + vkResetCommandBuffer(command_buffer, 0); + { VkCommandBufferBeginInfo begin_info{}; begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - if (vkBeginCommandBuffer(command_buffer, &begin_info) != VK_SUCCESS) { std::clog << "vulkan_minmax ERROR: Failed to begin record compute " "command buffer!\n"; return std::nullopt; } + } + { + VkMemoryBarrier mem_barrier{}; + mem_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; + mem_barrier.srcAccessMask = + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; + mem_barrier.dstAccessMask = + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; + std::array buf_mem_barriers{}; + buf_mem_barriers[0].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + buf_mem_barriers[0].srcAccessMask = + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; + buf_mem_barriers[0].dstAccessMask = + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; + buf_mem_barriers[0].srcQueueFamilyIndex = 0; + buf_mem_barriers[0].dstQueueFamilyIndex = 0; + buf_mem_barriers[0].buffer = max_in_buf; + buf_mem_barriers[0].offset = 0; + buf_mem_barriers[0].size = VK_WHOLE_SIZE; + buf_mem_barriers[1].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + buf_mem_barriers[1].srcAccessMask = + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; + buf_mem_barriers[1].dstAccessMask = + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; + buf_mem_barriers[1].srcQueueFamilyIndex = 0; + buf_mem_barriers[1].dstQueueFamilyIndex = 0; + buf_mem_barriers[1].buffer = min_in_buf; + buf_mem_barriers[1].offset = 0; + buf_mem_barriers[1].size = VK_WHOLE_SIZE; + buf_mem_barriers[2].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + buf_mem_barriers[2].srcAccessMask = + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; + buf_mem_barriers[2].dstAccessMask = + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; + buf_mem_barriers[2].srcQueueFamilyIndex = 0; + buf_mem_barriers[2].dstQueueFamilyIndex = 0; + buf_mem_barriers[2].buffer = max_out_buf; + buf_mem_barriers[2].offset = 0; + buf_mem_barriers[2].size = VK_WHOLE_SIZE; + buf_mem_barriers[3].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + buf_mem_barriers[3].srcAccessMask = + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; + buf_mem_barriers[3].dstAccessMask = + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; + buf_mem_barriers[3].srcQueueFamilyIndex = 0; + buf_mem_barriers[3].dstQueueFamilyIndex = 0; + buf_mem_barriers[3].buffer = min_out_buf; + buf_mem_barriers[3].offset = 0; + buf_mem_barriers[3].size = VK_WHOLE_SIZE; + while (current_size > 1) { + next_size = (current_size + 1) / 2; - vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, - minmax_pipeline); - vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, - minmax_pipeline_layout, 0, 1, - &minmax_descriptor_set, 0, nullptr); - vkCmdDispatch(command_buffer, std::ceil((float)next_size / 256.0F), 1, 1); + vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, + minmax_pipeline); + if (swap) { + vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, + minmax_pipeline_layout, 0, 1, + &minmax_desc_sets[1], 0, nullptr); + } else { + vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, + minmax_pipeline_layout, 0, 1, + &minmax_desc_sets[0], 0, nullptr); + } + vkCmdDispatch(command_buffer, std::ceil((float)next_size / 256.0F), 1, 1); + + if (next_size > 1) { + vkCmdPipelineBarrier( + command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &mem_barrier, + buf_mem_barriers.size(), buf_mem_barriers.data(), 0, nullptr); + } + + current_size = next_size; + swap = !swap; + } + } + + { if (vkEndCommandBuffer(command_buffer) != VK_SUCCESS) { std::clog << "vulkan_minmax ERROR: Failed to record compute command buffer!\n"; @@ -708,27 +777,19 @@ std::optional> dither::internal::vulkan_minmax( std::clog << "vulkan_minmax ERROR: Failed to vkDeviceWaitIdle!\n"; return std::nullopt; } - - if (next_size > 1) { - vulkan_copy_buffer(device, command_pool, queue, max_out_buf, max_in_buf, - next_size * sizeof(FloatAndIndex)); - vulkan_copy_buffer(device, command_pool, queue, min_out_buf, min_in_buf, - next_size * sizeof(FloatAndIndex)); - - fai[0].idx = next_size; - std::memcpy(staging_mapped, &fai[0].idx, sizeof(int)); - vkFlushMappedMemoryRanges(device, 1, &range); - vulkan_copy_buffer(device, command_pool, queue, staging_buf, state_buf, - sizeof(int)); - } - - current_size = next_size; } - vulkan_copy_buffer(device, command_pool, queue, min_out_buf, staging_buf, - sizeof(FloatAndIndex), 0, 0); - vulkan_copy_buffer(device, command_pool, queue, max_out_buf, staging_buf, - sizeof(FloatAndIndex), 0, sizeof(FloatAndIndex)); + if (swap) { + vulkan_copy_buffer(device, command_pool, queue, min_out_buf, staging_buf, + sizeof(FloatAndIndex), 0, 0); + vulkan_copy_buffer(device, command_pool, queue, max_out_buf, staging_buf, + sizeof(FloatAndIndex), 0, sizeof(FloatAndIndex)); + } else { + vulkan_copy_buffer(device, command_pool, queue, min_in_buf, staging_buf, + sizeof(FloatAndIndex), 0, 0); + vulkan_copy_buffer(device, command_pool, queue, max_in_buf, staging_buf, + sizeof(FloatAndIndex), 0, sizeof(FloatAndIndex)); + } if (sizeof(FloatAndIndex) * 2 < props.limits.nonCoherentAtomSize) { range.size = props.limits.nonCoherentAtomSize; @@ -1104,7 +1165,7 @@ image::Bl dither::blue_noise(int width, int height, int threads, &compute_desc_set_layout); } - VkDescriptorSetLayout minmax_compute_desc_set_layout; + std::array minmax_desc_set_layouts{}; utility::Cleanup cleanup_minmax_compute_desc_set_layout{}; { std::array compute_layout_bindings{}; @@ -1149,18 +1210,27 @@ image::Bl dither::blue_noise(int width, int height, int threads, layout_info.pBindings = compute_layout_bindings.data(); if (vkCreateDescriptorSetLayout(device, &layout_info, nullptr, - &minmax_compute_desc_set_layout) != + &minmax_desc_set_layouts[0]) != VK_SUCCESS) { std::clog << "WARNING: Failed to create compute descriptor set layout " "(minmax)!\n"; goto ENDOF_VULKAN; } + if (vkCreateDescriptorSetLayout(device, &layout_info, nullptr, + &minmax_desc_set_layouts[1]) != + VK_SUCCESS) { + std::clog + << "WARNING: Failed to create compute descriptor set layout 2 " + "(minmax)!\n"; + goto ENDOF_VULKAN; + } cleanup_minmax_compute_desc_set_layout = utility::Cleanup( [device](void *ptr) { - vkDestroyDescriptorSetLayout( - device, *((VkDescriptorSetLayout *)ptr), nullptr); + auto layouts = (std::array *)ptr; + vkDestroyDescriptorSetLayout(device, layouts->at(0), nullptr); + vkDestroyDescriptorSetLayout(device, layouts->at(1), nullptr); }, - &minmax_compute_desc_set_layout); + &minmax_desc_set_layouts); } // Check and compile compute shader. @@ -1350,8 +1420,8 @@ image::Bl dither::blue_noise(int width, int height, int threads, VkPipelineLayoutCreateInfo pipeline_layout_info{}; pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipeline_layout_info.setLayoutCount = 1; - pipeline_layout_info.pSetLayouts = &minmax_compute_desc_set_layout; + pipeline_layout_info.setLayoutCount = 2; + pipeline_layout_info.pSetLayouts = minmax_desc_set_layouts.data(); if (vkCreatePipelineLayout(device, &pipeline_layout_info, nullptr, &minmax_compute_pipeline_layout) != @@ -1592,7 +1662,8 @@ image::Bl dither::blue_noise(int width, int height, int threads, device, phys_device, width * height * sizeof(dither::internal::FloatAndIndex), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | - VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, max_in_buf, max_in_buf_mem)) { std::clog << "WARNING: Failed to create max_in buffer (minmax)!\n"; goto ENDOF_VULKAN; @@ -1612,7 +1683,8 @@ image::Bl dither::blue_noise(int width, int height, int threads, device, phys_device, width * height * sizeof(dither::internal::FloatAndIndex), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | - VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, min_in_buf, min_in_buf_mem)) { std::clog << "WARNING: Failed to create min_in buffer (minmax)!\n"; goto ENDOF_VULKAN; @@ -1721,15 +1793,17 @@ image::Bl dither::blue_noise(int width, int height, int threads, VkDescriptorPool minmax_descriptor_pool; utility::Cleanup cleanup_minmax_descriptor_pool{}; { - VkDescriptorPoolSize pool_size{}; - pool_size.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - pool_size.descriptorCount = 5; + std::array pool_sizes{}; + pool_sizes[0].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + pool_sizes[0].descriptorCount = 5; + pool_sizes[1].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + pool_sizes[1].descriptorCount = 5; VkDescriptorPoolCreateInfo pool_info{}; pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - pool_info.poolSizeCount = 1; - pool_info.pPoolSizes = &pool_size; - pool_info.maxSets = 1; + pool_info.poolSizeCount = pool_sizes.size(); + pool_info.pPoolSizes = pool_sizes.data(); + pool_info.maxSets = 2; if (vkCreateDescriptorPool(device, &pool_info, nullptr, &minmax_descriptor_pool) != VK_SUCCESS) { @@ -1813,16 +1887,16 @@ image::Bl dither::blue_noise(int width, int height, int threads, descriptor_writes.data(), 0, nullptr); } - VkDescriptorSet minmax_compute_descriptor_set; + std::array minmax_compute_desc_sets; { VkDescriptorSetAllocateInfo alloc_info{}; alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; alloc_info.descriptorPool = minmax_descriptor_pool; - alloc_info.descriptorSetCount = 1; - alloc_info.pSetLayouts = &minmax_compute_desc_set_layout; + alloc_info.descriptorSetCount = 2; + alloc_info.pSetLayouts = minmax_desc_set_layouts.data(); if (vkAllocateDescriptorSets(device, &alloc_info, - &minmax_compute_descriptor_set) != + minmax_compute_desc_sets.data()) != VK_SUCCESS) { std::clog << "WARNING: Failed to allocate descriptor set (minmax)!\n"; goto ENDOF_VULKAN; @@ -1831,7 +1905,7 @@ image::Bl dither::blue_noise(int width, int height, int threads, std::array descriptor_writes{}; descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_writes[0].dstSet = minmax_compute_descriptor_set; + descriptor_writes[0].dstSet = minmax_compute_desc_sets[0]; descriptor_writes[0].dstBinding = 0; descriptor_writes[0].dstArrayElement = 0; descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; @@ -1843,7 +1917,7 @@ image::Bl dither::blue_noise(int width, int height, int threads, descriptor_writes[0].pBufferInfo = &max_in_info; descriptor_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_writes[1].dstSet = minmax_compute_descriptor_set; + descriptor_writes[1].dstSet = minmax_compute_desc_sets[0]; descriptor_writes[1].dstBinding = 1; descriptor_writes[1].dstArrayElement = 0; descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; @@ -1855,7 +1929,7 @@ image::Bl dither::blue_noise(int width, int height, int threads, descriptor_writes[1].pBufferInfo = &min_in_info; descriptor_writes[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_writes[2].dstSet = minmax_compute_descriptor_set; + descriptor_writes[2].dstSet = minmax_compute_desc_sets[0]; descriptor_writes[2].dstBinding = 2; descriptor_writes[2].dstArrayElement = 0; descriptor_writes[2].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; @@ -1867,7 +1941,7 @@ image::Bl dither::blue_noise(int width, int height, int threads, descriptor_writes[2].pBufferInfo = &max_out_info; descriptor_writes[3].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_writes[3].dstSet = minmax_compute_descriptor_set; + descriptor_writes[3].dstSet = minmax_compute_desc_sets[0]; descriptor_writes[3].dstBinding = 3; descriptor_writes[3].dstArrayElement = 0; descriptor_writes[3].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; @@ -1879,7 +1953,73 @@ image::Bl dither::blue_noise(int width, int height, int threads, descriptor_writes[3].pBufferInfo = &min_out_info; descriptor_writes[4].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_writes[4].dstSet = minmax_compute_descriptor_set; + descriptor_writes[4].dstSet = minmax_compute_desc_sets[0]; + descriptor_writes[4].dstBinding = 4; + descriptor_writes[4].dstArrayElement = 0; + descriptor_writes[4].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptor_writes[4].descriptorCount = 1; + VkDescriptorBufferInfo state_info{}; + state_info.buffer = state_buf; + state_info.offset = 0; + state_info.range = VK_WHOLE_SIZE; + descriptor_writes[4].pBufferInfo = &state_info; + + vkUpdateDescriptorSets(device, descriptor_writes.size(), + descriptor_writes.data(), 0, nullptr); + } + { + std::array descriptor_writes{}; + + descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptor_writes[0].dstSet = minmax_compute_desc_sets[1]; + descriptor_writes[0].dstBinding = 0; + descriptor_writes[0].dstArrayElement = 0; + descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptor_writes[0].descriptorCount = 1; + VkDescriptorBufferInfo max_out_info{}; + max_out_info.buffer = max_out_buf; + max_out_info.offset = 0; + max_out_info.range = VK_WHOLE_SIZE; + descriptor_writes[0].pBufferInfo = &max_out_info; + + descriptor_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptor_writes[1].dstSet = minmax_compute_desc_sets[1]; + descriptor_writes[1].dstBinding = 1; + descriptor_writes[1].dstArrayElement = 0; + descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptor_writes[1].descriptorCount = 1; + VkDescriptorBufferInfo min_out_info{}; + min_out_info.buffer = min_out_buf; + min_out_info.offset = 0; + min_out_info.range = VK_WHOLE_SIZE; + descriptor_writes[1].pBufferInfo = &min_out_info; + + descriptor_writes[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptor_writes[2].dstSet = minmax_compute_desc_sets[1]; + descriptor_writes[2].dstBinding = 2; + descriptor_writes[2].dstArrayElement = 0; + descriptor_writes[2].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptor_writes[2].descriptorCount = 1; + VkDescriptorBufferInfo max_in_info{}; + max_in_info.buffer = max_in_buf; + max_in_info.offset = 0; + max_in_info.range = VK_WHOLE_SIZE; + descriptor_writes[2].pBufferInfo = &max_in_info; + + descriptor_writes[3].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptor_writes[3].dstSet = minmax_compute_desc_sets[1]; + descriptor_writes[3].dstBinding = 3; + descriptor_writes[3].dstArrayElement = 0; + descriptor_writes[3].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptor_writes[3].descriptorCount = 1; + VkDescriptorBufferInfo min_in_info{}; + min_in_info.buffer = min_in_buf; + min_in_info.offset = 0; + min_in_info.range = VK_WHOLE_SIZE; + descriptor_writes[3].pBufferInfo = &min_in_info; + + descriptor_writes[4].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptor_writes[4].dstSet = minmax_compute_desc_sets[1]; descriptor_writes[4].dstBinding = 4; descriptor_writes[4].dstArrayElement = 0; descriptor_writes[4].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; @@ -1913,9 +2053,8 @@ image::Bl dither::blue_noise(int width, int height, int threads, device, phys_device, command_buffer, command_pool, compute_queue, pbp_buf, compute_pipeline, compute_pipeline_layout, compute_descriptor_set, filter_out_buf, minmax_compute_pipeline, - minmax_compute_pipeline_layout, minmax_compute_descriptor_set, - max_in_buf, min_in_buf, max_out_buf, min_out_buf, state_buf, width, - height); + minmax_compute_pipeline_layout, minmax_compute_desc_sets, max_in_buf, + min_in_buf, max_out_buf, min_out_buf, state_buf, width, height); if (!result.empty()) { return internal::rangeToBl(result, width); } diff --git a/src/blue_noise.hpp b/src/blue_noise.hpp index 8f9e61a..43f9f44 100644 --- a/src/blue_noise.hpp +++ b/src/blue_noise.hpp @@ -76,7 +76,7 @@ std::vector blue_noise_vulkan_impl( VkBuffer pbp_buf, VkPipeline pipeline, VkPipelineLayout pipeline_layout, VkDescriptorSet descriptor_set, VkBuffer filter_out_buf, VkPipeline minmax_pipeline, VkPipelineLayout minmax_pipeline_layout, - VkDescriptorSet minmax_descriptor_set, VkBuffer max_in_buf, + std::array minmax_descriptor_sets, VkBuffer max_in_buf, VkBuffer min_in_buf, VkBuffer max_out_buf, VkBuffer min_out_buf, VkBuffer state_buf, const int width, const int height); @@ -159,7 +159,7 @@ std::optional> vulkan_minmax( VkDevice device, VkPhysicalDevice phys_dev, VkCommandBuffer command_buffer, VkCommandPool command_pool, VkQueue queue, VkPipeline minmax_pipeline, VkPipelineLayout minmax_pipeline_layout, - VkDescriptorSet minmax_descriptor_set, VkBuffer max_in_buf, + std::array minmax_desc_sets, VkBuffer max_in_buf, VkBuffer min_in_buf, VkBuffer max_out_buf, VkBuffer min_out_buf, VkBuffer state_buf, const int size, const float *const filter_mapped, std::vector pbp); diff --git a/src/blue_noise_minmax.glsl b/src/blue_noise_minmax.glsl index 830615e..fbdc0bc 100644 --- a/src/blue_noise_minmax.glsl +++ b/src/blue_noise_minmax.glsl @@ -47,6 +47,8 @@ void main() { } } else { max_out[index] = max_in[index * 2]; + max_out[index + 1].pbp = 0; min_out[index] = min_in[index * 2]; + min_out[index + 1].pbp = 1; } }