aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu/Image
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2022-12-21 20:39:58 -0300
committerGitHub <noreply@github.com>2022-12-21 20:39:58 -0300
commitf906eb06c28880c20160cb4a969e3f6fddb3029b (patch)
tree50b716246caeda439272b3d929bbeab1bfcf87c7 /Ryujinx.Graphics.Gpu/Image
parent219f63ff4ebb739f349ca3ddd6c11e5068bcf0f1 (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.cs4
-rw-r--r--Ryujinx.Graphics.Gpu/Image/Texture.cs22
-rw-r--r--Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs32
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;
}