| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788 |
- using Ryujinx.Graphics.Shader.Decoders;
- using Ryujinx.Graphics.Shader.IntermediateRepresentation;
- using Ryujinx.Graphics.Shader.Translation;
- using System.Collections.Generic;
- using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
- using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
- namespace Ryujinx.Graphics.Shader.Instructions
- {
- static partial class InstEmit
- {
- public static void SuatomB(EmitterContext context)
- {
- InstSuatomB op = context.GetOp<InstSuatomB>();
- EmitSuatom(
- context,
- op.Dim,
- op.Op,
- op.Size,
- 0,
- op.SrcA,
- op.SrcB,
- op.SrcC,
- op.Dest,
- op.Ba,
- isBindless: true,
- compareAndSwap: false);
- }
- public static void Suatom(EmitterContext context)
- {
- InstSuatom op = context.GetOp<InstSuatom>();
- EmitSuatom(
- context,
- op.Dim,
- op.Op,
- op.Size,
- op.TidB,
- op.SrcA,
- op.SrcB,
- 0,
- op.Dest,
- op.Ba,
- isBindless: false,
- compareAndSwap: false);
- }
- public static void SuatomB2(EmitterContext context)
- {
- InstSuatomB2 op = context.GetOp<InstSuatomB2>();
- EmitSuatom(
- context,
- op.Dim,
- op.Op,
- op.Size,
- 0,
- op.SrcA,
- op.SrcB,
- op.SrcC,
- op.Dest,
- op.Ba,
- isBindless: true,
- compareAndSwap: false);
- }
- public static void SuatomCasB(EmitterContext context)
- {
- InstSuatomCasB op = context.GetOp<InstSuatomCasB>();
- EmitSuatom(
- context,
- op.Dim,
- 0,
- op.Size,
- 0,
- op.SrcA,
- op.SrcB,
- op.SrcC,
- op.Dest,
- op.Ba,
- isBindless: true,
- compareAndSwap: true);
- }
- public static void SuatomCas(EmitterContext context)
- {
- InstSuatomCas op = context.GetOp<InstSuatomCas>();
- EmitSuatom(
- context,
- op.Dim,
- 0,
- op.Size,
- op.TidB,
- op.SrcA,
- op.SrcB,
- 0,
- op.Dest,
- op.Ba,
- isBindless: false,
- compareAndSwap: true);
- }
- public static void SuldDB(EmitterContext context)
- {
- InstSuldDB op = context.GetOp<InstSuldDB>();
- EmitSuld(context, op.CacheOp, op.Dim, op.Size, 0, 0, op.SrcA, op.Dest, op.SrcC, useComponents: false, op.Ba, isBindless: true);
- }
- public static void SuldD(EmitterContext context)
- {
- InstSuldD op = context.GetOp<InstSuldD>();
- EmitSuld(context, op.CacheOp, op.Dim, op.Size, op.TidB, 0, op.SrcA, op.Dest, 0, useComponents: false, op.Ba, isBindless: false);
- }
- public static void SuldB(EmitterContext context)
- {
- InstSuldB op = context.GetOp<InstSuldB>();
- EmitSuld(context, op.CacheOp, op.Dim, 0, 0, op.Rgba, op.SrcA, op.Dest, 0, useComponents: true, false, isBindless: true);
- }
- public static void Suld(EmitterContext context)
- {
- InstSuld op = context.GetOp<InstSuld>();
- EmitSuld(context, op.CacheOp, op.Dim, 0, op.TidB, op.Rgba, op.SrcA, op.Dest, 0, useComponents: true, false, isBindless: false);
- }
- public static void SuredB(EmitterContext context)
- {
- InstSuredB op = context.GetOp<InstSuredB>();
- EmitSured(context, op.Dim, op.Op, op.Size, 0, op.SrcA, op.Dest, op.SrcC, op.Ba, isBindless: true);
- }
- public static void Sured(EmitterContext context)
- {
- InstSured op = context.GetOp<InstSured>();
- EmitSured(context, op.Dim, op.Op, op.Size, op.TidB, op.SrcA, op.Dest, 0, op.Ba, isBindless: false);
- }
- public static void SustDB(EmitterContext context)
- {
- InstSustDB op = context.GetOp<InstSustDB>();
- EmitSust(context, op.CacheOp, op.Dim, op.Size, 0, 0, op.SrcA, op.Dest, op.SrcC, useComponents: false, op.Ba, isBindless: true);
- }
- public static void SustD(EmitterContext context)
- {
- InstSustD op = context.GetOp<InstSustD>();
- EmitSust(context, op.CacheOp, op.Dim, op.Size, op.TidB, 0, op.SrcA, op.Dest, 0, useComponents: false, op.Ba, isBindless: false);
- }
- public static void SustB(EmitterContext context)
- {
- InstSustB op = context.GetOp<InstSustB>();
- EmitSust(context, op.CacheOp, op.Dim, 0, 0, op.Rgba, op.SrcA, op.Dest, op.SrcC, useComponents: true, false, isBindless: true);
- }
- public static void Sust(EmitterContext context)
- {
- InstSust op = context.GetOp<InstSust>();
- EmitSust(context, op.CacheOp, op.Dim, 0, op.TidB, op.Rgba, op.SrcA, op.Dest, 0, useComponents: true, false, isBindless: false);
- }
- private static void EmitSuatom(
- EmitterContext context,
- SuDim dimensions,
- SuatomOp atomicOp,
- SuatomSize size,
- int imm,
- int srcA,
- int srcB,
- int srcC,
- int dest,
- bool byteAddress,
- bool isBindless,
- bool compareAndSwap)
- {
- SamplerType type = ConvertSamplerType(dimensions);
- if (type == SamplerType.None)
- {
- context.Config.GpuAccessor.Log("Invalid image atomic sampler type.");
- return;
- }
- Operand Ra()
- {
- if (srcA > RegisterConsts.RegisterZeroIndex)
- {
- return Const(0);
- }
- return context.Copy(Register(srcA++, RegisterType.Gpr));
- }
- Operand Rb()
- {
- if (srcB > RegisterConsts.RegisterZeroIndex)
- {
- return Const(0);
- }
- return context.Copy(Register(srcB++, RegisterType.Gpr));
- }
- Operand GetDest()
- {
- if (dest >= RegisterConsts.RegisterZeroIndex)
- {
- return null;
- }
- return Register(dest++, RegisterType.Gpr);
- }
- List<Operand> sourcesList = new List<Operand>();
- if (isBindless)
- {
- sourcesList.Add(context.Copy(GetSrcReg(context, srcC)));
- }
- int coordsCount = type.GetDimensions();
- for (int index = 0; index < coordsCount; index++)
- {
- sourcesList.Add(Ra());
- }
- if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D)
- {
- sourcesList.Add(Const(0));
- type &= ~SamplerType.Mask;
- type |= SamplerType.Texture2D;
- }
- if (type.HasFlag(SamplerType.Array))
- {
- sourcesList.Add(Ra());
- type |= SamplerType.Array;
- }
- if (byteAddress)
- {
- int xIndex = isBindless ? 1 : 0;
- sourcesList[xIndex] = context.ShiftRightS32(sourcesList[xIndex], Const(GetComponentSizeInBytesLog2(size)));
- }
- // TODO: FP and 64-bit formats.
- TextureFormat format = size == SuatomSize.Sd32 || size == SuatomSize.Sd64
- ? (isBindless ? TextureFormat.Unknown : context.Config.GetTextureFormatAtomic(imm))
- : GetTextureFormat(size);
- if (compareAndSwap)
- {
- sourcesList.Add(Rb());
- }
- sourcesList.Add(Rb());
- Operand[] sources = sourcesList.ToArray();
- TextureFlags flags = compareAndSwap ? TextureFlags.CAS : GetAtomicOpFlags(atomicOp);
- if (isBindless)
- {
- flags |= TextureFlags.Bindless;
- }
- TextureOperation operation = context.CreateTextureOperation(
- Instruction.ImageAtomic,
- type,
- format,
- flags,
- imm,
- 0,
- GetDest(),
- sources);
- context.Add(operation);
- }
- private static void EmitSuld(
- EmitterContext context,
- CacheOpLd cacheOp,
- SuDim dimensions,
- SuSize size,
- int imm,
- SuRgba componentMask,
- int srcA,
- int srcB,
- int srcC,
- bool useComponents,
- bool byteAddress,
- bool isBindless)
- {
- context.Config.SetUsedFeature(FeatureFlags.IntegerSampling);
- SamplerType type = ConvertSamplerType(dimensions);
- if (type == SamplerType.None)
- {
- context.Config.GpuAccessor.Log("Invalid image store sampler type.");
- return;
- }
- Operand Ra()
- {
- if (srcA > RegisterConsts.RegisterZeroIndex)
- {
- return Const(0);
- }
- return context.Copy(Register(srcA++, RegisterType.Gpr));
- }
- List<Operand> sourcesList = new List<Operand>();
- if (isBindless)
- {
- sourcesList.Add(context.Copy(Register(srcC, RegisterType.Gpr)));
- }
- int coordsCount = type.GetDimensions();
- for (int index = 0; index < coordsCount; index++)
- {
- sourcesList.Add(Ra());
- }
- if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D)
- {
- sourcesList.Add(Const(0));
- type &= ~SamplerType.Mask;
- type |= SamplerType.Texture2D;
- }
- if (type.HasFlag(SamplerType.Array))
- {
- sourcesList.Add(Ra());
- }
- Operand[] sources = sourcesList.ToArray();
- int handle = imm;
- TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None;
- if (cacheOp == CacheOpLd.Cg)
- {
- flags |= TextureFlags.Coherent;
- }
- if (useComponents)
- {
- for (int compMask = (int)componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
- {
- if ((compMask & 1) == 0)
- {
- continue;
- }
- if (srcB == RegisterConsts.RegisterZeroIndex)
- {
- break;
- }
- Operand rd = Register(srcB++, RegisterType.Gpr);
- TextureOperation operation = context.CreateTextureOperation(
- Instruction.ImageLoad,
- type,
- flags,
- handle,
- compIndex,
- rd,
- sources);
- if (!isBindless)
- {
- operation.Format = context.Config.GetTextureFormat(handle);
- }
- context.Add(operation);
- }
- }
- else
- {
- if (byteAddress)
- {
- int xIndex = isBindless ? 1 : 0;
- sources[xIndex] = context.ShiftRightS32(sources[xIndex], Const(GetComponentSizeInBytesLog2(size)));
- }
- int components = GetComponents(size);
- for (int compIndex = 0; compIndex < components; compIndex++)
- {
- if (srcB == RegisterConsts.RegisterZeroIndex)
- {
- break;
- }
- Operand rd = Register(srcB++, RegisterType.Gpr);
- TextureOperation operation = context.CreateTextureOperation(
- Instruction.ImageLoad,
- type,
- GetTextureFormat(size),
- flags,
- handle,
- compIndex,
- rd,
- sources);
- context.Add(operation);
- switch (size)
- {
- case SuSize.U8: context.Copy(rd, ZeroExtendTo32(context, rd, 8)); break;
- case SuSize.U16: context.Copy(rd, ZeroExtendTo32(context, rd, 16)); break;
- case SuSize.S8: context.Copy(rd, SignExtendTo32(context, rd, 8)); break;
- case SuSize.S16: context.Copy(rd, SignExtendTo32(context, rd, 16)); break;
- }
- }
- }
- }
- private static void EmitSured(
- EmitterContext context,
- SuDim dimensions,
- RedOp atomicOp,
- SuatomSize size,
- int imm,
- int srcA,
- int srcB,
- int srcC,
- bool byteAddress,
- bool isBindless)
- {
- SamplerType type = ConvertSamplerType(dimensions);
- if (type == SamplerType.None)
- {
- context.Config.GpuAccessor.Log("Invalid image reduction sampler type.");
- return;
- }
- Operand Ra()
- {
- if (srcA > RegisterConsts.RegisterZeroIndex)
- {
- return Const(0);
- }
- return context.Copy(Register(srcA++, RegisterType.Gpr));
- }
- Operand Rb()
- {
- if (srcB > RegisterConsts.RegisterZeroIndex)
- {
- return Const(0);
- }
- return context.Copy(Register(srcB++, RegisterType.Gpr));
- }
- List<Operand> sourcesList = new List<Operand>();
- if (isBindless)
- {
- sourcesList.Add(context.Copy(GetSrcReg(context, srcC)));
- }
- int coordsCount = type.GetDimensions();
- for (int index = 0; index < coordsCount; index++)
- {
- sourcesList.Add(Ra());
- }
- if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D)
- {
- sourcesList.Add(Const(0));
- type &= ~SamplerType.Mask;
- type |= SamplerType.Texture2D;
- }
- if (type.HasFlag(SamplerType.Array))
- {
- sourcesList.Add(Ra());
- type |= SamplerType.Array;
- }
- if (byteAddress)
- {
- int xIndex = isBindless ? 1 : 0;
- sourcesList[xIndex] = context.ShiftRightS32(sourcesList[xIndex], Const(GetComponentSizeInBytesLog2(size)));
- }
- // TODO: FP and 64-bit formats.
- TextureFormat format = size == SuatomSize.Sd32 || size == SuatomSize.Sd64
- ? (isBindless ? TextureFormat.Unknown : context.Config.GetTextureFormatAtomic(imm))
- : GetTextureFormat(size);
- sourcesList.Add(Rb());
- Operand[] sources = sourcesList.ToArray();
- TextureFlags flags = GetAtomicOpFlags((SuatomOp)atomicOp);
- if (isBindless)
- {
- flags |= TextureFlags.Bindless;
- }
- TextureOperation operation = context.CreateTextureOperation(
- Instruction.ImageAtomic,
- type,
- format,
- flags,
- imm,
- 0,
- null,
- sources);
- context.Add(operation);
- }
- private static void EmitSust(
- EmitterContext context,
- CacheOpSt cacheOp,
- SuDim dimensions,
- SuSize size,
- int imm,
- SuRgba componentMask,
- int srcA,
- int srcB,
- int srcC,
- bool useComponents,
- bool byteAddress,
- bool isBindless)
- {
- SamplerType type = ConvertSamplerType(dimensions);
- if (type == SamplerType.None)
- {
- context.Config.GpuAccessor.Log("Invalid image store sampler type.");
- return;
- }
- Operand Ra()
- {
- if (srcA > RegisterConsts.RegisterZeroIndex)
- {
- return Const(0);
- }
- return context.Copy(Register(srcA++, RegisterType.Gpr));
- }
- Operand Rb()
- {
- if (srcB > RegisterConsts.RegisterZeroIndex)
- {
- return Const(0);
- }
- return context.Copy(Register(srcB++, RegisterType.Gpr));
- }
- List<Operand> sourcesList = new List<Operand>();
- if (isBindless)
- {
- sourcesList.Add(context.Copy(Register(srcC, RegisterType.Gpr)));
- }
- int coordsCount = type.GetDimensions();
- for (int index = 0; index < coordsCount; index++)
- {
- sourcesList.Add(Ra());
- }
- if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D)
- {
- sourcesList.Add(Const(0));
- type &= ~SamplerType.Mask;
- type |= SamplerType.Texture2D;
- }
- if (type.HasFlag(SamplerType.Array))
- {
- sourcesList.Add(Ra());
- }
- TextureFormat format = TextureFormat.Unknown;
- if (useComponents)
- {
- for (int compMask = (int)componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
- {
- if ((compMask & 1) != 0)
- {
- sourcesList.Add(Rb());
- }
- }
- if (!isBindless)
- {
- format = context.Config.GetTextureFormat(imm);
- }
- }
- else
- {
- if (byteAddress)
- {
- int xIndex = isBindless ? 1 : 0;
- sourcesList[xIndex] = context.ShiftRightS32(sourcesList[xIndex], Const(GetComponentSizeInBytesLog2(size)));
- }
- int components = GetComponents(size);
- for (int compIndex = 0; compIndex < components; compIndex++)
- {
- sourcesList.Add(Rb());
- }
- format = GetTextureFormat(size);
- }
- Operand[] sources = sourcesList.ToArray();
- int handle = imm;
- TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None;
- if (cacheOp == CacheOpSt.Cg)
- {
- flags |= TextureFlags.Coherent;
- }
- TextureOperation operation = context.CreateTextureOperation(
- Instruction.ImageStore,
- type,
- format,
- flags,
- handle,
- 0,
- null,
- sources);
- context.Add(operation);
- }
- private static int GetComponentSizeInBytesLog2(SuatomSize size)
- {
- return size switch
- {
- SuatomSize.U32 => 2,
- SuatomSize.S32 => 2,
- SuatomSize.U64 => 3,
- SuatomSize.F32FtzRn => 2,
- SuatomSize.F16x2FtzRn => 2,
- SuatomSize.S64 => 3,
- SuatomSize.Sd32 => 2,
- SuatomSize.Sd64 => 3,
- _ => 2
- };
- }
- private static TextureFormat GetTextureFormat(SuatomSize size)
- {
- return size switch
- {
- SuatomSize.U32 => TextureFormat.R32Uint,
- SuatomSize.S32 => TextureFormat.R32Sint,
- SuatomSize.U64 => TextureFormat.R32G32Uint,
- SuatomSize.F32FtzRn => TextureFormat.R32Float,
- SuatomSize.F16x2FtzRn => TextureFormat.R16G16Float,
- SuatomSize.S64 => TextureFormat.R32G32Uint,
- SuatomSize.Sd32 => TextureFormat.R32Uint,
- SuatomSize.Sd64 => TextureFormat.R32G32Uint,
- _ => TextureFormat.R32Uint
- };
- }
- private static TextureFlags GetAtomicOpFlags(SuatomOp op)
- {
- return op switch
- {
- SuatomOp.Add => TextureFlags.Add,
- SuatomOp.Min => TextureFlags.Minimum,
- SuatomOp.Max => TextureFlags.Maximum,
- SuatomOp.Inc => TextureFlags.Increment,
- SuatomOp.Dec => TextureFlags.Decrement,
- SuatomOp.And => TextureFlags.BitwiseAnd,
- SuatomOp.Or => TextureFlags.BitwiseOr,
- SuatomOp.Xor => TextureFlags.BitwiseXor,
- SuatomOp.Exch => TextureFlags.Swap,
- _ => TextureFlags.Add
- };
- }
- private static int GetComponents(SuSize size)
- {
- return size switch
- {
- SuSize.B64 => 2,
- SuSize.B128 => 4,
- SuSize.UB128 => 4,
- _ => 1
- };
- }
- private static int GetComponentSizeInBytesLog2(SuSize size)
- {
- return size switch
- {
- SuSize.U8 => 0,
- SuSize.S8 => 0,
- SuSize.U16 => 1,
- SuSize.S16 => 1,
- SuSize.B32 => 2,
- SuSize.B64 => 3,
- SuSize.B128 => 4,
- SuSize.UB128 => 4,
- _ => 2
- };
- }
- private static TextureFormat GetTextureFormat(SuSize size)
- {
- return size switch
- {
- SuSize.U8 => TextureFormat.R8Uint,
- SuSize.S8 => TextureFormat.R8Sint,
- SuSize.U16 => TextureFormat.R16Uint,
- SuSize.S16 => TextureFormat.R16Sint,
- SuSize.B32 => TextureFormat.R32Uint,
- SuSize.B64 => TextureFormat.R32G32Uint,
- SuSize.B128 => TextureFormat.R32G32B32A32Uint,
- SuSize.UB128 => TextureFormat.R32G32B32A32Uint,
- _ => TextureFormat.R32Uint
- };
- }
- private static SamplerType ConvertSamplerType(SuDim target)
- {
- return target switch
- {
- SuDim._1d => SamplerType.Texture1D,
- SuDim._1dBuffer => SamplerType.TextureBuffer,
- SuDim._1dArray => SamplerType.Texture1D | SamplerType.Array,
- SuDim._2d => SamplerType.Texture2D,
- SuDim._2dArray => SamplerType.Texture2D | SamplerType.Array,
- SuDim._3d => SamplerType.Texture3D,
- _ => SamplerType.None
- };
- }
- }
- }
|