1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "render_context.h"
17 
18 #include <base/containers/fixed_string.h>
19 #include <base/containers/vector.h>
20 #include <core/intf_engine.h>
21 #include <core/io/intf_file_manager.h>
22 #include <core/plugin/intf_class_register.h>
23 
24 #if (RENDER_PERF_ENABLED == 1)
25 #include <core/perf/intf_performance_data_manager.h>
26 #endif
27 
28 #include "datastore/render_data_store_default_acceleration_structure_staging.h"
29 #include "datastore/render_data_store_default_gpu_resource_data_copy.h"
30 #include "datastore/render_data_store_default_staging.h"
31 #include "datastore/render_data_store_manager.h"
32 #include "datastore/render_data_store_pod.h"
33 #include "datastore/render_data_store_post_process.h"
34 #include "datastore/render_data_store_shader_passes.h"
35 #include "default_engine_constants.h"
36 #include "device/device.h"
37 #include "device/shader_manager.h"
38 #include "loader/render_data_loader.h"
39 #include "node/core_render_node_factory.h"
40 #include "nodecontext/render_node_graph_manager.h"
41 #include "nodecontext/render_node_graph_node_store.h"
42 #include "nodecontext/render_node_manager.h"
43 #include "nodecontext/render_node_post_process_util.h"
44 #include "renderer.h"
45 #include "util/render_util.h"
46 
47 #if RENDER_HAS_VULKAN_BACKEND
48 #include "vulkan/device_vk.h"
49 #endif
50 
51 #if (RENDER_HAS_GL_BACKEND) || (RENDER_HAS_GLES_BACKEND)
52 #include "gles/device_gles.h"
53 #include "gles/swapchain_gles.h"
54 #endif
55 
56 #include <algorithm>
57 
58 using namespace BASE_NS;
59 using namespace CORE_NS;
60 
61 RENDER_BEGIN_NAMESPACE()
62 namespace {
63 struct RegisterPathStrings {
64     string_view protocol;
65     string_view uri;
66 };
67 static constexpr RegisterPathStrings RENDER_DATA_PATHS[] = {
68     { "rendershaders", "rofsRndr://shaders/" },
69     { "rendershaderstates", "rofsRndr://shaderstates/" },
70     { "rendervertexinputdeclarations", "rofsRndr://vertexinputdeclarations/" },
71     { "renderpipelinelayouts", "rofsRndr://pipelinelayouts/" },
72     { "renderrenderdataconfigurations", "rofsRndr://renderdataconfigurations/" },
73     { "renderrendernodegraphs", "rofsRndr://rendernodegraphs/" },
74 };
75 
76 #if (RENDER_EMBEDDED_ASSETS_ENABLED == 1)
77 // Core Rofs Data.
78 extern "C" const uint64_t SIZEOFDATAFORRENDER;
79 extern "C" const void* const BINARYDATAFORRENDER[];
80 #endif
81 
82 // This is defined in the CMake generated version.cpp
LogRenderBuildInfo()83 void LogRenderBuildInfo()
84 {
85 #define RENDER_TO_STRING_INTERNAL(x) #x
86 #define RENDER_TO_STRING(x) RENDER_TO_STRING_INTERNAL(x)
87 
88     PLUGIN_LOG_I("RENDER_VALIDATION_ENABLED=" RENDER_TO_STRING(RENDER_VALIDATION_ENABLED));
89     PLUGIN_LOG_I("RENDER_DEV_ENABLED=" RENDER_TO_STRING(RENDER_DEV_ENABLED));
90 }
91 
92 template<class RenderDataStoreType>
FillRenderDataStoreTypeInfo()93 RenderDataStoreTypeInfo FillRenderDataStoreTypeInfo()
94 {
95     return {
96         { RenderDataStoreTypeInfo::UID },
97         RenderDataStoreType::UID,
98         RenderDataStoreType::TYPE_NAME,
99         RenderDataStoreType::Create,
100         RenderDataStoreType::Destroy,
101     };
102 }
103 
RegisterCoreRenderDataStores(RenderDataStoreManager & renderDataStoreManager)104 void RegisterCoreRenderDataStores(RenderDataStoreManager& renderDataStoreManager)
105 {
106     renderDataStoreManager.AddRenderDataStoreFactory(FillRenderDataStoreTypeInfo<RenderDataStorePod>());
107     renderDataStoreManager.AddRenderDataStoreFactory(
108         FillRenderDataStoreTypeInfo<RenderDataStoreDefaultAccelerationStructureStaging>());
109     renderDataStoreManager.AddRenderDataStoreFactory(FillRenderDataStoreTypeInfo<RenderDataStoreDefaultStaging>());
110     renderDataStoreManager.AddRenderDataStoreFactory(
111         FillRenderDataStoreTypeInfo<RenderDataStoreDefaultGpuResourceDataCopy>());
112     renderDataStoreManager.AddRenderDataStoreFactory(FillRenderDataStoreTypeInfo<RenderDataStoreShaderPasses>());
113     renderDataStoreManager.AddRenderDataStoreFactory(FillRenderDataStoreTypeInfo<RenderDataStorePostProcess>());
114 }
115 
116 template<typename DataStoreType>
CreateDataStore(IRenderDataStoreManager & renderDataStoreManager,const string_view name)117 IRenderDataStore* CreateDataStore(IRenderDataStoreManager& renderDataStoreManager, const string_view name)
118 {
119     IRenderDataStore* renderDataStore = renderDataStoreManager.Create(DataStoreType::UID, name.data());
120     PLUGIN_ASSERT(renderDataStore);
121     return renderDataStore;
122 }
123 
CreateDefaultRenderDataStores(IRenderDataStoreManager & renderDataStoreManager,RenderDataLoader & renderDataLoader)124 void CreateDefaultRenderDataStores(IRenderDataStoreManager& renderDataStoreManager, RenderDataLoader& renderDataLoader)
125 {
126     // add pod store
127     {
128         auto renderDataStorePod =
129             CreateDataStore<RenderDataStorePod>(renderDataStoreManager, RenderDataStorePod::TYPE_NAME);
130         if (renderDataStorePod) {
131             IRenderDataStorePod* renderDataStorePodTyped = static_cast<IRenderDataStorePod*>(renderDataStorePod);
132 
133             NodeGraphBackBufferConfiguration backBufferConfig {};
134             const auto len =
135                 DefaultEngineGpuResourceConstants::CORE_DEFAULT_BACKBUFFER.copy(backBufferConfig.backBufferName,
136                     NodeGraphBackBufferConfiguration::CORE_MAX_BACK_BUFFER_NAME_LENGTH - 1);
137             backBufferConfig.backBufferName[len] = '\0';
138             renderDataStorePodTyped->CreatePod(
139                 "NodeGraphConfiguration", "NodeGraphBackBufferConfiguration", arrayviewU8(backBufferConfig));
140 
141             // load and store configurations
142             renderDataLoader.Load("render", *renderDataStorePodTyped);
143         }
144     }
145 
146     CreateDataStore<RenderDataStoreDefaultAccelerationStructureStaging>(
147         renderDataStoreManager, RenderDataStoreDefaultAccelerationStructureStaging::TYPE_NAME);
148     CreateDataStore<RenderDataStoreDefaultStaging>(renderDataStoreManager, RenderDataStoreDefaultStaging::TYPE_NAME);
149     CreateDataStore<RenderDataStoreDefaultGpuResourceDataCopy>(
150         renderDataStoreManager, RenderDataStoreDefaultGpuResourceDataCopy::TYPE_NAME);
151     CreateDataStore<RenderDataStoreShaderPasses>(renderDataStoreManager, RenderDataStoreShaderPasses::TYPE_NAME);
152     CreateDataStore<RenderDataStorePostProcess>(renderDataStoreManager, RenderDataStorePostProcess::TYPE_NAME);
153 }
154 
CreateDefaultBuffers(IGpuResourceManager & gpuResourceMgr,vector<RenderHandleReference> & defaultGpuResources)155 void CreateDefaultBuffers(IGpuResourceManager& gpuResourceMgr, vector<RenderHandleReference>& defaultGpuResources)
156 {
157     defaultGpuResources.push_back(gpuResourceMgr.Create(DefaultEngineGpuResourceConstants::CORE_DEFAULT_GPU_BUFFER,
158         GpuBufferDesc { CORE_BUFFER_USAGE_TRANSFER_SRC_BIT | CORE_BUFFER_USAGE_TRANSFER_DST_BIT |
159                             CORE_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | CORE_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT |
160                             CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT | CORE_BUFFER_USAGE_STORAGE_BUFFER_BIT |
161                             CORE_BUFFER_USAGE_INDEX_BUFFER_BIT | CORE_BUFFER_USAGE_VERTEX_BUFFER_BIT |
162                             CORE_BUFFER_USAGE_INDIRECT_BUFFER_BIT | CORE_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT |
163                             CORE_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT,
164             (CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT), 0u, 1024u }));
165 }
166 
CreateDefaultTextures(IGpuResourceManager & gpuResourceMgr,vector<RenderHandleReference> & defaultGpuResources)167 void CreateDefaultTextures(IGpuResourceManager& gpuResourceMgr, vector<RenderHandleReference>& defaultGpuResources)
168 {
169     GpuImageDesc desc { ImageType::CORE_IMAGE_TYPE_2D, ImageViewType::CORE_IMAGE_VIEW_TYPE_2D,
170         Format::BASE_FORMAT_R8G8B8A8_UNORM, ImageTiling::CORE_IMAGE_TILING_OPTIMAL,
171         ImageUsageFlagBits::CORE_IMAGE_USAGE_SAMPLED_BIT | ImageUsageFlagBits::CORE_IMAGE_USAGE_TRANSFER_DST_BIT,
172         MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
173         0, // ImageCreateFlags
174         0, // EngineImageCreationFlags
175         2, 2, 1, 1, 1, SampleCountFlagBits::CORE_SAMPLE_COUNT_1_BIT, {} };
176 
177     constexpr uint32_t sizeOfUint32 = sizeof(uint32_t);
178     constexpr const uint32_t rgbData[4u] = { 0x0, 0x0, 0x0, 0x0 };
179     const auto rgbDataView = array_view(reinterpret_cast<const uint8_t*>(rgbData), sizeOfUint32 * countof(rgbData));
180     defaultGpuResources.push_back(
181         gpuResourceMgr.Create(DefaultEngineGpuResourceConstants::CORE_DEFAULT_GPU_IMAGE, desc, rgbDataView));
182     constexpr const uint32_t rgbDataWhite[4u] = { 0xFFFFffff, 0xFFFFffff, 0xFFFFffff, 0xFFFFffff };
183     const auto rgbDataViewWhite =
184         array_view(reinterpret_cast<const uint8_t*>(rgbDataWhite), sizeOfUint32 * countof(rgbDataWhite));
185     defaultGpuResources.push_back(
186         gpuResourceMgr.Create(DefaultEngineGpuResourceConstants::CORE_DEFAULT_GPU_IMAGE_WHITE, desc, rgbDataViewWhite));
187 }
188 
CreateDefaultTargets(IGpuResourceManager & gpuResourceMgr,vector<RenderHandleReference> & defaultGpuResources)189 void CreateDefaultTargets(IGpuResourceManager& gpuResourceMgr, vector<RenderHandleReference>& defaultGpuResources)
190 {
191     {
192         // hard-coded default backbuffer
193         // all presentations and swapchain semaphore syncs are done automatically for this client handle
194         GpuImageDesc desc {
195             ImageType::CORE_IMAGE_TYPE_2D,
196             ImageViewType::CORE_IMAGE_VIEW_TYPE_2D,
197             Format::BASE_FORMAT_R8G8B8A8_UNORM,
198             ImageTiling::CORE_IMAGE_TILING_OPTIMAL,
199             ImageUsageFlagBits::CORE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
200             MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
201             0, // ImageCreateFlags
202             EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_RESET_STATE_ON_FRAME_BORDERS |
203                 EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_DYNAMIC_BARRIERS, // EngineImageCreationFlags
204             2,
205             2,
206             1,
207             1,
208             1,
209             SampleCountFlagBits::CORE_SAMPLE_COUNT_1_BIT,
210             {},
211         };
212         GpuResourceManager& gpuResourceMgrImpl = (GpuResourceManager&)gpuResourceMgr;
213         // create as a swapchain image to get correct handle flags for fast check-up for additional processing
214         defaultGpuResources.push_back(gpuResourceMgrImpl.CreateSwapchainImage(
215             {}, DefaultEngineGpuResourceConstants::CORE_DEFAULT_BACKBUFFER, desc));
216     }
217     {
218         GpuImageDesc desc {
219             ImageType::CORE_IMAGE_TYPE_2D,
220             ImageViewType::CORE_IMAGE_VIEW_TYPE_2D,
221             Format::BASE_FORMAT_D16_UNORM,
222             ImageTiling::CORE_IMAGE_TILING_OPTIMAL,
223             ImageUsageFlagBits::CORE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
224                 ImageUsageFlagBits::CORE_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
225             MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
226                 MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT,
227             0,                                                                        // ImageCreateFlags
228             EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_DYNAMIC_BARRIERS, // EngineImageCreationFlags
229             2,
230             2,
231             1,
232             1,
233             1,
234             SampleCountFlagBits::CORE_SAMPLE_COUNT_1_BIT,
235             {},
236         };
237         defaultGpuResources.push_back(
238             gpuResourceMgr.Create(DefaultEngineGpuResourceConstants::CORE_DEFAULT_BACKBUFFER_DEPTH, desc));
239     }
240 }
241 
CreateDefaultSamplers(IGpuResourceManager & gpuResourceMgr,vector<RenderHandleReference> & defaultGpuResources)242 void CreateDefaultSamplers(IGpuResourceManager& gpuResourceMgr, vector<RenderHandleReference>& defaultGpuResources)
243 {
244     defaultGpuResources.push_back(
245         gpuResourceMgr.Create(DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_NEAREST_REPEAT,
246             GpuSamplerDesc {
247                 Filter::CORE_FILTER_NEAREST,                          // magFilter
248                 Filter::CORE_FILTER_NEAREST,                          // minFilter
249                 Filter::CORE_FILTER_NEAREST,                          // mipMapMode
250                 SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_REPEAT, // addressModeU
251                 SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_REPEAT, // addressModeV
252                 SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_REPEAT, // addressModeW
253             }));
254     defaultGpuResources.push_back(
255         gpuResourceMgr.Create(DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_NEAREST_CLAMP,
256             GpuSamplerDesc {
257                 Filter::CORE_FILTER_NEAREST,                                 // magFilter
258                 Filter::CORE_FILTER_NEAREST,                                 // minFilter
259                 Filter::CORE_FILTER_NEAREST,                                 // mipMapMode
260                 SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeU
261                 SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeV
262                 SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeW
263             }));
264 
265     defaultGpuResources.push_back(
266         gpuResourceMgr.Create(DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_LINEAR_REPEAT,
267             GpuSamplerDesc {
268                 Filter::CORE_FILTER_LINEAR,                           // magFilter
269                 Filter::CORE_FILTER_LINEAR,                           // minFilter
270                 Filter::CORE_FILTER_LINEAR,                           // mipMapMode
271                 SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_REPEAT, // addressModeU
272                 SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_REPEAT, // addressModeV
273                 SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_REPEAT, // addressModeW
274             }));
275     defaultGpuResources.push_back(
276         gpuResourceMgr.Create(DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_LINEAR_CLAMP,
277             GpuSamplerDesc {
278                 Filter::CORE_FILTER_LINEAR,                                  // magFilter
279                 Filter::CORE_FILTER_LINEAR,                                  // minFilter
280                 Filter::CORE_FILTER_LINEAR,                                  // mipMapMode
281                 SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeU
282                 SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeV
283                 SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeW
284             }));
285 
286     GpuSamplerDesc linearMipmapRepeat {
287         Filter::CORE_FILTER_LINEAR,                           // magFilter
288         Filter::CORE_FILTER_LINEAR,                           // minFilter
289         Filter::CORE_FILTER_LINEAR,                           // mipMapMode
290         SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_REPEAT, // addressModeU
291         SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_REPEAT, // addressModeV
292         SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_REPEAT, // addressModeW
293     };
294     linearMipmapRepeat.minLod = 0.0f;
295     linearMipmapRepeat.maxLod = 32.0f;
296     defaultGpuResources.push_back(gpuResourceMgr.Create(
297         DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_LINEAR_MIPMAP_REPEAT, linearMipmapRepeat));
298     GpuSamplerDesc linearMipmapClamp {
299         Filter::CORE_FILTER_LINEAR,                                  // magFilter
300         Filter::CORE_FILTER_LINEAR,                                  // minFilter
301         Filter::CORE_FILTER_LINEAR,                                  // mipMapMode
302         SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeU
303         SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeV
304         SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeW
305     };
306     linearMipmapClamp.minLod = 0.0f;
307     linearMipmapClamp.maxLod = 32.0f;
308     defaultGpuResources.push_back(gpuResourceMgr.Create(
309         DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_LINEAR_MIPMAP_CLAMP, linearMipmapClamp));
310 }
311 
GetPipelineCacheUri(DeviceBackendType backendType)312 string_view GetPipelineCacheUri(DeviceBackendType backendType)
313 {
314     switch (backendType) {
315         case DeviceBackendType::VULKAN:
316             return "cache://deviceVkCache.bin";
317         case DeviceBackendType::OPENGLES:
318             return "cache://deviceGLESCache.bin";
319         case DeviceBackendType::OPENGL:
320             return "cache://deviceGLCache.bin";
321         default:
322             break;
323     }
324     return "";
325 }
326 } // namespace
327 
CreateInstance(IEngine & engine)328 IRenderContext* RenderPluginState::CreateInstance(IEngine& engine)
329 {
330     if (!context_) {
331         context_ = IRenderContext::Ptr { new RenderContext(*this, engine) };
332     }
333     return context_.get();
334 }
335 
GetInstance()336 IRenderContext* RenderPluginState::GetInstance()
337 {
338     return context_.get();
339 }
340 
Destroy()341 void RenderPluginState::Destroy()
342 {
343     context_.reset();
344 }
345 
RenderContext(RenderPluginState & pluginState,IEngine & engine)346 RenderContext::RenderContext(RenderPluginState& pluginState, IEngine& engine)
347     : pluginState_(pluginState), engine_(engine), fileManager_(&engine.GetFileManager())
348 {
349     for (const auto& ref : interfaceInfos_) {
350         RegisterInterfaceType(ref);
351     }
352     LogRenderBuildInfo();
353     RegisterDefaultPaths();
354 }
355 
~RenderContext()356 RenderContext::~RenderContext()
357 {
358     GetPluginRegister().RemoveListener(*this);
359 
360     if (device_) {
361         device_->WaitForIdle();
362     }
363 
364     for (auto& info : plugins_) {
365         if (info.second && info.second->destroyPlugin) {
366             info.second->destroyPlugin(info.first);
367         }
368     }
369 
370     // NOTE: device needs to be active for render resources (e.g. with GLES)
371     if (device_) {
372         device_->Activate();
373 
374         if (device_->GetDeviceConfiguration().configurationFlags & CORE_DEVICE_CONFIGURATION_PIPELINE_CACHE_BIT) {
375             vector<uint8_t> pipelineCache = device_->GetPipelineCache();
376             if (auto file = fileManager_->CreateFile(GetPipelineCacheUri(device_->GetBackendType())); file) {
377                 file->Write(pipelineCache.data(), pipelineCache.size());
378             }
379         }
380     }
381     defaultGpuResources_.clear();
382     renderer_.reset();
383     renderNodeGraphMgr_.reset();
384     renderDataStoreMgr_.reset();
385     renderUtil_.reset(); // GLES semaphore/fence destruction device needs to be active
386     if (device_) {
387         device_->Deactivate();
388     }
389 }
390 
Init(const RenderCreateInfo & createInfo)391 RenderResultCode RenderContext::Init(const RenderCreateInfo& createInfo)
392 {
393     PLUGIN_LOG_D("Render init.");
394 
395     createInfo_ = createInfo;
396     device_ = CreateDevice(createInfo_.deviceCreateInfo);
397     if (!device_) {
398         PLUGIN_LOG_E("device not created successfully, invalid render interface");
399         return RenderResultCode::RENDER_ERROR;
400     } else {
401         device_->Activate();
402 
403         // Initialize the pipeline/ program cache.
404         if (device_->GetDeviceConfiguration().configurationFlags & CORE_DEVICE_CONFIGURATION_PIPELINE_CACHE_BIT) {
405             vector<uint8_t> pipelineCache;
406             if (auto file = fileManager_->OpenFile(GetPipelineCacheUri(device_->GetBackendType())); file) {
407                 pipelineCache.resize(static_cast<size_t>(file->GetLength()));
408                 file->Read(pipelineCache.data(), pipelineCache.size());
409             }
410             device_->InitializePipelineCache(pipelineCache);
411         }
412 
413         // set engine file manager with registered paths
414         ShaderManager& shaderMgr = (ShaderManager&)device_->GetShaderManager();
415         shaderMgr.SetFileManager(engine_.GetFileManager());
416 
417         {
418             IShaderManager::ShaderFilePathDesc desc;
419             desc.shaderPath = "rendershaders://";
420             desc.pipelineLayoutPath = "renderpipelinelayouts://";
421             // NOTE: does not have states and vids
422             shaderMgr.LoadShaderFiles(desc);
423         }
424         // make sure shaders found above have been created
425         shaderMgr.HandlePendingAllocations();
426 
427         renderDataStoreMgr_ = make_unique<RenderDataStoreManager>(*this);
428         RegisterCoreRenderDataStores(*renderDataStoreMgr_);
429 
430         // Add render data stores from plugins
431         for (auto info : CORE_NS::GetPluginRegister().GetTypeInfos(RenderDataStoreTypeInfo::UID)) {
432             renderDataStoreMgr_->AddRenderDataStoreFactory(*static_cast<const RenderDataStoreTypeInfo*>(info));
433         }
434 
435         auto loader = RenderDataLoader(*fileManager_);
436         CreateDefaultRenderDataStores(*renderDataStoreMgr_, loader);
437 
438         renderNodeGraphMgr_ = make_unique<RenderNodeGraphManager>(*device_, *fileManager_);
439 
440         auto& renderNodeMgr = renderNodeGraphMgr_->GetRenderNodeManager();
441         RegisterCoreRenderNodes(renderNodeMgr);
442         // Add render nodes from plugins
443         for (auto info : CORE_NS::GetPluginRegister().GetTypeInfos(RenderNodeTypeInfo::UID)) {
444             renderNodeMgr.AddRenderNodeFactory(*static_cast<const RenderNodeTypeInfo*>(info));
445         }
446 
447         renderUtil_ = make_unique<RenderUtil>(*this);
448 
449         renderer_ = make_unique<Renderer>(*this);
450 
451         IGpuResourceManager& gpuResourceMgr = device_->GetGpuResourceManager();
452         CreateDefaultBuffers(gpuResourceMgr, defaultGpuResources_);
453         CreateDefaultTextures(gpuResourceMgr, defaultGpuResources_);
454         CreateDefaultTargets(gpuResourceMgr, defaultGpuResources_);
455         CreateDefaultSamplers(gpuResourceMgr, defaultGpuResources_);
456 
457         device_->Deactivate();
458 
459         GetPluginRegister().AddListener(*this);
460 
461         for (auto info : CORE_NS::GetPluginRegister().GetTypeInfos(IRenderPlugin::UID)) {
462             if (auto renderPlugin = static_cast<const IRenderPlugin*>(info);
463                 renderPlugin && renderPlugin->createPlugin) {
464                 auto token = renderPlugin->createPlugin(*this);
465                 plugins_.push_back({ token, renderPlugin });
466             }
467         }
468 
469         return RenderResultCode::RENDER_SUCCESS;
470     }
471 }
472 
GetDevice() const473 IDevice& RenderContext::GetDevice() const
474 {
475     if (!device_) {
476         PLUGIN_LOG_E("Render Init not called or result was not success");
477     }
478     return *device_;
479 }
480 
GetRenderer() const481 IRenderer& RenderContext::GetRenderer() const
482 {
483     if (!renderer_) {
484         PLUGIN_LOG_E("Render Init not called or result was not success");
485     }
486     return *renderer_;
487 }
488 
GetRenderDataStoreManager() const489 IRenderDataStoreManager& RenderContext::GetRenderDataStoreManager() const
490 {
491     if (!renderDataStoreMgr_) {
492         PLUGIN_LOG_E("Render Init not called or result was not success");
493     }
494     return *renderDataStoreMgr_;
495 }
496 
GetRenderNodeGraphManager() const497 IRenderNodeGraphManager& RenderContext::GetRenderNodeGraphManager() const
498 {
499     if (!renderNodeGraphMgr_) {
500         PLUGIN_LOG_E("Render Init not called or result was not success");
501     }
502     return *renderNodeGraphMgr_;
503 }
504 
GetRenderUtil() const505 IRenderUtil& RenderContext::GetRenderUtil() const
506 {
507     if (!renderUtil_) {
508         PLUGIN_LOG_E("Render Init not called or result was not success");
509     }
510     return *renderUtil_;
511 }
512 
RegisterDefaultPaths()513 void RenderContext::RegisterDefaultPaths()
514 {
515     // Already handeled during plugin registration. If own filemanager instance is used then these are needed.
516 #if (RENDER_EMBEDDED_ASSETS_ENABLED == 1)
517     // Create engine:// protocol that points to embedded engine asset files.
518     PLUGIN_LOG_D("Registered core asset path: 'rofsRndr://render/'");
519     fileManager_->RegisterPath("render", "rofsRndr://render/", false);
520 #endif
521     for (uint32_t idx = 0; idx < countof(RENDER_DATA_PATHS); ++idx) {
522         fileManager_->RegisterPath(RENDER_DATA_PATHS[idx].protocol, RENDER_DATA_PATHS[idx].uri, false);
523     }
524 }
525 
CreateDevice(const DeviceCreateInfo & createInfo)526 unique_ptr<Device> RenderContext::CreateDevice(const DeviceCreateInfo& createInfo)
527 {
528     switch (createInfo.backendType) {
529         case DeviceBackendType::OPENGL:
530 #if (RENDER_HAS_GL_BACKEND)
531             return CreateDeviceGL(*this, createInfo);
532 #else
533             return nullptr;
534 #endif
535         case DeviceBackendType::OPENGLES:
536 #if (RENDER_HAS_GLES_BACKEND)
537             return CreateDeviceGLES(*this, createInfo);
538 #else
539             return nullptr;
540 #endif
541         case DeviceBackendType::VULKAN:
542 #if (RENDER_HAS_VULKAN_BACKEND)
543             return CreateDeviceVk(*this, createInfo);
544 #else
545             return nullptr;
546 #endif
547         default:
548             break;
549     }
550     return nullptr;
551 }
552 
GetEngine() const553 IEngine& RenderContext::GetEngine() const
554 {
555     return engine_;
556 }
557 
GetVersion()558 string_view RenderContext::GetVersion()
559 {
560     return {};
561 }
562 
GetCreateInfo() const563 RenderCreateInfo RenderContext::GetCreateInfo() const
564 {
565     return createInfo_;
566 }
567 
GetInterface(const Uid & uid) const568 const IInterface* RenderContext::GetInterface(const Uid& uid) const
569 {
570     if ((uid == IRenderContext::UID) || (uid == IClassFactory::UID) || (uid == IInterface::UID)) {
571         return static_cast<const IRenderContext*>(this);
572     }
573     if (uid == IClassRegister::UID) {
574         return static_cast<const IClassRegister*>(this);
575     }
576     return nullptr;
577 }
578 
GetInterface(const Uid & uid)579 IInterface* RenderContext::GetInterface(const Uid& uid)
580 {
581     if ((uid == IRenderContext::UID) || (uid == IClassFactory::UID) || (uid == IInterface::UID)) {
582         return static_cast<IRenderContext*>(this);
583     }
584     if (uid == IClassRegister::UID) {
585         return static_cast<IClassRegister*>(this);
586     }
587     return nullptr;
588 }
589 
Ref()590 void RenderContext::Ref()
591 {
592     refCount_++;
593 }
594 
Unref()595 void RenderContext::Unref()
596 {
597     if (--refCount_ == 1) {
598         pluginState_.Destroy();
599         delete this;
600     }
601 }
602 
CreateInstance(const Uid & uid)603 IInterface::Ptr RenderContext::CreateInstance(const Uid& uid)
604 {
605     const auto& data = GetInterfaceMetadata(uid);
606     if (data.createInterface) {
607         return IInterface::Ptr { data.createInterface(*this, data.token) };
608     }
609     return {};
610 }
611 
RegisterInterfaceType(const InterfaceTypeInfo & interfaceInfo)612 void RenderContext::RegisterInterfaceType(const InterfaceTypeInfo& interfaceInfo)
613 {
614     // keep interfaceTypeInfos_ sorted according to UIDs
615     const auto pos = std::upper_bound(interfaceTypeInfos_.cbegin(), interfaceTypeInfos_.cend(), interfaceInfo.uid,
616         [](Uid value, const InterfaceTypeInfo* element) { return value < element->uid; });
617     interfaceTypeInfos_.insert(pos, &interfaceInfo);
618 }
619 
UnregisterInterfaceType(const InterfaceTypeInfo & interfaceInfo)620 void RenderContext::UnregisterInterfaceType(const InterfaceTypeInfo& interfaceInfo)
621 {
622     if (!interfaceTypeInfos_.empty()) {
623         const auto pos = std::lower_bound(interfaceTypeInfos_.cbegin(), interfaceTypeInfos_.cend(), interfaceInfo.uid,
624             [](const InterfaceTypeInfo* element, Uid value) { return element->uid < value; });
625         if ((pos != interfaceTypeInfos_.cend()) && (*pos)->uid == interfaceInfo.uid) {
626             interfaceTypeInfos_.erase(pos);
627         }
628     }
629 }
630 
GetInterfaceMetadata() const631 array_view<const InterfaceTypeInfo* const> RenderContext::GetInterfaceMetadata() const
632 {
633     return interfaceTypeInfos_;
634 }
635 
GetInterfaceMetadata(const Uid & uid) const636 const InterfaceTypeInfo& RenderContext::GetInterfaceMetadata(const Uid& uid) const
637 {
638     static InterfaceTypeInfo invalidType {};
639 
640     if (!interfaceTypeInfos_.empty()) {
641         const auto pos = std::lower_bound(interfaceTypeInfos_.cbegin(), interfaceTypeInfos_.cend(), uid,
642             [](const InterfaceTypeInfo* element, Uid value) { return element->uid < value; });
643         if ((pos != interfaceTypeInfos_.cend()) && (*pos)->uid == uid) {
644             return *(*pos);
645         }
646     }
647     return invalidType;
648 }
649 
GetInstance(const Uid & uid) const650 IInterface* RenderContext::GetInstance(const Uid& uid) const
651 {
652     const auto& data = GetInterfaceMetadata(uid);
653     if (data.getInterface) {
654         return data.getInterface(const_cast<RenderContext&>(*this), data.token);
655     }
656     return nullptr;
657 }
658 
OnTypeInfoEvent(EventType type,array_view<const ITypeInfo * const> typeInfos)659 void RenderContext::OnTypeInfoEvent(EventType type, array_view<const ITypeInfo* const> typeInfos)
660 {
661     auto& renderNodeMgr = renderNodeGraphMgr_->GetRenderNodeManager();
662     if (type == EventType::ADDED) {
663         for (const auto* info : typeInfos) {
664             if (info && info->typeUid == IRenderPlugin::UID && static_cast<const IRenderPlugin*>(info)->createPlugin) {
665                 auto renderPlugin = static_cast<const IRenderPlugin*>(info);
666                 if (std::none_of(plugins_.begin(), plugins_.end(),
667                         [renderPlugin](const pair<PluginToken, const IRenderPlugin*>& pluginData) {
668                             return pluginData.second == renderPlugin;
669                         })) {
670                     auto token = renderPlugin->createPlugin(*this);
671                     plugins_.push_back({ token, renderPlugin });
672                 }
673             } else if (info && info->typeUid == RenderDataStoreTypeInfo::UID) {
674                 renderDataStoreMgr_->AddRenderDataStoreFactory(*static_cast<const RenderDataStoreTypeInfo*>(info));
675             } else if (info && info->typeUid == RenderNodeTypeInfo::UID) {
676                 renderNodeMgr.AddRenderNodeFactory(*static_cast<const RenderNodeTypeInfo*>(info));
677             }
678         }
679     } else if (type == EventType::REMOVED) {
680         for (const auto* info : typeInfos) {
681             if (info && info->typeUid == IRenderPlugin::UID) {
682                 auto renderPlugin = static_cast<const IRenderPlugin*>(info);
683                 if (auto pos = std::find_if(plugins_.begin(), plugins_.end(),
684                         [renderPlugin](const pair<PluginToken, const IRenderPlugin*>& pluginData) {
685                             return pluginData.second == renderPlugin;
686                         });
687                     pos != plugins_.end()) {
688                     if (renderPlugin->destroyPlugin) {
689                         renderPlugin->destroyPlugin(pos->first);
690                     }
691                     plugins_.erase(pos);
692                 }
693             } else if (info && info->typeUid == RenderDataStoreTypeInfo::UID) {
694                 renderDataStoreMgr_->RemoveRenderDataStoreFactory(*static_cast<const RenderDataStoreTypeInfo*>(info));
695             } else if (info && info->typeUid == RenderNodeTypeInfo::UID) {
696                 renderNodeGraphMgr_->Destroy(static_cast<const RenderNodeTypeInfo*>(info)->typeName);
697                 renderNodeMgr.RemoveRenderNodeFactory(*static_cast<const RenderNodeTypeInfo*>(info));
698             }
699         }
700     }
701 }
702 
703 RENDER_END_NAMESPACE()
704