diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index b9876fd18..b6b36c005 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -88,6 +88,8 @@ add_library(video_core STATIC renderer_vulkan/vk_blit_helper.h renderer_vulkan/vk_common.cpp renderer_vulkan/vk_common.h + renderer_vulkan/vk_descriptor_manager.cpp + renderer_vulkan/vk_descriptor_manager.h renderer_vulkan/vk_format_reinterpreter.cpp renderer_vulkan/vk_format_reinterpreter.h renderer_vulkan/vk_layout_tracker.h diff --git a/src/video_core/renderer_vulkan/vk_common.h b/src/video_core/renderer_vulkan/vk_common.h index 9f657385f..674565e4b 100644 --- a/src/video_core/renderer_vulkan/vk_common.h +++ b/src/video_core/renderer_vulkan/vk_common.h @@ -10,6 +10,8 @@ #define VK_NO_PROTOTYPES 1 #define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 #define VULKAN_HPP_NO_CONSTRUCTORS +#define VULKAN_HPP_NO_STRUCT_SETTERS +#define VULKAN_HPP_NO_SMART_HANDLE #include #define VMA_STATIC_VULKAN_FUNCTIONS 0 diff --git a/src/video_core/renderer_vulkan/vk_descriptor_manager.cpp b/src/video_core/renderer_vulkan/vk_descriptor_manager.cpp new file mode 100644 index 000000000..893536e99 --- /dev/null +++ b/src/video_core/renderer_vulkan/vk_descriptor_manager.cpp @@ -0,0 +1,176 @@ +// Copyright 2022 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "video_core/renderer_vulkan/vk_descriptor_manager.h" +#include "video_core/renderer_vulkan/vk_instance.h" +#include "video_core/renderer_vulkan/vk_task_scheduler.h" + +namespace Vulkan { + +struct Bindings { + std::array bindings; + u32 binding_count; +}; + +constexpr u32 DESCRIPTOR_BATCH_SIZE = 8; +constexpr u32 RASTERIZER_SET_COUNT = 4; +constexpr static std::array RASTERIZER_SETS = { + Bindings{// Utility set + .bindings = {vk::DescriptorType::eUniformBuffer, vk::DescriptorType::eUniformBuffer, + vk::DescriptorType::eUniformTexelBuffer, + vk::DescriptorType::eUniformTexelBuffer, + vk::DescriptorType::eUniformTexelBuffer}, + .binding_count = 5}, + Bindings{// Texture set + .bindings = {vk::DescriptorType::eSampledImage, vk::DescriptorType::eSampledImage, + vk::DescriptorType::eSampledImage, vk::DescriptorType::eSampledImage}, + .binding_count = 4}, + Bindings{// Sampler set + .bindings = {vk::DescriptorType::eSampler, vk::DescriptorType::eSampler, + vk::DescriptorType::eSampler, vk::DescriptorType::eSampler}, + .binding_count = 4}, + Bindings{// Shadow set + .bindings = {vk::DescriptorType::eStorageImage, vk::DescriptorType::eStorageImage, + vk::DescriptorType::eStorageImage, vk::DescriptorType::eStorageImage, + vk::DescriptorType::eStorageImage, vk::DescriptorType::eStorageImage, + vk::DescriptorType::eStorageImage}, + .binding_count = 7}}; + +constexpr vk::ShaderStageFlags ToVkStageFlags(vk::DescriptorType type) { + vk::ShaderStageFlags flags; + switch (type) { + case vk::DescriptorType::eSampler: + case vk::DescriptorType::eSampledImage: + case vk::DescriptorType::eUniformTexelBuffer: + case vk::DescriptorType::eStorageImage: + flags = vk::ShaderStageFlagBits::eFragment; + break; + case vk::DescriptorType::eUniformBuffer: + case vk::DescriptorType::eUniformBufferDynamic: + flags = vk::ShaderStageFlagBits::eFragment | vk::ShaderStageFlagBits::eVertex | + vk::ShaderStageFlagBits::eGeometry | vk::ShaderStageFlagBits::eCompute; + break; + default: + LOG_ERROR(Render_Vulkan, "Unknown descriptor type!"); + } + + return flags; +} + +DescriptorManager::DescriptorManager(const Instance& instance, TaskScheduler& scheduler) + : instance{instance}, scheduler{scheduler} { + descriptor_dirty.fill(true); + BuildLayouts(); +} + +DescriptorManager::~DescriptorManager() { + vk::Device device = instance.GetDevice(); + device.destroyPipelineLayout(layout); + + for (std::size_t i = 0; i < MAX_DESCRIPTOR_SETS; i++) { + device.destroyDescriptorSetLayout(descriptor_set_layouts[i]); + device.destroyDescriptorUpdateTemplate(update_templates[i]); + } +} + +void DescriptorManager::SetBinding(u32 set, u32 binding, DescriptorData data) { + if (update_data[set][binding] != data) { + update_data[set][binding] = data; + descriptor_dirty[set] = true; + } +} + +void DescriptorManager::BindDescriptorSets() { + vk::Device device = instance.GetDevice(); + std::array layouts; + + for (u32 i = 0; i < RASTERIZER_SET_COUNT; i++) { + if (descriptor_dirty[i] || !descriptor_sets[i]) { + auto& batch = descriptor_batch[i]; + if (batch.empty()) { + layouts.fill(descriptor_set_layouts[i]); + const vk::DescriptorSetAllocateInfo alloc_info = { + .descriptorPool = scheduler.GetDescriptorPool(), + .descriptorSetCount = DESCRIPTOR_BATCH_SIZE, + .pSetLayouts = layouts.data()}; + + try { + batch = device.allocateDescriptorSets(alloc_info); + } catch (vk::OutOfPoolMemoryError& err) { + LOG_CRITICAL(Render_Vulkan, "Run out of pool memory for layout {}: {}", i, + err.what()); + UNREACHABLE(); + } + } + + vk::DescriptorSet set = batch.back(); + device.updateDescriptorSetWithTemplate(set, update_templates[i], update_data[i][0]); + + descriptor_sets[i] = set; + descriptor_dirty[i] = false; + batch.pop_back(); + } + } + + // Bind the descriptor sets + vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer(); + command_buffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, layout, 0, + RASTERIZER_SET_COUNT, descriptor_sets.data(), 0, nullptr); +} + +void DescriptorManager::MarkDirty() { + descriptor_dirty.fill(true); + for (auto& batch : descriptor_batch) { + batch.clear(); + } +} + +void DescriptorManager::BuildLayouts() { + std::array set_bindings; + std::array update_entries; + + vk::Device device = instance.GetDevice(); + for (u32 i = 0; i < RASTERIZER_SET_COUNT; i++) { + const auto& set = RASTERIZER_SETS[i]; + for (u32 j = 0; j < set.binding_count; j++) { + vk::DescriptorType type = set.bindings[j]; + set_bindings[j] = vk::DescriptorSetLayoutBinding{.binding = j, + .descriptorType = type, + .descriptorCount = 1, + .stageFlags = ToVkStageFlags(type)}; + + update_entries[j] = + vk::DescriptorUpdateTemplateEntry{.dstBinding = j, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = type, + .offset = j * sizeof(DescriptorData), + .stride = 0}; + } + + const vk::DescriptorSetLayoutCreateInfo layout_info = {.bindingCount = set.binding_count, + .pBindings = set_bindings.data()}; + + // Create descriptor set layout + descriptor_set_layouts[i] = device.createDescriptorSetLayout(layout_info); + + const vk::DescriptorUpdateTemplateCreateInfo template_info = { + .descriptorUpdateEntryCount = set.binding_count, + .pDescriptorUpdateEntries = update_entries.data(), + .templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet, + .descriptorSetLayout = descriptor_set_layouts[i]}; + + // Create descriptor set update template + update_templates[i] = device.createDescriptorUpdateTemplate(template_info); + } + + const vk::PipelineLayoutCreateInfo layout_info = {.setLayoutCount = RASTERIZER_SET_COUNT, + .pSetLayouts = descriptor_set_layouts.data(), + .pushConstantRangeCount = 0, + .pPushConstantRanges = nullptr}; + + layout = device.createPipelineLayout(layout_info); +} + +} // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_descriptor_manager.h b/src/video_core/renderer_vulkan/vk_descriptor_manager.h new file mode 100644 index 000000000..1f4937127 --- /dev/null +++ b/src/video_core/renderer_vulkan/vk_descriptor_manager.h @@ -0,0 +1,68 @@ +// Copyright 2022 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "video_core/renderer_vulkan/vk_common.h" + +namespace Vulkan { + +constexpr u32 MAX_DESCRIPTORS = 8; +constexpr u32 MAX_DESCRIPTOR_SETS = 6; + +union DescriptorData { + vk::DescriptorImageInfo image_info; + vk::DescriptorBufferInfo buffer_info; + vk::BufferView buffer_view; + + bool operator!=(const DescriptorData& other) const { + return std::memcmp(this, &other, sizeof(DescriptorData)) != 0; + } +}; + +using DescriptorSetData = std::array; + +class Instance; +class TaskScheduler; + +class DescriptorManager { +public: + DescriptorManager(const Instance& instance, TaskScheduler& scheduler); + ~DescriptorManager(); + + /// Binds a resource to the provided binding + void SetBinding(u32 set, u32 binding, DescriptorData data); + + /// Builds descriptor sets that reference the currently bound resources + void BindDescriptorSets(); + + /// Marks cached descriptor state dirty + void MarkDirty(); + + /// Returns the rasterizer pipeline layout + vk::PipelineLayout GetPipelineLayout() const { + return layout; + } + +private: + /// Builds the rasterizer pipeline layout objects + void BuildLayouts(); + +private: + const Instance& instance; + TaskScheduler& scheduler; + + // Cached layouts for the rasterizer pipelines + vk::PipelineLayout layout; + std::array descriptor_set_layouts; + std::array update_templates; + + // Current data for the descriptor sets + std::array update_data{}; + std::array descriptor_dirty{}; + std::array descriptor_sets; + std::array, MAX_DESCRIPTOR_SETS> descriptor_batch; +}; + +} // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 6e6b590b1..0ee654f77 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -15,56 +15,6 @@ namespace Vulkan { -struct Bindings { - std::array bindings; - u32 binding_count; -}; - -constexpr u32 DESCRIPTOR_BATCH_SIZE = 8; -constexpr u32 RASTERIZER_SET_COUNT = 4; -constexpr static std::array RASTERIZER_SETS = { - Bindings{// Utility set - .bindings = {vk::DescriptorType::eUniformBuffer, vk::DescriptorType::eUniformBuffer, - vk::DescriptorType::eUniformTexelBuffer, - vk::DescriptorType::eUniformTexelBuffer, - vk::DescriptorType::eUniformTexelBuffer}, - .binding_count = 5}, - Bindings{// Texture set - .bindings = {vk::DescriptorType::eSampledImage, vk::DescriptorType::eSampledImage, - vk::DescriptorType::eSampledImage, vk::DescriptorType::eSampledImage}, - .binding_count = 4}, - Bindings{// Sampler set - .bindings = {vk::DescriptorType::eSampler, vk::DescriptorType::eSampler, - vk::DescriptorType::eSampler, vk::DescriptorType::eSampler}, - .binding_count = 4}, - Bindings{// Shadow set - .bindings = {vk::DescriptorType::eStorageImage, vk::DescriptorType::eStorageImage, - vk::DescriptorType::eStorageImage, vk::DescriptorType::eStorageImage, - vk::DescriptorType::eStorageImage, vk::DescriptorType::eStorageImage, - vk::DescriptorType::eStorageImage}, - .binding_count = 7}}; - -constexpr vk::ShaderStageFlags ToVkStageFlags(vk::DescriptorType type) { - vk::ShaderStageFlags flags; - switch (type) { - case vk::DescriptorType::eSampler: - case vk::DescriptorType::eSampledImage: - case vk::DescriptorType::eUniformTexelBuffer: - case vk::DescriptorType::eStorageImage: - flags = vk::ShaderStageFlagBits::eFragment; - break; - case vk::DescriptorType::eUniformBuffer: - case vk::DescriptorType::eUniformBufferDynamic: - flags = vk::ShaderStageFlagBits::eFragment | vk::ShaderStageFlagBits::eVertex | - vk::ShaderStageFlagBits::eGeometry | vk::ShaderStageFlagBits::eCompute; - break; - default: - LOG_ERROR(Render_Vulkan, "Unknown descriptor type!"); - } - - return flags; -} - u32 AttribBytes(VertexAttribute attrib) { switch (attrib.type) { case AttribType::Float: @@ -116,10 +66,9 @@ vk::ShaderStageFlagBits ToVkShaderStage(std::size_t index) { PipelineCache::PipelineCache(const Instance& instance, TaskScheduler& scheduler, RenderpassCache& renderpass_cache) - : instance{instance}, scheduler{scheduler}, renderpass_cache{renderpass_cache} { - descriptor_dirty.fill(true); - - BuildLayout(); + : instance{instance}, scheduler{scheduler}, renderpass_cache{renderpass_cache}, desc_manager{ + instance, + scheduler} { trivial_vertex_shader = Compile(GenerateTrivialVertexShader(), vk::ShaderStageFlagBits::eVertex, instance.GetDevice(), ShaderOptimization::Debug); } @@ -129,13 +78,8 @@ PipelineCache::~PipelineCache() { SaveDiskCache(); - device.destroyPipelineLayout(layout); device.destroyPipelineCache(pipeline_cache); device.destroyShaderModule(trivial_vertex_shader); - for (std::size_t i = 0; i < MAX_DESCRIPTOR_SETS; i++) { - device.destroyDescriptorSetLayout(descriptor_set_layouts[i]); - device.destroyDescriptorUpdateTemplate(update_templates[i]); - } for (auto& [key, module] : programmable_vertex_shaders.shader_cache) { device.destroyShaderModule(module); @@ -238,7 +182,7 @@ void PipelineCache::BindPipeline(const PipelineInfo& info) { current_pipeline = it->second; } - BindDescriptorSets(); + desc_manager.BindDescriptorSets(); } bool PipelineCache::UseProgrammableVertexShader(const Pica::Regs& regs, @@ -291,34 +235,29 @@ void PipelineCache::UseFragmentShader(const Pica::Regs& regs) { void PipelineCache::BindTexture(u32 binding, vk::ImageView image_view) { const vk::DescriptorImageInfo image_info = { .imageView = image_view, .imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal}; - - SetBinding(1, binding, DescriptorData{image_info}); + desc_manager.SetBinding(1, binding, DescriptorData{image_info}); } void PipelineCache::BindStorageImage(u32 binding, vk::ImageView image_view) { const vk::DescriptorImageInfo image_info = {.imageView = image_view, .imageLayout = vk::ImageLayout::eGeneral}; - - SetBinding(3, binding, DescriptorData{image_info}); + desc_manager.SetBinding(3, binding, DescriptorData{image_info}); } void PipelineCache::BindBuffer(u32 binding, vk::Buffer buffer, u32 offset, u32 size) { const DescriptorData data = { .buffer_info = vk::DescriptorBufferInfo{.buffer = buffer, .offset = offset, .range = size}}; - - SetBinding(0, binding, data); + desc_manager.SetBinding(0, binding, data); } void PipelineCache::BindTexelBuffer(u32 binding, vk::BufferView buffer_view) { const DescriptorData data = {.buffer_view = buffer_view}; - - SetBinding(0, binding, data); + desc_manager.SetBinding(0, binding, data); } void PipelineCache::BindSampler(u32 binding, vk::Sampler sampler) { const DescriptorData data = {.image_info = vk::DescriptorImageInfo{.sampler = sampler}}; - - SetBinding(2, binding, data); + desc_manager.SetBinding(2, binding, data); } void PipelineCache::SetViewport(float x, float y, float width, float height) { @@ -342,12 +281,9 @@ void PipelineCache::SetScissor(s32 x, s32 y, u32 width, u32 height) { } void PipelineCache::MarkDirty() { - descriptor_dirty.fill(true); + desc_manager.MarkDirty(); current_pipeline = VK_NULL_HANDLE; state_dirty = true; - for (auto& batch : descriptor_batch) { - batch.clear(); - } } void PipelineCache::ApplyDynamic(const PipelineInfo& info) { @@ -426,60 +362,6 @@ void PipelineCache::ApplyDynamic(const PipelineInfo& info) { state_dirty = false; } -void PipelineCache::SetBinding(u32 set, u32 binding, DescriptorData data) { - if (update_data[set][binding] != data) { - update_data[set][binding] = data; - descriptor_dirty[set] = true; - } -} - -void PipelineCache::BuildLayout() { - std::array set_bindings; - std::array update_entries; - - vk::Device device = instance.GetDevice(); - for (u32 i = 0; i < RASTERIZER_SET_COUNT; i++) { - const auto& set = RASTERIZER_SETS[i]; - for (u32 j = 0; j < set.binding_count; j++) { - vk::DescriptorType type = set.bindings[j]; - set_bindings[j] = vk::DescriptorSetLayoutBinding{.binding = j, - .descriptorType = type, - .descriptorCount = 1, - .stageFlags = ToVkStageFlags(type)}; - - update_entries[j] = - vk::DescriptorUpdateTemplateEntry{.dstBinding = j, - .dstArrayElement = 0, - .descriptorCount = 1, - .descriptorType = type, - .offset = j * sizeof(DescriptorData), - .stride = 0}; - } - - const vk::DescriptorSetLayoutCreateInfo layout_info = {.bindingCount = set.binding_count, - .pBindings = set_bindings.data()}; - - // Create descriptor set layout - descriptor_set_layouts[i] = device.createDescriptorSetLayout(layout_info); - - const vk::DescriptorUpdateTemplateCreateInfo template_info = { - .descriptorUpdateEntryCount = set.binding_count, - .pDescriptorUpdateEntries = update_entries.data(), - .templateType = vk::DescriptorUpdateTemplateType::eDescriptorSet, - .descriptorSetLayout = descriptor_set_layouts[i]}; - - // Create descriptor set update template - update_templates[i] = device.createDescriptorUpdateTemplate(template_info); - } - - const vk::PipelineLayoutCreateInfo layout_info = {.setLayoutCount = RASTERIZER_SET_COUNT, - .pSetLayouts = descriptor_set_layouts.data(), - .pushConstantRangeCount = 0, - .pPushConstantRanges = nullptr}; - - layout = device.createPipelineLayout(layout_info); -} - vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) { vk::Device device = instance.GetDevice(); @@ -495,12 +377,10 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) { .stage = ToVkShaderStage(i), .module = shader, .pName = "main"}; } - /** - * Vulkan doesn't intuitively support fixed attributes. To avoid duplicating the data and - * increasing data upload, when the fixed flag is true, we specify VK_VERTEX_INPUT_RATE_INSTANCE - * as the input rate. Since one instance is all we render, the shader will always read the - * single attribute. - */ + // Vulkan doesn't intuitively support fixed attributes. To avoid duplicating the data and + // increasing data upload, when the fixed flag is true, we specify VK_VERTEX_INPUT_RATE_INSTANCE + // as the input rate. Since one instance is all we render, the shader will always read the + // single attribute. std::array bindings; for (u32 i = 0; i < info.vertex_layout.binding_count; i++) { const auto& binding = info.vertex_layout.bindings[i]; @@ -624,7 +504,7 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) { .pDepthStencilState = &depth_info, .pColorBlendState = &color_blending, .pDynamicState = &dynamic_info, - .layout = layout, + .layout = desc_manager.GetPipelineLayout(), .renderPass = renderpass_cache.GetRenderpass(info.color_attachment, info.depth_attachment, false)}; @@ -639,46 +519,6 @@ vk::Pipeline PipelineCache::BuildPipeline(const PipelineInfo& info) { return VK_NULL_HANDLE; } -static_assert(sizeof(vk::DescriptorBufferInfo) == sizeof(VkDescriptorBufferInfo)); - -void PipelineCache::BindDescriptorSets() { - vk::Device device = instance.GetDevice(); - std::array layouts; - - for (u32 i = 0; i < RASTERIZER_SET_COUNT; i++) { - if (descriptor_dirty[i] || !descriptor_sets[i]) { - auto& batch = descriptor_batch[i]; - if (batch.empty()) { - layouts.fill(descriptor_set_layouts[i]); - const vk::DescriptorSetAllocateInfo alloc_info = { - .descriptorPool = scheduler.GetDescriptorPool(), - .descriptorSetCount = DESCRIPTOR_BATCH_SIZE, - .pSetLayouts = layouts.data()}; - - try { - batch = device.allocateDescriptorSets(alloc_info); - } catch (vk::OutOfPoolMemoryError& err) { - LOG_CRITICAL(Render_Vulkan, "Run out of pool memory for layout {}: {}", i, - err.what()); - UNREACHABLE(); - } - } - - vk::DescriptorSet set = batch.back(); - device.updateDescriptorSetWithTemplate(set, update_templates[i], update_data[i][0]); - - descriptor_sets[i] = set; - descriptor_dirty[i] = false; - batch.pop_back(); - } - } - - // Bind the descriptor sets - vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer(); - command_buffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, layout, 0, - RASTERIZER_SET_COUNT, descriptor_sets.data(), 0, nullptr); -} - bool PipelineCache::IsCacheValid(const u8* data, u64 size) const { if (size < sizeof(vk::PipelineCacheHeaderVersionOne)) { LOG_ERROR(Render_Vulkan, "Pipeline cache failed validation: Invalid header"); diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index 64cb68480..cd92d640a 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h @@ -9,7 +9,7 @@ #include "common/hash.h" #include "video_core/rasterizer_cache/pixel_format.h" #include "video_core/regs.h" -#include "video_core/renderer_vulkan/vk_common.h" +#include "video_core/renderer_vulkan/vk_descriptor_manager.h" #include "video_core/renderer_vulkan/vk_shader.h" #include "video_core/renderer_vulkan/vk_shader_gen.h" #include "video_core/shader/shader_cache.h" @@ -19,8 +19,6 @@ namespace Vulkan { constexpr u32 MAX_SHADER_STAGES = 3; constexpr u32 MAX_VERTEX_ATTRIBUTES = 16; constexpr u32 MAX_VERTEX_BINDINGS = 16; -constexpr u32 MAX_DESCRIPTORS = 8; -constexpr u32 MAX_DESCRIPTOR_SETS = 6; /** * The pipeline state is tightly packed with bitfields to reduce @@ -109,18 +107,6 @@ struct PipelineInfo { } }; -union DescriptorData { - vk::DescriptorImageInfo image_info; - vk::DescriptorBufferInfo buffer_info; - vk::BufferView buffer_view; - - bool operator!=(const DescriptorData& other) const { - return std::memcmp(this, &other, sizeof(DescriptorData)) != 0; - } -}; - -using DescriptorSetData = std::array; - /** * Vulkan specialized PICA shader caches */ @@ -197,9 +183,6 @@ public: void MarkDirty(); private: - /// Binds a resource to the provided binding - void SetBinding(u32 set, u32 binding, DescriptorData data); - /// Applies dynamic pipeline state to the current command buffer void ApplyDynamic(const PipelineInfo& info); @@ -209,9 +192,6 @@ private: /// Builds a rasterizer pipeline using the PipelineInfo struct vk::Pipeline BuildPipeline(const PipelineInfo& info); - /// Builds descriptor sets that reference the currently bound resources - void BindDescriptorSets(); - /// Returns true when the disk data can be used by the current driver bool IsCacheValid(const u8* data, u64 size) const; @@ -225,6 +205,7 @@ private: const Instance& instance; TaskScheduler& scheduler; RenderpassCache& renderpass_cache; + DescriptorManager desc_manager; // Cached pipelines vk::PipelineCache pipeline_cache; @@ -233,17 +214,6 @@ private: PipelineInfo current_info{}; vk::Viewport current_viewport{}; vk::Rect2D current_scissor{}; - - // Cached layouts for the rasterizer pipelines - vk::PipelineLayout layout; - std::array descriptor_set_layouts; - std::array update_templates; - - // Current data for the descriptor sets - std::array update_data{}; - std::array descriptor_dirty{}; - std::array descriptor_sets; - std::array, MAX_DESCRIPTOR_SETS> descriptor_batch; bool state_dirty = true; // Bound shader modules