diff --git a/src/video_core/buffer_cache/buffer.h b/src/video_core/buffer_cache/buffer.h index 26d48eaef..334975788 100644 --- a/src/video_core/buffer_cache/buffer.h +++ b/src/video_core/buffer_cache/buffer.h @@ -118,6 +118,25 @@ public: return buffer; } + std::optional GetBarrier(vk::AccessFlagBits2 dst_acess_mask, + vk::PipelineStageFlagBits2 dst_stage) { + if (dst_acess_mask == access_mask && stage == dst_stage) { + return {}; + } + + auto barrier = vk::BufferMemoryBarrier2{ + .srcStageMask = stage, + .srcAccessMask = access_mask, + .dstStageMask = dst_stage, + .dstAccessMask = dst_acess_mask, + .buffer = buffer.buffer, + .size = size_bytes, + }; + access_mask = dst_acess_mask; + stage = dst_stage; + return barrier; + } + public: VAddr cpu_addr = 0; bool is_picked{}; @@ -128,6 +147,8 @@ public: const Vulkan::Instance* instance{}; MemoryUsage usage; UniqueBuffer buffer; + vk::AccessFlagBits2 access_mask{vk::AccessFlagBits2::eNone}; + vk::PipelineStageFlagBits2 stage{vk::PipelineStageFlagBits2::eNone}; struct BufferView { u32 offset; u32 size; diff --git a/src/video_core/buffer_cache/buffer_cache.cpp b/src/video_core/buffer_cache/buffer_cache.cpp index 93e05085d..d67e953eb 100644 --- a/src/video_core/buffer_cache/buffer_cache.cpp +++ b/src/video_core/buffer_cache/buffer_cache.cpp @@ -248,11 +248,11 @@ std::pair BufferCache::ObtainBuffer(VAddr device_addr, u32 size, b return {&buffer, buffer.Offset(device_addr)}; } -std::pair BufferCache::ObtainTempBuffer(VAddr gpu_addr, u32 size) { +std::pair BufferCache::ObtainTempBuffer(VAddr gpu_addr, u32 size) { const u64 page = gpu_addr >> CACHING_PAGEBITS; const BufferId buffer_id = page_table[page]; if (buffer_id) { - const Buffer& buffer = slot_buffers[buffer_id]; + Buffer& buffer = slot_buffers[buffer_id]; if (buffer.IsInBounds(gpu_addr, size)) { return {&buffer, buffer.Offset(gpu_addr)}; } diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index b9002cea2..9be258ab9 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -70,7 +70,7 @@ public: bool is_texel_buffer = false); /// Obtains a temporary buffer for usage in texture cache. - [[nodiscard]] std::pair ObtainTempBuffer(VAddr gpu_addr, u32 size); + [[nodiscard]] std::pair ObtainTempBuffer(VAddr gpu_addr, u32 size); /// Return true when a region is registered on the cache [[nodiscard]] bool IsRegionRegistered(VAddr addr, size_t size); diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 08619dd6d..4f7fafee0 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp @@ -104,6 +104,7 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache, boost::container::static_vector buffer_infos; boost::container::static_vector image_infos; boost::container::small_vector set_writes; + boost::container::small_vector buffer_barriers; Shader::PushData push_data{}; u32 binding{}; @@ -183,6 +184,13 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache, } buffer_view = vk_buffer->View(offset_aligned, size + adjust, desc.is_written, vsharp.GetDataFmt(), vsharp.GetNumberFmt()); + + if (auto barrier = + vk_buffer->GetBarrier(desc.is_written ? vk::AccessFlagBits2::eShaderWrite + : vk::AccessFlagBits2::eShaderRead, + vk::PipelineStageFlagBits2::eComputeShader)) { + buffer_barriers.emplace_back(*barrier); + } } set_writes.push_back({ .dstSet = VK_NULL_HANDLE, @@ -224,7 +232,7 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache, const auto ssharp = sampler.GetSharp(*info); if (ssharp.force_degamma) { LOG_WARNING(Render_Vulkan, "Texture requires gamma correction"); - } + } const auto vk_sampler = texture_cache.GetSampler(ssharp); image_infos.emplace_back(vk_sampler, VK_NULL_HANDLE, vk::ImageLayout::eGeneral); set_writes.push_back({ @@ -242,6 +250,15 @@ bool ComputePipeline::BindResources(VideoCore::BufferCache& buffer_cache, } const auto cmdbuf = scheduler.CommandBuffer(); + + if (!buffer_barriers.empty()) { + auto dependencies = vk::DependencyInfo{ + .bufferMemoryBarrierCount = u32(buffer_barriers.size()), + .pBufferMemoryBarriers = buffer_barriers.data(), + }; + cmdbuf.pipelineBarrier2(dependencies); + } + cmdbuf.pushConstants(*pipeline_layout, vk::ShaderStageFlagBits::eCompute, 0u, sizeof(push_data), &push_data); cmdbuf.pushDescriptorSetKHR(vk::PipelineBindPoint::eCompute, *pipeline_layout, 0, set_writes); diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 7830de53b..708872a6f 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -359,7 +359,7 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs, boost::container::static_vector buffer_infos; boost::container::static_vector image_infos; boost::container::small_vector set_writes; - boost::container::small_vector buffer_barriers; + boost::container::small_vector buffer_barriers; Shader::PushData push_data{}; u32 binding{}; @@ -425,15 +425,11 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs, } buffer_view = vk_buffer->View(offset_aligned, size + adjust, tex_buffer.is_written, vsharp.GetDataFmt(), vsharp.GetNumberFmt()); - - if (buffer_cache.IsRegionGpuModified(address, size)) { - buffer_barriers.push_back(vk::BufferMemoryBarrier{ - .srcAccessMask = vk::AccessFlagBits::eShaderWrite, - .dstAccessMask = vk::AccessFlagBits::eShaderRead, - .buffer = vk_buffer->Handle(), - .offset = offset, - .size = size, - }); + const auto dst_access = tex_buffer.is_written ? vk::AccessFlagBits2::eShaderWrite + : vk::AccessFlagBits2::eShaderRead; + if (auto barrier = vk_buffer->GetBarrier( + dst_access, vk::PipelineStageFlagBits2::eVertexShader)) { + buffer_barriers.emplace_back(*barrier); } } set_writes.push_back({ @@ -501,10 +497,11 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs, const auto cmdbuf = scheduler.CommandBuffer(); if (!buffer_barriers.empty()) { - cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eFragmentShader | - vk::PipelineStageFlagBits::eComputeShader, - vk::PipelineStageFlagBits::eFragmentShader, - vk::DependencyFlagBits::eByRegion, {}, buffer_barriers, {}); + auto dependencies = vk::DependencyInfo{ + .bufferMemoryBarrierCount = u32(buffer_barriers.size()), + .pBufferMemoryBarriers = buffer_barriers.data(), + }; + cmdbuf.pipelineBarrier2(dependencies); } if (!set_writes.empty()) { diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 56ab229ce..9a9136c35 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -228,6 +228,7 @@ bool Instance::CreateDevice() { const bool maintenance5 = add_extension(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); add_extension(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); add_extension(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME); + add_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME); #ifdef __APPLE__ // Required by Vulkan spec if supported. diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index bf4470e05..967ef887b 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -314,6 +314,7 @@ ImageView& TextureCache::FindDepthTarget(const ImageInfo& image_info, // Update tracked image usage image.info.usage.depth_target = true; + image.info.usage.stencil = has_stencil; return RegisterImageView(image_id, view_info); } @@ -383,18 +384,13 @@ void TextureCache::RefreshImage(Image& image, Vulkan::Scheduler* custom_schedule // The obtained buffer may be written by a shader so we need to emit a barrier to prevent // RAW hazard - if (buffer_cache.IsRegionGpuModified(image_addr, image_size)) { - const vk::BufferMemoryBarrier post_barrier{ - .srcAccessMask = vk::AccessFlagBits::eShaderWrite, - .dstAccessMask = vk::AccessFlagBits::eTransferRead, - .buffer = buffer, - .offset = offset, - .size = image_size, + if (auto barrier = vk_buffer->GetBarrier(vk::AccessFlagBits2::eTransferRead, + vk::PipelineStageFlagBits2::eTransfer)) { + auto dependencies = vk::DependencyInfo{ + .bufferMemoryBarrierCount = 1, + .pBufferMemoryBarriers = &barrier.value(), }; - cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eFragmentShader | - vk::PipelineStageFlagBits::eComputeShader, - vk::PipelineStageFlagBits::eTransfer, - vk::DependencyFlagBits::eByRegion, {}, post_barrier, {}); + cmdbuf.pipelineBarrier2(dependencies); } }