|
|
@@ -34,7 +34,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|
|
|
|
|
protected PipelineDynamicState DynamicState;
|
|
|
private PipelineState _newState;
|
|
|
- private bool _stateDirty;
|
|
|
+ private bool _graphicsStateDirty;
|
|
|
+ private bool _computeStateDirty;
|
|
|
private PrimitiveTopology _topology;
|
|
|
|
|
|
private ulong _currentPipelineHandle;
|
|
|
@@ -353,7 +354,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|
|
}
|
|
|
|
|
|
EndRenderPass();
|
|
|
- RecreatePipelineIfNeeded(PipelineBindPoint.Compute);
|
|
|
+ RecreateComputePipelineIfNeeded();
|
|
|
|
|
|
Gd.Api.CmdDispatch(CommandBuffer, (uint)groupsX, (uint)groupsY, (uint)groupsZ);
|
|
|
}
|
|
|
@@ -366,19 +367,23 @@ namespace Ryujinx.Graphics.Vulkan
|
|
|
}
|
|
|
|
|
|
EndRenderPass();
|
|
|
- RecreatePipelineIfNeeded(PipelineBindPoint.Compute);
|
|
|
+ RecreateComputePipelineIfNeeded();
|
|
|
|
|
|
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 || vertexCount == 0)
|
|
|
+ if (vertexCount == 0)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!RecreateGraphicsPipelineIfNeeded())
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- RecreatePipelineIfNeeded(PipelineBindPoint.Graphics);
|
|
|
BeginRenderPass();
|
|
|
DrawCount++;
|
|
|
|
|
|
@@ -437,13 +442,18 @@ namespace Ryujinx.Graphics.Vulkan
|
|
|
|
|
|
public void DrawIndexed(int indexCount, int instanceCount, int firstIndex, int firstVertex, int firstInstance)
|
|
|
{
|
|
|
- if (!_program.IsLinked || indexCount == 0)
|
|
|
+ if (indexCount == 0)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
UpdateIndexBufferPattern();
|
|
|
- RecreatePipelineIfNeeded(PipelineBindPoint.Graphics);
|
|
|
+
|
|
|
+ if (!RecreateGraphicsPipelineIfNeeded())
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
BeginRenderPass();
|
|
|
DrawCount++;
|
|
|
|
|
|
@@ -476,17 +486,17 @@ namespace Ryujinx.Graphics.Vulkan
|
|
|
|
|
|
public void DrawIndexedIndirect(BufferRange indirectBuffer)
|
|
|
{
|
|
|
- if (!_program.IsLinked)
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
var buffer = Gd.BufferManager
|
|
|
.GetBuffer(CommandBuffer, indirectBuffer.Handle, indirectBuffer.Offset, indirectBuffer.Size, false)
|
|
|
.Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value;
|
|
|
|
|
|
UpdateIndexBufferPattern();
|
|
|
- RecreatePipelineIfNeeded(PipelineBindPoint.Graphics);
|
|
|
+
|
|
|
+ if (!RecreateGraphicsPipelineIfNeeded())
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
BeginRenderPass();
|
|
|
DrawCount++;
|
|
|
|
|
|
@@ -522,11 +532,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|
|
|
|
|
public void DrawIndexedIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
|
|
|
{
|
|
|
- if (!_program.IsLinked)
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
var countBuffer = Gd.BufferManager
|
|
|
.GetBuffer(CommandBuffer, parameterBuffer.Handle, parameterBuffer.Offset, parameterBuffer.Size, false)
|
|
|
.Get(Cbs, parameterBuffer.Offset, parameterBuffer.Size).Value;
|
|
|
@@ -536,7 +541,12 @@ namespace Ryujinx.Graphics.Vulkan
|
|
|
.Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value;
|
|
|
|
|
|
UpdateIndexBufferPattern();
|
|
|
- RecreatePipelineIfNeeded(PipelineBindPoint.Graphics);
|
|
|
+
|
|
|
+ if (!RecreateGraphicsPipelineIfNeeded())
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
BeginRenderPass();
|
|
|
DrawCount++;
|
|
|
|
|
|
@@ -614,18 +624,17 @@ namespace Ryujinx.Graphics.Vulkan
|
|
|
|
|
|
public void DrawIndirect(BufferRange indirectBuffer)
|
|
|
{
|
|
|
- if (!_program.IsLinked)
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
// TODO: Support quads and other unsupported topologies.
|
|
|
|
|
|
var buffer = Gd.BufferManager
|
|
|
.GetBuffer(CommandBuffer, indirectBuffer.Handle, indirectBuffer.Offset, indirectBuffer.Size, false)
|
|
|
.Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size, false).Value;
|
|
|
|
|
|
- RecreatePipelineIfNeeded(PipelineBindPoint.Graphics);
|
|
|
+ if (!RecreateGraphicsPipelineIfNeeded())
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
BeginRenderPass();
|
|
|
ResumeTransformFeedbackInternal();
|
|
|
DrawCount++;
|
|
|
@@ -641,11 +650,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|
|
throw new NotSupportedException();
|
|
|
}
|
|
|
|
|
|
- if (!_program.IsLinked)
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
var buffer = Gd.BufferManager
|
|
|
.GetBuffer(CommandBuffer, indirectBuffer.Handle, indirectBuffer.Offset, indirectBuffer.Size, false)
|
|
|
.Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size, false).Value;
|
|
|
@@ -656,7 +660,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|
|
|
|
|
// TODO: Support quads and other unsupported topologies.
|
|
|
|
|
|
- RecreatePipelineIfNeeded(PipelineBindPoint.Graphics);
|
|
|
+ if (!RecreateGraphicsPipelineIfNeeded())
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
BeginRenderPass();
|
|
|
ResumeTransformFeedbackInternal();
|
|
|
DrawCount++;
|
|
|
@@ -1576,10 +1584,23 @@ namespace Ryujinx.Graphics.Vulkan
|
|
|
|
|
|
protected void SignalStateChange()
|
|
|
{
|
|
|
- _stateDirty = true;
|
|
|
+ _graphicsStateDirty = true;
|
|
|
+ _computeStateDirty = true;
|
|
|
}
|
|
|
|
|
|
- private void RecreatePipelineIfNeeded(PipelineBindPoint pbp)
|
|
|
+ private void RecreateComputePipelineIfNeeded()
|
|
|
+ {
|
|
|
+ if (_computeStateDirty || Pbp != PipelineBindPoint.Compute)
|
|
|
+ {
|
|
|
+ CreatePipeline(PipelineBindPoint.Compute);
|
|
|
+ _computeStateDirty = false;
|
|
|
+ Pbp = PipelineBindPoint.Compute;
|
|
|
+ }
|
|
|
+
|
|
|
+ _descriptorSetUpdater.UpdateAndBindDescriptorSets(Cbs, PipelineBindPoint.Compute);
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool RecreateGraphicsPipelineIfNeeded()
|
|
|
{
|
|
|
if (AutoFlush.ShouldFlushDraw(DrawCount))
|
|
|
{
|
|
|
@@ -1620,17 +1641,23 @@ namespace Ryujinx.Graphics.Vulkan
|
|
|
_vertexBufferUpdater.Commit(Cbs);
|
|
|
}
|
|
|
|
|
|
- if (_stateDirty || Pbp != pbp)
|
|
|
+ if (_graphicsStateDirty || Pbp != PipelineBindPoint.Graphics)
|
|
|
{
|
|
|
- CreatePipeline(pbp);
|
|
|
- _stateDirty = false;
|
|
|
- Pbp = pbp;
|
|
|
+ if (!CreatePipeline(PipelineBindPoint.Graphics))
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ _graphicsStateDirty = false;
|
|
|
+ Pbp = PipelineBindPoint.Graphics;
|
|
|
}
|
|
|
|
|
|
- _descriptorSetUpdater.UpdateAndBindDescriptorSets(Cbs, pbp);
|
|
|
+ _descriptorSetUpdater.UpdateAndBindDescriptorSets(Cbs, PipelineBindPoint.Graphics);
|
|
|
+
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
- private void CreatePipeline(PipelineBindPoint pbp)
|
|
|
+ private bool CreatePipeline(PipelineBindPoint pbp)
|
|
|
{
|
|
|
// We can only create a pipeline if the have the shader stages set.
|
|
|
if (_newState.Stages != null)
|
|
|
@@ -1640,10 +1667,25 @@ namespace Ryujinx.Graphics.Vulkan
|
|
|
CreateRenderPass();
|
|
|
}
|
|
|
|
|
|
+ if (!_program.IsLinked)
|
|
|
+ {
|
|
|
+ // Background compile failed, we likely can't create the pipeline because the shader is broken
|
|
|
+ // or the driver failed to compile it.
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
var pipeline = pbp == PipelineBindPoint.Compute
|
|
|
? _newState.CreateComputePipeline(Gd, Device, _program, PipelineCache)
|
|
|
: _newState.CreateGraphicsPipeline(Gd, Device, _program, PipelineCache, _renderPass.Get(Cbs).Value);
|
|
|
|
|
|
+ if (pipeline == null)
|
|
|
+ {
|
|
|
+ // Host failed to create the pipeline, likely due to driver bugs.
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
ulong pipelineHandle = pipeline.GetUnsafe().Value.Handle;
|
|
|
|
|
|
if (_currentPipelineHandle != pipelineHandle)
|
|
|
@@ -1655,6 +1697,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|
|
Gd.Api.CmdBindPipeline(CommandBuffer, pbp, Pipeline.Get(Cbs).Value);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
private unsafe void BeginRenderPass()
|