Fixed Scissor Test on Intel based GPUs (#595)

* Reworked scissor tests to remove fixme and handle issues with intel gpu's

* Error handling for scissor tests

* Disable strict opengl by default

* Reformatting for JD

* Updated scheme for new property in config

* Fixed typo

* Moved magic value to constant. I liked the magic :(

* Fixed ordering for undertale

* Fixed undertale bug

* Removed strict opengl in favour of required. With this an exception is no longer thrown, just a warning for required extensions

* Uses clamp instead of if's

* Removed evil tabs and no longer used include
This commit is contained in:
BaronKiko 2019-03-02 10:50:21 +00:00 committed by jduncanator
parent e8aaa39396
commit 18db1a97cb
6 changed files with 171 additions and 73 deletions

View file

@ -1,19 +1,23 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Logging;
using System;
namespace Ryujinx.Graphics.Gal.OpenGL
{
static class OGLExtension
{
// Private lazy backing variables
private static Lazy<bool> s_EnhancedLayouts = new Lazy<bool>(() => HasExtension("GL_ARB_enhanced_layouts"));
private static Lazy<bool> s_TextureMirrorClamp = new Lazy<bool>(() => HasExtension("GL_EXT_texture_mirror_clamp"));
private static Lazy<bool> s_ViewportArray = new Lazy<bool>(() => HasExtension("GL_ARB_viewport_array"));
private static Lazy<bool> s_NvidiaDriver = new Lazy<bool>(() => IsNvidiaDriver());
// Public accessors
public static bool EnhancedLayouts => s_EnhancedLayouts.Value;
public static bool TextureMirrorClamp => s_TextureMirrorClamp.Value;
public static bool ViewportArray => s_ViewportArray.Value;
public static bool NvidiaDrvier => s_NvidiaDriver.Value;
private static bool HasExtension(string Name)
@ -28,11 +32,39 @@ namespace Ryujinx.Graphics.Gal.OpenGL
}
}
Logger.PrintInfo(LogClass.Gpu, $"OpenGL extension {Name} unavailable. You may experience some performance degredation");
return false;
}
private static bool IsNvidiaDriver() {
private static bool IsNvidiaDriver()
{
return GL.GetString(StringName.Vendor).Equals("NVIDIA Corporation");
}
public static class Required
{
// Public accessors
public static bool EnhancedLayouts => s_EnhancedLayoutsRequired.Value;
public static bool TextureMirrorClamp => s_TextureMirrorClampRequired.Value;
public static bool ViewportArray => s_ViewportArrayRequired.Value;
// Private lazy backing variables
private static Lazy<bool> s_EnhancedLayoutsRequired = new Lazy<bool>(() => HasExtensionRequired(OGLExtension.EnhancedLayouts, "GL_ARB_enhanced_layouts"));
private static Lazy<bool> s_TextureMirrorClampRequired = new Lazy<bool>(() => HasExtensionRequired(OGLExtension.TextureMirrorClamp, "GL_EXT_texture_mirror_clamp"));
private static Lazy<bool> s_ViewportArrayRequired = new Lazy<bool>(() => HasExtensionRequired(OGLExtension.ViewportArray, "GL_ARB_viewport_array"));
private static bool HasExtensionRequired(bool Value, string Name)
{
if (Value)
{
return true;
}
Logger.PrintWarning(LogClass.Gpu, $"Required OpenGL extension {Name} unavailable. You may experience some rendering issues");
return false;
}
}
}
}
}

View file

@ -270,47 +270,52 @@ namespace Ryujinx.Graphics.Gal.OpenGL
// Scissor Test
bool forceUpdate;
for (int Index = 0; Index < New.ScissorTestCount; Index++)
// 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
if (New.ScissorTestCount != 0)
{
forceUpdate = false;
int scissorsApplied = 0;
bool applyToAll = false;
if (New.ScissorTestEnabled[Index])
for (int Index = 0; Index < GalPipelineState.RenderTargetsCount; Index++)
{
// If there is only 1 scissor test, geometry shaders are disabled so the scissor test applies to all viewports
if (New.ScissorTestCount == 1)
if (New.ScissorTestEnabled[Index])
{
GL.Enable(EnableCap.ScissorTest);
}
else
{
GL.Enable(IndexedEnableCap.ScissorTest, Index);
}
forceUpdate = true;
}
else
{
GL.Disable(IndexedEnableCap.ScissorTest, Index);
}
// If viewport arrays are unavailable apply first scissor test to all or
// there is only 1 scissor test and it's the first, the scissor test applies to all viewports
if (!OGLExtension.Required.ViewportArray || (Index == 0 && New.ScissorTestCount == 1))
{
GL.Enable(EnableCap.ScissorTest);
applyToAll = true;
}
else
{
GL.Enable(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.ScissorTestEnabled[Index] != Old.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])
{
if (applyToAll)
{
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 all scissor tests have been applied, or viewport arrays are unavailable we can skip remaining itterations
if (!OGLExtension.Required.ViewportArray || ++scissorsApplied == New.ScissorTestCount)
{
break;
}
}
}
}
@ -378,6 +383,14 @@ namespace Ryujinx.Graphics.Gal.OpenGL
Old = New;
}
public void Unbind(GalPipelineState State)
{
if (State.ScissorTestCount > 0)
{
GL.Disable(EnableCap.ScissorTest);
}
}
private void SetAllBlendState(BlendState New)
{
Enable(EnableCap.Blend, New.Enabled);

View file

@ -367,9 +367,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.Disable(EnableCap.FramebufferSrgb);
// Will be re-enabled if needed while binding, called before any game GL calls
GL.Disable(EnableCap.ScissorTest);
GL.BlitFramebuffer(
SrcX0,
SrcY0,