mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-03-28 00:00:19 +00:00
* Move some properties out of ShaderConfig * Stop using ShaderConfig on backends * Replace ShaderConfig usages on Translator and passes * Move remaining properties out of ShaderConfig and delete ShaderConfig * Remove ResourceManager property from TranslatorContext * Move Rewriter passes to separate transform pass files * Fix TransformPasses.RunPass on cases where a node is removed * Move remaining ClipDistancePrimitivesWritten and UsedFeatures updates to decode stage * Reduce excessive parameter passing a bit by using structs more * Remove binding parameter from ShaderProperties methods since it is redundant * Replace decoder instruction checks with switch statement * Put GLSL on the same plan as SPIR-V for input/output declaration * Stop mutating TranslatorContext state when Translate is called * Pass most of the graphics state using a struct instead of individual query methods * Auto-format * Auto-format * Add backend logging interface * Auto-format * Remove unnecessary use of interpolated strings * Remove more modifications of AttributeUsage after decode * PR feedback * gl_Layer is not supported on compute
96 lines
3.2 KiB
C#
96 lines
3.2 KiB
C#
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
|
using Ryujinx.Graphics.Shader.StructuredIr;
|
|
using System.Collections.Generic;
|
|
|
|
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
|
|
|
namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|
{
|
|
class VectorComponentSelect : ITransformPass
|
|
{
|
|
public static bool IsEnabled(IGpuAccessor gpuAccessor, ShaderStage stage, TargetLanguage targetLanguage, FeatureFlags usedFeatures)
|
|
{
|
|
return gpuAccessor.QueryHostHasVectorIndexingBug();
|
|
}
|
|
|
|
public static LinkedListNode<INode> RunPass(TransformContext context, LinkedListNode<INode> node)
|
|
{
|
|
Operation operation = (Operation)node.Value;
|
|
|
|
if (operation.Inst != Instruction.Load ||
|
|
operation.StorageKind != StorageKind.ConstantBuffer ||
|
|
operation.SourcesCount < 3)
|
|
{
|
|
return node;
|
|
}
|
|
|
|
Operand bindingIndex = operation.GetSource(0);
|
|
Operand fieldIndex = operation.GetSource(1);
|
|
Operand elemIndex = operation.GetSource(operation.SourcesCount - 1);
|
|
|
|
if (bindingIndex.Type != OperandType.Constant ||
|
|
fieldIndex.Type != OperandType.Constant ||
|
|
elemIndex.Type == OperandType.Constant)
|
|
{
|
|
return node;
|
|
}
|
|
|
|
BufferDefinition buffer = context.ResourceManager.Properties.ConstantBuffers[bindingIndex.Value];
|
|
StructureField field = buffer.Type.Fields[fieldIndex.Value];
|
|
|
|
int elemCount = (field.Type & AggregateType.ElementCountMask) switch
|
|
{
|
|
AggregateType.Vector2 => 2,
|
|
AggregateType.Vector3 => 3,
|
|
AggregateType.Vector4 => 4,
|
|
_ => 1
|
|
};
|
|
|
|
if (elemCount == 1)
|
|
{
|
|
return node;
|
|
}
|
|
|
|
Operand result = null;
|
|
|
|
for (int i = 0; i < elemCount; i++)
|
|
{
|
|
Operand value = Local();
|
|
Operand[] inputs = new Operand[operation.SourcesCount];
|
|
|
|
for (int srcIndex = 0; srcIndex < inputs.Length - 1; srcIndex++)
|
|
{
|
|
inputs[srcIndex] = operation.GetSource(srcIndex);
|
|
}
|
|
|
|
inputs[^1] = Const(i);
|
|
|
|
Operation loadOp = new(Instruction.Load, StorageKind.ConstantBuffer, value, inputs);
|
|
|
|
node.List.AddBefore(node, loadOp);
|
|
|
|
if (i == 0)
|
|
{
|
|
result = value;
|
|
}
|
|
else
|
|
{
|
|
Operand isCurrentIndex = Local();
|
|
Operand selection = Local();
|
|
|
|
Operation compareOp = new(Instruction.CompareEqual, isCurrentIndex, new Operand[] { elemIndex, Const(i) });
|
|
Operation selectOp = new(Instruction.ConditionalSelect, selection, new Operand[] { isCurrentIndex, value, result });
|
|
|
|
node.List.AddBefore(node, compareOp);
|
|
node.List.AddBefore(node, selectOp);
|
|
|
|
result = selection;
|
|
}
|
|
}
|
|
|
|
operation.TurnIntoCopy(result);
|
|
|
|
return node;
|
|
}
|
|
}
|
|
}
|