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