aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Ryujinx.Graphics.GAL/BufferRange.cs2
-rw-r--r--Ryujinx.Graphics.GAL/IPipeline.cs2
-rw-r--r--Ryujinx.Graphics.Gpu/Memory/BufferManager.cs11
-rw-r--r--Ryujinx.Graphics.OpenGL/Buffer.cs11
-rw-r--r--Ryujinx.Graphics.OpenGL/Constants.cs1
-rw-r--r--Ryujinx.Graphics.OpenGL/Pipeline.cs87
-rw-r--r--Ryujinx.Graphics.OpenGL/Program.cs6
7 files changed, 91 insertions, 29 deletions
diff --git a/Ryujinx.Graphics.GAL/BufferRange.cs b/Ryujinx.Graphics.GAL/BufferRange.cs
index 34d523f9..9a030c80 100644
--- a/Ryujinx.Graphics.GAL/BufferRange.cs
+++ b/Ryujinx.Graphics.GAL/BufferRange.cs
@@ -4,7 +4,7 @@ namespace Ryujinx.Graphics.GAL
{
private static readonly BufferRange _empty = new BufferRange(BufferHandle.Null, 0, 0);
- public BufferRange Empty => _empty;
+ public static BufferRange Empty => _empty;
public BufferHandle Handle { get; }
diff --git a/Ryujinx.Graphics.GAL/IPipeline.cs b/Ryujinx.Graphics.GAL/IPipeline.cs
index a7f13893..818712c3 100644
--- a/Ryujinx.Graphics.GAL/IPipeline.cs
+++ b/Ryujinx.Graphics.GAL/IPipeline.cs
@@ -75,7 +75,7 @@ namespace Ryujinx.Graphics.GAL
void SetTexture(int index, ShaderStage stage, ITexture texture);
- void SetTransformFeedbackBuffer(int index, BufferRange buffer);
+ void SetTransformFeedbackBuffers(ReadOnlySpan<BufferRange> buffers);
void SetUniformBuffer(int index, ShaderStage stage, BufferRange buffer);
void SetUserClipDistance(int index, bool enableClip);
diff --git a/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs b/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs
index ee1be74b..eec545b9 100644
--- a/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs
+++ b/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs
@@ -587,21 +587,22 @@ namespace Ryujinx.Graphics.Gpu.Memory
{
_transformFeedbackBuffersDirty = false;
+ Span<BufferRange> tfbs = stackalloc BufferRange[Constants.TotalTransformFeedbackBuffers];
+
for (int index = 0; index < Constants.TotalTransformFeedbackBuffers; index++)
{
BufferBounds tfb = _transformFeedbackBuffers[index];
if (tfb.Address == 0)
{
- _context.Renderer.Pipeline.SetTransformFeedbackBuffer(index, new BufferRange(BufferHandle.Null, 0, 0));
-
+ tfbs[index] = BufferRange.Empty;
continue;
}
- BufferRange buffer = GetBufferRange(tfb.Address, tfb.Size);
-
- _context.Renderer.Pipeline.SetTransformFeedbackBuffer(index, buffer);
+ tfbs[index] = GetBufferRange(tfb.Address, tfb.Size);
}
+
+ _context.Renderer.Pipeline.SetTransformFeedbackBuffers(tfbs);
}
else
{
diff --git a/Ryujinx.Graphics.OpenGL/Buffer.cs b/Ryujinx.Graphics.OpenGL/Buffer.cs
index e8fd9a6b..89216b83 100644
--- a/Ryujinx.Graphics.OpenGL/Buffer.cs
+++ b/Ryujinx.Graphics.OpenGL/Buffer.cs
@@ -6,6 +6,11 @@ namespace Ryujinx.Graphics.OpenGL
{
static class Buffer
{
+ public static BufferHandle Create()
+ {
+ return Handle.FromInt32<BufferHandle>(GL.GenBuffer());
+ }
+
public static BufferHandle Create(int size)
{
int handle = GL.GenBuffer();
@@ -40,6 +45,12 @@ namespace Ryujinx.Graphics.OpenGL
return data;
}
+ public static void Resize(BufferHandle handle, int size)
+ {
+ GL.BindBuffer(BufferTarget.CopyWriteBuffer, handle.ToInt32());
+ GL.BufferData(BufferTarget.CopyWriteBuffer, size, IntPtr.Zero, BufferUsageHint.StreamCopy);
+ }
+
public static void SetData(BufferHandle buffer, int offset, ReadOnlySpan<byte> data)
{
GL.BindBuffer(BufferTarget.CopyWriteBuffer, buffer.ToInt32());
diff --git a/Ryujinx.Graphics.OpenGL/Constants.cs b/Ryujinx.Graphics.OpenGL/Constants.cs
index 9775b240..8817011a 100644
--- a/Ryujinx.Graphics.OpenGL/Constants.cs
+++ b/Ryujinx.Graphics.OpenGL/Constants.cs
@@ -6,5 +6,6 @@
public const int MaxViewports = 16;
public const int MaxVertexAttribs = 16;
public const int MaxVertexBuffers = 16;
+ public const int MaxTransformFeedbackBuffers = 4;
}
}
diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs
index 2650e9ee..6277fe16 100644
--- a/Ryujinx.Graphics.OpenGL/Pipeline.cs
+++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs
@@ -5,7 +5,6 @@ using Ryujinx.Graphics.OpenGL.Image;
using Ryujinx.Graphics.OpenGL.Queries;
using Ryujinx.Graphics.Shader;
using System;
-using System.Threading;
namespace Ryujinx.Graphics.OpenGL
{
@@ -49,6 +48,10 @@ namespace Ryujinx.Graphics.OpenGL
private bool _scissor0Enable = false;
private bool _tfEnabled;
+ private TransformFeedbackPrimitiveType _tfTopology;
+
+ private readonly BufferHandle[] _tfbs;
+ private readonly BufferRange[] _tfbTargets;
private ColorF _blendConstant;
@@ -74,6 +77,9 @@ namespace Ryujinx.Graphics.OpenGL
{
_cpRenderScale[index] = 1f;
}
+
+ _tfbs = new BufferHandle[Constants.MaxTransformFeedbackBuffers];
+ _tfbTargets = new BufferRange[Constants.MaxTransformFeedbackBuffers];
}
public void Barrier()
@@ -83,7 +89,7 @@ namespace Ryujinx.Graphics.OpenGL
public void BeginTransformFeedback(PrimitiveTopology topology)
{
- GL.BeginTransformFeedback(topology.ConvertToTfType());
+ GL.BeginTransformFeedback(_tfTopology = topology.ConvertToTfType());
_tfEnabled = true;
}
@@ -175,7 +181,7 @@ namespace Ryujinx.Graphics.OpenGL
return;
}
- PrepareForDraw();
+ PreDraw();
if (_primitiveType == PrimitiveType.Quads)
{
@@ -190,7 +196,7 @@ namespace Ryujinx.Graphics.OpenGL
DrawImpl(vertexCount, instanceCount, firstVertex, firstInstance);
}
- _framebuffer.SignalModified();
+ PostDraw();
}
private void DrawQuadsImpl(
@@ -293,7 +299,7 @@ namespace Ryujinx.Graphics.OpenGL
return;
}
- PrepareForDraw();
+ PreDraw();
int indexElemSize = 1;
@@ -335,7 +341,7 @@ namespace Ryujinx.Graphics.OpenGL
firstInstance);
}
- _framebuffer.SignalModified();
+ PostDraw();
}
private void DrawQuadsIndexedImpl(
@@ -790,9 +796,9 @@ namespace Ryujinx.Graphics.OpenGL
if (_tfEnabled)
{
- GL.PauseTransformFeedback();
+ GL.EndTransformFeedback();
_program.Bind();
- GL.ResumeTransformFeedback();
+ GL.BeginTransformFeedback(_tfTopology);
}
else
{
@@ -993,19 +999,39 @@ namespace Ryujinx.Graphics.OpenGL
}
}
- public void SetTransformFeedbackBuffer(int index, BufferRange buffer)
+ public void SetTransformFeedbackBuffers(ReadOnlySpan<BufferRange> buffers)
{
- const BufferRangeTarget target = BufferRangeTarget.TransformFeedbackBuffer;
-
if (_tfEnabled)
{
- GL.PauseTransformFeedback();
- GL.BindBufferRange(target, index, buffer.Handle.ToInt32(), (IntPtr)buffer.Offset, buffer.Size);
- GL.ResumeTransformFeedback();
+ GL.EndTransformFeedback();
}
- else
+
+ int count = Math.Min(buffers.Length, Constants.MaxTransformFeedbackBuffers);
+
+ for (int i = 0; i < count; i++)
{
- GL.BindBufferRange(target, index, buffer.Handle.ToInt32(), (IntPtr)buffer.Offset, buffer.Size);
+ BufferRange buffer = buffers[i];
+ _tfbTargets[i] = buffer;
+
+ if (buffer.Handle == BufferHandle.Null)
+ {
+ GL.BindBufferBase(BufferRangeTarget.TransformFeedbackBuffer, i, 0);
+ continue;
+ }
+
+ if (_tfbs[i] == BufferHandle.Null)
+ {
+ _tfbs[i] = Buffer.Create();
+ }
+
+ Buffer.Resize(_tfbs[i], buffer.Size);
+ Buffer.Copy(buffer.Handle, _tfbs[i], buffer.Offset, 0, buffer.Size);
+ GL.BindBufferBase(BufferRangeTarget.TransformFeedbackBuffer, i, _tfbs[i].ToInt32());
+ }
+
+ if (_tfEnabled)
+ {
+ GL.BeginTransformFeedback(_tfTopology);
}
}
@@ -1104,7 +1130,7 @@ namespace Ryujinx.Graphics.OpenGL
? BufferRangeTarget.ShaderStorageBuffer
: BufferRangeTarget.UniformBuffer;
- if (buffer.Handle == null)
+ if (buffer.Handle == BufferHandle.Null)
{
GL.BindBufferRange(target, bindingPoint, 0, IntPtr.Zero, 0);
return;
@@ -1237,7 +1263,7 @@ namespace Ryujinx.Graphics.OpenGL
}
}
- private void PrepareForDraw()
+ private void PreDraw()
{
_vertexArray.Validate();
@@ -1247,6 +1273,22 @@ namespace Ryujinx.Graphics.OpenGL
}
}
+ private void PostDraw()
+ {
+ _framebuffer?.SignalModified();
+
+ if (_tfEnabled)
+ {
+ for (int i = 0; i < Constants.MaxTransformFeedbackBuffers; i++)
+ {
+ if (_tfbTargets[i].Handle != BufferHandle.Null)
+ {
+ Buffer.Copy(_tfbs[i], _tfbTargets[i].Handle, 0, _tfbTargets[i].Offset, _tfbTargets[i].Size);
+ }
+ }
+ }
+ }
+
private void RestoreComponentMask(int index)
{
GL.ColorMask(
@@ -1319,6 +1361,15 @@ namespace Ryujinx.Graphics.OpenGL
public void Dispose()
{
+ for (int i = 0; i < Constants.MaxTransformFeedbackBuffers; i++)
+ {
+ if (_tfbs[i] != BufferHandle.Null)
+ {
+ Buffer.Delete(_tfbs[i]);
+ _tfbs[i] = BufferHandle.Null;
+ }
+ }
+
_framebuffer?.Dispose();
_vertexArray?.Dispose();
}
diff --git a/Ryujinx.Graphics.OpenGL/Program.cs b/Ryujinx.Graphics.OpenGL/Program.cs
index 6e253140..babe17a0 100644
--- a/Ryujinx.Graphics.OpenGL/Program.cs
+++ b/Ryujinx.Graphics.OpenGL/Program.cs
@@ -131,8 +131,6 @@ namespace Ryujinx.Graphics.OpenGL
CheckProgramLink();
- Bind();
-
int ubBindingPoint = 0;
int sbBindingPoint = 0;
int textureUnit = 0;
@@ -189,7 +187,7 @@ namespace Ryujinx.Graphics.OpenGL
continue;
}
- GL.Uniform1(location, textureUnit);
+ GL.ProgramUniform1(Handle, location, textureUnit);
int uIndex = (int)shader.Stage << TexStageShift | samplerIndex++;
@@ -209,7 +207,7 @@ namespace Ryujinx.Graphics.OpenGL
continue;
}
- GL.Uniform1(location, imageUnit);
+ GL.ProgramUniform1(Handle, location, imageUnit);
int uIndex = (int)shader.Stage << ImgStageShift | imageIndex++;