Kaynağa Gözat

Pass CbufSlot when getting info from the texture descriptor (#2291)

* Pass CbufSlot when getting info from the texture descriptor

Fixes some issues with bindless textures, when CbufSlot is not equal to the current TextureBufferIndex.

Specifically fixes a random chance of full screen colour flickering in Super Mario Party.

* Apply suggestions from code review

Oops

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
riperiperi 4 yıl önce
ebeveyn
işleme
0129250c2e

+ 3 - 2
Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs

@@ -398,10 +398,11 @@ namespace Ryujinx.Graphics.Gpu.Image
         /// <param name="state">The current GPU state</param>
         /// <param name="state">The current GPU state</param>
         /// <param name="stageIndex">The stage number where the texture is bound</param>
         /// <param name="stageIndex">The stage number where the texture is bound</param>
         /// <param name="handle">The texture handle</param>
         /// <param name="handle">The texture handle</param>
+        /// <param name="cbufSlot">The texture handle's constant buffer slot</param>
         /// <returns>The texture descriptor for the specified texture</returns>
         /// <returns>The texture descriptor for the specified texture</returns>
-        public TextureDescriptor GetTextureDescriptor(GpuState state, int stageIndex, int handle)
+        public TextureDescriptor GetTextureDescriptor(GpuState state, int stageIndex, int handle, int cbufSlot)
         {
         {
-            int packedId = ReadPackedId(stageIndex, handle, state.Get<int>(MethodOffset.TextureBufferIndex));
+            int packedId = ReadPackedId(stageIndex, handle, cbufSlot < 0 ? state.Get<int>(MethodOffset.TextureBufferIndex) : cbufSlot);
             int textureId = UnpackTextureId(packedId);
             int textureId = UnpackTextureId(packedId);
 
 
             var poolState = state.Get<PoolState>(MethodOffset.TexturePoolState);
             var poolState = state.Get<PoolState>(MethodOffset.TexturePoolState);

+ 7 - 5
Ryujinx.Graphics.Gpu/Image/TextureManager.cs

@@ -340,10 +340,11 @@ namespace Ryujinx.Graphics.Gpu.Image
         /// </summary>
         /// </summary>
         /// <param name="state">Current GPU state</param>
         /// <param name="state">Current GPU state</param>
         /// <param name="handle">Shader "fake" handle of the texture</param>
         /// <param name="handle">Shader "fake" handle of the texture</param>
+        /// <param name="cbufSlot">Shader constant buffer slot of the texture</param>
         /// <returns>The texture descriptor</returns>
         /// <returns>The texture descriptor</returns>
-        public TextureDescriptor GetComputeTextureDescriptor(GpuState state, int handle)
+        public TextureDescriptor GetComputeTextureDescriptor(GpuState state, int handle, int cbufSlot)
         {
         {
-            return _cpBindingsManager.GetTextureDescriptor(state, 0, handle);
+            return _cpBindingsManager.GetTextureDescriptor(state, 0, handle, cbufSlot);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -352,10 +353,11 @@ namespace Ryujinx.Graphics.Gpu.Image
         /// <param name="state">Current GPU state</param>
         /// <param name="state">Current GPU state</param>
         /// <param name="stageIndex">Index of the shader stage where the texture is bound</param>
         /// <param name="stageIndex">Index of the shader stage where the texture is bound</param>
         /// <param name="handle">Shader "fake" handle of the texture</param>
         /// <param name="handle">Shader "fake" handle of the texture</param>
+        /// <param name="cbufSlot">Shader constant buffer slot of the texture</param>
         /// <returns>The texture descriptor</returns>
         /// <returns>The texture descriptor</returns>
-        public TextureDescriptor GetGraphicsTextureDescriptor(GpuState state, int stageIndex, int handle)
+        public TextureDescriptor GetGraphicsTextureDescriptor(GpuState state, int stageIndex, int handle, int cbufSlot)
         {
         {
-            return _gpBindingsManager.GetTextureDescriptor(state, stageIndex, handle);
+            return _gpBindingsManager.GetTextureDescriptor(state, stageIndex, handle, cbufSlot);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1297,4 +1299,4 @@ namespace Ryujinx.Graphics.Gpu.Image
             }
             }
         }
         }
     }
     }
-}
+}

+ 1 - 1
Ryujinx.Graphics.Gpu/Shader/Cache/CacheHelper.cs

@@ -417,7 +417,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache
                 {
                 {
                     foreach (int textureHandle in context.TextureHandlesForCache)
                     foreach (int textureHandle in context.TextureHandlesForCache)
                     {
                     {
-                        GuestTextureDescriptor textureDescriptor = ((Image.TextureDescriptor)gpuAccessor.GetTextureDescriptor(textureHandle)).ToCache();
+                        GuestTextureDescriptor textureDescriptor = ((Image.TextureDescriptor)gpuAccessor.GetTextureDescriptor(textureHandle, -1)).ToCache();
 
 
                         textureDescriptor.Handle = (uint)textureHandle;
                         textureDescriptor.Handle = (uint)textureHandle;
 
 

+ 2 - 1
Ryujinx.Graphics.Gpu/Shader/CachedGpuAccessor.cs

@@ -140,8 +140,9 @@ namespace Ryujinx.Graphics.Gpu.Shader
         /// Gets the texture descriptor for a given texture on the pool.
         /// Gets the texture descriptor for a given texture on the pool.
         /// </summary>
         /// </summary>
         /// <param name="handle">Index of the texture (this is the word offset of the handle in the constant buffer)</param>
         /// <param name="handle">Index of the texture (this is the word offset of the handle in the constant buffer)</param>
+        /// <param name="cbufSlot">Constant buffer slot for the texture handle</param>
         /// <returns>Texture descriptor</returns>
         /// <returns>Texture descriptor</returns>
-        public override Image.ITextureDescriptor GetTextureDescriptor(int handle)
+        public override Image.ITextureDescriptor GetTextureDescriptor(int handle, int cbufSlot)
         {
         {
             if (!_textureDescriptors.TryGetValue(handle, out GuestTextureDescriptor textureDescriptor))
             if (!_textureDescriptors.TryGetValue(handle, out GuestTextureDescriptor textureDescriptor))
             {
             {

+ 4 - 3
Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs

@@ -184,16 +184,17 @@ namespace Ryujinx.Graphics.Gpu.Shader
         /// Gets the texture descriptor for a given texture on the pool.
         /// Gets the texture descriptor for a given texture on the pool.
         /// </summary>
         /// </summary>
         /// <param name="handle">Index of the texture (this is the word offset of the handle in the constant buffer)</param>
         /// <param name="handle">Index of the texture (this is the word offset of the handle in the constant buffer)</param>
+        /// <param name="cbufSlot">Constant buffer slot for the texture handle</param>
         /// <returns>Texture descriptor</returns>
         /// <returns>Texture descriptor</returns>
-        public override Image.ITextureDescriptor GetTextureDescriptor(int handle)
+        public override Image.ITextureDescriptor GetTextureDescriptor(int handle, int cbufSlot)
         {
         {
             if (_compute)
             if (_compute)
             {
             {
-                return _context.Methods.TextureManager.GetComputeTextureDescriptor(_state, handle);
+                return _context.Methods.TextureManager.GetComputeTextureDescriptor(_state, handle, cbufSlot);
             }
             }
             else
             else
             {
             {
-                return _context.Methods.TextureManager.GetGraphicsTextureDescriptor(_state, _stageIndex, handle);
+                return _context.Methods.TextureManager.GetGraphicsTextureDescriptor(_state, _stageIndex, handle, cbufSlot);
             }
             }
         }
         }
 
 

+ 10 - 7
Ryujinx.Graphics.Gpu/Shader/TextureDescriptorCapableGpuAccessor.cs

@@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
     {
     {
         public abstract T MemoryRead<T>(ulong address) where T : unmanaged;
         public abstract T MemoryRead<T>(ulong address) where T : unmanaged;
 
 
-        public abstract ITextureDescriptor GetTextureDescriptor(int handle);
+        public abstract ITextureDescriptor GetTextureDescriptor(int handle, int cbufSlot);
 
 
         /// <summary>
         /// <summary>
         /// Queries texture format information, for shaders using image load or store.
         /// Queries texture format information, for shaders using image load or store.
@@ -18,10 +18,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
         /// If the format of the texture is a compressed, depth or unsupported format, then a default value is returned.
         /// If the format of the texture is a compressed, depth or unsupported format, then a default value is returned.
         /// </remarks>
         /// </remarks>
         /// <param name="handle">Texture handle</param>
         /// <param name="handle">Texture handle</param>
+        /// <param name="cbufSlot">Constant buffer slot for the texture handle</param>
         /// <returns>Color format of the non-compressed texture</returns>
         /// <returns>Color format of the non-compressed texture</returns>
-        public TextureFormat QueryTextureFormat(int handle)
+        public TextureFormat QueryTextureFormat(int handle, int cbufSlot = -1)
         {
         {
-            var descriptor = GetTextureDescriptor(handle);
+            var descriptor = GetTextureDescriptor(handle, cbufSlot);
 
 
             if (!FormatTable.TryGetTextureFormat(descriptor.UnpackFormat(), descriptor.UnpackSrgb(), out FormatInfo formatInfo))
             if (!FormatTable.TryGetTextureFormat(descriptor.UnpackFormat(), descriptor.UnpackSrgb(), out FormatInfo formatInfo))
             {
             {
@@ -78,20 +79,22 @@ namespace Ryujinx.Graphics.Gpu.Shader
         /// Queries texture target information.
         /// Queries texture target information.
         /// </summary>
         /// </summary>
         /// <param name="handle">Texture handle</param>
         /// <param name="handle">Texture handle</param>
+        /// <param name="cbufSlot">Constant buffer slot for the texture handle</param>
         /// <returns>True if the texture is a buffer texture, false otherwise</returns>
         /// <returns>True if the texture is a buffer texture, false otherwise</returns>
-        public bool QueryIsTextureBuffer(int handle)
+        public bool QueryIsTextureBuffer(int handle, int cbufSlot = -1)
         {
         {
-            return GetTextureDescriptor(handle).UnpackTextureTarget() == TextureTarget.TextureBuffer;
+            return GetTextureDescriptor(handle, cbufSlot).UnpackTextureTarget() == TextureTarget.TextureBuffer;
         }
         }
 
 
         /// <summary>
         /// <summary>
         /// Queries texture target information.
         /// Queries texture target information.
         /// </summary>
         /// </summary>
         /// <param name="handle">Texture handle</param>
         /// <param name="handle">Texture handle</param>
+        /// <param name="cbufSlot">Constant buffer slot for the texture handle</param>
         /// <returns>True if the texture is a rectangle texture, false otherwise</returns>
         /// <returns>True if the texture is a rectangle texture, false otherwise</returns>
-        public bool QueryIsTextureRectangle(int handle)
+        public bool QueryIsTextureRectangle(int handle, int cbufSlot = -1)
         {
         {
-            var descriptor = GetTextureDescriptor(handle);
+            var descriptor = GetTextureDescriptor(handle, cbufSlot);
 
 
             TextureTarget target = descriptor.UnpackTextureTarget();
             TextureTarget target = descriptor.UnpackTextureTarget();
 
 

+ 3 - 3
Ryujinx.Graphics.Shader/IGpuAccessor.cs

@@ -44,12 +44,12 @@
             return 0xffff;
             return 0xffff;
         }
         }
 
 
-        bool QueryIsTextureBuffer(int handle)
+        bool QueryIsTextureBuffer(int handle, int cbufSlot = -1)
         {
         {
             return false;
             return false;
         }
         }
 
 
-        bool QueryIsTextureRectangle(int handle)
+        bool QueryIsTextureRectangle(int handle, int cbufSlot = -1)
         {
         {
             return false;
             return false;
         }
         }
@@ -74,7 +74,7 @@
             return true;
             return true;
         }
         }
 
 
-        TextureFormat QueryTextureFormat(int handle)
+        TextureFormat QueryTextureFormat(int handle, int cbufSlot = -1)
         {
         {
             return TextureFormat.R8G8B8A8Unorm;
             return TextureFormat.R8G8B8A8Unorm;
         }
         }

+ 1 - 1
Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessElimination.cs

@@ -65,7 +65,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
                     if (src0.Type == OperandType.ConstantBuffer)
                     if (src0.Type == OperandType.ConstantBuffer)
                     {
                     {
                         texOp.SetHandle(src0.GetCbufOffset(), src0.GetCbufSlot());
                         texOp.SetHandle(src0.GetCbufOffset(), src0.GetCbufSlot());
-                        texOp.Format = config.GetTextureFormat(texOp.Handle);
+                        texOp.Format = config.GetTextureFormat(texOp.Handle, texOp.CbufSlot);
                     }
                     }
                 }
                 }
             }
             }

+ 2 - 2
Ryujinx.Graphics.Shader/Translation/Rewriter.cs

@@ -142,7 +142,7 @@ namespace Ryujinx.Graphics.Shader.Translation
 
 
             bool hasInvalidOffset = (hasOffset || hasOffsets) && !config.GpuAccessor.QuerySupportsNonConstantTextureOffset();
             bool hasInvalidOffset = (hasOffset || hasOffsets) && !config.GpuAccessor.QuerySupportsNonConstantTextureOffset();
 
 
-            bool isRect = config.GpuAccessor.QueryIsTextureRectangle(texOp.Handle);
+            bool isRect = config.GpuAccessor.QueryIsTextureRectangle(texOp.Handle, texOp.CbufSlot);
 
 
             if (!(hasInvalidOffset || isRect))
             if (!(hasInvalidOffset || isRect))
             {
             {
@@ -433,7 +433,7 @@ namespace Ryujinx.Graphics.Shader.Translation
         {
         {
             TextureOperation texOp = (TextureOperation)node.Value;
             TextureOperation texOp = (TextureOperation)node.Value;
 
 
-            TextureFormat format = config.GpuAccessor.QueryTextureFormat(texOp.Handle);
+            TextureFormat format = config.GpuAccessor.QueryTextureFormat(texOp.Handle, texOp.CbufSlot);
 
 
             int maxPositive = format switch
             int maxPositive = format switch
             {
             {

+ 2 - 2
Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs

@@ -91,7 +91,7 @@ namespace Ryujinx.Graphics.Shader.Translation
             return count + 1;
             return count + 1;
         }
         }
 
 
-        public TextureFormat GetTextureFormat(int handle)
+        public TextureFormat GetTextureFormat(int handle, int cbufSlot = -1)
         {
         {
             // When the formatted load extension is supported, we don't need to
             // When the formatted load extension is supported, we don't need to
             // specify a format, we can just declare it without a format and the GPU will handle it.
             // specify a format, we can just declare it without a format and the GPU will handle it.
@@ -100,7 +100,7 @@ namespace Ryujinx.Graphics.Shader.Translation
                 return TextureFormat.Unknown;
                 return TextureFormat.Unknown;
             }
             }
 
 
-            var format = GpuAccessor.QueryTextureFormat(handle);
+            var format = GpuAccessor.QueryTextureFormat(handle, cbufSlot);
 
 
             if (format == TextureFormat.Unknown)
             if (format == TextureFormat.Unknown)
             {
             {