mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-02-21 16:43:35 +00:00
Add alpha test emulation on shader (but no shader specialisation yet...)
This commit is contained in:
parent
9a95c3c3bc
commit
4c7e6df7d1
7 changed files with 124 additions and 4 deletions
|
@ -1248,7 +1248,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
_state.State.ViewportTransformEnable == 0,
|
_state.State.ViewportTransformEnable == 0,
|
||||||
GetDepthMode() == DepthMode.MinusOneToOne,
|
GetDepthMode() == DepthMode.MinusOneToOne,
|
||||||
_state.State.VertexProgramPointSize,
|
_state.State.VertexProgramPointSize,
|
||||||
_state.State.PointSize);
|
_state.State.PointSize,
|
||||||
|
_state.State.AlphaTestEnable,
|
||||||
|
_state.State.AlphaTestFunc,
|
||||||
|
_state.State.AlphaTestRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DepthMode GetDepthMode()
|
private DepthMode GetDepthMode()
|
||||||
|
|
|
@ -170,7 +170,10 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
1f);
|
1f,
|
||||||
|
false,
|
||||||
|
CompareOp.Always,
|
||||||
|
0f);
|
||||||
|
|
||||||
TransformFeedbackDescriptor[] tfdNew = null;
|
TransformFeedbackDescriptor[] tfdNew = null;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.Gpu.Image;
|
using Ryujinx.Graphics.Gpu.Image;
|
||||||
using Ryujinx.Graphics.Shader;
|
using Ryujinx.Graphics.Shader;
|
||||||
|
using Ryujinx.Graphics.Shader.Translation;
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
@ -16,6 +18,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
private readonly AttributeType[] _attributeTypes;
|
private readonly AttributeType[] _attributeTypes;
|
||||||
private readonly int _stageIndex;
|
private readonly int _stageIndex;
|
||||||
private readonly bool _compute;
|
private readonly bool _compute;
|
||||||
|
private readonly bool _isVulkan;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the GPU state accessor for graphics shader translation.
|
/// Creates a new instance of the GPU state accessor for graphics shader translation.
|
||||||
|
@ -32,6 +35,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
AttributeType[] attributeTypes,
|
AttributeType[] attributeTypes,
|
||||||
int stageIndex) : base(context, state.ResourceCounts, stageIndex)
|
int stageIndex) : base(context, state.ResourceCounts, stageIndex)
|
||||||
{
|
{
|
||||||
|
_isVulkan = context.Capabilities.Api == TargetApi.Vulkan;
|
||||||
_channel = channel;
|
_channel = channel;
|
||||||
_state = state;
|
_state = state;
|
||||||
_attributeTypes = attributeTypes;
|
_attributeTypes = attributeTypes;
|
||||||
|
@ -74,6 +78,33 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
return MemoryMarshal.Cast<byte, ulong>(_channel.MemoryManager.GetSpan(address, size));
|
return MemoryMarshal.Cast<byte, ulong>(_channel.MemoryManager.GetSpan(address, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public AlphaTestOp QueryAlphaTestCompare()
|
||||||
|
{
|
||||||
|
if (!_isVulkan || !_state.GraphicsState.AlphaTestEnable)
|
||||||
|
{
|
||||||
|
return AlphaTestOp.Always;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _state.GraphicsState.AlphaTestCompare switch
|
||||||
|
{
|
||||||
|
CompareOp.Never or CompareOp.NeverGl => AlphaTestOp.Never,
|
||||||
|
CompareOp.Less or CompareOp.LessGl => AlphaTestOp.Less,
|
||||||
|
CompareOp.Equal or CompareOp.EqualGl => AlphaTestOp.Equal,
|
||||||
|
CompareOp.LessOrEqual or CompareOp.LessOrEqualGl => AlphaTestOp.LessOrEqual,
|
||||||
|
CompareOp.Greater or CompareOp.GreaterGl => AlphaTestOp.Greater,
|
||||||
|
CompareOp.NotEqual or CompareOp.NotEqualGl => AlphaTestOp.NotEqual,
|
||||||
|
CompareOp.GreaterOrEqual or CompareOp.GreaterOrEqualGl => AlphaTestOp.GreaterOrEqual,
|
||||||
|
_ => AlphaTestOp.Always
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public float QueryAlphaTestReference()
|
||||||
|
{
|
||||||
|
return _state.GraphicsState.AlphaTestReference;
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public AttributeType QueryAttributeType(int location)
|
public AttributeType QueryAttributeType(int location)
|
||||||
{
|
{
|
||||||
|
|
|
@ -45,6 +45,21 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly float PointSize;
|
public readonly float PointSize;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whenever alpha test is enabled.
|
||||||
|
/// </summary>
|
||||||
|
public readonly bool AlphaTestEnable;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When alpha test is enabled, indicates the comparison that decides if the fragment is discarded.
|
||||||
|
/// </summary>
|
||||||
|
public readonly CompareOp AlphaTestCompare;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When alpha test is enabled, indicates the value to compare with the fragment output alpha.
|
||||||
|
/// </summary>
|
||||||
|
public readonly float AlphaTestReference;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new GPU graphics state.
|
/// Creates a new GPU graphics state.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -55,6 +70,9 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
/// <param name="depthMode">Depth mode zero to one or minus one to one</param>
|
/// <param name="depthMode">Depth mode zero to one or minus one to one</param>
|
||||||
/// <param name="programPointSizeEnable">Indicates if the point size is set on the shader or is fixed</param>
|
/// <param name="programPointSizeEnable">Indicates if the point size is set on the shader or is fixed</param>
|
||||||
/// <param name="pointSize">Point size if not set from shader</param>
|
/// <param name="pointSize">Point size if not set from shader</param>
|
||||||
|
/// <param name="alphaTestEnable">Indicates whenever alpha test is enabled</param>
|
||||||
|
/// <param name="alphaTestCompare">When alpha test is enabled, indicates the comparison that decides if the fragment is discarded</param>
|
||||||
|
/// <param name="alphaTestReference">When alpha test is enabled, indicates the value to compare with the fragment output alpha</param>
|
||||||
public GpuChannelGraphicsState(
|
public GpuChannelGraphicsState(
|
||||||
bool earlyZForce,
|
bool earlyZForce,
|
||||||
PrimitiveTopology topology,
|
PrimitiveTopology topology,
|
||||||
|
@ -62,7 +80,10 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
bool viewportTransformDisable,
|
bool viewportTransformDisable,
|
||||||
bool depthMode,
|
bool depthMode,
|
||||||
bool programPointSizeEnable,
|
bool programPointSizeEnable,
|
||||||
float pointSize)
|
float pointSize,
|
||||||
|
bool alphaTestEnable,
|
||||||
|
CompareOp alphaTestCompare,
|
||||||
|
float alphaTestReference)
|
||||||
{
|
{
|
||||||
EarlyZForce = earlyZForce;
|
EarlyZForce = earlyZForce;
|
||||||
Topology = topology;
|
Topology = topology;
|
||||||
|
@ -71,6 +92,9 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
DepthMode = depthMode;
|
DepthMode = depthMode;
|
||||||
ProgramPointSizeEnable = programPointSizeEnable;
|
ProgramPointSizeEnable = programPointSizeEnable;
|
||||||
PointSize = pointSize;
|
PointSize = pointSize;
|
||||||
|
AlphaTestEnable = alphaTestEnable;
|
||||||
|
AlphaTestCompare = alphaTestCompare;
|
||||||
|
AlphaTestReference = alphaTestReference;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
14
Ryujinx.Graphics.Shader/AlphaTestOp.cs
Normal file
14
Ryujinx.Graphics.Shader/AlphaTestOp.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
namespace Ryujinx.Graphics.Shader
|
||||||
|
{
|
||||||
|
public enum AlphaTestOp
|
||||||
|
{
|
||||||
|
Never = 1,
|
||||||
|
Less,
|
||||||
|
Equal,
|
||||||
|
LessOrEqual,
|
||||||
|
Greater,
|
||||||
|
NotEqual,
|
||||||
|
GreaterOrEqual,
|
||||||
|
Always
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,6 +34,16 @@ namespace Ryujinx.Graphics.Shader
|
||||||
/// <returns>Span of the memory location</returns>
|
/// <returns>Span of the memory location</returns>
|
||||||
ReadOnlySpan<ulong> GetCode(ulong address, int minimumSize);
|
ReadOnlySpan<ulong> GetCode(ulong address, int minimumSize);
|
||||||
|
|
||||||
|
AlphaTestOp QueryAlphaTestCompare()
|
||||||
|
{
|
||||||
|
return AlphaTestOp.Always;
|
||||||
|
}
|
||||||
|
|
||||||
|
float QueryAlphaTestReference()
|
||||||
|
{
|
||||||
|
return 0f;
|
||||||
|
}
|
||||||
|
|
||||||
AttributeType QueryAttributeType(int location)
|
AttributeType QueryAttributeType(int location)
|
||||||
{
|
{
|
||||||
return AttributeType.Float;
|
return AttributeType.Float;
|
||||||
|
|
|
@ -234,6 +234,8 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
}
|
}
|
||||||
else if (Config.Stage == ShaderStage.Fragment)
|
else if (Config.Stage == ShaderStage.Fragment)
|
||||||
{
|
{
|
||||||
|
bool supportsBgra = Config.GpuAccessor.QueryHostSupportsBgraFormat();
|
||||||
|
|
||||||
if (Config.OmapDepth)
|
if (Config.OmapDepth)
|
||||||
{
|
{
|
||||||
Operand dest = Attribute(AttributeConsts.FragmentOutputDepth);
|
Operand dest = Attribute(AttributeConsts.FragmentOutputDepth);
|
||||||
|
@ -243,7 +245,40 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
this.Copy(dest, src);
|
this.Copy(dest, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool supportsBgra = Config.GpuAccessor.QueryHostSupportsBgraFormat();
|
AlphaTestOp alphaTestOp = Config.GpuAccessor.QueryAlphaTestCompare();
|
||||||
|
|
||||||
|
if (alphaTestOp != AlphaTestOp.Always && (Config.OmapTargets & 8) != 0)
|
||||||
|
{
|
||||||
|
if (alphaTestOp == AlphaTestOp.Never)
|
||||||
|
{
|
||||||
|
this.Discard();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Instruction comparator = alphaTestOp switch
|
||||||
|
{
|
||||||
|
AlphaTestOp.Equal => Instruction.CompareEqual,
|
||||||
|
AlphaTestOp.Greater => Instruction.CompareGreater,
|
||||||
|
AlphaTestOp.GreaterOrEqual => Instruction.CompareGreaterOrEqual,
|
||||||
|
AlphaTestOp.Less => Instruction.CompareLess,
|
||||||
|
AlphaTestOp.LessOrEqual => Instruction.CompareLessOrEqual,
|
||||||
|
AlphaTestOp.NotEqual => Instruction.CompareNotEqual,
|
||||||
|
_ => 0
|
||||||
|
};
|
||||||
|
|
||||||
|
Debug.Assert(comparator != 0, $"Invalid alpha test operation \"{alphaTestOp}\".");
|
||||||
|
|
||||||
|
Operand alpha = Register(3, RegisterType.Gpr);
|
||||||
|
Operand alphaRef = ConstF(Config.GpuAccessor.QueryAlphaTestReference());
|
||||||
|
Operand alphaPass = Add(Instruction.FP32 | comparator, Local(), alpha, alphaRef);
|
||||||
|
Operand alphaPassLabel = Label();
|
||||||
|
|
||||||
|
this.BranchIfTrue(alphaPassLabel, alphaPass);
|
||||||
|
this.Discard();
|
||||||
|
this.MarkLabel(alphaPassLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int regIndexBase = 0;
|
int regIndexBase = 0;
|
||||||
|
|
||||||
for (int rtIndex = 0; rtIndex < 8; rtIndex++)
|
for (int rtIndex = 0; rtIndex < 8; rtIndex++)
|
||||||
|
|
Loading…
Reference in a new issue