Fix incorrect fragment origin when YNegate is enabled (#4673)
* Fix incorrect fragment origin when YNegate is enabled * Shader cache version bump * Do not update support buffer if shader does not read gl_FragCoord * Pass unscaled viewport size to the support buffer
This commit is contained in:
@ -188,10 +188,19 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
context.AppendLine();
|
||||
}
|
||||
|
||||
if (context.Config.Stage == ShaderStage.Fragment && context.Config.GpuAccessor.QueryEarlyZForce())
|
||||
if (context.Config.Stage == ShaderStage.Fragment)
|
||||
{
|
||||
context.AppendLine("layout(early_fragment_tests) in;");
|
||||
context.AppendLine();
|
||||
if (context.Config.GpuAccessor.QueryEarlyZForce())
|
||||
{
|
||||
context.AppendLine("layout (early_fragment_tests) in;");
|
||||
context.AppendLine();
|
||||
}
|
||||
|
||||
if (context.Config.Properties.OriginUpperLeft)
|
||||
{
|
||||
context.AppendLine("layout (origin_upper_left) in vec4 gl_FragCoord;");
|
||||
context.AppendLine();
|
||||
}
|
||||
}
|
||||
|
||||
if ((info.HelperFunctionsMask & HelperFunctionsMask.MultiplyHighS32) != 0)
|
||||
|
@ -251,7 +251,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
}
|
||||
else if (context.Config.Stage == ShaderStage.Fragment)
|
||||
{
|
||||
context.AddExecutionMode(spvFunc, context.Config.Options.TargetApi == TargetApi.Vulkan
|
||||
context.AddExecutionMode(spvFunc, context.Config.Properties.OriginUpperLeft
|
||||
? ExecutionMode.OriginUpperLeft
|
||||
: ExecutionMode.OriginLowerLeft);
|
||||
|
||||
|
@ -178,6 +178,15 @@ namespace Ryujinx.Graphics.Shader
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queries if host state forces early depth testing.
|
||||
/// </summary>
|
||||
/// <returns>True if early depth testing is forced</returns>
|
||||
bool QueryEarlyZForce()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queries whenever the current draw has written the base vertex and base instance into Constant Buffer 0.
|
||||
/// </summary>
|
||||
@ -534,19 +543,19 @@ namespace Ryujinx.Graphics.Shader
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queries if host state forces early depth testing.
|
||||
/// Queries if host state disables the viewport transform.
|
||||
/// </summary>
|
||||
/// <returns>True if early depth testing is forced</returns>
|
||||
bool QueryEarlyZForce()
|
||||
/// <returns>True if the viewport transform is disabled</returns>
|
||||
bool QueryViewportTransformDisable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queries if host state disables the viewport transform.
|
||||
/// Queries Y negate enable state.
|
||||
/// </summary>
|
||||
/// <returns>True if the viewport transform is disabled</returns>
|
||||
bool QueryViewportTransformDisable()
|
||||
/// <returns>True if Y negate of the fragment coordinates is enabled, false otherwise</returns>
|
||||
bool QueryYNegateEnabled()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -161,6 +161,18 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
// FragCoord X/Y must be divided by the render target scale, if resolution scaling is active,
|
||||
// because the shader code is not expecting scaled values.
|
||||
res = context.FPDivide(res, context.Load(StorageKind.ConstantBuffer, SupportBuffer.Binding, Const((int)SupportBufferField.RenderScale), Const(0)));
|
||||
|
||||
if (op.Imm10 == AttributeConsts.PositionY && context.Config.Options.TargetApi != TargetApi.OpenGL)
|
||||
{
|
||||
// If YNegate is enabled, we need to flip the fragment coordinates vertically, unless
|
||||
// the API supports changing the origin (only OpenGL does).
|
||||
if (context.Config.GpuAccessor.QueryYNegateEnabled())
|
||||
{
|
||||
Operand viewportHeight = context.Load(StorageKind.ConstantBuffer, 0, Const((int)SupportBufferField.ViewportSize), Const(1));
|
||||
|
||||
res = context.FPSubtract(viewportHeight, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (op.Imm10 == AttributeConsts.FrontFacing && context.Config.GpuAccessor.QueryHostHasFrontFacingBug())
|
||||
{
|
||||
|
@ -13,6 +13,7 @@ namespace Ryujinx.Graphics.Shader
|
||||
public ShaderIdentification Identification { get; }
|
||||
public int GpLayerInputAttribute { get; }
|
||||
public ShaderStage Stage { get; }
|
||||
public bool UsesFragCoord { get; }
|
||||
public bool UsesInstanceId { get; }
|
||||
public bool UsesDrawParameters { get; }
|
||||
public bool UsesRtLayer { get; }
|
||||
@ -27,6 +28,7 @@ namespace Ryujinx.Graphics.Shader
|
||||
ShaderIdentification identification,
|
||||
int gpLayerInputAttribute,
|
||||
ShaderStage stage,
|
||||
bool usesFragCoord,
|
||||
bool usesInstanceId,
|
||||
bool usesDrawParameters,
|
||||
bool usesRtLayer,
|
||||
@ -41,6 +43,7 @@ namespace Ryujinx.Graphics.Shader
|
||||
Identification = identification;
|
||||
GpLayerInputAttribute = gpLayerInputAttribute;
|
||||
Stage = stage;
|
||||
UsesFragCoord = usesFragCoord;
|
||||
UsesInstanceId = usesInstanceId;
|
||||
UsesDrawParameters = usesDrawParameters;
|
||||
UsesRtLayer = usesRtLayer;
|
||||
|
@ -18,6 +18,8 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||
public IReadOnlyDictionary<int, MemoryDefinition> LocalMemories => _localMemories;
|
||||
public IReadOnlyDictionary<int, MemoryDefinition> SharedMemories => _sharedMemories;
|
||||
|
||||
public readonly bool OriginUpperLeft;
|
||||
|
||||
public ShaderProperties()
|
||||
{
|
||||
_constantBuffers = new Dictionary<int, BufferDefinition>();
|
||||
@ -28,6 +30,11 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||
_sharedMemories = new Dictionary<int, MemoryDefinition>();
|
||||
}
|
||||
|
||||
public ShaderProperties(bool originUpperLeft) : this()
|
||||
{
|
||||
OriginUpperLeft = originUpperLeft;
|
||||
}
|
||||
|
||||
public void AddOrUpdateConstantBuffer(int binding, BufferDefinition definition)
|
||||
{
|
||||
_constantBuffers[binding] = definition;
|
||||
|
@ -19,6 +19,7 @@ namespace Ryujinx.Graphics.Shader
|
||||
FragmentAlphaTest,
|
||||
FragmentIsBgra,
|
||||
ViewportInverse,
|
||||
ViewportSize,
|
||||
FragmentRenderScaleCount,
|
||||
RenderScale,
|
||||
}
|
||||
@ -33,6 +34,7 @@ namespace Ryujinx.Graphics.Shader
|
||||
public static readonly int FragmentAlphaTestOffset;
|
||||
public static readonly int FragmentIsBgraOffset;
|
||||
public static readonly int ViewportInverseOffset;
|
||||
public static readonly int ViewportSizeOffset;
|
||||
public static readonly int FragmentRenderScaleCountOffset;
|
||||
public static readonly int GraphicsRenderScaleOffset;
|
||||
public static readonly int ComputeRenderScaleOffset;
|
||||
@ -56,6 +58,7 @@ namespace Ryujinx.Graphics.Shader
|
||||
FragmentAlphaTestOffset = OffsetOf(ref instance, ref instance.FragmentAlphaTest);
|
||||
FragmentIsBgraOffset = OffsetOf(ref instance, ref instance.FragmentIsBgra);
|
||||
ViewportInverseOffset = OffsetOf(ref instance, ref instance.ViewportInverse);
|
||||
ViewportSizeOffset = OffsetOf(ref instance, ref instance.ViewportSize);
|
||||
FragmentRenderScaleCountOffset = OffsetOf(ref instance, ref instance.FragmentRenderScaleCount);
|
||||
GraphicsRenderScaleOffset = OffsetOf(ref instance, ref instance.RenderScale);
|
||||
ComputeRenderScaleOffset = GraphicsRenderScaleOffset + FieldSize;
|
||||
@ -68,6 +71,7 @@ namespace Ryujinx.Graphics.Shader
|
||||
new StructureField(AggregateType.U32, "s_alpha_test"),
|
||||
new StructureField(AggregateType.Array | AggregateType.U32, "s_is_bgra", FragmentIsBgraCount),
|
||||
new StructureField(AggregateType.Vector4 | AggregateType.FP32, "s_viewport_inverse"),
|
||||
new StructureField(AggregateType.Vector4 | AggregateType.FP32, "s_viewport_size"),
|
||||
new StructureField(AggregateType.S32, "s_frag_scale_count"),
|
||||
new StructureField(AggregateType.Array | AggregateType.FP32, "s_render_scale", RenderScaleMaxCount),
|
||||
});
|
||||
@ -76,6 +80,7 @@ namespace Ryujinx.Graphics.Shader
|
||||
public Vector4<int> FragmentAlphaTest;
|
||||
public Array8<Vector4<int>> FragmentIsBgra;
|
||||
public Vector4<float> ViewportInverse;
|
||||
public Vector4<float> ViewportSize;
|
||||
public Vector4<int> FragmentRenderScaleCount;
|
||||
|
||||
// Render scale max count: 1 + 64 + 8. First scale is fragment output scale, others are textures/image inputs.
|
||||
|
@ -429,6 +429,11 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
return context.Add(Instruction.FP32 | Instruction.SquareRoot, Local(), a);
|
||||
}
|
||||
|
||||
public static Operand FPSubtract(this EmitterContext context, Operand a, Operand b, Instruction fpType = Instruction.FP32)
|
||||
{
|
||||
return context.Add(fpType | Instruction.Subtract, Local(), a, b);
|
||||
}
|
||||
|
||||
public static Operand FPTruncate(this EmitterContext context, Operand a, Instruction fpType = Instruction.FP32)
|
||||
{
|
||||
return context.Add(fpType | Instruction.Truncate, Local(), a);
|
||||
|
@ -123,7 +123,20 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
UsedInputAttributesPerPatch = new HashSet<int>();
|
||||
UsedOutputAttributesPerPatch = new HashSet<int>();
|
||||
|
||||
ResourceManager = new ResourceManager(stage, gpuAccessor, new ShaderProperties());
|
||||
ShaderProperties properties;
|
||||
|
||||
switch (stage)
|
||||
{
|
||||
case ShaderStage.Fragment:
|
||||
bool originUpperLeft = options.TargetApi == TargetApi.Vulkan || gpuAccessor.QueryYNegateEnabled();
|
||||
properties = new ShaderProperties(originUpperLeft);
|
||||
break;
|
||||
default:
|
||||
properties = new ShaderProperties();
|
||||
break;
|
||||
}
|
||||
|
||||
ResourceManager = new ResourceManager(stage, gpuAccessor, properties);
|
||||
|
||||
if (!gpuAccessor.QueryHostSupportsTransformFeedback() && gpuAccessor.QueryTransformFeedbackEnabled())
|
||||
{
|
||||
@ -135,7 +148,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
|
||||
BufferDefinition tfeInfoBuffer = new(BufferLayout.Std430, 1, Constants.TfeInfoBinding, "tfe_info", tfeInfoStruct);
|
||||
|
||||
Properties.AddOrUpdateStorageBuffer(Constants.TfeInfoBinding, tfeInfoBuffer);
|
||||
properties.AddOrUpdateStorageBuffer(Constants.TfeInfoBinding, tfeInfoBuffer);
|
||||
|
||||
StructureType tfeDataStruct = new(new StructureField[]
|
||||
{
|
||||
@ -146,7 +159,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
{
|
||||
int binding = Constants.TfeBufferBaseBinding + i;
|
||||
BufferDefinition tfeDataBuffer = new(BufferLayout.Std430, 1, binding, $"tfe_data{i}", tfeDataStruct);
|
||||
Properties.AddOrUpdateStorageBuffer(binding, tfeDataBuffer);
|
||||
properties.AddOrUpdateStorageBuffer(binding, tfeDataBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -615,6 +628,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
identification,
|
||||
GpLayerInputAttribute,
|
||||
Stage,
|
||||
UsedFeatures.HasFlag(FeatureFlags.FragCoordXY),
|
||||
UsedFeatures.HasFlag(FeatureFlags.InstanceId),
|
||||
UsedFeatures.HasFlag(FeatureFlags.DrawParameters),
|
||||
UsedFeatures.HasFlag(FeatureFlags.RtLayer),
|
||||
|
Reference in New Issue
Block a user