mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-02-21 00:23:36 +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,
|
||||
GetDepthMode() == DepthMode.MinusOneToOne,
|
||||
_state.State.VertexProgramPointSize,
|
||||
_state.State.PointSize);
|
||||
_state.State.PointSize,
|
||||
_state.State.AlphaTestEnable,
|
||||
_state.State.AlphaTestFunc,
|
||||
_state.State.AlphaTestRef);
|
||||
}
|
||||
|
||||
private DepthMode GetDepthMode()
|
||||
|
|
|
@ -170,7 +170,10 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache
|
|||
false,
|
||||
false,
|
||||
false,
|
||||
1f);
|
||||
1f,
|
||||
false,
|
||||
CompareOp.Always,
|
||||
0f);
|
||||
|
||||
TransformFeedbackDescriptor[] tfdNew = null;
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.Gpu.Image;
|
||||
using Ryujinx.Graphics.Shader;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
@ -16,6 +18,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
private readonly AttributeType[] _attributeTypes;
|
||||
private readonly int _stageIndex;
|
||||
private readonly bool _compute;
|
||||
private readonly bool _isVulkan;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the GPU state accessor for graphics shader translation.
|
||||
|
@ -32,6 +35,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
AttributeType[] attributeTypes,
|
||||
int stageIndex) : base(context, state.ResourceCounts, stageIndex)
|
||||
{
|
||||
_isVulkan = context.Capabilities.Api == TargetApi.Vulkan;
|
||||
_channel = channel;
|
||||
_state = state;
|
||||
_attributeTypes = attributeTypes;
|
||||
|
@ -74,6 +78,33 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
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/>
|
||||
public AttributeType QueryAttributeType(int location)
|
||||
{
|
||||
|
|
|
@ -45,6 +45,21 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
/// </summary>
|
||||
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>
|
||||
/// Creates a new GPU graphics state.
|
||||
/// </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="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="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(
|
||||
bool earlyZForce,
|
||||
PrimitiveTopology topology,
|
||||
|
@ -62,7 +80,10 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
bool viewportTransformDisable,
|
||||
bool depthMode,
|
||||
bool programPointSizeEnable,
|
||||
float pointSize)
|
||||
float pointSize,
|
||||
bool alphaTestEnable,
|
||||
CompareOp alphaTestCompare,
|
||||
float alphaTestReference)
|
||||
{
|
||||
EarlyZForce = earlyZForce;
|
||||
Topology = topology;
|
||||
|
@ -71,6 +92,9 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
DepthMode = depthMode;
|
||||
ProgramPointSizeEnable = programPointSizeEnable;
|
||||
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>
|
||||
ReadOnlySpan<ulong> GetCode(ulong address, int minimumSize);
|
||||
|
||||
AlphaTestOp QueryAlphaTestCompare()
|
||||
{
|
||||
return AlphaTestOp.Always;
|
||||
}
|
||||
|
||||
float QueryAlphaTestReference()
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
AttributeType QueryAttributeType(int location)
|
||||
{
|
||||
return AttributeType.Float;
|
||||
|
|
|
@ -234,6 +234,8 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||
}
|
||||
else if (Config.Stage == ShaderStage.Fragment)
|
||||
{
|
||||
bool supportsBgra = Config.GpuAccessor.QueryHostSupportsBgraFormat();
|
||||
|
||||
if (Config.OmapDepth)
|
||||
{
|
||||
Operand dest = Attribute(AttributeConsts.FragmentOutputDepth);
|
||||
|
@ -243,7 +245,40 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||
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;
|
||||
|
||||
for (int rtIndex = 0; rtIndex < 8; rtIndex++)
|
||||
|
|
Loading…
Reference in a new issue