diff --git a/Ryujinx.Graphics.Gpu/Image/TextureTarget.cs b/Ryujinx.Graphics.Gpu/Image/TextureTarget.cs
index 1db758fcd2..5e0a0721f1 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureTarget.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureTarget.cs
@@ -1,4 +1,5 @@
using Ryujinx.Graphics.GAL;
+using Ryujinx.Graphics.Shader;
namespace Ryujinx.Graphics.Gpu.Image
{
@@ -54,5 +55,27 @@ namespace Ryujinx.Graphics.Gpu.Image
return Target.Texture1D;
}
+
+ ///
+ /// Converts the texture target enum to a shader sampler type.
+ ///
+ /// The target enum to convert
+ /// The shader sampler type
+ public static SamplerType ConvertSamplerType(this TextureTarget target)
+ {
+ return target switch
+ {
+ TextureTarget.Texture1D => SamplerType.Texture1D,
+ TextureTarget.Texture2D => SamplerType.Texture2D,
+ TextureTarget.Texture3D => SamplerType.Texture3D,
+ TextureTarget.Cubemap => SamplerType.TextureCube,
+ TextureTarget.Texture1DArray => SamplerType.Texture1D | SamplerType.Array,
+ TextureTarget.Texture2DArray => SamplerType.Texture2D | SamplerType.Array,
+ TextureTarget.TextureBuffer => SamplerType.TextureBuffer,
+ TextureTarget.Texture2DRect => SamplerType.Texture2D,
+ TextureTarget.CubemapArray => SamplerType.TextureCube | SamplerType.Array,
+ _ => SamplerType.Texture2D
+ };
+ }
}
}
\ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
index 0d47955964..cda3ecb32c 100644
--- a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
@@ -40,7 +40,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
///
/// Version of the codegen (to be changed when codegen or guest format change).
///
- private const ulong ShaderCodeGenVersion = 2092;
+ private const ulong ShaderCodeGenVersion = 2613;
// Progress reporting helpers
private volatile int _shaderCount;
diff --git a/Ryujinx.Graphics.Gpu/Shader/TextureDescriptorCapableGpuAccessor.cs b/Ryujinx.Graphics.Gpu/Shader/TextureDescriptorCapableGpuAccessor.cs
index 54b4133a08..7c4eea02f8 100644
--- a/Ryujinx.Graphics.Gpu/Shader/TextureDescriptorCapableGpuAccessor.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/TextureDescriptorCapableGpuAccessor.cs
@@ -119,14 +119,14 @@ namespace Ryujinx.Graphics.Gpu.Shader
}
///
- /// Queries texture target information.
+ /// Queries sampler type information.
///
/// Texture handle
/// Constant buffer slot for the texture handle
- /// True if the texture is a buffer texture, false otherwise
- public bool QueryIsTextureBuffer(int handle, int cbufSlot = -1)
+ /// The sampler type value for the given handle
+ public SamplerType QuerySamplerType(int handle, int cbufSlot = -1)
{
- return GetTextureDescriptor(handle, cbufSlot).UnpackTextureTarget() == TextureTarget.TextureBuffer;
+ return GetTextureDescriptor(handle, cbufSlot).UnpackTextureTarget().ConvertSamplerType();
}
///
diff --git a/Ryujinx.Graphics.Shader/IGpuAccessor.cs b/Ryujinx.Graphics.Shader/IGpuAccessor.cs
index 84c30479b6..9ae399f796 100644
--- a/Ryujinx.Graphics.Shader/IGpuAccessor.cs
+++ b/Ryujinx.Graphics.Shader/IGpuAccessor.cs
@@ -1,4 +1,6 @@
-namespace Ryujinx.Graphics.Shader
+using Ryujinx.Graphics.Shader.Decoders;
+
+namespace Ryujinx.Graphics.Shader
{
public interface IGpuAccessor
{
@@ -79,9 +81,9 @@
return true;
}
- bool QueryIsTextureBuffer(int handle, int cbufSlot = -1)
+ SamplerType QuerySamplerType(int handle, int cbufSlot = -1)
{
- return false;
+ return SamplerType.Texture2D;
}
bool QueryIsTextureRectangle(int handle, int cbufSlot = -1)
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs
index ce63398f92..88bafd7656 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs
@@ -697,7 +697,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
flags = ConvertTextureFlags(tldsOp.Target) | TextureFlags.IntCoords;
- if (tldsOp.Target == TexelLoadTarget.Texture1DLodZero && context.Config.GpuAccessor.QueryIsTextureBuffer(tldsOp.HandleOffset))
+ if (tldsOp.Target == TexelLoadTarget.Texture1DLodZero && context.Config.GpuAccessor.QuerySamplerType(tldsOp.HandleOffset) == SamplerType.TextureBuffer)
{
type = SamplerType.TextureBuffer;
flags &= ~TextureFlags.LodLevel;
@@ -1306,8 +1306,6 @@ namespace Ryujinx.Graphics.Shader.Instructions
// TODO: Validate and use property.
Instruction inst = Instruction.TextureSize;
- SamplerType type = SamplerType.Texture2D;
-
TextureFlags flags = bindless ? TextureFlags.Bindless : TextureFlags.None;
int raIndex = op.Ra.Index;
@@ -1347,6 +1345,17 @@ namespace Ryujinx.Graphics.Shader.Instructions
int handle = !bindless ? op.HandleOffset : 0;
+ SamplerType type;
+
+ if (bindless)
+ {
+ type = (op.ComponentMask & 4) != 0 ? SamplerType.Texture3D : SamplerType.Texture2D;
+ }
+ else
+ {
+ type = context.Config.GpuAccessor.QuerySamplerType(handle);
+ }
+
for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
{
if ((compMask & 1) != 0)
@@ -1422,7 +1431,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
{
// For bindless, we don't have any way to know the texture type,
// so we assume it's texture buffer when the sampler type is 1D, since that's more common.
- bool isTypeBuffer = isBindless || context.Config.GpuAccessor.QueryIsTextureBuffer(op.HandleOffset);
+ bool isTypeBuffer = isBindless || context.Config.GpuAccessor.QuerySamplerType(op.HandleOffset) == SamplerType.TextureBuffer;
if (isTypeBuffer)
{
diff --git a/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureOperation.cs b/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureOperation.cs
index e80f9c113d..ea9ae39ce3 100644
--- a/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureOperation.cs
+++ b/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureOperation.cs
@@ -4,7 +4,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
{
public const int DefaultCbufSlot = -1;
- public SamplerType Type { get; private set; }
+ public SamplerType Type { get; set; }
public TextureFormat Format { get; set; }
public TextureFlags Flags { get; private set; }
diff --git a/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessElimination.cs b/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessElimination.cs
index 709668f4aa..e2f2b752a7 100644
--- a/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessElimination.cs
+++ b/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessElimination.cs
@@ -30,10 +30,11 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
texOp.Inst == Instruction.TextureSize)
{
Operand bindlessHandle = Utils.FindLastOperation(texOp.GetSource(0), block);
+ bool rewriteSamplerType = texOp.Inst == Instruction.TextureSize;
if (bindlessHandle.Type == OperandType.ConstantBuffer)
{
- SetHandle(config, texOp, bindlessHandle.GetCbufOffset(), bindlessHandle.GetCbufSlot());
+ SetHandle(config, texOp, bindlessHandle.GetCbufOffset(), bindlessHandle.GetCbufSlot(), rewriteSamplerType);
continue;
}
@@ -59,7 +60,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
config,
texOp,
src0.GetCbufOffset() | ((src1.GetCbufOffset() + 1) << 16),
- src0.GetCbufSlot() | ((src1.GetCbufSlot() + 1) << 16));
+ src0.GetCbufSlot() | ((src1.GetCbufSlot() + 1) << 16),
+ rewriteSamplerType);
}
else if (texOp.Inst == Instruction.ImageLoad ||
texOp.Inst == Instruction.ImageStore ||
@@ -81,15 +83,21 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
texOp.Format = config.GetTextureFormat(cbufOffset, cbufSlot);
}
- SetHandle(config, texOp, cbufOffset, cbufSlot);
+ SetHandle(config, texOp, cbufOffset, cbufSlot, false);
}
}
}
}
- private static void SetHandle(ShaderConfig config, TextureOperation texOp, int cbufOffset, int cbufSlot)
+ private static void SetHandle(ShaderConfig config, TextureOperation texOp, int cbufOffset, int cbufSlot, bool rewriteSamplerType)
{
texOp.SetHandle(cbufOffset, cbufSlot);
+
+ if (rewriteSamplerType)
+ {
+ texOp.Type = config.GpuAccessor.QuerySamplerType(cbufOffset, cbufSlot);
+ }
+
config.SetUsedTexture(texOp.Inst, texOp.Type, texOp.Format, texOp.Flags, cbufSlot, cbufOffset);
}
}
diff --git a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
index 7d3246db16..72fa7733fd 100644
--- a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
+++ b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
@@ -294,7 +294,7 @@ namespace Ryujinx.Graphics.Shader.Translation
inst &= Instruction.Mask;
bool isImage = inst == Instruction.ImageLoad || inst == Instruction.ImageStore || inst == Instruction.ImageAtomic;
bool isWrite = inst == Instruction.ImageStore || inst == Instruction.ImageAtomic;
- bool accurateType = inst != Instruction.TextureSize && inst != Instruction.Lod;
+ bool accurateType = inst != Instruction.Lod;
if (isImage)
{