[Textures] Normalize 1D TICs that use layers to 1DArray; (#274)

Some TIC entries are tagged Texture1D but actually use array layers so previously it was marked as simple 1D and hence the assert, this fixes the said issue(Depth > 1 or baseLayer != 0).
Games fixed- God Eater 3

Reviewed-on: #274
Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev>
Co-authored-by: wildcard <wildcard@eden-emu.dev>
Co-committed-by: wildcard <wildcard@eden-emu.dev>
This commit is contained in:
wildcard 2025-08-19 02:28:17 +02:00 committed by crueter
parent 77b3f159af
commit 12f5a96f01
Signed by: crueter
GPG key ID: 425ACD2D4830EBC6
2 changed files with 129 additions and 107 deletions

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -48,68 +51,73 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept {
config.texture_type != TextureType::Texture2DNoMipmap) { config.texture_type != TextureType::Texture2DNoMipmap) {
ASSERT(!config.IsPitchLinear()); ASSERT(!config.IsPitchLinear());
} }
switch (config.texture_type) { //Normalize so that the 1D that actually uses layers is treated as 1DArray
case TextureType::Texture1D: TextureType tex_type = config.texture_type;
ASSERT(config.BaseLayer() == 0); if (tex_type == TextureType::Texture1D &&
type = ImageType::e1D; (config.Depth() > 1 || config.BaseLayer() != 0)) {
size.width = config.Width(); tex_type = TextureType::Texture1DArray;
resources.layers = 1; }
break; switch (tex_type) {
case TextureType::Texture1DArray: case TextureType::Texture1D:
UNIMPLEMENTED_IF(config.BaseLayer() != 0); ASSERT(config.BaseLayer() == 0);
type = ImageType::e1D; type = ImageType::e1D;
size.width = config.Width(); size.width = config.Width();
resources.layers = config.Depth(); resources.layers = 1;
break; break;
case TextureType::Texture2D: case TextureType::Texture1DArray:
case TextureType::Texture2DNoMipmap: type = ImageType::e1D;
ASSERT(config.Depth() == 1); size.width = config.Width();
type = config.IsPitchLinear() ? ImageType::Linear : ImageType::e2D; resources.layers = config.BaseLayer() + config.Depth();
rescaleable = !config.IsPitchLinear(); break;
size.width = config.Width(); case TextureType::Texture2D:
size.height = config.Height(); case TextureType::Texture2DNoMipmap:
resources.layers = config.BaseLayer() + 1; ASSERT(config.Depth() == 1);
break; type = config.IsPitchLinear() ? ImageType::Linear : ImageType::e2D;
case TextureType::Texture2DArray: rescaleable = !config.IsPitchLinear();
type = ImageType::e2D; size.width = config.Width();
rescaleable = true; size.height = config.Height();
size.width = config.Width(); resources.layers = config.BaseLayer() + 1;
size.height = config.Height(); break;
resources.layers = config.BaseLayer() + config.Depth(); case TextureType::Texture2DArray:
break; type = ImageType::e2D;
case TextureType::TextureCubemap: rescaleable = true;
ASSERT(config.Depth() == 1); size.width = config.Width();
type = ImageType::e2D; size.height = config.Height();
size.width = config.Width(); resources.layers = config.BaseLayer() + config.Depth();
size.height = config.Height(); break;
resources.layers = config.BaseLayer() + 6; case TextureType::TextureCubemap:
break; ASSERT(config.Depth() == 1);
case TextureType::TextureCubeArray: type = ImageType::e2D;
UNIMPLEMENTED_IF(config.load_store_hint != 0); size.width = config.Width();
type = ImageType::e2D; size.height = config.Height();
size.width = config.Width(); resources.layers = config.BaseLayer() + 6;
size.height = config.Height(); break;
resources.layers = config.BaseLayer() + config.Depth() * 6; case TextureType::TextureCubeArray:
break; UNIMPLEMENTED_IF(config.load_store_hint != 0);
case TextureType::Texture3D: type = ImageType::e2D;
ASSERT(config.BaseLayer() == 0); size.width = config.Width();
type = ImageType::e3D; size.height = config.Height();
size.width = config.Width(); resources.layers = config.BaseLayer() + config.Depth() * 6;
size.height = config.Height(); break;
size.depth = config.Depth(); case TextureType::Texture3D:
resources.layers = 1; ASSERT(config.BaseLayer() == 0);
break; type = ImageType::e3D;
case TextureType::Texture1DBuffer: size.width = config.Width();
type = ImageType::Buffer; size.height = config.Height();
size.width = config.Width(); size.depth = config.Depth();
resources.layers = 1; resources.layers = 1;
break; break;
default: case TextureType::Texture1DBuffer:
ASSERT_MSG(false, "Invalid texture_type={}", static_cast<int>(config.texture_type.Value())); type = ImageType::Buffer;
break; size.width = config.Width();
resources.layers = 1;
break;
default:
ASSERT_MSG(false, "Invalid texture_type={}", static_cast<int>(config.texture_type.Value()));
break;
} }
if (num_samples > 1) { if (num_samples > 1) {
size.width *= NumSamplesX(config.msaa_mode); size.width *= NumSamplesX(config.msaa_mode);
size.height *= NumSamplesY(config.msaa_mode); size.height *= NumSamplesY(config.msaa_mode);
} }
if (type != ImageType::Linear) { if (type != ImageType::Linear) {
@ -118,7 +126,7 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept {
maybe_unaligned_layer_stride = CalculateLayerSize(*this); maybe_unaligned_layer_stride = CalculateLayerSize(*this);
rescaleable &= (block.depth == 0) && resources.levels == 1; rescaleable &= (block.depth == 0) && resources.levels == 1;
rescaleable &= size.height > RescaleHeightThreshold || rescaleable &= size.height > RescaleHeightThreshold ||
GetFormatType(format) != SurfaceType::ColorTexture; GetFormatType(format) != SurfaceType::ColorTexture;
downscaleable = size.height > DownscaleHeightThreshold; downscaleable = size.height > DownscaleHeightThreshold;
} }
} }

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -27,53 +30,64 @@ constexpr u8 RENDER_TARGET_SWIZZLE = std::numeric_limits<u8>::max();
} // Anonymous namespace } // Anonymous namespace
ImageViewInfo::ImageViewInfo(const TICEntry& config, s32 base_layer) noexcept ImageViewInfo::ImageViewInfo(const TICEntry& config, s32 base_layer) noexcept
: format{PixelFormatFromTIC(config)}, x_source{CastSwizzle(config.x_source)}, : format{PixelFormatFromTIC(config)},
y_source{CastSwizzle(config.y_source)}, z_source{CastSwizzle(config.z_source)}, x_source{CastSwizzle(config.x_source)},
w_source{CastSwizzle(config.w_source)} { y_source{CastSwizzle(config.y_source)},
range.base = SubresourceBase{ z_source{CastSwizzle(config.z_source)},
.level = static_cast<s32>(config.res_min_mip_level), w_source{CastSwizzle(config.w_source)} {
.layer = base_layer, range.base = SubresourceBase{
}; .level = static_cast<s32>(config.res_min_mip_level),
range.extent.levels = config.res_max_mip_level - config.res_min_mip_level + 1; .layer = base_layer,
};
range.extent.levels = config.res_max_mip_level - config.res_min_mip_level + 1;
TextureType tex_type = config.texture_type;
//normalize 1D texture with many layers
if (tex_type == TextureType::Texture1D &&
(config.Depth() > 1 || base_layer != 0)) {
tex_type = TextureType::Texture1DArray;
}
switch (tex_type) {
case TextureType::Texture1D:
ASSERT(config.Height() == 1);
ASSERT(config.Depth() == 1);
type = ImageViewType::e1D;
break;
case TextureType::Texture1DArray:
ASSERT(config.Height() == 1);
type = ImageViewType::e1DArray;
range.extent.layers = config.Depth();
break;
case TextureType::Texture2D:
case TextureType::Texture2DNoMipmap:
ASSERT(config.Depth() == 1);
type = config.normalized_coords ? ImageViewType::e2D : ImageViewType::Rect;
break;
case TextureType::Texture2DArray:
type = ImageViewType::e2DArray;
range.extent.layers = config.Depth();
break;
case TextureType::Texture3D:
type = ImageViewType::e3D;
break;
case TextureType::TextureCubemap:
ASSERT(config.Depth() == 1);
type = ImageViewType::Cube;
range.extent.layers = 6;
break;
switch (config.texture_type) { case TextureType::TextureCubeArray:
case TextureType::Texture1D: type = ImageViewType::CubeArray;
ASSERT(config.Height() == 1); range.extent.layers = config.Depth() * 6;
ASSERT(config.Depth() == 1); break;
type = ImageViewType::e1D;
break; case TextureType::Texture1DBuffer:
case TextureType::Texture2D: type = ImageViewType::Buffer;
case TextureType::Texture2DNoMipmap: break;
ASSERT(config.Depth() == 1);
type = config.normalized_coords ? ImageViewType::e2D : ImageViewType::Rect; default:
break; ASSERT_MSG(false, "Invalid texture_type={}", static_cast<int>(config.texture_type.Value()));
case TextureType::Texture3D: break;
type = ImageViewType::e3D; }
break;
case TextureType::TextureCubemap:
ASSERT(config.Depth() == 1);
type = ImageViewType::Cube;
range.extent.layers = 6;
break;
case TextureType::Texture1DArray:
type = ImageViewType::e1DArray;
range.extent.layers = config.Depth();
break;
case TextureType::Texture2DArray:
type = ImageViewType::e2DArray;
range.extent.layers = config.Depth();
break;
case TextureType::Texture1DBuffer:
type = ImageViewType::Buffer;
break;
case TextureType::TextureCubeArray:
type = ImageViewType::CubeArray;
range.extent.layers = config.Depth() * 6;
break;
default:
ASSERT_MSG(false, "Invalid texture_type={}", static_cast<int>(config.texture_type.Value()));
break;
}
} }
ImageViewInfo::ImageViewInfo(ImageViewType type_, PixelFormat format_, ImageViewInfo::ImageViewInfo(ImageViewType type_, PixelFormat format_,