• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "render_node_default_material_objects.h"
17 
18 #include <3d/render/default_material_constants.h>
19 #include <3d/render/intf_render_data_store_default_material.h>
20 #include <base/containers/allocator.h>
21 #include <base/containers/type_traits.h>
22 #include <base/math/matrix.h>
23 #include <base/math/vector.h>
24 #include <core/log.h>
25 #include <core/namespace.h>
26 #include <render/datastore/intf_render_data_store.h>
27 #include <render/datastore/intf_render_data_store_manager.h>
28 #include <render/device/intf_gpu_resource_manager.h>
29 #include <render/device/pipeline_layout_desc.h>
30 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
31 #include <render/nodecontext/intf_render_command_list.h>
32 #include <render/nodecontext/intf_render_node_context_manager.h>
33 #include <render/resource_handle.h>
34 
35 namespace {
36 #include <3d/shaders/common/3d_dm_structures_common.h>
37 } // namespace
38 
39 CORE3D_BEGIN_NAMESPACE()
40 using namespace BASE_NS;
41 using namespace RENDER_NS;
42 
43 namespace {
44 constexpr uint32_t UBO_BIND_OFFSET_ALIGNMENT { PipelineLayoutConstants::MIN_UBO_BIND_OFFSET_ALIGNMENT_BYTE_SIZE };
45 constexpr uint32_t MIN_UBO_OBJECT_COUNT { CORE_UNIFORM_BUFFER_MAX_BIND_SIZE / UBO_BIND_OFFSET_ALIGNMENT };
46 constexpr uint32_t MIN_MATERIAL_DESC_SET_COUNT { 64U };
47 
48 constexpr GpuBufferDesc UBO_DESC { CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
49     (CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT | CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT),
50     CORE_ENGINE_BUFFER_CREATION_DYNAMIC_RING_BUFFER, 0U };
51 
Align(size_t value,size_t align)52 constexpr size_t Align(size_t value, size_t align)
53 {
54     if (value == 0) {
55         return 0;
56     }
57     return ((value + align) / align) * align;
58 }
59 
GetDefaultMaterialGpuResources(const IRenderNodeGpuResourceManager & gpuResourceMgr,RenderNodeDefaultMaterialObjects::MaterialHandleStruct & defaultMat)60 void GetDefaultMaterialGpuResources(const IRenderNodeGpuResourceManager& gpuResourceMgr,
61     RenderNodeDefaultMaterialObjects::MaterialHandleStruct& defaultMat)
62 {
63     defaultMat.resources[MaterialComponent::TextureIndex::BASE_COLOR].handle =
64         gpuResourceMgr.GetImageHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_MATERIAL_BASE_COLOR);
65     defaultMat.resources[MaterialComponent::TextureIndex::NORMAL].handle =
66         gpuResourceMgr.GetImageHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_MATERIAL_NORMAL);
67     defaultMat.resources[MaterialComponent::TextureIndex::MATERIAL].handle =
68         gpuResourceMgr.GetImageHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_MATERIAL_MATERIAL);
69     defaultMat.resources[MaterialComponent::TextureIndex::EMISSIVE].handle =
70         gpuResourceMgr.GetImageHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_MATERIAL_EMISSIVE);
71     defaultMat.resources[MaterialComponent::TextureIndex::AO].handle =
72         gpuResourceMgr.GetImageHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_MATERIAL_AO);
73 
74     defaultMat.resources[MaterialComponent::TextureIndex::CLEARCOAT].handle =
75         gpuResourceMgr.GetImageHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_MATERIAL_CLEARCOAT);
76     defaultMat.resources[MaterialComponent::TextureIndex::CLEARCOAT_ROUGHNESS].handle =
77         gpuResourceMgr.GetImageHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_MATERIAL_CLEARCOAT_ROUGHNESS);
78     defaultMat.resources[MaterialComponent::TextureIndex::CLEARCOAT_NORMAL].handle =
79         gpuResourceMgr.GetImageHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_MATERIAL_CLEARCOAT_NORMAL);
80 
81     defaultMat.resources[MaterialComponent::TextureIndex::SHEEN].handle =
82         gpuResourceMgr.GetImageHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_MATERIAL_SHEEN);
83 
84     defaultMat.resources[MaterialComponent::TextureIndex::TRANSMISSION].handle =
85         gpuResourceMgr.GetImageHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_MATERIAL_TRANSMISSION);
86 
87     defaultMat.resources[MaterialComponent::TextureIndex::SPECULAR].handle =
88         gpuResourceMgr.GetImageHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_MATERIAL_SPECULAR);
89 
90     const RenderHandle samplerHandle = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_MIPMAP_REPEAT");
91     for (uint32_t idx = 0; idx < countof(defaultMat.resources); ++idx) {
92         defaultMat.resources[idx].samplerHandle = samplerHandle;
93     }
94 }
95 
96 // returns if there were changes and needs a descriptor set update
UpdateCurrentMaterialHandles(IRenderNodeGpuResourceManager & gpuResourceMgr,const bool forceUpdate,const RenderNodeDefaultMaterialObjects::MaterialHandleStruct & defaultMat,const RenderDataDefaultMaterial::MaterialHandles & matHandles,RenderNodeDefaultMaterialObjects::MaterialHandleStruct & storedMaterialHandles)97 bool UpdateCurrentMaterialHandles(IRenderNodeGpuResourceManager& gpuResourceMgr, const bool forceUpdate,
98     const RenderNodeDefaultMaterialObjects::MaterialHandleStruct& defaultMat,
99     const RenderDataDefaultMaterial::MaterialHandles& matHandles,
100     RenderNodeDefaultMaterialObjects::MaterialHandleStruct& storedMaterialHandles)
101 {
102     RenderNodeDefaultMaterialObjects::MaterialHandleStruct currMaterialHandles;
103     bool hasChanges = false;
104     for (uint32_t idx = 0; idx < countof(matHandles.images); ++idx) {
105         const auto& defaultRes = defaultMat.resources[idx];
106         const auto& srcImage = matHandles.images[idx];
107         const auto& srcSampler = matHandles.samplers[idx];
108         auto& dst = currMaterialHandles.resources[idx];
109 
110         // fetch updated with generation counter raw handles
111         if (RenderHandleUtil::IsValid(srcImage)) {
112             dst.handle = gpuResourceMgr.GetRawHandle(srcImage);
113         } else {
114             dst.handle = defaultRes.handle;
115         }
116         if (RenderHandleUtil::IsValid(srcSampler)) {
117             dst.samplerHandle = gpuResourceMgr.GetRawHandle(srcSampler);
118         } else {
119             dst.samplerHandle = defaultRes.samplerHandle;
120         }
121 
122         // check if there are changes
123         auto& stored = storedMaterialHandles.resources[idx];
124         if ((stored.handle != dst.handle) || (stored.samplerHandle != dst.samplerHandle) ||
125             (dst.handle.id & RenderHandleUtil::RENDER_HANDLE_NEEDS_UPDATE_MASK)) {
126             hasChanges = true;
127             stored.handle = dst.handle;
128             stored.samplerHandle = dst.samplerHandle;
129         }
130     }
131     return hasChanges;
132 }
133 } // namespace
134 
InitNode(IRenderNodeContextManager & renderNodeContextMgr)135 void RenderNodeDefaultMaterialObjects::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
136 {
137     renderNodeContextMgr_ = &renderNodeContextMgr;
138     globalDescs_ = {};
139 
140     const auto& renderNodeGraphData = renderNodeContextMgr_->GetRenderNodeGraphData();
141     stores_ = RenderNodeSceneUtil::GetSceneRenderDataStores(
142         renderNodeContextMgr, renderNodeGraphData.renderNodeGraphDataStoreName);
143 
144     const auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
145     const auto& shaderMgr = renderNodeContextMgr_->GetShaderManager();
146     const RenderHandle defaultPlHandle =
147         shaderMgr.GetPipelineLayoutHandle(DefaultMaterialShaderConstants::PIPELINE_LAYOUT_FORWARD);
148     defaultMaterialPipelineLayout_ = shaderMgr.GetPipelineLayout(defaultPlHandle);
149     GetDefaultMaterialGpuResources(gpuResourceMgr, defaultMaterialStruct_);
150 
151     ProcessBuffers({ 1u, 1u, 1u, 1u });
152 }
153 
PreExecuteFrame()154 void RenderNodeDefaultMaterialObjects::PreExecuteFrame()
155 {
156     // re-create needed gpu resources
157     const auto& renderDataStoreMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
158     const IRenderDataStoreDefaultMaterial* dataStoreMaterial = static_cast<IRenderDataStoreDefaultMaterial*>(
159         renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameMaterial));
160     // we need to have all buffers created (reason to have at least 1u)
161     if (dataStoreMaterial) {
162         const auto dsOc = dataStoreMaterial->GetObjectCounts();
163         const ObjectCounts oc {
164             Math::max(dsOc.meshCount, 1u),
165             Math::max(dsOc.submeshCount, 1u),
166             Math::max(dsOc.skinCount, 1u),
167             Math::max(dsOc.materialCount, 1u),
168             Math::max(dsOc.uniqueMaterialCount, 1u),
169         };
170         ProcessBuffers(oc);
171     } else {
172         ProcessBuffers({ 1u, 1u, 1u, 1u, 1u });
173     }
174 }
175 
ExecuteFrame(IRenderCommandList & cmdList)176 void RenderNodeDefaultMaterialObjects::ExecuteFrame(IRenderCommandList& cmdList)
177 {
178     const auto& renderDataStoreMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
179     const auto* dataStoreMaterial = static_cast<IRenderDataStoreDefaultMaterial*>(
180         renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameMaterial));
181 
182     if (dataStoreMaterial) {
183         UpdateBuffers(*dataStoreMaterial);
184         UpdateDescriptorSets(cmdList, *dataStoreMaterial);
185     } else {
186         CORE_LOG_E("invalid render data store in RenderNodeDefaultMaterialObjects");
187     }
188 }
189 
UpdateBuffers(const IRenderDataStoreDefaultMaterial & dataStoreMaterial)190 void RenderNodeDefaultMaterialObjects::UpdateBuffers(const IRenderDataStoreDefaultMaterial& dataStoreMaterial)
191 {
192     UpdateMeshBuffer(dataStoreMaterial);
193     UpdateSkinBuffer(dataStoreMaterial);
194     UpdateMaterialBuffers(dataStoreMaterial);
195 }
196 
UpdateMeshBuffer(const IRenderDataStoreDefaultMaterial & dataStoreMaterial)197 void RenderNodeDefaultMaterialObjects::UpdateMeshBuffer(const IRenderDataStoreDefaultMaterial& dataStoreMaterial)
198 {
199     IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
200     // mesh data is copied to single buffer with UBO_BIND_OFFSET_ALIGNMENT alignments
201     if (auto meshDataPtr = reinterpret_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ubos_.mesh.GetHandle())); meshDataPtr) {
202         constexpr uint32_t meshByteSize = sizeof(DefaultMaterialSingleMeshStruct);
203         CORE_STATIC_ASSERT(meshByteSize >= UBO_BIND_OFFSET_ALIGNMENT);
204         CORE_STATIC_ASSERT(sizeof(RenderMeshData) == sizeof(DefaultMaterialSingleMeshStruct));
205         const auto* meshDataPtrEnd = meshDataPtr + meshByteSize * objectCounts_.maxMeshCount;
206         if (const auto meshData = dataStoreMaterial.GetMeshData(); !meshData.empty()) {
207             // clone all at once, they are in order
208             const size_t cloneByteSize = meshData.size_bytes();
209             if (!CloneData(meshDataPtr, size_t(meshDataPtrEnd - meshDataPtr), meshData.data(), cloneByteSize)) {
210                 CORE_LOG_I("meshData ubo copying failed");
211             }
212         }
213 
214         gpuResourceMgr.UnmapBuffer(ubos_.mesh.GetHandle());
215     }
216 }
217 
UpdateSkinBuffer(const IRenderDataStoreDefaultMaterial & dataStoreMaterial)218 void RenderNodeDefaultMaterialObjects::UpdateSkinBuffer(const IRenderDataStoreDefaultMaterial& dataStoreMaterial)
219 {
220     IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
221     // skindata is copied to a single buffer with sizeof(DefaultMaterialSkinStruct) offset
222     // skin offset for submesh is calculated submesh.skinIndex * sizeof(DefaultMaterialSkinStruct)
223     // NOTE: the size could be optimized, but render data store should calculate correct size with alignment
224     if (auto skinData = reinterpret_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ubos_.submeshSkin.GetHandle())); skinData) {
225         CORE_STATIC_ASSERT(
226             RenderDataDefaultMaterial::MAX_SKIN_MATRIX_COUNT * 2u == CORE_DEFAULT_MATERIAL_MAX_JOINT_COUNT);
227         const auto* skinDataEnd = skinData + sizeof(DefaultMaterialSkinStruct) * objectCounts_.maxSkinCount;
228         const auto meshJointMatrices = dataStoreMaterial.GetMeshJointMatrices();
229         for (const auto& jointRef : meshJointMatrices) {
230             // we copy first current frame matrices, then previous frame
231             const size_t copyCount = static_cast<size_t>(jointRef.count / 2u);
232             const size_t copySize = copyCount * sizeof(Math::Mat4X4);
233             const size_t ptrOffset = CORE_DEFAULT_MATERIAL_PREV_JOINT_OFFSET * sizeof(Math::Mat4X4);
234             if (!CloneData(skinData, size_t(skinDataEnd - skinData), jointRef.data, copySize)) {
235                 CORE_LOG_I("skinData ubo copying failed");
236             }
237             if (!CloneData(skinData + ptrOffset, size_t(skinDataEnd - (skinData + ptrOffset)),
238                     jointRef.data + copyCount, copySize)) {
239                 CORE_LOG_I("skinData ubo copying failed");
240             }
241             skinData = skinData + sizeof(DefaultMaterialSkinStruct);
242         }
243 
244         gpuResourceMgr.UnmapBuffer(ubos_.submeshSkin.GetHandle());
245     }
246 }
247 
UpdateMaterialBuffers(const IRenderDataStoreDefaultMaterial & dataStoreMaterial)248 void RenderNodeDefaultMaterialObjects::UpdateMaterialBuffers(const IRenderDataStoreDefaultMaterial& dataStoreMaterial)
249 {
250     IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
251     // material data is copied to single buffer with UBO_BIND_OFFSET_ALIGNMENT alignment
252     auto matFactorData = reinterpret_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ubos_.mat.GetHandle()));
253     auto matTransformData = reinterpret_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ubos_.matTransform.GetHandle()));
254     auto userMaterialData = reinterpret_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ubos_.userMat.GetHandle()));
255     if (!matFactorData || !matTransformData || !userMaterialData) {
256         return;
257     }
258     const auto* matFactorDataEnd = matFactorData + UBO_BIND_OFFSET_ALIGNMENT * objectCounts_.maxMaterialCount;
259     const auto* matTransformDataEnd = matTransformData + UBO_BIND_OFFSET_ALIGNMENT * objectCounts_.maxMaterialCount;
260     const auto* userMaterialDataEnd = userMaterialData + UBO_BIND_OFFSET_ALIGNMENT * objectCounts_.maxMaterialCount;
261     const auto materialUniforms = dataStoreMaterial.GetMaterialUniforms();
262     const auto materialFrameIndices = dataStoreMaterial.GetMaterialFrameIndices();
263     for (uint32_t matOff = 0; matOff < materialFrameIndices.size(); ++matOff) {
264         const uint32_t matIdx = materialFrameIndices[matOff];
265         if (matIdx >= materialUniforms.size()) {
266             continue;
267         }
268 
269         const RenderDataDefaultMaterial::AllMaterialUniforms& uniforms = materialUniforms[matIdx];
270         if (!CloneData(matFactorData, size_t(matFactorDataEnd - matFactorData), &uniforms.factors,
271                 sizeof(RenderDataDefaultMaterial::MaterialUniforms))) {
272             CORE_LOG_I("materialFactorData ubo copying failed");
273         }
274         if (!CloneData(matTransformData, size_t(matTransformDataEnd - matTransformData), &uniforms.transforms,
275                 sizeof(RenderDataDefaultMaterial::MaterialPackedUniforms))) {
276             CORE_LOG_I("materialTransformData ubo copying failed");
277         }
278         const auto materialCustomProperties = dataStoreMaterial.GetMaterialCustomPropertyData(matIdx);
279         if (!materialCustomProperties.empty()) {
280             CORE_ASSERT(materialCustomProperties.size_bytes() <= UBO_BIND_OFFSET_ALIGNMENT);
281             if (!CloneData(userMaterialData, size_t(userMaterialDataEnd - userMaterialData),
282                     materialCustomProperties.data(), materialCustomProperties.size_bytes())) {
283                 CORE_LOG_I("userMaterialData ubo copying failed");
284             }
285         }
286         matFactorData = matFactorData + UBO_BIND_OFFSET_ALIGNMENT;
287         matTransformData = matTransformData + UBO_BIND_OFFSET_ALIGNMENT;
288         userMaterialData = userMaterialData + UBO_BIND_OFFSET_ALIGNMENT;
289     }
290 
291     gpuResourceMgr.UnmapBuffer(ubos_.mat.GetHandle());
292     gpuResourceMgr.UnmapBuffer(ubos_.matTransform.GetHandle());
293     gpuResourceMgr.UnmapBuffer(ubos_.userMat.GetHandle());
294 }
295 
UpdateDescriptorSets(IRenderCommandList & cmdList,const IRenderDataStoreDefaultMaterial & dataStoreMaterial)296 void RenderNodeDefaultMaterialObjects::UpdateDescriptorSets(
297     IRenderCommandList& cmdList, const IRenderDataStoreDefaultMaterial& dataStoreMaterial)
298 {
299     // loop through all materials at the moment
300     {
301         const auto& materialHandles = dataStoreMaterial.GetMaterialHandles();
302         CORE_ASSERT(materialHandles.size() <= globalDescs_.descriptorSets.size());
303         CORE_ASSERT(globalDescs_.descriptorSets.size() == globalDescs_.materials.size());
304         IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
305         for (size_t idx = 0; idx < materialHandles.size(); ++idx) {
306             auto* binder = globalDescs_.descriptorSets[idx].get();
307             if (binder && (idx < materialHandles.size())) {
308                 const auto& matHandles = materialHandles[idx];
309                 MaterialHandleStruct& storedMatHandles = globalDescs_.materials[idx];
310                 const bool updateDescSet = UpdateCurrentMaterialHandles(
311                     gpuResourceMgr, globalDescs_.forceUpdate, defaultMaterialStruct_, matHandles, storedMatHandles);
312                 if (globalDescs_.forceUpdate || updateDescSet) {
313                     uint32_t bindingIdx = 0u;
314                     // base color is bound separately to support automatic hwbuffer/OES shader modification
315                     binder->BindImage(
316                         bindingIdx++, storedMatHandles.resources[MaterialComponent::TextureIndex::BASE_COLOR]);
317 
318                     CORE_STATIC_ASSERT(MaterialComponent::TextureIndex::BASE_COLOR == 0);
319                     // skip baseColor as it's bound already
320                     constexpr size_t theCount = RenderDataDefaultMaterial::MATERIAL_TEXTURE_COUNT - 1;
321                     binder->BindImages(bindingIdx++, array_view(storedMatHandles.resources + 1, theCount));
322 
323                     cmdList.UpdateDescriptorSet(
324                         binder->GetDescriptorSetHandle(), binder->GetDescriptorSetLayoutBindingResources());
325                 }
326             }
327         }
328         globalDescs_.forceUpdate = false;
329     }
330     if (auto* binder = globalDescs_.dmSet1Binder.get(); binder) {
331         // NOTE: should be PipelineLayoutConstants::MAX_UBO_BIND_BYTE_SIZE or current size
332         constexpr uint32_t skinSize = sizeof(DefaultMaterialSkinStruct);
333         uint32_t bindingIdx = 0u;
334         binder->BindBuffer(bindingIdx++, ubos_.mesh.GetHandle(), 0U, PipelineLayoutConstants::MAX_UBO_BIND_BYTE_SIZE);
335         binder->BindBuffer(bindingIdx++, ubos_.submeshSkin.GetHandle(), 0U, skinSize);
336         binder->BindBuffer(bindingIdx++, ubos_.mat.GetHandle(), 0U, PipelineLayoutConstants::MAX_UBO_BIND_BYTE_SIZE);
337         binder->BindBuffer(
338             bindingIdx++, ubos_.matTransform.GetHandle(), 0U, PipelineLayoutConstants::MAX_UBO_BIND_BYTE_SIZE);
339         binder->BindBuffer(
340             bindingIdx++, ubos_.userMat.GetHandle(), 0U, PipelineLayoutConstants::MAX_UBO_BIND_BYTE_SIZE);
341         cmdList.UpdateDescriptorSet(binder->GetDescriptorSetHandle(), binder->GetDescriptorSetLayoutBindingResources());
342     }
343     // update only once
344     if (!globalDescs_.dmSet2Ready) {
345         if (auto* binder = globalDescs_.dmSet2Binder.get(); binder) {
346             uint32_t bindingIdx = 0u;
347             // base color is bound separately to support automatic hwbuffer/OES shader modification
348             binder->BindImage(
349                 bindingIdx++, defaultMaterialStruct_.resources[MaterialComponent::TextureIndex::BASE_COLOR]);
350 
351             CORE_STATIC_ASSERT(MaterialComponent::TextureIndex::BASE_COLOR == 0);
352             // skip baseColor as it's bound already
353             constexpr size_t theCount = RenderDataDefaultMaterial::MATERIAL_TEXTURE_COUNT - 1;
354             binder->BindImages(bindingIdx++, array_view(defaultMaterialStruct_.resources + 1, theCount));
355 
356             cmdList.UpdateDescriptorSet(
357                 binder->GetDescriptorSetHandle(), binder->GetDescriptorSetLayoutBindingResources());
358             globalDescs_.dmSet2Ready = true;
359         }
360     }
361 }
362 
ProcessBuffers(const ObjectCounts & objectCounts)363 void RenderNodeDefaultMaterialObjects::ProcessBuffers(const ObjectCounts& objectCounts)
364 {
365     auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
366     constexpr uint32_t overEstimate { 16u };
367     constexpr uint32_t baseStructSize = CORE_UNIFORM_BUFFER_MAX_BIND_SIZE;
368     constexpr uint32_t singleComponentStructSize = UBO_BIND_OFFSET_ALIGNMENT;
369     const string_view us = stores_.dataStoreNameScene;
370     GpuBufferDesc bDesc = UBO_DESC;
371     // instancing utilization for mesh and materials
372     if (objectCounts_.maxMeshCount < objectCounts.maxMeshCount) {
373         // mesh matrix uses max ubo bind size to utilize gpu instancing
374         CORE_STATIC_ASSERT(sizeof(DefaultMaterialMeshStruct) <= PipelineLayoutConstants::MAX_UBO_BIND_BYTE_SIZE);
375         objectCounts_.maxMeshCount =
376             objectCounts.maxMeshCount + (objectCounts.maxMeshCount / overEstimate) + MIN_UBO_OBJECT_COUNT;
377 
378         const uint32_t byteSize =
379             static_cast<uint32_t>(Align(objectCounts_.maxMeshCount * singleComponentStructSize, baseStructSize));
380         objectCounts_.maxMeshCount = (byteSize / singleComponentStructSize) - MIN_UBO_OBJECT_COUNT;
381         CORE_ASSERT((int32_t(byteSize / singleComponentStructSize) - int32_t(MIN_UBO_OBJECT_COUNT)) > 0);
382 
383         bDesc.byteSize = byteSize;
384         ubos_.mesh = gpuResourceMgr.Create(us + DefaultMaterialMaterialConstants::MESH_DATA_BUFFER_NAME, bDesc);
385     }
386     if (objectCounts_.maxSkinCount < objectCounts.maxSkinCount) {
387         objectCounts_.maxSkinCount = objectCounts.maxSkinCount + (objectCounts.maxSkinCount / overEstimate);
388 
389         bDesc.byteSize = static_cast<uint32_t>(sizeof(DefaultMaterialSkinStruct)) * objectCounts_.maxSkinCount;
390         ubos_.submeshSkin = gpuResourceMgr.Create(us + DefaultMaterialMaterialConstants::SKIN_DATA_BUFFER_NAME, bDesc);
391     }
392     if (objectCounts_.maxMaterialCount < objectCounts.maxMaterialCount) {
393         CORE_STATIC_ASSERT(sizeof(RenderDataDefaultMaterial::MaterialUniforms) <= UBO_BIND_OFFSET_ALIGNMENT);
394         objectCounts_.maxMaterialCount =
395             objectCounts.maxMaterialCount + (objectCounts.maxMaterialCount / overEstimate) + MIN_UBO_OBJECT_COUNT;
396 
397         const uint32_t byteSize =
398             static_cast<uint32_t>(Align(objectCounts_.maxMaterialCount * singleComponentStructSize, baseStructSize));
399         objectCounts_.maxMaterialCount = (byteSize / singleComponentStructSize) - MIN_UBO_OBJECT_COUNT;
400         CORE_ASSERT((int32_t(byteSize / singleComponentStructSize) - int32_t(MIN_UBO_OBJECT_COUNT)) > 0);
401 
402         bDesc.byteSize = byteSize;
403         ubos_.mat = gpuResourceMgr.Create(us + DefaultMaterialMaterialConstants::MATERIAL_DATA_BUFFER_NAME, bDesc);
404         ubos_.matTransform =
405             gpuResourceMgr.Create(us + DefaultMaterialMaterialConstants::MATERIAL_TRANSFORM_DATA_BUFFER_NAME, bDesc);
406         ubos_.userMat =
407             gpuResourceMgr.Create(us + DefaultMaterialMaterialConstants::MATERIAL_USER_DATA_BUFFER_NAME, bDesc);
408     }
409     if (objectCounts_.maxUniqueMaterialCount < objectCounts.maxUniqueMaterialCount) {
410         CORE_STATIC_ASSERT(sizeof(RenderDataDefaultMaterial::MaterialUniforms) <= UBO_BIND_OFFSET_ALIGNMENT);
411         objectCounts_.maxUniqueMaterialCount = objectCounts.maxUniqueMaterialCount +
412                                                (objectCounts.maxUniqueMaterialCount / overEstimate) +
413                                                MIN_MATERIAL_DESC_SET_COUNT;
414         objectCounts_.maxUniqueMaterialCount =
415             static_cast<uint32_t>(Align(objectCounts_.maxUniqueMaterialCount, MIN_MATERIAL_DESC_SET_COUNT));
416         // global descriptor sets
417         INodeContextDescriptorSetManager& dsMgr = renderNodeContextMgr_->GetDescriptorSetManager();
418         constexpr uint32_t set = 2U;
419         globalDescs_.handles.clear();
420         globalDescs_.descriptorSets.clear();
421         globalDescs_.forceUpdate = true;
422         const auto& bindings = defaultMaterialPipelineLayout_.descriptorSetLayouts[set].bindings;
423         globalDescs_.handles = dsMgr.CreateGlobalDescriptorSets(
424             us + DefaultMaterialMaterialConstants::MATERIAL_RESOURCES_GLOBAL_DESCRIPTOR_SET_NAME, bindings,
425             objectCounts_.maxUniqueMaterialCount);
426         globalDescs_.descriptorSets.resize(globalDescs_.handles.size());
427         globalDescs_.materials.resize(globalDescs_.handles.size());
428         for (size_t idx = 0; idx < globalDescs_.handles.size(); ++idx) {
429             globalDescs_.descriptorSets[idx] =
430                 dsMgr.CreateDescriptorSetBinder(globalDescs_.handles[idx].GetHandle(), bindings);
431         }
432     }
433     ProcessGlobalBinders();
434 }
435 
ProcessGlobalBinders()436 void RenderNodeDefaultMaterialObjects::ProcessGlobalBinders()
437 {
438     if (!globalDescs_.dmSet1Binder) {
439         const string_view us = stores_.dataStoreNameScene;
440         INodeContextDescriptorSetManager& dsMgr = renderNodeContextMgr_->GetDescriptorSetManager();
441         globalDescs_.dmSet1 = {};
442         globalDescs_.dmSet1Binder = {};
443         constexpr uint32_t set = 1U;
444         const auto& bindings = defaultMaterialPipelineLayout_.descriptorSetLayouts[set].bindings;
445         globalDescs_.dmSet1 = dsMgr.CreateGlobalDescriptorSet(
446             us + DefaultMaterialMaterialConstants::MATERIAL_SET1_GLOBAL_DESCRIPTOR_SET_NAME, bindings);
447         globalDescs_.dmSet1Binder = dsMgr.CreateDescriptorSetBinder(globalDescs_.dmSet1.GetHandle(), bindings);
448     }
449     if (!globalDescs_.dmSet2Binder) {
450         const string_view us = stores_.dataStoreNameScene;
451         INodeContextDescriptorSetManager& dsMgr = renderNodeContextMgr_->GetDescriptorSetManager();
452         globalDescs_.dmSet2 = {};
453         globalDescs_.dmSet2Binder = {};
454         constexpr uint32_t set = 2U;
455         const auto& bindings = defaultMaterialPipelineLayout_.descriptorSetLayouts[set].bindings;
456         globalDescs_.dmSet2 = dsMgr.CreateGlobalDescriptorSet(
457             us + DefaultMaterialMaterialConstants::MATERIAL_DEFAULT_RESOURCE_GLOBAL_DESCRIPTOR_SET_NAME, bindings);
458         globalDescs_.dmSet2Binder = dsMgr.CreateDescriptorSetBinder(globalDescs_.dmSet2.GetHandle(), bindings);
459     }
460 }
461 
462 // for plugin / factory interface
Create()463 RENDER_NS::IRenderNode* RenderNodeDefaultMaterialObjects::Create()
464 {
465     return new RenderNodeDefaultMaterialObjects();
466 }
467 
Destroy(IRenderNode * instance)468 void RenderNodeDefaultMaterialObjects::Destroy(IRenderNode* instance)
469 {
470     delete static_cast<RenderNodeDefaultMaterialObjects*>(instance);
471 }
472 CORE3D_END_NAMESPACE()
473