Spanify Graphics Abstraction Layer (#1226)
* Spanify Graphics Abstraction Layer * Be explicit about BufferHandle size
This commit is contained in:
parent
cc8dbdd3fb
commit
5011640b30
24 changed files with 208 additions and 134 deletions
22
Ryujinx.Graphics.GAL/BufferHandle.cs
Normal file
22
Ryujinx.Graphics.GAL/BufferHandle.cs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.GAL
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential, Size = 8)]
|
||||||
|
public struct BufferHandle : IEquatable<BufferHandle>
|
||||||
|
{
|
||||||
|
private readonly ulong _value;
|
||||||
|
|
||||||
|
public static BufferHandle Null => new BufferHandle(0);
|
||||||
|
|
||||||
|
private BufferHandle(ulong value) => _value = value;
|
||||||
|
|
||||||
|
public override bool Equals(object obj) => obj is BufferHandle handle && Equals(handle);
|
||||||
|
public bool Equals([AllowNull] BufferHandle other) => other._value == _value;
|
||||||
|
public override int GetHashCode() => _value.GetHashCode();
|
||||||
|
public static bool operator ==(BufferHandle left, BufferHandle right) => left.Equals(right);
|
||||||
|
public static bool operator !=(BufferHandle left, BufferHandle right) => !(left == right);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,18 +2,18 @@ namespace Ryujinx.Graphics.GAL
|
||||||
{
|
{
|
||||||
public struct BufferRange
|
public struct BufferRange
|
||||||
{
|
{
|
||||||
private static BufferRange _empty = new BufferRange(null, 0, 0);
|
private static readonly BufferRange _empty = new BufferRange(BufferHandle.Null, 0, 0);
|
||||||
|
|
||||||
public BufferRange Empty => _empty;
|
public BufferRange Empty => _empty;
|
||||||
|
|
||||||
public IBuffer Buffer { get; }
|
public BufferHandle Handle { get; }
|
||||||
|
|
||||||
public int Offset { get; }
|
public int Offset { get; }
|
||||||
public int Size { get; }
|
public int Size { get; }
|
||||||
|
|
||||||
public BufferRange(IBuffer buffer, int offset, int size)
|
public BufferRange(BufferHandle handle, int offset, int size)
|
||||||
{
|
{
|
||||||
Buffer = buffer;
|
Handle = handle;
|
||||||
Offset = offset;
|
Offset = offset;
|
||||||
Size = size;
|
Size = size;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.GAL
|
|
||||||
{
|
|
||||||
public interface IBuffer : IDisposable
|
|
||||||
{
|
|
||||||
void CopyTo(IBuffer destination, int srcOffset, int dstOffset, int size);
|
|
||||||
|
|
||||||
byte[] GetData(int offset, int size);
|
|
||||||
|
|
||||||
void SetData(ReadOnlySpan<byte> data);
|
|
||||||
|
|
||||||
void SetData(int offset, ReadOnlySpan<byte> data);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Ryujinx.Graphics.Shader;
|
using Ryujinx.Graphics.Shader;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.GAL
|
namespace Ryujinx.Graphics.GAL
|
||||||
{
|
{
|
||||||
|
@ -14,6 +15,8 @@ namespace Ryujinx.Graphics.GAL
|
||||||
int stencilValue,
|
int stencilValue,
|
||||||
int stencilMask);
|
int stencilMask);
|
||||||
|
|
||||||
|
void CopyBuffer(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size);
|
||||||
|
|
||||||
void DispatchCompute(int groupsX, int groupsY, int groupsZ);
|
void DispatchCompute(int groupsX, int groupsY, int groupsZ);
|
||||||
|
|
||||||
void Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance);
|
void Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance);
|
||||||
|
@ -49,7 +52,7 @@ namespace Ryujinx.Graphics.GAL
|
||||||
|
|
||||||
void SetRasterizerDiscard(bool discard);
|
void SetRasterizerDiscard(bool discard);
|
||||||
|
|
||||||
void SetRenderTargetColorMasks(uint[] componentMask);
|
void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMask);
|
||||||
|
|
||||||
void SetRenderTargets(ITexture[] colors, ITexture depthStencil);
|
void SetRenderTargets(ITexture[] colors, ITexture depthStencil);
|
||||||
|
|
||||||
|
@ -68,10 +71,10 @@ namespace Ryujinx.Graphics.GAL
|
||||||
|
|
||||||
void SetUserClipDistance(int index, bool enableClip);
|
void SetUserClipDistance(int index, bool enableClip);
|
||||||
|
|
||||||
void SetVertexAttribs(VertexAttribDescriptor[] vertexAttribs);
|
void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs);
|
||||||
void SetVertexBuffers(VertexBufferDescriptor[] vertexBuffers);
|
void SetVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers);
|
||||||
|
|
||||||
void SetViewports(int first, Viewport[] viewports);
|
void SetViewports(int first, ReadOnlySpan<Viewport> viewports);
|
||||||
|
|
||||||
void TextureBarrier();
|
void TextureBarrier();
|
||||||
void TextureBarrierTiled();
|
void TextureBarrierTiled();
|
||||||
|
|
|
@ -11,15 +11,21 @@ namespace Ryujinx.Graphics.GAL
|
||||||
|
|
||||||
IShader CompileShader(ShaderProgram shader);
|
IShader CompileShader(ShaderProgram shader);
|
||||||
|
|
||||||
IBuffer CreateBuffer(int size);
|
BufferHandle CreateBuffer(int size);
|
||||||
|
|
||||||
IProgram CreateProgram(IShader[] shaders);
|
IProgram CreateProgram(IShader[] shaders);
|
||||||
|
|
||||||
ISampler CreateSampler(SamplerCreateInfo info);
|
ISampler CreateSampler(SamplerCreateInfo info);
|
||||||
ITexture CreateTexture(TextureCreateInfo info);
|
ITexture CreateTexture(TextureCreateInfo info);
|
||||||
|
|
||||||
|
void DeleteBuffer(BufferHandle buffer);
|
||||||
|
|
||||||
|
byte[] GetBufferData(BufferHandle buffer, int offset, int size);
|
||||||
|
|
||||||
Capabilities GetCapabilities();
|
Capabilities GetCapabilities();
|
||||||
|
|
||||||
|
void SetBufferData(BufferHandle buffer, int offset, ReadOnlySpan<byte> data);
|
||||||
|
|
||||||
void UpdateCounters();
|
void UpdateCounters();
|
||||||
|
|
||||||
ICounterEvent ReportCounter(CounterType type, EventHandler<ulong> resultHandler);
|
ICounterEvent ReportCounter(CounterType type, EventHandler<ulong> resultHandler);
|
||||||
|
|
|
@ -45,6 +45,11 @@ namespace Ryujinx.Graphics.Gpu
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int ShaderStages = 5;
|
public const int ShaderStages = 5;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum number of vertex attributes.
|
||||||
|
/// </summary>
|
||||||
|
public const int TotalVertexAttribs = 16;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maximum number of vertex buffers.
|
/// Maximum number of vertex buffers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -570,9 +570,9 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
/// <param name="state">Current GPU state</param>
|
/// <param name="state">Current GPU state</param>
|
||||||
private void UpdateVertexAttribState(GpuState state)
|
private void UpdateVertexAttribState(GpuState state)
|
||||||
{
|
{
|
||||||
VertexAttribDescriptor[] vertexAttribs = new VertexAttribDescriptor[16];
|
Span<VertexAttribDescriptor> vertexAttribs = stackalloc VertexAttribDescriptor[Constants.TotalVertexAttribs];
|
||||||
|
|
||||||
for (int index = 0; index < 16; index++)
|
for (int index = 0; index < Constants.TotalVertexAttribs; index++)
|
||||||
{
|
{
|
||||||
var vertexAttrib = state.Get<VertexAttribState>(MethodOffset.VertexAttribState, index);
|
var vertexAttrib = state.Get<VertexAttribState>(MethodOffset.VertexAttribState, index);
|
||||||
|
|
||||||
|
@ -660,7 +660,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
{
|
{
|
||||||
_isAnyVbInstanced = false;
|
_isAnyVbInstanced = false;
|
||||||
|
|
||||||
for (int index = 0; index < 16; index++)
|
for (int index = 0; index < Constants.TotalVertexBuffers; index++)
|
||||||
{
|
{
|
||||||
var vertexBuffer = state.Get<VertexBufferState>(MethodOffset.VertexBufferState, index);
|
var vertexBuffer = state.Get<VertexBufferState>(MethodOffset.VertexBufferState, index);
|
||||||
|
|
||||||
|
@ -728,7 +728,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
{
|
{
|
||||||
bool rtColorMaskShared = state.Get<Boolean32>(MethodOffset.RtColorMaskShared);
|
bool rtColorMaskShared = state.Get<Boolean32>(MethodOffset.RtColorMaskShared);
|
||||||
|
|
||||||
uint[] componentMasks = new uint[Constants.TotalRenderTargets];
|
Span<uint> componentMasks = stackalloc uint[Constants.TotalRenderTargets];
|
||||||
|
|
||||||
for (int index = 0; index < Constants.TotalRenderTargets; index++)
|
for (int index = 0; index < Constants.TotalRenderTargets; index++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,9 +11,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
private readonly GpuContext _context;
|
private readonly GpuContext _context;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Host buffer object.
|
/// Host buffer handle.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IBuffer HostBuffer { get; }
|
public BufferHandle Handle { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Start address of the buffer in guest memory.
|
/// Start address of the buffer in guest memory.
|
||||||
|
@ -46,7 +46,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
Address = address;
|
Address = address;
|
||||||
Size = size;
|
Size = size;
|
||||||
|
|
||||||
HostBuffer = context.Renderer.CreateBuffer((int)size);
|
Handle = context.Renderer.CreateBuffer((int)size);
|
||||||
|
|
||||||
_modifiedRanges = new (ulong, ulong)[size / PhysicalMemory.PageSize];
|
_modifiedRanges = new (ulong, ulong)[size / PhysicalMemory.PageSize];
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
{
|
{
|
||||||
int offset = (int)(address - Address);
|
int offset = (int)(address - Address);
|
||||||
|
|
||||||
return new BufferRange(HostBuffer, offset, (int)size);
|
return new BufferRange(Handle, offset, (int)size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -125,7 +125,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
|
|
||||||
int offset = (int)(mAddress - Address);
|
int offset = (int)(mAddress - Address);
|
||||||
|
|
||||||
HostBuffer.SetData(offset, _context.PhysicalMemory.GetSpan(mAddress, (int)mSize));
|
_context.Renderer.SetBufferData(Handle, offset, _context.PhysicalMemory.GetSpan(mAddress, (int)mSize));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// <param name="dstOffset">The offset of the destination buffer to copy into</param>
|
/// <param name="dstOffset">The offset of the destination buffer to copy into</param>
|
||||||
public void CopyTo(Buffer destination, int dstOffset)
|
public void CopyTo(Buffer destination, int dstOffset)
|
||||||
{
|
{
|
||||||
HostBuffer.CopyTo(destination.HostBuffer, 0, dstOffset, (int)Size);
|
_context.Renderer.Pipeline.CopyBuffer(Handle, destination.Handle, 0, dstOffset, (int)Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -149,7 +149,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
{
|
{
|
||||||
int offset = (int)(address - Address);
|
int offset = (int)(address - Address);
|
||||||
|
|
||||||
byte[] data = HostBuffer.GetData(offset, (int)size);
|
byte[] data = _context.Renderer.GetBufferData(Handle, offset, (int)size);
|
||||||
|
|
||||||
_context.PhysicalMemory.Write(address, data);
|
_context.PhysicalMemory.Write(address, data);
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
HostBuffer.Dispose();
|
_context.Renderer.DeleteBuffer(Handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -477,7 +477,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
{
|
{
|
||||||
_vertexBuffersDirty = false;
|
_vertexBuffersDirty = false;
|
||||||
|
|
||||||
VertexBufferDescriptor[] vertexBuffers = new VertexBufferDescriptor[Constants.TotalVertexBuffers];
|
Span<VertexBufferDescriptor> vertexBuffers = stackalloc VertexBufferDescriptor[Constants.TotalVertexBuffers];
|
||||||
|
|
||||||
for (int index = 0; (vbEnableMask >> index) != 0; index++)
|
for (int index = 0; (vbEnableMask >> index) != 0; index++)
|
||||||
{
|
{
|
||||||
|
@ -666,8 +666,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
int srcOffset = (int)(srcAddress - srcBuffer.Address);
|
int srcOffset = (int)(srcAddress - srcBuffer.Address);
|
||||||
int dstOffset = (int)(dstAddress - dstBuffer.Address);
|
int dstOffset = (int)(dstAddress - dstBuffer.Address);
|
||||||
|
|
||||||
srcBuffer.HostBuffer.CopyTo(
|
_context.Renderer.Pipeline.CopyBuffer(
|
||||||
dstBuffer.HostBuffer,
|
srcBuffer.Handle,
|
||||||
|
dstBuffer.Handle,
|
||||||
srcOffset,
|
srcOffset,
|
||||||
dstOffset,
|
dstOffset,
|
||||||
(int)size);
|
(int)size);
|
||||||
|
|
|
@ -4,22 +4,22 @@ using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.OpenGL
|
namespace Ryujinx.Graphics.OpenGL
|
||||||
{
|
{
|
||||||
class Buffer : IBuffer
|
static class Buffer
|
||||||
{
|
{
|
||||||
public int Handle { get; }
|
public static BufferHandle Create(int size)
|
||||||
|
|
||||||
public Buffer(int size)
|
|
||||||
{
|
{
|
||||||
Handle = GL.GenBuffer();
|
int handle = GL.GenBuffer();
|
||||||
|
|
||||||
GL.BindBuffer(BufferTarget.CopyWriteBuffer, Handle);
|
GL.BindBuffer(BufferTarget.CopyWriteBuffer, handle);
|
||||||
GL.BufferData(BufferTarget.CopyWriteBuffer, size, IntPtr.Zero, BufferUsageHint.DynamicDraw);
|
GL.BufferData(BufferTarget.CopyWriteBuffer, size, IntPtr.Zero, BufferUsageHint.DynamicDraw);
|
||||||
|
|
||||||
|
return Handle.FromInt32<BufferHandle>(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CopyTo(IBuffer destination, int srcOffset, int dstOffset, int size)
|
public static void Copy(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size)
|
||||||
{
|
{
|
||||||
GL.BindBuffer(BufferTarget.CopyReadBuffer, Handle);
|
GL.BindBuffer(BufferTarget.CopyReadBuffer, source.ToInt32());
|
||||||
GL.BindBuffer(BufferTarget.CopyWriteBuffer, ((Buffer)destination).Handle);
|
GL.BindBuffer(BufferTarget.CopyWriteBuffer, destination.ToInt32());
|
||||||
|
|
||||||
GL.CopyBufferSubData(
|
GL.CopyBufferSubData(
|
||||||
BufferTarget.CopyReadBuffer,
|
BufferTarget.CopyReadBuffer,
|
||||||
|
@ -29,9 +29,9 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
(IntPtr)size);
|
(IntPtr)size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] GetData(int offset, int size)
|
public static byte[] GetData(BufferHandle buffer, int offset, int size)
|
||||||
{
|
{
|
||||||
GL.BindBuffer(BufferTarget.CopyReadBuffer, Handle);
|
GL.BindBuffer(BufferTarget.CopyReadBuffer, buffer.ToInt32());
|
||||||
|
|
||||||
byte[] data = new byte[size];
|
byte[] data = new byte[size];
|
||||||
|
|
||||||
|
@ -40,22 +40,9 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetData(ReadOnlySpan<byte> data)
|
public static void SetData(BufferHandle buffer, int offset, ReadOnlySpan<byte> data)
|
||||||
{
|
{
|
||||||
unsafe
|
GL.BindBuffer(BufferTarget.CopyWriteBuffer, buffer.ToInt32());
|
||||||
{
|
|
||||||
GL.BindBuffer(BufferTarget.CopyWriteBuffer, Handle);
|
|
||||||
|
|
||||||
fixed (byte* ptr = data)
|
|
||||||
{
|
|
||||||
GL.BufferData(BufferTarget.CopyWriteBuffer, data.Length, (IntPtr)ptr, BufferUsageHint.DynamicDraw);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetData(int offset, ReadOnlySpan<byte> data)
|
|
||||||
{
|
|
||||||
GL.BindBuffer(BufferTarget.CopyWriteBuffer, Handle);
|
|
||||||
|
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
|
@ -66,9 +53,9 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public static void Delete(BufferHandle buffer)
|
||||||
{
|
{
|
||||||
GL.DeleteBuffer(Handle);
|
GL.DeleteBuffer(buffer.ToInt32());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
Ryujinx.Graphics.OpenGL/Constants.cs
Normal file
10
Ryujinx.Graphics.OpenGL/Constants.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
namespace Ryujinx.Graphics.OpenGL
|
||||||
|
{
|
||||||
|
static class Constants
|
||||||
|
{
|
||||||
|
public const int MaxRenderTargets = 8;
|
||||||
|
public const int MaxViewports = 16;
|
||||||
|
public const int MaxVertexAttribs = 16;
|
||||||
|
public const int MaxVertexBuffers = 16;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
|
using Ryujinx.Graphics.OpenGL.Image;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.OpenGL
|
namespace Ryujinx.Graphics.OpenGL
|
||||||
|
|
23
Ryujinx.Graphics.OpenGL/Handle.cs
Normal file
23
Ryujinx.Graphics.OpenGL/Handle.cs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
using Ryujinx.Graphics.GAL;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.OpenGL
|
||||||
|
{
|
||||||
|
static class Handle
|
||||||
|
{
|
||||||
|
public static T FromInt32<T>(int handle) where T : unmanaged
|
||||||
|
{
|
||||||
|
Debug.Assert(Unsafe.SizeOf<T>() == sizeof(ulong));
|
||||||
|
|
||||||
|
ulong handle64 = (uint)handle;
|
||||||
|
|
||||||
|
return Unsafe.As<ulong, T>(ref handle64);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int ToInt32(this BufferHandle handle)
|
||||||
|
{
|
||||||
|
return (int)Unsafe.As<BufferHandle, ulong>(ref handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.OpenGL
|
namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
{
|
{
|
||||||
class Sampler : ISampler
|
class Sampler : ISampler
|
||||||
{
|
{
|
|
@ -1,10 +1,7 @@
|
||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.OpenGL
|
namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
{
|
{
|
||||||
class TextureBase
|
class TextureBase
|
||||||
{
|
{
|
|
@ -2,14 +2,14 @@
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.OpenGL
|
namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
{
|
{
|
||||||
class TextureBuffer : TextureBase, ITexture
|
class TextureBuffer : TextureBase, ITexture
|
||||||
{
|
{
|
||||||
private int _bufferOffset;
|
private int _bufferOffset;
|
||||||
private int _bufferSize;
|
private int _bufferSize;
|
||||||
|
|
||||||
private Buffer _buffer;
|
private BufferHandle _buffer;
|
||||||
|
|
||||||
public TextureBuffer(TextureCreateInfo info) : base(info) {}
|
public TextureBuffer(TextureCreateInfo info) : base(info) {}
|
||||||
|
|
||||||
|
@ -30,24 +30,24 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
|
|
||||||
public byte[] GetData()
|
public byte[] GetData()
|
||||||
{
|
{
|
||||||
return _buffer?.GetData(_bufferOffset, _bufferSize);
|
return Buffer.GetData(_buffer, _bufferOffset, _bufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetData(ReadOnlySpan<byte> data)
|
public void SetData(ReadOnlySpan<byte> data)
|
||||||
{
|
{
|
||||||
_buffer?.SetData(_bufferOffset, data.Slice(0, Math.Min(data.Length, _bufferSize)));
|
Buffer.SetData(_buffer, _bufferOffset, data.Slice(0, Math.Min(data.Length, _bufferSize)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetStorage(BufferRange buffer)
|
public void SetStorage(BufferRange buffer)
|
||||||
{
|
{
|
||||||
if (buffer.Buffer == _buffer &&
|
if (buffer.Handle == _buffer &&
|
||||||
buffer.Offset == _bufferOffset &&
|
buffer.Offset == _bufferOffset &&
|
||||||
buffer.Size == _bufferSize)
|
buffer.Size == _bufferSize)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_buffer = (Buffer)buffer.Buffer;
|
_buffer = buffer.Handle;
|
||||||
_bufferOffset = buffer.Offset;
|
_bufferOffset = buffer.Offset;
|
||||||
_bufferSize = buffer.Size;
|
_bufferSize = buffer.Size;
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
|
|
||||||
SizedInternalFormat format = (SizedInternalFormat)FormatTable.GetFormatInfo(Info.Format).PixelInternalFormat;
|
SizedInternalFormat format = (SizedInternalFormat)FormatTable.GetFormatInfo(Info.Format).PixelInternalFormat;
|
||||||
|
|
||||||
GL.TexBufferRange(TextureBufferTarget.TextureBuffer, format, _buffer.Handle, (IntPtr)buffer.Offset, buffer.Size);
|
GL.TexBufferRange(TextureBufferTarget.TextureBuffer, format, _buffer.ToInt32(), (IntPtr)buffer.Offset, buffer.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
|
@ -2,7 +2,7 @@ using Ryujinx.Graphics.GAL;
|
||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.OpenGL
|
namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
{
|
{
|
||||||
class TextureCopy : IDisposable
|
class TextureCopy : IDisposable
|
||||||
{
|
{
|
|
@ -3,7 +3,7 @@ using Ryujinx.Common;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.OpenGL
|
namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
{
|
{
|
||||||
static class TextureCopyUnscaled
|
static class TextureCopyUnscaled
|
||||||
{
|
{
|
|
@ -2,7 +2,7 @@ using OpenTK.Graphics.OpenGL;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.OpenGL
|
namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
{
|
{
|
||||||
class TextureStorage
|
class TextureStorage
|
||||||
{
|
{
|
|
@ -2,7 +2,7 @@ using OpenTK.Graphics.OpenGL;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.OpenGL
|
namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
{
|
{
|
||||||
class TextureView : TextureBase, ITexture
|
class TextureView : TextureBase, ITexture
|
||||||
{
|
{
|
|
@ -1,6 +1,7 @@
|
||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
|
using Ryujinx.Graphics.OpenGL.Image;
|
||||||
using Ryujinx.Graphics.OpenGL.Queries;
|
using Ryujinx.Graphics.OpenGL.Queries;
|
||||||
using Ryujinx.Graphics.Shader;
|
using Ryujinx.Graphics.Shader;
|
||||||
using System;
|
using System;
|
||||||
|
@ -32,7 +33,7 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
private ClipOrigin _clipOrigin;
|
private ClipOrigin _clipOrigin;
|
||||||
private ClipDepthMode _clipDepthMode;
|
private ClipDepthMode _clipDepthMode;
|
||||||
|
|
||||||
private uint[] _componentMasks;
|
private readonly uint[] _componentMasks;
|
||||||
|
|
||||||
private bool _scissor0Enable = false;
|
private bool _scissor0Enable = false;
|
||||||
|
|
||||||
|
@ -43,6 +44,13 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
_rasterizerDiscard = false;
|
_rasterizerDiscard = false;
|
||||||
_clipOrigin = ClipOrigin.LowerLeft;
|
_clipOrigin = ClipOrigin.LowerLeft;
|
||||||
_clipDepthMode = ClipDepthMode.NegativeOneToOne;
|
_clipDepthMode = ClipDepthMode.NegativeOneToOne;
|
||||||
|
|
||||||
|
_componentMasks = new uint[Constants.MaxRenderTargets];
|
||||||
|
|
||||||
|
for (int index = 0; index < Constants.MaxRenderTargets; index++)
|
||||||
|
{
|
||||||
|
_componentMasks[index] = 0xf;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Barrier()
|
public void Barrier()
|
||||||
|
@ -112,6 +120,11 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
_framebuffer.SignalModified();
|
_framebuffer.SignalModified();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CopyBuffer(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size)
|
||||||
|
{
|
||||||
|
Buffer.Copy(source, destination, srcOffset, dstOffset, size);
|
||||||
|
}
|
||||||
|
|
||||||
public void DispatchCompute(int groupsX, int groupsY, int groupsZ)
|
public void DispatchCompute(int groupsX, int groupsY, int groupsZ)
|
||||||
{
|
{
|
||||||
if (!_program.IsLinked)
|
if (!_program.IsLinked)
|
||||||
|
@ -631,7 +644,7 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
|
|
||||||
EnsureVertexArray();
|
EnsureVertexArray();
|
||||||
|
|
||||||
_vertexArray.SetIndexBuffer((Buffer)buffer.Buffer);
|
_vertexArray.SetIndexBuffer(buffer.Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetPointSize(float size)
|
public void SetPointSize(float size)
|
||||||
|
@ -661,7 +674,6 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
public void SetProgram(IProgram program)
|
public void SetProgram(IProgram program)
|
||||||
{
|
{
|
||||||
_program = (Program)program;
|
_program = (Program)program;
|
||||||
|
|
||||||
_program.Bind();
|
_program.Bind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -679,12 +691,12 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
_rasterizerDiscard = discard;
|
_rasterizerDiscard = discard;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetRenderTargetColorMasks(uint[] componentMasks)
|
public void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMasks)
|
||||||
{
|
{
|
||||||
_componentMasks = (uint[])componentMasks.Clone();
|
|
||||||
|
|
||||||
for (int index = 0; index < componentMasks.Length; index++)
|
for (int index = 0; index < componentMasks.Length; index++)
|
||||||
{
|
{
|
||||||
|
_componentMasks[index] = componentMasks[index];
|
||||||
|
|
||||||
RestoreComponentMask(index);
|
RestoreComponentMask(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -823,21 +835,21 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
GL.Enable(EnableCap.ClipDistance0 + index);
|
GL.Enable(EnableCap.ClipDistance0 + index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetVertexAttribs(VertexAttribDescriptor[] vertexAttribs)
|
public void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs)
|
||||||
{
|
{
|
||||||
EnsureVertexArray();
|
EnsureVertexArray();
|
||||||
|
|
||||||
_vertexArray.SetVertexAttributes(vertexAttribs);
|
_vertexArray.SetVertexAttributes(vertexAttribs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetVertexBuffers(VertexBufferDescriptor[] vertexBuffers)
|
public void SetVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers)
|
||||||
{
|
{
|
||||||
EnsureVertexArray();
|
EnsureVertexArray();
|
||||||
|
|
||||||
_vertexArray.SetVertexBuffers(vertexBuffers);
|
_vertexArray.SetVertexBuffers(vertexBuffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetViewports(int first, Viewport[] viewports)
|
public void SetViewports(int first, ReadOnlySpan<Viewport> viewports)
|
||||||
{
|
{
|
||||||
bool flipY = false;
|
bool flipY = false;
|
||||||
|
|
||||||
|
@ -906,18 +918,16 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
? BufferRangeTarget.ShaderStorageBuffer
|
? BufferRangeTarget.ShaderStorageBuffer
|
||||||
: BufferRangeTarget.UniformBuffer;
|
: BufferRangeTarget.UniformBuffer;
|
||||||
|
|
||||||
if (buffer.Buffer == null)
|
if (buffer.Handle == null)
|
||||||
{
|
{
|
||||||
GL.BindBufferRange(target, bindingPoint, 0, IntPtr.Zero, 0);
|
GL.BindBufferRange(target, bindingPoint, 0, IntPtr.Zero, 0);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bufferHandle = ((Buffer)buffer.Buffer).Handle;
|
|
||||||
|
|
||||||
IntPtr bufferOffset = (IntPtr)buffer.Offset;
|
IntPtr bufferOffset = (IntPtr)buffer.Offset;
|
||||||
|
|
||||||
GL.BindBufferRange(target, bindingPoint, bufferHandle, bufferOffset, buffer.Size);
|
GL.BindBufferRange(target, bindingPoint, buffer.Handle.ToInt32(), bufferOffset, buffer.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetOrigin(ClipOrigin origin)
|
private void SetOrigin(ClipOrigin origin)
|
||||||
|
@ -997,15 +1007,12 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
|
|
||||||
private void RestoreComponentMask(int index)
|
private void RestoreComponentMask(int index)
|
||||||
{
|
{
|
||||||
if (_componentMasks != null)
|
GL.ColorMask(
|
||||||
{
|
index,
|
||||||
GL.ColorMask(
|
(_componentMasks[index] & 1u) != 0,
|
||||||
index,
|
(_componentMasks[index] & 2u) != 0,
|
||||||
(_componentMasks[index] & 1u) != 0,
|
(_componentMasks[index] & 4u) != 0,
|
||||||
(_componentMasks[index] & 2u) != 0,
|
(_componentMasks[index] & 8u) != 0);
|
||||||
(_componentMasks[index] & 4u) != 0,
|
|
||||||
(_componentMasks[index] & 8u) != 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RestoreScissor0Enable()
|
public void RestoreScissor0Enable()
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
|
using Ryujinx.Graphics.OpenGL.Image;
|
||||||
using Ryujinx.Graphics.OpenGL.Queries;
|
using Ryujinx.Graphics.OpenGL.Queries;
|
||||||
using Ryujinx.Graphics.Shader;
|
using Ryujinx.Graphics.Shader;
|
||||||
using System;
|
using System;
|
||||||
|
@ -38,9 +39,9 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
return new Shader(shader);
|
return new Shader(shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IBuffer CreateBuffer(int size)
|
public BufferHandle CreateBuffer(int size)
|
||||||
{
|
{
|
||||||
return new Buffer(size);
|
return Buffer.Create(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IProgram CreateProgram(IShader[] shaders)
|
public IProgram CreateProgram(IShader[] shaders)
|
||||||
|
@ -58,6 +59,16 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
return info.Target == Target.TextureBuffer ? new TextureBuffer(info) : new TextureStorage(this, info).CreateDefaultView();
|
return info.Target == Target.TextureBuffer ? new TextureBuffer(info) : new TextureStorage(this, info).CreateDefaultView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DeleteBuffer(BufferHandle buffer)
|
||||||
|
{
|
||||||
|
Buffer.Delete(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] GetBufferData(BufferHandle buffer, int offset, int size)
|
||||||
|
{
|
||||||
|
return Buffer.GetData(buffer, offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
public Capabilities GetCapabilities()
|
public Capabilities GetCapabilities()
|
||||||
{
|
{
|
||||||
return new Capabilities(
|
return new Capabilities(
|
||||||
|
@ -68,6 +79,11 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
HwCapabilities.MaxSupportedAnisotropy);
|
HwCapabilities.MaxSupportedAnisotropy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetBufferData(BufferHandle buffer, int offset, ReadOnlySpan<byte> data)
|
||||||
|
{
|
||||||
|
Buffer.SetData(buffer, offset, data);
|
||||||
|
}
|
||||||
|
|
||||||
public void UpdateCounters()
|
public void UpdateCounters()
|
||||||
{
|
{
|
||||||
_counters.Update();
|
_counters.Update();
|
||||||
|
|
|
@ -10,12 +10,18 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
|
|
||||||
private bool _needsAttribsUpdate;
|
private bool _needsAttribsUpdate;
|
||||||
|
|
||||||
private VertexBufferDescriptor[] _vertexBuffers;
|
private readonly VertexAttribDescriptor[] _vertexAttribs;
|
||||||
private VertexAttribDescriptor[] _vertexAttribs;
|
private readonly VertexBufferDescriptor[] _vertexBuffers;
|
||||||
|
|
||||||
|
private int _vertexAttribsCount;
|
||||||
|
private int _vertexBuffersCount;
|
||||||
|
|
||||||
public VertexArray()
|
public VertexArray()
|
||||||
{
|
{
|
||||||
Handle = GL.GenVertexArray();
|
Handle = GL.GenVertexArray();
|
||||||
|
|
||||||
|
_vertexAttribs = new VertexAttribDescriptor[Constants.MaxVertexAttribs];
|
||||||
|
_vertexBuffers = new VertexBufferDescriptor[Constants.MaxVertexBuffers];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Bind()
|
public void Bind()
|
||||||
|
@ -23,17 +29,17 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
GL.BindVertexArray(Handle);
|
GL.BindVertexArray(Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetVertexBuffers(VertexBufferDescriptor[] vertexBuffers)
|
public void SetVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers)
|
||||||
{
|
{
|
||||||
int bindingIndex = 0;
|
int bindingIndex = 0;
|
||||||
|
|
||||||
foreach (VertexBufferDescriptor vb in vertexBuffers)
|
for (int index = 0; index < vertexBuffers.Length; index++)
|
||||||
{
|
{
|
||||||
if (vb.Buffer.Buffer != null)
|
VertexBufferDescriptor vb = vertexBuffers[index];
|
||||||
{
|
|
||||||
int bufferHandle = ((Buffer)vb.Buffer.Buffer).Handle;
|
|
||||||
|
|
||||||
GL.BindVertexBuffer(bindingIndex, bufferHandle, (IntPtr)vb.Buffer.Offset, vb.Stride);
|
if (vb.Buffer.Handle != null)
|
||||||
|
{
|
||||||
|
GL.BindVertexBuffer(bindingIndex, vb.Buffer.Handle.ToInt32(), (IntPtr)vb.Buffer.Offset, vb.Stride);
|
||||||
|
|
||||||
GL.VertexBindingDivisor(bindingIndex, vb.Divisor);
|
GL.VertexBindingDivisor(bindingIndex, vb.Divisor);
|
||||||
}
|
}
|
||||||
|
@ -42,31 +48,35 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
GL.BindVertexBuffer(bindingIndex, 0, IntPtr.Zero, 0);
|
GL.BindVertexBuffer(bindingIndex, 0, IntPtr.Zero, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_vertexBuffers[index] = vb;
|
||||||
|
|
||||||
bindingIndex++;
|
bindingIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
_vertexBuffers = vertexBuffers;
|
_vertexBuffersCount = bindingIndex;
|
||||||
|
|
||||||
_needsAttribsUpdate = true;
|
_needsAttribsUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetVertexAttributes(VertexAttribDescriptor[] vertexAttribs)
|
public void SetVertexAttributes(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs)
|
||||||
{
|
{
|
||||||
int attribIndex = 0;
|
int index = 0;
|
||||||
|
|
||||||
foreach (VertexAttribDescriptor attrib in vertexAttribs)
|
for (; index < vertexAttribs.Length; index++)
|
||||||
{
|
{
|
||||||
|
VertexAttribDescriptor attrib = vertexAttribs[index];
|
||||||
|
|
||||||
FormatInfo fmtInfo = FormatTable.GetFormatInfo(attrib.Format);
|
FormatInfo fmtInfo = FormatTable.GetFormatInfo(attrib.Format);
|
||||||
|
|
||||||
if (attrib.IsZero)
|
if (attrib.IsZero)
|
||||||
{
|
{
|
||||||
// Disabling the attribute causes the shader to read a constant value.
|
// Disabling the attribute causes the shader to read a constant value.
|
||||||
// The value is configurable, but by default is a vector of (0, 0, 0, 1).
|
// The value is configurable, but by default is a vector of (0, 0, 0, 1).
|
||||||
GL.DisableVertexAttribArray(attribIndex);
|
GL.DisableVertexAttribArray(index);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GL.EnableVertexAttribArray(attribIndex);
|
GL.EnableVertexAttribArray(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
int offset = attrib.Offset;
|
int offset = attrib.Offset;
|
||||||
|
@ -79,47 +89,47 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
{
|
{
|
||||||
VertexAttribType type = (VertexAttribType)fmtInfo.PixelType;
|
VertexAttribType type = (VertexAttribType)fmtInfo.PixelType;
|
||||||
|
|
||||||
GL.VertexAttribFormat(attribIndex, size, type, fmtInfo.Normalized, offset);
|
GL.VertexAttribFormat(index, size, type, fmtInfo.Normalized, offset);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VertexAttribIntegerType type = (VertexAttribIntegerType)fmtInfo.PixelType;
|
VertexAttribIntegerType type = (VertexAttribIntegerType)fmtInfo.PixelType;
|
||||||
|
|
||||||
GL.VertexAttribIFormat(attribIndex, size, type, offset);
|
GL.VertexAttribIFormat(index, size, type, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.VertexAttribBinding(attribIndex, attrib.BufferIndex);
|
GL.VertexAttribBinding(index, attrib.BufferIndex);
|
||||||
|
|
||||||
attribIndex++;
|
_vertexAttribs[index] = attrib;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; attribIndex < 16; attribIndex++)
|
_vertexAttribsCount = index;
|
||||||
|
|
||||||
|
for (; index < Constants.MaxVertexAttribs; index++)
|
||||||
{
|
{
|
||||||
GL.DisableVertexAttribArray(attribIndex);
|
GL.DisableVertexAttribArray(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
_vertexAttribs = vertexAttribs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetIndexBuffer(Buffer indexBuffer)
|
public void SetIndexBuffer(BufferHandle buffer)
|
||||||
{
|
{
|
||||||
GL.BindBuffer(BufferTarget.ElementArrayBuffer, indexBuffer?.Handle ?? 0);
|
GL.BindBuffer(BufferTarget.ElementArrayBuffer, buffer.ToInt32());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Validate()
|
public void Validate()
|
||||||
{
|
{
|
||||||
for (int attribIndex = 0; attribIndex < _vertexAttribs.Length; attribIndex++)
|
for (int attribIndex = 0; attribIndex < _vertexAttribsCount; attribIndex++)
|
||||||
{
|
{
|
||||||
VertexAttribDescriptor attrib = _vertexAttribs[attribIndex];
|
VertexAttribDescriptor attrib = _vertexAttribs[attribIndex];
|
||||||
|
|
||||||
if ((uint)attrib.BufferIndex >= _vertexBuffers.Length)
|
if ((uint)attrib.BufferIndex >= _vertexBuffersCount)
|
||||||
{
|
{
|
||||||
GL.DisableVertexAttribArray(attribIndex);
|
GL.DisableVertexAttribArray(attribIndex);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_vertexBuffers[attrib.BufferIndex].Buffer.Buffer == null)
|
if (_vertexBuffers[attrib.BufferIndex].Buffer.Handle == null)
|
||||||
{
|
{
|
||||||
GL.DisableVertexAttribArray(attribIndex);
|
GL.DisableVertexAttribArray(attribIndex);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
|
using Ryujinx.Graphics.OpenGL.Image;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.OpenGL
|
namespace Ryujinx.Graphics.OpenGL
|
||||||
|
|
Reference in a new issue