This commit is contained in:
Isaac Marovitz 2024-05-09 12:38:23 -04:00
parent 21c3dd3bcb
commit 914f6d6af3
No known key found for this signature in database
GPG key ID: 97250B2B09A132E1
5 changed files with 68 additions and 55 deletions

View file

@ -88,7 +88,7 @@ namespace Ryujinx.Graphics.OpenGL
gd.Api.BindBuffer(BufferTargetARB.CopyReadBuffer, buffer.ToUInt32()); gd.Api.BindBuffer(BufferTargetARB.CopyReadBuffer, buffer.ToUInt32());
gd.Api.GetBufferSubData(BufferTargetARB.CopyReadBuffer, offset, (uint)size, target); gd.Api.GetBufferSubData(BufferTargetARB.CopyReadBuffer, offset, (uint)size, (void*)target);
return new PinnedSpan<byte>(target.ToPointer(), size); return new PinnedSpan<byte>(target.ToPointer(), size);
} }

View file

@ -1,6 +1,7 @@
using Silk.NET.OpenGL.Legacy; using Silk.NET.OpenGL.Legacy;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.OpenGL.Image; using Ryujinx.Graphics.OpenGL.Image;
using Silk.NET.OpenGL.Legacy.Extensions.NV;
using System; using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;

View file

@ -48,14 +48,14 @@ namespace Ryujinx.Graphics.OpenGL
public OpenGLRenderer(GL api) public OpenGLRenderer(GL api)
{ {
Api = api; Api = api;
_pipeline = new Pipeline(); _pipeline = new Pipeline(Api);
_counters = new Counters(Api); _counters = new Counters(Api);
_window = new Window(this); _window = new Window(this);
_textureCopy = new TextureCopy(this); _textureCopy = new TextureCopy(this);
_backgroundTextureCopy = new TextureCopy(this); _backgroundTextureCopy = new TextureCopy(this);
TextureCopyIncompatible = new TextureCopyIncompatible(this); TextureCopyIncompatible = new TextureCopyIncompatible(this);
TextureCopyMS = new TextureCopyMS(this); TextureCopyMS = new TextureCopyMS(this);
_sync = new Sync(); _sync = new Sync(Api);
PersistentBuffers = new PersistentBuffers(); PersistentBuffers = new PersistentBuffers();
ResourcePool = new ResourcePool(); ResourcePool = new ResourcePool();
} }
@ -100,7 +100,7 @@ namespace Ryujinx.Graphics.OpenGL
public IProgram CreateProgram(ShaderSource[] shaders, ShaderInfo info) public IProgram CreateProgram(ShaderSource[] shaders, ShaderInfo info)
{ {
return new Program(shaders, info.FragmentOutputMap); return new Program(Api, shaders, info.FragmentOutputMap);
} }
public ISampler CreateSampler(SamplerCreateInfo info) public ISampler CreateSampler(SamplerCreateInfo info)
@ -292,7 +292,7 @@ namespace Ryujinx.Graphics.OpenGL
public IProgram LoadProgramBinary(byte[] programBinary, bool hasFragmentShader, ShaderInfo info) public IProgram LoadProgramBinary(byte[] programBinary, bool hasFragmentShader, ShaderInfo info)
{ {
return new Program(programBinary, hasFragmentShader, info.FragmentOutputMap); return new Program(Api, programBinary, hasFragmentShader, info.FragmentOutputMap);
} }
public void CreateSync(ulong id, bool strict) public void CreateSync(ulong id, bool strict)

View file

@ -4,6 +4,7 @@ using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.OpenGL.Image; using Ryujinx.Graphics.OpenGL.Image;
using Ryujinx.Graphics.OpenGL.Queries; using Ryujinx.Graphics.OpenGL.Queries;
using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader;
using Silk.NET.OpenGL.Legacy.Extensions.NV;
using System; using System;
using Sampler = Ryujinx.Graphics.OpenGL.Image.Sampler; using Sampler = Ryujinx.Graphics.OpenGL.Image.Sampler;
@ -674,7 +675,9 @@ namespace Ryujinx.Graphics.OpenGL
{ {
if (HwCapabilities.SupportsDrawTexture) if (HwCapabilities.SupportsDrawTexture)
{ {
GL.NV.DrawTexture( _api.TryGetExtension(out NVDrawTexture drawTexture);
drawTexture.DrawTexture(
view.Handle, view.Handle,
samp.Handle, samp.Handle,
dstRegion.X1, dstRegion.X1,
@ -689,25 +692,25 @@ namespace Ryujinx.Graphics.OpenGL
} }
else else
{ {
static void Disable(EnableCap cap, bool enabled) static void Disable(GL api, EnableCap cap, bool enabled)
{ {
if (enabled) if (enabled)
{ {
_api.Disable(cap); api.Disable(cap);
} }
} }
static void Enable(EnableCap cap, bool enabled) static void Enable(GL api, EnableCap cap, bool enabled)
{ {
if (enabled) if (enabled)
{ {
_api.Enable(cap); api.Enable(cap);
} }
} }
Disable(EnableCap.CullFace, _cullEnable); Disable(_api, EnableCap.CullFace, _cullEnable);
Disable(EnableCap.StencilTest, _stencilTestEnable); Disable(_api, EnableCap.StencilTest, _stencilTestEnable);
Disable(EnableCap.DepthTest, _depthTestEnable); Disable(_api, EnableCap.DepthTest, _depthTestEnable);
if (_depthMask) if (_depthMask)
{ {
@ -779,10 +782,12 @@ namespace Ryujinx.Graphics.OpenGL
{ {
if (HwCapabilities.SupportsBlendEquationAdvanced) if (HwCapabilities.SupportsBlendEquationAdvanced)
{ {
GL.BlendEquation((BlendEquationMode)blend.Op.Convert()); _api.BlendEquation((GLEnum)blend.Op.Convert());
GL.NV.BlendParameter(NvBlendEquationAdvanced.BlendOverlapNv, (int)blend.Overlap.Convert());
GL.NV.BlendParameter(NvBlendEquationAdvanced.BlendPremultipliedSrcNv, blend.SrcPreMultiplied ? 1 : 0); _api.TryGetExtension(out NVBlendEquationAdvanced nvBlendEquationAdvanced);
GL.Enable(EnableCap.Blend); nvBlendEquationAdvanced.BlendParameter(NV.BlendOverlapNV, (int)blend.Overlap.Convert());
nvBlendEquationAdvanced.BlendParameter(NV.BlendPremultipliedSrcNV, blend.SrcPreMultiplied ? 1 : 0);
_api.Enable(EnableCap.Blend);
_advancedBlendEnable = true; _advancedBlendEnable = true;
} }
} }
@ -832,7 +837,7 @@ namespace Ryujinx.Graphics.OpenGL
blend.BlendConstant.Alpha); blend.BlendConstant.Alpha);
} }
GL.Enable(EnableCap.Blend, index); _api.Enable(EnableCap.Blend, index);
} }
public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp) public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp)
@ -1009,9 +1014,11 @@ namespace Ryujinx.Graphics.OpenGL
if (HwCapabilities.SupportsAlphaToCoverageDitherControl) if (HwCapabilities.SupportsAlphaToCoverageDitherControl)
{ {
GL.NV.AlphaToCoverageDitherControl(multisample.AlphaToCoverageDitherEnable _api.TryGetExtension(out NVAlphaToCoverageDitherControl nvAlphaToCoverageDitherControl);
? NvAlphaToCoverageDitherControl.AlphaToCoverageDitherEnableNv
: NvAlphaToCoverageDitherControl.AlphaToCoverageDitherDisableNv); nvAlphaToCoverageDitherControl.AlphaToCoverageDitherControl(multisample.AlphaToCoverageDitherEnable
? NV.AlphaToCoverageDitherEnableNV
: NV.AlphaToCoverageDitherDisableNV);
} }
} }
else else
@ -1055,11 +1062,11 @@ namespace Ryujinx.Graphics.OpenGL
// As we don't know if the current context is core or compat, it's safer to keep this code. // As we don't know if the current context is core or compat, it's safer to keep this code.
if (enablePointSprite) if (enablePointSprite)
{ {
_api.Enable(EnableCap.PointSprite); _api.Enable(GLEnum.PointSprite);
} }
else else
{ {
_api.Disable(EnableCap.PointSprite); _api.Disable(GLEnum.PointSprite);
} }
if (isProgramPointSize) if (isProgramPointSize)
@ -1390,11 +1397,11 @@ namespace Ryujinx.Graphics.OpenGL
float[] viewportArray = _viewportArray; float[] viewportArray = _viewportArray;
double[] depthRangeArray = _depthRangeArray; double[] depthRangeArray = _depthRangeArray;
for (int index = 0; index < viewports.Length; index++) for (uint index = 0; index < viewports.Length; index++)
{ {
int viewportElemIndex = index * 4; uint viewportElemIndex = index * 4;
Viewport viewport = viewports[index]; Viewport viewport = viewports[(int)index];
viewportArray[viewportElemIndex + 0] = viewport.Region.X; viewportArray[viewportElemIndex + 0] = viewport.Region.X;
viewportArray[viewportElemIndex + 1] = viewport.Region.Y + (viewport.Region.Height < 0 ? viewport.Region.Height : 0); viewportArray[viewportElemIndex + 1] = viewport.Region.Y + (viewport.Region.Height < 0 ? viewport.Region.Height : 0);
@ -1403,7 +1410,9 @@ namespace Ryujinx.Graphics.OpenGL
if (HwCapabilities.SupportsViewportSwizzle) if (HwCapabilities.SupportsViewportSwizzle)
{ {
GL.NV.ViewportSwizzle( _api.TryGetExtension(out NVViewportSwizzle nvViewportSwizzle);
nvViewportSwizzle.ViewportSwizzle(
index, index,
viewport.SwizzleX.Convert(), viewport.SwizzleX.Convert(),
viewport.SwizzleY.Convert(), viewport.SwizzleY.Convert(),
@ -1568,7 +1577,7 @@ namespace Ryujinx.Graphics.OpenGL
componentMask &= 0xfu; componentMask &= 0xfu;
_api.ColorMask( _api.ColorMask(
index, (uint)index,
(componentMask & redMask) != 0, (componentMask & redMask) != 0,
(componentMask & 2u) != 0, (componentMask & 2u) != 0,
(componentMask & blueMask) != 0, (componentMask & blueMask) != 0,

View file

@ -12,7 +12,7 @@ namespace Ryujinx.Graphics.OpenGL
{ {
private const int MaxShaderLogLength = 2048; private const int MaxShaderLogLength = 2048;
public int Handle { get; private set; } public uint Handle { get; private set; }
public bool IsLinked public bool IsLinked
{ {
@ -27,18 +27,20 @@ namespace Ryujinx.Graphics.OpenGL
} }
} }
private readonly GL _api;
private ProgramLinkStatus _status = ProgramLinkStatus.Incomplete; private ProgramLinkStatus _status = ProgramLinkStatus.Incomplete;
private int[] _shaderHandles; private uint[] _shaderHandles;
public int FragmentOutputMap { get; } public int FragmentOutputMap { get; }
public Program(ShaderSource[] shaders, int fragmentOutputMap) public Program(GL api, ShaderSource[] shaders, int fragmentOutputMap)
{ {
Handle = GL.CreateProgram(); _api = api;
Handle = _api.CreateProgram();
GL.ProgramParameter(Handle, ProgramParameterPName.BinaryRetrievableHint, 1); _api.ProgramParameter(Handle, ProgramParameterPName.BinaryRetrievableHint, 1);
_shaderHandles = new int[shaders.Length]; _shaderHandles = new uint[shaders.Length];
bool hasFragmentShader = false; bool hasFragmentShader = false;
for (int index = 0; index < shaders.Length; index++) for (int index = 0; index < shaders.Length; index++)
@ -50,43 +52,44 @@ namespace Ryujinx.Graphics.OpenGL
hasFragmentShader = true; hasFragmentShader = true;
} }
int shaderHandle = GL.CreateShader(shader.Stage.Convert()); uint shaderHandle = _api.CreateShader(shader.Stage.Convert());
switch (shader.Language) switch (shader.Language)
{ {
case TargetLanguage.Glsl: case TargetLanguage.Glsl:
GL.ShaderSource(shaderHandle, shader.Code); _api.ShaderSource(shaderHandle, shader.Code);
GL.CompileShader(shaderHandle); _api.CompileShader(shaderHandle);
break; break;
case TargetLanguage.Spirv: case TargetLanguage.Spirv:
GL.ShaderBinary(1, ref shaderHandle, (BinaryFormat)All.ShaderBinaryFormatSpirVArb, shader.BinaryCode, shader.BinaryCode.Length); _api.ShaderBinary(1, ref shaderHandle, ShaderBinaryFormat.ShaderBinaryFormatSpirV, shader.BinaryCode, shader.BinaryCode.Length);
GL.SpecializeShader(shaderHandle, "main", 0, (int[])null, (int[])null); _api.SpecializeShader(shaderHandle, "main", 0, (int[])null, (int[])null);
break; break;
} }
GL.AttachShader(Handle, shaderHandle); _api.AttachShader(Handle, shaderHandle);
_shaderHandles[index] = shaderHandle; _shaderHandles[index] = shaderHandle;
} }
GL.LinkProgram(Handle); _api.LinkProgram(Handle);
FragmentOutputMap = hasFragmentShader ? fragmentOutputMap : 0; FragmentOutputMap = hasFragmentShader ? fragmentOutputMap : 0;
} }
public Program(ReadOnlySpan<byte> code, bool hasFragmentShader, int fragmentOutputMap) public Program(GL api, ReadOnlySpan<byte> code, bool hasFragmentShader, int fragmentOutputMap)
{ {
Handle = GL.CreateProgram(); _api = api;
Handle = _api.CreateProgram();
if (code.Length >= 4) if (code.Length >= 4)
{ {
BinaryFormat binaryFormat = (BinaryFormat)BinaryPrimitives.ReadInt32LittleEndian(code.Slice(code.Length - 4, 4)); ShaderBinaryFormat binaryFormat = (ShaderBinaryFormat)BinaryPrimitives.ReadInt32LittleEndian(code.Slice(code.Length - 4, 4));
unsafe unsafe
{ {
fixed (byte* ptr = code) fixed (byte* ptr = code)
{ {
GL.ProgramBinary(Handle, binaryFormat, (IntPtr)ptr, code.Length - 4); _api.ProgramBinary(Handle, binaryFormat, (IntPtr)ptr, code.Length - 4);
} }
} }
} }
@ -96,14 +99,14 @@ namespace Ryujinx.Graphics.OpenGL
public void Bind() public void Bind()
{ {
GL.UseProgram(Handle); _api.UseProgram(Handle);
} }
public ProgramLinkStatus CheckProgramLink(bool blocking) public ProgramLinkStatus CheckProgramLink(bool blocking)
{ {
if (!blocking && HwCapabilities.SupportsParallelShaderCompile) if (!blocking && HwCapabilities.SupportsParallelShaderCompile)
{ {
GL.GetProgram(Handle, (GetProgramParameterName)ArbParallelShaderCompile.CompletionStatusArb, out int completed); _api.GetProgram(Handle, (GetProgramParameterName)ArbParallelShaderCompile.CompletionStatusArb, out int completed);
if (completed == 0) if (completed == 0)
{ {
@ -111,14 +114,14 @@ namespace Ryujinx.Graphics.OpenGL
} }
} }
GL.GetProgram(Handle, GetProgramParameterName.LinkStatus, out int status); _api.GetProgram(Handle, ProgramPropertyARB.LinkStatus, out int status);
DeleteShaders(); DeleteShaders();
if (status == 0) if (status == 0)
{ {
_status = ProgramLinkStatus.Failure; _status = ProgramLinkStatus.Failure;
string log = GL.GetProgramInfoLog(Handle); string log = _api.GetProgramInfoLog(Handle);
if (log.Length > MaxShaderLogLength) if (log.Length > MaxShaderLogLength)
{ {
@ -137,11 +140,11 @@ namespace Ryujinx.Graphics.OpenGL
public byte[] GetBinary() public byte[] GetBinary()
{ {
GL.GetProgram(Handle, (GetProgramParameterName)All.ProgramBinaryLength, out int size); _api.GetProgram(Handle, ProgramPropertyARB.ProgramBinaryLength, out int size);
byte[] data = new byte[size + 4]; byte[] data = new byte[size + 4];
GL.GetProgramBinary(Handle, size, out _, out BinaryFormat binFormat, data); _api.GetProgramBinary(Handle, size, out _, out ShaderBinaryFormat binFormat, data);
BinaryPrimitives.WriteInt32LittleEndian(data.AsSpan(size, 4), (int)binFormat); BinaryPrimitives.WriteInt32LittleEndian(data.AsSpan(size, 4), (int)binFormat);
@ -152,10 +155,10 @@ namespace Ryujinx.Graphics.OpenGL
{ {
if (_shaderHandles != null) if (_shaderHandles != null)
{ {
foreach (int shaderHandle in _shaderHandles) foreach (uint shaderHandle in _shaderHandles)
{ {
GL.DetachShader(Handle, shaderHandle); _api.DetachShader(Handle, shaderHandle);
GL.DeleteShader(shaderHandle); _api.DeleteShader(shaderHandle);
} }
_shaderHandles = null; _shaderHandles = null;
@ -167,7 +170,7 @@ namespace Ryujinx.Graphics.OpenGL
if (Handle != 0) if (Handle != 0)
{ {
DeleteShaders(); DeleteShaders();
GL.DeleteProgram(Handle); _api.DeleteProgram(Handle);
Handle = 0; Handle = 0;
} }