Reworked scissor tests to remove fixme and handle issues with intel gpu's
This commit is contained in:
parent
dd00a4b62d
commit
9f528d565e
2 changed files with 150 additions and 63 deletions
|
@ -270,39 +270,35 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
|
|
||||||
// Scissor Test
|
// Scissor Test
|
||||||
bool forceUpdate;
|
// All scissor test are disabled before drawing final framebuffer to screen so we don't need to handle disabling
|
||||||
|
// Skip if there are no scissor tests to enable
|
||||||
for (int Index = 0; Index < New.ScissorTestCount; Index++)
|
if (New.ScissorTestCount != 0)
|
||||||
{
|
{
|
||||||
forceUpdate = false;
|
int scissorsApplied = 0;
|
||||||
|
bool applyToAll = false;
|
||||||
|
|
||||||
|
for (int Index = 0; Index < GalPipelineState.RenderTargetsCount; Index++)
|
||||||
|
{
|
||||||
if (New.ScissorTestEnabled[Index])
|
if (New.ScissorTestEnabled[Index])
|
||||||
{
|
{
|
||||||
// If there is only 1 scissor test, geometry shaders are disabled so the scissor test applies to all viewports
|
// If there is only 1 scissor test, and it's the first, the scissor test applies to all viewports
|
||||||
if (New.ScissorTestCount == 1)
|
if (Index == 0 && New.ScissorTestCount == 1)
|
||||||
{
|
{
|
||||||
GL.Enable(EnableCap.ScissorTest);
|
GL.Enable(EnableCap.ScissorTest);
|
||||||
|
applyToAll = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GL.Enable(IndexedEnableCap.ScissorTest, Index);
|
GL.Enable(IndexedEnableCap.ScissorTest, Index);
|
||||||
}
|
}
|
||||||
forceUpdate = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GL.Disable(IndexedEnableCap.ScissorTest, Index);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (New.ScissorTestEnabled[Index] &&
|
if (New.ScissorTestEnabled[Index] != Old.ScissorTestEnabled[Index] ||
|
||||||
(New.ScissorTestX[Index] != Old.ScissorTestX[Index] ||
|
New.ScissorTestX[Index] != Old.ScissorTestX[Index] ||
|
||||||
New.ScissorTestY[Index] != Old.ScissorTestY[Index] ||
|
New.ScissorTestY[Index] != Old.ScissorTestY[Index] ||
|
||||||
New.ScissorTestWidth[Index] != Old.ScissorTestWidth[Index] ||
|
New.ScissorTestWidth[Index] != Old.ScissorTestWidth[Index] ||
|
||||||
New.ScissorTestHeight[Index] != Old.ScissorTestHeight[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 (applyToAll)
|
||||||
if (New.ScissorTestCount == 1)
|
|
||||||
{
|
{
|
||||||
GL.Scissor(New.ScissorTestX[Index], New.ScissorTestY[Index],
|
GL.Scissor(New.ScissorTestX[Index], New.ScissorTestY[Index],
|
||||||
New.ScissorTestWidth[Index], New.ScissorTestHeight[Index]);
|
New.ScissorTestWidth[Index], New.ScissorTestHeight[Index]);
|
||||||
|
@ -313,6 +309,14 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
New.ScissorTestWidth[Index], New.ScissorTestHeight[Index]);
|
New.ScissorTestWidth[Index], New.ScissorTestHeight[Index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If all scissor tests have been applied so we can skip remaining itterations
|
||||||
|
if (++scissorsApplied == New.ScissorTestCount)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,12 @@ namespace Ryujinx.Graphics.Graphics3d
|
||||||
|
|
||||||
private ConstBuffer[][] ConstBuffers;
|
private ConstBuffer[][] ConstBuffers;
|
||||||
|
|
||||||
// Height kept for flipping y axis
|
// Viewport dimensions kept for scissor test limits
|
||||||
|
private int ViewportX0 = 0;
|
||||||
|
private int ViewportY0 = 0;
|
||||||
|
private int ViewportX1 = 0;
|
||||||
|
private int ViewportY1 = 0;
|
||||||
|
private int ViewportWidth = 0;
|
||||||
private int ViewportHeight = 0;
|
private int ViewportHeight = 0;
|
||||||
|
|
||||||
private int CurrentInstance = 0;
|
private int CurrentInstance = 0;
|
||||||
|
@ -200,11 +205,11 @@ namespace Ryujinx.Graphics.Graphics3d
|
||||||
float SX = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNScaleX + FbIndex * 8);
|
float SX = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNScaleX + FbIndex * 8);
|
||||||
float SY = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNScaleY + FbIndex * 8);
|
float SY = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNScaleY + FbIndex * 8);
|
||||||
|
|
||||||
int VpX = (int)MathF.Max(0, TX - MathF.Abs(SX));
|
ViewportX0 = (int)MathF.Max(0, TX - MathF.Abs(SX));
|
||||||
int VpY = (int)MathF.Max(0, TY - MathF.Abs(SY));
|
ViewportY0 = (int)MathF.Max(0, TY - MathF.Abs(SY));
|
||||||
|
|
||||||
int VpW = (int)(TX + MathF.Abs(SX)) - VpX;
|
ViewportX1 = (int)(TX + MathF.Abs(SX));
|
||||||
int VpH = (int)(TY + MathF.Abs(SY)) - VpY;
|
ViewportY1 = (int)(TY + MathF.Abs(SY));
|
||||||
|
|
||||||
GalImageFormat Format = ImageUtils.ConvertSurface((GalSurfaceFormat)SurfFormat);
|
GalImageFormat Format = ImageUtils.ConvertSurface((GalSurfaceFormat)SurfFormat);
|
||||||
|
|
||||||
|
@ -212,9 +217,7 @@ 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, ViewportX0, ViewportY0, ViewportX1 - ViewportX0, ViewportY1 - ViewportY0);
|
||||||
|
|
||||||
Gpu.Renderer.RenderTarget.SetViewport(FbIndex, VpX, VpY, VpW, VpH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetFrameBuffer(GalPipelineState State)
|
private void SetFrameBuffer(GalPipelineState State)
|
||||||
|
@ -415,11 +418,9 @@ namespace Ryujinx.Graphics.Graphics3d
|
||||||
|
|
||||||
private void SetScissor(GalPipelineState State)
|
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.
|
int count = 0;
|
||||||
// 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 < State.ScissorTestCount; Index++)
|
for (int Index = 0; Index < GalPipelineState.RenderTargetsCount; Index++)
|
||||||
{
|
{
|
||||||
State.ScissorTestEnabled[Index] = ReadRegisterBool(NvGpuEngine3dReg.ScissorEnable + Index * 4);
|
State.ScissorTestEnabled[Index] = ReadRegisterBool(NvGpuEngine3dReg.ScissorEnable + Index * 4);
|
||||||
|
|
||||||
|
@ -428,25 +429,107 @@ namespace Ryujinx.Graphics.Graphics3d
|
||||||
uint ScissorHorizontal = (uint)ReadRegister(NvGpuEngine3dReg.ScissorHorizontal + Index * 4);
|
uint ScissorHorizontal = (uint)ReadRegister(NvGpuEngine3dReg.ScissorHorizontal + Index * 4);
|
||||||
uint ScissorVertical = (uint)ReadRegister(NvGpuEngine3dReg.ScissorVertical + Index * 4);
|
uint ScissorVertical = (uint)ReadRegister(NvGpuEngine3dReg.ScissorVertical + Index * 4);
|
||||||
|
|
||||||
State.ScissorTestX[Index] = (int)((ScissorHorizontal & 0xFFFF) * State.FlipX); // X, lower 16 bits
|
int left = (int)(ScissorHorizontal & 0xFFFF); // Left, lower 16 bits
|
||||||
State.ScissorTestWidth[Index] = (int)((ScissorHorizontal >> 16) * State.FlipX) - State.ScissorTestX[Index]; // Width, right side is upper 16 bits
|
int right = (int)(ScissorHorizontal >> 16); // Right, upper 16 bits
|
||||||
|
|
||||||
State.ScissorTestY[Index] = (int)((ScissorVertical & 0xFFFF)); // Y, lower 16 bits
|
int bottom = (int)(ScissorVertical & 0xFFFF); // Bottom, lower 16 bits
|
||||||
State.ScissorTestHeight[Index] = (int)((ScissorVertical >> 16)) - State.ScissorTestY[Index]; // Height, top side is upper 16 bits
|
int top = (int)(ScissorVertical >> 16); // Top, upper 16 bits
|
||||||
|
|
||||||
// Y coordinates may have to be flipped
|
int width = Math.Abs(right - left);
|
||||||
if ((int)State.FlipY == -1)
|
int height = Math.Abs(top - bottom);
|
||||||
|
|
||||||
|
// If the scissor test covers the whole possible viewport, i.e. uninititalized, disable scissor test
|
||||||
|
if ((width > 16383 && height > 16383) || width <= 0 || height <= 0)
|
||||||
{
|
{
|
||||||
State.ScissorTestY[Index] = ViewportHeight - State.ScissorTestY[Index] - State.ScissorTestHeight[Index];
|
State.ScissorTestEnabled[Index] = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle negative viewpont coordinate
|
// Keep track of how many scissor tests are active.
|
||||||
if (State.ScissorTestY[Index] < 0)
|
// If only 1, and it's the first user should apply to all viewports
|
||||||
|
count++;
|
||||||
|
|
||||||
|
// Flip X
|
||||||
|
if (State.FlipX == -1)
|
||||||
{
|
{
|
||||||
State.ScissorTestY[Index] = 0;
|
left = ViewportX1 - (left - ViewportX0);
|
||||||
}
|
right = ViewportX1 - (right - ViewportX0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure X is in the right order
|
||||||
|
if (left > right)
|
||||||
|
{
|
||||||
|
int temp = left;
|
||||||
|
left = right;
|
||||||
|
right = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flip Y
|
||||||
|
if (State.FlipY == -1)
|
||||||
|
{
|
||||||
|
bottom = ViewportY1 - (bottom - ViewportY0);
|
||||||
|
top = ViewportY1 - (top - ViewportY0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure Y is in the right order
|
||||||
|
if (bottom > top)
|
||||||
|
{
|
||||||
|
int temp = top;
|
||||||
|
top = bottom;
|
||||||
|
bottom = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle out of active viewport dimensions
|
||||||
|
// Left
|
||||||
|
if (left < ViewportX0)
|
||||||
|
{
|
||||||
|
left = ViewportX0;
|
||||||
|
}
|
||||||
|
else if (left > ViewportX1)
|
||||||
|
{
|
||||||
|
left = ViewportX1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right
|
||||||
|
if (right < ViewportX0)
|
||||||
|
{
|
||||||
|
right = ViewportX0;
|
||||||
|
}
|
||||||
|
else if (right > ViewportX1)
|
||||||
|
{
|
||||||
|
right = ViewportX1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bottom
|
||||||
|
if (bottom < ViewportY0)
|
||||||
|
{
|
||||||
|
bottom = ViewportY0;
|
||||||
|
}
|
||||||
|
else if (bottom > ViewportY1)
|
||||||
|
{
|
||||||
|
bottom = ViewportY1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Top
|
||||||
|
if (top < ViewportX0)
|
||||||
|
{
|
||||||
|
top = ViewportX0;
|
||||||
|
}
|
||||||
|
else if (top > ViewportX1)
|
||||||
|
{
|
||||||
|
top = ViewportX1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save values to state
|
||||||
|
State.ScissorTestX[Index] = left;
|
||||||
|
State.ScissorTestY[Index] = bottom;
|
||||||
|
|
||||||
|
State.ScissorTestWidth[Index] = right - left;
|
||||||
|
State.ScissorTestHeight[Index] = top - bottom;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
State.ScissorTestCount = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetBlending(GalPipelineState State)
|
private void SetBlending(GalPipelineState State)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue