diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/InstGenMemory.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/InstGenMemory.cs index 53d3217704..a9801dc048 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/InstGenMemory.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/InstGenMemory.cs @@ -35,10 +35,60 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl.Instructions case StorageKind.InputPerPatch: case StorageKind.Output: case StorageKind.OutputPerPatch: - return "I/O load or store"; + if (operation.GetSource(srcIndex++) is not AstOperand varId || varId.Type != OperandType.Constant) + { + throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand."); + } + + IoVariable ioVariable = (IoVariable)varId.Value; + bool isOutput = storageKind.IsOutput(); + + if (context.Definitions.HasPerLocationInputOrOutput(ioVariable, isOutput)) + { + if (operation.GetSource(srcIndex++) is not AstOperand vecIndex || vecIndex.Type != OperandType.Constant) + { + throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand."); + } + + if (operation.SourcesCount > srcIndex && + operation.GetSource(srcIndex) is AstOperand elemIndex && + elemIndex.Type == OperandType.Constant && + context.Definitions.HasPerLocationInputOrOutputComponent(ioVariable, vecIndex.Value, elemIndex.Value, isOutput)) + { + srcIndex++; + } + } + + (varName, varType) = IoMap.GetMslBuiltIn(ioVariable); + break; default: throw new InvalidOperationException($"Invalid storage kind {storageKind}."); } + + for (; srcIndex < inputsCount; srcIndex++) + { + IAstNode src = operation.GetSource(srcIndex); + + if ((varType & AggregateType.ElementCountMask) != 0 && + srcIndex == inputsCount - 1 && + src is AstOperand elementIndex && + elementIndex.Type == OperandType.Constant) + { + varName += "." + "xyzw"[elementIndex.Value & 3]; + } + else + { + varName += $"[{GetSourceExpr(context, src, AggregateType.S32)}]"; + } + } + + if (isStore) + { + varType &= AggregateType.ElementTypeMask; + varName = $"{varName} = {GetSourceExpr(context, operation.GetSource(srcIndex), varType)}"; + } + + return varName; } public static string Load(CodeGenContext context, AstOperation operation) diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/IoMap.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/IoMap.cs index 261a0e572c..8c0a54c0a2 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/IoMap.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Msl/Instructions/IoMap.cs @@ -5,7 +5,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl.Instructions { static class IoMap { - public static (string, AggregateType) GetMSLBuiltIn(IoVariable ioVariable) + public static (string, AggregateType) GetMslBuiltIn(IoVariable ioVariable) { return ioVariable switch { diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Msl/OperandManager.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Msl/OperandManager.cs index beaf25f688..7ec653fa88 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Msl/OperandManager.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Msl/OperandManager.cs @@ -118,7 +118,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl } } - (_, AggregateType varType) = IoMap.GetMSLBuiltIn(ioVariable); + (_, AggregateType varType) = IoMap.GetMslBuiltIn(ioVariable); return varType & AggregateType.ElementTypeMask; }