forked from Mirror/Ryujinx
Scissor test implementation. Partially stubbed until geometry shaders… (#556)
* Scissor test implementation. Partially stubbed until geometry shaders are fixed * Apply to all viewports when geometry shaders are disabled. * Also apply enable cap to all viewports when geometry shaders are disabled * Added fixme as per suggestion Co-Authored-By: BaronKiko <BaronKiko@users.noreply.github.com> * Apparently no alignment needed here. * Comment on new line * Correct height calculation
This commit is contained in:
parent
8406ec6272
commit
0cd5ba03fe
4 changed files with 103 additions and 0 deletions
|
@ -91,6 +91,13 @@
|
||||||
public GalStencilOp StencilFrontOpZPass;
|
public GalStencilOp StencilFrontOpZPass;
|
||||||
public uint StencilFrontMask;
|
public uint StencilFrontMask;
|
||||||
|
|
||||||
|
public int ScissorTestCount;
|
||||||
|
public bool[] ScissorTestEnabled;
|
||||||
|
public int[] ScissorTestX;
|
||||||
|
public int[] ScissorTestY;
|
||||||
|
public int[] ScissorTestWidth;
|
||||||
|
public int[] ScissorTestHeight;
|
||||||
|
|
||||||
public bool BlendIndependent;
|
public bool BlendIndependent;
|
||||||
public BlendState[] Blends;
|
public BlendState[] Blends;
|
||||||
|
|
||||||
|
@ -111,6 +118,12 @@
|
||||||
|
|
||||||
Blends = new BlendState[RenderTargetsCount];
|
Blends = new BlendState[RenderTargetsCount];
|
||||||
|
|
||||||
|
ScissorTestEnabled = new bool[RenderTargetsCount];
|
||||||
|
ScissorTestY = new int[RenderTargetsCount];
|
||||||
|
ScissorTestX = new int[RenderTargetsCount];
|
||||||
|
ScissorTestWidth = new int[RenderTargetsCount];
|
||||||
|
ScissorTestHeight = new int[RenderTargetsCount];
|
||||||
|
|
||||||
ColorMasks = new ColorMaskState[RenderTargetsCount];
|
ColorMasks = new ColorMaskState[RenderTargetsCount];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,6 +270,57 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Scissor Test
|
||||||
|
bool forceUpdate;
|
||||||
|
|
||||||
|
for (int Index = 0; Index < New.ScissorTestCount; Index++)
|
||||||
|
{
|
||||||
|
forceUpdate = false;
|
||||||
|
|
||||||
|
if (New.ScissorTestEnabled[Index] != Old.ScissorTestEnabled[Index])
|
||||||
|
{
|
||||||
|
if (New.ScissorTestEnabled[Index])
|
||||||
|
{
|
||||||
|
// If there is only 1 scissor test geometry shaders are disables so the scissor test applies to all viewports
|
||||||
|
if (New.ScissorTestCount == 1)
|
||||||
|
{
|
||||||
|
GL.Enable(EnableCap.ScissorTest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GL.Enable(IndexedEnableCap.ScissorTest, Index);
|
||||||
|
}
|
||||||
|
forceUpdate = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GL.Disable(IndexedEnableCap.ScissorTest, Index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (New.ScissorTestEnabled[Index] &&
|
||||||
|
(New.ScissorTestX[Index] != Old.ScissorTestX[Index] ||
|
||||||
|
New.ScissorTestY[Index] != Old.ScissorTestY[Index] ||
|
||||||
|
New.ScissorTestWidth[Index] != Old.ScissorTestWidth[Index] ||
|
||||||
|
New.ScissorTestHeight[Index] != Old.ScissorTestHeight[Index] ||
|
||||||
|
forceUpdate)) // Force update intentionally last to reduce if comparisons
|
||||||
|
{
|
||||||
|
// If there is only 1 scissor test geometry shaders are disables so the scissor test applies to all viewports
|
||||||
|
if (New.ScissorTestCount == 1)
|
||||||
|
{
|
||||||
|
GL.Scissor(New.ScissorTestX[Index], New.ScissorTestY[Index],
|
||||||
|
New.ScissorTestWidth[Index], New.ScissorTestHeight[Index]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GL.ScissorIndexed(Index, New.ScissorTestX[Index], New.ScissorTestY[Index],
|
||||||
|
New.ScissorTestWidth[Index], New.ScissorTestHeight[Index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (New.BlendIndependent)
|
if (New.BlendIndependent)
|
||||||
{
|
{
|
||||||
for (int Index = 0; Index < GalPipelineState.RenderTargetsCount; Index++)
|
for (int Index = 0; Index < GalPipelineState.RenderTargetsCount; Index++)
|
||||||
|
|
|
@ -24,6 +24,9 @@ namespace Ryujinx.Graphics.Graphics3d
|
||||||
|
|
||||||
private ConstBuffer[][] ConstBuffers;
|
private ConstBuffer[][] ConstBuffers;
|
||||||
|
|
||||||
|
// Height kept for flipping y axis
|
||||||
|
private int ViewportHeight = 0;
|
||||||
|
|
||||||
private int CurrentInstance = 0;
|
private int CurrentInstance = 0;
|
||||||
|
|
||||||
public NvGpuEngine3d(NvGpu Gpu)
|
public NvGpuEngine3d(NvGpu Gpu)
|
||||||
|
@ -97,6 +100,7 @@ namespace Ryujinx.Graphics.Graphics3d
|
||||||
SetCullFace(State);
|
SetCullFace(State);
|
||||||
SetDepth(State);
|
SetDepth(State);
|
||||||
SetStencil(State);
|
SetStencil(State);
|
||||||
|
SetScissor(State);
|
||||||
SetBlending(State);
|
SetBlending(State);
|
||||||
SetColorMask(State);
|
SetColorMask(State);
|
||||||
SetPrimitiveRestart(State);
|
SetPrimitiveRestart(State);
|
||||||
|
@ -208,6 +212,8 @@ namespace Ryujinx.Graphics.Graphics3d
|
||||||
|
|
||||||
Gpu.ResourceManager.SendColorBuffer(Vmm, Key, FbIndex, Image);
|
Gpu.ResourceManager.SendColorBuffer(Vmm, Key, FbIndex, Image);
|
||||||
|
|
||||||
|
ViewportHeight = VpH;
|
||||||
|
|
||||||
Gpu.Renderer.RenderTarget.SetViewport(FbIndex, VpX, VpY, VpW, VpH);
|
Gpu.Renderer.RenderTarget.SetViewport(FbIndex, VpX, VpY, VpW, VpH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,6 +413,36 @@ namespace Ryujinx.Graphics.Graphics3d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetScissor(GalPipelineState State)
|
||||||
|
{
|
||||||
|
// FIXME: Stubbed, only the first scissor test is valid without a geometry shader loaded. At time of writing geometry shaders are also stubbed.
|
||||||
|
// Once geometry shaders are fixed it should be equal to GalPipelineState.RenderTargetCount when shader loaded, otherwise equal to 1
|
||||||
|
State.ScissorTestCount = 1;
|
||||||
|
|
||||||
|
for (int Index = 0; Index < GalPipelineState.RenderTargetsCount; Index++)
|
||||||
|
{
|
||||||
|
State.ScissorTestEnabled[Index] = ReadRegisterBool(NvGpuEngine3dReg.ScissorEnable + Index * 4);
|
||||||
|
|
||||||
|
if (State.ScissorTestEnabled[Index])
|
||||||
|
{
|
||||||
|
uint ScissorHorizontal = (uint)ReadRegister(NvGpuEngine3dReg.ScissorHorizontal + Index * 4);
|
||||||
|
uint ScissorVertical = (uint)ReadRegister(NvGpuEngine3dReg.ScissorVertical + Index * 4);
|
||||||
|
|
||||||
|
State.ScissorTestX[Index] = (int)((ScissorHorizontal & 0xFFFF) * State.FlipX); // X, lower 16 bits
|
||||||
|
State.ScissorTestWidth[Index] = (int)((ScissorHorizontal >> 16) * State.FlipX) - State.ScissorTestX[Index]; // Width, right side is upper 16 bits
|
||||||
|
|
||||||
|
State.ScissorTestY[Index] = (int)((ScissorVertical & 0xFFFF)); // Y, lower 16 bits
|
||||||
|
State.ScissorTestHeight[Index] = (int)((ScissorVertical >> 16)) - State.ScissorTestY[Index]; // Height, top side is upper 16 bits
|
||||||
|
|
||||||
|
// Y coordinates may have to be flipped
|
||||||
|
if ((int)State.FlipY == -1)
|
||||||
|
{
|
||||||
|
State.ScissorTestY[Index] = ViewportHeight - State.ScissorTestY[Index] - State.ScissorTestHeight[Index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void SetBlending(GalPipelineState State)
|
private void SetBlending(GalPipelineState State)
|
||||||
{
|
{
|
||||||
bool BlendIndependent = ReadRegisterBool(NvGpuEngine3dReg.BlendIndependent);
|
bool BlendIndependent = ReadRegisterBool(NvGpuEngine3dReg.BlendIndependent);
|
||||||
|
|
|
@ -22,6 +22,9 @@ namespace Ryujinx.Graphics.Graphics3d
|
||||||
ClearNColor = 0x360,
|
ClearNColor = 0x360,
|
||||||
ClearDepth = 0x364,
|
ClearDepth = 0x364,
|
||||||
ClearStencil = 0x368,
|
ClearStencil = 0x368,
|
||||||
|
ScissorEnable = 0x380,
|
||||||
|
ScissorHorizontal = 0x381,
|
||||||
|
ScissorVertical = 0x382,
|
||||||
StencilBackFuncRef = 0x3d5,
|
StencilBackFuncRef = 0x3d5,
|
||||||
StencilBackMask = 0x3d6,
|
StencilBackMask = 0x3d6,
|
||||||
StencilBackFuncMask = 0x3d7,
|
StencilBackFuncMask = 0x3d7,
|
||||||
|
|
Loading…
Reference in a new issue