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 SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp);
void SetDepthMode(DepthMode mode);
void SetDepthTest(DepthTestDescriptor depthTest);
void SetFaceCulling(bool enable, Face face);
@ -56,6 +54,9 @@ namespace Ryujinx.Graphics.GAL
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 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>
private void Clear(GpuState state, int argument)
{
// Scissor affects clears aswell.
if (state.QueryModified(MethodOffset.ScissorState))
{
UpdateScissorState(state);
}
UpdateRenderTargetState(state, useControl: false);
TextureManager.CommitGraphicsBindings();

View file

@ -117,6 +117,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
UpdateRenderTargetState(state, useControl: true);
}
if (state.QueryModified(MethodOffset.ScissorState))
{
UpdateScissorState(state);
}
if (state.QueryModified(MethodOffset.DepthTestEnable,
MethodOffset.DepthWriteEnable,
MethodOffset.DepthTestFunc))
@ -321,6 +326,27 @@ namespace Ryujinx.Graphics.Gpu.Engine
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>
/// Updates host depth test state based on current GPU state.
/// </summary>

View file

@ -57,6 +57,7 @@ namespace Ryujinx.Graphics.Gpu.State
new TableItem(MethodOffset.ViewportExtents, typeof(ViewportExtents), 8),
new TableItem(MethodOffset.VertexBufferDrawState, typeof(VertexBufferDrawState), 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.RtDepthStencilState, typeof(RtDepthStencilState), 1),
new TableItem(MethodOffset.VertexAttribState, typeof(VertexAttribState), 16),

View file

@ -33,6 +33,7 @@ namespace Ryujinx.Graphics.Gpu.State
ClearStencilValue = 0x368,
DepthBiasState = 0x370,
TextureBarrier = 0x378,
ScissorState = 0x380,
StencilBackMasks = 0x3d5,
InvalidateTextures = 0x3dd,
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 readonly bool[] _scissorEnable;
internal Pipeline()
{
_clipOrigin = ClipOrigin.LowerLeft;
_clipDepthMode = ClipDepthMode.NegativeOneToOne;
_scissorEnable = new bool[8];
}
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)
{
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()
{
_framebuffer?.Dispose();

View file

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

View file

@ -6,9 +6,16 @@ namespace Ryujinx.Graphics.OpenGL
{
class TextureCopy : IDisposable
{
private readonly Renderer _renderer;
private int _srcFramebuffer;
private int _dstFramebuffer;
public TextureCopy(Renderer renderer)
{
_renderer = renderer;
}
public void Copy(
TextureView src,
TextureView dst,
@ -34,6 +41,8 @@ namespace Ryujinx.Graphics.OpenGL
GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
GL.Disable(EnableCap.ScissorTest);
GL.BlitFramebuffer(
srcRegion.X1,
srcRegion.Y1,
@ -48,6 +57,8 @@ namespace Ryujinx.Graphics.OpenGL
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
((Pipeline)_renderer.Pipeline).RestoreScissorEnable();
}
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 NativeHeight = 720;
private readonly Renderer _renderer;
private int _width;
private int _height;
private int _copyFramebufferHandle;
public Window()
public Window(Renderer renderer)
{
_renderer = renderer;
_width = NativeWidth;
_height = NativeHeight;
}
@ -35,13 +39,13 @@ namespace Ryujinx.Graphics.OpenGL
_height = height;
}
private void CopyTextureToFrameBufferRGB(int drawFramebuffer, int readFramebuffer, TextureView view, ImageCrop crop)
{
bool[] oldFramebufferColorWritemask = new bool[4];
int oldReadFramebufferHandle = GL.GetInteger(GetPName.ReadFramebufferBinding);
int oldDrawFramebufferHandle = GL.GetInteger(GetPName.DrawFramebufferBinding);
GL.GetBoolean(GetIndexedPName.ColorWritemask, drawFramebuffer, oldFramebufferColorWritemask);
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, drawFramebuffer);
@ -55,6 +59,8 @@ namespace Ryujinx.Graphics.OpenGL
GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
GL.Disable(EnableCap.ScissorTest);
GL.Clear(ClearBufferMask.ColorBufferBit);
int srcX0, srcX1, srcY0, srcY1;
@ -119,6 +125,8 @@ namespace Ryujinx.Graphics.OpenGL
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
((Pipeline)_renderer.Pipeline).RestoreScissorEnable();
}
private int GetCopyFramebufferHandleLazy()