OpenGL namespace is all done!

This commit is contained in:
Isaac Marovitz 2024-05-09 21:13:22 -04:00
parent 15978d9c55
commit 5db3568305
No known key found for this signature in database
GPG key ID: 97250B2B09A132E1
10 changed files with 471 additions and 417 deletions

View file

@ -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));
}

View file

@ -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;
}
}
}

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

@ -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;
}

View file

@ -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,

View file

@ -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));
}
@ -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);

View file

@ -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)

File diff suppressed because it is too large Load diff

View file

@ -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<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)
{
@ -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;
}

View file

@ -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<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, 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;
}
}