using Ryujinx.Graphics.GAL.Multithreading.Commands; using Ryujinx.Graphics.GAL.Multithreading.Model; using Ryujinx.Graphics.GAL.Multithreading.Resources; using Ryujinx.Graphics.Shader; using System; using System.Linq; namespace Ryujinx.Graphics.GAL.Multithreading { public class ThreadedPipeline : IPipeline { private readonly ThreadedRenderer _renderer; public ThreadedPipeline(ThreadedRenderer renderer) { _renderer = renderer; } private TableRef Ref(T reference) { return new TableRef(_renderer, reference); } public void Barrier() { _renderer.New(); _renderer.QueueCommand(); } public void BeginTransformFeedback(PrimitiveTopology topology) { _renderer.New().Set(topology); _renderer.QueueCommand(); } public void ClearBuffer(BufferHandle destination, int offset, int size, uint value) { _renderer.New().Set(destination, offset, size, value); _renderer.QueueCommand(); } public void ClearRenderTargetColor(int index, int layer, int layerCount, uint componentMask, ColorF color) { _renderer.New().Set(index, layer, layerCount, componentMask, color); _renderer.QueueCommand(); } public void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask) { _renderer.New().Set(layer, layerCount, depthValue, depthMask, stencilValue, stencilMask); _renderer.QueueCommand(); } public void CommandBufferBarrier() { _renderer.New(); _renderer.QueueCommand(); } public void CopyBuffer(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size) { _renderer.New().Set(source, destination, srcOffset, dstOffset, size); _renderer.QueueCommand(); } public void DispatchCompute(int groupsX, int groupsY, int groupsZ) { _renderer.New().Set(groupsX, groupsY, groupsZ); _renderer.QueueCommand(); } public void Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance) { _renderer.New().Set(vertexCount, instanceCount, firstVertex, firstInstance); _renderer.QueueCommand(); } public void DrawIndexed(int indexCount, int instanceCount, int firstIndex, int firstVertex, int firstInstance) { _renderer.New().Set(indexCount, instanceCount, firstIndex, firstVertex, firstInstance); _renderer.QueueCommand(); } public void DrawIndexedIndirect(BufferRange indirectBuffer) { _renderer.New().Set(indirectBuffer); _renderer.QueueCommand(); } public void DrawIndexedIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride) { _renderer.New().Set(indirectBuffer, parameterBuffer, maxDrawCount, stride); _renderer.QueueCommand(); } public void DrawIndirect(BufferRange indirectBuffer) { _renderer.New().Set(indirectBuffer); _renderer.QueueCommand(); } public void DrawIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride) { _renderer.New().Set(indirectBuffer, parameterBuffer, maxDrawCount, stride); _renderer.QueueCommand(); } public void DrawTexture(ITexture texture, ISampler sampler, Extents2DF srcRegion, Extents2DF dstRegion) { _renderer.New().Set(Ref(texture), Ref(sampler), srcRegion, dstRegion); _renderer.QueueCommand(); } public void EndHostConditionalRendering() { _renderer.New(); _renderer.QueueCommand(); } public void EndTransformFeedback() { _renderer.New(); _renderer.QueueCommand(); } public void SetAlphaTest(bool enable, float reference, CompareOp op) { _renderer.New().Set(enable, reference, op); _renderer.QueueCommand(); } public void SetBlendState(AdvancedBlendDescriptor blend) { _renderer.New().Set(blend); _renderer.QueueCommand(); } public void SetBlendState(int index, BlendDescriptor blend) { _renderer.New().Set(index, blend); _renderer.QueueCommand(); } public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp) { _renderer.New().Set(enables, factor, units, clamp); _renderer.QueueCommand(); } public void SetDepthClamp(bool clamp) { _renderer.New().Set(clamp); _renderer.QueueCommand(); } public void SetDepthMode(DepthMode mode) { _renderer.New().Set(mode); _renderer.QueueCommand(); } public void SetDepthTest(DepthTestDescriptor depthTest) { _renderer.New().Set(depthTest); _renderer.QueueCommand(); } public void SetFaceCulling(bool enable, Face face) { _renderer.New().Set(enable, face); _renderer.QueueCommand(); } public void SetFrontFace(FrontFace frontFace) { _renderer.New().Set(frontFace); _renderer.QueueCommand(); } public void SetImage(int binding, ITexture texture, Format imageFormat) { _renderer.New().Set(binding, Ref(texture), imageFormat); _renderer.QueueCommand(); } public void SetIndexBuffer(BufferRange buffer, IndexType type) { _renderer.New().Set(buffer, type); _renderer.QueueCommand(); } public void SetLineParameters(float width, bool smooth) { _renderer.New().Set(width, smooth); _renderer.QueueCommand(); } public void SetLogicOpState(bool enable, LogicalOp op) { _renderer.New().Set(enable, op); _renderer.QueueCommand(); } public void SetMultisampleState(MultisampleDescriptor multisample) { _renderer.New().Set(multisample); _renderer.QueueCommand(); } public void SetPatchParameters(int vertices, ReadOnlySpan defaultOuterLevel, ReadOnlySpan defaultInnerLevel) { _renderer.New().Set(vertices, defaultOuterLevel, defaultInnerLevel); _renderer.QueueCommand(); } public void SetPointParameters(float size, bool isProgramPointSize, bool enablePointSprite, Origin origin) { _renderer.New().Set(size, isProgramPointSize, enablePointSprite, origin); _renderer.QueueCommand(); } public void SetPolygonMode(PolygonMode frontMode, PolygonMode backMode) { _renderer.New().Set(frontMode, backMode); _renderer.QueueCommand(); } public void SetPrimitiveRestart(bool enable, int index) { _renderer.New().Set(enable, index); _renderer.QueueCommand(); } public void SetPrimitiveTopology(PrimitiveTopology topology) { _renderer.New().Set(topology); _renderer.QueueCommand(); } public void SetProgram(IProgram program) { _renderer.New().Set(Ref(program)); _renderer.QueueCommand(); } public void SetRasterizerDiscard(bool discard) { _renderer.New().Set(discard); _renderer.QueueCommand(); } public void SetRenderTargetColorMasks(ReadOnlySpan componentMask) { _renderer.New().Set(_renderer.CopySpan(componentMask)); _renderer.QueueCommand(); } public void SetRenderTargets(ITexture[] colors, ITexture depthStencil) { _renderer.New().Set(Ref(colors.ToArray()), Ref(depthStencil)); _renderer.QueueCommand(); } public void SetRenderTargetScale(float scale) { _renderer.New().Set(scale); _renderer.QueueCommand(); } public void SetScissors(ReadOnlySpan> scissors) { _renderer.New().Set(_renderer.CopySpan(scissors)); _renderer.QueueCommand(); } public void SetStencilTest(StencilTestDescriptor stencilTest) { _renderer.New().Set(stencilTest); _renderer.QueueCommand(); } public void SetStorageBuffers(ReadOnlySpan buffers) { _renderer.New().Set(_renderer.CopySpan(buffers)); _renderer.QueueCommand(); } public void SetTextureAndSampler(ShaderStage stage, int binding, ITexture texture, ISampler sampler) { _renderer.New().Set(stage, binding, Ref(texture), Ref(sampler)); _renderer.QueueCommand(); } public void SetTransformFeedbackBuffers(ReadOnlySpan buffers) { _renderer.New().Set(_renderer.CopySpan(buffers)); _renderer.QueueCommand(); } public void SetUniformBuffers(ReadOnlySpan buffers) { _renderer.New().Set(_renderer.CopySpan(buffers)); _renderer.QueueCommand(); } public void SetUserClipDistance(int index, bool enableClip) { _renderer.New().Set(index, enableClip); _renderer.QueueCommand(); } public void SetVertexAttribs(ReadOnlySpan vertexAttribs) { _renderer.New().Set(_renderer.CopySpan(vertexAttribs)); _renderer.QueueCommand(); } public void SetVertexBuffers(ReadOnlySpan vertexBuffers) { _renderer.New().Set(_renderer.CopySpan(vertexBuffers)); _renderer.QueueCommand(); } public void SetViewports(ReadOnlySpan viewports, bool disableTransform) { _renderer.New().Set(_renderer.CopySpan(viewports), disableTransform); _renderer.QueueCommand(); } public void TextureBarrier() { _renderer.New(); _renderer.QueueCommand(); } public void TextureBarrierTiled() { _renderer.New(); _renderer.QueueCommand(); } public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual) { var evt = value as ThreadedCounterEvent; if (evt != null) { if (compare == 0 && evt.Type == CounterType.SamplesPassed && evt.ClearCounter) { if (!evt.ReserveForHostAccess()) { return false; } _renderer.New().Set(Ref(evt), compare, isEqual); _renderer.QueueCommand(); return true; } } _renderer.New().Set(Ref(evt), Ref(null), isEqual); _renderer.QueueCommand(); return false; } public bool TryHostConditionalRendering(ICounterEvent value, ICounterEvent compare, bool isEqual) { _renderer.New().Set(Ref(value as ThreadedCounterEvent), Ref(compare as ThreadedCounterEvent), isEqual); _renderer.QueueCommand(); return false; } public void UpdateRenderScale(ReadOnlySpan scales, int totalCount, int fragmentCount) { _renderer.New().Set(_renderer.CopySpan(scales[..totalCount]), totalCount, fragmentCount); _renderer.QueueCommand(); } } }