This commit is contained in:
Isaac Marovitz 2024-05-18 07:48:45 +08:00 committed by GitHub
commit d29e9464c7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
50 changed files with 2042 additions and 1891 deletions

View file

@ -28,7 +28,6 @@
<PackageVersion Include="NUnit" Version="3.13.3" />
<PackageVersion Include="NUnit3TestAdapter" Version="4.1.0" />
<PackageVersion Include="OpenTK.Core" Version="4.8.2" />
<PackageVersion Include="OpenTK.Graphics" Version="4.8.2" />
<PackageVersion Include="OpenTK.Audio.OpenAL" Version="4.8.2" />
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.8.2" />
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
@ -39,6 +38,10 @@
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
<PackageVersion Include="shaderc.net" Version="0.1.0" />
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
<PackageVersion Include="Silk.NET.OpenGL.Legacy" Version="2.16.0" />
<PackageVersion Include="Silk.NET.OpenGL.Legacy.Extensions.ARB" Version="2.16.0" />
<PackageVersion Include="Silk.NET.OpenGL.Legacy.Extensions.EXT" Version="2.16.0" />
<PackageVersion Include="Silk.NET.OpenGL.Legacy.Extensions.NV" Version="2.16.0" />
<PackageVersion Include="Silk.NET.Vulkan" Version="2.16.0" />
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.16.0" />
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.16.0" />

View file

@ -1,14 +1,14 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
using System;
namespace Ryujinx.Graphics.OpenGL
{
static class Buffer
{
public static void Clear(BufferHandle destination, int offset, int size, uint value)
public static void Clear(GL api, BufferHandle destination, int offset, uint size, uint value)
{
GL.BindBuffer(BufferTarget.CopyWriteBuffer, destination.ToInt32());
api.BindBuffer(BufferTargetARB.CopyWriteBuffer, destination.ToUInt32());
unsafe
{
@ -16,106 +16,97 @@ namespace Ryujinx.Graphics.OpenGL
valueArr[0] = value;
GL.ClearBufferSubData(
BufferTarget.CopyWriteBuffer,
PixelInternalFormat.Rgba8ui,
(IntPtr)offset,
(IntPtr)size,
api.ClearBufferSubData(
BufferTargetARB.CopyWriteBuffer,
SizedInternalFormat.Rgba8ui,
offset,
size,
PixelFormat.RgbaInteger,
PixelType.UnsignedByte,
(IntPtr)valueArr);
valueArr);
}
}
public static BufferHandle Create()
public static BufferHandle Create(GL api)
{
return Handle.FromInt32<BufferHandle>(GL.GenBuffer());
return Handle.FromUInt32<BufferHandle>(api.GenBuffer());
}
public static BufferHandle Create(int size)
public unsafe static BufferHandle Create(GL api, int size)
{
int handle = GL.GenBuffer();
uint handle = api.GenBuffer();
GL.BindBuffer(BufferTarget.CopyWriteBuffer, handle);
GL.BufferData(BufferTarget.CopyWriteBuffer, size, IntPtr.Zero, BufferUsageHint.DynamicDraw);
api.BindBuffer(BufferTargetARB.CopyWriteBuffer, handle);
api.BufferData(BufferTargetARB.CopyWriteBuffer, (uint)size, null, BufferUsageARB.DynamicDraw);
return Handle.FromInt32<BufferHandle>(handle);
return Handle.FromUInt32<BufferHandle>(handle);
}
public static BufferHandle CreatePersistent(int size)
public unsafe static BufferHandle CreatePersistent(GL api, int size)
{
int handle = GL.GenBuffer();
uint handle = api.GenBuffer();
GL.BindBuffer(BufferTarget.CopyWriteBuffer, handle);
GL.BufferStorage(BufferTarget.CopyWriteBuffer, size, IntPtr.Zero,
BufferStorageFlags.MapPersistentBit |
BufferStorageFlags.MapCoherentBit |
BufferStorageFlags.ClientStorageBit |
BufferStorageFlags.MapReadBit);
api.BindBuffer(BufferTargetARB.CopyWriteBuffer, handle);
api.BufferStorage(BufferStorageTarget.CopyWriteBuffer, (uint)size, null,
BufferStorageMask.MapPersistentBit |
BufferStorageMask.MapCoherentBit |
BufferStorageMask.ClientStorageBit |
BufferStorageMask.MapReadBit);
return Handle.FromInt32<BufferHandle>(handle);
return Handle.FromUInt32<BufferHandle>(handle);
}
public static void Copy(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size)
public static void Copy(GL api, BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size)
{
GL.BindBuffer(BufferTarget.CopyReadBuffer, source.ToInt32());
GL.BindBuffer(BufferTarget.CopyWriteBuffer, destination.ToInt32());
api.BindBuffer(BufferTargetARB.CopyReadBuffer, source.ToUInt32());
api.BindBuffer(BufferTargetARB.CopyWriteBuffer, destination.ToUInt32());
GL.CopyBufferSubData(
BufferTarget.CopyReadBuffer,
BufferTarget.CopyWriteBuffer,
(IntPtr)srcOffset,
(IntPtr)dstOffset,
(IntPtr)size);
api.CopyBufferSubData(
CopyBufferSubDataTarget.CopyReadBuffer,
CopyBufferSubDataTarget.CopyWriteBuffer,
srcOffset,
dstOffset,
(uint)size);
}
public static unsafe PinnedSpan<byte> GetData(OpenGLRenderer renderer, BufferHandle buffer, int offset, int size)
public static unsafe PinnedSpan<byte> GetData(OpenGLRenderer gd, BufferHandle buffer, int offset, int size)
{
// Data in the persistent buffer and host array is guaranteed to be available
// until the next time the host thread requests data.
if (renderer.PersistentBuffers.TryGet(buffer, out IntPtr ptr))
if (gd.PersistentBuffers.TryGet(buffer, out IntPtr ptr))
{
return new PinnedSpan<byte>(IntPtr.Add(ptr, offset).ToPointer(), size);
}
else if (HwCapabilities.UsePersistentBufferForFlush)
if (gd.Capabilities.UsePersistentBufferForFlush)
{
return PinnedSpan<byte>.UnsafeFromSpan(renderer.PersistentBuffers.Default.GetBufferData(buffer, offset, size));
return PinnedSpan<byte>.UnsafeFromSpan(gd.PersistentBuffers.Default.GetBufferData(buffer, offset, size));
}
else
{
IntPtr target = renderer.PersistentBuffers.Default.GetHostArray(size);
GL.BindBuffer(BufferTarget.CopyReadBuffer, buffer.ToInt32());
IntPtr target = gd.PersistentBuffers.Default.GetHostArray(size);
GL.GetBufferSubData(BufferTarget.CopyReadBuffer, (IntPtr)offset, size, target);
gd.Api.BindBuffer(BufferTargetARB.CopyReadBuffer, buffer.ToUInt32());
gd.Api.GetBufferSubData(BufferTargetARB.CopyReadBuffer, offset, (uint)size, (void*)target);
return new PinnedSpan<byte>(target.ToPointer(), size);
}
return new PinnedSpan<byte>(target.ToPointer(), size);
}
public static void Resize(BufferHandle handle, int size)
public unsafe static void Resize(GL api, BufferHandle handle, int size)
{
GL.BindBuffer(BufferTarget.CopyWriteBuffer, handle.ToInt32());
GL.BufferData(BufferTarget.CopyWriteBuffer, size, IntPtr.Zero, BufferUsageHint.StreamCopy);
api.BindBuffer(BufferTargetARB.CopyWriteBuffer, handle.ToUInt32());
api.BufferData(BufferTargetARB.CopyWriteBuffer, (uint)size, null, BufferUsageARB.StreamCopy);
}
public static void SetData(BufferHandle buffer, int offset, ReadOnlySpan<byte> data)
public static void SetData(GL api, BufferHandle buffer, int offset, ReadOnlySpan<byte> data)
{
GL.BindBuffer(BufferTarget.CopyWriteBuffer, buffer.ToInt32());
unsafe
{
fixed (byte* ptr = data)
{
GL.BufferSubData(BufferTarget.CopyWriteBuffer, (IntPtr)offset, data.Length, (IntPtr)ptr);
}
}
api.BindBuffer(BufferTargetARB.CopyWriteBuffer, buffer.ToUInt32());
api.BufferSubData(BufferTargetARB.CopyWriteBuffer, offset, (uint)data.Length, data);
}
public static void Delete(BufferHandle buffer)
public static void Delete(GL api, BufferHandle buffer)
{
GL.DeleteBuffer(buffer.ToInt32());
api.DeleteBuffer(buffer.ToUInt32());
}
}
}

View file

@ -1,6 +1,6 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Silk.NET.OpenGL.Legacy;
using System;
using System.Runtime.InteropServices;
using System.Threading;
@ -13,55 +13,58 @@ namespace Ryujinx.Graphics.OpenGL
private static int _counter;
public static void Initialize(GraphicsDebugLevel logLevel)
public unsafe static void Initialize(GL gl, GraphicsDebugLevel logLevel)
{
// Disable everything
GL.DebugMessageControl(DebugSourceControl.DontCare, DebugTypeControl.DontCare, DebugSeverityControl.DontCare, 0, (int[])null, false);
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DontCare, DebugSeverity.DontCare, 0, (uint[])null, false);
if (logLevel == GraphicsDebugLevel.None)
{
GL.Disable(EnableCap.DebugOutputSynchronous);
GL.DebugMessageCallback(null, IntPtr.Zero);
gl.Disable(EnableCap.DebugOutputSynchronous);
gl.DebugMessageCallback(null, null);
return;
}
GL.Enable(EnableCap.DebugOutputSynchronous);
gl.Enable(EnableCap.DebugOutputSynchronous);
if (logLevel == GraphicsDebugLevel.Error)
switch (logLevel)
{
GL.DebugMessageControl(DebugSourceControl.DontCare, DebugTypeControl.DebugTypeError, DebugSeverityControl.DontCare, 0, (int[])null, true);
}
else if (logLevel == GraphicsDebugLevel.Slowdowns)
{
GL.DebugMessageControl(DebugSourceControl.DontCare, DebugTypeControl.DebugTypeError, DebugSeverityControl.DontCare, 0, (int[])null, true);
GL.DebugMessageControl(DebugSourceControl.DontCare, DebugTypeControl.DebugTypePerformance, DebugSeverityControl.DontCare, 0, (int[])null, true);
}
else
{
GL.DebugMessageControl(DebugSourceControl.DontCare, DebugTypeControl.DontCare, DebugSeverityControl.DontCare, 0, (int[])null, true);
case GraphicsDebugLevel.Error:
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DebugTypeError, DebugSeverity.DontCare, 0, (uint[])null, true);
break;
case GraphicsDebugLevel.Slowdowns:
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DebugTypeError, DebugSeverity.DontCare, 0, (uint[])null, true);
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DebugTypePerformance, DebugSeverity.DontCare, 0, (uint[])null, true);
break;
default:
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DontCare, DebugSeverity.DontCare, 0, (uint[])null, true);
break;
}
_counter = 0;
_debugCallback = GLDebugHandler;
GL.DebugMessageCallback(_debugCallback, IntPtr.Zero);
gl.DebugMessageCallback(_debugCallback, null);
Logger.Warning?.Print(LogClass.Gpu, "OpenGL Debugging is enabled. Performance will be negatively impacted.");
}
private static void GLDebugHandler(
DebugSource source,
DebugType type,
GLEnum source,
GLEnum type,
int id,
DebugSeverity severity,
GLEnum severity,
int length,
IntPtr message,
IntPtr userParam)
{
string msg = Marshal.PtrToStringUTF8(message).Replace('\n', ' ');
switch (type)
DebugType debugType = (DebugType)type;
DebugSource debugSource = (DebugSource)source;
switch (debugType)
{
case DebugType.DebugTypeError:
Logger.Error?.Print(LogClass.Gpu, $"{severity}: {msg}\nCallStack={Environment.StackTrace}", "GLERROR");
@ -76,7 +79,7 @@ namespace Ryujinx.Graphics.OpenGL
Logger.Info?.Print(LogClass.Gpu, $"}} ({id}) {severity}: {msg}", "GLINFO");
break;
default:
if (source == DebugSource.DebugSourceApplication)
if (debugSource == DebugSource.DebugSourceApplication)
{
Logger.Info?.Print(LogClass.Gpu, $"{type} {severity}: {msg}", "GLINFO");
}
@ -89,21 +92,21 @@ namespace Ryujinx.Graphics.OpenGL
}
// Useful debug helpers
public static void PushGroup(string dbgMsg)
public static void PushGroup(GL gl, string dbgMsg)
{
int counter = Interlocked.Increment(ref _counter);
GL.PushDebugGroup(DebugSourceExternal.DebugSourceApplication, counter, dbgMsg.Length, dbgMsg);
gl.PushDebugGroup(DebugSource.DebugSourceApplication, (uint)counter, (uint)dbgMsg.Length, dbgMsg);
}
public static void PopGroup()
public static void PopGroup(GL gl)
{
GL.PopDebugGroup();
gl.PopDebugGroup();
}
public static void Print(string dbgMsg, DebugType type = DebugType.DebugTypeMarker, DebugSeverity severity = DebugSeverity.DebugSeverityNotification, int id = 999999)
public static void Print(GL gl, string dbgMsg, DebugType type = DebugType.DebugTypeMarker, DebugSeverity severity = DebugSeverity.DebugSeverityNotification, int id = 999999)
{
GL.DebugMessageInsert(DebugSourceExternal.DebugSourceApplication, type, id, severity, dbgMsg.Length, dbgMsg);
gl.DebugMessageInsert(DebugSource.DebugSourceApplication, type, (uint)id, severity, (uint)dbgMsg.Length, dbgMsg);
}
}
}

View file

@ -1,6 +1,7 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.OpenGL.Image;
using Silk.NET.OpenGL.Legacy;
using System;
using Sampler = Ryujinx.Graphics.OpenGL.Image.Sampler;
namespace Ryujinx.Graphics.OpenGL
{
@ -35,9 +36,9 @@ void main()
colour = texture(tex, texcoord);
}";
private int _vsHandle;
private int _fsHandle;
private int _programHandle;
private uint _vsHandle;
private uint _fsHandle;
private uint _programHandle;
private int _uniformSrcX0Location;
private int _uniformSrcY0Location;
private int _uniformSrcX1Location;
@ -45,6 +46,7 @@ void main()
private bool _initialized;
public void Draw(
GL api,
TextureView texture,
Sampler sampler,
float x0,
@ -56,9 +58,9 @@ void main()
float s1,
float t1)
{
EnsureInitialized();
EnsureInitialized(api);
GL.UseProgram(_programHandle);
api.UseProgram(_programHandle);
texture.Bind(0);
sampler.Bind(0);
@ -73,17 +75,17 @@ void main()
(t1, t0) = (t0, t1);
}
GL.Uniform1(_uniformSrcX0Location, s0);
GL.Uniform1(_uniformSrcY0Location, t0);
GL.Uniform1(_uniformSrcX1Location, s1);
GL.Uniform1(_uniformSrcY1Location, t1);
api.Uniform1(_uniformSrcX0Location, s0);
api.Uniform1(_uniformSrcY0Location, t0);
api.Uniform1(_uniformSrcX1Location, s1);
api.Uniform1(_uniformSrcY1Location, t1);
GL.ViewportIndexed(0, MathF.Min(x0, x1), MathF.Min(y0, y1), MathF.Abs(x1 - x0), MathF.Abs(y1 - y0));
api.ViewportIndexed(0, MathF.Min(x0, x1), MathF.Min(y0, y1), MathF.Abs(x1 - x0), MathF.Abs(y1 - y0));
GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
api.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
}
private void EnsureInitialized()
private void EnsureInitialized(GL api)
{
if (_initialized)
{
@ -92,41 +94,41 @@ void main()
_initialized = true;
_vsHandle = GL.CreateShader(ShaderType.VertexShader);
_fsHandle = GL.CreateShader(ShaderType.FragmentShader);
_vsHandle = api.CreateShader(ShaderType.VertexShader);
_fsHandle = api.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(_vsHandle, VertexShader);
GL.ShaderSource(_fsHandle, FragmentShader);
api.ShaderSource(_vsHandle, VertexShader);
api.ShaderSource(_fsHandle, FragmentShader);
GL.CompileShader(_vsHandle);
GL.CompileShader(_fsHandle);
api.CompileShader(_vsHandle);
api.CompileShader(_fsHandle);
_programHandle = GL.CreateProgram();
_programHandle = api.CreateProgram();
GL.AttachShader(_programHandle, _vsHandle);
GL.AttachShader(_programHandle, _fsHandle);
api.AttachShader(_programHandle, _vsHandle);
api.AttachShader(_programHandle, _fsHandle);
GL.LinkProgram(_programHandle);
api.LinkProgram(_programHandle);
GL.DetachShader(_programHandle, _vsHandle);
GL.DetachShader(_programHandle, _fsHandle);
api.DetachShader(_programHandle, _vsHandle);
api.DetachShader(_programHandle, _fsHandle);
_uniformSrcX0Location = GL.GetUniformLocation(_programHandle, "srcX0");
_uniformSrcY0Location = GL.GetUniformLocation(_programHandle, "srcY0");
_uniformSrcX1Location = GL.GetUniformLocation(_programHandle, "srcX1");
_uniformSrcY1Location = GL.GetUniformLocation(_programHandle, "srcY1");
_uniformSrcX0Location = api.GetUniformLocation(_programHandle, "srcX0");
_uniformSrcY0Location = api.GetUniformLocation(_programHandle, "srcY0");
_uniformSrcX1Location = api.GetUniformLocation(_programHandle, "srcX1");
_uniformSrcY1Location = api.GetUniformLocation(_programHandle, "srcY1");
}
public void Dispose()
public void Dispose(GL api)
{
if (!_initialized)
{
return;
}
GL.DeleteShader(_vsHandle);
GL.DeleteShader(_fsHandle);
GL.DeleteProgram(_programHandle);
api.DeleteShader(_vsHandle);
api.DeleteShader(_fsHandle);
api.DeleteProgram(_programHandle);
_initialized = false;
}

View file

@ -1,7 +1,7 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Common;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.OpenGL.Image;
using Silk.NET.OpenGL.Legacy;
using System;
using static Ryujinx.Graphics.OpenGL.Effects.ShaderHelper;
@ -9,15 +9,15 @@ namespace Ryujinx.Graphics.OpenGL.Effects
{
internal class FsrScalingFilter : IScalingFilter
{
private readonly OpenGLRenderer _renderer;
private readonly OpenGLRenderer _gd;
private int _inputUniform;
private int _outputUniform;
private int _sharpeningUniform;
private int _srcX0Uniform;
private int _srcX1Uniform;
private int _srcY0Uniform;
private int _scalingShaderProgram;
private int _sharpeningShaderProgram;
private uint _scalingShaderProgram;
private uint _sharpeningShaderProgram;
private float _scale = 1;
private int _srcY1Uniform;
private int _dstX0Uniform;
@ -37,19 +37,19 @@ namespace Ryujinx.Graphics.OpenGL.Effects
}
}
public FsrScalingFilter(OpenGLRenderer renderer)
public FsrScalingFilter(OpenGLRenderer gd)
{
Initialize();
_renderer = renderer;
_gd = gd;
}
public void Dispose()
{
if (_scalingShaderProgram != 0)
{
GL.DeleteProgram(_scalingShaderProgram);
GL.DeleteProgram(_sharpeningShaderProgram);
_gd.Api.DeleteProgram(_scalingShaderProgram);
_gd.Api.DeleteProgram(_sharpeningShaderProgram);
}
_intermediaryTexture?.Dispose();
@ -67,23 +67,23 @@ namespace Ryujinx.Graphics.OpenGL.Effects
sharpeningShader = sharpeningShader.Replace("#include \"ffx_a.h\"", fsrA);
sharpeningShader = sharpeningShader.Replace("#include \"ffx_fsr1.h\"", fsr1);
_scalingShaderProgram = CompileProgram(scalingShader, ShaderType.ComputeShader);
_sharpeningShaderProgram = CompileProgram(sharpeningShader, ShaderType.ComputeShader);
_scalingShaderProgram = CompileProgram(_gd.Api, scalingShader, ShaderType.ComputeShader);
_sharpeningShaderProgram = CompileProgram(_gd.Api, sharpeningShader, ShaderType.ComputeShader);
_inputUniform = GL.GetUniformLocation(_scalingShaderProgram, "Source");
_outputUniform = GL.GetUniformLocation(_scalingShaderProgram, "imgOutput");
_sharpeningUniform = GL.GetUniformLocation(_sharpeningShaderProgram, "sharpening");
_inputUniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "Source");
_outputUniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "imgOutput");
_sharpeningUniform = _gd.Api.GetUniformLocation(_sharpeningShaderProgram, "sharpening");
_srcX0Uniform = GL.GetUniformLocation(_scalingShaderProgram, "srcX0");
_srcX1Uniform = GL.GetUniformLocation(_scalingShaderProgram, "srcX1");
_srcY0Uniform = GL.GetUniformLocation(_scalingShaderProgram, "srcY0");
_srcY1Uniform = GL.GetUniformLocation(_scalingShaderProgram, "srcY1");
_dstX0Uniform = GL.GetUniformLocation(_scalingShaderProgram, "dstX0");
_dstX1Uniform = GL.GetUniformLocation(_scalingShaderProgram, "dstX1");
_dstY0Uniform = GL.GetUniformLocation(_scalingShaderProgram, "dstY0");
_dstY1Uniform = GL.GetUniformLocation(_scalingShaderProgram, "dstY1");
_scaleXUniform = GL.GetUniformLocation(_scalingShaderProgram, "scaleX");
_scaleYUniform = GL.GetUniformLocation(_scalingShaderProgram, "scaleY");
_srcX0Uniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "srcX0");
_srcX1Uniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "srcX1");
_srcY0Uniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "srcY0");
_srcY1Uniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "srcY1");
_dstX0Uniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "dstX0");
_dstX1Uniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "dstX1");
_dstY0Uniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "dstY0");
_dstY1Uniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "dstY1");
_scaleXUniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "scaleX");
_scaleYUniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "scaleY");
}
public void Run(
@ -114,64 +114,64 @@ namespace Ryujinx.Graphics.OpenGL.Effects
originalInfo.SwizzleB,
originalInfo.SwizzleA);
_intermediaryTexture = new TextureStorage(_renderer, info);
_intermediaryTexture = new TextureStorage(_gd, info);
_intermediaryTexture.CreateDefaultView();
}
var textureView = _intermediaryTexture.CreateView(_intermediaryTexture.Info, 0, 0) as TextureView;
int previousProgram = GL.GetInteger(GetPName.CurrentProgram);
int previousUnit = GL.GetInteger(GetPName.ActiveTexture);
GL.ActiveTexture(TextureUnit.Texture0);
int previousTextureBinding = GL.GetInteger(GetPName.TextureBinding2D);
uint previousProgram = (uint)_gd.Api.GetInteger(GLEnum.CurrentProgram);
int previousUnit = _gd.Api.GetInteger(GLEnum.ActiveTexture);
_gd.Api.ActiveTexture(TextureUnit.Texture0);
uint previousTextureBinding = (uint)_gd.Api.GetInteger(GLEnum.TextureBinding2D);
GL.BindImageTexture(0, textureView.Handle, 0, false, 0, TextureAccess.ReadWrite, SizedInternalFormat.Rgba8);
_gd.Api.BindImageTexture(0, textureView.Handle, 0, false, 0, BufferAccessARB.ReadWrite, InternalFormat.Rgba8);
int threadGroupWorkRegionDim = 16;
int dispatchX = (width + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
int dispatchY = (height + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
uint dispatchX = (uint)((width + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim);
uint dispatchY = (uint)((height + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim);
// Scaling pass
float srcWidth = Math.Abs(source.X2 - source.X1);
float srcHeight = Math.Abs(source.Y2 - source.Y1);
float scaleX = srcWidth / view.Width;
float scaleY = srcHeight / view.Height;
GL.UseProgram(_scalingShaderProgram);
_gd.Api.UseProgram(_scalingShaderProgram);
view.Bind(0);
GL.Uniform1(_inputUniform, 0);
GL.Uniform1(_outputUniform, 0);
GL.Uniform1(_srcX0Uniform, (float)source.X1);
GL.Uniform1(_srcX1Uniform, (float)source.X2);
GL.Uniform1(_srcY0Uniform, (float)source.Y1);
GL.Uniform1(_srcY1Uniform, (float)source.Y2);
GL.Uniform1(_dstX0Uniform, (float)destination.X1);
GL.Uniform1(_dstX1Uniform, (float)destination.X2);
GL.Uniform1(_dstY0Uniform, (float)destination.Y1);
GL.Uniform1(_dstY1Uniform, (float)destination.Y2);
GL.Uniform1(_scaleXUniform, scaleX);
GL.Uniform1(_scaleYUniform, scaleY);
GL.DispatchCompute(dispatchX, dispatchY, 1);
_gd.Api.Uniform1(_inputUniform, 0);
_gd.Api.Uniform1(_outputUniform, 0);
_gd.Api.Uniform1(_srcX0Uniform, (float)source.X1);
_gd.Api.Uniform1(_srcX1Uniform, (float)source.X2);
_gd.Api.Uniform1(_srcY0Uniform, (float)source.Y1);
_gd.Api.Uniform1(_srcY1Uniform, (float)source.Y2);
_gd.Api.Uniform1(_dstX0Uniform, (float)destination.X1);
_gd.Api.Uniform1(_dstX1Uniform, (float)destination.X2);
_gd.Api.Uniform1(_dstY0Uniform, (float)destination.Y1);
_gd.Api.Uniform1(_dstY1Uniform, (float)destination.Y2);
_gd.Api.Uniform1(_scaleXUniform, scaleX);
_gd.Api.Uniform1(_scaleYUniform, scaleY);
_gd.Api.DispatchCompute(dispatchX, dispatchY, 1);
GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit);
_gd.Api.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);
// Sharpening Pass
GL.UseProgram(_sharpeningShaderProgram);
GL.BindImageTexture(0, destinationTexture.Handle, 0, false, 0, TextureAccess.ReadWrite, SizedInternalFormat.Rgba8);
_gd.Api.UseProgram(_sharpeningShaderProgram);
_gd.Api.BindImageTexture(0, destinationTexture.Handle, 0, false, 0, BufferAccessARB.ReadWrite, InternalFormat.Rgba8);
textureView.Bind(0);
GL.Uniform1(_inputUniform, 0);
GL.Uniform1(_outputUniform, 0);
GL.Uniform1(_sharpeningUniform, 1.5f - (Level * 0.01f * 1.5f));
GL.DispatchCompute(dispatchX, dispatchY, 1);
_gd.Api.Uniform1(_inputUniform, 0);
_gd.Api.Uniform1(_outputUniform, 0);
_gd.Api.Uniform1(_sharpeningUniform, 1.5f - (Level * 0.01f * 1.5f));
_gd.Api.DispatchCompute(dispatchX, dispatchY, 1);
GL.UseProgram(previousProgram);
GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit);
_gd.Api.UseProgram(previousProgram);
_gd.Api.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);
(_renderer.Pipeline as Pipeline).RestoreImages1And2();
(_gd.Pipeline as Pipeline).RestoreImages1And2();
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, previousTextureBinding);
_gd.Api.ActiveTexture(TextureUnit.Texture0);
_gd.Api.BindTexture(TextureTarget.Texture2D, previousTextureBinding);
GL.ActiveTexture((TextureUnit)previousUnit);
_gd.Api.ActiveTexture((TextureUnit)previousUnit);
}
}
}

View file

@ -1,41 +1,41 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Common;
using Ryujinx.Graphics.OpenGL.Image;
using Silk.NET.OpenGL.Legacy;
namespace Ryujinx.Graphics.OpenGL.Effects
{
internal class FxaaPostProcessingEffect : IPostProcessingEffect
{
private readonly OpenGLRenderer _renderer;
private readonly OpenGLRenderer _gd;
private int _resolutionUniform;
private int _inputUniform;
private int _outputUniform;
private int _shaderProgram;
private uint _shaderProgram;
private TextureStorage _textureStorage;
public FxaaPostProcessingEffect(OpenGLRenderer renderer)
public FxaaPostProcessingEffect(OpenGLRenderer gd)
{
Initialize();
_renderer = renderer;
_gd = gd;
}
public void Dispose()
{
if (_shaderProgram != 0)
{
GL.DeleteProgram(_shaderProgram);
_gd.Api.DeleteProgram(_shaderProgram);
_textureStorage?.Dispose();
}
}
private void Initialize()
{
_shaderProgram = ShaderHelper.CompileProgram(EmbeddedResources.ReadAllText("Ryujinx.Graphics.OpenGL/Effects/Shaders/fxaa.glsl"), ShaderType.ComputeShader);
_shaderProgram = ShaderHelper.CompileProgram(_gd.Api, EmbeddedResources.ReadAllText("Ryujinx.Graphics.OpenGL/Effects/Shaders/fxaa.glsl"), ShaderType.ComputeShader);
_resolutionUniform = GL.GetUniformLocation(_shaderProgram, "invResolution");
_inputUniform = GL.GetUniformLocation(_shaderProgram, "inputTexture");
_outputUniform = GL.GetUniformLocation(_shaderProgram, "imgOutput");
_resolutionUniform = _gd.Api.GetUniformLocation(_shaderProgram, "invResolution");
_inputUniform = _gd.Api.GetUniformLocation(_shaderProgram, "inputTexture");
_outputUniform = _gd.Api.GetUniformLocation(_shaderProgram, "imgOutput");
}
public TextureView Run(TextureView view, int width, int height)
@ -43,37 +43,37 @@ namespace Ryujinx.Graphics.OpenGL.Effects
if (_textureStorage == null || _textureStorage.Info.Width != view.Width || _textureStorage.Info.Height != view.Height)
{
_textureStorage?.Dispose();
_textureStorage = new TextureStorage(_renderer, view.Info);
_textureStorage = new TextureStorage(_gd, view.Info);
_textureStorage.CreateDefaultView();
}
var textureView = _textureStorage.CreateView(view.Info, 0, 0) as TextureView;
int previousProgram = GL.GetInteger(GetPName.CurrentProgram);
int previousUnit = GL.GetInteger(GetPName.ActiveTexture);
GL.ActiveTexture(TextureUnit.Texture0);
int previousTextureBinding = GL.GetInteger(GetPName.TextureBinding2D);
uint previousProgram = (uint)_gd.Api.GetInteger(GLEnum.CurrentProgram);
int previousUnit = _gd.Api.GetInteger(GLEnum.ActiveTexture);
_gd.Api.ActiveTexture(TextureUnit.Texture0);
uint previousTextureBinding = (uint)_gd.Api.GetInteger(GLEnum.TextureBinding2D);
GL.BindImageTexture(0, textureView.Handle, 0, false, 0, TextureAccess.ReadWrite, SizedInternalFormat.Rgba8);
GL.UseProgram(_shaderProgram);
_gd.Api.BindImageTexture(0, textureView.Handle, 0, false, 0, BufferAccessARB.ReadWrite, InternalFormat.Rgba8);
_gd.Api.UseProgram(_shaderProgram);
var dispatchX = BitUtils.DivRoundUp(view.Width, IPostProcessingEffect.LocalGroupSize);
var dispatchY = BitUtils.DivRoundUp(view.Height, IPostProcessingEffect.LocalGroupSize);
uint dispatchX = (uint)BitUtils.DivRoundUp(view.Width, IPostProcessingEffect.LocalGroupSize);
uint dispatchY = (uint)BitUtils.DivRoundUp(view.Height, IPostProcessingEffect.LocalGroupSize);
view.Bind(0);
GL.Uniform1(_inputUniform, 0);
GL.Uniform1(_outputUniform, 0);
GL.Uniform2(_resolutionUniform, (float)view.Width, (float)view.Height);
GL.DispatchCompute(dispatchX, dispatchY, 1);
GL.UseProgram(previousProgram);
GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit);
_gd.Api.Uniform1(_inputUniform, 0);
_gd.Api.Uniform1(_outputUniform, 0);
_gd.Api.Uniform2(_resolutionUniform, view.Width, view.Height);
_gd.Api.DispatchCompute(dispatchX, dispatchY, 1);
_gd.Api.UseProgram(previousProgram);
_gd.Api.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);
(_renderer.Pipeline as Pipeline).RestoreImages1And2();
(_gd.Pipeline as Pipeline).RestoreImages1And2();
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, previousTextureBinding);
_gd.Api.ActiveTexture(TextureUnit.Texture0);
_gd.Api.BindTexture(TextureTarget.Texture2D, previousTextureBinding);
GL.ActiveTexture((TextureUnit)previousUnit);
_gd.Api.ActiveTexture((TextureUnit)previousUnit);
return textureView;
}

View file

@ -1,37 +1,38 @@
using OpenTK.Graphics.OpenGL;
using Silk.NET.OpenGL.Legacy;
namespace Ryujinx.Graphics.OpenGL.Effects
{
internal static class ShaderHelper
{
public static int CompileProgram(string shaderCode, ShaderType shaderType)
public static uint CompileProgram(GL api, string shaderCode, ShaderType shaderType)
{
var shader = GL.CreateShader(shaderType);
GL.ShaderSource(shader, shaderCode);
GL.CompileShader(shader);
var shader = api.CreateShader(shaderType);
api.ShaderSource(shader, shaderCode);
api.CompileShader(shader);
var program = GL.CreateProgram();
GL.AttachShader(program, shader);
GL.LinkProgram(program);
var program = api.CreateProgram();
api.AttachShader(program, shader);
api.LinkProgram(program);
GL.DetachShader(program, shader);
GL.DeleteShader(shader);
api.DetachShader(program, shader);
api.DeleteShader(shader);
return program;
}
public static int CompileProgram(string[] shaders, ShaderType shaderType)
public static uint CompileProgram(GL api, string[] shaders, ShaderType shaderType)
{
var shader = GL.CreateShader(shaderType);
GL.ShaderSource(shader, shaders.Length, shaders, (int[])null);
GL.CompileShader(shader);
var shader = api.CreateShader(shaderType);
var length = 0;
api.ShaderSource(shader, (uint)shaders.Length, shaders, in length);
api.CompileShader(shader);
var program = GL.CreateProgram();
GL.AttachShader(program, shader);
GL.LinkProgram(program);
var program = api.CreateProgram();
api.AttachShader(program, shader);
api.LinkProgram(program);
GL.DetachShader(program, shader);
GL.DeleteShader(shader);
api.DetachShader(program, shader);
api.DeleteShader(shader);
return program;
}

View file

@ -1,25 +1,25 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Common;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.OpenGL.Image;
using Silk.NET.OpenGL.Legacy;
using System;
namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
{
internal partial class SmaaPostProcessingEffect : IPostProcessingEffect
internal class SmaaPostProcessingEffect : IPostProcessingEffect
{
public const int AreaWidth = 160;
public const int AreaHeight = 560;
public const int SearchWidth = 64;
public const int SearchHeight = 16;
private readonly OpenGLRenderer _renderer;
private readonly OpenGLRenderer _gd;
private TextureStorage _outputTexture;
private TextureStorage _searchTexture;
private TextureStorage _areaTexture;
private int[] _edgeShaderPrograms;
private int[] _blendShaderPrograms;
private int[] _neighbourShaderPrograms;
private uint[] _edgeShaderPrograms;
private uint[] _blendShaderPrograms;
private uint[] _neighbourShaderPrograms;
private TextureStorage _edgeOutputTexture;
private TextureStorage _blendOutputTexture;
private readonly string[] _qualities;
@ -39,15 +39,15 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
_quality = Math.Clamp(value, 0, _qualities.Length - 1);
}
}
public SmaaPostProcessingEffect(OpenGLRenderer renderer, int quality)
public SmaaPostProcessingEffect(OpenGLRenderer gd, int quality)
{
_renderer = renderer;
_gd = gd;
_edgeShaderPrograms = Array.Empty<int>();
_blendShaderPrograms = Array.Empty<int>();
_neighbourShaderPrograms = Array.Empty<int>();
_edgeShaderPrograms = Array.Empty<uint>();
_blendShaderPrograms = Array.Empty<uint>();
_neighbourShaderPrograms = Array.Empty<uint>();
_qualities = new string[] { "SMAA_PRESET_LOW", "SMAA_PRESET_MEDIUM", "SMAA_PRESET_HIGH", "SMAA_PRESET_ULTRA" };
_qualities = ["SMAA_PRESET_LOW", "SMAA_PRESET_MEDIUM", "SMAA_PRESET_HIGH", "SMAA_PRESET_ULTRA"];
Quality = quality;
@ -69,9 +69,9 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
{
for (int i = 0; i < _edgeShaderPrograms.Length; i++)
{
GL.DeleteProgram(_edgeShaderPrograms[i]);
GL.DeleteProgram(_blendShaderPrograms[i]);
GL.DeleteProgram(_neighbourShaderPrograms[i]);
_gd.Api.DeleteProgram(_edgeShaderPrograms[i]);
_gd.Api.DeleteProgram(_blendShaderPrograms[i]);
_gd.Api.DeleteProgram(_neighbourShaderPrograms[i]);
}
}
@ -80,9 +80,9 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
string baseShader = EmbeddedResources.ReadAllText("Ryujinx.Graphics.OpenGL/Effects/Shaders/smaa.hlsl");
var pixelSizeDefine = $"#define SMAA_RT_METRICS float4(1.0 / {width}.0, 1.0 / {height}.0, {width}, {height}) \n";
_edgeShaderPrograms = new int[_qualities.Length];
_blendShaderPrograms = new int[_qualities.Length];
_neighbourShaderPrograms = new int[_qualities.Length];
_edgeShaderPrograms = new uint[_qualities.Length];
_blendShaderPrograms = new uint[_qualities.Length];
_neighbourShaderPrograms = new uint[_qualities.Length];
for (int i = 0; i < +_edgeShaderPrograms.Length; i++)
{
@ -93,25 +93,25 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
var neighbourShaderData = EmbeddedResources.ReadAllText("Ryujinx.Graphics.OpenGL/Effects/Shaders/smaa_neighbour.glsl");
var shaders = new string[] { presets, edgeShaderData };
var edgeProgram = ShaderHelper.CompileProgram(shaders, ShaderType.ComputeShader);
var edgeProgram = ShaderHelper.CompileProgram(_gd.Api, shaders, ShaderType.ComputeShader);
shaders[1] = blendShaderData;
var blendProgram = ShaderHelper.CompileProgram(shaders, ShaderType.ComputeShader);
var blendProgram = ShaderHelper.CompileProgram(_gd.Api, shaders, ShaderType.ComputeShader);
shaders[1] = neighbourShaderData;
var neighbourProgram = ShaderHelper.CompileProgram(shaders, ShaderType.ComputeShader);
var neighbourProgram = ShaderHelper.CompileProgram(_gd.Api, shaders, ShaderType.ComputeShader);
_edgeShaderPrograms[i] = edgeProgram;
_blendShaderPrograms[i] = blendProgram;
_neighbourShaderPrograms[i] = neighbourProgram;
}
_inputUniform = GL.GetUniformLocation(_edgeShaderPrograms[0], "inputTexture");
_outputUniform = GL.GetUniformLocation(_edgeShaderPrograms[0], "imgOutput");
_samplerAreaUniform = GL.GetUniformLocation(_blendShaderPrograms[0], "samplerArea");
_samplerSearchUniform = GL.GetUniformLocation(_blendShaderPrograms[0], "samplerSearch");
_samplerBlendUniform = GL.GetUniformLocation(_neighbourShaderPrograms[0], "samplerBlend");
_resolutionUniform = GL.GetUniformLocation(_edgeShaderPrograms[0], "invResolution");
_inputUniform = _gd.Api.GetUniformLocation(_edgeShaderPrograms[0], "inputTexture");
_outputUniform = _gd.Api.GetUniformLocation(_edgeShaderPrograms[0], "imgOutput");
_samplerAreaUniform = _gd.Api.GetUniformLocation(_blendShaderPrograms[0], "samplerArea");
_samplerSearchUniform = _gd.Api.GetUniformLocation(_blendShaderPrograms[0], "samplerSearch");
_samplerBlendUniform = _gd.Api.GetUniformLocation(_neighbourShaderPrograms[0], "samplerBlend");
_resolutionUniform = _gd.Api.GetUniformLocation(_edgeShaderPrograms[0], "invResolution");
}
private void Initialize()
@ -148,8 +148,8 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
SwizzleComponent.Blue,
SwizzleComponent.Alpha);
_areaTexture = new TextureStorage(_renderer, areaInfo);
_searchTexture = new TextureStorage(_renderer, searchInfo);
_areaTexture = new TextureStorage(_gd, areaInfo);
_searchTexture = new TextureStorage(_gd, searchInfo);
var areaTexture = EmbeddedResources.ReadFileToRentedMemory("Ryujinx.Graphics.OpenGL/Effects/Textures/SmaaAreaTexture.bin");
var searchTexture = EmbeddedResources.ReadFileToRentedMemory("Ryujinx.Graphics.OpenGL/Effects/Textures/SmaaSearchTexture.bin");
@ -166,11 +166,11 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
if (_outputTexture == null || _outputTexture.Info.Width != view.Width || _outputTexture.Info.Height != view.Height)
{
_outputTexture?.Dispose();
_outputTexture = new TextureStorage(_renderer, view.Info);
_outputTexture = new TextureStorage(_gd, view.Info);
_outputTexture.CreateDefaultView();
_edgeOutputTexture = new TextureStorage(_renderer, view.Info);
_edgeOutputTexture = new TextureStorage(_gd, view.Info);
_edgeOutputTexture.CreateDefaultView();
_blendOutputTexture = new TextureStorage(_renderer, view.Info);
_blendOutputTexture = new TextureStorage(_gd, view.Info);
_blendOutputTexture.CreateDefaultView();
DeleteShaders();
@ -184,77 +184,77 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
var areaTexture = _areaTexture.DefaultView as TextureView;
var searchTexture = _searchTexture.DefaultView as TextureView;
var previousFramebuffer = GL.GetInteger(GetPName.FramebufferBinding);
int previousUnit = GL.GetInteger(GetPName.ActiveTexture);
GL.ActiveTexture(TextureUnit.Texture0);
int previousTextureBinding0 = GL.GetInteger(GetPName.TextureBinding2D);
GL.ActiveTexture(TextureUnit.Texture1);
int previousTextureBinding1 = GL.GetInteger(GetPName.TextureBinding2D);
GL.ActiveTexture(TextureUnit.Texture2);
int previousTextureBinding2 = GL.GetInteger(GetPName.TextureBinding2D);
uint previousFramebuffer = (uint)_gd.Api.GetInteger(GLEnum.DrawFramebufferBinding);
int previousUnit = _gd.Api.GetInteger(GLEnum.ActiveTexture);
_gd.Api.ActiveTexture(TextureUnit.Texture0);
uint previousTextureBinding0 = (uint)_gd.Api.GetInteger(GLEnum.TextureBinding2D);
_gd.Api.ActiveTexture(TextureUnit.Texture1);
uint previousTextureBinding1 = (uint)_gd.Api.GetInteger(GLEnum.TextureBinding2D);
_gd.Api.ActiveTexture(TextureUnit.Texture2);
uint previousTextureBinding2 = (uint)_gd.Api.GetInteger(GLEnum.TextureBinding2D);
var framebuffer = new Framebuffer();
var framebuffer = new Framebuffer(_gd.Api);
framebuffer.Bind();
framebuffer.AttachColor(0, edgeOutput);
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.ClearColor(0, 0, 0, 0);
_gd.Api.Clear(ClearBufferMask.ColorBufferBit);
_gd.Api.ClearColor(0, 0, 0, 0);
framebuffer.AttachColor(0, blendOutput);
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.ClearColor(0, 0, 0, 0);
_gd.Api.Clear(ClearBufferMask.ColorBufferBit);
_gd.Api.ClearColor(0, 0, 0, 0);
GL.BindFramebuffer(FramebufferTarget.Framebuffer, previousFramebuffer);
_gd.Api.BindFramebuffer(FramebufferTarget.Framebuffer, previousFramebuffer);
framebuffer.Dispose();
var dispatchX = BitUtils.DivRoundUp(view.Width, IPostProcessingEffect.LocalGroupSize);
var dispatchY = BitUtils.DivRoundUp(view.Height, IPostProcessingEffect.LocalGroupSize);
uint dispatchX = (uint)BitUtils.DivRoundUp(view.Width, IPostProcessingEffect.LocalGroupSize);
uint dispatchY = (uint)BitUtils.DivRoundUp(view.Height, IPostProcessingEffect.LocalGroupSize);
int previousProgram = GL.GetInteger(GetPName.CurrentProgram);
GL.BindImageTexture(0, edgeOutput.Handle, 0, false, 0, TextureAccess.ReadWrite, SizedInternalFormat.Rgba8);
GL.UseProgram(_edgeShaderPrograms[Quality]);
uint previousProgram = (uint)_gd.Api.GetInteger(GLEnum.CurrentProgram);
_gd.Api.BindImageTexture(0, edgeOutput.Handle, 0, false, 0, BufferAccessARB.ReadWrite, InternalFormat.Rgba8);
_gd.Api.UseProgram(_edgeShaderPrograms[Quality]);
view.Bind(0);
GL.Uniform1(_inputUniform, 0);
GL.Uniform1(_outputUniform, 0);
GL.Uniform2(_resolutionUniform, (float)view.Width, (float)view.Height);
GL.DispatchCompute(dispatchX, dispatchY, 1);
GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit);
_gd.Api.Uniform1(_inputUniform, 0);
_gd.Api.Uniform1(_outputUniform, 0);
_gd.Api.Uniform2(_resolutionUniform, view.Width, view.Height);
_gd.Api.DispatchCompute(dispatchX, dispatchY, 1);
_gd.Api.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);
GL.BindImageTexture(0, blendOutput.Handle, 0, false, 0, TextureAccess.ReadWrite, SizedInternalFormat.Rgba8);
GL.UseProgram(_blendShaderPrograms[Quality]);
_gd.Api.BindImageTexture(0, blendOutput.Handle, 0, false, 0, BufferAccessARB.ReadWrite, InternalFormat.Rgba8);
_gd.Api.UseProgram(_blendShaderPrograms[Quality]);
edgeOutput.Bind(0);
areaTexture.Bind(1);
searchTexture.Bind(2);
GL.Uniform1(_inputUniform, 0);
GL.Uniform1(_outputUniform, 0);
GL.Uniform1(_samplerAreaUniform, 1);
GL.Uniform1(_samplerSearchUniform, 2);
GL.Uniform2(_resolutionUniform, (float)view.Width, (float)view.Height);
GL.DispatchCompute(dispatchX, dispatchY, 1);
GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit);
_gd.Api.Uniform1(_inputUniform, 0);
_gd.Api.Uniform1(_outputUniform, 0);
_gd.Api.Uniform1(_samplerAreaUniform, 1);
_gd.Api.Uniform1(_samplerSearchUniform, 2);
_gd.Api.Uniform2(_resolutionUniform, view.Width, view.Height);
_gd.Api.DispatchCompute(dispatchX, dispatchY, 1);
_gd.Api.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);
GL.BindImageTexture(0, textureView.Handle, 0, false, 0, TextureAccess.ReadWrite, SizedInternalFormat.Rgba8);
GL.UseProgram(_neighbourShaderPrograms[Quality]);
_gd.Api.BindImageTexture(0, textureView.Handle, 0, false, 0, BufferAccessARB.ReadWrite, InternalFormat.Rgba8);
_gd.Api.UseProgram(_neighbourShaderPrograms[Quality]);
view.Bind(0);
blendOutput.Bind(1);
GL.Uniform1(_inputUniform, 0);
GL.Uniform1(_outputUniform, 0);
GL.Uniform1(_samplerBlendUniform, 1);
GL.Uniform2(_resolutionUniform, (float)view.Width, (float)view.Height);
GL.DispatchCompute(dispatchX, dispatchY, 1);
GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit);
_gd.Api.Uniform1(_inputUniform, 0);
_gd.Api.Uniform1(_outputUniform, 0);
_gd.Api.Uniform1(_samplerBlendUniform, 1);
_gd.Api.Uniform2(_resolutionUniform, view.Width, view.Height);
_gd.Api.DispatchCompute(dispatchX, dispatchY, 1);
_gd.Api.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);
(_renderer.Pipeline as Pipeline).RestoreImages1And2();
(_gd.Pipeline as Pipeline).RestoreImages1And2();
GL.UseProgram(previousProgram);
_gd.Api.UseProgram(previousProgram);
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, previousTextureBinding0);
GL.ActiveTexture(TextureUnit.Texture1);
GL.BindTexture(TextureTarget.Texture2D, previousTextureBinding1);
GL.ActiveTexture(TextureUnit.Texture2);
GL.BindTexture(TextureTarget.Texture2D, previousTextureBinding2);
_gd.Api.ActiveTexture(TextureUnit.Texture0);
_gd.Api.BindTexture(TextureTarget.Texture2D, previousTextureBinding0);
_gd.Api.ActiveTexture(TextureUnit.Texture1);
_gd.Api.BindTexture(TextureTarget.Texture2D, previousTextureBinding1);
_gd.Api.ActiveTexture(TextureUnit.Texture2);
_gd.Api.BindTexture(TextureTarget.Texture2D, previousTextureBinding2);
GL.ActiveTexture((TextureUnit)previousUnit);
_gd.Api.ActiveTexture((TextureUnit)previousUnit);
return textureView;
}

View file

@ -1,7 +1,9 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader;
using Silk.NET.OpenGL.Legacy;
using Silk.NET.OpenGL.Legacy.Extensions.EXT;
using Silk.NET.OpenGL.Legacy.Extensions.NV;
namespace Ryujinx.Graphics.OpenGL
{
@ -12,15 +14,17 @@ namespace Ryujinx.Graphics.OpenGL
switch (mode)
{
case AddressMode.Clamp:
#pragma warning disable CS0612 // Type or member is obsolete
return TextureWrapMode.Clamp;
#pragma warning restore CS0612 // Type or member is obsolete
case AddressMode.Repeat:
return TextureWrapMode.Repeat;
case AddressMode.MirrorClamp:
return (TextureWrapMode)ExtTextureMirrorClamp.MirrorClampExt;
return (TextureWrapMode)EXT.MirrorClampExt;
case AddressMode.MirrorClampToEdge:
return (TextureWrapMode)ExtTextureMirrorClamp.MirrorClampToEdgeExt;
return (TextureWrapMode)EXT.MirrorClampToEdgeExt;
case AddressMode.MirrorClampToBorder:
return (TextureWrapMode)ExtTextureMirrorClamp.MirrorClampToBorderExt;
return (TextureWrapMode)EXT.MirrorClampToBorderExt;
case AddressMode.ClampToBorder:
return TextureWrapMode.ClampToBorder;
case AddressMode.MirroredRepeat:
@ -31,217 +35,219 @@ namespace Ryujinx.Graphics.OpenGL
Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(AddressMode)} enum value: {mode}.");
#pragma warning disable CS0612 // Type or member is obsolete
return TextureWrapMode.Clamp;
#pragma warning restore CS0612 // Type or member is obsolete
}
public static NvBlendEquationAdvanced Convert(this AdvancedBlendOp op)
public static NV Convert(this AdvancedBlendOp op)
{
switch (op)
{
case AdvancedBlendOp.Zero:
return NvBlendEquationAdvanced.Zero;
return NV.Zero;
case AdvancedBlendOp.Src:
return NvBlendEquationAdvanced.SrcNv;
return NV.SrcNV;
case AdvancedBlendOp.Dst:
return NvBlendEquationAdvanced.DstNv;
return NV.DstNV;
case AdvancedBlendOp.SrcOver:
return NvBlendEquationAdvanced.SrcOverNv;
return NV.SrcOverNV;
case AdvancedBlendOp.DstOver:
return NvBlendEquationAdvanced.DstOverNv;
return NV.DstOverNV;
case AdvancedBlendOp.SrcIn:
return NvBlendEquationAdvanced.SrcInNv;
return NV.SrcInNV;
case AdvancedBlendOp.DstIn:
return NvBlendEquationAdvanced.DstInNv;
return NV.DstInNV;
case AdvancedBlendOp.SrcOut:
return NvBlendEquationAdvanced.SrcOutNv;
return NV.SrcOutNV;
case AdvancedBlendOp.DstOut:
return NvBlendEquationAdvanced.DstOutNv;
return NV.DstOutNV;
case AdvancedBlendOp.SrcAtop:
return NvBlendEquationAdvanced.SrcAtopNv;
return NV.SrcAtopNV;
case AdvancedBlendOp.DstAtop:
return NvBlendEquationAdvanced.DstAtopNv;
return NV.DstAtopNV;
case AdvancedBlendOp.Xor:
return NvBlendEquationAdvanced.XorNv;
return NV.XorNV;
case AdvancedBlendOp.Plus:
return NvBlendEquationAdvanced.PlusNv;
return NV.PlusNV;
case AdvancedBlendOp.PlusClamped:
return NvBlendEquationAdvanced.PlusClampedNv;
return NV.PlusClampedNV;
case AdvancedBlendOp.PlusClampedAlpha:
return NvBlendEquationAdvanced.PlusClampedAlphaNv;
return NV.PlusClampedAlphaNV;
case AdvancedBlendOp.PlusDarker:
return NvBlendEquationAdvanced.PlusDarkerNv;
return NV.PlusDarkerNV;
case AdvancedBlendOp.Multiply:
return NvBlendEquationAdvanced.MultiplyNv;
return NV.MultiplyNV;
case AdvancedBlendOp.Screen:
return NvBlendEquationAdvanced.ScreenNv;
return NV.ScreenNV;
case AdvancedBlendOp.Overlay:
return NvBlendEquationAdvanced.OverlayNv;
return NV.OverlayNV;
case AdvancedBlendOp.Darken:
return NvBlendEquationAdvanced.DarkenNv;
return NV.DarkenNV;
case AdvancedBlendOp.Lighten:
return NvBlendEquationAdvanced.LightenNv;
return NV.LightenNV;
case AdvancedBlendOp.ColorDodge:
return NvBlendEquationAdvanced.ColordodgeNv;
return NV.ColordodgeNV;
case AdvancedBlendOp.ColorBurn:
return NvBlendEquationAdvanced.ColorburnNv;
return NV.ColorburnNV;
case AdvancedBlendOp.HardLight:
return NvBlendEquationAdvanced.HardlightNv;
return NV.HardlightNV;
case AdvancedBlendOp.SoftLight:
return NvBlendEquationAdvanced.SoftlightNv;
return NV.SoftlightNV;
case AdvancedBlendOp.Difference:
return NvBlendEquationAdvanced.DifferenceNv;
return NV.DifferenceNV;
case AdvancedBlendOp.Minus:
return NvBlendEquationAdvanced.MinusNv;
return NV.MinusNV;
case AdvancedBlendOp.MinusClamped:
return NvBlendEquationAdvanced.MinusClampedNv;
return NV.MinusClampedNV;
case AdvancedBlendOp.Exclusion:
return NvBlendEquationAdvanced.ExclusionNv;
return NV.ExclusionNV;
case AdvancedBlendOp.Contrast:
return NvBlendEquationAdvanced.ContrastNv;
return NV.ContrastNV;
case AdvancedBlendOp.Invert:
return NvBlendEquationAdvanced.Invert;
return NV.Invert;
case AdvancedBlendOp.InvertRGB:
return NvBlendEquationAdvanced.InvertRgbNv;
return NV.InvertRgbNV;
case AdvancedBlendOp.InvertOvg:
return NvBlendEquationAdvanced.InvertOvgNv;
return NV.InvertOvgNV;
case AdvancedBlendOp.LinearDodge:
return NvBlendEquationAdvanced.LineardodgeNv;
return NV.LineardodgeNV;
case AdvancedBlendOp.LinearBurn:
return NvBlendEquationAdvanced.LinearburnNv;
return NV.LinearburnNV;
case AdvancedBlendOp.VividLight:
return NvBlendEquationAdvanced.VividlightNv;
return NV.VividlightNV;
case AdvancedBlendOp.LinearLight:
return NvBlendEquationAdvanced.LinearlightNv;
return NV.LinearlightNV;
case AdvancedBlendOp.PinLight:
return NvBlendEquationAdvanced.PinlightNv;
return NV.PinlightNV;
case AdvancedBlendOp.HardMix:
return NvBlendEquationAdvanced.HardmixNv;
return NV.HardmixNV;
case AdvancedBlendOp.Red:
return NvBlendEquationAdvanced.RedNv;
return NV.RedNV;
case AdvancedBlendOp.Green:
return NvBlendEquationAdvanced.GreenNv;
return NV.GreenNV;
case AdvancedBlendOp.Blue:
return NvBlendEquationAdvanced.BlueNv;
return NV.BlueNV;
case AdvancedBlendOp.HslHue:
return NvBlendEquationAdvanced.HslHueNv;
return NV.HslHueNV;
case AdvancedBlendOp.HslSaturation:
return NvBlendEquationAdvanced.HslSaturationNv;
return NV.HslSaturationNV;
case AdvancedBlendOp.HslColor:
return NvBlendEquationAdvanced.HslColorNv;
return NV.HslColorNV;
case AdvancedBlendOp.HslLuminosity:
return NvBlendEquationAdvanced.HslLuminosityNv;
return NV.HslLuminosityNV;
}
Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(AdvancedBlendOp)} enum value: {op}.");
return NvBlendEquationAdvanced.Zero;
return NV.Zero;
}
public static All Convert(this AdvancedBlendOverlap overlap)
public static NV Convert(this AdvancedBlendOverlap overlap)
{
switch (overlap)
{
case AdvancedBlendOverlap.Uncorrelated:
return All.UncorrelatedNv;
return NV.UncorrelatedNV;
case AdvancedBlendOverlap.Disjoint:
return All.DisjointNv;
return NV.DisjointNV;
case AdvancedBlendOverlap.Conjoint:
return All.ConjointNv;
return NV.ConjointNV;
}
Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(AdvancedBlendOverlap)} enum value: {overlap}.");
return All.UncorrelatedNv;
return NV.UncorrelatedNV;
}
public static All Convert(this BlendFactor factor)
public static GLEnum Convert(this BlendFactor factor)
{
switch (factor)
{
case BlendFactor.Zero:
case BlendFactor.ZeroGl:
return All.Zero;
return GLEnum.Zero;
case BlendFactor.One:
case BlendFactor.OneGl:
return All.One;
return GLEnum.One;
case BlendFactor.SrcColor:
case BlendFactor.SrcColorGl:
return All.SrcColor;
return GLEnum.SrcColor;
case BlendFactor.OneMinusSrcColor:
case BlendFactor.OneMinusSrcColorGl:
return All.OneMinusSrcColor;
return GLEnum.OneMinusSrcColor;
case BlendFactor.SrcAlpha:
case BlendFactor.SrcAlphaGl:
return All.SrcAlpha;
return GLEnum.SrcAlpha;
case BlendFactor.OneMinusSrcAlpha:
case BlendFactor.OneMinusSrcAlphaGl:
return All.OneMinusSrcAlpha;
return GLEnum.OneMinusSrcAlpha;
case BlendFactor.DstAlpha:
case BlendFactor.DstAlphaGl:
return All.DstAlpha;
return GLEnum.DstAlpha;
case BlendFactor.OneMinusDstAlpha:
case BlendFactor.OneMinusDstAlphaGl:
return All.OneMinusDstAlpha;
return GLEnum.OneMinusDstAlpha;
case BlendFactor.DstColor:
case BlendFactor.DstColorGl:
return All.DstColor;
return GLEnum.DstColor;
case BlendFactor.OneMinusDstColor:
case BlendFactor.OneMinusDstColorGl:
return All.OneMinusDstColor;
return GLEnum.OneMinusDstColor;
case BlendFactor.SrcAlphaSaturate:
case BlendFactor.SrcAlphaSaturateGl:
return All.SrcAlphaSaturate;
return GLEnum.SrcAlphaSaturate;
case BlendFactor.Src1Color:
case BlendFactor.Src1ColorGl:
return All.Src1Color;
return GLEnum.Src1Color;
case BlendFactor.OneMinusSrc1Color:
case BlendFactor.OneMinusSrc1ColorGl:
return All.OneMinusSrc1Color;
return GLEnum.OneMinusSrc1Color;
case BlendFactor.Src1Alpha:
case BlendFactor.Src1AlphaGl:
return All.Src1Alpha;
return GLEnum.Src1Alpha;
case BlendFactor.OneMinusSrc1Alpha:
case BlendFactor.OneMinusSrc1AlphaGl:
return All.OneMinusSrc1Alpha;
return GLEnum.OneMinusSrc1Alpha;
case BlendFactor.ConstantColor:
return All.ConstantColor;
return GLEnum.ConstantColor;
case BlendFactor.OneMinusConstantColor:
return All.OneMinusConstantColor;
return GLEnum.OneMinusConstantColor;
case BlendFactor.ConstantAlpha:
return All.ConstantAlpha;
return GLEnum.ConstantAlpha;
case BlendFactor.OneMinusConstantAlpha:
return All.OneMinusConstantAlpha;
return GLEnum.OneMinusConstantAlpha;
}
Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(BlendFactor)} enum value: {factor}.");
return All.Zero;
return GLEnum.Zero;
}
public static BlendEquationMode Convert(this BlendOp op)
public static GLEnum Convert(this BlendOp op)
{
switch (op)
{
case BlendOp.Add:
case BlendOp.AddGl:
return BlendEquationMode.FuncAdd;
return GLEnum.FuncAdd;
case BlendOp.Minimum:
case BlendOp.MinimumGl:
return BlendEquationMode.Min;
return GLEnum.Min;
case BlendOp.Maximum:
case BlendOp.MaximumGl:
return BlendEquationMode.Max;
return GLEnum.Max;
case BlendOp.Subtract:
case BlendOp.SubtractGl:
return BlendEquationMode.FuncSubtract;
return GLEnum.FuncSubtract;
case BlendOp.ReverseSubtract:
case BlendOp.ReverseSubtractGl:
return BlendEquationMode.FuncReverseSubtract;
return GLEnum.FuncReverseSubtract;
}
Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(BlendOp)} enum value: {op}.");
return BlendEquationMode.FuncAdd;
return GLEnum.FuncAdd;
}
public static TextureCompareMode Convert(this CompareMode mode)
@ -251,7 +257,7 @@ namespace Ryujinx.Graphics.OpenGL
case CompareMode.None:
return TextureCompareMode.None;
case CompareMode.CompareRToTexture:
return TextureCompareMode.CompareRToTexture;
return TextureCompareMode.CompareRefToTexture;
}
Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(CompareMode)} enum value: {mode}.");
@ -259,86 +265,86 @@ namespace Ryujinx.Graphics.OpenGL
return TextureCompareMode.None;
}
public static All Convert(this CompareOp op)
public static GLEnum Convert(this CompareOp op)
{
switch (op)
{
case CompareOp.Never:
case CompareOp.NeverGl:
return All.Never;
return GLEnum.Never;
case CompareOp.Less:
case CompareOp.LessGl:
return All.Less;
return GLEnum.Less;
case CompareOp.Equal:
case CompareOp.EqualGl:
return All.Equal;
return GLEnum.Equal;
case CompareOp.LessOrEqual:
case CompareOp.LessOrEqualGl:
return All.Lequal;
return GLEnum.Lequal;
case CompareOp.Greater:
case CompareOp.GreaterGl:
return All.Greater;
return GLEnum.Greater;
case CompareOp.NotEqual:
case CompareOp.NotEqualGl:
return All.Notequal;
return GLEnum.Notequal;
case CompareOp.GreaterOrEqual:
case CompareOp.GreaterOrEqualGl:
return All.Gequal;
return GLEnum.Gequal;
case CompareOp.Always:
case CompareOp.AlwaysGl:
return All.Always;
return GLEnum.Always;
}
Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(CompareOp)} enum value: {op}.");
return All.Never;
return GLEnum.Never;
}
public static ClipDepthMode Convert(this DepthMode mode)
public static GLEnum Convert(this DepthMode mode)
{
switch (mode)
{
case DepthMode.MinusOneToOne:
return ClipDepthMode.NegativeOneToOne;
return GLEnum.NegativeOneToOne;
case DepthMode.ZeroToOne:
return ClipDepthMode.ZeroToOne;
return GLEnum.ZeroToOne;
}
Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(DepthMode)} enum value: {mode}.");
return ClipDepthMode.NegativeOneToOne;
return GLEnum.NegativeOneToOne;
}
public static All Convert(this DepthStencilMode mode)
public static GLEnum Convert(this DepthStencilMode mode)
{
switch (mode)
{
case DepthStencilMode.Depth:
return All.DepthComponent;
return GLEnum.DepthComponent;
case DepthStencilMode.Stencil:
return All.StencilIndex;
return GLEnum.StencilIndex;
}
Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(DepthStencilMode)} enum value: {mode}.");
return All.Depth;
return GLEnum.Depth;
}
public static CullFaceMode Convert(this Face face)
public static GLEnum Convert(this Face face)
{
switch (face)
{
case Face.Back:
return CullFaceMode.Back;
return GLEnum.Back;
case Face.Front:
return CullFaceMode.Front;
return GLEnum.Front;
case Face.FrontAndBack:
return CullFaceMode.FrontAndBack;
return GLEnum.FrontAndBack;
}
Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(Face)} enum value: {face}.");
return CullFaceMode.Back;
return GLEnum.Back;
}
public static FrontFaceDirection Convert(this FrontFace frontFace)
@ -346,14 +352,14 @@ namespace Ryujinx.Graphics.OpenGL
switch (frontFace)
{
case FrontFace.Clockwise:
return FrontFaceDirection.Cw;
return FrontFaceDirection.CW;
case FrontFace.CounterClockwise:
return FrontFaceDirection.Ccw;
}
Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(FrontFace)} enum value: {frontFace}.");
return FrontFaceDirection.Cw;
return FrontFaceDirection.CW;
}
public static DrawElementsType Convert(this IndexType type)
@ -411,21 +417,21 @@ namespace Ryujinx.Graphics.OpenGL
return TextureMinFilter.Nearest;
}
public static OpenTK.Graphics.OpenGL.PolygonMode Convert(this GAL.PolygonMode mode)
public static Silk.NET.OpenGL.Legacy.PolygonMode Convert(this GAL.PolygonMode mode)
{
switch (mode)
{
case GAL.PolygonMode.Point:
return OpenTK.Graphics.OpenGL.PolygonMode.Point;
return Silk.NET.OpenGL.Legacy.PolygonMode.Point;
case GAL.PolygonMode.Line:
return OpenTK.Graphics.OpenGL.PolygonMode.Line;
return Silk.NET.OpenGL.Legacy.PolygonMode.Line;
case GAL.PolygonMode.Fill:
return OpenTK.Graphics.OpenGL.PolygonMode.Fill;
return Silk.NET.OpenGL.Legacy.PolygonMode.Fill;
}
Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(GAL.PolygonMode)} enum value: {mode}.");
return OpenTK.Graphics.OpenGL.PolygonMode.Fill;
return Silk.NET.OpenGL.Legacy.PolygonMode.Fill;
}
public static PrimitiveType Convert(this PrimitiveTopology topology)
@ -449,7 +455,9 @@ namespace Ryujinx.Graphics.OpenGL
case PrimitiveTopology.Quads:
return PrimitiveType.Quads;
case PrimitiveTopology.QuadStrip:
#pragma warning disable CS0612 // Type or member is obsolete
return PrimitiveType.QuadStrip;
#pragma warning restore CS0612 // Type or member is obsolete
case PrimitiveTopology.Polygon:
return PrimitiveType.TriangleFan;
case PrimitiveTopology.LinesAdjacency:
@ -469,92 +477,92 @@ namespace Ryujinx.Graphics.OpenGL
return PrimitiveType.Points;
}
public static TransformFeedbackPrimitiveType ConvertToTfType(this PrimitiveTopology topology)
public static PrimitiveType ConvertToTfType(this PrimitiveTopology topology)
{
switch (topology)
{
case PrimitiveTopology.Points:
return TransformFeedbackPrimitiveType.Points;
return PrimitiveType.Points;
case PrimitiveTopology.Lines:
case PrimitiveTopology.LineLoop:
case PrimitiveTopology.LineStrip:
case PrimitiveTopology.LinesAdjacency:
case PrimitiveTopology.LineStripAdjacency:
return TransformFeedbackPrimitiveType.Lines;
return PrimitiveType.Lines;
case PrimitiveTopology.Triangles:
case PrimitiveTopology.TriangleStrip:
case PrimitiveTopology.TriangleFan:
case PrimitiveTopology.TrianglesAdjacency:
case PrimitiveTopology.TriangleStripAdjacency:
return TransformFeedbackPrimitiveType.Triangles;
return PrimitiveType.Triangles;
}
Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(PrimitiveTopology)} enum value: {topology}.");
return TransformFeedbackPrimitiveType.Points;
return PrimitiveType.Points;
}
public static OpenTK.Graphics.OpenGL.StencilOp Convert(this GAL.StencilOp op)
public static Silk.NET.OpenGL.Legacy.StencilOp Convert(this GAL.StencilOp op)
{
switch (op)
{
case GAL.StencilOp.Keep:
case GAL.StencilOp.KeepGl:
return OpenTK.Graphics.OpenGL.StencilOp.Keep;
return Silk.NET.OpenGL.Legacy.StencilOp.Keep;
case GAL.StencilOp.Zero:
case GAL.StencilOp.ZeroGl:
return OpenTK.Graphics.OpenGL.StencilOp.Zero;
return Silk.NET.OpenGL.Legacy.StencilOp.Zero;
case GAL.StencilOp.Replace:
case GAL.StencilOp.ReplaceGl:
return OpenTK.Graphics.OpenGL.StencilOp.Replace;
return Silk.NET.OpenGL.Legacy.StencilOp.Replace;
case GAL.StencilOp.IncrementAndClamp:
case GAL.StencilOp.IncrementAndClampGl:
return OpenTK.Graphics.OpenGL.StencilOp.Incr;
return Silk.NET.OpenGL.Legacy.StencilOp.Incr;
case GAL.StencilOp.DecrementAndClamp:
case GAL.StencilOp.DecrementAndClampGl:
return OpenTK.Graphics.OpenGL.StencilOp.Decr;
return Silk.NET.OpenGL.Legacy.StencilOp.Decr;
case GAL.StencilOp.Invert:
case GAL.StencilOp.InvertGl:
return OpenTK.Graphics.OpenGL.StencilOp.Invert;
return Silk.NET.OpenGL.Legacy.StencilOp.Invert;
case GAL.StencilOp.IncrementAndWrap:
case GAL.StencilOp.IncrementAndWrapGl:
return OpenTK.Graphics.OpenGL.StencilOp.IncrWrap;
return Silk.NET.OpenGL.Legacy.StencilOp.IncrWrap;
case GAL.StencilOp.DecrementAndWrap:
case GAL.StencilOp.DecrementAndWrapGl:
return OpenTK.Graphics.OpenGL.StencilOp.DecrWrap;
return Silk.NET.OpenGL.Legacy.StencilOp.DecrWrap;
}
Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(GAL.StencilOp)} enum value: {op}.");
return OpenTK.Graphics.OpenGL.StencilOp.Keep;
return Silk.NET.OpenGL.Legacy.StencilOp.Keep;
}
public static All Convert(this SwizzleComponent swizzleComponent)
public static GLEnum Convert(this SwizzleComponent swizzleComponent)
{
switch (swizzleComponent)
{
case SwizzleComponent.Zero:
return All.Zero;
return GLEnum.Zero;
case SwizzleComponent.One:
return All.One;
return GLEnum.One;
case SwizzleComponent.Red:
return All.Red;
return GLEnum.Red;
case SwizzleComponent.Green:
return All.Green;
return GLEnum.Green;
case SwizzleComponent.Blue:
return All.Blue;
return GLEnum.Blue;
case SwizzleComponent.Alpha:
return All.Alpha;
return GLEnum.Alpha;
}
Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(SwizzleComponent)} enum value: {swizzleComponent}.");
return All.Zero;
return GLEnum.Zero;
}
public static ImageTarget ConvertToImageTarget(this Target target)
public static CopyImageSubDataTarget ConvertToImageTarget(this Target target)
{
return (ImageTarget)target.Convert();
return (CopyImageSubDataTarget)target.Convert();
}
public static TextureTarget Convert(this Target target)
@ -588,74 +596,74 @@ namespace Ryujinx.Graphics.OpenGL
return TextureTarget.Texture2D;
}
public static NvViewportSwizzle Convert(this ViewportSwizzle swizzle)
public static NV Convert(this ViewportSwizzle swizzle)
{
switch (swizzle)
{
case ViewportSwizzle.PositiveX:
return NvViewportSwizzle.ViewportSwizzlePositiveXNv;
return NV.ViewportSwizzlePositiveXNV;
case ViewportSwizzle.PositiveY:
return NvViewportSwizzle.ViewportSwizzlePositiveYNv;
return NV.ViewportSwizzlePositiveYNV;
case ViewportSwizzle.PositiveZ:
return NvViewportSwizzle.ViewportSwizzlePositiveZNv;
return NV.ViewportSwizzlePositiveZNV;
case ViewportSwizzle.PositiveW:
return NvViewportSwizzle.ViewportSwizzlePositiveWNv;
return NV.ViewportSwizzlePositiveWNV;
case ViewportSwizzle.NegativeX:
return NvViewportSwizzle.ViewportSwizzleNegativeXNv;
return NV.ViewportSwizzleNegativeXNV;
case ViewportSwizzle.NegativeY:
return NvViewportSwizzle.ViewportSwizzleNegativeYNv;
return NV.ViewportSwizzleNegativeYNV;
case ViewportSwizzle.NegativeZ:
return NvViewportSwizzle.ViewportSwizzleNegativeZNv;
return NV.ViewportSwizzleNegativeZNV;
case ViewportSwizzle.NegativeW:
return NvViewportSwizzle.ViewportSwizzleNegativeWNv;
return NV.ViewportSwizzleNegativeWNV;
}
Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(ViewportSwizzle)} enum value: {swizzle}.");
return NvViewportSwizzle.ViewportSwizzlePositiveXNv;
return NV.ViewportSwizzlePositiveXNV;
}
public static All Convert(this LogicalOp op)
public static GLEnum Convert(this LogicalOp op)
{
switch (op)
{
case LogicalOp.Clear:
return All.Clear;
return GLEnum.Clear;
case LogicalOp.And:
return All.And;
return GLEnum.And;
case LogicalOp.AndReverse:
return All.AndReverse;
return GLEnum.AndReverse;
case LogicalOp.Copy:
return All.Copy;
return GLEnum.Copy;
case LogicalOp.AndInverted:
return All.AndInverted;
return GLEnum.AndInverted;
case LogicalOp.Noop:
return All.Noop;
return GLEnum.Noop;
case LogicalOp.Xor:
return All.Xor;
return GLEnum.Xor;
case LogicalOp.Or:
return All.Or;
return GLEnum.Or;
case LogicalOp.Nor:
return All.Nor;
return GLEnum.Nor;
case LogicalOp.Equiv:
return All.Equiv;
return GLEnum.Equiv;
case LogicalOp.Invert:
return All.Invert;
return GLEnum.Invert;
case LogicalOp.OrReverse:
return All.OrReverse;
return GLEnum.OrReverse;
case LogicalOp.CopyInverted:
return All.CopyInverted;
return GLEnum.CopyInverted;
case LogicalOp.OrInverted:
return All.OrInverted;
return GLEnum.OrInverted;
case LogicalOp.Nand:
return All.Nand;
return GLEnum.Nand;
case LogicalOp.Set:
return All.Set;
return GLEnum.Set;
}
Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(LogicalOp)} enum value: {op}.");
return All.Never;
return GLEnum.Never;
}
public static ShaderType Convert(this ShaderStage stage)

View file

@ -1,4 +1,4 @@
using OpenTK.Graphics.OpenGL;
using Silk.NET.OpenGL.Legacy;
namespace Ryujinx.Graphics.OpenGL
{
@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.OpenGL
public bool Normalized { get; }
public bool Scaled { get; }
public PixelInternalFormat PixelInternalFormat { get; }
public InternalFormat InternalFormat { get; }
public PixelFormat PixelFormat { get; }
public PixelType PixelType { get; }
@ -18,25 +18,25 @@ namespace Ryujinx.Graphics.OpenGL
int components,
bool normalized,
bool scaled,
All pixelInternalFormat,
InternalFormat internalFormat,
PixelFormat pixelFormat,
PixelType pixelType)
{
Components = components;
Normalized = normalized;
Scaled = scaled;
PixelInternalFormat = (PixelInternalFormat)pixelInternalFormat;
InternalFormat = internalFormat;
PixelFormat = pixelFormat;
PixelType = pixelType;
IsCompressed = false;
}
public FormatInfo(int components, bool normalized, bool scaled, All pixelFormat)
public FormatInfo(int components, bool normalized, bool scaled, InternalFormat pixelFormat)
{
Components = components;
Normalized = normalized;
Scaled = scaled;
PixelInternalFormat = 0;
InternalFormat = 0;
PixelFormat = (PixelFormat)pixelFormat;
PixelType = 0;
IsCompressed = true;

View file

@ -1,5 +1,6 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
using Silk.NET.OpenGL.Legacy.Extensions.NV;
using System;
namespace Ryujinx.Graphics.OpenGL
@ -17,192 +18,192 @@ namespace Ryujinx.Graphics.OpenGL
_tableImage = new SizedInternalFormat[tableSize];
#pragma warning disable IDE0055 // Disable formatting
Add(Format.R8Unorm, new FormatInfo(1, true, false, All.R8, PixelFormat.Red, PixelType.UnsignedByte));
Add(Format.R8Snorm, new FormatInfo(1, true, false, All.R8Snorm, PixelFormat.Red, PixelType.Byte));
Add(Format.R8Uint, new FormatInfo(1, false, false, All.R8ui, PixelFormat.RedInteger, PixelType.UnsignedByte));
Add(Format.R8Sint, new FormatInfo(1, false, false, All.R8i, PixelFormat.RedInteger, PixelType.Byte));
Add(Format.R16Float, new FormatInfo(1, false, false, All.R16f, PixelFormat.Red, PixelType.HalfFloat));
Add(Format.R16Unorm, new FormatInfo(1, true, false, All.R16, PixelFormat.Red, PixelType.UnsignedShort));
Add(Format.R16Snorm, new FormatInfo(1, true, false, All.R16Snorm, PixelFormat.Red, PixelType.Short));
Add(Format.R16Uint, new FormatInfo(1, false, false, All.R16ui, PixelFormat.RedInteger, PixelType.UnsignedShort));
Add(Format.R16Sint, new FormatInfo(1, false, false, All.R16i, PixelFormat.RedInteger, PixelType.Short));
Add(Format.R32Float, new FormatInfo(1, false, false, All.R32f, PixelFormat.Red, PixelType.Float));
Add(Format.R32Uint, new FormatInfo(1, false, false, All.R32ui, PixelFormat.RedInteger, PixelType.UnsignedInt));
Add(Format.R32Sint, new FormatInfo(1, false, false, All.R32i, PixelFormat.RedInteger, PixelType.Int));
Add(Format.R8G8Unorm, new FormatInfo(2, true, false, All.Rg8, PixelFormat.Rg, PixelType.UnsignedByte));
Add(Format.R8G8Snorm, new FormatInfo(2, true, false, All.Rg8Snorm, PixelFormat.Rg, PixelType.Byte));
Add(Format.R8G8Uint, new FormatInfo(2, false, false, All.Rg8ui, PixelFormat.RgInteger, PixelType.UnsignedByte));
Add(Format.R8G8Sint, new FormatInfo(2, false, false, All.Rg8i, PixelFormat.RgInteger, PixelType.Byte));
Add(Format.R16G16Float, new FormatInfo(2, false, false, All.Rg16f, PixelFormat.Rg, PixelType.HalfFloat));
Add(Format.R16G16Unorm, new FormatInfo(2, true, false, All.Rg16, PixelFormat.Rg, PixelType.UnsignedShort));
Add(Format.R16G16Snorm, new FormatInfo(2, true, false, All.Rg16Snorm, PixelFormat.Rg, PixelType.Short));
Add(Format.R16G16Uint, new FormatInfo(2, false, false, All.Rg16ui, PixelFormat.RgInteger, PixelType.UnsignedShort));
Add(Format.R16G16Sint, new FormatInfo(2, false, false, All.Rg16i, PixelFormat.RgInteger, PixelType.Short));
Add(Format.R32G32Float, new FormatInfo(2, false, false, All.Rg32f, PixelFormat.Rg, PixelType.Float));
Add(Format.R32G32Uint, new FormatInfo(2, false, false, All.Rg32ui, PixelFormat.RgInteger, PixelType.UnsignedInt));
Add(Format.R32G32Sint, new FormatInfo(2, false, false, All.Rg32i, PixelFormat.RgInteger, PixelType.Int));
Add(Format.R8G8B8Unorm, new FormatInfo(3, true, false, All.Rgb8, PixelFormat.Rgb, PixelType.UnsignedByte));
Add(Format.R8G8B8Snorm, new FormatInfo(3, true, false, All.Rgb8Snorm, PixelFormat.Rgb, PixelType.Byte));
Add(Format.R8G8B8Uint, new FormatInfo(3, false, false, All.Rgb8ui, PixelFormat.RgbInteger, PixelType.UnsignedByte));
Add(Format.R8G8B8Sint, new FormatInfo(3, false, false, All.Rgb8i, PixelFormat.RgbInteger, PixelType.Byte));
Add(Format.R16G16B16Float, new FormatInfo(3, false, false, All.Rgb16f, PixelFormat.Rgb, PixelType.HalfFloat));
Add(Format.R16G16B16Unorm, new FormatInfo(3, true, false, All.Rgb16, PixelFormat.Rgb, PixelType.UnsignedShort));
Add(Format.R16G16B16Snorm, new FormatInfo(3, true, false, All.Rgb16Snorm, PixelFormat.Rgb, PixelType.Short));
Add(Format.R16G16B16Uint, new FormatInfo(3, false, false, All.Rgb16ui, PixelFormat.RgbInteger, PixelType.UnsignedShort));
Add(Format.R16G16B16Sint, new FormatInfo(3, false, false, All.Rgb16i, PixelFormat.RgbInteger, PixelType.Short));
Add(Format.R32G32B32Float, new FormatInfo(3, false, false, All.Rgb32f, PixelFormat.Rgb, PixelType.Float));
Add(Format.R32G32B32Uint, new FormatInfo(3, false, false, All.Rgb32ui, PixelFormat.RgbInteger, PixelType.UnsignedInt));
Add(Format.R32G32B32Sint, new FormatInfo(3, false, false, All.Rgb32i, PixelFormat.RgbInteger, PixelType.Int));
Add(Format.R8G8B8A8Unorm, new FormatInfo(4, true, false, All.Rgba8, PixelFormat.Rgba, PixelType.UnsignedByte));
Add(Format.R8G8B8A8Snorm, new FormatInfo(4, true, false, All.Rgba8Snorm, PixelFormat.Rgba, PixelType.Byte));
Add(Format.R8G8B8A8Uint, new FormatInfo(4, false, false, All.Rgba8ui, PixelFormat.RgbaInteger, PixelType.UnsignedByte));
Add(Format.R8G8B8A8Sint, new FormatInfo(4, false, false, All.Rgba8i, PixelFormat.RgbaInteger, PixelType.Byte));
Add(Format.R16G16B16A16Float, new FormatInfo(4, false, false, All.Rgba16f, PixelFormat.Rgba, PixelType.HalfFloat));
Add(Format.R16G16B16A16Unorm, new FormatInfo(4, true, false, All.Rgba16, PixelFormat.Rgba, PixelType.UnsignedShort));
Add(Format.R16G16B16A16Snorm, new FormatInfo(4, true, false, All.Rgba16Snorm, PixelFormat.Rgba, PixelType.Short));
Add(Format.R16G16B16A16Uint, new FormatInfo(4, false, false, All.Rgba16ui, PixelFormat.RgbaInteger, PixelType.UnsignedShort));
Add(Format.R16G16B16A16Sint, new FormatInfo(4, false, false, All.Rgba16i, PixelFormat.RgbaInteger, PixelType.Short));
Add(Format.R32G32B32A32Float, new FormatInfo(4, false, false, All.Rgba32f, PixelFormat.Rgba, PixelType.Float));
Add(Format.R32G32B32A32Uint, new FormatInfo(4, false, false, All.Rgba32ui, PixelFormat.RgbaInteger, PixelType.UnsignedInt));
Add(Format.R32G32B32A32Sint, new FormatInfo(4, false, false, All.Rgba32i, PixelFormat.RgbaInteger, PixelType.Int));
Add(Format.S8Uint, new FormatInfo(1, false, false, All.StencilIndex8, PixelFormat.StencilIndex, PixelType.UnsignedByte));
Add(Format.D16Unorm, new FormatInfo(1, false, false, All.DepthComponent16, PixelFormat.DepthComponent, PixelType.UnsignedShort));
Add(Format.S8UintD24Unorm, new FormatInfo(1, false, false, All.Depth24Stencil8, PixelFormat.DepthStencil, PixelType.UnsignedInt248));
Add(Format.X8UintD24Unorm, new FormatInfo(1, false, false, All.DepthComponent24, PixelFormat.DepthComponent, PixelType.UnsignedInt));
Add(Format.D32Float, new FormatInfo(1, false, false, All.DepthComponent32f, PixelFormat.DepthComponent, PixelType.Float));
Add(Format.D24UnormS8Uint, new FormatInfo(1, false, false, All.Depth24Stencil8, PixelFormat.DepthStencil, PixelType.UnsignedInt248));
Add(Format.D32FloatS8Uint, new FormatInfo(1, false, false, All.Depth32fStencil8, PixelFormat.DepthStencil, PixelType.Float32UnsignedInt248Rev));
Add(Format.R8G8B8A8Srgb, new FormatInfo(4, false, false, All.Srgb8Alpha8, PixelFormat.Rgba, PixelType.UnsignedByte));
Add(Format.R4G4B4A4Unorm, new FormatInfo(4, true, false, All.Rgba4, PixelFormat.Rgba, PixelType.UnsignedShort4444Reversed));
Add(Format.R5G5B5X1Unorm, new FormatInfo(4, true, false, All.Rgb5, PixelFormat.Rgb, PixelType.UnsignedShort1555Reversed));
Add(Format.R5G5B5A1Unorm, new FormatInfo(4, true, false, All.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort1555Reversed));
Add(Format.R5G6B5Unorm, new FormatInfo(3, true, false, All.Rgb565, PixelFormat.Rgb, PixelType.UnsignedShort565Reversed));
Add(Format.R10G10B10A2Unorm, new FormatInfo(4, true, false, All.Rgb10A2, PixelFormat.Rgba, PixelType.UnsignedInt2101010Reversed));
Add(Format.R10G10B10A2Uint, new FormatInfo(4, false, false, All.Rgb10A2ui, PixelFormat.RgbaInteger, PixelType.UnsignedInt2101010Reversed));
Add(Format.R11G11B10Float, new FormatInfo(3, false, false, All.R11fG11fB10f, PixelFormat.Rgb, PixelType.UnsignedInt10F11F11FRev));
Add(Format.R9G9B9E5Float, new FormatInfo(3, false, false, All.Rgb9E5, PixelFormat.Rgb, PixelType.UnsignedInt5999Rev));
Add(Format.Bc1RgbaUnorm, new FormatInfo(4, true, false, All.CompressedRgbaS3tcDxt1Ext));
Add(Format.Bc2Unorm, new FormatInfo(4, true, false, All.CompressedRgbaS3tcDxt3Ext));
Add(Format.Bc3Unorm, new FormatInfo(4, true, false, All.CompressedRgbaS3tcDxt5Ext));
Add(Format.Bc1RgbaSrgb, new FormatInfo(4, true, false, All.CompressedSrgbAlphaS3tcDxt1Ext));
Add(Format.Bc2Srgb, new FormatInfo(4, false, false, All.CompressedSrgbAlphaS3tcDxt3Ext));
Add(Format.Bc3Srgb, new FormatInfo(4, false, false, All.CompressedSrgbAlphaS3tcDxt5Ext));
Add(Format.Bc4Unorm, new FormatInfo(1, true, false, All.CompressedRedRgtc1));
Add(Format.Bc4Snorm, new FormatInfo(1, true, false, All.CompressedSignedRedRgtc1));
Add(Format.Bc5Unorm, new FormatInfo(2, true, false, All.CompressedRgRgtc2));
Add(Format.Bc5Snorm, new FormatInfo(2, true, false, All.CompressedSignedRgRgtc2));
Add(Format.Bc7Unorm, new FormatInfo(4, true, false, All.CompressedRgbaBptcUnorm));
Add(Format.Bc7Srgb, new FormatInfo(4, false, false, All.CompressedSrgbAlphaBptcUnorm));
Add(Format.Bc6HSfloat, new FormatInfo(4, false, false, All.CompressedRgbBptcSignedFloat));
Add(Format.Bc6HUfloat, new FormatInfo(4, false, false, All.CompressedRgbBptcUnsignedFloat));
Add(Format.Etc2RgbUnorm, new FormatInfo(4, false, false, All.CompressedRgb8Etc2));
Add(Format.Etc2RgbaUnorm, new FormatInfo(4, false, false, All.CompressedRgba8Etc2Eac));
Add(Format.Etc2RgbPtaUnorm, new FormatInfo(4, false, false, All.CompressedRgb8PunchthroughAlpha1Etc2));
Add(Format.Etc2RgbSrgb, new FormatInfo(4, false, false, All.CompressedSrgb8Etc2));
Add(Format.Etc2RgbaSrgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Etc2Eac));
Add(Format.Etc2RgbPtaSrgb, new FormatInfo(4, false, false, All.CompressedSrgb8PunchthroughAlpha1Etc2));
Add(Format.R8Uscaled, new FormatInfo(1, false, true, All.R8ui, PixelFormat.RedInteger, PixelType.UnsignedByte));
Add(Format.R8Sscaled, new FormatInfo(1, false, true, All.R8i, PixelFormat.RedInteger, PixelType.Byte));
Add(Format.R16Uscaled, new FormatInfo(1, false, true, All.R16ui, PixelFormat.RedInteger, PixelType.UnsignedShort));
Add(Format.R16Sscaled, new FormatInfo(1, false, true, All.R16i, PixelFormat.RedInteger, PixelType.Short));
Add(Format.R32Uscaled, new FormatInfo(1, false, true, All.R32ui, PixelFormat.RedInteger, PixelType.UnsignedInt));
Add(Format.R32Sscaled, new FormatInfo(1, false, true, All.R32i, PixelFormat.RedInteger, PixelType.Int));
Add(Format.R8G8Uscaled, new FormatInfo(2, false, true, All.Rg8ui, PixelFormat.RgInteger, PixelType.UnsignedByte));
Add(Format.R8G8Sscaled, new FormatInfo(2, false, true, All.Rg8i, PixelFormat.RgInteger, PixelType.Byte));
Add(Format.R16G16Uscaled, new FormatInfo(2, false, true, All.Rg16ui, PixelFormat.RgInteger, PixelType.UnsignedShort));
Add(Format.R16G16Sscaled, new FormatInfo(2, false, true, All.Rg16i, PixelFormat.RgInteger, PixelType.Short));
Add(Format.R32G32Uscaled, new FormatInfo(2, false, true, All.Rg32ui, PixelFormat.RgInteger, PixelType.UnsignedInt));
Add(Format.R32G32Sscaled, new FormatInfo(2, false, true, All.Rg32i, PixelFormat.RgInteger, PixelType.Int));
Add(Format.R8G8B8Uscaled, new FormatInfo(3, false, true, All.Rgb8ui, PixelFormat.RgbInteger, PixelType.UnsignedByte));
Add(Format.R8G8B8Sscaled, new FormatInfo(3, false, true, All.Rgb8i, PixelFormat.RgbInteger, PixelType.Byte));
Add(Format.R16G16B16Uscaled, new FormatInfo(3, false, true, All.Rgb16ui, PixelFormat.RgbInteger, PixelType.UnsignedShort));
Add(Format.R16G16B16Sscaled, new FormatInfo(3, false, true, All.Rgb16i, PixelFormat.RgbInteger, PixelType.Short));
Add(Format.R32G32B32Uscaled, new FormatInfo(3, false, true, All.Rgb32ui, PixelFormat.RgbInteger, PixelType.UnsignedInt));
Add(Format.R32G32B32Sscaled, new FormatInfo(3, false, true, All.Rgb32i, PixelFormat.RgbInteger, PixelType.Int));
Add(Format.R8G8B8A8Uscaled, new FormatInfo(4, false, true, All.Rgba8ui, PixelFormat.RgbaInteger, PixelType.UnsignedByte));
Add(Format.R8G8B8A8Sscaled, new FormatInfo(4, false, true, All.Rgba8i, PixelFormat.RgbaInteger, PixelType.Byte));
Add(Format.R16G16B16A16Uscaled, new FormatInfo(4, false, true, All.Rgba16ui, PixelFormat.RgbaInteger, PixelType.UnsignedShort));
Add(Format.R16G16B16A16Sscaled, new FormatInfo(4, false, true, All.Rgba16i, PixelFormat.RgbaInteger, PixelType.Short));
Add(Format.R32G32B32A32Uscaled, new FormatInfo(4, false, true, All.Rgba32ui, PixelFormat.RgbaInteger, PixelType.UnsignedInt));
Add(Format.R32G32B32A32Sscaled, new FormatInfo(4, false, true, All.Rgba32i, PixelFormat.RgbaInteger, PixelType.Int));
Add(Format.R10G10B10A2Snorm, new FormatInfo(4, true, false, All.Rgb10A2, PixelFormat.Rgba, (PixelType)All.Int2101010Rev));
Add(Format.R10G10B10A2Sint, new FormatInfo(4, false, false, All.Rgb10A2, PixelFormat.RgbaInteger, (PixelType)All.Int2101010Rev));
Add(Format.R10G10B10A2Uscaled, new FormatInfo(4, false, true, All.Rgb10A2ui, PixelFormat.RgbaInteger, PixelType.UnsignedInt2101010Reversed));
Add(Format.R10G10B10A2Sscaled, new FormatInfo(4, false, true, All.Rgb10A2, PixelFormat.RgbaInteger, PixelType.UnsignedInt2101010Reversed));
Add(Format.Astc4x4Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc4X4Khr));
Add(Format.Astc5x4Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc5X4Khr));
Add(Format.Astc5x5Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc5X5Khr));
Add(Format.Astc6x5Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc6X5Khr));
Add(Format.Astc6x6Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc6X6Khr));
Add(Format.Astc8x5Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc8X5Khr));
Add(Format.Astc8x6Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc8X6Khr));
Add(Format.Astc8x8Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc8X8Khr));
Add(Format.Astc10x5Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc10X5Khr));
Add(Format.Astc10x6Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc10X6Khr));
Add(Format.Astc10x8Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc10X8Khr));
Add(Format.Astc10x10Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc10X10Khr));
Add(Format.Astc12x10Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc12X10Khr));
Add(Format.Astc12x12Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc12X12Khr));
Add(Format.Astc4x4Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc4X4Khr));
Add(Format.Astc5x4Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc5X4Khr));
Add(Format.Astc5x5Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc5X5Khr));
Add(Format.Astc6x5Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc6X5Khr));
Add(Format.Astc6x6Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc6X6Khr));
Add(Format.Astc8x5Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc8X5Khr));
Add(Format.Astc8x6Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc8X6Khr));
Add(Format.Astc8x8Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc8X8Khr));
Add(Format.Astc10x5Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc10X5Khr));
Add(Format.Astc10x6Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc10X6Khr));
Add(Format.Astc10x8Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc10X8Khr));
Add(Format.Astc10x10Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc10X10Khr));
Add(Format.Astc12x10Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc12X10Khr));
Add(Format.Astc12x12Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc12X12Khr));
Add(Format.B5G6R5Unorm, new FormatInfo(3, true, false, All.Rgb565, PixelFormat.Rgb, PixelType.UnsignedShort565Reversed));
Add(Format.B5G5R5A1Unorm, new FormatInfo(4, true, false, All.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort1555Reversed));
Add(Format.A1B5G5R5Unorm, new FormatInfo(4, true, false, All.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort5551));
Add(Format.B8G8R8A8Unorm, new FormatInfo(4, true, false, All.Rgba8, PixelFormat.Rgba, PixelType.UnsignedByte));
Add(Format.B8G8R8A8Srgb, new FormatInfo(4, false, false, All.Srgb8Alpha8, PixelFormat.Rgba, PixelType.UnsignedByte));
Add(Format.B10G10R10A2Unorm, new FormatInfo(4, false, false, All.Rgb10A2, PixelFormat.Rgba, PixelType.UnsignedInt2101010Reversed));
Add(Format.R8Unorm, new FormatInfo(1, true, false, InternalFormat.R8, PixelFormat.Red, PixelType.UnsignedByte));
Add(Format.R8Snorm, new FormatInfo(1, true, false, InternalFormat.R8SNorm, PixelFormat.Red, PixelType.Byte));
Add(Format.R8Uint, new FormatInfo(1, false, false, InternalFormat.R8ui, PixelFormat.RedInteger, PixelType.UnsignedByte));
Add(Format.R8Sint, new FormatInfo(1, false, false, InternalFormat.R8i, PixelFormat.RedInteger, PixelType.Byte));
Add(Format.R16Float, new FormatInfo(1, false, false, InternalFormat.R16f, PixelFormat.Red, (PixelType)NV.HalfFloatNV));
Add(Format.R16Unorm, new FormatInfo(1, true, false, InternalFormat.R16, PixelFormat.Red, PixelType.UnsignedShort));
Add(Format.R16Snorm, new FormatInfo(1, true, false, InternalFormat.R16SNorm, PixelFormat.Red, PixelType.Short));
Add(Format.R16Uint, new FormatInfo(1, false, false, InternalFormat.R16ui, PixelFormat.RedInteger, PixelType.UnsignedShort));
Add(Format.R16Sint, new FormatInfo(1, false, false, InternalFormat.R16i, PixelFormat.RedInteger, PixelType.Short));
Add(Format.R32Float, new FormatInfo(1, false, false, InternalFormat.R32f, PixelFormat.Red, PixelType.Float));
Add(Format.R32Uint, new FormatInfo(1, false, false, InternalFormat.R32ui, PixelFormat.RedInteger, PixelType.UnsignedInt));
Add(Format.R32Sint, new FormatInfo(1, false, false, InternalFormat.R32i, PixelFormat.RedInteger, PixelType.Int));
Add(Format.R8G8Unorm, new FormatInfo(2, true, false, InternalFormat.RG8, PixelFormat.RG, PixelType.UnsignedByte));
Add(Format.R8G8Snorm, new FormatInfo(2, true, false, InternalFormat.RG8SNorm, PixelFormat.RG, PixelType.Byte));
Add(Format.R8G8Uint, new FormatInfo(2, false, false, InternalFormat.RG8ui, PixelFormat.RGInteger, PixelType.UnsignedByte));
Add(Format.R8G8Sint, new FormatInfo(2, false, false, InternalFormat.RG8i, PixelFormat.RGInteger, PixelType.Byte));
Add(Format.R16G16Float, new FormatInfo(2, false, false, InternalFormat.RG16f, PixelFormat.RG, (PixelType)NV.HalfFloatNV));
Add(Format.R16G16Unorm, new FormatInfo(2, true, false, InternalFormat.RG16, PixelFormat.RG, PixelType.UnsignedShort));
Add(Format.R16G16Snorm, new FormatInfo(2, true, false, InternalFormat.RG16SNorm, PixelFormat.RG, PixelType.Short));
Add(Format.R16G16Uint, new FormatInfo(2, false, false, InternalFormat.RG16ui, PixelFormat.RGInteger, PixelType.UnsignedShort));
Add(Format.R16G16Sint, new FormatInfo(2, false, false, InternalFormat.RG16i, PixelFormat.RGInteger, PixelType.Short));
Add(Format.R32G32Float, new FormatInfo(2, false, false, InternalFormat.RG32f, PixelFormat.RG, PixelType.Float));
Add(Format.R32G32Uint, new FormatInfo(2, false, false, InternalFormat.RG32ui, PixelFormat.RGInteger, PixelType.UnsignedInt));
Add(Format.R32G32Sint, new FormatInfo(2, false, false, InternalFormat.RG32i, PixelFormat.RGInteger, PixelType.Int));
Add(Format.R8G8B8Unorm, new FormatInfo(3, true, false, InternalFormat.Rgb8, PixelFormat.Rgb, PixelType.UnsignedByte));
Add(Format.R8G8B8Snorm, new FormatInfo(3, true, false, InternalFormat.Rgb8SNorm, PixelFormat.Rgb, PixelType.Byte));
Add(Format.R8G8B8Uint, new FormatInfo(3, false, false, InternalFormat.Rgb8ui, PixelFormat.RgbInteger, PixelType.UnsignedByte));
Add(Format.R8G8B8Sint, new FormatInfo(3, false, false, InternalFormat.Rgb8i, PixelFormat.RgbInteger, PixelType.Byte));
Add(Format.R16G16B16Float, new FormatInfo(3, false, false, InternalFormat.Rgb16f, PixelFormat.Rgb, (PixelType)NV.HalfFloatNV));
Add(Format.R16G16B16Unorm, new FormatInfo(3, true, false, InternalFormat.Rgb16, PixelFormat.Rgb, PixelType.UnsignedShort));
Add(Format.R16G16B16Snorm, new FormatInfo(3, true, false, InternalFormat.Rgb16SNorm, PixelFormat.Rgb, PixelType.Short));
Add(Format.R16G16B16Uint, new FormatInfo(3, false, false, InternalFormat.Rgb16ui, PixelFormat.RgbInteger, PixelType.UnsignedShort));
Add(Format.R16G16B16Sint, new FormatInfo(3, false, false, InternalFormat.Rgb16i, PixelFormat.RgbInteger, PixelType.Short));
Add(Format.R32G32B32Float, new FormatInfo(3, false, false, InternalFormat.Rgb32f, PixelFormat.Rgb, PixelType.Float));
Add(Format.R32G32B32Uint, new FormatInfo(3, false, false, InternalFormat.Rgb32ui, PixelFormat.RgbInteger, PixelType.UnsignedInt));
Add(Format.R32G32B32Sint, new FormatInfo(3, false, false, InternalFormat.Rgb32i, PixelFormat.RgbInteger, PixelType.Int));
Add(Format.R8G8B8A8Unorm, new FormatInfo(4, true, false, InternalFormat.Rgba8, PixelFormat.Rgba, PixelType.UnsignedByte));
Add(Format.R8G8B8A8Snorm, new FormatInfo(4, true, false, InternalFormat.Rgba8SNorm, PixelFormat.Rgba, PixelType.Byte));
Add(Format.R8G8B8A8Uint, new FormatInfo(4, false, false, InternalFormat.Rgba8ui, PixelFormat.RgbaInteger, PixelType.UnsignedByte));
Add(Format.R8G8B8A8Sint, new FormatInfo(4, false, false, InternalFormat.Rgba8i, PixelFormat.RgbaInteger, PixelType.Byte));
Add(Format.R16G16B16A16Float, new FormatInfo(4, false, false, InternalFormat.Rgba16f, PixelFormat.Rgba, (PixelType)NV.HalfFloatNV));
Add(Format.R16G16B16A16Unorm, new FormatInfo(4, true, false, InternalFormat.Rgba16, PixelFormat.Rgba, PixelType.UnsignedShort));
Add(Format.R16G16B16A16Snorm, new FormatInfo(4, true, false, InternalFormat.Rgba16SNorm, PixelFormat.Rgba, PixelType.Short));
Add(Format.R16G16B16A16Uint, new FormatInfo(4, false, false, InternalFormat.Rgba16ui, PixelFormat.RgbaInteger, PixelType.UnsignedShort));
Add(Format.R16G16B16A16Sint, new FormatInfo(4, false, false, InternalFormat.Rgba16i, PixelFormat.RgbaInteger, PixelType.Short));
Add(Format.R32G32B32A32Float, new FormatInfo(4, false, false, InternalFormat.Rgba32f, PixelFormat.Rgba, PixelType.Float));
Add(Format.R32G32B32A32Uint, new FormatInfo(4, false, false, InternalFormat.Rgba32ui, PixelFormat.RgbaInteger, PixelType.UnsignedInt));
Add(Format.R32G32B32A32Sint, new FormatInfo(4, false, false, InternalFormat.Rgba32i, PixelFormat.RgbaInteger, PixelType.Int));
Add(Format.S8Uint, new FormatInfo(1, false, false, InternalFormat.StencilIndex8, PixelFormat.StencilIndex, PixelType.UnsignedByte));
Add(Format.D16Unorm, new FormatInfo(1, false, false, InternalFormat.DepthComponent16, PixelFormat.DepthComponent, PixelType.UnsignedShort));
Add(Format.S8UintD24Unorm, new FormatInfo(1, false, false, InternalFormat.Depth24Stencil8, PixelFormat.DepthStencil, (PixelType)NV.UnsignedInt248NV));
Add(Format.X8UintD24Unorm, new FormatInfo(1, false, false, InternalFormat.DepthComponent24, PixelFormat.DepthComponent, PixelType.UnsignedInt));
Add(Format.D32Float, new FormatInfo(1, false, false, InternalFormat.DepthComponent32f, PixelFormat.DepthComponent, PixelType.Float));
Add(Format.D24UnormS8Uint, new FormatInfo(1, false, false, InternalFormat.Depth24Stencil8, PixelFormat.DepthStencil, (PixelType)NV.UnsignedInt248NV));
Add(Format.D32FloatS8Uint, new FormatInfo(1, false, false, InternalFormat.Depth32fStencil8, PixelFormat.DepthStencil, (PixelType)NV.Float32UnsignedInt248RevNV));
Add(Format.R8G8B8A8Srgb, new FormatInfo(4, false, false, InternalFormat.Srgb8Alpha8, PixelFormat.Rgba, PixelType.UnsignedByte));
Add(Format.R4G4B4A4Unorm, new FormatInfo(4, true, false, InternalFormat.Rgba4, PixelFormat.Rgba, PixelType.UnsignedShort4444Rev));
Add(Format.R5G5B5X1Unorm, new FormatInfo(4, true, false, InternalFormat.Rgb5, PixelFormat.Rgb, PixelType.UnsignedShort1555Rev));
Add(Format.R5G5B5A1Unorm, new FormatInfo(4, true, false, InternalFormat.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort1555Rev));
Add(Format.R5G6B5Unorm, new FormatInfo(3, true, false, InternalFormat.Rgb565, PixelFormat.Rgb, PixelType.UnsignedShort565Rev));
Add(Format.R10G10B10A2Unorm, new FormatInfo(4, true, false, InternalFormat.Rgb10A2, PixelFormat.Rgba, PixelType.UnsignedInt2101010Rev));
Add(Format.R10G10B10A2Uint, new FormatInfo(4, false, false, InternalFormat.Rgb10A2ui, PixelFormat.RgbaInteger, PixelType.UnsignedInt2101010Rev));
Add(Format.R11G11B10Float, new FormatInfo(3, false, false, InternalFormat.R11fG11fB10f, PixelFormat.Rgb, (PixelType)0x8C3B)); // GL_UNSIGNED_INT_10F_11F_11F_REV Defined in Updated Silk.NET
Add(Format.R9G9B9E5Float, new FormatInfo(3, false, false, InternalFormat.Rgb9E5, PixelFormat.Rgb, (PixelType)0x8C3E)); // GL_UNSIGNED_INT_5_9_9_9_REV Defined in Updated Silk.NET
Add(Format.Bc1RgbaUnorm, new FormatInfo(4, true, false, InternalFormat.CompressedRgbaS3TCDxt1Ext));
Add(Format.Bc2Unorm, new FormatInfo(4, true, false, InternalFormat.CompressedRgbaS3TCDxt3Ext));
Add(Format.Bc3Unorm, new FormatInfo(4, true, false, InternalFormat.CompressedRgbaS3TCDxt5Ext));
Add(Format.Bc1RgbaSrgb, new FormatInfo(4, true, false, InternalFormat.CompressedSrgbAlphaS3TCDxt1Ext));
Add(Format.Bc2Srgb, new FormatInfo(4, false, false, InternalFormat.CompressedSrgbAlphaS3TCDxt3Ext));
Add(Format.Bc3Srgb, new FormatInfo(4, false, false, InternalFormat.CompressedSrgbAlphaS3TCDxt5Ext));
Add(Format.Bc4Unorm, new FormatInfo(1, true, false, InternalFormat.CompressedRedRgtc1));
Add(Format.Bc4Snorm, new FormatInfo(1, true, false, InternalFormat.CompressedSignedRedRgtc1));
Add(Format.Bc5Unorm, new FormatInfo(2, true, false, InternalFormat.CompressedRGRgtc2));
Add(Format.Bc5Snorm, new FormatInfo(2, true, false, InternalFormat.CompressedSignedRGRgtc2));
Add(Format.Bc7Unorm, new FormatInfo(4, true, false, InternalFormat.CompressedRgbaBptcUnorm));
Add(Format.Bc7Srgb, new FormatInfo(4, false, false, InternalFormat.CompressedSrgbAlphaBptcUnorm));
Add(Format.Bc6HSfloat, new FormatInfo(4, false, false, InternalFormat.CompressedRgbBptcSignedFloat));
Add(Format.Bc6HUfloat, new FormatInfo(4, false, false, InternalFormat.CompressedRgbBptcUnsignedFloat));
Add(Format.Etc2RgbUnorm, new FormatInfo(4, false, false, InternalFormat.CompressedRgb8Etc2));
Add(Format.Etc2RgbaUnorm, new FormatInfo(4, false, false, InternalFormat.CompressedRgba8Etc2Eac));
Add(Format.Etc2RgbPtaUnorm, new FormatInfo(4, false, false, InternalFormat.CompressedRgb8PunchthroughAlpha1Etc2));
Add(Format.Etc2RgbSrgb, new FormatInfo(4, false, false, InternalFormat.CompressedSrgb8Etc2));
Add(Format.Etc2RgbaSrgb, new FormatInfo(4, false, false, InternalFormat.CompressedSrgb8Alpha8Etc2Eac));
Add(Format.Etc2RgbPtaSrgb, new FormatInfo(4, false, false, InternalFormat.CompressedSrgb8PunchthroughAlpha1Etc2));
Add(Format.R8Uscaled, new FormatInfo(1, false, true, InternalFormat.R8ui, PixelFormat.RedInteger, PixelType.UnsignedByte));
Add(Format.R8Sscaled, new FormatInfo(1, false, true, InternalFormat.R8i, PixelFormat.RedInteger, PixelType.Byte));
Add(Format.R16Uscaled, new FormatInfo(1, false, true, InternalFormat.R16ui, PixelFormat.RedInteger, PixelType.UnsignedShort));
Add(Format.R16Sscaled, new FormatInfo(1, false, true, InternalFormat.R16i, PixelFormat.RedInteger, PixelType.Short));
Add(Format.R32Uscaled, new FormatInfo(1, false, true, InternalFormat.R32ui, PixelFormat.RedInteger, PixelType.UnsignedInt));
Add(Format.R32Sscaled, new FormatInfo(1, false, true, InternalFormat.R32i, PixelFormat.RedInteger, PixelType.Int));
Add(Format.R8G8Uscaled, new FormatInfo(2, false, true, InternalFormat.RG8ui, PixelFormat.RGInteger, PixelType.UnsignedByte));
Add(Format.R8G8Sscaled, new FormatInfo(2, false, true, InternalFormat.RG8i, PixelFormat.RGInteger, PixelType.Byte));
Add(Format.R16G16Uscaled, new FormatInfo(2, false, true, InternalFormat.RG16ui, PixelFormat.RGInteger, PixelType.UnsignedShort));
Add(Format.R16G16Sscaled, new FormatInfo(2, false, true, InternalFormat.RG16i, PixelFormat.RGInteger, PixelType.Short));
Add(Format.R32G32Uscaled, new FormatInfo(2, false, true, InternalFormat.RG32ui, PixelFormat.RGInteger, PixelType.UnsignedInt));
Add(Format.R32G32Sscaled, new FormatInfo(2, false, true, InternalFormat.RG32i, PixelFormat.RGInteger, PixelType.Int));
Add(Format.R8G8B8Uscaled, new FormatInfo(3, false, true, InternalFormat.Rgb8ui, PixelFormat.RgbInteger, PixelType.UnsignedByte));
Add(Format.R8G8B8Sscaled, new FormatInfo(3, false, true, InternalFormat.Rgb8i, PixelFormat.RgbInteger, PixelType.Byte));
Add(Format.R16G16B16Uscaled, new FormatInfo(3, false, true, InternalFormat.Rgb16ui, PixelFormat.RgbInteger, PixelType.UnsignedShort));
Add(Format.R16G16B16Sscaled, new FormatInfo(3, false, true, InternalFormat.Rgb16i, PixelFormat.RgbInteger, PixelType.Short));
Add(Format.R32G32B32Uscaled, new FormatInfo(3, false, true, InternalFormat.Rgb32ui, PixelFormat.RgbInteger, PixelType.UnsignedInt));
Add(Format.R32G32B32Sscaled, new FormatInfo(3, false, true, InternalFormat.Rgb32i, PixelFormat.RgbInteger, PixelType.Int));
Add(Format.R8G8B8A8Uscaled, new FormatInfo(4, false, true, InternalFormat.Rgba8ui, PixelFormat.RgbaInteger, PixelType.UnsignedByte));
Add(Format.R8G8B8A8Sscaled, new FormatInfo(4, false, true, InternalFormat.Rgba8i, PixelFormat.RgbaInteger, PixelType.Byte));
Add(Format.R16G16B16A16Uscaled, new FormatInfo(4, false, true, InternalFormat.Rgba16ui, PixelFormat.RgbaInteger, PixelType.UnsignedShort));
Add(Format.R16G16B16A16Sscaled, new FormatInfo(4, false, true, InternalFormat.Rgba16i, PixelFormat.RgbaInteger, PixelType.Short));
Add(Format.R32G32B32A32Uscaled, new FormatInfo(4, false, true, InternalFormat.Rgba32ui, PixelFormat.RgbaInteger, PixelType.UnsignedInt));
Add(Format.R32G32B32A32Sscaled, new FormatInfo(4, false, true, InternalFormat.Rgba32i, PixelFormat.RgbaInteger, PixelType.Int));
Add(Format.R10G10B10A2Snorm, new FormatInfo(4, true, false, InternalFormat.Rgb10A2, PixelFormat.Rgba, (PixelType)GLEnum.Int2101010Rev));
Add(Format.R10G10B10A2Sint, new FormatInfo(4, false, false, InternalFormat.Rgb10A2, PixelFormat.RgbaInteger, (PixelType)GLEnum.Int2101010Rev));
Add(Format.R10G10B10A2Uscaled, new FormatInfo(4, false, true, InternalFormat.Rgb10A2ui, PixelFormat.RgbaInteger, PixelType.UnsignedInt2101010Rev));
Add(Format.R10G10B10A2Sscaled, new FormatInfo(4, false, true, InternalFormat.Rgb10A2, PixelFormat.RgbaInteger, PixelType.UnsignedInt2101010Rev));
Add(Format.Astc4x4Unorm, new FormatInfo(4, true, false, InternalFormat.CompressedRgbaAstc4x4Khr));
Add(Format.Astc5x4Unorm, new FormatInfo(4, true, false, InternalFormat.CompressedRgbaAstc5x4Khr));
Add(Format.Astc5x5Unorm, new FormatInfo(4, true, false, InternalFormat.CompressedRgbaAstc5x5Khr));
Add(Format.Astc6x5Unorm, new FormatInfo(4, true, false, InternalFormat.CompressedRgbaAstc6x5Khr));
Add(Format.Astc6x6Unorm, new FormatInfo(4, true, false, InternalFormat.CompressedRgbaAstc6x6Khr));
Add(Format.Astc8x5Unorm, new FormatInfo(4, true, false, InternalFormat.CompressedRgbaAstc8x5Khr));
Add(Format.Astc8x6Unorm, new FormatInfo(4, true, false, InternalFormat.CompressedRgbaAstc8x6Khr));
Add(Format.Astc8x8Unorm, new FormatInfo(4, true, false, InternalFormat.CompressedRgbaAstc8x8Khr));
Add(Format.Astc10x5Unorm, new FormatInfo(4, true, false, InternalFormat.CompressedRgbaAstc10x5Khr));
Add(Format.Astc10x6Unorm, new FormatInfo(4, true, false, InternalFormat.CompressedRgbaAstc10x6Khr));
Add(Format.Astc10x8Unorm, new FormatInfo(4, true, false, InternalFormat.CompressedRgbaAstc10x8Khr));
Add(Format.Astc10x10Unorm, new FormatInfo(4, true, false, InternalFormat.CompressedRgbaAstc10x10Khr));
Add(Format.Astc12x10Unorm, new FormatInfo(4, true, false, InternalFormat.CompressedRgbaAstc12x10Khr));
Add(Format.Astc12x12Unorm, new FormatInfo(4, true, false, InternalFormat.CompressedRgbaAstc12x12Khr));
Add(Format.Astc4x4Srgb, new FormatInfo(4, false, false, InternalFormat.CompressedSrgb8Alpha8Astc4x4Khr));
Add(Format.Astc5x4Srgb, new FormatInfo(4, false, false, InternalFormat.CompressedSrgb8Alpha8Astc5x4Khr));
Add(Format.Astc5x5Srgb, new FormatInfo(4, false, false, InternalFormat.CompressedSrgb8Alpha8Astc5x5Khr));
Add(Format.Astc6x5Srgb, new FormatInfo(4, false, false, InternalFormat.CompressedSrgb8Alpha8Astc6x5Khr));
Add(Format.Astc6x6Srgb, new FormatInfo(4, false, false, InternalFormat.CompressedSrgb8Alpha8Astc6x6Khr));
Add(Format.Astc8x5Srgb, new FormatInfo(4, false, false, InternalFormat.CompressedSrgb8Alpha8Astc8x5Khr));
Add(Format.Astc8x6Srgb, new FormatInfo(4, false, false, InternalFormat.CompressedSrgb8Alpha8Astc8x6Khr));
Add(Format.Astc8x8Srgb, new FormatInfo(4, false, false, InternalFormat.CompressedSrgb8Alpha8Astc8x8Khr));
Add(Format.Astc10x5Srgb, new FormatInfo(4, false, false, InternalFormat.CompressedSrgb8Alpha8Astc10x5Khr));
Add(Format.Astc10x6Srgb, new FormatInfo(4, false, false, InternalFormat.CompressedSrgb8Alpha8Astc10x6Khr));
Add(Format.Astc10x8Srgb, new FormatInfo(4, false, false, InternalFormat.CompressedSrgb8Alpha8Astc10x8Khr));
Add(Format.Astc10x10Srgb, new FormatInfo(4, false, false, InternalFormat.CompressedSrgb8Alpha8Astc10x10Khr));
Add(Format.Astc12x10Srgb, new FormatInfo(4, false, false, InternalFormat.CompressedSrgb8Alpha8Astc12x10Khr));
Add(Format.Astc12x12Srgb, new FormatInfo(4, false, false, InternalFormat.CompressedSrgb8Alpha8Astc12x12Khr));
Add(Format.B5G6R5Unorm, new FormatInfo(3, true, false, InternalFormat.Rgb565, PixelFormat.Rgb, PixelType.UnsignedShort565Rev));
Add(Format.B5G5R5A1Unorm, new FormatInfo(4, true, false, InternalFormat.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort1555Rev));
Add(Format.A1B5G5R5Unorm, new FormatInfo(4, true, false, InternalFormat.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort5551));
Add(Format.B8G8R8A8Unorm, new FormatInfo(4, true, false, InternalFormat.Rgba8, PixelFormat.Rgba, PixelType.UnsignedByte));
Add(Format.B8G8R8A8Srgb, new FormatInfo(4, false, false, InternalFormat.Srgb8Alpha8, PixelFormat.Rgba, PixelType.UnsignedByte));
Add(Format.B10G10R10A2Unorm, new FormatInfo(4, false, false, InternalFormat.Rgb10A2, PixelFormat.Rgba, PixelType.UnsignedInt2101010Rev));
Add(Format.R8Unorm, SizedInternalFormat.R8);
Add(Format.R8Uint, SizedInternalFormat.R8ui);
Add(Format.R8Sint, SizedInternalFormat.R8i);
Add(Format.R16Float, SizedInternalFormat.R16f);
Add(Format.R16Unorm, SizedInternalFormat.R16);
Add(Format.R16Snorm, (SizedInternalFormat)All.R16Snorm);
Add(Format.R16Snorm, SizedInternalFormat.R16SNorm);
Add(Format.R16Uint, SizedInternalFormat.R16ui);
Add(Format.R16Sint, SizedInternalFormat.R16i);
Add(Format.R32Float, SizedInternalFormat.R32f);
Add(Format.R32Uint, SizedInternalFormat.R32ui);
Add(Format.R32Sint, SizedInternalFormat.R32i);
Add(Format.R8G8Unorm, SizedInternalFormat.Rg8);
Add(Format.R8G8Snorm, (SizedInternalFormat)All.Rg8Snorm);
Add(Format.R8G8Uint, SizedInternalFormat.Rg8ui);
Add(Format.R8G8Sint, SizedInternalFormat.Rg8i);
Add(Format.R16G16Float, SizedInternalFormat.Rg16f);
Add(Format.R16G16Unorm, SizedInternalFormat.Rg16);
Add(Format.R16G16Snorm, (SizedInternalFormat)All.Rg16Snorm);
Add(Format.R16G16Uint, SizedInternalFormat.Rg16ui);
Add(Format.R16G16Sint, SizedInternalFormat.Rg16i);
Add(Format.R32G32Float, SizedInternalFormat.Rg32f);
Add(Format.R32G32Uint, SizedInternalFormat.Rg32ui);
Add(Format.R32G32Sint, SizedInternalFormat.Rg32i);
Add(Format.R8G8Unorm, SizedInternalFormat.RG8);
Add(Format.R8G8Snorm, SizedInternalFormat.RG8SNorm);
Add(Format.R8G8Uint, SizedInternalFormat.RG8ui);
Add(Format.R8G8Sint, SizedInternalFormat.RG8i);
Add(Format.R16G16Float, SizedInternalFormat.RG16f);
Add(Format.R16G16Unorm, SizedInternalFormat.RG16);
Add(Format.R16G16Snorm, SizedInternalFormat.RG16SNorm);
Add(Format.R16G16Uint, SizedInternalFormat.RG16ui);
Add(Format.R16G16Sint, SizedInternalFormat.RG16i);
Add(Format.R32G32Float, SizedInternalFormat.RG32f);
Add(Format.R32G32Uint, SizedInternalFormat.RG32ui);
Add(Format.R32G32Sint, SizedInternalFormat.RG32i);
Add(Format.R8G8B8A8Unorm, SizedInternalFormat.Rgba8);
Add(Format.R8G8B8A8Snorm, (SizedInternalFormat)All.Rgba8Snorm);
Add(Format.R8G8B8A8Snorm, SizedInternalFormat.Rgba8SNorm);
Add(Format.R8G8B8A8Uint, SizedInternalFormat.Rgba8ui);
Add(Format.R8G8B8A8Sint, SizedInternalFormat.Rgba8i);
Add(Format.R16G16B16A16Float, SizedInternalFormat.Rgba16f);
Add(Format.R16G16B16A16Unorm, SizedInternalFormat.Rgba16);
Add(Format.R16G16B16A16Snorm, (SizedInternalFormat)All.Rgba16Snorm);
Add(Format.R16G16B16A16Snorm, SizedInternalFormat.Rgba16SNorm);
Add(Format.R16G16B16A16Uint, SizedInternalFormat.Rgba16ui);
Add(Format.R16G16B16A16Sint, SizedInternalFormat.Rgba16i);
Add(Format.R32G32B32A32Float, SizedInternalFormat.Rgba32f);
Add(Format.R32G32B32A32Uint, SizedInternalFormat.Rgba32ui);
Add(Format.R32G32B32A32Sint, SizedInternalFormat.Rgba32i);
Add(Format.R8G8B8A8Srgb, SizedInternalFormat.Rgba8);
Add(Format.R10G10B10A2Unorm, (SizedInternalFormat)All.Rgb10A2);
Add(Format.R10G10B10A2Uint, (SizedInternalFormat)All.Rgb10A2ui);
Add(Format.R11G11B10Float, (SizedInternalFormat)All.R11fG11fB10f);
Add(Format.R10G10B10A2Unorm, SizedInternalFormat.Rgb10A2);
Add(Format.R10G10B10A2Uint, SizedInternalFormat.Rgb10A2ui);
Add(Format.R11G11B10Float, SizedInternalFormat.R11fG11fB10f);
#pragma warning restore IDE0055
}

View file

@ -1,6 +1,7 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.OpenGL.Image;
using Silk.NET.OpenGL.Legacy;
using Silk.NET.OpenGL.Legacy.Extensions.NV;
using System;
using System.Runtime.CompilerServices;
@ -8,8 +9,8 @@ namespace Ryujinx.Graphics.OpenGL
{
class Framebuffer : IDisposable
{
public int Handle { get; private set; }
private int _clearFbHandle;
public uint Handle { get; private set; }
private uint _clearFbHandle;
private bool _clearFbInitialized;
private FramebufferAttachment _lastDsAttachment;
@ -19,18 +20,21 @@ namespace Ryujinx.Graphics.OpenGL
private int _colorsCount;
private bool _dualSourceBlend;
private readonly GL _api;
public Framebuffer()
public Framebuffer(GL api)
{
Handle = GL.GenFramebuffer();
_clearFbHandle = GL.GenFramebuffer();
_api = api;
Handle = _api.GenFramebuffer();
_clearFbHandle = _api.GenFramebuffer();
_colors = new TextureView[8];
}
public int Bind()
public uint Bind()
{
GL.BindFramebuffer(FramebufferTarget.Framebuffer, Handle);
_api.BindFramebuffer(FramebufferTarget.Framebuffer, Handle);
return Handle;
}
@ -44,7 +48,7 @@ namespace Ryujinx.Graphics.OpenGL
FramebufferAttachment attachment = FramebufferAttachment.ColorAttachment0 + index;
GL.FramebufferTexture(FramebufferTarget.Framebuffer, attachment, color?.Handle ?? 0, 0);
_api.FramebufferTexture(FramebufferTarget.Framebuffer, attachment, color?.Handle ?? 0, 0);
_colors[index] = color;
}
@ -54,14 +58,14 @@ namespace Ryujinx.Graphics.OpenGL
// Detach the last depth/stencil buffer if there is any.
if (_lastDsAttachment != 0)
{
GL.FramebufferTexture(FramebufferTarget.Framebuffer, _lastDsAttachment, 0, 0);
_api.FramebufferTexture(FramebufferTarget.Framebuffer, _lastDsAttachment, 0, 0);
}
if (depthStencil != null)
{
FramebufferAttachment attachment = GetAttachment(depthStencil.Format);
GL.FramebufferTexture(
_api.FramebufferTexture(
FramebufferTarget.Framebuffer,
attachment,
depthStencil.Handle,
@ -87,11 +91,11 @@ namespace Ryujinx.Graphics.OpenGL
// we can only have one draw buffer.
if (enable)
{
GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
_api.DrawBuffer(DrawBufferMode.ColorAttachment0);
}
else if (oldEnable)
{
SetDrawBuffersImpl(_colorsCount);
SetDrawBuffersImpl(_api, _colorsCount);
}
}
@ -99,22 +103,22 @@ namespace Ryujinx.Graphics.OpenGL
{
if (_colorsCount != colorsCount && !_dualSourceBlend)
{
SetDrawBuffersImpl(colorsCount);
SetDrawBuffersImpl(_api, colorsCount);
}
_colorsCount = colorsCount;
}
private static void SetDrawBuffersImpl(int colorsCount)
private static void SetDrawBuffersImpl(GL api, int colorsCount)
{
DrawBuffersEnum[] drawBuffers = new DrawBuffersEnum[colorsCount];
DrawBufferMode[] drawBuffers = new DrawBufferMode[colorsCount];
for (int index = 0; index < colorsCount; index++)
{
drawBuffers[index] = DrawBuffersEnum.ColorAttachment0 + index;
drawBuffers[index] = DrawBufferMode.ColorAttachment0 + index;
}
GL.DrawBuffers(colorsCount, drawBuffers);
api.DrawBuffers((uint)colorsCount, drawBuffers);
}
private static FramebufferAttachment GetAttachment(Format format)
@ -123,14 +127,13 @@ namespace Ryujinx.Graphics.OpenGL
{
return FramebufferAttachment.DepthStencilAttachment;
}
else if (FormatTable.IsDepthOnly(format))
if (FormatTable.IsDepthOnly(format))
{
return FramebufferAttachment.DepthAttachment;
}
else
{
return FramebufferAttachment.StencilAttachment;
}
return FramebufferAttachment.StencilAttachment;
}
public int GetColorLayerCount(int index)
@ -153,7 +156,7 @@ namespace Ryujinx.Graphics.OpenGL
}
BindClearFb();
GL.FramebufferTextureLayer(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0 + index, color.Handle, 0, layer);
_api.FramebufferTextureLayer(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0 + index, color.Handle, 0, layer);
}
public void DetachColorLayerForClear(int index)
@ -165,7 +168,7 @@ namespace Ryujinx.Graphics.OpenGL
return;
}
GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0 + index, 0, 0);
_api.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0 + index, 0, 0);
Bind();
}
@ -179,7 +182,7 @@ namespace Ryujinx.Graphics.OpenGL
}
BindClearFb();
GL.FramebufferTextureLayer(FramebufferTarget.Framebuffer, GetAttachment(depthStencil.Format), depthStencil.Handle, 0, layer);
_api.FramebufferTextureLayer(FramebufferTarget.Framebuffer, GetAttachment(depthStencil.Format), depthStencil.Handle, 0, layer);
}
public void DetachDepthStencilLayerForClear()
@ -191,17 +194,17 @@ namespace Ryujinx.Graphics.OpenGL
return;
}
GL.FramebufferTexture(FramebufferTarget.Framebuffer, GetAttachment(depthStencil.Format), 0, 0);
_api.FramebufferTexture(FramebufferTarget.Framebuffer, GetAttachment(depthStencil.Format), 0, 0);
Bind();
}
private void BindClearFb()
{
GL.BindFramebuffer(FramebufferTarget.Framebuffer, _clearFbHandle);
_api.BindFramebuffer(FramebufferTarget.Framebuffer, _clearFbHandle);
if (!_clearFbInitialized)
{
SetDrawBuffersImpl(Constants.MaxRenderTargets);
SetDrawBuffersImpl(_api, Constants.MaxRenderTargets);
_clearFbInitialized = true;
}
}
@ -219,14 +222,14 @@ namespace Ryujinx.Graphics.OpenGL
{
if (Handle != 0)
{
GL.DeleteFramebuffer(Handle);
_api.DeleteFramebuffer(Handle);
Handle = 0;
}
if (_clearFbHandle != 0)
{
GL.DeleteFramebuffer(_clearFbHandle);
_api.DeleteFramebuffer(_clearFbHandle);
_clearFbHandle = 0;
}

View file

@ -6,18 +6,18 @@ namespace Ryujinx.Graphics.OpenGL
{
static class Handle
{
public static T FromInt32<T>(int handle) where T : unmanaged
public static T FromUInt32<T>(uint handle) where T : unmanaged
{
Debug.Assert(Unsafe.SizeOf<T>() == sizeof(ulong));
ulong handle64 = (uint)handle;
ulong handle64 = handle;
return Unsafe.As<ulong, T>(ref handle64);
}
public static int ToInt32(this BufferHandle handle)
public static uint ToUInt32(this BufferHandle handle)
{
return (int)Unsafe.As<BufferHandle, ulong>(ref handle);
return (uint)Unsafe.As<BufferHandle, ulong>(ref handle);
}
}
}

View file

@ -0,0 +1,163 @@
using Silk.NET.OpenGL.Legacy;
using System;
using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.OpenGL
{
public enum GpuVendor
{
Unknown,
AmdWindows,
AmdUnix,
IntelWindows,
IntelUnix,
Nvidia,
}
readonly struct HardwareCapabilities
{
public readonly bool SupportsAlphaToCoverageDitherControl;
public readonly bool SupportsAstcCompression;
public readonly bool SupportsBlendEquationAdvanced;
public readonly bool SupportsDrawTexture;
public readonly bool SupportsFragmentShaderInterlock;
public readonly bool SupportsFragmentShaderOrdering;
public readonly bool SupportsGeometryShaderPassthrough;
public readonly bool SupportsImageLoadFormatted;
public readonly bool SupportsIndirectParameters;
public readonly bool SupportsParallelShaderCompile;
public readonly bool SupportsPolygonOffsetClamp;
public readonly bool SupportsQuads;
public readonly bool SupportsSeamlessCubemapPerTexture;
public readonly bool SupportsShaderBallot;
public readonly bool SupportsShaderViewportLayerArray;
public readonly bool SupportsViewportArray2;
public readonly bool SupportsTextureCompressionBptc;
public readonly bool SupportsTextureCompressionRgtc;
public readonly bool SupportsTextureCompressionS3tc;
public readonly bool SupportsTextureShadowLod;
public readonly bool SupportsViewportSwizzle;
public bool SupportsMismatchingViewFormat => GpuVendor != GpuVendor.AmdWindows && GpuVendor != GpuVendor.IntelWindows;
public bool SupportsNonConstantTextureOffset => GpuVendor == GpuVendor.Nvidia;
public bool RequiresSyncFlush => GpuVendor == GpuVendor.AmdWindows || IsIntel;
public bool UsePersistentBufferForFlush => GpuVendor == GpuVendor.AmdWindows || GpuVendor == GpuVendor.Nvidia;
public readonly int MaximumComputeSharedMemorySize;
public readonly int StorageBufferOffsetAlignment;
public readonly int TextureBufferOffsetAlignment;
public readonly float MaximumSupportedAnisotropy;
public readonly GpuVendor GpuVendor;
public HardwareCapabilities(
bool supportsAlphaToCoverageDitherControl,
bool supportsAstcCompression,
bool supportsBlendEquationAdvanced,
bool supportsDrawTexture,
bool supportsFragmentShaderInterlock,
bool supportsFragmentShaderOrdering,
bool supportsGeometryShaderPassthrough,
bool supportsImageLoadFormatted,
bool supportsIndirectParameters,
bool supportsParallelShaderCompile,
bool supportsPolygonOffsetClamp,
bool supportsQuads,
bool supportsSeamlessCubemapPerTexture,
bool supportsShaderBallot,
bool supportsShaderViewportLayerArray,
bool supportsViewportArray2,
bool supportsTextureCompressionBptc,
bool supportsTextureCompressionRgtc,
bool supportsTextureCompressionS3Tc,
bool supportsTextureShadowLod,
bool supportsViewportSwizzle,
int maximumComputeSharedMemorySize,
int storageBufferOffsetAlignment,
int textureBufferOffsetAlignment,
float maximumSupportedAnisotropy,
GpuVendor gpuVendor)
{
SupportsAlphaToCoverageDitherControl = supportsAlphaToCoverageDitherControl;
SupportsAstcCompression = supportsAstcCompression;
SupportsBlendEquationAdvanced = supportsBlendEquationAdvanced;
SupportsDrawTexture = supportsDrawTexture;
SupportsFragmentShaderInterlock = supportsFragmentShaderInterlock;
SupportsFragmentShaderOrdering = supportsFragmentShaderOrdering;
SupportsGeometryShaderPassthrough = supportsGeometryShaderPassthrough;
SupportsImageLoadFormatted = supportsImageLoadFormatted;
SupportsIndirectParameters = supportsIndirectParameters;
SupportsParallelShaderCompile = supportsParallelShaderCompile;
SupportsPolygonOffsetClamp = supportsPolygonOffsetClamp;
SupportsQuads = supportsQuads;
SupportsSeamlessCubemapPerTexture = supportsSeamlessCubemapPerTexture;
SupportsShaderBallot = supportsShaderBallot;
SupportsShaderViewportLayerArray = supportsShaderViewportLayerArray;
SupportsViewportArray2 = supportsViewportArray2;
SupportsTextureCompressionBptc = supportsTextureCompressionBptc;
SupportsTextureCompressionRgtc = supportsTextureCompressionRgtc;
SupportsTextureCompressionS3tc = supportsTextureCompressionS3Tc;
SupportsTextureShadowLod = supportsTextureShadowLod;
SupportsViewportSwizzle = supportsViewportSwizzle;
MaximumComputeSharedMemorySize = maximumComputeSharedMemorySize;
StorageBufferOffsetAlignment = storageBufferOffsetAlignment;
TextureBufferOffsetAlignment = textureBufferOffsetAlignment;
MaximumSupportedAnisotropy = maximumSupportedAnisotropy;
GpuVendor = gpuVendor;
}
public bool IsIntel => GpuVendor == GpuVendor.IntelWindows || GpuVendor == GpuVendor.IntelUnix;
public static unsafe bool HasExtension(GL api, string name)
{
int numExtensions = api.GetInteger(GLEnum.NumExtensions);
for (uint extension = 0; extension < numExtensions; extension++)
{
if (Marshal.PtrToStringAnsi((IntPtr)api.GetString(StringName.Extensions, extension)) == name)
{
return true;
}
}
return false;
}
public static unsafe GpuVendor GetGpuVendor(GL api)
{
string vendor = Marshal.PtrToStringAnsi((IntPtr)api.GetString(StringName.Vendor)).ToLowerInvariant();
switch (vendor)
{
case "nvidia corporation":
return GpuVendor.Nvidia;
case "intel":
{
string renderer = Marshal.PtrToStringAnsi((IntPtr)api.GetString(StringName.Renderer)).ToLowerInvariant();
return renderer.Contains("mesa") ? GpuVendor.IntelUnix : GpuVendor.IntelWindows;
}
case "ati technologies inc.":
case "advanced micro devices, inc.":
return GpuVendor.AmdWindows;
case "amd":
case "x.org":
return GpuVendor.AmdUnix;
default:
return GpuVendor.Unknown;
}
}
public static bool SupportsQuadsCheck(GL api)
{
api.GetError(); // Clear any existing error.
#pragma warning disable CS0618 // Type or member is obsolete
api.Begin(PrimitiveType.Quads);
api.End();
#pragma warning restore CS0618 // Type or member is obsolete
return api.GetError() == GLEnum.NoError;
}
}
}

View file

@ -1,143 +0,0 @@
using OpenTK.Graphics.OpenGL;
using System;
namespace Ryujinx.Graphics.OpenGL
{
static class HwCapabilities
{
private static readonly Lazy<bool> _supportsAlphaToCoverageDitherControl = new(() => HasExtension("GL_NV_alpha_to_coverage_dither_control"));
private static readonly Lazy<bool> _supportsAstcCompression = new(() => HasExtension("GL_KHR_texture_compression_astc_ldr"));
private static readonly Lazy<bool> _supportsBlendEquationAdvanced = new(() => HasExtension("GL_NV_blend_equation_advanced"));
private static readonly Lazy<bool> _supportsDrawTexture = new(() => HasExtension("GL_NV_draw_texture"));
private static readonly Lazy<bool> _supportsFragmentShaderInterlock = new(() => HasExtension("GL_ARB_fragment_shader_interlock"));
private static readonly Lazy<bool> _supportsFragmentShaderOrdering = new(() => HasExtension("GL_INTEL_fragment_shader_ordering"));
private static readonly Lazy<bool> _supportsGeometryShaderPassthrough = new(() => HasExtension("GL_NV_geometry_shader_passthrough"));
private static readonly Lazy<bool> _supportsImageLoadFormatted = new(() => HasExtension("GL_EXT_shader_image_load_formatted"));
private static readonly Lazy<bool> _supportsIndirectParameters = new(() => HasExtension("GL_ARB_indirect_parameters"));
private static readonly Lazy<bool> _supportsParallelShaderCompile = new(() => HasExtension("GL_ARB_parallel_shader_compile"));
private static readonly Lazy<bool> _supportsPolygonOffsetClamp = new(() => HasExtension("GL_EXT_polygon_offset_clamp"));
private static readonly Lazy<bool> _supportsQuads = new(SupportsQuadsCheck);
private static readonly Lazy<bool> _supportsSeamlessCubemapPerTexture = new(() => HasExtension("GL_ARB_seamless_cubemap_per_texture"));
private static readonly Lazy<bool> _supportsShaderBallot = new(() => HasExtension("GL_ARB_shader_ballot"));
private static readonly Lazy<bool> _supportsShaderViewportLayerArray = new(() => HasExtension("GL_ARB_shader_viewport_layer_array"));
private static readonly Lazy<bool> _supportsViewportArray2 = new(() => HasExtension("GL_NV_viewport_array2"));
private static readonly Lazy<bool> _supportsTextureCompressionBptc = new(() => HasExtension("GL_EXT_texture_compression_bptc"));
private static readonly Lazy<bool> _supportsTextureCompressionRgtc = new(() => HasExtension("GL_EXT_texture_compression_rgtc"));
private static readonly Lazy<bool> _supportsTextureCompressionS3tc = new(() => HasExtension("GL_EXT_texture_compression_s3tc"));
private static readonly Lazy<bool> _supportsTextureShadowLod = new(() => HasExtension("GL_EXT_texture_shadow_lod"));
private static readonly Lazy<bool> _supportsViewportSwizzle = new(() => HasExtension("GL_NV_viewport_swizzle"));
private static readonly Lazy<int> _maximumComputeSharedMemorySize = new(() => GetLimit(All.MaxComputeSharedMemorySize));
private static readonly Lazy<int> _storageBufferOffsetAlignment = new(() => GetLimit(All.ShaderStorageBufferOffsetAlignment));
private static readonly Lazy<int> _textureBufferOffsetAlignment = new(() => GetLimit(All.TextureBufferOffsetAlignment));
public enum GpuVendor
{
Unknown,
AmdWindows,
AmdUnix,
IntelWindows,
IntelUnix,
Nvidia,
}
private static readonly Lazy<GpuVendor> _gpuVendor = new(GetGpuVendor);
private static bool IsIntel => _gpuVendor.Value == GpuVendor.IntelWindows || _gpuVendor.Value == GpuVendor.IntelUnix;
public static GpuVendor Vendor => _gpuVendor.Value;
private static readonly Lazy<float> _maxSupportedAnisotropy = new(GL.GetFloat((GetPName)All.MaxTextureMaxAnisotropy));
public static bool UsePersistentBufferForFlush => _gpuVendor.Value == GpuVendor.AmdWindows || _gpuVendor.Value == GpuVendor.Nvidia;
public static bool SupportsAlphaToCoverageDitherControl => _supportsAlphaToCoverageDitherControl.Value;
public static bool SupportsAstcCompression => _supportsAstcCompression.Value;
public static bool SupportsBlendEquationAdvanced => _supportsBlendEquationAdvanced.Value;
public static bool SupportsDrawTexture => _supportsDrawTexture.Value;
public static bool SupportsFragmentShaderInterlock => _supportsFragmentShaderInterlock.Value;
public static bool SupportsFragmentShaderOrdering => _supportsFragmentShaderOrdering.Value;
public static bool SupportsGeometryShaderPassthrough => _supportsGeometryShaderPassthrough.Value;
public static bool SupportsImageLoadFormatted => _supportsImageLoadFormatted.Value;
public static bool SupportsIndirectParameters => _supportsIndirectParameters.Value;
public static bool SupportsParallelShaderCompile => _supportsParallelShaderCompile.Value;
public static bool SupportsPolygonOffsetClamp => _supportsPolygonOffsetClamp.Value;
public static bool SupportsQuads => _supportsQuads.Value;
public static bool SupportsSeamlessCubemapPerTexture => _supportsSeamlessCubemapPerTexture.Value;
public static bool SupportsShaderBallot => _supportsShaderBallot.Value;
public static bool SupportsShaderViewportLayerArray => _supportsShaderViewportLayerArray.Value;
public static bool SupportsViewportArray2 => _supportsViewportArray2.Value;
public static bool SupportsTextureCompressionBptc => _supportsTextureCompressionBptc.Value;
public static bool SupportsTextureCompressionRgtc => _supportsTextureCompressionRgtc.Value;
public static bool SupportsTextureCompressionS3tc => _supportsTextureCompressionS3tc.Value;
public static bool SupportsTextureShadowLod => _supportsTextureShadowLod.Value;
public static bool SupportsViewportSwizzle => _supportsViewportSwizzle.Value;
public static bool SupportsMismatchingViewFormat => _gpuVendor.Value != GpuVendor.AmdWindows && _gpuVendor.Value != GpuVendor.IntelWindows;
public static bool SupportsNonConstantTextureOffset => _gpuVendor.Value == GpuVendor.Nvidia;
public static bool RequiresSyncFlush => _gpuVendor.Value == GpuVendor.AmdWindows || IsIntel;
public static int MaximumComputeSharedMemorySize => _maximumComputeSharedMemorySize.Value;
public static int StorageBufferOffsetAlignment => _storageBufferOffsetAlignment.Value;
public static int TextureBufferOffsetAlignment => _textureBufferOffsetAlignment.Value;
public static float MaximumSupportedAnisotropy => _maxSupportedAnisotropy.Value;
private static bool HasExtension(string name)
{
int numExtensions = GL.GetInteger(GetPName.NumExtensions);
for (int extension = 0; extension < numExtensions; extension++)
{
if (GL.GetString(StringNameIndexed.Extensions, extension) == name)
{
return true;
}
}
return false;
}
private static int GetLimit(All name)
{
return GL.GetInteger((GetPName)name);
}
private static GpuVendor GetGpuVendor()
{
string vendor = GL.GetString(StringName.Vendor).ToLowerInvariant();
if (vendor == "nvidia corporation")
{
return GpuVendor.Nvidia;
}
else if (vendor == "intel")
{
string renderer = GL.GetString(StringName.Renderer).ToLowerInvariant();
return renderer.Contains("mesa") ? GpuVendor.IntelUnix : GpuVendor.IntelWindows;
}
else if (vendor == "ati technologies inc." || vendor == "advanced micro devices, inc.")
{
return GpuVendor.AmdWindows;
}
else if (vendor == "amd" || vendor == "x.org")
{
return GpuVendor.AmdUnix;
}
else
{
return GpuVendor.Unknown;
}
}
private static bool SupportsQuadsCheck()
{
GL.GetError(); // Clear any existing error.
GL.Begin(PrimitiveType.Quads);
GL.End();
return GL.GetError() == ErrorCode.NoError;
}
}
}

View file

@ -1,4 +1,3 @@
using Ryujinx.Graphics.OpenGL.Helper;
using System;
namespace Ryujinx.Graphics.OpenGL

View file

@ -21,14 +21,14 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (Avx2.IsSupported)
{
var mask = Vector256.Create(
(byte)3, (byte)0, (byte)1, (byte)2,
(byte)7, (byte)4, (byte)5, (byte)6,
(byte)11, (byte)8, (byte)9, (byte)10,
(byte)15, (byte)12, (byte)13, (byte)14,
(byte)19, (byte)16, (byte)17, (byte)18,
(byte)23, (byte)20, (byte)21, (byte)22,
(byte)27, (byte)24, (byte)25, (byte)26,
(byte)31, (byte)28, (byte)29, (byte)30);
3, 0, 1, 2,
7, 4, 5, 6,
11, 8, 9, 10,
15, 12, 13, 14,
19, 16, 17, 18,
23, 20, 21, 22,
27, 24, 25, 26,
31, 28, 29, (byte)30);
int sizeAligned = data.Length & ~31;
@ -49,10 +49,10 @@ namespace Ryujinx.Graphics.OpenGL.Image
else if (Ssse3.IsSupported)
{
var mask = Vector128.Create(
(byte)3, (byte)0, (byte)1, (byte)2,
(byte)7, (byte)4, (byte)5, (byte)6,
(byte)11, (byte)8, (byte)9, (byte)10,
(byte)15, (byte)12, (byte)13, (byte)14);
3, 0, 1, 2,
7, 4, 5, 6,
11, 8, 9, 10,
15, 12, 13, (byte)14);
int sizeAligned = data.Length & ~15;
@ -90,14 +90,14 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (Avx2.IsSupported)
{
var mask = Vector256.Create(
(byte)1, (byte)2, (byte)3, (byte)0,
(byte)5, (byte)6, (byte)7, (byte)4,
(byte)9, (byte)10, (byte)11, (byte)8,
(byte)13, (byte)14, (byte)15, (byte)12,
(byte)17, (byte)18, (byte)19, (byte)16,
(byte)21, (byte)22, (byte)23, (byte)20,
(byte)25, (byte)26, (byte)27, (byte)24,
(byte)29, (byte)30, (byte)31, (byte)28);
1, 2, 3, 0,
5, 6, 7, 4,
9, 10, 11, 8,
13, 14, 15, 12,
17, 18, 19, 16,
21, 22, 23, 20,
25, 26, 27, 24,
29, 30, 31, (byte)28);
int sizeAligned = data.Length & ~31;
@ -118,10 +118,10 @@ namespace Ryujinx.Graphics.OpenGL.Image
else if (Ssse3.IsSupported)
{
var mask = Vector128.Create(
(byte)1, (byte)2, (byte)3, (byte)0,
(byte)5, (byte)6, (byte)7, (byte)4,
(byte)9, (byte)10, (byte)11, (byte)8,
(byte)13, (byte)14, (byte)15, (byte)12);
1, 2, 3, 0,
5, 6, 7, 4,
9, 10, 11, 8,
13, 14, 15, (byte)12);
int sizeAligned = data.Length & ~15;

View file

@ -5,9 +5,9 @@ namespace Ryujinx.Graphics.OpenGL.Image
interface ITextureInfo
{
ITextureInfo Storage { get; }
int Handle { get; }
int FirstLayer => 0;
int FirstLevel => 0;
uint Handle { get; }
uint FirstLayer => 0;
uint FirstLevel => 0;
TextureCreateInfo Info { get; }
}

View file

@ -1,6 +1,5 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.GAL;
using System;
using Silk.NET.OpenGL.Legacy;
namespace Ryujinx.Graphics.OpenGL.Image
{
@ -8,18 +7,20 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
private record struct TextureRef
{
public int Handle;
public uint Handle;
public Format Format;
}
private readonly TextureRef[] _images;
private readonly GL _api;
public ImageArray(int size)
public ImageArray(GL api, int size)
{
_api = api;
_images = new TextureRef[size];
}
public void SetFormats(int index, GAL.Format[] imageFormats)
public void SetFormats(int index, Format[] imageFormats)
{
for (int i = 0; i < imageFormats.Length; i++)
{
@ -44,21 +45,21 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
}
public void Bind(int baseBinding)
public void Bind(uint baseBinding)
{
for (int i = 0; i < _images.Length; i++)
{
if (_images[i].Handle == 0)
{
GL.BindImageTexture(baseBinding + i, 0, 0, true, 0, TextureAccess.ReadWrite, SizedInternalFormat.Rgba8);
_api.BindImageTexture((uint)(baseBinding + i), 0, 0, true, 0, BufferAccessARB.ReadWrite, InternalFormat.Rgba8);
}
else
{
SizedInternalFormat format = FormatTable.GetImageFormat(_images[i].Format);
InternalFormat format = (InternalFormat)FormatTable.GetImageFormat(_images[i].Format);
if (format != 0)
{
GL.BindImageTexture(baseBinding + i, _images[i].Handle, 0, true, 0, TextureAccess.ReadWrite, format);
_api.BindImageTexture((uint)(baseBinding + i), _images[i].Handle, 0, true, 0, BufferAccessARB.ReadWrite, format);
}
}
}

View file

@ -1,30 +1,32 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
namespace Ryujinx.Graphics.OpenGL.Image
{
class Sampler : ISampler
{
public int Handle { get; private set; }
public uint Handle { get; private set; }
private readonly OpenGLRenderer _gd;
public Sampler(SamplerCreateInfo info)
public Sampler(OpenGLRenderer gd, SamplerCreateInfo info)
{
Handle = GL.GenSampler();
_gd = gd;
Handle = _gd.Api.GenSampler();
GL.SamplerParameter(Handle, SamplerParameterName.TextureMinFilter, (int)info.MinFilter.Convert());
GL.SamplerParameter(Handle, SamplerParameterName.TextureMagFilter, (int)info.MagFilter.Convert());
_gd.Api.SamplerParameter(Handle, SamplerParameterI.MinFilter, (int)info.MinFilter.Convert());
_gd.Api.SamplerParameter(Handle, SamplerParameterI.MagFilter, (int)info.MagFilter.Convert());
if (HwCapabilities.SupportsSeamlessCubemapPerTexture)
if (_gd.Capabilities.SupportsSeamlessCubemapPerTexture)
{
GL.SamplerParameter(Handle, (SamplerParameterName)ArbSeamlessCubemapPerTexture.TextureCubeMapSeamless, info.SeamlessCubemap ? 1 : 0);
_gd.Api.SamplerParameter(Handle, GLEnum.TextureCubeMapSeamless, info.SeamlessCubemap ? 1 : 0);
}
GL.SamplerParameter(Handle, SamplerParameterName.TextureWrapS, (int)info.AddressU.Convert());
GL.SamplerParameter(Handle, SamplerParameterName.TextureWrapT, (int)info.AddressV.Convert());
GL.SamplerParameter(Handle, SamplerParameterName.TextureWrapR, (int)info.AddressP.Convert());
_gd.Api.SamplerParameter(Handle, SamplerParameterI.WrapS, (int)info.AddressU.Convert());
_gd.Api.SamplerParameter(Handle, SamplerParameterI.WrapT, (int)info.AddressV.Convert());
_gd.Api.SamplerParameter(Handle, SamplerParameterI.WrapR, (int)info.AddressP.Convert());
GL.SamplerParameter(Handle, SamplerParameterName.TextureCompareMode, (int)info.CompareMode.Convert());
GL.SamplerParameter(Handle, SamplerParameterName.TextureCompareFunc, (int)info.CompareOp.Convert());
_gd.Api.SamplerParameter(Handle, SamplerParameterI.CompareMode, (int)info.CompareMode.Convert());
_gd.Api.SamplerParameter(Handle, SamplerParameterI.CompareFunc, (int)info.CompareOp.Convert());
unsafe
{
@ -36,26 +38,26 @@ namespace Ryujinx.Graphics.OpenGL.Image
info.BorderColor.Alpha,
};
GL.SamplerParameter(Handle, SamplerParameterName.TextureBorderColor, borderColor);
_gd.Api.SamplerParameter(Handle, SamplerParameterF.BorderColor, borderColor);
}
GL.SamplerParameter(Handle, SamplerParameterName.TextureMinLod, info.MinLod);
GL.SamplerParameter(Handle, SamplerParameterName.TextureMaxLod, info.MaxLod);
GL.SamplerParameter(Handle, SamplerParameterName.TextureLodBias, info.MipLodBias);
_gd.Api.SamplerParameter(Handle, SamplerParameterF.MinLod, info.MinLod);
_gd.Api.SamplerParameter(Handle, SamplerParameterF.MaxLod, info.MaxLod);
_gd.Api.SamplerParameter(Handle, SamplerParameterF.LodBias, info.MipLodBias);
GL.SamplerParameter(Handle, SamplerParameterName.TextureMaxAnisotropyExt, info.MaxAnisotropy);
_gd.Api.SamplerParameter(Handle, SamplerParameterF.MaxAnisotropy, info.MaxAnisotropy);
}
public void Bind(int unit)
public void Bind(uint unit)
{
GL.BindSampler(unit, Handle);
_gd.Api.BindSampler(unit, Handle);
}
public void Dispose()
{
if (Handle != 0)
{
GL.DeleteSampler(Handle);
_gd.Api.DeleteSampler(Handle);
Handle = 0;
}

View file

@ -1,4 +1,5 @@
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
namespace Ryujinx.Graphics.OpenGL.Image
{
@ -11,9 +12,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
private readonly TextureRef[] _textureRefs;
private readonly GL _api;
public TextureArray(int size)
public TextureArray(GL api, int size)
{
_api = api;
_textureRefs = new TextureRef[size];
}
@ -33,9 +36,9 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
}
public void Bind(int baseBinding)
public void Bind(uint baseBinding)
{
for (int i = 0; i < _textureRefs.Length; i++)
for (uint i = 0; i < _textureRefs.Length; i++)
{
if (_textureRefs[i].Texture != null)
{
@ -44,7 +47,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
else
{
TextureBase.ClearBinding(baseBinding + i);
TextureBase.ClearBinding(_api, baseBinding + i);
}
}
}

View file

@ -1,11 +1,12 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
namespace Ryujinx.Graphics.OpenGL.Image
{
class TextureBase
{
public int Handle { get; protected set; }
private readonly protected OpenGLRenderer _gd;
public uint Handle { get; protected set; }
public TextureCreateInfo Info { get; }
@ -15,28 +16,29 @@ namespace Ryujinx.Graphics.OpenGL.Image
public Target Target => Info.Target;
public Format Format => Info.Format;
public TextureBase(TextureCreateInfo info)
public TextureBase(OpenGLRenderer gd, TextureCreateInfo info)
{
_gd = gd;
Info = info;
Handle = GL.GenTexture();
Handle = _gd.Api.GenTexture();
}
public void Bind(int unit)
public void Bind(uint unit)
{
Bind(Target.Convert(), unit);
}
protected void Bind(TextureTarget target, int unit)
protected void Bind(TextureTarget target, uint unit)
{
GL.ActiveTexture(TextureUnit.Texture0 + unit);
GL.BindTexture(target, Handle);
_gd.Api.ActiveTexture((TextureUnit)((uint)TextureUnit.Texture0 + unit));
_gd.Api.BindTexture(target, Handle);
}
public static void ClearBinding(int unit)
public static void ClearBinding(GL api, uint unit)
{
GL.ActiveTexture(TextureUnit.Texture0 + unit);
GL.BindTextureUnit(unit, 0);
api.ActiveTexture((TextureUnit)((uint)TextureUnit.Texture0 + unit));
api.BindTextureUnit(unit, 0);
}
}
}

View file

@ -1,5 +1,5 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
using System;
using System.Buffers;
@ -7,16 +7,15 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
class TextureBuffer : TextureBase, ITexture
{
private readonly OpenGLRenderer _renderer;
private int _bufferOffset;
private int _bufferSize;
private int _bufferCount;
private BufferHandle _buffer;
public TextureBuffer(OpenGLRenderer renderer, TextureCreateInfo info) : base(info)
public TextureBuffer(OpenGLRenderer gd, TextureCreateInfo info) : base(gd, info)
{
_renderer = renderer;
}
public void CopyTo(ITexture destination, int firstLayer, int firstLevel)
@ -41,7 +40,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
public PinnedSpan<byte> GetData()
{
return Buffer.GetData(_renderer, _buffer, _bufferOffset, _bufferSize);
return Buffer.GetData(_gd, _buffer, _bufferOffset, _bufferSize);
}
public PinnedSpan<byte> GetData(int layer, int level)
@ -59,7 +58,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
var dataSpan = data.Memory.Span;
Buffer.SetData(_buffer, _bufferOffset, dataSpan[..Math.Min(dataSpan.Length, _bufferSize)]);
Buffer.SetData(_gd.Api, _buffer, _bufferOffset, dataSpan[..Math.Min(dataSpan.Length, _bufferSize)]);
data.Dispose();
}
@ -82,7 +81,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
_buffer == buffer.Handle &&
buffer.Offset == _bufferOffset &&
buffer.Size == _bufferSize &&
_renderer.BufferCount == _bufferCount)
_gd.BufferCount == _bufferCount)
{
// Only rebind the buffer when more have been created.
return;
@ -91,20 +90,20 @@ namespace Ryujinx.Graphics.OpenGL.Image
_buffer = buffer.Handle;
_bufferOffset = buffer.Offset;
_bufferSize = buffer.Size;
_bufferCount = _renderer.BufferCount;
_bufferCount = _gd.BufferCount;
Bind(0);
SizedInternalFormat format = (SizedInternalFormat)FormatTable.GetFormatInfo(Info.Format).PixelInternalFormat;
SizedInternalFormat format = (SizedInternalFormat)FormatTable.GetFormatInfo(Info.Format).InternalFormat;
GL.TexBufferRange(TextureBufferTarget.TextureBuffer, format, _buffer.ToInt32(), (IntPtr)buffer.Offset, buffer.Size);
_gd.Api.TexBufferRange(TextureTarget.TextureBuffer, format, _buffer.ToUInt32(), buffer.Offset, (uint)buffer.Size);
}
public void Dispose()
{
if (Handle != 0)
{
GL.DeleteTexture(Handle);
_gd.Api.DeleteTexture(Handle);
Handle = 0;
}

View file

@ -1,26 +1,26 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Common;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
using System;
namespace Ryujinx.Graphics.OpenGL.Image
{
class TextureCopy : IDisposable
{
private readonly OpenGLRenderer _renderer;
private readonly OpenGLRenderer _gd;
private int _srcFramebuffer;
private int _dstFramebuffer;
private uint _srcFramebuffer;
private uint _dstFramebuffer;
private int _copyPboHandle;
private uint _copyPboHandle;
private int _copyPboSize;
public IntermediatePool IntermediatePool { get; }
public TextureCopy(OpenGLRenderer renderer)
public TextureCopy(OpenGLRenderer gd)
{
_renderer = renderer;
IntermediatePool = new IntermediatePool(renderer);
_gd = gd;
IntermediatePool = new IntermediatePool(gd);
}
public void Copy(
@ -55,10 +55,10 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
TextureView srcConverted = src.Format.IsBgr() != dst.Format.IsBgr() ? BgraSwap(src) : src;
(int oldDrawFramebufferHandle, int oldReadFramebufferHandle) = ((Pipeline)_renderer.Pipeline).GetBoundFramebuffers();
(uint oldDrawFramebufferHandle, uint oldReadFramebufferHandle) = ((Pipeline)_gd.Pipeline).GetBoundFramebuffers();
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, GetSrcFramebufferLazy());
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, GetDstFramebufferLazy());
_gd.Api.BindFramebuffer(FramebufferTarget.ReadFramebuffer, GetSrcFramebufferLazy());
_gd.Api.BindFramebuffer(FramebufferTarget.DrawFramebuffer, GetDstFramebufferLazy());
if (srcLevel != 0)
{
@ -76,13 +76,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
if ((srcLayer | dstLayer) != 0 || layers > 1)
{
Attach(FramebufferTarget.ReadFramebuffer, src.Format, srcConverted.Handle, srcLevel + level, srcLayer + layer);
Attach(FramebufferTarget.DrawFramebuffer, dst.Format, dst.Handle, dstLevel + level, dstLayer + layer);
Attach(_gd.Api, FramebufferTarget.ReadFramebuffer, src.Format, srcConverted.Handle, srcLevel + level, srcLayer + layer);
Attach(_gd.Api, FramebufferTarget.DrawFramebuffer, dst.Format, dst.Handle, dstLevel + level, dstLayer + layer);
}
else
{
Attach(FramebufferTarget.ReadFramebuffer, src.Format, srcConverted.Handle, srcLevel + level);
Attach(FramebufferTarget.DrawFramebuffer, dst.Format, dst.Handle, dstLevel + level);
Attach(_gd.Api, FramebufferTarget.ReadFramebuffer, src.Format, srcConverted.Handle, srcLevel + level);
Attach(_gd.Api, FramebufferTarget.DrawFramebuffer, dst.Format, dst.Handle, dstLevel + level);
}
ClearBufferMask mask = GetMask(src.Format);
@ -96,13 +96,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
? BlitFramebufferFilter.Linear
: BlitFramebufferFilter.Nearest;
GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
_gd.Api.ReadBuffer(ReadBufferMode.ColorAttachment0);
_gd.Api.DrawBuffer(DrawBufferMode.ColorAttachment0);
GL.Disable(EnableCap.RasterizerDiscard);
GL.Disable(IndexedEnableCap.ScissorTest, 0);
_gd.Api.Disable(EnableCap.RasterizerDiscard);
_gd.Api.Disable(EnableCap.ScissorTest, 0);
GL.BlitFramebuffer(
_gd.Api.BlitFramebuffer(
srcRegion.X1,
srcRegion.Y1,
srcRegion.X2,
@ -122,14 +122,14 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
}
Attach(FramebufferTarget.ReadFramebuffer, src.Format, 0);
Attach(FramebufferTarget.DrawFramebuffer, dst.Format, 0);
Attach(_gd.Api, FramebufferTarget.ReadFramebuffer, src.Format, 0);
Attach(_gd.Api, FramebufferTarget.DrawFramebuffer, dst.Format, 0);
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
_gd.Api.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
_gd.Api.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
((Pipeline)_renderer.Pipeline).RestoreScissor0Enable();
((Pipeline)_renderer.Pipeline).RestoreRasterizerDiscard();
((Pipeline)_gd.Pipeline).RestoreScissor0Enable();
((Pipeline)_gd.Pipeline).RestoreRasterizerDiscard();
if (srcConverted != src)
{
@ -178,8 +178,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
TextureCreateInfo srcInfo = src.Info;
TextureCreateInfo dstInfo = dst.Info;
int srcHandle = src.Handle;
int dstHandle = dst.Handle;
uint srcHandle = src.Handle;
uint dstHandle = dst.Handle;
int srcWidth = srcInfo.Width;
int srcHeight = srcInfo.Height;
@ -238,28 +238,28 @@ namespace Ryujinx.Graphics.OpenGL.Image
int copyWidth = sizeInBlocks ? BitUtils.DivRoundUp(width, blockWidth) : width;
int copyHeight = sizeInBlocks ? BitUtils.DivRoundUp(height, blockHeight) : height;
if (HwCapabilities.Vendor == HwCapabilities.GpuVendor.IntelWindows)
if (_gd.Capabilities.GpuVendor == GpuVendor.IntelWindows)
{
GL.CopyImageSubData(
_gd.Api.CopyImageSubData(
src.Storage.Handle,
src.Storage.Info.Target.ConvertToImageTarget(),
src.FirstLevel + srcLevel + level,
(int)src.FirstLevel + srcLevel + level,
0,
0,
src.FirstLayer + srcLayer,
(int)src.FirstLayer + srcLayer,
dst.Storage.Handle,
dst.Storage.Info.Target.ConvertToImageTarget(),
dst.FirstLevel + dstLevel + level,
(int)dst.FirstLevel + dstLevel + level,
0,
0,
dst.FirstLayer + dstLayer,
copyWidth,
copyHeight,
depth);
(int)dst.FirstLayer + dstLayer,
(uint)copyWidth,
(uint)copyHeight,
(uint)depth);
}
else
{
GL.CopyImageSubData(
_gd.Api.CopyImageSubData(
srcHandle,
srcInfo.Target.ConvertToImageTarget(),
srcLevel + level,
@ -272,9 +272,9 @@ namespace Ryujinx.Graphics.OpenGL.Image
0,
0,
dstLayer,
copyWidth,
copyHeight,
depth);
(uint)copyWidth,
(uint)copyHeight,
(uint)depth);
}
}
@ -308,18 +308,18 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
}
private static void Attach(FramebufferTarget target, Format format, int handle, int level = 0)
private static void Attach(GL api, FramebufferTarget target, Format format, uint handle, int level = 0)
{
FramebufferAttachment attachment = AttachmentForFormat(format);
GL.FramebufferTexture(target, attachment, handle, level);
api.FramebufferTexture(target, attachment, handle, level);
}
private static void Attach(FramebufferTarget target, Format format, int handle, int level, int layer)
private static void Attach(GL api, FramebufferTarget target, Format format, uint handle, int level, int layer)
{
FramebufferAttachment attachment = AttachmentForFormat(format);
GL.FramebufferTextureLayer(target, attachment, handle, level, layer);
api.FramebufferTextureLayer(target, attachment, handle, level, layer);
}
private static ClearBufferMask GetMask(Format format)
@ -344,20 +344,20 @@ namespace Ryujinx.Graphics.OpenGL.Image
public TextureView BgraSwap(TextureView from)
{
TextureView to = (TextureView)_renderer.CreateTexture(from.Info);
TextureView to = (TextureView)_gd.CreateTexture(from.Info);
EnsurePbo(from);
GL.BindBuffer(BufferTarget.PixelPackBuffer, _copyPboHandle);
_gd.Api.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyPboHandle);
from.WriteToPbo(0, forceBgra: true);
GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, _copyPboHandle);
_gd.Api.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
_gd.Api.BindBuffer(BufferTargetARB.PixelUnpackBuffer, _copyPboHandle);
to.ReadFromPbo(0, _copyPboSize);
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
_gd.Api.BindBuffer(BufferTargetARB.PixelUnpackBuffer, 0);
return to;
}
@ -393,7 +393,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
EnsurePbo(from);
GL.BindBuffer(BufferTarget.PixelPackBuffer, _copyPboHandle);
_gd.Api.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyPboHandle);
// The source texture is written out in full, then the destination is taken as a slice from the data using unpack params.
// The offset points to the base at which the requested layer is at.
@ -407,42 +407,42 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (slice)
{
// Set unpack parameters to take a slice of width/height:
GL.PixelStore(PixelStoreParameter.UnpackRowLength, unpackWidth);
GL.PixelStore(PixelStoreParameter.UnpackImageHeight, unpackHeight);
_gd.Api.PixelStore(PixelStoreParameter.UnpackRowLength, unpackWidth);
_gd.Api.PixelStore(PixelStoreParameter.UnpackImageHeight, unpackHeight);
if (to.Info.IsCompressed)
{
GL.PixelStore(PixelStoreParameter.UnpackCompressedBlockWidth, to.Info.BlockWidth);
GL.PixelStore(PixelStoreParameter.UnpackCompressedBlockHeight, to.Info.BlockHeight);
GL.PixelStore(PixelStoreParameter.UnpackCompressedBlockDepth, 1);
GL.PixelStore(PixelStoreParameter.UnpackCompressedBlockSize, to.Info.BytesPerPixel);
_gd.Api.PixelStore(GLEnum.UnpackCompressedBlockWidth, to.Info.BlockWidth);
_gd.Api.PixelStore(GLEnum.UnpackCompressedBlockHeight, to.Info.BlockHeight);
_gd.Api.PixelStore(GLEnum.UnpackCompressedBlockDepth, 1);
_gd.Api.PixelStore(GLEnum.UnpackCompressedBlockSize, to.Info.BytesPerPixel);
}
}
GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, _copyPboHandle);
_gd.Api.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
_gd.Api.BindBuffer(BufferTargetARB.PixelUnpackBuffer, _copyPboHandle);
to.ReadFromPbo2D(offset, dstLayer, dstLevel, dstWidth, dstHeight);
if (slice)
{
// Reset unpack parameters
GL.PixelStore(PixelStoreParameter.UnpackRowLength, 0);
GL.PixelStore(PixelStoreParameter.UnpackImageHeight, 0);
_gd.Api.PixelStore(PixelStoreParameter.UnpackRowLength, 0);
_gd.Api.PixelStore(PixelStoreParameter.UnpackImageHeight, 0);
if (to.Info.IsCompressed)
{
GL.PixelStore(PixelStoreParameter.UnpackCompressedBlockWidth, 0);
GL.PixelStore(PixelStoreParameter.UnpackCompressedBlockHeight, 0);
GL.PixelStore(PixelStoreParameter.UnpackCompressedBlockDepth, 0);
GL.PixelStore(PixelStoreParameter.UnpackCompressedBlockSize, 0);
_gd.Api.PixelStore(GLEnum.UnpackCompressedBlockWidth, 0);
_gd.Api.PixelStore(GLEnum.UnpackCompressedBlockHeight, 0);
_gd.Api.PixelStore(GLEnum.UnpackCompressedBlockDepth, 0);
_gd.Api.PixelStore(GLEnum.UnpackCompressedBlockSize, 0);
}
}
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
_gd.Api.BindBuffer(BufferTargetARB.PixelUnpackBuffer, 0);
}
private void EnsurePbo(TextureView view)
private unsafe void EnsurePbo(TextureView view)
{
int requiredSize = 0;
@ -453,36 +453,36 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (_copyPboSize < requiredSize && _copyPboHandle != 0)
{
GL.DeleteBuffer(_copyPboHandle);
_gd.Api.DeleteBuffer(_copyPboHandle);
_copyPboHandle = 0;
}
if (_copyPboHandle == 0)
{
_copyPboHandle = GL.GenBuffer();
_copyPboHandle = _gd.Api.GenBuffer();
_copyPboSize = requiredSize;
GL.BindBuffer(BufferTarget.PixelPackBuffer, _copyPboHandle);
GL.BufferData(BufferTarget.PixelPackBuffer, requiredSize, IntPtr.Zero, BufferUsageHint.DynamicCopy);
_gd.Api.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyPboHandle);
_gd.Api.BufferData(BufferTargetARB.PixelPackBuffer, (uint)requiredSize, null, BufferUsageARB.DynamicCopy);
}
}
private int GetSrcFramebufferLazy()
private uint GetSrcFramebufferLazy()
{
if (_srcFramebuffer == 0)
{
_srcFramebuffer = GL.GenFramebuffer();
_srcFramebuffer = _gd.Api.GenFramebuffer();
}
return _srcFramebuffer;
}
private int GetDstFramebufferLazy()
private uint GetDstFramebufferLazy()
{
if (_dstFramebuffer == 0)
{
_dstFramebuffer = GL.GenFramebuffer();
_dstFramebuffer = _gd.Api.GenFramebuffer();
}
return _dstFramebuffer;
@ -492,21 +492,21 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
if (_srcFramebuffer != 0)
{
GL.DeleteFramebuffer(_srcFramebuffer);
_gd.Api.DeleteFramebuffer(_srcFramebuffer);
_srcFramebuffer = 0;
}
if (_dstFramebuffer != 0)
{
GL.DeleteFramebuffer(_dstFramebuffer);
_gd.Api.DeleteFramebuffer(_dstFramebuffer);
_dstFramebuffer = 0;
}
if (_copyPboHandle != 0)
{
GL.DeleteBuffer(_copyPboHandle);
_gd.Api.DeleteBuffer(_copyPboHandle);
_copyPboHandle = 0;
}

View file

@ -1,4 +1,4 @@
using OpenTK.Graphics.OpenGL;
using Silk.NET.OpenGL.Legacy;
using System;
using System.Collections.Generic;
using System.Globalization;
@ -67,15 +67,15 @@ void main()
imageStore(dst, ivec2(coords), uvec4(r, g, b, a));
}";
private readonly OpenGLRenderer _renderer;
private readonly Dictionary<int, int> _shorteningProgramHandles;
private readonly Dictionary<int, int> _wideningProgramHandles;
private readonly OpenGLRenderer _gd;
private readonly Dictionary<int, uint> _shorteningProgramHandles;
private readonly Dictionary<int, uint> _wideningProgramHandles;
public TextureCopyIncompatible(OpenGLRenderer renderer)
public TextureCopyIncompatible(OpenGLRenderer gd)
{
_renderer = renderer;
_shorteningProgramHandles = new Dictionary<int, int>();
_wideningProgramHandles = new Dictionary<int, int>();
_gd = gd;
_shorteningProgramHandles = new Dictionary<int, uint>();
_wideningProgramHandles = new Dictionary<int, uint>();
}
public void CopyIncompatibleFormats(ITextureInfo src, ITextureInfo dst, int srcLayer, int dstLayer, int srcLevel, int dstLevel, int depth, int levels)
@ -91,10 +91,10 @@ void main()
int srcComponentsCount = srcBpp / componentSize;
int dstComponentsCount = dstBpp / componentSize;
var srcFormat = GetFormat(componentSize, srcComponentsCount);
var dstFormat = GetFormat(componentSize, dstComponentsCount);
var srcFormat = (InternalFormat)GetFormat(componentSize, srcComponentsCount);
var dstFormat = (InternalFormat)GetFormat(componentSize, dstComponentsCount);
GL.UseProgram(srcBpp < dstBpp
_gd.Api.UseProgram(srcBpp < dstBpp
? GetWideningShader(componentSize, srcComponentsCount, dstComponentsCount)
: GetShorteningShader(componentSize, srcComponentsCount, dstComponentsCount));
@ -106,19 +106,19 @@ void main()
int dstWidth = Math.Max(1, dst.Info.Width >> l);
int dstHeight = Math.Max(1, dst.Info.Height >> l);
int width = Math.Min(srcWidth, dstWidth);
int height = Math.Min(srcHeight, dstHeight);
uint width = (uint)Math.Min(srcWidth, dstWidth);
uint height = (uint)Math.Min(srcHeight, dstHeight);
for (int z = 0; z < depth; z++)
{
GL.BindImageTexture(0, src.Handle, srcLevel + l, false, srcLayer + z, TextureAccess.ReadOnly, srcFormat);
GL.BindImageTexture(1, dst.Handle, dstLevel + l, false, dstLayer + z, TextureAccess.WriteOnly, dstFormat);
_gd.Api.BindImageTexture(0, src.Handle, srcLevel + l, false, srcLayer + z, BufferAccessARB.ReadOnly, srcFormat);
_gd.Api.BindImageTexture(1, dst.Handle, dstLevel + l, false, dstLayer + z, BufferAccessARB.WriteOnly, dstFormat);
GL.DispatchCompute((width + 31) / 32, (height + 31) / 32, 1);
_gd.Api.DispatchCompute((width + 31) / 32, (height + 31) / 32, 1);
}
}
Pipeline pipeline = (Pipeline)_renderer.Pipeline;
Pipeline pipeline = (Pipeline)_gd.Pipeline;
pipeline.RestoreProgram();
pipeline.RestoreImages1And2();
@ -131,7 +131,7 @@ void main()
return componentsCount switch
{
1 => SizedInternalFormat.R8ui,
2 => SizedInternalFormat.Rg8ui,
2 => SizedInternalFormat.RG8ui,
4 => SizedInternalFormat.Rgba8ui,
_ => throw new ArgumentException($"Invalid components count {componentsCount}."),
};
@ -141,7 +141,7 @@ void main()
return componentsCount switch
{
1 => SizedInternalFormat.R16ui,
2 => SizedInternalFormat.Rg16ui,
2 => SizedInternalFormat.RG16ui,
4 => SizedInternalFormat.Rgba16ui,
_ => throw new ArgumentException($"Invalid components count {componentsCount}."),
};
@ -151,7 +151,7 @@ void main()
return componentsCount switch
{
1 => SizedInternalFormat.R32ui,
2 => SizedInternalFormat.Rg32ui,
2 => SizedInternalFormat.RG32ui,
4 => SizedInternalFormat.Rgba32ui,
_ => throw new ArgumentException($"Invalid components count {componentsCount}."),
};
@ -162,19 +162,19 @@ void main()
}
}
private int GetShorteningShader(int componentSize, int srcComponentsCount, int dstComponentsCount)
private uint GetShorteningShader(int componentSize, int srcComponentsCount, int dstComponentsCount)
{
return GetShader(ComputeShaderShortening, _shorteningProgramHandles, componentSize, srcComponentsCount, dstComponentsCount);
}
private int GetWideningShader(int componentSize, int srcComponentsCount, int dstComponentsCount)
private uint GetWideningShader(int componentSize, int srcComponentsCount, int dstComponentsCount)
{
return GetShader(ComputeShaderWidening, _wideningProgramHandles, componentSize, srcComponentsCount, dstComponentsCount);
}
private static int GetShader(
private uint GetShader(
string code,
Dictionary<int, int> programHandles,
Dictionary<int, uint> programHandles,
int componentSize,
int srcComponentsCount,
int dstComponentsCount)
@ -186,11 +186,11 @@ void main()
int key = srcIndex | (dstIndex << 8);
if (!programHandles.TryGetValue(key, out int programHandle))
if (!programHandles.TryGetValue(key, out uint programHandle))
{
int csHandle = GL.CreateShader(ShaderType.ComputeShader);
uint csHandle = _gd.Api.CreateShader(ShaderType.ComputeShader);
string[] formatTable = new[] { "r8ui", "r16ui", "r32ui", "rg8ui", "rg16ui", "rg32ui", "rgba8ui", "rgba16ui", "rgba32ui" };
string[] formatTable = ["r8ui", "r16ui", "r32ui", "rg8ui", "rg16ui", "rg32ui", "rgba8ui", "rgba16ui", "rgba32ui"];
string srcFormat = formatTable[srcIndex];
string dstFormat = formatTable[dstIndex];
@ -201,25 +201,25 @@ void main()
int ratio = srcBpp < dstBpp ? dstBpp / srcBpp : srcBpp / dstBpp;
int ratioLog2 = BitOperations.Log2((uint)ratio);
GL.ShaderSource(csHandle, code
_gd.Api.ShaderSource(csHandle, code
.Replace("$SRC_FORMAT$", srcFormat)
.Replace("$DST_FORMAT$", dstFormat)
.Replace("$RATIO_LOG2$", ratioLog2.ToString(CultureInfo.InvariantCulture)));
GL.CompileShader(csHandle);
_gd.Api.CompileShader(csHandle);
programHandle = GL.CreateProgram();
programHandle = _gd.Api.CreateProgram();
GL.AttachShader(programHandle, csHandle);
GL.LinkProgram(programHandle);
GL.DetachShader(programHandle, csHandle);
GL.DeleteShader(csHandle);
_gd.Api.AttachShader(programHandle, csHandle);
_gd.Api.LinkProgram(programHandle);
_gd.Api.DetachShader(programHandle, csHandle);
_gd.Api.DeleteShader(csHandle);
GL.GetProgram(programHandle, GetProgramParameterName.LinkStatus, out int status);
_gd.Api.GetProgram(programHandle, ProgramPropertyARB.LinkStatus, out int status);
if (status == 0)
{
throw new Exception(GL.GetProgramInfoLog(programHandle));
throw new Exception(_gd.Api.GetProgramInfoLog(programHandle));
}
programHandles.Add(key, programHandle);
@ -230,16 +230,16 @@ void main()
public void Dispose()
{
foreach (int handle in _shorteningProgramHandles.Values)
foreach (uint handle in _shorteningProgramHandles.Values)
{
GL.DeleteProgram(handle);
_gd.Api.DeleteProgram(handle);
}
_shorteningProgramHandles.Clear();
foreach (int handle in _wideningProgramHandles.Values)
foreach (uint handle in _wideningProgramHandles.Values)
{
GL.DeleteProgram(handle);
_gd.Api.DeleteProgram(handle);
}
_wideningProgramHandles.Clear();

View file

@ -1,5 +1,5 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
using System;
using System.Numerics;
@ -93,15 +93,15 @@ void main()
imageStore(imgOut, ivec2(int(coords.x) >> samplesInXLog2, int(coords.y) >> samplesInYLog2), sampleIdx, value);
}";
private readonly OpenGLRenderer _renderer;
private readonly int[] _msToNonMSProgramHandles;
private readonly int[] _nonMSToMSProgramHandles;
private readonly OpenGLRenderer _gd;
private readonly uint[] _msToNonMSProgramHandles;
private readonly uint[] _nonMSToMSProgramHandles;
public TextureCopyMS(OpenGLRenderer renderer)
public TextureCopyMS(OpenGLRenderer gd)
{
_renderer = renderer;
_msToNonMSProgramHandles = new int[5];
_nonMSToMSProgramHandles = new int[5];
_gd = gd;
_msToNonMSProgramHandles = new uint[5];
_nonMSToMSProgramHandles = new uint[5];
}
public void CopyMSToNonMS(ITextureInfo src, ITextureInfo dst, int srcLayer, int dstLayer, int depth)
@ -109,23 +109,23 @@ void main()
TextureCreateInfo srcInfo = src.Info;
TextureCreateInfo dstInfo = dst.Info;
int srcHandle = CreateViewIfNeeded(src);
int dstHandle = CreateViewIfNeeded(dst);
uint srcHandle = CreateViewIfNeeded(src);
uint dstHandle = CreateViewIfNeeded(dst);
int dstWidth = dstInfo.Width;
int dstHeight = dstInfo.Height;
uint dstWidth = (uint)dstInfo.Width;
uint dstHeight = (uint)dstInfo.Height;
GL.UseProgram(GetMSToNonMSShader(srcInfo.BytesPerPixel));
_gd.Api.UseProgram(GetMSToNonMSShader(srcInfo.BytesPerPixel));
for (int z = 0; z < depth; z++)
{
GL.BindImageTexture(0, srcHandle, 0, false, srcLayer + z, TextureAccess.ReadOnly, GetFormat(srcInfo.BytesPerPixel));
GL.BindImageTexture(1, dstHandle, 0, false, dstLayer + z, TextureAccess.WriteOnly, GetFormat(dstInfo.BytesPerPixel));
_gd.Api.BindImageTexture(0, srcHandle, 0, false, srcLayer + z, BufferAccessARB.ReadOnly, (InternalFormat)GetFormat(srcInfo.BytesPerPixel));
_gd.Api.BindImageTexture(1, dstHandle, 0, false, dstLayer + z, BufferAccessARB.WriteOnly, (InternalFormat)GetFormat(dstInfo.BytesPerPixel));
GL.DispatchCompute((dstWidth + 31) / 32, (dstHeight + 31) / 32, 1);
_gd.Api.DispatchCompute((dstWidth + 31) / 32, (dstHeight + 31) / 32, 1);
}
Pipeline pipeline = (Pipeline)_renderer.Pipeline;
Pipeline pipeline = (Pipeline)_gd.Pipeline;
pipeline.RestoreProgram();
pipeline.RestoreImages1And2();
@ -139,23 +139,23 @@ void main()
TextureCreateInfo srcInfo = src.Info;
TextureCreateInfo dstInfo = dst.Info;
int srcHandle = CreateViewIfNeeded(src);
int dstHandle = CreateViewIfNeeded(dst);
uint srcHandle = CreateViewIfNeeded(src);
uint dstHandle = CreateViewIfNeeded(dst);
int srcWidth = srcInfo.Width;
int srcHeight = srcInfo.Height;
uint srcWidth = (uint)srcInfo.Width;
uint srcHeight = (uint)srcInfo.Height;
GL.UseProgram(GetNonMSToMSShader(srcInfo.BytesPerPixel));
_gd.Api.UseProgram(GetNonMSToMSShader(srcInfo.BytesPerPixel));
for (int z = 0; z < depth; z++)
{
GL.BindImageTexture(0, srcHandle, 0, false, srcLayer + z, TextureAccess.ReadOnly, GetFormat(srcInfo.BytesPerPixel));
GL.BindImageTexture(1, dstHandle, 0, false, dstLayer + z, TextureAccess.WriteOnly, GetFormat(dstInfo.BytesPerPixel));
_gd.Api.BindImageTexture(0, srcHandle, 0, false, srcLayer + z, BufferAccessARB.ReadOnly, (InternalFormat)GetFormat(srcInfo.BytesPerPixel));
_gd.Api.BindImageTexture(1, dstHandle, 0, false, dstLayer + z, BufferAccessARB.WriteOnly, (InternalFormat)GetFormat(dstInfo.BytesPerPixel));
GL.DispatchCompute((srcWidth + 31) / 32, (srcHeight + 31) / 32, 1);
_gd.Api.DispatchCompute((srcWidth + 31) / 32, (srcHeight + 31) / 32, 1);
}
Pipeline pipeline = (Pipeline)_renderer.Pipeline;
Pipeline pipeline = (Pipeline)_gd.Pipeline;
pipeline.RestoreProgram();
pipeline.RestoreImages1And2();
@ -171,29 +171,29 @@ void main()
1 => SizedInternalFormat.R8ui,
2 => SizedInternalFormat.R16ui,
4 => SizedInternalFormat.R32ui,
8 => SizedInternalFormat.Rg32ui,
8 => SizedInternalFormat.RG32ui,
16 => SizedInternalFormat.Rgba32ui,
_ => throw new ArgumentException($"Invalid bytes per pixel {bytesPerPixel}."),
};
}
private static int CreateViewIfNeeded(ITextureInfo texture)
private uint CreateViewIfNeeded(ITextureInfo texture)
{
// Binding sRGB textures as images doesn't work on NVIDIA,
// we need to create and bind a RGBA view for it to work.
if (texture.Info.Format == Format.R8G8B8A8Srgb)
{
int handle = GL.GenTexture();
uint handle = _gd.Api.GenTexture();
GL.TextureView(
_gd.Api.TextureView(
handle,
texture.Info.Target.Convert(),
texture.Storage.Handle,
PixelInternalFormat.Rgba8,
SizedInternalFormat.Rgba8,
texture.FirstLevel,
1,
texture.FirstLayer,
texture.Info.GetLayers());
(uint)texture.Info.GetLayers());
return handle;
}
@ -201,49 +201,49 @@ void main()
return texture.Handle;
}
private static void DestroyViewIfNeeded(ITextureInfo info, int handle)
private void DestroyViewIfNeeded(ITextureInfo info, uint handle)
{
if (info.Handle != handle)
{
GL.DeleteTexture(handle);
_gd.Api.DeleteTexture(handle);
}
}
private int GetMSToNonMSShader(int bytesPerPixel)
private uint GetMSToNonMSShader(int bytesPerPixel)
{
return GetShader(ComputeShaderMSToNonMS, _msToNonMSProgramHandles, bytesPerPixel);
}
private int GetNonMSToMSShader(int bytesPerPixel)
private uint GetNonMSToMSShader(int bytesPerPixel)
{
return GetShader(ComputeShaderNonMSToMS, _nonMSToMSProgramHandles, bytesPerPixel);
}
private static int GetShader(string code, int[] programHandles, int bytesPerPixel)
private uint GetShader(string code, uint[] programHandles, int bytesPerPixel)
{
int index = BitOperations.Log2((uint)bytesPerPixel);
if (programHandles[index] == 0)
{
int csHandle = GL.CreateShader(ShaderType.ComputeShader);
uint csHandle = _gd.Api.CreateShader(ShaderType.ComputeShader);
string format = new[] { "r8ui", "r16ui", "r32ui", "rg32ui", "rgba32ui" }[index];
GL.ShaderSource(csHandle, code.Replace("$FORMAT$", format));
GL.CompileShader(csHandle);
_gd.Api.ShaderSource(csHandle, code.Replace("$FORMAT$", format));
_gd.Api.CompileShader(csHandle);
int programHandle = GL.CreateProgram();
uint programHandle = _gd.Api.CreateProgram();
GL.AttachShader(programHandle, csHandle);
GL.LinkProgram(programHandle);
GL.DetachShader(programHandle, csHandle);
GL.DeleteShader(csHandle);
_gd.Api.AttachShader(programHandle, csHandle);
_gd.Api.LinkProgram(programHandle);
_gd.Api.DetachShader(programHandle, csHandle);
_gd.Api.DeleteShader(csHandle);
GL.GetProgram(programHandle, GetProgramParameterName.LinkStatus, out int status);
_gd.Api.GetProgram(programHandle, ProgramPropertyARB.LinkStatus, out int status);
if (status == 0)
{
throw new Exception(GL.GetProgramInfoLog(programHandle));
throw new Exception(_gd.Api.GetProgramInfoLog(programHandle));
}
programHandles[index] = programHandle;
@ -258,7 +258,7 @@ void main()
{
if (_msToNonMSProgramHandles[i] != 0)
{
GL.DeleteProgram(_msToNonMSProgramHandles[i]);
_gd.Api.DeleteProgram(_msToNonMSProgramHandles[i]);
_msToNonMSProgramHandles[i] = 0;
}
}
@ -267,7 +267,7 @@ void main()
{
if (_nonMSToMSProgramHandles[i] != 0)
{
GL.DeleteProgram(_nonMSToMSProgramHandles[i]);
_gd.Api.DeleteProgram(_nonMSToMSProgramHandles[i]);
_nonMSToMSProgramHandles[i] = 0;
}
}

View file

@ -1,28 +1,28 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
namespace Ryujinx.Graphics.OpenGL.Image
{
class TextureStorage : ITextureInfo
{
public ITextureInfo Storage => this;
public int Handle { get; private set; }
public uint Handle { get; private set; }
public TextureCreateInfo Info { get; }
private readonly OpenGLRenderer _renderer;
private readonly OpenGLRenderer _gd;
private int _viewsCount;
internal ITexture DefaultView { get; private set; }
public TextureStorage(OpenGLRenderer renderer, TextureCreateInfo info)
public TextureStorage(OpenGLRenderer gd, TextureCreateInfo info)
{
_renderer = renderer;
_gd = gd;
Info = info;
Handle = GL.GenTexture();
Handle = _gd.Api.GenTexture();
CreateImmutableStorage();
}
@ -31,9 +31,9 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
TextureTarget target = Info.Target.Convert();
GL.ActiveTexture(TextureUnit.Texture0);
_gd.Api.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(target, Handle);
_gd.Api.BindTexture(target, Handle);
FormatInfo format = FormatTable.GetFormatInfo(Info.Format);
@ -45,97 +45,97 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
else
{
internalFormat = (SizedInternalFormat)format.PixelInternalFormat;
internalFormat = (SizedInternalFormat)format.InternalFormat;
}
int levels = Info.GetLevelsClamped();
uint levels = (uint)Info.GetLevelsClamped();
switch (Info.Target)
{
case Target.Texture1D:
GL.TexStorage1D(
TextureTarget1d.Texture1D,
_gd.Api.TexStorage1D(
TextureTarget.Texture1D,
levels,
internalFormat,
Info.Width);
(uint)Info.Width);
break;
case Target.Texture1DArray:
GL.TexStorage2D(
TextureTarget2d.Texture1DArray,
_gd.Api.TexStorage2D(
TextureTarget.Texture1DArray,
levels,
internalFormat,
Info.Width,
Info.Height);
(uint)Info.Width,
(uint)Info.Height);
break;
case Target.Texture2D:
GL.TexStorage2D(
TextureTarget2d.Texture2D,
_gd.Api.TexStorage2D(
TextureTarget.Texture2D,
levels,
internalFormat,
Info.Width,
Info.Height);
(uint)Info.Width,
(uint)Info.Height);
break;
case Target.Texture2DArray:
GL.TexStorage3D(
TextureTarget3d.Texture2DArray,
_gd.Api.TexStorage3D(
TextureTarget.Texture2DArray,
levels,
internalFormat,
Info.Width,
Info.Height,
Info.Depth);
(uint)Info.Width,
(uint)Info.Height,
(uint)Info.Depth);
break;
case Target.Texture2DMultisample:
GL.TexStorage2DMultisample(
TextureTargetMultisample2d.Texture2DMultisample,
Info.Samples,
_gd.Api.TexStorage2DMultisample(
TextureTarget.Texture2DMultisample,
(uint)Info.Samples,
internalFormat,
Info.Width,
Info.Height,
(uint)Info.Width,
(uint)Info.Height,
true);
break;
case Target.Texture2DMultisampleArray:
GL.TexStorage3DMultisample(
TextureTargetMultisample3d.Texture2DMultisampleArray,
Info.Samples,
_gd.Api.TexStorage3DMultisample(
TextureTarget.Texture2DMultisampleArray,
(uint)Info.Samples,
internalFormat,
Info.Width,
Info.Height,
Info.Depth,
(uint)Info.Width,
(uint)Info.Height,
(uint)Info.Depth,
true);
break;
case Target.Texture3D:
GL.TexStorage3D(
TextureTarget3d.Texture3D,
_gd.Api.TexStorage3D(
TextureTarget.Texture3D,
levels,
internalFormat,
Info.Width,
Info.Height,
Info.Depth);
(uint)Info.Width,
(uint)Info.Height,
(uint)Info.Depth);
break;
case Target.Cubemap:
GL.TexStorage2D(
TextureTarget2d.TextureCubeMap,
_gd.Api.TexStorage2D(
TextureTarget.TextureCubeMap,
levels,
internalFormat,
Info.Width,
Info.Height);
(uint)Info.Width,
(uint)Info.Height);
break;
case Target.CubemapArray:
GL.TexStorage3D(
(TextureTarget3d)All.TextureCubeMapArray,
_gd.Api.TexStorage3D(
TextureTarget.TextureCubeMapArray,
levels,
internalFormat,
Info.Width,
Info.Height,
Info.Depth);
(uint)Info.Width,
(uint)Info.Height,
(uint)Info.Depth);
break;
default:
@ -151,11 +151,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
return DefaultView;
}
public ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel)
public ITexture CreateView(TextureCreateInfo info, uint firstLayer, uint firstLevel)
{
IncrementViewsCount();
return new TextureView(_renderer, this, info, firstLayer, firstLevel);
return new TextureView(_gd, this, info, firstLayer, firstLevel);
}
private void IncrementViewsCount()
@ -187,7 +187,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
_viewsCount = 1; // When we are used again, we will have the default view.
_renderer.ResourcePool.AddTexture((TextureView)DefaultView);
_gd.ResourcePool.AddTexture((TextureView)DefaultView);
}
public void DeleteDefault()
@ -201,7 +201,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (Handle != 0)
{
GL.DeleteTexture(Handle);
_gd.Api.DeleteTexture(Handle);
Handle = 0;
}

View file

@ -1,6 +1,6 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Common;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
using System;
using System.Buffers;
using System.Diagnostics;
@ -9,23 +9,20 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
class TextureView : TextureBase, ITexture, ITextureInfo
{
private readonly OpenGLRenderer _renderer;
private readonly TextureStorage _parent;
public ITextureInfo Storage => _parent;
public int FirstLayer { get; private set; }
public int FirstLevel { get; private set; }
public uint FirstLayer { get; private set; }
public uint FirstLevel { get; private set; }
public TextureView(
OpenGLRenderer renderer,
OpenGLRenderer gd,
TextureStorage parent,
TextureCreateInfo info,
int firstLayer,
int firstLevel) : base(info)
uint firstLayer,
uint firstLevel) : base(gd, info)
{
_renderer = renderer;
_parent = parent;
FirstLayer = firstLayer;
@ -40,20 +37,20 @@ namespace Ryujinx.Graphics.OpenGL.Image
FormatInfo format = FormatTable.GetFormatInfo(Info.Format);
PixelInternalFormat pixelInternalFormat;
SizedInternalFormat pixelInternalFormat;
if (format.IsCompressed)
{
pixelInternalFormat = (PixelInternalFormat)format.PixelFormat;
pixelInternalFormat = (SizedInternalFormat)format.PixelFormat;
}
else
{
pixelInternalFormat = format.PixelInternalFormat;
pixelInternalFormat = (SizedInternalFormat)format.InternalFormat;
}
int levels = Info.GetLevelsClamped();
uint levels = (uint)Info.GetLevelsClamped();
GL.TextureView(
_gd.Api.TextureView(
Handle,
target,
_parent.Handle,
@ -61,19 +58,19 @@ namespace Ryujinx.Graphics.OpenGL.Image
FirstLevel,
levels,
FirstLayer,
Info.GetLayers());
(uint)Info.GetLayers());
GL.ActiveTexture(TextureUnit.Texture0);
_gd.Api.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(target, Handle);
_gd.Api.BindTexture(target, Handle);
int[] swizzleRgba = new int[]
{
int[] swizzleRgba =
[
(int)Info.SwizzleR.Convert(),
(int)Info.SwizzleG.Convert(),
(int)Info.SwizzleB.Convert(),
(int)Info.SwizzleA.Convert(),
};
(int)Info.SwizzleA.Convert()
];
if (Info.Format == Format.A1B5G5R5Unorm)
{
@ -91,25 +88,25 @@ namespace Ryujinx.Graphics.OpenGL.Image
(swizzleRgba[2], swizzleRgba[0]) = (swizzleRgba[0], swizzleRgba[2]);
}
GL.TexParameter(target, TextureParameterName.TextureSwizzleRgba, swizzleRgba);
_gd.Api.TexParameter(target, TextureParameterName.TextureSwizzleRgba, swizzleRgba);
int maxLevel = levels - 1;
uint maxLevel = levels - 1;
if (maxLevel < 0)
{
maxLevel = 0;
}
GL.TexParameter(target, TextureParameterName.TextureMaxLevel, maxLevel);
GL.TexParameter(target, TextureParameterName.DepthStencilTextureMode, (int)Info.DepthStencilMode.Convert());
_gd.Api.TexParameter(target, TextureParameterName.TextureMaxLevel, maxLevel);
_gd.Api.TexParameter(target, TextureParameterName.DepthStencilTextureMode, (int)Info.DepthStencilMode.Convert());
}
public ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel)
{
firstLayer += FirstLayer;
firstLevel += FirstLevel;
firstLayer += (int)FirstLayer;
firstLevel += (int)FirstLevel;
return _parent.CreateView(info, firstLayer, firstLevel);
return _parent.CreateView(info, (uint)firstLayer, (uint)firstLevel);
}
public void CopyTo(ITexture destination, int firstLayer, int firstLevel)
@ -121,24 +118,24 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (dstIsMultisample != srcIsMultisample && Info.Format.IsDepthOrStencil())
{
int layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
uint layers = (uint)Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
CopyWithBlitForDepthMS(destinationView, 0, firstLayer, layers);
}
else if (!dstIsMultisample && srcIsMultisample)
{
int layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
_renderer.TextureCopyMS.CopyMSToNonMS(this, destinationView, 0, firstLayer, layers);
uint layers = (uint)Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
_gd.TextureCopyMS.CopyMSToNonMS(this, destinationView, 0, firstLayer, (int)layers);
}
else if (dstIsMultisample && !srcIsMultisample)
{
int layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
_renderer.TextureCopyMS.CopyNonMSToMS(this, destinationView, 0, firstLayer, layers);
uint layers = (uint)Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
_gd.TextureCopyMS.CopyNonMSToMS(this, destinationView, 0, firstLayer, (int)layers);
}
else if (destinationView.Info.BytesPerPixel != Info.BytesPerPixel)
{
int layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
int levels = Math.Min(Info.Levels, destinationView.Info.Levels - firstLevel);
_renderer.TextureCopyIncompatible.CopyIncompatibleFormats(this, destinationView, 0, firstLayer, 0, firstLevel, layers, levels);
_gd.TextureCopyIncompatible.CopyIncompatibleFormats(this, destinationView, 0, firstLayer, 0, firstLevel, layers, levels);
}
else if (destinationView.Format.IsDepthOrStencil() != Format.IsDepthOrStencil())
{
@ -158,13 +155,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
for (int layer = 0; layer < layers; layer++)
{
_renderer.TextureCopy.PboCopy(this, destinationView, 0, firstLayer + layer, 0, firstLevel + level, minWidth, minHeight);
_gd.TextureCopy.PboCopy(this, destinationView, 0, firstLayer + layer, 0, firstLevel + level, minWidth, minHeight);
}
}
}
else
{
_renderer.TextureCopy.CopyUnscaled(this, destinationView, 0, firstLayer, 0, firstLevel);
_gd.TextureCopy.CopyUnscaled(this, destinationView, 0, firstLayer, 0, firstLevel);
}
}
@ -181,30 +178,30 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
else if (!dstIsMultisample && srcIsMultisample)
{
_renderer.TextureCopyMS.CopyMSToNonMS(this, destinationView, srcLayer, dstLayer, 1);
_gd.TextureCopyMS.CopyMSToNonMS(this, destinationView, srcLayer, dstLayer, 1);
}
else if (dstIsMultisample && !srcIsMultisample)
{
_renderer.TextureCopyMS.CopyNonMSToMS(this, destinationView, srcLayer, dstLayer, 1);
_gd.TextureCopyMS.CopyNonMSToMS(this, destinationView, srcLayer, dstLayer, 1);
}
else if (destinationView.Info.BytesPerPixel != Info.BytesPerPixel)
{
_renderer.TextureCopyIncompatible.CopyIncompatibleFormats(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
_gd.TextureCopyIncompatible.CopyIncompatibleFormats(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
}
else if (destinationView.Format.IsDepthOrStencil() != Format.IsDepthOrStencil())
{
int minWidth = Math.Min(Width, destinationView.Width);
int minHeight = Math.Min(Height, destinationView.Height);
_renderer.TextureCopy.PboCopy(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, minWidth, minHeight);
_gd.TextureCopy.PboCopy(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, minWidth, minHeight);
}
else
{
_renderer.TextureCopy.CopyUnscaled(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
_gd.TextureCopy.CopyUnscaled(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
}
}
private void CopyWithBlitForDepthMS(TextureView destinationView, int srcLayer, int dstLayer, int layers)
private void CopyWithBlitForDepthMS(TextureView destinationView, int srcLayer, int dstLayer, uint layers)
{
// This is currently used for multisample <-> non-multisample copies.
// We can't do that with compute because it's not possible to write depth textures on compute.
@ -218,7 +215,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (destinationView.Target.IsMultisample())
{
TextureView intermmediate = _renderer.TextureCopy.IntermediatePool.GetOrCreateWithAtLeast(
TextureView intermmediate = _gd.TextureCopy.IntermediatePool.GetOrCreateWithAtLeast(
Info.Target,
Info.BlockWidth,
Info.BlockHeight,
@ -230,8 +227,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
1,
1);
_renderer.TextureCopy.Copy(this, intermmediate, srcRegion, dstRegion, false);
_renderer.TextureCopy.Copy(intermmediate, destinationView, dstRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, layers, 1);
_gd.TextureCopy.Copy(this, intermmediate, srcRegion, dstRegion, false);
_gd.TextureCopy.Copy(intermmediate, destinationView, dstRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, (int)layers, 1);
}
else
{
@ -242,7 +239,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
_ => Target,
};
TextureView intermmediate = _renderer.TextureCopy.IntermediatePool.GetOrCreateWithAtLeast(
TextureView intermmediate = _gd.TextureCopy.IntermediatePool.GetOrCreateWithAtLeast(
target,
Info.BlockWidth,
Info.BlockHeight,
@ -254,14 +251,14 @@ namespace Ryujinx.Graphics.OpenGL.Image
1,
1);
_renderer.TextureCopy.Copy(this, intermmediate, srcRegion, srcRegion, false);
_renderer.TextureCopy.Copy(intermmediate, destinationView, srcRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, layers, 1);
_gd.TextureCopy.Copy(this, intermmediate, srcRegion, srcRegion, false);
_gd.TextureCopy.Copy(intermmediate, destinationView, srcRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, (int)layers, 1);
}
}
public void CopyTo(ITexture destination, Extents2D srcRegion, Extents2D dstRegion, bool linearFilter)
{
_renderer.TextureCopy.Copy(this, (TextureView)destination, srcRegion, dstRegion, linearFilter);
_gd.TextureCopy.Copy(this, (TextureView)destination, srcRegion, dstRegion, linearFilter);
}
public unsafe PinnedSpan<byte> GetData()
@ -276,13 +273,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
ReadOnlySpan<byte> data;
if (HwCapabilities.UsePersistentBufferForFlush)
if (_gd.Capabilities.UsePersistentBufferForFlush)
{
data = _renderer.PersistentBuffers.Default.GetTextureData(this, size);
data = _gd.PersistentBuffers.Default.GetTextureData(this, size);
}
else
{
IntPtr target = _renderer.PersistentBuffers.Default.GetHostArray(size);
IntPtr target = _gd.PersistentBuffers.Default.GetHostArray(size);
WriteTo(target);
@ -301,13 +298,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
int size = Info.GetMipSize(level);
if (HwCapabilities.UsePersistentBufferForFlush)
if (_gd.Capabilities.UsePersistentBufferForFlush)
{
return PinnedSpan<byte>.UnsafeFromSpan(_renderer.PersistentBuffers.Default.GetTextureData(this, size, layer, level));
return PinnedSpan<byte>.UnsafeFromSpan(_gd.PersistentBuffers.Default.GetTextureData(this, size, layer, level));
}
else
{
IntPtr target = _renderer.PersistentBuffers.Default.GetHostArray(size);
IntPtr target = _gd.PersistentBuffers.Default.GetHostArray(size);
int offset = WriteTo2D(target, layer, level);
@ -322,7 +319,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
throw new NotSupportedException("Stride conversion for texture copy to buffer not supported.");
}
GL.BindBuffer(BufferTarget.PixelPackBuffer, range.Handle.ToInt32());
_gd.Api.BindBuffer(BufferTargetARB.PixelPackBuffer, range.Handle.ToUInt32());
FormatInfo format = FormatTable.GetFormatInfo(Info.Format);
if (format.PixelFormat == PixelFormat.DepthStencil)
@ -334,7 +331,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
Debug.Assert(offset == 0);
GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);
_gd.Api.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
}
public void WriteToPbo(int offset, bool forceBgra)
@ -347,7 +344,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
return WriteTo2D(IntPtr.Zero + offset, layer, level);
}
private int WriteTo2D(IntPtr data, int layer, int level)
private unsafe int WriteTo2D(IntPtr data, int layer, int level)
{
TextureTarget target = Target.Convert();
@ -367,15 +364,37 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (format.IsCompressed)
{
GL.GetCompressedTextureSubImage(Handle, level, 0, 0, layer, Math.Max(1, Info.Width >> level), Math.Max(1, Info.Height >> level), 1, mipSize, data);
_gd.Api.GetCompressedTextureSubImage(
Handle,
level,
0,
0,
layer,
(uint)Math.Max(1, Info.Width >> level),
(uint)Math.Max(1, Info.Height >> level),
1,
(uint)mipSize,
(void*)data);
}
else if (format.PixelFormat != PixelFormat.DepthStencil)
{
GL.GetTextureSubImage(Handle, level, 0, 0, layer, Math.Max(1, Info.Width >> level), Math.Max(1, Info.Height >> level), 1, pixelFormat, pixelType, mipSize, data);
_gd.Api.GetTextureSubImage(
Handle,
level,
0,
0,
layer,
(uint)Math.Max(1, Info.Width >> level),
(uint)Math.Max(1, Info.Height >> level),
1,
pixelFormat,
pixelType,
(uint)mipSize,
(void*)data);
}
else
{
GL.GetTexImage(target, level, pixelFormat, pixelType, data);
_gd.Api.GetTexImage(target, level, pixelFormat, pixelType, (void*)data);
// The GL function returns all layers. Must return the offset of the layer we're interested in.
return target switch
@ -390,7 +409,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
return 0;
}
private void WriteTo(IntPtr data, bool forceBgra = false)
private unsafe void WriteTo(IntPtr data, bool forceBgra = false)
{
TextureTarget target = Target.Convert();
@ -405,9 +424,9 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
if (pixelType == PixelType.UnsignedShort565)
{
pixelType = PixelType.UnsignedShort565Reversed;
pixelType = PixelType.UnsignedShort565Rev;
}
else if (pixelType == PixelType.UnsignedShort565Reversed)
else if (pixelType == PixelType.UnsignedShort565Rev)
{
pixelType = PixelType.UnsignedShort565;
}
@ -436,11 +455,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (format.IsCompressed)
{
GL.GetCompressedTexImage(target + face, level, data + faceOffset);
_gd.Api.GetCompressedTexImage(target + face, level, (void*)(data + faceOffset));
}
else
{
GL.GetTexImage(target + face, level, pixelFormat, pixelType, data + faceOffset);
_gd.Api.GetTexImage(target + face, level, pixelFormat, pixelType, (void*)(data + faceOffset));
}
}
@ -535,7 +554,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
return data;
}
private void ReadFrom2D(IntPtr data, int layer, int level, int x, int y, int width, int height, int mipSize)
private unsafe void ReadFrom2D(IntPtr data, int layer, int level, int x, int y, int width, int height, int mipSize)
{
TextureTarget target = Target.Convert();
@ -548,83 +567,83 @@ namespace Ryujinx.Graphics.OpenGL.Image
case Target.Texture1D:
if (format.IsCompressed)
{
GL.CompressedTexSubImage1D(
_gd.Api.CompressedTexSubImage1D(
target,
level,
x,
width,
format.PixelFormat,
mipSize,
data);
(uint)width,
(InternalFormat)format.PixelFormat,
(uint)mipSize,
(void*)data);
}
else
{
GL.TexSubImage1D(
_gd.Api.TexSubImage1D(
target,
level,
x,
width,
(uint)width,
format.PixelFormat,
format.PixelType,
data);
(void*)data);
}
break;
case Target.Texture1DArray:
if (format.IsCompressed)
{
GL.CompressedTexSubImage2D(
_gd.Api.CompressedTexSubImage2D(
target,
level,
x,
layer,
width,
(uint)width,
1,
format.PixelFormat,
mipSize,
data);
(InternalFormat)format.PixelFormat,
(uint)mipSize,
(void*)data);
}
else
{
GL.TexSubImage2D(
_gd.Api.TexSubImage2D(
target,
level,
x,
layer,
width,
(uint)width,
1,
format.PixelFormat,
format.PixelType,
data);
(void*)data);
}
break;
case Target.Texture2D:
if (format.IsCompressed)
{
GL.CompressedTexSubImage2D(
_gd.Api.CompressedTexSubImage2D(
target,
level,
x,
y,
width,
height,
format.PixelFormat,
mipSize,
data);
(uint)width,
(uint)height,
(InternalFormat)format.PixelFormat,
(uint)mipSize,
(void*)data);
}
else
{
GL.TexSubImage2D(
_gd.Api.TexSubImage2D(
target,
level,
x,
y,
width,
height,
(uint)width,
(uint)height,
format.PixelFormat,
format.PixelType,
data);
(void*)data);
}
break;
@ -633,77 +652,77 @@ namespace Ryujinx.Graphics.OpenGL.Image
case Target.CubemapArray:
if (format.IsCompressed)
{
GL.CompressedTexSubImage3D(
_gd.Api.CompressedTexSubImage3D(
target,
level,
x,
y,
layer,
width,
height,
(uint)width,
(uint)height,
1,
format.PixelFormat,
mipSize,
data);
(InternalFormat)format.PixelFormat,
(uint)mipSize,
(void*)data);
}
else
{
GL.TexSubImage3D(
_gd.Api.TexSubImage3D(
target,
level,
x,
y,
layer,
width,
height,
(uint)width,
(uint)height,
1,
format.PixelFormat,
format.PixelType,
data);
(void*)data);
}
break;
case Target.Cubemap:
if (format.IsCompressed)
{
GL.CompressedTexSubImage2D(
_gd.Api.CompressedTexSubImage2D(
TextureTarget.TextureCubeMapPositiveX + layer,
level,
x,
y,
width,
height,
format.PixelFormat,
mipSize,
data);
(uint)width,
(uint)height,
(InternalFormat)format.PixelFormat,
(uint)mipSize,
(void*)data);
}
else
{
GL.TexSubImage2D(
_gd.Api.TexSubImage2D(
TextureTarget.TextureCubeMapPositiveX + layer,
level,
x,
y,
width,
height,
(uint)width,
(uint)height,
format.PixelFormat,
format.PixelType,
data);
(void*)data);
}
break;
}
}
private void ReadFrom(IntPtr data, int size)
private unsafe void ReadFrom(IntPtr data, int size)
{
TextureTarget target = Target.Convert();
int baseLevel = 0;
uint baseLevel = 0;
// glTexSubImage on cubemap views is broken on Intel, we have to use the storage instead.
if (Target == Target.Cubemap && HwCapabilities.Vendor == HwCapabilities.GpuVendor.IntelWindows)
if (Target == Target.Cubemap && _gd.Capabilities.GpuVendor == GpuVendor.IntelWindows)
{
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(target, Storage.Handle);
_gd.Api.ActiveTexture(TextureUnit.Texture0);
_gd.Api.BindTexture(target, Storage.Handle);
baseLevel = FirstLevel;
}
else
@ -713,9 +732,9 @@ namespace Ryujinx.Graphics.OpenGL.Image
FormatInfo format = FormatTable.GetFormatInfo(Info.Format);
int width = Info.Width;
int height = Info.Height;
int depth = Info.Depth;
uint width = (uint)Info.Width;
uint height = (uint)Info.Height;
uint depth = (uint)Info.Depth;
int levels = Info.GetLevelsClamped();
int offset = 0;
@ -736,25 +755,25 @@ namespace Ryujinx.Graphics.OpenGL.Image
case Target.Texture1D:
if (format.IsCompressed)
{
GL.CompressedTexSubImage1D(
_gd.Api.CompressedTexSubImage1D(
target,
level,
0,
width,
format.PixelFormat,
mipSize,
data);
(InternalFormat)format.PixelFormat,
(uint)mipSize,
(void*)data);
}
else
{
GL.TexSubImage1D(
_gd.Api.TexSubImage1D(
target,
level,
0,
width,
format.PixelFormat,
format.PixelType,
data);
(void*)data);
}
break;
@ -762,20 +781,20 @@ namespace Ryujinx.Graphics.OpenGL.Image
case Target.Texture2D:
if (format.IsCompressed)
{
GL.CompressedTexSubImage2D(
_gd.Api.CompressedTexSubImage2D(
target,
level,
0,
0,
width,
height,
format.PixelFormat,
mipSize,
data);
(InternalFormat)format.PixelFormat,
(uint)mipSize,
(void*)data);
}
else
{
GL.TexSubImage2D(
_gd.Api.TexSubImage2D(
target,
level,
0,
@ -784,7 +803,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
height,
format.PixelFormat,
format.PixelType,
data);
(void*)data);
}
break;
@ -793,7 +812,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
case Target.CubemapArray:
if (format.IsCompressed)
{
GL.CompressedTexSubImage3D(
_gd.Api.CompressedTexSubImage3D(
target,
level,
0,
@ -802,13 +821,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
width,
height,
depth,
format.PixelFormat,
mipSize,
data);
(InternalFormat)format.PixelFormat,
(uint)mipSize,
(void*)data);
}
else
{
GL.TexSubImage3D(
_gd.Api.TexSubImage3D(
target,
level,
0,
@ -819,7 +838,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
depth,
format.PixelFormat,
format.PixelType,
data);
(void*)data);
}
break;
@ -830,29 +849,29 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
if (format.IsCompressed)
{
GL.CompressedTexSubImage2D(
_gd.Api.CompressedTexSubImage2D(
TextureTarget.TextureCubeMapPositiveX + face,
baseLevel + level,
(int)baseLevel + level,
0,
0,
width,
height,
format.PixelFormat,
mipSize / 6,
data + faceOffset);
(InternalFormat)format.PixelFormat,
(uint)mipSize / 6,
(void*)(data + faceOffset));
}
else
{
GL.TexSubImage2D(
_gd.Api.TexSubImage2D(
TextureTarget.TextureCubeMapPositiveX + face,
baseLevel + level,
(int)baseLevel + level,
0,
0,
width,
height,
format.PixelFormat,
format.PixelType,
data + faceOffset);
(void*)(data + faceOffset));
}
}
break;
@ -880,7 +899,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
if (Handle != 0)
{
GL.DeleteTexture(Handle);
_gd.Api.DeleteTexture(Handle);
Handle = 0;
}

View file

@ -1,16 +1,20 @@
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.Translation;
using Silk.NET.OpenGL.Legacy;
using Silk.NET.OpenGL.Legacy.Extensions.ARB;
using System;
using System.Runtime.InteropServices;
using Sampler = Ryujinx.Graphics.OpenGL.Image.Sampler;
namespace Ryujinx.Graphics.OpenGL
{
public sealed class OpenGLRenderer : IRenderer
{
public readonly GL Api;
private readonly Pipeline _pipeline;
public IPipeline Pipeline => _pipeline;
@ -37,45 +41,46 @@ namespace Ryujinx.Graphics.OpenGL
internal int BufferCount { get; private set; }
internal HardwareCapabilities Capabilities;
public string GpuVendor { get; private set; }
public string GpuRenderer { get; private set; }
public string GpuVersion { get; private set; }
public bool PreferThreading => true;
public OpenGLRenderer()
public OpenGLRenderer(GL api)
{
_pipeline = new Pipeline();
_counters = new Counters();
Api = api;
_pipeline = new Pipeline(this);
_counters = new Counters(Api);
_window = new Window(this);
_textureCopy = new TextureCopy(this);
_backgroundTextureCopy = new TextureCopy(this);
TextureCopyIncompatible = new TextureCopyIncompatible(this);
TextureCopyMS = new TextureCopyMS(this);
_sync = new Sync();
PersistentBuffers = new PersistentBuffers();
_sync = new Sync(this);
PersistentBuffers = new PersistentBuffers(Api);
ResourcePool = new ResourcePool();
}
public BufferHandle CreateBuffer(int size, GAL.BufferAccess access)
public BufferHandle CreateBuffer(int size, BufferAccess access)
{
BufferCount++;
if (access.HasFlag(GAL.BufferAccess.FlushPersistent))
if (access.HasFlag(BufferAccess.FlushPersistent))
{
BufferHandle handle = Buffer.CreatePersistent(size);
BufferHandle handle = Buffer.CreatePersistent(Api, size);
PersistentBuffers.Map(handle, size);
return handle;
}
else
{
return Buffer.Create(size);
}
return Buffer.Create(Api, size);
}
public BufferHandle CreateBuffer(int size, GAL.BufferAccess access, BufferHandle storageHint)
public BufferHandle CreateBuffer(int size, BufferAccess access, BufferHandle storageHint)
{
return CreateBuffer(size, access);
}
@ -92,17 +97,17 @@ namespace Ryujinx.Graphics.OpenGL
public IImageArray CreateImageArray(int size, bool isBuffer)
{
return new ImageArray(size);
return new ImageArray(Api, size);
}
public IProgram CreateProgram(ShaderSource[] shaders, ShaderInfo info)
{
return new Program(shaders, info.FragmentOutputMap);
return new Program(this, shaders, info.FragmentOutputMap);
}
public ISampler CreateSampler(SamplerCreateInfo info)
{
return new Sampler(info);
return new Sampler(this, info);
}
public ITexture CreateTexture(TextureCreateInfo info)
@ -111,22 +116,20 @@ namespace Ryujinx.Graphics.OpenGL
{
return new TextureBuffer(this, info);
}
else
{
return ResourcePool.GetTextureOrNull(info) ?? new TextureStorage(this, info).CreateDefaultView();
}
return ResourcePool.GetTextureOrNull(info) ?? new TextureStorage(this, info).CreateDefaultView();
}
public ITextureArray CreateTextureArray(int size, bool isBuffer)
{
return new TextureArray(size);
return new TextureArray(Api, size);
}
public void DeleteBuffer(BufferHandle buffer)
{
PersistentBuffers.Unmap(buffer);
Buffer.Delete(buffer);
Buffer.Delete(Api, buffer);
}
public HardwareInfo GetHardwareInfo()
@ -141,9 +144,9 @@ namespace Ryujinx.Graphics.OpenGL
public Capabilities GetCapabilities()
{
bool intelWindows = HwCapabilities.Vendor == HwCapabilities.GpuVendor.IntelWindows;
bool intelUnix = HwCapabilities.Vendor == HwCapabilities.GpuVendor.IntelUnix;
bool amdWindows = HwCapabilities.Vendor == HwCapabilities.GpuVendor.AmdWindows;
bool intelWindows = Capabilities.GpuVendor == OpenGL.GpuVendor.IntelWindows;
bool intelUnix = Capabilities.GpuVendor == OpenGL.GpuVendor.IntelUnix;
bool amdWindows = Capabilities.GpuVendor == OpenGL.GpuVendor.AmdWindows;
return new Capabilities(
api: TargetApi.OpenGL,
@ -152,9 +155,9 @@ namespace Ryujinx.Graphics.OpenGL
hasVectorIndexingBug: amdWindows,
needsFragmentOutputSpecialization: false,
reduceShaderPrecision: false,
supportsAstcCompression: HwCapabilities.SupportsAstcCompression,
supportsBc123Compression: HwCapabilities.SupportsTextureCompressionS3tc,
supportsBc45Compression: HwCapabilities.SupportsTextureCompressionRgtc,
supportsAstcCompression: Capabilities.SupportsAstcCompression,
supportsBc123Compression: Capabilities.SupportsTextureCompressionS3tc,
supportsBc45Compression: Capabilities.SupportsTextureCompressionRgtc,
supportsBc67Compression: true, // Should check BPTC extension, but for some reason NVIDIA is not exposing the extension.
supportsEtc2Compression: true,
supports3DTextureCompression: false,
@ -165,45 +168,45 @@ namespace Ryujinx.Graphics.OpenGL
supportsSnormBufferTextureFormat: false,
supports5BitComponentFormat: true,
supportsSparseBuffer: false,
supportsBlendEquationAdvanced: HwCapabilities.SupportsBlendEquationAdvanced,
supportsFragmentShaderInterlock: HwCapabilities.SupportsFragmentShaderInterlock,
supportsFragmentShaderOrderingIntel: HwCapabilities.SupportsFragmentShaderOrdering,
supportsBlendEquationAdvanced: Capabilities.SupportsBlendEquationAdvanced,
supportsFragmentShaderInterlock: Capabilities.SupportsFragmentShaderInterlock,
supportsFragmentShaderOrderingIntel: Capabilities.SupportsFragmentShaderOrdering,
supportsGeometryShader: true,
supportsGeometryShaderPassthrough: HwCapabilities.SupportsGeometryShaderPassthrough,
supportsGeometryShaderPassthrough: Capabilities.SupportsGeometryShaderPassthrough,
supportsTransformFeedback: true,
supportsImageLoadFormatted: HwCapabilities.SupportsImageLoadFormatted,
supportsLayerVertexTessellation: HwCapabilities.SupportsShaderViewportLayerArray,
supportsMismatchingViewFormat: HwCapabilities.SupportsMismatchingViewFormat,
supportsImageLoadFormatted: Capabilities.SupportsImageLoadFormatted,
supportsLayerVertexTessellation: Capabilities.SupportsShaderViewportLayerArray,
supportsMismatchingViewFormat: Capabilities.SupportsMismatchingViewFormat,
supportsCubemapView: true,
supportsNonConstantTextureOffset: HwCapabilities.SupportsNonConstantTextureOffset,
supportsQuads: HwCapabilities.SupportsQuads,
supportsNonConstantTextureOffset: Capabilities.SupportsNonConstantTextureOffset,
supportsQuads: Capabilities.SupportsQuads,
supportsSeparateSampler: false,
supportsShaderBallot: HwCapabilities.SupportsShaderBallot,
supportsShaderBallot: Capabilities.SupportsShaderBallot,
supportsShaderBarrierDivergence: !(intelWindows || intelUnix),
supportsShaderFloat64: true,
supportsTextureGatherOffsets: true,
supportsTextureShadowLod: HwCapabilities.SupportsTextureShadowLod,
supportsTextureShadowLod: Capabilities.SupportsTextureShadowLod,
supportsVertexStoreAndAtomics: true,
supportsViewportIndexVertexTessellation: HwCapabilities.SupportsShaderViewportLayerArray,
supportsViewportMask: HwCapabilities.SupportsViewportArray2,
supportsViewportSwizzle: HwCapabilities.SupportsViewportSwizzle,
supportsIndirectParameters: HwCapabilities.SupportsIndirectParameters,
supportsViewportIndexVertexTessellation: Capabilities.SupportsShaderViewportLayerArray,
supportsViewportMask: Capabilities.SupportsViewportArray2,
supportsViewportSwizzle: Capabilities.SupportsViewportSwizzle,
supportsIndirectParameters: Capabilities.SupportsIndirectParameters,
supportsDepthClipControl: true,
maximumUniformBuffersPerStage: 13, // TODO: Avoid hardcoding those limits here and get from driver?
maximumStorageBuffersPerStage: 16,
maximumTexturesPerStage: 32,
maximumImagesPerStage: 8,
maximumComputeSharedMemorySize: HwCapabilities.MaximumComputeSharedMemorySize,
maximumSupportedAnisotropy: HwCapabilities.MaximumSupportedAnisotropy,
maximumComputeSharedMemorySize: Capabilities.MaximumComputeSharedMemorySize,
maximumSupportedAnisotropy: Capabilities.MaximumSupportedAnisotropy,
shaderSubgroupSize: Constants.MaxSubgroupSize,
storageBufferOffsetAlignment: HwCapabilities.StorageBufferOffsetAlignment,
textureBufferOffsetAlignment: HwCapabilities.TextureBufferOffsetAlignment,
storageBufferOffsetAlignment: Capabilities.StorageBufferOffsetAlignment,
textureBufferOffsetAlignment: Capabilities.TextureBufferOffsetAlignment,
gatherBiasPrecision: intelWindows || amdWindows ? 8 : 0); // Precision is 8 for these vendors on Vulkan.
}
public void SetBufferData(BufferHandle buffer, int offset, ReadOnlySpan<byte> data)
{
Buffer.SetData(buffer, offset, data);
Buffer.SetData(Api, buffer, offset, data);
}
public void UpdateCounters()
@ -224,13 +227,17 @@ namespace Ryujinx.Graphics.OpenGL
public void Initialize(GraphicsDebugLevel glLogLevel)
{
Debugger.Initialize(glLogLevel);
Debugger.Initialize(Api, glLogLevel);
LoadFeatures();
PrintGpuInformation();
if (HwCapabilities.SupportsParallelShaderCompile)
if (Capabilities.SupportsParallelShaderCompile)
{
GL.Arb.MaxShaderCompilerThreads(Math.Min(Environment.ProcessorCount, 8));
Api.TryGetExtension(out ArbParallelShaderCompile arbParallelShaderCompile);
arbParallelShaderCompile.MaxShaderCompilerThreads((uint)Math.Min(Environment.ProcessorCount, 8));
}
_counters.Initialize();
@ -238,15 +245,46 @@ namespace Ryujinx.Graphics.OpenGL
// This is required to disable [0, 1] clamping for SNorm outputs on compatibility profiles.
// This call is expected to fail if we're running with a core profile,
// as this clamp target was deprecated, but that's fine as a core profile
// should already have the desired behaviour were outputs are not clamped.
GL.ClampColor(ClampColorTarget.ClampFragmentColor, ClampColorMode.False);
// should already have the desired behaviour when outputs are not clamped.
Api.ClampColor(ClampColorTargetARB.FragmentColorArb, ClampColorModeARB.False);
}
private void PrintGpuInformation()
private void LoadFeatures()
{
GpuVendor = GL.GetString(StringName.Vendor);
GpuRenderer = GL.GetString(StringName.Renderer);
GpuVersion = GL.GetString(StringName.Version);
Capabilities = new HardwareCapabilities(
HardwareCapabilities.HasExtension(Api, "GL_NV_alpha_to_coverage_dither_control"),
HardwareCapabilities.HasExtension(Api, "GL_KHR_texture_compression_astc_ldr"),
HardwareCapabilities.HasExtension(Api, "GL_NV_blend_equation_advanced"),
HardwareCapabilities.HasExtension(Api, "GL_NV_draw_texture"),
HardwareCapabilities.HasExtension(Api, "GL_ARB_fragment_shader_interlock"),
HardwareCapabilities.HasExtension(Api, "GL_INTEL_fragment_shader_ordering"),
HardwareCapabilities.HasExtension(Api, "GL_NV_geometry_shader_passthrough"),
HardwareCapabilities.HasExtension(Api, "GL_EXT_shader_image_load_formatted"),
HardwareCapabilities.HasExtension(Api, "GL_ARB_indirect_parameters"),
HardwareCapabilities.HasExtension(Api, "GL_ARB_parallel_shader_compile"),
HardwareCapabilities.HasExtension(Api, "GL_EXT_polygon_offset_clamp"),
HardwareCapabilities.SupportsQuadsCheck(Api),
HardwareCapabilities.HasExtension(Api, "GL_ARB_seamless_cubemap_per_texture"),
HardwareCapabilities.HasExtension(Api, "GL_ARB_shader_ballot"),
HardwareCapabilities.HasExtension(Api, "GL_ARB_shader_viewport_layer_array"),
HardwareCapabilities.HasExtension(Api, "GL_NV_viewport_array2"),
HardwareCapabilities.HasExtension(Api, "GL_EXT_texture_compression_bptc"),
HardwareCapabilities.HasExtension(Api, "GL_EXT_texture_compression_rgtc"),
HardwareCapabilities.HasExtension(Api, "GL_EXT_texture_compression_s3tc"),
HardwareCapabilities.HasExtension(Api, "GL_EXT_texture_shadow_lod"),
HardwareCapabilities.HasExtension(Api, "GL_NV_viewport_swizzle"),
Api.GetInteger(GLEnum.MaxComputeSharedMemorySize),
Api.GetInteger(GLEnum.ShaderStorageBufferOffsetAlignment),
Api.GetInteger(GLEnum.TextureBufferOffsetAlignment),
Api.GetFloat(GLEnum.MaxTextureMaxAnisotropy),
HardwareCapabilities.GetGpuVendor(Api));
}
private unsafe void PrintGpuInformation()
{
GpuVendor = Marshal.PtrToStringAnsi((IntPtr)Api.GetString(StringName.Vendor));
GpuRenderer = Marshal.PtrToStringAnsi((IntPtr)Api.GetString(StringName.Renderer));
GpuVersion = Marshal.PtrToStringAnsi((IntPtr)Api.GetString(StringName.Version));
Logger.Notice.Print(LogClass.Gpu, $"{GpuVendor} {GpuRenderer} ({GpuVersion})");
}
@ -290,7 +328,7 @@ namespace Ryujinx.Graphics.OpenGL
public IProgram LoadProgramBinary(byte[] programBinary, bool hasFragmentShader, ShaderInfo info)
{
return new Program(programBinary, hasFragmentShader, info.FragmentOutputMap);
return new Program(this, programBinary, hasFragmentShader, info.FragmentOutputMap);
}
public void CreateSync(ulong id, bool strict)

View file

@ -1,7 +1,7 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.OpenGL.Image;
using Silk.NET.OpenGL.Legacy;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
@ -11,33 +11,41 @@ namespace Ryujinx.Graphics.OpenGL
{
class PersistentBuffers : IDisposable
{
private readonly PersistentBuffer _main = new();
private readonly PersistentBuffer _background = new();
private readonly GL _api;
private readonly PersistentBuffer _main;
private readonly PersistentBuffer _background;
private readonly Dictionary<BufferHandle, IntPtr> _maps = new();
public PersistentBuffer Default => BackgroundContextWorker.InBackground ? _background : _main;
public PersistentBuffers(GL api)
{
_api = api;
_main = new(_api);
_background = new(_api);
}
public void Dispose()
{
_main?.Dispose();
_background?.Dispose();
}
public void Map(BufferHandle handle, int size)
public unsafe void Map(BufferHandle handle, int size)
{
GL.BindBuffer(BufferTarget.CopyWriteBuffer, handle.ToInt32());
IntPtr ptr = GL.MapBufferRange(BufferTarget.CopyWriteBuffer, IntPtr.Zero, size, BufferAccessMask.MapReadBit | BufferAccessMask.MapPersistentBit);
_api.BindBuffer(BufferTargetARB.CopyWriteBuffer, handle.ToUInt32());
void* ptr = _api.MapBufferRange(BufferTargetARB.CopyWriteBuffer, IntPtr.Zero, (uint)size, MapBufferAccessMask.ReadBit | MapBufferAccessMask.PersistentBit);
_maps[handle] = ptr;
_maps[handle] = (IntPtr)ptr;
}
public void Unmap(BufferHandle handle)
{
if (_maps.ContainsKey(handle))
{
GL.BindBuffer(BufferTarget.CopyWriteBuffer, handle.ToInt32());
GL.UnmapBuffer(BufferTarget.CopyWriteBuffer);
_api.BindBuffer(BufferTargetARB.CopyWriteBuffer, handle.ToUInt32());
_api.UnmapBuffer(BufferTargetARB.CopyWriteBuffer);
_maps.Remove(handle);
}
@ -51,31 +59,37 @@ namespace Ryujinx.Graphics.OpenGL
class PersistentBuffer : IDisposable
{
private readonly GL _api;
private IntPtr _bufferMap;
private int _copyBufferHandle;
private uint _copyBufferHandle;
private int _copyBufferSize;
private byte[] _data;
private IntPtr _dataMap;
private void EnsureBuffer(int requiredSize)
public PersistentBuffer(GL api)
{
_api = api;
}
private unsafe void EnsureBuffer(int requiredSize)
{
if (_copyBufferSize < requiredSize && _copyBufferHandle != 0)
{
GL.DeleteBuffer(_copyBufferHandle);
_api.DeleteBuffer(_copyBufferHandle);
_copyBufferHandle = 0;
}
if (_copyBufferHandle == 0)
{
_copyBufferHandle = GL.GenBuffer();
_copyBufferHandle = _api.GenBuffer();
_copyBufferSize = requiredSize;
GL.BindBuffer(BufferTarget.CopyWriteBuffer, _copyBufferHandle);
GL.BufferStorage(BufferTarget.CopyWriteBuffer, requiredSize, IntPtr.Zero, BufferStorageFlags.MapReadBit | BufferStorageFlags.MapPersistentBit);
_api.BindBuffer(BufferTargetARB.CopyWriteBuffer, _copyBufferHandle);
_api.BufferStorage(BufferStorageTarget.CopyWriteBuffer, (uint)requiredSize, null, BufferStorageMask.MapReadBit | BufferStorageMask.MapPersistentBit);
_bufferMap = GL.MapBufferRange(BufferTarget.CopyWriteBuffer, IntPtr.Zero, requiredSize, BufferAccessMask.MapReadBit | BufferAccessMask.MapPersistentBit);
_bufferMap = (IntPtr)_api.MapBufferRange(BufferTargetARB.CopyWriteBuffer, IntPtr.Zero, (uint)requiredSize, MapBufferAccessMask.ReadBit | MapBufferAccessMask.PersistentBit);
}
}
@ -91,30 +105,30 @@ namespace Ryujinx.Graphics.OpenGL
return _dataMap;
}
private static void Sync()
private void Sync()
{
GL.MemoryBarrier(MemoryBarrierFlags.ClientMappedBufferBarrierBit);
_api.MemoryBarrier(MemoryBarrierMask.ClientMappedBufferBarrierBit);
IntPtr sync = GL.FenceSync(SyncCondition.SyncGpuCommandsComplete, WaitSyncFlags.None);
WaitSyncStatus syncResult = GL.ClientWaitSync(sync, ClientWaitSyncFlags.SyncFlushCommandsBit, 1000000000);
IntPtr sync = _api.FenceSync(SyncCondition.SyncGpuCommandsComplete, SyncBehaviorFlags.None);
GLEnum syncResult = _api.ClientWaitSync(sync, SyncObjectMask.Bit, 1000000000);
if (syncResult == WaitSyncStatus.TimeoutExpired)
if (syncResult == GLEnum.TimeoutExpired)
{
Logger.Error?.PrintMsg(LogClass.Gpu, $"Failed to sync persistent buffer state within 1000ms. Continuing...");
}
GL.DeleteSync(sync);
_api.DeleteSync(sync);
}
public unsafe ReadOnlySpan<byte> GetTextureData(TextureView view, int size)
{
EnsureBuffer(size);
GL.BindBuffer(BufferTarget.PixelPackBuffer, _copyBufferHandle);
_api.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyBufferHandle);
view.WriteToPbo(0, false);
GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);
_api.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
Sync();
@ -125,11 +139,11 @@ namespace Ryujinx.Graphics.OpenGL
{
EnsureBuffer(size);
GL.BindBuffer(BufferTarget.PixelPackBuffer, _copyBufferHandle);
_api.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyBufferHandle);
int offset = view.WriteToPbo2D(0, layer, level);
GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);
_api.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
Sync();
@ -140,12 +154,12 @@ namespace Ryujinx.Graphics.OpenGL
{
EnsureBuffer(size);
GL.BindBuffer(BufferTarget.CopyReadBuffer, buffer.ToInt32());
GL.BindBuffer(BufferTarget.CopyWriteBuffer, _copyBufferHandle);
_api.BindBuffer(BufferTargetARB.CopyReadBuffer, buffer.ToUInt32());
_api.BindBuffer(BufferTargetARB.CopyWriteBuffer, _copyBufferHandle);
GL.CopyBufferSubData(BufferTarget.CopyReadBuffer, BufferTarget.CopyWriteBuffer, (IntPtr)offset, IntPtr.Zero, size);
_api.CopyBufferSubData(CopyBufferSubDataTarget.CopyReadBuffer, CopyBufferSubDataTarget.CopyWriteBuffer, offset, IntPtr.Zero, (uint)size);
GL.BindBuffer(BufferTarget.CopyWriteBuffer, 0);
_api.BindBuffer(BufferTargetARB.CopyWriteBuffer, 0);
Sync();
@ -156,7 +170,7 @@ namespace Ryujinx.Graphics.OpenGL
{
if (_copyBufferHandle != 0)
{
GL.DeleteBuffer(_copyBufferHandle);
_api.DeleteBuffer(_copyBufferHandle);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,9 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader;
using Ryujinx.Graphics.Shader.Translation;
using Silk.NET.OpenGL.Legacy;
using Silk.NET.OpenGL.Legacy.Extensions.ARB;
using System;
using System.Buffers.Binary;
@ -12,7 +13,7 @@ namespace Ryujinx.Graphics.OpenGL
{
private const int MaxShaderLogLength = 2048;
public int Handle { get; private set; }
public uint Handle { get; private set; }
public bool IsLinked
{
@ -27,18 +28,20 @@ namespace Ryujinx.Graphics.OpenGL
}
}
private readonly OpenGLRenderer _gd;
private ProgramLinkStatus _status = ProgramLinkStatus.Incomplete;
private int[] _shaderHandles;
private uint[] _shaderHandles;
public int FragmentOutputMap { get; }
public Program(ShaderSource[] shaders, int fragmentOutputMap)
public unsafe Program(OpenGLRenderer gd, ShaderSource[] shaders, int fragmentOutputMap)
{
Handle = GL.CreateProgram();
_gd = gd;
Handle = _gd.Api.CreateProgram();
GL.ProgramParameter(Handle, ProgramParameterName.ProgramBinaryRetrievableHint, 1);
_gd.Api.ProgramParameter(Handle, ProgramParameterPName.BinaryRetrievableHint, 1);
_shaderHandles = new int[shaders.Length];
_shaderHandles = new uint[shaders.Length];
bool hasFragmentShader = false;
for (int index = 0; index < shaders.Length; index++)
@ -50,43 +53,47 @@ namespace Ryujinx.Graphics.OpenGL
hasFragmentShader = true;
}
int shaderHandle = GL.CreateShader(shader.Stage.Convert());
uint shaderHandle = _gd.Api.CreateShader(shader.Stage.Convert());
switch (shader.Language)
{
case TargetLanguage.Glsl:
GL.ShaderSource(shaderHandle, shader.Code);
GL.CompileShader(shaderHandle);
_gd.Api.ShaderSource(shaderHandle, shader.Code);
_gd.Api.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);
fixed (byte* ptr = shader.BinaryCode)
{
_gd.Api.ShaderBinary(1, in shaderHandle, ShaderBinaryFormat.ShaderBinaryFormatSpirV, ptr, (uint)shader.BinaryCode.Length);
}
_gd.Api.SpecializeShader(shaderHandle, "main", 0, (uint[])null, (uint[])null);
break;
}
GL.AttachShader(Handle, shaderHandle);
_gd.Api.AttachShader(Handle, shaderHandle);
_shaderHandles[index] = shaderHandle;
}
GL.LinkProgram(Handle);
_gd.Api.LinkProgram(Handle);
FragmentOutputMap = hasFragmentShader ? fragmentOutputMap : 0;
}
public Program(ReadOnlySpan<byte> code, bool hasFragmentShader, int fragmentOutputMap)
public Program(OpenGLRenderer gd, ReadOnlySpan<byte> code, bool hasFragmentShader, int fragmentOutputMap)
{
Handle = GL.CreateProgram();
_gd = gd;
Handle = _gd.Api.CreateProgram();
if (code.Length >= 4)
{
BinaryFormat binaryFormat = (BinaryFormat)BinaryPrimitives.ReadInt32LittleEndian(code.Slice(code.Length - 4, 4));
ShaderBinaryFormat binaryFormat = (ShaderBinaryFormat)BinaryPrimitives.ReadInt32LittleEndian(code.Slice(code.Length - 4, 4));
unsafe
{
fixed (byte* ptr = code)
{
GL.ProgramBinary(Handle, binaryFormat, (IntPtr)ptr, code.Length - 4);
_gd.Api.ProgramBinary(Handle, (GLEnum)binaryFormat, ptr, (uint)code.Length - 4);
}
}
}
@ -96,14 +103,14 @@ namespace Ryujinx.Graphics.OpenGL
public void Bind()
{
GL.UseProgram(Handle);
_gd.Api.UseProgram(Handle);
}
public ProgramLinkStatus CheckProgramLink(bool blocking)
{
if (!blocking && HwCapabilities.SupportsParallelShaderCompile)
if (!blocking && _gd.Capabilities.SupportsParallelShaderCompile)
{
GL.GetProgram(Handle, (GetProgramParameterName)ArbParallelShaderCompile.CompletionStatusArb, out int completed);
_gd.Api.GetProgram(Handle, (GLEnum)ARB.CompletionStatusArb, out int completed);
if (completed == 0)
{
@ -111,14 +118,14 @@ namespace Ryujinx.Graphics.OpenGL
}
}
GL.GetProgram(Handle, GetProgramParameterName.LinkStatus, out int status);
_gd.Api.GetProgram(Handle, ProgramPropertyARB.LinkStatus, out int status);
DeleteShaders();
if (status == 0)
{
_status = ProgramLinkStatus.Failure;
string log = GL.GetProgramInfoLog(Handle);
string log = _gd.Api.GetProgramInfoLog(Handle);
if (log.Length > MaxShaderLogLength)
{
@ -135,13 +142,17 @@ namespace Ryujinx.Graphics.OpenGL
return _status;
}
public byte[] GetBinary()
public unsafe byte[] GetBinary()
{
GL.GetProgram(Handle, (GetProgramParameterName)All.ProgramBinaryLength, out int size);
_gd.Api.GetProgram(Handle, ProgramPropertyARB.ProgramBinaryLength, out int size);
byte[] data = new byte[size + 4];
GLEnum binFormat;
GL.GetProgramBinary(Handle, size, out _, out BinaryFormat binFormat, data);
fixed (byte* ptr = data)
{
_gd.Api.GetProgramBinary(Handle, (uint)size, out _, out binFormat, ptr);
}
BinaryPrimitives.WriteInt32LittleEndian(data.AsSpan(size, 4), (int)binFormat);
@ -152,10 +163,10 @@ namespace Ryujinx.Graphics.OpenGL
{
if (_shaderHandles != null)
{
foreach (int shaderHandle in _shaderHandles)
foreach (uint shaderHandle in _shaderHandles)
{
GL.DetachShader(Handle, shaderHandle);
GL.DeleteShader(shaderHandle);
_gd.Api.DetachShader(Handle, shaderHandle);
_gd.Api.DeleteShader(shaderHandle);
}
_shaderHandles = null;
@ -167,7 +178,7 @@ namespace Ryujinx.Graphics.OpenGL
if (Handle != 0)
{
DeleteShaders();
GL.DeleteProgram(Handle);
_gd.Api.DeleteProgram(Handle);
Handle = 0;
}

View file

@ -1,5 +1,5 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Logging;
using Silk.NET.OpenGL.Legacy;
using System;
using System.Runtime.InteropServices;
using System.Threading;
@ -12,50 +12,53 @@ namespace Ryujinx.Graphics.OpenGL.Queries
private const long DefaultValue = -1;
private const ulong HighMask = 0xFFFFFFFF00000000;
public int Query { get; }
public uint Query { get; }
private readonly int _buffer;
private readonly uint _buffer;
private readonly IntPtr _bufferMap;
private readonly QueryTarget _type;
private readonly GL _api;
public BufferedQuery(QueryTarget type)
public BufferedQuery(GL api, QueryTarget type)
{
_buffer = GL.GenBuffer();
Query = GL.GenQuery();
_api = api;
_buffer = _api.GenBuffer();
Query = _api.GenQuery();
_type = type;
GL.BindBuffer(BufferTarget.QueryBuffer, _buffer);
_api.BindBuffer(BufferTargetARB.QueryBuffer, _buffer);
var defaultValue = DefaultValue;
_api.BufferStorage(BufferStorageTarget.QueryBuffer, sizeof(long), in defaultValue, BufferStorageMask.MapReadBit | BufferStorageMask.MapWriteBit | BufferStorageMask.MapPersistentBit);
unsafe
{
long defaultValue = DefaultValue;
GL.BufferStorage(BufferTarget.QueryBuffer, sizeof(long), (IntPtr)(&defaultValue), BufferStorageFlags.MapReadBit | BufferStorageFlags.MapWriteBit | BufferStorageFlags.MapPersistentBit);
_bufferMap = (IntPtr)_api.MapBufferRange(BufferTargetARB.QueryBuffer, IntPtr.Zero, sizeof(long), MapBufferAccessMask.ReadBit | MapBufferAccessMask.WriteBit | MapBufferAccessMask.PersistentBit);
}
_bufferMap = GL.MapBufferRange(BufferTarget.QueryBuffer, IntPtr.Zero, sizeof(long), BufferAccessMask.MapReadBit | BufferAccessMask.MapWriteBit | BufferAccessMask.MapPersistentBit);
}
public void Reset()
{
GL.EndQuery(_type);
GL.BeginQuery(_type, Query);
_api.EndQuery(_type);
_api.BeginQuery(_type, Query);
}
public void Begin()
{
GL.BeginQuery(_type, Query);
_api.BeginQuery(_type, Query);
}
public unsafe void End(bool withResult)
{
GL.EndQuery(_type);
_api.EndQuery(_type);
if (withResult)
{
GL.BindBuffer(BufferTarget.QueryBuffer, _buffer);
_api.BindBuffer(BufferTargetARB.QueryBuffer, _buffer);
Marshal.WriteInt64(_bufferMap, -1L);
GL.GetQueryObject(Query, GetQueryObjectParam.QueryResult, (long*)0);
GL.MemoryBarrier(MemoryBarrierFlags.QueryBufferBarrierBit | MemoryBarrierFlags.ClientMappedBufferBarrierBit);
_api.GetQueryObject(Query, QueryObjectParameterName.Result, (long*)0);
_api.MemoryBarrier(MemoryBarrierMask.QueryBufferBarrierBit | MemoryBarrierMask.ClientMappedBufferBarrierBit);
}
else
{
@ -111,10 +114,10 @@ namespace Ryujinx.Graphics.OpenGL.Queries
public void Dispose()
{
GL.BindBuffer(BufferTarget.QueryBuffer, _buffer);
GL.UnmapBuffer(BufferTarget.QueryBuffer);
GL.DeleteBuffer(_buffer);
GL.DeleteQuery(Query);
_api.BindBuffer(BufferTargetARB.QueryBuffer, _buffer);
_api.UnmapBuffer(BufferTargetARB.QueryBuffer);
_api.DeleteBuffer(_buffer);
_api.DeleteQuery(Query);
}
}
}

View file

@ -1,5 +1,5 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
using System;
using System.Collections.Generic;
using System.Threading;
@ -28,7 +28,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
private readonly Thread _consumerThread;
internal CounterQueue(CounterType type)
internal CounterQueue(GL api, CounterType type)
{
Type = type;
@ -37,10 +37,10 @@ namespace Ryujinx.Graphics.OpenGL.Queries
_queryPool = new Queue<BufferedQuery>(QueryPoolInitialSize);
for (int i = 0; i < QueryPoolInitialSize; i++)
{
_queryPool.Enqueue(new BufferedQuery(glType));
_queryPool.Enqueue(new BufferedQuery(api, glType));
}
_current = new CounterQueueEvent(this, glType, 0);
_current = new CounterQueueEvent(api, this, glType, 0);
_consumerThread = new Thread(EventConsumer);
_consumerThread.Start();
@ -76,7 +76,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
}
}
internal BufferedQuery GetQueryObject()
internal BufferedQuery GetQueryObject(GL api)
{
// Creating/disposing query objects on a context we're sharing with will cause issues.
// So instead, make a lot of query objects on the main thread and reuse them.
@ -90,7 +90,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
}
else
{
return new BufferedQuery(GetTarget(Type));
return new BufferedQuery(api, GetTarget(Type));
}
}
}
@ -103,7 +103,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
}
}
public CounterQueueEvent QueueReport(EventHandler<ulong> resultHandler, float divisor, ulong lastDrawIndex, bool hostReserved)
public CounterQueueEvent QueueReport(GL api, EventHandler<ulong> resultHandler, float divisor, ulong lastDrawIndex, bool hostReserved)
{
CounterQueueEvent result;
ulong draws = lastDrawIndex - _current.DrawIndex;
@ -126,7 +126,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
result = _current;
_current = new CounterQueueEvent(this, GetTarget(Type), lastDrawIndex);
_current = new CounterQueueEvent(api, this, GetTarget(Type), lastDrawIndex);
}
_queuedEvent.Set();

View file

@ -1,5 +1,5 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
using System;
using System.Threading;
@ -11,7 +11,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
public QueryTarget Type { get; }
public bool ClearCounter { get; private set; }
public int Query => _counter.Query;
public uint Query => _counter.Query;
public bool Disposed { get; private set; }
public bool Invalid { get; set; }
@ -28,11 +28,11 @@ namespace Ryujinx.Graphics.OpenGL.Queries
private ulong _result = ulong.MaxValue;
private double _divisor = 1f;
public CounterQueueEvent(CounterQueue queue, QueryTarget type, ulong drawIndex)
public CounterQueueEvent(GL api, CounterQueue queue, QueryTarget type, ulong drawIndex)
{
_queue = queue;
_counter = queue.GetQueryObject();
_counter = queue.GetQueryObject(api);
Type = type;
DrawIndex = drawIndex;
@ -62,7 +62,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
return true;
}
if (ClearCounter || Type == QueryTarget.Timestamp)
if (ClearCounter || Type == (QueryTarget)GLEnum.Timestamp)
{
result = 0;
}

View file

@ -1,4 +1,5 @@
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
using System;
namespace Ryujinx.Graphics.OpenGL.Queries
@ -6,12 +7,14 @@ namespace Ryujinx.Graphics.OpenGL.Queries
class Counters : IDisposable
{
private readonly CounterQueue[] _counterQueues;
private readonly GL _api;
public Counters()
public Counters(GL api)
{
int count = Enum.GetNames<CounterType>().Length;
_counterQueues = new CounterQueue[count];
_api = api;
}
public void Initialize()
@ -19,13 +22,13 @@ namespace Ryujinx.Graphics.OpenGL.Queries
for (int index = 0; index < _counterQueues.Length; index++)
{
CounterType type = (CounterType)index;
_counterQueues[index] = new CounterQueue(type);
_counterQueues[index] = new CounterQueue(_api, type);
}
}
public CounterQueueEvent QueueReport(CounterType type, EventHandler<ulong> resultHandler, float divisor, ulong lastDrawIndex, bool hostReserved)
{
return _counterQueues[(int)type].QueueReport(resultHandler, divisor, lastDrawIndex, hostReserved);
return _counterQueues[(int)type].QueueReport(_api, resultHandler, divisor, lastDrawIndex, hostReserved);
}
public void QueueReset(CounterType type)

View file

@ -6,7 +6,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="OpenTK.Graphics" />
<PackageReference Include="Silk.NET.OpenGL.Legacy" />
<PackageReference Include="Silk.NET.OpenGL.Legacy.Extensions.ARB" />
<PackageReference Include="Silk.NET.OpenGL.Legacy.Extensions.EXT" />
<PackageReference Include="Silk.NET.OpenGL.Legacy.Extensions.NV" />
</ItemGroup>
<ItemGroup>

View file

@ -1,5 +1,5 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Logging;
using Silk.NET.OpenGL.Legacy;
using System;
using System.Collections.Generic;
using System.Linq;
@ -14,24 +14,30 @@ namespace Ryujinx.Graphics.OpenGL
public IntPtr Handle;
}
private ulong _firstHandle = 0;
private static ClientWaitSyncFlags SyncFlags => HwCapabilities.RequiresSyncFlush ? ClientWaitSyncFlags.None : ClientWaitSyncFlags.SyncFlushCommandsBit;
private ulong _firstHandle;
private SyncObjectMask SyncFlags => _gd.Capabilities.RequiresSyncFlush ? 0 : SyncObjectMask.Bit;
private readonly List<SyncHandle> _handles = new();
private readonly OpenGLRenderer _gd;
public Sync(OpenGLRenderer gd)
{
_gd = gd;
}
public void Create(ulong id)
{
SyncHandle handle = new()
{
ID = id,
Handle = GL.FenceSync(SyncCondition.SyncGpuCommandsComplete, WaitSyncFlags.None),
Handle = _gd.Api.FenceSync(SyncCondition.SyncGpuCommandsComplete, SyncBehaviorFlags.None),
};
if (HwCapabilities.RequiresSyncFlush)
if (_gd.Capabilities.RequiresSyncFlush)
{
// Force commands to flush up to the syncpoint.
GL.ClientWaitSync(handle.Handle, ClientWaitSyncFlags.SyncFlushCommandsBit, 0);
_gd.Api.ClientWaitSync(handle.Handle, SyncObjectMask.Bit, 0);
}
lock (_handles)
@ -57,9 +63,9 @@ namespace Ryujinx.Graphics.OpenGL
if (handle.ID > lastHandle)
{
WaitSyncStatus syncResult = GL.ClientWaitSync(handle.Handle, SyncFlags, 0);
GLEnum syncResult = _gd.Api.ClientWaitSync(handle.Handle, SyncFlags, 0);
if (syncResult == WaitSyncStatus.AlreadySignaled)
if (syncResult == GLEnum.AlreadySignaled)
{
lastHandle = handle.ID;
}
@ -101,9 +107,9 @@ namespace Ryujinx.Graphics.OpenGL
return;
}
WaitSyncStatus syncResult = GL.ClientWaitSync(result.Handle, SyncFlags, 1000000000);
GLEnum syncResult = _gd.Api.ClientWaitSync(result.Handle, SyncFlags, 1000000000);
if (syncResult == WaitSyncStatus.TimeoutExpired)
if (syncResult == GLEnum.TimeoutExpired)
{
Logger.Error?.PrintMsg(LogClass.Gpu, $"GL Sync Object {result.ID} failed to signal within 1000ms. Continuing...");
}
@ -128,9 +134,9 @@ namespace Ryujinx.Graphics.OpenGL
break;
}
WaitSyncStatus syncResult = GL.ClientWaitSync(first.Handle, SyncFlags, 0);
GLEnum syncResult = _gd.Api.ClientWaitSync(first.Handle, SyncFlags, 0);
if (syncResult == WaitSyncStatus.AlreadySignaled)
if (syncResult == GLEnum.AlreadySignaled)
{
// Delete the sync object.
lock (_handles)
@ -139,7 +145,7 @@ namespace Ryujinx.Graphics.OpenGL
{
_firstHandle = first.ID + 1;
_handles.RemoveAt(0);
GL.DeleteSync(first.Handle);
_gd.Api.DeleteSync(first.Handle);
first.Handle = IntPtr.Zero;
}
}
@ -160,7 +166,7 @@ namespace Ryujinx.Graphics.OpenGL
{
lock (handle)
{
GL.DeleteSync(handle.Handle);
_gd.Api.DeleteSync(handle.Handle);
handle.Handle = IntPtr.Zero;
}
}

View file

@ -1,5 +1,6 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
using Silk.NET.OpenGL.Legacy.Extensions.NV;
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
@ -8,7 +9,7 @@ namespace Ryujinx.Graphics.OpenGL
{
class VertexArray : IDisposable
{
public int Handle { get; private set; }
public uint Handle { get; private set; }
private readonly VertexAttribDescriptor[] _vertexAttribs;
private readonly VertexBufferDescriptor[] _vertexBuffers;
@ -23,20 +24,22 @@ namespace Ryujinx.Graphics.OpenGL
private readonly BufferHandle _tempIndexBuffer;
private BufferHandle _tempVertexBuffer;
private int _tempVertexBufferSize;
private readonly GL _api;
public VertexArray()
public VertexArray(GL api)
{
Handle = GL.GenVertexArray();
_api = api;
Handle = _api.GenVertexArray();
_vertexAttribs = new VertexAttribDescriptor[Constants.MaxVertexAttribs];
_vertexBuffers = new VertexBufferDescriptor[Constants.MaxVertexBuffers];
_tempIndexBuffer = Buffer.Create();
_tempIndexBuffer = Buffer.Create(_api);
}
public void Bind()
{
GL.BindVertexArray(Handle);
_api.BindVertexArray(Handle);
}
public void SetVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers)
@ -56,15 +59,15 @@ namespace Ryujinx.Graphics.OpenGL
minVertexCount = vertexCount;
}
GL.BindVertexBuffer(bindingIndex, vb.Buffer.Handle.ToInt32(), (IntPtr)vb.Buffer.Offset, vb.Stride);
GL.VertexBindingDivisor(bindingIndex, vb.Divisor);
_api.BindVertexBuffer((uint)bindingIndex, vb.Buffer.Handle.ToUInt32(), vb.Buffer.Offset, (uint)vb.Stride);
_api.VertexBindingDivisor((uint)bindingIndex, (uint)vb.Divisor);
_vertexBuffersInUse |= 1u << bindingIndex;
}
else
{
if ((_vertexBuffersInUse & (1u << bindingIndex)) != 0)
{
GL.BindVertexBuffer(bindingIndex, 0, IntPtr.Zero, 0);
_api.BindVertexBuffer((uint)bindingIndex, 0, 0, 0);
_vertexBuffersInUse &= ~(1u << bindingIndex);
}
}
@ -105,22 +108,22 @@ namespace Ryujinx.Graphics.OpenGL
int size = fmtInfo.Components;
bool isFloat = fmtInfo.PixelType == PixelType.Float ||
fmtInfo.PixelType == PixelType.HalfFloat;
fmtInfo.PixelType == (PixelType)NV.HalfFloatNV;
if (isFloat || fmtInfo.Normalized || fmtInfo.Scaled)
{
VertexAttribType type = (VertexAttribType)fmtInfo.PixelType;
GL.VertexAttribFormat(index, size, type, fmtInfo.Normalized, offset);
_api.VertexAttribFormat((uint)index, size, type, fmtInfo.Normalized, (uint)offset);
}
else
{
VertexAttribIntegerType type = (VertexAttribIntegerType)fmtInfo.PixelType;
VertexAttribIType type = (VertexAttribIType)fmtInfo.PixelType;
GL.VertexAttribIFormat(index, size, type, offset);
_api.VertexAttribIFormat((uint)index, size, type, (uint)offset);
}
GL.VertexAttribBinding(index, attrib.BufferIndex);
_api.VertexAttribBinding((uint)index, (uint)attrib.BufferIndex);
_vertexAttribs[index] = attrib;
}
@ -134,19 +137,19 @@ namespace Ryujinx.Graphics.OpenGL
public void SetIndexBuffer(BufferRange range)
{
_indexBuffer = range;
GL.BindBuffer(BufferTarget.ElementArrayBuffer, range.Handle.ToInt32());
_api.BindBuffer(BufferTargetARB.ElementArrayBuffer, range.Handle.ToUInt32());
}
public void SetRangeOfIndexBuffer()
{
Buffer.Resize(_tempIndexBuffer, _indexBuffer.Size);
Buffer.Copy(_indexBuffer.Handle, _tempIndexBuffer, _indexBuffer.Offset, 0, _indexBuffer.Size);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, _tempIndexBuffer.ToInt32());
Buffer.Resize(_api, _tempIndexBuffer, _indexBuffer.Size);
Buffer.Copy(_api, _indexBuffer.Handle, _tempIndexBuffer, _indexBuffer.Offset, 0, _indexBuffer.Size);
_api.BindBuffer(BufferTargetARB.ElementArrayBuffer, _tempIndexBuffer.ToUInt32());
}
public void RestoreIndexBuffer()
{
GL.BindBuffer(BufferTarget.ElementArrayBuffer, _indexBuffer.Handle.ToInt32());
_api.BindBuffer(BufferTargetARB.ElementArrayBuffer, _indexBuffer.Handle.ToUInt32());
}
public void PreDraw(int vertexCount)
@ -185,10 +188,10 @@ namespace Ryujinx.Graphics.OpenGL
{
BufferHandle tempVertexBuffer = EnsureTempVertexBufferSize(currentTempVbOffset + requiredSize);
Buffer.Copy(vb.Buffer.Handle, tempVertexBuffer, vb.Buffer.Offset, currentTempVbOffset, vb.Buffer.Size);
Buffer.Clear(tempVertexBuffer, currentTempVbOffset + vb.Buffer.Size, requiredSize - vb.Buffer.Size, 0);
Buffer.Copy(_api, vb.Buffer.Handle, tempVertexBuffer, vb.Buffer.Offset, currentTempVbOffset, vb.Buffer.Size);
Buffer.Clear(_api, tempVertexBuffer, currentTempVbOffset + vb.Buffer.Size, (uint)(requiredSize - vb.Buffer.Size), 0);
GL.BindVertexBuffer(vbIndex, tempVertexBuffer.ToInt32(), (IntPtr)currentTempVbOffset, vb.Stride);
_api.BindVertexBuffer((uint)vbIndex, tempVertexBuffer.ToUInt32(), currentTempVbOffset, (uint)vb.Stride);
currentTempVbOffset += requiredSize;
_vertexBuffersLimited |= 1u << vbIndex;
@ -208,12 +211,12 @@ namespace Ryujinx.Graphics.OpenGL
if (tempVertexBuffer == BufferHandle.Null)
{
tempVertexBuffer = Buffer.Create(size);
tempVertexBuffer = Buffer.Create(_api, size);
_tempVertexBuffer = tempVertexBuffer;
return tempVertexBuffer;
}
Buffer.Resize(_tempVertexBuffer, size);
Buffer.Resize(_api, _tempVertexBuffer, size);
}
return tempVertexBuffer;
@ -234,7 +237,7 @@ namespace Ryujinx.Graphics.OpenGL
ref var vb = ref _vertexBuffers[vbIndex];
GL.BindVertexBuffer(vbIndex, vb.Buffer.Handle.ToInt32(), (IntPtr)vb.Buffer.Offset, vb.Stride);
_api.BindVertexBuffer((uint)vbIndex, vb.Buffer.Handle.ToUInt32(), vb.Buffer.Offset, (uint)vb.Stride);
buffersLimited &= ~(1u << vbIndex);
}
@ -250,7 +253,7 @@ namespace Ryujinx.Graphics.OpenGL
if ((_vertexAttribsInUse & mask) == 0)
{
_vertexAttribsInUse |= mask;
GL.EnableVertexAttribArray(index);
_api.EnableVertexAttribArray((uint)index);
}
}
@ -262,8 +265,8 @@ namespace Ryujinx.Graphics.OpenGL
if ((_vertexAttribsInUse & mask) != 0)
{
_vertexAttribsInUse &= ~mask;
GL.DisableVertexAttribArray(index);
GL.VertexAttrib4(index, 0f, 0f, 0f, 1f);
_api.DisableVertexAttribArray((uint)index);
_api.VertexAttrib4((uint)index, 0f, 0f, 0f, 1f);
}
}
@ -271,7 +274,7 @@ namespace Ryujinx.Graphics.OpenGL
{
if (Handle != 0)
{
GL.DeleteVertexArray(Handle);
_api.DeleteVertexArray(Handle);
Handle = 0;
}

View file

@ -1,22 +1,22 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.OpenGL.Effects;
using Ryujinx.Graphics.OpenGL.Effects.Smaa;
using Ryujinx.Graphics.OpenGL.Image;
using Silk.NET.OpenGL.Legacy;
using System;
namespace Ryujinx.Graphics.OpenGL
{
class Window : IWindow, IDisposable
{
private readonly OpenGLRenderer _renderer;
private readonly OpenGLRenderer _gd;
private bool _initialized;
private int _width;
private int _height;
private bool _updateSize;
private int _copyFramebufferHandle;
private uint _copyFramebufferHandle;
private IPostProcessingEffect _antiAliasing;
private IScalingFilter _scalingFilter;
private bool _isLinear;
@ -32,26 +32,26 @@ namespace Ryujinx.Graphics.OpenGL
internal bool ScreenCaptureRequested { get; set; }
public Window(OpenGLRenderer renderer)
public Window(OpenGLRenderer gd)
{
_renderer = renderer;
_gd = gd;
}
public void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback)
{
GL.Disable(EnableCap.FramebufferSrgb);
_gd.Api.Disable(EnableCap.FramebufferSrgb);
(int oldDrawFramebufferHandle, int oldReadFramebufferHandle) = ((Pipeline)_renderer.Pipeline).GetBoundFramebuffers();
(uint oldDrawFramebufferHandle, uint oldReadFramebufferHandle) = ((Pipeline)_gd.Pipeline).GetBoundFramebuffers();
CopyTextureToFrameBufferRGB(0, GetCopyFramebufferHandleLazy(), (TextureView)texture, crop, swapBuffersCallback);
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
_gd.Api.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
_gd.Api.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
GL.Enable(EnableCap.FramebufferSrgb);
_gd.Api.Enable(EnableCap.FramebufferSrgb);
// Restore unpack alignment to 4, as performance overlays such as RTSS may change this to load their resources.
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 4);
_gd.Api.PixelStore(PixelStoreParameter.UnpackAlignment, 4);
}
public void ChangeVSyncMode(bool vsyncEnabled) { }
@ -64,12 +64,12 @@ namespace Ryujinx.Graphics.OpenGL
_updateSize = true;
}
private void CopyTextureToFrameBufferRGB(int drawFramebuffer, int readFramebuffer, TextureView view, ImageCrop crop, Action swapBuffersCallback)
private void CopyTextureToFrameBufferRGB(uint drawFramebuffer, uint readFramebuffer, TextureView view, ImageCrop crop, Action swapBuffersCallback)
{
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, drawFramebuffer);
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, readFramebuffer);
_gd.Api.BindFramebuffer(FramebufferTarget.DrawFramebuffer, drawFramebuffer);
_gd.Api.BindFramebuffer(FramebufferTarget.ReadFramebuffer, readFramebuffer);
TextureView viewConverted = view.Format.IsBgr() ? _renderer.TextureCopy.BgraSwap(view) : view;
TextureView viewConverted = view.Format.IsBgr() ? _gd.TextureCopy.BgraSwap(view) : view;
UpdateEffect();
@ -81,9 +81,9 @@ namespace Ryujinx.Graphics.OpenGL
if (viewConverted.Format.IsBgr())
{
var swappedView = _renderer.TextureCopy.BgraSwap(viewConverted);
var swappedView = _gd.TextureCopy.BgraSwap(viewConverted);
viewConverted?.Dispose();
viewConverted.Dispose();
viewConverted = swappedView;
}
@ -94,21 +94,21 @@ namespace Ryujinx.Graphics.OpenGL
}
}
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, drawFramebuffer);
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, readFramebuffer);
_gd.Api.BindFramebuffer(FramebufferTarget.DrawFramebuffer, drawFramebuffer);
_gd.Api.BindFramebuffer(FramebufferTarget.ReadFramebuffer, readFramebuffer);
GL.FramebufferTexture(
_gd.Api.FramebufferTexture(
FramebufferTarget.ReadFramebuffer,
FramebufferAttachment.ColorAttachment0,
viewConverted.Handle,
0);
GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
_gd.Api.ReadBuffer(ReadBufferMode.ColorAttachment0);
GL.Disable(EnableCap.RasterizerDiscard);
GL.Disable(IndexedEnableCap.ScissorTest, 0);
_gd.Api.Disable(EnableCap.RasterizerDiscard);
_gd.Api.Disable(EnableCap.ScissorTest, 0);
GL.Clear(ClearBufferMask.ColorBufferBit);
_gd.Api.Clear(ClearBufferMask.ColorBufferBit);
int srcX0, srcX1, srcY0, srcY1;
@ -151,7 +151,7 @@ namespace Ryujinx.Graphics.OpenGL
if (ScreenCaptureRequested)
{
CaptureFrame(srcX0, srcY0, srcX1, srcY1, view.Format.IsBgr(), crop.FlipX, crop.FlipY);
CaptureFrame(srcX0, srcY0, (uint)srcX1, (uint)srcY1, view.Format.IsBgr(), crop.FlipX, crop.FlipY);
ScreenCaptureRequested = false;
}
@ -185,14 +185,14 @@ namespace Ryujinx.Graphics.OpenGL
srcX1 = dstX1;
srcY1 = dstY1;
GL.FramebufferTexture(
_gd.Api.FramebufferTexture(
FramebufferTarget.ReadFramebuffer,
FramebufferAttachment.ColorAttachment0,
_upscaledTexture.Handle,
0);
}
GL.BlitFramebuffer(
_gd.Api.BlitFramebuffer(
srcX0,
srcY0,
srcX1,
@ -205,26 +205,26 @@ namespace Ryujinx.Graphics.OpenGL
_isLinear ? BlitFramebufferFilter.Linear : BlitFramebufferFilter.Nearest);
// Remove Alpha channel
GL.ColorMask(false, false, false, true);
GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
GL.Clear(ClearBufferMask.ColorBufferBit);
_gd.Api.ColorMask(false, false, false, true);
_gd.Api.ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
_gd.Api.Clear(ClearBufferMask.ColorBufferBit);
for (int i = 0; i < Constants.MaxRenderTargets; i++)
{
((Pipeline)_renderer.Pipeline).RestoreComponentMask(i);
((Pipeline)_gd.Pipeline).RestoreComponentMask(i);
}
// Set clip control, viewport and the framebuffer to the output to placate overlays and OBS capture.
GL.ClipControl(ClipOrigin.LowerLeft, ClipDepthMode.NegativeOneToOne);
GL.Viewport(0, 0, _width, _height);
GL.BindFramebuffer(FramebufferTarget.Framebuffer, drawFramebuffer);
_gd.Api.ClipControl(ClipControlOrigin.LowerLeft, ClipControlDepth.NegativeOneToOne);
_gd.Api.Viewport(0, 0, (uint)_width, (uint)_height);
_gd.Api.BindFramebuffer(FramebufferTarget.Framebuffer, drawFramebuffer);
swapBuffersCallback();
((Pipeline)_renderer.Pipeline).RestoreClipControl();
((Pipeline)_renderer.Pipeline).RestoreScissor0Enable();
((Pipeline)_renderer.Pipeline).RestoreRasterizerDiscard();
((Pipeline)_renderer.Pipeline).RestoreViewport0();
((Pipeline)_gd.Pipeline).RestoreClipControl();
((Pipeline)_gd.Pipeline).RestoreScissor0Enable();
((Pipeline)_gd.Pipeline).RestoreRasterizerDiscard();
((Pipeline)_gd.Pipeline).RestoreViewport0();
if (viewConverted != view)
{
@ -232,13 +232,13 @@ namespace Ryujinx.Graphics.OpenGL
}
}
private int GetCopyFramebufferHandleLazy()
private uint GetCopyFramebufferHandleLazy()
{
int handle = _copyFramebufferHandle;
uint handle = _copyFramebufferHandle;
if (handle == 0)
{
handle = GL.GenFramebuffer();
handle = _gd.Api.GenFramebuffer();
_copyFramebufferHandle = handle;
}
@ -252,14 +252,15 @@ namespace Ryujinx.Graphics.OpenGL
_initialized = true;
}
public void CaptureFrame(int x, int y, int width, int height, bool isBgra, bool flipX, bool flipY)
public unsafe void CaptureFrame(int x, int y, uint width, uint height, bool isBgra, bool flipX, bool flipY)
{
long size = Math.Abs(4 * width * height);
byte[] bitmap = new byte[size];
long size = 4 * width * height;
GL.ReadPixels(x, y, width, height, isBgra ? PixelFormat.Bgra : PixelFormat.Rgba, PixelType.UnsignedByte, bitmap);
_gd.Api.ReadPixels(x, y, width, height, isBgra ? PixelFormat.Bgra : PixelFormat.Rgba, PixelType.UnsignedByte, out int data);
_renderer.OnScreenCaptured(new ScreenCaptureImageInfo(width, height, isBgra, bitmap, flipX, flipY));
var bitmap = new Span<byte>((void*)data, (int)size).ToArray();
_gd.OnScreenCaptured(new ScreenCaptureImageInfo((int)width, (int)height, isBgra, bitmap, flipX, flipY));
}
public void Dispose()
@ -273,7 +274,7 @@ namespace Ryujinx.Graphics.OpenGL
if (_copyFramebufferHandle != 0)
{
GL.DeleteFramebuffer(_copyFramebufferHandle);
_gd.Api.DeleteFramebuffer(_copyFramebufferHandle);
_copyFramebufferHandle = 0;
}
@ -319,7 +320,7 @@ namespace Ryujinx.Graphics.OpenGL
{
case AntiAliasing.Fxaa:
_antiAliasing?.Dispose();
_antiAliasing = new FxaaPostProcessingEffect(_renderer);
_antiAliasing = new FxaaPostProcessingEffect(_gd);
break;
case AntiAliasing.None:
_antiAliasing?.Dispose();
@ -337,7 +338,7 @@ namespace Ryujinx.Graphics.OpenGL
else
{
_antiAliasing?.Dispose();
_antiAliasing = new SmaaPostProcessingEffect(_renderer, quality);
_antiAliasing = new SmaaPostProcessingEffect(_gd, quality);
}
break;
}
@ -368,7 +369,7 @@ namespace Ryujinx.Graphics.OpenGL
if (_scalingFilter is not FsrScalingFilter)
{
_scalingFilter?.Dispose();
_scalingFilter = new FsrScalingFilter(_renderer);
_scalingFilter = new FsrScalingFilter(_gd);
}
_isLinear = false;
_scalingFilter.Level = _scalingFilterLevel;
@ -401,7 +402,7 @@ namespace Ryujinx.Graphics.OpenGL
SwizzleComponent.Alpha);
_isBgra = forceBgra;
_upscaledTexture = _renderer.CreateTexture(info) as TextureView;
_upscaledTexture = _gd.CreateTexture(info) as TextureView;
}
public void SetScalingFilterLevel(float level)

View file

@ -27,7 +27,6 @@
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64'" />
<PackageReference Include="OpenTK.Core" />
<PackageReference Include="OpenTK.Graphics" />
<PackageReference Include="SPB" />
<PackageReference Include="SharpZipLib" />
<PackageReference Include="SixLabors.ImageSharp" />

View file

@ -504,7 +504,7 @@ namespace Ryujinx.UI
}
else
{
renderer = new Graphics.OpenGL.OpenGLRenderer();
renderer = new Graphics.OpenGL.OpenGLRenderer(((OpenGLRenderer)RendererWidget).GetApi());
}
BackendThreading threadingMode = ConfigurationState.Instance.Graphics.BackendThreading;

View file

@ -1,7 +1,7 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Ryujinx.Input.HLE;
using Silk.NET.OpenGL.Legacy;
using SPB.Graphics;
using SPB.Graphics.Exceptions;
using SPB.Graphics.OpenGL;
@ -96,11 +96,18 @@ namespace Ryujinx.UI
_openGLContext.MakeCurrent(_nativeWindow);
GL.ClearColor(0, 0, 0, 1.0f);
GL.Clear(ClearBufferMask.ColorBufferBit);
var api = GetApi();
api.ClearColor(0, 0, 0, 1.0f);
api.Clear(ClearBufferMask.ColorBufferBit);
SwapBuffers();
}
public GL GetApi()
{
return GL.GetApi(_openGLContext.GetProcAddress);
}
public override void SwapBuffers()
{
_nativeWindow.SwapBuffers();

View file

@ -1,20 +0,0 @@
using SPB.Graphics;
using System;
namespace Ryujinx.UI
{
public class OpenToolkitBindingsContext : OpenTK.IBindingsContext
{
private readonly IBindingsContext _bindingContext;
public OpenToolkitBindingsContext(IBindingsContext bindingsContext)
{
_bindingContext = bindingsContext;
}
public IntPtr GetProcAddress(string procName)
{
return _bindingContext.GetProcAddress(procName);
}
}
}

View file

@ -1,4 +1,3 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.OpenGL;
using SPB.Graphics;
using SPB.Graphics.OpenGL;
@ -38,9 +37,6 @@ namespace Ryujinx.UI
context.Initialize(window);
context.MakeCurrent(window);
GL.LoadBindings(new OpenToolkitBindingsContext(context));
context.MakeCurrent(null);
return new SPBOpenGLContext(context, window);

View file

@ -1,9 +1,9 @@
using OpenTK;
using OpenTK.Graphics.OpenGL;
// using OpenTK;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.OpenGL;
using Ryujinx.Input.HLE;
using Silk.NET.OpenGL.Legacy;
using System;
using static SDL2.SDL;
@ -38,22 +38,16 @@ namespace Ryujinx.Headless.SDL2.OpenGL
CheckResult(SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_STEREO, 0));
}
private class OpenToolkitBindingsContext : IBindingsContext
{
public IntPtr GetProcAddress(string procName)
{
return SDL_GL_GetProcAddress(procName);
}
}
private class SDL2OpenGLContext : IOpenGLContext
{
public readonly GL Api;
private readonly IntPtr _context;
private readonly IntPtr _window;
private readonly bool _shouldDisposeWindow;
public SDL2OpenGLContext(IntPtr context, IntPtr window, bool shouldDisposeWindow = true)
public SDL2OpenGLContext(GL api, IntPtr context, IntPtr window, bool shouldDisposeWindow = true)
{
Api = api;
_context = context;
_window = window;
_shouldDisposeWindow = shouldDisposeWindow;
@ -68,13 +62,13 @@ namespace Ryujinx.Headless.SDL2.OpenGL
IntPtr windowHandle = SDL_CreateWindow("Ryujinx background context window", 0, 0, 1, 1, SDL_WindowFlags.SDL_WINDOW_OPENGL | SDL_WindowFlags.SDL_WINDOW_HIDDEN);
IntPtr context = SDL_GL_CreateContext(windowHandle);
GL.LoadBindings(new OpenToolkitBindingsContext());
GL api = GL.GetApi((_ => context));
CheckResult(SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 0));
CheckResult(SDL_GL_MakeCurrent(windowHandle, IntPtr.Zero));
return new SDL2OpenGLContext(context, windowHandle);
return new SDL2OpenGLContext(api, context, windowHandle);
}
public void MakeCurrent()
@ -111,6 +105,7 @@ namespace Ryujinx.Headless.SDL2.OpenGL
private readonly GraphicsDebugLevel _glLogLevel;
private SDL2OpenGLContext _openGLContext;
public GL Api => _openGLContext.Api;
public OpenGLWindow(
InputManager inputManager,
@ -142,15 +137,15 @@ namespace Ryujinx.Headless.SDL2.OpenGL
}
// NOTE: The window handle needs to be disposed by the thread that created it and is handled separately.
_openGLContext = new SDL2OpenGLContext(context, WindowHandle, false);
_openGLContext = new SDL2OpenGLContext(GL.GetApi((_ => context)), context, WindowHandle, false);
// First take exclusivity on the OpenGL context.
((OpenGLRenderer)Renderer).InitializeBackgroundContext(SDL2OpenGLContext.CreateBackgroundContext(_openGLContext));
_openGLContext.MakeCurrent();
GL.ClearColor(0, 0, 0, 1.0f);
GL.Clear(ClearBufferMask.ColorBufferBit);
_openGLContext.Api.ClearColor(0, 0, 0, 1.0f);
_openGLContext.Api.Clear(ClearBufferMask.ColorBufferBit);
SwapBuffers();
if (IsExclusiveFullscreen)

View file

@ -532,7 +532,8 @@ namespace Ryujinx.Headless.SDL2
preferredGpuId);
}
return new OpenGLRenderer();
var openGlWindow = window as OpenGLWindow;
return new OpenGLRenderer(openGlWindow.Api);
}
private static Switch InitializeEmulationContext(WindowBase window, IRenderer renderer, Options options)

View file

@ -823,7 +823,7 @@ namespace Ryujinx.Ava
}
else
{
renderer = new OpenGLRenderer();
renderer = new OpenGLRenderer((RendererHost.EmbeddedWindow as EmbeddedWindowOpenGL).CreateApi());
}
BackendThreading threadingMode = ConfigurationState.Instance.Graphics.BackendThreading;

View file

@ -1,9 +1,9 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.OpenGL;
using Ryujinx.UI.Common.Configuration;
using Silk.NET.OpenGL.Legacy;
using SPB.Graphics;
using SPB.Graphics.Exceptions;
using SPB.Graphics.OpenGL;
@ -44,6 +44,13 @@ namespace Ryujinx.Ava.UI.Renderer
throw new PlatformNotSupportedException();
}
Context.Initialize(_window);
Context.MakeCurrent(_window);
Context.MakeCurrent(null);
}
public GL CreateApi()
{
var flags = OpenGLContextFlags.Compat;
if (ConfigurationState.Instance.Logger.GraphicsDebugLevel != GraphicsDebugLevel.None)
{
@ -54,12 +61,7 @@ namespace Ryujinx.Ava.UI.Renderer
Context = PlatformHelper.CreateOpenGLContext(graphicsMode, 3, 3, flags);
Context.Initialize(_window);
Context.MakeCurrent(_window);
GL.LoadBindings(new OpenTKBindingsContext(Context.GetProcAddress));
Context.MakeCurrent(null);
return GL.GetApi(Context.GetProcAddress);
}
public void MakeCurrent(bool unbind = false, bool shouldThrow = true)

View file

@ -1,4 +1,3 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.OpenGL;
using SPB.Graphics;
using SPB.Graphics.OpenGL;
@ -38,9 +37,6 @@ namespace Ryujinx.Ava.UI.Renderer
context.Initialize(window);
context.MakeCurrent(window);
GL.LoadBindings(new OpenTKBindingsContext(context.GetProcAddress));
context.MakeCurrent(null);
return new SPBOpenGLContext(context, window);