X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fbackends%2Fvulkan%2Fsynchronizer.cpp;h=9995f248c89d06503dc00a507b2748e08f3cb964;hb=c356a20547afae97b412da36e0b0a7d51e879401;hp=7ce7c08a9d99fcc63763f3bb106e37fd9eb34e0f;hpb=a16145549dc87c3b12671f797bd77b14bcc7786b;p=libs%2Fgl.git diff --git a/source/backends/vulkan/synchronizer.cpp b/source/backends/vulkan/synchronizer.cpp index 7ce7c08a..9995f248 100644 --- a/source/backends/vulkan/synchronizer.cpp +++ b/source/backends/vulkan/synchronizer.cpp @@ -1,6 +1,7 @@ #include #include "buffer.h" #include "device.h" +#include "error.h" #include "texture.h" #include "synchronizer.h" #include "vulkan.h" @@ -14,12 +15,12 @@ Synchronizer::Synchronizer(Device &d): device(d) { } -void Synchronizer::access(VkBuffer buffer, size_t offset, size_t size) +void Synchronizer::write_buffer(VkBuffer buffer, size_t offset, size_t size, bool mapped) { - auto i = find_member(buffer_accesses, buffer, &BufferAccess::buffer); - if(i==buffer_accesses.end()) + auto i = lower_bound_member(buffer_accesses, buffer, &BufferAccess::buffer); + if(i==buffer_accesses.end() || i->buffer!=buffer) { - i = buffer_accesses.emplace(buffer_accesses.end()); + i = buffer_accesses.emplace(i); i->buffer = buffer; i->offset = offset; i->size = size; @@ -32,26 +33,84 @@ void Synchronizer::access(VkBuffer buffer, size_t offset, size_t size) i->size = end-begin; } + if(mapped) + i->was_written = true; i->pending_write = true; } -void Synchronizer::access(VkImage image, unsigned aspect, int layer, unsigned layout, bool discard) +void Synchronizer::split_image_mipmap(VkImage image, unsigned aspect, unsigned n_levels) { - auto i = find_member(image_accesses, image, &ImageAccess::image); - if(i==image_accesses.end()) + if(!n_levels) + throw invalid_argument("Synchronizer::split_image_mipmap"); + + auto i = lower_bound_member(image_accesses, image, &ImageAccess::image); + if(i!=image_accesses.end() && i->image==image && i->level>=0) + return; + + if(i!=image_accesses.end() && i->image==image && i->level==-1) + { + i = image_accesses.insert(i, n_levels-1, *i); + for(unsigned j=0; jlevel = j; + } + else { - i = image_accesses.emplace(image_accesses.end()); + ImageAccess access; + access.image = image; + access.aspect = aspect; + access.current_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + access.pending_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + if(i->level==-2) + i = image_accesses.erase(i); + + for(unsigned j=0; jimage!=image || i->level>static_cast(j)) + { + i = image_accesses.insert(i, access); + i->level = j; + } + } +} + +void Synchronizer::change_image_layout(VkImage image, unsigned aspect, int level, unsigned layout, bool discard) +{ + auto i = lower_bound_member(image_accesses, image, &ImageAccess::image); + + if(level>=0) + { + if(i==image_accesses.end() || i->image!=image) + { + i = image_accesses.emplace(i); + i->image = image; + i->level = -2; + ++i; + } + else if(i->level==-1) + throw invalid_operation("Synchronizer::change_image_layout"); + else + { + for(; (i!=image_accesses.end() && i->image==image && i->levelimage==image && i->level==-2) + throw invalid_operation("Synchronizer::change_image_layout"); + + if(i==image_accesses.end() || i->image!=image || (level>=0 && i->level!=level)) + { + i = image_accesses.emplace(i); i->image = image; i->aspect = aspect; - i->layer = layer; + i->level = (level<0 ? -1 : level); 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; + for(; (i!=image_accesses.end() && i->image==image && (level<0 || i->level==level)); ++i) + { + if(discard) + i->current_layout = VK_IMAGE_LAYOUT_UNDEFINED; + i->pending_layout = layout; + } } void Synchronizer::reset() @@ -74,12 +133,16 @@ void Synchronizer::barrier(VkCommandBuffer command_buffer) static constexpr VkPipelineStageFlags buffer_read_stages = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT| VK_PIPELINE_STAGE_VERTEX_SHADER_BIT|VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - static constexpr VkPipelineStageFlags buffer_write_stages = VK_PIPELINE_STAGE_TRANSFER_BIT; + static constexpr VkPipelineStageFlags buffer_write_stages = VK_PIPELINE_STAGE_TRANSFER_BIT| + VK_PIPELINE_STAGE_HOST_BIT; vector buffer_barriers; buffer_barriers.reserve(buffer_accesses.size()); for(BufferAccess &b: buffer_accesses) { + if(b.pending_write==b.was_written) + continue; + buffer_barriers.emplace_back(VkBufferMemoryBarrier{ }); VkBufferMemoryBarrier &barrier = buffer_barriers.back(); @@ -105,6 +168,9 @@ void Synchronizer::barrier(VkCommandBuffer command_buffer) image_barriers.reserve(image_accesses.size()); for(const ImageAccess &i: image_accesses) { + if(i.level==-2 || i.pending_layout==i.current_layout) + continue; + image_barriers.emplace_back(VkImageMemoryBarrier{ }); VkImageMemoryBarrier &barrier = image_barriers.back(); @@ -117,24 +183,19 @@ void Synchronizer::barrier(VkCommandBuffer command_buffer) 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; - } + barrier.subresourceRange.baseMipLevel = max(i.level, 0); + barrier.subresourceRange.levelCount = (i.level<0 ? VK_REMAINING_MIP_LEVELS : 1); + 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(buffer_barriers.empty() && image_barriers.empty()) + return; + if(!src_stage) src_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; if(!dst_stage) @@ -156,7 +217,25 @@ void Synchronizer::barrier(VkCommandBuffer command_buffer) for(auto i=image_accesses.begin(); i!=image_accesses.end(); ) { - if(i->pending_layout==VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + if(i->level!=-1) + { + auto j = i; + if(j->level==-2) + ++j; + + bool remove_image = true; + for(; (j!=image_accesses.end() && j->image==i->image); ++j) + remove_image &= (j->pending_layout==VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + if(remove_image) + i = image_accesses.erase(i, j); + else + { + for(; i!=j; ++i) + i->current_layout = i->pending_layout; + } + } + else if(i->pending_layout==VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) i = image_accesses.erase(i); else {