Implement GPU scissors (#1058)
* Implement GPU scissors * Remove unused using * Add missing changes for Clear
This commit is contained in:
parent
06bf25521f
commit
ab4867505e
10 changed files with 107 additions and 7 deletions
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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,
|
||||||
|
|
12
Ryujinx.Graphics.Gpu/State/ScissorState.cs
Normal file
12
Ryujinx.Graphics.Gpu/State/ScissorState.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Reference in a new issue