Move solution and projects to src

This commit is contained in:
TSR Berry 2023-04-08 01:22:00 +02:00 committed by Mary
parent cd124bda58
commit cee7121058
3466 changed files with 55 additions and 55 deletions

View file

@ -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);
}
}
}
}
}

View file

@ -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);
}
}
}

View file

@ -0,0 +1,8 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Resources.Programs
{
interface IProgramRequest
{
ThreadedProgram Threaded { get; set; }
IProgram Create(IRenderer renderer);
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}
}

View file

@ -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;
}
}
}

View file

@ -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();
}
}
}

View file

@ -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();
}
}
}