diff --git a/src/Ryujinx.Graphics.OpenGL/Buffer.cs b/src/Ryujinx.Graphics.OpenGL/Buffer.cs index 722b28abc..d09bee156 100644 --- a/src/Ryujinx.Graphics.OpenGL/Buffer.cs +++ b/src/Ryujinx.Graphics.OpenGL/Buffer.cs @@ -78,7 +78,7 @@ namespace Ryujinx.Graphics.OpenGL { return new PinnedSpan(IntPtr.Add(ptr, offset).ToPointer(), size); } - else if (HwCapabilities.UsePersistentBufferForFlush) + else if (gd.Capabilities.UsePersistentBufferForFlush) { return PinnedSpan.UnsafeFromSpan(gd.PersistentBuffers.Default.GetBufferData(buffer, offset, size)); } diff --git a/src/Ryujinx.Graphics.OpenGL/HardwareCapabilities.cs b/src/Ryujinx.Graphics.OpenGL/HardwareCapabilities.cs new file mode 100644 index 000000000..704cbcd02 --- /dev/null +++ b/src/Ryujinx.Graphics.OpenGL/HardwareCapabilities.cs @@ -0,0 +1,161 @@ +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. + api.Begin(PrimitiveType.Quads); + api.End(); + + return api.GetError() == GLEnum.NoError; + } + } +} diff --git a/src/Ryujinx.Graphics.OpenGL/HwCapabilities.cs b/src/Ryujinx.Graphics.OpenGL/HwCapabilities.cs deleted file mode 100644 index bd44379e7..000000000 --- a/src/Ryujinx.Graphics.OpenGL/HwCapabilities.cs +++ /dev/null @@ -1,143 +0,0 @@ -using Silk.NET.OpenGL.Legacy; -using System; - -namespace Ryujinx.Graphics.OpenGL -{ - static class HwCapabilities - { - private static readonly Lazy _supportsAlphaToCoverageDitherControl = new(() => HasExtension("GL_NV_alpha_to_coverage_dither_control")); - private static readonly Lazy _supportsAstcCompression = new(() => HasExtension("GL_KHR_texture_compression_astc_ldr")); - private static readonly Lazy _supportsBlendEquationAdvanced = new(() => HasExtension("GL_NV_blend_equation_advanced")); - private static readonly Lazy _supportsDrawTexture = new(() => HasExtension("GL_NV_draw_texture")); - private static readonly Lazy _supportsFragmentShaderInterlock = new(() => HasExtension("GL_ARB_fragment_shader_interlock")); - private static readonly Lazy _supportsFragmentShaderOrdering = new(() => HasExtension("GL_INTEL_fragment_shader_ordering")); - private static readonly Lazy _supportsGeometryShaderPassthrough = new(() => HasExtension("GL_NV_geometry_shader_passthrough")); - private static readonly Lazy _supportsImageLoadFormatted = new(() => HasExtension("GL_EXT_shader_image_load_formatted")); - private static readonly Lazy _supportsIndirectParameters = new(() => HasExtension("GL_ARB_indirect_parameters")); - private static readonly Lazy _supportsParallelShaderCompile = new(() => HasExtension("GL_ARB_parallel_shader_compile")); - private static readonly Lazy _supportsPolygonOffsetClamp = new(() => HasExtension("GL_EXT_polygon_offset_clamp")); - private static readonly Lazy _supportsQuads = new(SupportsQuadsCheck); - private static readonly Lazy _supportsSeamlessCubemapPerTexture = new(() => HasExtension("GL_ARB_seamless_cubemap_per_texture")); - private static readonly Lazy _supportsShaderBallot = new(() => HasExtension("GL_ARB_shader_ballot")); - private static readonly Lazy _supportsShaderViewportLayerArray = new(() => HasExtension("GL_ARB_shader_viewport_layer_array")); - private static readonly Lazy _supportsViewportArray2 = new(() => HasExtension("GL_NV_viewport_array2")); - private static readonly Lazy _supportsTextureCompressionBptc = new(() => HasExtension("GL_EXT_texture_compression_bptc")); - private static readonly Lazy _supportsTextureCompressionRgtc = new(() => HasExtension("GL_EXT_texture_compression_rgtc")); - private static readonly Lazy _supportsTextureCompressionS3tc = new(() => HasExtension("GL_EXT_texture_compression_s3tc")); - private static readonly Lazy _supportsTextureShadowLod = new(() => HasExtension("GL_EXT_texture_shadow_lod")); - private static readonly Lazy _supportsViewportSwizzle = new(() => HasExtension("GL_NV_viewport_swizzle")); - - private static readonly Lazy _maximumComputeSharedMemorySize = new(() => GetLimit(GLEnum.MaxComputeSharedMemorySize)); - private static readonly Lazy _storageBufferOffsetAlignment = new(() => GetLimit(GLEnum.ShaderStorageBufferOffsetAlignment)); - private static readonly Lazy _textureBufferOffsetAlignment = new(() => GetLimit(GLEnum.TextureBufferOffsetAlignment)); - - public enum GpuVendor - { - Unknown, - AmdWindows, - AmdUnix, - IntelWindows, - IntelUnix, - Nvidia, - } - - private static readonly Lazy _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 _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; - } - } -} diff --git a/src/Ryujinx.Graphics.OpenGL/Image/Sampler.cs b/src/Ryujinx.Graphics.OpenGL/Image/Sampler.cs index 47372deed..74e1543b2 100644 --- a/src/Ryujinx.Graphics.OpenGL/Image/Sampler.cs +++ b/src/Ryujinx.Graphics.OpenGL/Image/Sampler.cs @@ -6,27 +6,27 @@ 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; } diff --git a/src/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs b/src/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs index c5beb9d79..5a0732337 100644 --- a/src/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs +++ b/src/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs @@ -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, diff --git a/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs b/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs index 0fd3c0568..73b759aaf 100644 --- a/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs +++ b/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs @@ -273,7 +273,7 @@ namespace Ryujinx.Graphics.OpenGL.Image ReadOnlySpan 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.UnsafeFromSpan(_gd.PersistentBuffers.Default.GetTextureData(this, size, layer, level)); } @@ -719,7 +719,7 @@ namespace Ryujinx.Graphics.OpenGL.Image 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); diff --git a/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs b/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs index 00b3a439a..ae11daa25 100644 --- a/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs +++ b/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs @@ -1,11 +1,11 @@ using Silk.NET.OpenGL.Legacy; +using Silk.NET.OpenGL.Legacy.Extensions.ARB; 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.Extensions.ARB; using System; using System.Runtime.InteropServices; using Sampler = Ryujinx.Graphics.OpenGL.Image.Sampler; @@ -41,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; } @@ -50,14 +52,14 @@ 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); + _sync = new Sync(this); PersistentBuffers = new PersistentBuffers(Api); ResourcePool = new ResourcePool(); } @@ -102,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) @@ -146,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, @@ -157,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, @@ -169,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. } @@ -230,9 +232,11 @@ namespace Ryujinx.Graphics.OpenGL { Debugger.Initialize(Api, glLogLevel); + LoadFeatures(); + PrintGpuInformation(); - if (HwCapabilities.SupportsParallelShaderCompile) + if (Capabilities.SupportsParallelShaderCompile) { Api.TryGetExtension(out ArbParallelShaderCompile arbParallelShaderCompile); @@ -244,10 +248,41 @@ 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 LoadFeatures() + { + 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)); @@ -296,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) diff --git a/src/Ryujinx.Graphics.OpenGL/Pipeline.cs b/src/Ryujinx.Graphics.OpenGL/Pipeline.cs index 7a49f2c9f..4b3316fa5 100644 --- a/src/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ b/src/Ryujinx.Graphics.OpenGL/Pipeline.cs @@ -70,11 +70,12 @@ namespace Ryujinx.Graphics.OpenGL private ColorF _blendConstant; - private readonly GL _api; + private readonly OpenGLRenderer _gd; - internal Pipeline(GL api) + internal Pipeline(OpenGLRenderer gd) { - _api = api; + _gd = gd; + _drawTexture = new DrawTextureEmulation(); _rasterizerDiscard = false; _clipOrigin = ClipControlOrigin.LowerLeft; @@ -91,25 +92,25 @@ namespace Ryujinx.Graphics.OpenGL public void Barrier() { - _api.MemoryBarrier(MemoryBarrierMask.AllBarrierBits); + _gd.Api.MemoryBarrier(MemoryBarrierMask.AllBarrierBits); } public void BeginTransformFeedback(PrimitiveTopology topology) { - _api.BeginTransformFeedback(_tfTopology = topology.ConvertToTfType()); + _gd.Api.BeginTransformFeedback(_tfTopology = topology.ConvertToTfType()); _tfEnabled = true; } public void ClearBuffer(BufferHandle destination, int offset, int size, uint value) { - Buffer.Clear(_api, destination, offset, (uint)size, value); + Buffer.Clear(_gd.Api, destination, offset, (uint)size, value); } public void ClearRenderTargetColor(int index, int layer, int layerCount, uint componentMask, ColorF color) { EnsureFramebuffer(); - _api.ColorMask( + _gd.Api.ColorMask( (uint)index, (componentMask & 1) != 0, (componentMask & 2) != 0, @@ -124,14 +125,14 @@ namespace Ryujinx.Graphics.OpenGL { _framebuffer.AttachColorLayerForClear(index, l); - _api.ClearBuffer(BufferKind.Color, index, colors); + _gd.Api.ClearBuffer(BufferKind.Color, index, colors); } _framebuffer.DetachColorLayerForClear(index); } else { - _api.ClearBuffer(BufferKind.Color, index, colors); + _gd.Api.ClearBuffer(BufferKind.Color, index, colors); } RestoreComponentMask(index); @@ -149,12 +150,12 @@ namespace Ryujinx.Graphics.OpenGL if (stencilMaskChanged) { - _api.StencilMaskSeparate(TriangleFace.Front, (uint)stencilMask); + _gd.Api.StencilMaskSeparate(TriangleFace.Front, (uint)stencilMask); } if (depthMaskChanged) { - _api.DepthMask(depthMask); + _gd.Api.DepthMask(depthMask); } if (layer != 0 || layerCount != _framebuffer.GetDepthStencilLayerCount()) @@ -175,12 +176,12 @@ namespace Ryujinx.Graphics.OpenGL if (stencilMaskChanged) { - _api.StencilMaskSeparate(TriangleFace.Front, (uint)_stencilFrontMask); + _gd.Api.StencilMaskSeparate(TriangleFace.Front, (uint)_stencilFrontMask); } if (depthMaskChanged) { - _api.DepthMask(_depthMask); + _gd.Api.DepthMask(_depthMask); } } @@ -188,26 +189,26 @@ namespace Ryujinx.Graphics.OpenGL { if (depthMask && stencilMask != 0) { - _api.ClearBuffer(GLEnum.DepthStencil, 0, depthValue, stencilValue); + _gd.Api.ClearBuffer(GLEnum.DepthStencil, 0, depthValue, stencilValue); } else if (depthMask) { - _api.ClearBuffer(BufferKind.Depth, 0, ref depthValue); + _gd.Api.ClearBuffer(BufferKind.Depth, 0, ref depthValue); } else if (stencilMask != 0) { - _api.ClearBuffer(BufferKind.Stencil, 0, ref stencilValue); + _gd.Api.ClearBuffer(BufferKind.Stencil, 0, ref stencilValue); } } public void CommandBufferBarrier() { - _api.MemoryBarrier(MemoryBarrierMask.CommandBarrierBit); + _gd.Api.MemoryBarrier(MemoryBarrierMask.CommandBarrierBit); } public void CopyBuffer(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size) { - Buffer.Copy(_api, source, destination, srcOffset, dstOffset, size); + Buffer.Copy(_gd.Api, source, destination, srcOffset, dstOffset, size); } public void DispatchCompute(int groupsX, int groupsY, int groupsZ) @@ -220,7 +221,7 @@ namespace Ryujinx.Graphics.OpenGL PrepareForDispatch(); - _api.DispatchCompute((uint)groupsX, (uint)groupsY, (uint)groupsZ); + _gd.Api.DispatchCompute((uint)groupsX, (uint)groupsY, (uint)groupsZ); } public void Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance) @@ -233,11 +234,11 @@ namespace Ryujinx.Graphics.OpenGL PreDraw(vertexCount); - if (_primitiveType == PrimitiveType.Quads && !HwCapabilities.SupportsQuads) + if (_primitiveType == PrimitiveType.Quads && !_gd.Capabilities.SupportsQuads) { DrawQuadsImpl(vertexCount, instanceCount, firstVertex, firstInstance); } - else if (_primitiveType == PrimitiveType.QuadStrip && !HwCapabilities.SupportsQuads) + else if (_primitiveType == PrimitiveType.QuadStrip && !_gd.Capabilities.SupportsQuads) { DrawQuadStripImpl(vertexCount, instanceCount, firstVertex, firstInstance); } @@ -267,7 +268,7 @@ namespace Ryujinx.Graphics.OpenGL counts[quadIndex] = 4; } - _api.MultiDrawArrays( + _gd.Api.MultiDrawArrays( PrimitiveType.TriangleFan, firsts, counts, @@ -286,7 +287,7 @@ namespace Ryujinx.Graphics.OpenGL { for (int quadIndex = 0; quadIndex < quadsCount; quadIndex++) { - _api.DrawArraysInstancedBaseInstance(PrimitiveType.TriangleFan, firstVertex + quadIndex * 2, 4, (uint)instanceCount, (uint)firstInstance); + _gd.Api.DrawArraysInstancedBaseInstance(PrimitiveType.TriangleFan, firstVertex + quadIndex * 2, 4, (uint)instanceCount, (uint)firstInstance); } } else @@ -303,7 +304,7 @@ namespace Ryujinx.Graphics.OpenGL counts[quadIndex] = 4; } - _api.MultiDrawArrays( + _gd.Api.MultiDrawArrays( PrimitiveType.TriangleFan, firsts, counts, @@ -319,15 +320,15 @@ namespace Ryujinx.Graphics.OpenGL { if (firstInstance == 0 && instanceCount == 1) { - _api.DrawArrays(_primitiveType, firstVertex, (uint)vertexCount); + _gd.Api.DrawArrays(_primitiveType, firstVertex, (uint)vertexCount); } else if (firstInstance == 0) { - _api.DrawArraysInstanced(_primitiveType, firstVertex, (uint)vertexCount, (uint)instanceCount); + _gd.Api.DrawArraysInstanced(_primitiveType, firstVertex, (uint)vertexCount, (uint)instanceCount); } else { - _api.DrawArraysInstancedBaseInstance( + _gd.Api.DrawArraysInstancedBaseInstance( _primitiveType, firstVertex, (uint)vertexCount, @@ -365,7 +366,7 @@ namespace Ryujinx.Graphics.OpenGL IntPtr indexBaseOffset = _indexBaseOffset + firstIndex * indexElemSize; - if (_primitiveType == PrimitiveType.Quads && !HwCapabilities.SupportsQuads) + if (_primitiveType == PrimitiveType.Quads && !_gd.Capabilities.SupportsQuads) { DrawQuadsIndexedImpl( indexCount, @@ -375,7 +376,7 @@ namespace Ryujinx.Graphics.OpenGL firstVertex, firstInstance); } - else if (_primitiveType == PrimitiveType.QuadStrip && !HwCapabilities.SupportsQuads) + else if (_primitiveType == PrimitiveType.QuadStrip && !_gd.Capabilities.SupportsQuads) { DrawQuadStripIndexedImpl( indexCount, @@ -414,7 +415,7 @@ namespace Ryujinx.Graphics.OpenGL { for (int quadIndex = 0; quadIndex < quadsCount; quadIndex++) { - _api.DrawElementsInstancedBaseVertexBaseInstance( + _gd.Api.DrawElementsInstancedBaseVertexBaseInstance( PrimitiveType.TriangleFan, 4, _elementsType, @@ -428,7 +429,7 @@ namespace Ryujinx.Graphics.OpenGL { for (int quadIndex = 0; quadIndex < quadsCount; quadIndex++) { - _api.DrawElementsInstancedBaseInstance( + _gd.Api.DrawElementsInstancedBaseInstance( PrimitiveType.TriangleFan, 4, _elementsType, @@ -441,7 +442,7 @@ namespace Ryujinx.Graphics.OpenGL { for (int quadIndex = 0; quadIndex < quadsCount; quadIndex++) { - _api.DrawElementsInstanced( + _gd.Api.DrawElementsInstanced( PrimitiveType.TriangleFan, 4, _elementsType, @@ -471,7 +472,7 @@ namespace Ryujinx.Graphics.OpenGL fixed (void* indicesPtr = indices) fixed (int* baseVerticesPtr = baseVertices) { - _api.MultiDrawElementsBaseVertex( + _gd.Api.MultiDrawElementsBaseVertex( PrimitiveType.TriangleFan, countsPtr, _elementsType, @@ -518,7 +519,7 @@ namespace Ryujinx.Graphics.OpenGL fixed (void* indicesPtr = indices) fixed (int* baseVerticesPtr = baseVertices) { - _api.MultiDrawElementsBaseVertex( + _gd.Api.MultiDrawElementsBaseVertex( PrimitiveType.TriangleFan, countsPtr, _elementsType, @@ -537,11 +538,11 @@ namespace Ryujinx.Graphics.OpenGL { if (firstInstance == 0 && firstVertex == 0 && instanceCount == 1) { - _api.DrawElements(_primitiveType, (uint)indexCount, _elementsType, indexBaseOffset); + _gd.Api.DrawElements(_primitiveType, (uint)indexCount, _elementsType, indexBaseOffset); } else if (firstInstance == 0 && instanceCount == 1) { - _api.DrawElementsBaseVertex( + _gd.Api.DrawElementsBaseVertex( _primitiveType, (uint)indexCount, _elementsType, @@ -550,7 +551,7 @@ namespace Ryujinx.Graphics.OpenGL } else if (firstInstance == 0 && firstVertex == 0) { - _api.DrawElementsInstanced( + _gd.Api.DrawElementsInstanced( _primitiveType, (uint)indexCount, _elementsType, @@ -559,7 +560,7 @@ namespace Ryujinx.Graphics.OpenGL } else if (firstInstance == 0) { - _api.DrawElementsInstancedBaseVertex( + _gd.Api.DrawElementsInstancedBaseVertex( _primitiveType, (uint)indexCount, _elementsType, @@ -569,7 +570,7 @@ namespace Ryujinx.Graphics.OpenGL } else if (firstVertex == 0) { - _api.DrawElementsInstancedBaseInstance( + _gd.Api.DrawElementsInstancedBaseInstance( _primitiveType, (uint)indexCount, _elementsType, @@ -579,7 +580,7 @@ namespace Ryujinx.Graphics.OpenGL } else { - _api.DrawElementsInstancedBaseVertexBaseInstance( + _gd.Api.DrawElementsInstancedBaseVertexBaseInstance( _primitiveType, (uint)indexCount, _elementsType, @@ -602,9 +603,9 @@ namespace Ryujinx.Graphics.OpenGL _vertexArray.SetRangeOfIndexBuffer(); - _api.BindBuffer(BufferTargetARB.DrawIndirectBuffer, indirectBuffer.Handle.ToUInt32()); + _gd.Api.BindBuffer(BufferTargetARB.DrawIndirectBuffer, indirectBuffer.Handle.ToUInt32()); - _api.DrawElementsIndirect(_primitiveType, _elementsType, (IntPtr)indirectBuffer.Offset); + _gd.Api.DrawElementsIndirect(_primitiveType, _elementsType, (IntPtr)indirectBuffer.Offset); _vertexArray.RestoreIndexBuffer(); @@ -623,10 +624,10 @@ namespace Ryujinx.Graphics.OpenGL _vertexArray.SetRangeOfIndexBuffer(); - _api.BindBuffer(BufferTargetARB.DrawIndirectBuffer, indirectBuffer.Handle.ToUInt32()); - _api.BindBuffer(BufferTargetARB.ParameterBuffer, parameterBuffer.Handle.ToUInt32()); + _gd.Api.BindBuffer(BufferTargetARB.DrawIndirectBuffer, indirectBuffer.Handle.ToUInt32()); + _gd.Api.BindBuffer(BufferTargetARB.ParameterBuffer, parameterBuffer.Handle.ToUInt32()); - _api.MultiDrawElementsIndirectCount( + _gd.Api.MultiDrawElementsIndirectCount( _primitiveType, _elementsType, (IntPtr)indirectBuffer.Offset, @@ -649,9 +650,9 @@ namespace Ryujinx.Graphics.OpenGL PreDrawVbUnbounded(); - _api.BindBuffer(BufferTargetARB.DrawIndirectBuffer, indirectBuffer.Handle.ToUInt32()); + _gd.Api.BindBuffer(BufferTargetARB.DrawIndirectBuffer, indirectBuffer.Handle.ToUInt32()); - _api.DrawArraysIndirect(_primitiveType, (IntPtr)indirectBuffer.Offset); + _gd.Api.DrawArraysIndirect(_primitiveType, (IntPtr)indirectBuffer.Offset); PostDraw(); } @@ -666,10 +667,10 @@ namespace Ryujinx.Graphics.OpenGL PreDrawVbUnbounded(); - _api.BindBuffer(BufferTargetARB.DrawIndirectBuffer, indirectBuffer.Handle.ToUInt32()); - _api.BindBuffer(BufferTargetARB.ParameterBuffer, parameterBuffer.Handle.ToUInt32()); + _gd.Api.BindBuffer(BufferTargetARB.DrawIndirectBuffer, indirectBuffer.Handle.ToUInt32()); + _gd.Api.BindBuffer(BufferTargetARB.ParameterBuffer, parameterBuffer.Handle.ToUInt32()); - _api.MultiDrawArraysIndirectCount( + _gd.Api.MultiDrawArraysIndirectCount( _primitiveType, (IntPtr)indirectBuffer.Offset, parameterBuffer.Offset, @@ -683,9 +684,9 @@ namespace Ryujinx.Graphics.OpenGL { if (texture is TextureView view && sampler is Sampler samp) { - if (HwCapabilities.SupportsDrawTexture) + if (_gd.Capabilities.SupportsDrawTexture) { - _api.TryGetExtension(out NVDrawTexture drawTexture); + _gd.Api.TryGetExtension(out NVDrawTexture drawTexture); drawTexture.DrawTexture( view.Handle, @@ -718,24 +719,24 @@ namespace Ryujinx.Graphics.OpenGL } } - Disable(_api, EnableCap.CullFace, _cullEnable); - Disable(_api, EnableCap.StencilTest, _stencilTestEnable); - Disable(_api, EnableCap.DepthTest, _depthTestEnable); + Disable(_gd.Api, EnableCap.CullFace, _cullEnable); + Disable(_gd.Api, EnableCap.StencilTest, _stencilTestEnable); + Disable(_gd.Api, EnableCap.DepthTest, _depthTestEnable); if (_depthMask) { - _api.DepthMask(false); + _gd.Api.DepthMask(false); } if (_tfEnabled) { - _api.EndTransformFeedback(); + _gd.Api.EndTransformFeedback(); } - _api.ClipControl(ClipControlOrigin.UpperLeft, ClipControlDepth.NegativeOneToOne); + _gd.Api.ClipControl(ClipControlOrigin.UpperLeft, ClipControlDepth.NegativeOneToOne); _drawTexture.Draw( - _api, + _gd.Api, view, samp, dstRegion.X1, @@ -752,18 +753,18 @@ namespace Ryujinx.Graphics.OpenGL RestoreViewport0(); - Enable(_api, EnableCap.CullFace, _cullEnable); - Enable(_api, EnableCap.StencilTest, _stencilTestEnable); - Enable(_api, EnableCap.DepthTest, _depthTestEnable); + Enable(_gd.Api, EnableCap.CullFace, _cullEnable); + Enable(_gd.Api, EnableCap.StencilTest, _stencilTestEnable); + Enable(_gd.Api, EnableCap.DepthTest, _depthTestEnable); if (_depthMask) { - _api.DepthMask(true); + _gd.Api.DepthMask(true); } if (_tfEnabled) { - _api.BeginTransformFeedback(_tfTopology); + _gd.Api.BeginTransformFeedback(_tfTopology); } RestoreClipControl(); @@ -773,7 +774,7 @@ namespace Ryujinx.Graphics.OpenGL public void EndTransformFeedback() { - _api.EndTransformFeedback(); + _gd.Api.EndTransformFeedback(); _tfEnabled = false; } @@ -781,24 +782,24 @@ namespace Ryujinx.Graphics.OpenGL { if (!enable) { - _api.Disable(EnableCap.AlphaTest); + _gd.Api.Disable(EnableCap.AlphaTest); return; } - _api.AlphaFunc((AlphaFunction)op.Convert(), reference); - _api.Enable(EnableCap.AlphaTest); + _gd.Api.AlphaFunc((AlphaFunction)op.Convert(), reference); + _gd.Api.Enable(EnableCap.AlphaTest); } public void SetBlendState(AdvancedBlendDescriptor blend) { - if (HwCapabilities.SupportsBlendEquationAdvanced) + if (_gd.Capabilities.SupportsBlendEquationAdvanced) { - _api.BlendEquation((GLEnum)blend.Op.Convert()); + _gd.Api.BlendEquation((GLEnum)blend.Op.Convert()); - _api.TryGetExtension(out NVBlendEquationAdvanced nvBlendEquationAdvanced); + _gd.Api.TryGetExtension(out NVBlendEquationAdvanced nvBlendEquationAdvanced); nvBlendEquationAdvanced.BlendParameter(NV.BlendOverlapNV, (int)blend.Overlap.Convert()); nvBlendEquationAdvanced.BlendParameter(NV.BlendPremultipliedSrcNV, blend.SrcPreMultiplied ? 1 : 0); - _api.Enable(EnableCap.Blend); + _gd.Api.Enable(EnableCap.Blend); _advancedBlendEnable = true; } } @@ -807,22 +808,22 @@ namespace Ryujinx.Graphics.OpenGL { if (_advancedBlendEnable) { - _api.Disable(EnableCap.Blend); + _gd.Api.Disable(EnableCap.Blend); _advancedBlendEnable = false; } if (!blend.Enable) { - _api.Disable(EnableCap.Blend, (uint)index); + _gd.Api.Disable(EnableCap.Blend, (uint)index); return; } - _api.BlendEquationSeparate( + _gd.Api.BlendEquationSeparate( (uint)index, blend.ColorOp.Convert(), blend.AlphaOp.Convert()); - _api.BlendFuncSeparate( + _gd.Api.BlendFuncSeparate( (uint)index, (BlendingFactor)blend.ColorSrcFactor.Convert(), (BlendingFactor)blend.ColorDstFactor.Convert(), @@ -841,43 +842,43 @@ namespace Ryujinx.Graphics.OpenGL { _blendConstant = blend.BlendConstant; - _api.BlendColor( + _gd.Api.BlendColor( blend.BlendConstant.Red, blend.BlendConstant.Green, blend.BlendConstant.Blue, blend.BlendConstant.Alpha); } - _api.Enable(EnableCap.Blend, (uint)index); + _gd.Api.Enable(EnableCap.Blend, (uint)index); } public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp) { if ((enables & PolygonModeMask.Point) != 0) { - _api.Enable(EnableCap.PolygonOffsetPoint); + _gd.Api.Enable(EnableCap.PolygonOffsetPoint); } else { - _api.Disable(EnableCap.PolygonOffsetPoint); + _gd.Api.Disable(EnableCap.PolygonOffsetPoint); } if ((enables & PolygonModeMask.Line) != 0) { - _api.Enable(EnableCap.PolygonOffsetLine); + _gd.Api.Enable(EnableCap.PolygonOffsetLine); } else { - _api.Disable(EnableCap.PolygonOffsetLine); + _gd.Api.Disable(EnableCap.PolygonOffsetLine); } if ((enables & PolygonModeMask.Fill) != 0) { - _api.Enable(EnableCap.PolygonOffsetFill); + _gd.Api.Enable(EnableCap.PolygonOffsetFill); } else { - _api.Disable(EnableCap.PolygonOffsetFill); + _gd.Api.Disable(EnableCap.PolygonOffsetFill); } if (enables == 0) @@ -885,13 +886,13 @@ namespace Ryujinx.Graphics.OpenGL return; } - if (HwCapabilities.SupportsPolygonOffsetClamp) + if (_gd.Capabilities.SupportsPolygonOffsetClamp) { - _api.PolygonOffsetClamp(factor, units, clamp); + _gd.Api.PolygonOffsetClamp(factor, units, clamp); } else { - _api.PolygonOffset(factor, units); + _gd.Api.PolygonOffset(factor, units); } } @@ -899,11 +900,11 @@ namespace Ryujinx.Graphics.OpenGL { if (!clamp) { - _api.Disable(EnableCap.DepthClamp); + _gd.Api.Disable(EnableCap.DepthClamp); return; } - _api.Enable(EnableCap.DepthClamp); + _gd.Api.Enable(EnableCap.DepthClamp); } public void SetDepthMode(DepthMode mode) @@ -914,7 +915,7 @@ namespace Ryujinx.Graphics.OpenGL { _clipDepthMode = depthMode; - _api.ClipControl(_clipOrigin, depthMode); + _gd.Api.ClipControl(_clipOrigin, depthMode); } } @@ -922,15 +923,15 @@ namespace Ryujinx.Graphics.OpenGL { if (depthTest.TestEnable) { - _api.Enable(EnableCap.DepthTest); - _api.DepthFunc((DepthFunction)depthTest.Func.Convert()); + _gd.Api.Enable(EnableCap.DepthTest); + _gd.Api.DepthFunc((DepthFunction)depthTest.Func.Convert()); } else { - _api.Disable(EnableCap.DepthTest); + _gd.Api.Disable(EnableCap.DepthTest); } - _api.DepthMask(depthTest.WriteEnable); + _gd.Api.DepthMask(depthTest.WriteEnable); _depthMask = depthTest.WriteEnable; _depthTestEnable = depthTest.TestEnable; } @@ -941,13 +942,13 @@ namespace Ryujinx.Graphics.OpenGL if (!enable) { - _api.Disable(EnableCap.CullFace); + _gd.Api.Disable(EnableCap.CullFace); return; } - _api.CullFace(face.Convert()); + _gd.Api.CullFace(face.Convert()); - _api.Enable(EnableCap.CullFace); + _gd.Api.Enable(EnableCap.CullFace); } public void SetFrontFace(FrontFace frontFace) @@ -964,7 +965,7 @@ namespace Ryujinx.Graphics.OpenGL if (texture == null) { - _api.BindImageTexture((uint)binding, 0, 0, true, 0, BufferAccessARB.ReadWrite, InternalFormat.Rgba8); + _gd.Api.BindImageTexture((uint)binding, 0, 0, true, 0, BufferAccessARB.ReadWrite, InternalFormat.Rgba8); return; } @@ -974,7 +975,7 @@ namespace Ryujinx.Graphics.OpenGL if (format != 0) { - _api.BindImageTexture((uint)binding, texBase.Handle, 0, true, 0, BufferAccessARB.ReadWrite, format); + _gd.Api.BindImageTexture((uint)binding, texBase.Handle, 0, true, 0, BufferAccessARB.ReadWrite, format); } } @@ -998,13 +999,13 @@ namespace Ryujinx.Graphics.OpenGL { if (enable) { - _api.Enable(EnableCap.ColorLogicOp); + _gd.Api.Enable(EnableCap.ColorLogicOp); - _api.LogicOp((LogicOp)op.Convert()); + _gd.Api.LogicOp((LogicOp)op.Convert()); } else { - _api.Disable(EnableCap.ColorLogicOp); + _gd.Api.Disable(EnableCap.ColorLogicOp); } } @@ -1012,20 +1013,20 @@ namespace Ryujinx.Graphics.OpenGL { if (multisample.AlphaToCoverageEnable) { - _api.Enable(EnableCap.SampleAlphaToCoverage); + _gd.Api.Enable(EnableCap.SampleAlphaToCoverage); if (multisample.AlphaToOneEnable) { - _api.Enable(EnableCap.SampleAlphaToOne); + _gd.Api.Enable(EnableCap.SampleAlphaToOne); } else { - _api.Disable(EnableCap.SampleAlphaToOne); + _gd.Api.Disable(EnableCap.SampleAlphaToOne); } - if (HwCapabilities.SupportsAlphaToCoverageDitherControl) + if (_gd.Capabilities.SupportsAlphaToCoverageDitherControl) { - _api.TryGetExtension(out NVAlphaToCoverageDitherControl nvAlphaToCoverageDitherControl); + _gd.Api.TryGetExtension(out NVAlphaToCoverageDitherControl nvAlphaToCoverageDitherControl); nvAlphaToCoverageDitherControl.AlphaToCoverageDitherControl(multisample.AlphaToCoverageDitherEnable ? NV.AlphaToCoverageDitherEnableNV @@ -1034,7 +1035,7 @@ namespace Ryujinx.Graphics.OpenGL } else { - _api.Disable(EnableCap.SampleAlphaToCoverage); + _gd.Api.Disable(EnableCap.SampleAlphaToCoverage); } } @@ -1042,28 +1043,28 @@ namespace Ryujinx.Graphics.OpenGL { if (smooth) { - _api.Enable(EnableCap.LineSmooth); + _gd.Api.Enable(EnableCap.LineSmooth); } else { - _api.Disable(EnableCap.LineSmooth); + _gd.Api.Disable(EnableCap.LineSmooth); } - _api.LineWidth(width); + _gd.Api.LineWidth(width); } public unsafe void SetPatchParameters(int vertices, ReadOnlySpan defaultOuterLevel, ReadOnlySpan defaultInnerLevel) { - _api.PatchParameter(PatchParameterName.Vertices, vertices); + _gd.Api.PatchParameter(PatchParameterName.Vertices, vertices); fixed (float* pOuterLevel = defaultOuterLevel) { - _api.PatchParameter(PatchParameterName.DefaultOuterLevel, pOuterLevel); + _gd.Api.PatchParameter(PatchParameterName.DefaultOuterLevel, pOuterLevel); } fixed (float* pInnerLevel = defaultInnerLevel) { - _api.PatchParameter(PatchParameterName.DefaultInnerLevel, pInnerLevel); + _gd.Api.PatchParameter(PatchParameterName.DefaultInnerLevel, pInnerLevel); } } @@ -1073,41 +1074,41 @@ namespace Ryujinx.Graphics.OpenGL // As we don't know if the current context is core or compat, it's safer to keep this code. if (enablePointSprite) { - _api.Enable(GLEnum.PointSprite); + _gd.Api.Enable(GLEnum.PointSprite); } else { - _api.Disable(GLEnum.PointSprite); + _gd.Api.Disable(GLEnum.PointSprite); } if (isProgramPointSize) { - _api.Enable(EnableCap.ProgramPointSize); + _gd.Api.Enable(EnableCap.ProgramPointSize); } else { - _api.Disable(EnableCap.ProgramPointSize); + _gd.Api.Disable(EnableCap.ProgramPointSize); } - _api.PointParameter(GLEnum.PointSpriteCoordOrigin, (int)(origin == Origin.LowerLeft + _gd.Api.PointParameter(GLEnum.PointSpriteCoordOrigin, (int)(origin == Origin.LowerLeft ? GLEnum.LowerLeft : GLEnum.UpperLeft)); // Games seem to set point size to 0 which generates a GL_INVALID_VALUE // From the spec, GL_INVALID_VALUE is generated if size is less than or equal to 0. - _api.PointSize(Math.Max(float.Epsilon, size)); + _gd.Api.PointSize(Math.Max(float.Epsilon, size)); } public void SetPolygonMode(GAL.PolygonMode frontMode, GAL.PolygonMode backMode) { if (frontMode == backMode) { - _api.PolygonMode(TriangleFace.FrontAndBack, frontMode.Convert()); + _gd.Api.PolygonMode(TriangleFace.FrontAndBack, frontMode.Convert()); } else { - _api.PolygonMode(TriangleFace.Front, frontMode.Convert()); - _api.PolygonMode(TriangleFace.Back, backMode.Convert()); + _gd.Api.PolygonMode(TriangleFace.Front, frontMode.Convert()); + _gd.Api.PolygonMode(TriangleFace.Back, backMode.Convert()); } } @@ -1115,13 +1116,13 @@ namespace Ryujinx.Graphics.OpenGL { if (!enable) { - _api.Disable(EnableCap.PrimitiveRestart); + _gd.Api.Disable(EnableCap.PrimitiveRestart); return; } - _api.PrimitiveRestartIndex((uint)index); + _gd.Api.PrimitiveRestartIndex((uint)index); - _api.Enable(EnableCap.PrimitiveRestart); + _gd.Api.Enable(EnableCap.PrimitiveRestart); } public void SetPrimitiveTopology(PrimitiveTopology topology) @@ -1135,9 +1136,9 @@ namespace Ryujinx.Graphics.OpenGL if (_tfEnabled) { - _api.EndTransformFeedback(); + _gd.Api.EndTransformFeedback(); prg.Bind(); - _api.BeginTransformFeedback(_tfTopology); + _gd.Api.BeginTransformFeedback(_tfTopology); } else { @@ -1161,11 +1162,11 @@ namespace Ryujinx.Graphics.OpenGL { if (discard) { - _api.Enable(EnableCap.RasterizerDiscard); + _gd.Api.Enable(EnableCap.RasterizerDiscard); } else { - _api.Disable(EnableCap.RasterizerDiscard); + _gd.Api.Disable(EnableCap.RasterizerDiscard); } _rasterizerDiscard = discard; @@ -1237,7 +1238,7 @@ namespace Ryujinx.Graphics.OpenGL if ((_scissorEnables & mask) == 0) { _scissorEnables |= mask; - _api.Enable(EnableCap.ScissorTest, (uint)index); + _gd.Api.Enable(EnableCap.ScissorTest, (uint)index); } } else @@ -1245,12 +1246,12 @@ namespace Ryujinx.Graphics.OpenGL if ((_scissorEnables & mask) != 0) { _scissorEnables &= ~mask; - _api.Disable(EnableCap.ScissorTest, (uint)index); + _gd.Api.Disable(EnableCap.ScissorTest, (uint)index); } } } - _api.ScissorArray(0, (uint)count, ref v[0]); + _gd.Api.ScissorArray(0, (uint)count, ref v[0]); } public void SetStencilTest(StencilTestDescriptor stencilTest) @@ -1259,39 +1260,39 @@ namespace Ryujinx.Graphics.OpenGL if (!stencilTest.TestEnable) { - _api.Disable(EnableCap.StencilTest); + _gd.Api.Disable(EnableCap.StencilTest); return; } - _api.StencilOpSeparate( + _gd.Api.StencilOpSeparate( TriangleFace.Front, stencilTest.FrontSFail.Convert(), stencilTest.FrontDpFail.Convert(), stencilTest.FrontDpPass.Convert()); - _api.StencilFuncSeparate( + _gd.Api.StencilFuncSeparate( TriangleFace.Front, (StencilFunction)stencilTest.FrontFunc.Convert(), stencilTest.FrontFuncRef, (uint)stencilTest.FrontFuncMask); - _api.StencilMaskSeparate(TriangleFace.Front, (uint)stencilTest.FrontMask); + _gd.Api.StencilMaskSeparate(TriangleFace.Front, (uint)stencilTest.FrontMask); - _api.StencilOpSeparate( + _gd.Api.StencilOpSeparate( TriangleFace.Back, stencilTest.BackSFail.Convert(), stencilTest.BackDpFail.Convert(), stencilTest.BackDpPass.Convert()); - _api.StencilFuncSeparate( + _gd.Api.StencilFuncSeparate( TriangleFace.Back, (StencilFunction)stencilTest.BackFunc.Convert(), stencilTest.BackFuncRef, (uint)stencilTest.BackFuncMask); - _api.StencilMaskSeparate(TriangleFace.Back, (uint)stencilTest.BackMask); + _gd.Api.StencilMaskSeparate(TriangleFace.Back, (uint)stencilTest.BackMask); - _api.Enable(EnableCap.StencilTest); + _gd.Api.Enable(EnableCap.StencilTest); _stencilFrontMask = stencilTest.FrontMask; } @@ -1316,7 +1317,7 @@ namespace Ryujinx.Graphics.OpenGL } else { - TextureBase.ClearBinding(_api, (uint)binding); + TextureBase.ClearBinding(_gd.Api, (uint)binding); } Sampler glSampler = (Sampler)sampler; @@ -1338,7 +1339,7 @@ namespace Ryujinx.Graphics.OpenGL { if (_tfEnabled) { - _api.EndTransformFeedback(); + _gd.Api.EndTransformFeedback(); } int count = Math.Min(buffers.Length, Constants.MaxTransformFeedbackBuffers); @@ -1350,23 +1351,23 @@ namespace Ryujinx.Graphics.OpenGL if (buffer.Handle == BufferHandle.Null) { - _api.BindBufferBase(BufferTargetARB.TransformFeedbackBuffer, (uint)i, 0); + _gd.Api.BindBufferBase(BufferTargetARB.TransformFeedbackBuffer, (uint)i, 0); continue; } if (_tfbs[i] == BufferHandle.Null) { - _tfbs[i] = Buffer.Create(_api); + _tfbs[i] = Buffer.Create(_gd.Api); } - Buffer.Resize(_api, _tfbs[i], buffer.Size); - Buffer.Copy(_api, buffer.Handle, _tfbs[i], buffer.Offset, 0, buffer.Size); - _api.BindBufferBase(BufferTargetARB.TransformFeedbackBuffer, (uint)i, _tfbs[i].ToUInt32()); + Buffer.Resize(_gd.Api, _tfbs[i], buffer.Size); + Buffer.Copy(_gd.Api, buffer.Handle, _tfbs[i], buffer.Offset, 0, buffer.Size); + _gd.Api.BindBufferBase(BufferTargetARB.TransformFeedbackBuffer, (uint)i, _tfbs[i].ToUInt32()); } if (_tfEnabled) { - _api.BeginTransformFeedback(_tfTopology); + _gd.Api.BeginTransformFeedback(_tfTopology); } } @@ -1379,11 +1380,11 @@ namespace Ryujinx.Graphics.OpenGL { if (!enableClip) { - _api.Disable(EnableCap.ClipDistance0 + index); + _gd.Api.Disable(EnableCap.ClipDistance0 + index); return; } - _api.Enable(EnableCap.ClipDistance0 + index); + _gd.Api.Enable(EnableCap.ClipDistance0 + index); } public void SetVertexAttribs(ReadOnlySpan vertexAttribs) @@ -1419,9 +1420,9 @@ namespace Ryujinx.Graphics.OpenGL viewportArray[viewportElemIndex + 2] = viewport.Region.Width; viewportArray[viewportElemIndex + 3] = MathF.Abs(viewport.Region.Height); - if (HwCapabilities.SupportsViewportSwizzle) + if (_gd.Capabilities.SupportsViewportSwizzle) { - _api.TryGetExtension(out NVViewportSwizzle nvViewportSwizzle); + _gd.Api.TryGetExtension(out NVViewportSwizzle nvViewportSwizzle); nvViewportSwizzle.ViewportSwizzle( index, @@ -1439,18 +1440,18 @@ namespace Ryujinx.Graphics.OpenGL SetOrigin(flipY ? ClipControlOrigin.UpperLeft : ClipControlOrigin.LowerLeft); - _api.ViewportArray(0, (uint)viewports.Length, viewportArray); - _api.DepthRangeArray(0, (uint)viewports.Length, depthRangeArray); + _gd.Api.ViewportArray(0, (uint)viewports.Length, viewportArray); + _gd.Api.DepthRangeArray(0, (uint)viewports.Length, depthRangeArray); } public void TextureBarrier() { - _api.MemoryBarrier(MemoryBarrierMask.TextureFetchBarrierBit); + _gd.Api.MemoryBarrier(MemoryBarrierMask.TextureFetchBarrierBit); } public void TextureBarrierTiled() { - _api.MemoryBarrier(MemoryBarrierMask.TextureFetchBarrierBit); + _gd.Api.MemoryBarrier(MemoryBarrierMask.TextureFetchBarrierBit); } private void SetBuffers(ReadOnlySpan buffers, bool isStorage) @@ -1464,11 +1465,11 @@ namespace Ryujinx.Graphics.OpenGL if (buffer.Handle == BufferHandle.Null) { - _api.BindBufferRange(target, (uint)assignment.Binding, 0, IntPtr.Zero, 0); + _gd.Api.BindBufferRange(target, (uint)assignment.Binding, 0, IntPtr.Zero, 0); continue; } - _api.BindBufferRange(target, (uint)assignment.Binding, buffer.Handle.ToUInt32(), buffer.Offset, (UIntPtr)buffer.Size); + _gd.Api.BindBufferRange(target, (uint)assignment.Binding, buffer.Handle.ToUInt32(), buffer.Offset, (UIntPtr)buffer.Size); } } @@ -1478,7 +1479,7 @@ namespace Ryujinx.Graphics.OpenGL { _clipOrigin = origin; - _api.ClipControl(origin, _clipDepthMode); + _gd.Api.ClipControl(origin, _clipDepthMode); SetFrontFace(_frontFace); } @@ -1494,14 +1495,14 @@ namespace Ryujinx.Graphics.OpenGL frontFace = frontFace == FrontFaceDirection.Ccw ? FrontFaceDirection.CW : FrontFaceDirection.Ccw; } - _api.FrontFace(frontFace); + _gd.Api.FrontFace(frontFace); } private void EnsureVertexArray() { if (_vertexArray == null) { - _vertexArray = new VertexArray(_api); + _vertexArray = new VertexArray(_gd.Api); _vertexArray.Bind(); } @@ -1511,12 +1512,12 @@ namespace Ryujinx.Graphics.OpenGL { if (_framebuffer == null) { - _framebuffer = new Framebuffer(_api); + _framebuffer = new Framebuffer(_gd.Api); uint boundHandle = _framebuffer.Bind(); _boundDrawFramebuffer = _boundReadFramebuffer = boundHandle; - _api.Enable(EnableCap.FramebufferSrgb); + _gd.Api.Enable(EnableCap.FramebufferSrgb); } } @@ -1562,7 +1563,7 @@ namespace Ryujinx.Graphics.OpenGL { if (_tfbTargets[i].Handle != BufferHandle.Null) { - Buffer.Copy(_api, _tfbs[i], _tfbTargets[i].Handle, 0, _tfbTargets[i].Offset, _tfbTargets[i].Size); + Buffer.Copy(_gd.Api, _tfbs[i], _tfbTargets[i].Handle, 0, _tfbTargets[i].Offset, _tfbTargets[i].Size); } } } @@ -1587,7 +1588,7 @@ namespace Ryujinx.Graphics.OpenGL componentMask >>= shift; componentMask &= 0xfu; - _api.ColorMask( + _gd.Api.ColorMask( (uint)index, (componentMask & redMask) != 0, (componentMask & 2u) != 0, @@ -1600,14 +1601,14 @@ namespace Ryujinx.Graphics.OpenGL public void RestoreClipControl() { - _api.ClipControl(_clipOrigin, _clipDepthMode); + _gd.Api.ClipControl(_clipOrigin, _clipDepthMode); } public void RestoreScissor0Enable() { if ((_scissorEnables & 1u) != 0) { - _api.Enable(EnableCap.ScissorTest, 0); + _gd.Api.Enable(EnableCap.ScissorTest, 0); } } @@ -1615,7 +1616,7 @@ namespace Ryujinx.Graphics.OpenGL { if (_rasterizerDiscard) { - _api.Enable(EnableCap.RasterizerDiscard); + _gd.Api.Enable(EnableCap.RasterizerDiscard); } } @@ -1623,7 +1624,7 @@ namespace Ryujinx.Graphics.OpenGL { if (_viewportArray.Length > 0) { - _api.ViewportArray(0, 1, _viewportArray); + _gd.Api.ViewportArray(0, 1, _viewportArray); } } @@ -1644,12 +1645,12 @@ namespace Ryujinx.Graphics.OpenGL if (format != 0) { - _api.BindImageTexture((uint)i, texBase.Handle, 0, true, 0, BufferAccessARB.ReadWrite, format); + _gd.Api.BindImageTexture((uint)i, texBase.Handle, 0, true, 0, BufferAccessARB.ReadWrite, format); continue; } } - _api.BindImageTexture((uint)i, 0, 0, true, 0, BufferAccessARB.ReadWrite, InternalFormat.Rgba8); + _gd.Api.BindImageTexture((uint)i, 0, 0, true, 0, BufferAccessARB.ReadWrite, InternalFormat.Rgba8); } } @@ -1673,7 +1674,7 @@ namespace Ryujinx.Graphics.OpenGL return false; } - _api.BeginConditionalRender(evt.Query, isEqual ? ConditionalRenderMode.NoWaitInverted : ConditionalRenderMode.NoWait); + _gd.Api.BeginConditionalRender(evt.Query, isEqual ? ConditionalRenderMode.NoWaitInverted : ConditionalRenderMode.NoWait); _activeConditionalRender = evt; return true; @@ -1682,19 +1683,19 @@ namespace Ryujinx.Graphics.OpenGL // The GPU will flush the queries to CPU and evaluate the condition there instead. - _api.Flush(); // The thread will be stalled manually flushing the counter, so flush GL commands now. + _gd.Api.Flush(); // The thread will be stalled manually flushing the counter, so flush GL commands now. return false; } public bool TryHostConditionalRendering(ICounterEvent value, ICounterEvent compare, bool isEqual) { - _api.Flush(); // The GPU thread will be stalled manually flushing the counter, so flush GL commands now. + _gd.Api.Flush(); // The GPU thread will be stalled manually flushing the counter, so flush GL commands now. return false; // We don't currently have a way to compare two counters for conditional rendering. } public void EndHostConditionalRendering() { - _api.EndConditionalRender(); + _gd.Api.EndConditionalRender(); _activeConditionalRender?.ReleaseHostAccess(); _activeConditionalRender = null; @@ -1706,7 +1707,7 @@ namespace Ryujinx.Graphics.OpenGL { if (_tfbs[i] != BufferHandle.Null) { - Buffer.Delete(_api, _tfbs[i]); + Buffer.Delete(_gd.Api, _tfbs[i]); _tfbs[i] = BufferHandle.Null; } } @@ -1714,7 +1715,7 @@ namespace Ryujinx.Graphics.OpenGL _activeConditionalRender?.ReleaseHostAccess(); _framebuffer?.Dispose(); _vertexArray?.Dispose(); - _drawTexture.Dispose(_api); + _drawTexture.Dispose(_gd.Api); } } } diff --git a/src/Ryujinx.Graphics.OpenGL/Program.cs b/src/Ryujinx.Graphics.OpenGL/Program.cs index 9d388d301..ba231e65d 100644 --- a/src/Ryujinx.Graphics.OpenGL/Program.cs +++ b/src/Ryujinx.Graphics.OpenGL/Program.cs @@ -28,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 unsafe 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; @@ -53,37 +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: fixed (byte* ptr = shader.BinaryCode.AsSpan()) { - _api.ShaderBinary(1, in shaderHandle, ShaderBinaryFormat.ShaderBinaryFormatSpirV, ptr, (uint)shader.BinaryCode.Length); + _gd.Api.ShaderBinary(1, in shaderHandle, ShaderBinaryFormat.ShaderBinaryFormatSpirV, ptr, (uint)shader.BinaryCode.Length); } - _api.SpecializeShader(shaderHandle, "main", 0, (uint[])null, (uint[])null); + _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 code, bool hasFragmentShader, int fragmentOutputMap) + public Program(OpenGLRenderer gd, ReadOnlySpan code, bool hasFragmentShader, int fragmentOutputMap) { - _api = api; - Handle = _api.CreateProgram(); + _gd = gd; + Handle = _gd.Api.CreateProgram(); if (code.Length >= 4) { @@ -93,7 +93,7 @@ namespace Ryujinx.Graphics.OpenGL { fixed (byte* ptr = code) { - _api.ProgramBinary(Handle, (GLEnum)binaryFormat, (IntPtr)ptr, (uint)code.Length - 4); + _gd.Api.ProgramBinary(Handle, (GLEnum)binaryFormat, (IntPtr)ptr, (uint)code.Length - 4); } } } @@ -103,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, (GLEnum)ARB.CompletionStatusArb, out int completed); + _gd.Api.GetProgram(Handle, (GLEnum)ARB.CompletionStatusArb, out int completed); if (completed == 0) { @@ -118,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) { @@ -144,14 +144,14 @@ namespace Ryujinx.Graphics.OpenGL 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]; GLEnum binFormat; fixed (byte* ptr = data) { - _api.GetProgramBinary(Handle, (uint)size, out _, out binFormat, ptr); + _gd.Api.GetProgramBinary(Handle, (uint)size, out _, out binFormat, ptr); } BinaryPrimitives.WriteInt32LittleEndian(data, (int)binFormat); @@ -165,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; @@ -178,7 +178,7 @@ namespace Ryujinx.Graphics.OpenGL if (Handle != 0) { DeleteShaders(); - _api.DeleteProgram(Handle); + _gd.Api.DeleteProgram(Handle); Handle = 0; } diff --git a/src/Ryujinx.Graphics.OpenGL/Sync.cs b/src/Ryujinx.Graphics.OpenGL/Sync.cs index f853c4f88..fb2acbe48 100644 --- a/src/Ryujinx.Graphics.OpenGL/Sync.cs +++ b/src/Ryujinx.Graphics.OpenGL/Sync.cs @@ -14,15 +14,15 @@ namespace Ryujinx.Graphics.OpenGL public IntPtr Handle; } - private ulong _firstHandle = 0; - private static SyncObjectMask SyncFlags => HwCapabilities.RequiresSyncFlush ? 0 : SyncObjectMask.Bit; + private ulong _firstHandle; + private SyncObjectMask SyncFlags => _gd.Capabilities.RequiresSyncFlush ? 0 : SyncObjectMask.Bit; private readonly List _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, SyncObjectMask.Bit, 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; } }