From e37735ed2630a807c709d2d3e2099f6c1f2b10fe Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Thu, 15 Feb 2024 19:06:26 -0300
Subject: Implement X8Z24 texture format (#6315)

---
 src/Ryujinx.Graphics.GAL/Format.cs                 |  4 ++++
 .../Engine/Types/ZetaFormat.cs                     | 28 +++++++++++-----------
 src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs      |  2 ++
 .../Image/TextureCompatibility.cs                  |  3 ++-
 src/Ryujinx.Graphics.OpenGL/FormatTable.cs         | 13 ++++++++++
 src/Ryujinx.Graphics.OpenGL/Framebuffer.cs         | 16 ++-----------
 src/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs   | 11 +++------
 src/Ryujinx.Graphics.Vulkan/EnumConversion.cs      |  4 ++--
 src/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs  |  2 +-
 src/Ryujinx.Graphics.Vulkan/FormatTable.cs         |  1 +
 src/Ryujinx.Graphics.Vulkan/TextureStorage.cs      |  3 +--
 11 files changed, 45 insertions(+), 42 deletions(-)

(limited to 'src')

diff --git a/src/Ryujinx.Graphics.GAL/Format.cs b/src/Ryujinx.Graphics.GAL/Format.cs
index 03554356..bd3b38a9 100644
--- a/src/Ryujinx.Graphics.GAL/Format.cs
+++ b/src/Ryujinx.Graphics.GAL/Format.cs
@@ -148,6 +148,7 @@ namespace Ryujinx.Graphics.GAL
         B8G8R8A8Unorm,
         B8G8R8A8Srgb,
         B10G10R10A2Unorm,
+        X8UintD24Unorm,
     }
 
     public static class FormatExtensions
@@ -269,6 +270,7 @@ namespace Ryujinx.Graphics.GAL
                 case Format.D16Unorm:
                     return 2;
                 case Format.S8UintD24Unorm:
+                case Format.X8UintD24Unorm:
                 case Format.D32Float:
                 case Format.D24UnormS8Uint:
                     return 4;
@@ -349,6 +351,7 @@ namespace Ryujinx.Graphics.GAL
                 case Format.D16Unorm:
                 case Format.D24UnormS8Uint:
                 case Format.S8UintD24Unorm:
+                case Format.X8UintD24Unorm:
                 case Format.D32Float:
                 case Format.D32FloatS8Uint:
                     return true;
@@ -633,6 +636,7 @@ namespace Ryujinx.Graphics.GAL
                 case Format.D16Unorm:
                 case Format.D24UnormS8Uint:
                 case Format.S8UintD24Unorm:
+                case Format.X8UintD24Unorm:
                 case Format.D32Float:
                 case Format.D32FloatS8Uint:
                 case Format.S8Uint:
diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Types/ZetaFormat.cs b/src/Ryujinx.Graphics.Gpu/Engine/Types/ZetaFormat.cs
index e2a044e7..88fbe88f 100644
--- a/src/Ryujinx.Graphics.Gpu/Engine/Types/ZetaFormat.cs
+++ b/src/Ryujinx.Graphics.Gpu/Engine/Types/ZetaFormat.cs
@@ -8,13 +8,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Types
     /// </summary>
     enum ZetaFormat
     {
-        D32Float = 0xa,
-        D16Unorm = 0x13,
-        D24UnormS8Uint = 0x14,
-        D24Unorm = 0x15,
-        S8UintD24Unorm = 0x16,
+        Zf32 = 0xa,
+        Z16 = 0x13,
+        Z24S8 = 0x14,
+        X8Z24 = 0x15,
+        S8Z24 = 0x16,
         S8Uint = 0x17,
-        D32FloatS8Uint = 0x19,
+        Zf32X24S8 = 0x19,
     }
 
     static class ZetaFormatConverter
@@ -29,14 +29,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.Types
             return format switch
             {
 #pragma warning disable IDE0055 // Disable formatting
-                ZetaFormat.D32Float          => new FormatInfo(Format.D32Float,       1, 1, 4, 1),
-                ZetaFormat.D16Unorm          => new FormatInfo(Format.D16Unorm,       1, 1, 2, 1),
-                ZetaFormat.D24UnormS8Uint    => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 2),
-                ZetaFormat.D24Unorm          => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 1),
-                ZetaFormat.S8UintD24Unorm    => new FormatInfo(Format.S8UintD24Unorm, 1, 1, 4, 2),
-                ZetaFormat.S8Uint            => new FormatInfo(Format.S8Uint,         1, 1, 1, 1),
-                ZetaFormat.D32FloatS8Uint    => new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8, 2),
-                _                            => FormatInfo.Default,
+                ZetaFormat.Zf32      => new FormatInfo(Format.D32Float,       1, 1, 4, 1),
+                ZetaFormat.Z16       => new FormatInfo(Format.D16Unorm,       1, 1, 2, 1),
+                ZetaFormat.Z24S8     => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 2),
+                ZetaFormat.X8Z24     => new FormatInfo(Format.X8UintD24Unorm, 1, 1, 4, 1),
+                ZetaFormat.S8Z24     => new FormatInfo(Format.S8UintD24Unorm, 1, 1, 4, 2),
+                ZetaFormat.S8Uint    => new FormatInfo(Format.S8Uint,         1, 1, 1, 1),
+                ZetaFormat.Zf32X24S8 => new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8, 2),
+                _                    => FormatInfo.Default,
 #pragma warning restore IDE0055
             };
         }
diff --git a/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs b/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs
index 0af0725a..e30b29ef 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs
@@ -185,6 +185,7 @@ namespace Ryujinx.Graphics.Gpu.Image
             G24R8RUintGUnormBUnormAUnorm     = G24R8             | RUint  | GUnorm | BUnorm | AUnorm,        // 0x24a0e
             Z24S8RUintGUnormBUnormAUnorm     = Z24S8             | RUint  | GUnorm | BUnorm | AUnorm,        // 0x24a29
             Z24S8RUintGUnormBUintAUint       = Z24S8             | RUint  | GUnorm | BUint  | AUint,         // 0x48a29
+            X8Z24RUnormGUintBUintAUint       = X8Z24             | RUnorm | GUint  | BUint  | AUint,         // 0x4912a
             S8Z24RUnormGUintBUintAUint       = S8Z24             | RUnorm | GUint  | BUint  | AUint,         // 0x4912b
             R32B24G8RFloatGUintBUnormAUnorm  = R32B24G8          | RFloat | GUint  | BUnorm | AUnorm,        // 0x25385
             Zf32X24S8RFloatGUintBUnormAUnorm = Zf32X24S8         | RFloat | GUint  | BUnorm | AUnorm,        // 0x253b0
@@ -410,6 +411,7 @@ namespace Ryujinx.Graphics.Gpu.Image
             { TextureFormat.G24R8RUintGUnormBUnormAUnorm,     new FormatInfo(Format.D24UnormS8Uint,    1,  1,  4,  2) },
             { TextureFormat.Z24S8RUintGUnormBUnormAUnorm,     new FormatInfo(Format.D24UnormS8Uint,    1,  1,  4,  2) },
             { TextureFormat.Z24S8RUintGUnormBUintAUint,       new FormatInfo(Format.D24UnormS8Uint,    1,  1,  4,  2) },
+            { TextureFormat.X8Z24RUnormGUintBUintAUint,       new FormatInfo(Format.X8UintD24Unorm,    1,  1,  4,  2) },
             { TextureFormat.S8Z24RUnormGUintBUintAUint,       new FormatInfo(Format.S8UintD24Unorm,    1,  1,  4,  2) },
             { TextureFormat.R32B24G8RFloatGUintBUnormAUnorm,  new FormatInfo(Format.D32FloatS8Uint,    1,  1,  8,  2) },
             { TextureFormat.Zf32X24S8RFloatGUintBUnormAUnorm, new FormatInfo(Format.D32FloatS8Uint,    1,  1,  8,  2) },
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
index eef38948..5b930fa4 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
@@ -242,7 +242,8 @@ namespace Ryujinx.Graphics.Gpu.Image
                     return TextureMatchQuality.FormatAlias;
                 }
                 else if ((lhs.FormatInfo.Format == Format.D24UnormS8Uint ||
-                          lhs.FormatInfo.Format == Format.S8UintD24Unorm) && rhs.FormatInfo.Format == Format.B8G8R8A8Unorm)
+                          lhs.FormatInfo.Format == Format.S8UintD24Unorm ||
+                          lhs.FormatInfo.Format == Format.X8UintD24Unorm) && rhs.FormatInfo.Format == Format.B8G8R8A8Unorm)
                 {
                     return TextureMatchQuality.FormatAlias;
                 }
diff --git a/src/Ryujinx.Graphics.OpenGL/FormatTable.cs b/src/Ryujinx.Graphics.OpenGL/FormatTable.cs
index c7e3e4e2..4cf4dc76 100644
--- a/src/Ryujinx.Graphics.OpenGL/FormatTable.cs
+++ b/src/Ryujinx.Graphics.OpenGL/FormatTable.cs
@@ -68,6 +68,7 @@ namespace Ryujinx.Graphics.OpenGL
             Add(Format.S8Uint,              new FormatInfo(1, false, false, All.StencilIndex8,     PixelFormat.StencilIndex,   PixelType.UnsignedByte));
             Add(Format.D16Unorm,            new FormatInfo(1, false, false, All.DepthComponent16,  PixelFormat.DepthComponent, PixelType.UnsignedShort));
             Add(Format.S8UintD24Unorm,      new FormatInfo(1, false, false, All.Depth24Stencil8,   PixelFormat.DepthStencil,   PixelType.UnsignedInt248));
+            Add(Format.X8UintD24Unorm,      new FormatInfo(1, false, false, All.DepthComponent24,  PixelFormat.DepthComponent, PixelType.UnsignedInt));
             Add(Format.D32Float,            new FormatInfo(1, false, false, All.DepthComponent32f, PixelFormat.DepthComponent, PixelType.Float));
             Add(Format.D24UnormS8Uint,      new FormatInfo(1, false, false, All.Depth24Stencil8,   PixelFormat.DepthStencil,   PixelType.UnsignedInt248));
             Add(Format.D32FloatS8Uint,      new FormatInfo(1, false, false, All.Depth32fStencil8,  PixelFormat.DepthStencil,   PixelType.Float32UnsignedInt248Rev));
@@ -224,5 +225,17 @@ namespace Ryujinx.Graphics.OpenGL
         {
             return _tableImage[(int)format];
         }
+
+        public static bool IsPackedDepthStencil(Format format)
+        {
+            return format == Format.D24UnormS8Uint ||
+                   format == Format.D32FloatS8Uint ||
+                   format == Format.S8UintD24Unorm;
+        }
+
+        public static bool IsDepthOnly(Format format)
+        {
+            return format == Format.D16Unorm || format == Format.D32Float || format == Format.X8UintD24Unorm;
+        }
     }
 }
diff --git a/src/Ryujinx.Graphics.OpenGL/Framebuffer.cs b/src/Ryujinx.Graphics.OpenGL/Framebuffer.cs
index 3b79c5d6..394b8bc7 100644
--- a/src/Ryujinx.Graphics.OpenGL/Framebuffer.cs
+++ b/src/Ryujinx.Graphics.OpenGL/Framebuffer.cs
@@ -119,11 +119,11 @@ namespace Ryujinx.Graphics.OpenGL
 
         private static FramebufferAttachment GetAttachment(Format format)
         {
-            if (IsPackedDepthStencilFormat(format))
+            if (FormatTable.IsPackedDepthStencil(format))
             {
                 return FramebufferAttachment.DepthStencilAttachment;
             }
-            else if (IsDepthOnlyFormat(format))
+            else if (FormatTable.IsDepthOnly(format))
             {
                 return FramebufferAttachment.DepthAttachment;
             }
@@ -133,18 +133,6 @@ namespace Ryujinx.Graphics.OpenGL
             }
         }
 
-        private static bool IsPackedDepthStencilFormat(Format format)
-        {
-            return format == Format.D24UnormS8Uint ||
-                   format == Format.D32FloatS8Uint ||
-                   format == Format.S8UintD24Unorm;
-        }
-
-        private static bool IsDepthOnlyFormat(Format format)
-        {
-            return format == Format.D16Unorm || format == Format.D32Float;
-        }
-
         public int GetColorLayerCount(int index)
         {
             return _colors[index]?.Info.GetDepthOrLayers() ?? 0;
diff --git a/src/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs b/src/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs
index 128f481f..89bd5e4f 100644
--- a/src/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs
+++ b/src/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs
@@ -294,7 +294,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
             {
                 return FramebufferAttachment.DepthStencilAttachment;
             }
-            else if (IsDepthOnly(format))
+            else if (FormatTable.IsDepthOnly(format))
             {
                 return FramebufferAttachment.DepthAttachment;
             }
@@ -324,11 +324,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
 
         private static ClearBufferMask GetMask(Format format)
         {
-            if (format == Format.D24UnormS8Uint || format == Format.D32FloatS8Uint || format == Format.S8UintD24Unorm)
+            if (FormatTable.IsPackedDepthStencil(format))
             {
                 return ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit;
             }
-            else if (IsDepthOnly(format))
+            else if (FormatTable.IsDepthOnly(format))
             {
                 return ClearBufferMask.DepthBufferBit;
             }
@@ -342,11 +342,6 @@ namespace Ryujinx.Graphics.OpenGL.Image
             }
         }
 
-        private static bool IsDepthOnly(Format format)
-        {
-            return format == Format.D16Unorm || format == Format.D32Float;
-        }
-
         public TextureView BgraSwap(TextureView from)
         {
             TextureView to = (TextureView)_renderer.CreateTexture(from.Info);
diff --git a/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs b/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs
index e1002705..f9243bf8 100644
--- a/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs
+++ b/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs
@@ -376,7 +376,7 @@ namespace Ryujinx.Graphics.Vulkan
         {
             return format switch
             {
-                Format.D16Unorm or Format.D32Float => ImageAspectFlags.DepthBit,
+                Format.D16Unorm or Format.D32Float or Format.X8UintD24Unorm => ImageAspectFlags.DepthBit,
                 Format.S8Uint => ImageAspectFlags.StencilBit,
                 Format.D24UnormS8Uint or
                 Format.D32FloatS8Uint or
@@ -389,7 +389,7 @@ namespace Ryujinx.Graphics.Vulkan
         {
             return format switch
             {
-                Format.D16Unorm or Format.D32Float => ImageAspectFlags.DepthBit,
+                Format.D16Unorm or Format.D32Float or Format.X8UintD24Unorm => ImageAspectFlags.DepthBit,
                 Format.S8Uint => ImageAspectFlags.StencilBit,
                 Format.D24UnormS8Uint or
                 Format.D32FloatS8Uint or
diff --git a/src/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs b/src/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs
index 7307a0ee..9ea8cec4 100644
--- a/src/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs
+++ b/src/Ryujinx.Graphics.Vulkan/FormatCapabilities.cs
@@ -220,7 +220,7 @@ namespace Ryujinx.Graphics.Vulkan
 
         public static bool IsD24S8(Format format)
         {
-            return format == Format.D24UnormS8Uint || format == Format.S8UintD24Unorm;
+            return format == Format.D24UnormS8Uint || format == Format.S8UintD24Unorm || format == Format.X8UintD24Unorm;
         }
 
         private static bool IsRGB16IntFloat(Format format)
diff --git a/src/Ryujinx.Graphics.Vulkan/FormatTable.cs b/src/Ryujinx.Graphics.Vulkan/FormatTable.cs
index 596a665f..98796d9b 100644
--- a/src/Ryujinx.Graphics.Vulkan/FormatTable.cs
+++ b/src/Ryujinx.Graphics.Vulkan/FormatTable.cs
@@ -67,6 +67,7 @@ namespace Ryujinx.Graphics.Vulkan
             Add(Format.S8Uint,              VkFormat.S8Uint);
             Add(Format.D16Unorm,            VkFormat.D16Unorm);
             Add(Format.S8UintD24Unorm,      VkFormat.D24UnormS8Uint);
+            Add(Format.X8UintD24Unorm,      VkFormat.X8D24UnormPack32);
             Add(Format.D32Float,            VkFormat.D32Sfloat);
             Add(Format.D24UnormS8Uint,      VkFormat.D24UnormS8Uint);
             Add(Format.D32FloatS8Uint,      VkFormat.D32SfloatS8Uint);
diff --git a/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs b/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs
index b763fa98..bba65921 100644
--- a/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs
+++ b/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs
@@ -154,9 +154,8 @@ namespace Ryujinx.Graphics.Vulkan
             {
                 Format.S8Uint => Format.R8Unorm,
                 Format.D16Unorm => Format.R16Unorm,
-                Format.S8UintD24Unorm => Format.R8G8B8A8Unorm,
+                Format.D24UnormS8Uint or Format.S8UintD24Unorm or Format.X8UintD24Unorm => Format.R8G8B8A8Unorm,
                 Format.D32Float => Format.R32Float,
-                Format.D24UnormS8Uint => Format.R8G8B8A8Unorm,
                 Format.D32FloatS8Uint => Format.R32G32Float,
                 _ => throw new ArgumentException($"\"{format}\" is not a supported depth or stencil format."),
             };
-- 
cgit v1.2.3-70-g09d2