Implement GPU scissors (#1058)

* Implement GPU scissors

* Remove unused using

* Add missing changes for Clear
This commit is contained in:
gdkchan 2020-03-29 00:02:58 -03:00 committed by GitHub
parent 06bf25521f
commit ab4867505e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 107 additions and 7 deletions

View file

@ -29,9 +29,7 @@ namespace Ryujinx.Graphics.GAL
void SetBlendColor(ColorF color); void SetBlendColor(ColorF color);
void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp); void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp);
void SetDepthMode(DepthMode mode); void SetDepthMode(DepthMode mode);
void SetDepthTest(DepthTestDescriptor depthTest); void SetDepthTest(DepthTestDescriptor depthTest);
void SetFaceCulling(bool enable, Face face); void SetFaceCulling(bool enable, Face face);
@ -56,6 +54,9 @@ namespace Ryujinx.Graphics.GAL
void SetSampler(int index, ShaderStage stage, ISampler sampler); void SetSampler(int index, ShaderStage stage, ISampler sampler);
void SetScissorEnable(int index, bool enable);
void SetScissor(int index, int x, int y, int width, int height);
void SetStencilTest(StencilTestDescriptor stencilTest); void SetStencilTest(StencilTestDescriptor stencilTest);
void SetStorageBuffer(int index, ShaderStage stage, BufferRange buffer); void SetStorageBuffer(int index, ShaderStage stage, BufferRange buffer);

View file

@ -13,6 +13,12 @@ namespace Ryujinx.Graphics.Gpu.Engine
/// <param name="argument">Method call argument</param> /// <param name="argument">Method call argument</param>
private void Clear(GpuState state, int argument) private void Clear(GpuState state, int argument)
{ {
// Scissor affects clears aswell.
if (state.QueryModified(MethodOffset.ScissorState))
{
UpdateScissorState(state);
}
UpdateRenderTargetState(state, useControl: false); UpdateRenderTargetState(state, useControl: false);
TextureManager.CommitGraphicsBindings(); TextureManager.CommitGraphicsBindings();

View file

@ -117,6 +117,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
UpdateRenderTargetState(state, useControl: true); UpdateRenderTargetState(state, useControl: true);
} }
if (state.QueryModified(MethodOffset.ScissorState))
{
UpdateScissorState(state);
}
if (state.QueryModified(MethodOffset.DepthTestEnable, if (state.QueryModified(MethodOffset.DepthTestEnable,
MethodOffset.DepthWriteEnable, MethodOffset.DepthWriteEnable,
MethodOffset.DepthTestFunc)) MethodOffset.DepthTestFunc))
@ -321,6 +326,27 @@ namespace Ryujinx.Graphics.Gpu.Engine
return colorState.Format != 0 && colorState.WidthOrStride != 0; return colorState.Format != 0 && colorState.WidthOrStride != 0;
} }
/// <summary>
/// Updates host scissor test state based on current GPU state.
/// </summary>
/// <param name="state">Current GPU state</param>
private void UpdateScissorState(GpuState state)
{
for (int index = 0; index < Constants.TotalViewports; index++)
{
ScissorState scissor = state.Get<ScissorState>(MethodOffset.ScissorState, index);
bool enable = scissor.Enable && (scissor.X1 != 0 || scissor.Y1 != 0 || scissor.X2 != 0xffff || scissor.Y2 != 0xffff);
_context.Renderer.Pipeline.SetScissorEnable(index, enable);
if (enable)
{
_context.Renderer.Pipeline.SetScissor(index, scissor.X1, scissor.Y1, scissor.X2 - scissor.X1, scissor.Y2 - scissor.Y1);
}
}
}
/// <summary> /// <summary>
/// Updates host depth test state based on current GPU state. /// Updates host depth test state based on current GPU state.
/// </summary> /// </summary>

View file

@ -57,6 +57,7 @@ namespace Ryujinx.Graphics.Gpu.State
new TableItem(MethodOffset.ViewportExtents, typeof(ViewportExtents), 8), new TableItem(MethodOffset.ViewportExtents, typeof(ViewportExtents), 8),
new TableItem(MethodOffset.VertexBufferDrawState, typeof(VertexBufferDrawState), 1), new TableItem(MethodOffset.VertexBufferDrawState, typeof(VertexBufferDrawState), 1),
new TableItem(MethodOffset.DepthBiasState, typeof(DepthBiasState), 1), new TableItem(MethodOffset.DepthBiasState, typeof(DepthBiasState), 1),
new TableItem(MethodOffset.ScissorState, typeof(ScissorState), 8),
new TableItem(MethodOffset.StencilBackMasks, typeof(StencilBackMasks), 1), new TableItem(MethodOffset.StencilBackMasks, typeof(StencilBackMasks), 1),
new TableItem(MethodOffset.RtDepthStencilState, typeof(RtDepthStencilState), 1), new TableItem(MethodOffset.RtDepthStencilState, typeof(RtDepthStencilState), 1),
new TableItem(MethodOffset.VertexAttribState, typeof(VertexAttribState), 16), new TableItem(MethodOffset.VertexAttribState, typeof(VertexAttribState), 16),

View file

@ -33,6 +33,7 @@ namespace Ryujinx.Graphics.Gpu.State
ClearStencilValue = 0x368, ClearStencilValue = 0x368,
DepthBiasState = 0x370, DepthBiasState = 0x370,
TextureBarrier = 0x378, TextureBarrier = 0x378,
ScissorState = 0x380,
StencilBackMasks = 0x3d5, StencilBackMasks = 0x3d5,
InvalidateTextures = 0x3dd, InvalidateTextures = 0x3dd,
TextureBarrierTiled = 0x3df, TextureBarrierTiled = 0x3df,

View file

@ -0,0 +1,12 @@
namespace Ryujinx.Graphics.Gpu.State
{
struct ScissorState
{
public Boolean32 Enable;
public ushort X1;
public ushort X2;
public ushort Y1;
public ushort Y2;
public uint Padding;
}
}

View file

@ -31,10 +31,14 @@ namespace Ryujinx.Graphics.OpenGL
private uint[] _componentMasks; private uint[] _componentMasks;
private readonly bool[] _scissorEnable;
internal Pipeline() internal Pipeline()
{ {
_clipOrigin = ClipOrigin.LowerLeft; _clipOrigin = ClipOrigin.LowerLeft;
_clipDepthMode = ClipDepthMode.NegativeOneToOne; _clipDepthMode = ClipDepthMode.NegativeOneToOne;
_scissorEnable = new bool[8];
} }
public void Barrier() public void Barrier()
@ -674,6 +678,25 @@ namespace Ryujinx.Graphics.OpenGL
} }
} }
public void SetScissorEnable(int index, bool enable)
{
if (enable)
{
GL.Enable(IndexedEnableCap.ScissorTest, index);
}
else
{
GL.Disable(IndexedEnableCap.ScissorTest, index);
}
_scissorEnable[index] = enable;
}
public void SetScissor(int index, int x, int y, int width, int height)
{
GL.ScissorIndexed(index, x, y, width, height);
}
public void SetStencilTest(StencilTestDescriptor stencilTest) public void SetStencilTest(StencilTestDescriptor stencilTest)
{ {
if (!stencilTest.TestEnable) if (!stencilTest.TestEnable)
@ -928,6 +951,17 @@ namespace Ryujinx.Graphics.OpenGL
} }
} }
public void RestoreScissorEnable()
{
for (int index = 0; index < 8; index++)
{
if (_scissorEnable[index])
{
GL.Enable(IndexedEnableCap.ScissorTest, index);
}
}
}
public void Dispose() public void Dispose()
{ {
_framebuffer?.Dispose(); _framebuffer?.Dispose();

View file

@ -7,7 +7,7 @@ namespace Ryujinx.Graphics.OpenGL
{ {
public sealed class Renderer : IRenderer public sealed class Renderer : IRenderer
{ {
private Pipeline _pipeline; private readonly Pipeline _pipeline;
public IPipeline Pipeline => _pipeline; public IPipeline Pipeline => _pipeline;
@ -31,9 +31,9 @@ namespace Ryujinx.Graphics.OpenGL
_counters = new Counters(); _counters = new Counters();
_window = new Window(); _window = new Window(this);
TextureCopy = new TextureCopy(); TextureCopy = new TextureCopy(this);
} }
public IShader CompileShader(ShaderProgram shader) public IShader CompileShader(ShaderProgram shader)

View file

@ -6,9 +6,16 @@ namespace Ryujinx.Graphics.OpenGL
{ {
class TextureCopy : IDisposable class TextureCopy : IDisposable
{ {
private readonly Renderer _renderer;
private int _srcFramebuffer; private int _srcFramebuffer;
private int _dstFramebuffer; private int _dstFramebuffer;
public TextureCopy(Renderer renderer)
{
_renderer = renderer;
}
public void Copy( public void Copy(
TextureView src, TextureView src,
TextureView dst, TextureView dst,
@ -34,6 +41,8 @@ namespace Ryujinx.Graphics.OpenGL
GL.ReadBuffer(ReadBufferMode.ColorAttachment0); GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
GL.DrawBuffer(DrawBufferMode.ColorAttachment0); GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
GL.Disable(EnableCap.ScissorTest);
GL.BlitFramebuffer( GL.BlitFramebuffer(
srcRegion.X1, srcRegion.X1,
srcRegion.Y1, srcRegion.Y1,
@ -48,6 +57,8 @@ namespace Ryujinx.Graphics.OpenGL
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle); GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle); GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
((Pipeline)_renderer.Pipeline).RestoreScissorEnable();
} }
private static void Attach(FramebufferTarget target, Format format, int handle) private static void Attach(FramebufferTarget target, Format format, int handle)

View file

@ -9,13 +9,17 @@ namespace Ryujinx.Graphics.OpenGL
private const int NativeWidth = 1280; private const int NativeWidth = 1280;
private const int NativeHeight = 720; private const int NativeHeight = 720;
private readonly Renderer _renderer;
private int _width; private int _width;
private int _height; private int _height;
private int _copyFramebufferHandle; private int _copyFramebufferHandle;
public Window() public Window(Renderer renderer)
{ {
_renderer = renderer;
_width = NativeWidth; _width = NativeWidth;
_height = NativeHeight; _height = NativeHeight;
} }
@ -35,13 +39,13 @@ namespace Ryujinx.Graphics.OpenGL
_height = height; _height = height;
} }
private void CopyTextureToFrameBufferRGB(int drawFramebuffer, int readFramebuffer, TextureView view, ImageCrop crop) private void CopyTextureToFrameBufferRGB(int drawFramebuffer, int readFramebuffer, TextureView view, ImageCrop crop)
{ {
bool[] oldFramebufferColorWritemask = new bool[4]; bool[] oldFramebufferColorWritemask = new bool[4];
int oldReadFramebufferHandle = GL.GetInteger(GetPName.ReadFramebufferBinding); int oldReadFramebufferHandle = GL.GetInteger(GetPName.ReadFramebufferBinding);
int oldDrawFramebufferHandle = GL.GetInteger(GetPName.DrawFramebufferBinding); int oldDrawFramebufferHandle = GL.GetInteger(GetPName.DrawFramebufferBinding);
GL.GetBoolean(GetIndexedPName.ColorWritemask, drawFramebuffer, oldFramebufferColorWritemask); GL.GetBoolean(GetIndexedPName.ColorWritemask, drawFramebuffer, oldFramebufferColorWritemask);
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, drawFramebuffer); GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, drawFramebuffer);
@ -55,6 +59,8 @@ namespace Ryujinx.Graphics.OpenGL
GL.ReadBuffer(ReadBufferMode.ColorAttachment0); GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
GL.Disable(EnableCap.ScissorTest);
GL.Clear(ClearBufferMask.ColorBufferBit); GL.Clear(ClearBufferMask.ColorBufferBit);
int srcX0, srcX1, srcY0, srcY1; int srcX0, srcX1, srcY0, srcY1;
@ -119,6 +125,8 @@ namespace Ryujinx.Graphics.OpenGL
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle); GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle); GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
((Pipeline)_renderer.Pipeline).RestoreScissorEnable();
} }
private int GetCopyFramebufferHandleLazy() private int GetCopyFramebufferHandleLazy()