Slowly but surely

This commit is contained in:
Isaac Marovitz 2024-05-08 22:36:19 -04:00
parent c1c0ccbaf5
commit 0d72c7650a
No known key found for this signature in database
GPG key ID: 97250B2B09A132E1
16 changed files with 253 additions and 237 deletions

View file

@ -6,9 +6,9 @@ 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(BufferTargetARB.CopyWriteBuffer, destination.ToInt32());
api.BindBuffer(BufferTargetARB.CopyWriteBuffer, destination.ToUInt32());
unsafe
{
@ -16,60 +16,60 @@ namespace Ryujinx.Graphics.OpenGL
valueArr[0] = value;
GL.ClearBufferSubData(
api.ClearBufferSubData(
BufferTargetARB.CopyWriteBuffer,
InternalFormat.Rgba8ui,
(IntPtr)offset,
(IntPtr)size,
SizedInternalFormat.Rgba8ui,
offset,
size,
PixelFormat.RgbaInteger,
PixelType.UnsignedByte,
(IntPtr)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 static BufferHandle Create(GL api, int size)
{
int handle = GL.GenBuffer();
uint handle = api.GenBuffer();
GL.BindBuffer(BufferTargetARB.CopyWriteBuffer, handle);
GL.BufferData(BufferTargetARB.CopyWriteBuffer, size, IntPtr.Zero, BufferUsageARB.DynamicDraw);
api.BindBuffer(BufferTargetARB.CopyWriteBuffer, handle);
api.BufferData(BufferTargetARB.CopyWriteBuffer, (uint)size, UIntPtr.Zero, BufferUsageARB.DynamicDraw);
return Handle.FromInt32<BufferHandle>(handle);
return Handle.FromUInt32<BufferHandle>(handle);
}
public static BufferHandle CreatePersistent(int size)
public static BufferHandle CreatePersistent(GL api, int size)
{
int handle = GL.GenBuffer();
uint handle = api.GenBuffer();
GL.BindBuffer(BufferTargetARB.CopyWriteBuffer, handle);
GL.BufferStorage(BufferTargetARB.CopyWriteBuffer, size, IntPtr.Zero,
api.BindBuffer(BufferTargetARB.CopyWriteBuffer, handle);
api.BufferStorage(BufferStorageTarget.CopyWriteBuffer, (uint)size, UIntPtr.Zero,
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(BufferTargetARB.CopyReadBuffer, source.ToInt32());
GL.BindBuffer(BufferTargetARB.CopyWriteBuffer, destination.ToInt32());
api.BindBuffer(BufferTargetARB.CopyReadBuffer, source.ToUInt32());
api.BindBuffer(BufferTargetARB.CopyWriteBuffer, destination.ToUInt32());
GL.CopyBufferSubData(
BufferTargetARB.CopyReadBuffer,
BufferTargetARB.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(GL api, OpenGLRenderer renderer, 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.
@ -86,36 +86,36 @@ namespace Ryujinx.Graphics.OpenGL
{
IntPtr target = renderer.PersistentBuffers.Default.GetHostArray(size);
GL.BindBuffer(BufferTargetARB.CopyReadBuffer, buffer.ToInt32());
api.BindBuffer(BufferTargetARB.CopyReadBuffer, buffer.ToUInt32());
GL.GetBufferSubData(BufferTargetARB.CopyReadBuffer, (IntPtr)offset, size, target);
api.GetBufferSubData(BufferTargetARB.CopyReadBuffer, offset, (uint)size, target);
return new PinnedSpan<byte>(target.ToPointer(), size);
}
}
public static void Resize(BufferHandle handle, int size)
public static void Resize(GL api, BufferHandle handle, int size)
{
GL.BindBuffer(BufferTargetARB.CopyWriteBuffer, handle.ToInt32());
GL.BufferData(BufferTargetARB.CopyWriteBuffer, size, IntPtr.Zero, BufferUsageARB.StreamCopy);
api.BindBuffer(BufferTargetARB.CopyWriteBuffer, handle.ToUInt32());
api.BufferData(BufferTargetARB.CopyWriteBuffer, (uint)size, UIntPtr.Zero, 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(BufferTargetARB.CopyWriteBuffer, buffer.ToInt32());
api.BindBuffer(BufferTargetARB.CopyWriteBuffer, buffer.ToUInt32());
unsafe
{
fixed (byte* ptr = data)
{
GL.BufferSubData(BufferTargetARB.CopyWriteBuffer, (IntPtr)offset, data.Length, (IntPtr)ptr);
api.BufferSubData(BufferTargetARB.CopyWriteBuffer, offset, (uint)data.Length, (IntPtr)ptr);
}
}
}
public static void Delete(BufferHandle buffer)
public static void Delete(GL api, BufferHandle buffer)
{
GL.DeleteBuffer(buffer.ToInt32());
api.DeleteBuffer(buffer.ToUInt32());
}
}
}

View file

@ -13,48 +13,48 @@ namespace Ryujinx.Graphics.OpenGL
private static int _counter;
public static void Initialize(GraphicsDebugLevel logLevel)
public static void Initialize(GL gl, GraphicsDebugLevel logLevel)
{
// Disable everything
GL.DebugMessageControl(DebugSource.DontCare, DebugType.DontCare, DebugSeverity.DontCare, 0, (int[])null, false);
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DontCare, DebugSeverity.DontCare, 0, (int[])null, false);
if (logLevel == GraphicsDebugLevel.None)
{
GL.Disable(EnableCap.DebugOutputSynchronous);
GL.DebugMessageCallback(null, IntPtr.Zero);
gl.Disable(EnableCap.DebugOutputSynchronous);
gl.DebugMessageCallback(null, IntPtr.Zero);
return;
}
GL.Enable(EnableCap.DebugOutputSynchronous);
gl.Enable(EnableCap.DebugOutputSynchronous);
if (logLevel == GraphicsDebugLevel.Error)
{
GL.DebugMessageControl(DebugSource.DontCare, DebugType.DebugTypeError, DebugSeverity.DontCare, 0, (int[])null, true);
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DebugTypeError, DebugSeverity.DontCare, 0, (int[])null, true);
}
else if (logLevel == GraphicsDebugLevel.Slowdowns)
{
GL.DebugMessageControl(DebugSource.DontCare, DebugType.DebugTypeError, DebugSeverity.DontCare, 0, (int[])null, true);
GL.DebugMessageControl(DebugSource.DontCare, DebugType.DebugTypePerformance, DebugSeverity.DontCare, 0, (int[])null, true);
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DebugTypeError, DebugSeverity.DontCare, 0, (int[])null, true);
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DebugTypePerformance, DebugSeverity.DontCare, 0, (int[])null, true);
}
else
{
GL.DebugMessageControl(DebugSource.DontCare, DebugType.DontCare, DebugSeverity.DontCare, 0, (int[])null, true);
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DontCare, DebugSeverity.DontCare, 0, (int[])null, true);
}
_counter = 0;
_debugCallback = GLDebugHandler;
GL.DebugMessageCallback(_debugCallback, IntPtr.Zero);
gl.DebugMessageCallback(_debugCallback, IntPtr.Zero);
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)
@ -89,21 +89,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(DebugSource.DebugSourceApplication, counter, dbgMsg.Length, dbgMsg);
gl.PushDebugGroup(DebugSource.DebugSourceApplication, counter, 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(DebugSource.DebugSourceApplication, type, id, severity, dbgMsg.Length, dbgMsg);
gl.DebugMessageInsert(DebugSource.DebugSourceApplication, type, id, severity, dbgMsg.Length, dbgMsg);
}
}
}

View file

@ -35,9 +35,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 +45,7 @@ void main()
private bool _initialized;
public void Draw(
GL api,
TextureView texture,
Sampler sampler,
float x0,
@ -56,9 +57,9 @@ void main()
float s1,
float t1)
{
EnsureInitialized();
EnsureInitialized(api);
GL.UseProgram(_programHandle);
api.UseProgram(_programHandle);
texture.Bind(0);
sampler.Bind(0);
@ -73,17 +74,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 +93,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

@ -552,9 +552,9 @@ namespace Ryujinx.Graphics.OpenGL
return All.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)

View file

@ -8,8 +8,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 +19,20 @@ namespace Ryujinx.Graphics.OpenGL
private int _colorsCount;
private bool _dualSourceBlend;
private GL _api;
public Framebuffer()
public Framebuffer(GL api)
{
Handle = GL.GenFramebuffer();
_clearFbHandle = GL.GenFramebuffer();
_colors = new TextureView[8];
_api = api;
}
public int Bind()
{
GL.BindFramebuffer(FramebufferTarget.Framebuffer, Handle);
_api.BindFramebuffer(FramebufferTarget.Framebuffer, Handle);
return Handle;
}
@ -44,7 +46,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 +56,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 +89,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,13 +101,13 @@ 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)
{
DrawBufferMode[] drawBuffers = new DrawBufferMode[colorsCount];
@ -114,7 +116,7 @@ namespace Ryujinx.Graphics.OpenGL
drawBuffers[index] = DrawBufferMode.ColorAttachment0 + index;
}
GL.DrawBuffers(colorsCount, drawBuffers);
api.DrawBuffers(colorsCount, drawBuffers);
}
private static FramebufferAttachment GetAttachment(Format format)
@ -153,7 +155,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 +167,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 +181,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,13 +193,13 @@ 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)
{
@ -219,14 +221,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

@ -131,13 +131,13 @@ namespace Ryujinx.Graphics.OpenGL
}
}
private static bool SupportsQuadsCheck()
private static bool SupportsQuadsCheck(GL api)
{
GL.GetError(); // Clear any existing error.
GL.Begin(PrimitiveType.Quads);
GL.End();
api.GetError(); // Clear any existing error.
api.Begin(PrimitiveType.Quads);
api.End();
return GL.GetError() == ErrorCode.NoError;
return api.GetError() == ErrorCode.NoError;
}
}
}

View file

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

View file

@ -7,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 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++)
{
@ -43,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, BufferAccessARB.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, BufferAccessARB.ReadWrite, format);
_api.BindImageTexture((uint)(baseBinding + i), _images[i].Handle, 0, true, 0, BufferAccessARB.ReadWrite, format);
}
}
}

View file

@ -5,26 +5,28 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
class Sampler : ISampler
{
public int Handle { get; private set; }
public uint Handle { get; private set; }
private GL _api;
public Sampler(SamplerCreateInfo info)
public Sampler(GL api, SamplerCreateInfo info)
{
Handle = GL.GenSampler();
_api = api;
Handle = _api.GenSampler();
GL.SamplerParameter(Handle, SamplerParameterI.MinFilter, (int)info.MinFilter.Convert());
GL.SamplerParameter(Handle, SamplerParameterI.MagFilter, (int)info.MagFilter.Convert());
_api.SamplerParameter(Handle, SamplerParameterI.MinFilter, (int)info.MinFilter.Convert());
_api.SamplerParameter(Handle, SamplerParameterI.MagFilter, (int)info.MagFilter.Convert());
if (HwCapabilities.SupportsSeamlessCubemapPerTexture)
{
GL.SamplerParameter(Handle, (SamplerParameterName)ArbSeamlessCubemapPerTexture.TextureCubeMapSeamless, info.SeamlessCubemap ? 1 : 0);
_api.SamplerParameter(Handle, GLEnum.TextureCubeMapSeamless, info.SeamlessCubemap ? 1 : 0);
}
GL.SamplerParameter(Handle, SamplerParameterI.WrapS, (int)info.AddressU.Convert());
GL.SamplerParameter(Handle, SamplerParameterI.WrapT, (int)info.AddressV.Convert());
GL.SamplerParameter(Handle, SamplerParameterI.WrapR, (int)info.AddressP.Convert());
_api.SamplerParameter(Handle, SamplerParameterI.WrapS, (int)info.AddressU.Convert());
_api.SamplerParameter(Handle, SamplerParameterI.WrapT, (int)info.AddressV.Convert());
_api.SamplerParameter(Handle, SamplerParameterI.WrapR, (int)info.AddressP.Convert());
GL.SamplerParameter(Handle, SamplerParameterI.CompareMode, (int)info.CompareMode.Convert());
GL.SamplerParameter(Handle, SamplerParameterI.CompareFunc, (int)info.CompareOp.Convert());
_api.SamplerParameter(Handle, SamplerParameterI.CompareMode, (int)info.CompareMode.Convert());
_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, SamplerParameterF.BorderColor, borderColor);
_api.SamplerParameter(Handle, SamplerParameterF.BorderColor, borderColor);
}
GL.SamplerParameter(Handle, SamplerParameterF.TextureMinLod, info.MinLod);
GL.SamplerParameter(Handle, SamplerParameterF.TextureMaxLod, info.MaxLod);
GL.SamplerParameter(Handle, SamplerParameterF.TextureLodBias, info.MipLodBias);
_api.SamplerParameter(Handle, SamplerParameterF.TextureMinLod, info.MinLod);
_api.SamplerParameter(Handle, SamplerParameterF.TextureMaxLod, info.MaxLod);
_api.SamplerParameter(Handle, SamplerParameterF.TextureLodBias, info.MipLodBias);
GL.SamplerParameter(Handle, SamplerParameterF.MaxAnisotropy, info.MaxAnisotropy);
_api.SamplerParameter(Handle, SamplerParameterF.MaxAnisotropy, info.MaxAnisotropy);
}
public void Bind(int unit)
public void Bind(uint unit)
{
GL.BindSampler(unit, Handle);
_api.BindSampler(unit, Handle);
}
public void Dispose()
{
if (Handle != 0)
{
GL.DeleteSampler(Handle);
_api.DeleteSampler(Handle);
Handle = 0;
}

View file

@ -1,4 +1,5 @@
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL;
namespace Ryujinx.Graphics.OpenGL.Image
{
@ -11,9 +12,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
private readonly TextureRef[] _textureRefs;
private 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

@ -5,7 +5,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
class TextureBase
{
public int Handle { get; protected set; }
public uint Handle { get; protected set; }
public TextureCreateInfo Info { get; }
@ -15,28 +15,31 @@ namespace Ryujinx.Graphics.OpenGL.Image
public Target Target => Info.Target;
public Format Format => Info.Format;
public TextureBase(TextureCreateInfo info)
private protected GL _api;
public TextureBase(GL api, TextureCreateInfo info)
{
_api = api;
Info = info;
Handle = GL.GenTexture();
Handle = _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);
_api.ActiveTexture((TextureUnit)((uint)TextureUnit.Texture0 + unit));
_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

@ -14,7 +14,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
private BufferHandle _buffer;
public TextureBuffer(OpenGLRenderer renderer, TextureCreateInfo info) : base(info)
public TextureBuffer(GL api, OpenGLRenderer renderer, TextureCreateInfo info) : base(api, info)
{
_renderer = renderer;
}
@ -41,7 +41,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
public PinnedSpan<byte> GetData()
{
return Buffer.GetData(_renderer, _buffer, _bufferOffset, _bufferSize);
return Buffer.GetData(_api, _renderer, _buffer, _bufferOffset, _bufferSize);
}
public PinnedSpan<byte> GetData(int layer, int level)
@ -59,7 +59,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
var dataSpan = data.Memory.Span;
Buffer.SetData(_buffer, _bufferOffset, dataSpan[..Math.Min(dataSpan.Length, _bufferSize)]);
Buffer.SetData(_api, _buffer, _bufferOffset, dataSpan[..Math.Min(dataSpan.Length, _bufferSize)]);
data.Dispose();
}
@ -97,14 +97,14 @@ namespace Ryujinx.Graphics.OpenGL.Image
SizedInternalFormat format = (SizedInternalFormat)FormatTable.GetFormatInfo(Info.Format).InternalFormat;
GL.TexBufferRange(TextureTarget.TextureBuffer, format, _buffer.ToInt32(), (IntPtr)buffer.Offset, buffer.Size);
_api.TexBufferRange(TextureTarget.TextureBuffer, format, _buffer.ToUInt32(), buffer.Offset, (uint)buffer.Size);
}
public void Dispose()
{
if (Handle != 0)
{
GL.DeleteTexture(Handle);
_api.DeleteTexture(Handle);
Handle = 0;
}

View file

@ -7,18 +7,20 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
class TextureCopy : IDisposable
{
private GL _api;
private readonly OpenGLRenderer _renderer;
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(GL api, OpenGLRenderer renderer)
{
_api = api;
_renderer = renderer;
IntermediatePool = new IntermediatePool(renderer);
}
@ -55,10 +57,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)_renderer.Pipeline).GetBoundFramebuffers();
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, GetSrcFramebufferLazy());
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, GetDstFramebufferLazy());
_api.BindFramebuffer(FramebufferTarget.ReadFramebuffer, GetSrcFramebufferLazy());
_api.BindFramebuffer(FramebufferTarget.DrawFramebuffer, GetDstFramebufferLazy());
if (srcLevel != 0)
{
@ -76,13 +78,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(_api, FramebufferTarget.ReadFramebuffer, src.Format, srcConverted.Handle, srcLevel + level, srcLayer + layer);
Attach(_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(_api, FramebufferTarget.ReadFramebuffer, src.Format, srcConverted.Handle, srcLevel + level);
Attach(_api, FramebufferTarget.DrawFramebuffer, dst.Format, dst.Handle, dstLevel + level);
}
ClearBufferMask mask = GetMask(src.Format);
@ -96,13 +98,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
? BlitFramebufferFilter.Linear
: BlitFramebufferFilter.Nearest;
GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
_api.ReadBuffer(ReadBufferMode.ColorAttachment0);
_api.DrawBuffer(DrawBufferMode.ColorAttachment0);
GL.Disable(EnableCap.RasterizerDiscard);
GL.Disable(IndexedEnableCap.ScissorTest, 0);
_api.Disable(EnableCap.RasterizerDiscard);
_api.Disable(EnableCap.ScissorTest, 0);
GL.BlitFramebuffer(
_api.BlitFramebuffer(
srcRegion.X1,
srcRegion.Y1,
srcRegion.X2,
@ -122,11 +124,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
}
Attach(FramebufferTarget.ReadFramebuffer, src.Format, 0);
Attach(FramebufferTarget.DrawFramebuffer, dst.Format, 0);
Attach(_api, FramebufferTarget.ReadFramebuffer, src.Format, 0);
Attach(_api, FramebufferTarget.DrawFramebuffer, dst.Format, 0);
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
_api.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
_api.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
((Pipeline)_renderer.Pipeline).RestoreScissor0Enable();
((Pipeline)_renderer.Pipeline).RestoreRasterizerDiscard();
@ -178,8 +180,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
TextureCreateInfo srcInfo = src.Info;
TextureCreateInfo dstInfo = dst.Info;
int srcHandle = src.Handle;
int dstHandle = dst.Handle;
uint srcHandle = (uint)src.Handle;
uint dstHandle = (uint)dst.Handle;
int srcWidth = srcInfo.Width;
int srcHeight = srcInfo.Height;
@ -240,7 +242,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (HwCapabilities.Vendor == HwCapabilities.GpuVendor.IntelWindows)
{
GL.CopyImageSubData(
_api.CopyImageSubData(
src.Storage.Handle,
src.Storage.Info.Target.ConvertToImageTarget(),
src.FirstLevel + srcLevel + level,
@ -253,13 +255,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
0,
0,
dst.FirstLayer + dstLayer,
copyWidth,
copyHeight,
depth);
(uint)copyWidth,
(uint)copyHeight,
(uint)depth);
}
else
{
GL.CopyImageSubData(
_api.CopyImageSubData(
srcHandle,
srcInfo.Target.ConvertToImageTarget(),
srcLevel + level,
@ -272,9 +274,9 @@ namespace Ryujinx.Graphics.OpenGL.Image
0,
0,
dstLayer,
copyWidth,
copyHeight,
depth);
(uint)copyWidth,
(uint)copyHeight,
(uint)depth);
}
}
@ -308,18 +310,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)
@ -348,16 +350,16 @@ namespace Ryujinx.Graphics.OpenGL.Image
EnsurePbo(from);
GL.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyPboHandle);
_api.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyPboHandle);
from.WriteToPbo(0, forceBgra: true);
GL.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
GL.BindBuffer(BufferTargetARB.PixelUnpackBuffer, _copyPboHandle);
_api.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
_api.BindBuffer(BufferTargetARB.PixelUnpackBuffer, _copyPboHandle);
to.ReadFromPbo(0, _copyPboSize);
GL.BindBuffer(BufferTargetARB.PixelUnpackBuffer, 0);
_api.BindBuffer(BufferTargetARB.PixelUnpackBuffer, 0);
return to;
}
@ -393,7 +395,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
EnsurePbo(from);
GL.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyPboHandle);
_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,39 +409,39 @@ 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);
_api.PixelStore(PixelStoreParameter.UnpackRowLength, unpackWidth);
_api.PixelStore(PixelStoreParameter.UnpackImageHeight, unpackHeight);
if (to.Info.IsCompressed)
{
GL.PixelStore(GLEnum.UnpackCompressedBlockWidth, to.Info.BlockWidth);
GL.PixelStore(GLEnum.UnpackCompressedBlockHeight, to.Info.BlockHeight);
GL.PixelStore(GLEnum.UnpackCompressedBlockDepth, 1);
GL.PixelStore(GLEnum.UnpackCompressedBlockSize, to.Info.BytesPerPixel);
_api.PixelStore(GLEnum.UnpackCompressedBlockWidth, to.Info.BlockWidth);
_api.PixelStore(GLEnum.UnpackCompressedBlockHeight, to.Info.BlockHeight);
_api.PixelStore(GLEnum.UnpackCompressedBlockDepth, 1);
_api.PixelStore(GLEnum.UnpackCompressedBlockSize, to.Info.BytesPerPixel);
}
}
GL.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
GL.BindBuffer(BufferTargetARB.PixelUnpackBuffer, _copyPboHandle);
_api.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
_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);
_api.PixelStore(PixelStoreParameter.UnpackRowLength, 0);
_api.PixelStore(PixelStoreParameter.UnpackImageHeight, 0);
if (to.Info.IsCompressed)
{
GL.PixelStore(GLEnum.UnpackCompressedBlockWidth, 0);
GL.PixelStore(GLEnum.UnpackCompressedBlockHeight, 0);
GL.PixelStore(GLEnum.UnpackCompressedBlockDepth, 0);
GL.PixelStore(GLEnum.UnpackCompressedBlockSize, 0);
_api.PixelStore(GLEnum.UnpackCompressedBlockWidth, 0);
_api.PixelStore(GLEnum.UnpackCompressedBlockHeight, 0);
_api.PixelStore(GLEnum.UnpackCompressedBlockDepth, 0);
_api.PixelStore(GLEnum.UnpackCompressedBlockSize, 0);
}
}
GL.BindBuffer(BufferTargetARB.PixelUnpackBuffer, 0);
_api.BindBuffer(BufferTargetARB.PixelUnpackBuffer, 0);
}
private void EnsurePbo(TextureView view)
@ -453,36 +455,36 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (_copyPboSize < requiredSize && _copyPboHandle != 0)
{
GL.DeleteBuffer(_copyPboHandle);
_api.DeleteBuffer(_copyPboHandle);
_copyPboHandle = 0;
}
if (_copyPboHandle == 0)
{
_copyPboHandle = GL.GenBuffer();
_copyPboHandle = _api.GenBuffer();
_copyPboSize = requiredSize;
GL.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyPboHandle);
GL.BufferData(BufferTargetARB.PixelPackBuffer, requiredSize, IntPtr.Zero, BufferUsageARB.DynamicCopy);
_api.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyPboHandle);
_api.BufferData(BufferTargetARB.PixelPackBuffer, (uint)requiredSize, IntPtr.Zero, BufferUsageARB.DynamicCopy);
}
}
private int GetSrcFramebufferLazy()
private uint GetSrcFramebufferLazy()
{
if (_srcFramebuffer == 0)
{
_srcFramebuffer = GL.GenFramebuffer();
_srcFramebuffer = _api.GenFramebuffer();
}
return _srcFramebuffer;
}
private int GetDstFramebufferLazy()
private uint GetDstFramebufferLazy()
{
if (_dstFramebuffer == 0)
{
_dstFramebuffer = GL.GenFramebuffer();
_dstFramebuffer = _api.GenFramebuffer();
}
return _dstFramebuffer;
@ -492,21 +494,21 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
if (_srcFramebuffer != 0)
{
GL.DeleteFramebuffer(_srcFramebuffer);
_api.DeleteFramebuffer(_srcFramebuffer);
_srcFramebuffer = 0;
}
if (_dstFramebuffer != 0)
{
GL.DeleteFramebuffer(_dstFramebuffer);
_api.DeleteFramebuffer(_dstFramebuffer);
_dstFramebuffer = 0;
}
if (_copyPboHandle != 0)
{
GL.DeleteBuffer(_copyPboHandle);
_api.DeleteBuffer(_copyPboHandle);
_copyPboHandle = 0;
}

View file

@ -11,6 +11,7 @@ namespace Ryujinx.Graphics.OpenGL
{
public sealed class OpenGLRenderer : IRenderer
{
private GL _api;
private readonly Pipeline _pipeline;
public IPipeline Pipeline => _pipeline;
@ -57,13 +58,13 @@ namespace Ryujinx.Graphics.OpenGL
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);
@ -71,7 +72,7 @@ namespace Ryujinx.Graphics.OpenGL
}
else
{
return Buffer.Create(size);
return Buffer.Create(_api, size);
}
}

View file

@ -38,8 +38,8 @@ namespace Ryujinx.Graphics.OpenGL
private float[] _viewportArray = Array.Empty<float>();
private double[] _depthRangeArray = Array.Empty<double>();
private int _boundDrawFramebuffer;
private int _boundReadFramebuffer;
private uint _boundDrawFramebuffer;
private uint _boundReadFramebuffer;
private CounterQueueEvent _activeConditionalRender;
@ -1496,7 +1496,7 @@ namespace Ryujinx.Graphics.OpenGL
}
}
internal (int drawHandle, int readHandle) GetBoundFramebuffers()
internal (uint drawHandle, uint readHandle) GetBoundFramebuffers()
{
if (BackgroundContextWorker.InBackground)
{