pipeline_helper.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // Copyright 2021 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <cstddef>
  6. #include <boost/container/small_vector.hpp>
  7. #include "common/assert.h"
  8. #include "common/common_types.h"
  9. #include "shader_recompiler/shader_info.h"
  10. #include "video_core/renderer_vulkan/vk_texture_cache.h"
  11. #include "video_core/renderer_vulkan/vk_update_descriptor.h"
  12. #include "video_core/texture_cache/texture_cache.h"
  13. #include "video_core/texture_cache/types.h"
  14. #include "video_core/textures/texture.h"
  15. namespace Vulkan {
  16. class DescriptorLayoutBuilder {
  17. public:
  18. DescriptorLayoutBuilder(const vk::Device& device_) : device{&device_} {}
  19. vk::DescriptorSetLayout CreateDescriptorSetLayout() const {
  20. if (bindings.empty()) {
  21. return nullptr;
  22. }
  23. return device->CreateDescriptorSetLayout({
  24. .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
  25. .pNext = nullptr,
  26. .flags = 0,
  27. .bindingCount = static_cast<u32>(bindings.size()),
  28. .pBindings = bindings.data(),
  29. });
  30. }
  31. vk::DescriptorUpdateTemplateKHR CreateTemplate(VkDescriptorSetLayout descriptor_set_layout,
  32. VkPipelineLayout pipeline_layout) const {
  33. if (entries.empty()) {
  34. return nullptr;
  35. }
  36. return device->CreateDescriptorUpdateTemplateKHR({
  37. .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
  38. .pNext = nullptr,
  39. .flags = 0,
  40. .descriptorUpdateEntryCount = static_cast<u32>(entries.size()),
  41. .pDescriptorUpdateEntries = entries.data(),
  42. .templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR,
  43. .descriptorSetLayout = descriptor_set_layout,
  44. .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
  45. .pipelineLayout = pipeline_layout,
  46. .set = 0,
  47. });
  48. }
  49. vk::PipelineLayout CreatePipelineLayout(VkDescriptorSetLayout descriptor_set_layout) const {
  50. return device->CreatePipelineLayout({
  51. .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
  52. .pNext = nullptr,
  53. .flags = 0,
  54. .setLayoutCount = descriptor_set_layout ? 1U : 0U,
  55. .pSetLayouts = bindings.empty() ? nullptr : &descriptor_set_layout,
  56. .pushConstantRangeCount = 0,
  57. .pPushConstantRanges = nullptr,
  58. });
  59. }
  60. void Add(const Shader::Info& info, VkShaderStageFlags stage) {
  61. Add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, stage, info.constant_buffer_descriptors);
  62. Add(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, stage, info.storage_buffers_descriptors);
  63. Add(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, stage, info.texture_buffer_descriptors);
  64. Add(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, stage, info.image_buffer_descriptors);
  65. Add(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, stage, info.texture_descriptors);
  66. Add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, stage, info.image_descriptors);
  67. }
  68. private:
  69. template <typename Descriptors>
  70. void Add(VkDescriptorType type, VkShaderStageFlags stage, const Descriptors& descriptors) {
  71. const size_t num{descriptors.size()};
  72. for (size_t i = 0; i < num; ++i) {
  73. bindings.push_back({
  74. .binding = binding,
  75. .descriptorType = type,
  76. .descriptorCount = descriptors[i].count,
  77. .stageFlags = stage,
  78. .pImmutableSamplers = nullptr,
  79. });
  80. entries.push_back({
  81. .dstBinding = binding,
  82. .dstArrayElement = 0,
  83. .descriptorCount = descriptors[i].count,
  84. .descriptorType = type,
  85. .offset = offset,
  86. .stride = sizeof(DescriptorUpdateEntry),
  87. });
  88. ++binding;
  89. offset += sizeof(DescriptorUpdateEntry);
  90. }
  91. }
  92. const vk::Device* device{};
  93. boost::container::small_vector<VkDescriptorSetLayoutBinding, 32> bindings;
  94. boost::container::small_vector<VkDescriptorUpdateTemplateEntryKHR, 32> entries;
  95. u32 binding{};
  96. size_t offset{};
  97. };
  98. inline void PushImageDescriptors(const Shader::Info& info, const VkSampler*& samplers,
  99. const ImageId*& image_view_ids, TextureCache& texture_cache,
  100. VKUpdateDescriptorQueue& update_descriptor_queue) {
  101. for (const auto& desc : info.texture_buffer_descriptors) {
  102. image_view_ids += desc.count;
  103. }
  104. for (const auto& desc : info.image_buffer_descriptors) {
  105. image_view_ids += desc.count;
  106. }
  107. for (const auto& desc : info.texture_descriptors) {
  108. for (u32 index = 0; index < desc.count; ++index) {
  109. const VkSampler sampler{*(samplers++)};
  110. ImageView& image_view{texture_cache.GetImageView(*(image_view_ids++))};
  111. const VkImageView vk_image_view{image_view.Handle(desc.type)};
  112. update_descriptor_queue.AddSampledImage(vk_image_view, sampler);
  113. }
  114. }
  115. for (const auto& desc : info.image_descriptors) {
  116. for (u32 index = 0; index < desc.count; ++index) {
  117. ImageView& image_view{texture_cache.GetImageView(*(image_view_ids++))};
  118. if (desc.is_written) {
  119. texture_cache.MarkModification(image_view.image_id);
  120. }
  121. const VkImageView vk_image_view{image_view.StorageView(desc.type, desc.format)};
  122. update_descriptor_queue.AddImage(vk_image_view);
  123. }
  124. }
  125. }
  126. } // namespace Vulkan