summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorReinUsesLisp <reinuseslisp@airmail.cc>2020-03-12 17:28:49 -0300
committerReinUsesLisp <reinuseslisp@airmail.cc>2020-03-12 18:22:05 -0300
commite22816a5bbdc0f082c208d0c09294973e19d360c (patch)
treee71542579df3628d0ec5ad0ba9d2b2078bccc4de /src
parentfce33adcf1cb16bc308c39cd47b0a4e1aee68bf7 (diff)
texture_cache: Report incompatible textures as black
Some games bind incompatible texture types to certain types. For example Astral Chain binds a 2D texture with 1 layer (non-array) to a cubemap slot (that's how it's used in the shader). After testing this in hardware, the expected "undefined behavior" is to report all pixels as black. We already have a path for reporting black textures in the texture cache. When textures types are incompatible, this commit binds these kind of textures. This is done on the API agnostic texture cache so no extra code has to be inserted on OpenGL or Vulkan. As a side effect, this fixes invalidations of ASTC textures on Astral Chain. This happened because yuzu detected a cube texture and forced 6 faces, generating a texture larger than what the TIC reported.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/texture_cache/texture_cache.h41
1 files changed, 39 insertions, 2 deletions
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 51373b687..6cdbe63d0 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -104,6 +104,11 @@ public:
if (!cache_addr) {
return GetNullSurface(SurfaceParams::ExpectedTarget(entry));
}
+
+ if (!IsTypeCompatible(tic.texture_type, entry)) {
+ return GetNullSurface(SurfaceParams::ExpectedTarget(entry));
+ }
+
const auto params{SurfaceParams::CreateForTexture(format_lookup_table, tic, entry)};
const auto [surface, view] = GetSurface(gpu_addr, cache_addr, params, true, false);
if (guard_samplers) {
@@ -914,13 +919,15 @@ private:
params.width = 1;
params.height = 1;
params.depth = 1;
+ if (target == SurfaceTarget::TextureCubemap || target == SurfaceTarget::TextureCubeArray) {
+ params.depth = 6;
+ }
params.pitch = 4;
params.num_levels = 1;
params.emulated_levels = 1;
- params.pixel_format = VideoCore::Surface::PixelFormat::RGBA16F;
+ params.pixel_format = VideoCore::Surface::PixelFormat::R8U;
params.type = VideoCore::Surface::SurfaceType::ColorTexture;
auto surface = CreateSurface(0ULL, params);
- invalid_memory.clear();
invalid_memory.resize(surface->GetHostSizeInBytes(), 0U);
surface->UploadTexture(invalid_memory);
surface->MarkAsModified(false, Tick());
@@ -1082,6 +1089,36 @@ private:
return siblings_table[static_cast<std::size_t>(format)];
}
+ /// Returns true the shader sampler entry is compatible with the TIC texture type.
+ static bool IsTypeCompatible(Tegra::Texture::TextureType tic_type,
+ const VideoCommon::Shader::Sampler& entry) {
+ const auto shader_type = entry.GetType();
+ switch (tic_type) {
+ case Tegra::Texture::TextureType::Texture1D:
+ case Tegra::Texture::TextureType::Texture1DArray:
+ return shader_type == Tegra::Shader::TextureType::Texture1D;
+ case Tegra::Texture::TextureType::Texture1DBuffer:
+ // TODO(Rodrigo): Assume as valid for now
+ return true;
+ case Tegra::Texture::TextureType::Texture2D:
+ case Tegra::Texture::TextureType::Texture2DNoMipmap:
+ return shader_type == Tegra::Shader::TextureType::Texture2D;
+ case Tegra::Texture::TextureType::Texture2DArray:
+ return shader_type == Tegra::Shader::TextureType::Texture2D ||
+ shader_type == Tegra::Shader::TextureType::TextureCube;
+ case Tegra::Texture::TextureType::Texture3D:
+ return shader_type == Tegra::Shader::TextureType::Texture3D;
+ case Tegra::Texture::TextureType::TextureCubeArray:
+ case Tegra::Texture::TextureType::TextureCubemap:
+ if (shader_type == Tegra::Shader::TextureType::TextureCube) {
+ return true;
+ }
+ return shader_type == Tegra::Shader::TextureType::Texture2D && entry.IsArray();
+ }
+ UNREACHABLE();
+ return true;
+ }
+
struct FramebufferTargetInfo {
TSurface target;
TView view;