mirror of
https://git.ryujinx.app/projects/Kenji-NX.git
synced 2026-10-05 10:58:56 +02:00
Implement buffer texture alignment
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using Ryujinx.Graphics.Shader.Translation.Optimizations;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||
@@ -27,7 +28,19 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
||||
|
||||
if (texOp.Type == SamplerType.TextureBuffer && !context.GpuAccessor.QueryHostSupportsSnormBufferTextureFormat())
|
||||
{
|
||||
node = InsertSnormNormalization(node, context.ResourceManager, context.GpuAccessor);
|
||||
if (!context.GpuAccessor.QueryHostSupportsSnormBufferTextureFormat())
|
||||
{
|
||||
node = InsertSnormNormalization(node, context.ResourceManager, context.GpuAccessor);
|
||||
}
|
||||
|
||||
if (!context.GpuAccessor.QueryHostSupportsBufferTexturePixelAlignment())
|
||||
{
|
||||
node = InsertCoordOffset(node, context.ResourceManager, context.Stage, isImage: false);
|
||||
}
|
||||
}
|
||||
else if (!context.GpuAccessor.QueryHostSupportsBufferTexturePixelAlignment() && texOp.Inst.IsImage())
|
||||
{
|
||||
node = InsertCoordOffset(node, context.ResourceManager, context.Stage, isImage: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -278,6 +291,87 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
||||
return node;
|
||||
}
|
||||
|
||||
private static LinkedListNode<INode> InsertCoordOffset(LinkedListNode<INode> node, ResourceManager resourceManager, ShaderStage stage, bool isImage)
|
||||
{
|
||||
// Some GPUs have fixed alignment requirements for buffer textures.
|
||||
// For those cases, we bind the aligned buffer offset, and apply the remaining offset on the shader.
|
||||
|
||||
TextureOperation texOp = (TextureOperation)node.Value;
|
||||
|
||||
if ((texOp.Type & SamplerType.Mask) != SamplerType.TextureBuffer)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
Operand[] sources = new Operand[texOp.SourcesCount];
|
||||
|
||||
for (int i = 0; i < texOp.SourcesCount; i++)
|
||||
{
|
||||
sources[i] = texOp.GetSource(i);
|
||||
}
|
||||
|
||||
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||
bool isIndexed = resourceManager.IsArrayOfTexturesOrImages(texOp.Binding, isImage);
|
||||
|
||||
int coordsIndex = isBindless || isIndexed ? 1 : 0;
|
||||
|
||||
Operand[] dests = new Operand[texOp.DestsCount];
|
||||
|
||||
for (int i = 0; i < texOp.DestsCount; i++)
|
||||
{
|
||||
dests[i] = texOp.GetDest(i);
|
||||
}
|
||||
|
||||
LinkedListNode<INode> oldNode = node;
|
||||
|
||||
Operand source = sources[coordsIndex];
|
||||
Operand offset = Local();
|
||||
Operand coordPlusOffset = Local();
|
||||
|
||||
int stageIndex = stage switch
|
||||
{
|
||||
ShaderStage.TessellationControl => 1,
|
||||
ShaderStage.TessellationEvaluation => 2,
|
||||
ShaderStage.Geometry => 3,
|
||||
ShaderStage.Fragment => 4,
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
int bindingIndex = isImage
|
||||
? resourceManager.FindImageDescriptorIndex(texOp.Binding)
|
||||
: resourceManager.FindTextureDescriptorIndex(texOp.Binding);
|
||||
|
||||
node.List.AddBefore(node, new Operation(
|
||||
Instruction.Load,
|
||||
StorageKind.ConstantBuffer,
|
||||
offset,
|
||||
Const(SupportBuffer.Binding),
|
||||
Const((int)SupportBufferField.BufferTextureOffset),
|
||||
Const(stageIndex * SupportBuffer.TextureCount + bindingIndex),
|
||||
Const(isImage ? 1 : 0)));
|
||||
|
||||
node.List.AddBefore(node, new Operation(Instruction.Add, coordPlusOffset, source, offset));
|
||||
|
||||
sources[coordsIndex] = coordPlusOffset;
|
||||
|
||||
TextureOperation newTexOp = new(
|
||||
texOp.Inst,
|
||||
texOp.Type,
|
||||
texOp.Format,
|
||||
texOp.Flags,
|
||||
texOp.Set,
|
||||
texOp.Binding,
|
||||
texOp.Index,
|
||||
dests,
|
||||
sources);
|
||||
|
||||
node = node.List.AddBefore(node, newTexOp);
|
||||
|
||||
Utils.DeleteNode(oldNode, texOp);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
private static LinkedListNode<INode> InsertConstOffsets(LinkedListNode<INode> node, ResourceManager resourceManager, IGpuAccessor gpuAccessor, ShaderStage stage)
|
||||
{
|
||||
// Non-constant texture offsets are not allowed (according to the spec),
|
||||
|
||||
Reference in New Issue
Block a user