diff --git a/src/video_core/buffer_cache/buffer_cache.cpp b/src/video_core/buffer_cache/buffer_cache.cpp index 70e7e7d83..eea9f6a7f 100644 --- a/src/video_core/buffer_cache/buffer_cache.cpp +++ b/src/video_core/buffer_cache/buffer_cache.cpp @@ -584,8 +584,12 @@ void BufferCache::CreateFaultBuffers() { } for (const auto& range : fault_ranges) { const VAddr start = range.lower(); - const u32 size = range.upper() - start; - CreateBuffer(start, size); + const u64 size = range.upper() - start; + // Buffer size is 32 bits + for (VAddr addr = start; addr < size; addr += std::numeric_limits::max()) { + const u32 size_buffer = std::min(size, std::numeric_limits::max()); + CreateBuffer(addr, size_buffer); + } } } @@ -825,7 +829,7 @@ bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, VAddr device_addr, return true; } -void BufferCache::SynchronizeRange(VAddr device_addr, u32 size) { +void BufferCache::SynchronizeRange(VAddr device_addr, u64 size) { if (device_addr == 0) { return; } @@ -840,6 +844,25 @@ void BufferCache::SynchronizeRange(VAddr device_addr, u32 size) { }); } +void BufferCache::MemoryBarrier() { + // Vulkan doesn't know which buffer we access in a shader if we use + // BufferDeviceAddress. We need a full memory barrier. + // For now, we only read memory using BDA. If we want to write to it, + // we might need to change this. + scheduler.EndRendering(); + const auto cmdbuf = scheduler.CommandBuffer(); + vk::MemoryBarrier2 barrier = { + .srcStageMask = vk::PipelineStageFlagBits2::eTransfer, + .srcAccessMask = vk::AccessFlagBits2::eMemoryWrite, + .dstStageMask = vk::PipelineStageFlagBits2::eAllCommands, + .dstAccessMask = vk::AccessFlagBits2::eMemoryRead, + }; + cmdbuf.pipelineBarrier2(vk::DependencyInfo{ + .memoryBarrierCount = 1, + .pMemoryBarriers = &barrier, + }); +} + void BufferCache::InlineDataBuffer(Buffer& buffer, VAddr address, const void* value, u32 num_bytes) { scheduler.EndRendering(); diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 39992ea07..315246ea2 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -142,7 +142,10 @@ public: void ResetFaultReadbackBuffer(); /// Synchronizes all buffers in the specified range. - void SynchronizeRange(VAddr device_addr, u32 size); + void SynchronizeRange(VAddr device_addr, u64 size); + + /// Record memory barrier. Used for buffers when accessed via BDA. + void MemoryBarrier(); private: template diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index e89469818..3d79f4669 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -476,6 +476,7 @@ bool Rasterizer::BindResources(const Pipeline* pipeline) { } } buffer_cache.ResetFaultReadbackBuffer(); + buffer_cache.MemoryBarrier(); } return true;