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