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
16 #include "node_context_descriptor_set_manager_gles.h"
17
18 #include <render/device/intf_gpu_resource_manager.h>
19 #include <render/namespace.h>
20
21 #include "device/device.h"
22 #include "device/gpu_resource_manager.h"
23 #include "gles/gl_functions.h"
24 #include "gles/gpu_buffer_gles.h"
25 #include "gles/gpu_image_gles.h"
26 #include "gles/gpu_sampler_gles.h"
27 #include "nodecontext/pipeline_descriptor_set_binder.h"
28 #include "util/log.h"
29
30 using namespace BASE_NS;
31
32 RENDER_BEGIN_NAMESPACE()
33 namespace {
CreateCpuDescriptorSetData(const array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings)34 CpuDescriptorSet CreateCpuDescriptorSetData(
35 const array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings)
36 {
37 uint32_t dynamicOffsetCount = 0;
38 CpuDescriptorSet newSet;
39 newSet.bindings.reserve(descriptorSetLayoutBindings.size());
40 LowLevelDescriptorCounts descriptorCounts;
41 for (const auto& refBinding : descriptorSetLayoutBindings) {
42 // NOTE: sort from 0 to n
43 newSet.bindings.push_back({ refBinding, {} });
44 NodeContextDescriptorSetManager::IncreaseDescriptorSetCounts(refBinding, descriptorCounts, dynamicOffsetCount);
45 }
46 newSet.buffers.resize(descriptorCounts.bufferCount);
47 newSet.images.resize(descriptorCounts.imageCount);
48 newSet.samplers.resize(descriptorCounts.samplerCount);
49
50 newSet.dynamicOffsetDescriptors.resize(dynamicOffsetCount);
51 return newSet;
52 }
53
GetArrayOffset(const CpuDescriptorSet & data,const DescriptorSetLayoutBindingResource & res)54 constexpr uint32_t GetArrayOffset(const CpuDescriptorSet& data, const DescriptorSetLayoutBindingResource& res)
55 {
56 const RenderHandleType type = DescriptorSetBinderUtil::GetRenderHandleType(res.binding.descriptorType);
57 if (type == RenderHandleType::GPU_BUFFER) {
58 return data.buffers[res.resourceIndex].desc.arrayOffset;
59 }
60 if (type == RenderHandleType::GPU_IMAGE) {
61 return data.images[res.resourceIndex].desc.arrayOffset;
62 }
63 if (type == RenderHandleType::GPU_SAMPLER) {
64 return data.samplers[res.resourceIndex].desc.arrayOffset;
65 }
66 return 0u;
67 }
68
BindSampler(GpuResourceManager & gpuResourceMgr,const BindableSampler & res,Gles::Bind & obj,uint32_t index)69 inline void BindSampler(GpuResourceManager& gpuResourceMgr, const BindableSampler& res, Gles::Bind& obj, uint32_t index)
70 {
71 if (const auto* gpuSampler = gpuResourceMgr.GetSampler<GpuSamplerGLES>(res.handle)) {
72 const auto& plat = gpuSampler->GetPlatformData();
73 obj.resources[index].sampler.samplerId = plat.sampler;
74 } else {
75 obj.resources[index].sampler.samplerId = 0;
76 }
77 }
78
BindImage(GpuResourceManager & gpuResourceMgr_,const BindableImage & res,const GpuResourceState & resState,Gles::Bind & obj,uint32_t index)79 void BindImage(GpuResourceManager& gpuResourceMgr_, const BindableImage& res, const GpuResourceState& resState,
80 Gles::Bind& obj, uint32_t index)
81 {
82 const AccessFlags accessFlags = resState.accessFlags;
83 auto* gpuImage = gpuResourceMgr_.GetImage<GpuImageGLES>(res.handle);
84 auto& ref = obj.resources[index];
85 ref.image.image = gpuImage;
86 const bool read = (accessFlags & CORE_ACCESS_SHADER_READ_BIT) == CORE_ACCESS_SHADER_READ_BIT;
87 const bool write = (accessFlags & CORE_ACCESS_SHADER_WRITE_BIT) == CORE_ACCESS_SHADER_WRITE_BIT;
88 if (read && write) {
89 ref.image.mode = GL_READ_WRITE;
90 } else if (read) {
91 ref.image.mode = GL_READ_ONLY;
92 } else if (write) {
93 ref.image.mode = GL_WRITE_ONLY;
94 } else {
95 // no read and no write?
96 ref.image.mode = GL_READ_WRITE;
97 }
98 #if RENDER_HAS_GLES_BACKEND
99 if ((gpuImage) && (gpuImage->GetPlatformData().type == GL_TEXTURE_EXTERNAL_OES)) {
100 ref.image.mode |= Gles::EXTERNAL_BIT;
101 }
102 #endif
103 ref.image.mipLevel = res.mip;
104 }
105
BindImageSampler(GpuResourceManager & gpuResourceMgr,const BindableImage & res,const GpuResourceState & resState,Gles::Bind & obj,uint32_t index)106 inline void BindImageSampler(GpuResourceManager& gpuResourceMgr, const BindableImage& res,
107 const GpuResourceState& resState, Gles::Bind& obj, uint32_t index)
108 {
109 BindImage(gpuResourceMgr, res, resState, obj, index);
110 BindSampler(gpuResourceMgr, BindableSampler { res.samplerHandle }, obj, index);
111 }
112
BindBuffer(GpuResourceManager & gpuResourceMgr,const BindableBuffer & res,Gles::Bind & obj,uint32_t index)113 void BindBuffer(GpuResourceManager& gpuResourceMgr, const BindableBuffer& res, Gles::Bind& obj, uint32_t index)
114 {
115 if (const auto* gpuBuffer = gpuResourceMgr.GetBuffer<GpuBufferGLES>(res.handle)) {
116 const auto& plat = gpuBuffer->GetPlatformData();
117 const uint32_t baseOffset = res.byteOffset;
118 obj.resources[index].buffer.offset = baseOffset + plat.currentByteOffset;
119 obj.resources[index].buffer.size = Math::min(plat.bindMemoryByteSize - baseOffset, res.byteSize);
120 obj.resources[index].buffer.bufferId = plat.buffer;
121 } else {
122 obj.resources[index].buffer = {};
123 }
124 }
125
ConvertDescSetToResource(GpuResourceManager & gpuResMgr,const CpuDescriptorSet & srcSet,array_view<Gles::Bind> dst)126 void ConvertDescSetToResource(GpuResourceManager& gpuResMgr, const CpuDescriptorSet& srcSet, array_view<Gles::Bind> dst)
127 {
128 for (const auto& bindings : srcSet.bindings) {
129 auto& obj = dst[bindings.binding.binding];
130 const auto descriptorType = bindings.binding.descriptorType;
131 obj.descriptorType = descriptorType;
132 obj.resources.resize(bindings.binding.descriptorCount);
133
134 const bool hasArrOffset = (bindings.binding.descriptorCount > 1U);
135 const uint32_t arrayOffset = hasArrOffset ? GetArrayOffset(srcSet, bindings) : 0;
136 for (uint32_t index = 0; index < bindings.binding.descriptorCount; index++) {
137 const uint32_t resIdx = (index == 0) ? bindings.resourceIndex : (arrayOffset + index - 1);
138 switch (descriptorType) {
139 case CORE_DESCRIPTOR_TYPE_SAMPLER: {
140 const auto& samplerDescriptor = srcSet.samplers[resIdx].desc;
141 BindSampler(gpuResMgr, samplerDescriptor.resource, obj, index);
142 break;
143 }
144 case CORE_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
145 case CORE_DESCRIPTOR_TYPE_STORAGE_IMAGE:
146 case CORE_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
147 const auto& imageDescriptor = srcSet.images[resIdx].desc;
148 BindImage(gpuResMgr, imageDescriptor.resource, imageDescriptor.state, obj, index);
149 break;
150 }
151 case CORE_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
152 const auto& imageDescriptor = srcSet.images[resIdx].desc;
153 BindImageSampler(gpuResMgr, imageDescriptor.resource, imageDescriptor.state, obj, index);
154 break;
155 }
156 case CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
157 case CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
158 const auto& bufferDescriptor = srcSet.buffers[resIdx].desc;
159 BindBuffer(gpuResMgr, bufferDescriptor.resource, obj, index);
160 break;
161 }
162 case CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
163 case CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER: {
164 const auto& bufferDescriptor = srcSet.buffers[resIdx].desc;
165 BindBuffer(gpuResMgr, bufferDescriptor.resource, obj, index);
166 break;
167 }
168 case CORE_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
169 case CORE_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
170 case CORE_DESCRIPTOR_TYPE_MAX_ENUM:
171 default:
172 PLUGIN_ASSERT_MSG(false, "Unhandled descriptor type");
173 break;
174 }
175 }
176 }
177 }
178 } // namespace
179
DescriptorSetManagerGles(Device & device)180 DescriptorSetManagerGles::DescriptorSetManagerGles(Device& device) : DescriptorSetManager(device) {}
181
BeginFrame()182 void DescriptorSetManagerGles::BeginFrame()
183 {
184 DescriptorSetManager::BeginFrame();
185 }
186
BeginBackendFrame()187 void DescriptorSetManagerGles::BeginBackendFrame()
188 {
189 // handle write locking
190 // handle possible destruction
191 resources_.resize(descriptorSets_.size());
192 auto resourcesIt = resources_.begin();
193 for (const auto& descriptorSet : descriptorSets_) {
194 if (GlobalDescriptorSetBase* descriptorSetBase = descriptorSet.get(); descriptorSetBase) {
195 bool destroyDescriptorSets = true;
196 // if we have any descriptor sets in use we do not destroy the pool
197 for (auto& ref : descriptorSetBase->data) {
198 if (ref.renderHandleReference.GetRefCount() > 1) {
199 destroyDescriptorSets = false;
200 }
201 ref.frameWriteLocked = false;
202 }
203
204 if (destroyDescriptorSets) {
205 if (!descriptorSetBase->data.empty()) {
206 const RenderHandle handle = descriptorSetBase->data[0U].renderHandleReference.GetHandle();
207 // set handle (index location) to be available
208 availableHandles_.push_back(handle);
209 }
210 nameToIndex_.erase(descriptorSetBase->name);
211 *descriptorSetBase = {};
212 resourcesIt->clear();
213 } else {
214 resourcesIt->resize(descriptorSet->data.size());
215 }
216 }
217 ++resourcesIt;
218 }
219 }
220
CreateDescriptorSets(const uint32_t arrayIndex,const uint32_t descriptorSetCount,const array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings)221 void DescriptorSetManagerGles::CreateDescriptorSets(const uint32_t arrayIndex, const uint32_t descriptorSetCount,
222 const array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings)
223 {
224 PLUGIN_ASSERT((arrayIndex < descriptorSets_.size()) && (descriptorSets_[arrayIndex]));
225 PLUGIN_ASSERT(descriptorSets_[arrayIndex]->data.size() == descriptorSetCount);
226 if ((arrayIndex < descriptorSets_.size()) && (descriptorSets_[arrayIndex])) {
227 resources_.resize(descriptorSets_.size());
228 resources_[arrayIndex].resize(descriptorSetCount);
229 GlobalDescriptorSetBase* cpuData = descriptorSets_[arrayIndex].get();
230 for (uint32_t idx = 0; idx < descriptorSetCount; ++idx) {
231 const uint32_t additionalIndex = idx;
232 cpuData->data[additionalIndex].cpuDescriptorSet = CreateCpuDescriptorSetData(descriptorSetLayoutBindings);
233 }
234 }
235 }
236
UpdateDescriptorSetGpuHandle(const RenderHandle & handle)237 bool DescriptorSetManagerGles::UpdateDescriptorSetGpuHandle(const RenderHandle& handle)
238 {
239 // vulkan runs the inherited method, gles does not need it
240 const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
241 const uint32_t additionalIndex = RenderHandleUtil::GetAdditionalIndexPart(handle);
242 #if (RENDER_VALIDATION_ENABLED == 1)
243 PLUGIN_ASSERT(
244 RenderHandleUtil::GetAdditionalData(handle) == NodeContextDescriptorSetManager::GLOBAL_DESCRIPTOR_BIT);
245
246 if (arrayIndex >= static_cast<uint32_t>(descriptorSets_.size())) {
247 PLUGIN_LOG_E("invalid handle in descriptor set management");
248 }
249 #endif
250 auto& gpuResMgr = static_cast<GpuResourceManager&>(device_.GetGpuResourceManager());
251 if ((arrayIndex >= descriptorSets_.size()) || (!descriptorSets_[arrayIndex]) ||
252 (additionalIndex >= descriptorSets_[arrayIndex]->data.size())) {
253 return false;
254 }
255 const auto& srcSet = descriptorSets_[arrayIndex]->data[additionalIndex].cpuDescriptorSet;
256 auto& dst = resources_[arrayIndex][additionalIndex];
257 dst.resize(srcSet.bindings.size());
258 ConvertDescSetToResource(gpuResMgr, srcSet, dst);
259
260 return true;
261 }
262
UpdateCpuDescriptorSetPlatform(const DescriptorSetLayoutBindingResources & bindingResources)263 void DescriptorSetManagerGles::UpdateCpuDescriptorSetPlatform(
264 const DescriptorSetLayoutBindingResources& bindingResources)
265 {}
266
GetResources(RenderHandle handle) const267 array_view<const Gles::Bind> DescriptorSetManagerGles::GetResources(RenderHandle handle) const
268 {
269 const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
270 const uint32_t additionalIndex = RenderHandleUtil::GetAdditionalIndexPart(handle);
271 if (arrayIndex < resources_.size()) {
272 const auto& set = resources_[arrayIndex];
273 if (additionalIndex < set.size()) {
274 return set[additionalIndex];
275 }
276 }
277 return {};
278 }
279
NodeContextDescriptorSetManagerGles(Device & device)280 NodeContextDescriptorSetManagerGles::NodeContextDescriptorSetManagerGles(Device& device)
281 : NodeContextDescriptorSetManager(device), device_ { device }
282 {
283 PLUGIN_UNUSED(device_);
284 }
285
286 NodeContextDescriptorSetManagerGles::~NodeContextDescriptorSetManagerGles() = default;
287
ResetAndReserve(const DescriptorCounts & descriptorCounts)288 void NodeContextDescriptorSetManagerGles::ResetAndReserve(const DescriptorCounts& descriptorCounts)
289 {
290 NodeContextDescriptorSetManager::ResetAndReserve(descriptorCounts);
291 }
292
BeginFrame()293 void NodeContextDescriptorSetManagerGles::BeginFrame()
294 {
295 NodeContextDescriptorSetManager::BeginFrame();
296
297 #if (RENDER_VALIDATION_ENABLED == 1)
298 oneFrameDescSetGeneration_ = (oneFrameDescSetGeneration_ + 1) % MAX_ONE_FRAME_GENERATION_IDX;
299 #endif
300 }
301
CreateDescriptorSet(const array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings)302 RenderHandle NodeContextDescriptorSetManagerGles::CreateDescriptorSet(
303 const array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings)
304 {
305 RenderHandle clientHandle;
306 auto& cpuDescriptorSets = cpuDescriptorSets_[DESCRIPTOR_SET_INDEX_TYPE_STATIC];
307 #if (RENDER_VALIDATION_ENABLED == 1)
308 if (cpuDescriptorSets.size() >= maxSets_) {
309 PLUGIN_LOG_E("RENDER_VALIDATION: No more descriptor sets available");
310 }
311 #endif
312 if (cpuDescriptorSets.size() < maxSets_) {
313 const auto arrayIndex = (uint32_t)cpuDescriptorSets.size();
314 cpuDescriptorSets.push_back(CreateCpuDescriptorSetData(descriptorSetLayoutBindings));
315 auto& resources = resources_[DESCRIPTOR_SET_INDEX_TYPE_STATIC].emplace_back();
316 resources.resize(descriptorSetLayoutBindings.size());
317 // NOTE: can be used directly to index
318 clientHandle = RenderHandleUtil::CreateHandle(RenderHandleType::DESCRIPTOR_SET, arrayIndex, 0);
319 }
320 return clientHandle;
321 }
322
CreateOneFrameDescriptorSet(const array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings)323 RenderHandle NodeContextDescriptorSetManagerGles::CreateOneFrameDescriptorSet(
324 const array_view<const DescriptorSetLayoutBinding> descriptorSetLayoutBindings)
325 {
326 RenderHandle clientHandle;
327 auto& cpuDescriptorSets = cpuDescriptorSets_[DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME];
328
329 const auto arrayIndex = static_cast<uint32_t>(cpuDescriptorSets.size());
330 cpuDescriptorSets.push_back(CreateCpuDescriptorSetData(descriptorSetLayoutBindings));
331 auto& resources = resources_[DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME].emplace_back();
332 resources.resize(descriptorSetLayoutBindings.size());
333 // NOTE: can be used directly to index
334 clientHandle = RenderHandleUtil::CreateHandle(
335 RenderHandleType::DESCRIPTOR_SET, arrayIndex, oneFrameDescSetGeneration_, ONE_FRAME_DESC_SET_BIT);
336
337 return clientHandle;
338 }
339
UpdateDescriptorSetGpuHandle(const RenderHandle handle)340 bool NodeContextDescriptorSetManagerGles::UpdateDescriptorSetGpuHandle(const RenderHandle handle)
341 {
342 const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
343 const uint32_t oneFrameDescBit = RenderHandleUtil::GetAdditionalData(handle);
344 const uint32_t descSetIdx = (oneFrameDescBit & ONE_FRAME_DESC_SET_BIT) ? DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME
345 : DESCRIPTOR_SET_INDEX_TYPE_STATIC;
346 auto& cpuDescriptorSets = cpuDescriptorSets_[descSetIdx];
347 auto& resources = resources_[descSetIdx];
348 #if (RENDER_VALIDATION_ENABLED == 1)
349 if (arrayIndex >= static_cast<uint32_t>(cpuDescriptorSets.size())) {
350 PLUGIN_LOG_E("invalid handle in descriptor set management");
351 }
352 if (oneFrameDescBit & ONE_FRAME_DESC_SET_BIT) {
353 const uint32_t generationIndex = RenderHandleUtil::GetGenerationIndexPart(handle);
354 if (generationIndex != oneFrameDescSetGeneration_) {
355 PLUGIN_LOG_E(
356 "RENDER_VALIDATION: invalid one frame descriptor set handle generation. One frame descriptor sets can "
357 "only be used once.");
358 }
359 }
360 #endif
361 if (cpuDescriptorSets.size() > resources.size()) {
362 // This shouldn't happen unless CreateDescriptorSet hasn't been called.
363 resources.resize(cpuDescriptorSets.size());
364 }
365 const auto& srcSet = cpuDescriptorSets[arrayIndex];
366 auto& dst = resources[arrayIndex];
367 if (srcSet.bindings.size() > dst.size()) {
368 // This shouldn't happen unless CreateDescriptorSet hasn't been called.
369 dst.resize(srcSet.bindings.size());
370 }
371
372 auto& gpuResMgr = static_cast<GpuResourceManager&>(device_.GetGpuResourceManager());
373 ConvertDescSetToResource(gpuResMgr, srcSet, dst);
374
375 return true;
376 }
377
UpdateCpuDescriptorSetPlatform(const DescriptorSetLayoutBindingResources & bindingResources)378 void NodeContextDescriptorSetManagerGles::UpdateCpuDescriptorSetPlatform(
379 const DescriptorSetLayoutBindingResources& bindingResources)
380 {
381 // no op
382 }
383
GetResources(RenderHandle handle) const384 array_view<const Gles::Bind> NodeContextDescriptorSetManagerGles::GetResources(RenderHandle handle) const
385 {
386 const uint32_t additionalData = RenderHandleUtil::GetAdditionalData(handle);
387 if (additionalData & NodeContextDescriptorSetManager::GLOBAL_DESCRIPTOR_BIT) {
388 return static_cast<DescriptorSetManagerGles&>(globalDescriptorSetMgr_).GetResources(handle);
389 }
390
391 const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
392 const uint32_t oneFrameDescBit = RenderHandleUtil::GetAdditionalData(handle);
393 const uint32_t descSetIdx = (oneFrameDescBit & ONE_FRAME_DESC_SET_BIT) ? DESCRIPTOR_SET_INDEX_TYPE_ONE_FRAME
394 : DESCRIPTOR_SET_INDEX_TYPE_STATIC;
395
396 const auto& resources = resources_[descSetIdx];
397 if (arrayIndex < resources.size()) {
398 return resources[arrayIndex];
399 }
400 return {};
401 }
402 RENDER_END_NAMESPACE()
403