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
58using namespace BASE_NS;
59using namespace CORE_NS;
60
61RENDER_BEGIN_NAMESPACE()
62namespace {
63struct RegisterPathStrings {
64    string_view protocol;
65    string_view uri;
66};
67static 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.
78extern "C" const uint64_t SIZEOFDATAFORRENDER;
79extern "C" const void* const BINARYDATAFORRENDER[];
80#endif
81
82// This is defined in the CMake generated version.cpp
83void 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
92template<class RenderDataStoreType>
93RenderDataStoreTypeInfo FillRenderDataStoreTypeInfo()
94{
95    return {
96        { RenderDataStoreTypeInfo::UID },
97        RenderDataStoreType::UID,
98        RenderDataStoreType::TYPE_NAME,
99        RenderDataStoreType::Create,
100        RenderDataStoreType::Destroy,
101    };
102}
103
104void 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
116template<typename DataStoreType>
117IRenderDataStore* 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
124void 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
155void 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
167void 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
189void 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
242void 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
312string_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
328IRenderContext* RenderPluginState::CreateInstance(IEngine& engine)
329{
330    if (!context_) {
331        context_ = IRenderContext::Ptr { new RenderContext(*this, engine) };
332    }
333    return context_.get();
334}
335
336IRenderContext* RenderPluginState::GetInstance()
337{
338    return context_.get();
339}
340
341void RenderPluginState::Destroy()
342{
343    context_.reset();
344}
345
346RenderContext::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
356RenderContext::~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
391RenderResultCode 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
473IDevice& 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
481IRenderer& 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
489IRenderDataStoreManager& 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
497IRenderNodeGraphManager& 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
505IRenderUtil& 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
513void 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
526unique_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
553IEngine& RenderContext::GetEngine() const
554{
555    return engine_;
556}
557
558string_view RenderContext::GetVersion()
559{
560    return {};
561}
562
563RenderCreateInfo RenderContext::GetCreateInfo() const
564{
565    return createInfo_;
566}
567
568const 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
579IInterface* 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
590void RenderContext::Ref()
591{
592    refCount_++;
593}
594
595void RenderContext::Unref()
596{
597    if (--refCount_ == 1) {
598        pluginState_.Destroy();
599        delete this;
600    }
601}
602
603IInterface::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
612void 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
620void 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
631array_view<const InterfaceTypeInfo* const> RenderContext::GetInterfaceMetadata() const
632{
633    return interfaceTypeInfos_;
634}
635
636const 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
650IInterface* 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
659void 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
703RENDER_END_NAMESPACE()
704