vulkan: Create pipeline layouts in separate threads
This commit is contained in:
parent
2fc698b040
commit
8771639d1e
|
@ -35,18 +35,15 @@ 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({
|
||||
DescriptorLayoutBuilder(const vk::Device& device_) : device{&device_} {}
|
||||
|
||||
vk::DescriptorSetLayout CreateDescriptorSetLayout() const {
|
||||
if (bindings.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
return device->CreateDescriptorSetLayout({
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
|
@ -54,30 +51,36 @@ public:
|
|||
.pBindings = bindings.data(),
|
||||
});
|
||||
}
|
||||
result.pipeline_layout = 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(),
|
||||
.pushConstantRangeCount = 0,
|
||||
.pPushConstantRanges = nullptr,
|
||||
});
|
||||
if (!entries.empty()) {
|
||||
result.descriptor_update_template = device.CreateDescriptorUpdateTemplateKHR({
|
||||
|
||||
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 = *result.descriptor_set_layout,
|
||||
.descriptorSetLayout = descriptor_set_layout,
|
||||
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
.pipelineLayout = *result.pipeline_layout,
|
||||
.pipelineLayout = pipeline_layout,
|
||||
.set = 0,
|
||||
});
|
||||
}
|
||||
return result;
|
||||
|
||||
vk::PipelineLayout CreatePipelineLayout(VkDescriptorSetLayout descriptor_set_layout) const {
|
||||
return device->CreatePipelineLayout({
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.setLayoutCount = descriptor_set_layout ? 1U : 0U,
|
||||
.pSetLayouts = bindings.empty() ? nullptr : &descriptor_set_layout,
|
||||
.pushConstantRangeCount = 0,
|
||||
.pPushConstantRanges = nullptr,
|
||||
});
|
||||
}
|
||||
|
||||
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{};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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{
|
||||
|
|
Reference in New Issue