Compare commits

...

4 Commits

Author SHA1 Message Date
gdkchan
d4b960d348 Implement primitive restart draw arrays properly on OpenGL (#3256) 2022-04-04 18:43:24 -03:00
gdkchan
b2a225558d Do not force scissor on clear if scissor is disabled (#3258) 2022-04-04 18:30:43 -03:00
gdkchan
0ef0fc044a Small graphics abstraction layer cleanup (#3257) 2022-04-04 18:21:06 -03:00
gdkchan
04bd87ed5a Fix shader textureSize with multisample and buffer textures (#3240)
* Fix shader textureSize with multisample and buffer textures

* Replace out param with tuple return value
2022-04-04 14:43:58 -03:00
8 changed files with 60 additions and 65 deletions

View File

@@ -1,47 +0,0 @@
namespace Ryujinx.Graphics.GAL
{
public struct DepthStencilState
{
public bool DepthTestEnable { get; }
public bool DepthWriteEnable { get; }
public bool StencilTestEnable { get; }
public CompareOp DepthFunc { get; }
public CompareOp StencilFrontFunc { get; }
public StencilOp StencilFrontSFail { get; }
public StencilOp StencilFrontDpPass { get; }
public StencilOp StencilFrontDpFail { get; }
public CompareOp StencilBackFunc { get; }
public StencilOp StencilBackSFail { get; }
public StencilOp StencilBackDpPass { get; }
public StencilOp StencilBackDpFail { get; }
public DepthStencilState(
bool depthTestEnable,
bool depthWriteEnable,
bool stencilTestEnable,
CompareOp depthFunc,
CompareOp stencilFrontFunc,
StencilOp stencilFrontSFail,
StencilOp stencilFrontDpPass,
StencilOp stencilFrontDpFail,
CompareOp stencilBackFunc,
StencilOp stencilBackSFail,
StencilOp stencilBackDpPass,
StencilOp stencilBackDpFail)
{
DepthTestEnable = depthTestEnable;
DepthWriteEnable = depthWriteEnable;
StencilTestEnable = stencilTestEnable;
DepthFunc = depthFunc;
StencilFrontFunc = stencilFrontFunc;
StencilFrontSFail = stencilFrontSFail;
StencilFrontDpPass = stencilFrontDpPass;
StencilFrontDpFail = stencilFrontDpFail;
StencilBackFunc = stencilBackFunc;
StencilBackSFail = stencilBackSFail;
StencilBackDpPass = stencilBackDpPass;
StencilBackDpFail = stencilBackDpFail;
}
}
}

View File

@@ -9,7 +9,6 @@ namespace Ryujinx.Graphics.GAL
Texture2DArray,
Texture2DMultisample,
Texture2DMultisampleArray,
Rectangle,
Cubemap,
CubemapArray,
TextureBuffer

View File

@@ -525,7 +525,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
int scissorW = screenScissorState.Width;
int scissorH = screenScissorState.Height;
if (clearAffectedByScissor)
if (clearAffectedByScissor && _state.State.ScissorState[0].Enable)
{
ref var scissorState = ref _state.State.ScissorState[0];

View File

@@ -20,6 +20,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
public const int RasterizerStateIndex = 1;
public const int ScissorStateIndex = 2;
public const int VertexBufferStateIndex = 3;
public const int PrimitiveRestartStateIndex = 4;
private readonly GpuContext _context;
private readonly GpuChannel _channel;
@@ -75,6 +76,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
nameof(ThreedClassState.VertexBufferState),
nameof(ThreedClassState.VertexBufferEndAddress)),
new StateUpdateCallbackEntry(UpdatePrimitiveRestartState,
nameof(ThreedClassState.PrimitiveRestartDrawArrays),
nameof(ThreedClassState.PrimitiveRestartState)),
new StateUpdateCallbackEntry(UpdateTessellationState,
nameof(ThreedClassState.TessOuterLevel),
nameof(ThreedClassState.TessInnerLevel),
@@ -140,8 +145,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
nameof(ThreedClassState.PointSpriteEnable),
nameof(ThreedClassState.PointCoordReplace)),
new StateUpdateCallbackEntry(UpdatePrimitiveRestartState, nameof(ThreedClassState.PrimitiveRestartState)),
new StateUpdateCallbackEntry(UpdateIndexBufferState,
nameof(ThreedClassState.IndexBufferState),
nameof(ThreedClassState.IndexBufferCount)),
@@ -197,6 +200,17 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
if (_drawState.DrawIndexed != _prevDrawIndexed)
{
_updateTracker.ForceDirty(VertexBufferStateIndex);
// If PrimitiveRestartDrawArrays is false and this is a non-indexed draw, we need to ensure primitive restart is disabled.
// If PrimitiveRestartDrawArrays is false and this is a indexed draw, we need to ensure primitive restart enable matches GPU state.
// If PrimitiveRestartDrawArrays is true, then primitive restart enable should always match GPU state.
// That is because "PrimitiveRestartDrawArrays" is not configurable on the backend, it is always
// true on OpenGL and always false on Vulkan.
if (!_state.State.PrimitiveRestartDrawArrays && _state.State.PrimitiveRestartState.Enable)
{
_updateTracker.ForceDirty(PrimitiveRestartStateIndex);
}
_prevDrawIndexed = _drawState.DrawIndexed;
}
@@ -816,8 +830,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
private void UpdatePrimitiveRestartState()
{
PrimitiveRestartState primitiveRestart = _state.State.PrimitiveRestartState;
bool enable = primitiveRestart.Enable && (_drawState.DrawIndexed || _state.State.PrimitiveRestartDrawArrays);
_context.Renderer.Pipeline.SetPrimitiveRestart(primitiveRestart.Enable, primitiveRestart.Index);
_context.Renderer.Pipeline.SetPrimitiveRestart(enable, primitiveRestart.Index);
}
/// <summary>

View File

@@ -730,7 +730,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
public int PatchVertices;
public fixed uint ReservedDD0[4];
public uint TextureBarrier;
public fixed uint ReservedDE4[7];
public uint WatchdogTimer;
public Boolean32 PrimitiveRestartDrawArrays;
public fixed uint ReservedDEC[5];
public Array16<ScissorState> ScissorState;
public fixed uint ReservedF00[21];
public StencilBackMasks StencilBackMasks;

View File

@@ -444,8 +444,8 @@ namespace Ryujinx.Graphics.OpenGL
return TextureTarget.Texture2DArray;
case Target.Texture2DMultisample:
return TextureTarget.Texture2DMultisample;
case Target.Rectangle:
return TextureTarget.TextureRectangle;
case Target.Texture2DMultisampleArray:
return TextureTarget.Texture2DMultisampleArray;
case Target.Cubemap:
return TextureTarget.TextureCubeMap;
case Target.CubemapArray:

View File

@@ -70,6 +70,25 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
AppendLine("}" + suffix);
}
public (TextureDescriptor, int) FindTextureDescriptor(AstTextureOperation texOp)
{
TextureDescriptor[] descriptors = Config.GetTextureDescriptors();
for (int i = 0; i < descriptors.Length; i++)
{
var descriptor = descriptors[i];
if (descriptor.CbufSlot == texOp.CbufSlot &&
descriptor.HandleIndex == texOp.Handle &&
descriptor.Format == texOp.Format)
{
return (descriptor, i);
}
}
return (default, -1);
}
private static int FindDescriptorIndex(TextureDescriptor[] array, AstTextureOperation texOp)
{
for (int i = 0; i < array.Length; i++)

View File

@@ -756,27 +756,34 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
string samplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr);
int lodSrcIndex = isBindless || isIndexed ? 1 : 0;
IAstNode lod = operation.GetSource(lodSrcIndex);
string lodExpr = GetSoureExpr(context, lod, GetSrcVarType(operation.Inst, lodSrcIndex));
if (texOp.Index == 3)
{
return $"textureQueryLevels({samplerName})";
}
else
{
string texCall = $"textureSize({samplerName}, {lodExpr}){GetMask(texOp.Index)}";
(TextureDescriptor descriptor, int descriptorIndex) = context.FindTextureDescriptor(texOp);
bool hasLod = !descriptor.Type.HasFlag(SamplerType.Multisample) && descriptor.Type != SamplerType.TextureBuffer;
string texCall;
if (hasLod)
{
int lodSrcIndex = isBindless || isIndexed ? 1 : 0;
IAstNode lod = operation.GetSource(lodSrcIndex);
string lodExpr = GetSoureExpr(context, lod, GetSrcVarType(operation.Inst, lodSrcIndex));
texCall = $"textureSize({samplerName}, {lodExpr}){GetMask(texOp.Index)}";
}
else
{
texCall = $"textureSize({samplerName}){GetMask(texOp.Index)}";
}
if (context.Config.Stage.SupportsRenderScale() &&
!isBindless &&
!isIndexed)
{
int index = context.FindTextureDescriptorIndex(texOp);
texCall = "Helper_TextureSizeUnscale(" + texCall + ", " + index + ")";
texCall = $"Helper_TextureSizeUnscale({texCall}, {descriptorIndex})";
}
return texCall;