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/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 CORE_LOG_I("CORE3D_VALIDATION_ENABLED=" CORE3D_TO_STRING(CORE3D_VALIDATION_ENABLED));
105 CORE_LOG_I("CORE3D_DEV_ENABLED=" CORE3D_TO_STRING(CORE3D_DEV_ENABLED));
106 }
107
CreateDefaultImages(IDevice & device,vector<RenderHandleReference> & defaultGpuResources)108 void CreateDefaultImages(IDevice& device, vector<RenderHandleReference>& defaultGpuResources)
109 {
110 IGpuResourceManager& gpuResourceMgr = device.GetGpuResourceManager();
111 // default material gpu images
112 GpuImageDesc desc { ImageType::CORE_IMAGE_TYPE_2D, ImageViewType::CORE_IMAGE_VIEW_TYPE_2D,
113 Format::BASE_FORMAT_R8G8B8A8_SRGB, ImageTiling::CORE_IMAGE_TILING_OPTIMAL,
114 ImageUsageFlagBits::CORE_IMAGE_USAGE_SAMPLED_BIT | ImageUsageFlagBits::CORE_IMAGE_USAGE_TRANSFER_DST_BIT,
115 MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, 0, 2, 2, 1, 1, 1,
116 SampleCountFlagBits::CORE_SAMPLE_COUNT_1_BIT, {} };
117 constexpr uint32_t sizeOfUint32 = sizeof(uint32_t);
118 desc.format = Format::BASE_FORMAT_R8G8B8A8_UNORM;
119 {
120 constexpr const uint32_t normalData[4u] = { 0xFFFF7f7f, 0xFFFF7f7f, 0xFFFF7f7f, 0xFFFF7f7f };
121 const auto normalDataView =
122 array_view(reinterpret_cast<const uint8_t*>(normalData), sizeOfUint32 * countof(normalData));
123 defaultGpuResources.push_back(gpuResourceMgr.Create(
124 DefaultMaterialGpuResourceConstants::CORE_DEFAULT_MATERIAL_NORMAL, desc, normalDataView));
125 }
126
127 desc.format = Format::BASE_FORMAT_R8_UNORM;
128 {
129 constexpr const uint8_t byteData[4u] = { 0xff, 0xff, 0xff, 0xff };
130 const auto byteDataView =
131 array_view(reinterpret_cast<const uint8_t*>(byteData), sizeof(uint8_t) * countof(byteData));
132 defaultGpuResources.push_back(
133 gpuResourceMgr.Create(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_MATERIAL_AO, desc, byteDataView));
134 }
135 // env cubemaps
136 desc.imageViewType = ImageViewType::CORE_IMAGE_VIEW_TYPE_CUBE;
137 desc.format = Format::BASE_FORMAT_R8G8B8A8_SRGB;
138 desc.createFlags = ImageCreateFlagBits::CORE_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
139 desc.layerCount = 6u;
140 {
141 // Env color is currently in rgbd format (alpha channel is used as a divider for the rgb values).
142 const vector<uint32_t> cubeData(4u * 6u, 0xFFFFffff);
143 const array_view<const uint8_t> cubeDataView(
144 reinterpret_cast<const uint8_t*>(cubeData.data()), cubeData.size() * sizeOfUint32);
145 defaultGpuResources.push_back(gpuResourceMgr.Create(
146 DefaultMaterialGpuResourceConstants::CORE_DEFAULT_RADIANCE_CUBEMAP, desc, cubeDataView));
147
148 // Skybox is currently in rgbd format (alpha channel is used as a divider for the rgb values).
149 defaultGpuResources.push_back(gpuResourceMgr.Create(
150 DefaultMaterialGpuResourceConstants::CORE_DEFAULT_SKYBOX_CUBEMAP, desc, cubeDataView));
151 }
152 }
153
CreateDefaultSamplers(IDevice & device,vector<RenderHandleReference> & defaultGpuResources)154 void CreateDefaultSamplers(IDevice& device, vector<RenderHandleReference>& defaultGpuResources)
155 {
156 IGpuResourceManager& gpuResourceMgr = device.GetGpuResourceManager();
157 {
158 GpuSamplerDesc sampler {
159 Filter::CORE_FILTER_LINEAR, // magFilter
160 Filter::CORE_FILTER_LINEAR, // minFilter
161 Filter::CORE_FILTER_LINEAR, // mipMapMode
162 SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeU
163 SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeV
164 SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeW
165 };
166 constexpr float CUBE_MAP_LOD_COEFF { 8.0f };
167 sampler.minLod = 0.0f;
168 sampler.maxLod = CUBE_MAP_LOD_COEFF;
169 defaultGpuResources.push_back(
170 gpuResourceMgr.Create(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_RADIANCE_CUBEMAP_SAMPLER, sampler));
171 }
172 {
173 GpuSamplerDesc sampler {
174 Filter::CORE_FILTER_LINEAR, // magFilter
175 Filter::CORE_FILTER_LINEAR, // minFilter
176 Filter::CORE_FILTER_LINEAR, // mipMapMode
177 SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeU
178 SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeV
179 SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeW
180 };
181 defaultGpuResources.push_back(
182 gpuResourceMgr.Create(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_VSM_SHADOW_SAMPLER, sampler));
183
184 sampler.compareOp = CompareOp::CORE_COMPARE_OP_GREATER;
185 sampler.enableCompareOp = true;
186 defaultGpuResources.push_back(
187 gpuResourceMgr.Create(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_PCF_SHADOW_SAMPLER, sampler));
188 }
189 }
190
CreateDefaultResources(IDevice & device,vector<RenderHandleReference> & defaultGpuResources)191 void CreateDefaultResources(IDevice& device, vector<RenderHandleReference>& defaultGpuResources)
192 {
193 CreateDefaultImages(device, defaultGpuResources);
194 CreateDefaultSamplers(device, defaultGpuResources);
195 }
196 } // namespace
197
198 // Core Rofs Data.
199 extern "C" {
200 extern const void* const BINARY_DATA_FOR_3D[];
201 extern const uint64_t SIZE_OF_DATA_FOR_3D;
202 }
203
204 array_view<const RenderDataStoreTypeInfo> GetRenderDataStores3D();
205 array_view<const RenderNodeTypeInfo> GetRenderNodes3D();
206 array_view<const ComponentManagerTypeInfo> GetComponentManagers3D();
207 array_view<const SystemTypeInfo> GetSystems3D();
208
209 struct Agp3DPluginState {
210 IRenderContext& renderContext;
211 unique_ptr<GraphicsContext> context;
212
213 vector<RenderHandleReference> defaultGpuResources;
214 vector<string> defaultPostProcesses;
215
216 Picking picker_;
217 RenderNodeSceneUtilImpl renderNodeSceneUtil;
218 InterfaceTypeInfo interfaces[4] = {
219 InterfaceTypeInfo {
220 this,
221 UID_MESH_BUILDER,
222 CORE_NS::GetName<IMeshBuilder>().data(),
__anon857cb7160202Agp3DPluginState223 [](IClassFactory&, PluginToken token) -> IInterface* {
224 if (token) {
225 Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
226 return new MeshBuilder(state->renderContext);
227 }
228 return nullptr;
229 },
230 nullptr,
231 },
232 InterfaceTypeInfo {
233 this,
234 UID_PICKING,
235 CORE_NS::GetName<IPicking>().data(),
236 nullptr,
__anon857cb7160302Agp3DPluginState237 [](IClassRegister& registry, PluginToken token) -> IInterface* {
238 if (token) {
239 Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
240 return &state->picker_;
241 }
242 return nullptr;
243 },
244 },
245 InterfaceTypeInfo {
246 this,
247 UID_RENDER_NODE_SCENE_UTIL,
248 CORE_NS::GetName<IRenderNodeSceneUtil>().data(),
249 nullptr,
__anon857cb7160402Agp3DPluginState250 [](IClassRegister& registry, PluginToken token) -> IInterface* {
251 if (token) {
252 Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
253 return &state->renderNodeSceneUtil;
254 }
255 return nullptr;
256 },
257 },
258 InterfaceTypeInfo {
259 this,
260 UID_GRAPHICS_CONTEXT,
261 CORE_NS::GetName<IGraphicsContext>().data(),
__anon857cb7160502Agp3DPluginState262 [](IClassFactory& registry, PluginToken token) -> IInterface* {
263 if (token) {
264 Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
265 if (!state->context) {
266 state->context = make_unique<GraphicsContext>(*state, state->renderContext);
267 }
268 return state->context->GetInterface(IInterface::UID);
269 }
270 return nullptr;
271 },
__anon857cb7160602Agp3DPluginState272 [](IClassRegister& registry, PluginToken token) -> IInterface* {
273 if (token) {
274 Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
275 return state->context->GetInterface(IInterface::UID);
276 }
277 return nullptr;
278 },
279 },
280 };
281
DestroyAgp3DPluginState282 void Destroy()
283 {
284 context.reset();
285 }
286 };
287
GraphicsContext(struct Agp3DPluginState & factory,IRenderContext & context)288 GraphicsContext::GraphicsContext(struct Agp3DPluginState& factory, IRenderContext& context)
289 : factory_(factory), context_(context)
290 {
291 LogCore3dBuildInfo();
292 }
293
~GraphicsContext()294 GraphicsContext ::~GraphicsContext()
295 {
296 GetPluginRegister().RemoveListener(*this);
297
298 for (auto& info : plugins_) {
299 if (info.second && info.second->destroyPlugin) {
300 info.second->destroyPlugin(info.first);
301 }
302 }
303 if (sceneUtil_ && gltf2_) {
304 sceneUtil_->UnregisterSceneLoader(IInterface::Ptr { gltf2_->GetInterface(ISceneLoader::UID) });
305 }
306 }
307
Init(const CreateInfo & createInfo)308 void GraphicsContext::Init(const CreateInfo& createInfo)
309 {
310 CORE_LOG_D("3D graphics context init.");
311 CORE_CPU_PERF_SCOPE("CORE3D", "GraphicsContext::Init", "", CORE3D_PROFILER_DEFAULT_COLOR);
312
313 if (initialized_) {
314 return;
315 }
316 auto& engine = context_.GetEngine();
317
318 createInfo_ = createInfo;
319 meshUtil_ = make_unique<MeshUtil>(*engine.GetInterface<CORE_NS::IClassFactory>());
320 gltf2_ = make_unique<Gltf2>(*this);
321 sceneUtil_ = make_unique<SceneUtil>(*this);
322 renderUtil_ = make_unique<RenderUtil>(*this);
323 sceneUtil_->RegisterSceneLoader(IInterface::Ptr { gltf2_->GetInterface(ISceneLoader::UID) });
324 initialized_ = true;
325
326 GetPluginRegister().AddListener(*this);
327
328 for (auto info : CORE_NS::GetPluginRegister().GetTypeInfos(I3DPlugin::UID)) {
329 if (auto plugin = static_cast<const I3DPlugin*>(info); plugin && plugin->createPlugin) {
330 auto token = plugin->createPlugin(*this);
331 plugins_.push_back({ token, plugin });
332 }
333 }
334 }
335
Init()336 void GraphicsContext::Init()
337 {
338 Init({});
339 }
340
GetRenderContext() const341 IRenderContext& GraphicsContext::GetRenderContext() const
342 {
343 return context_;
344 }
345
GetRenderNodeGraphs(const IEcs & ecs) const346 array_view<const RenderHandleReference> GraphicsContext::GetRenderNodeGraphs(const IEcs& ecs) const
347 {
348 // NOTE: gets the render node graphs from built-in RenderSystem
349 if (IRenderSystem* rs = GetSystem<IRenderSystem>(ecs); rs) {
350 return rs->GetRenderNodeGraphs();
351 } else {
352 return {};
353 }
354 }
355
GetSceneUtil() const356 ISceneUtil& GraphicsContext::GetSceneUtil() const
357 {
358 return *sceneUtil_;
359 }
360
GetMeshUtil() const361 IMeshUtil& GraphicsContext::GetMeshUtil() const
362 {
363 return *meshUtil_;
364 }
365
GetGltf() const366 IGltf2& GraphicsContext::GetGltf() const
367 {
368 return *gltf2_;
369 }
370
GetRenderUtil() const371 IRenderUtil& GraphicsContext::GetRenderUtil() const
372 {
373 return *renderUtil_;
374 }
375
GetColorSpaceFlags() const376 ColorSpaceFlags GraphicsContext::GetColorSpaceFlags() const
377 {
378 return createInfo_.colorSpaceFlags;
379 }
380
GetInterface(const Uid & uid) const381 const IInterface* GraphicsContext::GetInterface(const Uid& uid) const
382 {
383 if (uid == IGraphicsContext::UID) {
384 return static_cast<const IGraphicsContext*>(this);
385 } else if (uid == IInterface::UID) {
386 return static_cast<const IInterface*>(static_cast<const IGraphicsContext*>(this));
387 } else if (uid == IClassRegister::UID) {
388 return static_cast<const IClassRegister*>(this);
389 } else if (uid == IClassFactory::UID) {
390 return static_cast<const IClassFactory*>(this);
391 }
392 return nullptr;
393 }
394
GetInterface(const Uid & uid)395 IInterface* GraphicsContext::GetInterface(const Uid& uid)
396 {
397 if (uid == IGraphicsContext::UID) {
398 return static_cast<IGraphicsContext*>(this);
399 } else if (uid == IInterface::UID) {
400 return static_cast<IInterface*>(static_cast<IGraphicsContext*>(this));
401 } else if (uid == IClassRegister::UID) {
402 return static_cast<IClassRegister*>(this);
403 } else if (uid == IClassFactory::UID) {
404 return static_cast<IClassFactory*>(this);
405 }
406 return nullptr;
407 }
408
Ref()409 void GraphicsContext::Ref()
410 {
411 refcnt_++;
412 }
413
Unref()414 void GraphicsContext::Unref()
415 {
416 if (--refcnt_ == 0) {
417 factory_.Destroy();
418 }
419 }
420
RegisterInterfaceType(const InterfaceTypeInfo & interfaceInfo)421 void GraphicsContext::RegisterInterfaceType(const InterfaceTypeInfo& interfaceInfo)
422 {
423 // keep interfaceTypeInfos_ sorted according to UIDs
424 const auto pos = std::upper_bound(interfaceTypeInfos_.cbegin(), interfaceTypeInfos_.cend(), interfaceInfo.uid,
425 [](Uid value, const InterfaceTypeInfo* element) { return value < element->uid; });
426 interfaceTypeInfos_.insert(pos, &interfaceInfo);
427 }
428
UnregisterInterfaceType(const InterfaceTypeInfo & interfaceInfo)429 void GraphicsContext::UnregisterInterfaceType(const InterfaceTypeInfo& interfaceInfo)
430 {
431 if (!interfaceTypeInfos_.empty()) {
432 const auto pos = std::lower_bound(interfaceTypeInfos_.cbegin(), interfaceTypeInfos_.cend(), interfaceInfo.uid,
433 [](const InterfaceTypeInfo* element, Uid value) { return element->uid < value; });
434 if ((pos != interfaceTypeInfos_.cend()) && (*pos)->uid == interfaceInfo.uid) {
435 interfaceTypeInfos_.erase(pos);
436 }
437 }
438 }
439
GetInterfaceMetadata() const440 array_view<const InterfaceTypeInfo* const> GraphicsContext::GetInterfaceMetadata() const
441 {
442 return interfaceTypeInfos_;
443 }
444
GetInterfaceMetadata(const Uid & uid) const445 const InterfaceTypeInfo& GraphicsContext::GetInterfaceMetadata(const Uid& uid) const
446 {
447 static InterfaceTypeInfo invalidType {};
448
449 if (!interfaceTypeInfos_.empty()) {
450 const auto pos = std::lower_bound(interfaceTypeInfos_.cbegin(), interfaceTypeInfos_.cend(), uid,
451 [](const InterfaceTypeInfo* element, Uid value) { return element->uid < value; });
452 if ((pos != interfaceTypeInfos_.cend()) && (*pos)->uid == uid) {
453 return *(*pos);
454 }
455 }
456 return invalidType;
457 }
458
GetInstance(const BASE_NS::Uid & uid) const459 IInterface* GraphicsContext::GetInstance(const BASE_NS::Uid& uid) const
460 {
461 const auto& data = GetInterfaceMetadata(uid);
462 if (data.getInterface) {
463 return data.getInterface(const_cast<GraphicsContext&>(*this), data.token);
464 }
465 return nullptr;
466 }
467
CreateInstance(const BASE_NS::Uid & uid)468 IInterface::Ptr GraphicsContext::CreateInstance(const BASE_NS::Uid& uid)
469 {
470 const auto& data = GetInterfaceMetadata(uid);
471 if (data.createInterface) {
472 return IInterface::Ptr { data.createInterface(*this, data.token) };
473 }
474 return IInterface::Ptr {};
475 }
476
OnTypeInfoEvent(EventType type,array_view<const ITypeInfo * const> typeInfos)477 void GraphicsContext::OnTypeInfoEvent(EventType type, array_view<const ITypeInfo* const> typeInfos)
478 {
479 if (type == EventType::ADDED) {
480 for (const auto* info : typeInfos) {
481 if (info && info->typeUid == I3DPlugin::UID && static_cast<const I3DPlugin*>(info)->createPlugin) {
482 auto plugin = static_cast<const I3DPlugin*>(info);
483 if (std::none_of(plugins_.begin(), plugins_.end(),
484 [plugin](const pair<PluginToken, const I3DPlugin*>& pluginData) {
485 return pluginData.second == plugin;
486 })) {
487 auto token = plugin->createPlugin(*this);
488 plugins_.push_back({ token, plugin });
489 }
490 }
491 }
492 } else if (type == EventType::REMOVED) {
493 for (const auto* info : typeInfos) {
494 if (info && info->typeUid == I3DPlugin::UID) {
495 auto plugin = static_cast<const I3DPlugin*>(info);
496 if (auto pos = std::find_if(plugins_.begin(), plugins_.end(),
497 [plugin](const pair<PluginToken, const I3DPlugin*>& pluginData) {
498 return pluginData.second == plugin;
499 });
500 pos != plugins_.end()) {
501 if (plugin->destroyPlugin) {
502 plugin->destroyPlugin(pos->first);
503 }
504 plugins_.erase(pos);
505 }
506 }
507 }
508 }
509 }
510
511 void RegisterTypes(IPluginRegister& pluginRegistry);
512 void UnregisterTypes(IPluginRegister& pluginRegistry);
513
514 namespace {
CreatePlugin3D(IRenderContext & context)515 PluginToken CreatePlugin3D(IRenderContext& context)
516 {
517 CORE_CPU_PERF_SCOPE("CORE3D", "CreatePlugin3D", "", CORE3D_PROFILER_DEFAULT_COLOR);
518
519 Agp3DPluginState* token = new Agp3DPluginState { context, {}, {}, {}, {}, {} };
520 auto& registry = *context.GetInterface<IClassRegister>();
521 for (const auto& info : token->interfaces) {
522 registry.RegisterInterfaceType(info);
523 }
524
525 IFileManager& fileManager = context.GetEngine().GetFileManager();
526 #if (CORE3D_EMBEDDED_ASSETS_ENABLED == 1)
527 // Create rofs3D:// protocol that points to embedded asset files.
528 fileManager.RegisterFilesystem("rofs3D", fileManager.CreateROFilesystem(BINARY_DATA_FOR_3D, SIZE_OF_DATA_FOR_3D));
529 #endif
530 for (uint32_t idx = 0; idx < countof(RENDER_DATA_PATHS); ++idx) {
531 fileManager.RegisterPath(RENDER_DATA_PATHS[idx].protocol, RENDER_DATA_PATHS[idx].uri, false);
532 }
533 context.GetDevice().GetShaderManager().LoadShaderFiles(SHADER_FILE_PATHS);
534
535 CreateDefaultResources(context.GetDevice(), token->defaultGpuResources);
536 {
537 auto* renderDataConfigurationLoader = CORE_NS::GetInstance<IRenderDataConfigurationLoader>(
538 *context.GetInterface<IClassRegister>(), UID_RENDER_DATA_CONFIGURATION_LOADER);
539 auto dataStore = context.GetRenderDataStoreManager().GetRenderDataStore(POST_PROCESS_DATA_STORE_NAME);
540 if (renderDataConfigurationLoader && dataStore) {
541 auto& fileMgr = context.GetEngine().GetFileManager();
542 constexpr string_view ppPath = POST_PROCESS_PATH;
543 if (auto dir = fileMgr.OpenDirectory(ppPath); dir) {
544 for (const auto& entry : dir->GetEntries()) {
545 if (entry.type == IDirectory::Entry::Type::FILE) {
546 const auto loadedPP =
547 renderDataConfigurationLoader->LoadPostProcess(fileMgr, ppPath + entry.name);
548 if (loadedPP.loadResult.success) {
549 token->defaultPostProcesses.push_back(loadedPP.name);
550 auto pod = static_cast<IRenderDataStorePod*>(dataStore.get());
551 pod->CreatePod(
552 POST_PROCESS_NAME, loadedPP.name, arrayviewU8(loadedPP.postProcessConfiguration));
553 }
554 }
555 }
556 }
557 }
558 }
559
560 return token;
561 }
562
DestroyPlugin3D(PluginToken token)563 void DestroyPlugin3D(PluginToken token)
564 {
565 if (token == nullptr) {
566 return;
567 }
568 Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
569 IFileManager& fileManager = state->renderContext.GetEngine().GetFileManager();
570
571 state->defaultGpuResources.clear();
572 {
573 auto* renderDataConfigurationLoader = CORE_NS::GetInstance<IRenderDataConfigurationLoader>(
574 *state->renderContext.GetInterface<IClassRegister>(), UID_RENDER_DATA_CONFIGURATION_LOADER);
575 auto dataStore =
576 state->renderContext.GetRenderDataStoreManager().GetRenderDataStore(POST_PROCESS_DATA_STORE_NAME);
577 if (renderDataConfigurationLoader && dataStore) {
578 auto pod = static_cast<IRenderDataStorePod*>(dataStore.get());
579 for (const auto& ref : state->defaultPostProcesses) {
580 pod->DestroyPod(POST_PROCESS_NAME, ref);
581 }
582 }
583 state->defaultPostProcesses.clear();
584 }
585 state->renderContext.GetDevice().GetShaderManager().UnloadShaderFiles(SHADER_FILE_PATHS);
586 #if (CORE3D_EMBEDDED_ASSETS_ENABLED == 1)
587 fileManager.UnregisterFilesystem("rofs3D");
588 #endif
589 for (uint32_t idx = 0; idx < countof(RENDER_DATA_PATHS); ++idx) {
590 fileManager.UnregisterPath(RENDER_DATA_PATHS[idx].protocol, RENDER_DATA_PATHS[idx].uri);
591 }
592
593 auto& registry = *state->renderContext.GetInterface<IClassRegister>();
594 for (const auto& info : state->interfaces) {
595 registry.UnregisterInterfaceType(info);
596 }
597
598 delete state;
599 }
600
CreateEcsPlugin3D(IEcs & ecs)601 PluginToken CreateEcsPlugin3D(IEcs& ecs)
602 {
603 return {};
604 }
605
DestroyEcsPlugin3D(PluginToken token)606 void DestroyEcsPlugin3D(PluginToken token) {}
607
608 constexpr IRenderPlugin RENDER_PLUGIN(CreatePlugin3D, DestroyPlugin3D);
609 constexpr IEcsPlugin ECS_PLUGIN(CreateEcsPlugin3D, DestroyEcsPlugin3D);
610 } // namespace
611
RegisterInterfaces3D(IPluginRegister & pluginRegistry)612 PluginToken RegisterInterfaces3D(IPluginRegister& pluginRegistry)
613 {
614 InitRegistry(pluginRegistry);
615 pluginRegistry.RegisterTypeInfo(RENDER_PLUGIN);
616 pluginRegistry.RegisterTypeInfo(ECS_PLUGIN);
617
618 RegisterTypes(GetPluginRegister());
619
620 return &pluginRegistry;
621 }
622
UnregisterInterfaces3D(PluginToken token)623 void UnregisterInterfaces3D(PluginToken token)
624 {
625 if (!token) {
626 return;
627 }
628 IPluginRegister* pluginRegistry = static_cast<IPluginRegister*>(token);
629
630 UnregisterTypes(GetPluginRegister());
631
632 pluginRegistry->UnregisterTypeInfo(ECS_PLUGIN);
633 pluginRegistry->UnregisterTypeInfo(RENDER_PLUGIN);
634 }
635 CORE3D_END_NAMESPACE()
636