Add a pass to turn global memory access into storage access, and do all storage related transformations on IR
This commit is contained in:
@ -86,7 +86,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
|
||||
if (info.SBuffers.Count != 0)
|
||||
{
|
||||
DeclareUsedStorage(context, info);
|
||||
DeclareStorages(context, info);
|
||||
|
||||
context.AppendLine();
|
||||
}
|
||||
@ -176,11 +176,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
|
||||
context.AppendLine(GetVarTypeName(decl.VarType) + " " + name + ";");
|
||||
}
|
||||
|
||||
if ((info.HelperFunctionsMask & HelperFunctionsMask.GlobalMemory) != 0)
|
||||
{
|
||||
context.AppendLine($"ivec2 {DefaultNames.GmemOffsetName};");
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetVarTypeName(VariableType type)
|
||||
@ -218,31 +213,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
}
|
||||
}
|
||||
|
||||
private static void DeclareAllStorage(CodeGenContext context, StructuredProgramInfo info)
|
||||
{
|
||||
string sbName = OperandManager.GetShaderStagePrefix(context.Config.Stage);
|
||||
|
||||
sbName += "_" + DefaultNames.StorageNamePrefix;
|
||||
|
||||
string blockName = $"{sbName}_{DefaultNames.BlockSuffix}";
|
||||
|
||||
context.AppendLine("layout (std430) buffer " + blockName);
|
||||
|
||||
context.EnterScope();
|
||||
|
||||
context.AppendLine("uint " + DefaultNames.DataName + "[];");
|
||||
|
||||
string arraySize = NumberFormatter.FormatInt(Constants.MaxShaderStorageBuffers);
|
||||
|
||||
context.LeaveScope($" {sbName}[{arraySize}];");
|
||||
|
||||
for (int sbufSlot = 0; sbufSlot < Constants.MaxShaderStorageBuffers; sbufSlot++)
|
||||
{
|
||||
context.SBufferDescriptors.Add(new BufferDescriptor($"{blockName}[{sbufSlot}]", sbufSlot));
|
||||
}
|
||||
}
|
||||
|
||||
private static void DeclareUsedStorage(CodeGenContext context, StructuredProgramInfo info)
|
||||
private static void DeclareStorages(CodeGenContext context, StructuredProgramInfo info)
|
||||
{
|
||||
string sbName = OperandManager.GetShaderStagePrefix(context.Config.Stage);
|
||||
|
||||
|
@ -22,8 +22,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
public const string LocalMemoryName = "local_mem";
|
||||
public const string SharedMemoryName = "shared_mem";
|
||||
|
||||
public const string GmemOffsetName = "gmemOffset";
|
||||
|
||||
public const string UndefinedName = "undef";
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
ivec2 Helper_GetStorageBuffer(uint aLow, uint aHigh)
|
||||
{
|
||||
uint64_t address = packUint2x32(uvec2(aLow, aHigh));
|
||||
int i;
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
int offset = 0x40 + i * 4;
|
||||
uint baseLow = fp_c0_data[offset];
|
||||
uint baseHigh = fp_c0_data[offset + 1];
|
||||
uint size = fp_c0_data[offset + 2];
|
||||
uint64_t baseAddr = packUint2x32(uvec2(baseLow, baseHigh));
|
||||
if (address >= baseAddr && address < baseAddr + packUint2x32(uvec2(size, 0)))
|
||||
{
|
||||
return ivec2(i, int(unpackUint2x32(address - (baseAddr & ~63ul)).x) >> 2);
|
||||
}
|
||||
}
|
||||
return ivec2(0);
|
||||
}
|
@ -2,8 +2,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
{
|
||||
static class HelperFunctionNames
|
||||
{
|
||||
public static string GetStorageBuffer = "Helper_GetStorageBuffer";
|
||||
|
||||
public static string Shuffle = "Helper_Shuffle";
|
||||
public static string ShuffleDown = "Helper_ShuffleDown";
|
||||
public static string ShuffleUp = "Helper_ShuffleUp";
|
||||
|
@ -49,12 +49,18 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
|
||||
if (argIndex == 0 && atomic)
|
||||
{
|
||||
switch (inst & Instruction.MrMask)
|
||||
Instruction memRegion = inst & Instruction.MrMask;
|
||||
|
||||
switch (memRegion)
|
||||
{
|
||||
// TODO: Global.
|
||||
case Instruction.MrShared: args += LoadShared (context, operation); break;
|
||||
case Instruction.MrStorage: args += LoadStorage(context, operation); break;
|
||||
|
||||
default: throw new InvalidOperationException($"Invalid memory region \"{memRegion}\".");
|
||||
}
|
||||
|
||||
// We use the first 2 operands above.
|
||||
argIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -150,8 +156,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
}
|
||||
}
|
||||
|
||||
return "0";
|
||||
|
||||
throw new InvalidOperationException($"Unexpected instruction type \"{info.Type}\".");
|
||||
}
|
||||
}
|
||||
|
@ -119,19 +119,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
return OperandManager.GetConstantBufferName(src1, offsetExpr, context.Config.Stage);
|
||||
}
|
||||
|
||||
public static string LoadGlobal(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
IAstNode src1 = operation.GetSource(0);
|
||||
IAstNode src2 = operation.GetSource(1);
|
||||
|
||||
string addrLowExpr = GetSoureExpr(context, src1, GetSrcVarType(operation.Inst, 0));
|
||||
string addrHighExpr = GetSoureExpr(context, src2, GetSrcVarType(operation.Inst, 1));
|
||||
|
||||
context.AppendLine($"{DefaultNames.GmemOffsetName} = {HelperFunctionNames.GetStorageBuffer}({addrLowExpr}, {addrHighExpr});");
|
||||
|
||||
return GetStorageBufferAccessor($"{DefaultNames.GmemOffsetName}.x", $"{DefaultNames.GmemOffsetName}.y", context.Config.Stage);
|
||||
}
|
||||
|
||||
public static string LoadLocal(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return LoadLocalOrShared(context, operation, DefaultNames.LocalMemoryName);
|
||||
@ -152,29 +139,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
}
|
||||
|
||||
public static string LoadStorage(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
IAstNode src1 = operation.GetSource(0);
|
||||
|
||||
string offsetExpr = GetSoureExpr(context, src1, GetSrcVarType(operation.Inst, 0));
|
||||
|
||||
return GetStorageBufferAccessor(operation.Index, offsetExpr, context.Config.Stage);
|
||||
}
|
||||
|
||||
public static string StoreGlobal(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
IAstNode src1 = operation.GetSource(0);
|
||||
IAstNode src2 = operation.GetSource(1);
|
||||
IAstNode src3 = operation.GetSource(2);
|
||||
|
||||
string addrLowExpr = GetSoureExpr(context, src1, GetSrcVarType(operation.Inst, 0));
|
||||
string addrHighExpr = GetSoureExpr(context, src2, GetSrcVarType(operation.Inst, 1));
|
||||
string valueExpr = GetSoureExpr(context, src3, GetSrcVarType(operation.Inst, 2));
|
||||
string indexExpr = GetSoureExpr(context, src1, GetSrcVarType(operation.Inst, 0));
|
||||
string offsetExpr = GetSoureExpr(context, src2, GetSrcVarType(operation.Inst, 1));
|
||||
|
||||
context.AppendLine($"{DefaultNames.GmemOffsetName} = {HelperFunctionNames.GetStorageBuffer}({addrLowExpr}, {addrHighExpr});");
|
||||
|
||||
string sb = GetStorageBufferAccessor($"{DefaultNames.GmemOffsetName}.x", $"{DefaultNames.GmemOffsetName}.y", context.Config.Stage);
|
||||
|
||||
return $"{sb} = {valueExpr}";
|
||||
return GetStorageBufferAccessor(indexExpr, offsetExpr, context.Config.Stage);
|
||||
}
|
||||
|
||||
public static string StoreLocal(CodeGenContext context, AstOperation operation)
|
||||
@ -205,14 +177,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
{
|
||||
IAstNode src1 = operation.GetSource(0);
|
||||
IAstNode src2 = operation.GetSource(1);
|
||||
IAstNode src3 = operation.GetSource(2);
|
||||
|
||||
string offsetExpr = GetSoureExpr(context, src1, GetSrcVarType(operation.Inst, 0));
|
||||
string indexExpr = GetSoureExpr(context, src1, GetSrcVarType(operation.Inst, 0));
|
||||
string offsetExpr = GetSoureExpr(context, src2, GetSrcVarType(operation.Inst, 1));
|
||||
|
||||
VariableType srcType = OperandManager.GetNodeDestType(src2);
|
||||
VariableType srcType = OperandManager.GetNodeDestType(src3);
|
||||
|
||||
string src = TypeConversion.ReinterpretCast(context, src2, srcType, VariableType.U32);
|
||||
string src = TypeConversion.ReinterpretCast(context, src3, srcType, VariableType.U32);
|
||||
|
||||
string sb = GetStorageBufferAccessor(operation.Index, offsetExpr, context.Config.Stage);
|
||||
string sb = GetStorageBufferAccessor(indexExpr, offsetExpr, context.Config.Stage);
|
||||
|
||||
return $"{sb} = {src}";
|
||||
}
|
||||
@ -489,27 +463,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
return $"{sbName}[{slotExpr}].{DefaultNames.DataName}[{offsetExpr}]";
|
||||
}
|
||||
|
||||
private static string GetStorageBufferAccessor(int slot, string offsetExpr, ShaderStage stage)
|
||||
{
|
||||
string sbName = OperandManager.GetShaderStagePrefix(stage);
|
||||
|
||||
sbName += "_" + DefaultNames.StorageNamePrefix;
|
||||
|
||||
string mask = NumberFormatter.FormatUint(~(64u - 1));
|
||||
|
||||
// Subtract the base address of the global memory, to get the
|
||||
// storage buffer offset. The mask is used to keep the lower bits,
|
||||
// since the bound storage buffer must match the host alignment
|
||||
// restrictions.
|
||||
int ubOffset = GlobalToStorage.GetStorageCbOffset(stage, slot);
|
||||
|
||||
string ubName = OperandManager.GetConstantBufferName(0, ubOffset, stage);
|
||||
|
||||
offsetExpr = $"{offsetExpr} - int((floatBitsToUint({ubName}) & {mask}) >> 2)";
|
||||
|
||||
return $"{sbName}[{NumberFormatter.FormatInt(slot)}].{DefaultNames.DataName}[{offsetExpr}]";
|
||||
}
|
||||
|
||||
private static string GetMask(int index)
|
||||
{
|
||||
return '.' + "rgba".Substring(index, 1);
|
||||
|
@ -11,15 +11,17 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
OpBinaryCom = Op | 2 | Commutative,
|
||||
OpTernary = Op | 3,
|
||||
|
||||
AtomicBinary = CallBinary | Atomic,
|
||||
AtomicTernary = CallTernary | Atomic,
|
||||
|
||||
CallNullary = Call | 0,
|
||||
CallUnary = Call | 1,
|
||||
CallBinary = Call | 2,
|
||||
CallTernary = Call | 3,
|
||||
CallQuaternary = Call | 4,
|
||||
|
||||
// The atomic instructions have one extra operand,
|
||||
// for the storage slot and offset pair.
|
||||
AtomicBinary = Call | Atomic | 3,
|
||||
AtomicTernary = Call | Atomic | 4,
|
||||
|
||||
Commutative = 1 << 8,
|
||||
Op = 1 << 9,
|
||||
Call = 1 << 10,
|
||||
|
Reference in New Issue
Block a user