aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReinUsesLisp <reinuseslisp@airmail.cc>2018-07-19 16:02:51 -0300
committergdkchan <gab.dark.100@gmail.com>2018-07-19 16:02:51 -0300
commit5fe0bc584b21c660e083a9cb37aa0a8be4719f95 (patch)
tree1d8a1e44d379d03a0d967a92475756d05a9e62e2
parent45bb24dbae7b4fb4118036aa74024605995510fd (diff)
Send data to OpenGL host without client-side copies (#285)
* Directly send host address to buffer data * Cleanup OGLShader * Directly copy vertex and index data too * Revert shader bind "cache" * Address feedback
-rw-r--r--ChocolArm64/Memory/AMemory.cs7
-rw-r--r--Ryujinx.Graphics/Gal/IGalRasterizer.cs6
-rw-r--r--Ryujinx.Graphics/Gal/IGalShader.cs3
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs16
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs22
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLStreamBuffer.cs85
-rw-r--r--Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs12
-rw-r--r--Ryujinx.HLE/Gpu/Memory/NvGpuVmm.cs6
8 files changed, 51 insertions, 106 deletions
diff --git a/ChocolArm64/Memory/AMemory.cs b/ChocolArm64/Memory/AMemory.cs
index da5cf007..054277b2 100644
--- a/ChocolArm64/Memory/AMemory.cs
+++ b/ChocolArm64/Memory/AMemory.cs
@@ -204,6 +204,13 @@ namespace ChocolArm64.Memory
return Modified;
}
+ public IntPtr GetHostAddress(long Position, long Size)
+ {
+ EnsureRangeIsValid(Position, Size, AMemoryPerm.Read);
+
+ return (IntPtr)(RamPtr + (ulong)Position);
+ }
+
public sbyte ReadSByte(long Position)
{
return (sbyte)ReadByte(Position);
diff --git a/Ryujinx.Graphics/Gal/IGalRasterizer.cs b/Ryujinx.Graphics/Gal/IGalRasterizer.cs
index 0c5d37e4..a87d36c3 100644
--- a/Ryujinx.Graphics/Gal/IGalRasterizer.cs
+++ b/Ryujinx.Graphics/Gal/IGalRasterizer.cs
@@ -1,3 +1,5 @@
+using System;
+
namespace Ryujinx.Graphics.Gal
{
public interface IGalRasterizer
@@ -45,9 +47,9 @@ namespace Ryujinx.Graphics.Gal
void SetPrimitiveRestartIndex(uint Index);
- void CreateVbo(long Key, byte[] Buffer);
+ void CreateVbo(long Key, int DataSize, IntPtr HostAddress);
- void CreateIbo(long Key, byte[] Buffer);
+ void CreateIbo(long Key, int DataSize, IntPtr HostAddress);
void SetVertexArray(int Stride, long VboKey, GalVertexAttrib[] Attribs);
diff --git a/Ryujinx.Graphics/Gal/IGalShader.cs b/Ryujinx.Graphics/Gal/IGalShader.cs
index 9adaceaf..56235a07 100644
--- a/Ryujinx.Graphics/Gal/IGalShader.cs
+++ b/Ryujinx.Graphics/Gal/IGalShader.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections.Generic;
namespace Ryujinx.Graphics.Gal
@@ -10,7 +11,7 @@ namespace Ryujinx.Graphics.Gal
IEnumerable<ShaderDeclInfo> GetTextureUsage(long Key);
- void SetConstBuffer(long Key, int Cbuf, byte[] Data);
+ void SetConstBuffer(long Key, int Cbuf, int DataSize, IntPtr HostAddress);
void EnsureTextureBinding(string UniformName, int Value);
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs
index 0dc56966..f2e5859e 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs
@@ -211,28 +211,28 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.PrimitiveRestartIndex(Index);
}
- public void CreateVbo(long Key, byte[] Buffer)
+ public void CreateVbo(long Key, int DataSize, IntPtr HostAddress)
{
int Handle = GL.GenBuffer();
- VboCache.AddOrUpdate(Key, Handle, (uint)Buffer.Length);
+ VboCache.AddOrUpdate(Key, Handle, (uint)DataSize);
- IntPtr Length = new IntPtr(Buffer.Length);
+ IntPtr Length = new IntPtr(DataSize);
GL.BindBuffer(BufferTarget.ArrayBuffer, Handle);
- GL.BufferData(BufferTarget.ArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw);
+ GL.BufferData(BufferTarget.ArrayBuffer, Length, HostAddress, BufferUsageHint.StreamDraw);
}
- public void CreateIbo(long Key, byte[] Buffer)
+ public void CreateIbo(long Key, int DataSize, IntPtr HostAddress)
{
int Handle = GL.GenBuffer();
- IboCache.AddOrUpdate(Key, Handle, (uint)Buffer.Length);
+ IboCache.AddOrUpdate(Key, Handle, (uint)DataSize);
- IntPtr Length = new IntPtr(Buffer.Length);
+ IntPtr Length = new IntPtr(DataSize);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, Handle);
- GL.BufferData(BufferTarget.ElementArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw);
+ GL.BufferData(BufferTarget.ElementArrayBuffer, Length, HostAddress, BufferUsageHint.StreamDraw);
}
public void SetVertexArray(int Stride, long VboKey, GalVertexAttrib[] Attribs)
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs
index fe98aa09..37213d8e 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs
@@ -5,6 +5,8 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
+using Buffer = System.Buffer;
+
namespace Ryujinx.Graphics.Gal.OpenGL
{
public class OGLShader : IGalShader
@@ -151,7 +153,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
return Enumerable.Empty<ShaderDeclInfo>();
}
- public void SetConstBuffer(long Key, int Cbuf, byte[] Data)
+ public void SetConstBuffer(long Key, int Cbuf, int DataSize, IntPtr HostAddress)
{
if (Stages.TryGetValue(Key, out ShaderStage Stage))
{
@@ -159,13 +161,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
OGLStreamBuffer Buffer = GetConstBuffer(Stage.Type, Cbuf);
- int Size = Math.Min(Data.Length, Buffer.Size);
-
- byte[] Destiny = Buffer.Map(Size);
-
- Array.Copy(Data, Destiny, Size);
+ int Size = Math.Min(DataSize, Buffer.Size);
- Buffer.Unmap(Size);
+ Buffer.SetData(Size, HostAddress);
}
}
}
@@ -278,7 +276,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
int FreeBinding = 0;
- int BindUniformBlocksIfNotNull(ShaderStage Stage)
+ void BindUniformBlocksIfNotNull(ShaderStage Stage)
{
if (Stage != null)
{
@@ -297,8 +295,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
FreeBinding++;
}
}
-
- return FreeBinding;
}
BindUniformBlocksIfNotNull(Current.Vertex);
@@ -312,7 +308,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
int FreeBinding = 0;
- int BindUniformBuffersIfNotNull(ShaderStage Stage)
+ void BindUniformBuffersIfNotNull(ShaderStage Stage)
{
if (Stage != null)
{
@@ -325,8 +321,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
FreeBinding++;
}
}
-
- return FreeBinding;
}
BindUniformBuffersIfNotNull(Current.Vertex);
@@ -347,7 +341,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
//Allocate a maximum of 64 KiB
int Size = Math.Min(GL.GetInteger(GetPName.MaxUniformBlockSize), 64 * 1024);
- Buffer = OGLStreamBuffer.Create(BufferTarget.UniformBuffer, Size);
+ Buffer = new OGLStreamBuffer(BufferTarget.UniformBuffer, Size);
ConstBuffers[StageIndex][Cbuf] = Buffer;
}
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLStreamBuffer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLStreamBuffer.cs
index 329c5b5d..0d5dee93 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLStreamBuffer.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLStreamBuffer.cs
@@ -1,9 +1,9 @@
-using System;
using OpenTK.Graphics.OpenGL;
+using System;
namespace Ryujinx.Graphics.Gal.OpenGL
{
- abstract class OGLStreamBuffer : IDisposable
+ class OGLStreamBuffer : IDisposable
{
public int Handle { get; protected set; }
@@ -11,53 +11,25 @@ namespace Ryujinx.Graphics.Gal.OpenGL
protected BufferTarget Target { get; private set; }
- private bool Mapped = false;
-
- public OGLStreamBuffer(BufferTarget Target, int MaxSize)
+ public OGLStreamBuffer(BufferTarget Target, int Size)
{
- Handle = 0;
- Mapped = false;
-
this.Target = Target;
- this.Size = MaxSize;
- }
+ this.Size = Size;
- public static OGLStreamBuffer Create(BufferTarget Target, int MaxSize)
- {
- //TODO: Query here for ARB_buffer_storage and use when available
- return new SubDataBuffer(Target, MaxSize);
- }
-
- public byte[] Map(int Size)
- {
- if (Handle == 0 || Mapped || Size > this.Size)
- {
- throw new InvalidOperationException();
- }
+ Handle = GL.GenBuffer();
- byte[] Memory = InternMap(Size);
-
- Mapped = true;
+ GL.BindBuffer(Target, Handle);
- return Memory;
+ GL.BufferData(Target, Size, IntPtr.Zero, BufferUsageHint.StreamDraw);
}
- public void Unmap(int UsedSize)
+ public void SetData(int Size, IntPtr HostAddress)
{
- if (Handle == 0 || !Mapped)
- {
- throw new InvalidOperationException();
- }
-
- InternUnmap(UsedSize);
+ GL.BindBuffer(Target, Handle);
- Mapped = false;
+ GL.BufferSubData(Target, IntPtr.Zero, Size, HostAddress);
}
- protected abstract byte[] InternMap(int Size);
-
- protected abstract void InternUnmap(int UsedSize);
-
public void Dispose()
{
Dispose(true);
@@ -73,41 +45,4 @@ namespace Ryujinx.Graphics.Gal.OpenGL
}
}
}
-
- class SubDataBuffer : OGLStreamBuffer
- {
- private byte[] Memory;
-
- public SubDataBuffer(BufferTarget Target, int MaxSize)
- : base(Target, MaxSize)
- {
- Memory = new byte[MaxSize];
-
- GL.GenBuffers(1, out int Handle);
-
- GL.BindBuffer(Target, Handle);
-
- GL.BufferData(Target, Size, IntPtr.Zero, BufferUsageHint.StreamDraw);
-
- this.Handle = Handle;
- }
-
- protected override byte[] InternMap(int Size)
- {
- return Memory;
- }
-
- protected override void InternUnmap(int UsedSize)
- {
- GL.BindBuffer(Target, Handle);
-
- unsafe
- {
- fixed (byte* MemoryPtr = Memory)
- {
- GL.BufferSubData(Target, IntPtr.Zero, UsedSize, (IntPtr)MemoryPtr);
- }
- }
- }
- }
}
diff --git a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs
index dce25a5e..c3e7a77f 100644
--- a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs
+++ b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs
@@ -560,9 +560,9 @@ namespace Ryujinx.HLE.Gpu.Engines
if (Cb.Enabled)
{
- byte[] Data = Vmm.ReadBytes(Cb.Position, (uint)Cb.Size);
+ IntPtr DataAddress = Vmm.GetHostAddress(Cb.Position, Cb.Size);
- Gpu.Renderer.Shader.SetConstBuffer(BasePosition + (uint)Offset, Cbuf, Data);
+ Gpu.Renderer.Shader.SetConstBuffer(BasePosition + (uint)Offset, Cbuf, Cb.Size, DataAddress);
}
}
}
@@ -595,9 +595,9 @@ namespace Ryujinx.HLE.Gpu.Engines
if (!IboCached || Vmm.IsRegionModified(IboKey, (uint)IbSize, NvGpuBufferType.Index))
{
- byte[] Data = Vmm.ReadBytes(IndexPosition, (uint)IbSize);
+ IntPtr DataAddress = Vmm.GetHostAddress(IndexPosition, IbSize);
- Gpu.Renderer.Rasterizer.CreateIbo(IboKey, Data);
+ Gpu.Renderer.Rasterizer.CreateIbo(IboKey, IbSize, DataAddress);
}
Gpu.Renderer.Rasterizer.SetIndexArray(IbSize, IndexFormat);
@@ -659,9 +659,9 @@ namespace Ryujinx.HLE.Gpu.Engines
if (!VboCached || Vmm.IsRegionModified(VboKey, VbSize, NvGpuBufferType.Vertex))
{
- byte[] Data = Vmm.ReadBytes(VertexPosition, VbSize);
+ IntPtr DataAddress = Vmm.GetHostAddress(VertexPosition, VbSize);
- Gpu.Renderer.Rasterizer.CreateVbo(VboKey, Data);
+ Gpu.Renderer.Rasterizer.CreateVbo(VboKey, (int)VbSize, DataAddress);
}
Gpu.Renderer.Rasterizer.SetVertexArray(Stride, VboKey, Attribs[Index].ToArray());
diff --git a/Ryujinx.HLE/Gpu/Memory/NvGpuVmm.cs b/Ryujinx.HLE/Gpu/Memory/NvGpuVmm.cs
index 0c81dd15..7b23e49f 100644
--- a/Ryujinx.HLE/Gpu/Memory/NvGpuVmm.cs
+++ b/Ryujinx.HLE/Gpu/Memory/NvGpuVmm.cs
@@ -1,5 +1,6 @@
using ChocolArm64.Memory;
using Ryujinx.Graphics.Gal;
+using System;
using System.Collections.Concurrent;
namespace Ryujinx.HLE.Gpu.Memory
@@ -279,6 +280,11 @@ namespace Ryujinx.HLE.Gpu.Memory
return Cache.IsRegionModified(Memory, BufferType, PA, Size);
}
+ public IntPtr GetHostAddress(long Position, long Size)
+ {
+ return Memory.GetHostAddress(GetPhysicalAddress(Position), Size);
+ }
+
public byte ReadByte(long Position)
{
Position = GetPhysicalAddress(Position);