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 "custom/lume_custom_render.h"
17
18 #include <securec.h>
19
20 #include <3d/ecs/components/camera_component.h>
21 #include <3d/ecs/components/environment_component.h>
22 #include <3d/ecs/components/light_component.h>
23 #include <3d/ecs/components/render_configuration_component.h>
24 #include <3d/ecs/components/render_handle_component.h>
25 #include <3d/ecs/components/transform_component.h>
26 #include <3d/ecs/systems/intf_node_system.h>
27 #include <3d/util/intf_scene_util.h>
28
29 #include <base/containers/string_view.h>
30 #include <base/math/matrix_util.h>
31 #include <base/math/quaternion.h>
32 #include <base/math/quaternion_util.h>
33 #include <base/math/vector.h>
34 #include <base/math/vector_util.h>
35
36 #include <core/ecs/intf_system_graph_loader.h>
37 #include <core/image/intf_image_loader_manager.h>
38 #include <core/io/intf_file_manager.h>
39
40 #include <render/device/intf_shader_manager.h>
41 #include <render/nodecontext/intf_render_node_graph_manager.h>
42
43 #include "3d_widget_adapter_log.h"
44
45 namespace OHOS::Render3D {
Initialize(const CustomRenderInput & input)46 void LumeCustomRender::Initialize(const CustomRenderInput& input)
47 {
48 ecs_ = input.ecs_;
49 graphicsContext_ = input.graphicsContext_;
50 engine_ = input.engine_;
51 renderContext_ = input.renderContext_;
52 useMultiSwapChain_ = input.useMultiSwapChain_;
53
54 if (!ecs_ || !graphicsContext_ || !renderContext_ || !engine_) {
55 WIDGET_LOGD("invalid input ecs %d, graphic context%d, render context %d, engine %d",
56 ecs_ != nullptr,
57 graphicsContext_ != nullptr,
58 renderContext_ != nullptr,
59 engine_ != nullptr);
60 return;
61 }
62
63 PrepareResolutionInputBuffer();
64 GetDefaultStaging();
65 if (!useMultiSwapChain_) {
66 OnSizeChange(input.width_, input.height_);
67 }
68 width_ = input.width_;
69 height_ = input.height_;
70 }
71
RegistorShaderPath(const std::string & shaderPath)72 void LumeCustomRender::RegistorShaderPath(const std::string &shaderPath)
73 {
74 WIDGET_LOGD("lume custom render registor shader path");
75 // for old deprecated
76 auto tempPath = shaderPath;
77 auto index = tempPath.find_last_of("/");
78 auto strSize = tempPath.size();
79 if (index != std::string::npos && index != (strSize - 1)) {
80 auto fileName = tempPath.substr(index + 1);
81 auto suffixIndex = fileName.find_last_of(".");
82 if (suffixIndex != std::string::npos) {
83 tempPath = tempPath.substr(0, index);
84 auto dirIndex = tempPath.find_last_of("/");
85 tempPath = (dirIndex != std::string::npos) ? tempPath.substr(0, dirIndex) : tempPath;
86 }
87 }
88 engine_->GetFileManager().RegisterPath("shaders", tempPath.c_str(), false);
89 static constexpr const RENDER_NS::IShaderManager::ShaderFilePathDesc desc{ "shaders://" };
90 renderContext_->GetDevice().GetShaderManager().LoadShaderFiles(desc);
91 renderContext_->GetDevice().GetShaderManager().LoadShaderFile(shaderPath.c_str());
92 }
93
SetRenderOutput(const RENDER_NS::RenderHandleReference & output)94 void LumeCustomRender::SetRenderOutput(const RENDER_NS::RenderHandleReference &output)
95 {
96 if (output) {
97 RENDER_NS::IRenderNodeGraphManager &graphManager = renderContext_->GetRenderNodeGraphManager();
98 graphManager.SetRenderNodeGraphResources(GetRenderHandle(), {}, { &output, 1u });
99 }
100 }
101
GetDefaultStaging()102 void LumeCustomRender::GetDefaultStaging()
103 {
104 renderDataStoreDefaultStaging_ = BASE_NS::refcnt_ptr<RENDER_NS::IRenderDataStoreDefaultStaging>(
105 static_cast<RENDER_NS::IRenderDataStoreDefaultStaging *>(
106 renderContext_->GetRenderDataStoreManager().GetRenderDataStore(RENDER_DATA_STORE_DEFAULT_STAGING).get()));
107 if (renderDataStoreDefaultStaging_ == nullptr) {
108 WIDGET_LOGE("Get default staging error");
109 }
110 }
111
PrepareResolutionInputBuffer()112 void LumeCustomRender::PrepareResolutionInputBuffer()
113 {
114 const uint32_t resolutionSize = 2U;
115 if (!resolutionBuffer_.Alloc(resolutionSize)) {
116 WIDGET_LOGE("alloc resolution input buffer error!");
117 }
118 resolutionBuffer_.Update(0.0, 0U);
119 resolutionBuffer_.Update(0.0, 1U);
120 }
121
DestroyBuffer()122 void LumeCustomRender::DestroyBuffer()
123 {
124 shaderInputBufferHandle_ = {};
125 resolutionBuffer_ = {};
126 }
127
UpdateShaderSpecialization(const std::vector<uint32_t> & values)128 void LumeCustomRender::UpdateShaderSpecialization(const std::vector<uint32_t> &values)
129 {
130 auto dataStore = BASE_NS::refcnt_ptr<RENDER_NS::IRenderDataStorePod>(static_cast<RENDER_NS::IRenderDataStorePod *>(
131 renderContext_->GetRenderDataStoreManager().GetRenderDataStore(RENDER_DATA_STORE_POD).get()));
132 if (dataStore) {
133 RENDER_NS::ShaderSpecializationRenderPod shaderSpecialization;
134 auto count = std::min(static_cast<uint32_t>(values.size()),
135 RENDER_NS::ShaderSpecializationRenderPod::MAX_SPECIALIZATION_CONSTANT_COUNT);
136 shaderSpecialization.specializationConstantCount = count;
137
138 for (auto i = 0U; i < count; i++) {
139 shaderSpecialization.specializationFlags[i].value = values[i];
140 }
141 dataStore->Set(SPECIALIZATION_CONFIG_NAME, BASE_NS::arrayviewU8(shaderSpecialization));
142 }
143 }
144
DestroyDataStorePod()145 void LumeCustomRender::DestroyDataStorePod()
146 {}
147
LoadImages(const std::vector<std::string> & imageUris)148 void LumeCustomRender::LoadImages(const std::vector<std::string> &imageUris)
149 {
150 for (auto &imageUri : imageUris) {
151 LoadImage(imageUri);
152 }
153 }
154
LoadImage(const std::string & imageUri)155 void LumeCustomRender::LoadImage(const std::string &imageUri)
156 {
157 auto &imageManager = engine_->GetImageLoaderManager();
158 auto &gpuResourceMgr = renderContext_->GetDevice().GetGpuResourceManager();
159 auto handleManager = CORE_NS::GetManager<CORE3D_NS::IRenderHandleComponentManager>(*ecs_);
160
161 auto result = imageManager.LoadImage(imageUri.c_str(), 0);
162 if (!result.success) {
163 WIDGET_LOGE("3D image update fail %s error", imageUri.c_str());
164 return;
165 }
166
167 RENDER_NS::GpuImageDesc gpuImageDesc = gpuResourceMgr.CreateGpuImageDesc(result.image->GetImageDesc());
168 std::string name = std::string(IMAGE_NAME) + "_" + std::to_string(images_.size());
169 auto handle = gpuResourceMgr.Create(name.c_str(), gpuImageDesc, std::move(result.image));
170
171 auto entity = ecs_->GetEntityManager().CreateReferenceCounted();
172 handleManager->Create(entity);
173 handleManager->Write(entity)->reference = BASE_NS::move(handle);
174 images_.push_back(std::make_pair(imageUri, entity));
175 }
176
UnloadImages()177 void LumeCustomRender::UnloadImages()
178 {
179 images_.clear();
180 }
181
DestroyRes()182 void LumeCustomRender::DestroyRes()
183 {
184 DestroyBuffer();
185 DestroyDataStorePod();
186 UnloadImages();
187 UnloadRenderNodeGraph();
188 }
189
~LumeCustomRender()190 LumeCustomRender::~LumeCustomRender()
191 {
192 DestroyRes();
193 }
194
OnSizeChange(int32_t width,int32_t height)195 void LumeCustomRender::OnSizeChange(int32_t width, int32_t height)
196 {
197 uint32_t floatSize = 2u;
198 if (width <= 0 || height <= 0) {
199 WIDGET_LOGE("width and height must be larger than zero");
200 return;
201 }
202 width_ = static_cast<uint32_t>(width);
203 height_ = static_cast<uint32_t>(height);
204 const float *buffer = resolutionBuffer_.Map(floatSize);
205 if (!buffer) {
206 WIDGET_LOGE("custom render resolution resolutionBuffer error!");
207 return;
208 }
209
210 auto bSize = resolutionBuffer_.ByteSize();
211 if (!resolutionBufferHandle_ || useMultiSwapChain_) {
212 RENDER_NS::GpuBufferDesc bufferDesc{
213 RENDER_NS::CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT | RENDER_NS::CORE_BUFFER_USAGE_TRANSFER_DST_BIT,
214 RENDER_NS::CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT | RENDER_NS::CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT,
215 RENDER_NS::CORE_ENGINE_BUFFER_CREATION_DYNAMIC_RING_BUFFER,
216 0u};
217 bufferDesc.byteSize = bSize;
218 resolutionBufferHandle_ =
219 renderContext_->GetDevice().GetGpuResourceManager().Create(GetResolutionBufferName().c_str(), bufferDesc);
220 WIDGET_LOGD("create resolution buffer handle");
221 }
222
223 auto fWidth = static_cast<float>(width);
224 auto fHeight = static_cast<float>(height);
225 if ((buffer[0] == fWidth) && (buffer[1] == fHeight)) {
226 return;
227 }
228
229 WIDGET_LOGD("update custom shader resolution %f X %f", fWidth, fHeight);
230 resolutionBuffer_.Update(fWidth, 0U);
231 resolutionBuffer_.Update(fHeight, 1U);
232 BASE_NS::array_view<const uint8_t> data(reinterpret_cast<const uint8_t *>(buffer), bSize);
233 const RENDER_NS::BufferCopy bufferCopy{ 0, 0, bSize };
234 renderDataStoreDefaultStaging_->CopyDataToBufferOnCpu(data, resolutionBufferHandle_, bufferCopy);
235 }
236
GetRenderHandles()237 BASE_NS::vector<RENDER_NS::RenderHandleReference> LumeCustomRender::GetRenderHandles()
238 {
239 return {renderHandle_};
240 }
241
GetRenderHandle()242 const RENDER_NS::RenderHandleReference LumeCustomRender::GetRenderHandle()
243 {
244 return renderHandle_;
245 }
246
GetFileNameFromPath(const std::string & path)247 std::string GetFileNameFromPath(const std::string &path)
248 {
249 size_t found = path.find_last_of("/\\");
250 size_t foundEnd = path.rfind(".rng");
251 if (found > 0U && foundEnd >= (found + 1U) &&
252 found != std::string::npos && foundEnd != std::string::npos) {
253 return path.substr(found + 1, foundEnd - found - 1);
254 }
255 return path;
256 }
257
LoadRenderNodeGraph(const std::string & rngUri,const RENDER_NS::RenderHandleReference & output)258 void LumeCustomRender::LoadRenderNodeGraph(const std::string &rngUri, const RENDER_NS::RenderHandleReference &output)
259 {
260 const std::string rngFileName = GetFileNameFromPath(rngUri);
261 // add multiswapchain name, inputbuffer name, resolutionbuffer name by file name.
262 if (useMultiSwapChain_) {
263 swapchainName_ = rngFileName.c_str();
264 inputBufferName_ = ("INPUT_BUFFER_" + rngFileName).c_str();
265 resolutionBufferName_ = ("RESOLUTION_BUFFER_" + rngFileName).c_str();
266 OnSizeChange(width_, height_);
267 }
268
269 RENDER_NS::IRenderNodeGraphManager &graphManager = renderContext_->GetRenderNodeGraphManager();
270 auto *loader = &graphManager.GetRenderNodeGraphLoader();
271 auto graphUri = BASE_NS::string_view(rngUri.c_str());
272
273 auto const result = loader->Load(graphUri);
274 if (!result.error.empty()) {
275 WIDGET_LOGE("3D render node graph load fail: %s, uri %s", result.error.c_str(), rngUri.c_str());
276 return;
277 }
278
279 renderHandle_ = graphManager.Create(
280 RENDER_NS::IRenderNodeGraphManager::RenderNodeGraphUsageType::RENDER_NODE_GRAPH_STATIC, result.desc);
281 }
282
UnloadRenderNodeGraph()283 void LumeCustomRender::UnloadRenderNodeGraph()
284 {
285 renderHandle_ = {};
286 }
287
UpdateShaderInputBuffer(const std::shared_ptr<ShaderInputBuffer> & shaderInputBuffer)288 bool LumeCustomRender::UpdateShaderInputBuffer(const std::shared_ptr<ShaderInputBuffer> &shaderInputBuffer)
289 {
290 if (!shaderInputBuffer || !shaderInputBuffer->IsValid()) {
291 WIDGET_LOGE("3D shader input buffer update fail: invalid shaderInputBuffer");
292 return false;
293 }
294
295 if (renderContext_ == nullptr) {
296 WIDGET_LOGE("3D shader input buffer update fail: Call UpdateBuffer before Initiliaze error");
297 return false;
298 }
299
300 auto fSize = shaderInputBuffer->FloatSize();
301 auto bSize = shaderInputBuffer->ByteSize();
302 if (bufferDesc_.byteSize != bSize) {
303 bufferDesc_.byteSize = bSize;
304 shaderInputBufferHandle_ =
305 renderContext_->GetDevice().GetGpuResourceManager().Create(GetInputBufferName().c_str(), bufferDesc_);
306 }
307
308 const float *buffer = shaderInputBuffer->Map(fSize);
309 if (!buffer) {
310 WIDGET_LOGE("3D shader input buffer update fail: map shaderInputBuffer error!");
311 return false;
312 }
313
314 BASE_NS::array_view<const uint8_t> data(reinterpret_cast<const uint8_t *>(buffer), bSize);
315 const RENDER_NS::BufferCopy bufferCopy{0, 0, bSize};
316
317 renderDataStoreDefaultStaging_->CopyDataToBufferOnCpu(data, shaderInputBufferHandle_, bufferCopy);
318 return true;
319 }
320
OnDrawFrame()321 void LumeCustomRender::OnDrawFrame()
322 {}
323
324 } // namespace OHOS::Render3D
325