aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Shader/Translation
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2022-12-29 12:09:34 -0300
committerGitHub <noreply@github.com>2022-12-29 16:09:34 +0100
commit9dfe81770a8337a7a469eb3bac0ae9599cc0f61c (patch)
treee0c470a0ae67984394037f72fb7e16250674ba7e /Ryujinx.Graphics.Shader/Translation
parent52c115a1f8f98dcd0a1f9da3d176f4a100f825b4 (diff)
Use vector outputs for texture operations (#3939)
* Change AggregateType to include vector type counts * Replace VariableType uses with AggregateType and delete VariableType * Support new local vector types on SPIR-V and GLSL * Start using vector outputs for texture operations * Use vectors on more texture operations * Use vector output for ImageLoad operations * Replace all uses of single destination texture constructors with multi destination ones * Update textureGatherOffsets replacement to split vector operations * Shader cache version bump Co-authored-by: Ac_K <Acoustik666@gmail.com>
Diffstat (limited to 'Ryujinx.Graphics.Shader/Translation')
-rw-r--r--Ryujinx.Graphics.Shader/Translation/AggregateType.cs11
-rw-r--r--Ryujinx.Graphics.Shader/Translation/AttributeInfo.cs60
-rw-r--r--Ryujinx.Graphics.Shader/Translation/EmitterContext.cs8
-rw-r--r--Ryujinx.Graphics.Shader/Translation/Rewriter.cs258
4 files changed, 210 insertions, 127 deletions
diff --git a/Ryujinx.Graphics.Shader/Translation/AggregateType.cs b/Ryujinx.Graphics.Shader/Translation/AggregateType.cs
index dcd1e0bd..24993e00 100644
--- a/Ryujinx.Graphics.Shader/Translation/AggregateType.cs
+++ b/Ryujinx.Graphics.Shader/Translation/AggregateType.cs
@@ -12,7 +12,14 @@
ElementTypeMask = 0xff,
- Vector = 1 << 8,
- Array = 1 << 9
+ ElementCountShift = 8,
+ ElementCountMask = 3 << ElementCountShift,
+
+ Scalar = 0 << ElementCountShift,
+ Vector2 = 1 << ElementCountShift,
+ Vector3 = 2 << ElementCountShift,
+ Vector4 = 3 << ElementCountShift,
+
+ Array = 1 << 10
}
}
diff --git a/Ryujinx.Graphics.Shader/Translation/AttributeInfo.cs b/Ryujinx.Graphics.Shader/Translation/AttributeInfo.cs
index 1647f656..fa1ae17f 100644
--- a/Ryujinx.Graphics.Shader/Translation/AttributeInfo.cs
+++ b/Ryujinx.Graphics.Shader/Translation/AttributeInfo.cs
@@ -9,22 +9,22 @@ namespace Ryujinx.Graphics.Shader.Translation
{ AttributeConsts.Layer, new AttributeInfo(AttributeConsts.Layer, 0, 1, AggregateType.S32) },
{ AttributeConsts.ViewportIndex, new AttributeInfo(AttributeConsts.ViewportIndex, 0, 1, AggregateType.S32) },
{ AttributeConsts.PointSize, new AttributeInfo(AttributeConsts.PointSize, 0, 1, AggregateType.FP32) },
- { AttributeConsts.PositionX, new AttributeInfo(AttributeConsts.PositionX, 0, 4, AggregateType.Vector | AggregateType.FP32) },
- { AttributeConsts.PositionY, new AttributeInfo(AttributeConsts.PositionX, 1, 4, AggregateType.Vector | AggregateType.FP32) },
- { AttributeConsts.PositionZ, new AttributeInfo(AttributeConsts.PositionX, 2, 4, AggregateType.Vector | AggregateType.FP32) },
- { AttributeConsts.PositionW, new AttributeInfo(AttributeConsts.PositionX, 3, 4, AggregateType.Vector | AggregateType.FP32) },
- { AttributeConsts.ClipDistance0, new AttributeInfo(AttributeConsts.ClipDistance0, 0, 8, AggregateType.Array | AggregateType.FP32) },
- { AttributeConsts.ClipDistance1, new AttributeInfo(AttributeConsts.ClipDistance0, 1, 8, AggregateType.Array | AggregateType.FP32) },
- { AttributeConsts.ClipDistance2, new AttributeInfo(AttributeConsts.ClipDistance0, 2, 8, AggregateType.Array | AggregateType.FP32) },
- { AttributeConsts.ClipDistance3, new AttributeInfo(AttributeConsts.ClipDistance0, 3, 8, AggregateType.Array | AggregateType.FP32) },
- { AttributeConsts.ClipDistance4, new AttributeInfo(AttributeConsts.ClipDistance0, 4, 8, AggregateType.Array | AggregateType.FP32) },
- { AttributeConsts.ClipDistance5, new AttributeInfo(AttributeConsts.ClipDistance0, 5, 8, AggregateType.Array | AggregateType.FP32) },
- { AttributeConsts.ClipDistance6, new AttributeInfo(AttributeConsts.ClipDistance0, 6, 8, AggregateType.Array | AggregateType.FP32) },
- { AttributeConsts.ClipDistance7, new AttributeInfo(AttributeConsts.ClipDistance0, 7, 8, AggregateType.Array | AggregateType.FP32) },
- { AttributeConsts.PointCoordX, new AttributeInfo(AttributeConsts.PointCoordX, 0, 2, AggregateType.Vector | AggregateType.FP32) },
- { AttributeConsts.PointCoordY, new AttributeInfo(AttributeConsts.PointCoordX, 1, 2, AggregateType.Vector | AggregateType.FP32) },
- { AttributeConsts.TessCoordX, new AttributeInfo(AttributeConsts.TessCoordX, 0, 3, AggregateType.Vector | AggregateType.FP32) },
- { AttributeConsts.TessCoordY, new AttributeInfo(AttributeConsts.TessCoordX, 1, 3, AggregateType.Vector | AggregateType.FP32) },
+ { AttributeConsts.PositionX, new AttributeInfo(AttributeConsts.PositionX, 0, 4, AggregateType.Vector4 | AggregateType.FP32) },
+ { AttributeConsts.PositionY, new AttributeInfo(AttributeConsts.PositionX, 1, 4, AggregateType.Vector4 | AggregateType.FP32) },
+ { AttributeConsts.PositionZ, new AttributeInfo(AttributeConsts.PositionX, 2, 4, AggregateType.Vector4 | AggregateType.FP32) },
+ { AttributeConsts.PositionW, new AttributeInfo(AttributeConsts.PositionX, 3, 4, AggregateType.Vector4 | AggregateType.FP32) },
+ { AttributeConsts.ClipDistance0, new AttributeInfo(AttributeConsts.ClipDistance0, 0, 8, AggregateType.Array | AggregateType.FP32) },
+ { AttributeConsts.ClipDistance1, new AttributeInfo(AttributeConsts.ClipDistance0, 1, 8, AggregateType.Array | AggregateType.FP32) },
+ { AttributeConsts.ClipDistance2, new AttributeInfo(AttributeConsts.ClipDistance0, 2, 8, AggregateType.Array | AggregateType.FP32) },
+ { AttributeConsts.ClipDistance3, new AttributeInfo(AttributeConsts.ClipDistance0, 3, 8, AggregateType.Array | AggregateType.FP32) },
+ { AttributeConsts.ClipDistance4, new AttributeInfo(AttributeConsts.ClipDistance0, 4, 8, AggregateType.Array | AggregateType.FP32) },
+ { AttributeConsts.ClipDistance5, new AttributeInfo(AttributeConsts.ClipDistance0, 5, 8, AggregateType.Array | AggregateType.FP32) },
+ { AttributeConsts.ClipDistance6, new AttributeInfo(AttributeConsts.ClipDistance0, 6, 8, AggregateType.Array | AggregateType.FP32) },
+ { AttributeConsts.ClipDistance7, new AttributeInfo(AttributeConsts.ClipDistance0, 7, 8, AggregateType.Array | AggregateType.FP32) },
+ { AttributeConsts.PointCoordX, new AttributeInfo(AttributeConsts.PointCoordX, 0, 2, AggregateType.Vector4 | AggregateType.FP32) },
+ { AttributeConsts.PointCoordY, new AttributeInfo(AttributeConsts.PointCoordX, 1, 2, AggregateType.Vector4 | AggregateType.FP32) },
+ { AttributeConsts.TessCoordX, new AttributeInfo(AttributeConsts.TessCoordX, 0, 3, AggregateType.Vector4 | AggregateType.FP32) },
+ { AttributeConsts.TessCoordY, new AttributeInfo(AttributeConsts.TessCoordX, 1, 3, AggregateType.Vector4 | AggregateType.FP32) },
{ AttributeConsts.InstanceId, new AttributeInfo(AttributeConsts.InstanceId, 0, 1, AggregateType.S32) },
{ AttributeConsts.VertexId, new AttributeInfo(AttributeConsts.VertexId, 0, 1, AggregateType.S32) },
{ AttributeConsts.BaseInstance, new AttributeInfo(AttributeConsts.BaseInstance, 0, 1, AggregateType.S32) },
@@ -37,21 +37,21 @@ namespace Ryujinx.Graphics.Shader.Translation
// Special.
{ AttributeConsts.FragmentOutputDepth, new AttributeInfo(AttributeConsts.FragmentOutputDepth, 0, 1, AggregateType.FP32) },
{ AttributeConsts.ThreadKill, new AttributeInfo(AttributeConsts.ThreadKill, 0, 1, AggregateType.Bool) },
- { AttributeConsts.ThreadIdX, new AttributeInfo(AttributeConsts.ThreadIdX, 0, 3, AggregateType.Vector | AggregateType.U32) },
- { AttributeConsts.ThreadIdY, new AttributeInfo(AttributeConsts.ThreadIdX, 1, 3, AggregateType.Vector | AggregateType.U32) },
- { AttributeConsts.ThreadIdZ, new AttributeInfo(AttributeConsts.ThreadIdX, 2, 3, AggregateType.Vector | AggregateType.U32) },
- { AttributeConsts.CtaIdX, new AttributeInfo(AttributeConsts.CtaIdX, 0, 3, AggregateType.Vector | AggregateType.U32) },
- { AttributeConsts.CtaIdY, new AttributeInfo(AttributeConsts.CtaIdX, 1, 3, AggregateType.Vector | AggregateType.U32) },
- { AttributeConsts.CtaIdZ, new AttributeInfo(AttributeConsts.CtaIdX, 2, 3, AggregateType.Vector | AggregateType.U32) },
+ { AttributeConsts.ThreadIdX, new AttributeInfo(AttributeConsts.ThreadIdX, 0, 3, AggregateType.Vector3 | AggregateType.U32) },
+ { AttributeConsts.ThreadIdY, new AttributeInfo(AttributeConsts.ThreadIdX, 1, 3, AggregateType.Vector3 | AggregateType.U32) },
+ { AttributeConsts.ThreadIdZ, new AttributeInfo(AttributeConsts.ThreadIdX, 2, 3, AggregateType.Vector3 | AggregateType.U32) },
+ { AttributeConsts.CtaIdX, new AttributeInfo(AttributeConsts.CtaIdX, 0, 3, AggregateType.Vector3 | AggregateType.U32) },
+ { AttributeConsts.CtaIdY, new AttributeInfo(AttributeConsts.CtaIdX, 1, 3, AggregateType.Vector3 | AggregateType.U32) },
+ { AttributeConsts.CtaIdZ, new AttributeInfo(AttributeConsts.CtaIdX, 2, 3, AggregateType.Vector3 | AggregateType.U32) },
{ AttributeConsts.LaneId, new AttributeInfo(AttributeConsts.LaneId, 0, 1, AggregateType.U32) },
{ AttributeConsts.InvocationId, new AttributeInfo(AttributeConsts.InvocationId, 0, 1, AggregateType.S32) },
{ AttributeConsts.PrimitiveId, new AttributeInfo(AttributeConsts.PrimitiveId, 0, 1, AggregateType.S32) },
{ AttributeConsts.PatchVerticesIn, new AttributeInfo(AttributeConsts.PatchVerticesIn, 0, 1, AggregateType.S32) },
- { AttributeConsts.EqMask, new AttributeInfo(AttributeConsts.EqMask, 0, 4, AggregateType.Vector | AggregateType.U32) },
- { AttributeConsts.GeMask, new AttributeInfo(AttributeConsts.GeMask, 0, 4, AggregateType.Vector | AggregateType.U32) },
- { AttributeConsts.GtMask, new AttributeInfo(AttributeConsts.GtMask, 0, 4, AggregateType.Vector | AggregateType.U32) },
- { AttributeConsts.LeMask, new AttributeInfo(AttributeConsts.LeMask, 0, 4, AggregateType.Vector | AggregateType.U32) },
- { AttributeConsts.LtMask, new AttributeInfo(AttributeConsts.LtMask, 0, 4, AggregateType.Vector | AggregateType.U32) },
+ { AttributeConsts.EqMask, new AttributeInfo(AttributeConsts.EqMask, 0, 4, AggregateType.Vector4 | AggregateType.U32) },
+ { AttributeConsts.GeMask, new AttributeInfo(AttributeConsts.GeMask, 0, 4, AggregateType.Vector4 | AggregateType.U32) },
+ { AttributeConsts.GtMask, new AttributeInfo(AttributeConsts.GtMask, 0, 4, AggregateType.Vector4 | AggregateType.U32) },
+ { AttributeConsts.LeMask, new AttributeInfo(AttributeConsts.LeMask, 0, 4, AggregateType.Vector4 | AggregateType.U32) },
+ { AttributeConsts.LtMask, new AttributeInfo(AttributeConsts.LtMask, 0, 4, AggregateType.Vector4 | AggregateType.U32) },
};
private static readonly Dictionary<int, AttributeInfo> _builtInAttributesPerPatch = new Dictionary<int, AttributeInfo>()
@@ -124,11 +124,11 @@ namespace Ryujinx.Graphics.Shader.Translation
elemType = AggregateType.FP32;
}
- return new AttributeInfo(value & ~0xf, (value >> 2) & 3, 4, AggregateType.Vector | elemType, false);
+ return new AttributeInfo(value & ~0xf, (value >> 2) & 3, 4, AggregateType.Vector4 | elemType, false);
}
else if (value >= AttributeConsts.FragmentOutputColorBase && value < AttributeConsts.FragmentOutputColorEnd)
{
- return new AttributeInfo(value & ~0xf, (value >> 2) & 3, 4, AggregateType.Vector | AggregateType.FP32, false);
+ return new AttributeInfo(value & ~0xf, (value >> 2) & 3, 4, AggregateType.Vector4 | AggregateType.FP32, false);
}
else if (value == AttributeConsts.SupportBlockViewInverseX || value == AttributeConsts.SupportBlockViewInverseY)
{
@@ -149,7 +149,7 @@ namespace Ryujinx.Graphics.Shader.Translation
if (value >= AttributeConsts.UserAttributePerPatchBase && value < AttributeConsts.UserAttributePerPatchEnd)
{
int offset = (value - AttributeConsts.UserAttributePerPatchBase) & 0xf;
- return new AttributeInfo(value - offset, offset >> 2, 4, AggregateType.Vector | AggregateType.FP32, false);
+ return new AttributeInfo(value - offset, offset >> 2, 4, AggregateType.Vector4 | AggregateType.FP32, false);
}
else if (_builtInAttributesPerPatch.TryGetValue(value, out AttributeInfo info))
{
diff --git a/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs b/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
index 7961ada8..ad55c010 100644
--- a/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
+++ b/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
@@ -109,10 +109,10 @@ namespace Ryujinx.Graphics.Shader.Translation
TextureFlags flags,
int handle,
int compIndex,
- Operand dest,
+ Operand[] dests,
params Operand[] sources)
{
- return CreateTextureOperation(inst, type, TextureFormat.Unknown, flags, handle, compIndex, dest, sources);
+ return CreateTextureOperation(inst, type, TextureFormat.Unknown, flags, handle, compIndex, dests, sources);
}
public TextureOperation CreateTextureOperation(
@@ -122,7 +122,7 @@ namespace Ryujinx.Graphics.Shader.Translation
TextureFlags flags,
int handle,
int compIndex,
- Operand dest,
+ Operand[] dests,
params Operand[] sources)
{
if (!flags.HasFlag(TextureFlags.Bindless))
@@ -130,7 +130,7 @@ namespace Ryujinx.Graphics.Shader.Translation
Config.SetUsedTexture(inst, type, format, flags, TextureOperation.DefaultCbufSlot, handle);
}
- return new TextureOperation(inst, type, format, flags, handle, compIndex, dest, sources);
+ return new TextureOperation(inst, type, format, flags, handle, compIndex, dests, sources);
}
public void FlagAttributeRead(int attribute)
diff --git a/Ryujinx.Graphics.Shader/Translation/Rewriter.cs b/Ryujinx.Graphics.Shader/Translation/Rewriter.cs
index 0c3c4a57..3ec4e49a 100644
--- a/Ryujinx.Graphics.Shader/Translation/Rewriter.cs
+++ b/Ryujinx.Graphics.Shader/Translation/Rewriter.cs
@@ -385,15 +385,6 @@ namespace Ryujinx.Graphics.Shader.Translation
int componentIndex = texOp.Index;
- Operand Int(Operand value)
- {
- Operand res = Local();
-
- node.List.AddBefore(node, new Operation(Instruction.ConvertFP32ToS32, res, value));
-
- return res;
- }
-
Operand Float(Operand value)
{
Operand res = Local();
@@ -436,7 +427,7 @@ namespace Ryujinx.Graphics.Shader.Translation
texOp.CbufSlot,
texOp.Handle,
index,
- coordSize,
+ new[] { coordSize },
texSizeSources));
config.SetUsedTexture(Instruction.TextureSize, texOp.Type, texOp.Format, texOp.Flags, texOp.CbufSlot, texOp.Handle);
@@ -451,124 +442,204 @@ namespace Ryujinx.Graphics.Shader.Translation
}
}
+ Operand[] dests = new Operand[texOp.DestsCount];
+
+ for (int i = 0; i < texOp.DestsCount; i++)
+ {
+ dests[i] = texOp.GetDest(i);
+ }
+
+ Operand bindlessHandle = isBindless || isIndexed ? sources[0] : null;
+
+ LinkedListNode<INode> oldNode = node;
+
// Technically, non-constant texture offsets are not allowed (according to the spec),
// however some GPUs does support that.
// For GPUs where it is not supported, we can replace the instruction with the following:
// For texture*Offset, we replace it by texture*, and add the offset to the P coords.
// The offset can be calculated as offset / textureSize(lod), where lod = textureQueryLod(coords).
// For texelFetchOffset, we replace it by texelFetch and add the offset to the P coords directly.
- // For textureGatherOffset, we take advantage of the fact that the operation is already broken down
- // to read the 4 pixels separately, and just replace it with 4 textureGather with a different offset
- // for each pixel.
- if (hasInvalidOffset)
+ // For textureGatherOffset, we split the operation into up to 4 operations, one for each component
+ // that is accessed, where each textureGather operation has a different offset for each pixel.
+ if (hasInvalidOffset && isGather && !isShadow)
{
- if (intCoords)
+ config.SetUsedFeature(FeatureFlags.IntegerSampling);
+
+ Operand[] newSources = new Operand[sources.Length];
+
+ sources.CopyTo(newSources, 0);
+
+ Operand[] texSizes = InsertTextureSize(node, texOp, lodSources, bindlessHandle, coordsCount);
+
+ int destIndex = 0;
+
+ for (int compIndex = 0; compIndex < 4; compIndex++)
{
+ if (((texOp.Index >> compIndex) & 1) == 0)
+ {
+ continue;
+ }
+
for (int index = 0; index < coordsCount; index++)
{
+ config.SetUsedTexture(Instruction.TextureSize, texOp.Type, texOp.Format, texOp.Flags, texOp.CbufSlot, texOp.Handle);
+
+ Operand offset = Local();
+
+ Operand intOffset = offsets[index + (hasOffsets ? compIndex * coordsCount : 0)];
+
+ node.List.AddBefore(node, new Operation(Instruction.FP32 | Instruction.Divide, offset, Float(intOffset), Float(texSizes[index])));
+
Operand source = sources[coordsIndex + index];
Operand coordPlusOffset = Local();
- node.List.AddBefore(node, new Operation(Instruction.Add, coordPlusOffset, source, offsets[index]));
+ node.List.AddBefore(node, new Operation(Instruction.FP32 | Instruction.Add, coordPlusOffset, source, offset));
- sources[coordsIndex + index] = coordPlusOffset;
+ newSources[coordsIndex + index] = coordPlusOffset;
}
- }
- else
- {
- config.SetUsedFeature(FeatureFlags.IntegerSampling);
-
- Operand lod = Local();
- node.List.AddBefore(node, new TextureOperation(
- Instruction.Lod,
+ TextureOperation newTexOp = new TextureOperation(
+ Instruction.TextureSample,
texOp.Type,
texOp.Format,
- texOp.Flags,
+ texOp.Flags & ~(TextureFlags.Offset | TextureFlags.Offsets),
texOp.CbufSlot,
texOp.Handle,
- 0,
- lod,
- lodSources));
+ 1,
+ new[] { dests[destIndex++] },
+ newSources);
- for (int index = 0; index < coordsCount; index++)
+ node = node.List.AddBefore(node, newTexOp);
+ }
+ }
+ else
+ {
+ if (hasInvalidOffset)
+ {
+ if (intCoords)
{
- Operand coordSize = Local();
+ for (int index = 0; index < coordsCount; index++)
+ {
+ Operand source = sources[coordsIndex + index];
- Operand[] texSizeSources;
+ Operand coordPlusOffset = Local();
- if (isBindless || isIndexed)
- {
- texSizeSources = new Operand[] { sources[0], Int(lod) };
- }
- else
- {
- texSizeSources = new Operand[] { Int(lod) };
+ node.List.AddBefore(node, new Operation(Instruction.Add, coordPlusOffset, source, offsets[index]));
+
+ sources[coordsIndex + index] = coordPlusOffset;
}
+ }
+ else
+ {
+ config.SetUsedFeature(FeatureFlags.IntegerSampling);
- node.List.AddBefore(node, new TextureOperation(
- Instruction.TextureSize,
- texOp.Type,
- texOp.Format,
- texOp.Flags,
- texOp.CbufSlot,
- texOp.Handle,
- index,
- coordSize,
- texSizeSources));
+ Operand[] texSizes = InsertTextureSize(node, texOp, lodSources, bindlessHandle, coordsCount);
- config.SetUsedTexture(Instruction.TextureSize, texOp.Type, texOp.Format, texOp.Flags, texOp.CbufSlot, texOp.Handle);
+ for (int index = 0; index < coordsCount; index++)
+ {
+ config.SetUsedTexture(Instruction.TextureSize, texOp.Type, texOp.Format, texOp.Flags, texOp.CbufSlot, texOp.Handle);
- Operand offset = Local();
+ Operand offset = Local();
- Operand intOffset = offsets[index + (hasOffsets ? texOp.Index * coordsCount : 0)];
+ Operand intOffset = offsets[index];
- node.List.AddBefore(node, new Operation(Instruction.FP32 | Instruction.Divide, offset, Float(intOffset), Float(coordSize)));
+ node.List.AddBefore(node, new Operation(Instruction.FP32 | Instruction.Divide, offset, Float(intOffset), Float(texSizes[index])));
- Operand source = sources[coordsIndex + index];
+ Operand source = sources[coordsIndex + index];
- Operand coordPlusOffset = Local();
+ Operand coordPlusOffset = Local();
- node.List.AddBefore(node, new Operation(Instruction.FP32 | Instruction.Add, coordPlusOffset, source, offset));
+ node.List.AddBefore(node, new Operation(Instruction.FP32 | Instruction.Add, coordPlusOffset, source, offset));
- sources[coordsIndex + index] = coordPlusOffset;
+ sources[coordsIndex + index] = coordPlusOffset;
+ }
}
}
- if (isGather && !isShadow)
- {
- Operand gatherComponent = sources[dstIndex - 1];
+ TextureOperation newTexOp = new TextureOperation(
+ Instruction.TextureSample,
+ texOp.Type,
+ texOp.Format,
+ texOp.Flags & ~(TextureFlags.Offset | TextureFlags.Offsets),
+ texOp.CbufSlot,
+ texOp.Handle,
+ componentIndex,
+ dests,
+ sources);
- Debug.Assert(gatherComponent.Type == OperandType.Constant);
+ node = node.List.AddBefore(node, newTexOp);
+ }
- componentIndex = gatherComponent.Value;
- }
+ node.List.Remove(oldNode);
+
+ for (int index = 0; index < texOp.SourcesCount; index++)
+ {
+ texOp.SetSource(index, null);
+ }
+
+ return node;
+ }
+
+ private static Operand[] InsertTextureSize(
+ LinkedListNode<INode> node,
+ TextureOperation texOp,
+ Operand[] lodSources,
+ Operand bindlessHandle,
+ int coordsCount)
+ {
+ Operand Int(Operand value)
+ {
+ Operand res = Local();
+
+ node.List.AddBefore(node, new Operation(Instruction.ConvertFP32ToS32, res, value));
+
+ return res;
}
- TextureOperation newTexOp = new TextureOperation(
- Instruction.TextureSample,
+ Operand[] texSizes = new Operand[coordsCount];
+
+ Operand lod = Local();
+
+ node.List.AddBefore(node, new TextureOperation(
+ Instruction.Lod,
texOp.Type,
texOp.Format,
- texOp.Flags & ~(TextureFlags.Offset | TextureFlags.Offsets),
+ texOp.Flags,
texOp.CbufSlot,
texOp.Handle,
- componentIndex,
- texOp.Dest,
- sources);
+ 0,
+ new[] { lod },
+ lodSources));
- for (int index = 0; index < texOp.SourcesCount; index++)
+ for (int index = 0; index < coordsCount; index++)
{
- texOp.SetSource(index, null);
- }
+ texSizes[index] = Local();
- LinkedListNode<INode> oldNode = node;
+ Operand[] texSizeSources;
- node = node.List.AddBefore(node, newTexOp);
+ if (bindlessHandle != null)
+ {
+ texSizeSources = new Operand[] { bindlessHandle, Int(lod) };
+ }
+ else
+ {
+ texSizeSources = new Operand[] { Int(lod) };
+ }
- node.List.Remove(oldNode);
+ node.List.AddBefore(node, new TextureOperation(
+ Instruction.TextureSize,
+ texOp.Type,
+ texOp.Format,
+ texOp.Flags,
+ texOp.CbufSlot,
+ texOp.Handle,
+ index,
+ new[] { texSizes[index] },
+ texSizeSources));
+ }
- return node;
+ return texSizes;
}
private static LinkedListNode<INode> InsertSnormNormalization(LinkedListNode<INode> node, ShaderConfig config)
@@ -604,27 +675,32 @@ namespace Ryujinx.Graphics.Shader.Translation
// Do normalization. We assume SINT formats are being used
// as replacement for SNORM (which is not supported).
- INode[] uses = texOp.Dest.UseOps.ToArray();
+ for (int i = 0; i < texOp.DestsCount; i++)
+ {
+ Operand dest = texOp.GetDest(i);
- Operation convOp = new Operation(Instruction.ConvertS32ToFP32, Local(), texOp.Dest);
- Operation normOp = new Operation(Instruction.FP32 | Instruction.Multiply, Local(), convOp.Dest, ConstF(1f / maxPositive));
+ INode[] uses = dest.UseOps.ToArray();
- node = node.List.AddAfter(node, convOp);
- node = node.List.AddAfter(node, normOp);
+ Operation convOp = new Operation(Instruction.ConvertS32ToFP32, Local(), dest);
+ Operation normOp = new Operation(Instruction.FP32 | Instruction.Multiply, Local(), convOp.Dest, ConstF(1f / maxPositive));
- foreach (INode useOp in uses)
- {
- if (useOp is not Operation op)
- {
- continue;
- }
+ node = node.List.AddAfter(node, convOp);
+ node = node.List.AddAfter(node, normOp);
- // Replace all uses of the texture pixel value with the normalized value.
- for (int index = 0; index < op.SourcesCount; index++)
+ foreach (INode useOp in uses)
{
- if (op.GetSource(index) == texOp.Dest)
+ if (useOp is not Operation op)
{
- op.SetSource(index, normOp.Dest);
+ continue;
+ }
+
+ // Replace all uses of the texture pixel value with the normalized value.
+ for (int index = 0; index < op.SourcesCount; index++)
+ {
+ if (op.GetSource(index) == dest)
+ {
+ op.SetSource(index, normOp.Dest);
+ }
}
}
}