diff options
| author | ReinUsesLisp <reinuseslisp@airmail.cc> | 2018-08-10 01:09:40 -0300 |
|---|---|---|
| committer | gdkchan <gab.dark.100@gmail.com> | 2018-08-10 01:09:40 -0300 |
| commit | 25dd5f4238d898120f2f65c4d5d5b9c192ce1e10 (patch) | |
| tree | 347a58054594d9236fd9c3fa1432e0ee45b99949 /Ryujinx.Graphics | |
| parent | 652238f526509ed54e1c0ba2e953097ef7b2501c (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
Diffstat (limited to 'Ryujinx.Graphics')
| -rw-r--r-- | Ryujinx.Graphics/Gal/GalPipelineState.cs | 73 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/IGalBlend.cs | 22 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/IGalConstBuffer.cs | 16 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/IGalPipeline.cs | 7 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/IGalRasterizer.cs | 42 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/IGalRenderer.cs | 4 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/IGalShader.cs | 4 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/OpenGL/OGLBlend.cs | 49 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/OpenGL/OGLConstBuffer.cs | 66 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs | 379 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs | 213 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs | 10 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs | 222 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/OpenGL/OGLShaderProgram.cs | 86 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/OpenGL/OGLStreamBuffer.cs | 10 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/Shader/GlslDecl.cs | 1 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs | 6 |
17 files changed, 718 insertions, 492 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(); |
