mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-04 00:49:02 -06:00 
			
		
		
		
	vulkan: Rework descriptor allocation algorithm
Create multiple descriptor pools on demand. There are some degrees of freedom what is considered a compatible pool to avoid wasting large pools on small descriptors.
This commit is contained in:
		@@ -49,6 +49,16 @@ constexpr VkDescriptorSetLayoutCreateInfo ONE_TEXTURE_DESCRIPTOR_SET_LAYOUT_CREA
 | 
			
		||||
    .bindingCount = 1,
 | 
			
		||||
    .pBindings = &TEXTURE_DESCRIPTOR_SET_LAYOUT_BINDING<0>,
 | 
			
		||||
};
 | 
			
		||||
template <u32 num_textures>
 | 
			
		||||
inline constexpr DescriptorBankInfo TEXTURE_DESCRIPTOR_BANK_INFO{
 | 
			
		||||
    .uniform_buffers = 0,
 | 
			
		||||
    .storage_buffers = 0,
 | 
			
		||||
    .texture_buffers = 0,
 | 
			
		||||
    .image_buffers = 0,
 | 
			
		||||
    .textures = num_textures,
 | 
			
		||||
    .images = 0,
 | 
			
		||||
    .score = 2,
 | 
			
		||||
};
 | 
			
		||||
constexpr VkDescriptorSetLayoutCreateInfo TWO_TEXTURES_DESCRIPTOR_SET_LAYOUT_CREATE_INFO{
 | 
			
		||||
    .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
 | 
			
		||||
    .pNext = nullptr,
 | 
			
		||||
@@ -326,14 +336,16 @@ void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Regi
 | 
			
		||||
} // Anonymous namespace
 | 
			
		||||
 | 
			
		||||
BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_,
 | 
			
		||||
                                 StateTracker& state_tracker_, VKDescriptorPool& descriptor_pool)
 | 
			
		||||
                                 StateTracker& state_tracker_, DescriptorPool& descriptor_pool)
 | 
			
		||||
    : device{device_}, scheduler{scheduler_}, state_tracker{state_tracker_},
 | 
			
		||||
      one_texture_set_layout(device.GetLogical().CreateDescriptorSetLayout(
 | 
			
		||||
          ONE_TEXTURE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO)),
 | 
			
		||||
      two_textures_set_layout(device.GetLogical().CreateDescriptorSetLayout(
 | 
			
		||||
          TWO_TEXTURES_DESCRIPTOR_SET_LAYOUT_CREATE_INFO)),
 | 
			
		||||
      one_texture_descriptor_allocator(descriptor_pool, *one_texture_set_layout),
 | 
			
		||||
      two_textures_descriptor_allocator(descriptor_pool, *two_textures_set_layout),
 | 
			
		||||
      one_texture_descriptor_allocator{
 | 
			
		||||
          descriptor_pool.Allocator(*one_texture_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<1>)},
 | 
			
		||||
      two_textures_descriptor_allocator{
 | 
			
		||||
          descriptor_pool.Allocator(*two_textures_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<2>)},
 | 
			
		||||
      one_texture_pipeline_layout(device.GetLogical().CreatePipelineLayout(
 | 
			
		||||
          PipelineLayoutCreateInfo(one_texture_set_layout.address()))),
 | 
			
		||||
      two_textures_pipeline_layout(device.GetLogical().CreatePipelineLayout(
 | 
			
		||||
@@ -415,7 +427,6 @@ void BlitImageHelper::ConvertD32ToR32(const Framebuffer* dst_framebuffer,
 | 
			
		||||
 | 
			
		||||
void BlitImageHelper::ConvertR32ToD32(const Framebuffer* dst_framebuffer,
 | 
			
		||||
                                      const ImageView& src_image_view) {
 | 
			
		||||
 | 
			
		||||
    ConvertColorToDepthPipeline(convert_r32_to_d32_pipeline, dst_framebuffer->RenderPass());
 | 
			
		||||
    Convert(*convert_r32_to_d32_pipeline, dst_framebuffer, src_image_view);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,7 @@ struct BlitImagePipelineKey {
 | 
			
		||||
class BlitImageHelper {
 | 
			
		||||
public:
 | 
			
		||||
    explicit BlitImageHelper(const Device& device, VKScheduler& scheduler,
 | 
			
		||||
                             StateTracker& state_tracker, VKDescriptorPool& descriptor_pool);
 | 
			
		||||
                             StateTracker& state_tracker, DescriptorPool& descriptor_pool);
 | 
			
		||||
    ~BlitImageHelper();
 | 
			
		||||
 | 
			
		||||
    void BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view,
 | 
			
		||||
 
 | 
			
		||||
@@ -116,7 +116,7 @@ VkBufferView Buffer::View(u32 offset, u32 size, VideoCore::Surface::PixelFormat
 | 
			
		||||
BufferCacheRuntime::BufferCacheRuntime(const Device& device_, MemoryAllocator& memory_allocator_,
 | 
			
		||||
                                       VKScheduler& scheduler_, StagingBufferPool& staging_pool_,
 | 
			
		||||
                                       VKUpdateDescriptorQueue& update_descriptor_queue_,
 | 
			
		||||
                                       VKDescriptorPool& descriptor_pool)
 | 
			
		||||
                                       DescriptorPool& descriptor_pool)
 | 
			
		||||
    : device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_},
 | 
			
		||||
      staging_pool{staging_pool_}, update_descriptor_queue{update_descriptor_queue_},
 | 
			
		||||
      uint8_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue),
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@
 | 
			
		||||
namespace Vulkan {
 | 
			
		||||
 | 
			
		||||
class Device;
 | 
			
		||||
class VKDescriptorPool;
 | 
			
		||||
class DescriptorPool;
 | 
			
		||||
class VKScheduler;
 | 
			
		||||
 | 
			
		||||
class BufferCacheRuntime;
 | 
			
		||||
@@ -61,7 +61,7 @@ public:
 | 
			
		||||
    explicit BufferCacheRuntime(const Device& device_, MemoryAllocator& memory_manager_,
 | 
			
		||||
                                VKScheduler& scheduler_, StagingBufferPool& staging_pool_,
 | 
			
		||||
                                VKUpdateDescriptorQueue& update_descriptor_queue_,
 | 
			
		||||
                                VKDescriptorPool& descriptor_pool);
 | 
			
		||||
                                DescriptorPool& descriptor_pool);
 | 
			
		||||
 | 
			
		||||
    void Finish();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -41,80 +41,92 @@ constexpr u32 ASTC_BINDING_SWIZZLE_BUFFER = 2;
 | 
			
		||||
constexpr u32 ASTC_BINDING_OUTPUT_IMAGE = 3;
 | 
			
		||||
constexpr size_t ASTC_NUM_BINDINGS = 4;
 | 
			
		||||
 | 
			
		||||
VkPushConstantRange BuildComputePushConstantRange(std::size_t size) {
 | 
			
		||||
    return {
 | 
			
		||||
        .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
 | 
			
		||||
        .offset = 0,
 | 
			
		||||
        .size = static_cast<u32>(size),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
template <size_t size>
 | 
			
		||||
inline constexpr VkPushConstantRange COMPUTE_PUSH_CONSTANT_RANGE{
 | 
			
		||||
    .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
 | 
			
		||||
    .offset = 0,
 | 
			
		||||
    .size = static_cast<u32>(size),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::array<VkDescriptorSetLayoutBinding, 2> BuildInputOutputDescriptorSetBindings() {
 | 
			
		||||
    return {{
 | 
			
		||||
        {
 | 
			
		||||
            .binding = 0,
 | 
			
		||||
            .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
 | 
			
		||||
            .descriptorCount = 1,
 | 
			
		||||
            .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
 | 
			
		||||
            .pImmutableSamplers = nullptr,
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            .binding = 1,
 | 
			
		||||
            .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
 | 
			
		||||
            .descriptorCount = 1,
 | 
			
		||||
            .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
 | 
			
		||||
            .pImmutableSamplers = nullptr,
 | 
			
		||||
        },
 | 
			
		||||
    }};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::array<VkDescriptorSetLayoutBinding, ASTC_NUM_BINDINGS> BuildASTCDescriptorSetBindings() {
 | 
			
		||||
    return {{
 | 
			
		||||
        {
 | 
			
		||||
            .binding = ASTC_BINDING_INPUT_BUFFER,
 | 
			
		||||
            .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
 | 
			
		||||
            .descriptorCount = 1,
 | 
			
		||||
            .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
 | 
			
		||||
            .pImmutableSamplers = nullptr,
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            .binding = ASTC_BINDING_ENC_BUFFER,
 | 
			
		||||
            .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
 | 
			
		||||
            .descriptorCount = 1,
 | 
			
		||||
            .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
 | 
			
		||||
            .pImmutableSamplers = nullptr,
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            .binding = ASTC_BINDING_SWIZZLE_BUFFER,
 | 
			
		||||
            .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
 | 
			
		||||
            .descriptorCount = 1,
 | 
			
		||||
            .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
 | 
			
		||||
            .pImmutableSamplers = nullptr,
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            .binding = ASTC_BINDING_OUTPUT_IMAGE,
 | 
			
		||||
            .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
 | 
			
		||||
            .descriptorCount = 1,
 | 
			
		||||
            .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
 | 
			
		||||
            .pImmutableSamplers = nullptr,
 | 
			
		||||
        },
 | 
			
		||||
    }};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VkDescriptorUpdateTemplateEntryKHR BuildInputOutputDescriptorUpdateTemplate() {
 | 
			
		||||
    return {
 | 
			
		||||
        .dstBinding = 0,
 | 
			
		||||
        .dstArrayElement = 0,
 | 
			
		||||
        .descriptorCount = 2,
 | 
			
		||||
constexpr std::array<VkDescriptorSetLayoutBinding, 2> INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS{{
 | 
			
		||||
    {
 | 
			
		||||
        .binding = 0,
 | 
			
		||||
        .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
 | 
			
		||||
        .offset = 0,
 | 
			
		||||
        .stride = sizeof(DescriptorUpdateEntry),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
        .descriptorCount = 1,
 | 
			
		||||
        .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
 | 
			
		||||
        .pImmutableSamplers = nullptr,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .binding = 1,
 | 
			
		||||
        .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
 | 
			
		||||
        .descriptorCount = 1,
 | 
			
		||||
        .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
 | 
			
		||||
        .pImmutableSamplers = nullptr,
 | 
			
		||||
    },
 | 
			
		||||
}};
 | 
			
		||||
 | 
			
		||||
std::array<VkDescriptorUpdateTemplateEntryKHR, ASTC_NUM_BINDINGS>
 | 
			
		||||
BuildASTCPassDescriptorUpdateTemplateEntry() {
 | 
			
		||||
    return {{
 | 
			
		||||
constexpr DescriptorBankInfo INPUT_OUTPUT_BANK_INFO{
 | 
			
		||||
    .uniform_buffers = 0,
 | 
			
		||||
    .storage_buffers = 2,
 | 
			
		||||
    .texture_buffers = 0,
 | 
			
		||||
    .image_buffers = 0,
 | 
			
		||||
    .textures = 0,
 | 
			
		||||
    .images = 0,
 | 
			
		||||
    .score = 2,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
constexpr std::array<VkDescriptorSetLayoutBinding, 4> ASTC_DESCRIPTOR_SET_BINDINGS{{
 | 
			
		||||
    {
 | 
			
		||||
        .binding = ASTC_BINDING_INPUT_BUFFER,
 | 
			
		||||
        .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
 | 
			
		||||
        .descriptorCount = 1,
 | 
			
		||||
        .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
 | 
			
		||||
        .pImmutableSamplers = nullptr,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .binding = ASTC_BINDING_ENC_BUFFER,
 | 
			
		||||
        .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
 | 
			
		||||
        .descriptorCount = 1,
 | 
			
		||||
        .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
 | 
			
		||||
        .pImmutableSamplers = nullptr,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .binding = ASTC_BINDING_SWIZZLE_BUFFER,
 | 
			
		||||
        .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
 | 
			
		||||
        .descriptorCount = 1,
 | 
			
		||||
        .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
 | 
			
		||||
        .pImmutableSamplers = nullptr,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        .binding = ASTC_BINDING_OUTPUT_IMAGE,
 | 
			
		||||
        .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
 | 
			
		||||
        .descriptorCount = 1,
 | 
			
		||||
        .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
 | 
			
		||||
        .pImmutableSamplers = nullptr,
 | 
			
		||||
    },
 | 
			
		||||
}};
 | 
			
		||||
 | 
			
		||||
constexpr DescriptorBankInfo ASTC_BANK_INFO{
 | 
			
		||||
    .uniform_buffers = 0,
 | 
			
		||||
    .storage_buffers = 3,
 | 
			
		||||
    .texture_buffers = 0,
 | 
			
		||||
    .image_buffers = 0,
 | 
			
		||||
    .textures = 0,
 | 
			
		||||
    .images = 1,
 | 
			
		||||
    .score = 4,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
constexpr VkDescriptorUpdateTemplateEntryKHR INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE{
 | 
			
		||||
    .dstBinding = 0,
 | 
			
		||||
    .dstArrayElement = 0,
 | 
			
		||||
    .descriptorCount = 2,
 | 
			
		||||
    .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
 | 
			
		||||
    .offset = 0,
 | 
			
		||||
    .stride = sizeof(DescriptorUpdateEntry),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
constexpr std::array<VkDescriptorUpdateTemplateEntryKHR, ASTC_NUM_BINDINGS>
 | 
			
		||||
    ASTC_PASS_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY{{
 | 
			
		||||
        {
 | 
			
		||||
            .dstBinding = ASTC_BINDING_INPUT_BUFFER,
 | 
			
		||||
            .dstArrayElement = 0,
 | 
			
		||||
@@ -148,7 +160,6 @@ BuildASTCPassDescriptorUpdateTemplateEntry() {
 | 
			
		||||
            .stride = sizeof(DescriptorUpdateEntry),
 | 
			
		||||
        },
 | 
			
		||||
    }};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct AstcPushConstants {
 | 
			
		||||
    std::array<u32, 2> blocks_dims;
 | 
			
		||||
@@ -159,14 +170,13 @@ struct AstcPushConstants {
 | 
			
		||||
    u32 block_height;
 | 
			
		||||
    u32 block_height_mask;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // Anonymous namespace
 | 
			
		||||
 | 
			
		||||
VKComputePass::VKComputePass(const Device& device, VKDescriptorPool& descriptor_pool,
 | 
			
		||||
                             vk::Span<VkDescriptorSetLayoutBinding> bindings,
 | 
			
		||||
                             vk::Span<VkDescriptorUpdateTemplateEntryKHR> templates,
 | 
			
		||||
                             vk::Span<VkPushConstantRange> push_constants,
 | 
			
		||||
                             std::span<const u32> code) {
 | 
			
		||||
ComputePass::ComputePass(const Device& device, DescriptorPool& descriptor_pool,
 | 
			
		||||
                         vk::Span<VkDescriptorSetLayoutBinding> bindings,
 | 
			
		||||
                         vk::Span<VkDescriptorUpdateTemplateEntryKHR> templates,
 | 
			
		||||
                         const DescriptorBankInfo& bank_info,
 | 
			
		||||
                         vk::Span<VkPushConstantRange> push_constants, std::span<const u32> code) {
 | 
			
		||||
    descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout({
 | 
			
		||||
        .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
 | 
			
		||||
        .pNext = nullptr,
 | 
			
		||||
@@ -196,8 +206,7 @@ VKComputePass::VKComputePass(const Device& device, VKDescriptorPool& descriptor_
 | 
			
		||||
            .pipelineLayout = *layout,
 | 
			
		||||
            .set = 0,
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        descriptor_allocator.emplace(descriptor_pool, *descriptor_set_layout);
 | 
			
		||||
        descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, bank_info);
 | 
			
		||||
    }
 | 
			
		||||
    module = device.GetLogical().CreateShaderModule({
 | 
			
		||||
        .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
 | 
			
		||||
@@ -226,23 +235,23 @@ VKComputePass::VKComputePass(const Device& device, VKDescriptorPool& descriptor_
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VKComputePass::~VKComputePass() = default;
 | 
			
		||||
ComputePass::~ComputePass() = default;
 | 
			
		||||
 | 
			
		||||
VkDescriptorSet VKComputePass::CommitDescriptorSet(
 | 
			
		||||
    VKUpdateDescriptorQueue& update_descriptor_queue) {
 | 
			
		||||
VkDescriptorSet ComputePass::CommitDescriptorSet(VKUpdateDescriptorQueue& update_descriptor_queue) {
 | 
			
		||||
    if (!descriptor_template) {
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
    const VkDescriptorSet set = descriptor_allocator->Commit();
 | 
			
		||||
    const VkDescriptorSet set = descriptor_allocator.Commit();
 | 
			
		||||
    update_descriptor_queue.Send(descriptor_template.address(), set);
 | 
			
		||||
    return set;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Uint8Pass::Uint8Pass(const Device& device, VKScheduler& scheduler_,
 | 
			
		||||
                     VKDescriptorPool& descriptor_pool, StagingBufferPool& staging_buffer_pool_,
 | 
			
		||||
Uint8Pass::Uint8Pass(const Device& device, VKScheduler& scheduler_, DescriptorPool& descriptor_pool,
 | 
			
		||||
                     StagingBufferPool& staging_buffer_pool_,
 | 
			
		||||
                     VKUpdateDescriptorQueue& update_descriptor_queue_)
 | 
			
		||||
    : VKComputePass(device, descriptor_pool, BuildInputOutputDescriptorSetBindings(),
 | 
			
		||||
                    BuildInputOutputDescriptorUpdateTemplate(), {}, VULKAN_UINT8_COMP_SPV),
 | 
			
		||||
    : ComputePass(device, descriptor_pool, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS,
 | 
			
		||||
                  INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO, {},
 | 
			
		||||
                  VULKAN_UINT8_COMP_SPV),
 | 
			
		||||
      scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_},
 | 
			
		||||
      update_descriptor_queue{update_descriptor_queue_} {}
 | 
			
		||||
 | 
			
		||||
@@ -277,12 +286,12 @@ std::pair<VkBuffer, VkDeviceSize> Uint8Pass::Assemble(u32 num_vertices, VkBuffer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QuadIndexedPass::QuadIndexedPass(const Device& device_, VKScheduler& scheduler_,
 | 
			
		||||
                                 VKDescriptorPool& descriptor_pool_,
 | 
			
		||||
                                 DescriptorPool& descriptor_pool_,
 | 
			
		||||
                                 StagingBufferPool& staging_buffer_pool_,
 | 
			
		||||
                                 VKUpdateDescriptorQueue& update_descriptor_queue_)
 | 
			
		||||
    : VKComputePass(device_, descriptor_pool_, BuildInputOutputDescriptorSetBindings(),
 | 
			
		||||
                    BuildInputOutputDescriptorUpdateTemplate(),
 | 
			
		||||
                    BuildComputePushConstantRange(sizeof(u32) * 2), VULKAN_QUAD_INDEXED_COMP_SPV),
 | 
			
		||||
    : ComputePass(device_, descriptor_pool_, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS,
 | 
			
		||||
                  INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO,
 | 
			
		||||
                  COMPUTE_PUSH_CONSTANT_RANGE<sizeof(u32) * 2>, VULKAN_QUAD_INDEXED_COMP_SPV),
 | 
			
		||||
      scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_},
 | 
			
		||||
      update_descriptor_queue{update_descriptor_queue_} {}
 | 
			
		||||
 | 
			
		||||
@@ -337,14 +346,13 @@ std::pair<VkBuffer, VkDeviceSize> QuadIndexedPass::Assemble(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ASTCDecoderPass::ASTCDecoderPass(const Device& device_, VKScheduler& scheduler_,
 | 
			
		||||
                                 VKDescriptorPool& descriptor_pool_,
 | 
			
		||||
                                 DescriptorPool& descriptor_pool_,
 | 
			
		||||
                                 StagingBufferPool& staging_buffer_pool_,
 | 
			
		||||
                                 VKUpdateDescriptorQueue& update_descriptor_queue_,
 | 
			
		||||
                                 MemoryAllocator& memory_allocator_)
 | 
			
		||||
    : VKComputePass(device_, descriptor_pool_, BuildASTCDescriptorSetBindings(),
 | 
			
		||||
                    BuildASTCPassDescriptorUpdateTemplateEntry(),
 | 
			
		||||
                    BuildComputePushConstantRange(sizeof(AstcPushConstants)),
 | 
			
		||||
                    ASTC_DECODER_COMP_SPV),
 | 
			
		||||
    : ComputePass(device_, descriptor_pool_, ASTC_DESCRIPTOR_SET_BINDINGS,
 | 
			
		||||
                  ASTC_PASS_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY, ASTC_BANK_INFO,
 | 
			
		||||
                  COMPUTE_PUSH_CONSTANT_RANGE<sizeof(AstcPushConstants)>, ASTC_DECODER_COMP_SPV),
 | 
			
		||||
      device{device_}, scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_},
 | 
			
		||||
      update_descriptor_queue{update_descriptor_queue_}, memory_allocator{memory_allocator_} {}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,6 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <span>
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
@@ -27,13 +26,14 @@ class VKUpdateDescriptorQueue;
 | 
			
		||||
class Image;
 | 
			
		||||
struct StagingBufferRef;
 | 
			
		||||
 | 
			
		||||
class VKComputePass {
 | 
			
		||||
class ComputePass {
 | 
			
		||||
public:
 | 
			
		||||
    explicit VKComputePass(const Device& device, VKDescriptorPool& descriptor_pool,
 | 
			
		||||
                           vk::Span<VkDescriptorSetLayoutBinding> bindings,
 | 
			
		||||
                           vk::Span<VkDescriptorUpdateTemplateEntryKHR> templates,
 | 
			
		||||
                           vk::Span<VkPushConstantRange> push_constants, std::span<const u32> code);
 | 
			
		||||
    ~VKComputePass();
 | 
			
		||||
    explicit ComputePass(const Device& device, DescriptorPool& descriptor_pool,
 | 
			
		||||
                         vk::Span<VkDescriptorSetLayoutBinding> bindings,
 | 
			
		||||
                         vk::Span<VkDescriptorUpdateTemplateEntryKHR> templates,
 | 
			
		||||
                         const DescriptorBankInfo& bank_info,
 | 
			
		||||
                         vk::Span<VkPushConstantRange> push_constants, std::span<const u32> code);
 | 
			
		||||
    ~ComputePass();
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    VkDescriptorSet CommitDescriptorSet(VKUpdateDescriptorQueue& update_descriptor_queue);
 | 
			
		||||
@@ -44,14 +44,14 @@ protected:
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    vk::DescriptorSetLayout descriptor_set_layout;
 | 
			
		||||
    std::optional<DescriptorAllocator> descriptor_allocator;
 | 
			
		||||
    DescriptorAllocator descriptor_allocator;
 | 
			
		||||
    vk::ShaderModule module;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class Uint8Pass final : public VKComputePass {
 | 
			
		||||
class Uint8Pass final : public ComputePass {
 | 
			
		||||
public:
 | 
			
		||||
    explicit Uint8Pass(const Device& device_, VKScheduler& scheduler_,
 | 
			
		||||
                       VKDescriptorPool& descriptor_pool_, StagingBufferPool& staging_buffer_pool_,
 | 
			
		||||
                       DescriptorPool& descriptor_pool_, StagingBufferPool& staging_buffer_pool_,
 | 
			
		||||
                       VKUpdateDescriptorQueue& update_descriptor_queue_);
 | 
			
		||||
    ~Uint8Pass();
 | 
			
		||||
 | 
			
		||||
@@ -66,10 +66,10 @@ private:
 | 
			
		||||
    VKUpdateDescriptorQueue& update_descriptor_queue;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class QuadIndexedPass final : public VKComputePass {
 | 
			
		||||
class QuadIndexedPass final : public ComputePass {
 | 
			
		||||
public:
 | 
			
		||||
    explicit QuadIndexedPass(const Device& device_, VKScheduler& scheduler_,
 | 
			
		||||
                             VKDescriptorPool& descriptor_pool_,
 | 
			
		||||
                             DescriptorPool& descriptor_pool_,
 | 
			
		||||
                             StagingBufferPool& staging_buffer_pool_,
 | 
			
		||||
                             VKUpdateDescriptorQueue& update_descriptor_queue_);
 | 
			
		||||
    ~QuadIndexedPass();
 | 
			
		||||
@@ -84,10 +84,10 @@ private:
 | 
			
		||||
    VKUpdateDescriptorQueue& update_descriptor_queue;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class ASTCDecoderPass final : public VKComputePass {
 | 
			
		||||
class ASTCDecoderPass final : public ComputePass {
 | 
			
		||||
public:
 | 
			
		||||
    explicit ASTCDecoderPass(const Device& device_, VKScheduler& scheduler_,
 | 
			
		||||
                             VKDescriptorPool& descriptor_pool_,
 | 
			
		||||
                             DescriptorPool& descriptor_pool_,
 | 
			
		||||
                             StagingBufferPool& staging_buffer_pool_,
 | 
			
		||||
                             VKUpdateDescriptorQueue& update_descriptor_queue_,
 | 
			
		||||
                             MemoryAllocator& memory_allocator_);
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@
 | 
			
		||||
 | 
			
		||||
namespace Vulkan {
 | 
			
		||||
 | 
			
		||||
ComputePipeline::ComputePipeline(const Device& device, VKDescriptorPool& descriptor_pool,
 | 
			
		||||
ComputePipeline::ComputePipeline(const Device& device, DescriptorPool& descriptor_pool,
 | 
			
		||||
                                 VKUpdateDescriptorQueue& update_descriptor_queue_,
 | 
			
		||||
                                 Common::ThreadWorker* thread_worker, const Shader::Info& info_,
 | 
			
		||||
                                 vk::ShaderModule spv_module_)
 | 
			
		||||
@@ -30,7 +30,7 @@ ComputePipeline::ComputePipeline(const Device& device, VKDescriptorPool& descrip
 | 
			
		||||
    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 = descriptor_pool.Allocator(*descriptor_set_layout, info);
 | 
			
		||||
 | 
			
		||||
    auto func{[this, &device] {
 | 
			
		||||
        const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ class VKScheduler;
 | 
			
		||||
 | 
			
		||||
class ComputePipeline {
 | 
			
		||||
public:
 | 
			
		||||
    explicit ComputePipeline(const Device& device, VKDescriptorPool& descriptor_pool,
 | 
			
		||||
    explicit ComputePipeline(const Device& device, DescriptorPool& descriptor_pool,
 | 
			
		||||
                             VKUpdateDescriptorQueue& update_descriptor_queue,
 | 
			
		||||
                             Common::ThreadWorker* thread_worker, const Shader::Info& info,
 | 
			
		||||
                             vk::ShaderModule spv_module);
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,8 @@
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include <mutex>
 | 
			
		||||
#include <span>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
@@ -13,77 +15,149 @@
 | 
			
		||||
 | 
			
		||||
namespace Vulkan {
 | 
			
		||||
 | 
			
		||||
// Prefer small grow rates to avoid saturating the descriptor pool with barely used pipelines.
 | 
			
		||||
constexpr std::size_t SETS_GROW_RATE = 0x20;
 | 
			
		||||
// Prefer small grow rates to avoid saturating the descriptor pool with barely used pipelines
 | 
			
		||||
constexpr size_t SETS_GROW_RATE = 16;
 | 
			
		||||
constexpr s32 SCORE_THRESHOLD = 3;
 | 
			
		||||
constexpr u32 SETS_PER_POOL = 64;
 | 
			
		||||
 | 
			
		||||
DescriptorAllocator::DescriptorAllocator(VKDescriptorPool& descriptor_pool_,
 | 
			
		||||
                                         VkDescriptorSetLayout layout_)
 | 
			
		||||
    : ResourcePool(descriptor_pool_.master_semaphore, SETS_GROW_RATE),
 | 
			
		||||
      descriptor_pool{&descriptor_pool_}, layout{layout_} {}
 | 
			
		||||
struct DescriptorBank {
 | 
			
		||||
    DescriptorBankInfo info;
 | 
			
		||||
    std::vector<vk::DescriptorPool> pools;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
VkDescriptorSet DescriptorAllocator::Commit() {
 | 
			
		||||
    const std::size_t index = CommitResource();
 | 
			
		||||
    return descriptors_allocations[index / SETS_GROW_RATE][index % SETS_GROW_RATE];
 | 
			
		||||
bool DescriptorBankInfo::IsSuperset(const DescriptorBankInfo& subset) const noexcept {
 | 
			
		||||
    return uniform_buffers >= subset.uniform_buffers && storage_buffers >= subset.storage_buffers &&
 | 
			
		||||
           texture_buffers >= subset.texture_buffers && image_buffers >= subset.image_buffers &&
 | 
			
		||||
           textures >= subset.textures && images >= subset.image_buffers;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DescriptorAllocator::Allocate(std::size_t begin, std::size_t end) {
 | 
			
		||||
    descriptors_allocations.push_back(descriptor_pool->AllocateDescriptors(layout, end - begin));
 | 
			
		||||
template <typename Descriptors>
 | 
			
		||||
static u32 Accumulate(const Descriptors& descriptors) {
 | 
			
		||||
    u32 count = 0;
 | 
			
		||||
    for (const auto& descriptor : descriptors) {
 | 
			
		||||
        count += descriptor.count;
 | 
			
		||||
    }
 | 
			
		||||
    return count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VKDescriptorPool::VKDescriptorPool(const Device& device_, VKScheduler& scheduler)
 | 
			
		||||
    : device{device_}, master_semaphore{scheduler.GetMasterSemaphore()}, active_pool{
 | 
			
		||||
                                                                             AllocateNewPool()} {}
 | 
			
		||||
static DescriptorBankInfo MakeBankInfo(std::span<const Shader::Info> infos) {
 | 
			
		||||
    DescriptorBankInfo bank;
 | 
			
		||||
    for (const Shader::Info& info : infos) {
 | 
			
		||||
        bank.uniform_buffers += Accumulate(info.constant_buffer_descriptors);
 | 
			
		||||
        bank.storage_buffers += Accumulate(info.storage_buffers_descriptors);
 | 
			
		||||
        bank.texture_buffers += Accumulate(info.texture_buffer_descriptors);
 | 
			
		||||
        bank.image_buffers += Accumulate(info.image_buffer_descriptors);
 | 
			
		||||
        bank.textures += Accumulate(info.texture_descriptors);
 | 
			
		||||
        bank.images += Accumulate(info.image_descriptors);
 | 
			
		||||
    }
 | 
			
		||||
    bank.score = bank.uniform_buffers + bank.storage_buffers + bank.texture_buffers +
 | 
			
		||||
                 bank.image_buffers + bank.textures + bank.images;
 | 
			
		||||
    return bank;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VKDescriptorPool::~VKDescriptorPool() = default;
 | 
			
		||||
 | 
			
		||||
vk::DescriptorPool* VKDescriptorPool::AllocateNewPool() {
 | 
			
		||||
    static constexpr u32 num_sets = 0x20000;
 | 
			
		||||
    static constexpr VkDescriptorPoolSize pool_sizes[] = {
 | 
			
		||||
        {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, num_sets * 90},
 | 
			
		||||
        {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, num_sets * 60},
 | 
			
		||||
        {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, num_sets * 64},
 | 
			
		||||
        {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, num_sets * 64},
 | 
			
		||||
        {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, num_sets * 64},
 | 
			
		||||
        {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, num_sets * 40},
 | 
			
		||||
static void AllocatePool(const Device& device, DescriptorBank& bank) {
 | 
			
		||||
    std::array<VkDescriptorPoolSize, 6> pool_sizes;
 | 
			
		||||
    size_t pool_cursor{};
 | 
			
		||||
    const auto add = [&](VkDescriptorType type, u32 count) {
 | 
			
		||||
        if (count > 0) {
 | 
			
		||||
            pool_sizes[pool_cursor++] = {
 | 
			
		||||
                .type = type,
 | 
			
		||||
                .descriptorCount = count * SETS_PER_POOL,
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const VkDescriptorPoolCreateInfo ci{
 | 
			
		||||
    const auto& info{bank.info};
 | 
			
		||||
    add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, info.uniform_buffers);
 | 
			
		||||
    add(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, info.storage_buffers);
 | 
			
		||||
    add(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, info.texture_buffers);
 | 
			
		||||
    add(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, info.image_buffers);
 | 
			
		||||
    add(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, info.textures);
 | 
			
		||||
    add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, info.images);
 | 
			
		||||
    bank.pools.push_back(device.GetLogical().CreateDescriptorPool({
 | 
			
		||||
        .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
 | 
			
		||||
        .pNext = nullptr,
 | 
			
		||||
        .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
 | 
			
		||||
        .maxSets = num_sets,
 | 
			
		||||
        .poolSizeCount = static_cast<u32>(std::size(pool_sizes)),
 | 
			
		||||
        .maxSets = SETS_PER_POOL,
 | 
			
		||||
        .poolSizeCount = static_cast<u32>(pool_cursor),
 | 
			
		||||
        .pPoolSizes = std::data(pool_sizes),
 | 
			
		||||
    };
 | 
			
		||||
    return &pools.emplace_back(device.GetLogical().CreateDescriptorPool(ci));
 | 
			
		||||
    }));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vk::DescriptorSets VKDescriptorPool::AllocateDescriptors(VkDescriptorSetLayout layout,
 | 
			
		||||
                                                         std::size_t count) {
 | 
			
		||||
    const std::vector layout_copies(count, layout);
 | 
			
		||||
    VkDescriptorSetAllocateInfo ai{
 | 
			
		||||
DescriptorAllocator::DescriptorAllocator(const Device& device_, MasterSemaphore& master_semaphore_,
 | 
			
		||||
                                         DescriptorBank& bank_, VkDescriptorSetLayout layout_)
 | 
			
		||||
    : ResourcePool(master_semaphore_, SETS_GROW_RATE), device{&device_}, bank{&bank_},
 | 
			
		||||
      layout{layout_} {}
 | 
			
		||||
 | 
			
		||||
VkDescriptorSet DescriptorAllocator::Commit() {
 | 
			
		||||
    const size_t index = CommitResource();
 | 
			
		||||
    return sets[index / SETS_GROW_RATE][index % SETS_GROW_RATE];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DescriptorAllocator::Allocate(size_t begin, size_t end) {
 | 
			
		||||
    sets.push_back(AllocateDescriptors(end - begin));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vk::DescriptorSets DescriptorAllocator::AllocateDescriptors(size_t count) {
 | 
			
		||||
    const std::vector<VkDescriptorSetLayout> layouts(count, layout);
 | 
			
		||||
    VkDescriptorSetAllocateInfo allocate_info{
 | 
			
		||||
        .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
 | 
			
		||||
        .pNext = nullptr,
 | 
			
		||||
        .descriptorPool = **active_pool,
 | 
			
		||||
        .descriptorPool = *bank->pools.back(),
 | 
			
		||||
        .descriptorSetCount = static_cast<u32>(count),
 | 
			
		||||
        .pSetLayouts = layout_copies.data(),
 | 
			
		||||
        .pSetLayouts = layouts.data(),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    vk::DescriptorSets sets = active_pool->Allocate(ai);
 | 
			
		||||
    if (!sets.IsOutOfPoolMemory()) {
 | 
			
		||||
        return sets;
 | 
			
		||||
    vk::DescriptorSets new_sets = bank->pools.back().Allocate(allocate_info);
 | 
			
		||||
    if (!new_sets.IsOutOfPoolMemory()) {
 | 
			
		||||
        return new_sets;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Our current pool is out of memory. Allocate a new one and retry
 | 
			
		||||
    active_pool = AllocateNewPool();
 | 
			
		||||
    ai.descriptorPool = **active_pool;
 | 
			
		||||
    sets = active_pool->Allocate(ai);
 | 
			
		||||
    if (!sets.IsOutOfPoolMemory()) {
 | 
			
		||||
        return sets;
 | 
			
		||||
    AllocatePool(*device, *bank);
 | 
			
		||||
    allocate_info.descriptorPool = *bank->pools.back();
 | 
			
		||||
    new_sets = bank->pools.back().Allocate(allocate_info);
 | 
			
		||||
    if (!new_sets.IsOutOfPoolMemory()) {
 | 
			
		||||
        return new_sets;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // After allocating a new pool, we are out of memory again. We can't handle this from here.
 | 
			
		||||
    throw vk::Exception(VK_ERROR_OUT_OF_POOL_MEMORY);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DescriptorPool::DescriptorPool(const Device& device_, VKScheduler& scheduler)
 | 
			
		||||
    : device{device_}, master_semaphore{scheduler.GetMasterSemaphore()} {}
 | 
			
		||||
 | 
			
		||||
DescriptorPool::~DescriptorPool() = default;
 | 
			
		||||
 | 
			
		||||
DescriptorAllocator DescriptorPool::Allocator(VkDescriptorSetLayout layout,
 | 
			
		||||
                                              std::span<const Shader::Info> infos) {
 | 
			
		||||
    return Allocator(layout, MakeBankInfo(infos));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DescriptorAllocator DescriptorPool::Allocator(VkDescriptorSetLayout layout,
 | 
			
		||||
                                              const Shader::Info& info) {
 | 
			
		||||
    return Allocator(layout, MakeBankInfo(std::array{info}));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DescriptorAllocator DescriptorPool::Allocator(VkDescriptorSetLayout layout,
 | 
			
		||||
                                              const DescriptorBankInfo& info) {
 | 
			
		||||
    return DescriptorAllocator(device, master_semaphore, Bank(info), layout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DescriptorBank& DescriptorPool::Bank(const DescriptorBankInfo& reqs) {
 | 
			
		||||
    std::shared_lock read_lock{banks_mutex};
 | 
			
		||||
    const auto it = std::ranges::find_if(bank_infos, [&reqs](const DescriptorBankInfo& bank) {
 | 
			
		||||
        return std::abs(bank.score - reqs.score) < SCORE_THRESHOLD && bank.IsSuperset(reqs);
 | 
			
		||||
    });
 | 
			
		||||
    if (it != bank_infos.end()) {
 | 
			
		||||
        return *banks[std::distance(bank_infos.begin(), it)].get();
 | 
			
		||||
    }
 | 
			
		||||
    read_lock.unlock();
 | 
			
		||||
 | 
			
		||||
    std::unique_lock write_lock{banks_mutex};
 | 
			
		||||
    bank_infos.push_back(reqs);
 | 
			
		||||
 | 
			
		||||
    auto& bank = *banks.emplace_back(std::make_unique<DescriptorBank>());
 | 
			
		||||
    bank.info = reqs;
 | 
			
		||||
    AllocatePool(device, bank);
 | 
			
		||||
    return bank;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Vulkan
 | 
			
		||||
 
 | 
			
		||||
@@ -4,21 +4,38 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <shared_mutex>
 | 
			
		||||
#include <span>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include "shader_recompiler/shader_info.h"
 | 
			
		||||
#include "video_core/renderer_vulkan/vk_resource_pool.h"
 | 
			
		||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
 | 
			
		||||
 | 
			
		||||
namespace Vulkan {
 | 
			
		||||
 | 
			
		||||
class Device;
 | 
			
		||||
class VKDescriptorPool;
 | 
			
		||||
class VKScheduler;
 | 
			
		||||
 | 
			
		||||
struct DescriptorBank;
 | 
			
		||||
 | 
			
		||||
struct DescriptorBankInfo {
 | 
			
		||||
    [[nodiscard]] bool IsSuperset(const DescriptorBankInfo& subset) const noexcept;
 | 
			
		||||
 | 
			
		||||
    u32 uniform_buffers{}; ///< Number of uniform buffer descriptors
 | 
			
		||||
    u32 storage_buffers{}; ///< Number of storage buffer descriptors
 | 
			
		||||
    u32 texture_buffers{}; ///< Number of texture buffer descriptors
 | 
			
		||||
    u32 image_buffers{};   ///< Number of image buffer descriptors
 | 
			
		||||
    u32 textures{};        ///< Number of texture descriptors
 | 
			
		||||
    u32 images{};          ///< Number of image descriptors
 | 
			
		||||
    s32 score{};           ///< Number of descriptors in total
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class DescriptorAllocator final : public ResourcePool {
 | 
			
		||||
    friend class DescriptorPool;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    explicit DescriptorAllocator() = default;
 | 
			
		||||
    explicit DescriptorAllocator(VKDescriptorPool& descriptor_pool, VkDescriptorSetLayout layout);
 | 
			
		||||
    ~DescriptorAllocator() override = default;
 | 
			
		||||
 | 
			
		||||
    DescriptorAllocator& operator=(DescriptorAllocator&&) noexcept = default;
 | 
			
		||||
@@ -29,36 +46,43 @@ public:
 | 
			
		||||
 | 
			
		||||
    VkDescriptorSet Commit();
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    void Allocate(std::size_t begin, std::size_t end) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    VKDescriptorPool* descriptor_pool{};
 | 
			
		||||
    explicit DescriptorAllocator(const Device& device_, MasterSemaphore& master_semaphore_,
 | 
			
		||||
                                 DescriptorBank& bank_, VkDescriptorSetLayout layout_);
 | 
			
		||||
 | 
			
		||||
    void Allocate(size_t begin, size_t end) override;
 | 
			
		||||
 | 
			
		||||
    vk::DescriptorSets AllocateDescriptors(size_t count);
 | 
			
		||||
 | 
			
		||||
    const Device* device{};
 | 
			
		||||
    DescriptorBank* bank{};
 | 
			
		||||
    VkDescriptorSetLayout layout{};
 | 
			
		||||
 | 
			
		||||
    std::vector<vk::DescriptorSets> descriptors_allocations;
 | 
			
		||||
    std::vector<vk::DescriptorSets> sets;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class VKDescriptorPool final {
 | 
			
		||||
    friend DescriptorAllocator;
 | 
			
		||||
 | 
			
		||||
class DescriptorPool {
 | 
			
		||||
public:
 | 
			
		||||
    explicit VKDescriptorPool(const Device& device, VKScheduler& scheduler);
 | 
			
		||||
    ~VKDescriptorPool();
 | 
			
		||||
    explicit DescriptorPool(const Device& device, VKScheduler& scheduler);
 | 
			
		||||
    ~DescriptorPool();
 | 
			
		||||
 | 
			
		||||
    VKDescriptorPool(const VKDescriptorPool&) = delete;
 | 
			
		||||
    VKDescriptorPool& operator=(const VKDescriptorPool&) = delete;
 | 
			
		||||
    DescriptorPool& operator=(const DescriptorPool&) = delete;
 | 
			
		||||
    DescriptorPool(const DescriptorPool&) = delete;
 | 
			
		||||
 | 
			
		||||
    DescriptorAllocator Allocator(VkDescriptorSetLayout layout,
 | 
			
		||||
                                  std::span<const Shader::Info> infos);
 | 
			
		||||
    DescriptorAllocator Allocator(VkDescriptorSetLayout layout, const Shader::Info& info);
 | 
			
		||||
    DescriptorAllocator Allocator(VkDescriptorSetLayout layout, const DescriptorBankInfo& info);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    vk::DescriptorPool* AllocateNewPool();
 | 
			
		||||
 | 
			
		||||
    vk::DescriptorSets AllocateDescriptors(VkDescriptorSetLayout layout, std::size_t count);
 | 
			
		||||
    DescriptorBank& Bank(const DescriptorBankInfo& reqs);
 | 
			
		||||
 | 
			
		||||
    const Device& device;
 | 
			
		||||
    MasterSemaphore& master_semaphore;
 | 
			
		||||
 | 
			
		||||
    std::vector<vk::DescriptorPool> pools;
 | 
			
		||||
    vk::DescriptorPool* active_pool;
 | 
			
		||||
    std::shared_mutex banks_mutex;
 | 
			
		||||
    std::vector<DescriptorBankInfo> bank_infos;
 | 
			
		||||
    std::vector<std::unique_ptr<DescriptorBank>> banks;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Vulkan
 | 
			
		||||
@@ -205,7 +205,7 @@ ConfigureFuncPtr ConfigureFunc(const std::array<vk::ShaderModule, NUM_STAGES>& m
 | 
			
		||||
GraphicsPipeline::GraphicsPipeline(Tegra::Engines::Maxwell3D& maxwell3d_,
 | 
			
		||||
                                   Tegra::MemoryManager& gpu_memory_, VKScheduler& scheduler_,
 | 
			
		||||
                                   BufferCache& buffer_cache_, TextureCache& texture_cache_,
 | 
			
		||||
                                   const Device& device, VKDescriptorPool& descriptor_pool,
 | 
			
		||||
                                   const Device& device, DescriptorPool& descriptor_pool,
 | 
			
		||||
                                   VKUpdateDescriptorQueue& update_descriptor_queue_,
 | 
			
		||||
                                   Common::ThreadWorker* worker_thread,
 | 
			
		||||
                                   RenderPassCache& render_pass_cache,
 | 
			
		||||
@@ -220,7 +220,7 @@ GraphicsPipeline::GraphicsPipeline(Tegra::Engines::Maxwell3D& maxwell3d_,
 | 
			
		||||
 | 
			
		||||
    DescriptorLayoutBuilder builder{MakeBuilder(device, stage_infos)};
 | 
			
		||||
    descriptor_set_layout = builder.CreateDescriptorSetLayout();
 | 
			
		||||
    descriptor_allocator = DescriptorAllocator(descriptor_pool, *descriptor_set_layout);
 | 
			
		||||
    descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, stage_infos);
 | 
			
		||||
 | 
			
		||||
    auto func{[this, &device, &render_pass_cache, builder] {
 | 
			
		||||
        const VkDescriptorSetLayout set_layout{*descriptor_set_layout};
 | 
			
		||||
 
 | 
			
		||||
@@ -67,7 +67,7 @@ public:
 | 
			
		||||
    explicit GraphicsPipeline(Tegra::Engines::Maxwell3D& maxwell3d,
 | 
			
		||||
                              Tegra::MemoryManager& gpu_memory, VKScheduler& scheduler,
 | 
			
		||||
                              BufferCache& buffer_cache, TextureCache& texture_cache,
 | 
			
		||||
                              const Device& device, VKDescriptorPool& descriptor_pool,
 | 
			
		||||
                              const Device& device, DescriptorPool& descriptor_pool,
 | 
			
		||||
                              VKUpdateDescriptorQueue& update_descriptor_queue,
 | 
			
		||||
                              Common::ThreadWorker* worker_thread,
 | 
			
		||||
                              RenderPassCache& render_pass_cache,
 | 
			
		||||
 
 | 
			
		||||
@@ -647,7 +647,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::GPU& gpu_,
 | 
			
		||||
                             Tegra::Engines::Maxwell3D& maxwell3d_,
 | 
			
		||||
                             Tegra::Engines::KeplerCompute& kepler_compute_,
 | 
			
		||||
                             Tegra::MemoryManager& gpu_memory_, const Device& device_,
 | 
			
		||||
                             VKScheduler& scheduler_, VKDescriptorPool& descriptor_pool_,
 | 
			
		||||
                             VKScheduler& scheduler_, DescriptorPool& descriptor_pool_,
 | 
			
		||||
                             VKUpdateDescriptorQueue& update_descriptor_queue_,
 | 
			
		||||
                             RenderPassCache& render_pass_cache_, BufferCache& buffer_cache_,
 | 
			
		||||
                             TextureCache& texture_cache_)
 | 
			
		||||
 
 | 
			
		||||
@@ -75,10 +75,10 @@ namespace Vulkan {
 | 
			
		||||
 | 
			
		||||
class ComputePipeline;
 | 
			
		||||
class Device;
 | 
			
		||||
class DescriptorPool;
 | 
			
		||||
class GenericEnvironment;
 | 
			
		||||
class RasterizerVulkan;
 | 
			
		||||
class RenderPassCache;
 | 
			
		||||
class VKDescriptorPool;
 | 
			
		||||
class VKScheduler;
 | 
			
		||||
class VKUpdateDescriptorQueue;
 | 
			
		||||
 | 
			
		||||
@@ -105,7 +105,7 @@ public:
 | 
			
		||||
                           Tegra::Engines::Maxwell3D& maxwell3d,
 | 
			
		||||
                           Tegra::Engines::KeplerCompute& kepler_compute,
 | 
			
		||||
                           Tegra::MemoryManager& gpu_memory, const Device& device,
 | 
			
		||||
                           VKScheduler& scheduler, VKDescriptorPool& descriptor_pool,
 | 
			
		||||
                           VKScheduler& scheduler, DescriptorPool& descriptor_pool,
 | 
			
		||||
                           VKUpdateDescriptorQueue& update_descriptor_queue,
 | 
			
		||||
                           RenderPassCache& render_pass_cache, BufferCache& buffer_cache,
 | 
			
		||||
                           TextureCache& texture_cache);
 | 
			
		||||
@@ -147,7 +147,7 @@ private:
 | 
			
		||||
 | 
			
		||||
    const Device& device;
 | 
			
		||||
    VKScheduler& scheduler;
 | 
			
		||||
    VKDescriptorPool& descriptor_pool;
 | 
			
		||||
    DescriptorPool& descriptor_pool;
 | 
			
		||||
    VKUpdateDescriptorQueue& update_descriptor_queue;
 | 
			
		||||
    RenderPassCache& render_pass_cache;
 | 
			
		||||
    BufferCache& buffer_cache;
 | 
			
		||||
 
 | 
			
		||||
@@ -147,7 +147,7 @@ private:
 | 
			
		||||
    VKScheduler& scheduler;
 | 
			
		||||
 | 
			
		||||
    StagingBufferPool staging_pool;
 | 
			
		||||
    VKDescriptorPool descriptor_pool;
 | 
			
		||||
    DescriptorPool descriptor_pool;
 | 
			
		||||
    VKUpdateDescriptorQueue update_descriptor_queue;
 | 
			
		||||
    BlitImageHelper blit_image;
 | 
			
		||||
    ASTCDecoderPass astc_decoder_pass;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user