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