aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSssnowyyy <78863999+Sssnowyyy@users.noreply.github.com>2026-11-02 11:30:32 -0500
committerSssnowyyy <78863999+Sssnowyyy@users.noreply.github.com>2026-11-02 14:53:47 -0500
commite46c6cbfb0f6735ca35f1150338c300f3c9c18fe (patch)
treedb5074467c500a20e45b2c7b0723275373237f83 /src
parent0ed4a3a9e795896a4751d0330c78958a309d1aa0 (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.cpp3
-rw-r--r--src/video_core/texture_cache/texture_cache.h3
-rw-r--r--src/video_core/textures/texture.h8
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;