aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.OpenGL
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.OpenGL')
-rw-r--r--Ryujinx.Graphics.OpenGL/EnumConversion.cs15
-rw-r--r--Ryujinx.Graphics.OpenGL/Program.cs72
-rw-r--r--Ryujinx.Graphics.OpenGL/Renderer.cs14
-rw-r--r--Ryujinx.Graphics.OpenGL/Shader.cs42
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;
- }
- }
- }
-}