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