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