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