• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "node_context_descriptor_set_manager_vk.h"
16 
17 #include <algorithm>
18 #include <cstdint>
19 #include <vulkan/vulkan.h>
20 
21 #include <base/math/mathf.h>
22 #include <render/device/pipeline_state_desc.h>
23 #include <render/namespace.h>
24 
25 #include "device/device.h"
26 #include "device/gpu_resource_handle_util.h"
27 #include "device/gpu_resource_manager.h"
28 #include "nodecontext/node_context_descriptor_set_manager.h"
29 #include "util/log.h"
30 #include "vulkan/device_vk.h"
31 #include "vulkan/gpu_image_vk.h"
32 #include "vulkan/validate_vk.h"
33 
34 using namespace BASE_NS;
35 
RENDER_BEGIN_NAMESPACE()36 RENDER_BEGIN_NAMESPACE()
37 NodeContextDescriptorSetManagerVk::NodeContextDescriptorSetManagerVk(Device& device)
38     : NodeContextDescriptorSetManager(), device_ { device },
39       bufferingCount_(
40           Math::min(LowLevelContextDescriptorPoolVk::MAX_BUFFERING_COUNT, device_.GetCommandBufferingCount()))
41 {
42 #if (RENDER_VALIDATION_ENABLED == 1)
43     if (device_.GetCommandBufferingCount() > LowLevelContextDescriptorPoolVk::MAX_BUFFERING_COUNT) {
44         PLUGIN_LOG_ONCE_W("device_command_buffering_count_desc_set_vk_buffering",
45             "RENDER_VALIDATION: device command buffering count (%u) is larger than supported vulkan descriptor set "
46             "buffering count (%u)",
47             device_.GetCommandBufferingCount(), LowLevelContextDescriptorPoolVk::MAX_BUFFERING_COUNT);
48     }
49 #endif
50 }
51 
~NodeContextDescriptorSetManagerVk()52 NodeContextDescriptorSetManagerVk::~NodeContextDescriptorSetManagerVk()
53 {
54     DestroyPool(descriptorPool_[DESCRIPTOR_SET_INDEX_TYPE_STATIC]);
55     DestroyPool(descriptorPool_[DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME]);
56     for (auto& ref : pendingDeallocations_) {
57         DestroyPool(ref.descriptorPool);
58     }
59 }
60 
DestroyPool(LowLevelContextDescriptorPoolVk & descriptorPool)61 void NodeContextDescriptorSetManagerVk::DestroyPool(LowLevelContextDescriptorPoolVk& descriptorPool)
62 {
63     const VkDevice device = ((const DevicePlatformDataVk&)device_.GetPlatformData()).device;
64 
65     for (auto& ref : descriptorPool.descriptorSets) {
66         for (uint32_t bufferingIdx = 0; bufferingIdx < bufferingCount_; ++bufferingIdx) {
67             auto& bufferingSetRef = ref.bufferingSet[bufferingIdx];
68             if (bufferingSetRef.descriptorSetLayout) {
69                 vkDestroyDescriptorSetLayout(device,     // device
70                     bufferingSetRef.descriptorSetLayout, // descriptorSetLayout
71                     nullptr);                            // pAllocator
72                 bufferingSetRef.descriptorSetLayout = VK_NULL_HANDLE;
73             }
74         }
75         if (ref.additionalPlatformSet.descriptorSetLayout) {
76             vkDestroyDescriptorSetLayout(device,               // device
77                 ref.additionalPlatformSet.descriptorSetLayout, // descriptorSetLayout
78                 nullptr);                                      // pAllocator
79             ref.additionalPlatformSet.descriptorSetLayout = VK_NULL_HANDLE;
80         }
81     }
82     descriptorPool.descriptorSets.clear();
83     if (descriptorPool.descriptorPool) {
84         vkDestroyDescriptorPool(device,    // device
85             descriptorPool.descriptorPool, // descriptorPool
86             nullptr);                      // pAllocator
87         descriptorPool.descriptorPool = VK_NULL_HANDLE;
88     }
89     if (descriptorPool.additionalPlatformDescriptorPool) {
90         vkDestroyDescriptorPool(device,                      // device
91             descriptorPool.additionalPlatformDescriptorPool, // descriptorPool
92             nullptr);                                        // pAllocator
93         descriptorPool.additionalPlatformDescriptorPool = VK_NULL_HANDLE;
94     }
95 }
96 
ResetAndReserve(const DescriptorCounts & descriptorCounts)97 void NodeContextDescriptorSetManagerVk::ResetAndReserve(const DescriptorCounts& descriptorCounts)
98 {
99     NodeContextDescriptorSetManager::ResetAndReserve(descriptorCounts);
100     if (maxSets_ > 0) {
101         auto& descriptorPool = descriptorPool_[DESCRIPTOR_SET_INDEX_TYPE_STATIC];
102         // usually there are less descriptor sets than max sets count
103         // due to maxsets count has been calculated for single descriptors
104         // (one descriptor set has multiple descriptors)
105         const uint32_t reserveCount = maxSets_ / 2u; // questimate for possible max vector size;
106 
107         constexpr VkDescriptorPoolCreateFlags descriptorPoolCreateFlags { 0 };
108         if (descriptorPool.descriptorPool) { // push for dealloation vec
109             PendingDeallocations pd;
110             pd.descriptorPool.descriptorPool = move(descriptorPool.descriptorPool);
111             pd.descriptorPool.descriptorSets = move(descriptorPool.descriptorSets);
112             pd.frameIndex = device_.GetFrameCount();
113             pendingDeallocations_.emplace_back(move(pd));
114 
115             descriptorPool.descriptorSets.clear();
116             descriptorPool.descriptorPool = VK_NULL_HANDLE;
117         }
118 
119         descriptorPoolSizes_.clear();
120         descriptorPoolSizes_.reserve(descriptorCounts.counts.size()); // max count reserve
121         for (const auto& ref : descriptorCounts.counts) {
122             if (ref.count > 0) {
123                 descriptorPoolSizes_.emplace_back(
124                     VkDescriptorPoolSize { (VkDescriptorType)ref.type, ref.count * bufferingCount_ });
125             }
126         }
127 
128         if (!descriptorPoolSizes_.empty()) {
129             const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo {
130                 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // sType
131                 nullptr,                                       // pNext
132                 descriptorPoolCreateFlags,                     // flags
133                 maxSets_ * bufferingCount_,                    // maxSets
134                 (uint32_t)descriptorPoolSizes_.size(),         // poolSizeCount
135                 descriptorPoolSizes_.data(),                   // pPoolSizes
136             };
137 
138             const VkDevice device = ((const DevicePlatformDataVk&)device_.GetPlatformData()).device;
139             VALIDATE_VK_RESULT(vkCreateDescriptorPool(device, // device
140                 &descriptorPoolCreateInfo,                    // pCreateInfo
141                 nullptr,                                      // pAllocator
142                 &descriptorPool.descriptorPool));             // pDescriptorPool
143 
144             descriptorPool.descriptorSets.reserve(reserveCount);
145         }
146     }
147 }
148 
BeginFrame()149 void NodeContextDescriptorSetManagerVk::BeginFrame()
150 {
151     NodeContextDescriptorSetManager::BeginFrame();
152 
153     oneFrameDescriptorNeed_ = {};
154     auto& oneFrameDescriptorPool = descriptorPool_[DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME];
155     if (oneFrameDescriptorPool.descriptorPool) {
156         const uint32_t descriptorSetCount = static_cast<uint32_t>(oneFrameDescriptorPool.descriptorSets.size());
157         PendingDeallocations pd;
158         pd.descriptorPool.descriptorPool = move(oneFrameDescriptorPool.descriptorPool);
159         pd.descriptorPool.descriptorSets = move(oneFrameDescriptorPool.descriptorSets);
160         pd.frameIndex = device_.GetFrameCount();
161         pendingDeallocations_.emplace_back(move(pd));
162 
163         oneFrameDescriptorPool.descriptorSets.reserve(descriptorSetCount);
164         oneFrameDescriptorPool.descriptorPool = VK_NULL_HANDLE;
165     }
166     oneFrameDescriptorPool.descriptorSets.clear();
167 
168     // we need to check through platform special format desriptor sets/pool
169     auto& descriptorPool = descriptorPool_[DESCRIPTOR_SET_INDEX_TYPE_STATIC];
170     if (descriptorPool.additionalPlatformDescriptorPool) {
171         PendingDeallocations pd;
172         pd.descriptorPool.additionalPlatformDescriptorPool = move(descriptorPool.additionalPlatformDescriptorPool);
173         // no buffering set
174         pd.frameIndex = device_.GetFrameCount();
175         pendingDeallocations_.emplace_back(move(pd));
176         descriptorPool.additionalPlatformDescriptorPool = VK_NULL_HANDLE;
177         // immediate desctruction of descriptor set layouts
178         const VkDevice device = ((const DevicePlatformDataVk&)device_.GetPlatformData()).device;
179         for (auto& descriptorSetRef : descriptorPool.descriptorSets) {
180             if (descriptorSetRef.additionalPlatformSet.descriptorSetLayout) {
181                 vkDestroyDescriptorSetLayout(device,                            // device
182                     descriptorSetRef.additionalPlatformSet.descriptorSetLayout, // descriptorSetLayout
183                     nullptr);                                                   // pAllocator
184                 descriptorSetRef.additionalPlatformSet.descriptorSetLayout = VK_NULL_HANDLE;
185             }
186         }
187         auto& cpuDescriptorSet = cpuDescriptorSets_[DESCRIPTOR_SET_INDEX_TYPE_STATIC];
188         for (auto& descriptorSetRef : cpuDescriptorSet) {
189             descriptorSetRef.hasPlatformConversionBindings = false;
190         }
191     }
192 
193     // clear aged descriptor pools
194     if (!pendingDeallocations_.empty()) {
195         // this is normally empty or only has single item
196         const auto minAge = device_.GetCommandBufferingCount() + 1;
197         const auto ageLimit = (device_.GetFrameCount() < minAge) ? 0 : (device_.GetFrameCount() - minAge);
198 
199         auto oldRes = std::partition(pendingDeallocations_.begin(), pendingDeallocations_.end(),
200             [ageLimit](auto const& pd) { return pd.frameIndex >= ageLimit; });
201 
202         std::for_each(oldRes, pendingDeallocations_.end(), [this](auto& res) { DestroyPool(res.descriptorPool); });
203         pendingDeallocations_.erase(oldRes, pendingDeallocations_.end());
204     }
205 
206 #if (RENDER_VALIDATION_ENABLED == 1)
207     oneFrameDescSetGeneration_ = (oneFrameDescSetGeneration_ + 1) % MAX_ONE_FRAME_GENERATION_IDX;
208 #endif
209 }
210 
BeginBackendFrame()211 void NodeContextDescriptorSetManagerVk::BeginBackendFrame()
212 {
213     auto CreateDescriptorPool = [](const VkDevice device, const uint32_t descriptorSetCount,
214                                     VkDescriptorPool& descriptorPool,
215                                     vector<VkDescriptorPoolSize>& descriptorPoolSizes) {
216         constexpr VkDescriptorPoolCreateFlags descriptorPoolCreateFlags { 0 };
217         const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo {
218             VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // sType
219             nullptr,                                       // pNext
220             descriptorPoolCreateFlags,                     // flags
221             descriptorSetCount,                            // maxSets
222             (uint32_t)descriptorPoolSizes.size(),          // poolSizeCount
223             descriptorPoolSizes.data(),                    // pPoolSizes
224         };
225 
226         VALIDATE_VK_RESULT(vkCreateDescriptorPool(device, // device
227             &descriptorPoolCreateInfo,                    // pCreateInfo
228             nullptr,                                      // pAllocator
229             &descriptorPool));                            // pDescriptorPool
230     };
231 
232     const VkDevice device = ((const DevicePlatformDataVk&)device_.GetPlatformData()).device;
233     // reserve descriptors for descriptors sets that need platform special formats for one frame
234     if (hasPlatformConversionBindings_) {
235         const auto& cpuDescriptorSets = cpuDescriptorSets_[DESCRIPTOR_SET_INDEX_TYPE_STATIC];
236         uint32_t descriptorSetCount = 0u;
237         uint8_t descriptorCounts[OneFrameDescriptorNeed::DESCRIPTOR_ARRAY_SIZE] { 0 };
238         for (const auto& cpuDescriptorSetRef : cpuDescriptorSets) {
239             if (cpuDescriptorSetRef.hasPlatformConversionBindings) {
240                 descriptorSetCount++;
241                 for (const auto& bindingRef : cpuDescriptorSetRef.bindings) {
242                     uint32_t descriptorCount = bindingRef.binding.descriptorCount;
243                     const uint32_t descTypeIndex = static_cast<uint32_t>(bindingRef.binding.descriptorType);
244                     if (descTypeIndex < OneFrameDescriptorNeed::DESCRIPTOR_ARRAY_SIZE) {
245                         if ((bindingRef.binding.descriptorType ==
246                                 DescriptorType::CORE_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&
247                             RenderHandleUtil::IsPlatformConversionResource(
248                                 cpuDescriptorSetRef.images[bindingRef.resourceIndex].resource.handle)) {
249                             // expecting planar formats and making sure that there is enough descriptors
250                             constexpr uint32_t descriptorCountMultiplier = 3u;
251                             descriptorCount *= descriptorCountMultiplier;
252                         }
253                         descriptorCounts[descTypeIndex] += static_cast<uint8_t>(descriptorCount);
254                     }
255                 }
256             }
257         }
258         if (descriptorSetCount > 0) {
259             auto& descriptorPool = descriptorPool_[DESCRIPTOR_SET_INDEX_TYPE_STATIC];
260             PLUGIN_ASSERT(descriptorPool.additionalPlatformDescriptorPool == VK_NULL_HANDLE);
261             descriptorPoolSizes_.clear();
262             descriptorPoolSizes_.reserve(OneFrameDescriptorNeed::DESCRIPTOR_ARRAY_SIZE);
263             // no buffering, only descriptors for one frame
264             for (uint32_t idx = 0; idx < OneFrameDescriptorNeed::DESCRIPTOR_ARRAY_SIZE; ++idx) {
265                 const uint8_t count = descriptorCounts[idx];
266                 if (count > 0) {
267                     descriptorPoolSizes_.emplace_back(VkDescriptorPoolSize { (VkDescriptorType)idx, count });
268                 }
269             }
270             if (!descriptorPoolSizes_.empty()) {
271                 CreateDescriptorPool(
272                     device, descriptorSetCount, descriptorPool.additionalPlatformDescriptorPool, descriptorPoolSizes_);
273             }
274         }
275     }
276     // create one frame descriptor pool
277     {
278         auto& descriptorPool = descriptorPool_[DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME];
279         auto& cpuDescriptorSets = cpuDescriptorSets_[DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME];
280 
281         PLUGIN_ASSERT(descriptorPool.descriptorPool == VK_NULL_HANDLE);
282         const uint32_t descriptorSetCount = static_cast<uint32_t>(cpuDescriptorSets.size());
283         if (descriptorSetCount > 0) {
284             descriptorPoolSizes_.clear();
285             descriptorPoolSizes_.reserve(OneFrameDescriptorNeed::DESCRIPTOR_ARRAY_SIZE);
286             for (uint32_t idx = 0; idx < OneFrameDescriptorNeed::DESCRIPTOR_ARRAY_SIZE; ++idx) {
287                 const uint8_t count = oneFrameDescriptorNeed_.descriptorCount[idx];
288                 if (count > 0) {
289                     descriptorPoolSizes_.emplace_back(VkDescriptorPoolSize { (VkDescriptorType)idx, count });
290                 }
291             }
292 
293             if (!descriptorPoolSizes_.empty()) {
294                 CreateDescriptorPool(device, descriptorSetCount, descriptorPool.descriptorPool, descriptorPoolSizes_);
295             }
296         }
297     }
298 }
299 
CreateDescriptorSet(const array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings)300 RenderHandle NodeContextDescriptorSetManagerVk::CreateDescriptorSet(
301     const array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings)
302 {
303     RenderHandle clientHandle;
304     auto& cpuDescriptorSets = cpuDescriptorSets_[DESCRIPTOR_SET_INDEX_TYPE_STATIC];
305     auto& descriptorPool = descriptorPool_[DESCRIPTOR_SET_INDEX_TYPE_STATIC];
306     PLUGIN_ASSERT_MSG(cpuDescriptorSets.size() < maxSets_, "no more descriptor sets available");
307     if (cpuDescriptorSets.size() < maxSets_) {
308         uint32_t dynamicOffsetCount = 0;
309         CpuDescriptorSet newSet;
310         LowLevelContextDescriptorPoolVk::DescriptorSetData descSetData;
311 
312         newSet.bindings.reserve(descriptorSetLayoutBindings.size());
313         descSetData.descriptorCounts.writeDescriptorCount = static_cast<uint32_t>(descriptorSetLayoutBindings.size());
314         for (const auto& refBinding : descriptorSetLayoutBindings) {
315             // NOTE: sort from 0 to n
316             newSet.bindings.push_back({ refBinding, {} });
317             if (IsDynamicDescriptor(refBinding.descriptorType)) {
318                 dynamicOffsetCount++;
319             }
320 
321             const uint32_t descriptorCount = refBinding.descriptorCount;
322             if (refBinding.descriptorType == CORE_DESCRIPTOR_TYPE_SAMPLER) {
323                 descSetData.descriptorCounts.samplerCount += descriptorCount;
324             } else if (((refBinding.descriptorType >= CORE_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&
325                            (refBinding.descriptorType <= CORE_DESCRIPTOR_TYPE_STORAGE_IMAGE)) ||
326                        (refBinding.descriptorType == CORE_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)) {
327                 descSetData.descriptorCounts.imageCount += refBinding.descriptorCount;
328             } else if (((refBinding.descriptorType >= CORE_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) &&
329                            (refBinding.descriptorType <= CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) ||
330                        (refBinding.descriptorType == CORE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE)) {
331                 descSetData.descriptorCounts.bufferCount += refBinding.descriptorCount;
332             } else {
333                 PLUGIN_ASSERT_MSG(false, "descriptor type not found");
334             }
335         }
336         newSet.buffers.resize(descSetData.descriptorCounts.bufferCount);
337         newSet.images.resize(descSetData.descriptorCounts.imageCount);
338         newSet.samplers.resize(descSetData.descriptorCounts.samplerCount);
339 
340         const uint32_t arrayIndex = (uint32_t)cpuDescriptorSets.size();
341         cpuDescriptorSets.emplace_back(move(newSet));
342 
343         auto& currCpuDescriptorSet = cpuDescriptorSets[arrayIndex];
344         currCpuDescriptorSet.dynamicOffsetDescriptors.resize(dynamicOffsetCount);
345 
346         // allocate storage from vector to gpu descriptor sets
347         // don't create the actual gpu descriptor sets yet
348         descriptorPool.descriptorSets.emplace_back(descSetData);
349 
350         // NOTE: can be used directly to index
351         clientHandle = RenderHandleUtil::CreateHandle(RenderHandleType::DESCRIPTOR_SET, arrayIndex, 0);
352     }
353 
354     return clientHandle;
355 }
356 
CreateOneFrameDescriptorSet(const array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings)357 RenderHandle NodeContextDescriptorSetManagerVk::CreateOneFrameDescriptorSet(
358     const array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings)
359 {
360     RenderHandle clientHandle;
361     auto& cpuDescriptorSets = cpuDescriptorSets_[DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME];
362     auto& descriptorPool = descriptorPool_[DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME];
363     uint32_t dynamicOffsetCount = 0;
364     CpuDescriptorSet newSet;
365     LowLevelContextDescriptorPoolVk::DescriptorSetData descSetData;
366 
367     newSet.bindings.reserve(descriptorSetLayoutBindings.size());
368     descSetData.descriptorCounts.writeDescriptorCount = static_cast<uint32_t>(descriptorSetLayoutBindings.size());
369     for (const auto& refBinding : descriptorSetLayoutBindings) {
370         // NOTE: sort from 0 to n
371         newSet.bindings.push_back({ refBinding, {} });
372         if (IsDynamicDescriptor(refBinding.descriptorType)) {
373             dynamicOffsetCount++;
374         }
375 
376         if (refBinding.descriptorType == CORE_DESCRIPTOR_TYPE_SAMPLER) {
377             descSetData.descriptorCounts.samplerCount += refBinding.descriptorCount;
378         } else if (((refBinding.descriptorType >= CORE_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&
379                        (refBinding.descriptorType <= CORE_DESCRIPTOR_TYPE_STORAGE_IMAGE)) ||
380                    (refBinding.descriptorType == CORE_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)) {
381             descSetData.descriptorCounts.imageCount += refBinding.descriptorCount;
382         } else if (((refBinding.descriptorType >= CORE_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) &&
383                        (refBinding.descriptorType <= CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) ||
384                    (refBinding.descriptorType == CORE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE)) {
385             descSetData.descriptorCounts.bufferCount += refBinding.descriptorCount;
386         } else {
387             PLUGIN_LOG_E("descriptor type not found");
388         }
389 
390         newSet.buffers.resize(descSetData.descriptorCounts.bufferCount);
391         newSet.images.resize(descSetData.descriptorCounts.imageCount);
392         newSet.samplers.resize(descSetData.descriptorCounts.samplerCount);
393 
394         if (static_cast<uint32_t>(refBinding.descriptorType) < OneFrameDescriptorNeed::DESCRIPTOR_ARRAY_SIZE) {
395             oneFrameDescriptorNeed_.descriptorCount[refBinding.descriptorType] +=
396                 static_cast<uint8_t>(refBinding.descriptorCount);
397         }
398     }
399 
400     const uint32_t arrayIndex = static_cast<uint32_t>(cpuDescriptorSets.size());
401     cpuDescriptorSets.emplace_back(move(newSet));
402 
403     auto& currCpuDescriptorSet = cpuDescriptorSets[arrayIndex];
404     currCpuDescriptorSet.dynamicOffsetDescriptors.resize(dynamicOffsetCount);
405 
406     // allocate storage from vector to gpu descriptor sets
407     // don't create the actual gpu descriptor sets yet
408     descriptorPool.descriptorSets.emplace_back(descSetData);
409 
410     // NOTE: can be used directly to index
411     clientHandle = RenderHandleUtil::CreateHandle(
412         RenderHandleType::DESCRIPTOR_SET, arrayIndex, oneFrameDescSetGeneration_, ONE_FRAME_DESC_SET_BIT);
413 
414     return clientHandle;
415 }
416 
CreateGpuDescriptorSet(const uint32_t bufferCount,const RenderHandle clientHandle,const CpuDescriptorSet & cpuDescriptorSet,LowLevelContextDescriptorPoolVk & descriptorPool)417 void NodeContextDescriptorSetManagerVk::CreateGpuDescriptorSet(const uint32_t bufferCount,
418     const RenderHandle clientHandle, const CpuDescriptorSet& cpuDescriptorSet,
419     LowLevelContextDescriptorPoolVk& descriptorPool)
420 {
421 #if (RENDER_VALIDATION_ENABLED == 1)
422     if (cpuDescriptorSet.bindings.size() > PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT) {
423         PLUGIN_LOG_W("RENDER_VALIDATION: descriptor set binding count exceeds (max:%u, current:%u)",
424             PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT,
425             static_cast<uint32_t>(cpuDescriptorSet.bindings.size()));
426     }
427 #endif
428     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(clientHandle);
429     VkDescriptorSetLayoutBinding descriptorSetLayoutBindings[PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT];
430     const uint32_t bindingCount = Math::min(static_cast<uint32_t>(cpuDescriptorSet.bindings.size()),
431         PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT);
432     const bool hasPlatformBindings = cpuDescriptorSet.hasPlatformConversionBindings;
433     bool hasImmutableSamplers = false;
434     uint16_t immutableSamplerBitmask = 0;
435     const auto& gpuResourceMgr = static_cast<const GpuResourceManager&>(device_.GetGpuResourceManager());
436     // NOTE: if we cannot provide explicit flags that custom immutable sampler with conversion is needed
437     // we should first loop through the bindings and check
438     // normal hw buffers do not need any rebindings or immutable samplers
439     for (uint32_t idx = 0; idx < bindingCount; ++idx) {
440         const DescriptorSetLayoutBindingResource& cpuBinding = cpuDescriptorSet.bindings[idx];
441         const VkDescriptorType descriptorType = (VkDescriptorType)cpuBinding.binding.descriptorType;
442         const VkShaderStageFlags stageFlags = (VkShaderStageFlags)cpuBinding.binding.shaderStageFlags;
443         const uint32_t bindingIdx = cpuBinding.binding.binding;
444         const VkSampler* immutableSampler = nullptr;
445         if (hasPlatformBindings && (descriptorType == VkDescriptorType::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)) {
446             const RenderHandle handle = cpuDescriptorSet.images[cpuBinding.resourceIndex].resource.handle;
447             if (RenderHandleUtil::IsPlatformConversionResource(handle)) {
448                 if (const auto* gpuImage = static_cast<GpuImageVk*>(gpuResourceMgr.GetImage(handle)); gpuImage) {
449                     const GpuImage::AdditionalFlags additionalFlags = gpuImage->GetAdditionalFlags();
450                     immutableSampler = &(gpuImage->GetPlaformDataConversion().sampler);
451                     if ((additionalFlags & GpuImage::AdditionalFlagBits::ADDITIONAL_PLATFORM_CONVERSION_BIT) &&
452                         immutableSampler) {
453                         hasImmutableSamplers = true;
454                         immutableSamplerBitmask |= (1 << bindingIdx);
455                     }
456                 }
457             }
458 #if (RENDER_VALIDATION_ENABLED == 1)
459             if (!immutableSampler) {
460                 PLUGIN_LOG_W("RENDER_VALIDATION: immutable sampler for platform conversion resource not found");
461             }
462 #endif
463         }
464         descriptorSetLayoutBindings[idx] = {
465             bindingIdx,                         // binding
466             descriptorType,                     // descriptorType
467             cpuBinding.binding.descriptorCount, // descriptorCount
468             stageFlags,                         // stageFlags
469             immutableSampler,                   // pImmutableSamplers
470         };
471     }
472 
473     constexpr VkDescriptorSetLayoutCreateFlags descriptorSetLayoutCreateFlags { 0 };
474     const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo {
475         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType
476         nullptr,                                             // pNext
477         descriptorSetLayoutCreateFlags,                      // flags
478         bindingCount,                                        // bindingCount
479         descriptorSetLayoutBindings,                         // pBindings
480     };
481 
482     const VkDevice device = ((const DevicePlatformDataVk&)device_.GetPlatformData()).device;
483     for (uint32_t idx = 0; idx < bufferCount; ++idx) {
484         LowLevelDescriptorSetVk newDescriptorSet;
485         newDescriptorSet.flags |=
486             (hasImmutableSamplers) ? LowLevelDescriptorSetVk::DESCRIPTOR_SET_LAYOUT_IMMUTABLE_SAMPLER_BIT : 0u;
487         newDescriptorSet.immutableSamplerBitmask = immutableSamplerBitmask;
488 
489         VALIDATE_VK_RESULT(vkCreateDescriptorSetLayout(device, // device
490             &descriptorSetLayoutCreateInfo,                    // pCreateInfo
491             nullptr,                                           // pAllocator
492             &newDescriptorSet.descriptorSetLayout));           // pSetLayout
493 
494         // for immutable set we use created additional descriptor pool (currently only used with ycbcr)
495         const VkDescriptorPool descriptorPoolVk = (immutableSamplerBitmask != 0)
496                                                       ? descriptorPool.additionalPlatformDescriptorPool
497                                                       : descriptorPool.descriptorPool;
498         PLUGIN_ASSERT(descriptorPoolVk);
499         const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo {
500             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // sType
501             nullptr,                                        // pNext
502             descriptorPoolVk,                               // descriptorPool
503             1u,                                             // descriptorSetCount
504             &newDescriptorSet.descriptorSetLayout,          // pSetLayouts
505         };
506 
507         VALIDATE_VK_RESULT(vkAllocateDescriptorSets(device, // device
508             &descriptorSetAllocateInfo,                     // pAllocateInfo
509             &newDescriptorSet.descriptorSet));              // pDescriptorSets
510 
511         if (immutableSamplerBitmask != 0) {
512             descriptorPool.descriptorSets[arrayIndex].additionalPlatformSet = newDescriptorSet;
513         } else {
514             PLUGIN_ASSERT(descriptorPool.descriptorSets[arrayIndex].bufferingSet[idx].descriptorSet == VK_NULL_HANDLE);
515             descriptorPool.descriptorSets[arrayIndex].bufferingSet[idx] = newDescriptorSet;
516         }
517         // NOTE: descriptor sets could be tagged with debug name
518         // might be a bit overkill to do it always
519 #if (RENDER_VALIDATION_ENABLED == 1)
520         if (newDescriptorSet.descriptorSet == VK_NULL_HANDLE) {
521             PLUGIN_LOG_E("RENDER_VALIDATION: gpu descriptor set creation failed, ds node: %s, ds binding count: %u",
522                 debugName_.c_str(), bindingCount);
523         }
524 #endif
525     }
526 }
527 
GetLowLevelDescriptorCounts(const RenderHandle handle)528 const LowLevelDescriptorCountsVk& NodeContextDescriptorSetManagerVk::GetLowLevelDescriptorCounts(
529     const RenderHandle handle)
530 {
531     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
532     const uint32_t oneFrameDescBit = RenderHandleUtil::GetAdditionalData(handle);
533     const uint32_t descSetIdx = (oneFrameDescBit == ONE_FRAME_DESC_SET_BIT) ? DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME
534                                                                             : DESCRIPTOR_SET_INDEX_TYPE_STATIC;
535     const auto& descriptorPool = descriptorPool_[descSetIdx];
536     if (arrayIndex < (uint32_t)descriptorPool.descriptorSets.size()) {
537         return descriptorPool.descriptorSets[arrayIndex].descriptorCounts;
538     } else {
539         PLUGIN_LOG_E("invalid handle in descriptor set management");
540         return defaultLowLevelDescriptorSetMemoryStoreVk_;
541     }
542 }
543 
GetDescriptorSet(const RenderHandle handle) const544 const LowLevelDescriptorSetVk* NodeContextDescriptorSetManagerVk::GetDescriptorSet(const RenderHandle handle) const
545 {
546     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
547     const uint32_t oneFrameDescBit = RenderHandleUtil::GetAdditionalData(handle);
548     const uint32_t descSetIdx = (oneFrameDescBit == ONE_FRAME_DESC_SET_BIT) ? DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME
549                                                                             : DESCRIPTOR_SET_INDEX_TYPE_STATIC;
550     const auto& cpuDescriptorSets = cpuDescriptorSets_[descSetIdx];
551     const auto& descriptorPool = descriptorPool_[descSetIdx];
552     const LowLevelDescriptorSetVk* set = nullptr;
553     if (arrayIndex < (uint32_t)cpuDescriptorSets.size()) {
554         if (arrayIndex < descriptorPool.descriptorSets.size()) {
555             // additional set is only used there are platform buffer bindings and additional set created
556             const bool useAdditionalSet =
557                 (cpuDescriptorSets[arrayIndex].hasPlatformConversionBindings &&
558                     descriptorPool.descriptorSets[arrayIndex].additionalPlatformSet.descriptorSet);
559             if (useAdditionalSet) {
560                 PLUGIN_ASSERT_MSG(descriptorPool.descriptorSets[arrayIndex].additionalPlatformSet.descriptorSet,
561                     "descriptor set not updated");
562                 set = &descriptorPool.descriptorSets[arrayIndex].additionalPlatformSet;
563             } else {
564                 const uint32_t bufferingIndex = cpuDescriptorSets[arrayIndex].currentGpuBufferingIndex;
565                 PLUGIN_ASSERT_MSG(descriptorPool.descriptorSets[arrayIndex].bufferingSet[bufferingIndex].descriptorSet,
566                     "descriptor set not updated");
567                 set = &descriptorPool.descriptorSets[arrayIndex].bufferingSet[bufferingIndex];
568             }
569         }
570 
571 #if (RENDER_VALIDATION_ENABLED == 1)
572         if (set) {
573             if (set->descriptorSet == VK_NULL_HANDLE) {
574                 PLUGIN_LOG_E("RENDER_VALIDATION: descriptor set has not been updated prior to binding");
575                 PLUGIN_LOG_E(
576                     "RENDER_VALIDATION: gpu descriptor set created ? %u, descriptor set node: %s, buffer count: %u, "
577                     "image count: %u, sampler count: %u",
578                     (uint32_t)cpuDescriptorSets[arrayIndex].gpuDescriptorSetCreated, debugName_.c_str(),
579                     (uint32_t)descriptorPool.descriptorSets[arrayIndex].descriptorCounts.bufferCount,
580                     (uint32_t)descriptorPool.descriptorSets[arrayIndex].descriptorCounts.imageCount,
581                     (uint32_t)descriptorPool.descriptorSets[arrayIndex].descriptorCounts.samplerCount);
582             }
583         }
584 #endif
585     }
586 
587     return set;
588 }
589 
UpdateDescriptorSetGpuHandle(const RenderHandle handle)590 void NodeContextDescriptorSetManagerVk::UpdateDescriptorSetGpuHandle(const RenderHandle handle)
591 {
592     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
593     const uint32_t oneFrameDescBit = RenderHandleUtil::GetAdditionalData(handle);
594     const uint32_t descSetIdx = (oneFrameDescBit == ONE_FRAME_DESC_SET_BIT) ? DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME
595                                                                             : DESCRIPTOR_SET_INDEX_TYPE_STATIC;
596     auto& cpuDescriptorSets = cpuDescriptorSets_[descSetIdx];
597     auto& descriptorPool = descriptorPool_[descSetIdx];
598     const uint32_t bufferingCount = (oneFrameDescBit == ONE_FRAME_DESC_SET_BIT) ? 1u : bufferingCount_;
599     if (arrayIndex < (uint32_t)cpuDescriptorSets.size()) {
600         CpuDescriptorSet& refCpuSet = cpuDescriptorSets[arrayIndex];
601 
602         // with platform buffer bindings descriptor set creation needs to be checked
603         if (refCpuSet.hasPlatformConversionBindings) {
604             // no buffering
605             CreateGpuDescriptorSet(1u, handle, refCpuSet, descriptorPool);
606         } else if (!refCpuSet.gpuDescriptorSetCreated) { // deferred creation
607             CreateGpuDescriptorSet(bufferingCount, handle, refCpuSet, descriptorPool);
608             refCpuSet.gpuDescriptorSetCreated = true;
609         }
610 
611         if (refCpuSet.isDirty) {
612             refCpuSet.isDirty = false;
613             // advance to next gpu descriptor set
614             if (oneFrameDescBit != ONE_FRAME_DESC_SET_BIT) {
615                 refCpuSet.currentGpuBufferingIndex = (refCpuSet.currentGpuBufferingIndex + 1) % bufferingCount_;
616             }
617         }
618     } else {
619 #if (RENDER_VALIDATION_ENABLED == 1)
620         PLUGIN_LOG_E("invalid handle in descriptor set management");
621 #endif
622     }
623 #if (RENDER_VALIDATION_ENABLED == 1)
624     if (oneFrameDescBit == ONE_FRAME_DESC_SET_BIT) {
625         const uint32_t generationIndex = RenderHandleUtil::GetGenerationIndexPart(handle);
626         if (generationIndex != oneFrameDescSetGeneration_) {
627             PLUGIN_LOG_E(
628                 "RENDER_VALIDATION: invalid one frame descriptor set handle generation. One frame descriptor sets "
629                 "can only be used once.");
630         }
631     }
632 #endif
633 }
634 RENDER_END_NAMESPACE()
635