aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/shader_environment.cpp5
-rw-r--r--src/video_core/texture_cache/texture_cache.h1
-rw-r--r--src/video_core/textures/texture.h11
3 files changed, 15 insertions, 2 deletions
diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp
index 78438769f5..be1dfe482b 100644
--- a/src/video_core/shader_environment.cpp
+++ b/src/video_core/shader_environment.cpp
@@ -315,8 +315,9 @@ 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)};
- ASSERT(handle.first <= tic_limit);
- const GPUVAddr descriptor_addr{tic_addr + handle.first * sizeof(Tegra::Texture::TICEntry)};
+ const u32 index{Tegra::Texture::TextureHeaderIndex(handle.first, tic_limit)};
+ ASSERT(index <= tic_limit);
+ const GPUVAddr descriptor_addr{tic_addr + index * sizeof(Tegra::Texture::TICEntry)};
Tegra::Texture::TICEntry entry;
gpu_memory->ReadBlock(descriptor_addr, &entry, sizeof(entry));
return entry;
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 77485a282e..e583d48349 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -684,6 +684,7 @@ 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);
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 9fc6a631bd..79396d8a68 100644
--- a/src/video_core/textures/texture.h
+++ b/src/video_core/textures/texture.h
@@ -165,6 +165,17 @@ 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) {
+ return index / 32;
+ }
+ return index;
+}
+
struct TICEntry {
union {
struct {