• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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