diff options
Diffstat (limited to 'Ryujinx.Graphics.Vulkan/PipelineBase.cs')
-rw-r--r-- | Ryujinx.Graphics.Vulkan/PipelineBase.cs | 267 |
1 files changed, 204 insertions, 63 deletions
diff --git a/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/Ryujinx.Graphics.Vulkan/PipelineBase.cs index f333c944..55c3fea2 100644 --- a/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -294,6 +294,19 @@ namespace Ryujinx.Graphics.Vulkan Gd.Api.CmdDispatch(CommandBuffer, (uint)groupsX, (uint)groupsY, (uint)groupsZ); } + public void DispatchComputeIndirect(Auto<DisposableBuffer> indirectBuffer, int indirectBufferOffset) + { + if (!_program.IsLinked) + { + return; + } + + EndRenderPass(); + RecreatePipelineIfNeeded(PipelineBindPoint.Compute); + + Gd.Api.CmdDispatchIndirect(CommandBuffer, indirectBuffer.Get(Cbs, indirectBufferOffset, 12).Value, (ulong)indirectBufferOffset); + } + public void Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance) { if (!_program.IsLinked) @@ -395,121 +408,195 @@ namespace Ryujinx.Graphics.Vulkan } } - public void DrawTexture(ITexture texture, ISampler sampler, Extents2DF srcRegion, Extents2DF dstRegion) + public void DrawIndexedIndirect(BufferRange indirectBuffer) { - if (texture is TextureView srcTexture) + if (!_program.IsLinked) { - SupportBufferUpdater.Commit(); + return; + } - var oldCullMode = _newState.CullMode; - var oldStencilTestEnable = _newState.StencilTestEnable; - var oldDepthTestEnable = _newState.DepthTestEnable; - var oldDepthWriteEnable = _newState.DepthWriteEnable; - var oldTopology = _newState.Topology; - var oldViewports = DynamicState.Viewports; - var oldViewportsCount = _newState.ViewportsCount; + UpdateIndexBufferPattern(); + RecreatePipelineIfNeeded(PipelineBindPoint.Graphics); + BeginRenderPass(); + DrawCount++; - _newState.CullMode = CullModeFlags.CullModeNone; - _newState.StencilTestEnable = false; - _newState.DepthTestEnable = false; - _newState.DepthWriteEnable = false; - SignalStateChange(); + if (_indexBufferPattern != null) + { + // Convert the index buffer into a supported topology. + IndexBufferPattern pattern = _indexBufferPattern; - Gd.HelperShader.DrawTexture( + Auto<DisposableBuffer> indirectBufferAuto = _indexBuffer.BindConvertedIndexBufferIndirect( Gd, - this, - srcTexture, - sampler, - srcRegion, - dstRegion); + Cbs, + indirectBuffer, + BufferRange.Empty, + pattern, + false, + 1, + indirectBuffer.Size); - _newState.CullMode = oldCullMode; - _newState.StencilTestEnable = oldStencilTestEnable; - _newState.DepthTestEnable = oldDepthTestEnable; - _newState.DepthWriteEnable = oldDepthWriteEnable; - _newState.Topology = oldTopology; + _needsIndexBufferRebind = false; - DynamicState.Viewports = oldViewports; - DynamicState.ViewportsCount = (int)oldViewportsCount; - DynamicState.SetViewportsDirty(); + BeginRenderPass(); // May have been interrupted to set buffer data. + ResumeTransformFeedbackInternal(); - _newState.ViewportsCount = oldViewportsCount; - SignalStateChange(); + Gd.Api.CmdDrawIndexedIndirect(CommandBuffer, indirectBufferAuto.Get(Cbs, 0, indirectBuffer.Size).Value, 0, 1, (uint)indirectBuffer.Size); } - } + else + { + var buffer = Gd.BufferManager + .GetBuffer(CommandBuffer, indirectBuffer.Handle, indirectBuffer.Offset, indirectBuffer.Size, false) + .Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value; - public void EndTransformFeedback() - { - PauseTransformFeedbackInternal(); - _tfEnabled = false; - } + ResumeTransformFeedbackInternal(); - public bool IsCommandBufferActive(CommandBuffer cb) - { - return CommandBuffer.Handle == cb.Handle; + Gd.Api.CmdDrawIndexedIndirect(CommandBuffer, buffer, (ulong)indirectBuffer.Offset, 1, (uint)indirectBuffer.Size); + } } - public void MultiDrawIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride) + public void DrawIndexedIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride) { - if (!Gd.Capabilities.SupportsIndirectParameters) + if (!_program.IsLinked) { - throw new NotSupportedException(); + return; + } + + UpdateIndexBufferPattern(); + RecreatePipelineIfNeeded(PipelineBindPoint.Graphics); + BeginRenderPass(); + DrawCount++; + + var countBuffer = Gd.BufferManager + .GetBuffer(CommandBuffer, parameterBuffer.Handle, parameterBuffer.Offset, parameterBuffer.Size, false) + .Get(Cbs, parameterBuffer.Offset, parameterBuffer.Size).Value; + + if (_indexBufferPattern != null) + { + // Convert the index buffer into a supported topology. + IndexBufferPattern pattern = _indexBufferPattern; + + Auto<DisposableBuffer> indirectBufferAuto = _indexBuffer.BindConvertedIndexBufferIndirect( + Gd, + Cbs, + indirectBuffer, + parameterBuffer, + pattern, + true, + maxDrawCount, + stride); + + _needsIndexBufferRebind = false; + + BeginRenderPass(); // May have been interrupted to set buffer data. + ResumeTransformFeedbackInternal(); + + if (Gd.Capabilities.SupportsIndirectParameters) + { + Gd.DrawIndirectCountApi.CmdDrawIndexedIndirectCount( + CommandBuffer, + indirectBufferAuto.Get(Cbs, 0, indirectBuffer.Size).Value, + 0, + countBuffer, + (ulong)parameterBuffer.Offset, + (uint)maxDrawCount, + (uint)stride); + } + else + { + // This is also fine because the indirect data conversion always zeros + // the entries that are past the current draw count. + + Gd.Api.CmdDrawIndexedIndirect( + CommandBuffer, + indirectBufferAuto.Get(Cbs, 0, indirectBuffer.Size).Value, + 0, + (uint)maxDrawCount, + (uint)stride); + } + + } + else + { + var buffer = Gd.BufferManager + .GetBuffer(CommandBuffer, indirectBuffer.Handle, indirectBuffer.Offset, indirectBuffer.Size, false) + .Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value; + + ResumeTransformFeedbackInternal(); + + if (Gd.Capabilities.SupportsIndirectParameters) + { + Gd.DrawIndirectCountApi.CmdDrawIndexedIndirectCount( + CommandBuffer, + buffer, + (ulong)indirectBuffer.Offset, + countBuffer, + (ulong)parameterBuffer.Offset, + (uint)maxDrawCount, + (uint)stride); + } + else + { + // Not fully correct, but we can't do much better if the host does not support indirect count. + Gd.Api.CmdDrawIndexedIndirect( + CommandBuffer, + buffer, + (ulong)indirectBuffer.Offset, + (uint)maxDrawCount, + (uint)stride); + } } + } - if (_program.LinkStatus != ProgramLinkStatus.Success) + public void DrawIndirect(BufferRange indirectBuffer) + { + if (!_program.IsLinked) { return; } + // TODO: Support quads and other unsupported topologies. + RecreatePipelineIfNeeded(PipelineBindPoint.Graphics); BeginRenderPass(); ResumeTransformFeedbackInternal(); DrawCount++; var buffer = Gd.BufferManager - .GetBuffer(CommandBuffer, indirectBuffer.Handle, indirectBuffer.Offset, indirectBuffer.Size, true) + .GetBuffer(CommandBuffer, indirectBuffer.Handle, indirectBuffer.Offset, indirectBuffer.Size, false) .Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value; - var countBuffer = Gd.BufferManager - .GetBuffer(CommandBuffer, parameterBuffer.Handle, parameterBuffer.Offset, parameterBuffer.Size, true) - .Get(Cbs, parameterBuffer.Offset, parameterBuffer.Size).Value; - - Gd.DrawIndirectCountApi.CmdDrawIndirectCount( - CommandBuffer, - buffer, - (ulong)indirectBuffer.Offset, - countBuffer, - (ulong)parameterBuffer.Offset, - (uint)maxDrawCount, - (uint)stride); + Gd.Api.CmdDrawIndirect(CommandBuffer, buffer, (ulong)indirectBuffer.Offset, 1, (uint)indirectBuffer.Size); } - public void MultiDrawIndexedIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride) + public void DrawIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride) { if (!Gd.Capabilities.SupportsIndirectParameters) { + // TODO: Fallback for when this is not supported. throw new NotSupportedException(); } - if (_program.LinkStatus != ProgramLinkStatus.Success) + if (!_program.IsLinked) { return; } + // TODO: Support quads and other unsupported topologies. + RecreatePipelineIfNeeded(PipelineBindPoint.Graphics); BeginRenderPass(); ResumeTransformFeedbackInternal(); DrawCount++; var buffer = Gd.BufferManager - .GetBuffer(CommandBuffer, indirectBuffer.Handle, parameterBuffer.Offset, parameterBuffer.Size, true) + .GetBuffer(CommandBuffer, indirectBuffer.Handle, indirectBuffer.Offset, indirectBuffer.Size, false) .Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value; var countBuffer = Gd.BufferManager - .GetBuffer(CommandBuffer, parameterBuffer.Handle, parameterBuffer.Offset, parameterBuffer.Size, true) + .GetBuffer(CommandBuffer, parameterBuffer.Handle, parameterBuffer.Offset, parameterBuffer.Size, false) .Get(Cbs, parameterBuffer.Offset, parameterBuffer.Size).Value; - Gd.DrawIndirectCountApi.CmdDrawIndexedIndirectCount( + Gd.DrawIndirectCountApi.CmdDrawIndirectCount( CommandBuffer, buffer, (ulong)indirectBuffer.Offset, @@ -519,6 +606,60 @@ namespace Ryujinx.Graphics.Vulkan (uint)stride); } + public void DrawTexture(ITexture texture, ISampler sampler, Extents2DF srcRegion, Extents2DF dstRegion) + { + if (texture is TextureView srcTexture) + { + SupportBufferUpdater.Commit(); + + var oldCullMode = _newState.CullMode; + var oldStencilTestEnable = _newState.StencilTestEnable; + var oldDepthTestEnable = _newState.DepthTestEnable; + var oldDepthWriteEnable = _newState.DepthWriteEnable; + var oldTopology = _newState.Topology; + var oldViewports = DynamicState.Viewports; + var oldViewportsCount = _newState.ViewportsCount; + + _newState.CullMode = CullModeFlags.CullModeNone; + _newState.StencilTestEnable = false; + _newState.DepthTestEnable = false; + _newState.DepthWriteEnable = false; + SignalStateChange(); + + Gd.HelperShader.DrawTexture( + Gd, + this, + srcTexture, + sampler, + srcRegion, + dstRegion); + + _newState.CullMode = oldCullMode; + _newState.StencilTestEnable = oldStencilTestEnable; + _newState.DepthTestEnable = oldDepthTestEnable; + _newState.DepthWriteEnable = oldDepthWriteEnable; + _newState.Topology = oldTopology; + + DynamicState.Viewports = oldViewports; + DynamicState.ViewportsCount = (int)oldViewportsCount; + DynamicState.SetViewportsDirty(); + + _newState.ViewportsCount = oldViewportsCount; + SignalStateChange(); + } + } + + public void EndTransformFeedback() + { + PauseTransformFeedbackInternal(); + _tfEnabled = false; + } + + public bool IsCommandBufferActive(CommandBuffer cb) + { + return CommandBuffer.Handle == cb.Handle; + } + public void SetAlphaTest(bool enable, float reference, GAL.CompareOp op) { // This is currently handled using shader specialization, as Vulkan does not support alpha test. @@ -706,7 +847,7 @@ namespace Ryujinx.Graphics.Vulkan if (!dataSpan.SequenceEqual(_newState.SpecializationData.Span)) { _newState.SpecializationData = new SpecData(dataSpan); - + SignalStateChange(); } } |