aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2021-12-30 13:10:54 -0300
committerGitHub <noreply@github.com>2021-12-30 17:10:54 +0100
commitc05c8e09d48eb36beef02fda885ec0fd36135463 (patch)
tree7a83c260c275e9d445e0c2561c2894158b8620a5
parent1485780d90a554a9a71585ff1dd6e049b32b761e (diff)
Add support for the R4G4 texture format (#2956)
-rw-r--r--Ryujinx.Graphics.GAL/Capabilities.cs3
-rw-r--r--Ryujinx.Graphics.GAL/Format.cs1
-rw-r--r--Ryujinx.Graphics.Gpu/Image/FormatTable.cs1
-rw-r--r--Ryujinx.Graphics.Gpu/Image/Texture.cs10
-rw-r--r--Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs5
-rw-r--r--Ryujinx.Graphics.OpenGL/Renderer.cs31
-rw-r--r--Ryujinx.Graphics.Texture/PixelConverter.cs39
7 files changed, 72 insertions, 18 deletions
diff --git a/Ryujinx.Graphics.GAL/Capabilities.cs b/Ryujinx.Graphics.GAL/Capabilities.cs
index 20bd87c6..54a9ae3b 100644
--- a/Ryujinx.Graphics.GAL/Capabilities.cs
+++ b/Ryujinx.Graphics.GAL/Capabilities.cs
@@ -6,6 +6,7 @@ namespace Ryujinx.Graphics.GAL
public bool HasVectorIndexingBug { get; }
public bool SupportsAstcCompression { get; }
+ public bool SupportsR4G4Format { get; }
public bool SupportsFragmentShaderInterlock { get; }
public bool SupportsFragmentShaderOrderingIntel { get; }
public bool SupportsImageLoadFormatted { get; }
@@ -24,6 +25,7 @@ namespace Ryujinx.Graphics.GAL
bool hasFrontFacingBug,
bool hasVectorIndexingBug,
bool supportsAstcCompression,
+ bool supportsR4G4Format,
bool supportsFragmentShaderInterlock,
bool supportsFragmentShaderOrderingIntel,
bool supportsImageLoadFormatted,
@@ -40,6 +42,7 @@ namespace Ryujinx.Graphics.GAL
HasFrontFacingBug = hasFrontFacingBug;
HasVectorIndexingBug = hasVectorIndexingBug;
SupportsAstcCompression = supportsAstcCompression;
+ SupportsR4G4Format = supportsR4G4Format;
SupportsFragmentShaderInterlock = supportsFragmentShaderInterlock;
SupportsFragmentShaderOrderingIntel = supportsFragmentShaderOrderingIntel;
SupportsImageLoadFormatted = supportsImageLoadFormatted;
diff --git a/Ryujinx.Graphics.GAL/Format.cs b/Ryujinx.Graphics.GAL/Format.cs
index 98b6f506..d5e183ba 100644
--- a/Ryujinx.Graphics.GAL/Format.cs
+++ b/Ryujinx.Graphics.GAL/Format.cs
@@ -58,6 +58,7 @@ namespace Ryujinx.Graphics.GAL
D32FloatS8Uint,
R8G8B8X8Srgb,
R8G8B8A8Srgb,
+ R4G4Unorm,
R4G4B4A4Unorm,
R5G5B5X1Unorm,
R5G5B5A1Unorm,
diff --git a/Ryujinx.Graphics.Gpu/Image/FormatTable.cs b/Ryujinx.Graphics.Gpu/Image/FormatTable.cs
index 03687ade..3c97e2e2 100644
--- a/Ryujinx.Graphics.Gpu/Image/FormatTable.cs
+++ b/Ryujinx.Graphics.Gpu/Image/FormatTable.cs
@@ -58,6 +58,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{ 0x25385, new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8, 2) },
{ 0x253b0, new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8, 2) },
{ 0xa4908, new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4, 4) },
+ { 0x2491e, new FormatInfo(Format.R4G4Unorm, 1, 1, 1, 2) },
{ 0x24912, new FormatInfo(Format.R4G4B4A4Unorm, 1, 1, 2, 4) },
{ 0x24914, new FormatInfo(Format.R5G5B5A1Unorm, 1, 1, 2, 4) },
{ 0x24915, new FormatInfo(Format.R5G6B5Unorm, 1, 1, 2, 3) },
diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs
index 590356e3..6d981479 100644
--- a/Ryujinx.Graphics.Gpu/Image/Texture.cs
+++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs
@@ -785,7 +785,7 @@ namespace Ryujinx.Graphics.Gpu.Image
// Handle compressed cases not supported by the host:
// - ASTC is usually not supported on desktop cards.
// - BC4/BC5 is not supported on 3D textures.
- if (!_context.Capabilities.SupportsAstcCompression && Info.FormatInfo.Format.IsAstc())
+ if (!_context.Capabilities.SupportsAstcCompression && Format.IsAstc())
{
if (!AstcDecoder.TryDecodeToRgba8P(
data.ToArray(),
@@ -805,11 +805,15 @@ namespace Ryujinx.Graphics.Gpu.Image
data = decoded;
}
- else if (Target == Target.Texture3D && Info.FormatInfo.Format.IsBc4())
+ else if (!_context.Capabilities.SupportsR4G4Format && Format == Format.R4G4Unorm)
+ {
+ data = PixelConverter.ConvertR4G4ToR4G4B4A4(data);
+ }
+ else if (Target == Target.Texture3D && Format.IsBc4())
{
data = BCnDecoder.DecodeBC4(data, width, height, depth, levels, layers, Info.FormatInfo.Format == Format.Bc4Snorm);
}
- else if (Target == Target.Texture3D && Info.FormatInfo.Format.IsBc5())
+ else if (Target == Target.Texture3D && Format.IsBc5())
{
data = BCnDecoder.DecodeBC5(data, width, height, depth, levels, layers, Info.FormatInfo.Format == Format.Bc5Snorm);
}
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs b/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
index c70b2971..ce9fd75c 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
@@ -66,6 +66,11 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
+ if (!caps.SupportsR4G4Format && info.FormatInfo.Format == Format.R4G4Unorm)
+ {
+ return new FormatInfo(Format.R4G4B4A4Unorm, 1, 1, 2, 4);
+ }
+
if (info.Target == Target.Texture3D)
{
// The host API does not support 3D BC4/BC5 compressed formats.
diff --git a/Ryujinx.Graphics.OpenGL/Renderer.cs b/Ryujinx.Graphics.OpenGL/Renderer.cs
index 25b762b2..0c16ec5a 100644
--- a/Ryujinx.Graphics.OpenGL/Renderer.cs
+++ b/Ryujinx.Graphics.OpenGL/Renderer.cs
@@ -101,21 +101,22 @@ namespace Ryujinx.Graphics.OpenGL
public Capabilities GetCapabilities()
{
return new Capabilities(
- HwCapabilities.Vendor == HwCapabilities.GpuVendor.IntelWindows,
- HwCapabilities.Vendor == HwCapabilities.GpuVendor.AmdWindows,
- HwCapabilities.SupportsAstcCompression,
- HwCapabilities.SupportsFragmentShaderInterlock,
- HwCapabilities.SupportsFragmentShaderOrdering,
- HwCapabilities.SupportsImageLoadFormatted,
- HwCapabilities.SupportsMismatchingViewFormat,
- HwCapabilities.SupportsNonConstantTextureOffset,
- HwCapabilities.SupportsShaderBallot,
- HwCapabilities.SupportsTextureShadowLod,
- HwCapabilities.SupportsViewportSwizzle,
- HwCapabilities.SupportsIndirectParameters,
- HwCapabilities.MaximumComputeSharedMemorySize,
- HwCapabilities.MaximumSupportedAnisotropy,
- HwCapabilities.StorageBufferOffsetAlignment);
+ hasFrontFacingBug: HwCapabilities.Vendor == HwCapabilities.GpuVendor.IntelWindows,
+ hasVectorIndexingBug: HwCapabilities.Vendor == HwCapabilities.GpuVendor.AmdWindows,
+ supportsAstcCompression: HwCapabilities.SupportsAstcCompression,
+ supportsR4G4Format: false,
+ supportsFragmentShaderInterlock: HwCapabilities.SupportsFragmentShaderInterlock,
+ supportsFragmentShaderOrderingIntel: HwCapabilities.SupportsFragmentShaderOrdering,
+ supportsImageLoadFormatted: HwCapabilities.SupportsImageLoadFormatted,
+ supportsMismatchingViewFormat: HwCapabilities.SupportsMismatchingViewFormat,
+ supportsNonConstantTextureOffset: HwCapabilities.SupportsNonConstantTextureOffset,
+ supportsShaderBallot: HwCapabilities.SupportsShaderBallot,
+ supportsTextureShadowLod: HwCapabilities.SupportsTextureShadowLod,
+ supportsViewportSwizzle: HwCapabilities.SupportsViewportSwizzle,
+ supportsIndirectParameters: HwCapabilities.SupportsIndirectParameters,
+ maximumComputeSharedMemorySize: HwCapabilities.MaximumComputeSharedMemorySize,
+ maximumSupportedAnisotropy: HwCapabilities.MaximumSupportedAnisotropy,
+ storageBufferOffsetAlignment: HwCapabilities.StorageBufferOffsetAlignment);
}
public void SetBufferData(BufferHandle buffer, int offset, ReadOnlySpan<byte> data)
diff --git a/Ryujinx.Graphics.Texture/PixelConverter.cs b/Ryujinx.Graphics.Texture/PixelConverter.cs
new file mode 100644
index 00000000..d7e45a69
--- /dev/null
+++ b/Ryujinx.Graphics.Texture/PixelConverter.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace Ryujinx.Graphics.Texture
+{
+ public static class PixelConverter
+ {
+ public unsafe static byte[] ConvertR4G4ToR4G4B4A4(ReadOnlySpan<byte> data)
+ {
+ byte[] output = new byte[data.Length * 2];
+ int start = 0;
+
+ if (Sse41.IsSupported)
+ {
+ int sizeTrunc = data.Length & ~7;
+ start = sizeTrunc;
+
+ fixed (byte* inputPtr = data, outputPtr = output)
+ {
+ for (ulong offset = 0; offset < (ulong)sizeTrunc; offset += 8)
+ {
+ Sse2.Store(outputPtr + offset * 2, Sse41.ConvertToVector128Int16(inputPtr + offset).AsByte());
+ }
+ }
+ }
+
+ Span<ushort> outputSpan = MemoryMarshal.Cast<byte, ushort>(output);
+
+ for (int i = start; i < data.Length; i++)
+ {
+ outputSpan[i] = (ushort)data[i];
+ }
+
+ return output;
+ }
+ }
+}