mirror of
https://git.ryujinx.app/projects/Kenji-NX.git
synced 2026-09-22 02:31:12 +02:00
gpu allocation optimizations
ObjectPool now uses ConcurrentBag instead if ConcurrentStack, as it has a smaller memory footprint. Fix compiler warnings related to Audio Command Pools. Switch gpu command initialization to use pointers, that way skipping the allocation of the command which is unnecessary. Skip byte array allocation in Ioctl2/3 if it isn't needed (if the source data is all continuous we don't need to copy it to make it continuous).
This commit is contained in:
@@ -167,7 +167,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||
return new TableRef<T>(this, reference);
|
||||
}
|
||||
|
||||
internal ref T New<T>() where T : struct
|
||||
internal unsafe T* New<T>() where T : unmanaged, IGALCommand
|
||||
{
|
||||
while (_producerPtr == (Volatile.Read(ref _consumerPtr) + QueueCount - 1) % QueueCount)
|
||||
{
|
||||
@@ -183,11 +183,12 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||
_producerPtr = (_producerPtr + 1) % QueueCount;
|
||||
|
||||
Span<byte> memory = new(_commandQueue, taken * _elementSize, _elementSize);
|
||||
ref T result = ref Unsafe.As<byte, T>(ref MemoryMarshal.GetReference(memory));
|
||||
T* result = (T*)Unsafe.AsPointer(ref memory.GetPinnableReference());
|
||||
// ref T result = ref Unsafe.As<byte, T>(ref MemoryMarshal.GetReference(memory));
|
||||
|
||||
memory[^1] = (byte)((IGALCommand)result).CommandType;
|
||||
memory[^1] = (byte)(result)->CommandType;
|
||||
|
||||
return ref result;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal int AddTableRef(object obj)
|
||||
@@ -251,12 +252,12 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||
return Thread.CurrentThread == _gpuThread;
|
||||
}
|
||||
|
||||
public void BackgroundContextAction(Action action, bool alwaysBackground = false)
|
||||
public unsafe void BackgroundContextAction(Action action, bool alwaysBackground = false)
|
||||
{
|
||||
if (IsGpuThread() && !alwaysBackground)
|
||||
{
|
||||
// The action must be performed on the render thread.
|
||||
New<ActionCommand>().Set(Ref(action));
|
||||
New<ActionCommand>()->Set(Ref(action));
|
||||
InvokeCommand();
|
||||
}
|
||||
else
|
||||
@@ -265,43 +266,43 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||
}
|
||||
}
|
||||
|
||||
public BufferHandle CreateBuffer(int size, BufferAccess access)
|
||||
public unsafe BufferHandle CreateBuffer(int size, BufferAccess access)
|
||||
{
|
||||
BufferHandle handle = Buffers.CreateBufferHandle();
|
||||
New<CreateBufferAccessCommand>().Set(handle, size, access);
|
||||
New<CreateBufferAccessCommand>()->Set(handle, size, access);
|
||||
QueueCommand();
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
public BufferHandle CreateBuffer(nint pointer, int size)
|
||||
public unsafe BufferHandle CreateBuffer(nint pointer, int size)
|
||||
{
|
||||
BufferHandle handle = Buffers.CreateBufferHandle();
|
||||
New<CreateHostBufferCommand>().Set(handle, pointer, size);
|
||||
New<CreateHostBufferCommand>()->Set(handle, pointer, size);
|
||||
QueueCommand();
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
public BufferHandle CreateBufferSparse(ReadOnlySpan<BufferRange> storageBuffers)
|
||||
public unsafe BufferHandle CreateBufferSparse(ReadOnlySpan<BufferRange> storageBuffers)
|
||||
{
|
||||
BufferHandle handle = Buffers.CreateBufferHandle();
|
||||
New<CreateBufferSparseCommand>().Set(handle, CopySpan(storageBuffers));
|
||||
New<CreateBufferSparseCommand>()->Set(handle, CopySpan(storageBuffers));
|
||||
QueueCommand();
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
public IImageArray CreateImageArray(int size, bool isBuffer)
|
||||
public unsafe IImageArray CreateImageArray(int size, bool isBuffer)
|
||||
{
|
||||
var imageArray = new ThreadedImageArray(this);
|
||||
New<CreateImageArrayCommand>().Set(Ref(imageArray), size, isBuffer);
|
||||
New<CreateImageArrayCommand>()->Set(Ref(imageArray), size, isBuffer);
|
||||
QueueCommand();
|
||||
|
||||
return imageArray;
|
||||
}
|
||||
|
||||
public IProgram CreateProgram(ShaderSource[] shaders, ShaderInfo info)
|
||||
public unsafe IProgram CreateProgram(ShaderSource[] shaders, ShaderInfo info)
|
||||
{
|
||||
var program = new ThreadedProgram(this);
|
||||
|
||||
@@ -311,34 +312,34 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||
|
||||
ProgramCount++;
|
||||
|
||||
New<CreateProgramCommand>().Set(Ref((IProgramRequest)request));
|
||||
New<CreateProgramCommand>()->Set(Ref((IProgramRequest)request));
|
||||
QueueCommand();
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
public ISampler CreateSampler(SamplerCreateInfo info)
|
||||
public unsafe ISampler CreateSampler(SamplerCreateInfo info)
|
||||
{
|
||||
var sampler = new ThreadedSampler(this);
|
||||
New<CreateSamplerCommand>().Set(Ref(sampler), info);
|
||||
New<CreateSamplerCommand>()->Set(Ref(sampler), info);
|
||||
QueueCommand();
|
||||
|
||||
return sampler;
|
||||
}
|
||||
|
||||
public void CreateSync(ulong id, bool strict)
|
||||
public unsafe void CreateSync(ulong id, bool strict)
|
||||
{
|
||||
Sync.CreateSyncHandle(id);
|
||||
New<CreateSyncCommand>().Set(id, strict);
|
||||
New<CreateSyncCommand>()->Set(id, strict);
|
||||
QueueCommand();
|
||||
}
|
||||
|
||||
public ITexture CreateTexture(TextureCreateInfo info)
|
||||
public unsafe ITexture CreateTexture(TextureCreateInfo info)
|
||||
{
|
||||
if (IsGpuThread())
|
||||
{
|
||||
var texture = new ThreadedTexture(this, info);
|
||||
New<CreateTextureCommand>().Set(Ref(texture), info);
|
||||
New<CreateTextureCommand>()->Set(Ref(texture), info);
|
||||
QueueCommand();
|
||||
|
||||
return texture;
|
||||
@@ -353,27 +354,27 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||
return texture;
|
||||
}
|
||||
}
|
||||
public ITextureArray CreateTextureArray(int size, bool isBuffer)
|
||||
public unsafe ITextureArray CreateTextureArray(int size, bool isBuffer)
|
||||
{
|
||||
var textureArray = new ThreadedTextureArray(this);
|
||||
New<CreateTextureArrayCommand>().Set(Ref(textureArray), size, isBuffer);
|
||||
New<CreateTextureArrayCommand>()->Set(Ref(textureArray), size, isBuffer);
|
||||
QueueCommand();
|
||||
|
||||
return textureArray;
|
||||
}
|
||||
|
||||
public void DeleteBuffer(BufferHandle buffer)
|
||||
public unsafe void DeleteBuffer(BufferHandle buffer)
|
||||
{
|
||||
New<BufferDisposeCommand>().Set(buffer);
|
||||
New<BufferDisposeCommand>()->Set(buffer);
|
||||
QueueCommand();
|
||||
}
|
||||
|
||||
public PinnedSpan<byte> GetBufferData(BufferHandle buffer, int offset, int size)
|
||||
public unsafe PinnedSpan<byte> GetBufferData(BufferHandle buffer, int offset, int size)
|
||||
{
|
||||
if (IsGpuThread())
|
||||
{
|
||||
ResultBox<PinnedSpan<byte>> box = new();
|
||||
New<BufferGetDataCommand>().Set(buffer, offset, size, Ref(box));
|
||||
New<BufferGetDataCommand>()->Set(buffer, offset, size, Ref(box));
|
||||
InvokeCommand();
|
||||
|
||||
return box.Result;
|
||||
@@ -384,10 +385,10 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||
}
|
||||
}
|
||||
|
||||
public Capabilities GetCapabilities()
|
||||
public unsafe Capabilities GetCapabilities()
|
||||
{
|
||||
ResultBox<Capabilities> box = new();
|
||||
New<GetCapabilitiesCommand>().Set(Ref(box));
|
||||
New<GetCapabilitiesCommand>()->Set(Ref(box));
|
||||
InvokeCommand();
|
||||
|
||||
return box.Result;
|
||||
@@ -412,29 +413,29 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||
_baseRenderer.Initialize(logLevel);
|
||||
}
|
||||
|
||||
public IProgram LoadProgramBinary(byte[] programBinary, bool hasFragmentShader, ShaderInfo info)
|
||||
public unsafe IProgram LoadProgramBinary(byte[] programBinary, bool hasFragmentShader, ShaderInfo info)
|
||||
{
|
||||
var program = new ThreadedProgram(this);
|
||||
|
||||
BinaryProgramRequest request = new(program, programBinary, hasFragmentShader, info);
|
||||
Programs.Add(request);
|
||||
|
||||
New<CreateProgramCommand>().Set(Ref((IProgramRequest)request));
|
||||
New<CreateProgramCommand>()->Set(Ref((IProgramRequest)request));
|
||||
QueueCommand();
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
public void PreFrame()
|
||||
public unsafe void PreFrame()
|
||||
{
|
||||
New<PreFrameCommand>();
|
||||
QueueCommand();
|
||||
}
|
||||
|
||||
public ICounterEvent ReportCounter(CounterType type, EventHandler<ulong> resultHandler, float divisor, bool hostReserved)
|
||||
public unsafe ICounterEvent ReportCounter(CounterType type, EventHandler<ulong> resultHandler, float divisor, bool hostReserved)
|
||||
{
|
||||
ThreadedCounterEvent evt = new(this, type, _lastSampleCounterClear);
|
||||
New<ReportCounterCommand>().Set(Ref(evt), type, Ref(resultHandler), divisor, hostReserved);
|
||||
New<ReportCounterCommand>()->Set(Ref(evt), type, Ref(resultHandler), divisor, hostReserved);
|
||||
QueueCommand();
|
||||
|
||||
if (type == CounterType.SamplesPassed)
|
||||
@@ -445,9 +446,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||
return evt;
|
||||
}
|
||||
|
||||
public void ResetCounter(CounterType type)
|
||||
public unsafe void ResetCounter(CounterType type)
|
||||
{
|
||||
New<ResetCounterCommand>().Set(type);
|
||||
New<ResetCounterCommand>()->Set(type);
|
||||
QueueCommand();
|
||||
_lastSampleCounterClear = true;
|
||||
}
|
||||
@@ -457,13 +458,13 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||
_baseRenderer.Screenshot();
|
||||
}
|
||||
|
||||
public void SetBufferData(BufferHandle buffer, int offset, ReadOnlySpan<byte> data)
|
||||
public unsafe void SetBufferData(BufferHandle buffer, int offset, ReadOnlySpan<byte> data)
|
||||
{
|
||||
New<BufferSetDataCommand>().Set(buffer, offset, CopySpan(data));
|
||||
New<BufferSetDataCommand>()->Set(buffer, offset, CopySpan(data));
|
||||
QueueCommand();
|
||||
}
|
||||
|
||||
public void UpdateCounters()
|
||||
public unsafe void UpdateCounters()
|
||||
{
|
||||
New<UpdateCountersCommand>();
|
||||
QueueCommand();
|
||||
|
||||
Reference in New Issue
Block a user