fix(vk): create the bindless image heap at device setup (#1088)
The heap was created lazily by pipeline creation and by the shader prewarm, but a draw binds its bindless slot table before it creates its pipeline. A title whose first draw samples images, with no pending prewarm work, hit a null heap in BindFlattenedResourceTable. The heap depends only on a device capability, so create it with the stores and drop the lazy calls.
This commit is contained in:
parent
7ebf642aff
commit
682ad298ef
|
|
@ -1474,6 +1474,7 @@ internal static unsafe partial class VulkanVideoPresenter
|
||||||
CreateScheduler();
|
CreateScheduler();
|
||||||
CreateBufferCache();
|
CreateBufferCache();
|
||||||
CreateImageCache();
|
CreateImageCache();
|
||||||
|
CreateBindlessImageHeap();
|
||||||
_descriptorHeap = new DescriptorHeap(_deviceInfo, _scheduler);
|
_descriptorHeap = new DescriptorHeap(_deviceInfo, _scheduler);
|
||||||
CreateCommandStream();
|
CreateCommandStream();
|
||||||
LoadDebugUtilsCommands();
|
LoadDebugUtilsCommands();
|
||||||
|
|
|
||||||
|
|
@ -622,17 +622,11 @@ internal static unsafe partial class VulkanVideoPresenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnsureBindlessImageHeap(params ShaderProgramInfo?[] programs)
|
// Every translated program samples through this one set when the device supports it,
|
||||||
=> EnsureBindlessImageHeapForMode(programs.Any(program => program?.Bindings?.UsesBindlessImages == true));
|
// and a draw binds its slots before it creates its pipeline. Create it with the stores.
|
||||||
|
private void CreateBindlessImageHeap()
|
||||||
private void EnsureBindlessImageHeapForMode(bool usesBindlessImages)
|
|
||||||
{
|
{
|
||||||
if (_bindlessImageHeap is not null)
|
if (!BindlessImageHeapEnabled)
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!usesBindlessImages)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -730,7 +724,6 @@ internal static unsafe partial class VulkanVideoPresenter
|
||||||
throw SubmissionScheduler.Fatal($"The draw binds more color attachments than the device supports: count={description.Rendering.ColorCount} max={_maxColorAttachments}.");
|
throw SubmissionScheduler.Fatal($"The draw binds more color attachments than the device supports: count={description.Rendering.ColorCount} max={_maxColorAttachments}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
EnsureBindlessImageHeap(description.VertexStage, description.PixelStage);
|
|
||||||
var usesBindlessImages = description.VertexStage.Bindings!.UsesBindlessImages ||
|
var usesBindlessImages = description.VertexStage.Bindings!.UsesBindlessImages ||
|
||||||
description.PixelStage?.Bindings?.UsesBindlessImages == true;
|
description.PixelStage?.Bindings?.UsesBindlessImages == true;
|
||||||
|
|
||||||
|
|
@ -1197,7 +1190,6 @@ internal static unsafe partial class VulkanVideoPresenter
|
||||||
public PipelineHandle CreateComputePipeline(ComputePipelineDescription description)
|
public PipelineHandle CreateComputePipeline(ComputePipelineDescription description)
|
||||||
{
|
{
|
||||||
using var profileScope = RenderPhaseProfile.MeasureDetail(RenderPhaseProfile.Phase.PipelineSetup);
|
using var profileScope = RenderPhaseProfile.MeasureDetail(RenderPhaseProfile.Phase.PipelineSetup);
|
||||||
EnsureBindlessImageHeap(description.Stage);
|
|
||||||
var bindings = new List<DescriptorSetLayoutBinding>();
|
var bindings = new List<DescriptorSetLayoutBinding>();
|
||||||
CollectLayoutBindings(bindings, description.Stage, ShaderStage.Compute);
|
CollectLayoutBindings(bindings, description.Stage, ShaderStage.Compute);
|
||||||
var setLayout = CreateDescriptorSetLayout(bindings, out var usesPushDescriptors, out var demand);
|
var setLayout = CreateDescriptorSetLayout(bindings, out var usesPushDescriptors, out var demand);
|
||||||
|
|
@ -1336,7 +1328,6 @@ internal static unsafe partial class VulkanVideoPresenter
|
||||||
var bindings = new List<DescriptorSetLayoutBinding>();
|
var bindings = new List<DescriptorSetLayoutBinding>();
|
||||||
CollectLayoutBindings(bindings, description.Stage, ShaderStage.Compute);
|
CollectLayoutBindings(bindings, description.Stage, ShaderStage.Compute);
|
||||||
var setLayout = CreateDescriptorSetLayout(bindings, out var usesPushDescriptors, out var demand);
|
var setLayout = CreateDescriptorSetLayout(bindings, out var usesPushDescriptors, out var demand);
|
||||||
EnsureBindlessImageHeap(description.Stage);
|
|
||||||
var layout = CreatePipelineLayout(setLayout, ShaderStageFlags.ComputeBit, description.Stage.Bindings!.UsesBindlessImages);
|
var layout = CreatePipelineLayout(setLayout, ShaderStageFlags.ComputeBit, description.Stage.Bindings!.UsesBindlessImages);
|
||||||
var computeModule = new ShaderModule(description.Program.Module);
|
var computeModule = new ShaderModule(description.Program.Module);
|
||||||
if (computeModule.Handle == 0)
|
if (computeModule.Handle == 0)
|
||||||
|
|
|
||||||
|
|
@ -93,9 +93,6 @@ internal static unsafe partial class VulkanVideoPresenter
|
||||||
var workerCount = Math.Clamp(Environment.ProcessorCount / 4, 1, 4);
|
var workerCount = Math.Clamp(Environment.ProcessorCount / 4, 1, 4);
|
||||||
var remaining = workerCount;
|
var remaining = workerCount;
|
||||||
var host = (IShaderPipelineHost)this;
|
var host = (IShaderPipelineHost)this;
|
||||||
// The workers create layouts that include the global set. Initialize
|
|
||||||
// it once on the device setup thread, before any worker can use it.
|
|
||||||
EnsureBindlessImageHeapForMode(host.UsesBindlessImages);
|
|
||||||
Volatile.Write(ref _shaderPrewarmTotal, pending.Count);
|
Volatile.Write(ref _shaderPrewarmTotal, pending.Count);
|
||||||
Volatile.Write(ref _shaderPrewarmProgress, 0);
|
Volatile.Write(ref _shaderPrewarmProgress, 0);
|
||||||
Console.Error.WriteLine(
|
Console.Error.WriteLine(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue