mirror of
https://git.ryujinx.app/kenji-nx/ryujinx.git
synced 2025-12-12 10:37:06 +00: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:
parent
cdbe568620
commit
f98af9e175
20 changed files with 295 additions and 232 deletions
|
|
@ -100,7 +100,6 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||
break;
|
||||
case CommandType.BiquadFilterFloatCoeff:
|
||||
throw new NotImplementedException();
|
||||
break;
|
||||
case CommandType.Mix:
|
||||
_mixCommandPool.Release((MixCommand)command);
|
||||
break;
|
||||
|
|
@ -160,7 +159,6 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||
break;
|
||||
case CommandType.MultiTapBiquadFilterFloatCoeff:
|
||||
throw new NotImplementedException();
|
||||
break;
|
||||
case CommandType.CaptureBuffer:
|
||||
_captureBufferCommandPool.Release((CaptureBufferCommand)command);
|
||||
break;
|
||||
|
|
@ -172,25 +170,19 @@ namespace Ryujinx.Audio.Renderer.Server
|
|||
break;
|
||||
case CommandType.BiquadFilterAndMixFloatCoeff:
|
||||
throw new NotImplementedException();
|
||||
break;
|
||||
case CommandType.MultiTapBiquadFilterAndMix:
|
||||
_multiTapBiquadFilterAndMixCommandPool.Release((MultiTapBiquadFilterAndMixCommand)command);
|
||||
break;
|
||||
case CommandType.MultiTapBiquadFilterAndMixFloatCoef:
|
||||
throw new NotImplementedException();
|
||||
break;
|
||||
case CommandType.AuxiliaryBufferGrouped:
|
||||
throw new NotImplementedException();
|
||||
break;
|
||||
case CommandType.FillMixBuffer:
|
||||
throw new NotImplementedException();
|
||||
break;
|
||||
case CommandType.BiquadFilterCrossFade:
|
||||
throw new NotImplementedException();
|
||||
break;
|
||||
case CommandType.MultiTapBiquadFilterCrossFade:
|
||||
throw new NotImplementedException();
|
||||
break;
|
||||
case CommandType.FillBuffer:
|
||||
_fillBufferCommandPool.Release((FillBufferCommand)command);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ namespace Ryujinx.Common
|
|||
where T : class
|
||||
{
|
||||
private int _size = size;
|
||||
private readonly ConcurrentStack<T> _items = new();
|
||||
private readonly ConcurrentBag<T> _items = new();
|
||||
|
||||
public T Allocate()
|
||||
{
|
||||
bool success = _items.TryPop(out T instance);
|
||||
bool success = _items.TryTake(out T instance);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
|
|
@ -26,7 +26,7 @@ namespace Ryujinx.Common
|
|||
{
|
||||
if (_size < 0 || _items.Count < _size)
|
||||
{
|
||||
_items.Push(obj);
|
||||
_items.Add(obj);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -151,6 +151,11 @@ namespace Ryujinx.Cpu.AppleHv
|
|||
}
|
||||
}
|
||||
|
||||
public override bool TryReadUnsafe(ulong va, int length, out Span<byte> data)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void Write(ulong va, ReadOnlySpan<byte> data)
|
||||
{
|
||||
try
|
||||
|
|
|
|||
|
|
@ -175,6 +175,11 @@ namespace Ryujinx.Cpu.Jit
|
|||
}
|
||||
}
|
||||
|
||||
public override bool TryReadUnsafe(ulong va, int length, out Span<byte> data)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void Write(ulong va, ReadOnlySpan<byte> data)
|
||||
{
|
||||
try
|
||||
|
|
|
|||
|
|
@ -152,6 +152,11 @@ namespace Ryujinx.Cpu.Jit
|
|||
}
|
||||
}
|
||||
|
||||
public override bool TryReadUnsafe(ulong va, int length, out Span<byte> data)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override T ReadTracked<T>(ulong va)
|
||||
{
|
||||
try
|
||||
|
|
|
|||
|
|
@ -233,6 +233,11 @@ namespace Ryujinx.Cpu.Jit
|
|||
}
|
||||
}
|
||||
|
||||
public override bool TryReadUnsafe(ulong va, int length, out Span<byte> data)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override bool WriteWithRedundancyCheck(ulong va, ReadOnlySpan<byte> data)
|
||||
{
|
||||
if (data.Length == 0)
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
|
|||
return new TableRef<T>(_renderer, reference);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
public unsafe void Dispose()
|
||||
{
|
||||
_renderer.New<CounterEventDisposeCommand>().Set(Ref(this));
|
||||
_renderer.New<CounterEventDisposeCommand>()->Set(Ref(this));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,15 +21,15 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
|
|||
return new TableRef<T>(_renderer, reference);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
public unsafe void Dispose()
|
||||
{
|
||||
_renderer.New<ImageArrayDisposeCommand>().Set(Ref(this));
|
||||
_renderer.New<ImageArrayDisposeCommand>()->Set(Ref(this));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetImages(int index, ITexture[] images)
|
||||
public unsafe void SetImages(int index, ITexture[] images)
|
||||
{
|
||||
_renderer.New<ImageArraySetImagesCommand>().Set(Ref(this), index, Ref(images));
|
||||
_renderer.New<ImageArraySetImagesCommand>()->Set(Ref(this), index, Ref(images));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,25 +21,25 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
|
|||
return new TableRef<T>(_renderer, reference);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
public unsafe void Dispose()
|
||||
{
|
||||
_renderer.New<ProgramDisposeCommand>().Set(Ref(this));
|
||||
_renderer.New<ProgramDisposeCommand>()->Set(Ref(this));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public byte[] GetBinary()
|
||||
public unsafe byte[] GetBinary()
|
||||
{
|
||||
ResultBox<byte[]> box = new();
|
||||
_renderer.New<ProgramGetBinaryCommand>().Set(Ref(this), Ref(box));
|
||||
_renderer.New<ProgramGetBinaryCommand>()->Set(Ref(this), Ref(box));
|
||||
_renderer.InvokeCommand();
|
||||
|
||||
return box.Result;
|
||||
}
|
||||
|
||||
public ProgramLinkStatus CheckProgramLink(bool blocking)
|
||||
public unsafe ProgramLinkStatus CheckProgramLink(bool blocking)
|
||||
{
|
||||
ResultBox<ProgramLinkStatus> box = new();
|
||||
_renderer.New<ProgramCheckLinkCommand>().Set(Ref(this), blocking, Ref(box));
|
||||
_renderer.New<ProgramCheckLinkCommand>()->Set(Ref(this), blocking, Ref(box));
|
||||
_renderer.InvokeCommand();
|
||||
|
||||
return box.Result;
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
|
|||
_renderer = renderer;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
public unsafe void Dispose()
|
||||
{
|
||||
_renderer.New<SamplerDisposeCommand>().Set(new TableRef<ThreadedSampler>(_renderer, this));
|
||||
_renderer.New<SamplerDisposeCommand>()->Set(new TableRef<ThreadedSampler>(_renderer, this));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,25 +28,25 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
|
|||
return new TableRef<T>(_renderer, reference);
|
||||
}
|
||||
|
||||
public void CopyTo(ITexture destination, int firstLayer, int firstLevel)
|
||||
public unsafe void CopyTo(ITexture destination, int firstLayer, int firstLevel)
|
||||
{
|
||||
_renderer.New<TextureCopyToCommand>().Set(Ref(this), Ref((ThreadedTexture)destination), firstLayer, firstLevel);
|
||||
_renderer.New<TextureCopyToCommand>()->Set(Ref(this), Ref((ThreadedTexture)destination), firstLayer, firstLevel);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void CopyTo(ITexture destination, int srcLayer, int dstLayer, int srcLevel, int dstLevel)
|
||||
public unsafe void CopyTo(ITexture destination, int srcLayer, int dstLayer, int srcLevel, int dstLevel)
|
||||
{
|
||||
_renderer.New<TextureCopyToSliceCommand>().Set(Ref(this), Ref((ThreadedTexture)destination), srcLayer, dstLayer, srcLevel, dstLevel);
|
||||
_renderer.New<TextureCopyToSliceCommand>()->Set(Ref(this), Ref((ThreadedTexture)destination), srcLayer, dstLayer, srcLevel, dstLevel);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void CopyTo(ITexture destination, Extents2D srcRegion, Extents2D dstRegion, bool linearFilter)
|
||||
public unsafe void CopyTo(ITexture destination, Extents2D srcRegion, Extents2D dstRegion, bool linearFilter)
|
||||
{
|
||||
ThreadedTexture dest = (ThreadedTexture)destination;
|
||||
|
||||
if (_renderer.IsGpuThread())
|
||||
{
|
||||
_renderer.New<TextureCopyToScaledCommand>().Set(Ref(this), Ref(dest), srcRegion, dstRegion, linearFilter);
|
||||
_renderer.New<TextureCopyToScaledCommand>()->Set(Ref(this), Ref(dest), srcRegion, dstRegion, linearFilter);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
else
|
||||
|
|
@ -59,21 +59,21 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
|
|||
}
|
||||
}
|
||||
|
||||
public ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel)
|
||||
public unsafe ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel)
|
||||
{
|
||||
ThreadedTexture newTex = new(_renderer, info);
|
||||
_renderer.New<TextureCreateViewCommand>().Set(Ref(this), Ref(newTex), info, firstLayer, firstLevel);
|
||||
_renderer.New<TextureCreateViewCommand>()->Set(Ref(this), Ref(newTex), info, firstLayer, firstLevel);
|
||||
_renderer.QueueCommand();
|
||||
|
||||
return newTex;
|
||||
}
|
||||
|
||||
public PinnedSpan<byte> GetData()
|
||||
public unsafe PinnedSpan<byte> GetData()
|
||||
{
|
||||
if (_renderer.IsGpuThread())
|
||||
{
|
||||
ResultBox<PinnedSpan<byte>> box = new();
|
||||
_renderer.New<TextureGetDataCommand>().Set(Ref(this), Ref(box));
|
||||
_renderer.New<TextureGetDataCommand>()->Set(Ref(this), Ref(box));
|
||||
_renderer.InvokeCommand();
|
||||
|
||||
return box.Result;
|
||||
|
|
@ -86,12 +86,12 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
|
|||
}
|
||||
}
|
||||
|
||||
public PinnedSpan<byte> GetData(int layer, int level)
|
||||
public unsafe PinnedSpan<byte> GetData(int layer, int level)
|
||||
{
|
||||
if (_renderer.IsGpuThread())
|
||||
{
|
||||
ResultBox<PinnedSpan<byte>> box = new();
|
||||
_renderer.New<TextureGetDataSliceCommand>().Set(Ref(this), Ref(box), layer, level);
|
||||
_renderer.New<TextureGetDataSliceCommand>()->Set(Ref(this), Ref(box), layer, level);
|
||||
_renderer.InvokeCommand();
|
||||
|
||||
return box.Result;
|
||||
|
|
@ -104,42 +104,42 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
|
|||
}
|
||||
}
|
||||
|
||||
public void CopyTo(BufferRange range, int layer, int level, int stride)
|
||||
public unsafe void CopyTo(BufferRange range, int layer, int level, int stride)
|
||||
{
|
||||
_renderer.New<TextureCopyToBufferCommand>().Set(Ref(this), range, layer, level, stride);
|
||||
_renderer.New<TextureCopyToBufferCommand>()->Set(Ref(this), range, layer, level, stride);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void SetData(MemoryOwner<byte> data)
|
||||
public unsafe void SetData(MemoryOwner<byte> data)
|
||||
{
|
||||
_renderer.New<TextureSetDataCommand>().Set(Ref(this), Ref(data));
|
||||
_renderer.New<TextureSetDataCommand>()->Set(Ref(this), Ref(data));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void SetData(MemoryOwner<byte> data, int layer, int level)
|
||||
public unsafe void SetData(MemoryOwner<byte> data, int layer, int level)
|
||||
{
|
||||
_renderer.New<TextureSetDataSliceCommand>().Set(Ref(this), Ref(data), layer, level);
|
||||
_renderer.New<TextureSetDataSliceCommand>()->Set(Ref(this), Ref(data), layer, level);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void SetData(MemoryOwner<byte> data, int layer, int level, Rectangle<int> region)
|
||||
public unsafe void SetData(MemoryOwner<byte> data, int layer, int level, Rectangle<int> region)
|
||||
{
|
||||
_renderer.New<TextureSetDataSliceRegionCommand>().Set(Ref(this), Ref(data), layer, level, region);
|
||||
_renderer.New<TextureSetDataSliceRegionCommand>()->Set(Ref(this), Ref(data), layer, level, region);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetStorage(BufferRange buffer)
|
||||
public unsafe void SetStorage(BufferRange buffer)
|
||||
{
|
||||
_renderer.New<TextureSetStorageCommand>().Set(Ref(this), buffer);
|
||||
_renderer.New<TextureSetStorageCommand>()->Set(Ref(this), buffer);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void Release()
|
||||
public unsafe void Release()
|
||||
{
|
||||
_renderer.New<TextureReleaseCommand>().Set(Ref(this));
|
||||
_renderer.New<TextureReleaseCommand>()->Set(Ref(this));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,21 +22,21 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
|
|||
return new TableRef<T>(_renderer, reference);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
public unsafe void Dispose()
|
||||
{
|
||||
_renderer.New<TextureArrayDisposeCommand>().Set(Ref(this));
|
||||
_renderer.New<TextureArrayDisposeCommand>()->Set(Ref(this));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetSamplers(int index, ISampler[] samplers)
|
||||
public unsafe void SetSamplers(int index, ISampler[] samplers)
|
||||
{
|
||||
_renderer.New<TextureArraySetSamplersCommand>().Set(Ref(this), index, Ref(samplers.ToArray()));
|
||||
_renderer.New<TextureArraySetSamplersCommand>()->Set(Ref(this), index, Ref(samplers.ToArray()));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetTextures(int index, ITexture[] textures)
|
||||
public unsafe void SetTextures(int index, ITexture[] textures)
|
||||
{
|
||||
_renderer.New<TextureArraySetTexturesCommand>().Set(Ref(this), index, Ref(textures.ToArray()));
|
||||
_renderer.New<TextureArraySetTexturesCommand>()->Set(Ref(this), index, Ref(textures.ToArray()));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,343 +21,343 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
|||
return new TableRef<T>(_renderer, reference);
|
||||
}
|
||||
|
||||
public void Barrier()
|
||||
public unsafe void Barrier()
|
||||
{
|
||||
_renderer.New<BarrierCommand>();
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void BeginTransformFeedback(PrimitiveTopology topology)
|
||||
public unsafe void BeginTransformFeedback(PrimitiveTopology topology)
|
||||
{
|
||||
_renderer.New<BeginTransformFeedbackCommand>().Set(topology);
|
||||
_renderer.New<BeginTransformFeedbackCommand>()->Set(topology);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void ClearBuffer(BufferHandle destination, int offset, int size, uint value)
|
||||
public unsafe void ClearBuffer(BufferHandle destination, int offset, int size, uint value)
|
||||
{
|
||||
_renderer.New<ClearBufferCommand>().Set(destination, offset, size, value);
|
||||
_renderer.New<ClearBufferCommand>()->Set(destination, offset, size, value);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void ClearRenderTargetColor(int index, int layer, int layerCount, uint componentMask, ColorF color)
|
||||
public unsafe void ClearRenderTargetColor(int index, int layer, int layerCount, uint componentMask, ColorF color)
|
||||
{
|
||||
_renderer.New<ClearRenderTargetColorCommand>().Set(index, layer, layerCount, componentMask, color);
|
||||
_renderer.New<ClearRenderTargetColorCommand>()->Set(index, layer, layerCount, componentMask, color);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask)
|
||||
public unsafe void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask)
|
||||
{
|
||||
_renderer.New<ClearRenderTargetDepthStencilCommand>().Set(layer, layerCount, depthValue, depthMask, stencilValue, stencilMask);
|
||||
_renderer.New<ClearRenderTargetDepthStencilCommand>()->Set(layer, layerCount, depthValue, depthMask, stencilValue, stencilMask);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void CommandBufferBarrier()
|
||||
public unsafe void CommandBufferBarrier()
|
||||
{
|
||||
_renderer.New<CommandBufferBarrierCommand>();
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void CopyBuffer(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size)
|
||||
public unsafe void CopyBuffer(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size)
|
||||
{
|
||||
_renderer.New<CopyBufferCommand>().Set(source, destination, srcOffset, dstOffset, size);
|
||||
_renderer.New<CopyBufferCommand>()->Set(source, destination, srcOffset, dstOffset, size);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void DispatchCompute(int groupsX, int groupsY, int groupsZ)
|
||||
public unsafe void DispatchCompute(int groupsX, int groupsY, int groupsZ)
|
||||
{
|
||||
_renderer.New<DispatchComputeCommand>().Set(groupsX, groupsY, groupsZ);
|
||||
_renderer.New<DispatchComputeCommand>()->Set(groupsX, groupsY, groupsZ);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance)
|
||||
public unsafe void Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance)
|
||||
{
|
||||
_renderer.New<DrawCommand>().Set(vertexCount, instanceCount, firstVertex, firstInstance);
|
||||
_renderer.New<DrawCommand>()->Set(vertexCount, instanceCount, firstVertex, firstInstance);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void DrawIndexed(int indexCount, int instanceCount, int firstIndex, int firstVertex, int firstInstance)
|
||||
public unsafe void DrawIndexed(int indexCount, int instanceCount, int firstIndex, int firstVertex, int firstInstance)
|
||||
{
|
||||
_renderer.New<DrawIndexedCommand>().Set(indexCount, instanceCount, firstIndex, firstVertex, firstInstance);
|
||||
_renderer.New<DrawIndexedCommand>()->Set(indexCount, instanceCount, firstIndex, firstVertex, firstInstance);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void DrawIndexedIndirect(BufferRange indirectBuffer)
|
||||
public unsafe void DrawIndexedIndirect(BufferRange indirectBuffer)
|
||||
{
|
||||
_renderer.New<DrawIndexedIndirectCommand>().Set(indirectBuffer);
|
||||
_renderer.New<DrawIndexedIndirectCommand>()->Set(indirectBuffer);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void DrawIndexedIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
|
||||
public unsafe void DrawIndexedIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
|
||||
{
|
||||
_renderer.New<DrawIndexedIndirectCountCommand>().Set(indirectBuffer, parameterBuffer, maxDrawCount, stride);
|
||||
_renderer.New<DrawIndexedIndirectCountCommand>()->Set(indirectBuffer, parameterBuffer, maxDrawCount, stride);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void DrawIndirect(BufferRange indirectBuffer)
|
||||
public unsafe void DrawIndirect(BufferRange indirectBuffer)
|
||||
{
|
||||
_renderer.New<DrawIndirectCommand>().Set(indirectBuffer);
|
||||
_renderer.New<DrawIndirectCommand>()->Set(indirectBuffer);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void DrawIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
|
||||
public unsafe void DrawIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
|
||||
{
|
||||
_renderer.New<DrawIndirectCountCommand>().Set(indirectBuffer, parameterBuffer, maxDrawCount, stride);
|
||||
_renderer.New<DrawIndirectCountCommand>()->Set(indirectBuffer, parameterBuffer, maxDrawCount, stride);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void DrawTexture(ITexture texture, ISampler sampler, Extents2DF srcRegion, Extents2DF dstRegion)
|
||||
public unsafe void DrawTexture(ITexture texture, ISampler sampler, Extents2DF srcRegion, Extents2DF dstRegion)
|
||||
{
|
||||
_renderer.New<DrawTextureCommand>().Set(Ref(texture), Ref(sampler), srcRegion, dstRegion);
|
||||
_renderer.New<DrawTextureCommand>()->Set(Ref(texture), Ref(sampler), srcRegion, dstRegion);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void EndHostConditionalRendering()
|
||||
public unsafe void EndHostConditionalRendering()
|
||||
{
|
||||
_renderer.New<EndHostConditionalRenderingCommand>();
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void EndTransformFeedback()
|
||||
public unsafe void EndTransformFeedback()
|
||||
{
|
||||
_renderer.New<EndTransformFeedbackCommand>();
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetAlphaTest(bool enable, float reference, CompareOp op)
|
||||
public unsafe void SetAlphaTest(bool enable, float reference, CompareOp op)
|
||||
{
|
||||
_renderer.New<SetAlphaTestCommand>().Set(enable, reference, op);
|
||||
_renderer.New<SetAlphaTestCommand>()->Set(enable, reference, op);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetBlendState(AdvancedBlendDescriptor blend)
|
||||
public unsafe void SetBlendState(AdvancedBlendDescriptor blend)
|
||||
{
|
||||
_renderer.New<SetBlendStateAdvancedCommand>().Set(blend);
|
||||
_renderer.New<SetBlendStateAdvancedCommand>()->Set(blend);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetBlendState(int index, BlendDescriptor blend)
|
||||
public unsafe void SetBlendState(int index, BlendDescriptor blend)
|
||||
{
|
||||
_renderer.New<SetBlendStateCommand>().Set(index, blend);
|
||||
_renderer.New<SetBlendStateCommand>()->Set(index, blend);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp)
|
||||
public unsafe void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp)
|
||||
{
|
||||
_renderer.New<SetDepthBiasCommand>().Set(enables, factor, units, clamp);
|
||||
_renderer.New<SetDepthBiasCommand>()->Set(enables, factor, units, clamp);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetDepthClamp(bool clamp)
|
||||
public unsafe void SetDepthClamp(bool clamp)
|
||||
{
|
||||
_renderer.New<SetDepthClampCommand>().Set(clamp);
|
||||
_renderer.New<SetDepthClampCommand>()->Set(clamp);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetDepthMode(DepthMode mode)
|
||||
public unsafe void SetDepthMode(DepthMode mode)
|
||||
{
|
||||
_renderer.New<SetDepthModeCommand>().Set(mode);
|
||||
_renderer.New<SetDepthModeCommand>()->Set(mode);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetDepthTest(DepthTestDescriptor depthTest)
|
||||
public unsafe void SetDepthTest(DepthTestDescriptor depthTest)
|
||||
{
|
||||
_renderer.New<SetDepthTestCommand>().Set(depthTest);
|
||||
_renderer.New<SetDepthTestCommand>()->Set(depthTest);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetFaceCulling(bool enable, Face face)
|
||||
public unsafe void SetFaceCulling(bool enable, Face face)
|
||||
{
|
||||
_renderer.New<SetFaceCullingCommand>().Set(enable, face);
|
||||
_renderer.New<SetFaceCullingCommand>()->Set(enable, face);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetFrontFace(FrontFace frontFace)
|
||||
public unsafe void SetFrontFace(FrontFace frontFace)
|
||||
{
|
||||
_renderer.New<SetFrontFaceCommand>().Set(frontFace);
|
||||
_renderer.New<SetFrontFaceCommand>()->Set(frontFace);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetImage(ShaderStage stage, int binding, ITexture texture)
|
||||
public unsafe void SetImage(ShaderStage stage, int binding, ITexture texture)
|
||||
{
|
||||
_renderer.New<SetImageCommand>().Set(stage, binding, Ref(texture));
|
||||
_renderer.New<SetImageCommand>()->Set(stage, binding, Ref(texture));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetImageArray(ShaderStage stage, int binding, IImageArray array)
|
||||
public unsafe void SetImageArray(ShaderStage stage, int binding, IImageArray array)
|
||||
{
|
||||
_renderer.New<SetImageArrayCommand>().Set(stage, binding, Ref(array));
|
||||
_renderer.New<SetImageArrayCommand>()->Set(stage, binding, Ref(array));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetImageArraySeparate(ShaderStage stage, int setIndex, IImageArray array)
|
||||
public unsafe void SetImageArraySeparate(ShaderStage stage, int setIndex, IImageArray array)
|
||||
{
|
||||
_renderer.New<SetImageArraySeparateCommand>().Set(stage, setIndex, Ref(array));
|
||||
_renderer.New<SetImageArraySeparateCommand>()->Set(stage, setIndex, Ref(array));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetIndexBuffer(BufferRange buffer, IndexType type)
|
||||
public unsafe void SetIndexBuffer(BufferRange buffer, IndexType type)
|
||||
{
|
||||
_renderer.New<SetIndexBufferCommand>().Set(buffer, type);
|
||||
_renderer.New<SetIndexBufferCommand>()->Set(buffer, type);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetLineParameters(float width, bool smooth)
|
||||
public unsafe void SetLineParameters(float width, bool smooth)
|
||||
{
|
||||
_renderer.New<SetLineParametersCommand>().Set(width, smooth);
|
||||
_renderer.New<SetLineParametersCommand>()->Set(width, smooth);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetLogicOpState(bool enable, LogicalOp op)
|
||||
public unsafe void SetLogicOpState(bool enable, LogicalOp op)
|
||||
{
|
||||
_renderer.New<SetLogicOpStateCommand>().Set(enable, op);
|
||||
_renderer.New<SetLogicOpStateCommand>()->Set(enable, op);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetMultisampleState(MultisampleDescriptor multisample)
|
||||
public unsafe void SetMultisampleState(MultisampleDescriptor multisample)
|
||||
{
|
||||
_renderer.New<SetMultisampleStateCommand>().Set(multisample);
|
||||
_renderer.New<SetMultisampleStateCommand>()->Set(multisample);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetPatchParameters(int vertices, ReadOnlySpan<float> defaultOuterLevel, ReadOnlySpan<float> defaultInnerLevel)
|
||||
public unsafe void SetPatchParameters(int vertices, ReadOnlySpan<float> defaultOuterLevel, ReadOnlySpan<float> defaultInnerLevel)
|
||||
{
|
||||
_renderer.New<SetPatchParametersCommand>().Set(vertices, defaultOuterLevel, defaultInnerLevel);
|
||||
_renderer.New<SetPatchParametersCommand>()->Set(vertices, defaultOuterLevel, defaultInnerLevel);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetPointParameters(float size, bool isProgramPointSize, bool enablePointSprite, Origin origin)
|
||||
public unsafe void SetPointParameters(float size, bool isProgramPointSize, bool enablePointSprite, Origin origin)
|
||||
{
|
||||
_renderer.New<SetPointParametersCommand>().Set(size, isProgramPointSize, enablePointSprite, origin);
|
||||
_renderer.New<SetPointParametersCommand>()->Set(size, isProgramPointSize, enablePointSprite, origin);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetPolygonMode(PolygonMode frontMode, PolygonMode backMode)
|
||||
public unsafe void SetPolygonMode(PolygonMode frontMode, PolygonMode backMode)
|
||||
{
|
||||
_renderer.New<SetPolygonModeCommand>().Set(frontMode, backMode);
|
||||
_renderer.New<SetPolygonModeCommand>()->Set(frontMode, backMode);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetPrimitiveRestart(bool enable, int index)
|
||||
public unsafe void SetPrimitiveRestart(bool enable, int index)
|
||||
{
|
||||
_renderer.New<SetPrimitiveRestartCommand>().Set(enable, index);
|
||||
_renderer.New<SetPrimitiveRestartCommand>()->Set(enable, index);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetPrimitiveTopology(PrimitiveTopology topology)
|
||||
public unsafe void SetPrimitiveTopology(PrimitiveTopology topology)
|
||||
{
|
||||
_renderer.New<SetPrimitiveTopologyCommand>().Set(topology);
|
||||
_renderer.New<SetPrimitiveTopologyCommand>()->Set(topology);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetProgram(IProgram program)
|
||||
public unsafe void SetProgram(IProgram program)
|
||||
{
|
||||
_renderer.New<SetProgramCommand>().Set(Ref(program));
|
||||
_renderer.New<SetProgramCommand>()->Set(Ref(program));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetRasterizerDiscard(bool discard)
|
||||
public unsafe void SetRasterizerDiscard(bool discard)
|
||||
{
|
||||
_renderer.New<SetRasterizerDiscardCommand>().Set(discard);
|
||||
_renderer.New<SetRasterizerDiscardCommand>()->Set(discard);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMask)
|
||||
public unsafe void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMask)
|
||||
{
|
||||
_renderer.New<SetRenderTargetColorMasksCommand>().Set(_renderer.CopySpan(componentMask));
|
||||
_renderer.New<SetRenderTargetColorMasksCommand>()->Set(_renderer.CopySpan(componentMask));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetRenderTargets(ITexture[] colors, ITexture depthStencil)
|
||||
public unsafe void SetRenderTargets(ITexture[] colors, ITexture depthStencil)
|
||||
{
|
||||
_renderer.New<SetRenderTargetsCommand>().Set(Ref(colors.ToArray()), Ref(depthStencil));
|
||||
_renderer.New<SetRenderTargetsCommand>()->Set(Ref(colors.ToArray()), Ref(depthStencil));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetScissors(ReadOnlySpan<Rectangle<int>> scissors)
|
||||
public unsafe void SetScissors(ReadOnlySpan<Rectangle<int>> scissors)
|
||||
{
|
||||
_renderer.New<SetScissorsCommand>().Set(_renderer.CopySpan(scissors));
|
||||
_renderer.New<SetScissorsCommand>()->Set(_renderer.CopySpan(scissors));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetStencilTest(StencilTestDescriptor stencilTest)
|
||||
public unsafe void SetStencilTest(StencilTestDescriptor stencilTest)
|
||||
{
|
||||
_renderer.New<SetStencilTestCommand>().Set(stencilTest);
|
||||
_renderer.New<SetStencilTestCommand>()->Set(stencilTest);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetStorageBuffers(ReadOnlySpan<BufferAssignment> buffers)
|
||||
public unsafe void SetStorageBuffers(ReadOnlySpan<BufferAssignment> buffers)
|
||||
{
|
||||
_renderer.New<SetStorageBuffersCommand>().Set(_renderer.CopySpan(buffers));
|
||||
_renderer.New<SetStorageBuffersCommand>()->Set(_renderer.CopySpan(buffers));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetTextureAndSampler(ShaderStage stage, int binding, ITexture texture, ISampler sampler)
|
||||
public unsafe void SetTextureAndSampler(ShaderStage stage, int binding, ITexture texture, ISampler sampler)
|
||||
{
|
||||
_renderer.New<SetTextureAndSamplerCommand>().Set(stage, binding, Ref(texture), Ref(sampler));
|
||||
_renderer.New<SetTextureAndSamplerCommand>()->Set(stage, binding, Ref(texture), Ref(sampler));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetTextureArray(ShaderStage stage, int binding, ITextureArray array)
|
||||
public unsafe void SetTextureArray(ShaderStage stage, int binding, ITextureArray array)
|
||||
{
|
||||
_renderer.New<SetTextureArrayCommand>().Set(stage, binding, Ref(array));
|
||||
_renderer.New<SetTextureArrayCommand>()->Set(stage, binding, Ref(array));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetTextureArraySeparate(ShaderStage stage, int setIndex, ITextureArray array)
|
||||
public unsafe void SetTextureArraySeparate(ShaderStage stage, int setIndex, ITextureArray array)
|
||||
{
|
||||
_renderer.New<SetTextureArraySeparateCommand>().Set(stage, setIndex, Ref(array));
|
||||
_renderer.New<SetTextureArraySeparateCommand>()->Set(stage, setIndex, Ref(array));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetTransformFeedbackBuffers(ReadOnlySpan<BufferRange> buffers)
|
||||
public unsafe void SetTransformFeedbackBuffers(ReadOnlySpan<BufferRange> buffers)
|
||||
{
|
||||
_renderer.New<SetTransformFeedbackBuffersCommand>().Set(_renderer.CopySpan(buffers));
|
||||
_renderer.New<SetTransformFeedbackBuffersCommand>()->Set(_renderer.CopySpan(buffers));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetUniformBuffers(ReadOnlySpan<BufferAssignment> buffers)
|
||||
public unsafe void SetUniformBuffers(ReadOnlySpan<BufferAssignment> buffers)
|
||||
{
|
||||
_renderer.New<SetUniformBuffersCommand>().Set(_renderer.CopySpan(buffers));
|
||||
_renderer.New<SetUniformBuffersCommand>()->Set(_renderer.CopySpan(buffers));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetUserClipDistance(int index, bool enableClip)
|
||||
public unsafe void SetUserClipDistance(int index, bool enableClip)
|
||||
{
|
||||
_renderer.New<SetUserClipDistanceCommand>().Set(index, enableClip);
|
||||
_renderer.New<SetUserClipDistanceCommand>()->Set(index, enableClip);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs)
|
||||
public unsafe void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs)
|
||||
{
|
||||
_renderer.New<SetVertexAttribsCommand>().Set(_renderer.CopySpan(vertexAttribs));
|
||||
_renderer.New<SetVertexAttribsCommand>()->Set(_renderer.CopySpan(vertexAttribs));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers)
|
||||
public unsafe void SetVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers)
|
||||
{
|
||||
_renderer.New<SetVertexBuffersCommand>().Set(_renderer.CopySpan(vertexBuffers));
|
||||
_renderer.New<SetVertexBuffersCommand>()->Set(_renderer.CopySpan(vertexBuffers));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetViewports(ReadOnlySpan<Viewport> viewports)
|
||||
public unsafe void SetViewports(ReadOnlySpan<Viewport> viewports)
|
||||
{
|
||||
_renderer.New<SetViewportsCommand>().Set(_renderer.CopySpan(viewports));
|
||||
_renderer.New<SetViewportsCommand>()->Set(_renderer.CopySpan(viewports));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void TextureBarrier()
|
||||
public unsafe void TextureBarrier()
|
||||
{
|
||||
_renderer.New<TextureBarrierCommand>();
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void TextureBarrierTiled()
|
||||
public unsafe void TextureBarrierTiled()
|
||||
{
|
||||
_renderer.New<TextureBarrierTiledCommand>();
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual)
|
||||
public unsafe bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual)
|
||||
{
|
||||
var evt = value as ThreadedCounterEvent;
|
||||
if (evt != null)
|
||||
|
|
@ -369,20 +369,20 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
|||
return false;
|
||||
}
|
||||
|
||||
_renderer.New<TryHostConditionalRenderingCommand>().Set(Ref(evt), compare, isEqual);
|
||||
_renderer.New<TryHostConditionalRenderingCommand>()->Set(Ref(evt), compare, isEqual);
|
||||
_renderer.QueueCommand();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
_renderer.New<TryHostConditionalRenderingFlushCommand>().Set(Ref(evt), Ref<ThreadedCounterEvent>(null), isEqual);
|
||||
_renderer.New<TryHostConditionalRenderingFlushCommand>()->Set(Ref(evt), Ref<ThreadedCounterEvent>(null), isEqual);
|
||||
_renderer.QueueCommand();
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryHostConditionalRendering(ICounterEvent value, ICounterEvent compare, bool isEqual)
|
||||
public unsafe bool TryHostConditionalRendering(ICounterEvent value, ICounterEvent compare, bool isEqual)
|
||||
{
|
||||
_renderer.New<TryHostConditionalRenderingFlushCommand>().Set(Ref(value as ThreadedCounterEvent), Ref(compare as ThreadedCounterEvent), isEqual);
|
||||
_renderer.New<TryHostConditionalRenderingFlushCommand>()->Set(Ref(value as ThreadedCounterEvent), Ref(compare as ThreadedCounterEvent), isEqual);
|
||||
_renderer.QueueCommand();
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -16,13 +16,13 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
|||
_impl = impl;
|
||||
}
|
||||
|
||||
public void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback)
|
||||
public unsafe void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback)
|
||||
{
|
||||
// If there's already a frame in the pipeline, wait for it to be presented first.
|
||||
// This is a multithread rate limit - we can't be more than one frame behind the command queue.
|
||||
|
||||
_renderer.WaitForFrame();
|
||||
_renderer.New<WindowPresentCommand>().Set(new TableRef<ThreadedTexture>(_renderer, texture as ThreadedTexture), crop, new TableRef<Action>(_renderer, swapBuffersCallback));
|
||||
_renderer.New<WindowPresentCommand>()->Set(new TableRef<ThreadedTexture>(_renderer, texture as ThreadedTexture), crop, new TableRef<Action>(_renderer, swapBuffersCallback));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,12 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
/// </summary>
|
||||
internal CounterCache CounterCache { get; }
|
||||
|
||||
private delegate void WriteCallback(ulong address, ReadOnlySpan<byte> data);
|
||||
|
||||
private WriteCallback _write;
|
||||
private WriteCallback _writeTrackedResource;
|
||||
private WriteCallback _writeUntracked;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the GPU memory manager.
|
||||
/// </summary>
|
||||
|
|
@ -58,6 +64,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
internal MemoryManager(PhysicalMemory physicalMemory, ulong cpuMemorySize)
|
||||
{
|
||||
Physical = physicalMemory;
|
||||
_write = physicalMemory.Write;
|
||||
_writeTrackedResource = physicalMemory.WriteTrackedResource;
|
||||
_writeUntracked = physicalMemory.WriteUntracked;
|
||||
VirtualRangeCache = new VirtualRangeCache(this);
|
||||
CounterCache = new CounterCache();
|
||||
_pageTable = new ulong[PtLvl0Size][];
|
||||
|
|
@ -269,7 +278,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
/// <param name="data">The data to be written</param>
|
||||
public void Write(ulong va, ReadOnlySpan<byte> data)
|
||||
{
|
||||
WriteImpl(va, data, Physical.Write);
|
||||
WriteImpl(va, data, _write);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -279,7 +288,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
/// <param name="data">The data to be written</param>
|
||||
public void WriteTrackedResource(ulong va, ReadOnlySpan<byte> data)
|
||||
{
|
||||
WriteImpl(va, data, Physical.WriteTrackedResource);
|
||||
WriteImpl(va, data, _writeTrackedResource);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -289,11 +298,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
/// <param name="data">The data to be written</param>
|
||||
public void WriteUntracked(ulong va, ReadOnlySpan<byte> data)
|
||||
{
|
||||
WriteImpl(va, data, Physical.WriteUntracked);
|
||||
WriteImpl(va, data, _writeUntracked);
|
||||
}
|
||||
|
||||
private delegate void WriteCallback(ulong address, ReadOnlySpan<byte> data);
|
||||
|
||||
/// <summary>
|
||||
/// Writes data to possibly non-contiguous GPU mapped memory.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -123,15 +123,15 @@ namespace Ryujinx.HLE.HOS.Services.Nv
|
|||
return NvResult.InvalidSize;
|
||||
}
|
||||
|
||||
byte[] outputData = new byte[outputDataSize];
|
||||
|
||||
byte[] temp = new byte[inputDataSize];
|
||||
|
||||
context.Memory.Read(inputDataPosition, temp);
|
||||
|
||||
Buffer.BlockCopy(temp, 0, outputData, 0, temp.Length);
|
||||
|
||||
arguments = new Span<byte>(outputData);
|
||||
if (!context.Memory.TryReadUnsafe(inputDataPosition, (int)inputDataSize, out arguments))
|
||||
{
|
||||
arguments = new byte[inputDataSize];
|
||||
context.Memory.Read(inputDataPosition, arguments);
|
||||
}
|
||||
else
|
||||
{
|
||||
arguments = arguments.ToArray();
|
||||
}
|
||||
}
|
||||
else if (isWrite)
|
||||
{
|
||||
|
|
@ -471,11 +471,11 @@ namespace Ryujinx.HLE.HOS.Services.Nv
|
|||
|
||||
errorCode = GetIoctlArgument(context, ioctlCommand, out Span<byte> arguments);
|
||||
|
||||
byte[] temp = new byte[inlineInBufferSize];
|
||||
|
||||
context.Memory.Read(inlineInBufferPosition, temp);
|
||||
|
||||
Span<byte> inlineInBuffer = new(temp);
|
||||
if (!context.Memory.TryReadUnsafe(inlineInBufferPosition, (int)inlineInBufferSize, out Span<byte> inlineInBuffer))
|
||||
{
|
||||
inlineInBuffer = new byte[inlineInBufferSize];
|
||||
context.Memory.Read(inlineInBufferPosition, inlineInBuffer);
|
||||
}
|
||||
|
||||
if (errorCode == NvResult.Success)
|
||||
{
|
||||
|
|
@ -520,11 +520,11 @@ namespace Ryujinx.HLE.HOS.Services.Nv
|
|||
|
||||
errorCode = GetIoctlArgument(context, ioctlCommand, out Span<byte> arguments);
|
||||
|
||||
byte[] temp = new byte[inlineOutBufferSize];
|
||||
|
||||
context.Memory.Read(inlineOutBufferPosition, temp);
|
||||
|
||||
Span<byte> inlineOutBuffer = new(temp);
|
||||
if (!context.Memory.TryReadUnsafe(inlineOutBufferPosition, (int)inlineOutBufferSize, out Span<byte> inlineOutBuffer))
|
||||
{
|
||||
inlineOutBuffer = new byte[inlineOutBufferSize];
|
||||
context.Memory.Read(inlineOutBufferPosition, inlineOutBuffer);
|
||||
}
|
||||
|
||||
if (errorCode == NvResult.Success)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -61,6 +61,15 @@ namespace Ryujinx.Memory
|
|||
/// <exception cref="InvalidMemoryRegionException">Throw for unhandled invalid or unmapped memory accesses</exception>
|
||||
void Read(ulong va, Span<byte> data);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a span of CPU mapped memory.
|
||||
/// </summary>
|
||||
/// <param name="va">Virtual address of the data in memory</param>
|
||||
/// <param name="length">Length of the data in memory</param>
|
||||
/// <param name="data">Span that references the data being read</param>
|
||||
/// <exception cref="InvalidMemoryRegionException">Throw for unhandled invalid or unmapped memory accesses</exception>
|
||||
bool TryReadUnsafe(ulong va, int length, out Span<byte> data);
|
||||
|
||||
/// <summary>
|
||||
/// Writes data to CPU mapped memory.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -159,6 +159,13 @@ namespace Ryujinx.Memory
|
|||
|
||||
AssertValidAddressAndSize(va, data.Length);
|
||||
|
||||
if (IsContiguousAndMapped(va, data.Length))
|
||||
{
|
||||
nuint pa = TranslateVirtualAddressChecked(va);
|
||||
|
||||
GetPhysicalAddressSpan(pa, data.Length).CopyTo(data);
|
||||
}
|
||||
|
||||
int offset = 0, size;
|
||||
|
||||
if ((va & PageMask) != 0)
|
||||
|
|
@ -182,6 +189,28 @@ namespace Ryujinx.Memory
|
|||
}
|
||||
}
|
||||
|
||||
public virtual bool TryReadUnsafe(ulong va, int length, out Span<byte> data)
|
||||
{
|
||||
if (!IsContiguousAndMapped(va, length))
|
||||
{
|
||||
data = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
data = Span<byte>.Empty;
|
||||
return true;
|
||||
}
|
||||
|
||||
AssertValidAddressAndSize(va, length);
|
||||
|
||||
nuint pa = TranslateVirtualAddressChecked(va);
|
||||
|
||||
data = GetPhysicalAddressSpan(pa, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual T ReadTracked<T>(ulong va) where T : unmanaged
|
||||
{
|
||||
SignalMemoryTracking(va, (ulong)Unsafe.SizeOf<T>(), false);
|
||||
|
|
|
|||
|
|
@ -43,6 +43,11 @@ namespace Ryujinx.Tests.Memory
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool TryReadUnsafe(ulong va, int lenfth, out Span<byte> data)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Write<T>(ulong va, T value) where T : unmanaged
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue