mirror of
https://github.com/Ryujinx/Ryujinx.git
synced 2024-05-20 15:37:15 +01:00
Compare commits
12 commits
ae4c629284
...
6e9024b7ed
Author | SHA1 | Date | |
---|---|---|---|
6e9024b7ed | |||
e584f8d37d | |||
5db3568305 | |||
15978d9c55 | |||
0c88c23b30 | |||
1d18ed2ba2 | |||
a9d0dd3893 | |||
8df23211f6 | |||
e46b671875 | |||
38d900c932 | |||
740842d600 | |||
65abc70edc |
|
@ -39,6 +39,7 @@
|
|||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
||||
<PackageVersion Include="Silk.NET.OpenGL.Legacy" Version="2.21.0" />
|
||||
<PackageVersion Include="Silk.NET.OpenGL.Legacy.Extensions.ARB" Version="2.21.0" />
|
||||
<PackageVersion Include="Silk.NET.OpenGL.Legacy.Extensions.EXT" Version="2.21.0" />
|
||||
<PackageVersion Include="Silk.NET.OpenGL.Legacy.Extensions.NV" Version="2.21.0" />
|
||||
<PackageVersion Include="Silk.NET.Vulkan" Version="2.16.0" />
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
public static void Initialize(GL gl, GraphicsDebugLevel logLevel)
|
||||
{
|
||||
// Disable everything
|
||||
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DontCare, DebugSeverity.DontCare, 0, (int[])null, false);
|
||||
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DontCare, DebugSeverity.DontCare, 0, (uint[])null, false);
|
||||
|
||||
if (logLevel == GraphicsDebugLevel.None)
|
||||
{
|
||||
|
@ -30,16 +30,16 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
|
||||
if (logLevel == GraphicsDebugLevel.Error)
|
||||
{
|
||||
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DebugTypeError, DebugSeverity.DontCare, 0, (int[])null, true);
|
||||
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DebugTypeError, DebugSeverity.DontCare, 0, (uint[])null, true);
|
||||
}
|
||||
else if (logLevel == GraphicsDebugLevel.Slowdowns)
|
||||
{
|
||||
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DebugTypeError, DebugSeverity.DontCare, 0, (int[])null, true);
|
||||
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DebugTypePerformance, DebugSeverity.DontCare, 0, (int[])null, true);
|
||||
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DebugTypeError, DebugSeverity.DontCare, 0, (uint[])null, true);
|
||||
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DebugTypePerformance, DebugSeverity.DontCare, 0, (uint[])null, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DontCare, DebugSeverity.DontCare, 0, (int[])null, true);
|
||||
gl.DebugMessageControl(DebugSource.DontCare, DebugType.DontCare, DebugSeverity.DontCare, 0, (uint[])null, true);
|
||||
}
|
||||
|
||||
_counter = 0;
|
||||
|
@ -61,7 +61,10 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
{
|
||||
string msg = Marshal.PtrToStringUTF8(message).Replace('\n', ' ');
|
||||
|
||||
switch (type)
|
||||
DebugType debugType = (DebugType)type;
|
||||
DebugSource debugSource = (DebugSource)source;
|
||||
|
||||
switch (debugType)
|
||||
{
|
||||
case DebugType.DebugTypeError:
|
||||
Logger.Error?.Print(LogClass.Gpu, $"{severity}: {msg}\nCallStack={Environment.StackTrace}", "GLERROR");
|
||||
|
@ -76,7 +79,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
Logger.Info?.Print(LogClass.Gpu, $"}} ({id}) {severity}: {msg}", "GLINFO");
|
||||
break;
|
||||
default:
|
||||
if (source == DebugSource.DebugSourceApplication)
|
||||
if (debugSource == DebugSource.DebugSourceApplication)
|
||||
{
|
||||
Logger.Info?.Print(LogClass.Gpu, $"{type} {severity}: {msg}", "GLINFO");
|
||||
}
|
||||
|
@ -93,7 +96,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
{
|
||||
int counter = Interlocked.Increment(ref _counter);
|
||||
|
||||
gl.PushDebugGroup(DebugSource.DebugSourceApplication, counter, dbgMsg.Length, dbgMsg);
|
||||
gl.PushDebugGroup(DebugSource.DebugSourceApplication, (uint)counter, (uint)dbgMsg.Length, dbgMsg);
|
||||
}
|
||||
|
||||
public static void PopGroup(GL gl)
|
||||
|
@ -103,7 +106,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
|
||||
public static void Print(GL gl, string dbgMsg, DebugType type = DebugType.DebugTypeMarker, DebugSeverity severity = DebugSeverity.DebugSeverityNotification, int id = 999999)
|
||||
{
|
||||
gl.DebugMessageInsert(DebugSource.DebugSourceApplication, type, id, severity, dbgMsg.Length, dbgMsg);
|
||||
gl.DebugMessageInsert(DebugSource.DebugSourceApplication, type, (uint)id, severity, (uint)dbgMsg.Length, dbgMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,13 +123,13 @@ namespace Ryujinx.Graphics.OpenGL.Effects
|
|||
uint previousProgram = (uint)_gd.Api.GetInteger(GetPName.CurrentProgram);
|
||||
int previousUnit = _gd.Api.GetInteger(GetPName.ActiveTexture);
|
||||
_gd.Api.ActiveTexture(TextureUnit.Texture0);
|
||||
int previousTextureBinding = _gd.Api.GetInteger(GetPName.TextureBinding2D);
|
||||
uint previousTextureBinding = (uint)_gd.Api.GetInteger(GetPName.TextureBinding2D);
|
||||
|
||||
_gd.Api.BindImageTexture(0, textureView.Handle, 0, false, 0, BufferAccessARB.ReadWrite, SizedInternalFormat.Rgba8);
|
||||
_gd.Api.BindImageTexture(0, textureView.Handle, 0, false, 0, BufferAccessARB.ReadWrite, InternalFormat.Rgba8);
|
||||
|
||||
int threadGroupWorkRegionDim = 16;
|
||||
int dispatchX = (width + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
|
||||
int dispatchY = (height + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
|
||||
uint dispatchX = (uint)((width + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim);
|
||||
uint dispatchY = (uint)((height + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim);
|
||||
|
||||
// Scaling pass
|
||||
float srcWidth = Math.Abs(source.X2 - source.X1);
|
||||
|
@ -156,7 +156,7 @@ namespace Ryujinx.Graphics.OpenGL.Effects
|
|||
|
||||
// Sharpening Pass
|
||||
_gd.Api.UseProgram(_sharpeningShaderProgram);
|
||||
_gd.Api.BindImageTexture(0, destinationTexture.Handle, 0, false, 0, BufferAccessARB.ReadWrite, SizedInternalFormat.Rgba8);
|
||||
_gd.Api.BindImageTexture(0, destinationTexture.Handle, 0, false, 0, BufferAccessARB.ReadWrite, InternalFormat.Rgba8);
|
||||
textureView.Bind(0);
|
||||
_gd.Api.Uniform1(_inputUniform, 0);
|
||||
_gd.Api.Uniform1(_outputUniform, 0);
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace Ryujinx.Graphics.OpenGL.Effects
|
|||
|
||||
private void Initialize()
|
||||
{
|
||||
_shaderProgram = ShaderHelper.CompileProgram(EmbeddedResources.ReadAllText("Ryujinx.Graphics.OpenGL/Effects/Shaders/fxaa.glsl"), ShaderType.ComputeShader);
|
||||
_shaderProgram = ShaderHelper.CompileProgram(_gd.Api, EmbeddedResources.ReadAllText("Ryujinx.Graphics.OpenGL/Effects/Shaders/fxaa.glsl"), ShaderType.ComputeShader);
|
||||
|
||||
_resolutionUniform = _gd.Api.GetUniformLocation(_shaderProgram, "invResolution");
|
||||
_inputUniform = _gd.Api.GetUniformLocation(_shaderProgram, "inputTexture");
|
||||
|
@ -49,21 +49,21 @@ namespace Ryujinx.Graphics.OpenGL.Effects
|
|||
|
||||
var textureView = _textureStorage.CreateView(view.Info, 0, 0) as TextureView;
|
||||
|
||||
int previousProgram = _gd.Api.GetInteger(GetPName.CurrentProgram);
|
||||
uint previousProgram = (uint)_gd.Api.GetInteger(GetPName.CurrentProgram);
|
||||
int previousUnit = _gd.Api.GetInteger(GetPName.ActiveTexture);
|
||||
_gd.Api.ActiveTexture(TextureUnit.Texture0);
|
||||
int previousTextureBinding = _gd.Api.GetInteger(GetPName.TextureBinding2D);
|
||||
uint previousTextureBinding = (uint)_gd.Api.GetInteger(GetPName.TextureBinding2D);
|
||||
|
||||
_gd.Api.BindImageTexture(0, textureView.Handle, 0, false, 0, BufferAccessARB.ReadWrite, SizedInternalFormat.Rgba8);
|
||||
_gd.Api.BindImageTexture(0, textureView.Handle, 0, false, 0, BufferAccessARB.ReadWrite, InternalFormat.Rgba8);
|
||||
_gd.Api.UseProgram(_shaderProgram);
|
||||
|
||||
var dispatchX = BitUtils.DivRoundUp(view.Width, IPostProcessingEffect.LocalGroupSize);
|
||||
var dispatchY = BitUtils.DivRoundUp(view.Height, IPostProcessingEffect.LocalGroupSize);
|
||||
uint dispatchX = (uint)BitUtils.DivRoundUp(view.Width, IPostProcessingEffect.LocalGroupSize);
|
||||
uint dispatchY = (uint)BitUtils.DivRoundUp(view.Height, IPostProcessingEffect.LocalGroupSize);
|
||||
|
||||
view.Bind(0);
|
||||
_gd.Api.Uniform1(_inputUniform, 0);
|
||||
_gd.Api.Uniform1(_outputUniform, 0);
|
||||
_gd.Api.Uniform2(_resolutionUniform, (float)view.Width, (float)view.Height);
|
||||
_gd.Api.Uniform2(_resolutionUniform, view.Width, view.Height);
|
||||
_gd.Api.DispatchCompute(dispatchX, dispatchY, 1);
|
||||
_gd.Api.UseProgram(previousProgram);
|
||||
_gd.Api.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);
|
||||
|
|
|
@ -93,13 +93,13 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
|
|||
var neighbourShaderData = EmbeddedResources.ReadAllText("Ryujinx.Graphics.OpenGL/Effects/Shaders/smaa_neighbour.glsl");
|
||||
|
||||
var shaders = new string[] { presets, edgeShaderData };
|
||||
var edgeProgram = ShaderHelper.CompileProgram(shaders, ShaderType.ComputeShader);
|
||||
var edgeProgram = ShaderHelper.CompileProgram(_gd.Api, shaders, ShaderType.ComputeShader);
|
||||
|
||||
shaders[1] = blendShaderData;
|
||||
var blendProgram = ShaderHelper.CompileProgram(shaders, ShaderType.ComputeShader);
|
||||
var blendProgram = ShaderHelper.CompileProgram(_gd.Api, shaders, ShaderType.ComputeShader);
|
||||
|
||||
shaders[1] = neighbourShaderData;
|
||||
var neighbourProgram = ShaderHelper.CompileProgram(shaders, ShaderType.ComputeShader);
|
||||
var neighbourProgram = ShaderHelper.CompileProgram(_gd.Api, shaders, ShaderType.ComputeShader);
|
||||
|
||||
_edgeShaderPrograms[i] = edgeProgram;
|
||||
_blendShaderPrograms[i] = blendProgram;
|
||||
|
@ -184,14 +184,14 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
|
|||
var areaTexture = _areaTexture.DefaultView as TextureView;
|
||||
var searchTexture = _searchTexture.DefaultView as TextureView;
|
||||
|
||||
var previousFramebuffer = _gd.Api.GetInteger(GetPName.DrawFramebufferBinding);
|
||||
uint previousFramebuffer = (uint)_gd.Api.GetInteger(GetPName.DrawFramebufferBinding);
|
||||
int previousUnit = _gd.Api.GetInteger(GetPName.ActiveTexture);
|
||||
_gd.Api.ActiveTexture(TextureUnit.Texture0);
|
||||
int previousTextureBinding0 = _gd.Api.GetInteger(GetPName.TextureBinding2D);
|
||||
uint previousTextureBinding0 = (uint)_gd.Api.GetInteger(GetPName.TextureBinding2D);
|
||||
_gd.Api.ActiveTexture(TextureUnit.Texture1);
|
||||
int previousTextureBinding1 = _gd.Api.GetInteger(GetPName.TextureBinding2D);
|
||||
uint previousTextureBinding1 = (uint)_gd.Api.GetInteger(GetPName.TextureBinding2D);
|
||||
_gd.Api.ActiveTexture(TextureUnit.Texture2);
|
||||
int previousTextureBinding2 = _gd.Api.GetInteger(GetPName.TextureBinding2D);
|
||||
uint previousTextureBinding2 = (uint)_gd.Api.GetInteger(GetPName.TextureBinding2D);
|
||||
|
||||
var framebuffer = new Framebuffer(_gd.Api);
|
||||
framebuffer.Bind();
|
||||
|
@ -206,11 +206,11 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
|
|||
|
||||
framebuffer.Dispose();
|
||||
|
||||
var dispatchX = BitUtils.DivRoundUp(view.Width, IPostProcessingEffect.LocalGroupSize);
|
||||
var dispatchY = BitUtils.DivRoundUp(view.Height, IPostProcessingEffect.LocalGroupSize);
|
||||
uint dispatchX = (uint)BitUtils.DivRoundUp(view.Width, IPostProcessingEffect.LocalGroupSize);
|
||||
uint dispatchY = (uint)BitUtils.DivRoundUp(view.Height, IPostProcessingEffect.LocalGroupSize);
|
||||
|
||||
uint previousProgram = (uint)_gd.Api.GetInteger(GetPName.CurrentProgram);
|
||||
_gd.Api.BindImageTexture(0, edgeOutput.Handle, 0, false, 0, BufferAccessARB.ReadWrite, SizedInternalFormat.Rgba8);
|
||||
_gd.Api.BindImageTexture(0, edgeOutput.Handle, 0, false, 0, BufferAccessARB.ReadWrite, InternalFormat.Rgba8);
|
||||
_gd.Api.UseProgram(_edgeShaderPrograms[Quality]);
|
||||
view.Bind(0);
|
||||
_gd.Api.Uniform1(_inputUniform, 0);
|
||||
|
@ -219,7 +219,7 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
|
|||
_gd.Api.DispatchCompute(dispatchX, dispatchY, 1);
|
||||
_gd.Api.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);
|
||||
|
||||
_gd.Api.BindImageTexture(0, blendOutput.Handle, 0, false, 0, BufferAccessARB.ReadWrite, SizedInternalFormat.Rgba8);
|
||||
_gd.Api.BindImageTexture(0, blendOutput.Handle, 0, false, 0, BufferAccessARB.ReadWrite,InternalFormat.Rgba8);
|
||||
_gd.Api.UseProgram(_blendShaderPrograms[Quality]);
|
||||
edgeOutput.Bind(0);
|
||||
areaTexture.Bind(1);
|
||||
|
@ -232,7 +232,7 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
|
|||
_gd.Api.DispatchCompute(dispatchX, dispatchY, 1);
|
||||
_gd.Api.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);
|
||||
|
||||
_gd.Api.BindImageTexture(0, textureView.Handle, 0, false, 0, BufferAccessARB.ReadWrite, SizedInternalFormat.Rgba8);
|
||||
_gd.Api.BindImageTexture(0, textureView.Handle, 0, false, 0, BufferAccessARB.ReadWrite, InternalFormat.Rgba8);
|
||||
_gd.Api.UseProgram(_neighbourShaderPrograms[Quality]);
|
||||
view.Bind(0);
|
||||
blendOutput.Bind(1);
|
||||
|
|
|
@ -118,7 +118,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
drawBuffers[index] = DrawBufferMode.ColorAttachment0 + index;
|
||||
}
|
||||
|
||||
api.DrawBuffers(colorsCount, drawBuffers);
|
||||
api.DrawBuffers((uint)colorsCount, drawBuffers);
|
||||
}
|
||||
|
||||
private static FramebufferAttachment GetAttachment(Format format)
|
||||
|
|
161
src/Ryujinx.Graphics.OpenGL/HardwareCapabilities.cs
Normal file
161
src/Ryujinx.Graphics.OpenGL/HardwareCapabilities.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -101,15 +101,15 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
_gd.Api.TexParameter(target, TextureParameterName.DepthStencilTextureMode, (int)Info.DepthStencilMode.Convert());
|
||||
}
|
||||
|
||||
public ITexture CreateView(TextureCreateInfo info, uint firstLayer, uint firstLevel)
|
||||
public ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel)
|
||||
{
|
||||
firstLayer += FirstLayer;
|
||||
firstLevel += FirstLevel;
|
||||
firstLayer += (int)FirstLayer;
|
||||
firstLevel += (int)FirstLevel;
|
||||
|
||||
return _parent.CreateView(info, firstLayer, firstLevel);
|
||||
return _parent.CreateView(info, (uint)firstLayer, (uint)firstLevel);
|
||||
}
|
||||
|
||||
public void CopyTo(ITexture destination, uint firstLayer, uint firstLevel)
|
||||
public void CopyTo(ITexture destination, int firstLayer, int firstLevel)
|
||||
{
|
||||
TextureView destinationView = (TextureView)destination;
|
||||
|
||||
|
@ -118,18 +118,18 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
|
||||
if (dstIsMultisample != srcIsMultisample && Info.Format.IsDepthOrStencil())
|
||||
{
|
||||
uint layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
|
||||
uint layers = (uint)Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
|
||||
CopyWithBlitForDepthMS(destinationView, 0, firstLayer, layers);
|
||||
}
|
||||
else if (!dstIsMultisample && srcIsMultisample)
|
||||
{
|
||||
uint layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
|
||||
_gd.TextureCopyMS.CopyMSToNonMS(this, destinationView, 0, firstLayer, layers);
|
||||
uint layers = (uint)Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
|
||||
_gd.TextureCopyMS.CopyMSToNonMS(this, destinationView, 0, firstLayer, (int)layers);
|
||||
}
|
||||
else if (dstIsMultisample && !srcIsMultisample)
|
||||
{
|
||||
uint layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
|
||||
_gd.TextureCopyMS.CopyNonMSToMS(this, destinationView, 0, firstLayer, layers);
|
||||
uint layers = (uint)Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
|
||||
_gd.TextureCopyMS.CopyNonMSToMS(this, destinationView, 0, firstLayer, (int)layers);
|
||||
}
|
||||
else if (destinationView.Info.BytesPerPixel != Info.BytesPerPixel)
|
||||
{
|
||||
|
@ -228,7 +228,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
1);
|
||||
|
||||
_gd.TextureCopy.Copy(this, intermmediate, srcRegion, dstRegion, false);
|
||||
_gd.TextureCopy.Copy(intermmediate, destinationView, dstRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, layers, 1);
|
||||
_gd.TextureCopy.Copy(intermmediate, destinationView, dstRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, (int)layers, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -252,7 +252,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
1);
|
||||
|
||||
_gd.TextureCopy.Copy(this, intermmediate, srcRegion, srcRegion, false);
|
||||
_gd.TextureCopy.Copy(intermmediate, destinationView, srcRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, layers, 1);
|
||||
_gd.TextureCopy.Copy(intermmediate, destinationView, srcRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, (int)layers, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -273,7 +273,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
|
||||
ReadOnlySpan<byte> data;
|
||||
|
||||
if (HwCapabilities.UsePersistentBufferForFlush)
|
||||
if (_gd.Capabilities.UsePersistentBufferForFlush)
|
||||
{
|
||||
data = _gd.PersistentBuffers.Default.GetTextureData(this, size);
|
||||
}
|
||||
|
@ -298,7 +298,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
{
|
||||
int size = Info.GetMipSize(level);
|
||||
|
||||
if (HwCapabilities.UsePersistentBufferForFlush)
|
||||
if (_gd.Capabilities.UsePersistentBufferForFlush)
|
||||
{
|
||||
return PinnedSpan<byte>.UnsafeFromSpan(_gd.PersistentBuffers.Default.GetTextureData(this, size, layer, level));
|
||||
}
|
||||
|
@ -344,7 +344,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
return WriteTo2D(IntPtr.Zero + offset, layer, level);
|
||||
}
|
||||
|
||||
private int WriteTo2D(IntPtr data, int layer, int level)
|
||||
private unsafe int WriteTo2D(IntPtr data, int layer, int level)
|
||||
{
|
||||
TextureTarget target = Target.Convert();
|
||||
|
||||
|
@ -364,15 +364,37 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
|
||||
if (format.IsCompressed)
|
||||
{
|
||||
_gd.Api.GetCompressedTextureSubImage(Handle, level, 0, 0, layer, Math.Max(1, Info.Width >> level), Math.Max(1, Info.Height >> level), 1, mipSize, data);
|
||||
_gd.Api.GetCompressedTextureSubImage(
|
||||
Handle,
|
||||
level,
|
||||
0,
|
||||
0,
|
||||
layer,
|
||||
(uint)Math.Max(1, Info.Width >> level),
|
||||
(uint)Math.Max(1, Info.Height >> level),
|
||||
1,
|
||||
(uint)mipSize,
|
||||
(void*)data);
|
||||
}
|
||||
else if (format.PixelFormat != PixelFormat.DepthStencil)
|
||||
{
|
||||
_gd.Api.GetTextureSubImage(Handle, level, 0, 0, layer, Math.Max(1, Info.Width >> level), Math.Max(1, Info.Height >> level), 1, pixelFormat, pixelType, mipSize, data);
|
||||
_gd.Api.GetTextureSubImage(
|
||||
Handle,
|
||||
level,
|
||||
0,
|
||||
0,
|
||||
layer,
|
||||
(uint)Math.Max(1, Info.Width >> level),
|
||||
(uint)Math.Max(1, Info.Height >> level),
|
||||
1,
|
||||
pixelFormat,
|
||||
pixelType,
|
||||
(uint)mipSize,
|
||||
(void*)data);
|
||||
}
|
||||
else
|
||||
{
|
||||
_gd.Api.GetTexImage(target, level, pixelFormat, pixelType, data);
|
||||
_gd.Api.GetTexImage(target, level, pixelFormat, pixelType, (void*)data);
|
||||
|
||||
// The GL function returns all layers. Must return the offset of the layer we're interested in.
|
||||
return target switch
|
||||
|
@ -387,7 +409,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
return 0;
|
||||
}
|
||||
|
||||
private void WriteTo(IntPtr data, bool forceBgra = false)
|
||||
private unsafe void WriteTo(IntPtr data, bool forceBgra = false)
|
||||
{
|
||||
TextureTarget target = Target.Convert();
|
||||
|
||||
|
@ -433,11 +455,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
|
||||
if (format.IsCompressed)
|
||||
{
|
||||
_gd.Api.GetCompressedTexImage(target + face, level, data + faceOffset);
|
||||
_gd.Api.GetCompressedTexImage(target + face, level, (void*)(data + faceOffset));
|
||||
}
|
||||
else
|
||||
{
|
||||
_gd.Api.GetTexImage(target + face, level, pixelFormat, pixelType, data + faceOffset);
|
||||
_gd.Api.GetTexImage(target + face, level, pixelFormat, pixelType, (void*)(data + faceOffset));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -697,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);
|
||||
|
@ -710,9 +732,9 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
|
||||
FormatInfo format = FormatTable.GetFormatInfo(Info.Format);
|
||||
|
||||
int width = Info.Width;
|
||||
int height = Info.Height;
|
||||
int depth = Info.Depth;
|
||||
uint width = (uint)Info.Width;
|
||||
uint height = (uint)Info.Height;
|
||||
uint depth = (uint)Info.Depth;
|
||||
int levels = Info.GetLevelsClamped();
|
||||
|
||||
int offset = 0;
|
||||
|
@ -738,8 +760,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
level,
|
||||
0,
|
||||
width,
|
||||
format.PixelFormat,
|
||||
mipSize,
|
||||
(InternalFormat)format.PixelFormat,
|
||||
(uint)mipSize,
|
||||
data);
|
||||
}
|
||||
else
|
||||
|
@ -766,8 +788,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
0,
|
||||
width,
|
||||
height,
|
||||
format.PixelFormat,
|
||||
mipSize,
|
||||
(InternalFormat)format.PixelFormat,
|
||||
(uint)mipSize,
|
||||
data);
|
||||
}
|
||||
else
|
||||
|
@ -799,8 +821,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
width,
|
||||
height,
|
||||
depth,
|
||||
format.PixelFormat,
|
||||
mipSize,
|
||||
(InternalFormat)format.PixelFormat,
|
||||
(uint)mipSize,
|
||||
data);
|
||||
}
|
||||
else
|
||||
|
@ -829,20 +851,20 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
{
|
||||
_gd.Api.CompressedTexSubImage2D(
|
||||
TextureTarget.TextureCubeMapPositiveX + face,
|
||||
baseLevel + level,
|
||||
(int)baseLevel + level,
|
||||
0,
|
||||
0,
|
||||
width,
|
||||
height,
|
||||
format.PixelFormat,
|
||||
mipSize / 6,
|
||||
(InternalFormat)format.PixelFormat,
|
||||
(uint)mipSize / 6,
|
||||
data + faceOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
_gd.Api.TexSubImage2D(
|
||||
TextureTarget.TextureCubeMapPositiveX + face,
|
||||
baseLevel + level,
|
||||
(int)baseLevel + level,
|
||||
0,
|
||||
0,
|
||||
width,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Silk.NET.OpenGL.Legacy;
|
||||
using Silk.NET.OpenGL.Legacy.Extensions.ARB;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
|
@ -6,6 +7,7 @@ using Ryujinx.Graphics.OpenGL.Image;
|
|||
using Ryujinx.Graphics.OpenGL.Queries;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Sampler = Ryujinx.Graphics.OpenGL.Image.Sampler;
|
||||
|
||||
namespace Ryujinx.Graphics.OpenGL
|
||||
|
@ -39,6 +41,8 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
|
||||
internal int BufferCount { get; private set; }
|
||||
|
||||
internal HardwareCapabilities Capabilities;
|
||||
|
||||
public string GpuVendor { get; private set; }
|
||||
public string GpuRenderer { get; private set; }
|
||||
public string GpuVersion { get; private set; }
|
||||
|
@ -48,15 +52,15 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
public OpenGLRenderer(GL api)
|
||||
{
|
||||
Api = api;
|
||||
_pipeline = new Pipeline(Api);
|
||||
_pipeline = new Pipeline(this);
|
||||
_counters = new Counters(Api);
|
||||
_window = new Window(this);
|
||||
_textureCopy = new TextureCopy(this);
|
||||
_backgroundTextureCopy = new TextureCopy(this);
|
||||
TextureCopyIncompatible = new TextureCopyIncompatible(this);
|
||||
TextureCopyMS = new TextureCopyMS(this);
|
||||
_sync = new Sync(Api);
|
||||
PersistentBuffers = new PersistentBuffers();
|
||||
_sync = new Sync(this);
|
||||
PersistentBuffers = new PersistentBuffers(Api);
|
||||
ResourcePool = new ResourcePool();
|
||||
}
|
||||
|
||||
|
@ -100,12 +104,12 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
|
||||
public IProgram CreateProgram(ShaderSource[] shaders, ShaderInfo info)
|
||||
{
|
||||
return new Program(Api, shaders, info.FragmentOutputMap);
|
||||
return new Program(this, shaders, info.FragmentOutputMap);
|
||||
}
|
||||
|
||||
public ISampler CreateSampler(SamplerCreateInfo info)
|
||||
{
|
||||
return new Sampler(Api, info);
|
||||
return new Sampler(this, info);
|
||||
}
|
||||
|
||||
public ITexture CreateTexture(TextureCreateInfo info)
|
||||
|
@ -144,9 +148,9 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
|
||||
public Capabilities GetCapabilities()
|
||||
{
|
||||
bool intelWindows = HwCapabilities.Vendor == HwCapabilities.GpuVendor.IntelWindows;
|
||||
bool intelUnix = HwCapabilities.Vendor == HwCapabilities.GpuVendor.IntelUnix;
|
||||
bool amdWindows = HwCapabilities.Vendor == HwCapabilities.GpuVendor.AmdWindows;
|
||||
bool intelWindows = Capabilities.GpuVendor == OpenGL.GpuVendor.IntelWindows;
|
||||
bool intelUnix = Capabilities.GpuVendor == OpenGL.GpuVendor.IntelUnix;
|
||||
bool amdWindows = Capabilities.GpuVendor == OpenGL.GpuVendor.AmdWindows;
|
||||
|
||||
return new Capabilities(
|
||||
api: TargetApi.OpenGL,
|
||||
|
@ -155,9 +159,9 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
hasVectorIndexingBug: amdWindows,
|
||||
needsFragmentOutputSpecialization: false,
|
||||
reduceShaderPrecision: false,
|
||||
supportsAstcCompression: HwCapabilities.SupportsAstcCompression,
|
||||
supportsBc123Compression: HwCapabilities.SupportsTextureCompressionS3tc,
|
||||
supportsBc45Compression: HwCapabilities.SupportsTextureCompressionRgtc,
|
||||
supportsAstcCompression: Capabilities.SupportsAstcCompression,
|
||||
supportsBc123Compression: Capabilities.SupportsTextureCompressionS3tc,
|
||||
supportsBc45Compression: Capabilities.SupportsTextureCompressionRgtc,
|
||||
supportsBc67Compression: true, // Should check BPTC extension, but for some reason NVIDIA is not exposing the extension.
|
||||
supportsEtc2Compression: true,
|
||||
supports3DTextureCompression: false,
|
||||
|
@ -167,39 +171,39 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
supportsSnormBufferTextureFormat: false,
|
||||
supports5BitComponentFormat: true,
|
||||
supportsSparseBuffer: false,
|
||||
supportsBlendEquationAdvanced: HwCapabilities.SupportsBlendEquationAdvanced,
|
||||
supportsFragmentShaderInterlock: HwCapabilities.SupportsFragmentShaderInterlock,
|
||||
supportsFragmentShaderOrderingIntel: HwCapabilities.SupportsFragmentShaderOrdering,
|
||||
supportsBlendEquationAdvanced: Capabilities.SupportsBlendEquationAdvanced,
|
||||
supportsFragmentShaderInterlock: Capabilities.SupportsFragmentShaderInterlock,
|
||||
supportsFragmentShaderOrderingIntel: Capabilities.SupportsFragmentShaderOrdering,
|
||||
supportsGeometryShader: true,
|
||||
supportsGeometryShaderPassthrough: HwCapabilities.SupportsGeometryShaderPassthrough,
|
||||
supportsGeometryShaderPassthrough: Capabilities.SupportsGeometryShaderPassthrough,
|
||||
supportsTransformFeedback: true,
|
||||
supportsImageLoadFormatted: HwCapabilities.SupportsImageLoadFormatted,
|
||||
supportsLayerVertexTessellation: HwCapabilities.SupportsShaderViewportLayerArray,
|
||||
supportsMismatchingViewFormat: HwCapabilities.SupportsMismatchingViewFormat,
|
||||
supportsImageLoadFormatted: Capabilities.SupportsImageLoadFormatted,
|
||||
supportsLayerVertexTessellation: Capabilities.SupportsShaderViewportLayerArray,
|
||||
supportsMismatchingViewFormat: Capabilities.SupportsMismatchingViewFormat,
|
||||
supportsCubemapView: true,
|
||||
supportsNonConstantTextureOffset: HwCapabilities.SupportsNonConstantTextureOffset,
|
||||
supportsNonConstantTextureOffset: Capabilities.SupportsNonConstantTextureOffset,
|
||||
supportsScaledVertexFormats: true,
|
||||
supportsSeparateSampler: false,
|
||||
supportsShaderBallot: HwCapabilities.SupportsShaderBallot,
|
||||
supportsShaderBallot: Capabilities.SupportsShaderBallot,
|
||||
supportsShaderBarrierDivergence: !(intelWindows || intelUnix),
|
||||
supportsShaderFloat64: true,
|
||||
supportsTextureGatherOffsets: true,
|
||||
supportsTextureShadowLod: HwCapabilities.SupportsTextureShadowLod,
|
||||
supportsTextureShadowLod: Capabilities.SupportsTextureShadowLod,
|
||||
supportsVertexStoreAndAtomics: true,
|
||||
supportsViewportIndexVertexTessellation: HwCapabilities.SupportsShaderViewportLayerArray,
|
||||
supportsViewportMask: HwCapabilities.SupportsViewportArray2,
|
||||
supportsViewportSwizzle: HwCapabilities.SupportsViewportSwizzle,
|
||||
supportsIndirectParameters: HwCapabilities.SupportsIndirectParameters,
|
||||
supportsViewportIndexVertexTessellation: Capabilities.SupportsShaderViewportLayerArray,
|
||||
supportsViewportMask: Capabilities.SupportsViewportArray2,
|
||||
supportsViewportSwizzle: Capabilities.SupportsViewportSwizzle,
|
||||
supportsIndirectParameters: Capabilities.SupportsIndirectParameters,
|
||||
supportsDepthClipControl: true,
|
||||
maximumUniformBuffersPerStage: 13, // TODO: Avoid hardcoding those limits here and get from driver?
|
||||
maximumStorageBuffersPerStage: 16,
|
||||
maximumTexturesPerStage: 32,
|
||||
maximumImagesPerStage: 8,
|
||||
maximumComputeSharedMemorySize: HwCapabilities.MaximumComputeSharedMemorySize,
|
||||
maximumSupportedAnisotropy: HwCapabilities.MaximumSupportedAnisotropy,
|
||||
maximumComputeSharedMemorySize: Capabilities.MaximumComputeSharedMemorySize,
|
||||
maximumSupportedAnisotropy: Capabilities.MaximumSupportedAnisotropy,
|
||||
shaderSubgroupSize: Constants.MaxSubgroupSize,
|
||||
storageBufferOffsetAlignment: HwCapabilities.StorageBufferOffsetAlignment,
|
||||
textureBufferOffsetAlignment: HwCapabilities.TextureBufferOffsetAlignment,
|
||||
storageBufferOffsetAlignment: Capabilities.StorageBufferOffsetAlignment,
|
||||
textureBufferOffsetAlignment: Capabilities.TextureBufferOffsetAlignment,
|
||||
gatherBiasPrecision: intelWindows || amdWindows ? 8 : 0); // Precision is 8 for these vendors on Vulkan.
|
||||
}
|
||||
|
||||
|
@ -228,11 +232,15 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
{
|
||||
Debugger.Initialize(Api, glLogLevel);
|
||||
|
||||
LoadFeatures();
|
||||
|
||||
PrintGpuInformation();
|
||||
|
||||
if (HwCapabilities.SupportsParallelShaderCompile)
|
||||
if (Capabilities.SupportsParallelShaderCompile)
|
||||
{
|
||||
GL.Arb.MaxShaderCompilerThreads(Math.Min(Environment.ProcessorCount, 8));
|
||||
Api.TryGetExtension(out ArbParallelShaderCompile arbParallelShaderCompile);
|
||||
|
||||
arbParallelShaderCompile.MaxShaderCompilerThreads((uint)Math.Min(Environment.ProcessorCount, 8));
|
||||
}
|
||||
|
||||
_counters.Initialize();
|
||||
|
@ -240,15 +248,46 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
// This is required to disable [0, 1] clamping for SNorm outputs on compatibility profiles.
|
||||
// This call is expected to fail if we're running with a core profile,
|
||||
// as this clamp target was deprecated, but that's fine as a core profile
|
||||
// should already have the desired behaviour were outputs are not clamped.
|
||||
// should already have the desired behaviour when outputs are not clamped.
|
||||
Api.ClampColor(ClampColorTargetARB.FragmentColorArb, ClampColorModeARB.False);
|
||||
}
|
||||
|
||||
private void PrintGpuInformation()
|
||||
private void LoadFeatures()
|
||||
{
|
||||
GpuVendor = Api.GetString(StringName.Vendor);
|
||||
GpuRenderer = Api.GetString(StringName.Renderer);
|
||||
GpuVersion = Api.GetString(StringName.Version);
|
||||
Capabilities = new HardwareCapabilities(
|
||||
HardwareCapabilities.HasExtension(Api, "GL_NV_alpha_to_coverage_dither_control"),
|
||||
HardwareCapabilities.HasExtension(Api, "GL_KHR_texture_compression_astc_ldr"),
|
||||
HardwareCapabilities.HasExtension(Api, "GL_NV_blend_equation_advanced"),
|
||||
HardwareCapabilities.HasExtension(Api, "GL_NV_draw_texture"),
|
||||
HardwareCapabilities.HasExtension(Api, "GL_ARB_fragment_shader_interlock"),
|
||||
HardwareCapabilities.HasExtension(Api, "GL_INTEL_fragment_shader_ordering"),
|
||||
HardwareCapabilities.HasExtension(Api, "GL_NV_geometry_shader_passthrough"),
|
||||
HardwareCapabilities.HasExtension(Api, "GL_EXT_shader_image_load_formatted"),
|
||||
HardwareCapabilities.HasExtension(Api, "GL_ARB_indirect_parameters"),
|
||||
HardwareCapabilities.HasExtension(Api, "GL_ARB_parallel_shader_compile"),
|
||||
HardwareCapabilities.HasExtension(Api, "GL_EXT_polygon_offset_clamp"),
|
||||
HardwareCapabilities.SupportsQuadsCheck(Api),
|
||||
HardwareCapabilities.HasExtension(Api, "GL_ARB_seamless_cubemap_per_texture"),
|
||||
HardwareCapabilities.HasExtension(Api, "GL_ARB_shader_ballot"),
|
||||
HardwareCapabilities.HasExtension(Api, "GL_ARB_shader_viewport_layer_array"),
|
||||
HardwareCapabilities.HasExtension(Api, "GL_NV_viewport_array2"),
|
||||
HardwareCapabilities.HasExtension(Api, "GL_EXT_texture_compression_bptc"),
|
||||
HardwareCapabilities.HasExtension(Api, "GL_EXT_texture_compression_rgtc"),
|
||||
HardwareCapabilities.HasExtension(Api, "GL_EXT_texture_compression_s3tc"),
|
||||
HardwareCapabilities.HasExtension(Api, "GL_EXT_texture_shadow_lod"),
|
||||
HardwareCapabilities.HasExtension(Api, "GL_NV_viewport_swizzle"),
|
||||
Api.GetInteger(GLEnum.MaxComputeSharedMemorySize),
|
||||
Api.GetInteger(GLEnum.ShaderStorageBufferOffsetAlignment),
|
||||
Api.GetInteger(GLEnum.TextureBufferOffsetAlignment),
|
||||
Api.GetFloat(GLEnum.MaxTextureMaxAnisotropy),
|
||||
HardwareCapabilities.GetGpuVendor(Api));
|
||||
}
|
||||
|
||||
private unsafe void PrintGpuInformation()
|
||||
{
|
||||
GpuVendor = Marshal.PtrToStringAnsi((IntPtr)Api.GetString(StringName.Vendor));
|
||||
GpuRenderer = Marshal.PtrToStringAnsi((IntPtr)Api.GetString(StringName.Renderer));
|
||||
GpuVersion = Marshal.PtrToStringAnsi((IntPtr)Api.GetString(StringName.Version));
|
||||
|
||||
Logger.Notice.Print(LogClass.Gpu, $"{GpuVendor} {GpuRenderer} ({GpuVersion})");
|
||||
}
|
||||
|
@ -292,7 +331,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
|
||||
public IProgram LoadProgramBinary(byte[] programBinary, bool hasFragmentShader, ShaderInfo info)
|
||||
{
|
||||
return new Program(Api, programBinary, hasFragmentShader, info.FragmentOutputMap);
|
||||
return new Program(this, programBinary, hasFragmentShader, info.FragmentOutputMap);
|
||||
}
|
||||
|
||||
public void CreateSync(ulong id, bool strict)
|
||||
|
|
|
@ -11,33 +11,41 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
{
|
||||
class PersistentBuffers : IDisposable
|
||||
{
|
||||
private readonly PersistentBuffer _main = new();
|
||||
private readonly PersistentBuffer _background = new();
|
||||
private readonly GL _api;
|
||||
private readonly PersistentBuffer _main;
|
||||
private readonly PersistentBuffer _background;
|
||||
|
||||
private readonly Dictionary<BufferHandle, IntPtr> _maps = new();
|
||||
|
||||
public PersistentBuffer Default => BackgroundContextWorker.InBackground ? _background : _main;
|
||||
|
||||
public PersistentBuffers(GL api)
|
||||
{
|
||||
_api = api;
|
||||
_main = new(_api);
|
||||
_background = new(_api);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_main?.Dispose();
|
||||
_background?.Dispose();
|
||||
}
|
||||
|
||||
public void Map(BufferHandle handle, int size)
|
||||
public unsafe void Map(BufferHandle handle, int size)
|
||||
{
|
||||
GL.BindBuffer(BufferTargetARB.CopyWriteBuffer, handle.ToInt32());
|
||||
IntPtr ptr = GL.MapBufferRange(BufferTargetARB.CopyWriteBuffer, IntPtr.Zero, size, BufferAccessMask.MapReadBit | BufferAccessMask.MapPersistentBit);
|
||||
_api.BindBuffer(BufferTargetARB.CopyWriteBuffer, handle.ToUInt32());
|
||||
void* ptr = _api.MapBufferRange(BufferTargetARB.CopyWriteBuffer, IntPtr.Zero, (uint)size, MapBufferAccessMask.ReadBit | MapBufferAccessMask.PersistentBit);
|
||||
|
||||
_maps[handle] = ptr;
|
||||
_maps[handle] = (IntPtr)ptr;
|
||||
}
|
||||
|
||||
public void Unmap(BufferHandle handle)
|
||||
{
|
||||
if (_maps.ContainsKey(handle))
|
||||
{
|
||||
GL.BindBuffer(BufferTargetARB.CopyWriteBuffer, handle.ToInt32());
|
||||
GL.UnmapBuffer(BufferTargetARB.CopyWriteBuffer);
|
||||
_api.BindBuffer(BufferTargetARB.CopyWriteBuffer, handle.ToUInt32());
|
||||
_api.UnmapBuffer(BufferTargetARB.CopyWriteBuffer);
|
||||
|
||||
_maps.Remove(handle);
|
||||
}
|
||||
|
@ -51,6 +59,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
|
||||
class PersistentBuffer : IDisposable
|
||||
{
|
||||
private readonly GL _api;
|
||||
private IntPtr _bufferMap;
|
||||
private uint _copyBufferHandle;
|
||||
private int _copyBufferSize;
|
||||
|
@ -58,24 +67,29 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
private byte[] _data;
|
||||
private IntPtr _dataMap;
|
||||
|
||||
private void EnsureBuffer(int requiredSize)
|
||||
public PersistentBuffer(GL api)
|
||||
{
|
||||
_api = api;
|
||||
}
|
||||
|
||||
private unsafe void EnsureBuffer(int requiredSize)
|
||||
{
|
||||
if (_copyBufferSize < requiredSize && _copyBufferHandle != 0)
|
||||
{
|
||||
GL.DeleteBuffer(_copyBufferHandle);
|
||||
_api.DeleteBuffer(_copyBufferHandle);
|
||||
|
||||
_copyBufferHandle = 0;
|
||||
}
|
||||
|
||||
if (_copyBufferHandle == 0)
|
||||
{
|
||||
_copyBufferHandle = GL.GenBuffer();
|
||||
_copyBufferHandle = _api.GenBuffer();
|
||||
_copyBufferSize = requiredSize;
|
||||
|
||||
GL.BindBuffer(BufferTargetARB.CopyWriteBuffer, _copyBufferHandle);
|
||||
GL.BufferStorage(BufferTargetARB.CopyWriteBuffer, requiredSize, IntPtr.Zero, BufferStorageFlags.MapReadBit | BufferStorageFlags.MapPersistentBit);
|
||||
_api.BindBuffer(BufferTargetARB.CopyWriteBuffer, _copyBufferHandle);
|
||||
_api.BufferStorage(BufferStorageTarget.CopyWriteBuffer, (uint)requiredSize, IntPtr.Zero, BufferStorageMask.MapReadBit | BufferStorageMask.MapPersistentBit);
|
||||
|
||||
_bufferMap = GL.MapBufferRange(BufferTargetARB.CopyWriteBuffer, IntPtr.Zero, requiredSize, BufferAccessMask.MapReadBit | BufferAccessMask.MapPersistentBit);
|
||||
_bufferMap = (IntPtr)_api.MapBufferRange(BufferTargetARB.CopyWriteBuffer, IntPtr.Zero, (uint)requiredSize, MapBufferAccessMask.ReadBit | MapBufferAccessMask.PersistentBit);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,30 +105,30 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
return _dataMap;
|
||||
}
|
||||
|
||||
private static void Sync()
|
||||
private void Sync()
|
||||
{
|
||||
GL.MemoryBarrier(MemoryBarrierFlags.ClientMappedBufferBarrierBit);
|
||||
_api.MemoryBarrier(MemoryBarrierMask.ClientMappedBufferBarrierBit);
|
||||
|
||||
IntPtr sync = GL.FenceSync(SyncCondition.SyncGpuCommandsComplete, WaitSyncFlags.None);
|
||||
WaitSyncStatus syncResult = GL.ClientWaitSync(sync, ClientWaitSyncFlags.SyncFlushCommandsBit, 1000000000);
|
||||
IntPtr sync = _api.FenceSync(SyncCondition.SyncGpuCommandsComplete, SyncBehaviorFlags.None);
|
||||
GLEnum syncResult = _api.ClientWaitSync(sync, SyncObjectMask.Bit, 1000000000);
|
||||
|
||||
if (syncResult == WaitSyncStatus.TimeoutExpired)
|
||||
if (syncResult == GLEnum.TimeoutExpired)
|
||||
{
|
||||
Logger.Error?.PrintMsg(LogClass.Gpu, $"Failed to sync persistent buffer state within 1000ms. Continuing...");
|
||||
}
|
||||
|
||||
GL.DeleteSync(sync);
|
||||
_api.DeleteSync(sync);
|
||||
}
|
||||
|
||||
public unsafe ReadOnlySpan<byte> GetTextureData(TextureView view, int size)
|
||||
{
|
||||
EnsureBuffer(size);
|
||||
|
||||
GL.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyBufferHandle);
|
||||
_api.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyBufferHandle);
|
||||
|
||||
view.WriteToPbo(0, false);
|
||||
|
||||
GL.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
|
||||
_api.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
|
||||
|
||||
Sync();
|
||||
|
||||
|
@ -125,11 +139,11 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
{
|
||||
EnsureBuffer(size);
|
||||
|
||||
GL.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyBufferHandle);
|
||||
_api.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyBufferHandle);
|
||||
|
||||
int offset = view.WriteToPbo2D(0, layer, level);
|
||||
|
||||
GL.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
|
||||
_api.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
|
||||
|
||||
Sync();
|
||||
|
||||
|
@ -140,12 +154,12 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
{
|
||||
EnsureBuffer(size);
|
||||
|
||||
GL.BindBuffer(BufferTargetARB.CopyReadBuffer, buffer.ToUInt32());
|
||||
GL.BindBuffer(BufferTargetARB.CopyWriteBuffer, _copyBufferHandle);
|
||||
_api.BindBuffer(BufferTargetARB.CopyReadBuffer, buffer.ToUInt32());
|
||||
_api.BindBuffer(BufferTargetARB.CopyWriteBuffer, _copyBufferHandle);
|
||||
|
||||
GL.CopyBufferSubData(BufferTargetARB.CopyReadBuffer, BufferTargetARB.CopyWriteBuffer, (IntPtr)offset, IntPtr.Zero, size);
|
||||
_api.CopyBufferSubData(CopyBufferSubDataTarget.CopyReadBuffer, CopyBufferSubDataTarget.CopyWriteBuffer, offset, IntPtr.Zero, (uint)size);
|
||||
|
||||
GL.BindBuffer(BufferTargetARB.CopyWriteBuffer, 0);
|
||||
_api.BindBuffer(BufferTargetARB.CopyWriteBuffer, 0);
|
||||
|
||||
Sync();
|
||||
|
||||
|
@ -156,7 +170,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
{
|
||||
if (_copyBufferHandle != 0)
|
||||
{
|
||||
GL.DeleteBuffer(_copyBufferHandle);
|
||||
_api.DeleteBuffer(_copyBufferHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,5 @@
|
|||
using Silk.NET.OpenGL.Legacy;
|
||||
using Silk.NET.OpenGL.Legacy.Extensions.ARB;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.Shader;
|
||||
|
@ -27,18 +28,18 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
}
|
||||
}
|
||||
|
||||
private readonly GL _api;
|
||||
private readonly OpenGLRenderer _gd;
|
||||
private ProgramLinkStatus _status = ProgramLinkStatus.Incomplete;
|
||||
private uint[] _shaderHandles;
|
||||
|
||||
public int FragmentOutputMap { get; }
|
||||
|
||||
public Program(GL api, ShaderSource[] shaders, int fragmentOutputMap)
|
||||
public unsafe Program(OpenGLRenderer gd, ShaderSource[] shaders, int fragmentOutputMap)
|
||||
{
|
||||
_api = api;
|
||||
Handle = _api.CreateProgram();
|
||||
_gd = gd;
|
||||
Handle = _gd.Api.CreateProgram();
|
||||
|
||||
_api.ProgramParameter(Handle, ProgramParameterPName.BinaryRetrievableHint, 1);
|
||||
_gd.Api.ProgramParameter(Handle, ProgramParameterPName.BinaryRetrievableHint, 1);
|
||||
|
||||
_shaderHandles = new uint[shaders.Length];
|
||||
bool hasFragmentShader = false;
|
||||
|
@ -52,34 +53,37 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
hasFragmentShader = true;
|
||||
}
|
||||
|
||||
uint shaderHandle = _api.CreateShader(shader.Stage.Convert());
|
||||
uint shaderHandle = _gd.Api.CreateShader(shader.Stage.Convert());
|
||||
|
||||
switch (shader.Language)
|
||||
{
|
||||
case TargetLanguage.Glsl:
|
||||
_api.ShaderSource(shaderHandle, shader.Code);
|
||||
_api.CompileShader(shaderHandle);
|
||||
_gd.Api.ShaderSource(shaderHandle, shader.Code);
|
||||
_gd.Api.CompileShader(shaderHandle);
|
||||
break;
|
||||
case TargetLanguage.Spirv:
|
||||
_api.ShaderBinary(1, ref shaderHandle, ShaderBinaryFormat.ShaderBinaryFormatSpirV, shader.BinaryCode, shader.BinaryCode.Length);
|
||||
_api.SpecializeShader(shaderHandle, "main", 0, (int[])null, (int[])null);
|
||||
fixed (byte* ptr = shader.BinaryCode.AsSpan())
|
||||
{
|
||||
_gd.Api.ShaderBinary(1, in shaderHandle, ShaderBinaryFormat.ShaderBinaryFormatSpirV, ptr, (uint)shader.BinaryCode.Length);
|
||||
}
|
||||
_gd.Api.SpecializeShader(shaderHandle, "main", 0, (uint[])null, (uint[])null);
|
||||
break;
|
||||
}
|
||||
|
||||
_api.AttachShader(Handle, shaderHandle);
|
||||
_gd.Api.AttachShader(Handle, shaderHandle);
|
||||
|
||||
_shaderHandles[index] = shaderHandle;
|
||||
}
|
||||
|
||||
_api.LinkProgram(Handle);
|
||||
_gd.Api.LinkProgram(Handle);
|
||||
|
||||
FragmentOutputMap = hasFragmentShader ? fragmentOutputMap : 0;
|
||||
}
|
||||
|
||||
public Program(GL api, ReadOnlySpan<byte> code, bool hasFragmentShader, int fragmentOutputMap)
|
||||
public Program(OpenGLRenderer gd, ReadOnlySpan<byte> code, bool hasFragmentShader, int fragmentOutputMap)
|
||||
{
|
||||
_api = api;
|
||||
Handle = _api.CreateProgram();
|
||||
_gd = gd;
|
||||
Handle = _gd.Api.CreateProgram();
|
||||
|
||||
if (code.Length >= 4)
|
||||
{
|
||||
|
@ -89,7 +93,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
{
|
||||
fixed (byte* ptr = code)
|
||||
{
|
||||
_api.ProgramBinary(Handle, binaryFormat, (IntPtr)ptr, code.Length - 4);
|
||||
_gd.Api.ProgramBinary(Handle, (GLEnum)binaryFormat, (IntPtr)ptr, (uint)code.Length - 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,14 +103,14 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
|
||||
public void Bind()
|
||||
{
|
||||
_api.UseProgram(Handle);
|
||||
_gd.Api.UseProgram(Handle);
|
||||
}
|
||||
|
||||
public ProgramLinkStatus CheckProgramLink(bool blocking)
|
||||
{
|
||||
if (!blocking && HwCapabilities.SupportsParallelShaderCompile)
|
||||
if (!blocking && _gd.Capabilities.SupportsParallelShaderCompile)
|
||||
{
|
||||
_api.GetProgram(Handle, (GetProgramParameterName)ArbParallelShaderCompile.CompletionStatusArb, out int completed);
|
||||
_gd.Api.GetProgram(Handle, (GLEnum)ARB.CompletionStatusArb, out int completed);
|
||||
|
||||
if (completed == 0)
|
||||
{
|
||||
|
@ -114,14 +118,14 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
}
|
||||
}
|
||||
|
||||
_api.GetProgram(Handle, ProgramPropertyARB.LinkStatus, out int status);
|
||||
_gd.Api.GetProgram(Handle, ProgramPropertyARB.LinkStatus, out int status);
|
||||
DeleteShaders();
|
||||
|
||||
if (status == 0)
|
||||
{
|
||||
_status = ProgramLinkStatus.Failure;
|
||||
|
||||
string log = _api.GetProgramInfoLog(Handle);
|
||||
string log = _gd.Api.GetProgramInfoLog(Handle);
|
||||
|
||||
if (log.Length > MaxShaderLogLength)
|
||||
{
|
||||
|
@ -138,15 +142,19 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
return _status;
|
||||
}
|
||||
|
||||
public byte[] GetBinary()
|
||||
public unsafe byte[] GetBinary()
|
||||
{
|
||||
_api.GetProgram(Handle, ProgramPropertyARB.ProgramBinaryLength, out int size);
|
||||
_gd.Api.GetProgram(Handle, ProgramPropertyARB.ProgramBinaryLength, out int size);
|
||||
|
||||
byte[] data = new byte[size + 4];
|
||||
byte[] data = new byte[size];
|
||||
GLEnum binFormat;
|
||||
|
||||
_api.GetProgramBinary(Handle, size, out _, out ShaderBinaryFormat binFormat, data);
|
||||
fixed (byte* ptr = data)
|
||||
{
|
||||
_gd.Api.GetProgramBinary(Handle, (uint)size, out _, out binFormat, ptr);
|
||||
}
|
||||
|
||||
BinaryPrimitives.WriteInt32LittleEndian(data.AsSpan(size, 4), (int)binFormat);
|
||||
BinaryPrimitives.WriteInt32LittleEndian(data, (int)binFormat);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
@ -157,8 +165,8 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
{
|
||||
foreach (uint shaderHandle in _shaderHandles)
|
||||
{
|
||||
_api.DetachShader(Handle, shaderHandle);
|
||||
_api.DeleteShader(shaderHandle);
|
||||
_gd.Api.DetachShader(Handle, shaderHandle);
|
||||
_gd.Api.DeleteShader(shaderHandle);
|
||||
}
|
||||
|
||||
_shaderHandles = null;
|
||||
|
@ -170,7 +178,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
if (Handle != 0)
|
||||
{
|
||||
DeleteShaders();
|
||||
_api.DeleteProgram(Handle);
|
||||
_gd.Api.DeleteProgram(Handle);
|
||||
|
||||
Handle = 0;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||
|
||||
unsafe
|
||||
{
|
||||
_bufferMap = new IntPtr(_api.MapBufferRange(BufferTargetARB.QueryBuffer, IntPtr.Zero, sizeof(long), MapBufferAccessMask.ReadBit | MapBufferAccessMask.WriteBit | MapBufferAccessMask.PersistentBit));
|
||||
_bufferMap = (IntPtr)_api.MapBufferRange(BufferTargetARB.QueryBuffer, IntPtr.Zero, sizeof(long), MapBufferAccessMask.ReadBit | MapBufferAccessMask.WriteBit | MapBufferAccessMask.PersistentBit);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Silk.NET.OpenGL.Legacy" />
|
||||
<PackageReference Include="Silk.NET.OpenGL.Legacy.Extensions.ARB" />
|
||||
<PackageReference Include="Silk.NET.OpenGL.Legacy.Extensions.EXT" />
|
||||
<PackageReference Include="Silk.NET.OpenGL.Legacy.Extensions.NV" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -14,15 +14,15 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
public IntPtr Handle;
|
||||
}
|
||||
|
||||
private ulong _firstHandle = 0;
|
||||
private static SyncBehaviorFlags SyncFlags => HwCapabilities.RequiresSyncFlush ? SyncBehaviorFlags.None : SyncBehaviorFlags.SyncFlushCommandsBit;
|
||||
private ulong _firstHandle;
|
||||
private SyncObjectMask SyncFlags => _gd.Capabilities.RequiresSyncFlush ? 0 : SyncObjectMask.Bit;
|
||||
|
||||
private readonly List<SyncHandle> _handles = new();
|
||||
private readonly GL _api;
|
||||
private readonly OpenGLRenderer _gd;
|
||||
|
||||
public Sync(GL api)
|
||||
public Sync(OpenGLRenderer gd)
|
||||
{
|
||||
_api = api;
|
||||
_gd = gd;
|
||||
}
|
||||
|
||||
public void Create(ulong id)
|
||||
|
@ -30,14 +30,14 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
SyncHandle handle = new()
|
||||
{
|
||||
ID = id,
|
||||
Handle = _api.FenceSync(SyncCondition.SyncGpuCommandsComplete, SyncBehaviorFlags.None),
|
||||
Handle = _gd.Api.FenceSync(SyncCondition.SyncGpuCommandsComplete, SyncBehaviorFlags.None),
|
||||
};
|
||||
|
||||
|
||||
if (HwCapabilities.RequiresSyncFlush)
|
||||
if (_gd.Capabilities.RequiresSyncFlush)
|
||||
{
|
||||
// Force commands to flush up to the syncpoint.
|
||||
_api.ClientWaitSync(handle.Handle, SyncBehaviorFlags.SyncFlushCommandsBit, 0);
|
||||
_gd.Api.ClientWaitSync(handle.Handle, SyncObjectMask.Bit, 0);
|
||||
}
|
||||
|
||||
lock (_handles)
|
||||
|
@ -63,7 +63,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
|
||||
if (handle.ID > lastHandle)
|
||||
{
|
||||
GLEnum syncResult = _api.ClientWaitSync(handle.Handle, SyncFlags, 0);
|
||||
GLEnum syncResult = _gd.Api.ClientWaitSync(handle.Handle, SyncFlags, 0);
|
||||
|
||||
if (syncResult == GLEnum.AlreadySignaled)
|
||||
{
|
||||
|
@ -107,7 +107,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
return;
|
||||
}
|
||||
|
||||
GLEnum syncResult = _api.ClientWaitSync(result.Handle, SyncFlags, 1000000000);
|
||||
GLEnum syncResult = _gd.Api.ClientWaitSync(result.Handle, SyncFlags, 1000000000);
|
||||
|
||||
if (syncResult == GLEnum.TimeoutExpired)
|
||||
{
|
||||
|
@ -134,7 +134,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
break;
|
||||
}
|
||||
|
||||
GLEnum syncResult = _api.ClientWaitSync(first.Handle, SyncFlags, 0);
|
||||
GLEnum syncResult = _gd.Api.ClientWaitSync(first.Handle, SyncFlags, 0);
|
||||
|
||||
if (syncResult == GLEnum.AlreadySignaled)
|
||||
{
|
||||
|
@ -145,7 +145,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
{
|
||||
_firstHandle = first.ID + 1;
|
||||
_handles.RemoveAt(0);
|
||||
_api.DeleteSync(first.Handle);
|
||||
_gd.Api.DeleteSync(first.Handle);
|
||||
first.Handle = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
{
|
||||
lock (handle)
|
||||
{
|
||||
_api.DeleteSync(handle.Handle);
|
||||
_gd.Api.DeleteSync(handle.Handle);
|
||||
handle.Handle = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
{
|
||||
class VertexArray : IDisposable
|
||||
{
|
||||
public int Handle { get; private set; }
|
||||
public uint Handle { get; private set; }
|
||||
|
||||
private readonly VertexAttribDescriptor[] _vertexAttribs;
|
||||
private readonly VertexBufferDescriptor[] _vertexBuffers;
|
||||
|
@ -23,20 +23,22 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
private readonly BufferHandle _tempIndexBuffer;
|
||||
private BufferHandle _tempVertexBuffer;
|
||||
private int _tempVertexBufferSize;
|
||||
private readonly GL _api;
|
||||
|
||||
public VertexArray()
|
||||
public VertexArray(GL api)
|
||||
{
|
||||
Handle = GL.GenVertexArray();
|
||||
_api = api;
|
||||
Handle = _api.GenVertexArray();
|
||||
|
||||
_vertexAttribs = new VertexAttribDescriptor[Constants.MaxVertexAttribs];
|
||||
_vertexBuffers = new VertexBufferDescriptor[Constants.MaxVertexBuffers];
|
||||
|
||||
_tempIndexBuffer = Buffer.Create();
|
||||
_tempIndexBuffer = Buffer.Create(_api);
|
||||
}
|
||||
|
||||
public void Bind()
|
||||
{
|
||||
GL.BindVertexArray(Handle);
|
||||
_api.BindVertexArray(Handle);
|
||||
}
|
||||
|
||||
public void SetVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers)
|
||||
|
@ -56,15 +58,15 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
minVertexCount = vertexCount;
|
||||
}
|
||||
|
||||
GL.BindVertexBuffer(bindingIndex, vb.Buffer.Handle.ToInt32(), (IntPtr)vb.Buffer.Offset, vb.Stride);
|
||||
GL.VertexBindingDivisor(bindingIndex, vb.Divisor);
|
||||
_api.BindVertexBuffer((uint)bindingIndex, vb.Buffer.Handle.ToUInt32(), vb.Buffer.Offset, (uint)vb.Stride);
|
||||
_api.VertexBindingDivisor((uint)bindingIndex, (uint)vb.Divisor);
|
||||
_vertexBuffersInUse |= 1u << bindingIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((_vertexBuffersInUse & (1u << bindingIndex)) != 0)
|
||||
{
|
||||
GL.BindVertexBuffer(bindingIndex, 0, IntPtr.Zero, 0);
|
||||
_api.BindVertexBuffer((uint)bindingIndex, 0, IntPtr.Zero, 0);
|
||||
_vertexBuffersInUse &= ~(1u << bindingIndex);
|
||||
}
|
||||
}
|
||||
|
@ -111,16 +113,16 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
{
|
||||
VertexAttribType type = (VertexAttribType)fmtInfo.PixelType;
|
||||
|
||||
GL.VertexAttribFormat(index, size, type, fmtInfo.Normalized, offset);
|
||||
_api.VertexAttribFormat((uint)index, size, type, fmtInfo.Normalized, (uint)offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
VertexAttribIntegerType type = (VertexAttribIntegerType)fmtInfo.PixelType;
|
||||
VertexAttribIType type = (VertexAttribIType)fmtInfo.PixelType;
|
||||
|
||||
GL.VertexAttribIFormat(index, size, type, offset);
|
||||
_api.VertexAttribIFormat((uint)index, size, type, (uint)offset);
|
||||
}
|
||||
|
||||
GL.VertexAttribBinding(index, attrib.BufferIndex);
|
||||
_api.VertexAttribBinding((uint)index, (uint)attrib.BufferIndex);
|
||||
|
||||
_vertexAttribs[index] = attrib;
|
||||
}
|
||||
|
@ -134,19 +136,19 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
public void SetIndexBuffer(BufferRange range)
|
||||
{
|
||||
_indexBuffer = range;
|
||||
GL.BindBuffer(BufferTargetARB.ElementArrayBuffer, range.Handle.ToInt32());
|
||||
_api.BindBuffer(BufferTargetARB.ElementArrayBuffer, range.Handle.ToUInt32());
|
||||
}
|
||||
|
||||
public void SetRangeOfIndexBuffer()
|
||||
{
|
||||
Buffer.Resize(_tempIndexBuffer, _indexBuffer.Size);
|
||||
Buffer.Copy(_indexBuffer.Handle, _tempIndexBuffer, _indexBuffer.Offset, 0, _indexBuffer.Size);
|
||||
GL.BindBuffer(BufferTargetARB.ElementArrayBuffer, _tempIndexBuffer.ToInt32());
|
||||
Buffer.Resize(_api, _tempIndexBuffer, _indexBuffer.Size);
|
||||
Buffer.Copy(_api, _indexBuffer.Handle, _tempIndexBuffer, _indexBuffer.Offset, 0, _indexBuffer.Size);
|
||||
_api.BindBuffer(BufferTargetARB.ElementArrayBuffer, _tempIndexBuffer.ToUInt32());
|
||||
}
|
||||
|
||||
public void RestoreIndexBuffer()
|
||||
{
|
||||
GL.BindBuffer(BufferTargetARB.ElementArrayBuffer, _indexBuffer.Handle.ToInt32());
|
||||
_api.BindBuffer(BufferTargetARB.ElementArrayBuffer, _indexBuffer.Handle.ToUInt32());
|
||||
}
|
||||
|
||||
public void PreDraw(int vertexCount)
|
||||
|
@ -185,10 +187,10 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
{
|
||||
BufferHandle tempVertexBuffer = EnsureTempVertexBufferSize(currentTempVbOffset + requiredSize);
|
||||
|
||||
Buffer.Copy(vb.Buffer.Handle, tempVertexBuffer, vb.Buffer.Offset, currentTempVbOffset, vb.Buffer.Size);
|
||||
Buffer.Clear(tempVertexBuffer, currentTempVbOffset + vb.Buffer.Size, requiredSize - vb.Buffer.Size, 0);
|
||||
Buffer.Copy(_api, vb.Buffer.Handle, tempVertexBuffer, vb.Buffer.Offset, currentTempVbOffset, vb.Buffer.Size);
|
||||
Buffer.Clear(_api, tempVertexBuffer, currentTempVbOffset + vb.Buffer.Size, (uint)(requiredSize - vb.Buffer.Size), 0);
|
||||
|
||||
GL.BindVertexBuffer(vbIndex, tempVertexBuffer.ToInt32(), (IntPtr)currentTempVbOffset, vb.Stride);
|
||||
_api.BindVertexBuffer((uint)vbIndex, tempVertexBuffer.ToUInt32(), (IntPtr)currentTempVbOffset, (uint)vb.Stride);
|
||||
|
||||
currentTempVbOffset += requiredSize;
|
||||
_vertexBuffersLimited |= 1u << vbIndex;
|
||||
|
@ -208,12 +210,12 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
|
||||
if (tempVertexBuffer == BufferHandle.Null)
|
||||
{
|
||||
tempVertexBuffer = Buffer.Create(size);
|
||||
tempVertexBuffer = Buffer.Create(_api, size);
|
||||
_tempVertexBuffer = tempVertexBuffer;
|
||||
return tempVertexBuffer;
|
||||
}
|
||||
|
||||
Buffer.Resize(_tempVertexBuffer, size);
|
||||
Buffer.Resize(_api, _tempVertexBuffer, size);
|
||||
}
|
||||
|
||||
return tempVertexBuffer;
|
||||
|
@ -234,7 +236,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
|
||||
ref var vb = ref _vertexBuffers[vbIndex];
|
||||
|
||||
GL.BindVertexBuffer(vbIndex, vb.Buffer.Handle.ToInt32(), (IntPtr)vb.Buffer.Offset, vb.Stride);
|
||||
_api.BindVertexBuffer((uint)vbIndex, vb.Buffer.Handle.ToUInt32(), (IntPtr)vb.Buffer.Offset, (uint)vb.Stride);
|
||||
|
||||
buffersLimited &= ~(1u << vbIndex);
|
||||
}
|
||||
|
@ -250,7 +252,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
if ((_vertexAttribsInUse & mask) == 0)
|
||||
{
|
||||
_vertexAttribsInUse |= mask;
|
||||
GL.EnableVertexAttribArray(index);
|
||||
_api.EnableVertexAttribArray((uint)index);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -262,8 +264,8 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
if ((_vertexAttribsInUse & mask) != 0)
|
||||
{
|
||||
_vertexAttribsInUse &= ~mask;
|
||||
GL.DisableVertexAttribArray(index);
|
||||
GL.VertexAttrib4(index, 0f, 0f, 0f, 1f);
|
||||
_api.DisableVertexAttribArray((uint)index);
|
||||
_api.VertexAttrib4((uint)index, 0f, 0f, 0f, 1f);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -271,7 +273,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
{
|
||||
if (Handle != 0)
|
||||
{
|
||||
GL.DeleteVertexArray(Handle);
|
||||
_api.DeleteVertexArray(Handle);
|
||||
|
||||
Handle = 0;
|
||||
}
|
||||
|
|
|
@ -252,12 +252,13 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
_initialized = true;
|
||||
}
|
||||
|
||||
public void CaptureFrame(int x, int y, uint width, uint height, bool isBgra, bool flipX, bool flipY)
|
||||
public unsafe void CaptureFrame(int x, int y, uint width, uint height, bool isBgra, bool flipX, bool flipY)
|
||||
{
|
||||
long size = 4 * width * height;
|
||||
byte[] bitmap = new byte[size];
|
||||
|
||||
_gd.Api.ReadPixels(x, y, width, height, isBgra ? PixelFormat.Bgra : PixelFormat.Rgba, PixelType.UnsignedByte, bitmap);
|
||||
_gd.Api.ReadPixels(x, y, width, height, isBgra ? PixelFormat.Bgra : PixelFormat.Rgba, PixelType.UnsignedByte, out int data);
|
||||
|
||||
var bitmap = new Span<byte>((void*)data, (int)size).ToArray();
|
||||
|
||||
_gd.OnScreenCaptured(new ScreenCaptureImageInfo((int)width, (int)height, isBgra, bitmap, flipX, flipY));
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using OpenTK;
|
||||
// using OpenTK;
|
||||
using Silk.NET.OpenGL.Legacy;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
|
|
|
@ -532,7 +532,8 @@ namespace Ryujinx.Headless.SDL2
|
|||
preferredGpuId);
|
||||
}
|
||||
|
||||
return new OpenGLRenderer();
|
||||
var openGlWindow = (OpenGLWindow)window;
|
||||
return new OpenGLRenderer(window.);
|
||||
}
|
||||
|
||||
private static Switch InitializeEmulationContext(WindowBase window, IRenderer renderer, Options options)
|
||||
|
|
|
@ -823,7 +823,7 @@ namespace Ryujinx.Ava
|
|||
}
|
||||
else
|
||||
{
|
||||
renderer = new OpenGLRenderer();
|
||||
renderer = new OpenGLRenderer((RendererHost.EmbeddedWindow as EmbeddedWindowOpenGL).CreateApi());
|
||||
}
|
||||
|
||||
BackendThreading threadingMode = ConfigurationState.Instance.Graphics.BackendThreading;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using OpenTK.Graphics.OpenGL;
|
||||
using Silk.NET.OpenGL.Legacy;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
|
@ -44,6 +44,13 @@ namespace Ryujinx.Ava.UI.Renderer
|
|||
throw new PlatformNotSupportedException();
|
||||
}
|
||||
|
||||
Context.Initialize(_window);
|
||||
Context.MakeCurrent(_window);
|
||||
Context.MakeCurrent(null);
|
||||
}
|
||||
|
||||
public GL CreateApi()
|
||||
{
|
||||
var flags = OpenGLContextFlags.Compat;
|
||||
if (ConfigurationState.Instance.Logger.GraphicsDebugLevel != GraphicsDebugLevel.None)
|
||||
{
|
||||
|
@ -54,12 +61,7 @@ namespace Ryujinx.Ava.UI.Renderer
|
|||
|
||||
Context = PlatformHelper.CreateOpenGLContext(graphicsMode, 3, 3, flags);
|
||||
|
||||
Context.Initialize(_window);
|
||||
Context.MakeCurrent(_window);
|
||||
|
||||
GL.LoadBindings(new OpenTKBindingsContext(Context.GetProcAddress));
|
||||
|
||||
Context.MakeCurrent(null);
|
||||
return GL.GetApi(Context.GetProcAddress);
|
||||
}
|
||||
|
||||
public void MakeCurrent(bool unbind = false, bool shouldThrow = true)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using OpenTK.Graphics.OpenGL;
|
||||
using Silk.NET.OpenGL.Legacy;
|
||||
using Ryujinx.Graphics.OpenGL;
|
||||
using SPB.Graphics;
|
||||
using SPB.Graphics.OpenGL;
|
||||
|
@ -9,11 +9,13 @@ namespace Ryujinx.Ava.UI.Renderer
|
|||
{
|
||||
class SPBOpenGLContext : IOpenGLContext
|
||||
{
|
||||
private readonly GL _api;
|
||||
private readonly OpenGLContextBase _context;
|
||||
private readonly NativeWindowBase _window;
|
||||
|
||||
private SPBOpenGLContext(OpenGLContextBase context, NativeWindowBase window)
|
||||
private SPBOpenGLContext(GL api, OpenGLContextBase context, NativeWindowBase window)
|
||||
{
|
||||
_api = api;
|
||||
_context = context;
|
||||
_window = window;
|
||||
}
|
||||
|
@ -39,11 +41,11 @@ namespace Ryujinx.Ava.UI.Renderer
|
|||
context.Initialize(window);
|
||||
context.MakeCurrent(window);
|
||||
|
||||
GL.LoadBindings(new OpenTKBindingsContext(context.GetProcAddress));
|
||||
GL api = GL.GetApi(context.GetProcAddress);
|
||||
|
||||
context.MakeCurrent(null);
|
||||
|
||||
return new SPBOpenGLContext(context, window);
|
||||
return new SPBOpenGLContext(api, context, window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue