X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fbackends%2Fvulkan%2Fsynchronizer.cpp;h=7ce7c08a9d99fcc63763f3bb106e37fd9eb34e0f;hp=85c813e261e79536910f468480db1ce74c969f7a;hb=a16145549dc87c3b12671f797bd77b14bcc7786b;hpb=bbdf52425b736a59d01dda215458c3a1c9bdb320 diff --git a/source/backends/vulkan/synchronizer.cpp b/source/backends/vulkan/synchronizer.cpp index 85c813e2..7ce7c08a 100644 --- a/source/backends/vulkan/synchronizer.cpp +++ b/source/backends/vulkan/synchronizer.cpp @@ -35,17 +35,38 @@ void Synchronizer::access(VkBuffer buffer, size_t offset, size_t size) i->pending_write = true; } +void Synchronizer::access(VkImage image, unsigned aspect, int layer, unsigned layout, bool discard) +{ + auto i = find_member(image_accesses, image, &ImageAccess::image); + if(i==image_accesses.end()) + { + i = image_accesses.emplace(image_accesses.end()); + i->image = image; + i->aspect = aspect; + i->layer = layer; + i->current_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + } + + if(discard) + i->current_layout = VK_IMAGE_LAYOUT_UNDEFINED; + if(layer!=i->layer) + i->layer = -1; + i->pending_layout = layout; +} + void Synchronizer::reset() { for(BufferAccess &b: buffer_accesses) b.pending_write = false; + for(ImageAccess &i: image_accesses) + i.pending_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; } void Synchronizer::barrier(VkCommandBuffer command_buffer) { const VulkanFunctions &vk = device.get_functions(); - if(buffer_accesses.empty()) + if(buffer_accesses.empty() && image_accesses.empty()) return; VkPipelineStageFlags src_stage = 0; @@ -75,13 +96,52 @@ void Synchronizer::barrier(VkCommandBuffer command_buffer) dst_stage |= (b.pending_write ? buffer_write_stages : buffer_read_stages); } + static constexpr VkPipelineStageFlags image_read_stages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT|VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT| + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT|VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + static constexpr VkPipelineStageFlags image_write_stages = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT| + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT|VK_PIPELINE_STAGE_TRANSFER_BIT; + + vector image_barriers; + image_barriers.reserve(image_accesses.size()); + for(const ImageAccess &i: image_accesses) + { + image_barriers.emplace_back(VkImageMemoryBarrier{ }); + VkImageMemoryBarrier &barrier = image_barriers.back(); + + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.srcAccessMask = (is_write_layout(i.current_layout) ? VK_ACCESS_MEMORY_WRITE_BIT : 0); + barrier.dstAccessMask = (is_write_layout(i.pending_layout) ? VK_ACCESS_MEMORY_WRITE_BIT : VK_ACCESS_MEMORY_READ_BIT); + barrier.oldLayout = static_cast(i.current_layout); + barrier.newLayout = static_cast(i.pending_layout); + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = handle_cast<::VkImage>(i.image); + barrier.subresourceRange.aspectMask = i.aspect; + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + if(i.layer>=0) + { + barrier.subresourceRange.baseArrayLayer = i.layer; + barrier.subresourceRange.layerCount = 1; + } + else + { + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + } + + if(i.current_layout!=VK_IMAGE_LAYOUT_UNDEFINED) + src_stage |= (is_write_layout(i.current_layout) ? image_write_stages : image_read_stages); + dst_stage |= (is_write_layout(i.pending_layout) ? image_write_stages : image_read_stages); + } + if(!src_stage) src_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; if(!dst_stage) dst_stage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; vk.CmdPipelineBarrier(command_buffer, src_stage, dst_stage, 0, 0, 0, - buffer_barriers.size(), buffer_barriers.data(), 0, 0); + buffer_barriers.size(), buffer_barriers.data(), image_barriers.size(), image_barriers.data()); for(auto i=buffer_accesses.begin(); i!=buffer_accesses.end(); ) { @@ -93,6 +153,23 @@ void Synchronizer::barrier(VkCommandBuffer command_buffer) ++i; } } + + for(auto i=image_accesses.begin(); i!=image_accesses.end(); ) + { + if(i->pending_layout==VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + i = image_accesses.erase(i); + else + { + i->current_layout = i->pending_layout; + ++i; + } + } +} + +bool Synchronizer::is_write_layout(unsigned layout) +{ + return layout==VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL || layout==VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL || + layout==VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; } } // namespace GL