aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReinUsesLisp <reinuseslisp@airmail.cc>2018-08-10 01:09:40 -0300
committergdkchan <gab.dark.100@gmail.com>2018-08-10 01:09:40 -0300
commit25dd5f4238d898120f2f65c4d5d5b9c192ce1e10 (patch)
tree347a58054594d9236fd9c3fa1432e0ee45b99949
parent652238f526509ed54e1c0ba2e953097ef7b2501c (diff)
Low level graphics API prerequisites (#319)
* Add GalPipelineState and IGalPipeline * Separate UploadVertex call * Add ConstBuffer cache * Move Vertex Assembly into GalPipelineState * Move Uniform binds to GalPipelineState * Move framebuffer flip into a buffer * Rebase * Fix regression * Move clear values from VertexEndGl to ClearBuffers * Rename obscure names O->Old S->New
-rw-r--r--Ryujinx.Graphics/Gal/GalPipelineState.cs73
-rw-r--r--Ryujinx.Graphics/Gal/IGalBlend.cs22
-rw-r--r--Ryujinx.Graphics/Gal/IGalConstBuffer.cs16
-rw-r--r--Ryujinx.Graphics/Gal/IGalPipeline.cs7
-rw-r--r--Ryujinx.Graphics/Gal/IGalRasterizer.cs42
-rw-r--r--Ryujinx.Graphics/Gal/IGalRenderer.cs4
-rw-r--r--Ryujinx.Graphics/Gal/IGalShader.cs4
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLBlend.cs49
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLConstBuffer.cs66
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs379
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs213
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs10
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs222
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLShaderProgram.cs86
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLStreamBuffer.cs10
-rw-r--r--Ryujinx.Graphics/Gal/Shader/GlslDecl.cs1
-rw-r--r--Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs6
-rw-r--r--Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs344
-rw-r--r--Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs1
-rw-r--r--Ryujinx.HLE/Gpu/Memory/NvGpuBufferType.cs1
20 files changed, 854 insertions, 702 deletions
diff --git a/Ryujinx.Graphics/Gal/GalPipelineState.cs b/Ryujinx.Graphics/Gal/GalPipelineState.cs
new file mode 100644
index 00000000..d1ffbe76
--- /dev/null
+++ b/Ryujinx.Graphics/Gal/GalPipelineState.cs
@@ -0,0 +1,73 @@
+namespace Ryujinx.Graphics.Gal
+{
+ public struct GalVertexBinding
+ {
+ //VboKey shouldn't be here, but ARB_vertex_attrib_binding is core since 4.3
+
+ public bool Enabled;
+ public int Stride;
+ public long VboKey;
+ public GalVertexAttrib[] Attribs;
+ }
+
+ public class GalPipelineState
+ {
+ public const int Stages = 5;
+ public const int ConstBuffersPerStage = 18;
+
+ public long[][] ConstBufferKeys;
+
+ public GalVertexBinding[] VertexBindings;
+
+ public float FlipX;
+ public float FlipY;
+
+ public GalFrontFace FrontFace;
+
+ public bool CullFaceEnabled;
+ public GalCullFace CullFace;
+
+ public bool DepthTestEnabled;
+ public GalComparisonOp DepthFunc;
+
+ public bool StencilTestEnabled;
+
+ public GalComparisonOp StencilBackFuncFunc;
+ public int StencilBackFuncRef;
+ public uint StencilBackFuncMask;
+ public GalStencilOp StencilBackOpFail;
+ public GalStencilOp StencilBackOpZFail;
+ public GalStencilOp StencilBackOpZPass;
+ public uint StencilBackMask;
+
+ public GalComparisonOp StencilFrontFuncFunc;
+ public int StencilFrontFuncRef;
+ public uint StencilFrontFuncMask;
+ public GalStencilOp StencilFrontOpFail;
+ public GalStencilOp StencilFrontOpZFail;
+ public GalStencilOp StencilFrontOpZPass;
+ public uint StencilFrontMask;
+
+ public bool BlendEnabled;
+ public bool BlendSeparateAlpha;
+ public GalBlendEquation BlendEquationRgb;
+ public GalBlendFactor BlendFuncSrcRgb;
+ public GalBlendFactor BlendFuncDstRgb;
+ public GalBlendEquation BlendEquationAlpha;
+ public GalBlendFactor BlendFuncSrcAlpha;
+ public GalBlendFactor BlendFuncDstAlpha;
+
+ public bool PrimitiveRestartEnabled;
+ public uint PrimitiveRestartIndex;
+
+ public GalPipelineState()
+ {
+ ConstBufferKeys = new long[Stages][];
+
+ for (int Stage = 0; Stage < Stages; Stage++)
+ {
+ ConstBufferKeys[Stage] = new long[ConstBuffersPerStage];
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/IGalBlend.cs b/Ryujinx.Graphics/Gal/IGalBlend.cs
deleted file mode 100644
index 5c96a492..00000000
--- a/Ryujinx.Graphics/Gal/IGalBlend.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-namespace Ryujinx.Graphics.Gal
-{
- public interface IGalBlend
- {
- void Enable();
-
- void Disable();
-
- void Set(
- GalBlendEquation Equation,
- GalBlendFactor FuncSrc,
- GalBlendFactor FuncDst);
-
- void SetSeparate(
- GalBlendEquation EquationRgb,
- GalBlendEquation EquationAlpha,
- GalBlendFactor FuncSrcRgb,
- GalBlendFactor FuncDstRgb,
- GalBlendFactor FuncSrcAlpha,
- GalBlendFactor FuncDstAlpha);
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/IGalConstBuffer.cs b/Ryujinx.Graphics/Gal/IGalConstBuffer.cs
new file mode 100644
index 00000000..37545b2a
--- /dev/null
+++ b/Ryujinx.Graphics/Gal/IGalConstBuffer.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Ryujinx.Graphics.Gal
+{
+ public interface IGalConstBuffer
+ {
+ void LockCache();
+ void UnlockCache();
+
+ void Create(long Key, long Size);
+
+ bool IsCached(long Key, long Size);
+
+ void SetData(long Key, long Size, IntPtr HostAddress);
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/IGalPipeline.cs b/Ryujinx.Graphics/Gal/IGalPipeline.cs
new file mode 100644
index 00000000..d8cf266a
--- /dev/null
+++ b/Ryujinx.Graphics/Gal/IGalPipeline.cs
@@ -0,0 +1,7 @@
+namespace Ryujinx.Graphics.Gal
+{
+ public interface IGalPipeline
+ {
+ void Bind(GalPipelineState State);
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/IGalRasterizer.cs b/Ryujinx.Graphics/Gal/IGalRasterizer.cs
index a87d36c3..89e50b1f 100644
--- a/Ryujinx.Graphics/Gal/IGalRasterizer.cs
+++ b/Ryujinx.Graphics/Gal/IGalRasterizer.cs
@@ -7,52 +7,20 @@ namespace Ryujinx.Graphics.Gal
void LockCaches();
void UnlockCaches();
- void ClearBuffers(GalClearBufferFlags Flags);
+ void ClearBuffers(
+ GalClearBufferFlags Flags,
+ float Red, float Green, float Blue, float Alpha,
+ float Depth,
+ int Stencil);
bool IsVboCached(long Key, long DataSize);
bool IsIboCached(long Key, long DataSize);
- void SetFrontFace(GalFrontFace FrontFace);
-
- void EnableCullFace();
-
- void DisableCullFace();
-
- void SetCullFace(GalCullFace CullFace);
-
- void EnableDepthTest();
-
- void DisableDepthTest();
-
- void SetDepthFunction(GalComparisonOp Func);
-
- void SetClearDepth(float Depth);
-
- void EnableStencilTest();
-
- void DisableStencilTest();
-
- void SetStencilFunction(bool IsFrontFace, GalComparisonOp Func, int Ref, int Mask);
-
- void SetStencilOp(bool IsFrontFace, GalStencilOp Fail, GalStencilOp ZFail, GalStencilOp ZPass);
-
- void SetStencilMask(bool IsFrontFace, int Mask);
-
- void SetClearStencil(int Stencil);
-
- void EnablePrimitiveRestart();
-
- void DisablePrimitiveRestart();
-
- void SetPrimitiveRestartIndex(uint Index);
-
void CreateVbo(long Key, int DataSize, IntPtr HostAddress);
void CreateIbo(long Key, int DataSize, IntPtr HostAddress);
- void SetVertexArray(int Stride, long VboKey, GalVertexAttrib[] Attribs);
-
void SetIndexArray(int Size, GalIndexFormat Format);
void DrawArrays(int First, int PrimCount, GalPrimitiveType PrimType);
diff --git a/Ryujinx.Graphics/Gal/IGalRenderer.cs b/Ryujinx.Graphics/Gal/IGalRenderer.cs
index c6324c4a..b47ac71d 100644
--- a/Ryujinx.Graphics/Gal/IGalRenderer.cs
+++ b/Ryujinx.Graphics/Gal/IGalRenderer.cs
@@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Gal
void RunActions();
- IGalBlend Blend { get; }
+ IGalConstBuffer Buffer { get; }
IGalFrameBuffer FrameBuffer { get; }
@@ -16,6 +16,8 @@ namespace Ryujinx.Graphics.Gal
IGalShader Shader { get; }
+ IGalPipeline Pipeline { get; }
+
IGalTexture Texture { get; }
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/IGalShader.cs b/Ryujinx.Graphics/Gal/IGalShader.cs
index 56235a07..a9bd1381 100644
--- a/Ryujinx.Graphics/Gal/IGalShader.cs
+++ b/Ryujinx.Graphics/Gal/IGalShader.cs
@@ -11,12 +11,8 @@ namespace Ryujinx.Graphics.Gal
IEnumerable<ShaderDeclInfo> GetTextureUsage(long Key);
- void SetConstBuffer(long Key, int Cbuf, int DataSize, IntPtr HostAddress);
-
void EnsureTextureBinding(string UniformName, int Value);
- void SetFlip(float X, float Y);
-
void Bind(long Key);
void Unbind(GalShaderType Type);
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLBlend.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLBlend.cs
deleted file mode 100644
index 7175e3a0..00000000
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLBlend.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-using OpenTK.Graphics.OpenGL;
-
-namespace Ryujinx.Graphics.Gal.OpenGL
-{
- public class OGLBlend : IGalBlend
- {
- public void Enable()
- {
- GL.Enable(EnableCap.Blend);
- }
-
- public void Disable()
- {
- GL.Disable(EnableCap.Blend);
- }
-
- public void Set(
- GalBlendEquation Equation,
- GalBlendFactor FuncSrc,
- GalBlendFactor FuncDst)
- {
- GL.BlendEquation(
- OGLEnumConverter.GetBlendEquation(Equation));
-
- GL.BlendFunc(
- OGLEnumConverter.GetBlendFactor(FuncSrc),
- OGLEnumConverter.GetBlendFactor(FuncDst));
- }
-
- public void SetSeparate(
- GalBlendEquation EquationRgb,
- GalBlendEquation EquationAlpha,
- GalBlendFactor FuncSrcRgb,
- GalBlendFactor FuncDstRgb,
- GalBlendFactor FuncSrcAlpha,
- GalBlendFactor FuncDstAlpha)
- {
- GL.BlendEquationSeparate(
- OGLEnumConverter.GetBlendEquation(EquationRgb),
- OGLEnumConverter.GetBlendEquation(EquationAlpha));
-
- GL.BlendFuncSeparate(
- (BlendingFactorSrc)OGLEnumConverter.GetBlendFactor(FuncSrcRgb),
- (BlendingFactorDest)OGLEnumConverter.GetBlendFactor(FuncDstRgb),
- (BlendingFactorSrc)OGLEnumConverter.GetBlendFactor(FuncSrcAlpha),
- (BlendingFactorDest)OGLEnumConverter.GetBlendFactor(FuncDstAlpha));
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLConstBuffer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLConstBuffer.cs
new file mode 100644
index 00000000..50825541
--- /dev/null
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLConstBuffer.cs
@@ -0,0 +1,66 @@
+using OpenTK.Graphics.OpenGL;
+using System;
+
+namespace Ryujinx.Graphics.Gal.OpenGL
+{
+ class OGLConstBuffer : IGalConstBuffer
+ {
+ private OGLCachedResource<OGLStreamBuffer> Cache;
+
+ public OGLConstBuffer()
+ {
+ Cache = new OGLCachedResource<OGLStreamBuffer>(DeleteBuffer);
+ }
+
+ public void LockCache()
+ {
+ Cache.Lock();
+ }
+
+ public void UnlockCache()
+ {
+ Cache.Unlock();
+ }
+
+ public void Create(long Key, long Size)
+ {
+ OGLStreamBuffer Buffer = new OGLStreamBuffer(BufferTarget.UniformBuffer, Size);
+
+ Cache.AddOrUpdate(Key, Buffer, Size);
+ }
+
+ public bool IsCached(long Key, long Size)
+ {
+ return Cache.TryGetSize(Key, out long CachedSize) && CachedSize == Size;
+ }
+
+ public void SetData(long Key, long Size, IntPtr HostAddress)
+ {
+ if (!Cache.TryGetValue(Key, out OGLStreamBuffer Buffer))
+ {
+ throw new InvalidOperationException();
+ }
+
+ Buffer.SetData(Size, HostAddress);
+ }
+
+ public bool TryGetUbo(long Key, out int UboHandle)
+ {
+ if (Cache.TryGetValue(Key, out OGLStreamBuffer Buffer))
+ {
+ UboHandle = Buffer.Handle;
+
+ return true;
+ }
+
+ UboHandle = 0;
+
+ return false;
+ }
+
+ private static void DeleteBuffer(OGLStreamBuffer Buffer)
+ {
+ Buffer.Dispose();
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs
new file mode 100644
index 00000000..54f984cd
--- /dev/null
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs
@@ -0,0 +1,379 @@
+using OpenTK.Graphics.OpenGL;
+using System;
+using System.Collections.Generic;
+
+namespace Ryujinx.Graphics.Gal.OpenGL
+{
+ class OGLPipeline : IGalPipeline
+ {
+ private static Dictionary<GalVertexAttribSize, int> AttribElements =
+ new Dictionary<GalVertexAttribSize, int>()
+ {
+ { GalVertexAttribSize._32_32_32_32, 4 },
+ { GalVertexAttribSize._32_32_32, 3 },
+ { GalVertexAttribSize._16_16_16_16, 4 },
+ { GalVertexAttribSize._32_32, 2 },
+ { GalVertexAttribSize._16_16_16, 3 },
+ { GalVertexAttribSize._8_8_8_8, 4 },
+ { GalVertexAttribSize._16_16, 2 },
+ { GalVertexAttribSize._32, 1 },
+ { GalVertexAttribSize._8_8_8, 3 },
+ { GalVertexAttribSize._8_8, 2 },
+ { GalVertexAttribSize._16, 1 },
+ { GalVertexAttribSize._8, 1 },
+ { GalVertexAttribSize._10_10_10_2, 4 },
+ { GalVertexAttribSize._11_11_10, 3 }
+ };
+
+ private static Dictionary<GalVertexAttribSize, VertexAttribPointerType> AttribTypes =
+ new Dictionary<GalVertexAttribSize, VertexAttribPointerType>()
+ {
+ { GalVertexAttribSize._32_32_32_32, VertexAttribPointerType.Int },
+ { GalVertexAttribSize._32_32_32, VertexAttribPointerType.Int },
+ { GalVertexAttribSize._16_16_16_16, VertexAttribPointerType.Short },
+ { GalVertexAttribSize._32_32, VertexAttribPointerType.Int },
+ { GalVertexAttribSize._16_16_16, VertexAttribPointerType.Short },
+ { GalVertexAttribSize._8_8_8_8, VertexAttribPointerType.Byte },
+ { GalVertexAttribSize._16_16, VertexAttribPointerType.Short },
+ { GalVertexAttribSize._32, VertexAttribPointerType.Int },
+ { GalVertexAttribSize._8_8_8, VertexAttribPointerType.Byte },
+ { GalVertexAttribSize._8_8, VertexAttribPointerType.Byte },
+ { GalVertexAttribSize._16, VertexAttribPointerType.Short },
+ { GalVertexAttribSize._8, VertexAttribPointerType.Byte },
+ { GalVertexAttribSize._10_10_10_2, VertexAttribPointerType.Int }, //?
+ { GalVertexAttribSize._11_11_10, VertexAttribPointerType.Int } //?
+ };
+
+ private GalPipelineState Old;
+
+ private OGLConstBuffer Buffer;
+ private OGLRasterizer Rasterizer;
+ private OGLShader Shader;
+
+ private int VaoHandle;
+
+ public OGLPipeline(OGLConstBuffer Buffer, OGLRasterizer Rasterizer, OGLShader Shader)
+ {
+ this.Buffer = Buffer;
+ this.Rasterizer = Rasterizer;
+ this.Shader = Shader;
+
+ //These values match OpenGL's defaults
+ Old = new GalPipelineState
+ {
+ FrontFace = GalFrontFace.CCW,
+
+ CullFaceEnabled = false,
+ CullFace = GalCullFace.Back,
+
+ DepthTestEnabled = false,
+ DepthFunc = GalComparisonOp.Less,
+
+ StencilTestEnabled = false,
+
+ StencilBackFuncFunc = GalComparisonOp.Always,
+ StencilBackFuncRef = 0,
+ StencilBackFuncMask = UInt32.MaxValue,
+ StencilBackOpFail = GalStencilOp.Keep,
+ StencilBackOpZFail = GalStencilOp.Keep,
+ StencilBackOpZPass = GalStencilOp.Keep,
+ StencilBackMask = UInt32.MaxValue,
+
+ StencilFrontFuncFunc = GalComparisonOp.Always,
+ StencilFrontFuncRef = 0,
+ StencilFrontFuncMask = UInt32.MaxValue,
+ StencilFrontOpFail = GalStencilOp.Keep,
+ StencilFrontOpZFail = GalStencilOp.Keep,
+ StencilFrontOpZPass = GalStencilOp.Keep,
+ StencilFrontMask = UInt32.MaxValue,
+
+ BlendEnabled = false,
+ BlendSeparateAlpha = false,
+
+ BlendEquationRgb = 0,
+ BlendFuncSrcRgb = GalBlendFactor.One,
+ BlendFuncDstRgb = GalBlendFactor.Zero,
+ BlendEquationAlpha = 0,
+ BlendFuncSrcAlpha = GalBlendFactor.One,
+ BlendFuncDstAlpha = GalBlendFactor.Zero,
+
+ PrimitiveRestartEnabled = false,
+ PrimitiveRestartIndex = 0
+ };
+ }
+
+ public void Bind(GalPipelineState New)
+ {
+ BindConstBuffers(New);
+
+ BindVertexLayout(New);
+
+ if (New.FlipX != Old.FlipX || New.FlipY != Old.FlipY)
+ {
+ Shader.SetFlip(New.FlipX, New.FlipY);
+ }
+
+ //Note: Uncomment SetFrontFace and SetCullFace when flipping issues are solved
+
+ //if (New.FrontFace != O.FrontFace)
+ //{
+ // GL.FrontFace(OGLEnumConverter.GetFrontFace(New.FrontFace));
+ //}
+
+ //if (New.CullFaceEnabled != O.CullFaceEnabled)
+ //{
+ // Enable(EnableCap.CullFace, New.CullFaceEnabled);
+ //}
+
+ //if (New.CullFaceEnabled)
+ //{
+ // if (New.CullFace != O.CullFace)
+ // {
+ // GL.CullFace(OGLEnumConverter.GetCullFace(New.CullFace));
+ // }
+ //}
+
+ if (New.DepthTestEnabled != Old.DepthTestEnabled)
+ {
+ Enable(EnableCap.DepthTest, New.DepthTestEnabled);
+ }
+
+ if (New.DepthTestEnabled)
+ {
+ if (New.DepthFunc != Old.DepthFunc)
+ {
+ GL.DepthFunc(OGLEnumConverter.GetDepthFunc(New.DepthFunc));
+ }
+ }
+
+ if (New.StencilTestEnabled != Old.StencilTestEnabled)
+ {
+ Enable(EnableCap.StencilTest, New.StencilTestEnabled);
+ }
+
+ if (New.StencilTestEnabled)
+ {
+ if (New.StencilBackFuncFunc != Old.StencilBackFuncFunc ||
+ New.StencilBackFuncRef != Old.StencilBackFuncRef ||
+ New.StencilBackFuncMask != Old.StencilBackFuncMask)
+ {
+ GL.StencilFuncSeparate(
+ StencilFace.Back,
+ OGLEnumConverter.GetStencilFunc(New.StencilBackFuncFunc),
+ New.StencilBackFuncRef,
+ New.StencilBackFuncMask);
+ }
+
+ if (New.StencilBackOpFail != Old.StencilBackOpFail ||
+ New.StencilBackOpZFail != Old.StencilBackOpZFail ||
+ New.StencilBackOpZPass != Old.StencilBackOpZPass)
+ {
+ GL.StencilOpSeparate(
+ StencilFace.Back,
+ OGLEnumConverter.GetStencilOp(New.StencilBackOpFail),
+ OGLEnumConverter.GetStencilOp(New.StencilBackOpZFail),
+ OGLEnumConverter.GetStencilOp(New.StencilBackOpZPass));
+ }
+
+ if (New.StencilBackMask != Old.StencilBackMask)
+ {
+ GL.StencilMaskSeparate(StencilFace.Back, New.StencilBackMask);
+ }
+
+ if (New.StencilFrontFuncFunc != Old.StencilFrontFuncFunc ||
+ New.StencilFrontFuncRef != Old.StencilFrontFuncRef ||
+ New.StencilFrontFuncMask != Old.StencilFrontFuncMask)
+ {
+ GL.StencilFuncSeparate(
+ StencilFace.Front,
+ OGLEnumConverter.GetStencilFunc(New.StencilFrontFuncFunc),
+ New.StencilFrontFuncRef,
+ New.StencilFrontFuncMask);
+ }
+
+ if (New.StencilFrontOpFail != Old.StencilFrontOpFail ||
+ New.StencilFrontOpZFail != Old.StencilFrontOpZFail ||
+ New.StencilFrontOpZPass != Old.StencilFrontOpZPass)
+ {
+ GL.StencilOpSeparate(
+ StencilFace.Front,
+ OGLEnumConverter.GetStencilOp(New.StencilFrontOpFail),
+ OGLEnumConverter.GetStencilOp(New.StencilFrontOpZFail),
+ OGLEnumConverter.GetStencilOp(New.StencilFrontOpZPass));
+ }
+
+ if (New.StencilFrontMask != Old.StencilFrontMask)
+ {
+ GL.StencilMaskSeparate(StencilFace.Front, New.StencilFrontMask);
+ }
+ }
+
+ if (New.BlendEnabled != Old.BlendEnabled)
+ {
+ Enable(EnableCap.Blend, New.BlendEnabled);
+ }
+
+ if (New.BlendEnabled)
+ {
+ if (New.BlendSeparateAlpha)
+ {
+ if (New.BlendEquationRgb != Old.BlendEquationRgb ||
+ New.BlendEquationAlpha != Old.BlendEquationAlpha)
+ {
+ GL.BlendEquationSeparate(
+ OGLEnumConverter.GetBlendEquation(New.BlendEquationRgb),
+ OGLEnumConverter.GetBlendEquation(New.BlendEquationAlpha));
+ }
+
+ if (New.BlendFuncSrcRgb != Old.BlendFuncSrcRgb ||
+ New.BlendFuncDstRgb != Old.BlendFuncDstRgb ||
+ New.BlendFuncSrcAlpha != Old.BlendFuncSrcAlpha ||
+ New.BlendFuncDstAlpha != Old.BlendFuncDstAlpha)
+ {
+ GL.BlendFuncSeparate(
+ (BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.BlendFuncSrcRgb),
+ (BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.BlendFuncDstRgb),
+ (BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.BlendFuncSrcAlpha),
+ (BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.BlendFuncDstAlpha));
+ }
+ }
+ else
+ {
+ if (New.BlendEquationRgb != Old.BlendEquationRgb)
+ {
+ GL.BlendEquation(OGLEnumConverter.GetBlendEquation(New.BlendEquationRgb));
+ }
+
+ if (New.BlendFuncSrcRgb != Old.BlendFuncSrcRgb ||
+ New.BlendFuncDstRgb != Old.BlendFuncDstRgb)
+ {
+ GL.BlendFunc(
+ OGLEnumConverter.GetBlendFactor(New.BlendFuncSrcRgb),
+ OGLEnumConverter.GetBlendFactor(New.BlendFuncDstRgb));
+ }
+ }
+ }
+
+ if (New.PrimitiveRestartEnabled != Old.PrimitiveRestartEnabled)
+ {
+ Enable(EnableCap.PrimitiveRestart, New.PrimitiveRestartEnabled);
+ }
+
+ if (New.PrimitiveRestartEnabled)
+ {
+ if (New.PrimitiveRestartIndex != Old.PrimitiveRestartIndex)
+ {
+ GL.PrimitiveRestartIndex(New.PrimitiveRestartIndex);
+ }
+ }
+
+ Old = New;
+ }
+
+ private void BindConstBuffers(GalPipelineState New)
+ {
+ //Index 0 is reserved
+ int FreeBinding = 1;
+
+ void BindIfNotNull(OGLShaderStage Stage)
+ {
+ if (Stage != null)
+ {
+ foreach (ShaderDeclInfo DeclInfo in Stage.UniformUsage)
+ {
+ long Key = New.ConstBufferKeys[(int)Stage.Type][DeclInfo.Cbuf];
+
+ if (Key != 0 && Buffer.TryGetUbo(Key, out int UboHandle))
+ {
+ GL.BindBufferBase(BufferRangeTarget.UniformBuffer, FreeBinding, UboHandle);
+ }
+
+ FreeBinding++;
+ }
+ }
+ }
+
+ BindIfNotNull(Shader.Current.Vertex);
+ BindIfNotNull(Shader.Current.TessControl);
+ BindIfNotNull(Shader.Current.TessEvaluation);
+ BindIfNotNull(Shader.Current.Geometry);
+ BindIfNotNull(Shader.Current.Fragment);
+ }
+
+ private void BindVertexLayout(GalPipelineState New)
+ {
+ foreach (GalVertexBinding Binding in New.VertexBindings)
+ {
+ if (!Binding.Enabled || !Rasterizer.TryGetVbo(Binding.VboKey, out int VboHandle))
+ {
+ continue;
+ }
+
+ if (VaoHandle == 0)
+ {
+ VaoHandle = GL.GenVertexArray();
+
+ //Vertex arrays shouldn't be used anywhere else in OpenGL's backend
+ //if you want to use it, move this line out of the if
+ GL.BindVertexArray(VaoHandle);
+ }
+
+ foreach (GalVertexAttrib Attrib in Binding.Attribs)
+ {
+ GL.EnableVertexAttribArray(Attrib.Index);
+
+ GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
+
+ bool Unsigned =
+ Attrib.Type == GalVertexAttribType.Unorm ||
+ Attrib.Type == GalVertexAttribType.Uint ||
+ Attrib.Type == GalVertexAttribType.Uscaled;
+
+ bool Normalize =
+ Attrib.Type == GalVertexAttribType.Snorm ||
+ Attrib.Type == GalVertexAttribType.Unorm;
+
+ VertexAttribPointerType Type = 0;
+
+ if (Attrib.Type == GalVertexAttribType.Float)
+ {
+ Type = VertexAttribPointerType.Float;
+ }
+ else
+ {
+ Type = AttribTypes[Attrib.Size] + (Unsigned ? 1 : 0);
+ }
+
+ int Size = AttribElements[Attrib.Size];
+ int Offset = Attrib.Offset;
+
+ if (Attrib.Type == GalVertexAttribType.Sint ||
+ Attrib.Type == GalVertexAttribType.Uint)
+ {
+ IntPtr Pointer = new IntPtr(Offset);
+
+ VertexAttribIntegerType IType = (VertexAttribIntegerType)Type;
+
+ GL.VertexAttribIPointer(Attrib.Index, Size, IType, Binding.Stride, Pointer);
+ }
+ else
+ {
+ GL.VertexAttribPointer(Attrib.Index, Size, Type, Normalize, Binding.Stride, Offset);
+ }
+ }
+ }
+ }
+
+ private void Enable(EnableCap Cap, bool Enabled)
+ {
+ if (Enabled)
+ {
+ GL.Enable(Cap);
+ }
+ else
+ {
+ GL.Disable(Cap);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs
index c5166b51..08021478 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs
@@ -6,46 +6,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
public class OGLRasterizer : IGalRasterizer
{
- private static Dictionary<GalVertexAttribSize, int> AttribElements =
- new Dictionary<GalVertexAttribSize, int>()
- {
- { GalVertexAttribSize._32_32_32_32, 4 },
- { GalVertexAttribSize._32_32_32, 3 },
- { GalVertexAttribSize._16_16_16_16, 4 },
- { GalVertexAttribSize._32_32, 2 },
- { GalVertexAttribSize._16_16_16, 3 },
- { GalVertexAttribSize._8_8_8_8, 4 },
- { GalVertexAttribSize._16_16, 2 },
- { GalVertexAttribSize._32, 1 },
- { GalVertexAttribSize._8_8_8, 3 },
- { GalVertexAttribSize._8_8, 2 },
- { GalVertexAttribSize._16, 1 },
- { GalVertexAttribSize._8, 1 },
- { GalVertexAttribSize._10_10_10_2, 4 },
- { GalVertexAttribSize._11_11_10, 3 }
- };
-
- private static Dictionary<GalVertexAttribSize, VertexAttribPointerType> AttribTypes =
- new Dictionary<GalVertexAttribSize, VertexAttribPointerType>()
- {
- { GalVertexAttribSize._32_32_32_32, VertexAttribPointerType.Int },
- { GalVertexAttribSize._32_32_32, VertexAttribPointerType.Int },
- { GalVertexAttribSize._16_16_16_16, VertexAttribPointerType.Short },
- { GalVertexAttribSize._32_32, VertexAttribPointerType.Int },
- { GalVertexAttribSize._16_16_16, VertexAttribPointerType.Short },
- { GalVertexAttribSize._8_8_8_8, VertexAttribPointerType.Byte },
- { GalVertexAttribSize._16_16, VertexAttribPointerType.Short },
- { GalVertexAttribSize._32, VertexAttribPointerType.Int },
- { GalVertexAttribSize._8_8_8, VertexAttribPointerType.Byte },
- { GalVertexAttribSize._8_8, VertexAttribPointerType.Byte },
- { GalVertexAttribSize._16, VertexAttribPointerType.Short },
- { GalVertexAttribSize._8, VertexAttribPointerType.Byte },
- { GalVertexAttribSize._10_10_10_2, VertexAttribPointerType.Int }, //?
- { GalVertexAttribSize._11_11_10, VertexAttribPointerType.Int } //?
- };
-
- private int VaoHandle;
-
private int[] VertexBuffers;
private OGLCachedResource<int> VboCache;
@@ -83,7 +43,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
IboCache.Unlock();
}
- public void ClearBuffers(GalClearBufferFlags Flags)
+ public void ClearBuffers(
+ GalClearBufferFlags Flags,
+ float Red, float Green, float Blue, float Alpha,
+ float Depth,
+ int Stencil)
{
ClearBufferMask Mask = ClearBufferMask.ColorBufferBit;
@@ -103,6 +67,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL
Mask |= ClearBufferMask.StencilBufferBit;
}
+ GL.ClearColor(Red, Green, Blue, Alpha);
+
+ GL.ClearDepth(Depth);
+
+ GL.ClearStencil(Stencil);
+
GL.Clear(Mask);
GL.ColorMask(true, true, true, true);
@@ -118,99 +88,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
return IboCache.TryGetSize(Key, out long Size) && Size == DataSize;
}
- public void SetFrontFace(GalFrontFace FrontFace)
- {
- GL.FrontFace(OGLEnumConverter.GetFrontFace(FrontFace));
- }
-
- public void EnableCullFace()
- {
- GL.Enable(EnableCap.CullFace);
- }
-
- public void DisableCullFace()
- {
- GL.Disable(EnableCap.CullFace);
- }
-
- public void SetCullFace(GalCullFace CullFace)
- {
- GL.CullFace(OGLEnumConverter.GetCullFace(CullFace));
- }
-
- public void EnableDepthTest()
- {
- GL.Enable(EnableCap.DepthTest);
- }
-
- public void DisableDepthTest()
- {
- GL.Disable(EnableCap.DepthTest);
- }
-
- public void SetDepthFunction(GalComparisonOp Func)
- {
- GL.DepthFunc(OGLEnumConverter.GetDepthFunc(Func));
- }
-
- public void SetClearDepth(float Depth)
- {
- GL.ClearDepth(Depth);
- }
-
- public void EnableStencilTest()
- {
- GL.Enable(EnableCap.StencilTest);
- }
-
- public void DisableStencilTest()
- {
- GL.Disable(EnableCap.StencilTest);
- }
-
- public void SetStencilFunction(bool IsFrontFace, GalComparisonOp Func, int Ref, int Mask)
- {
- GL.StencilFuncSeparate(
- IsFrontFace ? StencilFace.Front : StencilFace.Back,
- OGLEnumConverter.GetStencilFunc(Func),
- Ref,
- Mask);
- }
-
- public void SetStencilOp(bool IsFrontFace, GalStencilOp Fail, GalStencilOp ZFail, GalStencilOp ZPass)
- {
- GL.StencilOpSeparate(
- IsFrontFace ? StencilFace.Front : StencilFace.Back,
- OGLEnumConverter.GetStencilOp(Fail),
- OGLEnumConverter.GetStencilOp(ZFail),
- OGLEnumConverter.GetStencilOp(ZPass));
- }
-
- public void SetStencilMask(bool IsFrontFace, int Mask)
- {
- GL.StencilMaskSeparate(IsFrontFace ? StencilFace.Front : StencilFace.Back, Mask);
- }
-
- public void SetClearStencil(int Stencil)
- {
- GL.ClearStencil(Stencil);
- }
-
- public void EnablePrimitiveRestart()
- {
- GL.Enable(EnableCap.PrimitiveRestart);
- }
-
- public void DisablePrimitiveRestart()
- {
- GL.Disable(EnableCap.PrimitiveRestart);
- }
-
- public void SetPrimitiveRestartIndex(uint Index)
- {
- GL.PrimitiveRestartIndex(Index);
- }
-
public void CreateVbo(long Key, int DataSize, IntPtr HostAddress)
{
int Handle = GL.GenBuffer();
@@ -235,65 +112,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.BufferData(BufferTarget.ElementArrayBuffer, Length, HostAddress, BufferUsageHint.StreamDraw);
}
- public void SetVertexArray(int Stride, long VboKey, GalVertexAttrib[] Attribs)
- {
- if (!VboCache.TryGetValue(VboKey, out int VboHandle))
- {
- return;
- }
-
- if (VaoHandle == 0)
- {
- VaoHandle = GL.GenVertexArray();
- }
-
- GL.BindVertexArray(VaoHandle);
-
- foreach (GalVertexAttrib Attrib in Attribs)
- {
- GL.EnableVertexAttribArray(Attrib.Index);
-
- GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
-
- bool Unsigned =
- Attrib.Type == GalVertexAttribType.Unorm ||
- Attrib.Type == GalVertexAttribType.Uint ||
- Attrib.Type == GalVertexAttribType.Uscaled;
-
- bool Normalize =
- Attrib.Type == GalVertexAttribType.Snorm ||
- Attrib.Type == GalVertexAttribType.Unorm;
-
- VertexAttribPointerType Type = 0;
-
- if (Attrib.Type == GalVertexAttribType.Float)
- {
- Type = VertexAttribPointerType.Float;
- }
- else
- {
- Type = AttribTypes[Attrib.Size] + (Unsigned ? 1 : 0);
- }
-
- int Size = AttribElements[Attrib.Size];
- int Offset = Attrib.Offset;
-
- if (Attrib.Type == GalVertexAttribType.Sint ||
- Attrib.Type == GalVertexAttribType.Uint)
- {
- IntPtr Pointer = new IntPtr(Offset);
-
- VertexAttribIntegerType IType = (VertexAttribIntegerType)Type;
-
- GL.VertexAttribIPointer(Attrib.Index, Size, IType, Stride, Pointer);
- }
- else
- {
- GL.VertexAttribPointer(Attrib.Index, Size, Type, Normalize, Stride, Offset);
- }
- }
- }
-
public void SetIndexArray(int Size, GalIndexFormat Format)
{
IndexBuffer.Type = OGLEnumConverter.GetDrawElementsType(Format);
@@ -310,8 +128,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
return;
}
- GL.BindVertexArray(VaoHandle);
-
GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), First, PrimCount);
}
@@ -324,8 +140,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
PrimitiveType Mode = OGLEnumConverter.GetPrimitiveType(PrimType);
- GL.BindVertexArray(VaoHandle);
-
GL.BindBuffer(BufferTarget.ElementArrayBuffer, IboHandle);
First <<= IndexBuffer.ElemSizeLog2;
@@ -341,5 +155,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.DrawElements(Mode, IndexBuffer.Count, IndexBuffer.Type, First);
}
}
+
+ public bool TryGetVbo(long VboKey, out int VboHandle)
+ {
+ return VboCache.TryGetValue(VboKey, out VboHandle);
+ }
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs
index ca70d4f6..b0f6da45 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs
@@ -5,7 +5,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
public class OGLRenderer : IGalRenderer
{
- public IGalBlend Blend { get; private set; }
+ public IGalConstBuffer Buffer { get; private set; }
public IGalFrameBuffer FrameBuffer { get; private set; }
@@ -13,19 +13,23 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public IGalShader Shader { get; private set; }
+ public IGalPipeline Pipeline { get; private set; }
+
public IGalTexture Texture { get; private set; }
private ConcurrentQueue<Action> ActionsQueue;
public OGLRenderer()
{
- Blend = new OGLBlend();
+ Buffer = new OGLConstBuffer();
FrameBuffer = new OGLFrameBuffer();
Rasterizer = new OGLRasterizer();
- Shader = new OGLShader();
+ Shader = new OGLShader(Buffer as OGLConstBuffer);
+
+ Pipeline = new OGLPipeline(Buffer as OGLConstBuffer, Rasterizer as OGLRasterizer, Shader as OGLShader);
Texture = new OGLTexture();
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs
index 3f3f23b8..4792bc5e 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs
@@ -5,96 +5,29 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
-using Buffer = System.Buffer;
-
namespace Ryujinx.Graphics.Gal.OpenGL
{
- public class OGLShader : IGalShader
+ class OGLShader : IGalShader
{
- private class ShaderStage : IDisposable
- {
- public int Handle { get; private set; }
-
- public bool IsCompiled { get; private set; }
-
- public GalShaderType Type { get; private set; }
-
- public string Code { get; private set; }
-
- public IEnumerable<ShaderDeclInfo> TextureUsage { get; private set; }
- public IEnumerable<ShaderDeclInfo> UniformUsage { get; private set; }
-
- public ShaderStage(
- GalShaderType Type,
- string Code,
- IEnumerable<ShaderDeclInfo> TextureUsage,
- IEnumerable<ShaderDeclInfo> UniformUsage)
- {
- this.Type = Type;
- this.Code = Code;
- this.TextureUsage = TextureUsage;
- this.UniformUsage = UniformUsage;
- }
-
- public void Compile()
- {
- if (Handle == 0)
- {
- Handle = GL.CreateShader(OGLEnumConverter.GetShaderType(Type));
-
- CompileAndCheck(Handle, Code);
- }
- }
-
- public void Dispose()
- {
- Dispose(true);
- }
-
- protected virtual void Dispose(bool Disposing)
- {
- if (Disposing && Handle != 0)
- {
- GL.DeleteShader(Handle);
-
- Handle = 0;
- }
- }
- }
-
- private struct ShaderProgram
- {
- public ShaderStage Vertex;
- public ShaderStage TessControl;
- public ShaderStage TessEvaluation;
- public ShaderStage Geometry;
- public ShaderStage Fragment;
- }
-
- const int ConstBuffersPerStage = 18;
-
- private ShaderProgram Current;
+ public OGLShaderProgram Current;
- private ConcurrentDictionary<long, ShaderStage> Stages;
+ private ConcurrentDictionary<long, OGLShaderStage> Stages;
- private Dictionary<ShaderProgram, int> Programs;
+ private Dictionary<OGLShaderProgram, int> Programs;
public int CurrentProgramHandle { get; private set; }
- private OGLStreamBuffer[][] ConstBuffers;
+ private OGLConstBuffer Buffer;
- public OGLShader()
- {
- Stages = new ConcurrentDictionary<long, ShaderStage>();
+ private int ExtraUboHandle;
- Programs = new Dictionary<ShaderProgram, int>();
+ public OGLShader(OGLConstBuffer Buffer)
+ {
+ this.Buffer = Buffer;
- ConstBuffers = new OGLStreamBuffer[5][];
+ Stages = new ConcurrentDictionary<long, OGLShaderStage>();
- for (int i = 0; i < 5; i++)
- {
- ConstBuffers[i] = new OGLStreamBuffer[ConstBuffersPerStage];
- }
+ Programs = new Dictionary<OGLShaderProgram, int>();
}
public void Create(IGalMemory Memory, long Key, GalShaderType Type)
@@ -107,7 +40,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
Stages.GetOrAdd(Key, (Stage) => ShaderStageFactory(Memory, VpAPos, Key, true, Type));
}
- private ShaderStage ShaderStageFactory(
+ private OGLShaderStage ShaderStageFactory(
IGalMemory Memory,
long Position,
long PositionB,
@@ -136,7 +69,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
Program = Decompiler.Decompile(Memory, Position, Type);
}
- return new ShaderStage(
+ return new OGLShaderStage(
Type,
Program.Code,
Program.Textures,
@@ -145,7 +78,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public IEnumerable<ShaderDeclInfo> GetTextureUsage(long Key)
{
- if (Stages.TryGetValue(Key, out ShaderStage Stage))
+ if (Stages.TryGetValue(Key, out OGLShaderStage Stage))
{
return Stage.TextureUsage;
}
@@ -153,21 +86,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
return Enumerable.Empty<ShaderDeclInfo>();
}
- public void SetConstBuffer(long Key, int Cbuf, int DataSize, IntPtr HostAddress)
- {
- if (Stages.TryGetValue(Key, out ShaderStage Stage))
- {
- foreach (ShaderDeclInfo DeclInfo in Stage.UniformUsage.Where(x => x.Cbuf == Cbuf))
- {
- OGLStreamBuffer Buffer = GetConstBuffer(Stage.Type, Cbuf);
-
- int Size = Math.Min(DataSize, Buffer.Size);
-
- Buffer.SetData(Size, HostAddress);
- }
- }
- }
-
public void EnsureTextureBinding(string UniformName, int Value)
{
BindProgram();
@@ -177,24 +95,33 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.Uniform1(Location, Value);
}
- public void SetFlip(float X, float Y)
+ public unsafe void SetFlip(float X, float Y)
{
BindProgram();
- int Location = GL.GetUniformLocation(CurrentProgramHandle, GlslDecl.FlipUniformName);
+ EnsureExtraBlock();
+
+ GL.BindBuffer(BufferTarget.UniformBuffer, ExtraUboHandle);
+
+ float* Data = stackalloc float[4];
+ Data[0] = X;
+ Data[1] = Y;
- GL.Uniform2(Location, X, Y);
+ //Invalidate buffer
+ GL.BufferData(BufferTarget.UniformBuffer, 4 * sizeof(float), IntPtr.Zero, BufferUsageHint.StreamDraw);
+
+ GL.BufferSubData(BufferTarget.UniformBuffer, IntPtr.Zero, 4 * sizeof(float), (IntPtr)Data);
}
public void Bind(long Key)
{
- if (Stages.TryGetValue(Key, out ShaderStage Stage))
+ if (Stages.TryGetValue(Key, out OGLShaderStage Stage))
{
Bind(Stage);
}
}
- private void Bind(ShaderStage Stage)
+ private void Bind(OGLShaderStage Stage)
{
if (Stage.Type == GalShaderType.Geometry)
{
@@ -257,15 +184,24 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.UseProgram(Handle);
- if (CurrentProgramHandle != Handle)
+ CurrentProgramHandle = Handle;
+ }
+
+ private void EnsureExtraBlock()
+ {
+ if (ExtraUboHandle == 0)
{
- BindUniformBuffers(Handle);
- }
+ ExtraUboHandle = GL.GenBuffer();
- CurrentProgramHandle = Handle;
+ GL.BindBuffer(BufferTarget.UniformBuffer, ExtraUboHandle);
+
+ GL.BufferData(BufferTarget.UniformBuffer, 4 * sizeof(float), IntPtr.Zero, BufferUsageHint.StreamDraw);
+
+ GL.BindBufferBase(BufferRangeTarget.UniformBuffer, 0, ExtraUboHandle);
+ }
}
- private void AttachIfNotNull(int ProgramHandle, ShaderStage Stage)
+ private void AttachIfNotNull(int ProgramHandle, OGLShaderStage Stage)
{
if (Stage != null)
{
@@ -277,9 +213,14 @@ namespace Ryujinx.Graphics.Gal.OpenGL
private void BindUniformBlocks(int ProgramHandle)
{
- int FreeBinding = 0;
+ int ExtraBlockindex = GL.GetUniformBlockIndex(ProgramHandle, GlslDecl.ExtraUniformBlockName);
+
+ GL.UniformBlockBinding(ProgramHandle, ExtraBlockindex, 0);
+
+ //First index is reserved
+ int FreeBinding = 1;
- void BindUniformBlocksIfNotNull(ShaderStage Stage)
+ void BindUniformBlocksIfNotNull(OGLShaderStage Stage)
{
if (Stage != null)
{
@@ -307,71 +248,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
BindUniformBlocksIfNotNull(Current.Fragment);
}
- private void BindUniformBuffers(int ProgramHandle)
- {
- int FreeBinding = 0;
-
- void BindUniformBuffersIfNotNull(ShaderStage Stage)
- {
- if (Stage != null)
- {
- foreach (ShaderDeclInfo DeclInfo in Stage.UniformUsage)
- {
- OGLStreamBuffer Buffer = GetConstBuffer(Stage.Type, DeclInfo.Cbuf);
-
- GL.BindBufferBase(BufferRangeTarget.UniformBuffer, FreeBinding, Buffer.Handle);
-
- FreeBinding++;
- }
- }
- }
-
- BindUniformBuffersIfNotNull(Current.Vertex);
- BindUniformBuffersIfNotNull(Current.TessControl);
- BindUniformBuffersIfNotNull(Current.TessEvaluation);
- BindUniformBuffersIfNotNull(Current.Geometry);
- BindUniformBuffersIfNotNull(Current.Fragment);
- }
-
- private OGLStreamBuffer GetConstBuffer(GalShaderType StageType, int Cbuf)
- {
- int StageIndex = (int)StageType;
-
- OGLStreamBuffer Buffer = ConstBuffers[StageIndex][Cbuf];
-
- if (Buffer == null)
- {
- //Allocate a maximum of 64 KiB
- int Size = Math.Min(GL.GetInteger(GetPName.MaxUniformBlockSize), 64 * 1024);
-
- Buffer = new OGLStreamBuffer(BufferTarget.UniformBuffer, Size);
-
- ConstBuffers[StageIndex][Cbuf] = Buffer;
- }
-
- return Buffer;
- }
-
- public static void CompileAndCheck(int Handle, string Code)
- {
- GL.ShaderSource(Handle, Code);
- GL.CompileShader(Handle);
-
- CheckCompilation(Handle);
- }
-
- private static void CheckCompilation(int Handle)
- {
- int Status = 0;
-
- GL.GetShader(Handle, ShaderParameter.CompileStatus, out Status);
-
- if (Status == 0)
- {
- throw new ShaderException(GL.GetShaderInfoLog(Handle));
- }
- }
-
private static void CheckProgramLink(int Handle)
{
int Status = 0;
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLShaderProgram.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLShaderProgram.cs
new file mode 100644
index 00000000..731994ce
--- /dev/null
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLShaderProgram.cs
@@ -0,0 +1,86 @@
+using OpenTK.Graphics.OpenGL;
+using System;
+using System.Collections.Generic;
+
+namespace Ryujinx.Graphics.Gal.OpenGL
+{
+ struct OGLShaderProgram
+ {
+ public OGLShaderStage Vertex;
+ public OGLShaderStage TessControl;
+ public OGLShaderStage TessEvaluation;
+ public OGLShaderStage Geometry;
+ public OGLShaderStage Fragment;
+ }
+
+ class OGLShaderStage : IDisposable
+ {
+ public int Handle { get; private set; }
+
+ public bool IsCompiled { get; private set; }
+
+ public GalShaderType Type { get; private set; }
+
+ public string Code { get; private set; }
+
+ public IEnumerable<ShaderDeclInfo> TextureUsage { get; private set; }
+ public IEnumerable<ShaderDeclInfo> UniformUsage { get; private set; }
+
+ public OGLShaderStage(
+ GalShaderType Type,
+ string Code,
+ IEnumerable<ShaderDeclInfo> TextureUsage,
+ IEnumerable<ShaderDeclInfo> UniformUsage)
+ {
+ this.Type = Type;
+ this.Code = Code;
+ this.TextureUsage = TextureUsage;
+ this.UniformUsage = UniformUsage;
+ }
+
+ public void Compile()
+ {
+ if (Handle == 0)
+ {
+ Handle = GL.CreateShader(OGLEnumConverter.GetShaderType(Type));
+
+ CompileAndCheck(Handle, Code);
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool Disposing)
+ {
+ if (Disposing && Handle != 0)
+ {
+ GL.DeleteShader(Handle);
+
+ Handle = 0;
+ }
+ }
+
+ public static void CompileAndCheck(int Handle, string Code)
+ {
+ GL.ShaderSource(Handle, Code);
+ GL.CompileShader(Handle);
+
+ CheckCompilation(Handle);
+ }
+
+ private static void CheckCompilation(int Handle)
+ {
+ int Status = 0;
+
+ GL.GetShader(Handle, ShaderParameter.CompileStatus, out Status);
+
+ if (Status == 0)
+ {
+ throw new ShaderException(GL.GetShaderInfoLog(Handle));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLStreamBuffer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLStreamBuffer.cs
index 0d5dee93..94639405 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLStreamBuffer.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLStreamBuffer.cs
@@ -7,11 +7,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
public int Handle { get; protected set; }
- public int Size { get; protected set; }
+ public long Size { get; protected set; }
protected BufferTarget Target { get; private set; }
- public OGLStreamBuffer(BufferTarget Target, int Size)
+ public OGLStreamBuffer(BufferTarget Target, long Size)
{
this.Target = Target;
this.Size = Size;
@@ -20,14 +20,14 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.BindBuffer(Target, Handle);
- GL.BufferData(Target, Size, IntPtr.Zero, BufferUsageHint.StreamDraw);
+ GL.BufferData(Target, (IntPtr)Size, IntPtr.Zero, BufferUsageHint.StreamDraw);
}
- public void SetData(int Size, IntPtr HostAddress)
+ public void SetData(long Size, IntPtr HostAddress)
{
GL.BindBuffer(Target, Handle);
- GL.BufferSubData(Target, IntPtr.Zero, Size, HostAddress);
+ GL.BufferSubData(Target, IntPtr.Zero, (IntPtr)Size, HostAddress);
}
public void Dispose()
diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs
index 7688545c..a0c747ba 100644
--- a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs
+++ b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs
@@ -35,6 +35,7 @@ namespace Ryujinx.Graphics.Gal.Shader
public const string FragmentOutputName = "FragColor";
+ public const string ExtraUniformBlockName = "Extra";
public const string FlipUniformName = "flip";
public const string ProgramName = "program";
diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
index 5261d677..aa1803a5 100644
--- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
+++ b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
@@ -220,7 +220,11 @@ namespace Ryujinx.Graphics.Gal.Shader
{
if (Decl.ShaderType == GalShaderType.Vertex)
{
- SB.AppendLine("uniform vec2 " + GlslDecl.FlipUniformName + ";");
+ SB.AppendLine("layout (std140) uniform " + GlslDecl.ExtraUniformBlockName + "{");
+
+ SB.AppendLine(IdentationStr + "vec2 " + GlslDecl.FlipUniformName + ";");
+
+ SB.AppendLine("};");
}
SB.AppendLine();
diff --git a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs
index 3dd0e98e..0576601f 100644
--- a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs
+++ b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs
@@ -84,35 +84,41 @@ namespace Ryujinx.HLE.Gpu.Engines
{
LockCaches();
+ GalPipelineState State = new GalPipelineState();
+
+ SetFlip(State);
+ SetFrontFace(State);
+ SetCullFace(State);
+ SetDepth(State);
+ SetStencil(State);
+ SetAlphaBlending(State);
+ SetPrimitiveRestart(State);
+
SetFrameBuffer(Vmm, 0);
long[] Keys = UploadShaders(Vmm);
Gpu.Renderer.Shader.BindProgram();
- //Note: Uncomment SetFrontFace SetCullFace when flipping issues are solved
- //SetFrontFace();
- //SetCullFace();
- SetDepth();
- SetStencil();
- SetAlphaBlending();
- SetPrimitiveRestart();
+ UploadTextures(Vmm, State, Keys);
+ UploadConstBuffers(Vmm, State);
+ UploadVertexArrays(Vmm, State);
- UploadTextures(Vmm, Keys);
- UploadUniforms(Vmm);
- UploadVertexArrays(Vmm);
+ DispatchRender(Vmm, State);
UnlockCaches();
}
private void LockCaches()
{
+ Gpu.Renderer.Buffer.LockCache();
Gpu.Renderer.Rasterizer.LockCaches();
Gpu.Renderer.Texture.LockCache();
}
private void UnlockCaches()
{
+ Gpu.Renderer.Buffer.UnlockCache();
Gpu.Renderer.Rasterizer.UnlockCaches();
Gpu.Renderer.Texture.UnlockCache();
}
@@ -125,9 +131,22 @@ namespace Ryujinx.HLE.Gpu.Engines
GalClearBufferFlags Flags = (GalClearBufferFlags)(Arg0 & 0x3f);
+ float Red = ReadRegisterFloat(NvGpuEngine3dReg.ClearNColor + 0);
+ float Green = ReadRegisterFloat(NvGpuEngine3dReg.ClearNColor + 1);
+ float Blue = ReadRegisterFloat(NvGpuEngine3dReg.ClearNColor + 2);
+ float Alpha = ReadRegisterFloat(NvGpuEngine3dReg.ClearNColor + 3);
+
+ float Depth = ReadRegisterFloat(NvGpuEngine3dReg.ClearDepth);
+
+ int Stencil = ReadRegister(NvGpuEngine3dReg.ClearStencil);
+
SetFrameBuffer(Vmm, FbIndex);
- Gpu.Renderer.Rasterizer.ClearBuffers(Flags);
+ Gpu.Renderer.Rasterizer.ClearBuffers(
+ Flags,
+ Red, Green, Blue, Alpha,
+ Depth,
+ Stencil);
}
private void SetFrameBuffer(NvGpuVmm Vmm, int FbIndex)
@@ -185,6 +204,8 @@ namespace Ryujinx.HLE.Gpu.Engines
long VpAPos = BasePosition + (uint)VpAOffset;
long VpBPos = BasePosition + (uint)VpBOffset;
+ Keys[(int)GalShaderType.Vertex] = VpBPos;
+
Gpu.Renderer.Shader.Create(Vmm, VpAPos, VpBPos, GalShaderType.Vertex);
Gpu.Renderer.Shader.Bind(VpBPos);
@@ -216,11 +237,6 @@ namespace Ryujinx.HLE.Gpu.Engines
Gpu.Renderer.Shader.Bind(Key);
}
- float SignX = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleX);
- float SignY = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleY);
-
- Gpu.Renderer.Shader.SetFlip(SignX, SignY);
-
return Keys;
}
@@ -239,7 +255,13 @@ namespace Ryujinx.HLE.Gpu.Engines
throw new ArgumentOutOfRangeException(nameof(Program));
}
- private void SetFrontFace()
+ private void SetFlip(GalPipelineState State)
+ {
+ State.FlipX = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleX);
+ State.FlipY = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleY);
+ }
+
+ private void SetFrontFace(GalPipelineState State)
{
float SignX = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleX);
float SignY = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleY);
@@ -261,198 +283,82 @@ namespace Ryujinx.HLE.Gpu.Engines
}
}
- Gpu.Renderer.Rasterizer.SetFrontFace(FrontFace);
+ State.FrontFace = FrontFace;
}
- private void SetCullFace()
+ private void SetCullFace(GalPipelineState State)
{
- bool Enable = (ReadRegister(NvGpuEngine3dReg.CullFaceEnable) & 1) != 0;
+ State.CullFaceEnabled = (ReadRegister(NvGpuEngine3dReg.CullFaceEnable) & 1) != 0;
- if (Enable)
+ if (State.CullFaceEnabled)
{
- Gpu.Renderer.Rasterizer.EnableCullFace();
+ State.CullFace = (GalCullFace)ReadRegister(NvGpuEngine3dReg.CullFace);
}
- else
- {
- Gpu.Renderer.Rasterizer.DisableCullFace();
- }
-
- if (!Enable)
- {
- return;
- }
-
- GalCullFace CullFace = (GalCullFace)ReadRegister(NvGpuEngine3dReg.CullFace);
-
- Gpu.Renderer.Rasterizer.SetCullFace(CullFace);
}
- private void SetDepth()
+ private void SetDepth(GalPipelineState State)
{
- float ClearDepth = ReadRegisterFloat(NvGpuEngine3dReg.ClearDepth);
-
- Gpu.Renderer.Rasterizer.SetClearDepth(ClearDepth);
-
- bool Enable = (ReadRegister(NvGpuEngine3dReg.DepthTestEnable) & 1) != 0;
-
- if (Enable)
- {
- Gpu.Renderer.Rasterizer.EnableDepthTest();
- }
- else
- {
- Gpu.Renderer.Rasterizer.DisableDepthTest();
- }
+ State.DepthTestEnabled = (ReadRegister(NvGpuEngine3dReg.DepthTestEnable) & 1) != 0;
- if (!Enable)
+ if (State.DepthTestEnabled)
{
- return;
+ State.DepthFunc = (GalComparisonOp)ReadRegister(NvGpuEngine3dReg.DepthTestFunction);
}
-
- GalComparisonOp Func = (GalComparisonOp)ReadRegister(NvGpuEngine3dReg.DepthTestFunction);
-
- Gpu.Renderer.Rasterizer.SetDepthFunction(Func);
}
- private void SetStencil()
+ private void SetStencil(GalPipelineState State)
{
- int ClearStencil = ReadRegister(NvGpuEngine3dReg.ClearStencil);
-
- Gpu.Renderer.Rasterizer.SetClearStencil(ClearStencil);
-
- bool Enable = (ReadRegister(NvGpuEngine3dReg.StencilEnable) & 1) != 0;
-
- if (Enable)
- {
- Gpu.Renderer.Rasterizer.EnableStencilTest();
- }
- else
- {
- Gpu.Renderer.Rasterizer.DisableStencilTest();
+ State.StencilTestEnabled = (ReadRegister(NvGpuEngine3dReg.StencilEnable) & 1) != 0;
+
+ if (State.StencilTestEnabled)
+ {
+ State.StencilBackFuncFunc = (GalComparisonOp)ReadRegister(NvGpuEngine3dReg.StencilBackFuncFunc);
+ State.StencilBackFuncRef = ReadRegister(NvGpuEngine3dReg.StencilBackFuncRef);
+ State.StencilBackFuncMask = (uint)ReadRegister(NvGpuEngine3dReg.StencilBackFuncMask);
+ State.StencilBackOpFail = (GalStencilOp)ReadRegister(NvGpuEngine3dReg.StencilBackOpFail);
+ State.StencilBackOpZFail = (GalStencilOp)ReadRegister(NvGpuEngine3dReg.StencilBackOpZFail);
+ State.StencilBackOpZPass = (GalStencilOp)ReadRegister(NvGpuEngine3dReg.StencilBackOpZPass);
+ State.StencilBackMask = (uint)ReadRegister(NvGpuEngine3dReg.StencilBackMask);
+
+ State.StencilFrontFuncFunc = (GalComparisonOp)ReadRegister(NvGpuEngine3dReg.StencilFrontFuncFunc);
+ State.StencilFrontFuncRef = ReadRegister(NvGpuEngine3dReg.StencilFrontFuncRef);
+ State.StencilFrontFuncMask = (uint)ReadRegister(NvGpuEngine3dReg.StencilFrontFuncMask);
+ State.StencilFrontOpFail = (GalStencilOp)ReadRegister(NvGpuEngine3dReg.StencilFrontOpFail);
+ State.StencilFrontOpZFail = (GalStencilOp)ReadRegister(NvGpuEngine3dReg.StencilFrontOpZFail);
+ State.StencilFrontOpZPass = (GalStencilOp)ReadRegister(NvGpuEngine3dReg.StencilFrontOpZPass);
+ State.StencilFrontMask = (uint)ReadRegister(NvGpuEngine3dReg.StencilFrontMask);
}
-
- if (!Enable)
- {
- return;
- }
-
- void SetFaceStencil(
- bool IsFrontFace,
- NvGpuEngine3dReg Func,
- NvGpuEngine3dReg FuncRef,
- NvGpuEngine3dReg FuncMask,
- NvGpuEngine3dReg OpFail,
- NvGpuEngine3dReg OpZFail,
- NvGpuEngine3dReg OpZPass,
- NvGpuEngine3dReg Mask)
- {
- Gpu.Renderer.Rasterizer.SetStencilFunction(
- IsFrontFace,
- (GalComparisonOp)ReadRegister(Func),
- ReadRegister(FuncRef),
- ReadRegister(FuncMask));
-
- Gpu.Renderer.Rasterizer.SetStencilOp(
- IsFrontFace,
- (GalStencilOp)ReadRegister(OpFail),
- (GalStencilOp)ReadRegister(OpZFail),
- (GalStencilOp)ReadRegister(OpZPass));
-
- Gpu.Renderer.Rasterizer.SetStencilMask(IsFrontFace, ReadRegister(Mask));
- }
-
- SetFaceStencil(false,
- NvGpuEngine3dReg.StencilBackFuncFunc,
- NvGpuEngine3dReg.StencilBackFuncRef,
- NvGpuEngine3dReg.StencilBackFuncMask,
- NvGpuEngine3dReg.StencilBackOpFail,
- NvGpuEngine3dReg.StencilBackOpZFail,
- NvGpuEngine3dReg.StencilBackOpZPass,
- NvGpuEngine3dReg.StencilBackMask);
-
- SetFaceStencil(true,
- NvGpuEngine3dReg.StencilFrontFuncFunc,
- NvGpuEngine3dReg.StencilFrontFuncRef,
- NvGpuEngine3dReg.StencilFrontFuncMask,
- NvGpuEngine3dReg.StencilFrontOpFail,
- NvGpuEngine3dReg.StencilFrontOpZFail,
- NvGpuEngine3dReg.StencilFrontOpZPass,
- NvGpuEngine3dReg.StencilFrontMask);
}
- private void SetAlphaBlending()
+ private void SetAlphaBlending(GalPipelineState State)
{
//TODO: Support independent blend properly.
- bool Enable = (ReadRegister(NvGpuEngine3dReg.IBlendNEnable) & 1) != 0;
+ State.BlendEnabled = (ReadRegister(NvGpuEngine3dReg.IBlendNEnable) & 1) != 0;
- if (Enable)
- {
- Gpu.Renderer.Blend.Enable();
- }
- else
+ if (State.BlendEnabled)
{
- Gpu.Renderer.Blend.Disable();
- }
+ State.BlendSeparateAlpha = (ReadRegister(NvGpuEngine3dReg.IBlendNSeparateAlpha) & 1) != 0;
- if (!Enable)
- {
- //If blend is not enabled, then the other values have no effect.
- //Note that if it is disabled, the register may contain invalid values.
- return;
- }
-
- bool BlendSeparateAlpha = (ReadRegister(NvGpuEngine3dReg.IBlendNSeparateAlpha) & 1) != 0;
-
- GalBlendEquation EquationRgb = (GalBlendEquation)ReadRegister(NvGpuEngine3dReg.IBlendNEquationRgb);
-
- GalBlendFactor FuncSrcRgb = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncSrcRgb);
- GalBlendFactor FuncDstRgb = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncDstRgb);
-
- if (BlendSeparateAlpha)
- {
- GalBlendEquation EquationAlpha = (GalBlendEquation)ReadRegister(NvGpuEngine3dReg.IBlendNEquationAlpha);
-
- GalBlendFactor FuncSrcAlpha = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncSrcAlpha);
- GalBlendFactor FuncDstAlpha = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncDstAlpha);
-
- Gpu.Renderer.Blend.SetSeparate(
- EquationRgb,
- EquationAlpha,
- FuncSrcRgb,
- FuncDstRgb,
- FuncSrcAlpha,
- FuncDstAlpha);
- }
- else
- {
- Gpu.Renderer.Blend.Set(EquationRgb, FuncSrcRgb, FuncDstRgb);
+ State.BlendEquationRgb = (GalBlendEquation)ReadRegister(NvGpuEngine3dReg.IBlendNEquationRgb);
+ State.BlendFuncSrcRgb = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncSrcRgb);
+ State.BlendFuncDstRgb = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncDstRgb);
+ State.BlendEquationAlpha = (GalBlendEquation)ReadRegister(NvGpuEngine3dReg.IBlendNEquationAlpha);
+ State.BlendFuncSrcAlpha = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncSrcAlpha);
+ State.BlendFuncDstAlpha = (GalBlendFactor)ReadRegister(NvGpuEngine3dReg.IBlendNFuncDstAlpha);
}
}
- private void SetPrimitiveRestart()
+ private void SetPrimitiveRestart(GalPipelineState State)
{
- bool Enable = (ReadRegister(NvGpuEngine3dReg.PrimRestartEnable) & 1) != 0;
-
- if (Enable)
- {
- Gpu.Renderer.Rasterizer.EnablePrimitiveRestart();
- }
- else
- {
- Gpu.Renderer.Rasterizer.DisablePrimitiveRestart();
- }
+ State.PrimitiveRestartEnabled = (ReadRegister(NvGpuEngine3dReg.PrimRestartEnable) & 1) != 0;
- if (!Enable)
+ if (State.PrimitiveRestartEnabled)
{
- return;
+ State.PrimitiveRestartIndex = (uint)ReadRegister(NvGpuEngine3dReg.PrimRestartIndex);
}
-
- uint Index = (uint)ReadRegister(NvGpuEngine3dReg.PrimRestartIndex);
-
- Gpu.Renderer.Rasterizer.SetPrimitiveRestartIndex(Index);
}
- private void UploadTextures(NvGpuVmm Vmm, long[] Keys)
+ private void UploadTextures(NvGpuVmm Vmm, GalPipelineState State, long[] Keys)
{
long BaseShPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.ShaderAddress);
@@ -546,45 +452,35 @@ namespace Ryujinx.HLE.Gpu.Engines
Gpu.Renderer.Texture.SetSampler(Sampler);
}
- private void UploadUniforms(NvGpuVmm Vmm)
+ private void UploadConstBuffers(NvGpuVmm Vmm, GalPipelineState State)
{
- long BasePosition = MakeInt64From2xInt32(NvGpuEngine3dReg.ShaderAddress);
-
- for (int Index = 0; Index < 5; Index++)
+ for (int Stage = 0; Stage < State.ConstBufferKeys.Length; Stage++)
{
- int Control = ReadRegister(NvGpuEngine3dReg.ShaderNControl + (Index + 1) * 0x10);
- int Offset = ReadRegister(NvGpuEngine3dReg.ShaderNOffset + (Index + 1) * 0x10);
-
- //Note: Vertex Program (B) is always enabled.
- bool Enable = (Control & 1) != 0 || Index == 0;
-
- if (!Enable)
+ for (int Index = 0; Index < State.ConstBufferKeys[Stage].Length; Index++)
{
- continue;
- }
+ ConstBuffer Cb = ConstBuffers[Stage][Index];
- for (int Cbuf = 0; Cbuf < ConstBuffers[Index].Length; Cbuf++)
- {
- ConstBuffer Cb = ConstBuffers[Index][Cbuf];
+ long Key = Cb.Position;
- if (Cb.Enabled)
+ if (Cb.Enabled && QueryKeyUpload(Vmm, Key, Cb.Size, NvGpuBufferType.ConstBuffer))
{
- IntPtr DataAddress = Vmm.GetHostAddress(Cb.Position, Cb.Size);
+ IntPtr Source = Vmm.GetHostAddress(Key, Cb.Size);
- Gpu.Renderer.Shader.SetConstBuffer(BasePosition + (uint)Offset, Cbuf, Cb.Size, DataAddress);
+ Gpu.Renderer.Buffer.SetData(Key, Cb.Size, Source);
}
+
+ State.ConstBufferKeys[Stage][Index] = Key;
}
}
}
- private void UploadVertexArrays(NvGpuVmm Vmm)
+ private void UploadVertexArrays(NvGpuVmm Vmm, GalPipelineState State)
{
long IndexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.IndexArrayAddress);
long IboKey = Vmm.GetPhysicalAddress(IndexPosition);
int IndexEntryFmt = ReadRegister(NvGpuEngine3dReg.IndexArrayFormat);
- int IndexFirst = ReadRegister(NvGpuEngine3dReg.IndexBatchFirst);
int IndexCount = ReadRegister(NvGpuEngine3dReg.IndexBatchCount);
GalIndexFormat IndexFormat = (GalIndexFormat)IndexEntryFmt;
@@ -634,10 +530,7 @@ namespace Ryujinx.HLE.Gpu.Engines
((Packed >> 31) & 0x1) != 0));
}
- int VertexFirst = ReadRegister(NvGpuEngine3dReg.VertexArrayFirst);
- int VertexCount = ReadRegister(NvGpuEngine3dReg.VertexArrayCount);
-
- int PrimCtrl = ReadRegister(NvGpuEngine3dReg.VertexBeginGl);
+ State.VertexBindings = new GalVertexBinding[32];
for (int Index = 0; Index < 32; Index++)
{
@@ -650,14 +543,14 @@ namespace Ryujinx.HLE.Gpu.Engines
bool Enable = (Control & 0x1000) != 0;
- long VertexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNAddress + Index * 4);
- long VertexEndPos = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNEndAddr + Index * 2);
-
if (!Enable)
{
continue;
}
+ long VertexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNAddress + Index * 4);
+ long VertexEndPos = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNEndAddr + Index * 2);
+
long VboKey = Vmm.GetPhysicalAddress(VertexPosition);
int Stride = Control & 0xfff;
@@ -673,19 +566,39 @@ namespace Ryujinx.HLE.Gpu.Engines
Gpu.Renderer.Rasterizer.CreateVbo(VboKey, (int)VbSize, DataAddress);
}
- Gpu.Renderer.Rasterizer.SetVertexArray(Stride, VboKey, Attribs[Index].ToArray());
+ State.VertexBindings[Index].Enabled = true;
+ State.VertexBindings[Index].Stride = Stride;
+ State.VertexBindings[Index].VboKey = VboKey;
+ State.VertexBindings[Index].Attribs = Attribs[Index].ToArray();
}
+ }
+
+ private void DispatchRender(NvGpuVmm Vmm, GalPipelineState State)
+ {
+ int IndexCount = ReadRegister(NvGpuEngine3dReg.IndexBatchCount);
+ int PrimCtrl = ReadRegister(NvGpuEngine3dReg.VertexBeginGl);
GalPrimitiveType PrimType = (GalPrimitiveType)(PrimCtrl & 0xffff);
+ Gpu.Renderer.Pipeline.Bind(State);
+
if (IndexCount != 0)
{
- int VertexBase = ReadRegister(NvGpuEngine3dReg.VertexArrayElemBase);
+ int IndexEntryFmt = ReadRegister(NvGpuEngine3dReg.IndexArrayFormat);
+ int IndexFirst = ReadRegister(NvGpuEngine3dReg.IndexBatchFirst);
+ int VertexBase = ReadRegister(NvGpuEngine3dReg.VertexArrayElemBase);
+
+ long IndexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.IndexArrayAddress);
+
+ long IboKey = Vmm.GetPhysicalAddress(IndexPosition);
Gpu.Renderer.Rasterizer.DrawElements(IboKey, IndexFirst, VertexBase, PrimType);
}
else
{
+ int VertexFirst = ReadRegister(NvGpuEngine3dReg.VertexArrayFirst);
+ int VertexCount = ReadRegister(NvGpuEngine3dReg.VertexArrayCount);
+
Gpu.Renderer.Rasterizer.DrawArrays(VertexFirst, VertexCount, PrimType);
}
}
@@ -741,10 +654,21 @@ namespace Ryujinx.HLE.Gpu.Engines
long Position = MakeInt64From2xInt32(NvGpuEngine3dReg.ConstBufferAddress);
- ConstBuffers[Stage][Index].Position = Position;
- ConstBuffers[Stage][Index].Enabled = Enabled;
+ int Size = ReadRegister(NvGpuEngine3dReg.ConstBufferSize);
- ConstBuffers[Stage][Index].Size = ReadRegister(NvGpuEngine3dReg.ConstBufferSize);
+ if (!Gpu.Renderer.Buffer.IsCached(Position, Size))
+ {
+ Gpu.Renderer.Buffer.Create(Position, Size);
+ }
+
+ ConstBuffer Cb = ConstBuffers[Stage][Index];
+
+ if (Cb.Position != Position || Cb.Enabled != Enabled || Cb.Size != Size)
+ {
+ ConstBuffers[Stage][Index].Position = Position;
+ ConstBuffers[Stage][Index].Enabled = Enabled;
+ ConstBuffers[Stage][Index].Size = Size;
+ }
}
private float GetFlipSign(NvGpuEngine3dReg Reg)
diff --git a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs
index e7dabe44..39a5ee8c 100644
--- a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs
+++ b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs
@@ -16,6 +16,7 @@ namespace Ryujinx.HLE.Gpu.Engines
ViewportNVert = 0x301,
VertexArrayFirst = 0x35d,
VertexArrayCount = 0x35e,
+ ClearNColor = 0x360,
ClearDepth = 0x364,
ClearStencil = 0x368,
StencilBackFuncRef = 0x3d5,
diff --git a/Ryujinx.HLE/Gpu/Memory/NvGpuBufferType.cs b/Ryujinx.HLE/Gpu/Memory/NvGpuBufferType.cs
index 469cd6cd..a6c03f42 100644
--- a/Ryujinx.HLE/Gpu/Memory/NvGpuBufferType.cs
+++ b/Ryujinx.HLE/Gpu/Memory/NvGpuBufferType.cs
@@ -5,6 +5,7 @@ namespace Ryujinx.HLE.Gpu.Memory
Index,
Vertex,
Texture,
+ ConstBuffer,
Count
}
} \ No newline at end of file