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