diff options
| author | rdenno <rhysdenno@gmail.com> | 2026-11-02 09:26:01 -0500 |
|---|---|---|
| committer | rdenno <rhysdenno@gmail.com> | 2026-11-02 09:26:01 -0500 |
| commit | 2786bdf580e41bf0ba6e2a6452db73c4f5b97ed2 (patch) | |
| tree | 2c59cf5d66b869af52f338f3dea6e679e590f7bb /src/video_core/buffer_cache | |
| parent | 7ac108e2571d7cb39585c58994524131dd9d8c22 (diff) | |
| parent | c0cb3325e22756edb65c87d33ef298349ade0ad3 (diff) | |
Merge branch 'nx2-experimental' into fix/hw-shader-lowering
nx2-experimental lowers partial-mask TXD as well (Splatoon Raiders).
Keep its RZ second destination and this branch's odd register for a
lone third channel; take its wider F2I mode check with the .H1 source.
Assisted-by: Claude Opus 5.5 (conflict resolution)
Diffstat (limited to 'src/video_core/buffer_cache')
| -rw-r--r-- | src/video_core/buffer_cache/buffer_cache.h | 43 |
1 files changed, 40 insertions, 3 deletions
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index a030b563d4..53bbae7610 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -390,6 +390,10 @@ template <class P> void BufferCache<P>::BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) { const std::optional<DAddr> device_addr = gpu_memory->GpuToCpuAddress(gpu_addr); + if (!device_addr) { + channel_state->uniform_buffers[stage][index] = NULL_BINDING; + return; + } const Binding binding{ .device_addr = *device_addr, .size = size, @@ -400,7 +404,11 @@ void BufferCache<P>::BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr template <class P> void BufferCache<P>::DisableGraphicsUniformBuffer(size_t stage, u32 index) { - channel_state->uniform_buffers[stage][index] = NULL_BINDING; + auto& current = channel_state->uniform_buffers[stage][index]; + if (current.device_addr == 0 && current.size == 0 && !current.buffer_id) [[likely]] { + return; + } + current = NULL_BINDING; } template <class P> @@ -1005,6 +1013,26 @@ void BufferCache<P>::BindHostGraphicsUniformBuffers(size_t stage) { template <class P> void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 binding_index, bool needs_bind) { ++channel_state->uniform_cache_shots[0]; + // Bank 24 (root table 0, NVN2's push constants) is read from bank 17, which such games do not + // bind: stream the table's current words as that buffer. + if (index == 17 && maxwell3d->root_tables.loaded && channel_state->uniform_buffers[stage][index].size == 0) { + const auto& words = maxwell3d->root_tables.tables[0]; + const u32 size = (*channel_state->uniform_buffer_sizes)[stage][index]; + const u32 copied = (std::min)(size, static_cast<u32>(sizeof(words))); + if constexpr (IS_OPENGL) { + std::array<u8, sizeof(words)> data{}; + std::memcpy(data.data(), words.data(), copied); + runtime.BindFastUniformBuffer(stage, binding_index, copied); + runtime.PushFastUniformBuffer(stage, binding_index, std::span<const u8>(data.data(), copied)); + } else { + const std::span<u8> span = runtime.BindMappedUniformBuffer(stage, binding_index, size); + std::memset(span.data(), 0, span.size()); + std::memcpy(span.data(), words.data(), copied); + } + channel_state->fast_bound_uniform_buffers[stage] |= 1u << binding_index; + channel_state->uniform_buffer_binding_sizes[stage][binding_index] = size; + return; + } 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]); @@ -1505,6 +1533,9 @@ void BufferCache<P>::UpdateDrawIndirect() { template <class P> void BufferCache<P>::UpdateUniformBuffers(size_t stage) { + if (channel_state->enabled_uniform_buffer_masks[stage] == 0) [[likely]] { + return; + } ForEachEnabledBit(channel_state->enabled_uniform_buffer_masks[stage], [&](u32 index) { Binding& binding = channel_state->uniform_buffers[stage][index]; if (binding.buffer_id) { @@ -1522,6 +1553,9 @@ void BufferCache<P>::UpdateUniformBuffers(size_t stage) { template <class P> void BufferCache<P>::UpdateStorageBuffers(size_t stage) { + if (channel_state->enabled_storage_buffers[stage] == 0) [[likely]] { + return; + } ForEachEnabledBit(channel_state->enabled_storage_buffers[stage], [&](u32 index) { // Resolve buffer Binding& binding = channel_state->storage_buffers[stage][index]; @@ -1534,6 +1568,9 @@ void BufferCache<P>::UpdateStorageBuffers(size_t stage) { template <class P> void BufferCache<P>::UpdateTextureBuffers(size_t stage) { + if (channel_state->enabled_texture_buffers[stage] == 0) [[likely]] { + return; + } ForEachEnabledBit(channel_state->enabled_texture_buffers[stage], [&](u32 index) { Binding& binding = channel_state->texture_buffers[stage][index]; binding.buffer_id = FindBuffer(binding.device_addr, binding.size, false); @@ -1628,10 +1665,10 @@ void BufferCache<P>::MarkWrittenBuffer(BufferId buffer_id, DAddr device_addr, u3 template <class P> BufferId BufferCache<P>::FindBuffer(DAddr device_addr, u32 size, bool sparse_compatible) { - if (device_addr == 0) { + const u64 page = device_addr >> CACHING_PAGEBITS; + if (device_addr == 0 || page >= page_table.size()) { return NULL_BUFFER_ID; } - const u64 page = device_addr >> CACHING_PAGEBITS; const BufferId buffer_id = page_table[page]; if (buffer_id) { Buffer& buffer = slot_buffers[buffer_id]; |
