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