Stop identifying shader textures with handle and cbuf, use binding instead (#5266)

* Stop identifying shader textures with handle and cbuf, use binding instead

* Remove now unused code

* Consider image operations as having accurate type information too

I don't know why that was not the case before

* Fix missing unscale on InsertCoordNormalization, stop calling SetUsageFlagsForTextureQuery when not needed

* Shader cache version bump

* Change get texture methods to return descriptors created from ResourceManager state

 This is required to ensure that reserved textures and images will not be bound as a guest texture/image

* Fix BindlessElimination.SetHandle inserting coords at the wrong place
This commit is contained in:
gdkchan 2023-07-03 14:29:27 -03:00 committed by GitHub
parent 3b46bb73f7
commit 1c7a90ef35
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 656 additions and 659 deletions

View file

@ -218,7 +218,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
return context.Copy(Register(srcB++, RegisterType.Gpr));
}
Operand destOperand = dest != RegisterConsts.RegisterZeroIndex ? Register(dest, RegisterType.Gpr) : null;
Operand d = dest != RegisterConsts.RegisterZeroIndex ? Register(dest, RegisterType.Gpr) : null;
List<Operand> sourcesList = new();
@ -277,17 +277,17 @@ namespace Ryujinx.Graphics.Shader.Instructions
flags |= TextureFlags.Bindless;
}
TextureOperation operation = context.CreateTextureOperation(
int binding = isBindless ? 0 : context.Config.ResourceManager.GetTextureOrImageBinding(
Instruction.ImageAtomic,
type,
format,
flags,
imm,
0,
new[] { destOperand },
sources);
TextureOperation.DefaultCbufSlot,
imm);
context.Add(operation);
Operand res = context.ImageAtomic(type, format, flags, binding, sources);
context.Copy(d, res);
}
private static void EmitSuld(
@ -383,21 +383,17 @@ namespace Ryujinx.Graphics.Shader.Instructions
Array.Resize(ref dests, outputIndex);
}
TextureOperation operation = context.CreateTextureOperation(
TextureFormat format = isBindless ? TextureFormat.Unknown : context.Config.GetTextureFormat(handle);
int binding = isBindless ? 0 : context.Config.ResourceManager.GetTextureOrImageBinding(
Instruction.ImageLoad,
type,
format,
flags,
handle,
(int)componentMask,
dests,
sources);
TextureOperation.DefaultCbufSlot,
handle);
if (!isBindless)
{
operation.Format = context.Config.GetTextureFormat(handle);
}
context.Add(operation);
context.ImageLoad(type, format, flags, binding, (int)componentMask, dests, sources);
}
else
{
@ -430,17 +426,17 @@ namespace Ryujinx.Graphics.Shader.Instructions
Array.Resize(ref dests, outputIndex);
}
TextureOperation operation = context.CreateTextureOperation(
TextureFormat format = GetTextureFormat(size);
int binding = isBindless ? 0 : context.Config.ResourceManager.GetTextureOrImageBinding(
Instruction.ImageLoad,
type,
GetTextureFormat(size),
format,
flags,
handle,
compMask,
dests,
sources);
TextureOperation.DefaultCbufSlot,
handle);
context.Add(operation);
context.ImageLoad(type, format, flags, binding, compMask, dests, sources);
switch (size)
{
@ -552,17 +548,15 @@ namespace Ryujinx.Graphics.Shader.Instructions
flags |= TextureFlags.Bindless;
}
TextureOperation operation = context.CreateTextureOperation(
int binding = isBindless ? 0 : context.Config.ResourceManager.GetTextureOrImageBinding(
Instruction.ImageAtomic,
type,
format,
flags,
imm,
0,
null,
sources);
TextureOperation.DefaultCbufSlot,
imm);
context.Add(operation);
context.ImageAtomic(type, format, flags, binding, sources);
}
private static void EmitSust(
@ -681,17 +675,15 @@ namespace Ryujinx.Graphics.Shader.Instructions
flags |= TextureFlags.Coherent;
}
TextureOperation operation = context.CreateTextureOperation(
int binding = isBindless ? 0 : context.Config.ResourceManager.GetTextureOrImageBinding(
Instruction.ImageStore,
type,
format,
flags,
handle,
0,
null,
sources);
TextureOperation.DefaultCbufSlot,
handle);
context.Add(operation);
context.ImageStore(type, format, flags, binding, sources);
}
private static int GetComponentSizeInBytesLog2(SuatomSize size)

View file

@ -324,16 +324,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
int handle = !isBindless ? imm : 0;
TextureOperation operation = context.CreateTextureOperation(
Instruction.TextureSample,
type,
flags,
handle,
componentMask,
dests,
sources);
context.Add(operation);
EmitTextureSample(context, type, flags, handle, componentMask, dests, sources);
}
private static void EmitTexs(
@ -657,16 +648,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
Array.Resize(ref dests, outputIndex);
}
TextureOperation operation = context.CreateTextureOperation(
Instruction.TextureSample,
type,
flags,
handle,
componentMask,
dests,
sources);
context.Add(operation);
EmitTextureSample(context, type, flags, handle, componentMask, dests, sources);
if (isF16)
{
@ -812,18 +794,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
Array.Resize(ref dests, outputIndex);
}
int handle = imm;
TextureOperation operation = context.CreateTextureOperation(
Instruction.TextureSample,
type,
flags,
handle,
componentMask,
dests,
sources);
context.Add(operation);
EmitTextureSample(context, type, flags, imm, componentMask, dests, sources);
}
private static void EmitTmml(
@ -913,15 +884,21 @@ namespace Ryujinx.Graphics.Shader.Instructions
return Register(dest++, RegisterType.Gpr);
}
int handle = imm;
int binding = isBindless ? 0 : context.Config.ResourceManager.GetTextureOrImageBinding(
Instruction.Lod,
type,
TextureFormat.Unknown,
flags,
TextureOperation.DefaultCbufSlot,
imm);
for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
{
if ((compMask & 1) != 0)
{
Operand destOperand = GetDest();
Operand d = GetDest();
if (destOperand == null)
if (d == null)
{
break;
}
@ -930,28 +907,18 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (compIndex >= 2)
{
context.Add(new CommentNode("Unsupported component z or w found"));
context.Copy(destOperand, Const(0));
context.Copy(d, Const(0));
}
else
{
Operand tempDest = Local();
// The instruction component order is the inverse of GLSL's.
Operand res = context.Lod(type, flags, binding, compIndex ^ 1, sources);
TextureOperation operation = context.CreateTextureOperation(
Instruction.Lod,
type,
flags,
handle,
compIndex ^ 1, // The instruction component order is the inverse of GLSL's.
new[] { tempDest },
sources);
res = context.FPMultiply(res, ConstF(256.0f));
context.Add(operation);
Operand fixedPointValue = context.FP32ConvertToS32(res);
tempDest = context.FPMultiply(tempDest, ConstF(256.0f));
Operand fixedPointValue = context.FP32ConvertToS32(tempDest);
context.Copy(destOperand, fixedPointValue);
context.Copy(d, fixedPointValue);
}
}
}
@ -1081,18 +1048,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
Array.Resize(ref dests, outputIndex);
}
int handle = imm;
TextureOperation operation = context.CreateTextureOperation(
Instruction.TextureSample,
type,
flags,
handle,
componentMask,
dests,
sources);
context.Add(operation);
EmitTextureSample(context, type, flags, imm, componentMask, dests, sources);
}
private static void EmitTxq(
@ -1111,10 +1067,6 @@ namespace Ryujinx.Graphics.Shader.Instructions
context.Config.SetUsedFeature(FeatureFlags.IntegerSampling);
// TODO: Validate and use query.
Instruction inst = Instruction.TextureSize;
TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None;
Operand Ra()
{
if (srcA > RegisterConsts.RegisterZeroIndex)
@ -1157,31 +1109,55 @@ namespace Ryujinx.Graphics.Shader.Instructions
type = context.Config.GpuAccessor.QuerySamplerType(imm);
}
TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None;
int binding = isBindless ? 0 : context.Config.ResourceManager.GetTextureOrImageBinding(
Instruction.TextureSize,
type,
TextureFormat.Unknown,
flags,
TextureOperation.DefaultCbufSlot,
imm);
for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
{
if ((compMask & 1) != 0)
{
Operand destOperand = GetDest();
Operand d = GetDest();
if (destOperand == null)
if (d == null)
{
break;
}
TextureOperation operation = context.CreateTextureOperation(
inst,
type,
flags,
imm,
compIndex,
new[] { destOperand },
sources);
// TODO: Validate and use query parameter.
Operand res = context.TextureSize(type, flags, binding, compIndex, sources);
context.Add(operation);
context.Copy(d, res);
}
}
}
private static void EmitTextureSample(
EmitterContext context,
SamplerType type,
TextureFlags flags,
int handle,
int componentMask,
Operand[] dests,
Operand[] sources)
{
int binding = flags.HasFlag(TextureFlags.Bindless) ? 0 : context.Config.ResourceManager.GetTextureOrImageBinding(
Instruction.TextureSample,
type,
TextureFormat.Unknown,
flags,
TextureOperation.DefaultCbufSlot,
handle);
context.TextureSample(type, flags, binding, componentMask, dests, sources);
}
private static SamplerType ConvertSamplerType(TexDim dimensions)
{
return dimensions switch