diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 779d6a1822..bad593a00d 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -905,9 +905,23 @@ void BufferCache

::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 const u32 size = (std::min)(binding.size, (*channel_state->uniform_buffer_sizes)[stage][index]); Buffer& buffer = slot_buffers[binding.buffer_id]; TouchBuffer(buffer, binding.buffer_id); - const bool use_fast_buffer = binding.buffer_id != NULL_BUFFER_ID && - size <= channel_state->uniform_buffer_skip_cache_size && - !memory_tracker.IsRegionGpuModified(device_addr, size); + const bool has_host_buffer = binding.buffer_id != NULL_BUFFER_ID; + const u32 offset = has_host_buffer ? buffer.Offset(device_addr) : 0; + const bool needs_alignment_stream = [&]() { + if constexpr (IS_OPENGL) { + return false; + } else { + if (!has_host_buffer) { + return false; + } + const u32 alignment = runtime.GetUniformBufferAlignment(); + return alignment > 1 && (offset % alignment) != 0; + } + }(); + const bool use_fast_buffer = needs_alignment_stream || + (has_host_buffer && + size <= channel_state->uniform_buffer_skip_cache_size && + !memory_tracker.IsRegionGpuModified(device_addr, size)); if (use_fast_buffer) { if constexpr (IS_OPENGL) { if (runtime.HasFastBufferSubData()) { @@ -946,7 +960,6 @@ void BufferCache

::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 if (!needs_bind) { return; } - const u32 offset = buffer.Offset(device_addr); if constexpr (IS_OPENGL) { // Mark the index as dirty if offset doesn't match const bool is_copy_bind = offset != 0 && !runtime.SupportsNonZeroUniformOffset(); @@ -1063,9 +1076,30 @@ void BufferCache

::BindHostComputeUniformBuffers() { TouchBuffer(buffer, binding.buffer_id); const u32 size = (std::min)(binding.size, (*channel_state->compute_uniform_buffer_sizes)[index]); + const bool has_host_buffer = binding.buffer_id != NULL_BUFFER_ID; + const u32 offset = has_host_buffer ? buffer.Offset(binding.device_addr) : 0; + const bool needs_alignment_stream = [&]() { + if constexpr (IS_OPENGL) { + return false; + } else { + if (!has_host_buffer) { + return false; + } + const u32 alignment = runtime.GetUniformBufferAlignment(); + return alignment > 1 && (offset % alignment) != 0; + } + }(); + if constexpr (!IS_OPENGL) { + if (needs_alignment_stream) { + const std::span span = + runtime.BindMappedUniformBuffer(0, binding_index, size); + device_memory.ReadBlockUnsafe(binding.device_addr, span.data(), size); + return; + } + } + SynchronizeBuffer(buffer, binding.device_addr, size); - const u32 offset = buffer.Offset(binding.device_addr); buffer.MarkUsage(offset, size); if constexpr (NEEDS_BIND_UNIFORM_INDEX) { runtime.BindComputeUniformBuffer(binding_index, buffer, offset, size); diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h index 4188dec7cc..23ebe50196 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.h +++ b/src/video_core/renderer_opengl/gl_buffer_cache.h @@ -198,6 +198,10 @@ public: return device.CanReportMemoryUsage(); } + u32 GetUniformBufferAlignment() const { + return static_cast(device.GetUniformBufferAlignment()); + } + u32 GetStorageBufferAlignment() const { return static_cast(device.GetShaderStorageBufferAlignment()); } diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 821ad82562..6912e315d8 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp @@ -415,6 +415,10 @@ bool BufferCacheRuntime::CanReportMemoryUsage() const { return device.CanReportMemoryUsage(); } +u32 BufferCacheRuntime::GetUniformBufferAlignment() const { + return static_cast(device.GetUniformBufferAlignment()); +} + u32 BufferCacheRuntime::GetStorageBufferAlignment() const { return static_cast(device.GetStorageBufferAlignment()); } diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index 4cf2510124..8d4020e0e5 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h @@ -96,6 +96,8 @@ public: bool CanReportMemoryUsage() const; + u32 GetUniformBufferAlignment() const; + u32 GetStorageBufferAlignment() const; [[nodiscard]] StagingBufferRef UploadStagingBuffer(size_t size);