diff options
| author | 2021-04-25 00:15:32 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:29 -0400 | |
| commit | 2f3c3dfc10a318f63862c4976f0608ea50c19387 (patch) | |
| tree | 243109289cc347fe1e8d3ea8adee8e32c791af3b | |
| parent | vk_graphics_pipeline: Generate specialized pipeline config functions and impr... (diff) | |
| download | yuzu-2f3c3dfc10a318f63862c4976f0608ea50c19387.tar.gz yuzu-2f3c3dfc10a318f63862c4976f0608ea50c19387.tar.xz yuzu-2f3c3dfc10a318f63862c4976f0608ea50c19387.zip | |
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.
Diffstat (limited to '')
15 files changed, 314 insertions, 197 deletions
diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index 39fe9289b..4058f62cd 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp | |||
| @@ -49,6 +49,16 @@ constexpr VkDescriptorSetLayoutCreateInfo ONE_TEXTURE_DESCRIPTOR_SET_LAYOUT_CREA | |||
| 49 | .bindingCount = 1, | 49 | .bindingCount = 1, |
| 50 | .pBindings = &TEXTURE_DESCRIPTOR_SET_LAYOUT_BINDING<0>, | 50 | .pBindings = &TEXTURE_DESCRIPTOR_SET_LAYOUT_BINDING<0>, |
| 51 | }; | 51 | }; |
| 52 | template <u32 num_textures> | ||
| 53 | inline constexpr DescriptorBankInfo TEXTURE_DESCRIPTOR_BANK_INFO{ | ||
| 54 | .uniform_buffers = 0, | ||
| 55 | .storage_buffers = 0, | ||
| 56 | .texture_buffers = 0, | ||
| 57 | .image_buffers = 0, | ||
| 58 | .textures = num_textures, | ||
| 59 | .images = 0, | ||
| 60 | .score = 2, | ||
| 61 | }; | ||
| 52 | constexpr VkDescriptorSetLayoutCreateInfo TWO_TEXTURES_DESCRIPTOR_SET_LAYOUT_CREATE_INFO{ | 62 | constexpr VkDescriptorSetLayoutCreateInfo TWO_TEXTURES_DESCRIPTOR_SET_LAYOUT_CREATE_INFO{ |
| 53 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, | 63 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, |
| 54 | .pNext = nullptr, | 64 | .pNext = nullptr, |
| @@ -326,14 +336,16 @@ void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Regi | |||
| 326 | } // Anonymous namespace | 336 | } // Anonymous namespace |
| 327 | 337 | ||
| 328 | BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_, | 338 | BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_, |
| 329 | StateTracker& state_tracker_, VKDescriptorPool& descriptor_pool) | 339 | StateTracker& state_tracker_, DescriptorPool& descriptor_pool) |
| 330 | : device{device_}, scheduler{scheduler_}, state_tracker{state_tracker_}, | 340 | : device{device_}, scheduler{scheduler_}, state_tracker{state_tracker_}, |
| 331 | one_texture_set_layout(device.GetLogical().CreateDescriptorSetLayout( | 341 | one_texture_set_layout(device.GetLogical().CreateDescriptorSetLayout( |
| 332 | ONE_TEXTURE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO)), | 342 | ONE_TEXTURE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO)), |
| 333 | two_textures_set_layout(device.GetLogical().CreateDescriptorSetLayout( | 343 | two_textures_set_layout(device.GetLogical().CreateDescriptorSetLayout( |
| 334 | TWO_TEXTURES_DESCRIPTOR_SET_LAYOUT_CREATE_INFO)), | 344 | TWO_TEXTURES_DESCRIPTOR_SET_LAYOUT_CREATE_INFO)), |
| 335 | one_texture_descriptor_allocator(descriptor_pool, *one_texture_set_layout), | 345 | one_texture_descriptor_allocator{ |
| 336 | two_textures_descriptor_allocator(descriptor_pool, *two_textures_set_layout), | 346 | descriptor_pool.Allocator(*one_texture_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<1>)}, |
| 347 | two_textures_descriptor_allocator{ | ||
| 348 | descriptor_pool.Allocator(*two_textures_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<2>)}, | ||
| 337 | one_texture_pipeline_layout(device.GetLogical().CreatePipelineLayout( | 349 | one_texture_pipeline_layout(device.GetLogical().CreatePipelineLayout( |
| 338 | PipelineLayoutCreateInfo(one_texture_set_layout.address()))), | 350 | PipelineLayoutCreateInfo(one_texture_set_layout.address()))), |
| 339 | two_textures_pipeline_layout(device.GetLogical().CreatePipelineLayout( | 351 | two_textures_pipeline_layout(device.GetLogical().CreatePipelineLayout( |
| @@ -415,7 +427,6 @@ void BlitImageHelper::ConvertD32ToR32(const Framebuffer* dst_framebuffer, | |||
| 415 | 427 | ||
| 416 | void BlitImageHelper::ConvertR32ToD32(const Framebuffer* dst_framebuffer, | 428 | void BlitImageHelper::ConvertR32ToD32(const Framebuffer* dst_framebuffer, |
| 417 | const ImageView& src_image_view) { | 429 | const ImageView& src_image_view) { |
| 418 | |||
| 419 | ConvertColorToDepthPipeline(convert_r32_to_d32_pipeline, dst_framebuffer->RenderPass()); | 430 | ConvertColorToDepthPipeline(convert_r32_to_d32_pipeline, dst_framebuffer->RenderPass()); |
| 420 | Convert(*convert_r32_to_d32_pipeline, dst_framebuffer, src_image_view); | 431 | Convert(*convert_r32_to_d32_pipeline, dst_framebuffer, src_image_view); |
| 421 | } | 432 | } |
diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h index 0d81a06ed..33ee095c1 100644 --- a/src/video_core/renderer_vulkan/blit_image.h +++ b/src/video_core/renderer_vulkan/blit_image.h | |||
| @@ -31,7 +31,7 @@ struct BlitImagePipelineKey { | |||
| 31 | class BlitImageHelper { | 31 | class BlitImageHelper { |
| 32 | public: | 32 | public: |
| 33 | explicit BlitImageHelper(const Device& device, VKScheduler& scheduler, | 33 | explicit BlitImageHelper(const Device& device, VKScheduler& scheduler, |
| 34 | StateTracker& state_tracker, VKDescriptorPool& descriptor_pool); | 34 | StateTracker& state_tracker, DescriptorPool& descriptor_pool); |
| 35 | ~BlitImageHelper(); | 35 | ~BlitImageHelper(); |
| 36 | 36 | ||
| 37 | void BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, | 37 | void BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, |
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index cdda56ab1..568993c58 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp | |||
| @@ -116,7 +116,7 @@ VkBufferView Buffer::View(u32 offset, u32 size, VideoCore::Surface::PixelFormat | |||
| 116 | BufferCacheRuntime::BufferCacheRuntime(const Device& device_, MemoryAllocator& memory_allocator_, | 116 | BufferCacheRuntime::BufferCacheRuntime(const Device& device_, MemoryAllocator& memory_allocator_, |
| 117 | VKScheduler& scheduler_, StagingBufferPool& staging_pool_, | 117 | VKScheduler& scheduler_, StagingBufferPool& staging_pool_, |
| 118 | VKUpdateDescriptorQueue& update_descriptor_queue_, | 118 | VKUpdateDescriptorQueue& update_descriptor_queue_, |
| 119 | VKDescriptorPool& descriptor_pool) | 119 | DescriptorPool& descriptor_pool) |
| 120 | : device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_}, | 120 | : device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_}, |
| 121 | staging_pool{staging_pool_}, update_descriptor_queue{update_descriptor_queue_}, | 121 | staging_pool{staging_pool_}, update_descriptor_queue{update_descriptor_queue_}, |
| 122 | uint8_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue), | 122 | uint8_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue), |
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index ea17406dc..c52001b5a 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | namespace Vulkan { | 16 | namespace Vulkan { |
| 17 | 17 | ||
| 18 | class Device; | 18 | class Device; |
| 19 | class VKDescriptorPool; | 19 | class DescriptorPool; |
| 20 | class VKScheduler; | 20 | class VKScheduler; |
| 21 | 21 | ||
| 22 | class BufferCacheRuntime; | 22 | class BufferCacheRuntime; |
| @@ -61,7 +61,7 @@ public: | |||
| 61 | explicit BufferCacheRuntime(const Device& device_, MemoryAllocator& memory_manager_, | 61 | explicit BufferCacheRuntime(const Device& device_, MemoryAllocator& memory_manager_, |
| 62 | VKScheduler& scheduler_, StagingBufferPool& staging_pool_, | 62 | VKScheduler& scheduler_, StagingBufferPool& staging_pool_, |
| 63 | VKUpdateDescriptorQueue& update_descriptor_queue_, | 63 | VKUpdateDescriptorQueue& update_descriptor_queue_, |
| 64 | VKDescriptorPool& descriptor_pool); | 64 | DescriptorPool& descriptor_pool); |
| 65 | 65 | ||
| 66 | void Finish(); | 66 | void Finish(); |
| 67 | 67 | ||
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp index ec9866605..e2f3d16bf 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp | |||
| @@ -41,80 +41,92 @@ constexpr u32 ASTC_BINDING_SWIZZLE_BUFFER = 2; | |||
| 41 | constexpr u32 ASTC_BINDING_OUTPUT_IMAGE = 3; | 41 | constexpr u32 ASTC_BINDING_OUTPUT_IMAGE = 3; |
| 42 | constexpr size_t ASTC_NUM_BINDINGS = 4; | 42 | constexpr size_t ASTC_NUM_BINDINGS = 4; |
| 43 | 43 | ||
| 44 | VkPushConstantRange BuildComputePushConstantRange(std::size_t size) { | 44 | template <size_t size> |
| 45 | return { | 45 | inline constexpr VkPushConstantRange COMPUTE_PUSH_CONSTANT_RANGE{ |
| 46 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | 46 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, |
| 47 | .offset = 0, | 47 | .offset = 0, |
| 48 | .size = static_cast<u32>(size), | 48 | .size = static_cast<u32>(size), |
| 49 | }; | 49 | }; |
| 50 | } | ||
| 51 | |||
| 52 | std::array<VkDescriptorSetLayoutBinding, 2> BuildInputOutputDescriptorSetBindings() { | ||
| 53 | return {{ | ||
| 54 | { | ||
| 55 | .binding = 0, | ||
| 56 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||
| 57 | .descriptorCount = 1, | ||
| 58 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 59 | .pImmutableSamplers = nullptr, | ||
| 60 | }, | ||
| 61 | { | ||
| 62 | .binding = 1, | ||
| 63 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||
| 64 | .descriptorCount = 1, | ||
| 65 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 66 | .pImmutableSamplers = nullptr, | ||
| 67 | }, | ||
| 68 | }}; | ||
| 69 | } | ||
| 70 | 50 | ||
| 71 | std::array<VkDescriptorSetLayoutBinding, ASTC_NUM_BINDINGS> BuildASTCDescriptorSetBindings() { | 51 | constexpr std::array<VkDescriptorSetLayoutBinding, 2> INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS{{ |
| 72 | return {{ | 52 | { |
| 73 | { | 53 | .binding = 0, |
| 74 | .binding = ASTC_BINDING_INPUT_BUFFER, | 54 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, |
| 75 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | 55 | .descriptorCount = 1, |
| 76 | .descriptorCount = 1, | 56 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, |
| 77 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | 57 | .pImmutableSamplers = nullptr, |
| 78 | .pImmutableSamplers = nullptr, | 58 | }, |
| 79 | }, | 59 | { |
| 80 | { | 60 | .binding = 1, |
| 81 | .binding = ASTC_BINDING_ENC_BUFFER, | 61 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, |
| 82 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | 62 | .descriptorCount = 1, |
| 83 | .descriptorCount = 1, | 63 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, |
| 84 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | 64 | .pImmutableSamplers = nullptr, |
| 85 | .pImmutableSamplers = nullptr, | 65 | }, |
| 86 | }, | 66 | }}; |
| 87 | { | 67 | |
| 88 | .binding = ASTC_BINDING_SWIZZLE_BUFFER, | 68 | constexpr DescriptorBankInfo INPUT_OUTPUT_BANK_INFO{ |
| 89 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | 69 | .uniform_buffers = 0, |
| 90 | .descriptorCount = 1, | 70 | .storage_buffers = 2, |
| 91 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | 71 | .texture_buffers = 0, |
| 92 | .pImmutableSamplers = nullptr, | 72 | .image_buffers = 0, |
| 93 | }, | 73 | .textures = 0, |
| 94 | { | 74 | .images = 0, |
| 95 | .binding = ASTC_BINDING_OUTPUT_IMAGE, | 75 | .score = 2, |
| 96 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, | 76 | }; |
| 97 | .descriptorCount = 1, | ||
| 98 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 99 | .pImmutableSamplers = nullptr, | ||
| 100 | }, | ||
| 101 | }}; | ||
| 102 | } | ||
| 103 | 77 | ||
| 104 | VkDescriptorUpdateTemplateEntryKHR BuildInputOutputDescriptorUpdateTemplate() { | 78 | constexpr std::array<VkDescriptorSetLayoutBinding, 4> ASTC_DESCRIPTOR_SET_BINDINGS{{ |
| 105 | return { | 79 | { |
| 106 | .dstBinding = 0, | 80 | .binding = ASTC_BINDING_INPUT_BUFFER, |
| 107 | .dstArrayElement = 0, | ||
| 108 | .descriptorCount = 2, | ||
| 109 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | 81 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, |
| 110 | .offset = 0, | 82 | .descriptorCount = 1, |
| 111 | .stride = sizeof(DescriptorUpdateEntry), | 83 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, |
| 112 | }; | 84 | .pImmutableSamplers = nullptr, |
| 113 | } | 85 | }, |
| 86 | { | ||
| 87 | .binding = ASTC_BINDING_ENC_BUFFER, | ||
| 88 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||
| 89 | .descriptorCount = 1, | ||
| 90 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 91 | .pImmutableSamplers = nullptr, | ||
| 92 | }, | ||
| 93 | { | ||
| 94 | .binding = ASTC_BINDING_SWIZZLE_BUFFER, | ||
| 95 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||
| 96 | .descriptorCount = 1, | ||
| 97 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 98 | .pImmutableSamplers = nullptr, | ||
| 99 | }, | ||
| 100 | { | ||
| 101 | .binding = ASTC_BINDING_OUTPUT_IMAGE, | ||
| 102 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, | ||
| 103 | .descriptorCount = 1, | ||
| 104 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 105 | .pImmutableSamplers = nullptr, | ||
| 106 | }, | ||
| 107 | }}; | ||
| 108 | |||
| 109 | constexpr DescriptorBankInfo ASTC_BANK_INFO{ | ||
| 110 | .uniform_buffers = 0, | ||
| 111 | .storage_buffers = 3, | ||
| 112 | .texture_buffers = 0, | ||
| 113 | .image_buffers = 0, | ||
| 114 | .textures = 0, | ||
| 115 | .images = 1, | ||
| 116 | .score = 4, | ||
| 117 | }; | ||
| 118 | |||
| 119 | constexpr VkDescriptorUpdateTemplateEntryKHR INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE{ | ||
| 120 | .dstBinding = 0, | ||
| 121 | .dstArrayElement = 0, | ||
| 122 | .descriptorCount = 2, | ||
| 123 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, | ||
| 124 | .offset = 0, | ||
| 125 | .stride = sizeof(DescriptorUpdateEntry), | ||
| 126 | }; | ||
| 114 | 127 | ||
| 115 | std::array<VkDescriptorUpdateTemplateEntryKHR, ASTC_NUM_BINDINGS> | 128 | constexpr std::array<VkDescriptorUpdateTemplateEntryKHR, ASTC_NUM_BINDINGS> |
| 116 | BuildASTCPassDescriptorUpdateTemplateEntry() { | 129 | ASTC_PASS_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY{{ |
| 117 | return {{ | ||
| 118 | { | 130 | { |
| 119 | .dstBinding = ASTC_BINDING_INPUT_BUFFER, | 131 | .dstBinding = ASTC_BINDING_INPUT_BUFFER, |
| 120 | .dstArrayElement = 0, | 132 | .dstArrayElement = 0, |
| @@ -148,7 +160,6 @@ BuildASTCPassDescriptorUpdateTemplateEntry() { | |||
| 148 | .stride = sizeof(DescriptorUpdateEntry), | 160 | .stride = sizeof(DescriptorUpdateEntry), |
| 149 | }, | 161 | }, |
| 150 | }}; | 162 | }}; |
| 151 | } | ||
| 152 | 163 | ||
| 153 | struct AstcPushConstants { | 164 | struct AstcPushConstants { |
| 154 | std::array<u32, 2> blocks_dims; | 165 | std::array<u32, 2> blocks_dims; |
| @@ -159,14 +170,13 @@ struct AstcPushConstants { | |||
| 159 | u32 block_height; | 170 | u32 block_height; |
| 160 | u32 block_height_mask; | 171 | u32 block_height_mask; |
| 161 | }; | 172 | }; |
| 162 | |||
| 163 | } // Anonymous namespace | 173 | } // Anonymous namespace |
| 164 | 174 | ||
| 165 | VKComputePass::VKComputePass(const Device& device, VKDescriptorPool& descriptor_pool, | 175 | ComputePass::ComputePass(const Device& device, DescriptorPool& descriptor_pool, |
| 166 | vk::Span<VkDescriptorSetLayoutBinding> bindings, | 176 | vk::Span<VkDescriptorSetLayoutBinding> bindings, |
| 167 | vk::Span<VkDescriptorUpdateTemplateEntryKHR> templates, | 177 | vk::Span<VkDescriptorUpdateTemplateEntryKHR> templates, |
| 168 | vk::Span<VkPushConstantRange> push_constants, | 178 | const DescriptorBankInfo& bank_info, |
| 169 | std::span<const u32> code) { | 179 | vk::Span<VkPushConstantRange> push_constants, std::span<const u32> code) { |
| 170 | descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout({ | 180 | descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout({ |
| 171 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, | 181 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, |
| 172 | .pNext = nullptr, | 182 | .pNext = nullptr, |
| @@ -196,8 +206,7 @@ VKComputePass::VKComputePass(const Device& device, VKDescriptorPool& descriptor_ | |||
| 196 | .pipelineLayout = *layout, | 206 | .pipelineLayout = *layout, |
| 197 | .set = 0, | 207 | .set = 0, |
| 198 | }); | 208 | }); |
| 199 | 209 | descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, bank_info); | |
| 200 | descriptor_allocator.emplace(descriptor_pool, *descriptor_set_layout); | ||
| 201 | } | 210 | } |
| 202 | module = device.GetLogical().CreateShaderModule({ | 211 | module = device.GetLogical().CreateShaderModule({ |
| 203 | .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, | 212 | .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, |
| @@ -226,23 +235,23 @@ VKComputePass::VKComputePass(const Device& device, VKDescriptorPool& descriptor_ | |||
| 226 | }); | 235 | }); |
| 227 | } | 236 | } |
| 228 | 237 | ||
| 229 | VKComputePass::~VKComputePass() = default; | 238 | ComputePass::~ComputePass() = default; |
| 230 | 239 | ||
| 231 | VkDescriptorSet VKComputePass::CommitDescriptorSet( | 240 | VkDescriptorSet ComputePass::CommitDescriptorSet(VKUpdateDescriptorQueue& update_descriptor_queue) { |
| 232 | VKUpdateDescriptorQueue& update_descriptor_queue) { | ||
| 233 | if (!descriptor_template) { | 241 | if (!descriptor_template) { |
| 234 | return nullptr; | 242 | return nullptr; |
| 235 | } | 243 | } |
| 236 | const VkDescriptorSet set = descriptor_allocator->Commit(); | 244 | const VkDescriptorSet set = descriptor_allocator.Commit(); |
| 237 | update_descriptor_queue.Send(descriptor_template.address(), set); | 245 | update_descriptor_queue.Send(descriptor_template.address(), set); |
| 238 | return set; | 246 | return set; |
| 239 | } | 247 | } |
| 240 | 248 | ||
| 241 | Uint8Pass::Uint8Pass(const Device& device, VKScheduler& scheduler_, | 249 | Uint8Pass::Uint8Pass(const Device& device, VKScheduler& scheduler_, DescriptorPool& descriptor_pool, |
| 242 | VKDescriptorPool& descriptor_pool, StagingBufferPool& staging_buffer_pool_, | 250 | StagingBufferPool& staging_buffer_pool_, |
| 243 | VKUpdateDescriptorQueue& update_descriptor_queue_) | 251 | VKUpdateDescriptorQueue& update_descriptor_queue_) |
| 244 | : VKComputePass(device, descriptor_pool, BuildInputOutputDescriptorSetBindings(), | 252 | : ComputePass(device, descriptor_pool, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS, |
| 245 | BuildInputOutputDescriptorUpdateTemplate(), {}, VULKAN_UINT8_COMP_SPV), | 253 | INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO, {}, |
| 254 | VULKAN_UINT8_COMP_SPV), | ||
| 246 | scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_}, | 255 | scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_}, |
| 247 | update_descriptor_queue{update_descriptor_queue_} {} | 256 | update_descriptor_queue{update_descriptor_queue_} {} |
| 248 | 257 | ||
| @@ -277,12 +286,12 @@ std::pair<VkBuffer, VkDeviceSize> Uint8Pass::Assemble(u32 num_vertices, VkBuffer | |||
| 277 | } | 286 | } |
| 278 | 287 | ||
| 279 | QuadIndexedPass::QuadIndexedPass(const Device& device_, VKScheduler& scheduler_, | 288 | QuadIndexedPass::QuadIndexedPass(const Device& device_, VKScheduler& scheduler_, |
| 280 | VKDescriptorPool& descriptor_pool_, | 289 | DescriptorPool& descriptor_pool_, |
| 281 | StagingBufferPool& staging_buffer_pool_, | 290 | StagingBufferPool& staging_buffer_pool_, |
| 282 | VKUpdateDescriptorQueue& update_descriptor_queue_) | 291 | VKUpdateDescriptorQueue& update_descriptor_queue_) |
| 283 | : VKComputePass(device_, descriptor_pool_, BuildInputOutputDescriptorSetBindings(), | 292 | : ComputePass(device_, descriptor_pool_, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS, |
| 284 | BuildInputOutputDescriptorUpdateTemplate(), | 293 | INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO, |
| 285 | BuildComputePushConstantRange(sizeof(u32) * 2), VULKAN_QUAD_INDEXED_COMP_SPV), | 294 | COMPUTE_PUSH_CONSTANT_RANGE<sizeof(u32) * 2>, VULKAN_QUAD_INDEXED_COMP_SPV), |
| 286 | scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_}, | 295 | scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_}, |
| 287 | update_descriptor_queue{update_descriptor_queue_} {} | 296 | update_descriptor_queue{update_descriptor_queue_} {} |
| 288 | 297 | ||
| @@ -337,14 +346,13 @@ std::pair<VkBuffer, VkDeviceSize> QuadIndexedPass::Assemble( | |||
| 337 | } | 346 | } |
| 338 | 347 | ||
| 339 | ASTCDecoderPass::ASTCDecoderPass(const Device& device_, VKScheduler& scheduler_, | 348 | ASTCDecoderPass::ASTCDecoderPass(const Device& device_, VKScheduler& scheduler_, |
| 340 | VKDescriptorPool& descriptor_pool_, | 349 | DescriptorPool& descriptor_pool_, |
| 341 | StagingBufferPool& staging_buffer_pool_, | 350 | StagingBufferPool& staging_buffer_pool_, |
| 342 | VKUpdateDescriptorQueue& update_descriptor_queue_, | 351 | VKUpdateDescriptorQueue& update_descriptor_queue_, |
| 343 | MemoryAllocator& memory_allocator_) | 352 | MemoryAllocator& memory_allocator_) |
| 344 | : VKComputePass(device_, descriptor_pool_, BuildASTCDescriptorSetBindings(), | 353 | : ComputePass(device_, descriptor_pool_, ASTC_DESCRIPTOR_SET_BINDINGS, |
| 345 | BuildASTCPassDescriptorUpdateTemplateEntry(), | 354 | ASTC_PASS_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY, ASTC_BANK_INFO, |
| 346 | BuildComputePushConstantRange(sizeof(AstcPushConstants)), | 355 | COMPUTE_PUSH_CONSTANT_RANGE<sizeof(AstcPushConstants)>, ASTC_DECODER_COMP_SPV), |
| 347 | ASTC_DECODER_COMP_SPV), | ||
| 348 | device{device_}, scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_}, | 356 | device{device_}, scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_}, |
| 349 | update_descriptor_queue{update_descriptor_queue_}, memory_allocator{memory_allocator_} {} | 357 | update_descriptor_queue{update_descriptor_queue_}, memory_allocator{memory_allocator_} {} |
| 350 | 358 | ||
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.h b/src/video_core/renderer_vulkan/vk_compute_pass.h index 5ea187c30..54c1ac4cb 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.h +++ b/src/video_core/renderer_vulkan/vk_compute_pass.h | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <optional> | ||
| 8 | #include <span> | 7 | #include <span> |
| 9 | #include <utility> | 8 | #include <utility> |
| 10 | 9 | ||
| @@ -27,13 +26,14 @@ class VKUpdateDescriptorQueue; | |||
| 27 | class Image; | 26 | class Image; |
| 28 | struct StagingBufferRef; | 27 | struct StagingBufferRef; |
| 29 | 28 | ||
| 30 | class VKComputePass { | 29 | class ComputePass { |
| 31 | public: | 30 | public: |
| 32 | explicit VKComputePass(const Device& device, VKDescriptorPool& descriptor_pool, | 31 | explicit ComputePass(const Device& device, DescriptorPool& descriptor_pool, |
| 33 | vk::Span<VkDescriptorSetLayoutBinding> bindings, | 32 | vk::Span<VkDescriptorSetLayoutBinding> bindings, |
| 34 | vk::Span<VkDescriptorUpdateTemplateEntryKHR> templates, | 33 | vk::Span<VkDescriptorUpdateTemplateEntryKHR> templates, |
| 35 | vk::Span<VkPushConstantRange> push_constants, std::span<const u32> code); | 34 | const DescriptorBankInfo& bank_info, |
| 36 | ~VKComputePass(); | 35 | vk::Span<VkPushConstantRange> push_constants, std::span<const u32> code); |
| 36 | ~ComputePass(); | ||
| 37 | 37 | ||
| 38 | protected: | 38 | protected: |
| 39 | VkDescriptorSet CommitDescriptorSet(VKUpdateDescriptorQueue& update_descriptor_queue); | 39 | VkDescriptorSet CommitDescriptorSet(VKUpdateDescriptorQueue& update_descriptor_queue); |
| @@ -44,14 +44,14 @@ protected: | |||
| 44 | 44 | ||
| 45 | private: | 45 | private: |
| 46 | vk::DescriptorSetLayout descriptor_set_layout; | 46 | vk::DescriptorSetLayout descriptor_set_layout; |
| 47 | std::optional<DescriptorAllocator> descriptor_allocator; | 47 | DescriptorAllocator descriptor_allocator; |
| 48 | vk::ShaderModule module; | 48 | vk::ShaderModule module; |
| 49 | }; | 49 | }; |
| 50 | 50 | ||
| 51 | class Uint8Pass final : public VKComputePass { | 51 | class Uint8Pass final : public ComputePass { |
| 52 | public: | 52 | public: |
| 53 | explicit Uint8Pass(const Device& device_, VKScheduler& scheduler_, | 53 | explicit Uint8Pass(const Device& device_, VKScheduler& scheduler_, |
| 54 | VKDescriptorPool& descriptor_pool_, StagingBufferPool& staging_buffer_pool_, | 54 | DescriptorPool& descriptor_pool_, StagingBufferPool& staging_buffer_pool_, |
| 55 | VKUpdateDescriptorQueue& update_descriptor_queue_); | 55 | VKUpdateDescriptorQueue& update_descriptor_queue_); |
| 56 | ~Uint8Pass(); | 56 | ~Uint8Pass(); |
| 57 | 57 | ||
| @@ -66,10 +66,10 @@ private: | |||
| 66 | VKUpdateDescriptorQueue& update_descriptor_queue; | 66 | VKUpdateDescriptorQueue& update_descriptor_queue; |
| 67 | }; | 67 | }; |
| 68 | 68 | ||
| 69 | class QuadIndexedPass final : public VKComputePass { | 69 | class QuadIndexedPass final : public ComputePass { |
| 70 | public: | 70 | public: |
| 71 | explicit QuadIndexedPass(const Device& device_, VKScheduler& scheduler_, | 71 | explicit QuadIndexedPass(const Device& device_, VKScheduler& scheduler_, |
| 72 | VKDescriptorPool& descriptor_pool_, | 72 | DescriptorPool& descriptor_pool_, |
| 73 | StagingBufferPool& staging_buffer_pool_, | 73 | StagingBufferPool& staging_buffer_pool_, |
| 74 | VKUpdateDescriptorQueue& update_descriptor_queue_); | 74 | VKUpdateDescriptorQueue& update_descriptor_queue_); |
| 75 | ~QuadIndexedPass(); | 75 | ~QuadIndexedPass(); |
| @@ -84,10 +84,10 @@ private: | |||
| 84 | VKUpdateDescriptorQueue& update_descriptor_queue; | 84 | VKUpdateDescriptorQueue& update_descriptor_queue; |
| 85 | }; | 85 | }; |
| 86 | 86 | ||
| 87 | class ASTCDecoderPass final : public VKComputePass { | 87 | class ASTCDecoderPass final : public ComputePass { |
| 88 | public: | 88 | public: |
| 89 | explicit ASTCDecoderPass(const Device& device_, VKScheduler& scheduler_, | 89 | explicit ASTCDecoderPass(const Device& device_, VKScheduler& scheduler_, |
| 90 | VKDescriptorPool& descriptor_pool_, | 90 | DescriptorPool& descriptor_pool_, |
| 91 | StagingBufferPool& staging_buffer_pool_, | 91 | StagingBufferPool& staging_buffer_pool_, |
| 92 | VKUpdateDescriptorQueue& update_descriptor_queue_, | 92 | VKUpdateDescriptorQueue& update_descriptor_queue_, |
| 93 | MemoryAllocator& memory_allocator_); | 93 | MemoryAllocator& memory_allocator_); |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 990ead575..54a57c358 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | |||
| @@ -18,7 +18,7 @@ | |||
| 18 | 18 | ||
| 19 | namespace Vulkan { | 19 | namespace Vulkan { |
| 20 | 20 | ||
| 21 | ComputePipeline::ComputePipeline(const Device& device, VKDescriptorPool& descriptor_pool, | 21 | ComputePipeline::ComputePipeline(const Device& device, DescriptorPool& descriptor_pool, |
| 22 | VKUpdateDescriptorQueue& update_descriptor_queue_, | 22 | VKUpdateDescriptorQueue& update_descriptor_queue_, |
| 23 | Common::ThreadWorker* thread_worker, const Shader::Info& info_, | 23 | Common::ThreadWorker* thread_worker, const Shader::Info& info_, |
| 24 | vk::ShaderModule spv_module_) | 24 | vk::ShaderModule spv_module_) |
| @@ -30,7 +30,7 @@ ComputePipeline::ComputePipeline(const Device& device, VKDescriptorPool& descrip | |||
| 30 | descriptor_set_layout = builder.CreateDescriptorSetLayout(); | 30 | descriptor_set_layout = builder.CreateDescriptorSetLayout(); |
| 31 | pipeline_layout = builder.CreatePipelineLayout(*descriptor_set_layout); | 31 | pipeline_layout = builder.CreatePipelineLayout(*descriptor_set_layout); |
| 32 | descriptor_update_template = builder.CreateTemplate(*descriptor_set_layout, *pipeline_layout); | 32 | descriptor_update_template = builder.CreateTemplate(*descriptor_set_layout, *pipeline_layout); |
| 33 | descriptor_allocator = DescriptorAllocator(descriptor_pool, *descriptor_set_layout); | 33 | descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, info); |
| 34 | 34 | ||
| 35 | auto func{[this, &device] { | 35 | auto func{[this, &device] { |
| 36 | const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{ | 36 | const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{ |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.h b/src/video_core/renderer_vulkan/vk_compute_pipeline.h index 8efdc2926..0d4cd37be 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.h | |||
| @@ -25,7 +25,7 @@ class VKScheduler; | |||
| 25 | 25 | ||
| 26 | class ComputePipeline { | 26 | class ComputePipeline { |
| 27 | public: | 27 | public: |
| 28 | explicit ComputePipeline(const Device& device, VKDescriptorPool& descriptor_pool, | 28 | explicit ComputePipeline(const Device& device, DescriptorPool& descriptor_pool, |
| 29 | VKUpdateDescriptorQueue& update_descriptor_queue, | 29 | VKUpdateDescriptorQueue& update_descriptor_queue, |
| 30 | Common::ThreadWorker* thread_worker, const Shader::Info& info, | 30 | Common::ThreadWorker* thread_worker, const Shader::Info& info, |
| 31 | vk::ShaderModule spv_module); | 31 | vk::ShaderModule spv_module); |
diff --git a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp index 3bea1ff44..8e77e4796 100644 --- a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <mutex> | ||
| 6 | #include <span> | ||
| 5 | #include <vector> | 7 | #include <vector> |
| 6 | 8 | ||
| 7 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| @@ -13,77 +15,149 @@ | |||
| 13 | 15 | ||
| 14 | namespace Vulkan { | 16 | namespace Vulkan { |
| 15 | 17 | ||
| 16 | // Prefer small grow rates to avoid saturating the descriptor pool with barely used pipelines. | 18 | // Prefer small grow rates to avoid saturating the descriptor pool with barely used pipelines |
| 17 | constexpr std::size_t SETS_GROW_RATE = 0x20; | 19 | constexpr size_t SETS_GROW_RATE = 16; |
| 20 | constexpr s32 SCORE_THRESHOLD = 3; | ||
| 21 | constexpr u32 SETS_PER_POOL = 64; | ||
| 18 | 22 | ||
| 19 | DescriptorAllocator::DescriptorAllocator(VKDescriptorPool& descriptor_pool_, | 23 | struct DescriptorBank { |
| 20 | VkDescriptorSetLayout layout_) | 24 | DescriptorBankInfo info; |
| 21 | : ResourcePool(descriptor_pool_.master_semaphore, SETS_GROW_RATE), | 25 | std::vector<vk::DescriptorPool> pools; |
| 22 | descriptor_pool{&descriptor_pool_}, layout{layout_} {} | 26 | }; |
| 23 | 27 | ||
| 24 | VkDescriptorSet DescriptorAllocator::Commit() { | 28 | bool DescriptorBankInfo::IsSuperset(const DescriptorBankInfo& subset) const noexcept { |
| 25 | const std::size_t index = CommitResource(); | 29 | return uniform_buffers >= subset.uniform_buffers && storage_buffers >= subset.storage_buffers && |
| 26 | return descriptors_allocations[index / SETS_GROW_RATE][index % SETS_GROW_RATE]; | 30 | texture_buffers >= subset.texture_buffers && image_buffers >= subset.image_buffers && |
| 31 | textures >= subset.textures && images >= subset.image_buffers; | ||
| 27 | } | 32 | } |
| 28 | 33 | ||
| 29 | void DescriptorAllocator::Allocate(std::size_t begin, std::size_t end) { | 34 | template <typename Descriptors> |
| 30 | descriptors_allocations.push_back(descriptor_pool->AllocateDescriptors(layout, end - begin)); | 35 | static u32 Accumulate(const Descriptors& descriptors) { |
| 36 | u32 count = 0; | ||
| 37 | for (const auto& descriptor : descriptors) { | ||
| 38 | count += descriptor.count; | ||
| 39 | } | ||
| 40 | return count; | ||
| 31 | } | 41 | } |
| 32 | 42 | ||
| 33 | VKDescriptorPool::VKDescriptorPool(const Device& device_, VKScheduler& scheduler) | 43 | static DescriptorBankInfo MakeBankInfo(std::span<const Shader::Info> infos) { |
| 34 | : device{device_}, master_semaphore{scheduler.GetMasterSemaphore()}, active_pool{ | 44 | DescriptorBankInfo bank; |
| 35 | AllocateNewPool()} {} | 45 | for (const Shader::Info& info : infos) { |
| 36 | 46 | bank.uniform_buffers += Accumulate(info.constant_buffer_descriptors); | |
| 37 | VKDescriptorPool::~VKDescriptorPool() = default; | 47 | bank.storage_buffers += Accumulate(info.storage_buffers_descriptors); |
| 38 | 48 | bank.texture_buffers += Accumulate(info.texture_buffer_descriptors); | |
| 39 | vk::DescriptorPool* VKDescriptorPool::AllocateNewPool() { | 49 | bank.image_buffers += Accumulate(info.image_buffer_descriptors); |
| 40 | static constexpr u32 num_sets = 0x20000; | 50 | bank.textures += Accumulate(info.texture_descriptors); |
| 41 | static constexpr VkDescriptorPoolSize pool_sizes[] = { | 51 | bank.images += Accumulate(info.image_descriptors); |
| 42 | {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, num_sets * 90}, | 52 | } |
| 43 | {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, num_sets * 60}, | 53 | bank.score = bank.uniform_buffers + bank.storage_buffers + bank.texture_buffers + |
| 44 | {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, num_sets * 64}, | 54 | bank.image_buffers + bank.textures + bank.images; |
| 45 | {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, num_sets * 64}, | 55 | return bank; |
| 46 | {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, num_sets * 64}, | 56 | } |
| 47 | {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, num_sets * 40}, | ||
| 48 | }; | ||
| 49 | 57 | ||
| 50 | const VkDescriptorPoolCreateInfo ci{ | 58 | static void AllocatePool(const Device& device, DescriptorBank& bank) { |
| 59 | std::array<VkDescriptorPoolSize, 6> pool_sizes; | ||
| 60 | size_t pool_cursor{}; | ||
| 61 | const auto add = [&](VkDescriptorType type, u32 count) { | ||
| 62 | if (count > 0) { | ||
| 63 | pool_sizes[pool_cursor++] = { | ||
| 64 | .type = type, | ||
| 65 | .descriptorCount = count * SETS_PER_POOL, | ||
| 66 | }; | ||
| 67 | } | ||
| 68 | }; | ||
| 69 | const auto& info{bank.info}; | ||
| 70 | add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, info.uniform_buffers); | ||
| 71 | add(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, info.storage_buffers); | ||
| 72 | add(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, info.texture_buffers); | ||
| 73 | add(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, info.image_buffers); | ||
| 74 | add(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, info.textures); | ||
| 75 | add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, info.images); | ||
| 76 | bank.pools.push_back(device.GetLogical().CreateDescriptorPool({ | ||
| 51 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, | 77 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, |
| 52 | .pNext = nullptr, | 78 | .pNext = nullptr, |
| 53 | .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, | 79 | .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, |
| 54 | .maxSets = num_sets, | 80 | .maxSets = SETS_PER_POOL, |
| 55 | .poolSizeCount = static_cast<u32>(std::size(pool_sizes)), | 81 | .poolSizeCount = static_cast<u32>(pool_cursor), |
| 56 | .pPoolSizes = std::data(pool_sizes), | 82 | .pPoolSizes = std::data(pool_sizes), |
| 57 | }; | 83 | })); |
| 58 | return &pools.emplace_back(device.GetLogical().CreateDescriptorPool(ci)); | ||
| 59 | } | 84 | } |
| 60 | 85 | ||
| 61 | vk::DescriptorSets VKDescriptorPool::AllocateDescriptors(VkDescriptorSetLayout layout, | 86 | DescriptorAllocator::DescriptorAllocator(const Device& device_, MasterSemaphore& master_semaphore_, |
| 62 | std::size_t count) { | 87 | DescriptorBank& bank_, VkDescriptorSetLayout layout_) |
| 63 | const std::vector layout_copies(count, layout); | 88 | : ResourcePool(master_semaphore_, SETS_GROW_RATE), device{&device_}, bank{&bank_}, |
| 64 | VkDescriptorSetAllocateInfo ai{ | 89 | layout{layout_} {} |
| 90 | |||
| 91 | VkDescriptorSet DescriptorAllocator::Commit() { | ||
| 92 | const size_t index = CommitResource(); | ||
| 93 | return sets[index / SETS_GROW_RATE][index % SETS_GROW_RATE]; | ||
| 94 | } | ||
| 95 | |||
| 96 | void DescriptorAllocator::Allocate(size_t begin, size_t end) { | ||
| 97 | sets.push_back(AllocateDescriptors(end - begin)); | ||
| 98 | } | ||
| 99 | |||
| 100 | vk::DescriptorSets DescriptorAllocator::AllocateDescriptors(size_t count) { | ||
| 101 | const std::vector<VkDescriptorSetLayout> layouts(count, layout); | ||
| 102 | VkDescriptorSetAllocateInfo allocate_info{ | ||
| 65 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, | 103 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, |
| 66 | .pNext = nullptr, | 104 | .pNext = nullptr, |
| 67 | .descriptorPool = **active_pool, | 105 | .descriptorPool = *bank->pools.back(), |
| 68 | .descriptorSetCount = static_cast<u32>(count), | 106 | .descriptorSetCount = static_cast<u32>(count), |
| 69 | .pSetLayouts = layout_copies.data(), | 107 | .pSetLayouts = layouts.data(), |
| 70 | }; | 108 | }; |
| 71 | 109 | vk::DescriptorSets new_sets = bank->pools.back().Allocate(allocate_info); | |
| 72 | vk::DescriptorSets sets = active_pool->Allocate(ai); | 110 | if (!new_sets.IsOutOfPoolMemory()) { |
| 73 | if (!sets.IsOutOfPoolMemory()) { | 111 | return new_sets; |
| 74 | return sets; | ||
| 75 | } | 112 | } |
| 76 | |||
| 77 | // Our current pool is out of memory. Allocate a new one and retry | 113 | // Our current pool is out of memory. Allocate a new one and retry |
| 78 | active_pool = AllocateNewPool(); | 114 | AllocatePool(*device, *bank); |
| 79 | ai.descriptorPool = **active_pool; | 115 | allocate_info.descriptorPool = *bank->pools.back(); |
| 80 | sets = active_pool->Allocate(ai); | 116 | new_sets = bank->pools.back().Allocate(allocate_info); |
| 81 | if (!sets.IsOutOfPoolMemory()) { | 117 | if (!new_sets.IsOutOfPoolMemory()) { |
| 82 | return sets; | 118 | return new_sets; |
| 83 | } | 119 | } |
| 84 | |||
| 85 | // After allocating a new pool, we are out of memory again. We can't handle this from here. | 120 | // After allocating a new pool, we are out of memory again. We can't handle this from here. |
| 86 | throw vk::Exception(VK_ERROR_OUT_OF_POOL_MEMORY); | 121 | throw vk::Exception(VK_ERROR_OUT_OF_POOL_MEMORY); |
| 87 | } | 122 | } |
| 88 | 123 | ||
| 124 | DescriptorPool::DescriptorPool(const Device& device_, VKScheduler& scheduler) | ||
| 125 | : device{device_}, master_semaphore{scheduler.GetMasterSemaphore()} {} | ||
| 126 | |||
| 127 | DescriptorPool::~DescriptorPool() = default; | ||
| 128 | |||
| 129 | DescriptorAllocator DescriptorPool::Allocator(VkDescriptorSetLayout layout, | ||
| 130 | std::span<const Shader::Info> infos) { | ||
| 131 | return Allocator(layout, MakeBankInfo(infos)); | ||
| 132 | } | ||
| 133 | |||
| 134 | DescriptorAllocator DescriptorPool::Allocator(VkDescriptorSetLayout layout, | ||
| 135 | const Shader::Info& info) { | ||
| 136 | return Allocator(layout, MakeBankInfo(std::array{info})); | ||
| 137 | } | ||
| 138 | |||
| 139 | DescriptorAllocator DescriptorPool::Allocator(VkDescriptorSetLayout layout, | ||
| 140 | const DescriptorBankInfo& info) { | ||
| 141 | return DescriptorAllocator(device, master_semaphore, Bank(info), layout); | ||
| 142 | } | ||
| 143 | |||
| 144 | DescriptorBank& DescriptorPool::Bank(const DescriptorBankInfo& reqs) { | ||
| 145 | std::shared_lock read_lock{banks_mutex}; | ||
| 146 | const auto it = std::ranges::find_if(bank_infos, [&reqs](const DescriptorBankInfo& bank) { | ||
| 147 | return std::abs(bank.score - reqs.score) < SCORE_THRESHOLD && bank.IsSuperset(reqs); | ||
| 148 | }); | ||
| 149 | if (it != bank_infos.end()) { | ||
| 150 | return *banks[std::distance(bank_infos.begin(), it)].get(); | ||
| 151 | } | ||
| 152 | read_lock.unlock(); | ||
| 153 | |||
| 154 | std::unique_lock write_lock{banks_mutex}; | ||
| 155 | bank_infos.push_back(reqs); | ||
| 156 | |||
| 157 | auto& bank = *banks.emplace_back(std::make_unique<DescriptorBank>()); | ||
| 158 | bank.info = reqs; | ||
| 159 | AllocatePool(device, bank); | ||
| 160 | return bank; | ||
| 161 | } | ||
| 162 | |||
| 89 | } // namespace Vulkan | 163 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_descriptor_pool.h b/src/video_core/renderer_vulkan/vk_descriptor_pool.h index 2501f9967..59466aac5 100644 --- a/src/video_core/renderer_vulkan/vk_descriptor_pool.h +++ b/src/video_core/renderer_vulkan/vk_descriptor_pool.h | |||
| @@ -4,21 +4,38 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <shared_mutex> | ||
| 8 | #include <span> | ||
| 7 | #include <vector> | 9 | #include <vector> |
| 8 | 10 | ||
| 11 | #include "shader_recompiler/shader_info.h" | ||
| 9 | #include "video_core/renderer_vulkan/vk_resource_pool.h" | 12 | #include "video_core/renderer_vulkan/vk_resource_pool.h" |
| 10 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 13 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 11 | 14 | ||
| 12 | namespace Vulkan { | 15 | namespace Vulkan { |
| 13 | 16 | ||
| 14 | class Device; | 17 | class Device; |
| 15 | class VKDescriptorPool; | ||
| 16 | class VKScheduler; | 18 | class VKScheduler; |
| 17 | 19 | ||
| 20 | struct DescriptorBank; | ||
| 21 | |||
| 22 | struct DescriptorBankInfo { | ||
| 23 | [[nodiscard]] bool IsSuperset(const DescriptorBankInfo& subset) const noexcept; | ||
| 24 | |||
| 25 | u32 uniform_buffers{}; ///< Number of uniform buffer descriptors | ||
| 26 | u32 storage_buffers{}; ///< Number of storage buffer descriptors | ||
| 27 | u32 texture_buffers{}; ///< Number of texture buffer descriptors | ||
| 28 | u32 image_buffers{}; ///< Number of image buffer descriptors | ||
| 29 | u32 textures{}; ///< Number of texture descriptors | ||
| 30 | u32 images{}; ///< Number of image descriptors | ||
| 31 | s32 score{}; ///< Number of descriptors in total | ||
| 32 | }; | ||
| 33 | |||
| 18 | class DescriptorAllocator final : public ResourcePool { | 34 | class DescriptorAllocator final : public ResourcePool { |
| 35 | friend class DescriptorPool; | ||
| 36 | |||
| 19 | public: | 37 | public: |
| 20 | explicit DescriptorAllocator() = default; | 38 | explicit DescriptorAllocator() = default; |
| 21 | explicit DescriptorAllocator(VKDescriptorPool& descriptor_pool, VkDescriptorSetLayout layout); | ||
| 22 | ~DescriptorAllocator() override = default; | 39 | ~DescriptorAllocator() override = default; |
| 23 | 40 | ||
| 24 | DescriptorAllocator& operator=(DescriptorAllocator&&) noexcept = default; | 41 | DescriptorAllocator& operator=(DescriptorAllocator&&) noexcept = default; |
| @@ -29,36 +46,43 @@ public: | |||
| 29 | 46 | ||
| 30 | VkDescriptorSet Commit(); | 47 | VkDescriptorSet Commit(); |
| 31 | 48 | ||
| 32 | protected: | ||
| 33 | void Allocate(std::size_t begin, std::size_t end) override; | ||
| 34 | |||
| 35 | private: | 49 | private: |
| 36 | VKDescriptorPool* descriptor_pool{}; | 50 | explicit DescriptorAllocator(const Device& device_, MasterSemaphore& master_semaphore_, |
| 51 | DescriptorBank& bank_, VkDescriptorSetLayout layout_); | ||
| 52 | |||
| 53 | void Allocate(size_t begin, size_t end) override; | ||
| 54 | |||
| 55 | vk::DescriptorSets AllocateDescriptors(size_t count); | ||
| 56 | |||
| 57 | const Device* device{}; | ||
| 58 | DescriptorBank* bank{}; | ||
| 37 | VkDescriptorSetLayout layout{}; | 59 | VkDescriptorSetLayout layout{}; |
| 38 | 60 | ||
| 39 | std::vector<vk::DescriptorSets> descriptors_allocations; | 61 | std::vector<vk::DescriptorSets> sets; |
| 40 | }; | 62 | }; |
| 41 | 63 | ||
| 42 | class VKDescriptorPool final { | 64 | class DescriptorPool { |
| 43 | friend DescriptorAllocator; | ||
| 44 | |||
| 45 | public: | 65 | public: |
| 46 | explicit VKDescriptorPool(const Device& device, VKScheduler& scheduler); | 66 | explicit DescriptorPool(const Device& device, VKScheduler& scheduler); |
| 47 | ~VKDescriptorPool(); | 67 | ~DescriptorPool(); |
| 48 | 68 | ||
| 49 | VKDescriptorPool(const VKDescriptorPool&) = delete; | 69 | DescriptorPool& operator=(const DescriptorPool&) = delete; |
| 50 | VKDescriptorPool& operator=(const VKDescriptorPool&) = delete; | 70 | DescriptorPool(const DescriptorPool&) = delete; |
| 51 | 71 | ||
| 52 | private: | 72 | DescriptorAllocator Allocator(VkDescriptorSetLayout layout, |
| 53 | vk::DescriptorPool* AllocateNewPool(); | 73 | std::span<const Shader::Info> infos); |
| 74 | DescriptorAllocator Allocator(VkDescriptorSetLayout layout, const Shader::Info& info); | ||
| 75 | DescriptorAllocator Allocator(VkDescriptorSetLayout layout, const DescriptorBankInfo& info); | ||
| 54 | 76 | ||
| 55 | vk::DescriptorSets AllocateDescriptors(VkDescriptorSetLayout layout, std::size_t count); | 77 | private: |
| 78 | DescriptorBank& Bank(const DescriptorBankInfo& reqs); | ||
| 56 | 79 | ||
| 57 | const Device& device; | 80 | const Device& device; |
| 58 | MasterSemaphore& master_semaphore; | 81 | MasterSemaphore& master_semaphore; |
| 59 | 82 | ||
| 60 | std::vector<vk::DescriptorPool> pools; | 83 | std::shared_mutex banks_mutex; |
| 61 | vk::DescriptorPool* active_pool; | 84 | std::vector<DescriptorBankInfo> bank_infos; |
| 85 | std::vector<std::unique_ptr<DescriptorBank>> banks; | ||
| 62 | }; | 86 | }; |
| 63 | 87 | ||
| 64 | } // namespace Vulkan \ No newline at end of file | 88 | } // namespace Vulkan \ No newline at end of file |
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 674226cb7..0526c197a 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | |||
| @@ -205,7 +205,7 @@ ConfigureFuncPtr ConfigureFunc(const std::array<vk::ShaderModule, NUM_STAGES>& m | |||
| 205 | GraphicsPipeline::GraphicsPipeline(Tegra::Engines::Maxwell3D& maxwell3d_, | 205 | GraphicsPipeline::GraphicsPipeline(Tegra::Engines::Maxwell3D& maxwell3d_, |
| 206 | Tegra::MemoryManager& gpu_memory_, VKScheduler& scheduler_, | 206 | Tegra::MemoryManager& gpu_memory_, VKScheduler& scheduler_, |
| 207 | BufferCache& buffer_cache_, TextureCache& texture_cache_, | 207 | BufferCache& buffer_cache_, TextureCache& texture_cache_, |
| 208 | const Device& device, VKDescriptorPool& descriptor_pool, | 208 | const Device& device, DescriptorPool& descriptor_pool, |
| 209 | VKUpdateDescriptorQueue& update_descriptor_queue_, | 209 | VKUpdateDescriptorQueue& update_descriptor_queue_, |
| 210 | Common::ThreadWorker* worker_thread, | 210 | Common::ThreadWorker* worker_thread, |
| 211 | RenderPassCache& render_pass_cache, | 211 | RenderPassCache& render_pass_cache, |
| @@ -220,7 +220,7 @@ GraphicsPipeline::GraphicsPipeline(Tegra::Engines::Maxwell3D& maxwell3d_, | |||
| 220 | 220 | ||
| 221 | DescriptorLayoutBuilder builder{MakeBuilder(device, stage_infos)}; | 221 | DescriptorLayoutBuilder builder{MakeBuilder(device, stage_infos)}; |
| 222 | descriptor_set_layout = builder.CreateDescriptorSetLayout(); | 222 | descriptor_set_layout = builder.CreateDescriptorSetLayout(); |
| 223 | descriptor_allocator = DescriptorAllocator(descriptor_pool, *descriptor_set_layout); | 223 | descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, stage_infos); |
| 224 | 224 | ||
| 225 | auto func{[this, &device, &render_pass_cache, builder] { | 225 | auto func{[this, &device, &render_pass_cache, builder] { |
| 226 | const VkDescriptorSetLayout set_layout{*descriptor_set_layout}; | 226 | const VkDescriptorSetLayout set_layout{*descriptor_set_layout}; |
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index edab5703f..454fc049e 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h | |||
| @@ -67,7 +67,7 @@ public: | |||
| 67 | explicit GraphicsPipeline(Tegra::Engines::Maxwell3D& maxwell3d, | 67 | explicit GraphicsPipeline(Tegra::Engines::Maxwell3D& maxwell3d, |
| 68 | Tegra::MemoryManager& gpu_memory, VKScheduler& scheduler, | 68 | Tegra::MemoryManager& gpu_memory, VKScheduler& scheduler, |
| 69 | BufferCache& buffer_cache, TextureCache& texture_cache, | 69 | BufferCache& buffer_cache, TextureCache& texture_cache, |
| 70 | const Device& device, VKDescriptorPool& descriptor_pool, | 70 | const Device& device, DescriptorPool& descriptor_pool, |
| 71 | VKUpdateDescriptorQueue& update_descriptor_queue, | 71 | VKUpdateDescriptorQueue& update_descriptor_queue, |
| 72 | Common::ThreadWorker* worker_thread, | 72 | Common::ThreadWorker* worker_thread, |
| 73 | RenderPassCache& render_pass_cache, | 73 | RenderPassCache& render_pass_cache, |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 2bd870060..9d9729022 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -647,7 +647,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::GPU& gpu_, | |||
| 647 | Tegra::Engines::Maxwell3D& maxwell3d_, | 647 | Tegra::Engines::Maxwell3D& maxwell3d_, |
| 648 | Tegra::Engines::KeplerCompute& kepler_compute_, | 648 | Tegra::Engines::KeplerCompute& kepler_compute_, |
| 649 | Tegra::MemoryManager& gpu_memory_, const Device& device_, | 649 | Tegra::MemoryManager& gpu_memory_, const Device& device_, |
| 650 | VKScheduler& scheduler_, VKDescriptorPool& descriptor_pool_, | 650 | VKScheduler& scheduler_, DescriptorPool& descriptor_pool_, |
| 651 | VKUpdateDescriptorQueue& update_descriptor_queue_, | 651 | VKUpdateDescriptorQueue& update_descriptor_queue_, |
| 652 | RenderPassCache& render_pass_cache_, BufferCache& buffer_cache_, | 652 | RenderPassCache& render_pass_cache_, BufferCache& buffer_cache_, |
| 653 | TextureCache& texture_cache_) | 653 | TextureCache& texture_cache_) |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index ad569acc4..eec17d3fd 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h | |||
| @@ -75,10 +75,10 @@ namespace Vulkan { | |||
| 75 | 75 | ||
| 76 | class ComputePipeline; | 76 | class ComputePipeline; |
| 77 | class Device; | 77 | class Device; |
| 78 | class DescriptorPool; | ||
| 78 | class GenericEnvironment; | 79 | class GenericEnvironment; |
| 79 | class RasterizerVulkan; | 80 | class RasterizerVulkan; |
| 80 | class RenderPassCache; | 81 | class RenderPassCache; |
| 81 | class VKDescriptorPool; | ||
| 82 | class VKScheduler; | 82 | class VKScheduler; |
| 83 | class VKUpdateDescriptorQueue; | 83 | class VKUpdateDescriptorQueue; |
| 84 | 84 | ||
| @@ -105,7 +105,7 @@ public: | |||
| 105 | Tegra::Engines::Maxwell3D& maxwell3d, | 105 | Tegra::Engines::Maxwell3D& maxwell3d, |
| 106 | Tegra::Engines::KeplerCompute& kepler_compute, | 106 | Tegra::Engines::KeplerCompute& kepler_compute, |
| 107 | Tegra::MemoryManager& gpu_memory, const Device& device, | 107 | Tegra::MemoryManager& gpu_memory, const Device& device, |
| 108 | VKScheduler& scheduler, VKDescriptorPool& descriptor_pool, | 108 | VKScheduler& scheduler, DescriptorPool& descriptor_pool, |
| 109 | VKUpdateDescriptorQueue& update_descriptor_queue, | 109 | VKUpdateDescriptorQueue& update_descriptor_queue, |
| 110 | RenderPassCache& render_pass_cache, BufferCache& buffer_cache, | 110 | RenderPassCache& render_pass_cache, BufferCache& buffer_cache, |
| 111 | TextureCache& texture_cache); | 111 | TextureCache& texture_cache); |
| @@ -147,7 +147,7 @@ private: | |||
| 147 | 147 | ||
| 148 | const Device& device; | 148 | const Device& device; |
| 149 | VKScheduler& scheduler; | 149 | VKScheduler& scheduler; |
| 150 | VKDescriptorPool& descriptor_pool; | 150 | DescriptorPool& descriptor_pool; |
| 151 | VKUpdateDescriptorQueue& update_descriptor_queue; | 151 | VKUpdateDescriptorQueue& update_descriptor_queue; |
| 152 | RenderPassCache& render_pass_cache; | 152 | RenderPassCache& render_pass_cache; |
| 153 | BufferCache& buffer_cache; | 153 | BufferCache& buffer_cache; |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 2f1551e65..1302bed02 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h | |||
| @@ -147,7 +147,7 @@ private: | |||
| 147 | VKScheduler& scheduler; | 147 | VKScheduler& scheduler; |
| 148 | 148 | ||
| 149 | StagingBufferPool staging_pool; | 149 | StagingBufferPool staging_pool; |
| 150 | VKDescriptorPool descriptor_pool; | 150 | DescriptorPool descriptor_pool; |
| 151 | VKUpdateDescriptorQueue update_descriptor_queue; | 151 | VKUpdateDescriptorQueue update_descriptor_queue; |
| 152 | BlitImageHelper blit_image; | 152 | BlitImageHelper blit_image; |
| 153 | ASTCDecoderPass astc_decoder_pass; | 153 | ASTCDecoderPass astc_decoder_pass; |