diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 9eaa322c9c..b5949c8b61 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -790,6 +790,12 @@ void BufferCache
::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 const Binding& binding = channel_state->uniform_buffers[stage][index]; const DAddr device_addr = binding.device_addr; const u32 size = (std::min)(binding.size, (*channel_state->uniform_buffer_sizes)[stage][index]); + u32 size_for_bind = size; + if constexpr (!IS_OPENGL) { + if constexpr (requires(const Runtime& r) { r.GetMaxUniformBufferRange(); }) { + size_for_bind = (std::min)(size_for_bind, runtime.GetMaxUniformBufferRange()); + } + } Buffer& buffer = slot_buffers[binding.buffer_id]; TouchBuffer(buffer, binding.buffer_id); const bool use_fast_buffer = binding.buffer_id != NULL_BUFFER_ID && @@ -814,10 +820,10 @@ void BufferCache
::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32
}
}
channel_state->fast_bound_uniform_buffers[stage] |= 1u << binding_index;
- channel_state->uniform_buffer_binding_sizes[stage][binding_index] = size;
+ channel_state->uniform_buffer_binding_sizes[stage][binding_index] = size_for_bind;
// Stream buffer path to avoid stalling on non-Nvidia drivers or Vulkan
- const std::span ::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32
// This exists to avoid instances where the fast buffer is bound and a GPU write happens
needs_bind |= HasFastUniformBufferBound(stage, binding_index);
if constexpr (HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS) {
- needs_bind |= channel_state->uniform_buffer_binding_sizes[stage][binding_index] != size;
+ needs_bind |= channel_state->uniform_buffer_binding_sizes[stage][binding_index] != size_for_bind;
}
if (!needs_bind) {
return;
}
const u32 offset = buffer.Offset(device_addr);
- if constexpr (IS_OPENGL) {
+ if constexpr (!IS_OPENGL) {
+ // Vulkan requires aligned uniform buffer offsets. If unaligned, stream into the
+ // aligned uniform ring as a correctness fallback (stock Qualcomm)
+ if constexpr (requires(const Runtime& r) { r.GetUniformBufferAlignment(); }) {
+ const u32 ubo_align = runtime.GetUniformBufferAlignment();
+ if (ubo_align != 0 && (offset % ubo_align) != 0) {
+ if constexpr (HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS) {
+ channel_state->uniform_buffer_binding_sizes[stage][binding_index] = size_for_bind;
+ }
+ const std::span ::BindHostComputeUniformBuffers() {
TouchBuffer(buffer, binding.buffer_id);
const u32 size =
(std::min)(binding.size, (*channel_state->compute_uniform_buffer_sizes)[index]);
+ u32 size_for_bind = size;
+ if constexpr (!IS_OPENGL) {
+ if constexpr (requires(const Runtime& r) { r.GetMaxUniformBufferRange(); }) {
+ size_for_bind = (std::min)(size_for_bind, runtime.GetMaxUniformBufferRange());
+ }
+ }
SynchronizeBuffer(buffer, binding.device_addr, size);
const u32 offset = buffer.Offset(binding.device_addr);
- buffer.MarkUsage(offset, size);
+ if constexpr (!IS_OPENGL) {
+ if constexpr (requires(const Runtime& r) { r.GetUniformBufferAlignment(); }) {
+ const u32 ubo_align = runtime.GetUniformBufferAlignment();
+ if (ubo_align != 0 && (offset % ubo_align) != 0) {
+ const std::span