• 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 "graphics_context.h"
17 
18 #include <algorithm>
19 
20 #include <base/containers/string_view.h>
21 #include <base/containers/unordered_map.h>
22 #include <base/util/uid.h>
23 #include <core/ecs/intf_ecs.h>
24 #include <core/ecs/intf_entity_manager.h>
25 #include <core/intf_engine.h>
26 #include <core/io/intf_file_manager.h>
27 #include <core/log.h>
28 #include <core/perf/cpu_perf_scope.h>
29 #include <core/plugin/intf_plugin.h>
30 #include <core/plugin/intf_plugin_register.h>
31 #include <core/property/intf_property_handle.h>
32 #include <render/datastore/intf_render_data_store_manager.h>
33 #include <render/datastore/intf_render_data_store_pod.h>
34 #include <render/device/intf_device.h>
35 #include <render/device/intf_gpu_resource_manager.h>
36 #include <render/device/intf_shader_manager.h>
37 #include <render/implementation_uids.h>
38 #include <render/intf_plugin.h>
39 #include <render/intf_render_context.h>
40 #include <render/loader/intf_render_data_configuration_loader.h>
41 #include <render/nodecontext/intf_render_node_graph_manager.h>
42 
43 #if (RENDER_HAS_VULKAN_BACKEND)
44 #include <render/vulkan/intf_device_vk.h>
45 #endif
46 
47 #include <3d/ecs/components/material_component.h>
48 #include <3d/ecs/components/uri_component.h>
49 #include <3d/ecs/systems/intf_render_system.h>
50 #include <3d/implementation_uids.h>
51 #include <3d/intf_plugin.h>
52 #include <3d/loaders/intf_scene_loader.h>
53 #include <3d/render/default_material_constants.h>
54 #include <3d/render/intf_render_node_scene_util.h>
55 #include <3d/util/intf_mesh_util.h>
56 #include <3d/util/intf_scene_util.h>
57 
58 #include "gltf/gltf2.h"
59 #include "render/render_node_scene_util.h"
60 #include "util/log.h"
61 #include "util/mesh_builder.h"
62 #include "util/mesh_util.h"
63 #include "util/picking.h"
64 #include "util/render_util.h"
65 #include "util/scene_util.h"
66 #include "util/uri_lookup.h"
67 
68 extern "C" void InitRegistry(CORE_NS::IPluginRegister& pluginRegistry);
69 
70 CORE3D_BEGIN_NAMESPACE()
71 using namespace BASE_NS;
72 using namespace CORE_NS;
73 using namespace RENDER_NS;
74 
75 namespace {
76 struct RegisterPathStrings {
77     string_view protocol;
78     string_view uri;
79 };
80 static constexpr RegisterPathStrings RENDER_DATA_PATHS[] = {
81     { "3dshaders", "rofs3D://shaders/" },
82     { "3dshaderstates", "rofs3D://shaderstates/" },
83     { "3dvertexinputdeclarations", "rofs3D://vertexinputdeclarations/" },
84     { "3dpipelinelayouts", "rofs3D://pipelinelayouts/" },
85     { "3drenderdataconfigurations", "rofs3D://renderdataconfigurations/" },
86     { "3drendernodegraphs", "rofs3D://rendernodegraphs/" },
87 };
88 
89 static constexpr IShaderManager::ShaderFilePathDesc SHADER_FILE_PATHS {
90     "3dshaders://",
91     "3dshaderstates://",
92     "3dpipelinelayouts://",
93     "3dvertexinputdeclarations://",
94 };
95 
96 static constexpr string_view POST_PROCESS_PATH { "3drenderdataconfigurations://postprocess/" };
97 static constexpr string_view POST_PROCESS_DATA_STORE_NAME { "RenderDataStorePod" };
98 static constexpr string_view POST_PROCESS_NAME { "PostProcess" };
99 
LogCore3dBuildInfo()100 void LogCore3dBuildInfo()
101 {
102 #define CORE3D_TO_STRING_INTERNAL(x) #x
103 #define CORE3D_TO_STRING(x) CORE3D_TO_STRING_INTERNAL(x)
104 
105     CORE_LOG_I("CORE3D_VALIDATION_ENABLED=" CORE3D_TO_STRING(CORE3D_VALIDATION_ENABLED));
106     CORE_LOG_I("CORE3D_DEV_ENABLED=" CORE3D_TO_STRING(CORE3D_DEV_ENABLED));
107 }
108 
CreateDefaultImages(IDevice & device,vector<RenderHandleReference> & defaultGpuResources)109 void CreateDefaultImages(IDevice& device, vector<RenderHandleReference>& defaultGpuResources)
110 {
111     IGpuResourceManager& gpuResourceMgr = device.GetGpuResourceManager();
112 
113     // default material gpu images
114     GpuImageDesc desc { ImageType::CORE_IMAGE_TYPE_2D, ImageViewType::CORE_IMAGE_VIEW_TYPE_2D,
115         Format::BASE_FORMAT_R8G8B8A8_SRGB, ImageTiling::CORE_IMAGE_TILING_OPTIMAL,
116         ImageUsageFlagBits::CORE_IMAGE_USAGE_SAMPLED_BIT | ImageUsageFlagBits::CORE_IMAGE_USAGE_TRANSFER_DST_BIT,
117         MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, 0, 2, 2, 1, 1, 1,
118         SampleCountFlagBits::CORE_SAMPLE_COUNT_1_BIT, {} };
119     constexpr uint32_t sizeOfUint32 = sizeof(uint32_t);
120 
121     desc.format = Format::BASE_FORMAT_R8G8B8A8_UNORM;
122     {
123         constexpr const uint32_t normalData[4u] = { 0xFFFF7f7f, 0xFFFF7f7f, 0xFFFF7f7f, 0xFFFF7f7f };
124         const auto normalDataView =
125             array_view(reinterpret_cast<const uint8_t*>(normalData), sizeOfUint32 * countof(normalData));
126         defaultGpuResources.push_back(gpuResourceMgr.Create(
127             DefaultMaterialGpuResourceConstants::CORE_DEFAULT_MATERIAL_NORMAL, desc, normalDataView));
128     }
129 
130     desc.format = Format::BASE_FORMAT_R8_UNORM;
131     {
132         constexpr const uint8_t byteData[4u] = { 0xff, 0xff, 0xff, 0xff };
133         const auto byteDataView =
134             array_view(reinterpret_cast<const uint8_t*>(byteData), sizeof(uint8_t) * countof(byteData));
135         defaultGpuResources.push_back(
136             gpuResourceMgr.Create(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_MATERIAL_AO, desc, byteDataView));
137     }
138 
139     // env cubemaps
140     desc.imageViewType = ImageViewType::CORE_IMAGE_VIEW_TYPE_CUBE;
141     desc.format = Format::BASE_FORMAT_R8G8B8A8_SRGB;
142     desc.createFlags = ImageCreateFlagBits::CORE_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
143     desc.layerCount = 6u;
144     {
145         // Env color is currently in rgbd format (alpha channel is used as a divider for the rgb values).
146         const vector<uint32_t> cubeData(4u * 6u, 0xFFFFffff);
147         const array_view<const uint8_t> cubeDataView(
148             reinterpret_cast<const uint8_t*>(cubeData.data()), cubeData.size() * sizeOfUint32);
149         defaultGpuResources.push_back(gpuResourceMgr.Create(
150             DefaultMaterialGpuResourceConstants::CORE_DEFAULT_RADIANCE_CUBEMAP, desc, cubeDataView));
151 
152         // Skybox is currently in rgbd format (alpha channel is used as a divider for the rgb values).
153         defaultGpuResources.push_back(gpuResourceMgr.Create(
154             DefaultMaterialGpuResourceConstants::CORE_DEFAULT_SKYBOX_CUBEMAP, desc, cubeDataView));
155     }
156 }
157 
CreateDefaultSamplers(IDevice & device,vector<RenderHandleReference> & defaultGpuResources)158 void CreateDefaultSamplers(IDevice& device, vector<RenderHandleReference>& defaultGpuResources)
159 {
160     IGpuResourceManager& gpuResourceMgr = device.GetGpuResourceManager();
161     {
162         GpuSamplerDesc sampler {
163             Filter::CORE_FILTER_LINEAR,                                  // magFilter
164             Filter::CORE_FILTER_LINEAR,                                  // minFilter
165             Filter::CORE_FILTER_LINEAR,                                  // mipMapMode
166             SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeU
167             SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeV
168             SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeW
169         };
170         constexpr float CUBE_MAP_LOD_COEFF { 8.0f };
171         sampler.minLod = 0.0f;
172         sampler.maxLod = CUBE_MAP_LOD_COEFF;
173         defaultGpuResources.push_back(
174             gpuResourceMgr.Create(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_RADIANCE_CUBEMAP_SAMPLER, sampler));
175     }
176     {
177         GpuSamplerDesc sampler {
178             Filter::CORE_FILTER_LINEAR,                                  // magFilter
179             Filter::CORE_FILTER_LINEAR,                                  // minFilter
180             Filter::CORE_FILTER_LINEAR,                                  // mipMapMode
181             SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeU
182             SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeV
183             SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeW
184         };
185         defaultGpuResources.push_back(
186             gpuResourceMgr.Create(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_VSM_SHADOW_SAMPLER, sampler));
187 
188         sampler.compareOp = CompareOp::CORE_COMPARE_OP_GREATER;
189         sampler.enableCompareOp = true;
190         defaultGpuResources.push_back(
191             gpuResourceMgr.Create(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_PCF_SHADOW_SAMPLER, sampler));
192     }
193 }
194 
CreateDefaultResources(IDevice & device,vector<RenderHandleReference> & defaultGpuResources)195 void CreateDefaultResources(IDevice& device, vector<RenderHandleReference>& defaultGpuResources)
196 {
197     CreateDefaultImages(device, defaultGpuResources);
198     CreateDefaultSamplers(device, defaultGpuResources);
199 }
200 } // namespace
201 
202 // Core Rofs Data.
203 extern "C" {
204 extern const void* const BINARY_DATA_FOR_3D[];
205 extern const uint64_t SIZE_OF_DATA_FOR_3D;
206 }
207 
208 array_view<const RenderDataStoreTypeInfo> GetRenderDataStores3D();
209 array_view<const RenderNodeTypeInfo> GetRenderNodes3D();
210 array_view<const ComponentManagerTypeInfo> GetComponentManagers3D();
211 array_view<const SystemTypeInfo> GetSystems3D();
212 
213 struct Agp3DPluginState {
214     IRenderContext& renderContext;
215     unique_ptr<GraphicsContext> context;
216 
217     vector<RenderHandleReference> defaultGpuResources;
218     vector<string> defaultPostProcesses;
219 
220     Picking picker_;
221     RenderNodeSceneUtilImpl renderNodeSceneUtil;
222     InterfaceTypeInfo interfaces[4] = {
223         InterfaceTypeInfo {
224             this,
225             UID_MESH_BUILDER,
226             CORE_NS::GetName<IMeshBuilder>().data(),
__anonc7e394b80202Agp3DPluginState227             [](IClassFactory&, PluginToken token) -> IInterface* {
228                 if (token) {
229                     Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
230                     return new MeshBuilder(state->renderContext);
231                 }
232                 return nullptr;
233             },
234             nullptr,
235         },
236         InterfaceTypeInfo {
237             this,
238             UID_PICKING,
239             CORE_NS::GetName<IPicking>().data(),
240             nullptr,
__anonc7e394b80302Agp3DPluginState241             [](IClassRegister& registry, PluginToken token) -> IInterface* {
242                 if (token) {
243                     Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
244                     return &state->picker_;
245                 }
246                 return nullptr;
247             },
248         },
249         InterfaceTypeInfo {
250             this,
251             UID_RENDER_NODE_SCENE_UTIL,
252             CORE_NS::GetName<IRenderNodeSceneUtil>().data(),
253             nullptr,
__anonc7e394b80402Agp3DPluginState254             [](IClassRegister& registry, PluginToken token) -> IInterface* {
255                 if (token) {
256                     Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
257                     return &state->renderNodeSceneUtil;
258                 }
259                 return nullptr;
260             },
261         },
262         InterfaceTypeInfo {
263             this,
264             UID_GRAPHICS_CONTEXT,
265             CORE_NS::GetName<IGraphicsContext>().data(),
__anonc7e394b80502Agp3DPluginState266             [](IClassFactory& registry, PluginToken token) -> IInterface* {
267                 if (token) {
268                     Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
269                     if (!state->context) {
270                         state->context = make_unique<GraphicsContext>(*state, state->renderContext);
271                     }
272                     return state->context->GetInterface(IInterface::UID);
273                 }
274                 return nullptr;
275             },
__anonc7e394b80602Agp3DPluginState276             [](IClassRegister& registry, PluginToken token) -> IInterface* {
277                 if (token) {
278                     Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
279                     return state->context->GetInterface(IInterface::UID);
280                 }
281                 return nullptr;
282             },
283         },
284     };
285 
DestroyAgp3DPluginState286     void Destroy()
287     {
288         context.reset();
289     }
290 };
291 
GraphicsContext(struct Agp3DPluginState & factory,IRenderContext & context)292 GraphicsContext::GraphicsContext(struct Agp3DPluginState& factory, IRenderContext& context)
293     : factory_(factory), context_(context)
294 {
295     LogCore3dBuildInfo();
296 }
297 
~GraphicsContext()298 GraphicsContext ::~GraphicsContext()
299 {
300     GetPluginRegister().RemoveListener(*this);
301 
302     for (auto& info : plugins_) {
303         if (info.second && info.second->destroyPlugin) {
304             info.second->destroyPlugin(info.first);
305         }
306     }
307     if (sceneUtil_ && gltf2_) {
308         sceneUtil_->UnregisterSceneLoader(IInterface::Ptr { gltf2_->GetInterface(ISceneLoader::UID) });
309     }
310 }
311 
Init(const CreateInfo & createInfo)312 void GraphicsContext::Init(const CreateInfo& createInfo)
313 {
314     CORE_LOG_D("3D graphics context init.");
315     CORE_CPU_PERF_SCOPE("CORE3D", "GraphicsContext::Init", "", CORE3D_PROFILER_DEFAULT_COLOR);
316 
317     if (initialized_) {
318         return;
319     }
320     auto& engine = context_.GetEngine();
321 
322     createInfo_ = createInfo;
323     meshUtil_ = make_unique<MeshUtil>(*engine.GetInterface<CORE_NS::IClassFactory>());
324     gltf2_ = make_unique<Gltf2>(*this);
325     sceneUtil_ = make_unique<SceneUtil>(*this);
326     renderUtil_ = make_unique<RenderUtil>(*this);
327     sceneUtil_->RegisterSceneLoader(IInterface::Ptr { gltf2_->GetInterface(ISceneLoader::UID) });
328     initialized_ = true;
329 
330     GetPluginRegister().AddListener(*this);
331 
332     for (auto info : CORE_NS::GetPluginRegister().GetTypeInfos(I3DPlugin::UID)) {
333         if (auto plugin = static_cast<const I3DPlugin*>(info); plugin && plugin->createPlugin) {
334             auto token = plugin->createPlugin(*this);
335             plugins_.push_back({ token, plugin });
336         }
337     }
338 }
339 
Init()340 void GraphicsContext::Init()
341 {
342     Init({});
343 }
344 
GetRenderContext() const345 IRenderContext& GraphicsContext::GetRenderContext() const
346 {
347     return context_;
348 }
349 
GetRenderNodeGraphs(const IEcs & ecs) const350 array_view<const RenderHandleReference> GraphicsContext::GetRenderNodeGraphs(const IEcs& ecs) const
351 {
352     // NOTE: gets the render node graphs from built-in RenderSystem
353     if (IRenderSystem* rs = GetSystem<IRenderSystem>(ecs); rs) {
354         return rs->GetRenderNodeGraphs();
355     } else {
356         return {};
357     }
358 }
359 
GetSceneUtil() const360 ISceneUtil& GraphicsContext::GetSceneUtil() const
361 {
362     return *sceneUtil_;
363 }
364 
GetMeshUtil() const365 IMeshUtil& GraphicsContext::GetMeshUtil() const
366 {
367     return *meshUtil_;
368 }
369 
GetGltf() const370 IGltf2& GraphicsContext::GetGltf() const
371 {
372     return *gltf2_;
373 }
374 
GetRenderUtil() const375 IRenderUtil& GraphicsContext::GetRenderUtil() const
376 {
377     return *renderUtil_;
378 }
379 
GetCreateInfo() const380 GraphicsContext::CreateInfo GraphicsContext::GetCreateInfo() const
381 {
382     return createInfo_;
383 }
384 
GetInterface(const Uid & uid) const385 const IInterface* GraphicsContext::GetInterface(const Uid& uid) const
386 {
387     if (uid == IGraphicsContext::UID) {
388         return static_cast<const IGraphicsContext*>(this);
389     } else if (uid == IInterface::UID) {
390         return static_cast<const IInterface*>(static_cast<const IGraphicsContext*>(this));
391     } else if (uid == IClassRegister::UID) {
392         return static_cast<const IClassRegister*>(this);
393     } else if (uid == IClassFactory::UID) {
394         return static_cast<const IClassFactory*>(this);
395     }
396     return nullptr;
397 }
398 
GetInterface(const Uid & uid)399 IInterface* GraphicsContext::GetInterface(const Uid& uid)
400 {
401     if (uid == IGraphicsContext::UID) {
402         return static_cast<IGraphicsContext*>(this);
403     } else if (uid == IInterface::UID) {
404         return static_cast<IInterface*>(static_cast<IGraphicsContext*>(this));
405     } else if (uid == IClassRegister::UID) {
406         return static_cast<IClassRegister*>(this);
407     } else if (uid == IClassFactory::UID) {
408         return static_cast<IClassFactory*>(this);
409     }
410     return nullptr;
411 }
412 
Ref()413 void GraphicsContext::Ref()
414 {
415     refcnt_++;
416 }
417 
Unref()418 void GraphicsContext::Unref()
419 {
420     if (--refcnt_ == 0) {
421         factory_.Destroy();
422     }
423 }
424 
RegisterInterfaceType(const InterfaceTypeInfo & interfaceInfo)425 void GraphicsContext::RegisterInterfaceType(const InterfaceTypeInfo& interfaceInfo)
426 {
427     // keep interfaceTypeInfos_ sorted according to UIDs
428     const auto pos = std::upper_bound(interfaceTypeInfos_.cbegin(), interfaceTypeInfos_.cend(), interfaceInfo.uid,
429         [](Uid value, const InterfaceTypeInfo* element) { return value < element->uid; });
430     interfaceTypeInfos_.insert(pos, &interfaceInfo);
431 }
432 
UnregisterInterfaceType(const InterfaceTypeInfo & interfaceInfo)433 void GraphicsContext::UnregisterInterfaceType(const InterfaceTypeInfo& interfaceInfo)
434 {
435     if (!interfaceTypeInfos_.empty()) {
436         const auto pos = std::lower_bound(interfaceTypeInfos_.cbegin(), interfaceTypeInfos_.cend(), interfaceInfo.uid,
437             [](const InterfaceTypeInfo* element, Uid value) { return element->uid < value; });
438         if ((pos != interfaceTypeInfos_.cend()) && (*pos)->uid == interfaceInfo.uid) {
439             interfaceTypeInfos_.erase(pos);
440         }
441     }
442 }
443 
GetInterfaceMetadata() const444 array_view<const InterfaceTypeInfo* const> GraphicsContext::GetInterfaceMetadata() const
445 {
446     return interfaceTypeInfos_;
447 }
448 
GetInterfaceMetadata(const Uid & uid) const449 const InterfaceTypeInfo& GraphicsContext::GetInterfaceMetadata(const Uid& uid) const
450 {
451     static InterfaceTypeInfo invalidType {};
452 
453     if (!interfaceTypeInfos_.empty()) {
454         const auto pos = std::lower_bound(interfaceTypeInfos_.cbegin(), interfaceTypeInfos_.cend(), uid,
455             [](const InterfaceTypeInfo* element, Uid value) { return element->uid < value; });
456         if ((pos != interfaceTypeInfos_.cend()) && (*pos)->uid == uid) {
457             return *(*pos);
458         }
459     }
460     return invalidType;
461 }
462 
GetInstance(const BASE_NS::Uid & uid) const463 IInterface* GraphicsContext::GetInstance(const BASE_NS::Uid& uid) const
464 {
465     const auto& data = GetInterfaceMetadata(uid);
466     if (data.getInterface) {
467         return data.getInterface(const_cast<GraphicsContext&>(*this), data.token);
468     }
469     return nullptr;
470 }
471 
CreateInstance(const BASE_NS::Uid & uid)472 IInterface::Ptr GraphicsContext::CreateInstance(const BASE_NS::Uid& uid)
473 {
474     const auto& data = GetInterfaceMetadata(uid);
475     if (data.createInterface) {
476         return IInterface::Ptr { data.createInterface(*this, data.token) };
477     }
478     return IInterface::Ptr {};
479 }
480 
OnTypeInfoEvent(EventType type,array_view<const ITypeInfo * const> typeInfos)481 void GraphicsContext::OnTypeInfoEvent(EventType type, array_view<const ITypeInfo* const> typeInfos)
482 {
483     if (type == EventType::ADDED) {
484         for (const auto* info : typeInfos) {
485             if (info && info->typeUid == I3DPlugin::UID && static_cast<const I3DPlugin*>(info)->createPlugin) {
486                 auto plugin = static_cast<const I3DPlugin*>(info);
487                 if (std::none_of(plugins_.begin(), plugins_.end(),
488                         [plugin](const pair<PluginToken, const I3DPlugin*>& pluginData) {
489                             return pluginData.second == plugin;
490                         })) {
491                     auto token = plugin->createPlugin(*this);
492                     plugins_.push_back({ token, plugin });
493                 }
494             }
495         }
496     } else if (type == EventType::REMOVED) {
497         for (const auto* info : typeInfos) {
498             if (info && info->typeUid == I3DPlugin::UID) {
499                 auto plugin = static_cast<const I3DPlugin*>(info);
500                 if (auto pos = std::find_if(plugins_.begin(), plugins_.end(),
501                         [plugin](const pair<PluginToken, const I3DPlugin*>& pluginData) {
502                             return pluginData.second == plugin;
503                         });
504                     pos != plugins_.end()) {
505                     if (plugin->destroyPlugin) {
506                         plugin->destroyPlugin(pos->first);
507                     }
508                     plugins_.erase(pos);
509                 }
510             }
511         }
512     }
513 }
514 
515 void RegisterTypes(IPluginRegister& pluginRegistry);
516 void UnregisterTypes(IPluginRegister& pluginRegistry);
517 
518 namespace {
CreatePlugin3D(IRenderContext & context)519 PluginToken CreatePlugin3D(IRenderContext& context)
520 {
521     CORE_CPU_PERF_SCOPE("CORE3D", "CreatePlugin3D", "", CORE3D_PROFILER_DEFAULT_COLOR);
522 
523     Agp3DPluginState* token = new Agp3DPluginState { context, {}, {}, {}, {}, {} };
524     auto& registry = *context.GetInterface<IClassRegister>();
525     for (const auto& info : token->interfaces) {
526         registry.RegisterInterfaceType(info);
527     }
528 
529     IFileManager& fileManager = context.GetEngine().GetFileManager();
530 #if (CORE3D_EMBEDDED_ASSETS_ENABLED == 1)
531     // Create rofs3D:// protocol that points to embedded asset files.
532     fileManager.RegisterFilesystem("rofs3D", fileManager.CreateROFilesystem(BINARY_DATA_FOR_3D, SIZE_OF_DATA_FOR_3D));
533 #endif
534     for (uint32_t idx = 0; idx < countof(RENDER_DATA_PATHS); ++idx) {
535         fileManager.RegisterPath(RENDER_DATA_PATHS[idx].protocol, RENDER_DATA_PATHS[idx].uri, false);
536     }
537     context.GetDevice().GetShaderManager().LoadShaderFiles(SHADER_FILE_PATHS);
538 
539     CreateDefaultResources(context.GetDevice(), token->defaultGpuResources);
540     {
541         auto* renderDataConfigurationLoader = CORE_NS::GetInstance<IRenderDataConfigurationLoader>(
542             *context.GetInterface<IClassRegister>(), UID_RENDER_DATA_CONFIGURATION_LOADER);
543         auto dataStore = context.GetRenderDataStoreManager().GetRenderDataStore(POST_PROCESS_DATA_STORE_NAME);
544         if (renderDataConfigurationLoader && dataStore) {
545             auto& fileMgr = context.GetEngine().GetFileManager();
546             constexpr string_view ppPath = POST_PROCESS_PATH;
547             if (auto dir = fileMgr.OpenDirectory(ppPath); dir) {
548                 for (const auto& entry : dir->GetEntries()) {
549                     if (entry.type == IDirectory::Entry::Type::FILE) {
550                         const auto loadedPP =
551                             renderDataConfigurationLoader->LoadPostProcess(fileMgr, ppPath + entry.name);
552                         if (loadedPP.loadResult.success) {
553                             token->defaultPostProcesses.push_back(loadedPP.name);
554                             auto pod = static_cast<IRenderDataStorePod*>(dataStore.get());
555                             pod->CreatePod(
556                                 POST_PROCESS_NAME, loadedPP.name, arrayviewU8(loadedPP.postProcessConfiguration));
557                         }
558                     }
559                 }
560             }
561         }
562     }
563 
564     return token;
565 }
566 
DestroyPlugin3D(PluginToken token)567 void DestroyPlugin3D(PluginToken token)
568 {
569     Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
570     IFileManager& fileManager = state->renderContext.GetEngine().GetFileManager();
571 
572     state->defaultGpuResources.clear();
573     {
574         auto* renderDataConfigurationLoader = CORE_NS::GetInstance<IRenderDataConfigurationLoader>(
575             *state->renderContext.GetInterface<IClassRegister>(), UID_RENDER_DATA_CONFIGURATION_LOADER);
576         auto dataStore =
577             state->renderContext.GetRenderDataStoreManager().GetRenderDataStore(POST_PROCESS_DATA_STORE_NAME);
578         if (renderDataConfigurationLoader && dataStore) {
579             auto pod = static_cast<IRenderDataStorePod*>(dataStore.get());
580             for (const auto& ref : state->defaultPostProcesses) {
581                 pod->DestroyPod(POST_PROCESS_NAME, ref);
582             }
583         }
584         state->defaultPostProcesses.clear();
585     }
586     state->renderContext.GetDevice().GetShaderManager().UnloadShaderFiles(SHADER_FILE_PATHS);
587 #if (CORE3D_EMBEDDED_ASSETS_ENABLED == 1)
588     fileManager.UnregisterFilesystem("rofs3D");
589 #endif
590     for (uint32_t idx = 0; idx < countof(RENDER_DATA_PATHS); ++idx) {
591         fileManager.UnregisterPath(RENDER_DATA_PATHS[idx].protocol, RENDER_DATA_PATHS[idx].uri);
592     }
593 
594     auto& registry = *state->renderContext.GetInterface<IClassRegister>();
595     for (const auto& info : state->interfaces) {
596         registry.UnregisterInterfaceType(info);
597     }
598 
599     delete state;
600 }
601 
CreateEcsPlugin3D(IEcs & ecs)602 PluginToken CreateEcsPlugin3D(IEcs& ecs)
603 {
604     return {};
605 }
606 
DestroyEcsPlugin3D(PluginToken token)607 void DestroyEcsPlugin3D(PluginToken token) {}
608 
609 constexpr IRenderPlugin RENDER_PLUGIN(CreatePlugin3D, DestroyPlugin3D);
610 constexpr IEcsPlugin ECS_PLUGIN(CreateEcsPlugin3D, DestroyEcsPlugin3D);
611 } // namespace
612 
RegisterInterfaces3D(IPluginRegister & pluginRegistry)613 PluginToken RegisterInterfaces3D(IPluginRegister& pluginRegistry)
614 {
615     InitRegistry(pluginRegistry);
616     pluginRegistry.RegisterTypeInfo(RENDER_PLUGIN);
617     pluginRegistry.RegisterTypeInfo(ECS_PLUGIN);
618 
619     RegisterTypes(GetPluginRegister());
620 
621     return &pluginRegistry;
622 }
623 
UnregisterInterfaces3D(PluginToken token)624 void UnregisterInterfaces3D(PluginToken token)
625 {
626     if (!token) {
627         return;
628     }
629     IPluginRegister* pluginRegistry = static_cast<IPluginRegister*>(token);
630 
631     UnregisterTypes(GetPluginRegister());
632 
633     pluginRegistry->UnregisterTypeInfo(ECS_PLUGIN);
634     pluginRegistry->UnregisterTypeInfo(RENDER_PLUGIN);
635 }
636 CORE3D_END_NAMESPACE()
637