diff options
Diffstat (limited to 'Ryujinx.Graphics.OpenGL')
-rw-r--r-- | Ryujinx.Graphics.OpenGL/EnumConversion.cs | 15 | ||||
-rw-r--r-- | Ryujinx.Graphics.OpenGL/Program.cs | 72 | ||||
-rw-r--r-- | Ryujinx.Graphics.OpenGL/Renderer.cs | 14 | ||||
-rw-r--r-- | Ryujinx.Graphics.OpenGL/Shader.cs | 42 |
4 files changed, 69 insertions, 74 deletions
diff --git a/Ryujinx.Graphics.OpenGL/EnumConversion.cs b/Ryujinx.Graphics.OpenGL/EnumConversion.cs index 22e81605..24cf1fc4 100644 --- a/Ryujinx.Graphics.OpenGL/EnumConversion.cs +++ b/Ryujinx.Graphics.OpenGL/EnumConversion.cs @@ -1,6 +1,7 @@ using OpenTK.Graphics.OpenGL; using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; +using Ryujinx.Graphics.Shader; namespace Ryujinx.Graphics.OpenGL { @@ -528,5 +529,19 @@ namespace Ryujinx.Graphics.OpenGL return All.Never; } + + public static ShaderType Convert(this ShaderStage stage) + { + return stage switch + { + ShaderStage.Compute => ShaderType.ComputeShader, + ShaderStage.Vertex => ShaderType.VertexShader, + ShaderStage.TessellationControl => ShaderType.TessControlShader, + ShaderStage.TessellationEvaluation => ShaderType.TessEvaluationShader, + ShaderStage.Geometry => ShaderType.GeometryShader, + ShaderStage.Fragment => ShaderType.FragmentShader, + _ => ShaderType.VertexShader + }; + } } } diff --git a/Ryujinx.Graphics.OpenGL/Program.cs b/Ryujinx.Graphics.OpenGL/Program.cs index d2b559a8..0cc722e6 100644 --- a/Ryujinx.Graphics.OpenGL/Program.cs +++ b/Ryujinx.Graphics.OpenGL/Program.cs @@ -1,6 +1,8 @@ using OpenTK.Graphics.OpenGL; using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; +using Ryujinx.Graphics.Shader; +using Ryujinx.Graphics.Shader.Translation; using System; using System.Buffers.Binary; @@ -24,46 +26,66 @@ namespace Ryujinx.Graphics.OpenGL } private ProgramLinkStatus _status = ProgramLinkStatus.Incomplete; - private IShader[] _shaders; + private int[] _shaderHandles; public bool HasFragmentShader; public int FragmentOutputMap { get; } - public Program(IShader[] shaders, int fragmentOutputMap) + public Program(ShaderSource[] shaders, int fragmentOutputMap) { Handle = GL.CreateProgram(); GL.ProgramParameter(Handle, ProgramParameterName.ProgramBinaryRetrievableHint, 1); + _shaderHandles = new int[shaders.Length]; + for (int index = 0; index < shaders.Length; index++) { - Shader shader = (Shader)shaders[index]; + ShaderSource shader = shaders[index]; - if (shader.IsFragment) + if (shader.Stage == ShaderStage.Fragment) { HasFragmentShader = true; } - GL.AttachShader(Handle, shader.Handle); + int shaderHandle = GL.CreateShader(shader.Stage.Convert()); + + switch (shader.Language) + { + case TargetLanguage.Glsl: + GL.ShaderSource(shaderHandle, shader.Code); + GL.CompileShader(shaderHandle); + break; + case TargetLanguage.Spirv: + GL.ShaderBinary(1, ref shaderHandle, (BinaryFormat)All.ShaderBinaryFormatSpirVArb, shader.BinaryCode, shader.BinaryCode.Length); + GL.SpecializeShader(shaderHandle, "main", 0, (int[])null, (int[])null); + break; + } + + GL.AttachShader(Handle, shaderHandle); + + _shaderHandles[index] = shaderHandle; } GL.LinkProgram(Handle); - _shaders = shaders; FragmentOutputMap = fragmentOutputMap; } public Program(ReadOnlySpan<byte> code, bool hasFragmentShader, int fragmentOutputMap) { - BinaryFormat binaryFormat = (BinaryFormat)BinaryPrimitives.ReadInt32LittleEndian(code.Slice(code.Length - 4, 4)); - Handle = GL.CreateProgram(); - unsafe + if (code.Length >= 4) { - fixed (byte* ptr = code) + BinaryFormat binaryFormat = (BinaryFormat)BinaryPrimitives.ReadInt32LittleEndian(code.Slice(code.Length - 4, 4)); + + unsafe { - GL.ProgramBinary(Handle, binaryFormat, (IntPtr)ptr, code.Length - 4); + fixed (byte* ptr = code) + { + GL.ProgramBinary(Handle, binaryFormat, (IntPtr)ptr, code.Length - 4); + } } } @@ -89,18 +111,7 @@ namespace Ryujinx.Graphics.OpenGL } GL.GetProgram(Handle, GetProgramParameterName.LinkStatus, out int status); - - if (_shaders != null) - { - for (int index = 0; index < _shaders.Length; index++) - { - int shaderHandle = ((Shader)_shaders[index]).Handle; - - GL.DetachShader(Handle, shaderHandle); - } - - _shaders = null; - } + DeleteShaders(); if (status == 0) { @@ -129,10 +140,25 @@ namespace Ryujinx.Graphics.OpenGL return data; } + private void DeleteShaders() + { + if (_shaderHandles != null) + { + foreach (int shaderHandle in _shaderHandles) + { + GL.DetachShader(Handle, shaderHandle); + GL.DeleteShader(shaderHandle); + } + + _shaderHandles = null; + } + } + public void Dispose() { if (Handle != 0) { + DeleteShaders(); GL.DeleteProgram(Handle); Handle = 0; diff --git a/Ryujinx.Graphics.OpenGL/Renderer.cs b/Ryujinx.Graphics.OpenGL/Renderer.cs index 8a6b4689..2a9ab422 100644 --- a/Ryujinx.Graphics.OpenGL/Renderer.cs +++ b/Ryujinx.Graphics.OpenGL/Renderer.cs @@ -1,11 +1,10 @@ -using OpenTK.Graphics; -using OpenTK.Graphics.OpenGL; +using OpenTK.Graphics.OpenGL; using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.OpenGL.Image; using Ryujinx.Graphics.OpenGL.Queries; -using Ryujinx.Graphics.Shader; +using Ryujinx.Graphics.Shader.Translation; using System; namespace Ryujinx.Graphics.OpenGL @@ -54,11 +53,6 @@ namespace Ryujinx.Graphics.OpenGL ResourcePool = new ResourcePool(); } - public IShader CompileShader(ShaderStage stage, string code) - { - return new Shader(stage, code); - } - public BufferHandle CreateBuffer(int size) { BufferCount++; @@ -66,7 +60,7 @@ namespace Ryujinx.Graphics.OpenGL return Buffer.Create(size); } - public IProgram CreateProgram(IShader[] shaders, ShaderInfo info) + public IProgram CreateProgram(ShaderSource[] shaders, ShaderInfo info) { return new Program(shaders, info.FragmentOutputMap); } @@ -101,6 +95,8 @@ namespace Ryujinx.Graphics.OpenGL public Capabilities GetCapabilities() { return new Capabilities( + api: TargetApi.OpenGL, + vendorName: GpuVendor, hasFrontFacingBug: HwCapabilities.Vendor == HwCapabilities.GpuVendor.IntelWindows, hasVectorIndexingBug: HwCapabilities.Vendor == HwCapabilities.GpuVendor.AmdWindows, supportsAstcCompression: HwCapabilities.SupportsAstcCompression, diff --git a/Ryujinx.Graphics.OpenGL/Shader.cs b/Ryujinx.Graphics.OpenGL/Shader.cs deleted file mode 100644 index 8374fa62..00000000 --- a/Ryujinx.Graphics.OpenGL/Shader.cs +++ /dev/null @@ -1,42 +0,0 @@ -using OpenTK.Graphics.OpenGL; -using Ryujinx.Graphics.GAL; -using Ryujinx.Graphics.Shader; - -namespace Ryujinx.Graphics.OpenGL -{ - class Shader : IShader - { - public int Handle { get; private set; } - public bool IsFragment { get; } - - public Shader(ShaderStage stage, string code) - { - ShaderType type = stage switch - { - ShaderStage.Compute => ShaderType.ComputeShader, - ShaderStage.Vertex => ShaderType.VertexShader, - ShaderStage.TessellationControl => ShaderType.TessControlShader, - ShaderStage.TessellationEvaluation => ShaderType.TessEvaluationShader, - ShaderStage.Geometry => ShaderType.GeometryShader, - ShaderStage.Fragment => ShaderType.FragmentShader, - _ => ShaderType.VertexShader - }; - - Handle = GL.CreateShader(type); - IsFragment = stage == ShaderStage.Fragment; - - GL.ShaderSource(Handle, code); - GL.CompileShader(Handle); - } - - public void Dispose() - { - if (Handle != 0) - { - GL.DeleteShader(Handle); - - Handle = 0; - } - } - } -} |