diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2022-12-21 20:39:58 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-12-21 20:39:58 -0300 |
| commit | f906eb06c28880c20160cb4a969e3f6fddb3029b (patch) | |
| tree | 50b716246caeda439272b3d929bbeab1bfcf87c7 /Ryujinx.Graphics.Gpu/Image | |
| parent | 219f63ff4ebb739f349ca3ddd6c11e5068bcf0f1 (diff) | |
Implement a software ETC2 texture decoder (#4121)
* Implement a software ETC2 texture decoder
* Fix output size calculation for non-2D textures
* Address PR feedback
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Image')
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/FormatTable.cs | 4 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/Texture.cs | 22 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs | 32 |
3 files changed, 48 insertions, 10 deletions
diff --git a/Ryujinx.Graphics.Gpu/Image/FormatTable.cs b/Ryujinx.Graphics.Gpu/Image/FormatTable.cs index c76e1fca..72901610 100644 --- a/Ryujinx.Graphics.Gpu/Image/FormatTable.cs +++ b/Ryujinx.Graphics.Gpu/Image/FormatTable.cs @@ -208,8 +208,10 @@ namespace Ryujinx.Graphics.Gpu.Image Bc6HSf16Float = Bc6HSf16 | RFloat | GFloat | BFloat | AFloat, // 0x7ff90 Bc6HUf16Float = Bc6HUf16 | RFloat | GFloat | BFloat | AFloat, // 0x7ff91 Etc2RgbUnorm = Etc2Rgb | RUnorm | GUnorm | BUnorm | AUnorm, // 0x24906 + Etc2RgbPtaUnorm = Etc2RgbPta | RUnorm | GUnorm | BUnorm | AUnorm, // 0x2490a Etc2RgbaUnorm = Etc2Rgba | RUnorm | GUnorm | BUnorm | AUnorm, // 0x2490b Etc2RgbUnormSrgb = Etc2Rgb | RUnorm | GUnorm | BUnorm | AUnorm | Srgb, // 0xa4906 + Etc2RgbPtaUnormSrgb = Etc2RgbPta | RUnorm | GUnorm | BUnorm | AUnorm | Srgb, // 0xa490a Etc2RgbaUnormSrgb = Etc2Rgba | RUnorm | GUnorm | BUnorm | AUnorm | Srgb, // 0xa490b Astc2D4x4Unorm = Astc2D4x4 | RUnorm | GUnorm | BUnorm | AUnorm, // 0x24940 Astc2D5x4Unorm = Astc2D5x4 | RUnorm | GUnorm | BUnorm | AUnorm, // 0x24950 @@ -429,8 +431,10 @@ namespace Ryujinx.Graphics.Gpu.Image { TextureFormat.Bc6HSf16Float, new FormatInfo(Format.Bc6HSfloat, 4, 4, 16, 4) }, { TextureFormat.Bc6HUf16Float, new FormatInfo(Format.Bc6HUfloat, 4, 4, 16, 4) }, { TextureFormat.Etc2RgbUnorm, new FormatInfo(Format.Etc2RgbUnorm, 4, 4, 8, 3) }, + { TextureFormat.Etc2RgbPtaUnorm, new FormatInfo(Format.Etc2RgbPtaUnorm, 4, 4, 8, 4) }, { TextureFormat.Etc2RgbaUnorm, new FormatInfo(Format.Etc2RgbaUnorm, 4, 4, 16, 4) }, { TextureFormat.Etc2RgbUnormSrgb, new FormatInfo(Format.Etc2RgbSrgb, 4, 4, 8, 3) }, + { TextureFormat.Etc2RgbPtaUnormSrgb, new FormatInfo(Format.Etc2RgbPtaSrgb, 4, 4, 8, 4) }, { TextureFormat.Etc2RgbaUnormSrgb, new FormatInfo(Format.Etc2RgbaSrgb, 4, 4, 16, 4) }, { TextureFormat.Astc2D4x4Unorm, new FormatInfo(Format.Astc4x4Unorm, 4, 4, 16, 4) }, { TextureFormat.Astc2D5x4Unorm, new FormatInfo(Format.Astc5x4Unorm, 5, 4, 16, 4) }, diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs index 4203cb00..904c908f 100644 --- a/Ryujinx.Graphics.Gpu/Image/Texture.cs +++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs @@ -857,9 +857,23 @@ namespace Ryujinx.Graphics.Gpu.Image result = decoded; } - else if (!_context.Capabilities.SupportsR4G4Format && Format == Format.R4G4Unorm) + else if (!_context.Capabilities.SupportsEtc2Compression && Format.IsEtc2()) { - result = PixelConverter.ConvertR4G4ToR4G4B4A4(result); + switch (Format) + { + case Format.Etc2RgbaSrgb: + case Format.Etc2RgbaUnorm: + result = ETC2Decoder.DecodeRgba(result, width, height, depth, levels, layers); + break; + case Format.Etc2RgbPtaSrgb: + case Format.Etc2RgbPtaUnorm: + result = ETC2Decoder.DecodePta(result, width, height, depth, levels, layers); + break; + case Format.Etc2RgbSrgb: + case Format.Etc2RgbUnorm: + result = ETC2Decoder.DecodeRgb(result, width, height, depth, levels, layers); + break; + } } else if (!TextureCompatibility.HostSupportsBcFormat(Format, Target, _context.Capabilities)) { @@ -895,6 +909,10 @@ namespace Ryujinx.Graphics.Gpu.Image break; } } + else if (!_context.Capabilities.SupportsR4G4Format && Format == Format.R4G4Unorm) + { + result = PixelConverter.ConvertR4G4ToR4G4B4A4(result); + } return result; } diff --git a/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs b/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs index 91a1a728..642e03b6 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs +++ b/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs @@ -67,6 +67,10 @@ namespace Ryujinx.Graphics.Gpu.Image /// <returns>A host compatible format</returns> public static FormatInfo ToHostCompatibleFormat(TextureInfo info, Capabilities caps) { + // The host API does not support those compressed formats. + // We assume software decompression will be done for those textures, + // and so we adjust the format here to match the decompressor output. + if (!caps.SupportsAstcCompression) { if (info.FormatInfo.Format.IsAstcUnorm()) @@ -83,16 +87,8 @@ namespace Ryujinx.Graphics.Gpu.Image } } - if (!caps.SupportsR4G4Format && info.FormatInfo.Format == Format.R4G4Unorm) - { - return new FormatInfo(Format.R4G4B4A4Unorm, 1, 1, 2, 4); - } - if (!HostSupportsBcFormat(info.FormatInfo.Format, info.Target, caps)) { - // The host API does not this compressed format. - // We assume software decompression will be done for those textures, - // and so we adjust the format here to match the decompressor output. switch (info.FormatInfo.Format) { case Format.Bc1RgbaSrgb: @@ -119,6 +115,26 @@ namespace Ryujinx.Graphics.Gpu.Image } } + if (!caps.SupportsEtc2Compression) + { + switch (info.FormatInfo.Format) + { + case Format.Etc2RgbaSrgb: + case Format.Etc2RgbPtaSrgb: + case Format.Etc2RgbSrgb: + return new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4, 4); + case Format.Etc2RgbaUnorm: + case Format.Etc2RgbPtaUnorm: + case Format.Etc2RgbUnorm: + return new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4, 4); + } + } + + if (!caps.SupportsR4G4Format && info.FormatInfo.Format == Format.R4G4Unorm) + { + return new FormatInfo(Format.R4G4B4A4Unorm, 1, 1, 2, 4); + } + return info.FormatInfo; } |
