• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 <base/containers/string_view.h>
19 #include <base/containers/unordered_map.h>
20 #include <base/util/uid.h>
21 #include <core/ecs/intf_ecs.h>
22 #include <core/ecs/intf_entity_manager.h>
23 #include <core/intf_engine.h>
24 #include <core/io/intf_file_manager.h>
25 #include <core/log.h>
26 #include <core/plugin/intf_plugin.h>
27 #include <core/plugin/intf_plugin_register.h>
28 #include <core/property/intf_property_handle.h>
29 #include <render/datastore/intf_render_data_store_manager.h>
30 #include <render/datastore/intf_render_data_store_pod.h>
31 #include <render/device/intf_device.h>
32 #include <render/device/intf_gpu_resource_manager.h>
33 #include <render/device/intf_shader_manager.h>
34 #include <render/implementation_uids.h>
35 #include <render/intf_plugin.h>
36 #include <render/intf_render_context.h>
37 #include <render/loader/intf_render_data_configuration_loader.h>
38 #include <render/nodecontext/intf_render_node_graph_manager.h>
39 
40 #if (RENDER_HAS_VULKAN_BACKEND)
41 #include <render/vulkan/intf_device_vk.h>
42 #endif
43 
44 #include <3d/ecs/components/material_component.h>
45 #include <3d/ecs/components/uri_component.h>
46 #include <3d/ecs/systems/intf_render_system.h>
47 #include <3d/implementation_uids.h>
48 #include <3d/render/default_material_constants.h>
49 #include <3d/render/intf_render_node_scene_util.h>
50 #include <3d/util/intf_mesh_util.h>
51 #include <3d/util/intf_scene_util.h>
52 
53 #include "gltf/gltf2.h"
54 #include "render/render_node_scene_util.h"
55 #include "util/mesh_builder.h"
56 #include "util/mesh_util.h"
57 #include "util/picking.h"
58 #include "util/render_util.h"
59 #include "util/scene_util.h"
60 #include "util/uri_lookup.h"
61 
62 extern "C" void InitRegistry(CORE_NS::IPluginRegister& pluginRegistry);
63 
64 CORE3D_BEGIN_NAMESPACE()
65 using namespace BASE_NS;
66 using namespace CORE_NS;
67 using namespace RENDER_NS;
68 
69 namespace {
70 struct RegisterPathStrings {
71     string_view protocol;
72     string_view uri;
73 };
74 static constexpr RegisterPathStrings RENDER_DATA_PATHS[] = {
75     { "3dshaders", "rofs3D://shaders/" },
76     { "3dshaderstates", "rofs3D://shaderstates/" },
77     { "3dvertexinputdeclarations", "rofs3D://vertexinputdeclarations/" },
78     { "3dpipelinelayouts", "rofs3D://pipelinelayouts/" },
79     { "3drenderdataconfigurations", "rofs3D://renderdataconfigurations/" },
80     { "3drendernodegraphs", "rofs3D://rendernodegraphs/" },
81 };
82 
83 static constexpr IShaderManager::ShaderFilePathDesc SHADER_FILE_PATHS {
84     "3dshaders://",
85     "3dshaderstates://",
86     "3dpipelinelayouts://",
87     "3dvertexinputdeclarations://",
88 };
89 
CreateDefaultResources(IDevice & device,vector<RenderHandleReference> & defaultGpuResources)90 void CreateDefaultResources(IDevice& device, vector<RenderHandleReference>& defaultGpuResources)
91 {
92     // default material gpu images
93     {
94         GpuImageDesc desc { ImageType::CORE_IMAGE_TYPE_2D, ImageViewType::CORE_IMAGE_VIEW_TYPE_2D,
95             Format::BASE_FORMAT_R8G8B8A8_SRGB, ImageTiling::CORE_IMAGE_TILING_OPTIMAL,
96             ImageUsageFlagBits::CORE_IMAGE_USAGE_SAMPLED_BIT | ImageUsageFlagBits::CORE_IMAGE_USAGE_TRANSFER_DST_BIT,
97             MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, 0, 2, 2, 1, 1, 1,
98             SampleCountFlagBits::CORE_SAMPLE_COUNT_1_BIT, {} };
99 
100         IGpuResourceManager& gpuResourceMgr = device.GetGpuResourceManager();
101         constexpr uint32_t sizeOfUint32 = sizeof(uint32_t);
102         constexpr const uint32_t rgbData[4u] = { 0xFFFFffff, 0xFFFFffff, 0xFFFFffff, 0xFFFFffff };
103         const auto rgbDataView = array_view(reinterpret_cast<const uint8_t*>(rgbData), sizeOfUint32 * countof(rgbData));
104         defaultGpuResources.emplace_back(
105             gpuResourceMgr.Create(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_MATERIAL_BASE_COLOR,
106                 reinterpret_cast<GpuImageDesc&>(desc), rgbDataView));
107 
108         desc.format = Format::BASE_FORMAT_R8G8B8A8_UNORM;
109         {
110             constexpr const uint32_t normalData[4u] = { 0xFFFF7f7f, 0xFFFF7f7f, 0xFFFF7f7f, 0xFFFF7f7f };
111             const auto normalDataView =
112                 array_view(reinterpret_cast<const uint8_t*>(normalData), sizeOfUint32 * countof(normalData));
113             defaultGpuResources.emplace_back(gpuResourceMgr.Create(
114                 DefaultMaterialGpuResourceConstants::CORE_DEFAULT_MATERIAL_NORMAL, desc, normalDataView));
115         }
116         defaultGpuResources.emplace_back(gpuResourceMgr.Create(
117             DefaultMaterialGpuResourceConstants::CORE_DEFAULT_MATERIAL_MATERIAL, desc, rgbDataView));
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.emplace_back(gpuResourceMgr.Create(
125                 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.emplace_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.emplace_back(gpuResourceMgr.Create(
143                 DefaultMaterialGpuResourceConstants::CORE_DEFAULT_SKYBOX_CUBEMAP, desc, cubeDataView));
144         }
145     }
146 }
147 } // namespace
148 
149 // Core Rofs Data.
150 extern "C" {
151 extern const void* const BINARY_DATA_FOR_3D[];
152 extern const uint64_t SIZE_OF_DATA_FOR_3D;
153 }
154 
155 array_view<const RenderDataStoreTypeInfo> GetRenderDataStores3D();
156 array_view<const RenderNodeTypeInfo> GetRenderNodes3D();
157 array_view<const ComponentManagerTypeInfo> GetComponentManagers3D();
158 array_view<const SystemTypeInfo> GetSystems3D();
159 
160 struct Agp3DPluginState {
161     IRenderContext& renderContext;
162     unique_ptr<GraphicsContext> context;
163 
164     Picking picker;
165     RenderNodeSceneUtilImpl renderNodeSceneUtil;
166     InterfaceTypeInfo interfaces[4] = {
167         InterfaceTypeInfo {
168             this,
169             UID_MESH_BUILDER,
170             CORE_NS::GetName<IMeshBuilder>().data(),
__anon4aa43ab70202Agp3DPluginState171             [](IClassFactory&, PluginToken token) -> IInterface* { return new MeshBuilder; },
172             nullptr,
173         },
174         InterfaceTypeInfo {
175             this,
176             UID_PICKING,
177             CORE_NS::GetName<IPicking>().data(),
178             nullptr,
__anon4aa43ab70302Agp3DPluginState179             [](IClassRegister& registry, PluginToken token) -> IInterface* {
180                 if (token) {
181                     Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
182                     return &state->picker;
183                 }
184                 return nullptr;
185             },
186         },
187         InterfaceTypeInfo {
188             this,
189             UID_RENDER_NODE_SCENE_UTIL,
190             CORE_NS::GetName<IRenderNodeSceneUtil>().data(),
191             nullptr,
__anon4aa43ab70402Agp3DPluginState192             [](IClassRegister& registry, PluginToken token) -> IInterface* {
193                 if (token) {
194                     Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
195                     return &state->renderNodeSceneUtil;
196                 }
197                 return nullptr;
198             },
199         },
200         InterfaceTypeInfo {
201             this,
202             UID_GRAPHICS_CONTEXT,
203             CORE_NS::GetName<IGraphicsContext>().data(),
__anon4aa43ab70502Agp3DPluginState204             [](IClassFactory& registry, PluginToken token) -> IInterface* {
205                 if (token) {
206                     Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
207                     if (!state->context) {
208                         state->context = make_unique<GraphicsContext>(*state, state->renderContext);
209                     }
210                     return state->context.get();
211                 }
212                 return nullptr;
213             },
__anon4aa43ab70602Agp3DPluginState214             [](IClassRegister& registry, PluginToken token) -> IInterface* {
215                 if (token) {
216                     Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
217                     return state->context.get();
218                 }
219                 return nullptr;
220             },
221         },
222     };
223 
DestroyAgp3DPluginState224     void Destroy(IRenderContext& engine)
225     {
226         context.reset();
227     }
228 };
229 
GraphicsContext(struct Agp3DPluginState & factory,IRenderContext & context)230 GraphicsContext::GraphicsContext(struct Agp3DPluginState& factory, IRenderContext& context)
231     : factory_(factory), context_(context)
232 {}
233 
~GraphicsContext()234 GraphicsContext ::~GraphicsContext() {}
235 
Init()236 void GraphicsContext::Init()
237 {
238     if (initialized_) {
239         return;
240     }
241     auto& engine = context_.GetEngine();
242 
243     meshUtil_ = make_unique<MeshUtil>(engine);
244     gltf2_ = make_unique<Gltf2>(*this);
245     CreateDefaultResources(context_.GetDevice(), defaultGpuResources_);
246 
247     auto* renderDataConfigurationLoader = GetInstance<IRenderDataConfigurationLoader>(
248         *context_.GetInterface<IClassRegister>(), UID_RENDER_DATA_CONFIGURATION_LOADER);
249     auto* dataStore = context_.GetRenderDataStoreManager().GetRenderDataStore("RenderDataStorePod");
250     if (renderDataConfigurationLoader && dataStore) {
251         auto& fileMgr = engine.GetFileManager();
252         constexpr string_view ppPath = "3drenderdataconfigurations://postprocess/";
253         if (auto dir = fileMgr.OpenDirectory(ppPath); dir) {
254             for (const auto& entry : dir->GetEntries()) {
255                 if (entry.type == IDirectory::Entry::Type::FILE) {
256                     const auto loadedPP =
257                         renderDataConfigurationLoader->LoadPostProcess(engine.GetFileManager(), ppPath + entry.name);
258                     if (loadedPP.loadResult.success) {
259                         auto pod = static_cast<IRenderDataStorePod*>(dataStore);
260                         pod->CreatePod("PostProcess", loadedPP.name, arrayviewU8(loadedPP.postProcessConfiguration));
261                     }
262                 }
263             }
264         }
265     }
266     sceneUtil_ = make_unique<SceneUtil>(*this);
267     renderUtil_ = make_unique<RenderUtil>(*this);
268 
269     initialized_ = true;
270 }
271 
GetRenderContext() const272 IRenderContext& GraphicsContext::GetRenderContext() const
273 {
274     return context_;
275 }
276 
GetRenderNodeGraphs(const IEcs & ecs) const277 array_view<const RenderHandleReference> GraphicsContext::GetRenderNodeGraphs(const IEcs& ecs) const
278 {
279     // NOTE: gets the render node graphs from built-in RenderSystem
280     if (IRenderSystem* rs = GetSystem<IRenderSystem>(ecs); rs) {
281         return rs->GetRenderNodeGraphs();
282     } else {
283         return {};
284     }
285 }
286 
GetSceneUtil() const287 ISceneUtil& GraphicsContext::GetSceneUtil() const
288 {
289     return *sceneUtil_;
290 }
291 
GetMeshUtil() const292 IMeshUtil& GraphicsContext::GetMeshUtil() const
293 {
294     return *meshUtil_;
295 }
296 
GetGltf() const297 IGltf2& GraphicsContext::GetGltf() const
298 {
299     return *gltf2_;
300 }
301 
GetRenderUtil() const302 IRenderUtil& GraphicsContext::GetRenderUtil() const
303 {
304     return *renderUtil_;
305 }
306 
GetInterface(const Uid & uid) const307 const IInterface* GraphicsContext::GetInterface(const Uid& uid) const
308 {
309     if (uid == IGraphicsContext::UID) {
310         return this;
311     }
312     return nullptr;
313 }
314 
GetInterface(const Uid & uid)315 IInterface* GraphicsContext::GetInterface(const Uid& uid)
316 {
317     if (uid == IGraphicsContext::UID) {
318         return this;
319     }
320     return nullptr;
321 }
322 
Ref()323 void GraphicsContext::Ref()
324 {
325     refcnt_++;
326 }
327 
Unref()328 void GraphicsContext::Unref()
329 {
330     if (--refcnt_ == 0) {
331         factory_.Destroy(context_);
332     }
333 }
334 
335 void RegisterTypes(IPluginRegister& pluginRegistry);
336 void UnregisterTypes(IPluginRegister& pluginRegistry);
337 
338 namespace {
CreatePlugin3D(IRenderContext & context)339 PluginToken CreatePlugin3D(IRenderContext& context)
340 {
341     Agp3DPluginState* token = new Agp3DPluginState { context, {}, {}, {} };
342     auto& registry = *context.GetInterface<IClassRegister>();
343     for (const auto& info : token->interfaces) {
344         registry.RegisterInterfaceType(info);
345     }
346 
347     RegisterTypes(GetPluginRegister());
348 
349     IFileManager& fileManager = context.GetEngine().GetFileManager();
350 #if (CORE3D_EMBEDDED_ASSETS_ENABLED == 1)
351     // Create engine:// protocol that points to embedded asset files.
352     fileManager.RegisterFilesystem("rofs3D", fileManager.CreateROFilesystem(BINARY_DATA_FOR_3D, SIZE_OF_DATA_FOR_3D));
353 #endif
354 #if (CORE3D_EMBEDDED_ASSETS_ENABLED == 0) || (CORE3D_DEV_ENABLED == 1)
355     const string assets = context.GetEngine().GetRootPath() + "../Lume3D/assets/3d/";
356     fileManager.RegisterPath("engine", assets, true);
357 #endif
358     for (uint32_t idx = 0; idx < countof(RENDER_DATA_PATHS); ++idx) {
359         fileManager.RegisterPath(RENDER_DATA_PATHS[idx].protocol, RENDER_DATA_PATHS[idx].uri, false);
360     }
361     context.GetDevice().GetShaderManager().LoadShaderFiles(SHADER_FILE_PATHS);
362 
363     return token;
364 }
365 
DestroyPlugin3D(PluginToken token)366 void DestroyPlugin3D(PluginToken token)
367 {
368     Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
369     IFileManager& fileManager = state->renderContext.GetEngine().GetFileManager();
370 
371     state->renderContext.GetDevice().GetShaderManager().UnloadShaderFiles(SHADER_FILE_PATHS);
372 #if (CORE3D_EMBEDDED_ASSETS_ENABLED == 1)
373     fileManager.UnregisterFilesystem("rofs3D");
374 #endif
375 #if (CORE3D_EMBEDDED_ASSETS_ENABLED == 0) || (CORE3D_DEV_ENABLED == 1)
376     const string assets = state->renderContext.GetEngine().GetRootPath() + "../Lume3D/assets/3d/";
377     fileManager.UnregisterPath("engine", assets);
378 #endif
379     for (uint32_t idx = 0; idx < countof(RENDER_DATA_PATHS); ++idx) {
380         fileManager.UnregisterPath(RENDER_DATA_PATHS[idx].protocol, RENDER_DATA_PATHS[idx].uri);
381     }
382 
383     UnregisterTypes(GetPluginRegister());
384 
385     auto& registry = *state->renderContext.GetInterface<IClassRegister>();
386     for (const auto& info : state->interfaces) {
387         registry.UnregisterInterfaceType(info);
388     }
389 
390     delete state;
391 }
392 
CreateEcsPlugin3D(IEcs & ecs)393 PluginToken CreateEcsPlugin3D(IEcs& ecs)
394 {
395     return {};
396 }
397 
DestroyEcsPlugin3D(PluginToken token)398 void DestroyEcsPlugin3D(PluginToken token) {}
399 
400 constexpr IRenderPlugin RENDER_PLUGIN(CreatePlugin3D, DestroyPlugin3D);
401 constexpr IEcsPlugin ECS_PLUGIN(CreateEcsPlugin3D, DestroyEcsPlugin3D);
402 } // namespace
403 
RegisterInterfaces3D(IPluginRegister & pluginRegistry)404 PluginToken RegisterInterfaces3D(IPluginRegister& pluginRegistry)
405 {
406     InitRegistry(pluginRegistry);
407     pluginRegistry.RegisterTypeInfo(RENDER_PLUGIN);
408     pluginRegistry.RegisterTypeInfo(ECS_PLUGIN);
409 
410     return &pluginRegistry;
411 }
412 
UnregisterInterfaces3D(PluginToken token)413 void UnregisterInterfaces3D(PluginToken token)
414 {
415     IPluginRegister* pluginRegistry = static_cast<IPluginRegister*>(token);
416     pluginRegistry->UnregisterTypeInfo(ECS_PLUGIN);
417     pluginRegistry->UnregisterTypeInfo(RENDER_PLUGIN);
418 }
419 CORE3D_END_NAMESPACE()
420