Compare commits

...

16 Commits

Author SHA1 Message Date
Isaac Marovitz 0a0e642132
Merge 4ec9793602 into a23d8cb92f 2024-05-10 03:34:17 +00:00
Isaac Marovitz 4ec9793602
Style 2024-05-09 23:34:11 -04:00
Isaac Marovitz bab7457b99
Fix some warnings 2024-05-09 23:10:13 -04:00
Isaac Marovitz 2b07d783c8
Formatting 2024-05-09 22:59:34 -04:00
Isaac Marovitz 3e422f020c
Hook up SDL2 and GTK 2024-05-09 22:59:08 -04:00
IsaacMarovitz e72bf35c03
Fix some stack overflows 2024-05-09 22:20:43 -04:00
Isaac Marovitz e584f8d37d
Ava Working? 2024-05-09 21:22:38 -04:00
Isaac Marovitz 5db3568305
OpenGL namespace is all done! 2024-05-09 21:13:22 -04:00
Isaac Marovitz 15978d9c55
Pipeline 2024-05-09 20:28:46 -04:00
Isaac Marovitz 0c88c23b30
Debugger, Pipeline 2024-05-09 20:04:29 -04:00
Isaac Marovitz 1d18ed2ba2
Program 2024-05-09 19:44:22 -04:00
Isaac Marovitz a9d0dd3893
Convert GetBinary 2024-05-09 19:34:19 -04:00
Isaac Marovitz 8df23211f6
Effects 2024-05-09 19:21:01 -04:00
Isaac Marovitz e46b671875
Cleanup IntPtr casts 2024-05-09 19:16:26 -04:00
Isaac Marovitz 38d900c932
PersistentBuffers & Sync 2024-05-09 19:13:37 -04:00
Isaac Marovitz 740842d600
TextureView 2024-05-09 19:00:02 -04:00
41 changed files with 808 additions and 702 deletions

View File

@ -39,6 +39,7 @@
<PackageVersion Include="shaderc.net" Version="0.1.0" />
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
<PackageVersion Include="Silk.NET.OpenGL.Legacy" Version="2.21.0" />
<PackageVersion Include="Silk.NET.OpenGL.Legacy.Extensions.ARB" Version="2.21.0" />
<PackageVersion Include="Silk.NET.OpenGL.Legacy.Extensions.EXT" Version="2.21.0" />
<PackageVersion Include="Silk.NET.OpenGL.Legacy.Extensions.NV" Version="2.21.0" />
<PackageVersion Include="Silk.NET.Vulkan" Version="2.16.0" />

View File

@ -1,5 +1,5 @@
using Silk.NET.OpenGL.Legacy;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
using System;
namespace Ryujinx.Graphics.OpenGL
@ -23,7 +23,7 @@ namespace Ryujinx.Graphics.OpenGL
size,
PixelFormat.RgbaInteger,
PixelType.UnsignedByte,
(IntPtr)valueArr);
valueArr);
}
}
@ -37,7 +37,7 @@ namespace Ryujinx.Graphics.OpenGL
uint handle = api.GenBuffer();
api.BindBuffer(BufferTargetARB.CopyWriteBuffer, handle);
api.BufferData(BufferTargetARB.CopyWriteBuffer, (uint)size, UIntPtr.Zero, BufferUsageARB.DynamicDraw);
api.BufferData(BufferTargetARB.CopyWriteBuffer, (uint)size, in UIntPtr.Zero, BufferUsageARB.DynamicDraw);
return Handle.FromUInt32<BufferHandle>(handle);
}
@ -47,7 +47,7 @@ namespace Ryujinx.Graphics.OpenGL
uint handle = api.GenBuffer();
api.BindBuffer(BufferTargetARB.CopyWriteBuffer, handle);
api.BufferStorage(BufferStorageTarget.CopyWriteBuffer, (uint)size, UIntPtr.Zero,
api.BufferStorage(BufferStorageTarget.CopyWriteBuffer, (uint)size, in UIntPtr.Zero,
BufferStorageMask.MapPersistentBit |
BufferStorageMask.MapCoherentBit |
BufferStorageMask.ClientStorageBit |
@ -78,7 +78,7 @@ namespace Ryujinx.Graphics.OpenGL
{
return new PinnedSpan<byte>(IntPtr.Add(ptr, offset).ToPointer(), size);
}
else if (HwCapabilities.UsePersistentBufferForFlush)
else if (gd.Capabilities.UsePersistentBufferForFlush)
{
return PinnedSpan<byte>.UnsafeFromSpan(gd.PersistentBuffers.Default.GetBufferData(buffer, offset, size));
}
@ -97,20 +97,13 @@ namespace Ryujinx.Graphics.OpenGL
public static void Resize(GL api, BufferHandle handle, int size)
{
api.BindBuffer(BufferTargetARB.CopyWriteBuffer, handle.ToUInt32());
api.BufferData(BufferTargetARB.CopyWriteBuffer, (uint)size, UIntPtr.Zero, BufferUsageARB.StreamCopy);
api.BufferData(BufferTargetARB.CopyWriteBuffer, (uint)size, in UIntPtr.Zero, BufferUsageARB.StreamCopy);
}
public static void SetData(GL api, BufferHandle buffer, int offset, ReadOnlySpan<byte> data)
{
api.BindBuffer(BufferTargetARB.CopyWriteBuffer, buffer.ToUInt32());
unsafe
{
fixed (byte* ptr = data)
{
api.BufferSubData(BufferTargetARB.CopyWriteBuffer, offset, (uint)data.Length, (IntPtr)ptr);
}
}
api.BufferSubData(BufferTargetARB.CopyWriteBuffer, offset, (uint)data.Length, data);
}
public static void Delete(GL api, BufferHandle buffer)

View File

@ -1,6 +1,6 @@
using Silk.NET.OpenGL.Legacy;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Silk.NET.OpenGL.Legacy;
using System;
using System.Runtime.InteropServices;
using System.Threading;
@ -16,12 +16,12 @@ namespace Ryujinx.Graphics.OpenGL
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, (uint[])null, false);
if (logLevel == GraphicsDebugLevel.None)
{
gl.Disable(EnableCap.DebugOutputSynchronous);
gl.DebugMessageCallback(null, IntPtr.Zero);
gl.DebugMessageCallback(null, in IntPtr.Zero);
return;
}
@ -30,22 +30,22 @@ namespace Ryujinx.Graphics.OpenGL
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, (uint[])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, (uint[])null, true);
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DebugTypePerformance, DebugSeverity.DontCare, 0, (uint[])null, true);
}
else
{
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DontCare, DebugSeverity.DontCare, 0, (int[])null, true);
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DontCare, DebugSeverity.DontCare, 0, (uint[])null, true);
}
_counter = 0;
_debugCallback = GLDebugHandler;
gl.DebugMessageCallback(_debugCallback, IntPtr.Zero);
gl.DebugMessageCallback(_debugCallback, in IntPtr.Zero);
Logger.Warning?.Print(LogClass.Gpu, "OpenGL Debugging is enabled. Performance will be negatively impacted.");
}
@ -61,7 +61,10 @@ namespace Ryujinx.Graphics.OpenGL
{
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");
}
@ -93,7 +96,7 @@ namespace Ryujinx.Graphics.OpenGL
{
int counter = Interlocked.Increment(ref _counter);
gl.PushDebugGroup(DebugSource.DebugSourceApplication, counter, dbgMsg.Length, dbgMsg);
gl.PushDebugGroup(DebugSource.DebugSourceApplication, (uint)counter, (uint)dbgMsg.Length, dbgMsg);
}
public static void PopGroup(GL gl)
@ -103,7 +106,7 @@ namespace Ryujinx.Graphics.OpenGL
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, (uint)id, severity, (uint)dbgMsg.Length, dbgMsg);
}
}
}

View File

@ -1,5 +1,5 @@
using Silk.NET.OpenGL.Legacy;
using Ryujinx.Graphics.OpenGL.Image;
using Silk.NET.OpenGL.Legacy;
using System;
using Sampler = Ryujinx.Graphics.OpenGL.Image.Sampler;

View File

@ -1,7 +1,7 @@
using Silk.NET.OpenGL.Legacy;
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;
@ -123,13 +123,13 @@ namespace Ryujinx.Graphics.OpenGL.Effects
uint previousProgram = (uint)_gd.Api.GetInteger(GetPName.CurrentProgram);
int previousUnit = _gd.Api.GetInteger(GetPName.ActiveTexture);
_gd.Api.ActiveTexture(TextureUnit.Texture0);
int previousTextureBinding = _gd.Api.GetInteger(GetPName.TextureBinding2D);
uint previousTextureBinding = (uint)_gd.Api.GetInteger(GetPName.TextureBinding2D);
_gd.Api.BindImageTexture(0, textureView.Handle, 0, false, 0, BufferAccessARB.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);
@ -156,7 +156,7 @@ namespace Ryujinx.Graphics.OpenGL.Effects
// Sharpening Pass
_gd.Api.UseProgram(_sharpeningShaderProgram);
_gd.Api.BindImageTexture(0, destinationTexture.Handle, 0, false, 0, BufferAccessARB.ReadWrite, SizedInternalFormat.Rgba8);
_gd.Api.BindImageTexture(0, destinationTexture.Handle, 0, false, 0, BufferAccessARB.ReadWrite, InternalFormat.Rgba8);
textureView.Bind(0);
_gd.Api.Uniform1(_inputUniform, 0);
_gd.Api.Uniform1(_outputUniform, 0);

View File

@ -1,6 +1,6 @@
using Silk.NET.OpenGL.Legacy;
using Ryujinx.Common;
using Ryujinx.Graphics.OpenGL.Image;
using Silk.NET.OpenGL.Legacy;
namespace Ryujinx.Graphics.OpenGL.Effects
{
@ -31,7 +31,7 @@ namespace Ryujinx.Graphics.OpenGL.Effects
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 = _gd.Api.GetUniformLocation(_shaderProgram, "invResolution");
_inputUniform = _gd.Api.GetUniformLocation(_shaderProgram, "inputTexture");
@ -49,21 +49,21 @@ namespace Ryujinx.Graphics.OpenGL.Effects
var textureView = _textureStorage.CreateView(view.Info, 0, 0) as TextureView;
int previousProgram = _gd.Api.GetInteger(GetPName.CurrentProgram);
uint previousProgram = (uint)_gd.Api.GetInteger(GetPName.CurrentProgram);
int previousUnit = _gd.Api.GetInteger(GetPName.ActiveTexture);
_gd.Api.ActiveTexture(TextureUnit.Texture0);
int previousTextureBinding = _gd.Api.GetInteger(GetPName.TextureBinding2D);
uint previousTextureBinding = (uint)_gd.Api.GetInteger(GetPName.TextureBinding2D);
_gd.Api.BindImageTexture(0, textureView.Handle, 0, false, 0, BufferAccessARB.ReadWrite, SizedInternalFormat.Rgba8);
_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);
_gd.Api.Uniform1(_inputUniform, 0);
_gd.Api.Uniform1(_outputUniform, 0);
_gd.Api.Uniform2(_resolutionUniform, (float)view.Width, (float)view.Height);
_gd.Api.Uniform2(_resolutionUniform, view.Width, view.Height);
_gd.Api.DispatchCompute(dispatchX, dispatchY, 1);
_gd.Api.UseProgram(previousProgram);
_gd.Api.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);

View File

@ -1,7 +1,7 @@
using Silk.NET.OpenGL.Legacy;
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
@ -93,13 +93,13 @@ 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;
@ -184,14 +184,14 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
var areaTexture = _areaTexture.DefaultView as TextureView;
var searchTexture = _searchTexture.DefaultView as TextureView;
var previousFramebuffer = _gd.Api.GetInteger(GetPName.DrawFramebufferBinding);
uint previousFramebuffer = (uint)_gd.Api.GetInteger(GetPName.DrawFramebufferBinding);
int previousUnit = _gd.Api.GetInteger(GetPName.ActiveTexture);
_gd.Api.ActiveTexture(TextureUnit.Texture0);
int previousTextureBinding0 = _gd.Api.GetInteger(GetPName.TextureBinding2D);
uint previousTextureBinding0 = (uint)_gd.Api.GetInteger(GetPName.TextureBinding2D);
_gd.Api.ActiveTexture(TextureUnit.Texture1);
int previousTextureBinding1 = _gd.Api.GetInteger(GetPName.TextureBinding2D);
uint previousTextureBinding1 = (uint)_gd.Api.GetInteger(GetPName.TextureBinding2D);
_gd.Api.ActiveTexture(TextureUnit.Texture2);
int previousTextureBinding2 = _gd.Api.GetInteger(GetPName.TextureBinding2D);
uint previousTextureBinding2 = (uint)_gd.Api.GetInteger(GetPName.TextureBinding2D);
var framebuffer = new Framebuffer(_gd.Api);
framebuffer.Bind();
@ -206,11 +206,11 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
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);
uint previousProgram = (uint)_gd.Api.GetInteger(GetPName.CurrentProgram);
_gd.Api.BindImageTexture(0, edgeOutput.Handle, 0, false, 0, BufferAccessARB.ReadWrite, SizedInternalFormat.Rgba8);
_gd.Api.BindImageTexture(0, edgeOutput.Handle, 0, false, 0, BufferAccessARB.ReadWrite, InternalFormat.Rgba8);
_gd.Api.UseProgram(_edgeShaderPrograms[Quality]);
view.Bind(0);
_gd.Api.Uniform1(_inputUniform, 0);
@ -219,7 +219,7 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
_gd.Api.DispatchCompute(dispatchX, dispatchY, 1);
_gd.Api.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);
_gd.Api.BindImageTexture(0, blendOutput.Handle, 0, false, 0, BufferAccessARB.ReadWrite, SizedInternalFormat.Rgba8);
_gd.Api.BindImageTexture(0, blendOutput.Handle, 0, false, 0, BufferAccessARB.ReadWrite, InternalFormat.Rgba8);
_gd.Api.UseProgram(_blendShaderPrograms[Quality]);
edgeOutput.Bind(0);
areaTexture.Bind(1);
@ -232,7 +232,7 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
_gd.Api.DispatchCompute(dispatchX, dispatchY, 1);
_gd.Api.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);
_gd.Api.BindImageTexture(0, textureView.Handle, 0, false, 0, BufferAccessARB.ReadWrite, SizedInternalFormat.Rgba8);
_gd.Api.BindImageTexture(0, textureView.Handle, 0, false, 0, BufferAccessARB.ReadWrite, InternalFormat.Rgba8);
_gd.Api.UseProgram(_neighbourShaderPrograms[Quality]);
view.Bind(0);
blendOutput.Bind(1);

View File

@ -1,9 +1,9 @@
using Silk.NET.OpenGL.Legacy;
using Silk.NET.OpenGL.Legacy.Extensions.NV;
using Silk.NET.OpenGL.Legacy.Extensions.EXT;
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
{
@ -14,7 +14,9 @@ namespace Ryujinx.Graphics.OpenGL
switch (mode)
{
case AddressMode.Clamp:
#pragma warning disable CS0618 // Type or member is obsolete
return TextureWrapMode.Clamp;
#pragma warning restore CS0618 // Type or member is obsolete
case AddressMode.Repeat:
return TextureWrapMode.Repeat;
case AddressMode.MirrorClamp:
@ -33,7 +35,9 @@ namespace Ryujinx.Graphics.OpenGL
Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(AddressMode)} enum value: {mode}.");
#pragma warning disable CS0618 // Type or member is obsolete
return TextureWrapMode.Clamp;
#pragma warning restore CS0618 // Type or member is obsolete
}
public static NV Convert(this AdvancedBlendOp op)
@ -451,7 +455,9 @@ namespace Ryujinx.Graphics.OpenGL
case PrimitiveTopology.Quads:
return PrimitiveType.Quads;
case PrimitiveTopology.QuadStrip:
#pragma warning disable CS0618 // Type or member is obsolete
return PrimitiveType.QuadStrip;
#pragma warning restore CS0618 // Type or member is obsolete
case PrimitiveTopology.Polygon:
return PrimitiveType.TriangleFan;
case PrimitiveTopology.LinesAdjacency:

View File

@ -1,5 +1,5 @@
using Silk.NET.OpenGL.Legacy;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
using System;
namespace Ryujinx.Graphics.OpenGL

View File

@ -1,6 +1,6 @@
using Silk.NET.OpenGL.Legacy;
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;
@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.OpenGL
private int _colorsCount;
private bool _dualSourceBlend;
private GL _api;
private readonly GL _api;
public Framebuffer(GL api)
{

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(GetPName.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 Silk.NET.OpenGL.Legacy;
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(GLEnum.MaxComputeSharedMemorySize));
private static readonly Lazy<int> _storageBufferOffsetAlignment = new(() => GetLimit(GLEnum.ShaderStorageBufferOffsetAlignment));
private static readonly Lazy<int> _textureBufferOffsetAlignment = new(() => GetLimit(GLEnum.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)GLEnum.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(GLEnum 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 api)
{
api.GetError(); // Clear any existing error.
api.Begin(PrimitiveType.Quads);
api.End();
return api.GetError() == ErrorCode.NoError;
}
}
}

View File

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

View File

@ -1,5 +1,5 @@
using Silk.NET.OpenGL.Legacy;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
namespace Ryujinx.Graphics.OpenGL.Image
{

View File

@ -1,32 +1,32 @@
using Silk.NET.OpenGL.Legacy;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
namespace Ryujinx.Graphics.OpenGL.Image
{
class Sampler : ISampler
{
public uint Handle { get; private set; }
private readonly GL _api;
private readonly OpenGLRenderer _gd;
public Sampler(GL api, SamplerCreateInfo info)
public Sampler(OpenGLRenderer gd, SamplerCreateInfo info)
{
_api = api;
Handle = _api.GenSampler();
_gd = gd;
Handle = _gd.Api.GenSampler();
_api.SamplerParameter(Handle, SamplerParameterI.MinFilter, (int)info.MinFilter.Convert());
_api.SamplerParameter(Handle, SamplerParameterI.MagFilter, (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)
{
_api.SamplerParameter(Handle, GLEnum.TextureCubeMapSeamless, info.SeamlessCubemap ? 1 : 0);
_gd.Api.SamplerParameter(Handle, GLEnum.TextureCubeMapSeamless, info.SeamlessCubemap ? 1 : 0);
}
_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());
_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());
_api.SamplerParameter(Handle, SamplerParameterI.CompareMode, (int)info.CompareMode.Convert());
_api.SamplerParameter(Handle, SamplerParameterI.CompareFunc, (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
{
@ -38,26 +38,26 @@ namespace Ryujinx.Graphics.OpenGL.Image
info.BorderColor.Alpha,
};
_api.SamplerParameter(Handle, SamplerParameterF.BorderColor, borderColor);
_gd.Api.SamplerParameter(Handle, SamplerParameterF.BorderColor, borderColor);
}
_api.SamplerParameter(Handle, SamplerParameterF.MinLod, info.MinLod);
_api.SamplerParameter(Handle, SamplerParameterF.MaxLod, info.MaxLod);
_api.SamplerParameter(Handle, SamplerParameterF.LodBias, 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);
_api.SamplerParameter(Handle, SamplerParameterF.MaxAnisotropy, info.MaxAnisotropy);
_gd.Api.SamplerParameter(Handle, SamplerParameterF.MaxAnisotropy, info.MaxAnisotropy);
}
public void Bind(uint unit)
{
_api.BindSampler(unit, Handle);
_gd.Api.BindSampler(unit, Handle);
}
public void Dispose()
{
if (Handle != 0)
{
_api.DeleteSampler(Handle);
_gd.Api.DeleteSampler(Handle);
Handle = 0;
}

View File

@ -1,5 +1,5 @@
using Silk.NET.OpenGL.Legacy;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
namespace Ryujinx.Graphics.OpenGL.Image
{

View File

@ -1,5 +1,5 @@
using Silk.NET.OpenGL.Legacy;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
using System;
using System.Buffers;

View File

@ -1,6 +1,6 @@
using Silk.NET.OpenGL.Legacy;
using Ryujinx.Common;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
using System;
namespace Ryujinx.Graphics.OpenGL.Image
@ -238,7 +238,7 @@ 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)
{
_gd.Api.CopyImageSubData(
src.Storage.Handle,
@ -464,7 +464,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
_copyPboSize = requiredSize;
_gd.Api.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyPboHandle);
_gd.Api.BufferData(BufferTargetARB.PixelPackBuffer, (uint)requiredSize, IntPtr.Zero, BufferUsageARB.DynamicCopy);
_gd.Api.BufferData(BufferTargetARB.PixelPackBuffer, (uint)requiredSize, in IntPtr.Zero, BufferUsageARB.DynamicCopy);
}
}

View File

@ -1,5 +1,5 @@
using Silk.NET.OpenGL.Legacy;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
using System;
using System.Numerics;

View File

@ -1,6 +1,6 @@
using Silk.NET.OpenGL.Legacy;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
namespace Ryujinx.Graphics.OpenGL.Image
{

View File

@ -1,6 +1,6 @@
using Silk.NET.OpenGL.Legacy;
using Ryujinx.Common;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
using System;
using System.Buffers;
using System.Diagnostics;
@ -101,15 +101,15 @@ namespace Ryujinx.Graphics.OpenGL.Image
_gd.Api.TexParameter(target, TextureParameterName.DepthStencilTextureMode, (int)Info.DepthStencilMode.Convert());
}
public ITexture CreateView(TextureCreateInfo info, uint firstLayer, uint firstLevel)
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, uint firstLayer, uint firstLevel)
public void CopyTo(ITexture destination, int firstLayer, int firstLevel)
{
TextureView destinationView = (TextureView)destination;
@ -118,18 +118,18 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (dstIsMultisample != srcIsMultisample && Info.Format.IsDepthOrStencil())
{
uint 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)
{
uint layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
_gd.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)
{
uint layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
_gd.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)
{
@ -228,7 +228,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
1);
_gd.TextureCopy.Copy(this, intermmediate, srcRegion, dstRegion, false);
_gd.TextureCopy.Copy(intermmediate, destinationView, dstRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, layers, 1);
_gd.TextureCopy.Copy(intermmediate, destinationView, dstRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, (int)layers, 1);
}
else
{
@ -252,7 +252,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
1);
_gd.TextureCopy.Copy(this, intermmediate, srcRegion, srcRegion, false);
_gd.TextureCopy.Copy(intermmediate, destinationView, srcRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, layers, 1);
_gd.TextureCopy.Copy(intermmediate, destinationView, srcRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, (int)layers, 1);
}
}
@ -273,7 +273,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
ReadOnlySpan<byte> data;
if (HwCapabilities.UsePersistentBufferForFlush)
if (_gd.Capabilities.UsePersistentBufferForFlush)
{
data = _gd.PersistentBuffers.Default.GetTextureData(this, size);
}
@ -298,7 +298,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
int size = Info.GetMipSize(level);
if (HwCapabilities.UsePersistentBufferForFlush)
if (_gd.Capabilities.UsePersistentBufferForFlush)
{
return PinnedSpan<byte>.UnsafeFromSpan(_gd.PersistentBuffers.Default.GetTextureData(this, size, layer, level));
}
@ -344,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();
@ -364,15 +364,37 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (format.IsCompressed)
{
_gd.Api.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)
{
_gd.Api.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
{
_gd.Api.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
@ -387,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();
@ -433,11 +455,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (format.IsCompressed)
{
_gd.Api.GetCompressedTexImage(target + face, level, data + faceOffset);
_gd.Api.GetCompressedTexImage(target + face, level, (void*)(data + faceOffset));
}
else
{
_gd.Api.GetTexImage(target + face, level, pixelFormat, pixelType, data + faceOffset);
_gd.Api.GetTexImage(target + face, level, pixelFormat, pixelType, (void*)(data + faceOffset));
}
}
@ -532,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();
@ -552,7 +574,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
(uint)width,
(InternalFormat)format.PixelFormat,
(uint)mipSize,
data);
(void*)data);
}
else
{
@ -563,7 +585,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
(uint)width,
format.PixelFormat,
format.PixelType,
data);
(void*)data);
}
break;
@ -579,7 +601,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
1,
(InternalFormat)format.PixelFormat,
(uint)mipSize,
data);
(void*)data);
}
else
{
@ -592,7 +614,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
1,
format.PixelFormat,
format.PixelType,
data);
(void*)data);
}
break;
@ -608,7 +630,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
(uint)height,
(InternalFormat)format.PixelFormat,
(uint)mipSize,
data);
(void*)data);
}
else
{
@ -621,7 +643,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
(uint)height,
format.PixelFormat,
format.PixelType,
data);
(void*)data);
}
break;
@ -641,7 +663,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
1,
(InternalFormat)format.PixelFormat,
(uint)mipSize,
data);
(void*)data);
}
else
{
@ -656,7 +678,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
1,
format.PixelFormat,
format.PixelType,
data);
(void*)data);
}
break;
@ -672,7 +694,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
(uint)height,
(InternalFormat)format.PixelFormat,
(uint)mipSize,
data);
(void*)data);
}
else
{
@ -685,19 +707,19 @@ namespace Ryujinx.Graphics.OpenGL.Image
(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();
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)
{
_gd.Api.ActiveTexture(TextureUnit.Texture0);
_gd.Api.BindTexture(target, Storage.Handle);
@ -710,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;
@ -738,9 +760,9 @@ namespace Ryujinx.Graphics.OpenGL.Image
level,
0,
width,
format.PixelFormat,
mipSize,
data);
(InternalFormat)format.PixelFormat,
(uint)mipSize,
(void*)data);
}
else
{
@ -751,7 +773,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
width,
format.PixelFormat,
format.PixelType,
data);
(void*)data);
}
break;
@ -766,9 +788,9 @@ namespace Ryujinx.Graphics.OpenGL.Image
0,
width,
height,
format.PixelFormat,
mipSize,
data);
(InternalFormat)format.PixelFormat,
(uint)mipSize,
(void*)data);
}
else
{
@ -781,7 +803,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
height,
format.PixelFormat,
format.PixelType,
data);
(void*)data);
}
break;
@ -799,9 +821,9 @@ namespace Ryujinx.Graphics.OpenGL.Image
width,
height,
depth,
format.PixelFormat,
mipSize,
data);
(InternalFormat)format.PixelFormat,
(uint)mipSize,
(void*)data);
}
else
{
@ -816,7 +838,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
depth,
format.PixelFormat,
format.PixelType,
data);
(void*)data);
}
break;
@ -829,27 +851,27 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
_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
{
_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;

View File

@ -1,11 +1,13 @@
using Silk.NET.OpenGL.Legacy;
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
@ -39,6 +41,8 @@ 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; }
@ -48,15 +52,15 @@ namespace Ryujinx.Graphics.OpenGL
public OpenGLRenderer(GL api)
{
Api = api;
_pipeline = new Pipeline(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(Api);
PersistentBuffers = new PersistentBuffers();
_sync = new Sync(this);
PersistentBuffers = new PersistentBuffers(Api);
ResourcePool = new ResourcePool();
}
@ -100,12 +104,12 @@ namespace Ryujinx.Graphics.OpenGL
public IProgram CreateProgram(ShaderSource[] shaders, ShaderInfo info)
{
return new Program(Api, shaders, info.FragmentOutputMap);
return new Program(this, shaders, info.FragmentOutputMap);
}
public ISampler CreateSampler(SamplerCreateInfo info)
{
return new Sampler(Api, info);
return new Sampler(this, info);
}
public ITexture CreateTexture(TextureCreateInfo info)
@ -144,9 +148,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,
@ -155,9 +159,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,
@ -167,39 +171,39 @@ 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,
supportsNonConstantTextureOffset: Capabilities.SupportsNonConstantTextureOffset,
supportsScaledVertexFormats: true,
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.
}
@ -228,11 +232,15 @@ namespace Ryujinx.Graphics.OpenGL
{
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();
@ -240,15 +248,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.
// should already have the desired behaviour when outputs are not clamped.
Api.ClampColor(ClampColorTargetARB.FragmentColorArb, ClampColorModeARB.False);
}
private void PrintGpuInformation()
private void LoadFeatures()
{
GpuVendor = Api.GetString(StringName.Vendor);
GpuRenderer = Api.GetString(StringName.Renderer);
GpuVersion = Api.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})");
}
@ -292,7 +331,7 @@ namespace Ryujinx.Graphics.OpenGL
public IProgram LoadProgramBinary(byte[] programBinary, bool hasFragmentShader, ShaderInfo info)
{
return new Program(Api, 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 Silk.NET.OpenGL.Legacy;
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(BufferTargetARB.CopyWriteBuffer, handle.ToUInt32());
IntPtr ptr = GL.MapBufferRange(BufferTargetARB.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(BufferTargetARB.CopyWriteBuffer, handle.ToUInt32());
GL.UnmapBuffer(BufferTargetARB.CopyWriteBuffer);
_api.BindBuffer(BufferTargetARB.CopyWriteBuffer, handle.ToUInt32());
_api.UnmapBuffer(BufferTargetARB.CopyWriteBuffer);
_maps.Remove(handle);
}
@ -51,6 +59,7 @@ namespace Ryujinx.Graphics.OpenGL
class PersistentBuffer : IDisposable
{
private readonly GL _api;
private IntPtr _bufferMap;
private uint _copyBufferHandle;
private int _copyBufferSize;
@ -58,24 +67,29 @@ namespace Ryujinx.Graphics.OpenGL
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(BufferTargetARB.CopyWriteBuffer, _copyBufferHandle);
GL.BufferStorage(BufferTargetARB.CopyWriteBuffer, requiredSize, IntPtr.Zero, BufferStorageFlags.MapReadBit | BufferStorageFlags.MapPersistentBit);
_api.BindBuffer(BufferTargetARB.CopyWriteBuffer, _copyBufferHandle);
_api.BufferStorage(BufferStorageTarget.CopyWriteBuffer, (uint)requiredSize, in IntPtr.Zero, BufferStorageMask.MapReadBit | BufferStorageMask.MapPersistentBit);
_bufferMap = GL.MapBufferRange(BufferTargetARB.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(MemoryBarrierMask.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(BufferTargetARB.PixelPackBuffer, _copyBufferHandle);
_api.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyBufferHandle);
view.WriteToPbo(0, false);
GL.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
_api.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
Sync();
@ -125,11 +139,11 @@ namespace Ryujinx.Graphics.OpenGL
{
EnsureBuffer(size);
GL.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyBufferHandle);
_api.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyBufferHandle);
int offset = view.WriteToPbo2D(0, layer, level);
GL.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
_api.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
Sync();
@ -140,12 +154,12 @@ namespace Ryujinx.Graphics.OpenGL
{
EnsureBuffer(size);
GL.BindBuffer(BufferTargetARB.CopyReadBuffer, buffer.ToUInt32());
GL.BindBuffer(BufferTargetARB.CopyWriteBuffer, _copyBufferHandle);
_api.BindBuffer(BufferTargetARB.CopyReadBuffer, buffer.ToUInt32());
_api.BindBuffer(BufferTargetARB.CopyWriteBuffer, _copyBufferHandle);
GL.CopyBufferSubData(BufferTargetARB.CopyReadBuffer, BufferTargetARB.CopyWriteBuffer, (IntPtr)offset, IntPtr.Zero, size);
_api.CopyBufferSubData(CopyBufferSubDataTarget.CopyReadBuffer, CopyBufferSubDataTarget.CopyWriteBuffer, offset, IntPtr.Zero, (uint)size);
GL.BindBuffer(BufferTargetARB.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 Silk.NET.OpenGL.Legacy;
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;
@ -27,18 +28,18 @@ namespace Ryujinx.Graphics.OpenGL
}
}
private readonly GL _api;
private readonly OpenGLRenderer _gd;
private ProgramLinkStatus _status = ProgramLinkStatus.Incomplete;
private uint[] _shaderHandles;
public int FragmentOutputMap { get; }
public Program(GL api, ShaderSource[] shaders, int fragmentOutputMap)
public unsafe Program(OpenGLRenderer gd, ShaderSource[] shaders, int fragmentOutputMap)
{
_api = api;
Handle = _api.CreateProgram();
_gd = gd;
Handle = _gd.Api.CreateProgram();
_api.ProgramParameter(Handle, ProgramParameterPName.BinaryRetrievableHint, 1);
_gd.Api.ProgramParameter(Handle, ProgramParameterPName.BinaryRetrievableHint, 1);
_shaderHandles = new uint[shaders.Length];
bool hasFragmentShader = false;
@ -52,34 +53,37 @@ namespace Ryujinx.Graphics.OpenGL
hasFragmentShader = true;
}
uint shaderHandle = _api.CreateShader(shader.Stage.Convert());
uint shaderHandle = _gd.Api.CreateShader(shader.Stage.Convert());
switch (shader.Language)
{
case TargetLanguage.Glsl:
_api.ShaderSource(shaderHandle, shader.Code);
_api.CompileShader(shaderHandle);
_gd.Api.ShaderSource(shaderHandle, shader.Code);
_gd.Api.CompileShader(shaderHandle);
break;
case TargetLanguage.Spirv:
_api.ShaderBinary(1, ref shaderHandle, ShaderBinaryFormat.ShaderBinaryFormatSpirV, shader.BinaryCode, shader.BinaryCode.Length);
_api.SpecializeShader(shaderHandle, "main", 0, (int[])null, (int[])null);
fixed (byte* ptr = shader.BinaryCode.AsSpan())
{
_gd.Api.ShaderBinary(1, in shaderHandle, ShaderBinaryFormat.ShaderBinaryFormatSpirV, ptr, (uint)shader.BinaryCode.Length);
}
_gd.Api.SpecializeShader(shaderHandle, "main", 0, (uint[])null, (uint[])null);
break;
}
_api.AttachShader(Handle, shaderHandle);
_gd.Api.AttachShader(Handle, shaderHandle);
_shaderHandles[index] = shaderHandle;
}
_api.LinkProgram(Handle);
_gd.Api.LinkProgram(Handle);
FragmentOutputMap = hasFragmentShader ? fragmentOutputMap : 0;
}
public Program(GL api, ReadOnlySpan<byte> code, bool hasFragmentShader, int fragmentOutputMap)
public Program(OpenGLRenderer gd, ReadOnlySpan<byte> code, bool hasFragmentShader, int fragmentOutputMap)
{
_api = api;
Handle = _api.CreateProgram();
_gd = gd;
Handle = _gd.Api.CreateProgram();
if (code.Length >= 4)
{
@ -89,7 +93,7 @@ namespace Ryujinx.Graphics.OpenGL
{
fixed (byte* ptr = code)
{
_api.ProgramBinary(Handle, binaryFormat, (IntPtr)ptr, code.Length - 4);
_gd.Api.ProgramBinary(Handle, (GLEnum)binaryFormat, ptr, (uint)code.Length - 4);
}
}
}
@ -99,14 +103,14 @@ namespace Ryujinx.Graphics.OpenGL
public void Bind()
{
_api.UseProgram(Handle);
_gd.Api.UseProgram(Handle);
}
public ProgramLinkStatus CheckProgramLink(bool blocking)
{
if (!blocking && HwCapabilities.SupportsParallelShaderCompile)
if (!blocking && _gd.Capabilities.SupportsParallelShaderCompile)
{
_api.GetProgram(Handle, (GetProgramParameterName)ArbParallelShaderCompile.CompletionStatusArb, out int completed);
_gd.Api.GetProgram(Handle, (GLEnum)ARB.CompletionStatusArb, out int completed);
if (completed == 0)
{
@ -114,14 +118,14 @@ namespace Ryujinx.Graphics.OpenGL
}
}
_api.GetProgram(Handle, ProgramPropertyARB.LinkStatus, out int status);
_gd.Api.GetProgram(Handle, ProgramPropertyARB.LinkStatus, out int status);
DeleteShaders();
if (status == 0)
{
_status = ProgramLinkStatus.Failure;
string log = _api.GetProgramInfoLog(Handle);
string log = _gd.Api.GetProgramInfoLog(Handle);
if (log.Length > MaxShaderLogLength)
{
@ -138,15 +142,19 @@ namespace Ryujinx.Graphics.OpenGL
return _status;
}
public byte[] GetBinary()
public unsafe byte[] GetBinary()
{
_api.GetProgram(Handle, ProgramPropertyARB.ProgramBinaryLength, out int size);
_gd.Api.GetProgram(Handle, ProgramPropertyARB.ProgramBinaryLength, out int size);
byte[] data = new byte[size + 4];
byte[] data = new byte[size];
GLEnum binFormat;
_api.GetProgramBinary(Handle, (uint)size, out _, out GLEnum binFormat, data);
fixed (byte* ptr = data)
{
_gd.Api.GetProgramBinary(Handle, (uint)size, out _, out binFormat, ptr);
}
BinaryPrimitives.WriteInt32LittleEndian(data.AsSpan(size, 4), (int)binFormat);
BinaryPrimitives.WriteInt32LittleEndian(data, (int)binFormat);
return data;
}
@ -157,8 +165,8 @@ namespace Ryujinx.Graphics.OpenGL
{
foreach (uint shaderHandle in _shaderHandles)
{
_api.DetachShader(Handle, shaderHandle);
_api.DeleteShader(shaderHandle);
_gd.Api.DetachShader(Handle, shaderHandle);
_gd.Api.DeleteShader(shaderHandle);
}
_shaderHandles = null;
@ -170,7 +178,7 @@ namespace Ryujinx.Graphics.OpenGL
if (Handle != 0)
{
DeleteShaders();
_api.DeleteProgram(Handle);
_gd.Api.DeleteProgram(Handle);
Handle = 0;
}

View File

@ -1,5 +1,5 @@
using Silk.NET.OpenGL.Legacy;
using Ryujinx.Common.Logging;
using Silk.NET.OpenGL.Legacy;
using System;
using System.Runtime.InteropServices;
using System.Threading;
@ -27,16 +27,11 @@ namespace Ryujinx.Graphics.OpenGL.Queries
_type = type;
_api.BindBuffer(BufferTargetARB.QueryBuffer, _buffer);
_api.BufferStorage(BufferStorageTarget.QueryBuffer, sizeof(long), DefaultValue, BufferStorageMask.MapReadBit | BufferStorageMask.MapWriteBit | BufferStorageMask.MapPersistentBit);
unsafe
{
long defaultValue = DefaultValue;
_api.BufferStorage(BufferStorageTarget.QueryBuffer, sizeof(long), (IntPtr)(&defaultValue), BufferStorageMask.MapReadBit | BufferStorageMask.MapWriteBit | BufferStorageMask.MapPersistentBit);
}
unsafe
{
_bufferMap = new IntPtr(_api.MapBufferRange(BufferTargetARB.QueryBuffer, IntPtr.Zero, sizeof(long), MapBufferAccessMask.ReadBit | MapBufferAccessMask.WriteBit | MapBufferAccessMask.PersistentBit));
_bufferMap = (IntPtr)_api.MapBufferRange(BufferTargetARB.QueryBuffer, IntPtr.Zero, sizeof(long), MapBufferAccessMask.ReadBit | MapBufferAccessMask.WriteBit | MapBufferAccessMask.PersistentBit);
}
}
@ -60,7 +55,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
_api.BindBuffer(BufferTargetARB.QueryBuffer, _buffer);
Marshal.WriteInt64(_bufferMap, -1L);
_api.GetQueryObject(Query,QueryObjectParameterName.Result, (long*)0);
_api.GetQueryObject(Query, QueryObjectParameterName.Result, (long*)0);
_api.MemoryBarrier(MemoryBarrierMask.QueryBufferBarrierBit | MemoryBarrierMask.ClientMappedBufferBarrierBit);
}
else

View File

@ -1,5 +1,5 @@
using Silk.NET.OpenGL.Legacy;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
using System;
using System.Collections.Generic;
using System.Threading;

View File

@ -1,5 +1,5 @@
using Silk.NET.OpenGL.Legacy;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
using System;
using System.Threading;

View File

@ -7,6 +7,7 @@
<ItemGroup>
<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>

View File

@ -1,5 +1,5 @@
using Silk.NET.OpenGL.Legacy;
using Ryujinx.Common.Logging;
using Silk.NET.OpenGL.Legacy;
using System;
using System.Collections.Generic;
using System.Linq;
@ -14,15 +14,15 @@ namespace Ryujinx.Graphics.OpenGL
public IntPtr Handle;
}
private ulong _firstHandle = 0;
private static SyncBehaviorFlags SyncFlags => HwCapabilities.RequiresSyncFlush ? SyncBehaviorFlags.None : SyncBehaviorFlags.SyncFlushCommandsBit;
private ulong _firstHandle;
private SyncObjectMask SyncFlags => _gd.Capabilities.RequiresSyncFlush ? 0 : SyncObjectMask.Bit;
private readonly List<SyncHandle> _handles = new();
private readonly GL _api;
private readonly OpenGLRenderer _gd;
public Sync(GL api)
public Sync(OpenGLRenderer gd)
{
_api = api;
_gd = gd;
}
public void Create(ulong id)
@ -30,14 +30,14 @@ namespace Ryujinx.Graphics.OpenGL
SyncHandle handle = new()
{
ID = id,
Handle = _api.FenceSync(SyncCondition.SyncGpuCommandsComplete, SyncBehaviorFlags.None),
Handle = _gd.Api.FenceSync(SyncCondition.SyncGpuCommandsComplete, SyncBehaviorFlags.None),
};
if (HwCapabilities.RequiresSyncFlush)
if (_gd.Capabilities.RequiresSyncFlush)
{
// Force commands to flush up to the syncpoint.
_api.ClientWaitSync(handle.Handle, SyncBehaviorFlags.SyncFlushCommandsBit, 0);
_gd.Api.ClientWaitSync(handle.Handle, SyncObjectMask.Bit, 0);
}
lock (_handles)
@ -63,7 +63,7 @@ namespace Ryujinx.Graphics.OpenGL
if (handle.ID > lastHandle)
{
GLEnum syncResult = _api.ClientWaitSync(handle.Handle, SyncFlags, 0);
GLEnum syncResult = _gd.Api.ClientWaitSync(handle.Handle, SyncFlags, 0);
if (syncResult == GLEnum.AlreadySignaled)
{
@ -107,7 +107,7 @@ namespace Ryujinx.Graphics.OpenGL
return;
}
GLEnum syncResult = _api.ClientWaitSync(result.Handle, SyncFlags, 1000000000);
GLEnum syncResult = _gd.Api.ClientWaitSync(result.Handle, SyncFlags, 1000000000);
if (syncResult == GLEnum.TimeoutExpired)
{
@ -134,7 +134,7 @@ namespace Ryujinx.Graphics.OpenGL
break;
}
GLEnum syncResult = _api.ClientWaitSync(first.Handle, SyncFlags, 0);
GLEnum syncResult = _gd.Api.ClientWaitSync(first.Handle, SyncFlags, 0);
if (syncResult == GLEnum.AlreadySignaled)
{
@ -145,7 +145,7 @@ namespace Ryujinx.Graphics.OpenGL
{
_firstHandle = first.ID + 1;
_handles.RemoveAt(0);
_api.DeleteSync(first.Handle);
_gd.Api.DeleteSync(first.Handle);
first.Handle = IntPtr.Zero;
}
}
@ -166,7 +166,7 @@ namespace Ryujinx.Graphics.OpenGL
{
lock (handle)
{
_api.DeleteSync(handle.Handle);
_gd.Api.DeleteSync(handle.Handle);
handle.Handle = IntPtr.Zero;
}
}

View File

@ -1,5 +1,5 @@
using Silk.NET.OpenGL.Legacy;
using Ryujinx.Graphics.GAL;
using Silk.NET.OpenGL.Legacy;
using System;
using System.Numerics;
using System.Runtime.CompilerServices;

View File

@ -1,8 +1,8 @@
using Silk.NET.OpenGL.Legacy;
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

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 Silk.NET.OpenGL.Legacy;
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,5 +1,5 @@
using Silk.NET.OpenGL.Legacy;
using Ryujinx.Graphics.OpenGL;
using Silk.NET.OpenGL.Legacy;
using SPB.Graphics;
using SPB.Graphics.OpenGL;
using SPB.Platform;
@ -39,7 +39,7 @@ namespace Ryujinx.UI
context.Initialize(window);
context.MakeCurrent(window);
GL.LoadBindings(new OpenToolkitBindingsContext(context));
GL api = GL.GetApi(context.GetProcAddress);
context.MakeCurrent(null);

View File

@ -1,9 +1,9 @@
using OpenTK;
using Silk.NET.OpenGL.Legacy;
// 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,5 +1,5 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.OpenGL;
using Silk.NET.OpenGL.Legacy;
using SPB.Graphics;
using SPB.Graphics.OpenGL;
using SPB.Platform;
@ -39,7 +39,7 @@ namespace Ryujinx.Ava.UI.Renderer
context.Initialize(window);
context.MakeCurrent(window);
GL.LoadBindings(new OpenTKBindingsContext(context.GetProcAddress));
GL api = GL.GetApi(context.GetProcAddress);
context.MakeCurrent(null);