aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Vulkan/PipelineBase.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Vulkan/PipelineBase.cs')
-rw-r--r--Ryujinx.Graphics.Vulkan/PipelineBase.cs267
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();
}
}