More progress

This commit is contained in:
Isaac Marovitz 2024-05-09 11:46:39 -04:00
parent 5f1c880805
commit 4ee4b0f3ac
No known key found for this signature in database
GPG key ID: 97250B2B09A132E1
21 changed files with 697 additions and 695 deletions

View file

@ -69,26 +69,26 @@ namespace Ryujinx.Graphics.OpenGL
(uint)size);
}
public static unsafe PinnedSpan<byte> GetData(GL api, OpenGLRenderer renderer, BufferHandle buffer, int offset, int size)
public static unsafe PinnedSpan<byte> GetData(OpenGLRenderer gd, BufferHandle buffer, int offset, int size)
{
// Data in the persistent buffer and host array is guaranteed to be available
// until the next time the host thread requests data.
if (renderer.PersistentBuffers.TryGet(buffer, out IntPtr ptr))
if (gd.PersistentBuffers.TryGet(buffer, out IntPtr ptr))
{
return new PinnedSpan<byte>(IntPtr.Add(ptr, offset).ToPointer(), size);
}
else if (HwCapabilities.UsePersistentBufferForFlush)
{
return PinnedSpan<byte>.UnsafeFromSpan(renderer.PersistentBuffers.Default.GetBufferData(buffer, offset, size));
return PinnedSpan<byte>.UnsafeFromSpan(gd.PersistentBuffers.Default.GetBufferData(buffer, offset, size));
}
else
{
IntPtr target = renderer.PersistentBuffers.Default.GetHostArray(size);
IntPtr target = gd.PersistentBuffers.Default.GetHostArray(size);
api.BindBuffer(BufferTargetARB.CopyReadBuffer, buffer.ToUInt32());
gd.Api.BindBuffer(BufferTargetARB.CopyReadBuffer, buffer.ToUInt32());
api.GetBufferSubData(BufferTargetARB.CopyReadBuffer, offset, (uint)size, target);
gd.Api.GetBufferSubData(BufferTargetARB.CopyReadBuffer, offset, (uint)size, target);
return new PinnedSpan<byte>(target.ToPointer(), size);
}

View file

@ -1,6 +1,7 @@
using Silk.NET.OpenGL;
using Ryujinx.Graphics.OpenGL.Image;
using System;
using Sampler = Ryujinx.Graphics.OpenGL.Image.Sampler;
namespace Ryujinx.Graphics.OpenGL
{

View file

@ -9,15 +9,15 @@ namespace Ryujinx.Graphics.OpenGL.Effects
{
internal class FsrScalingFilter : IScalingFilter
{
private readonly OpenGLRenderer _renderer;
private readonly OpenGLRenderer _gd;
private int _inputUniform;
private int _outputUniform;
private int _sharpeningUniform;
private int _srcX0Uniform;
private int _srcX1Uniform;
private int _srcY0Uniform;
private int _scalingShaderProgram;
private int _sharpeningShaderProgram;
private uint _scalingShaderProgram;
private uint _sharpeningShaderProgram;
private float _scale = 1;
private int _srcY1Uniform;
private int _dstX0Uniform;
@ -37,19 +37,19 @@ namespace Ryujinx.Graphics.OpenGL.Effects
}
}
public FsrScalingFilter(OpenGLRenderer renderer)
public FsrScalingFilter(OpenGLRenderer gd)
{
Initialize();
_renderer = renderer;
_gd = gd;
}
public void Dispose()
{
if (_scalingShaderProgram != 0)
{
GL.DeleteProgram(_scalingShaderProgram);
GL.DeleteProgram(_sharpeningShaderProgram);
_gd.Api.DeleteProgram(_scalingShaderProgram);
_gd.Api.DeleteProgram(_sharpeningShaderProgram);
}
_intermediaryTexture?.Dispose();
@ -67,23 +67,23 @@ namespace Ryujinx.Graphics.OpenGL.Effects
sharpeningShader = sharpeningShader.Replace("#include \"ffx_a.h\"", fsrA);
sharpeningShader = sharpeningShader.Replace("#include \"ffx_fsr1.h\"", fsr1);
_scalingShaderProgram = CompileProgram(scalingShader, ShaderType.ComputeShader);
_sharpeningShaderProgram = CompileProgram(sharpeningShader, ShaderType.ComputeShader);
_scalingShaderProgram = CompileProgram(_gd.Api, scalingShader, ShaderType.ComputeShader);
_sharpeningShaderProgram = CompileProgram(_gd.Api, sharpeningShader, ShaderType.ComputeShader);
_inputUniform = GL.GetUniformLocation(_scalingShaderProgram, "Source");
_outputUniform = GL.GetUniformLocation(_scalingShaderProgram, "imgOutput");
_sharpeningUniform = GL.GetUniformLocation(_sharpeningShaderProgram, "sharpening");
_inputUniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "Source");
_outputUniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "imgOutput");
_sharpeningUniform = _gd.Api.GetUniformLocation(_sharpeningShaderProgram, "sharpening");
_srcX0Uniform = GL.GetUniformLocation(_scalingShaderProgram, "srcX0");
_srcX1Uniform = GL.GetUniformLocation(_scalingShaderProgram, "srcX1");
_srcY0Uniform = GL.GetUniformLocation(_scalingShaderProgram, "srcY0");
_srcY1Uniform = GL.GetUniformLocation(_scalingShaderProgram, "srcY1");
_dstX0Uniform = GL.GetUniformLocation(_scalingShaderProgram, "dstX0");
_dstX1Uniform = GL.GetUniformLocation(_scalingShaderProgram, "dstX1");
_dstY0Uniform = GL.GetUniformLocation(_scalingShaderProgram, "dstY0");
_dstY1Uniform = GL.GetUniformLocation(_scalingShaderProgram, "dstY1");
_scaleXUniform = GL.GetUniformLocation(_scalingShaderProgram, "scaleX");
_scaleYUniform = GL.GetUniformLocation(_scalingShaderProgram, "scaleY");
_srcX0Uniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "srcX0");
_srcX1Uniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "srcX1");
_srcY0Uniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "srcY0");
_srcY1Uniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "srcY1");
_dstX0Uniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "dstX0");
_dstX1Uniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "dstX1");
_dstY0Uniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "dstY0");
_dstY1Uniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "dstY1");
_scaleXUniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "scaleX");
_scaleYUniform = _gd.Api.GetUniformLocation(_scalingShaderProgram, "scaleY");
}
public void Run(
@ -114,18 +114,18 @@ namespace Ryujinx.Graphics.OpenGL.Effects
originalInfo.SwizzleB,
originalInfo.SwizzleA);
_intermediaryTexture = new TextureStorage(_renderer, info);
_intermediaryTexture = new TextureStorage(_gd, info);
_intermediaryTexture.CreateDefaultView();
}
var textureView = _intermediaryTexture.CreateView(_intermediaryTexture.Info, 0, 0) as TextureView;
int previousProgram = GL.GetInteger(GetPName.CurrentProgram);
int previousUnit = GL.GetInteger(GetPName.ActiveTexture);
GL.ActiveTexture(TextureUnit.Texture0);
int previousTextureBinding = GL.GetInteger(GetPName.TextureBinding2D);
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);
GL.BindImageTexture(0, textureView.Handle, 0, false, 0, BufferAccessARB.ReadWrite, SizedInternalFormat.Rgba8);
_gd.Api.BindImageTexture(0, textureView.Handle, 0, false, 0, BufferAccessARB.ReadWrite, SizedInternalFormat.Rgba8);
int threadGroupWorkRegionDim = 16;
int dispatchX = (width + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
@ -136,42 +136,42 @@ namespace Ryujinx.Graphics.OpenGL.Effects
float srcHeight = Math.Abs(source.Y2 - source.Y1);
float scaleX = srcWidth / view.Width;
float scaleY = srcHeight / view.Height;
GL.UseProgram(_scalingShaderProgram);
_gd.Api.UseProgram(_scalingShaderProgram);
view.Bind(0);
GL.Uniform1(_inputUniform, 0);
GL.Uniform1(_outputUniform, 0);
GL.Uniform1(_srcX0Uniform, (float)source.X1);
GL.Uniform1(_srcX1Uniform, (float)source.X2);
GL.Uniform1(_srcY0Uniform, (float)source.Y1);
GL.Uniform1(_srcY1Uniform, (float)source.Y2);
GL.Uniform1(_dstX0Uniform, (float)destination.X1);
GL.Uniform1(_dstX1Uniform, (float)destination.X2);
GL.Uniform1(_dstY0Uniform, (float)destination.Y1);
GL.Uniform1(_dstY1Uniform, (float)destination.Y2);
GL.Uniform1(_scaleXUniform, scaleX);
GL.Uniform1(_scaleYUniform, scaleY);
GL.DispatchCompute(dispatchX, dispatchY, 1);
_gd.Api.Uniform1(_inputUniform, 0);
_gd.Api.Uniform1(_outputUniform, 0);
_gd.Api.Uniform1(_srcX0Uniform, (float)source.X1);
_gd.Api.Uniform1(_srcX1Uniform, (float)source.X2);
_gd.Api.Uniform1(_srcY0Uniform, (float)source.Y1);
_gd.Api.Uniform1(_srcY1Uniform, (float)source.Y2);
_gd.Api.Uniform1(_dstX0Uniform, (float)destination.X1);
_gd.Api.Uniform1(_dstX1Uniform, (float)destination.X2);
_gd.Api.Uniform1(_dstY0Uniform, (float)destination.Y1);
_gd.Api.Uniform1(_dstY1Uniform, (float)destination.Y2);
_gd.Api.Uniform1(_scaleXUniform, scaleX);
_gd.Api.Uniform1(_scaleYUniform, scaleY);
_gd.Api.DispatchCompute(dispatchX, dispatchY, 1);
GL.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);
_gd.Api.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);
// Sharpening Pass
GL.UseProgram(_sharpeningShaderProgram);
GL.BindImageTexture(0, destinationTexture.Handle, 0, false, 0, BufferAccessARB.ReadWrite, SizedInternalFormat.Rgba8);
_gd.Api.UseProgram(_sharpeningShaderProgram);
_gd.Api.BindImageTexture(0, destinationTexture.Handle, 0, false, 0, BufferAccessARB.ReadWrite, SizedInternalFormat.Rgba8);
textureView.Bind(0);
GL.Uniform1(_inputUniform, 0);
GL.Uniform1(_outputUniform, 0);
GL.Uniform1(_sharpeningUniform, 1.5f - (Level * 0.01f * 1.5f));
GL.DispatchCompute(dispatchX, dispatchY, 1);
_gd.Api.Uniform1(_inputUniform, 0);
_gd.Api.Uniform1(_outputUniform, 0);
_gd.Api.Uniform1(_sharpeningUniform, 1.5f - (Level * 0.01f * 1.5f));
_gd.Api.DispatchCompute(dispatchX, dispatchY, 1);
GL.UseProgram(previousProgram);
GL.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);
_gd.Api.UseProgram(previousProgram);
_gd.Api.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);
(_renderer.Pipeline as Pipeline).RestoreImages1And2();
(_gd.Pipeline as Pipeline).RestoreImages1And2();
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, previousTextureBinding);
_gd.Api.ActiveTexture(TextureUnit.Texture0);
_gd.Api.BindTexture(TextureTarget.Texture2D, previousTextureBinding);
GL.ActiveTexture((TextureUnit)previousUnit);
_gd.Api.ActiveTexture((TextureUnit)previousUnit);
}
}
}

View file

@ -6,25 +6,25 @@ namespace Ryujinx.Graphics.OpenGL.Effects
{
internal class FxaaPostProcessingEffect : IPostProcessingEffect
{
private readonly OpenGLRenderer _renderer;
private readonly OpenGLRenderer _gd;
private int _resolutionUniform;
private int _inputUniform;
private int _outputUniform;
private int _shaderProgram;
private uint _shaderProgram;
private TextureStorage _textureStorage;
public FxaaPostProcessingEffect(OpenGLRenderer renderer)
public FxaaPostProcessingEffect(OpenGLRenderer gd)
{
Initialize();
_renderer = renderer;
_gd = gd;
}
public void Dispose()
{
if (_shaderProgram != 0)
{
GL.DeleteProgram(_shaderProgram);
_gd.Api.DeleteProgram(_shaderProgram);
_textureStorage?.Dispose();
}
}
@ -33,9 +33,9 @@ namespace Ryujinx.Graphics.OpenGL.Effects
{
_shaderProgram = ShaderHelper.CompileProgram(EmbeddedResources.ReadAllText("Ryujinx.Graphics.OpenGL/Effects/Shaders/fxaa.glsl"), ShaderType.ComputeShader);
_resolutionUniform = GL.GetUniformLocation(_shaderProgram, "invResolution");
_inputUniform = GL.GetUniformLocation(_shaderProgram, "inputTexture");
_outputUniform = GL.GetUniformLocation(_shaderProgram, "imgOutput");
_resolutionUniform = _gd.Api.GetUniformLocation(_shaderProgram, "invResolution");
_inputUniform = _gd.Api.GetUniformLocation(_shaderProgram, "inputTexture");
_outputUniform = _gd.Api.GetUniformLocation(_shaderProgram, "imgOutput");
}
public TextureView Run(TextureView view, int width, int height)
@ -43,37 +43,37 @@ namespace Ryujinx.Graphics.OpenGL.Effects
if (_textureStorage == null || _textureStorage.Info.Width != view.Width || _textureStorage.Info.Height != view.Height)
{
_textureStorage?.Dispose();
_textureStorage = new TextureStorage(_renderer, view.Info);
_textureStorage = new TextureStorage(_gd, view.Info);
_textureStorage.CreateDefaultView();
}
var textureView = _textureStorage.CreateView(view.Info, 0, 0) as TextureView;
int previousProgram = GL.GetInteger(GetPName.CurrentProgram);
int previousUnit = GL.GetInteger(GetPName.ActiveTexture);
GL.ActiveTexture(TextureUnit.Texture0);
int previousTextureBinding = GL.GetInteger(GetPName.TextureBinding2D);
int previousProgram = _gd.Api.GetInteger(GetPName.CurrentProgram);
int previousUnit = _gd.Api.GetInteger(GetPName.ActiveTexture);
_gd.Api.ActiveTexture(TextureUnit.Texture0);
int previousTextureBinding = _gd.Api.GetInteger(GetPName.TextureBinding2D);
GL.BindImageTexture(0, textureView.Handle, 0, false, 0, TextureAccess.ReadWrite, SizedInternalFormat.Rgba8);
GL.UseProgram(_shaderProgram);
_gd.Api.BindImageTexture(0, textureView.Handle, 0, false, 0, BufferAccessARB.ReadWrite, SizedInternalFormat.Rgba8);
_gd.Api.UseProgram(_shaderProgram);
var dispatchX = BitUtils.DivRoundUp(view.Width, IPostProcessingEffect.LocalGroupSize);
var dispatchY = BitUtils.DivRoundUp(view.Height, IPostProcessingEffect.LocalGroupSize);
view.Bind(0);
GL.Uniform1(_inputUniform, 0);
GL.Uniform1(_outputUniform, 0);
GL.Uniform2(_resolutionUniform, (float)view.Width, (float)view.Height);
GL.DispatchCompute(dispatchX, dispatchY, 1);
GL.UseProgram(previousProgram);
GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit);
_gd.Api.Uniform1(_inputUniform, 0);
_gd.Api.Uniform1(_outputUniform, 0);
_gd.Api.Uniform2(_resolutionUniform, (float)view.Width, (float)view.Height);
_gd.Api.DispatchCompute(dispatchX, dispatchY, 1);
_gd.Api.UseProgram(previousProgram);
_gd.Api.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);
(_renderer.Pipeline as Pipeline).RestoreImages1And2();
(_gd.Pipeline as Pipeline).RestoreImages1And2();
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, previousTextureBinding);
_gd.Api.ActiveTexture(TextureUnit.Texture0);
_gd.Api.BindTexture(TextureTarget.Texture2D, previousTextureBinding);
GL.ActiveTexture((TextureUnit)previousUnit);
_gd.Api.ActiveTexture((TextureUnit)previousUnit);
return textureView;
}

View file

@ -4,34 +4,34 @@ namespace Ryujinx.Graphics.OpenGL.Effects
{
internal static class ShaderHelper
{
public static int CompileProgram(string shaderCode, ShaderType shaderType)
public static uint CompileProgram(GL api, string shaderCode, ShaderType shaderType)
{
var shader = GL.CreateShader(shaderType);
GL.ShaderSource(shader, shaderCode);
GL.CompileShader(shader);
var shader = api.CreateShader(shaderType);
api.ShaderSource(shader, shaderCode);
api.CompileShader(shader);
var program = GL.CreateProgram();
GL.AttachShader(program, shader);
GL.LinkProgram(program);
var program = api.CreateProgram();
api.AttachShader(program, shader);
api.LinkProgram(program);
GL.DetachShader(program, shader);
GL.DeleteShader(shader);
api.DetachShader(program, shader);
api.DeleteShader(shader);
return program;
}
public static int CompileProgram(string[] shaders, ShaderType shaderType)
public static uint CompileProgram(GL api, string[] shaders, ShaderType shaderType)
{
var shader = GL.CreateShader(shaderType);
GL.ShaderSource(shader, shaders.Length, shaders, (int[])null);
GL.CompileShader(shader);
var shader = api.CreateShader(shaderType);
api.ShaderSource(shader, (uint)shaders.Length, shaders, 0);
api.CompileShader(shader);
var program = GL.CreateProgram();
GL.AttachShader(program, shader);
GL.LinkProgram(program);
var program = api.CreateProgram();
api.AttachShader(program, shader);
api.LinkProgram(program);
GL.DetachShader(program, shader);
GL.DeleteShader(shader);
api.DetachShader(program, shader);
api.DeleteShader(shader);
return program;
}

View file

@ -6,20 +6,20 @@ using System;
namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
{
internal partial class SmaaPostProcessingEffect : IPostProcessingEffect
internal class SmaaPostProcessingEffect : IPostProcessingEffect
{
public const int AreaWidth = 160;
public const int AreaHeight = 560;
public const int SearchWidth = 64;
public const int SearchHeight = 16;
private readonly OpenGLRenderer _renderer;
private readonly OpenGLRenderer _gd;
private TextureStorage _outputTexture;
private TextureStorage _searchTexture;
private TextureStorage _areaTexture;
private int[] _edgeShaderPrograms;
private int[] _blendShaderPrograms;
private int[] _neighbourShaderPrograms;
private uint[] _edgeShaderPrograms;
private uint[] _blendShaderPrograms;
private uint[] _neighbourShaderPrograms;
private TextureStorage _edgeOutputTexture;
private TextureStorage _blendOutputTexture;
private readonly string[] _qualities;
@ -39,15 +39,15 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
_quality = Math.Clamp(value, 0, _qualities.Length - 1);
}
}
public SmaaPostProcessingEffect(OpenGLRenderer renderer, int quality)
public SmaaPostProcessingEffect(OpenGLRenderer gd, int quality)
{
_renderer = renderer;
_gd = gd;
_edgeShaderPrograms = Array.Empty<int>();
_blendShaderPrograms = Array.Empty<int>();
_neighbourShaderPrograms = Array.Empty<int>();
_edgeShaderPrograms = Array.Empty<uint>();
_blendShaderPrograms = Array.Empty<uint>();
_neighbourShaderPrograms = Array.Empty<uint>();
_qualities = new string[] { "SMAA_PRESET_LOW", "SMAA_PRESET_MEDIUM", "SMAA_PRESET_HIGH", "SMAA_PRESET_ULTRA" };
_qualities = ["SMAA_PRESET_LOW", "SMAA_PRESET_MEDIUM", "SMAA_PRESET_HIGH", "SMAA_PRESET_ULTRA"];
Quality = quality;
@ -69,9 +69,9 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
{
for (int i = 0; i < _edgeShaderPrograms.Length; i++)
{
GL.DeleteProgram(_edgeShaderPrograms[i]);
GL.DeleteProgram(_blendShaderPrograms[i]);
GL.DeleteProgram(_neighbourShaderPrograms[i]);
_gd.Api.DeleteProgram(_edgeShaderPrograms[i]);
_gd.Api.DeleteProgram(_blendShaderPrograms[i]);
_gd.Api.DeleteProgram(_neighbourShaderPrograms[i]);
}
}
@ -80,9 +80,9 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
string baseShader = EmbeddedResources.ReadAllText("Ryujinx.Graphics.OpenGL/Effects/Shaders/smaa.hlsl");
var pixelSizeDefine = $"#define SMAA_RT_METRICS float4(1.0 / {width}.0, 1.0 / {height}.0, {width}, {height}) \n";
_edgeShaderPrograms = new int[_qualities.Length];
_blendShaderPrograms = new int[_qualities.Length];
_neighbourShaderPrograms = new int[_qualities.Length];
_edgeShaderPrograms = new uint[_qualities.Length];
_blendShaderPrograms = new uint[_qualities.Length];
_neighbourShaderPrograms = new uint[_qualities.Length];
for (int i = 0; i < +_edgeShaderPrograms.Length; i++)
{
@ -106,12 +106,12 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
_neighbourShaderPrograms[i] = neighbourProgram;
}
_inputUniform = GL.GetUniformLocation(_edgeShaderPrograms[0], "inputTexture");
_outputUniform = GL.GetUniformLocation(_edgeShaderPrograms[0], "imgOutput");
_samplerAreaUniform = GL.GetUniformLocation(_blendShaderPrograms[0], "samplerArea");
_samplerSearchUniform = GL.GetUniformLocation(_blendShaderPrograms[0], "samplerSearch");
_samplerBlendUniform = GL.GetUniformLocation(_neighbourShaderPrograms[0], "samplerBlend");
_resolutionUniform = GL.GetUniformLocation(_edgeShaderPrograms[0], "invResolution");
_inputUniform = _gd.Api.GetUniformLocation(_edgeShaderPrograms[0], "inputTexture");
_outputUniform = _gd.Api.GetUniformLocation(_edgeShaderPrograms[0], "imgOutput");
_samplerAreaUniform = _gd.Api.GetUniformLocation(_blendShaderPrograms[0], "samplerArea");
_samplerSearchUniform = _gd.Api.GetUniformLocation(_blendShaderPrograms[0], "samplerSearch");
_samplerBlendUniform = _gd.Api.GetUniformLocation(_neighbourShaderPrograms[0], "samplerBlend");
_resolutionUniform = _gd.Api.GetUniformLocation(_edgeShaderPrograms[0], "invResolution");
}
private void Initialize()
@ -148,8 +148,8 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
SwizzleComponent.Blue,
SwizzleComponent.Alpha);
_areaTexture = new TextureStorage(_renderer, areaInfo);
_searchTexture = new TextureStorage(_renderer, searchInfo);
_areaTexture = new TextureStorage(_gd, areaInfo);
_searchTexture = new TextureStorage(_gd, searchInfo);
var areaTexture = EmbeddedResources.ReadFileToRentedMemory("Ryujinx.Graphics.OpenGL/Effects/Textures/SmaaAreaTexture.bin");
var searchTexture = EmbeddedResources.ReadFileToRentedMemory("Ryujinx.Graphics.OpenGL/Effects/Textures/SmaaSearchTexture.bin");
@ -166,11 +166,11 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
if (_outputTexture == null || _outputTexture.Info.Width != view.Width || _outputTexture.Info.Height != view.Height)
{
_outputTexture?.Dispose();
_outputTexture = new TextureStorage(_renderer, view.Info);
_outputTexture = new TextureStorage(_gd, view.Info);
_outputTexture.CreateDefaultView();
_edgeOutputTexture = new TextureStorage(_renderer, view.Info);
_edgeOutputTexture = new TextureStorage(_gd, view.Info);
_edgeOutputTexture.CreateDefaultView();
_blendOutputTexture = new TextureStorage(_renderer, view.Info);
_blendOutputTexture = new TextureStorage(_gd, view.Info);
_blendOutputTexture.CreateDefaultView();
DeleteShaders();
@ -184,77 +184,77 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
var areaTexture = _areaTexture.DefaultView as TextureView;
var searchTexture = _searchTexture.DefaultView as TextureView;
var previousFramebuffer = GL.GetInteger(GetPName.FramebufferBinding);
int previousUnit = GL.GetInteger(GetPName.ActiveTexture);
GL.ActiveTexture(TextureUnit.Texture0);
int previousTextureBinding0 = GL.GetInteger(GetPName.TextureBinding2D);
GL.ActiveTexture(TextureUnit.Texture1);
int previousTextureBinding1 = GL.GetInteger(GetPName.TextureBinding2D);
GL.ActiveTexture(TextureUnit.Texture2);
int previousTextureBinding2 = GL.GetInteger(GetPName.TextureBinding2D);
var previousFramebuffer = _gd.Api.GetInteger(GetPName.DrawFramebufferBinding);
int previousUnit = _gd.Api.GetInteger(GetPName.ActiveTexture);
_gd.Api.ActiveTexture(TextureUnit.Texture0);
int previousTextureBinding0 = _gd.Api.GetInteger(GetPName.TextureBinding2D);
_gd.Api.ActiveTexture(TextureUnit.Texture1);
int previousTextureBinding1 = _gd.Api.GetInteger(GetPName.TextureBinding2D);
_gd.Api.ActiveTexture(TextureUnit.Texture2);
int previousTextureBinding2 = _gd.Api.GetInteger(GetPName.TextureBinding2D);
var framebuffer = new Framebuffer();
var framebuffer = new Framebuffer(_gd.Api);
framebuffer.Bind();
framebuffer.AttachColor(0, edgeOutput);
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.ClearColor(0, 0, 0, 0);
_gd.Api.Clear(ClearBufferMask.ColorBufferBit);
_gd.Api.ClearColor(0, 0, 0, 0);
framebuffer.AttachColor(0, blendOutput);
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.ClearColor(0, 0, 0, 0);
_gd.Api.Clear(ClearBufferMask.ColorBufferBit);
_gd.Api.ClearColor(0, 0, 0, 0);
GL.BindFramebuffer(FramebufferTarget.Framebuffer, previousFramebuffer);
_gd.Api.BindFramebuffer(FramebufferTarget.Framebuffer, previousFramebuffer);
framebuffer.Dispose();
var dispatchX = BitUtils.DivRoundUp(view.Width, IPostProcessingEffect.LocalGroupSize);
var dispatchY = BitUtils.DivRoundUp(view.Height, IPostProcessingEffect.LocalGroupSize);
int previousProgram = GL.GetInteger(GetPName.CurrentProgram);
GL.BindImageTexture(0, edgeOutput.Handle, 0, false, 0, BufferAccessARB.ReadWrite, SizedInternalFormat.Rgba8);
GL.UseProgram(_edgeShaderPrograms[Quality]);
uint previousProgram = (uint)_gd.Api.GetInteger(GetPName.CurrentProgram);
_gd.Api.BindImageTexture(0, edgeOutput.Handle, 0, false, 0, BufferAccessARB.ReadWrite, SizedInternalFormat.Rgba8);
_gd.Api.UseProgram(_edgeShaderPrograms[Quality]);
view.Bind(0);
GL.Uniform1(_inputUniform, 0);
GL.Uniform1(_outputUniform, 0);
GL.Uniform2(_resolutionUniform, (float)view.Width, (float)view.Height);
GL.DispatchCompute(dispatchX, dispatchY, 1);
GL.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);
_gd.Api.Uniform1(_inputUniform, 0);
_gd.Api.Uniform1(_outputUniform, 0);
_gd.Api.Uniform2(_resolutionUniform, view.Width, view.Height);
_gd.Api.DispatchCompute(dispatchX, dispatchY, 1);
_gd.Api.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);
GL.BindImageTexture(0, blendOutput.Handle, 0, false, 0, BufferAccessARB.ReadWrite, SizedInternalFormat.Rgba8);
GL.UseProgram(_blendShaderPrograms[Quality]);
_gd.Api.BindImageTexture(0, blendOutput.Handle, 0, false, 0, BufferAccessARB.ReadWrite, SizedInternalFormat.Rgba8);
_gd.Api.UseProgram(_blendShaderPrograms[Quality]);
edgeOutput.Bind(0);
areaTexture.Bind(1);
searchTexture.Bind(2);
GL.Uniform1(_inputUniform, 0);
GL.Uniform1(_outputUniform, 0);
GL.Uniform1(_samplerAreaUniform, 1);
GL.Uniform1(_samplerSearchUniform, 2);
GL.Uniform2(_resolutionUniform, (float)view.Width, (float)view.Height);
GL.DispatchCompute(dispatchX, dispatchY, 1);
GL.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);
_gd.Api.Uniform1(_inputUniform, 0);
_gd.Api.Uniform1(_outputUniform, 0);
_gd.Api.Uniform1(_samplerAreaUniform, 1);
_gd.Api.Uniform1(_samplerSearchUniform, 2);
_gd.Api.Uniform2(_resolutionUniform, view.Width, view.Height);
_gd.Api.DispatchCompute(dispatchX, dispatchY, 1);
_gd.Api.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);
GL.BindImageTexture(0, textureView.Handle, 0, false, 0, BufferAccessARB.ReadWrite, SizedInternalFormat.Rgba8);
GL.UseProgram(_neighbourShaderPrograms[Quality]);
_gd.Api.BindImageTexture(0, textureView.Handle, 0, false, 0, BufferAccessARB.ReadWrite, SizedInternalFormat.Rgba8);
_gd.Api.UseProgram(_neighbourShaderPrograms[Quality]);
view.Bind(0);
blendOutput.Bind(1);
GL.Uniform1(_inputUniform, 0);
GL.Uniform1(_outputUniform, 0);
GL.Uniform1(_samplerBlendUniform, 1);
GL.Uniform2(_resolutionUniform, (float)view.Width, (float)view.Height);
GL.DispatchCompute(dispatchX, dispatchY, 1);
GL.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);
_gd.Api.Uniform1(_inputUniform, 0);
_gd.Api.Uniform1(_outputUniform, 0);
_gd.Api.Uniform1(_samplerBlendUniform, 1);
_gd.Api.Uniform2(_resolutionUniform, view.Width, view.Height);
_gd.Api.DispatchCompute(dispatchX, dispatchY, 1);
_gd.Api.MemoryBarrier(MemoryBarrierMask.ShaderImageAccessBarrierBit);
(_renderer.Pipeline as Pipeline).RestoreImages1And2();
(_gd.Pipeline as Pipeline).RestoreImages1And2();
GL.UseProgram(previousProgram);
_gd.Api.UseProgram(previousProgram);
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, previousTextureBinding0);
GL.ActiveTexture(TextureUnit.Texture1);
GL.BindTexture(TextureTarget.Texture2D, previousTextureBinding1);
GL.ActiveTexture(TextureUnit.Texture2);
GL.BindTexture(TextureTarget.Texture2D, previousTextureBinding2);
_gd.Api.ActiveTexture(TextureUnit.Texture0);
_gd.Api.BindTexture(TextureTarget.Texture2D, previousTextureBinding0);
_gd.Api.ActiveTexture(TextureUnit.Texture1);
_gd.Api.BindTexture(TextureTarget.Texture2D, previousTextureBinding1);
_gd.Api.ActiveTexture(TextureUnit.Texture2);
_gd.Api.BindTexture(TextureTarget.Texture2D, previousTextureBinding2);
GL.ActiveTexture((TextureUnit)previousUnit);
_gd.Api.ActiveTexture((TextureUnit)previousUnit);
return textureView;
}

View file

@ -23,14 +23,15 @@ namespace Ryujinx.Graphics.OpenGL
public Framebuffer(GL api)
{
Handle = GL.GenFramebuffer();
_clearFbHandle = GL.GenFramebuffer();
_api = api;
Handle = _api.GenFramebuffer();
_clearFbHandle = _api.GenFramebuffer();
_colors = new TextureView[8];
_api = api;
}
public int Bind()
public uint Bind()
{
_api.BindFramebuffer(FramebufferTarget.Framebuffer, Handle);
return Handle;
@ -203,7 +204,7 @@ namespace Ryujinx.Graphics.OpenGL
if (!_clearFbInitialized)
{
SetDrawBuffersImpl(Constants.MaxRenderTargets);
SetDrawBuffersImpl(_api, Constants.MaxRenderTargets);
_clearFbInitialized = true;
}
}

View file

@ -6,7 +6,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
class Sampler : ISampler
{
public uint Handle { get; private set; }
private GL _api;
private readonly GL _api;
public Sampler(GL api, SamplerCreateInfo info)
{

View file

@ -5,7 +5,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
class TextureBase
{
private readonly protected GL Api;
private readonly protected OpenGLRenderer _gd;
public uint Handle { get; protected set; }
public TextureCreateInfo Info { get; }
@ -16,12 +16,12 @@ namespace Ryujinx.Graphics.OpenGL.Image
public Target Target => Info.Target;
public Format Format => Info.Format;
public TextureBase(GL api, TextureCreateInfo info)
public TextureBase(OpenGLRenderer gd, TextureCreateInfo info)
{
Api = api;
_gd = gd;
Info = info;
Handle = Api.GenTexture();
Handle = _gd.Api.GenTexture();
}
public void Bind(uint unit)
@ -31,8 +31,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
protected void Bind(TextureTarget target, uint unit)
{
Api.ActiveTexture((TextureUnit)((uint)TextureUnit.Texture0 + unit));
Api.BindTexture(target, Handle);
_gd.Api.ActiveTexture((TextureUnit)((uint)TextureUnit.Texture0 + unit));
_gd.Api.BindTexture(target, Handle);
}
public static void ClearBinding(GL api, uint unit)

View file

@ -7,16 +7,15 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
class TextureBuffer : TextureBase, ITexture
{
private readonly OpenGLRenderer _renderer;
private int _bufferOffset;
private int _bufferSize;
private int _bufferCount;
private BufferHandle _buffer;
public TextureBuffer(GL api, OpenGLRenderer renderer, TextureCreateInfo info) : base(api, info)
public TextureBuffer(OpenGLRenderer gd, TextureCreateInfo info) : base(gd, info)
{
_renderer = renderer;
}
public void CopyTo(ITexture destination, int firstLayer, int firstLevel)
@ -41,7 +40,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
public PinnedSpan<byte> GetData()
{
return Buffer.GetData(Api, _renderer, _buffer, _bufferOffset, _bufferSize);
return Buffer.GetData(_gd, _buffer, _bufferOffset, _bufferSize);
}
public PinnedSpan<byte> GetData(int layer, int level)
@ -59,7 +58,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
var dataSpan = data.Memory.Span;
Buffer.SetData(Api, _buffer, _bufferOffset, dataSpan[..Math.Min(dataSpan.Length, _bufferSize)]);
Buffer.SetData(_gd.Api, _buffer, _bufferOffset, dataSpan[..Math.Min(dataSpan.Length, _bufferSize)]);
data.Dispose();
}
@ -82,7 +81,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
_buffer == buffer.Handle &&
buffer.Offset == _bufferOffset &&
buffer.Size == _bufferSize &&
_renderer.BufferCount == _bufferCount)
_gd.BufferCount == _bufferCount)
{
// Only rebind the buffer when more have been created.
return;
@ -91,20 +90,20 @@ namespace Ryujinx.Graphics.OpenGL.Image
_buffer = buffer.Handle;
_bufferOffset = buffer.Offset;
_bufferSize = buffer.Size;
_bufferCount = _renderer.BufferCount;
_bufferCount = _gd.BufferCount;
Bind(0);
SizedInternalFormat format = (SizedInternalFormat)FormatTable.GetFormatInfo(Info.Format).InternalFormat;
Api.TexBufferRange(TextureTarget.TextureBuffer, format, _buffer.ToUInt32(), buffer.Offset, (uint)buffer.Size);
_gd.Api.TexBufferRange(TextureTarget.TextureBuffer, format, _buffer.ToUInt32(), buffer.Offset, (uint)buffer.Size);
}
public void Dispose()
{
if (Handle != 0)
{
Api.DeleteTexture(Handle);
_gd.Api.DeleteTexture(Handle);
Handle = 0;
}

View file

@ -7,8 +7,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
class TextureCopy : IDisposable
{
private readonly GL _api;
private readonly OpenGLRenderer _renderer;
private readonly OpenGLRenderer _gd;
private uint _srcFramebuffer;
private uint _dstFramebuffer;
@ -18,11 +17,10 @@ namespace Ryujinx.Graphics.OpenGL.Image
public IntermediatePool IntermediatePool { get; }
public TextureCopy(GL api, OpenGLRenderer renderer)
public TextureCopy(OpenGLRenderer gd)
{
_api = api;
_renderer = renderer;
IntermediatePool = new IntermediatePool(renderer);
_gd = gd;
IntermediatePool = new IntermediatePool(gd);
}
public void Copy(
@ -57,10 +55,10 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
TextureView srcConverted = src.Format.IsBgr() != dst.Format.IsBgr() ? BgraSwap(src) : src;
(uint oldDrawFramebufferHandle, uint oldReadFramebufferHandle) = ((Pipeline)_renderer.Pipeline).GetBoundFramebuffers();
(uint oldDrawFramebufferHandle, uint oldReadFramebufferHandle) = ((Pipeline)_gd.Pipeline).GetBoundFramebuffers();
_api.BindFramebuffer(FramebufferTarget.ReadFramebuffer, GetSrcFramebufferLazy());
_api.BindFramebuffer(FramebufferTarget.DrawFramebuffer, GetDstFramebufferLazy());
_gd.Api.BindFramebuffer(FramebufferTarget.ReadFramebuffer, GetSrcFramebufferLazy());
_gd.Api.BindFramebuffer(FramebufferTarget.DrawFramebuffer, GetDstFramebufferLazy());
if (srcLevel != 0)
{
@ -78,13 +76,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
if ((srcLayer | dstLayer) != 0 || layers > 1)
{
Attach(_api, FramebufferTarget.ReadFramebuffer, src.Format, srcConverted.Handle, srcLevel + level, srcLayer + layer);
Attach(_api, FramebufferTarget.DrawFramebuffer, dst.Format, dst.Handle, dstLevel + level, dstLayer + layer);
Attach(_gd.Api, FramebufferTarget.ReadFramebuffer, src.Format, srcConverted.Handle, srcLevel + level, srcLayer + layer);
Attach(_gd.Api, FramebufferTarget.DrawFramebuffer, dst.Format, dst.Handle, dstLevel + level, dstLayer + layer);
}
else
{
Attach(_api, FramebufferTarget.ReadFramebuffer, src.Format, srcConverted.Handle, srcLevel + level);
Attach(_api, FramebufferTarget.DrawFramebuffer, dst.Format, dst.Handle, dstLevel + level);
Attach(_gd.Api, FramebufferTarget.ReadFramebuffer, src.Format, srcConverted.Handle, srcLevel + level);
Attach(_gd.Api, FramebufferTarget.DrawFramebuffer, dst.Format, dst.Handle, dstLevel + level);
}
ClearBufferMask mask = GetMask(src.Format);
@ -98,13 +96,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
? BlitFramebufferFilter.Linear
: BlitFramebufferFilter.Nearest;
_api.ReadBuffer(ReadBufferMode.ColorAttachment0);
_api.DrawBuffer(DrawBufferMode.ColorAttachment0);
_gd.Api.ReadBuffer(ReadBufferMode.ColorAttachment0);
_gd.Api.DrawBuffer(DrawBufferMode.ColorAttachment0);
_api.Disable(EnableCap.RasterizerDiscard);
_api.Disable(EnableCap.ScissorTest, 0);
_gd.Api.Disable(EnableCap.RasterizerDiscard);
_gd.Api.Disable(EnableCap.ScissorTest, 0);
_api.BlitFramebuffer(
_gd.Api.BlitFramebuffer(
srcRegion.X1,
srcRegion.Y1,
srcRegion.X2,
@ -124,14 +122,14 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
}
Attach(_api, FramebufferTarget.ReadFramebuffer, src.Format, 0);
Attach(_api, FramebufferTarget.DrawFramebuffer, dst.Format, 0);
Attach(_gd.Api, FramebufferTarget.ReadFramebuffer, src.Format, 0);
Attach(_gd.Api, FramebufferTarget.DrawFramebuffer, dst.Format, 0);
_api.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
_api.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
_gd.Api.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
_gd.Api.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
((Pipeline)_renderer.Pipeline).RestoreScissor0Enable();
((Pipeline)_renderer.Pipeline).RestoreRasterizerDiscard();
((Pipeline)_gd.Pipeline).RestoreScissor0Enable();
((Pipeline)_gd.Pipeline).RestoreRasterizerDiscard();
if (srcConverted != src)
{
@ -180,8 +178,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
TextureCreateInfo srcInfo = src.Info;
TextureCreateInfo dstInfo = dst.Info;
uint srcHandle = (uint)src.Handle;
uint dstHandle = (uint)dst.Handle;
uint srcHandle = src.Handle;
uint dstHandle = dst.Handle;
int srcWidth = srcInfo.Width;
int srcHeight = srcInfo.Height;
@ -242,7 +240,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (HwCapabilities.Vendor == HwCapabilities.GpuVendor.IntelWindows)
{
_api.CopyImageSubData(
_gd.Api.CopyImageSubData(
src.Storage.Handle,
src.Storage.Info.Target.ConvertToImageTarget(),
(int)src.FirstLevel + srcLevel + level,
@ -261,7 +259,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
else
{
_api.CopyImageSubData(
_gd.Api.CopyImageSubData(
srcHandle,
srcInfo.Target.ConvertToImageTarget(),
srcLevel + level,
@ -346,20 +344,20 @@ namespace Ryujinx.Graphics.OpenGL.Image
public TextureView BgraSwap(TextureView from)
{
TextureView to = (TextureView)_renderer.CreateTexture(from.Info);
TextureView to = (TextureView)_gd.CreateTexture(from.Info);
EnsurePbo(from);
_api.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyPboHandle);
_gd.Api.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyPboHandle);
from.WriteToPbo(0, forceBgra: true);
_api.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
_api.BindBuffer(BufferTargetARB.PixelUnpackBuffer, _copyPboHandle);
_gd.Api.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
_gd.Api.BindBuffer(BufferTargetARB.PixelUnpackBuffer, _copyPboHandle);
to.ReadFromPbo(0, _copyPboSize);
_api.BindBuffer(BufferTargetARB.PixelUnpackBuffer, 0);
_gd.Api.BindBuffer(BufferTargetARB.PixelUnpackBuffer, 0);
return to;
}
@ -395,7 +393,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
EnsurePbo(from);
_api.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyPboHandle);
_gd.Api.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyPboHandle);
// The source texture is written out in full, then the destination is taken as a slice from the data using unpack params.
// The offset points to the base at which the requested layer is at.
@ -409,39 +407,39 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (slice)
{
// Set unpack parameters to take a slice of width/height:
_api.PixelStore(PixelStoreParameter.UnpackRowLength, unpackWidth);
_api.PixelStore(PixelStoreParameter.UnpackImageHeight, unpackHeight);
_gd.Api.PixelStore(PixelStoreParameter.UnpackRowLength, unpackWidth);
_gd.Api.PixelStore(PixelStoreParameter.UnpackImageHeight, unpackHeight);
if (to.Info.IsCompressed)
{
_api.PixelStore(GLEnum.UnpackCompressedBlockWidth, to.Info.BlockWidth);
_api.PixelStore(GLEnum.UnpackCompressedBlockHeight, to.Info.BlockHeight);
_api.PixelStore(GLEnum.UnpackCompressedBlockDepth, 1);
_api.PixelStore(GLEnum.UnpackCompressedBlockSize, to.Info.BytesPerPixel);
_gd.Api.PixelStore(GLEnum.UnpackCompressedBlockWidth, to.Info.BlockWidth);
_gd.Api.PixelStore(GLEnum.UnpackCompressedBlockHeight, to.Info.BlockHeight);
_gd.Api.PixelStore(GLEnum.UnpackCompressedBlockDepth, 1);
_gd.Api.PixelStore(GLEnum.UnpackCompressedBlockSize, to.Info.BytesPerPixel);
}
}
_api.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
_api.BindBuffer(BufferTargetARB.PixelUnpackBuffer, _copyPboHandle);
_gd.Api.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
_gd.Api.BindBuffer(BufferTargetARB.PixelUnpackBuffer, _copyPboHandle);
to.ReadFromPbo2D(offset, dstLayer, dstLevel, dstWidth, dstHeight);
if (slice)
{
// Reset unpack parameters
_api.PixelStore(PixelStoreParameter.UnpackRowLength, 0);
_api.PixelStore(PixelStoreParameter.UnpackImageHeight, 0);
_gd.Api.PixelStore(PixelStoreParameter.UnpackRowLength, 0);
_gd.Api.PixelStore(PixelStoreParameter.UnpackImageHeight, 0);
if (to.Info.IsCompressed)
{
_api.PixelStore(GLEnum.UnpackCompressedBlockWidth, 0);
_api.PixelStore(GLEnum.UnpackCompressedBlockHeight, 0);
_api.PixelStore(GLEnum.UnpackCompressedBlockDepth, 0);
_api.PixelStore(GLEnum.UnpackCompressedBlockSize, 0);
_gd.Api.PixelStore(GLEnum.UnpackCompressedBlockWidth, 0);
_gd.Api.PixelStore(GLEnum.UnpackCompressedBlockHeight, 0);
_gd.Api.PixelStore(GLEnum.UnpackCompressedBlockDepth, 0);
_gd.Api.PixelStore(GLEnum.UnpackCompressedBlockSize, 0);
}
}
_api.BindBuffer(BufferTargetARB.PixelUnpackBuffer, 0);
_gd.Api.BindBuffer(BufferTargetARB.PixelUnpackBuffer, 0);
}
private void EnsurePbo(TextureView view)
@ -455,18 +453,18 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (_copyPboSize < requiredSize && _copyPboHandle != 0)
{
_api.DeleteBuffer(_copyPboHandle);
_gd.Api.DeleteBuffer(_copyPboHandle);
_copyPboHandle = 0;
}
if (_copyPboHandle == 0)
{
_copyPboHandle = _api.GenBuffer();
_copyPboHandle = _gd.Api.GenBuffer();
_copyPboSize = requiredSize;
_api.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyPboHandle);
_api.BufferData(BufferTargetARB.PixelPackBuffer, (uint)requiredSize, IntPtr.Zero, BufferUsageARB.DynamicCopy);
_gd.Api.BindBuffer(BufferTargetARB.PixelPackBuffer, _copyPboHandle);
_gd.Api.BufferData(BufferTargetARB.PixelPackBuffer, (uint)requiredSize, IntPtr.Zero, BufferUsageARB.DynamicCopy);
}
}
@ -474,7 +472,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
if (_srcFramebuffer == 0)
{
_srcFramebuffer = _api.GenFramebuffer();
_srcFramebuffer = _gd.Api.GenFramebuffer();
}
return _srcFramebuffer;
@ -484,7 +482,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
if (_dstFramebuffer == 0)
{
_dstFramebuffer = _api.GenFramebuffer();
_dstFramebuffer = _gd.Api.GenFramebuffer();
}
return _dstFramebuffer;
@ -494,21 +492,21 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
if (_srcFramebuffer != 0)
{
_api.DeleteFramebuffer(_srcFramebuffer);
_gd.Api.DeleteFramebuffer(_srcFramebuffer);
_srcFramebuffer = 0;
}
if (_dstFramebuffer != 0)
{
_api.DeleteFramebuffer(_dstFramebuffer);
_gd.Api.DeleteFramebuffer(_dstFramebuffer);
_dstFramebuffer = 0;
}
if (_copyPboHandle != 0)
{
_api.DeleteBuffer(_copyPboHandle);
_gd.Api.DeleteBuffer(_copyPboHandle);
_copyPboHandle = 0;
}

View file

@ -67,15 +67,13 @@ void main()
imageStore(dst, ivec2(coords), uvec4(r, g, b, a));
}";
private readonly GL _api;
private readonly OpenGLRenderer _renderer;
private readonly OpenGLRenderer _gd;
private readonly Dictionary<int, uint> _shorteningProgramHandles;
private readonly Dictionary<int, uint> _wideningProgramHandles;
public TextureCopyIncompatible(GL api, OpenGLRenderer renderer)
public TextureCopyIncompatible(OpenGLRenderer gd)
{
_api = api;
_renderer = renderer;
_gd = gd;
_shorteningProgramHandles = new Dictionary<int, uint>();
_wideningProgramHandles = new Dictionary<int, uint>();
}
@ -96,7 +94,7 @@ void main()
var srcFormat = (InternalFormat)GetFormat(componentSize, srcComponentsCount);
var dstFormat = (InternalFormat)GetFormat(componentSize, dstComponentsCount);
_api.UseProgram(srcBpp < dstBpp
_gd.Api.UseProgram(srcBpp < dstBpp
? GetWideningShader(componentSize, srcComponentsCount, dstComponentsCount)
: GetShorteningShader(componentSize, srcComponentsCount, dstComponentsCount));
@ -113,14 +111,14 @@ void main()
for (int z = 0; z < depth; z++)
{
_api.BindImageTexture(0, src.Handle, srcLevel + l, false, srcLayer + z, BufferAccessARB.ReadOnly, srcFormat);
_api.BindImageTexture(1, dst.Handle, dstLevel + l, false, dstLayer + z, BufferAccessARB.WriteOnly, dstFormat);
_gd.Api.BindImageTexture(0, src.Handle, srcLevel + l, false, srcLayer + z, BufferAccessARB.ReadOnly, srcFormat);
_gd.Api.BindImageTexture(1, dst.Handle, dstLevel + l, false, dstLayer + z, BufferAccessARB.WriteOnly, dstFormat);
_api.DispatchCompute((width + 31) / 32, (height + 31) / 32, 1);
_gd.Api.DispatchCompute((width + 31) / 32, (height + 31) / 32, 1);
}
}
Pipeline pipeline = (Pipeline)_renderer.Pipeline;
Pipeline pipeline = (Pipeline)_gd.Pipeline;
pipeline.RestoreProgram();
pipeline.RestoreImages1And2();
@ -190,7 +188,7 @@ void main()
if (!programHandles.TryGetValue(key, out uint programHandle))
{
uint csHandle = _api.CreateShader(ShaderType.ComputeShader);
uint csHandle = _gd.Api.CreateShader(ShaderType.ComputeShader);
string[] formatTable = new[] { "r8ui", "r16ui", "r32ui", "rg8ui", "rg16ui", "rg32ui", "rgba8ui", "rgba16ui", "rgba32ui" };
@ -203,25 +201,25 @@ void main()
int ratio = srcBpp < dstBpp ? dstBpp / srcBpp : srcBpp / dstBpp;
int ratioLog2 = BitOperations.Log2((uint)ratio);
_api.ShaderSource(csHandle, code
_gd.Api.ShaderSource(csHandle, code
.Replace("$SRC_FORMAT$", srcFormat)
.Replace("$DST_FORMAT$", dstFormat)
.Replace("$RATIO_LOG2$", ratioLog2.ToString(CultureInfo.InvariantCulture)));
_api.CompileShader(csHandle);
_gd.Api.CompileShader(csHandle);
programHandle = _api.CreateProgram();
programHandle = _gd.Api.CreateProgram();
_api.AttachShader(programHandle, csHandle);
_api.LinkProgram(programHandle);
_api.DetachShader(programHandle, csHandle);
_api.DeleteShader(csHandle);
_gd.Api.AttachShader(programHandle, csHandle);
_gd.Api.LinkProgram(programHandle);
_gd.Api.DetachShader(programHandle, csHandle);
_gd.Api.DeleteShader(csHandle);
_api.GetProgram(programHandle, ProgramPropertyARB.LinkStatus, out int status);
_gd.Api.GetProgram(programHandle, ProgramPropertyARB.LinkStatus, out int status);
if (status == 0)
{
throw new Exception(_api.GetProgramInfoLog(programHandle));
throw new Exception(_gd.Api.GetProgramInfoLog(programHandle));
}
programHandles.Add(key, programHandle);
@ -234,14 +232,14 @@ void main()
{
foreach (uint handle in _shorteningProgramHandles.Values)
{
_api.DeleteProgram(handle);
_gd.Api.DeleteProgram(handle);
}
_shorteningProgramHandles.Clear();
foreach (uint handle in _wideningProgramHandles.Values)
{
_api.DeleteProgram(handle);
_gd.Api.DeleteProgram(handle);
}
_wideningProgramHandles.Clear();

View file

@ -93,15 +93,13 @@ void main()
imageStore(imgOut, ivec2(int(coords.x) >> samplesInXLog2, int(coords.y) >> samplesInYLog2), sampleIdx, value);
}";
private readonly GL _api;
private readonly OpenGLRenderer _renderer;
private readonly OpenGLRenderer _gd;
private readonly uint[] _msToNonMSProgramHandles;
private readonly uint[] _nonMSToMSProgramHandles;
public TextureCopyMS(GL api, OpenGLRenderer renderer)
public TextureCopyMS(OpenGLRenderer gd)
{
_api = api;
_renderer = renderer;
_gd = gd;
_msToNonMSProgramHandles = new uint[5];
_nonMSToMSProgramHandles = new uint[5];
}
@ -117,17 +115,17 @@ void main()
uint dstWidth = (uint)dstInfo.Width;
uint dstHeight = (uint)dstInfo.Height;
_api.UseProgram(GetMSToNonMSShader(srcInfo.BytesPerPixel));
_gd.Api.UseProgram(GetMSToNonMSShader(srcInfo.BytesPerPixel));
for (int z = 0; z < depth; z++)
{
_api.BindImageTexture(0, srcHandle, 0, false, srcLayer + z, BufferAccessARB.ReadOnly, (InternalFormat)GetFormat(srcInfo.BytesPerPixel));
_api.BindImageTexture(1, dstHandle, 0, false, dstLayer + z, BufferAccessARB.WriteOnly, (InternalFormat)GetFormat(dstInfo.BytesPerPixel));
_gd.Api.BindImageTexture(0, srcHandle, 0, false, srcLayer + z, BufferAccessARB.ReadOnly, (InternalFormat)GetFormat(srcInfo.BytesPerPixel));
_gd.Api.BindImageTexture(1, dstHandle, 0, false, dstLayer + z, BufferAccessARB.WriteOnly, (InternalFormat)GetFormat(dstInfo.BytesPerPixel));
_api.DispatchCompute((dstWidth + 31) / 32, (dstHeight + 31) / 32, 1);
_gd.Api.DispatchCompute((dstWidth + 31) / 32, (dstHeight + 31) / 32, 1);
}
Pipeline pipeline = (Pipeline)_renderer.Pipeline;
Pipeline pipeline = (Pipeline)_gd.Pipeline;
pipeline.RestoreProgram();
pipeline.RestoreImages1And2();
@ -147,17 +145,17 @@ void main()
uint srcWidth = (uint)srcInfo.Width;
uint srcHeight = (uint)srcInfo.Height;
_api.UseProgram(GetNonMSToMSShader(srcInfo.BytesPerPixel));
_gd.Api.UseProgram(GetNonMSToMSShader(srcInfo.BytesPerPixel));
for (int z = 0; z < depth; z++)
{
_api.BindImageTexture(0, srcHandle, 0, false, srcLayer + z, BufferAccessARB.ReadOnly, (InternalFormat)GetFormat(srcInfo.BytesPerPixel));
_api.BindImageTexture(1, dstHandle, 0, false, dstLayer + z, BufferAccessARB.WriteOnly, (InternalFormat)GetFormat(dstInfo.BytesPerPixel));
_gd.Api.BindImageTexture(0, srcHandle, 0, false, srcLayer + z, BufferAccessARB.ReadOnly, (InternalFormat)GetFormat(srcInfo.BytesPerPixel));
_gd.Api.BindImageTexture(1, dstHandle, 0, false, dstLayer + z, BufferAccessARB.WriteOnly, (InternalFormat)GetFormat(dstInfo.BytesPerPixel));
_api.DispatchCompute((srcWidth + 31) / 32, (srcHeight + 31) / 32, 1);
_gd.Api.DispatchCompute((srcWidth + 31) / 32, (srcHeight + 31) / 32, 1);
}
Pipeline pipeline = (Pipeline)_renderer.Pipeline;
Pipeline pipeline = (Pipeline)_gd.Pipeline;
pipeline.RestoreProgram();
pipeline.RestoreImages1And2();
@ -185,9 +183,9 @@ void main()
// we need to create and bind a RGBA view for it to work.
if (texture.Info.Format == Format.R8G8B8A8Srgb)
{
uint handle = _api.GenTexture();
uint handle = _gd.Api.GenTexture();
_api.TextureView(
_gd.Api.TextureView(
handle,
texture.Info.Target.Convert(),
texture.Storage.Handle,
@ -207,7 +205,7 @@ void main()
{
if (info.Handle != handle)
{
_api.DeleteTexture(handle);
_gd.Api.DeleteTexture(handle);
}
}
@ -227,25 +225,25 @@ void main()
if (programHandles[index] == 0)
{
uint csHandle = _api.CreateShader(ShaderType.ComputeShader);
uint csHandle = _gd.Api.CreateShader(ShaderType.ComputeShader);
string format = new[] { "r8ui", "r16ui", "r32ui", "rg32ui", "rgba32ui" }[index];
_api.ShaderSource(csHandle, code.Replace("$FORMAT$", format));
_api.CompileShader(csHandle);
_gd.Api.ShaderSource(csHandle, code.Replace("$FORMAT$", format));
_gd.Api.CompileShader(csHandle);
uint programHandle = _api.CreateProgram();
uint programHandle = _gd.Api.CreateProgram();
_api.AttachShader(programHandle, csHandle);
_api.LinkProgram(programHandle);
_api.DetachShader(programHandle, csHandle);
_api.DeleteShader(csHandle);
_gd.Api.AttachShader(programHandle, csHandle);
_gd.Api.LinkProgram(programHandle);
_gd.Api.DetachShader(programHandle, csHandle);
_gd.Api.DeleteShader(csHandle);
_api.GetProgram(programHandle, ProgramPropertyARB.LinkStatus, out int status);
_gd.Api.GetProgram(programHandle, ProgramPropertyARB.LinkStatus, out int status);
if (status == 0)
{
throw new Exception(_api.GetProgramInfoLog(programHandle));
throw new Exception(_gd.Api.GetProgramInfoLog(programHandle));
}
programHandles[index] = programHandle;
@ -260,7 +258,7 @@ void main()
{
if (_msToNonMSProgramHandles[i] != 0)
{
_api.DeleteProgram(_msToNonMSProgramHandles[i]);
_gd.Api.DeleteProgram(_msToNonMSProgramHandles[i]);
_msToNonMSProgramHandles[i] = 0;
}
}
@ -269,7 +267,7 @@ void main()
{
if (_nonMSToMSProgramHandles[i] != 0)
{
_api.DeleteProgram(_nonMSToMSProgramHandles[i]);
_gd.Api.DeleteProgram(_nonMSToMSProgramHandles[i]);
_nonMSToMSProgramHandles[i] = 0;
}
}

View file

@ -11,20 +11,18 @@ namespace Ryujinx.Graphics.OpenGL.Image
public TextureCreateInfo Info { get; }
private readonly OpenGLRenderer _renderer;
private readonly GL _api;
private readonly OpenGLRenderer _gd;
private int _viewsCount;
internal ITexture DefaultView { get; private set; }
public TextureStorage(GL api, OpenGLRenderer renderer, TextureCreateInfo info)
public TextureStorage(OpenGLRenderer gd, TextureCreateInfo info)
{
_api = api;
_renderer = renderer;
_gd = gd;
Info = info;
Handle = _api.GenTexture();
Handle = _gd.Api.GenTexture();
CreateImmutableStorage();
}
@ -33,9 +31,9 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
TextureTarget target = Info.Target.Convert();
_api.ActiveTexture(TextureUnit.Texture0);
_gd.Api.ActiveTexture(TextureUnit.Texture0);
_api.BindTexture(target, Handle);
_gd.Api.BindTexture(target, Handle);
FormatInfo format = FormatTable.GetFormatInfo(Info.Format);
@ -55,7 +53,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
switch (Info.Target)
{
case Target.Texture1D:
_api.TexStorage1D(
_gd.Api.TexStorage1D(
TextureTarget.Texture1D,
levels,
internalFormat,
@ -63,7 +61,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
break;
case Target.Texture1DArray:
_api.TexStorage2D(
_gd.Api.TexStorage2D(
TextureTarget.Texture1DArray,
levels,
internalFormat,
@ -72,7 +70,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
break;
case Target.Texture2D:
_api.TexStorage2D(
_gd.Api.TexStorage2D(
TextureTarget.Texture2D,
levels,
internalFormat,
@ -81,7 +79,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
break;
case Target.Texture2DArray:
_api.TexStorage3D(
_gd.Api.TexStorage3D(
TextureTarget.Texture2DArray,
levels,
internalFormat,
@ -91,7 +89,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
break;
case Target.Texture2DMultisample:
_api.TexStorage2DMultisample(
_gd.Api.TexStorage2DMultisample(
TextureTarget.Texture2DMultisample,
(uint)Info.Samples,
internalFormat,
@ -101,7 +99,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
break;
case Target.Texture2DMultisampleArray:
_api.TexStorage3DMultisample(
_gd.Api.TexStorage3DMultisample(
TextureTarget.Texture2DMultisampleArray,
(uint)Info.Samples,
internalFormat,
@ -112,7 +110,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
break;
case Target.Texture3D:
_api.TexStorage3D(
_gd.Api.TexStorage3D(
TextureTarget.Texture3D,
levels,
internalFormat,
@ -122,7 +120,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
break;
case Target.Cubemap:
_api.TexStorage2D(
_gd.Api.TexStorage2D(
TextureTarget.TextureCubeMap,
levels,
internalFormat,
@ -131,7 +129,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
break;
case Target.CubemapArray:
_api.TexStorage3D(
_gd.Api.TexStorage3D(
TextureTarget.TextureCubeMapArray,
levels,
internalFormat,
@ -153,11 +151,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
return DefaultView;
}
public ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel)
public ITexture CreateView(TextureCreateInfo info, uint firstLayer, uint firstLevel)
{
IncrementViewsCount();
return new TextureView(_renderer, this, info, firstLayer, firstLevel);
return new TextureView(_gd, this, info, firstLayer, firstLevel);
}
private void IncrementViewsCount()
@ -189,7 +187,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
_viewsCount = 1; // When we are used again, we will have the default view.
_renderer.ResourcePool.AddTexture((TextureView)DefaultView);
_gd.ResourcePool.AddTexture((TextureView)DefaultView);
}
public void DeleteDefault()
@ -203,7 +201,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (Handle != 0)
{
_api.DeleteTexture(Handle);
_gd.Api.DeleteTexture(Handle);
Handle = 0;
}

View file

@ -9,23 +9,20 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
class TextureView : TextureBase, ITexture, ITextureInfo
{
private readonly OpenGLRenderer _renderer;
private readonly TextureStorage _parent;
public ITextureInfo Storage => _parent;
public int FirstLayer { get; private set; }
public int FirstLevel { get; private set; }
public uint FirstLayer { get; private set; }
public uint FirstLevel { get; private set; }
public TextureView(
OpenGLRenderer renderer,
OpenGLRenderer gd,
TextureStorage parent,
TextureCreateInfo info,
int firstLayer,
int firstLevel) : base(info)
uint firstLayer,
uint firstLevel) : base(gd, info)
{
_renderer = renderer;
_parent = parent;
FirstLayer = firstLayer;
@ -40,20 +37,20 @@ namespace Ryujinx.Graphics.OpenGL.Image
FormatInfo format = FormatTable.GetFormatInfo(Info.Format);
InternalFormat pixelInternalFormat;
SizedInternalFormat pixelInternalFormat;
if (format.IsCompressed)
{
pixelInternalFormat = (InternalFormat)format.PixelFormat;
pixelInternalFormat = (SizedInternalFormat)format.PixelFormat;
}
else
{
pixelInternalFormat = format.InternalFormat;
pixelInternalFormat = (SizedInternalFormat)format.InternalFormat;
}
int levels = Info.GetLevelsClamped();
uint levels = (uint)Info.GetLevelsClamped();
GL.TextureView(
_gd.Api.TextureView(
Handle,
target,
_parent.Handle,
@ -61,11 +58,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
FirstLevel,
levels,
FirstLayer,
Info.GetLayers());
(uint)Info.GetLayers());
GL.ActiveTexture(TextureUnit.Texture0);
_gd.Api.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(target, Handle);
_gd.Api.BindTexture(target, Handle);
int[] swizzleRgba = new int[]
{
@ -91,20 +88,20 @@ namespace Ryujinx.Graphics.OpenGL.Image
(swizzleRgba[2], swizzleRgba[0]) = (swizzleRgba[0], swizzleRgba[2]);
}
GL.TexParameter(target, TextureParameterName.TextureSwizzleRgba, swizzleRgba);
_gd.Api.TexParameter(target, TextureParameterName.TextureSwizzleRgba, swizzleRgba);
int maxLevel = levels - 1;
uint maxLevel = levels - 1;
if (maxLevel < 0)
{
maxLevel = 0;
}
GL.TexParameter(target, TextureParameterName.TextureMaxLevel, maxLevel);
GL.TexParameter(target, TextureParameterName.DepthStencilTextureMode, (int)Info.DepthStencilMode.Convert());
_gd.Api.TexParameter(target, TextureParameterName.TextureMaxLevel, maxLevel);
_gd.Api.TexParameter(target, TextureParameterName.DepthStencilTextureMode, (int)Info.DepthStencilMode.Convert());
}
public ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel)
public ITexture CreateView(TextureCreateInfo info, uint firstLayer, uint firstLevel)
{
firstLayer += FirstLayer;
firstLevel += FirstLevel;
@ -112,7 +109,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
return _parent.CreateView(info, firstLayer, firstLevel);
}
public void CopyTo(ITexture destination, int firstLayer, int firstLevel)
public void CopyTo(ITexture destination, uint firstLayer, uint firstLevel)
{
TextureView destinationView = (TextureView)destination;
@ -121,24 +118,24 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (dstIsMultisample != srcIsMultisample && Info.Format.IsDepthOrStencil())
{
int layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
uint layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
CopyWithBlitForDepthMS(destinationView, 0, firstLayer, layers);
}
else if (!dstIsMultisample && srcIsMultisample)
{
int layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
_renderer.TextureCopyMS.CopyMSToNonMS(this, destinationView, 0, firstLayer, layers);
uint layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
_gd.TextureCopyMS.CopyMSToNonMS(this, destinationView, 0, firstLayer, layers);
}
else if (dstIsMultisample && !srcIsMultisample)
{
int layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
_renderer.TextureCopyMS.CopyNonMSToMS(this, destinationView, 0, firstLayer, layers);
uint layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
_gd.TextureCopyMS.CopyNonMSToMS(this, destinationView, 0, firstLayer, layers);
}
else if (destinationView.Info.BytesPerPixel != Info.BytesPerPixel)
{
int layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
int levels = Math.Min(Info.Levels, destinationView.Info.Levels - firstLevel);
_renderer.TextureCopyIncompatible.CopyIncompatibleFormats(this, destinationView, 0, firstLayer, 0, firstLevel, layers, levels);
_gd.TextureCopyIncompatible.CopyIncompatibleFormats(this, destinationView, 0, firstLayer, 0, firstLevel, layers, levels);
}
else if (destinationView.Format.IsDepthOrStencil() != Format.IsDepthOrStencil())
{
@ -158,13 +155,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
for (int layer = 0; layer < layers; layer++)
{
_renderer.TextureCopy.PboCopy(this, destinationView, 0, firstLayer + layer, 0, firstLevel + level, minWidth, minHeight);
_gd.TextureCopy.PboCopy(this, destinationView, 0, firstLayer + layer, 0, firstLevel + level, minWidth, minHeight);
}
}
}
else
{
_renderer.TextureCopy.CopyUnscaled(this, destinationView, 0, firstLayer, 0, firstLevel);
_gd.TextureCopy.CopyUnscaled(this, destinationView, 0, firstLayer, 0, firstLevel);
}
}
@ -181,30 +178,30 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
else if (!dstIsMultisample && srcIsMultisample)
{
_renderer.TextureCopyMS.CopyMSToNonMS(this, destinationView, srcLayer, dstLayer, 1);
_gd.TextureCopyMS.CopyMSToNonMS(this, destinationView, srcLayer, dstLayer, 1);
}
else if (dstIsMultisample && !srcIsMultisample)
{
_renderer.TextureCopyMS.CopyNonMSToMS(this, destinationView, srcLayer, dstLayer, 1);
_gd.TextureCopyMS.CopyNonMSToMS(this, destinationView, srcLayer, dstLayer, 1);
}
else if (destinationView.Info.BytesPerPixel != Info.BytesPerPixel)
{
_renderer.TextureCopyIncompatible.CopyIncompatibleFormats(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
_gd.TextureCopyIncompatible.CopyIncompatibleFormats(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
}
else if (destinationView.Format.IsDepthOrStencil() != Format.IsDepthOrStencil())
{
int minWidth = Math.Min(Width, destinationView.Width);
int minHeight = Math.Min(Height, destinationView.Height);
_renderer.TextureCopy.PboCopy(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, minWidth, minHeight);
_gd.TextureCopy.PboCopy(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, minWidth, minHeight);
}
else
{
_renderer.TextureCopy.CopyUnscaled(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
_gd.TextureCopy.CopyUnscaled(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
}
}
private void CopyWithBlitForDepthMS(TextureView destinationView, int srcLayer, int dstLayer, int layers)
private void CopyWithBlitForDepthMS(TextureView destinationView, int srcLayer, int dstLayer, uint layers)
{
// This is currently used for multisample <-> non-multisample copies.
// We can't do that with compute because it's not possible to write depth textures on compute.
@ -218,7 +215,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (destinationView.Target.IsMultisample())
{
TextureView intermmediate = _renderer.TextureCopy.IntermediatePool.GetOrCreateWithAtLeast(
TextureView intermmediate = _gd.TextureCopy.IntermediatePool.GetOrCreateWithAtLeast(
Info.Target,
Info.BlockWidth,
Info.BlockHeight,
@ -230,8 +227,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
1,
1);
_renderer.TextureCopy.Copy(this, intermmediate, srcRegion, dstRegion, false);
_renderer.TextureCopy.Copy(intermmediate, destinationView, dstRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, layers, 1);
_gd.TextureCopy.Copy(this, intermmediate, srcRegion, dstRegion, false);
_gd.TextureCopy.Copy(intermmediate, destinationView, dstRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, layers, 1);
}
else
{
@ -242,7 +239,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
_ => Target,
};
TextureView intermmediate = _renderer.TextureCopy.IntermediatePool.GetOrCreateWithAtLeast(
TextureView intermmediate = _gd.TextureCopy.IntermediatePool.GetOrCreateWithAtLeast(
target,
Info.BlockWidth,
Info.BlockHeight,
@ -254,14 +251,14 @@ namespace Ryujinx.Graphics.OpenGL.Image
1,
1);
_renderer.TextureCopy.Copy(this, intermmediate, srcRegion, srcRegion, false);
_renderer.TextureCopy.Copy(intermmediate, destinationView, srcRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, layers, 1);
_gd.TextureCopy.Copy(this, intermmediate, srcRegion, srcRegion, false);
_gd.TextureCopy.Copy(intermmediate, destinationView, srcRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, layers, 1);
}
}
public void CopyTo(ITexture destination, Extents2D srcRegion, Extents2D dstRegion, bool linearFilter)
{
_renderer.TextureCopy.Copy(this, (TextureView)destination, srcRegion, dstRegion, linearFilter);
_gd.TextureCopy.Copy(this, (TextureView)destination, srcRegion, dstRegion, linearFilter);
}
public unsafe PinnedSpan<byte> GetData()
@ -278,11 +275,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (HwCapabilities.UsePersistentBufferForFlush)
{
data = _renderer.PersistentBuffers.Default.GetTextureData(this, size);
data = _gd.PersistentBuffers.Default.GetTextureData(this, size);
}
else
{
IntPtr target = _renderer.PersistentBuffers.Default.GetHostArray(size);
IntPtr target = _gd.PersistentBuffers.Default.GetHostArray(size);
WriteTo(target);
@ -303,11 +300,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (HwCapabilities.UsePersistentBufferForFlush)
{
return PinnedSpan<byte>.UnsafeFromSpan(_renderer.PersistentBuffers.Default.GetTextureData(this, size, layer, level));
return PinnedSpan<byte>.UnsafeFromSpan(_gd.PersistentBuffers.Default.GetTextureData(this, size, layer, level));
}
else
{
IntPtr target = _renderer.PersistentBuffers.Default.GetHostArray(size);
IntPtr target = _gd.PersistentBuffers.Default.GetHostArray(size);
int offset = WriteTo2D(target, layer, level);
@ -322,7 +319,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
throw new NotSupportedException("Stride conversion for texture copy to buffer not supported.");
}
GL.BindBuffer(BufferTargetARB.PixelPackBuffer, range.Handle.ToInt32());
_gd.Api.BindBuffer(BufferTargetARB.PixelPackBuffer, range.Handle.ToUInt32());
FormatInfo format = FormatTable.GetFormatInfo(Info.Format);
if (format.PixelFormat == PixelFormat.DepthStencil)
@ -334,7 +331,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
Debug.Assert(offset == 0);
GL.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
_gd.Api.BindBuffer(BufferTargetARB.PixelPackBuffer, 0);
}
public void WriteToPbo(int offset, bool forceBgra)
@ -367,15 +364,15 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (format.IsCompressed)
{
GL.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, Math.Max(1, Info.Width >> level), Math.Max(1, Info.Height >> level), 1, mipSize, data);
}
else if (format.PixelFormat != PixelFormat.DepthStencil)
{
GL.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, Math.Max(1, Info.Width >> level), Math.Max(1, Info.Height >> level), 1, pixelFormat, pixelType, mipSize, data);
}
else
{
GL.GetTexImage(target, level, pixelFormat, pixelType, data);
_gd.Api.GetTexImage(target, level, pixelFormat, pixelType, data);
// The GL function returns all layers. Must return the offset of the layer we're interested in.
return target switch
@ -436,11 +433,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (format.IsCompressed)
{
GL.GetCompressedTexImage(target + face, level, data + faceOffset);
_gd.Api.GetCompressedTexImage(target + face, level, data + faceOffset);
}
else
{
GL.GetTexImage(target + face, level, pixelFormat, pixelType, data + faceOffset);
_gd.Api.GetTexImage(target + face, level, pixelFormat, pixelType, data + faceOffset);
}
}
@ -548,22 +545,22 @@ namespace Ryujinx.Graphics.OpenGL.Image
case Target.Texture1D:
if (format.IsCompressed)
{
GL.CompressedTexSubImage1D(
_gd.Api.CompressedTexSubImage1D(
target,
level,
x,
width,
format.PixelFormat,
mipSize,
(uint)width,
(InternalFormat)format.PixelFormat,
(uint)mipSize,
data);
}
else
{
GL.TexSubImage1D(
_gd.Api.TexSubImage1D(
target,
level,
x,
width,
(uint)width,
format.PixelFormat,
format.PixelType,
data);
@ -573,25 +570,25 @@ namespace Ryujinx.Graphics.OpenGL.Image
case Target.Texture1DArray:
if (format.IsCompressed)
{
GL.CompressedTexSubImage2D(
_gd.Api.CompressedTexSubImage2D(
target,
level,
x,
layer,
width,
(uint)width,
1,
format.PixelFormat,
mipSize,
(InternalFormat)format.PixelFormat,
(uint)mipSize,
data);
}
else
{
GL.TexSubImage2D(
_gd.Api.TexSubImage2D(
target,
level,
x,
layer,
width,
(uint)width,
1,
format.PixelFormat,
format.PixelType,
@ -602,26 +599,26 @@ namespace Ryujinx.Graphics.OpenGL.Image
case Target.Texture2D:
if (format.IsCompressed)
{
GL.CompressedTexSubImage2D(
_gd.Api.CompressedTexSubImage2D(
target,
level,
x,
y,
width,
height,
format.PixelFormat,
mipSize,
(uint)width,
(uint)height,
(InternalFormat)format.PixelFormat,
(uint)mipSize,
data);
}
else
{
GL.TexSubImage2D(
_gd.Api.TexSubImage2D(
target,
level,
x,
y,
width,
height,
(uint)width,
(uint)height,
format.PixelFormat,
format.PixelType,
data);
@ -633,29 +630,29 @@ namespace Ryujinx.Graphics.OpenGL.Image
case Target.CubemapArray:
if (format.IsCompressed)
{
GL.CompressedTexSubImage3D(
_gd.Api.CompressedTexSubImage3D(
target,
level,
x,
y,
layer,
width,
height,
(uint)width,
(uint)height,
1,
format.PixelFormat,
mipSize,
(InternalFormat)format.PixelFormat,
(uint)mipSize,
data);
}
else
{
GL.TexSubImage3D(
_gd.Api.TexSubImage3D(
target,
level,
x,
y,
layer,
width,
height,
(uint)width,
(uint)height,
1,
format.PixelFormat,
format.PixelType,
@ -666,26 +663,26 @@ namespace Ryujinx.Graphics.OpenGL.Image
case Target.Cubemap:
if (format.IsCompressed)
{
GL.CompressedTexSubImage2D(
_gd.Api.CompressedTexSubImage2D(
TextureTarget.TextureCubeMapPositiveX + layer,
level,
x,
y,
width,
height,
format.PixelFormat,
mipSize,
(uint)width,
(uint)height,
(InternalFormat)format.PixelFormat,
(uint)mipSize,
data);
}
else
{
GL.TexSubImage2D(
_gd.Api.TexSubImage2D(
TextureTarget.TextureCubeMapPositiveX + layer,
level,
x,
y,
width,
height,
(uint)width,
(uint)height,
format.PixelFormat,
format.PixelType,
data);
@ -697,13 +694,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
private void ReadFrom(IntPtr data, int size)
{
TextureTarget target = Target.Convert();
int baseLevel = 0;
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)
{
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(target, Storage.Handle);
_gd.Api.ActiveTexture(TextureUnit.Texture0);
_gd.Api.BindTexture(target, Storage.Handle);
baseLevel = FirstLevel;
}
else
@ -736,7 +733,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
case Target.Texture1D:
if (format.IsCompressed)
{
GL.CompressedTexSubImage1D(
_gd.Api.CompressedTexSubImage1D(
target,
level,
0,
@ -747,7 +744,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
else
{
GL.TexSubImage1D(
_gd.Api.TexSubImage1D(
target,
level,
0,
@ -762,7 +759,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
case Target.Texture2D:
if (format.IsCompressed)
{
GL.CompressedTexSubImage2D(
_gd.Api.CompressedTexSubImage2D(
target,
level,
0,
@ -775,7 +772,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
else
{
GL.TexSubImage2D(
_gd.Api.TexSubImage2D(
target,
level,
0,
@ -793,7 +790,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
case Target.CubemapArray:
if (format.IsCompressed)
{
GL.CompressedTexSubImage3D(
_gd.Api.CompressedTexSubImage3D(
target,
level,
0,
@ -808,7 +805,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
else
{
GL.TexSubImage3D(
_gd.Api.TexSubImage3D(
target,
level,
0,
@ -830,7 +827,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
if (format.IsCompressed)
{
GL.CompressedTexSubImage2D(
_gd.Api.CompressedTexSubImage2D(
TextureTarget.TextureCubeMapPositiveX + face,
baseLevel + level,
0,
@ -843,7 +840,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
else
{
GL.TexSubImage2D(
_gd.Api.TexSubImage2D(
TextureTarget.TextureCubeMapPositiveX + face,
baseLevel + level,
0,
@ -880,7 +877,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
{
if (Handle != 0)
{
GL.DeleteTexture(Handle);
_gd.Api.DeleteTexture(Handle);
Handle = 0;
}

View file

@ -6,12 +6,13 @@ using Ryujinx.Graphics.OpenGL.Image;
using Ryujinx.Graphics.OpenGL.Queries;
using Ryujinx.Graphics.Shader.Translation;
using System;
using Sampler = Ryujinx.Graphics.OpenGL.Image.Sampler;
namespace Ryujinx.Graphics.OpenGL
{
public sealed class OpenGLRenderer : IRenderer
{
private GL _api;
public readonly GL Api;
private readonly Pipeline _pipeline;
public IPipeline Pipeline => _pipeline;
@ -44,10 +45,11 @@ namespace Ryujinx.Graphics.OpenGL
public bool PreferThreading => true;
public OpenGLRenderer()
public OpenGLRenderer(GL api)
{
Api = api;
_pipeline = new Pipeline();
_counters = new Counters();
_counters = new Counters(Api);
_window = new Window(this);
_textureCopy = new TextureCopy(this);
_backgroundTextureCopy = new TextureCopy(this);
@ -64,7 +66,7 @@ namespace Ryujinx.Graphics.OpenGL
if (access.HasFlag(BufferAccess.FlushPersistent))
{
BufferHandle handle = Buffer.CreatePersistent(_api, size);
BufferHandle handle = Buffer.CreatePersistent(Api, size);
PersistentBuffers.Map(handle, size);
@ -72,7 +74,7 @@ namespace Ryujinx.Graphics.OpenGL
}
else
{
return Buffer.Create(_api, size);
return Buffer.Create(Api, size);
}
}
@ -93,7 +95,7 @@ namespace Ryujinx.Graphics.OpenGL
public IImageArray CreateImageArray(int size, bool isBuffer)
{
return new ImageArray(size);
return new ImageArray(Api, size);
}
public IProgram CreateProgram(ShaderSource[] shaders, ShaderInfo info)
@ -103,7 +105,7 @@ namespace Ryujinx.Graphics.OpenGL
public ISampler CreateSampler(SamplerCreateInfo info)
{
return new Sampler(info);
return new Sampler(Api, info);
}
public ITexture CreateTexture(TextureCreateInfo info)
@ -120,14 +122,14 @@ namespace Ryujinx.Graphics.OpenGL
public ITextureArray CreateTextureArray(int size, bool isBuffer)
{
return new TextureArray(size);
return new TextureArray(Api, size);
}
public void DeleteBuffer(BufferHandle buffer)
{
PersistentBuffers.Unmap(buffer);
Buffer.Delete(buffer);
Buffer.Delete(Api, buffer);
}
public HardwareInfo GetHardwareInfo()
@ -203,7 +205,7 @@ namespace Ryujinx.Graphics.OpenGL
public void SetBufferData(BufferHandle buffer, int offset, ReadOnlySpan<byte> data)
{
Buffer.SetData(buffer, offset, data);
Buffer.SetData(Api, buffer, offset, data);
}
public void UpdateCounters()
@ -224,7 +226,7 @@ namespace Ryujinx.Graphics.OpenGL
public void Initialize(GraphicsDebugLevel glLogLevel)
{
Debugger.Initialize(glLogLevel);
Debugger.Initialize(Api, glLogLevel);
PrintGpuInformation();
@ -239,14 +241,14 @@ namespace Ryujinx.Graphics.OpenGL
// 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.
GL.ClampColor(ClampColorTargetARB.FragmentColorArb, ClampColorModeARB.False);
Api.ClampColor(ClampColorTargetARB.FragmentColorArb, ClampColorModeARB.False);
}
private void PrintGpuInformation()
{
GpuVendor = GL.GetString(StringName.Vendor);
GpuRenderer = GL.GetString(StringName.Renderer);
GpuVersion = GL.GetString(StringName.Version);
GpuVendor = Api.GetString(StringName.Vendor);
GpuRenderer = Api.GetString(StringName.Renderer);
GpuVersion = Api.GetString(StringName.Version);
Logger.Notice.Print(LogClass.Gpu, $"{GpuVendor} {GpuRenderer} ({GpuVersion})");
}

View file

@ -52,7 +52,7 @@ namespace Ryujinx.Graphics.OpenGL
class PersistentBuffer : IDisposable
{
private IntPtr _bufferMap;
private int _copyBufferHandle;
private uint _copyBufferHandle;
private int _copyBufferSize;
private byte[] _data;
@ -140,7 +140,7 @@ namespace Ryujinx.Graphics.OpenGL
{
EnsureBuffer(size);
GL.BindBuffer(BufferTargetARB.CopyReadBuffer, buffer.ToInt32());
GL.BindBuffer(BufferTargetARB.CopyReadBuffer, buffer.ToUInt32());
GL.BindBuffer(BufferTargetARB.CopyWriteBuffer, _copyBufferHandle);
GL.CopyBufferSubData(BufferTargetARB.CopyReadBuffer, BufferTargetARB.CopyWriteBuffer, (IntPtr)offset, IntPtr.Zero, size);

File diff suppressed because it is too large Load diff

View file

@ -36,7 +36,7 @@ namespace Ryujinx.Graphics.OpenGL
{
Handle = GL.CreateProgram();
GL.ProgramParameter(Handle, ProgramParameterName.ProgramBinaryRetrievableHint, 1);
GL.ProgramParameter(Handle, ProgramParameterPName.BinaryRetrievableHint, 1);
_shaderHandles = new int[shaders.Length];
bool hasFragmentShader = false;

View file

@ -15,23 +15,29 @@ namespace Ryujinx.Graphics.OpenGL
}
private ulong _firstHandle = 0;
private static ClientWaitSyncFlags SyncFlags => HwCapabilities.RequiresSyncFlush ? ClientWaitSyncFlags.None : ClientWaitSyncFlags.SyncFlushCommandsBit;
private static SyncBehaviorFlags SyncFlags => HwCapabilities.RequiresSyncFlush ? SyncBehaviorFlags.None : SyncBehaviorFlags.SyncFlushCommandsBit;
private readonly List<SyncHandle> _handles = new();
private readonly GL _api;
public Sync(GL api)
{
_api = api;
}
public void Create(ulong id)
{
SyncHandle handle = new()
{
ID = id,
Handle = GL.FenceSync(SyncCondition.SyncGpuCommandsComplete, WaitSyncFlags.None),
Handle = _api.FenceSync(SyncCondition.SyncGpuCommandsComplete, SyncBehaviorFlags.None),
};
if (HwCapabilities.RequiresSyncFlush)
{
// Force commands to flush up to the syncpoint.
GL.ClientWaitSync(handle.Handle, ClientWaitSyncFlags.SyncFlushCommandsBit, 0);
_api.ClientWaitSync(handle.Handle, SyncBehaviorFlags.SyncFlushCommandsBit, 0);
}
lock (_handles)
@ -57,9 +63,9 @@ namespace Ryujinx.Graphics.OpenGL
if (handle.ID > lastHandle)
{
WaitSyncStatus syncResult = GL.ClientWaitSync(handle.Handle, SyncFlags, 0);
GLEnum syncResult = _api.ClientWaitSync(handle.Handle, SyncFlags, 0);
if (syncResult == WaitSyncStatus.AlreadySignaled)
if (syncResult == GLEnum.AlreadySignaled)
{
lastHandle = handle.ID;
}
@ -101,9 +107,9 @@ namespace Ryujinx.Graphics.OpenGL
return;
}
WaitSyncStatus syncResult = GL.ClientWaitSync(result.Handle, SyncFlags, 1000000000);
GLEnum syncResult = _api.ClientWaitSync(result.Handle, SyncFlags, 1000000000);
if (syncResult == WaitSyncStatus.TimeoutExpired)
if (syncResult == GLEnum.TimeoutExpired)
{
Logger.Error?.PrintMsg(LogClass.Gpu, $"GL Sync Object {result.ID} failed to signal within 1000ms. Continuing...");
}
@ -128,9 +134,9 @@ namespace Ryujinx.Graphics.OpenGL
break;
}
WaitSyncStatus syncResult = GL.ClientWaitSync(first.Handle, SyncFlags, 0);
GLEnum syncResult = _api.ClientWaitSync(first.Handle, SyncFlags, 0);
if (syncResult == WaitSyncStatus.AlreadySignaled)
if (syncResult == GLEnum.AlreadySignaled)
{
// Delete the sync object.
lock (_handles)
@ -139,7 +145,7 @@ namespace Ryujinx.Graphics.OpenGL
{
_firstHandle = first.ID + 1;
_handles.RemoveAt(0);
GL.DeleteSync(first.Handle);
_api.DeleteSync(first.Handle);
first.Handle = IntPtr.Zero;
}
}
@ -160,7 +166,7 @@ namespace Ryujinx.Graphics.OpenGL
{
lock (handle)
{
GL.DeleteSync(handle.Handle);
_api.DeleteSync(handle.Handle);
handle.Handle = IntPtr.Zero;
}
}

View file

@ -9,14 +9,14 @@ namespace Ryujinx.Graphics.OpenGL
{
class Window : IWindow, IDisposable
{
private readonly OpenGLRenderer _renderer;
private readonly OpenGLRenderer _gd;
private bool _initialized;
private int _width;
private int _height;
private bool _updateSize;
private int _copyFramebufferHandle;
private uint _copyFramebufferHandle;
private IPostProcessingEffect _antiAliasing;
private IScalingFilter _scalingFilter;
private bool _isLinear;
@ -32,26 +32,26 @@ namespace Ryujinx.Graphics.OpenGL
internal bool ScreenCaptureRequested { get; set; }
public Window(OpenGLRenderer renderer)
public Window(OpenGLRenderer gd)
{
_renderer = renderer;
_gd = gd;
}
public void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback)
{
GL.Disable(EnableCap.FramebufferSrgb);
_gd.Api.Disable(EnableCap.FramebufferSrgb);
(int oldDrawFramebufferHandle, int oldReadFramebufferHandle) = ((Pipeline)_renderer.Pipeline).GetBoundFramebuffers();
(uint oldDrawFramebufferHandle, uint oldReadFramebufferHandle) = ((Pipeline)_gd.Pipeline).GetBoundFramebuffers();
CopyTextureToFrameBufferRGB(0, GetCopyFramebufferHandleLazy(), (TextureView)texture, crop, swapBuffersCallback);
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
_gd.Api.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
_gd.Api.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
GL.Enable(EnableCap.FramebufferSrgb);
_gd.Api.Enable(EnableCap.FramebufferSrgb);
// Restore unpack alignment to 4, as performance overlays such as RTSS may change this to load their resources.
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 4);
_gd.Api.PixelStore(PixelStoreParameter.UnpackAlignment, 4);
}
public void ChangeVSyncMode(bool vsyncEnabled) { }
@ -64,12 +64,12 @@ namespace Ryujinx.Graphics.OpenGL
_updateSize = true;
}
private void CopyTextureToFrameBufferRGB(int drawFramebuffer, int readFramebuffer, TextureView view, ImageCrop crop, Action swapBuffersCallback)
private void CopyTextureToFrameBufferRGB(uint drawFramebuffer, uint readFramebuffer, TextureView view, ImageCrop crop, Action swapBuffersCallback)
{
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, drawFramebuffer);
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, readFramebuffer);
_gd.Api.BindFramebuffer(FramebufferTarget.DrawFramebuffer, drawFramebuffer);
_gd.Api.BindFramebuffer(FramebufferTarget.ReadFramebuffer, readFramebuffer);
TextureView viewConverted = view.Format.IsBgr() ? _renderer.TextureCopy.BgraSwap(view) : view;
TextureView viewConverted = view.Format.IsBgr() ? _gd.TextureCopy.BgraSwap(view) : view;
UpdateEffect();
@ -81,7 +81,7 @@ namespace Ryujinx.Graphics.OpenGL
if (viewConverted.Format.IsBgr())
{
var swappedView = _renderer.TextureCopy.BgraSwap(viewConverted);
var swappedView = _gd.TextureCopy.BgraSwap(viewConverted);
viewConverted?.Dispose();
@ -94,21 +94,21 @@ namespace Ryujinx.Graphics.OpenGL
}
}
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, drawFramebuffer);
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, readFramebuffer);
_gd.Api.BindFramebuffer(FramebufferTarget.DrawFramebuffer, drawFramebuffer);
_gd.Api.BindFramebuffer(FramebufferTarget.ReadFramebuffer, readFramebuffer);
GL.FramebufferTexture(
_gd.Api.FramebufferTexture(
FramebufferTarget.ReadFramebuffer,
FramebufferAttachment.ColorAttachment0,
viewConverted.Handle,
0);
GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
_gd.Api.ReadBuffer(ReadBufferMode.ColorAttachment0);
GL.Disable(EnableCap.RasterizerDiscard);
GL.Disable(IndexedEnableCap.ScissorTest, 0);
_gd.Api.Disable(EnableCap.RasterizerDiscard);
_gd.Api.Disable(EnableCap.ScissorTest, 0);
GL.Clear(ClearBufferMask.ColorBufferBit);
_gd.Api.Clear(ClearBufferMask.ColorBufferBit);
int srcX0, srcX1, srcY0, srcY1;
@ -151,7 +151,7 @@ namespace Ryujinx.Graphics.OpenGL
if (ScreenCaptureRequested)
{
CaptureFrame(srcX0, srcY0, srcX1, srcY1, view.Format.IsBgr(), crop.FlipX, crop.FlipY);
CaptureFrame(srcX0, srcY0, (uint)srcX1, (uint)srcY1, view.Format.IsBgr(), crop.FlipX, crop.FlipY);
ScreenCaptureRequested = false;
}
@ -185,14 +185,14 @@ namespace Ryujinx.Graphics.OpenGL
srcX1 = dstX1;
srcY1 = dstY1;
GL.FramebufferTexture(
_gd.Api.FramebufferTexture(
FramebufferTarget.ReadFramebuffer,
FramebufferAttachment.ColorAttachment0,
_upscaledTexture.Handle,
0);
}
GL.BlitFramebuffer(
_gd.Api.BlitFramebuffer(
srcX0,
srcY0,
srcX1,
@ -205,26 +205,26 @@ namespace Ryujinx.Graphics.OpenGL
_isLinear ? BlitFramebufferFilter.Linear : BlitFramebufferFilter.Nearest);
// Remove Alpha channel
GL.ColorMask(false, false, false, true);
GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
GL.Clear(ClearBufferMask.ColorBufferBit);
_gd.Api.ColorMask(false, false, false, true);
_gd.Api.ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
_gd.Api.Clear(ClearBufferMask.ColorBufferBit);
for (int i = 0; i < Constants.MaxRenderTargets; i++)
{
((Pipeline)_renderer.Pipeline).RestoreComponentMask(i);
((Pipeline)_gd.Pipeline).RestoreComponentMask(i);
}
// Set clip control, viewport and the framebuffer to the output to placate overlays and OBS capture.
GL.ClipControl(ClipOrigin.LowerLeft, ClipDepthMode.NegativeOneToOne);
GL.Viewport(0, 0, _width, _height);
GL.BindFramebuffer(FramebufferTarget.Framebuffer, drawFramebuffer);
_gd.Api.ClipControl(ClipControlOrigin.LowerLeft, ClipControlDepth.NegativeOneToOne);
_gd.Api.Viewport(0, 0, (uint)_width, (uint)_height);
_gd.Api.BindFramebuffer(FramebufferTarget.Framebuffer, drawFramebuffer);
swapBuffersCallback();
((Pipeline)_renderer.Pipeline).RestoreClipControl();
((Pipeline)_renderer.Pipeline).RestoreScissor0Enable();
((Pipeline)_renderer.Pipeline).RestoreRasterizerDiscard();
((Pipeline)_renderer.Pipeline).RestoreViewport0();
((Pipeline)_gd.Pipeline).RestoreClipControl();
((Pipeline)_gd.Pipeline).RestoreScissor0Enable();
((Pipeline)_gd.Pipeline).RestoreRasterizerDiscard();
((Pipeline)_gd.Pipeline).RestoreViewport0();
if (viewConverted != view)
{
@ -232,13 +232,13 @@ namespace Ryujinx.Graphics.OpenGL
}
}
private int GetCopyFramebufferHandleLazy()
private uint GetCopyFramebufferHandleLazy()
{
int handle = _copyFramebufferHandle;
uint handle = _copyFramebufferHandle;
if (handle == 0)
{
handle = GL.GenFramebuffer();
handle = _gd.Api.GenFramebuffer();
_copyFramebufferHandle = handle;
}
@ -252,14 +252,14 @@ namespace Ryujinx.Graphics.OpenGL
_initialized = true;
}
public void CaptureFrame(int x, int y, int width, int height, bool isBgra, bool flipX, bool flipY)
public void CaptureFrame(int x, int y, uint width, uint height, bool isBgra, bool flipX, bool flipY)
{
long size = Math.Abs(4 * width * height);
long size = 4 * width * height;
byte[] bitmap = new byte[size];
GL.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, bitmap);
_renderer.OnScreenCaptured(new ScreenCaptureImageInfo(width, height, isBgra, bitmap, flipX, flipY));
_gd.OnScreenCaptured(new ScreenCaptureImageInfo((int)width, (int)height, isBgra, bitmap, flipX, flipY));
}
public void Dispose()
@ -273,7 +273,7 @@ namespace Ryujinx.Graphics.OpenGL
if (_copyFramebufferHandle != 0)
{
GL.DeleteFramebuffer(_copyFramebufferHandle);
_gd.Api.DeleteFramebuffer(_copyFramebufferHandle);
_copyFramebufferHandle = 0;
}
@ -319,7 +319,7 @@ namespace Ryujinx.Graphics.OpenGL
{
case AntiAliasing.Fxaa:
_antiAliasing?.Dispose();
_antiAliasing = new FxaaPostProcessingEffect(_renderer);
_antiAliasing = new FxaaPostProcessingEffect(_gd);
break;
case AntiAliasing.None:
_antiAliasing?.Dispose();
@ -337,7 +337,7 @@ namespace Ryujinx.Graphics.OpenGL
else
{
_antiAliasing?.Dispose();
_antiAliasing = new SmaaPostProcessingEffect(_renderer, quality);
_antiAliasing = new SmaaPostProcessingEffect(_gd, quality);
}
break;
}
@ -368,7 +368,7 @@ namespace Ryujinx.Graphics.OpenGL
if (_scalingFilter is not FsrScalingFilter)
{
_scalingFilter?.Dispose();
_scalingFilter = new FsrScalingFilter(_renderer);
_scalingFilter = new FsrScalingFilter(_gd);
}
_isLinear = false;
_scalingFilter.Level = _scalingFilterLevel;
@ -401,7 +401,7 @@ namespace Ryujinx.Graphics.OpenGL
SwizzleComponent.Alpha);
_isBgra = forceBgra;
_upscaledTexture = _renderer.CreateTexture(info) as TextureView;
_upscaledTexture = _gd.CreateTexture(info) as TextureView;
}
public void SetScalingFilterLevel(float level)