Browse Source

2nd step on the bindless implementation

temporary-branch
CamilleLaVey 2 days ago
parent
commit
fb65aa3c33
  1. 16
      src/video_core/renderer_vulkan/pipeline_helper.h
  2. 71
      src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
  3. 8
      src/video_core/renderer_vulkan/vk_graphics_pipeline.h
  4. 4
      src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
  5. 4
      src/video_core/vulkan_common/vulkan_device.h

16
src/video_core/renderer_vulkan/pipeline_helper.h

@ -177,7 +177,6 @@ public:
return result;
}
// TODO(crueter): utilize layout binding flags
vk::DescriptorSetLayout CreateDescriptorSetLayout(bool use_push_descriptor,
bool use_descriptor_buffer = false) const {
if (bindings.empty()) {
@ -190,9 +189,22 @@ public:
if (use_descriptor_buffer) {
flags |= VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT;
}
boost::container::small_vector<VkDescriptorBindingFlags, 32> binding_flags;
VkDescriptorSetLayoutBindingFlagsCreateInfo binding_flags_ci{};
const void* pnext = nullptr;
if (!use_push_descriptor && device->IsDescriptorBindingPartiallyBoundSupported()) {
binding_flags.assign(bindings.size(), VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT);
binding_flags_ci = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
.pNext = nullptr,
.bindingCount = static_cast<u32>(binding_flags.size()),
.pBindingFlags = binding_flags.data(),
};
pnext = &binding_flags_ci;
}
return device->GetLogical().CreateDescriptorSetLayout({
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.pNext = nullptr,
.pNext = pnext,
.flags = flags,
.bindingCount = static_cast<u32>(bindings.size()),
.pBindings = bindings.data(),

71
src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp

@ -251,13 +251,15 @@ GraphicsPipeline::GraphicsPipeline(
Scheduler& scheduler_, BufferCache& buffer_cache_, TextureCache& texture_cache_,
vk::PipelineCache& pipeline_cache_, VideoCore::ShaderNotify* shader_notify,
const Device& device_, DescriptorPool& descriptor_pool,
GuestDescriptorQueue& guest_descriptor_queue_, Common::ThreadWorker* worker_thread,
GuestDescriptorQueue& guest_descriptor_queue_, DescriptorBufferRing& descriptor_buffer_ring_,
Common::ThreadWorker* worker_thread,
PipelineStatistics* pipeline_statistics, RenderPassCache& render_pass_cache,
const GraphicsPipelineCacheKey& key_, std::array<vk::ShaderModule, NUM_STAGES> stages,
const std::array<const Shader::Info*, NUM_STAGES>& infos)
: key{key_}, device{device_}, texture_cache{texture_cache_}, buffer_cache{buffer_cache_},
pipeline_cache(pipeline_cache_), scheduler{scheduler_},
guest_descriptor_queue{guest_descriptor_queue_}, spv_modules{std::move(stages)} {
guest_descriptor_queue{guest_descriptor_queue_},
descriptor_buffer_ring{descriptor_buffer_ring_}, spv_modules{std::move(stages)} {
if (shader_notify) {
shader_notify->MarkShaderBuilding();
}
@ -277,20 +279,36 @@ GraphicsPipeline::GraphicsPipeline(
num_descriptor_entries += NumDescriptorEntries(*info);
}
fragment_has_color0_output = stage_infos[NUM_STAGES - 1].stores_frag_color[0];
auto func{[this, shader_notify, &render_pass_cache, &descriptor_pool, pipeline_statistics] {
DescriptorLayoutBuilder builder{MakeBuilder(device, stage_infos)};
uses_push_descriptor = builder.CanUsePushDescriptor();
descriptor_set_layout = builder.CreateDescriptorSetLayout(uses_push_descriptor);
if (!uses_push_descriptor) {
descriptor_allocator = descriptor_pool.Allocator(device, scheduler, *descriptor_set_layout, stage_infos);
DescriptorLayoutBuilder builder{MakeBuilder(device, stage_infos)};
uses_push_descriptor = builder.CanUsePushDescriptor();
uses_descriptor_buffer = builder.CanUseDescriptorBuffer() && descriptor_buffer_ring.IsValid();
descriptor_set_layout =
builder.CreateDescriptorSetLayout(uses_push_descriptor, uses_descriptor_buffer);
if (uses_descriptor_buffer) {
descriptor_buffer_layout = builder.MakeDescriptorBufferLayout(*descriptor_set_layout);
if (descriptor_buffer_layout.size > DescriptorBufferRing::MaxAllocationSize()) {
LOG_WARNING(Render_Vulkan,
"Graphics pipeline {:016X} needs {} descriptor bytes, falling back to sets",
key.Hash(), descriptor_buffer_layout.size);
uses_descriptor_buffer = false;
descriptor_buffer_layout = {};
descriptor_set_layout = builder.CreateDescriptorSetLayout(false);
}
}
const VkDescriptorSetLayout set_layout{*descriptor_set_layout};
pipeline_layout = builder.CreatePipelineLayout(set_layout);
const VkDescriptorSetLayout set_layout{*descriptor_set_layout};
pipeline_layout = builder.CreatePipelineLayout(set_layout);
if (!uses_descriptor_buffer) {
descriptor_update_template =
builder.CreateTemplate(set_layout, *pipeline_layout, uses_push_descriptor);
if (!uses_push_descriptor) {
descriptor_allocator =
descriptor_pool.Allocator(device, scheduler, set_layout, stage_infos);
}
}
auto func{[this, shader_notify, &render_pass_cache, pipeline_statistics] {
VkRenderPass render_pass{};
if (!device.IsKhrDynamicRenderingSupported()) {
render_pass = render_pass_cache.Get(MakeRenderPassKey(key.state, device));
@ -500,7 +518,7 @@ bool GraphicsPipeline::ConfigureImpl(bool is_indexed) {
buffer_cache.UpdateGraphicsBuffers(is_indexed);
buffer_cache.BindHostGeometryBuffers(is_indexed);
guest_descriptor_queue.Acquire(scheduler, num_descriptor_entries);
guest_descriptor_queue.Acquire(scheduler, num_descriptor_entries, uses_descriptor_buffer);
RescalingPushConstant rescaling;
RenderAreaPushConstant render_area;
@ -570,7 +588,7 @@ void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling,
const void* const descriptor_data{guest_descriptor_queue.UpdateData()};
bool update_descriptors = true;
if (descriptor_set_layout && !uses_push_descriptor) {
if (descriptor_set_layout && !uses_push_descriptor && !uses_descriptor_buffer) {
const auto* const entries = static_cast<const DescriptorUpdateEntry*>(descriptor_data);
update_descriptors =
bind_pipeline || last_descriptor_payload.size() != num_descriptor_entries ||
@ -580,7 +598,21 @@ void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling,
last_descriptor_payload.assign(entries, entries + num_descriptor_entries);
}
}
VkDeviceSize descriptor_buffer_offset{};
bool descriptor_buffer_ready{false};
if (descriptor_set_layout && uses_descriptor_buffer) {
const DescriptorBufferRing::Allocation alloc{
descriptor_buffer_ring.Allocate(scheduler, descriptor_buffer_layout.size)};
if (alloc.host) {
WriteDescriptorBuffer(device, descriptor_buffer_layout,
static_cast<const DescriptorUpdateEntry*>(descriptor_data),
alloc.host);
descriptor_buffer_offset = alloc.offset;
descriptor_buffer_ready = true;
}
}
scheduler.Record([this, descriptor_data, bind_pipeline, update_descriptors,
descriptor_buffer_offset, descriptor_buffer_ready,
rescaling_data = rescaling.Data(), is_rescaling, update_rescaling,
uses_render_area = render_area.uses_render_area,
render_area_data = render_area.words](vk::CommandBuffer cmdbuf) {
@ -608,7 +640,17 @@ void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling,
if (!descriptor_set_layout) {
return;
}
if (uses_push_descriptor) {
if (uses_descriptor_buffer) {
if (!descriptor_buffer_ready) {
return;
}
const VkDescriptorBufferBindingInfoEXT binding_info{
descriptor_buffer_ring.BindingInfo()};
cmdbuf.BindDescriptorBuffersEXT(binding_info);
const u32 buffer_index{};
cmdbuf.SetDescriptorBufferOffsetsEXT(VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline_layout,
0, buffer_index, descriptor_buffer_offset);
} else if (uses_push_descriptor) {
cmdbuf.PushDescriptorSetWithTemplateKHR(*descriptor_update_template, *pipeline_layout,
0, descriptor_data);
} else if (update_descriptors) {
@ -1017,6 +1059,9 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
if (device.IsKhrPipelineExecutablePropertiesEnabled() && Settings::values.renderer_debug.GetValue()) {
flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR;
}
if (uses_descriptor_buffer) {
flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT;
}
const RenderPassKey renderpass_key{MakeRenderPassKey(key.state, device)};
std::array<VkFormat, Maxwell::NumRenderTargets> color_attachment_formats{};

8
src/video_core/renderer_vulkan/vk_graphics_pipeline.h

@ -18,7 +18,9 @@
#include "shader_recompiler/shader_info.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/renderer_vulkan/fixed_pipeline_state.h"
#include "video_core/renderer_vulkan/pipeline_helper.h"
#include "video_core/renderer_vulkan/vk_buffer_cache.h"
#include "video_core/renderer_vulkan/vk_descriptor_buffer.h"
#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
#include "video_core/renderer_vulkan/vk_texture_cache.h"
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
@ -78,7 +80,8 @@ public:
Scheduler& scheduler, BufferCache& buffer_cache, TextureCache& texture_cache,
vk::PipelineCache& pipeline_cache, VideoCore::ShaderNotify* shader_notify,
const Device& device, DescriptorPool& descriptor_pool,
GuestDescriptorQueue& guest_descriptor_queue, Common::ThreadWorker* worker_thread,
GuestDescriptorQueue& guest_descriptor_queue,
DescriptorBufferRing& descriptor_buffer_ring, Common::ThreadWorker* worker_thread,
PipelineStatistics* pipeline_statistics, RenderPassCache& render_pass_cache,
const GraphicsPipelineCacheKey& key, std::array<vk::ShaderModule, NUM_STAGES> stages,
const std::array<const Shader::Info*, NUM_STAGES>& infos);
@ -150,6 +153,7 @@ private:
vk::PipelineCache& pipeline_cache;
Scheduler& scheduler;
GuestDescriptorQueue& guest_descriptor_queue;
DescriptorBufferRing& descriptor_buffer_ring;
bool (*configure_func)(GraphicsPipeline*, bool){};
@ -172,12 +176,14 @@ private:
vk::DescriptorUpdateTemplate descriptor_update_template;
vk::Pipeline pipeline;
DescriptorBufferLayout descriptor_buffer_layout;
std::vector<DescriptorUpdateEntry> last_descriptor_payload;
std::condition_variable build_condvar;
std::mutex build_mutex;
std::atomic_bool is_built{false};
bool uses_push_descriptor{false};
bool uses_descriptor_buffer{false};
};
} // namespace Vulkan

4
src/video_core/renderer_vulkan/vk_pipeline_cache.cpp

@ -873,8 +873,8 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr};
return std::make_unique<GraphicsPipeline>(
scheduler, buffer_cache, texture_cache, vulkan_pipeline_cache, &shader_notify, device,
descriptor_pool, guest_descriptor_queue, thread_worker, statistics, render_pass_cache, key,
std::move(modules), infos);
descriptor_pool, guest_descriptor_queue, descriptor_buffer_ring, thread_worker, statistics,
render_pass_cache, key, std::move(modules), infos);
} catch (const Shader::Exception& exception) {
auto hash = key.Hash();

4
src/video_core/vulkan_common/vulkan_device.h

@ -905,6 +905,10 @@ FN_MAX_LIMIT_LIST
return extensions.external_memory_host;
}
bool IsDescriptorBindingPartiallyBoundSupported() const {
return features.descriptor_indexing.descriptorBindingPartiallyBound;
}
u64 GetMinImportedHostPointerAlignment() const {
return properties.external_memory_host.minImportedHostPointerAlignment;
}

Loading…
Cancel
Save