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