Implement textureSamples texture query shader instruction (#5750)
* Implement textureSamples texture query shader instruction * Shader cache version bump
This commit is contained in:
parent
8b2625b0be
commit
a2a97e1b11
12 changed files with 186 additions and 58 deletions
|
@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
||||||
private const ushort FileFormatVersionMajor = 1;
|
private const ushort FileFormatVersionMajor = 1;
|
||||||
private const ushort FileFormatVersionMinor = 2;
|
private const ushort FileFormatVersionMinor = 2;
|
||||||
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
|
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
|
||||||
private const uint CodeGenVersion = 5682;
|
private const uint CodeGenVersion = 5750;
|
||||||
|
|
||||||
private const string SharedTocFileName = "shared.toc";
|
private const string SharedTocFileName = "shared.toc";
|
||||||
private const string SharedDataFileName = "shared.data";
|
private const string SharedDataFileName = "shared.data";
|
||||||
|
|
|
@ -184,8 +184,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||||
case Instruction.TextureSample:
|
case Instruction.TextureSample:
|
||||||
return TextureSample(context, operation);
|
return TextureSample(context, operation);
|
||||||
|
|
||||||
case Instruction.TextureSize:
|
case Instruction.TextureQuerySamples:
|
||||||
return TextureSize(context, operation);
|
return TextureQuerySamples(context, operation);
|
||||||
|
|
||||||
|
case Instruction.TextureQuerySize:
|
||||||
|
return TextureQuerySize(context, operation);
|
||||||
|
|
||||||
case Instruction.UnpackDouble2x32:
|
case Instruction.UnpackDouble2x32:
|
||||||
return UnpackDouble2x32(context, operation);
|
return UnpackDouble2x32(context, operation);
|
||||||
|
|
|
@ -118,7 +118,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||||
Add(Instruction.Subtract, InstType.OpBinary, "-", 2);
|
Add(Instruction.Subtract, InstType.OpBinary, "-", 2);
|
||||||
Add(Instruction.SwizzleAdd, InstType.CallTernary, HelperFunctionNames.SwizzleAdd);
|
Add(Instruction.SwizzleAdd, InstType.CallTernary, HelperFunctionNames.SwizzleAdd);
|
||||||
Add(Instruction.TextureSample, InstType.Special);
|
Add(Instruction.TextureSample, InstType.Special);
|
||||||
Add(Instruction.TextureSize, InstType.Special);
|
Add(Instruction.TextureQuerySamples, InstType.Special);
|
||||||
|
Add(Instruction.TextureQuerySize, InstType.Special);
|
||||||
Add(Instruction.Truncate, InstType.CallUnary, "trunc");
|
Add(Instruction.Truncate, InstType.CallUnary, "trunc");
|
||||||
Add(Instruction.UnpackDouble2x32, InstType.Special);
|
Add(Instruction.UnpackDouble2x32, InstType.Special);
|
||||||
Add(Instruction.UnpackHalf2x16, InstType.Special);
|
Add(Instruction.UnpackHalf2x16, InstType.Special);
|
||||||
|
|
|
@ -517,7 +517,33 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||||
return texCall;
|
return texCall;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string TextureSize(CodeGenContext context, AstOperation operation)
|
public static string TextureQuerySamples(CodeGenContext context, AstOperation operation)
|
||||||
|
{
|
||||||
|
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||||
|
|
||||||
|
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||||
|
|
||||||
|
// TODO: Bindless texture support. For now we just return 0.
|
||||||
|
if (isBindless)
|
||||||
|
{
|
||||||
|
return NumberFormatter.FormatInt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||||
|
|
||||||
|
string indexExpr = null;
|
||||||
|
|
||||||
|
if (isIndexed)
|
||||||
|
{
|
||||||
|
indexExpr = GetSoureExpr(context, texOp.GetSource(0), AggregateType.S32);
|
||||||
|
}
|
||||||
|
|
||||||
|
string samplerName = GetSamplerName(context.Properties, texOp, indexExpr);
|
||||||
|
|
||||||
|
return $"textureSamples({samplerName})";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string TextureQuerySize(CodeGenContext context, AstOperation operation)
|
||||||
{
|
{
|
||||||
AstTextureOperation texOp = (AstTextureOperation)operation;
|
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||||
|
|
||||||
|
|
|
@ -134,7 +134,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||||
Add(Instruction.Subtract, GenerateSubtract);
|
Add(Instruction.Subtract, GenerateSubtract);
|
||||||
Add(Instruction.SwizzleAdd, GenerateSwizzleAdd);
|
Add(Instruction.SwizzleAdd, GenerateSwizzleAdd);
|
||||||
Add(Instruction.TextureSample, GenerateTextureSample);
|
Add(Instruction.TextureSample, GenerateTextureSample);
|
||||||
Add(Instruction.TextureSize, GenerateTextureSize);
|
Add(Instruction.TextureQuerySamples, GenerateTextureQuerySamples);
|
||||||
|
Add(Instruction.TextureQuerySize, GenerateTextureQuerySize);
|
||||||
Add(Instruction.Truncate, GenerateTruncate);
|
Add(Instruction.Truncate, GenerateTruncate);
|
||||||
Add(Instruction.UnpackDouble2x32, GenerateUnpackDouble2x32);
|
Add(Instruction.UnpackDouble2x32, GenerateUnpackDouble2x32);
|
||||||
Add(Instruction.UnpackHalf2x16, GenerateUnpackHalf2x16);
|
Add(Instruction.UnpackHalf2x16, GenerateUnpackHalf2x16);
|
||||||
|
@ -1492,7 +1493,36 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||||
return new OperationResult(swizzledResultType, result);
|
return new OperationResult(swizzledResultType, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static OperationResult GenerateTextureSize(CodeGenContext context, AstOperation operation)
|
private static OperationResult GenerateTextureQuerySamples(CodeGenContext context, AstOperation operation)
|
||||||
|
{
|
||||||
|
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||||
|
|
||||||
|
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||||
|
|
||||||
|
// TODO: Bindless texture support. For now we just return 0.
|
||||||
|
if (isBindless)
|
||||||
|
{
|
||||||
|
return new OperationResult(AggregateType.S32, context.Constant(context.TypeS32(), 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||||
|
|
||||||
|
if (isIndexed)
|
||||||
|
{
|
||||||
|
context.GetS32(texOp.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
(var imageType, var sampledImageType, var sampledImageVariable) = context.Samplers[texOp.Binding];
|
||||||
|
|
||||||
|
var image = context.Load(sampledImageType, sampledImageVariable);
|
||||||
|
image = context.Image(imageType, image);
|
||||||
|
|
||||||
|
SpvInstruction result = context.ImageQuerySamples(context.TypeS32(), image);
|
||||||
|
|
||||||
|
return new OperationResult(AggregateType.S32, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static OperationResult GenerateTextureQuerySize(CodeGenContext context, AstOperation operation)
|
||||||
{
|
{
|
||||||
AstTextureOperation texOp = (AstTextureOperation)operation;
|
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||||
|
|
||||||
|
|
|
@ -1094,7 +1094,14 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
|
|
||||||
if (isBindless)
|
if (isBindless)
|
||||||
{
|
{
|
||||||
type = (componentMask & 4) != 0 ? SamplerType.Texture3D : SamplerType.Texture2D;
|
if (query == TexQuery.TexHeaderTextureType)
|
||||||
|
{
|
||||||
|
type = SamplerType.Texture2D | SamplerType.Multisample;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
type = (componentMask & 4) != 0 ? SamplerType.Texture3D : SamplerType.Texture2D;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1102,31 +1109,69 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None;
|
TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None;
|
||||||
|
int binding;
|
||||||
|
|
||||||
int binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding(
|
switch (query)
|
||||||
Instruction.TextureSize,
|
|
||||||
type,
|
|
||||||
TextureFormat.Unknown,
|
|
||||||
flags,
|
|
||||||
TextureOperation.DefaultCbufSlot,
|
|
||||||
imm);
|
|
||||||
|
|
||||||
for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
|
|
||||||
{
|
{
|
||||||
if ((compMask & 1) != 0)
|
case TexQuery.TexHeaderDimension:
|
||||||
{
|
binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding(
|
||||||
Operand d = GetDest();
|
Instruction.TextureQuerySize,
|
||||||
|
type,
|
||||||
|
TextureFormat.Unknown,
|
||||||
|
flags,
|
||||||
|
TextureOperation.DefaultCbufSlot,
|
||||||
|
imm);
|
||||||
|
|
||||||
if (d == null)
|
for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
|
||||||
{
|
{
|
||||||
break;
|
if ((compMask & 1) != 0)
|
||||||
|
{
|
||||||
|
Operand d = GetDest();
|
||||||
|
|
||||||
|
if (d == null)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Copy(d, context.TextureQuerySize(type, flags, binding, compIndex, sources));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
// TODO: Validate and use query parameter.
|
case TexQuery.TexHeaderTextureType:
|
||||||
Operand res = context.TextureSize(type, flags, binding, compIndex, sources);
|
binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding(
|
||||||
|
Instruction.TextureQuerySamples,
|
||||||
|
type,
|
||||||
|
TextureFormat.Unknown,
|
||||||
|
flags,
|
||||||
|
TextureOperation.DefaultCbufSlot,
|
||||||
|
imm);
|
||||||
|
|
||||||
context.Copy(d, res);
|
if ((componentMask & 4) != 0)
|
||||||
}
|
{
|
||||||
|
// Skip first 2 components if necessary.
|
||||||
|
if ((componentMask & 1) != 0)
|
||||||
|
{
|
||||||
|
GetDest();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((componentMask & 2) != 0)
|
||||||
|
{
|
||||||
|
GetDest();
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand d = GetDest();
|
||||||
|
|
||||||
|
if (d != null)
|
||||||
|
{
|
||||||
|
context.Copy(d, context.TextureQuerySamples(type, flags, binding, sources));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
context.TranslatorContext.GpuAccessor.Log($"Invalid or unsupported query type \"{query}\".");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
|
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
|
||||||
{
|
{
|
||||||
[Flags]
|
[Flags]
|
||||||
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
|
|
||||||
enum Instruction
|
enum Instruction
|
||||||
{
|
{
|
||||||
Absolute = 1,
|
Absolute = 1,
|
||||||
|
@ -118,7 +116,8 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
|
||||||
Subtract,
|
Subtract,
|
||||||
SwizzleAdd,
|
SwizzleAdd,
|
||||||
TextureSample,
|
TextureSample,
|
||||||
TextureSize,
|
TextureQuerySamples,
|
||||||
|
TextureQuerySize,
|
||||||
Truncate,
|
Truncate,
|
||||||
UnpackDouble2x32,
|
UnpackDouble2x32,
|
||||||
UnpackHalf2x16,
|
UnpackHalf2x16,
|
||||||
|
@ -160,7 +159,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
|
||||||
public static bool IsTextureQuery(this Instruction inst)
|
public static bool IsTextureQuery(this Instruction inst)
|
||||||
{
|
{
|
||||||
inst &= Instruction.Mask;
|
inst &= Instruction.Mask;
|
||||||
return inst == Instruction.Lod || inst == Instruction.TextureSize;
|
return inst == Instruction.Lod || inst == Instruction.TextureQuerySamples || inst == Instruction.TextureQuerySize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,7 +124,8 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||||
Add(Instruction.Subtract, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
|
Add(Instruction.Subtract, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
|
||||||
Add(Instruction.SwizzleAdd, AggregateType.FP32, AggregateType.FP32, AggregateType.FP32, AggregateType.S32);
|
Add(Instruction.SwizzleAdd, AggregateType.FP32, AggregateType.FP32, AggregateType.FP32, AggregateType.S32);
|
||||||
Add(Instruction.TextureSample, AggregateType.FP32);
|
Add(Instruction.TextureSample, AggregateType.FP32);
|
||||||
Add(Instruction.TextureSize, AggregateType.S32, AggregateType.S32, AggregateType.S32);
|
Add(Instruction.TextureQuerySamples, AggregateType.S32, AggregateType.S32);
|
||||||
|
Add(Instruction.TextureQuerySize, AggregateType.S32, AggregateType.S32, AggregateType.S32);
|
||||||
Add(Instruction.Truncate, AggregateType.Scalar, AggregateType.Scalar);
|
Add(Instruction.Truncate, AggregateType.Scalar, AggregateType.Scalar);
|
||||||
Add(Instruction.UnpackDouble2x32, AggregateType.U32, AggregateType.FP64);
|
Add(Instruction.UnpackDouble2x32, AggregateType.U32, AggregateType.FP64);
|
||||||
Add(Instruction.UnpackHalf2x16, AggregateType.FP32, AggregateType.U32);
|
Add(Instruction.UnpackHalf2x16, AggregateType.FP32, AggregateType.U32);
|
||||||
|
|
|
@ -897,7 +897,21 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
context.Add(new TextureOperation(Instruction.TextureSample, type, TextureFormat.Unknown, flags, binding, compMask, dests, sources));
|
context.Add(new TextureOperation(Instruction.TextureSample, type, TextureFormat.Unknown, flags, binding, compMask, dests, sources));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand TextureSize(
|
public static Operand TextureQuerySamples(
|
||||||
|
this EmitterContext context,
|
||||||
|
SamplerType type,
|
||||||
|
TextureFlags flags,
|
||||||
|
int binding,
|
||||||
|
Operand[] sources)
|
||||||
|
{
|
||||||
|
Operand dest = Local();
|
||||||
|
|
||||||
|
context.Add(new TextureOperation(Instruction.TextureQuerySamples, type, TextureFormat.Unknown, flags, binding, 0, new[] { dest }, sources));
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operand TextureQuerySize(
|
||||||
this EmitterContext context,
|
this EmitterContext context,
|
||||||
SamplerType type,
|
SamplerType type,
|
||||||
TextureFlags flags,
|
TextureFlags flags,
|
||||||
|
@ -907,7 +921,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
{
|
{
|
||||||
Operand dest = Local();
|
Operand dest = Local();
|
||||||
|
|
||||||
context.Add(new TextureOperation(Instruction.TextureSize, type, TextureFormat.Unknown, flags, binding, compIndex, new[] { dest }, sources));
|
context.Add(new TextureOperation(Instruction.TextureQuerySize, type, TextureFormat.Unknown, flags, binding, compIndex, new[] { dest }, sources));
|
||||||
|
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (texOp.Inst == Instruction.Lod ||
|
if (texOp.Inst == Instruction.TextureSample || texOp.Inst.IsTextureQuery())
|
||||||
texOp.Inst == Instruction.TextureSample ||
|
|
||||||
texOp.Inst == Instruction.TextureSize)
|
|
||||||
{
|
{
|
||||||
Operand bindlessHandle = Utils.FindLastOperation(texOp.GetSource(0), block);
|
Operand bindlessHandle = Utils.FindLastOperation(texOp.GetSource(0), block);
|
||||||
|
|
||||||
|
@ -40,7 +38,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
||||||
// as long bindless elimination is successful and we know where the texture descriptor is located.
|
// as long bindless elimination is successful and we know where the texture descriptor is located.
|
||||||
bool rewriteSamplerType =
|
bool rewriteSamplerType =
|
||||||
texOp.Type == SamplerType.TextureBuffer ||
|
texOp.Type == SamplerType.TextureBuffer ||
|
||||||
texOp.Inst == Instruction.TextureSize;
|
texOp.Inst == Instruction.TextureQuerySamples ||
|
||||||
|
texOp.Inst == Instruction.TextureQuerySize;
|
||||||
|
|
||||||
if (bindlessHandle.Type == OperandType.ConstantBuffer)
|
if (bindlessHandle.Type == OperandType.ConstantBuffer)
|
||||||
{
|
{
|
||||||
|
|
|
@ -232,8 +232,8 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
inst &= Instruction.Mask;
|
inst &= Instruction.Mask;
|
||||||
bool isImage = inst == Instruction.ImageLoad || inst == Instruction.ImageStore || inst == Instruction.ImageAtomic;
|
bool isImage = inst == Instruction.ImageLoad || inst == Instruction.ImageStore || inst == Instruction.ImageAtomic;
|
||||||
bool isWrite = inst == Instruction.ImageStore || inst == Instruction.ImageAtomic;
|
bool isWrite = inst == Instruction.ImageStore || inst == Instruction.ImageAtomic;
|
||||||
bool accurateType = inst != Instruction.Lod && inst != Instruction.TextureSize;
|
bool accurateType = !inst.IsTextureQuery();
|
||||||
bool intCoords = isImage || flags.HasFlag(TextureFlags.IntCoords) || inst == Instruction.TextureSize;
|
bool intCoords = isImage || flags.HasFlag(TextureFlags.IntCoords) || inst == Instruction.TextureQuerySize;
|
||||||
bool coherent = flags.HasFlag(TextureFlags.Coherent);
|
bool coherent = flags.HasFlag(TextureFlags.Coherent);
|
||||||
|
|
||||||
if (!isImage)
|
if (!isImage)
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
||||||
{
|
{
|
||||||
node = InsertCoordNormalization(context.Hfm, node, context.ResourceManager, context.GpuAccessor, context.Stage);
|
node = InsertCoordNormalization(context.Hfm, node, context.ResourceManager, context.GpuAccessor, context.Stage);
|
||||||
node = InsertCoordGatherBias(node, context.ResourceManager, context.GpuAccessor);
|
node = InsertCoordGatherBias(node, context.ResourceManager, context.GpuAccessor);
|
||||||
node = InsertConstOffsets(node, context.ResourceManager, context.GpuAccessor);
|
node = InsertConstOffsets(node, context.GpuAccessor, context.Stage);
|
||||||
|
|
||||||
if (texOp.Type == SamplerType.TextureBuffer && !context.GpuAccessor.QueryHostSupportsSnormBufferTextureFormat())
|
if (texOp.Type == SamplerType.TextureBuffer && !context.GpuAccessor.QueryHostSupportsSnormBufferTextureFormat())
|
||||||
{
|
{
|
||||||
|
@ -99,7 +99,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
||||||
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||||
|
|
||||||
if (texOp.Inst == Instruction.TextureSize &&
|
if (texOp.Inst == Instruction.TextureQuerySize &&
|
||||||
texOp.Index < 2 &&
|
texOp.Index < 2 &&
|
||||||
!isBindless &&
|
!isBindless &&
|
||||||
!isIndexed &&
|
!isIndexed &&
|
||||||
|
@ -190,7 +190,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
||||||
}
|
}
|
||||||
|
|
||||||
LinkedListNode<INode> textureSizeNode = node.List.AddBefore(node, new TextureOperation(
|
LinkedListNode<INode> textureSizeNode = node.List.AddBefore(node, new TextureOperation(
|
||||||
Instruction.TextureSize,
|
Instruction.TextureQuerySize,
|
||||||
texOp.Type,
|
texOp.Type,
|
||||||
texOp.Format,
|
texOp.Format,
|
||||||
texOp.Flags,
|
texOp.Flags,
|
||||||
|
@ -259,7 +259,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
||||||
}
|
}
|
||||||
|
|
||||||
node.List.AddBefore(node, new TextureOperation(
|
node.List.AddBefore(node, new TextureOperation(
|
||||||
Instruction.TextureSize,
|
Instruction.TextureQuerySize,
|
||||||
texOp.Type,
|
texOp.Type,
|
||||||
texOp.Format,
|
texOp.Format,
|
||||||
texOp.Flags,
|
texOp.Flags,
|
||||||
|
@ -287,7 +287,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LinkedListNode<INode> InsertConstOffsets(LinkedListNode<INode> node, ResourceManager resourceManager, IGpuAccessor gpuAccessor)
|
private static LinkedListNode<INode> InsertConstOffsets(LinkedListNode<INode> node, IGpuAccessor gpuAccessor, ShaderStage stage)
|
||||||
{
|
{
|
||||||
// Non-constant texture offsets are not allowed (according to the spec),
|
// Non-constant texture offsets are not allowed (according to the spec),
|
||||||
// however some GPUs does support that.
|
// however some GPUs does support that.
|
||||||
|
@ -440,7 +440,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
||||||
|
|
||||||
sources.CopyTo(newSources, 0);
|
sources.CopyTo(newSources, 0);
|
||||||
|
|
||||||
Operand[] texSizes = InsertTextureLod(node, texOp, lodSources, bindlessHandle, coordsCount);
|
Operand[] texSizes = InsertTextureLod(node, texOp, lodSources, bindlessHandle, coordsCount, stage);
|
||||||
|
|
||||||
int destIndex = 0;
|
int destIndex = 0;
|
||||||
|
|
||||||
|
@ -502,7 +502,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Operand[] texSizes = InsertTextureLod(node, texOp, lodSources, bindlessHandle, coordsCount);
|
Operand[] texSizes = InsertTextureLod(node, texOp, lodSources, bindlessHandle, coordsCount, stage);
|
||||||
|
|
||||||
for (int index = 0; index < coordsCount; index++)
|
for (int index = 0; index < coordsCount; index++)
|
||||||
{
|
{
|
||||||
|
@ -554,21 +554,31 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
||||||
TextureOperation texOp,
|
TextureOperation texOp,
|
||||||
Operand[] lodSources,
|
Operand[] lodSources,
|
||||||
Operand bindlessHandle,
|
Operand bindlessHandle,
|
||||||
int coordsCount)
|
int coordsCount,
|
||||||
|
ShaderStage stage)
|
||||||
{
|
{
|
||||||
Operand[] texSizes = new Operand[coordsCount];
|
Operand[] texSizes = new Operand[coordsCount];
|
||||||
|
|
||||||
Operand lod = Local();
|
Operand lod;
|
||||||
|
|
||||||
node.List.AddBefore(node, new TextureOperation(
|
if (stage == ShaderStage.Fragment)
|
||||||
Instruction.Lod,
|
{
|
||||||
texOp.Type,
|
lod = Local();
|
||||||
texOp.Format,
|
|
||||||
texOp.Flags,
|
node.List.AddBefore(node, new TextureOperation(
|
||||||
texOp.Binding,
|
Instruction.Lod,
|
||||||
0,
|
texOp.Type,
|
||||||
new[] { lod },
|
texOp.Format,
|
||||||
lodSources));
|
texOp.Flags,
|
||||||
|
texOp.Binding,
|
||||||
|
0,
|
||||||
|
new[] { lod },
|
||||||
|
lodSources));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lod = Const(0);
|
||||||
|
}
|
||||||
|
|
||||||
for (int index = 0; index < coordsCount; index++)
|
for (int index = 0; index < coordsCount; index++)
|
||||||
{
|
{
|
||||||
|
@ -586,7 +596,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
||||||
}
|
}
|
||||||
|
|
||||||
node.List.AddBefore(node, new TextureOperation(
|
node.List.AddBefore(node, new TextureOperation(
|
||||||
Instruction.TextureSize,
|
Instruction.TextureQuerySize,
|
||||||
texOp.Type,
|
texOp.Type,
|
||||||
texOp.Format,
|
texOp.Format,
|
||||||
texOp.Flags,
|
texOp.Flags,
|
||||||
|
|
Reference in a new issue