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/Gal/OpenGL/OGLShader.cs | |
| 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/Gal/OpenGL/OGLShader.cs')
| -rw-r--r-- | Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs | 222 |
1 files changed, 49 insertions, 173 deletions
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; |
