HwCapabilities.cs
1 using OpenTK.Graphics.OpenGL; 2 using System; 3 4 namespace Ryujinx.Graphics.OpenGL 5 { 6 static class HwCapabilities 7 { 8 private static readonly Lazy<bool> _supportsAlphaToCoverageDitherControl = new(() => HasExtension("GL_NV_alpha_to_coverage_dither_control")); 9 private static readonly Lazy<bool> _supportsAstcCompression = new(() => HasExtension("GL_KHR_texture_compression_astc_ldr")); 10 private static readonly Lazy<bool> _supportsBlendEquationAdvanced = new(() => HasExtension("GL_NV_blend_equation_advanced")); 11 private static readonly Lazy<bool> _supportsDrawTexture = new(() => HasExtension("GL_NV_draw_texture")); 12 private static readonly Lazy<bool> _supportsFragmentShaderInterlock = new(() => HasExtension("GL_ARB_fragment_shader_interlock")); 13 private static readonly Lazy<bool> _supportsFragmentShaderOrdering = new(() => HasExtension("GL_INTEL_fragment_shader_ordering")); 14 private static readonly Lazy<bool> _supportsGeometryShaderPassthrough = new(() => HasExtension("GL_NV_geometry_shader_passthrough")); 15 private static readonly Lazy<bool> _supportsImageLoadFormatted = new(() => HasExtension("GL_EXT_shader_image_load_formatted")); 16 private static readonly Lazy<bool> _supportsIndirectParameters = new(() => HasExtension("GL_ARB_indirect_parameters")); 17 private static readonly Lazy<bool> _supportsParallelShaderCompile = new(() => HasExtension("GL_ARB_parallel_shader_compile")); 18 private static readonly Lazy<bool> _supportsPolygonOffsetClamp = new(() => HasExtension("GL_EXT_polygon_offset_clamp")); 19 private static readonly Lazy<bool> _supportsQuads = new(SupportsQuadsCheck); 20 private static readonly Lazy<bool> _supportsSeamlessCubemapPerTexture = new(() => HasExtension("GL_ARB_seamless_cubemap_per_texture")); 21 private static readonly Lazy<bool> _supportsShaderBallot = new(() => HasExtension("GL_ARB_shader_ballot")); 22 private static readonly Lazy<bool> _supportsShaderViewportLayerArray = new(() => HasExtension("GL_ARB_shader_viewport_layer_array")); 23 private static readonly Lazy<bool> _supportsViewportArray2 = new(() => HasExtension("GL_NV_viewport_array2")); 24 private static readonly Lazy<bool> _supportsTextureCompressionBptc = new(() => HasExtension("GL_EXT_texture_compression_bptc")); 25 private static readonly Lazy<bool> _supportsTextureCompressionRgtc = new(() => HasExtension("GL_EXT_texture_compression_rgtc")); 26 private static readonly Lazy<bool> _supportsTextureCompressionS3tc = new(() => HasExtension("GL_EXT_texture_compression_s3tc")); 27 private static readonly Lazy<bool> _supportsTextureShadowLod = new(() => HasExtension("GL_EXT_texture_shadow_lod")); 28 private static readonly Lazy<bool> _supportsViewportSwizzle = new(() => HasExtension("GL_NV_viewport_swizzle")); 29 30 private static readonly Lazy<int> _maximumComputeSharedMemorySize = new(() => GetLimit(All.MaxComputeSharedMemorySize)); 31 private static readonly Lazy<int> _storageBufferOffsetAlignment = new(() => GetLimit(All.ShaderStorageBufferOffsetAlignment)); 32 private static readonly Lazy<int> _textureBufferOffsetAlignment = new(() => GetLimit(All.TextureBufferOffsetAlignment)); 33 34 public enum GpuVendor 35 { 36 Unknown, 37 AmdWindows, 38 AmdUnix, 39 IntelWindows, 40 IntelUnix, 41 Nvidia, 42 } 43 44 private static readonly Lazy<GpuVendor> _gpuVendor = new(GetGpuVendor); 45 46 private static bool IsIntel => _gpuVendor.Value == GpuVendor.IntelWindows || _gpuVendor.Value == GpuVendor.IntelUnix; 47 48 public static GpuVendor Vendor => _gpuVendor.Value; 49 50 private static readonly Lazy<float> _maxSupportedAnisotropy = new(GL.GetFloat((GetPName)All.MaxTextureMaxAnisotropy)); 51 52 public static bool UsePersistentBufferForFlush => _gpuVendor.Value == GpuVendor.AmdWindows || _gpuVendor.Value == GpuVendor.Nvidia; 53 54 public static bool SupportsAlphaToCoverageDitherControl => _supportsAlphaToCoverageDitherControl.Value; 55 public static bool SupportsAstcCompression => _supportsAstcCompression.Value; 56 public static bool SupportsBlendEquationAdvanced => _supportsBlendEquationAdvanced.Value; 57 public static bool SupportsDrawTexture => _supportsDrawTexture.Value; 58 public static bool SupportsFragmentShaderInterlock => _supportsFragmentShaderInterlock.Value; 59 public static bool SupportsFragmentShaderOrdering => _supportsFragmentShaderOrdering.Value; 60 public static bool SupportsGeometryShaderPassthrough => _supportsGeometryShaderPassthrough.Value; 61 public static bool SupportsImageLoadFormatted => _supportsImageLoadFormatted.Value; 62 public static bool SupportsIndirectParameters => _supportsIndirectParameters.Value; 63 public static bool SupportsParallelShaderCompile => _supportsParallelShaderCompile.Value; 64 public static bool SupportsPolygonOffsetClamp => _supportsPolygonOffsetClamp.Value; 65 public static bool SupportsQuads => _supportsQuads.Value; 66 public static bool SupportsSeamlessCubemapPerTexture => _supportsSeamlessCubemapPerTexture.Value; 67 public static bool SupportsShaderBallot => _supportsShaderBallot.Value; 68 public static bool SupportsShaderViewportLayerArray => _supportsShaderViewportLayerArray.Value; 69 public static bool SupportsViewportArray2 => _supportsViewportArray2.Value; 70 public static bool SupportsTextureCompressionBptc => _supportsTextureCompressionBptc.Value; 71 public static bool SupportsTextureCompressionRgtc => _supportsTextureCompressionRgtc.Value; 72 public static bool SupportsTextureCompressionS3tc => _supportsTextureCompressionS3tc.Value; 73 public static bool SupportsTextureShadowLod => _supportsTextureShadowLod.Value; 74 public static bool SupportsViewportSwizzle => _supportsViewportSwizzle.Value; 75 76 public static bool SupportsMismatchingViewFormat => _gpuVendor.Value != GpuVendor.AmdWindows && _gpuVendor.Value != GpuVendor.IntelWindows; 77 public static bool SupportsNonConstantTextureOffset => _gpuVendor.Value == GpuVendor.Nvidia; 78 public static bool RequiresSyncFlush => _gpuVendor.Value == GpuVendor.AmdWindows || IsIntel; 79 80 public static int MaximumComputeSharedMemorySize => _maximumComputeSharedMemorySize.Value; 81 public static int StorageBufferOffsetAlignment => _storageBufferOffsetAlignment.Value; 82 public static int TextureBufferOffsetAlignment => _textureBufferOffsetAlignment.Value; 83 84 public static float MaximumSupportedAnisotropy => _maxSupportedAnisotropy.Value; 85 86 private static bool HasExtension(string name) 87 { 88 int numExtensions = GL.GetInteger(GetPName.NumExtensions); 89 90 for (int extension = 0; extension < numExtensions; extension++) 91 { 92 if (GL.GetString(StringNameIndexed.Extensions, extension) == name) 93 { 94 return true; 95 } 96 } 97 98 return false; 99 } 100 101 private static int GetLimit(All name) 102 { 103 return GL.GetInteger((GetPName)name); 104 } 105 106 private static GpuVendor GetGpuVendor() 107 { 108 string vendor = GL.GetString(StringName.Vendor).ToLowerInvariant(); 109 110 if (vendor == "nvidia corporation") 111 { 112 return GpuVendor.Nvidia; 113 } 114 else if (vendor == "intel") 115 { 116 string renderer = GL.GetString(StringName.Renderer).ToLowerInvariant(); 117 118 return renderer.Contains("mesa") ? GpuVendor.IntelUnix : GpuVendor.IntelWindows; 119 } 120 else if (vendor == "ati technologies inc." || vendor == "advanced micro devices, inc.") 121 { 122 return GpuVendor.AmdWindows; 123 } 124 else if (vendor == "amd" || vendor == "x.org") 125 { 126 return GpuVendor.AmdUnix; 127 } 128 else 129 { 130 return GpuVendor.Unknown; 131 } 132 } 133 134 private static bool SupportsQuadsCheck() 135 { 136 GL.GetError(); // Clear any existing error. 137 GL.Begin(PrimitiveType.Quads); 138 GL.End(); 139 140 return GL.GetError() == ErrorCode.NoError; 141 } 142 } 143 }