• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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