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