mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-07-25 08:27:11 +02:00
Move solution and projects to src
This commit is contained in:
parent
cd124bda58
commit
cee7121058
3466 changed files with 55 additions and 55 deletions
|
@ -0,0 +1,107 @@
|
|||
using Ryujinx.Graphics.GAL.Multithreading.Resources.Programs;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL.Multithreading.Resources
|
||||
{
|
||||
/// <summary>
|
||||
/// A structure handling multithreaded compilation for programs.
|
||||
/// </summary>
|
||||
class ProgramQueue
|
||||
{
|
||||
private const int MaxConcurrentCompilations = 8;
|
||||
|
||||
private IRenderer _renderer;
|
||||
|
||||
private Queue<IProgramRequest> _toCompile;
|
||||
private List<ThreadedProgram> _inProgress;
|
||||
|
||||
public ProgramQueue(IRenderer renderer)
|
||||
{
|
||||
_renderer = renderer;
|
||||
|
||||
_toCompile = new Queue<IProgramRequest>();
|
||||
_inProgress = new List<ThreadedProgram>();
|
||||
}
|
||||
|
||||
public void Add(IProgramRequest request)
|
||||
{
|
||||
lock (_toCompile)
|
||||
{
|
||||
_toCompile.Enqueue(request);
|
||||
}
|
||||
}
|
||||
|
||||
public void ProcessQueue()
|
||||
{
|
||||
for (int i = 0; i < _inProgress.Count; i++)
|
||||
{
|
||||
ThreadedProgram program = _inProgress[i];
|
||||
|
||||
ProgramLinkStatus status = program.Base.CheckProgramLink(false);
|
||||
|
||||
if (status != ProgramLinkStatus.Incomplete)
|
||||
{
|
||||
program.Compiled = true;
|
||||
_inProgress.RemoveAt(i--);
|
||||
}
|
||||
}
|
||||
|
||||
int freeSpace = MaxConcurrentCompilations - _inProgress.Count;
|
||||
|
||||
for (int i = 0; i < freeSpace; i++)
|
||||
{
|
||||
// Begin compilation of some programs in the compile queue.
|
||||
IProgramRequest program;
|
||||
|
||||
lock (_toCompile)
|
||||
{
|
||||
if (!_toCompile.TryDequeue(out program))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (program.Threaded.Base != null)
|
||||
{
|
||||
ProgramLinkStatus status = program.Threaded.Base.CheckProgramLink(false);
|
||||
|
||||
if (status != ProgramLinkStatus.Incomplete)
|
||||
{
|
||||
// This program is already compiled. Keep going through the queue.
|
||||
program.Threaded.Compiled = true;
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
program.Threaded.Base = program.Create(_renderer);
|
||||
}
|
||||
|
||||
_inProgress.Add(program.Threaded);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process the queue until the given program has finished compiling.
|
||||
/// This will begin compilation of other programs on the queue as well.
|
||||
/// </summary>
|
||||
/// <param name="program">The program to wait for</param>
|
||||
public void WaitForProgram(ThreadedProgram program)
|
||||
{
|
||||
Span<SpinWait> spinWait = stackalloc SpinWait[1];
|
||||
|
||||
while (!program.Compiled)
|
||||
{
|
||||
ProcessQueue();
|
||||
|
||||
if (!program.Compiled)
|
||||
{
|
||||
spinWait[0].SpinOnce(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
namespace Ryujinx.Graphics.GAL.Multithreading.Resources.Programs
|
||||
{
|
||||
class BinaryProgramRequest : IProgramRequest
|
||||
{
|
||||
public ThreadedProgram Threaded { get; set; }
|
||||
|
||||
private byte[] _data;
|
||||
private bool _hasFragmentShader;
|
||||
private ShaderInfo _info;
|
||||
|
||||
public BinaryProgramRequest(ThreadedProgram program, byte[] data, bool hasFragmentShader, ShaderInfo info)
|
||||
{
|
||||
Threaded = program;
|
||||
|
||||
_data = data;
|
||||
_hasFragmentShader = hasFragmentShader;
|
||||
_info = info;
|
||||
}
|
||||
|
||||
public IProgram Create(IRenderer renderer)
|
||||
{
|
||||
return renderer.LoadProgramBinary(_data, _hasFragmentShader, _info);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
namespace Ryujinx.Graphics.GAL.Multithreading.Resources.Programs
|
||||
{
|
||||
interface IProgramRequest
|
||||
{
|
||||
ThreadedProgram Threaded { get; set; }
|
||||
IProgram Create(IRenderer renderer);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
namespace Ryujinx.Graphics.GAL.Multithreading.Resources.Programs
|
||||
{
|
||||
class SourceProgramRequest : IProgramRequest
|
||||
{
|
||||
public ThreadedProgram Threaded { get; set; }
|
||||
|
||||
private ShaderSource[] _shaders;
|
||||
private ShaderInfo _info;
|
||||
|
||||
public SourceProgramRequest(ThreadedProgram program, ShaderSource[] shaders, ShaderInfo info)
|
||||
{
|
||||
Threaded = program;
|
||||
|
||||
_shaders = shaders;
|
||||
_info = info;
|
||||
}
|
||||
|
||||
public IProgram Create(IRenderer renderer)
|
||||
{
|
||||
return renderer.CreateProgram(_shaders, _info);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
using Ryujinx.Graphics.GAL.Multithreading.Commands.CounterEvent;
|
||||
using Ryujinx.Graphics.GAL.Multithreading.Model;
|
||||
using System.Threading;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL.Multithreading.Resources
|
||||
{
|
||||
class ThreadedCounterEvent : ICounterEvent
|
||||
{
|
||||
private ThreadedRenderer _renderer;
|
||||
public ICounterEvent Base;
|
||||
|
||||
public bool Invalid { get; set; }
|
||||
|
||||
public CounterType Type { get; }
|
||||
public bool ClearCounter { get; }
|
||||
|
||||
private bool _reserved;
|
||||
private int _createLock;
|
||||
|
||||
public ThreadedCounterEvent(ThreadedRenderer renderer, CounterType type, bool clearCounter)
|
||||
{
|
||||
_renderer = renderer;
|
||||
Type = type;
|
||||
ClearCounter = clearCounter;
|
||||
}
|
||||
|
||||
private TableRef<T> Ref<T>(T reference)
|
||||
{
|
||||
return new TableRef<T>(_renderer, reference);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_renderer.New<CounterEventDisposeCommand>().Set(Ref(this));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
ThreadedHelpers.SpinUntilNonNull(ref Base);
|
||||
|
||||
Base.Flush();
|
||||
}
|
||||
|
||||
public bool ReserveForHostAccess()
|
||||
{
|
||||
if (Base != null)
|
||||
{
|
||||
return Base.ReserveForHostAccess();
|
||||
}
|
||||
else
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
// A very light lock, as this case is uncommon.
|
||||
ThreadedHelpers.SpinUntilExchange(ref _createLock, 1, 0);
|
||||
|
||||
if (Base != null)
|
||||
{
|
||||
result = Base.ReserveForHostAccess();
|
||||
}
|
||||
else
|
||||
{
|
||||
_reserved = true;
|
||||
}
|
||||
|
||||
Volatile.Write(ref _createLock, 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public void Create(IRenderer renderer, CounterType type, System.EventHandler<ulong> eventHandler, bool hostReserved)
|
||||
{
|
||||
ThreadedHelpers.SpinUntilExchange(ref _createLock, 1, 0);
|
||||
Base = renderer.ReportCounter(type, eventHandler, hostReserved || _reserved);
|
||||
Volatile.Write(ref _createLock, 0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
using Ryujinx.Graphics.GAL.Multithreading.Commands.Program;
|
||||
using Ryujinx.Graphics.GAL.Multithreading.Model;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL.Multithreading.Resources
|
||||
{
|
||||
class ThreadedProgram : IProgram
|
||||
{
|
||||
private ThreadedRenderer _renderer;
|
||||
|
||||
public IProgram Base;
|
||||
|
||||
internal bool Compiled;
|
||||
|
||||
public ThreadedProgram(ThreadedRenderer renderer)
|
||||
{
|
||||
_renderer = renderer;
|
||||
}
|
||||
|
||||
private TableRef<T> Ref<T>(T reference)
|
||||
{
|
||||
return new TableRef<T>(_renderer, reference);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_renderer.New<ProgramDisposeCommand>().Set(Ref(this));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public byte[] GetBinary()
|
||||
{
|
||||
ResultBox<byte[]> box = new ResultBox<byte[]>();
|
||||
_renderer.New<ProgramGetBinaryCommand>().Set(Ref(this), Ref(box));
|
||||
_renderer.InvokeCommand();
|
||||
|
||||
return box.Result;
|
||||
}
|
||||
|
||||
public ProgramLinkStatus CheckProgramLink(bool blocking)
|
||||
{
|
||||
ResultBox<ProgramLinkStatus> box = new ResultBox<ProgramLinkStatus>();
|
||||
_renderer.New<ProgramCheckLinkCommand>().Set(Ref(this), blocking, Ref(box));
|
||||
_renderer.InvokeCommand();
|
||||
|
||||
return box.Result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
using Ryujinx.Graphics.GAL.Multithreading.Commands.Sampler;
|
||||
using Ryujinx.Graphics.GAL.Multithreading.Model;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL.Multithreading.Resources
|
||||
{
|
||||
class ThreadedSampler : ISampler
|
||||
{
|
||||
private ThreadedRenderer _renderer;
|
||||
public ISampler Base;
|
||||
|
||||
public ThreadedSampler(ThreadedRenderer renderer)
|
||||
{
|
||||
_renderer = renderer;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_renderer.New<SamplerDisposeCommand>().Set(new TableRef<ThreadedSampler>(_renderer, this));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.GAL.Multithreading.Commands.Texture;
|
||||
using Ryujinx.Graphics.GAL.Multithreading.Model;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL.Multithreading.Resources
|
||||
{
|
||||
/// <summary>
|
||||
/// Threaded representation of a texture.
|
||||
/// </summary>
|
||||
class ThreadedTexture : ITexture
|
||||
{
|
||||
private ThreadedRenderer _renderer;
|
||||
private TextureCreateInfo _info;
|
||||
public ITexture Base;
|
||||
|
||||
public int Width => _info.Width;
|
||||
|
||||
public int Height => _info.Height;
|
||||
|
||||
public float ScaleFactor { get; }
|
||||
|
||||
public ThreadedTexture(ThreadedRenderer renderer, TextureCreateInfo info, float scale)
|
||||
{
|
||||
_renderer = renderer;
|
||||
_info = info;
|
||||
ScaleFactor = scale;
|
||||
}
|
||||
|
||||
private TableRef<T> Ref<T>(T reference)
|
||||
{
|
||||
return new TableRef<T>(_renderer, reference);
|
||||
}
|
||||
|
||||
public void CopyTo(ITexture destination, int firstLayer, int 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)
|
||||
{
|
||||
_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)
|
||||
{
|
||||
ThreadedTexture dest = (ThreadedTexture)destination;
|
||||
|
||||
if (_renderer.IsGpuThread())
|
||||
{
|
||||
_renderer.New<TextureCopyToScaledCommand>().Set(Ref(this), Ref(dest), srcRegion, dstRegion, linearFilter);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Scaled copy can happen on another thread for a res scale flush.
|
||||
ThreadedHelpers.SpinUntilNonNull(ref Base);
|
||||
ThreadedHelpers.SpinUntilNonNull(ref dest.Base);
|
||||
|
||||
Base.CopyTo(dest.Base, srcRegion, dstRegion, linearFilter);
|
||||
}
|
||||
}
|
||||
|
||||
public ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel)
|
||||
{
|
||||
ThreadedTexture newTex = new ThreadedTexture(_renderer, info, ScaleFactor);
|
||||
_renderer.New<TextureCreateViewCommand>().Set(Ref(this), Ref(newTex), info, firstLayer, firstLevel);
|
||||
_renderer.QueueCommand();
|
||||
|
||||
return newTex;
|
||||
}
|
||||
|
||||
public PinnedSpan<byte> GetData()
|
||||
{
|
||||
if (_renderer.IsGpuThread())
|
||||
{
|
||||
ResultBox<PinnedSpan<byte>> box = new ResultBox<PinnedSpan<byte>>();
|
||||
_renderer.New<TextureGetDataCommand>().Set(Ref(this), Ref(box));
|
||||
_renderer.InvokeCommand();
|
||||
|
||||
return box.Result;
|
||||
}
|
||||
else
|
||||
{
|
||||
ThreadedHelpers.SpinUntilNonNull(ref Base);
|
||||
|
||||
return Base.GetData();
|
||||
}
|
||||
}
|
||||
|
||||
public PinnedSpan<byte> GetData(int layer, int level)
|
||||
{
|
||||
if (_renderer.IsGpuThread())
|
||||
{
|
||||
ResultBox<PinnedSpan<byte>> box = new ResultBox<PinnedSpan<byte>>();
|
||||
_renderer.New<TextureGetDataSliceCommand>().Set(Ref(this), Ref(box), layer, level);
|
||||
_renderer.InvokeCommand();
|
||||
|
||||
return box.Result;
|
||||
}
|
||||
else
|
||||
{
|
||||
ThreadedHelpers.SpinUntilNonNull(ref Base);
|
||||
|
||||
return Base.GetData(layer, level);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetData(SpanOrArray<byte> data)
|
||||
{
|
||||
_renderer.New<TextureSetDataCommand>().Set(Ref(this), Ref(data.ToArray()));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetData(SpanOrArray<byte> data, int layer, int level)
|
||||
{
|
||||
_renderer.New<TextureSetDataSliceCommand>().Set(Ref(this), Ref(data.ToArray()), layer, level);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetData(SpanOrArray<byte> data, int layer, int level, Rectangle<int> region)
|
||||
{
|
||||
_renderer.New<TextureSetDataSliceRegionCommand>().Set(Ref(this), Ref(data.ToArray()), layer, level, region);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetStorage(BufferRange buffer)
|
||||
{
|
||||
_renderer.New<TextureSetStorageCommand>().Set(Ref(this), buffer);
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void Release()
|
||||
{
|
||||
_renderer.New<TextureReleaseCommand>().Set(Ref(this));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue