Geometry shader emulation for macOS (#5551)
* Implement vertex and geometry shader conversion to compute * Call InitializeReservedCounts for compute too * PR feedback * Set clip distance mask for geometry and tessellation shaders too * Transform feedback emulation only for vertex
This commit is contained in:
parent
93d78f9ac4
commit
f09bba82b9
65 changed files with 3912 additions and 593 deletions
123
src/Ryujinx.Graphics.Gpu/Memory/BufferUpdater.cs
Normal file
123
src/Ryujinx.Graphics.Gpu/Memory/BufferUpdater.cs
Normal file
|
@ -0,0 +1,123 @@
|
|||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.Shader;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu.Memory
|
||||
{
|
||||
/// <summary>
|
||||
/// Buffer data updater.
|
||||
/// </summary>
|
||||
class BufferUpdater : IDisposable
|
||||
{
|
||||
private BufferHandle _handle;
|
||||
|
||||
/// <summary>
|
||||
/// Handle of the buffer.
|
||||
/// </summary>
|
||||
public BufferHandle Handle => _handle;
|
||||
|
||||
private readonly IRenderer _renderer;
|
||||
private int _startOffset = -1;
|
||||
private int _endOffset = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the buffer updater.
|
||||
/// </summary>
|
||||
/// <param name="renderer">Renderer that the buffer will be used with</param>
|
||||
public BufferUpdater(IRenderer renderer)
|
||||
{
|
||||
_renderer = renderer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mark a region of the buffer as modified and needing to be sent to the GPU.
|
||||
/// </summary>
|
||||
/// <param name="startOffset">Start offset of the region in bytes</param>
|
||||
/// <param name="byteSize">Size of the region in bytes</param>
|
||||
protected void MarkDirty(int startOffset, int byteSize)
|
||||
{
|
||||
int endOffset = startOffset + byteSize;
|
||||
|
||||
if (_startOffset == -1)
|
||||
{
|
||||
_startOffset = startOffset;
|
||||
_endOffset = endOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (startOffset < _startOffset)
|
||||
{
|
||||
_startOffset = startOffset;
|
||||
}
|
||||
|
||||
if (endOffset > _endOffset)
|
||||
{
|
||||
_endOffset = endOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Submits all pending buffer updates to the GPU.
|
||||
/// </summary>
|
||||
/// <param name="data">All data that should be sent to the GPU. Only the modified regions will be updated</param>
|
||||
/// <param name="binding">Optional binding to bind the buffer if a new buffer was created</param>
|
||||
protected void Commit(ReadOnlySpan<byte> data, int binding = -1)
|
||||
{
|
||||
if (_startOffset != -1)
|
||||
{
|
||||
if (_handle == BufferHandle.Null)
|
||||
{
|
||||
_handle = _renderer.CreateBuffer(data.Length, BufferAccess.Stream);
|
||||
_renderer.Pipeline.ClearBuffer(_handle, 0, data.Length, 0);
|
||||
|
||||
if (binding >= 0)
|
||||
{
|
||||
var range = new BufferRange(_handle, 0, data.Length);
|
||||
_renderer.Pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, range) });
|
||||
}
|
||||
};
|
||||
|
||||
_renderer.SetBufferData(_handle, _startOffset, data[_startOffset.._endOffset]);
|
||||
|
||||
_startOffset = -1;
|
||||
_endOffset = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a reference to a given element of a vector.
|
||||
/// </summary>
|
||||
/// <param name="vector">Vector to get the element reference from</param>
|
||||
/// <param name="elementIndex">Element index</param>
|
||||
/// <returns>Reference to the specified element</returns>
|
||||
protected static ref T GetElementRef<T>(ref Vector4<T> vector, int elementIndex)
|
||||
{
|
||||
switch (elementIndex)
|
||||
{
|
||||
case 0:
|
||||
return ref vector.X;
|
||||
case 1:
|
||||
return ref vector.Y;
|
||||
case 2:
|
||||
return ref vector.Z;
|
||||
case 3:
|
||||
return ref vector.W;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(elementIndex));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys the buffer.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (_handle != BufferHandle.Null)
|
||||
{
|
||||
_renderer.DeleteBuffer(_handle);
|
||||
_handle = BufferHandle.Null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue