vulkan: Create pipeline layouts in separate threads

This commit is contained in:
ReinUsesLisp 2021-04-01 03:15:28 -03:00 committed by ameerj
parent 2fc698b040
commit 8771639d1e
7 changed files with 65 additions and 63 deletions

View File

@ -35,49 +35,52 @@ struct TextureHandle {
u32 sampler; u32 sampler;
}; };
struct DescriptorLayoutTuple {
vk::DescriptorSetLayout descriptor_set_layout;
vk::PipelineLayout pipeline_layout;
vk::DescriptorUpdateTemplateKHR descriptor_update_template;
};
class DescriptorLayoutBuilder { class DescriptorLayoutBuilder {
public: public:
DescriptorLayoutTuple Create(const vk::Device& device) { DescriptorLayoutBuilder(const vk::Device& device_) : device{&device_} {}
DescriptorLayoutTuple result;
if (!bindings.empty()) { vk::DescriptorSetLayout CreateDescriptorSetLayout() const {
result.descriptor_set_layout = device.CreateDescriptorSetLayout({ if (bindings.empty()) {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, return nullptr;
.pNext = nullptr,
.flags = 0,
.bindingCount = static_cast<u32>(bindings.size()),
.pBindings = bindings.data(),
});
} }
result.pipeline_layout = device.CreatePipelineLayout({ return device->CreateDescriptorSetLayout({
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.bindingCount = static_cast<u32>(bindings.size()),
.pBindings = bindings.data(),
});
}
vk::DescriptorUpdateTemplateKHR CreateTemplate(VkDescriptorSetLayout descriptor_set_layout,
VkPipelineLayout pipeline_layout) const {
if (entries.empty()) {
return nullptr;
}
return device->CreateDescriptorUpdateTemplateKHR({
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
.pNext = nullptr,
.flags = 0,
.descriptorUpdateEntryCount = static_cast<u32>(entries.size()),
.pDescriptorUpdateEntries = entries.data(),
.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR,
.descriptorSetLayout = descriptor_set_layout,
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
.pipelineLayout = pipeline_layout,
.set = 0,
});
}
vk::PipelineLayout CreatePipelineLayout(VkDescriptorSetLayout descriptor_set_layout) const {
return device->CreatePipelineLayout({
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
.flags = 0, .flags = 0,
.setLayoutCount = result.descriptor_set_layout ? 1U : 0U, .setLayoutCount = descriptor_set_layout ? 1U : 0U,
.pSetLayouts = bindings.empty() ? nullptr : result.descriptor_set_layout.address(), .pSetLayouts = bindings.empty() ? nullptr : &descriptor_set_layout,
.pushConstantRangeCount = 0, .pushConstantRangeCount = 0,
.pPushConstantRanges = nullptr, .pPushConstantRanges = nullptr,
}); });
if (!entries.empty()) {
result.descriptor_update_template = device.CreateDescriptorUpdateTemplateKHR({
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
.pNext = nullptr,
.flags = 0,
.descriptorUpdateEntryCount = static_cast<u32>(entries.size()),
.pDescriptorUpdateEntries = entries.data(),
.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR,
.descriptorSetLayout = *result.descriptor_set_layout,
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
.pipelineLayout = *result.pipeline_layout,
.set = 0,
});
}
return result;
} }
void Add(const Shader::Info& info, VkShaderStageFlags stage) { void Add(const Shader::Info& info, VkShaderStageFlags stage) {
@ -113,6 +116,7 @@ private:
offset += sizeof(DescriptorUpdateEntry); offset += sizeof(DescriptorUpdateEntry);
} }
const vk::Device* device{};
boost::container::small_vector<VkDescriptorSetLayoutBinding, 32> bindings; boost::container::small_vector<VkDescriptorSetLayoutBinding, 32> bindings;
boost::container::small_vector<VkDescriptorUpdateTemplateEntryKHR, 32> entries; boost::container::small_vector<VkDescriptorUpdateTemplateEntryKHR, 32> entries;
u32 binding{}; u32 binding{};

View File

@ -237,7 +237,7 @@ VkDescriptorSet VKComputePass::CommitDescriptorSet(
return nullptr; return nullptr;
} }
const VkDescriptorSet set = descriptor_allocator->Commit(); const VkDescriptorSet set = descriptor_allocator->Commit();
update_descriptor_queue.Send(*descriptor_template, set); update_descriptor_queue.Send(descriptor_template.address(), set);
return set; return set;
} }

View File

@ -17,13 +17,6 @@
#include "video_core/vulkan_common/vulkan_wrapper.h" #include "video_core/vulkan_common/vulkan_wrapper.h"
namespace Vulkan { namespace Vulkan {
namespace {
DescriptorLayoutTuple CreateLayout(const Device& device, const Shader::Info& info) {
DescriptorLayoutBuilder builder;
builder.Add(info, VK_SHADER_STAGE_COMPUTE_BIT);
return builder.Create(device.GetLogical());
}
} // Anonymous namespace
ComputePipeline::ComputePipeline(const Device& device, VKDescriptorPool& descriptor_pool, ComputePipeline::ComputePipeline(const Device& device, VKDescriptorPool& descriptor_pool,
VKUpdateDescriptorQueue& update_descriptor_queue_, VKUpdateDescriptorQueue& update_descriptor_queue_,
@ -31,10 +24,12 @@ ComputePipeline::ComputePipeline(const Device& device, VKDescriptorPool& descrip
vk::ShaderModule spv_module_) vk::ShaderModule spv_module_)
: update_descriptor_queue{update_descriptor_queue_}, info{info_}, : update_descriptor_queue{update_descriptor_queue_}, info{info_},
spv_module(std::move(spv_module_)) { spv_module(std::move(spv_module_)) {
DescriptorLayoutTuple tuple{CreateLayout(device, info)}; DescriptorLayoutBuilder builder{device.GetLogical()};
descriptor_set_layout = std::move(tuple.descriptor_set_layout); builder.Add(info, VK_SHADER_STAGE_COMPUTE_BIT);
pipeline_layout = std::move(tuple.pipeline_layout);
descriptor_update_template = std::move(tuple.descriptor_update_template); descriptor_set_layout = builder.CreateDescriptorSetLayout();
pipeline_layout = builder.CreatePipelineLayout(*descriptor_set_layout);
descriptor_update_template = builder.CreateTemplate(*descriptor_set_layout, *pipeline_layout);
descriptor_allocator = DescriptorAllocator(descriptor_pool, *descriptor_set_layout); descriptor_allocator = DescriptorAllocator(descriptor_pool, *descriptor_set_layout);
auto func{[this, &device] { auto func{[this, &device] {
@ -128,7 +123,7 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
return; return;
} }
const VkDescriptorSet descriptor_set{descriptor_allocator.Commit()}; const VkDescriptorSet descriptor_set{descriptor_allocator.Commit()};
update_descriptor_queue.Send(*descriptor_update_template, descriptor_set); update_descriptor_queue.Send(descriptor_update_template.address(), descriptor_set);
scheduler.Record([this, descriptor_set](vk::CommandBuffer cmdbuf) { scheduler.Record([this, descriptor_set](vk::CommandBuffer cmdbuf) {
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline_layout, 0, cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline_layout, 0,
descriptor_set, nullptr); descriptor_set, nullptr);

View File

@ -27,8 +27,8 @@ using VideoCore::Surface::PixelFormat;
using VideoCore::Surface::PixelFormatFromDepthFormat; using VideoCore::Surface::PixelFormatFromDepthFormat;
using VideoCore::Surface::PixelFormatFromRenderTargetFormat; using VideoCore::Surface::PixelFormatFromRenderTargetFormat;
DescriptorLayoutTuple CreateLayout(const Device& device, std::span<const Shader::Info> infos) { DescriptorLayoutBuilder MakeBuilder(const Device& device, std::span<const Shader::Info> infos) {
DescriptorLayoutBuilder builder; DescriptorLayoutBuilder builder{device.GetLogical()};
for (size_t index = 0; index < infos.size(); ++index) { for (size_t index = 0; index < infos.size(); ++index) {
static constexpr std::array stages{ static constexpr std::array stages{
VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_VERTEX_BIT,
@ -39,7 +39,7 @@ DescriptorLayoutTuple CreateLayout(const Device& device, std::span<const Shader:
}; };
builder.Add(infos[index], stages.at(index)); builder.Add(infos[index], stages.at(index));
} }
return builder.Create(device.GetLogical()); return builder;
} }
template <class StencilFace> template <class StencilFace>
@ -124,13 +124,15 @@ GraphicsPipeline::GraphicsPipeline(Tegra::Engines::Maxwell3D& maxwell3d_,
std::ranges::transform(infos, stage_infos.begin(), std::ranges::transform(infos, stage_infos.begin(),
[](const Shader::Info* info) { return info ? *info : Shader::Info{}; }); [](const Shader::Info* info) { return info ? *info : Shader::Info{}; });
DescriptorLayoutTuple tuple{CreateLayout(device, stage_infos)}; DescriptorLayoutBuilder builder{MakeBuilder(device, stage_infos)};
descriptor_set_layout = std::move(tuple.descriptor_set_layout); descriptor_set_layout = builder.CreateDescriptorSetLayout();
pipeline_layout = std::move(tuple.pipeline_layout);
descriptor_update_template = std::move(tuple.descriptor_update_template);
descriptor_allocator = DescriptorAllocator(descriptor_pool, *descriptor_set_layout); descriptor_allocator = DescriptorAllocator(descriptor_pool, *descriptor_set_layout);
auto func{[this, &device, &render_pass_cache] { auto func{[this, &device, &render_pass_cache, builder] {
const VkDescriptorSetLayout set_layout{*descriptor_set_layout};
pipeline_layout = builder.CreatePipelineLayout(set_layout);
descriptor_update_template = builder.CreateTemplate(set_layout, *pipeline_layout);
const VkRenderPass render_pass{render_pass_cache.Get(MakeRenderPassKey(state))}; const VkRenderPass render_pass{render_pass_cache.Get(MakeRenderPassKey(state))};
MakePipeline(device, render_pass); MakePipeline(device, render_pass);
building_flag.test_and_set(); building_flag.test_and_set();
@ -206,11 +208,11 @@ void GraphicsPipeline::Configure(bool is_indexed) {
return; return;
} }
const VkDescriptorSet descriptor_set{descriptor_allocator.Commit()}; const VkDescriptorSet descriptor_set{descriptor_allocator.Commit()};
update_descriptor_queue.Send(*descriptor_update_template, descriptor_set); update_descriptor_queue.Send(descriptor_update_template.address(), descriptor_set);
scheduler.Record([descriptor_set, layout = *pipeline_layout](vk::CommandBuffer cmdbuf) { scheduler.Record([this, descriptor_set](vk::CommandBuffer cmdbuf) {
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set, cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline_layout, 0,
nullptr); descriptor_set, nullptr);
}); });
} }

View File

@ -620,7 +620,8 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::GPU& gpu_,
kepler_compute{kepler_compute_}, gpu_memory{gpu_memory_}, device{device_}, kepler_compute{kepler_compute_}, gpu_memory{gpu_memory_}, device{device_},
scheduler{scheduler_}, descriptor_pool{descriptor_pool_}, scheduler{scheduler_}, descriptor_pool{descriptor_pool_},
update_descriptor_queue{update_descriptor_queue_}, render_pass_cache{render_pass_cache_}, update_descriptor_queue{update_descriptor_queue_}, render_pass_cache{render_pass_cache_},
buffer_cache{buffer_cache_}, texture_cache{texture_cache_}, workers(11, "PipelineBuilder") { buffer_cache{buffer_cache_}, texture_cache{texture_cache_},
workers(11, "yuzu:PipelineBuilder") {
const auto& float_control{device.FloatControlProperties()}; const auto& float_control{device.FloatControlProperties()};
const VkDriverIdKHR driver_id{device.GetDriverID()}; const VkDriverIdKHR driver_id{device.GetDriverID()};
base_profile = Shader::Profile{ base_profile = Shader::Profile{

View File

@ -36,12 +36,12 @@ void VKUpdateDescriptorQueue::Acquire() {
upload_start = payload_cursor; upload_start = payload_cursor;
} }
void VKUpdateDescriptorQueue::Send(VkDescriptorUpdateTemplateKHR update_template, void VKUpdateDescriptorQueue::Send(const VkDescriptorUpdateTemplateKHR* update_template,
VkDescriptorSet set) { VkDescriptorSet set) {
const void* const data = upload_start; const void* const data = upload_start;
const vk::Device* const logical = &device.GetLogical(); const vk::Device* const logical = &device.GetLogical();
scheduler.Record([data, logical, set, update_template](vk::CommandBuffer) { scheduler.Record([data, logical, set, update_template](vk::CommandBuffer) {
logical->UpdateDescriptorSet(set, update_template, data); logical->UpdateDescriptorSet(set, *update_template, data);
}); });
} }

View File

@ -39,7 +39,7 @@ public:
void Acquire(); void Acquire();
void Send(VkDescriptorUpdateTemplateKHR update_template, VkDescriptorSet set); void Send(const VkDescriptorUpdateTemplateKHR* update_template, VkDescriptorSet set);
void AddSampledImage(VkImageView image_view, VkSampler sampler) { void AddSampledImage(VkImageView image_view, VkSampler sampler) {
*(payload_cursor++) = VkDescriptorImageInfo{ *(payload_cursor++) = VkDescriptorImageInfo{