• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 <cinttypes>
19 #include <cstdint>
20 #include <vulkan/vulkan_core.h>
21 
22 #include <base/math/mathf.h>
23 #include <render/device/pipeline_state_desc.h>
24 #include <render/namespace.h>
25 
26 #include "device/device.h"
27 #include "device/gpu_resource_handle_util.h"
28 #include "device/gpu_resource_manager.h"
29 #include "nodecontext/node_context_descriptor_set_manager.h"
30 #include "util/log.h"
31 #include "vulkan/device_vk.h"
32 #include "vulkan/gpu_image_vk.h"
33 #include "vulkan/gpu_resource_util_vk.h"
34 #include "vulkan/gpu_sampler_vk.h"
35 #include "vulkan/validate_vk.h"
36 
37 using namespace BASE_NS;
38 
39 RENDER_BEGIN_NAMESPACE()
40 namespace {
GetDescriptorIndex(const DescriptorType & dt)41 inline constexpr uint32_t GetDescriptorIndex(const DescriptorType& dt)
42 {
43     return (dt == CORE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE) ? (OneFrameDescriptorNeed::ACCELERATION_LOCAL_TYPE)
44                                                                : static_cast<uint32_t>(dt);
45 }
46 
GetDescriptorTypeVk(const uint32_t & idx)47 inline constexpr VkDescriptorType GetDescriptorTypeVk(const uint32_t& idx)
48 {
49     return (idx == OneFrameDescriptorNeed::ACCELERATION_LOCAL_TYPE) ? VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR
50                                                                     : static_cast<VkDescriptorType>(idx);
51 }
52 
GetSampler(const GpuResourceManager & gpuResourceMgr,const RenderHandle handle)53 const VkSampler* GetSampler(const GpuResourceManager& gpuResourceMgr, const RenderHandle handle)
54 {
55     if (const auto* gpuSampler = static_cast<GpuSamplerVk*>(gpuResourceMgr.GetSampler(handle)); gpuSampler) {
56         return &(gpuSampler->GetPlatformData().sampler);
57     } else {
58         return nullptr;
59     }
60 }
61 
CreatePoolFunc(const VkDevice device,const uint32_t maxSets,BASE_NS::vector<VkDescriptorPoolSize> & descriptorPoolSizes)62 VkDescriptorPool CreatePoolFunc(
63     const VkDevice device, const uint32_t maxSets, BASE_NS::vector<VkDescriptorPoolSize>& descriptorPoolSizes)
64 {
65     constexpr VkDescriptorPoolCreateFlags descriptorPoolCreateFlags { 0 };
66     const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo {
67         VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // sType
68         nullptr,                                       // pNext
69         descriptorPoolCreateFlags,                     // flags
70         maxSets,                                       // maxSets
71         (uint32_t)descriptorPoolSizes.size(),          // poolSizeCount
72         descriptorPoolSizes.data(),                    // pPoolSizes
73     };
74 
75     VkDescriptorPool descriptorPool { VK_NULL_HANDLE };
76     VALIDATE_VK_RESULT(vkCreateDescriptorPool(device, // device
77         &descriptorPoolCreateInfo,                    // pCreateInfo
78         nullptr,                                      // pAllocator
79         &descriptorPool));                            // pDescriptorPool
80 
81     return descriptorPool;
82 }
83 
DestroyPoolFunc(const VkDevice device,LowLevelContextDescriptorPoolVk & descriptorPool)84 void DestroyPoolFunc(const VkDevice device, LowLevelContextDescriptorPoolVk& descriptorPool)
85 {
86     for (auto& ref : descriptorPool.descriptorSets) {
87         {
88             // re-used with buffered descriptor sets, destroy only once
89             auto& bufferingSetRef = ref.bufferingSet[0U];
90             if (bufferingSetRef.descriptorSetLayout) {
91                 vkDestroyDescriptorSetLayout(device,     // device
92                     bufferingSetRef.descriptorSetLayout, // descriptorSetLayout
93                     nullptr);                            // pAllocator
94                 bufferingSetRef.descriptorSetLayout = VK_NULL_HANDLE;
95             }
96         }
97         if (ref.additionalPlatformSet.descriptorSetLayout) {
98             vkDestroyDescriptorSetLayout(device,               // device
99                 ref.additionalPlatformSet.descriptorSetLayout, // descriptorSetLayout
100                 nullptr);                                      // pAllocator
101             ref.additionalPlatformSet.descriptorSetLayout = VK_NULL_HANDLE;
102         }
103     }
104     descriptorPool.descriptorSets.clear();
105     if (descriptorPool.descriptorPool) {
106         vkDestroyDescriptorPool(device,    // device
107             descriptorPool.descriptorPool, // descriptorPool
108             nullptr);                      // pAllocator
109         descriptorPool.descriptorPool = VK_NULL_HANDLE;
110     }
111     if (descriptorPool.additionalPlatformDescriptorPool) {
112         vkDestroyDescriptorPool(device,                      // device
113             descriptorPool.additionalPlatformDescriptorPool, // descriptorPool
114             nullptr);                                        // pAllocator
115         descriptorPool.additionalPlatformDescriptorPool = VK_NULL_HANDLE;
116     }
117 }
118 
CreateCpuDescriptorSetData(const array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings,const bool oneFrame,CpuDescriptorSet & newSet,LowLevelContextDescriptorPoolVk::DescriptorSetData & descSetData,OneFrameDescriptorNeed * oneFrameDescriptorNeed)119 void CreateCpuDescriptorSetData(const array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings,
120     const bool oneFrame, CpuDescriptorSet& newSet, LowLevelContextDescriptorPoolVk::DescriptorSetData& descSetData,
121     OneFrameDescriptorNeed* oneFrameDescriptorNeed)
122 {
123     uint32_t dynamicOffsetCount = 0;
124     newSet.bindings.reserve(descriptorSetLayoutBindings.size());
125     descSetData.descriptorCounts.writeDescriptorCount = static_cast<uint32_t>(descriptorSetLayoutBindings.size());
126     for (const auto& refBinding : descriptorSetLayoutBindings) {
127         // NOTE: sort from 0 to n
128         newSet.bindings.push_back({ refBinding, {} });
129         NodeContextDescriptorSetManager::IncreaseDescriptorSetCounts(
130             refBinding, descSetData.descriptorCounts, dynamicOffsetCount);
131 
132 #if (RENDER_VALIDATION_ENABLED == 1)
133         if (refBinding.descriptorType > DescriptorType::CORE_DESCRIPTOR_TYPE_INPUT_ATTACHMENT &&
134             refBinding.descriptorType != DescriptorType::CORE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE) {
135             PLUGIN_LOG_E("RENDER_VALIDATION: Unhandled descriptor type");
136         }
137 #endif
138         const uint32_t descIndex = GetDescriptorIndex(refBinding.descriptorType);
139         if (oneFrame && (descIndex < OneFrameDescriptorNeed::DESCRIPTOR_ARRAY_SIZE)) {
140             PLUGIN_ASSERT(oneFrameDescriptorNeed);
141             oneFrameDescriptorNeed->descriptorCount[descIndex] += refBinding.descriptorCount;
142         }
143     }
144     newSet.buffers.resize(descSetData.descriptorCounts.bufferCount);
145     newSet.images.resize(descSetData.descriptorCounts.imageCount);
146     newSet.samplers.resize(descSetData.descriptorCounts.samplerCount);
147 
148     newSet.dynamicOffsetDescriptors.resize(dynamicOffsetCount);
149 }
150 
CreateGpuDescriptorSetFunc(const Device & device,const uint32_t bufferCount,const RenderHandle clientHandle,const CpuDescriptorSet & cpuDescriptorSet,LowLevelContextDescriptorPoolVk & descriptorPool,const string & debugName)151 void CreateGpuDescriptorSetFunc(const Device& device, const uint32_t bufferCount, const RenderHandle clientHandle,
152     const CpuDescriptorSet& cpuDescriptorSet, LowLevelContextDescriptorPoolVk& descriptorPool, const string& debugName)
153 {
154 #if (RENDER_VALIDATION_ENABLED == 1)
155     if (cpuDescriptorSet.bindings.size() > PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT) {
156         PLUGIN_LOG_W("RENDER_VALIDATION: descriptor set binding count exceeds (max:%u, current:%u)",
157             PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT,
158             static_cast<uint32_t>(cpuDescriptorSet.bindings.size()));
159     }
160 #endif
161     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(clientHandle);
162     VkDescriptorBindingFlags descriptorBindingFlags[PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT];
163     VkDescriptorSetLayoutBinding descriptorSetLayoutBindings[PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT];
164     const uint32_t bindingCount = Math::min(static_cast<uint32_t>(cpuDescriptorSet.bindings.size()),
165         PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT);
166     const bool hasPlatformBindings = cpuDescriptorSet.hasPlatformConversionBindings;
167     const bool hasBindImmutableSamplers = cpuDescriptorSet.hasImmutableSamplers;
168     uint16_t immutableSamplerBitmask = 0;
169     const auto& gpuResourceMgr = static_cast<const GpuResourceManager&>(device.GetGpuResourceManager());
170     // NOTE: if we cannot provide explicit flags that custom immutable sampler with conversion is needed
171     // we should first loop through the bindings and check
172     // normal hw buffers do not need any rebindings or immutable samplers
173     for (uint32_t idx = 0; idx < bindingCount; ++idx) {
174         const DescriptorSetLayoutBindingResource& cpuBinding = cpuDescriptorSet.bindings[idx];
175         const auto descriptorType = (VkDescriptorType)cpuBinding.binding.descriptorType;
176         const auto stageFlags = (VkShaderStageFlags)cpuBinding.binding.shaderStageFlags;
177         const uint32_t bindingIdx = cpuBinding.binding.binding;
178         const VkSampler* immutableSampler = nullptr;
179         if (hasBindImmutableSamplers) {
180             if (descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
181                 const auto& imgRef = cpuDescriptorSet.images[cpuBinding.resourceIndex].desc;
182                 if (imgRef.additionalFlags & CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT) {
183                     immutableSampler = GetSampler(gpuResourceMgr, imgRef.resource.samplerHandle);
184                     immutableSamplerBitmask |= (1 << bindingIdx);
185                 }
186             } else if (descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) {
187                 const auto& samRef = cpuDescriptorSet.samplers[cpuBinding.resourceIndex].desc;
188                 if (samRef.additionalFlags & CORE_ADDITIONAL_DESCRIPTOR_IMMUTABLE_SAMPLER_BIT) {
189                     immutableSampler = GetSampler(gpuResourceMgr, samRef.resource.handle);
190                     immutableSamplerBitmask |= (1 << bindingIdx);
191                 }
192             }
193         } else if (hasPlatformBindings && (descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)) {
194             const RenderHandle handle = cpuDescriptorSet.images[cpuBinding.resourceIndex].desc.resource.handle;
195             if (RenderHandleUtil::IsPlatformConversionResource(handle)) {
196                 if (const auto* gpuImage = static_cast<GpuImageVk*>(gpuResourceMgr.GetImage(handle)); gpuImage) {
197                     const GpuImage::AdditionalFlags additionalFlags = gpuImage->GetAdditionalFlags();
198                     immutableSampler = &(gpuImage->GetPlaformDataConversion().sampler);
199                     if ((additionalFlags & GpuImage::AdditionalFlagBits::ADDITIONAL_PLATFORM_CONVERSION_BIT) &&
200                         immutableSampler) {
201                         immutableSamplerBitmask |= (1 << bindingIdx);
202                     }
203 #if (RENDER_VALIDATION_ENABLED == 1)
204                     if (!immutableSampler) {
205                         PLUGIN_LOG_W("RENDER_VALIDATION: immutable sampler for platform conversion resource not found");
206                     }
207 #endif
208                 }
209             }
210         }
211         descriptorSetLayoutBindings[idx] = {
212             bindingIdx,                         // binding
213             descriptorType,                     // descriptorType
214             cpuBinding.binding.descriptorCount, // descriptorCount
215             stageFlags,                         // stageFlags
216             immutableSampler,                   // pImmutableSamplers
217         };
218         // NOTE: partially bound is not used at the moment
219         descriptorBindingFlags[idx] = 0U;
220     }
221 
222     const auto& deviceVk = (const DeviceVk&)device;
223     const VkDevice vkDevice = deviceVk.GetPlatformDataVk().device;
224 
225     const VkDescriptorSetLayoutBindingFlagsCreateInfo descriptorSetLayoutBindingFlagsCreateInfo {
226         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, // sType
227         nullptr,                                                           // pNext
228         bindingCount,                                                      // bindingCount
229         descriptorBindingFlags,                                            // pBindingFlags
230     };
231     const bool dsiEnabled = deviceVk.GetCommonDeviceExtensions().descriptorIndexing;
232     const void* pNextPtr = dsiEnabled ? (&descriptorSetLayoutBindingFlagsCreateInfo) : nullptr;
233     // NOTE: update after bind etc. are not currently in use
234     // descriptor set indexing is used with normal binding model
235     constexpr VkDescriptorSetLayoutCreateFlags descriptorSetLayoutCreateFlags { 0U };
236     const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo {
237         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType
238         pNextPtr,                                            // pNext
239         descriptorSetLayoutCreateFlags,                      // flags
240         bindingCount,                                        // bindingCount
241         descriptorSetLayoutBindings,                         // pBindings
242     };
243 
244     // used with all buffered sets
245     VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE;
246     VALIDATE_VK_RESULT(vkCreateDescriptorSetLayout(vkDevice, // device
247         &descriptorSetLayoutCreateInfo,                      // pCreateInfo
248         nullptr,                                             // pAllocator
249         &descriptorSetLayout));                              // pSetLayout
250 
251     for (uint32_t idx = 0; idx < bufferCount; ++idx) {
252         PLUGIN_ASSERT(!descriptorPool.descriptorSets.empty());
253 
254         LowLevelDescriptorSetVk newDescriptorSet;
255         newDescriptorSet.descriptorSetLayout = descriptorSetLayout;
256         newDescriptorSet.flags |=
257             (immutableSamplerBitmask != 0) ? LowLevelDescriptorSetVk::DESCRIPTOR_SET_LAYOUT_IMMUTABLE_SAMPLER_BIT : 0u;
258         newDescriptorSet.immutableSamplerBitmask = immutableSamplerBitmask;
259 
260         VkDescriptorPool descriptorPoolVk = VK_NULL_HANDLE;
261         // for platform immutable set we use created additional descriptor pool (currently only used with ycbcr)
262         const bool platImmutable = (hasPlatformBindings && (immutableSamplerBitmask != 0));
263         if (platImmutable) {
264             descriptorPoolVk = descriptorPool.additionalPlatformDescriptorPool;
265         }
266         if (!descriptorPoolVk) {
267 #if (RENDER_VULKAN_VALIDATION_ENABLED == 1)
268             if (platImmutable) {
269                 const auto errorType = "plat_immutable_hwbuffer_" + to_string(idx);
270                 PLUGIN_LOG_ONCE_E(
271                     errorType, "Platform descriptor set not available, using regular (name:%s)", debugName.c_str());
272             }
273 #endif
274             descriptorPoolVk = descriptorPool.descriptorPool;
275         }
276         PLUGIN_ASSERT(descriptorPoolVk);
277         const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo {
278             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // sType
279             nullptr,                                        // pNext
280             descriptorPoolVk,                               // descriptorPool
281             1u,                                             // descriptorSetCount
282             &newDescriptorSet.descriptorSetLayout,          // pSetLayouts
283         };
284 
285         VALIDATE_VK_RESULT(vkAllocateDescriptorSets(vkDevice, // device
286             &descriptorSetAllocateInfo,                       // pAllocateInfo
287             &newDescriptorSet.descriptorSet));                // pDescriptorSets
288 #if (RENDER_VULKAN_VALIDATION_ENABLED == 1)
289         GpuResourceUtil::DebugObjectNameVk(device, VK_OBJECT_TYPE_DESCRIPTOR_SET,
290             VulkanHandleCast<uint64_t>(newDescriptorSet.descriptorSet),
291             debugName + "_ds_" + to_string(arrayIndex) + "_" + to_string(idx));
292 #endif
293 
294         if (platImmutable) {
295             descriptorPool.descriptorSets[arrayIndex].additionalPlatformSet = newDescriptorSet;
296         } else {
297             PLUGIN_ASSERT(descriptorPool.descriptorSets[arrayIndex].bufferingSet[idx].descriptorSet == VK_NULL_HANDLE);
298             descriptorPool.descriptorSets[arrayIndex].bufferingSet[idx] = newDescriptorSet;
299         }
300         // NOTE: descriptor sets could be tagged with debug name
301         // might be a bit overkill to do it always
302 #if (RENDER_VALIDATION_ENABLED == 1)
303         if (newDescriptorSet.descriptorSet == VK_NULL_HANDLE) {
304             PLUGIN_LOG_E("RENDER_VALIDATION: gpu descriptor set creation failed, ds node: %s, ds binding count: %u",
305                 debugName.c_str(), bindingCount);
306         }
307 #endif
308     }
309 }
310 
GetDescriptorSetFunc(const CpuDescriptorSet & cpuDescriptorSet,const LowLevelContextDescriptorPoolVk::DescriptorSetData & descriptorSetData,const string & debugName,const RenderHandle & handle)311 const LowLevelDescriptorSetVk* GetDescriptorSetFunc(const CpuDescriptorSet& cpuDescriptorSet,
312     const LowLevelContextDescriptorPoolVk::DescriptorSetData& descriptorSetData, const string& debugName,
313     const RenderHandle& handle)
314 {
315     const LowLevelDescriptorSetVk* set = nullptr;
316     {
317         // additional set is only used there are platform buffer bindings and additional set created
318         const bool useAdditionalSet =
319             (cpuDescriptorSet.hasPlatformConversionBindings && descriptorSetData.additionalPlatformSet.descriptorSet);
320         if (useAdditionalSet) {
321 #if (RENDER_VALIDATION_ENABLED == 1)
322             if (!descriptorSetData.additionalPlatformSet.descriptorSet) {
323                 PLUGIN_LOG_ONCE_E(debugName.c_str() + to_string(handle.id) + "_dsnu0",
324                     "RENDER_VALIDATION: descriptor set not updated (handle:%" PRIx64 ")", handle.id);
325             }
326 #endif
327             set = &descriptorSetData.additionalPlatformSet;
328         } else {
329             const uint32_t bufferingIndex = cpuDescriptorSet.currentGpuBufferingIndex;
330 #if (RENDER_VALIDATION_ENABLED == 1)
331             if (!descriptorSetData.bufferingSet[bufferingIndex].descriptorSet) {
332                 PLUGIN_LOG_ONCE_E(debugName.c_str() + to_string(handle.id) + "_dsn1",
333                     "RENDER_VALIDATION: descriptor set not updated (handle:%" PRIx64 ")", handle.id);
334             }
335 #endif
336             set = &descriptorSetData.bufferingSet[bufferingIndex];
337         }
338     }
339 
340 #if (RENDER_VALIDATION_ENABLED == 1)
341     if (set) {
342         if (set->descriptorSet == VK_NULL_HANDLE) {
343             PLUGIN_LOG_ONCE_E(debugName.c_str() + to_string(handle.id) + "_dsnu2",
344                 "RENDER_VALIDATION: descriptor set has not been updated prior to binding");
345             PLUGIN_LOG_ONCE_E(debugName.c_str() + to_string(handle.id) + "_dsnu3",
346                 "RENDER_VALIDATION: gpu descriptor set created? %u, descriptor set node: %s,"
347                 "buffer count: %u, "
348                 "image count: %u, sampler count: %u",
349                 (uint32_t)cpuDescriptorSet.gpuDescriptorSetCreated, debugName.c_str(),
350                 descriptorSetData.descriptorCounts.bufferCount, descriptorSetData.descriptorCounts.imageCount,
351                 descriptorSetData.descriptorCounts.samplerCount);
352         }
353     }
354 #endif
355 
356     return set;
357 }
358 } // namespace
359 
DescriptorSetManagerVk(Device & device)360 DescriptorSetManagerVk::DescriptorSetManagerVk(Device& device)
361     : DescriptorSetManager(device), vkDevice_ { ((const DevicePlatformDataVk&)device_.GetPlatformData()).device },
362       bufferingCount_(
363           Math::min(LowLevelContextDescriptorPoolVk::MAX_BUFFERING_COUNT, device_.GetCommandBufferingCount()))
364 {}
365 
~DescriptorSetManagerVk()366 DescriptorSetManagerVk::~DescriptorSetManagerVk()
367 {
368 #if (RENDER_VALIDATION_ENABLED == 1)
369     uint32_t referenceCounts = 0U;
370     for (const auto& baseRef : descriptorSets_) {
371         if (baseRef) {
372             for (const auto& ref : baseRef->data) {
373                 if (ref.renderHandleReference.GetRefCount() > 1) {
374                     referenceCounts++;
375                 }
376             }
377         }
378     }
379     if (referenceCounts > 0U) {
380         PLUGIN_LOG_W(
381             "RENDER_VALIDATION: Not all references removed from global descriptor set handles (%u)", referenceCounts);
382     }
383 #endif
384     for (auto& ref : lowLevelDescriptorPools_) {
385         DestroyPoolFunc(vkDevice_, ref);
386     }
387     for (auto& ref : pendingDeallocations_) {
388         DestroyPoolFunc(vkDevice_, ref.descriptorPool);
389     }
390 }
391 
BeginFrame()392 void DescriptorSetManagerVk::BeginFrame()
393 {
394     DescriptorSetManager::BeginFrame();
395 
396     lowLevelDescriptorWriteData_.Clear();
397 }
398 
BeginBackendFrame()399 void DescriptorSetManagerVk::BeginBackendFrame()
400 {
401     // NOTE: ATM during backend there's no possiblity to lock for creation
402     // -> we don't need locks here
403 
404     ResizeDescriptorSetWriteData();
405 
406     // clear aged descriptor pools
407     if (!pendingDeallocations_.empty()) {
408         // this is normally empty or only has single item
409         const auto minAge = device_.GetCommandBufferingCount() + 1;
410         const auto ageLimit = (device_.GetFrameCount() < minAge) ? 0 : (device_.GetFrameCount() - minAge);
411 
412         auto oldRes = std::partition(pendingDeallocations_.begin(), pendingDeallocations_.end(),
413             [ageLimit](auto const& pd) { return pd.frameIndex >= ageLimit; });
414 
415         std::for_each(
416             oldRes, pendingDeallocations_.end(), [this](auto& res) { DestroyPoolFunc(vkDevice_, res.descriptorPool); });
417         pendingDeallocations_.erase(oldRes, pendingDeallocations_.end());
418     }
419 
420     // handle pool creations and write locking
421     // handle possible destruction
422     PLUGIN_ASSERT(descriptorSets_.size() == lowLevelDescriptorPools_.size());
423     for (uint32_t idx = 0; idx < descriptorSets_.size(); ++idx) {
424         LowLevelContextDescriptorPoolVk& descriptorPool = lowLevelDescriptorPools_[idx];
425         GlobalDescriptorSetBase* descriptorSetBase = descriptorSets_[idx].get();
426         if (!descriptorSetBase) {
427             continue;
428         }
429         bool destroyDescriptorSets = true;
430         // if we have any descriptor sets in use we do not destroy the pool
431         for (auto& ref : descriptorSetBase->data) {
432             if (ref.renderHandleReference.GetRefCount() > 1) {
433                 destroyDescriptorSets = false;
434             }
435             ref.frameWriteLocked = false;
436         }
437 
438         // destroy or create pool
439         if (destroyDescriptorSets) {
440             if (descriptorPool.descriptorPool || descriptorPool.additionalPlatformDescriptorPool) {
441                 PendingDeallocations pd;
442                 pd.descriptorPool.descriptorPool = exchange(descriptorPool.descriptorPool, VK_NULL_HANDLE);
443                 pd.descriptorPool.additionalPlatformDescriptorPool =
444                     exchange(descriptorPool.additionalPlatformDescriptorPool, VK_NULL_HANDLE);
445                 pd.descriptorPool.descriptorSets = move(descriptorPool.descriptorSets);
446                 pd.frameIndex = device_.GetFrameCount();
447                 pendingDeallocations_.push_back(move(pd));
448             }
449             if (!descriptorSetBase->data.empty()) {
450                 const RenderHandle handle = descriptorSetBase->data[0U].renderHandleReference.GetHandle();
451                 // set handle (index location) to be available
452                 availableHandles_.push_back(handle);
453             }
454             // reset
455             nameToIndex_.erase(descriptorSetBase->name);
456             *descriptorSetBase = {};
457         } else if (descriptorPool.descriptorPool == VK_NULL_HANDLE) {
458             descriptorPoolSizes_.clear();
459             descriptorPoolSizes_.reserve(PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT);
460             // all the the descriptor sets have the same amount of data
461             if ((!descriptorSetBase->data.empty()) && (!descriptorPool.descriptorSets.empty())) {
462                 const auto descriptorSetCount = static_cast<uint32_t>(descriptorPool.descriptorSets.size());
463                 for (const auto& bindRef : descriptorSetBase->data[0U].cpuDescriptorSet.bindings) {
464                     const auto& bind = bindRef.binding;
465                     descriptorPoolSizes_.push_back(VkDescriptorPoolSize { (VkDescriptorType)bind.descriptorType,
466                         bind.descriptorCount * descriptorSetCount * bufferingCount_ });
467                 }
468                 if (!descriptorPoolSizes_.empty()) {
469                     descriptorPool.descriptorPool =
470                         CreatePoolFunc(vkDevice_, descriptorSetCount * bufferingCount_, descriptorPoolSizes_);
471                 }
472             }
473         }
474     }
475 }
476 
CreateDescriptorSets(const uint32_t arrayIndex,const uint32_t descriptorSetCount,const array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings)477 void DescriptorSetManagerVk::CreateDescriptorSets(const uint32_t arrayIndex, const uint32_t descriptorSetCount,
478     const array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings)
479 {
480     PLUGIN_ASSERT((arrayIndex < descriptorSets_.size()) && (descriptorSets_[arrayIndex]));
481     PLUGIN_ASSERT(descriptorSets_[arrayIndex]->data.size() == descriptorSetCount);
482     if ((arrayIndex < descriptorSets_.size()) && (descriptorSets_[arrayIndex])) {
483         // resize based on cpu descriptor sets
484         lowLevelDescriptorPools_.resize(descriptorSets_.size());
485         PLUGIN_ASSERT(arrayIndex < lowLevelDescriptorPools_.size());
486 
487         LowLevelContextDescriptorPoolVk& descriptorPool = lowLevelDescriptorPools_[arrayIndex];
488         // destroy old pool properly
489         if (descriptorPool.descriptorPool || descriptorPool.additionalPlatformDescriptorPool) {
490             PendingDeallocations pd;
491             pd.descriptorPool.descriptorPool = exchange(descriptorPool.descriptorPool, VK_NULL_HANDLE);
492             pd.descriptorPool.additionalPlatformDescriptorPool =
493                 exchange(descriptorPool.additionalPlatformDescriptorPool, VK_NULL_HANDLE);
494             pd.descriptorPool.descriptorSets = move(descriptorPool.descriptorSets);
495             pd.frameIndex = device_.GetFrameCount();
496             pendingDeallocations_.push_back(move(pd));
497         }
498         descriptorPool.descriptorSets.clear();
499 
500         descriptorPool.descriptorSets.resize(descriptorSetCount);
501         GlobalDescriptorSetBase* cpuData = descriptorSets_[arrayIndex].get();
502         PLUGIN_ASSERT(cpuData->data.size() == descriptorPool.descriptorSets.size());
503         for (uint32_t idx = 0; idx < descriptorSetCount; ++idx) {
504             CpuDescriptorSet newSet;
505             LowLevelContextDescriptorPoolVk::DescriptorSetData descSetData;
506             CreateCpuDescriptorSetData(descriptorSetLayoutBindings, false, newSet, descSetData, nullptr);
507 
508             const uint32_t additionalIndex = idx;
509             cpuData->data[additionalIndex].cpuDescriptorSet = move(newSet);
510             // don't create the actual gpu descriptor sets yet
511             descriptorPool.descriptorSets[additionalIndex] = descSetData;
512         }
513     }
514 }
515 
UpdateDescriptorSetGpuHandle(const RenderHandle & handle)516 bool DescriptorSetManagerVk::UpdateDescriptorSetGpuHandle(const RenderHandle& handle)
517 {
518     PLUGIN_ASSERT(RenderHandleUtil::GetHandleType(handle) == RenderHandleType::DESCRIPTOR_SET);
519 
520     // NOTE: this is called from the backend from a single thread and other threads cannot access the data
521     // does not need to be locked
522 
523     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
524     GlobalDescriptorSetBase* baseSet = nullptr;
525     if ((index < descriptorSets_.size()) && descriptorSets_[index]) {
526         baseSet = descriptorSets_[index].get();
527     }
528 
529     bool retValue = false;
530     if (baseSet && (index < lowLevelDescriptorPools_.size())) {
531         LowLevelContextDescriptorPoolVk& descriptorPool = lowLevelDescriptorPools_[index];
532         const uint32_t additionalIndex = RenderHandleUtil::GetAdditionalIndexPart(handle);
533         if ((additionalIndex < baseSet->data.size()) && (additionalIndex < descriptorPool.descriptorSets.size())) {
534             CpuDescriptorSet& refCpuSet = baseSet->data[additionalIndex].cpuDescriptorSet;
535             const RenderHandle indexHandle = RenderHandleUtil::CreateHandle(
536                 RenderHandleType::DESCRIPTOR_SET, additionalIndex); // using array index from handle
537 
538             // with platform buffer bindings descriptor set creation needs to be checked
539             if (refCpuSet.hasPlatformConversionBindings) {
540                 // no buffering
541                 CreateGpuDescriptorSetFunc(device_, 1U, indexHandle, refCpuSet, descriptorPool, baseSet->name);
542             } else if (!refCpuSet.gpuDescriptorSetCreated) { // deferred creation
543                 CreateGpuDescriptorSetFunc(
544                     device_, bufferingCount_, indexHandle, refCpuSet, descriptorPool, baseSet->name);
545                 refCpuSet.gpuDescriptorSetCreated = true;
546             }
547 
548             // at the moment should be always dirty when coming here from the backend update
549             if (refCpuSet.isDirty) {
550                 refCpuSet.isDirty = false;
551                 // advance to next gpu descriptor set
552                 refCpuSet.currentGpuBufferingIndex = (refCpuSet.currentGpuBufferingIndex + 1) % bufferingCount_;
553                 retValue = true;
554             }
555         }
556     }
557     return retValue;
558 }
559 
GetDescriptorSet(const RenderHandle & handle) const560 const LowLevelDescriptorSetVk* DescriptorSetManagerVk::GetDescriptorSet(const RenderHandle& handle) const
561 {
562     // NOTE: this is called from the backend from a single thread and other threads cannot access the data
563     // does not need to be locked
564 
565     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
566     GlobalDescriptorSetBase* baseSet = nullptr;
567     if ((index < descriptorSets_.size()) && descriptorSets_[index]) {
568         baseSet = descriptorSets_[index].get();
569     }
570 
571     const LowLevelDescriptorSetVk* set = nullptr;
572     if (baseSet && (index < lowLevelDescriptorPools_.size())) {
573         const LowLevelContextDescriptorPoolVk& descriptorPool = lowLevelDescriptorPools_[index];
574         const uint32_t additionalIndex = RenderHandleUtil::GetAdditionalIndexPart(handle);
575         if ((additionalIndex < baseSet->data.size()) && (additionalIndex < descriptorPool.descriptorSets.size())) {
576             const CpuDescriptorSet& refCpuSet = baseSet->data[additionalIndex].cpuDescriptorSet;
577             if ((!descriptorPool.descriptorSets.empty()) && (additionalIndex < descriptorPool.descriptorSets.size())) {
578                 const RenderHandle indexHandle = RenderHandleUtil::CreateHandle(
579                     RenderHandleType::DESCRIPTOR_SET, additionalIndex); // using array index from handle
580                 set = GetDescriptorSetFunc(
581                     refCpuSet, descriptorPool.descriptorSets[additionalIndex], baseSet->name, indexHandle);
582             }
583         }
584     }
585     return set;
586 }
587 
588 // needs to be locked when called
UpdateCpuDescriptorSetPlatform(const DescriptorSetLayoutBindingResources & bindingResources)589 void DescriptorSetManagerVk::UpdateCpuDescriptorSetPlatform(const DescriptorSetLayoutBindingResources& bindingResources)
590 {
591     // needs to be locked when accessed from multiple threads
592 
593     lowLevelDescriptorWriteData_.writeBindingCount += static_cast<uint32_t>(bindingResources.bindings.size());
594 
595     lowLevelDescriptorWriteData_.bufferBindingCount += static_cast<uint32_t>(bindingResources.buffers.size());
596     lowLevelDescriptorWriteData_.imageBindingCount += static_cast<uint32_t>(bindingResources.images.size());
597     lowLevelDescriptorWriteData_.samplerBindingCount += static_cast<uint32_t>(bindingResources.samplers.size());
598 }
599 
ResizeDescriptorSetWriteData()600 void DescriptorSetManagerVk::ResizeDescriptorSetWriteData()
601 {
602     auto& descWd = lowLevelDescriptorWriteData_;
603     if (descWd.writeBindingCount > 0U) {
604         lowLevelDescriptorWriteData_.writeDescriptorSets.resize(descWd.writeBindingCount);
605         lowLevelDescriptorWriteData_.descriptorBufferInfos.resize(descWd.bufferBindingCount);
606         lowLevelDescriptorWriteData_.descriptorImageInfos.resize(descWd.imageBindingCount);
607         lowLevelDescriptorWriteData_.descriptorSamplerInfos.resize(descWd.samplerBindingCount);
608 #if (RENDER_VULKAN_RT_ENABLED == 1)
609         lowLevelDescriptorWriteData_.descriptorAccelInfos.resize(descWd.bufferBindingCount);
610 #endif
611     }
612 }
613 
GetLowLevelDescriptorWriteData()614 LowLevelContextDescriptorWriteDataVk& DescriptorSetManagerVk::GetLowLevelDescriptorWriteData()
615 {
616     return lowLevelDescriptorWriteData_;
617 }
618 
NodeContextDescriptorSetManagerVk(Device & device)619 NodeContextDescriptorSetManagerVk::NodeContextDescriptorSetManagerVk(Device& device)
620     : NodeContextDescriptorSetManager(device), device_ { device },
621       vkDevice_ { ((const DevicePlatformDataVk&)device_.GetPlatformData()).device },
622       bufferingCount_(
623           Math::min(LowLevelContextDescriptorPoolVk::MAX_BUFFERING_COUNT, device_.GetCommandBufferingCount()))
624 {
625 #if (RENDER_VALIDATION_ENABLED == 1)
626     if (device_.GetCommandBufferingCount() > LowLevelContextDescriptorPoolVk::MAX_BUFFERING_COUNT) {
627         PLUGIN_LOG_ONCE_W("device_command_buffering_count_desc_set_vk_buffering",
628             "RENDER_VALIDATION: device command buffering count (%u) is larger than supported vulkan descriptor set "
629             "buffering count (%u)",
630             device_.GetCommandBufferingCount(), LowLevelContextDescriptorPoolVk::MAX_BUFFERING_COUNT);
631     }
632 #endif
633 }
634 
~NodeContextDescriptorSetManagerVk()635 NodeContextDescriptorSetManagerVk::~NodeContextDescriptorSetManagerVk()
636 {
637     DestroyPoolFunc(vkDevice_, descriptorPool_[DESCRIPTOR_SET_INDEX_TYPE_STATIC]);
638     DestroyPoolFunc(vkDevice_, descriptorPool_[DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME]);
639     for (auto& ref : pendingDeallocations_) {
640         DestroyPoolFunc(vkDevice_, ref.descriptorPool);
641     }
642 }
643 
ResetAndReserve(const DescriptorCounts & descriptorCounts)644 void NodeContextDescriptorSetManagerVk::ResetAndReserve(const DescriptorCounts& descriptorCounts)
645 {
646     NodeContextDescriptorSetManager::ResetAndReserve(descriptorCounts);
647     if (maxSets_ > 0) {
648         auto& descriptorPool = descriptorPool_[DESCRIPTOR_SET_INDEX_TYPE_STATIC];
649         // usually there are less descriptor sets than max sets count
650         // due to maxsets count has been calculated for single descriptors
651         // (one descriptor set has multiple descriptors)
652         const uint32_t reserveCount = maxSets_ / 2u; // questimate for possible max vector size;
653 
654         if (descriptorPool.descriptorPool) { // push for dealloation vec
655             PendingDeallocations pd;
656             pd.descriptorPool.descriptorPool = move(descriptorPool.descriptorPool);
657             pd.descriptorPool.descriptorSets = move(descriptorPool.descriptorSets);
658             pd.frameIndex = device_.GetFrameCount();
659             pendingDeallocations_.push_back(move(pd));
660 
661             descriptorPool.descriptorSets.clear();
662             descriptorPool.descriptorPool = VK_NULL_HANDLE;
663         }
664 
665         descriptorPoolSizes_.clear();
666         descriptorPoolSizes_.reserve(descriptorCounts.counts.size()); // max count reserve
667         for (const auto& ref : descriptorCounts.counts) {
668             if (ref.count > 0) {
669                 descriptorPoolSizes_.push_back(
670                     VkDescriptorPoolSize { (VkDescriptorType)ref.type, ref.count * bufferingCount_ });
671             }
672         }
673 
674         if (!descriptorPoolSizes_.empty()) {
675             descriptorPool.descriptorPool = CreatePoolFunc(vkDevice_, maxSets_ * bufferingCount_, descriptorPoolSizes_);
676             descriptorPool.descriptorSets.reserve(reserveCount);
677         }
678     }
679 }
680 
BeginFrame()681 void NodeContextDescriptorSetManagerVk::BeginFrame()
682 {
683     NodeContextDescriptorSetManager::BeginFrame();
684 
685     ClearDescriptorSetWriteData();
686 
687     // clear aged descriptor pools
688     if (!pendingDeallocations_.empty()) {
689         // this is normally empty or only has single item
690         const auto minAge = device_.GetCommandBufferingCount() + 1;
691         const auto ageLimit = (device_.GetFrameCount() < minAge) ? 0 : (device_.GetFrameCount() - minAge);
692 
693         auto oldRes = std::partition(pendingDeallocations_.begin(), pendingDeallocations_.end(),
694             [ageLimit](auto const& pd) { return pd.frameIndex >= ageLimit; });
695 
696         std::for_each(
697             oldRes, pendingDeallocations_.end(), [this](auto& res) { DestroyPoolFunc(vkDevice_, res.descriptorPool); });
698         pendingDeallocations_.erase(oldRes, pendingDeallocations_.end());
699     }
700 
701     oneFrameDescriptorNeed_ = {};
702     auto& oneFrameDescriptorPool = descriptorPool_[DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME];
703     if (oneFrameDescriptorPool.descriptorPool || oneFrameDescriptorPool.additionalPlatformDescriptorPool) {
704         const auto descriptorSetCount = static_cast<uint32_t>(oneFrameDescriptorPool.descriptorSets.size());
705         PendingDeallocations pd;
706         pd.descriptorPool.descriptorPool = exchange(oneFrameDescriptorPool.descriptorPool, VK_NULL_HANDLE);
707         pd.descriptorPool.additionalPlatformDescriptorPool =
708             exchange(oneFrameDescriptorPool.additionalPlatformDescriptorPool, VK_NULL_HANDLE);
709         pd.descriptorPool.descriptorSets = move(oneFrameDescriptorPool.descriptorSets);
710         pd.frameIndex = device_.GetFrameCount();
711         pendingDeallocations_.push_back(move(pd));
712 
713         oneFrameDescriptorPool.descriptorSets.reserve(descriptorSetCount);
714     }
715     oneFrameDescriptorPool.descriptorSets.clear();
716 
717     // we need to check through platform special format desriptor sets/pool
718     auto& descriptorPool = descriptorPool_[DESCRIPTOR_SET_INDEX_TYPE_STATIC];
719     if (descriptorPool.additionalPlatformDescriptorPool) {
720         PendingDeallocations pd;
721         pd.descriptorPool.additionalPlatformDescriptorPool = move(descriptorPool.additionalPlatformDescriptorPool);
722         // no buffering set
723         pd.frameIndex = device_.GetFrameCount();
724         pendingDeallocations_.push_back(move(pd));
725         descriptorPool.additionalPlatformDescriptorPool = VK_NULL_HANDLE;
726         // immediate desctruction of descriptor set layouts
727         for (auto& descriptorSetRef : descriptorPool.descriptorSets) {
728             if (descriptorSetRef.additionalPlatformSet.descriptorSetLayout) {
729                 vkDestroyDescriptorSetLayout(vkDevice_,                         // device
730                     descriptorSetRef.additionalPlatformSet.descriptorSetLayout, // descriptorSetLayout
731                     nullptr);                                                   // pAllocator
732                 descriptorSetRef.additionalPlatformSet.descriptorSetLayout = VK_NULL_HANDLE;
733             }
734         }
735         auto& cpuDescriptorSet = cpuDescriptorSets_[DESCRIPTOR_SET_INDEX_TYPE_STATIC];
736         for (auto& descriptorSetRef : cpuDescriptorSet) {
737             descriptorSetRef.hasPlatformConversionBindings = false;
738         }
739     }
740 
741 #if (RENDER_VALIDATION_ENABLED == 1)
742     oneFrameDescSetGeneration_ = (oneFrameDescSetGeneration_ + 1) % MAX_ONE_FRAME_GENERATION_IDX;
743 #endif
744 }
745 
BeginBackendFrame()746 void NodeContextDescriptorSetManagerVk::BeginBackendFrame()
747 {
748     // resize vector data
749     ResizeDescriptorSetWriteData();
750 
751     // reserve descriptors for descriptors sets that need platform special formats for one frame
752     if (hasPlatformConversionBindings_) {
753         const auto& cpuDescriptorSets = cpuDescriptorSets_[DESCRIPTOR_SET_INDEX_TYPE_STATIC];
754         uint32_t descriptorSetCount = 0u;
755         uint32_t descriptorCounts[OneFrameDescriptorNeed::DESCRIPTOR_ARRAY_SIZE] { 0 };
756         for (const auto& cpuDescriptorSetRef : cpuDescriptorSets) {
757             if (cpuDescriptorSetRef.hasPlatformConversionBindings) {
758                 descriptorSetCount++;
759                 for (const auto& bindingRef : cpuDescriptorSetRef.bindings) {
760                     uint32_t descriptorCount = bindingRef.binding.descriptorCount;
761                     const auto descTypeIndex = GetDescriptorIndex(bindingRef.binding.descriptorType);
762                     if (descTypeIndex < OneFrameDescriptorNeed::DESCRIPTOR_ARRAY_SIZE) {
763                         if ((bindingRef.binding.descriptorType ==
764                                 DescriptorType::CORE_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&
765                             RenderHandleUtil::IsPlatformConversionResource(
766                                 cpuDescriptorSetRef.images[bindingRef.resourceIndex].desc.resource.handle)) {
767                             // expecting planar formats and making sure that there is enough descriptors
768                             constexpr uint32_t descriptorCountMultiplier = 3u;
769                             descriptorCount *= descriptorCountMultiplier;
770                         }
771                         descriptorCounts[descTypeIndex] += descriptorCount;
772                     }
773                 }
774             }
775         }
776         if (descriptorSetCount > 0) {
777             auto& descriptorPool = descriptorPool_[DESCRIPTOR_SET_INDEX_TYPE_STATIC];
778             PLUGIN_ASSERT(descriptorPool.additionalPlatformDescriptorPool == VK_NULL_HANDLE);
779             descriptorPoolSizes_.clear();
780             descriptorPoolSizes_.reserve(OneFrameDescriptorNeed::DESCRIPTOR_ARRAY_SIZE);
781             // no buffering, only descriptors for one frame
782             for (uint32_t idx = 0; idx < OneFrameDescriptorNeed::DESCRIPTOR_ARRAY_SIZE; ++idx) {
783                 const uint32_t count = descriptorCounts[idx];
784                 if (count > 0) {
785                     descriptorPoolSizes_.push_back(VkDescriptorPoolSize { GetDescriptorTypeVk(idx), count });
786                 }
787             }
788             if (!descriptorPoolSizes_.empty()) {
789                 descriptorPool.additionalPlatformDescriptorPool =
790                     CreatePoolFunc(vkDevice_, descriptorSetCount, descriptorPoolSizes_);
791             }
792         }
793     }
794     // create one frame descriptor pool
795     {
796         auto& descriptorPool = descriptorPool_[DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME];
797         auto& cpuDescriptorSets = cpuDescriptorSets_[DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME];
798 
799         PLUGIN_ASSERT(descriptorPool.descriptorPool == VK_NULL_HANDLE);
800         const auto descriptorSetCount = static_cast<uint32_t>(cpuDescriptorSets.size());
801         if (descriptorSetCount > 0) {
802             descriptorPoolSizes_.clear();
803             descriptorPoolSizes_.reserve(OneFrameDescriptorNeed::DESCRIPTOR_ARRAY_SIZE);
804             for (uint32_t idx = 0; idx < OneFrameDescriptorNeed::DESCRIPTOR_ARRAY_SIZE; ++idx) {
805                 const uint32_t count = oneFrameDescriptorNeed_.descriptorCount[idx];
806                 if (count > 0) {
807                     descriptorPoolSizes_.push_back(VkDescriptorPoolSize { GetDescriptorTypeVk(idx), count });
808                 }
809             }
810 
811             if (!descriptorPoolSizes_.empty()) {
812                 descriptorPool.descriptorPool = CreatePoolFunc(vkDevice_, descriptorSetCount, descriptorPoolSizes_);
813             }
814         }
815         // check the need for additional platform conversion bindings
816         if (hasPlatformConversionBindings_) {
817             uint32_t platConvDescriptorCounts[OneFrameDescriptorNeed::DESCRIPTOR_ARRAY_SIZE] { 0 };
818             for (const auto& cpuDescriptorSetRef : cpuDescriptorSets) {
819                 if (cpuDescriptorSetRef.hasPlatformConversionBindings) {
820                     for (const auto& bindingRef : cpuDescriptorSetRef.bindings) {
821                         uint32_t descriptorCount = bindingRef.binding.descriptorCount;
822                         const auto descTypeIndex = GetDescriptorIndex(bindingRef.binding.descriptorType);
823                         if (descTypeIndex < OneFrameDescriptorNeed::DESCRIPTOR_ARRAY_SIZE) {
824                             if ((bindingRef.binding.descriptorType ==
825                                     DescriptorType::CORE_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&
826                                 RenderHandleUtil::IsPlatformConversionResource(
827                                     cpuDescriptorSetRef.images[bindingRef.resourceIndex].desc.resource.handle)) {
828                                 // expecting planar formats and making sure that there is enough descriptors
829                                 constexpr uint32_t descriptorCountMultiplier = 3u;
830                                 descriptorCount *= descriptorCountMultiplier;
831                             }
832                             platConvDescriptorCounts[descTypeIndex] += descriptorCount;
833                         }
834                     }
835                 }
836             }
837             if (descriptorSetCount > 0) {
838                 PLUGIN_ASSERT(descriptorPool.additionalPlatformDescriptorPool == VK_NULL_HANDLE);
839                 descriptorPoolSizes_.clear();
840                 descriptorPoolSizes_.reserve(OneFrameDescriptorNeed::DESCRIPTOR_ARRAY_SIZE);
841                 // no buffering, only descriptors for one frame
842                 for (uint32_t idx = 0; idx < OneFrameDescriptorNeed::DESCRIPTOR_ARRAY_SIZE; ++idx) {
843                     const uint32_t count = platConvDescriptorCounts[idx];
844                     if (count > 0) {
845                         descriptorPoolSizes_.push_back(VkDescriptorPoolSize { GetDescriptorTypeVk(idx), count });
846                     }
847                 }
848                 if (!descriptorPoolSizes_.empty()) {
849                     descriptorPool.additionalPlatformDescriptorPool =
850                         CreatePoolFunc(vkDevice_, descriptorSetCount, descriptorPoolSizes_);
851                 }
852             }
853         }
854     }
855 }
856 
CreateDescriptorSet(const array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings)857 RenderHandle NodeContextDescriptorSetManagerVk::CreateDescriptorSet(
858     const array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings)
859 {
860     RenderHandle clientHandle;
861     auto& cpuDescriptorSets = cpuDescriptorSets_[DESCRIPTOR_SET_INDEX_TYPE_STATIC];
862     auto& descriptorPool = descriptorPool_[DESCRIPTOR_SET_INDEX_TYPE_STATIC];
863 #if (RENDER_VALIDATION_ENABLED == 1)
864     if (cpuDescriptorSets.size() >= maxSets_) {
865         PLUGIN_LOG_E("RENDER_VALIDATION: No more descriptor sets available");
866     }
867 #endif
868     if (cpuDescriptorSets.size() < maxSets_) {
869         CpuDescriptorSet newSet;
870         LowLevelContextDescriptorPoolVk::DescriptorSetData descSetData;
871         CreateCpuDescriptorSetData(descriptorSetLayoutBindings, false, newSet, descSetData, nullptr);
872 
873         const auto arrayIndex = static_cast<uint32_t>(cpuDescriptorSets.size());
874         cpuDescriptorSets.push_back(move(newSet));
875         // allocate storage from vector to gpu descriptor sets
876         // don't create the actual gpu descriptor sets yet
877         descriptorPool.descriptorSets.push_back(descSetData);
878 
879         // NOTE: can be used directly to index
880         clientHandle = RenderHandleUtil::CreateHandle(RenderHandleType::DESCRIPTOR_SET, arrayIndex, 0);
881     }
882 
883     return clientHandle;
884 }
885 
CreateOneFrameDescriptorSet(const array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings)886 RenderHandle NodeContextDescriptorSetManagerVk::CreateOneFrameDescriptorSet(
887     const array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings)
888 {
889     RenderHandle clientHandle;
890     auto& cpuDescriptorSets = cpuDescriptorSets_[DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME];
891     auto& descriptorPool = descriptorPool_[DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME];
892     CpuDescriptorSet newSet;
893     LowLevelContextDescriptorPoolVk::DescriptorSetData descSetData;
894 
895     CreateCpuDescriptorSetData(descriptorSetLayoutBindings, true, newSet, descSetData, &oneFrameDescriptorNeed_);
896 
897     const auto arrayIndex = static_cast<uint32_t>(cpuDescriptorSets.size());
898     cpuDescriptorSets.push_back(move(newSet));
899     // allocate storage from vector to gpu descriptor sets
900     // don't create the actual gpu descriptor sets yet
901     descriptorPool.descriptorSets.push_back(descSetData);
902 
903     // NOTE: can be used directly to index
904     clientHandle = RenderHandleUtil::CreateHandle(
905         RenderHandleType::DESCRIPTOR_SET, arrayIndex, oneFrameDescSetGeneration_, ONE_FRAME_DESC_SET_BIT);
906 
907     return clientHandle;
908 }
909 
GetDescriptorSet(const RenderHandle handle) const910 const LowLevelDescriptorSetVk* NodeContextDescriptorSetManagerVk::GetDescriptorSet(const RenderHandle handle) const
911 {
912     const uint32_t descSetIdx = GetCpuDescriptorSetIndex(handle);
913     if (descSetIdx == ~0U) {
914         return ((const DescriptorSetManagerVk&)globalDescriptorSetMgr_).GetDescriptorSet(handle);
915     } else {
916         PLUGIN_ASSERT(descSetIdx < DESCRIPTOR_SET_INDEX_TYPE_COUNT);
917 
918         const auto& cpuDescriptorSets = cpuDescriptorSets_[descSetIdx];
919         const auto& descriptorPool = descriptorPool_[descSetIdx];
920         const LowLevelDescriptorSetVk* set = nullptr;
921         const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
922         if (arrayIndex < (uint32_t)cpuDescriptorSets.size()) {
923             if (arrayIndex < descriptorPool.descriptorSets.size()) {
924                 set = GetDescriptorSetFunc(
925                     cpuDescriptorSets[arrayIndex], descriptorPool.descriptorSets[arrayIndex], debugName_, handle);
926             }
927 
928             return set;
929         }
930     }
931     return nullptr;
932 }
933 
GetLowLevelDescriptorWriteData()934 LowLevelContextDescriptorWriteDataVk& NodeContextDescriptorSetManagerVk::GetLowLevelDescriptorWriteData()
935 {
936     return lowLevelDescriptorWriteData_;
937 }
938 
UpdateDescriptorSetGpuHandle(const RenderHandle handle)939 bool NodeContextDescriptorSetManagerVk::UpdateDescriptorSetGpuHandle(const RenderHandle handle)
940 {
941     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
942     uint32_t descSetIdx = GetCpuDescriptorSetIndex(handle);
943     PLUGIN_ASSERT(descSetIdx != ~0U);
944     PLUGIN_ASSERT(descSetIdx < DESCRIPTOR_SET_INDEX_TYPE_COUNT);
945     auto& cpuDescriptorSets = cpuDescriptorSets_[descSetIdx];
946     auto& descriptorPool = descriptorPool_[descSetIdx];
947     const uint32_t bufferingCount = (descSetIdx == DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME) ? 1u : bufferingCount_;
948     bool retValue = false;
949     if (arrayIndex < (uint32_t)cpuDescriptorSets.size()) {
950         CpuDescriptorSet& refCpuSet = cpuDescriptorSets[arrayIndex];
951 
952         // with platform buffer bindings descriptor set creation needs to be checked
953         if (refCpuSet.hasPlatformConversionBindings) {
954             // no buffering
955             CreateGpuDescriptorSetFunc(device_, 1u, handle, refCpuSet, descriptorPool, debugName_);
956         } else if (!refCpuSet.gpuDescriptorSetCreated) { // deferred creation
957             CreateGpuDescriptorSetFunc(device_, bufferingCount, handle, refCpuSet, descriptorPool, debugName_);
958             refCpuSet.gpuDescriptorSetCreated = true;
959         }
960 
961         // at the moment should be always dirty when coming here from the backend update
962         if (refCpuSet.isDirty) {
963             refCpuSet.isDirty = false;
964             // advance to next gpu descriptor set
965             if (descSetIdx != DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME) {
966                 refCpuSet.currentGpuBufferingIndex = (refCpuSet.currentGpuBufferingIndex + 1) % bufferingCount_;
967             }
968             retValue = true;
969         }
970     } else {
971 #if (RENDER_VALIDATION_ENABLED == 1)
972         PLUGIN_LOG_E("invalid handle in descriptor set management");
973 #endif
974     }
975 #if (RENDER_VALIDATION_ENABLED == 1)
976     if (descSetIdx == DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME) {
977         const uint32_t generationIndex = RenderHandleUtil::GetGenerationIndexPart(handle);
978         if (generationIndex != oneFrameDescSetGeneration_) {
979             PLUGIN_LOG_E("RENDER_VALIDATION: invalid one frame descriptor set handle generation. One frame "
980                          "descriptor sets "
981                          "can only be used once.");
982         }
983     }
984 #endif
985     return retValue;
986 }
987 
UpdateCpuDescriptorSetPlatform(const DescriptorSetLayoutBindingResources & bindingResources)988 void NodeContextDescriptorSetManagerVk::UpdateCpuDescriptorSetPlatform(
989     const DescriptorSetLayoutBindingResources& bindingResources)
990 {
991     lowLevelDescriptorWriteData_.writeBindingCount += static_cast<uint32_t>(bindingResources.bindings.size());
992 
993     lowLevelDescriptorWriteData_.bufferBindingCount += static_cast<uint32_t>(bindingResources.buffers.size());
994     lowLevelDescriptorWriteData_.imageBindingCount += static_cast<uint32_t>(bindingResources.images.size());
995     lowLevelDescriptorWriteData_.samplerBindingCount += static_cast<uint32_t>(bindingResources.samplers.size());
996 }
997 
ClearDescriptorSetWriteData()998 void NodeContextDescriptorSetManagerVk::ClearDescriptorSetWriteData()
999 {
1000     lowLevelDescriptorWriteData_.Clear();
1001 }
1002 
ResizeDescriptorSetWriteData()1003 void NodeContextDescriptorSetManagerVk::ResizeDescriptorSetWriteData()
1004 {
1005     auto& descWd = lowLevelDescriptorWriteData_;
1006     if (descWd.writeBindingCount > 0U) {
1007         lowLevelDescriptorWriteData_.writeDescriptorSets.resize(descWd.writeBindingCount);
1008         lowLevelDescriptorWriteData_.descriptorBufferInfos.resize(descWd.bufferBindingCount);
1009         lowLevelDescriptorWriteData_.descriptorImageInfos.resize(descWd.imageBindingCount);
1010         lowLevelDescriptorWriteData_.descriptorSamplerInfos.resize(descWd.samplerBindingCount);
1011 #if (RENDER_VULKAN_RT_ENABLED == 1)
1012         lowLevelDescriptorWriteData_.descriptorAccelInfos.resize(descWd.bufferBindingCount);
1013 #endif
1014     }
1015 }
1016 
1017 RENDER_END_NAMESPACE()
1018