From 3361eb389b9bab515688e07eab365221aba77fca Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 1 Aug 2018 02:04:10 -0300 Subject: [PATCH] Move Uniform binds to GalPipelineState --- Ryujinx.Graphics/Gal/GalPipelineState.cs | 21 ++- Ryujinx.Graphics/Gal/IGalConstBuffer.cs | 2 - Ryujinx.Graphics/Gal/IGalPipeline.cs | 2 +- Ryujinx.Graphics/Gal/IGalShader.cs | 2 - Ryujinx.Graphics/Gal/OpenGL/OGLConstBuffer.cs | 30 ++-- Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs | 143 ++++++++++++------ Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs | 2 +- Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs | 128 ++-------------- .../Gal/OpenGL/OGLShaderProgram.cs | 86 +++++++++++ Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs | 81 ++++------ 10 files changed, 247 insertions(+), 250 deletions(-) create mode 100644 Ryujinx.Graphics/Gal/OpenGL/OGLShaderProgram.cs diff --git a/Ryujinx.Graphics/Gal/GalPipelineState.cs b/Ryujinx.Graphics/Gal/GalPipelineState.cs index c35d226cbf..2be5f4517a 100644 --- a/Ryujinx.Graphics/Gal/GalPipelineState.cs +++ b/Ryujinx.Graphics/Gal/GalPipelineState.cs @@ -10,17 +10,12 @@ public GalVertexAttrib[] Attribs; } - public struct GalConstBufferBinding - { - public bool Enabled; - public long Key; - } - - public struct GalPipelineState + public class GalPipelineState { + public const int Stages = 5; public const int ConstBuffersPerStage = 18; - public GalConstBufferBinding[][] ConstBufferKeys; + public long[][] ConstBufferKeys; public GalVertexBinding[] VertexBindings; @@ -63,5 +58,15 @@ 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/IGalConstBuffer.cs b/Ryujinx.Graphics/Gal/IGalConstBuffer.cs index 3e87d0641c..37545b2a99 100644 --- a/Ryujinx.Graphics/Gal/IGalConstBuffer.cs +++ b/Ryujinx.Graphics/Gal/IGalConstBuffer.cs @@ -12,7 +12,5 @@ namespace Ryujinx.Graphics.Gal bool IsCached(long Key, long Size); void SetData(long Key, long Size, IntPtr HostAddress); - - void Bind(GalShaderType ShaderType, int Index, long Key); } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/IGalPipeline.cs b/Ryujinx.Graphics/Gal/IGalPipeline.cs index 1fad7a4ecd..d8cf266af4 100644 --- a/Ryujinx.Graphics/Gal/IGalPipeline.cs +++ b/Ryujinx.Graphics/Gal/IGalPipeline.cs @@ -2,6 +2,6 @@ { public interface IGalPipeline { - void Bind(ref GalPipelineState State); + void Bind(GalPipelineState State); } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/IGalShader.cs b/Ryujinx.Graphics/Gal/IGalShader.cs index 7103227cbe..4f351e0b9c 100644 --- a/Ryujinx.Graphics/Gal/IGalShader.cs +++ b/Ryujinx.Graphics/Gal/IGalShader.cs @@ -11,8 +11,6 @@ namespace Ryujinx.Graphics.Gal IEnumerable GetTextureUsage(long Key); - void BindConstBuffers(); - void EnsureTextureBinding(string UniformName, int Value); void SetFlip(float X, float Y); diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLConstBuffer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLConstBuffer.cs index 3451de2c79..5082554135 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLConstBuffer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLConstBuffer.cs @@ -5,22 +5,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL { class OGLConstBuffer : IGalConstBuffer { - public const int ConstBuffersPerStage = 18; - private OGLCachedResource Cache; - private long[][] Keys; - public OGLConstBuffer() { Cache = new OGLCachedResource(DeleteBuffer); - - Keys = new long[5][]; - - for (int i = 0; i < Keys.Length; i++) - { - Keys[i] = new long[ConstBuffersPerStage]; - } } public void LockCache() @@ -55,19 +44,18 @@ namespace Ryujinx.Graphics.Gal.OpenGL Buffer.SetData(Size, HostAddress); } - public void Bind(GalShaderType Stage, int Index, long Key) + public bool TryGetUbo(long Key, out int UboHandle) { - Keys[(int)Stage][Index] = Key; - } - - public void PipelineBind(GalShaderType Stage, int Index, int BindingIndex) - { - long Key = Keys[(int)Stage][Index]; - - if (Key != 0 && Cache.TryGetValue(Key, out OGLStreamBuffer Buffer)) + if (Cache.TryGetValue(Key, out OGLStreamBuffer Buffer)) { - GL.BindBufferBase(BufferRangeTarget.UniformBuffer, BindingIndex, Buffer.Handle); + UboHandle = Buffer.Handle; + + return true; } + + UboHandle = 0; + + return false; } private static void DeleteBuffer(OGLStreamBuffer Buffer) diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs index 4e2fbc72ca..ba4a1f0a82 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; namespace Ryujinx.Graphics.Gal.OpenGL { - public class OGLPipeline : IGalPipeline + class OGLPipeline : IGalPipeline { private static Dictionary AttribElements = new Dictionary() @@ -46,13 +46,17 @@ namespace Ryujinx.Graphics.Gal.OpenGL private GalPipelineState O; + private OGLConstBuffer Buffer; private OGLRasterizer Rasterizer; + private OGLShader Shader; private int VaoHandle; - public OGLPipeline(OGLRasterizer Rasterizer) + public OGLPipeline(OGLConstBuffer Buffer, OGLRasterizer Rasterizer, OGLShader Shader) { + this.Buffer = Buffer; this.Rasterizer = Rasterizer; + this.Shader = Shader; //These values match OpenGL's defaults O = new GalPipelineState @@ -100,58 +104,13 @@ namespace Ryujinx.Graphics.Gal.OpenGL }; } - public void Bind(ref GalPipelineState S) + public void Bind(GalPipelineState S) { //O stands for Older, S for (current) State - foreach (GalVertexBinding Binding in S.VertexBindings) - { - if (!Binding.Enabled || !Rasterizer.TryGetVbo(Binding.VboKey, out int VboHandle)) - { - continue; - } + BindUniforms(S); - 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; - - GL.VertexAttribPointer(Attrib.Index, Size, Type, Normalize, Binding.Stride, Offset); - } - } + BindVertexLayout(S); //Note: Uncomment SetFrontFace and SetCullFace when flipping issues are solved @@ -320,6 +279,90 @@ namespace Ryujinx.Graphics.Gal.OpenGL O = S; } + private void BindUniforms(GalPipelineState S) + { + int FreeBinding = 0; + + void BindIfNotNull(OGLShaderStage Stage) + { + if (Stage != null) + { + foreach (ShaderDeclInfo DeclInfo in Stage.UniformUsage) + { + long Key = S.ConstBufferKeys[(int)Stage.Type][DeclInfo.Cbuf]; + + if (Key != 0 && Key != O.ConstBufferKeys[(int)Stage.Type][DeclInfo.Cbuf]) + { + if (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 S) + { + foreach (GalVertexBinding Binding in S.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; + + GL.VertexAttribPointer(Attrib.Index, Size, Type, Normalize, Binding.Stride, Offset); + } + } + } + private void Enable(EnableCap Cap, bool Enabled) { if (Enabled) diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs index db0c4400dd..b0f6da45e5 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs @@ -29,7 +29,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL Shader = new OGLShader(Buffer as OGLConstBuffer); - Pipeline = new OGLPipeline(Rasterizer as OGLRasterizer); + 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 25c2314391..895a9b79e3 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs @@ -11,71 +11,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL { class OGLShader : IGalShader { - private class ShaderStage : IDisposable - { - public int Handle { get; private set; } + public OGLShaderProgram Current; - public bool IsCompiled { get; private set; } + private ConcurrentDictionary Stages; - public GalShaderType Type { get; private set; } - - public string Code { get; private set; } - - public IEnumerable TextureUsage { get; private set; } - public IEnumerable UniformUsage { get; private set; } - - public ShaderStage( - GalShaderType Type, - string Code, - IEnumerable TextureUsage, - IEnumerable 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; - } - - private ShaderProgram Current; - - private ConcurrentDictionary Stages; - - private Dictionary Programs; + private Dictionary Programs; public int CurrentProgramHandle { get; private set; } @@ -85,9 +25,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL { this.Buffer = Buffer; - Stages = new ConcurrentDictionary(); + Stages = new ConcurrentDictionary(); - Programs = new Dictionary(); + Programs = new Dictionary(); } public void Create(IGalMemory Memory, long Key, GalShaderType Type) @@ -100,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, @@ -129,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, @@ -138,7 +78,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL public IEnumerable GetTextureUsage(long Key) { - if (Stages.TryGetValue(Key, out ShaderStage Stage)) + if (Stages.TryGetValue(Key, out OGLShaderStage Stage)) { return Stage.TextureUsage; } @@ -146,30 +86,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL return Enumerable.Empty(); } - public void BindConstBuffers() - { - int FreeBinding = 0; - - void BindIfNotNull(ShaderStage Stage) - { - if (Stage != null) - { - foreach (ShaderDeclInfo DeclInfo in Stage.UniformUsage) - { - Buffer.PipelineBind(Stage.Type, DeclInfo.Cbuf, FreeBinding); - - FreeBinding++; - } - } - } - - BindIfNotNull(Current.Vertex); - BindIfNotNull(Current.TessControl); - BindIfNotNull(Current.TessEvaluation); - BindIfNotNull(Current.Geometry); - BindIfNotNull(Current.Fragment); - } - public void EnsureTextureBinding(string UniformName, int Value) { BindProgram(); @@ -190,13 +106,13 @@ namespace Ryujinx.Graphics.Gal.OpenGL 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) { @@ -262,7 +178,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL CurrentProgramHandle = Handle; } - private void AttachIfNotNull(int ProgramHandle, ShaderStage Stage) + private void AttachIfNotNull(int ProgramHandle, OGLShaderStage Stage) { if (Stage != null) { @@ -276,7 +192,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL { int FreeBinding = 0; - void BindUniformBlocksIfNotNull(ShaderStage Stage) + void BindUniformBlocksIfNotNull(OGLShaderStage Stage) { if (Stage != null) { @@ -304,26 +220,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL BindUniformBlocksIfNotNull(Current.Fragment); } - 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 0000000000..731994cec7 --- /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 TextureUsage { get; private set; } + public IEnumerable UniformUsage { get; private set; } + + public OGLShaderStage( + GalShaderType Type, + string Code, + IEnumerable TextureUsage, + IEnumerable 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.HLE/Gpu/Engines/NvGpuEngine3d.cs b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs index be993d4dec..8fe8c7be67 100644 --- a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs +++ b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs @@ -27,10 +27,6 @@ namespace Ryujinx.HLE.Gpu.Engines private List[] UploadedKeys; - private GalPipelineState State; - - private bool ConstBufferBindingsChanged; - public NvGpuEngine3d(NvGpu Gpu) { this.Gpu = Gpu; @@ -70,8 +66,6 @@ namespace Ryujinx.HLE.Gpu.Engines { UploadedKeys[i] = new List(); } - - State = new GalPipelineState(); } public void CallMethod(NvGpuVmm Vmm, NvGpuPBEntry PBEntry) @@ -90,32 +84,26 @@ namespace Ryujinx.HLE.Gpu.Engines { LockCaches(); + GalPipelineState State = new GalPipelineState(); + SetFrameBuffer(Vmm, 0); long[] Keys = UploadShaders(Vmm); Gpu.Renderer.Shader.BindProgram(); - if (ConstBufferBindingsChanged) - { - ConstBufferBindingsChanged = false; + SetFrontFace(State); + SetCullFace(State); + SetDepth(State); + SetStencil(State); + SetAlphaBlending(State); + SetPrimitiveRestart(State); - Gpu.Renderer.Shader.BindConstBuffers(); - } + UploadTextures(Vmm, State, Keys); + UploadConstBuffers(Vmm, State); + UploadVertexArrays(Vmm, State); - //Note: Uncomment SetFrontFace and SetCullFace when flipping issues are solved - //SetFrontFace(); - //SetCullFace(); - SetDepth(); - SetStencil(); - SetAlphaBlending(); - SetPrimitiveRestart(); - - UploadTextures(Vmm, Keys); - UploadConstBuffers(Vmm); - UploadVertexArrays(Vmm); - - DispatchRender(Vmm); + DispatchRender(Vmm, State); UnlockCaches(); } @@ -256,7 +244,7 @@ namespace Ryujinx.HLE.Gpu.Engines throw new ArgumentOutOfRangeException(nameof(Program)); } - private void SetFrontFace() + private void SetFrontFace(GalPipelineState State) { float SignX = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleX); float SignY = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleY); @@ -281,7 +269,7 @@ namespace Ryujinx.HLE.Gpu.Engines State.FrontFace = FrontFace; } - private void SetCullFace() + private void SetCullFace(GalPipelineState State) { State.CullFaceEnabled = (ReadRegister(NvGpuEngine3dReg.CullFaceEnable) & 1) != 0; @@ -291,7 +279,7 @@ namespace Ryujinx.HLE.Gpu.Engines } } - private void SetDepth() + private void SetDepth(GalPipelineState State) { State.DepthTestEnabled = (ReadRegister(NvGpuEngine3dReg.DepthTestEnable) & 1) != 0; @@ -303,7 +291,7 @@ namespace Ryujinx.HLE.Gpu.Engines } } - private void SetStencil() + private void SetStencil(GalPipelineState State) { State.StencilTestEnabled = (ReadRegister(NvGpuEngine3dReg.StencilEnable) & 1) != 0; @@ -329,7 +317,7 @@ namespace Ryujinx.HLE.Gpu.Engines } } - private void SetAlphaBlending() + private void SetAlphaBlending(GalPipelineState State) { //TODO: Support independent blend properly. State.BlendEnabled = (ReadRegister(NvGpuEngine3dReg.IBlendNEnable) & 1) != 0; @@ -347,7 +335,7 @@ namespace Ryujinx.HLE.Gpu.Engines } } - private void SetPrimitiveRestart() + private void SetPrimitiveRestart(GalPipelineState State) { State.PrimitiveRestartEnabled = (ReadRegister(NvGpuEngine3dReg.PrimRestartEnable) & 1) != 0; @@ -357,7 +345,7 @@ namespace Ryujinx.HLE.Gpu.Engines } } - private void UploadTextures(NvGpuVmm Vmm, long[] Keys) + private void UploadTextures(NvGpuVmm Vmm, GalPipelineState State, long[] Keys) { long BaseShPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.ShaderAddress); @@ -451,30 +439,29 @@ namespace Ryujinx.HLE.Gpu.Engines Gpu.Renderer.Texture.SetSampler(Sampler); } - private void UploadConstBuffers(NvGpuVmm Vmm) + private void UploadConstBuffers(NvGpuVmm Vmm, GalPipelineState State) { - for (int Stage = 0; Stage < 5; Stage++) + for (int Stage = 0; Stage < State.ConstBufferKeys.Length; Stage++) { - for (int Index = 0; Index < 18; Index++) + for (int Index = 0; Index < State.ConstBufferKeys[Stage].Length; Index++) { ConstBuffer Cb = ConstBuffers[Stage][Index]; - if (Cb.Enabled) + long Key = Cb.Position; + + if (Cb.Enabled && QueryKeyUpload(Vmm, Key, Cb.Size, NvGpuBufferType.ConstBuffer)) { - long Key = Cb.Position; + IntPtr Source = Vmm.GetHostAddress(Key, Cb.Size); - if (QueryKeyUpload(Vmm, Key, Cb.Size, NvGpuBufferType.ConstBuffer)) - { - IntPtr Source = Vmm.GetHostAddress(Key, Cb.Size); - - Gpu.Renderer.Buffer.SetData(Key, Cb.Size, Source); - } + 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); @@ -573,14 +560,14 @@ namespace Ryujinx.HLE.Gpu.Engines } } - private void DispatchRender(NvGpuVmm Vmm) + 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(ref State); + Gpu.Renderer.Pipeline.Bind(State); if (IndexCount != 0) { @@ -665,10 +652,6 @@ namespace Ryujinx.HLE.Gpu.Engines if (Cb.Position != Position || Cb.Enabled != Enabled || Cb.Size != Size) { - Gpu.Renderer.Buffer.Bind((GalShaderType)Stage, Index, Enabled ? Position : 0); - - ConstBufferBindingsChanged = true; - ConstBuffers[Stage][Index].Position = Position; ConstBuffers[Stage][Index].Enabled = Enabled; ConstBuffers[Stage][Index].Size = Size;