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;
};
struct DescriptorLayoutTuple {
vk::DescriptorSetLayout descriptor_set_layout;
vk::PipelineLayout pipeline_layout;
vk::DescriptorUpdateTemplateKHR descriptor_update_template;
};
class DescriptorLayoutBuilder {
public:
DescriptorLayoutTuple Create(const vk::Device& device) {
DescriptorLayoutTuple result;
if (!bindings.empty()) {
result.descriptor_set_layout = device.CreateDescriptorSetLayout({
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.bindingCount = static_cast<u32>(bindings.size()),
.pBindings = bindings.data(),
});
DescriptorLayoutBuilder(const vk::Device& device_) : device{&device_} {}
vk::DescriptorSetLayout CreateDescriptorSetLayout() const {
if (bindings.empty()) {
return nullptr;
}
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,
.pNext = nullptr,
.flags = 0,
.setLayoutCount = result.descriptor_set_layout ? 1U : 0U,
.pSetLayouts = bindings.empty() ? nullptr : result.descriptor_set_layout.address(),
.setLayoutCount = descriptor_set_layout ? 1U : 0U,
.pSetLayouts = bindings.empty() ? nullptr : &descriptor_set_layout,
.pushConstantRangeCount = 0,
.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) {
@ -113,6 +116,7 @@ private:
offset += sizeof(DescriptorUpdateEntry);
}
const vk::Device* device{};
boost::container::small_vector<VkDescriptorSetLayoutBinding, 32> bindings;
boost::container::small_vector<VkDescriptorUpdateTemplateEntryKHR, 32> entries;
u32 binding{};

View file

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

View file

@ -17,13 +17,6 @@
#include "video_core/vulkan_common/vulkan_wrapper.h"
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,
VKUpdateDescriptorQueue& update_descriptor_queue_,
@ -31,10 +24,12 @@ ComputePipeline::ComputePipeline(const Device& device, VKDescriptorPool& descrip
vk::ShaderModule spv_module_)
: update_descriptor_queue{update_descriptor_queue_}, info{info_},
spv_module(std::move(spv_module_)) {
DescriptorLayoutTuple tuple{CreateLayout(device, info)};
descriptor_set_layout = std::move(tuple.descriptor_set_layout);
pipeline_layout = std::move(tuple.pipeline_layout);
descriptor_update_template = std::move(tuple.descriptor_update_template);
DescriptorLayoutBuilder builder{device.GetLogical()};
builder.Add(info, VK_SHADER_STAGE_COMPUTE_BIT);
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);
auto func{[this, &device] {
@ -128,7 +123,7 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
return;
}
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) {
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline_layout, 0,
descriptor_set, nullptr);

View file

@ -27,8 +27,8 @@ using VideoCore::Surface::PixelFormat;
using VideoCore::Surface::PixelFormatFromDepthFormat;
using VideoCore::Surface::PixelFormatFromRenderTargetFormat;
DescriptorLayoutTuple CreateLayout(const Device& device, std::span<const Shader::Info> infos) {
DescriptorLayoutBuilder builder;
DescriptorLayoutBuilder MakeBuilder(const Device& device, std::span<const Shader::Info> infos) {
DescriptorLayoutBuilder builder{device.GetLogical()};
for (size_t index = 0; index < infos.size(); ++index) {
static constexpr std::array stages{
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));
}
return builder.Create(device.GetLogical());
return builder;
}
template <class StencilFace>
@ -124,13 +124,15 @@ GraphicsPipeline::GraphicsPipeline(Tegra::Engines::Maxwell3D& maxwell3d_,
std::ranges::transform(infos, stage_infos.begin(),
[](const Shader::Info* info) { return info ? *info : Shader::Info{}; });
DescriptorLayoutTuple tuple{CreateLayout(device, stage_infos)};
descriptor_set_layout = std::move(tuple.descriptor_set_layout);
pipeline_layout = std::move(tuple.pipeline_layout);
descriptor_update_template = std::move(tuple.descriptor_update_template);
DescriptorLayoutBuilder builder{MakeBuilder(device, stage_infos)};
descriptor_set_layout = builder.CreateDescriptorSetLayout();
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))};
MakePipeline(device, render_pass);
building_flag.test_and_set();
@ -206,11 +208,11 @@ void GraphicsPipeline::Configure(bool is_indexed) {
return;
}
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) {
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set,
nullptr);
scheduler.Record([this, descriptor_set](vk::CommandBuffer cmdbuf) {
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline_layout, 0,
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_},
scheduler{scheduler_}, descriptor_pool{descriptor_pool_},
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 VkDriverIdKHR driver_id{device.GetDriverID()};
base_profile = Shader::Profile{

View file

@ -36,12 +36,12 @@ void VKUpdateDescriptorQueue::Acquire() {
upload_start = payload_cursor;
}
void VKUpdateDescriptorQueue::Send(VkDescriptorUpdateTemplateKHR update_template,
void VKUpdateDescriptorQueue::Send(const VkDescriptorUpdateTemplateKHR* update_template,
VkDescriptorSet set) {
const void* const data = upload_start;
const vk::Device* const logical = &device.GetLogical();
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 Send(VkDescriptorUpdateTemplateKHR update_template, VkDescriptorSet set);
void Send(const VkDescriptorUpdateTemplateKHR* update_template, VkDescriptorSet set);
void AddSampledImage(VkImageView image_view, VkSampler sampler) {
*(payload_cursor++) = VkDescriptorImageInfo{