diff options
| author | Sssnowyyy <78863999+Sssnowyyy@users.noreply.github.com> | 2026-11-02 11:30:32 -0500 |
|---|---|---|
| committer | Sssnowyyy <78863999+Sssnowyyy@users.noreply.github.com> | 2026-11-02 14:53:47 -0500 |
| commit | e46c6cbfb0f6735ca35f1150338c300f3c9c18fe (patch) | |
| tree | db5074467c500a20e45b2c7b0723275373237f83 /src | |
| parent | 0ed4a3a9e795896a4751d0330c78958a309d1aa0 (diff) | |
video_core: read texture handles as header offsets only on Switch 2
049c9633ed made TextureHeaderIndex take index / 32 for any texture index past the
pool that is a multiple of 32, in VisitImageView and in the shader environment.
That was written for Switch 2 handles that hold a header byte offset, but it ran
for Switch 1 games too, where such an out-of-range index used to give a null view
(and fail the shader environment's range check) and now binds an unrelated
header. Pass whether the memory manager uses native tiling, which is how Switch 2
titles are set up, and keep the previous behaviour otherwise.
Follow-up to 049c9633ed.
Assisted-by: Claude Sonnet 5.5 (implementation and commit message)
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/shader_environment.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 3 | ||||
| -rw-r--r-- | src/video_core/textures/texture.h | 8 |
3 files changed, 8 insertions, 6 deletions
diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp index 22e661c849..8d340ba881 100644 --- a/src/video_core/shader_environment.cpp +++ b/src/video_core/shader_environment.cpp @@ -316,7 +316,8 @@ std::optional<u64> GenericEnvironment::TryFindSize() { Tegra::Texture::TICEntry GenericEnvironment::ReadTextureInfo(GPUVAddr tic_addr, u32 tic_limit, bool via_header_index, u32 raw) { const auto handle{Tegra::Texture::TexturePair(raw, via_header_index)}; - const u32 index{Tegra::Texture::TextureHeaderIndex(handle.first, tic_limit)}; + const u32 index{Tegra::Texture::TextureHeaderIndex(handle.first, tic_limit, + gpu_memory->UsesNativeTiling())}; ASSERT(index <= tic_limit); const GPUVAddr descriptor_addr{tic_addr + index * sizeof(Tegra::Texture::TICEntry)}; Tegra::Texture::TICEntry entry; diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 3f3ae9cafd..4929c2df44 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -809,7 +809,8 @@ typename P::Framebuffer* TextureCache<P>::GetFramebuffer() { template <class P> ImageViewId TextureCache<P>::VisitImageView(u32 index, bool compute) { auto& table = compute ? channel_state->compute_image_table : channel_state->graphics_image_table; - index = Tegra::Texture::TextureHeaderIndex(index, table.current_limit); + index = Tegra::Texture::TextureHeaderIndex(index, table.current_limit, + gpu_memory->UsesNativeTiling()); if (index > table.current_limit) { LOG_DEBUG(HW_GPU, "Invalid image view index={}", index); return NULL_IMAGE_VIEW_ID; diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h index 79396d8a68..35a4c8eecf 100644 --- a/src/video_core/textures/texture.h +++ b/src/video_core/textures/texture.h @@ -167,10 +167,10 @@ static_assert(sizeof(TextureHandle) == 4, "TextureHandle has wrong size"); /// Some Switch 2 bindless handles (Switch Sports' scenery, read from a uniform register) hold /// the texture header's byte offset in the pool, index * 32, where the handle normally has the -/// index. Read it as an offset only when the plain index falls past the pool and the offset -/// lands inside it, so handles that already resolve are left alone. -[[nodiscard]] constexpr u32 TextureHeaderIndex(u32 index, u32 limit) { - if (index > limit && index % 32 == 0 && index / 32 <= limit) { +/// index. Read it as an offset only on Switch 2 (native tiling), when the plain index falls past +/// the pool and the offset lands inside it, so handles that already resolve are left alone. +[[nodiscard]] constexpr u32 TextureHeaderIndex(u32 index, u32 limit, bool switch2) { + if (switch2 && index > limit && index % 32 == 0 && index / 32 <= limit) { return index / 32; } return index; |
