diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/buffer_cache/buffer_cache.h | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index d004199ba..a75de4384 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -405,8 +405,6 @@ private: | |||
| 405 | u32 written_compute_texture_buffers = 0; | 405 | u32 written_compute_texture_buffers = 0; |
| 406 | u32 image_compute_texture_buffers = 0; | 406 | u32 image_compute_texture_buffers = 0; |
| 407 | 407 | ||
| 408 | std::array<u32, NUM_STAGES> fast_bound_uniform_buffers{}; | ||
| 409 | |||
| 410 | std::array<u32, 16> uniform_cache_hits{}; | 408 | std::array<u32, 16> uniform_cache_hits{}; |
| 411 | std::array<u32, 16> uniform_cache_shots{}; | 409 | std::array<u32, 16> uniform_cache_shots{}; |
| 412 | 410 | ||
| @@ -416,6 +414,10 @@ private: | |||
| 416 | 414 | ||
| 417 | std::conditional_t<HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS, std::array<u32, NUM_STAGES>, Empty> | 415 | std::conditional_t<HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS, std::array<u32, NUM_STAGES>, Empty> |
| 418 | dirty_uniform_buffers{}; | 416 | dirty_uniform_buffers{}; |
| 417 | std::conditional_t<IS_OPENGL, std::array<u32, NUM_STAGES>, Empty> fast_bound_uniform_buffers{}; | ||
| 418 | std::conditional_t<HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS, | ||
| 419 | std::array<std::array<u32, NUM_GRAPHICS_UNIFORM_BUFFERS>, NUM_STAGES>, Empty> | ||
| 420 | uniform_buffer_binding_sizes{}; | ||
| 419 | 421 | ||
| 420 | std::vector<BufferId> cached_write_buffer_ids; | 422 | std::vector<BufferId> cached_write_buffer_ids; |
| 421 | 423 | ||
| @@ -684,6 +686,7 @@ void BufferCache<P>::SetUniformBuffersState(const std::array<u32, NUM_STAGES>& m | |||
| 684 | fast_bound_uniform_buffers.fill(0); | 686 | fast_bound_uniform_buffers.fill(0); |
| 685 | } | 687 | } |
| 686 | dirty_uniform_buffers.fill(~u32{0}); | 688 | dirty_uniform_buffers.fill(~u32{0}); |
| 689 | uniform_buffer_binding_sizes.fill({}); | ||
| 687 | } | 690 | } |
| 688 | } | 691 | } |
| 689 | enabled_uniform_buffer_masks = mask; | 692 | enabled_uniform_buffer_masks = mask; |
| @@ -1016,14 +1019,18 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 | |||
| 1016 | TouchBuffer(buffer); | 1019 | TouchBuffer(buffer); |
| 1017 | const bool use_fast_buffer = binding.buffer_id != NULL_BUFFER_ID && | 1020 | const bool use_fast_buffer = binding.buffer_id != NULL_BUFFER_ID && |
| 1018 | size <= uniform_buffer_skip_cache_size && | 1021 | size <= uniform_buffer_skip_cache_size && |
| 1019 | !buffer.IsRegionGpuModified(cpu_addr, size); | 1022 | !buffer.IsRegionGpuModified(cpu_addr, size) && false; |
| 1020 | if (use_fast_buffer) { | 1023 | if (use_fast_buffer) { |
| 1021 | if constexpr (IS_OPENGL) { | 1024 | if constexpr (IS_OPENGL) { |
| 1022 | if (runtime.HasFastBufferSubData()) { | 1025 | if (runtime.HasFastBufferSubData()) { |
| 1023 | // Fast path for Nvidia | 1026 | // Fast path for Nvidia |
| 1024 | if (!HasFastUniformBufferBound(stage, binding_index)) { | 1027 | const bool should_fast_bind = |
| 1028 | !HasFastUniformBufferBound(stage, binding_index) || | ||
| 1029 | uniform_buffer_binding_sizes[stage][binding_index] != size; | ||
| 1030 | if (should_fast_bind) { | ||
| 1025 | // We only have to bind when the currently bound buffer is not the fast version | 1031 | // We only have to bind when the currently bound buffer is not the fast version |
| 1026 | fast_bound_uniform_buffers[stage] |= 1U << binding_index; | 1032 | fast_bound_uniform_buffers[stage] |= 1U << binding_index; |
| 1033 | uniform_buffer_binding_sizes[stage][binding_index] = size; | ||
| 1027 | runtime.BindFastUniformBuffer(stage, binding_index, size); | 1034 | runtime.BindFastUniformBuffer(stage, binding_index, size); |
| 1028 | } | 1035 | } |
| 1029 | const auto span = ImmediateBufferWithData(cpu_addr, size); | 1036 | const auto span = ImmediateBufferWithData(cpu_addr, size); |
| @@ -1033,6 +1040,7 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 | |||
| 1033 | } | 1040 | } |
| 1034 | if constexpr (IS_OPENGL) { | 1041 | if constexpr (IS_OPENGL) { |
| 1035 | fast_bound_uniform_buffers[stage] |= 1U << binding_index; | 1042 | fast_bound_uniform_buffers[stage] |= 1U << binding_index; |
| 1043 | uniform_buffer_binding_sizes[stage][binding_index] = size; | ||
| 1036 | } | 1044 | } |
| 1037 | // Stream buffer path to avoid stalling on non-Nvidia drivers or Vulkan | 1045 | // Stream buffer path to avoid stalling on non-Nvidia drivers or Vulkan |
| 1038 | const std::span<u8> span = runtime.BindMappedUniformBuffer(stage, binding_index, size); | 1046 | const std::span<u8> span = runtime.BindMappedUniformBuffer(stage, binding_index, size); |
| @@ -1046,9 +1054,13 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 | |||
| 1046 | } | 1054 | } |
| 1047 | ++uniform_cache_shots[0]; | 1055 | ++uniform_cache_shots[0]; |
| 1048 | 1056 | ||
| 1049 | if (!needs_bind && !HasFastUniformBufferBound(stage, binding_index)) { | 1057 | // Skip binding if it's not needed and if the bound buffer is not the fast version |
| 1050 | // Skip binding if it's not needed and if the bound buffer is not the fast version | 1058 | // This exists to avoid instances where the fast buffer is bound and a GPU write happens |
| 1051 | // This exists to avoid instances where the fast buffer is bound and a GPU write happens | 1059 | needs_bind |= HasFastUniformBufferBound(stage, binding_index); |
| 1060 | if constexpr (HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS) { | ||
| 1061 | needs_bind |= uniform_buffer_binding_sizes[stage][binding_index] != size; | ||
| 1062 | } | ||
| 1063 | if (!needs_bind) { | ||
| 1052 | return; | 1064 | return; |
| 1053 | } | 1065 | } |
| 1054 | const u32 offset = buffer.Offset(cpu_addr); | 1066 | const u32 offset = buffer.Offset(cpu_addr); |
| @@ -1060,6 +1072,9 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 | |||
| 1060 | const bool is_copy_bind = offset != 0 && !runtime.SupportsNonZeroUniformOffset(); | 1072 | const bool is_copy_bind = offset != 0 && !runtime.SupportsNonZeroUniformOffset(); |
| 1061 | dirty_uniform_buffers[stage] |= (is_copy_bind ? 1U : 0U) << index; | 1073 | dirty_uniform_buffers[stage] |= (is_copy_bind ? 1U : 0U) << index; |
| 1062 | } | 1074 | } |
| 1075 | if constexpr (HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS) { | ||
| 1076 | uniform_buffer_binding_sizes[stage][binding_index] = size; | ||
| 1077 | } | ||
| 1063 | if constexpr (NEEDS_BIND_UNIFORM_INDEX) { | 1078 | if constexpr (NEEDS_BIND_UNIFORM_INDEX) { |
| 1064 | runtime.BindUniformBuffer(stage, binding_index, buffer, offset, size); | 1079 | runtime.BindUniformBuffer(stage, binding_index, buffer, offset, size); |
| 1065 | } else { | 1080 | } else { |
| @@ -1725,6 +1740,7 @@ template <class P> | |||
| 1725 | void BufferCache<P>::NotifyBufferDeletion() { | 1740 | void BufferCache<P>::NotifyBufferDeletion() { |
| 1726 | if constexpr (HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS) { | 1741 | if constexpr (HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS) { |
| 1727 | dirty_uniform_buffers.fill(~u32{0}); | 1742 | dirty_uniform_buffers.fill(~u32{0}); |
| 1743 | uniform_buffer_binding_sizes.fill({}); | ||
| 1728 | } | 1744 | } |
| 1729 | auto& flags = maxwell3d.dirty.flags; | 1745 | auto& flags = maxwell3d.dirty.flags; |
| 1730 | flags[Dirty::IndexBuffer] = true; | 1746 | flags[Dirty::IndexBuffer] = true; |