1 /*
2 * Copyright (C) 2023 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
53 if (!ecs_ || !graphicsContext_ || !renderContext_ || !engine_) {
54 WIDGET_LOGD("invalid input ecs %d, graphic context%d, render context %d, engine %d",
55 ecs_ != nullptr, graphicsContext_ != nullptr, renderContext_ != nullptr, engine_ != nullptr);
56 return;
57 }
58
59 PrepareResolutionInputBuffer();
60 GetDefaultStaging();
61 OnSizeChange(input.width_, input.height_);
62 }
63
RegistorShaderPath(const std::string & shaderPath)64 void LumeCustomRender::RegistorShaderPath(const std::string& shaderPath)
65 {
66 WIDGET_LOGD("lume custom render registor shader path");
67 engine_->GetFileManager().RegisterPath("shaders", shaderPath.c_str(), false);
68 static constexpr const RENDER_NS::IShaderManager::ShaderFilePathDesc desc { "shaders://" };
69 renderContext_->GetDevice().GetShaderManager().LoadShaderFiles(desc);
70 }
71
SetRenderOutput(const RENDER_NS::RenderHandleReference & output)72 void LumeCustomRender::SetRenderOutput(const RENDER_NS::RenderHandleReference& output)
73 {
74 if (output) {
75 RENDER_NS::IRenderNodeGraphManager& graphManager = renderContext_->GetRenderNodeGraphManager();
76 graphManager.SetRenderNodeGraphResources(GetRenderHandle(), {}, { &output, 1u });
77 }
78 }
79
GetDefaultStaging()80 void LumeCustomRender::GetDefaultStaging()
81 {
82 renderDataStoreDefaultStaging_ = reinterpret_cast<RENDER_NS::IRenderDataStoreDefaultStaging*>(
83 renderContext_->GetRenderDataStoreManager().GetRenderDataStore(RENDER_DATA_STORE_DEFAULT_STAGING));
84 if (renderDataStoreDefaultStaging_ == nullptr) {
85 WIDGET_LOGE("Get default staging error");
86 }
87 }
88
PrepareResolutionInputBuffer()89 void LumeCustomRender::PrepareResolutionInputBuffer()
90 {
91 const uint32_t resolutionSize = 2U;
92 if (!resolutionBuffer_.Alloc(resolutionSize)) {
93 WIDGET_LOGE("alloc resolution input buffer error!");
94 }
95 resolutionBuffer_.Update(0.0, 0U);
96 resolutionBuffer_.Update(0.0, 1U);
97 }
98
DestroyBuffer()99 void LumeCustomRender::DestroyBuffer()
100 {
101 shaderInputBufferHandle_ = {};
102 resolutionBuffer_ = {};
103 }
104
UpdateShaderSpecialization(const std::vector<uint32_t> & values)105 void LumeCustomRender::UpdateShaderSpecialization(const std::vector<uint32_t>& values)
106 {
107 RENDER_NS::IRenderDataStorePod* dataStore = static_cast<RENDER_NS::IRenderDataStorePod*>(
108 renderContext_->GetRenderDataStoreManager().GetRenderDataStore(RENDER_DATA_STORE_POD));
109 if (dataStore) {
110 RENDER_NS::ShaderSpecializationRenderPod shaderSpecialization;
111 auto count = std::min(static_cast<uint32_t>(values.size()),
112 RENDER_NS::ShaderSpecializationRenderPod::MAX_SPECIALIZATION_CONSTANT_COUNT);
113 shaderSpecialization.specializationConstantCount = count;
114
115 for (auto i = 0U; i < count; i++) {
116 shaderSpecialization.specializationFlags[i].value = values[i];
117 }
118 dataStore->Set(SPECIALIZATION_CONFIG_NAME, BASE_NS::arrayviewU8(shaderSpecialization));
119 }
120 }
121
DestroyDataStorePod()122 void LumeCustomRender::DestroyDataStorePod()
123 {
124 }
125
LoadImages(const std::vector<std::string> & imageUris)126 void LumeCustomRender::LoadImages(const std::vector<std::string>& imageUris)
127 {
128 for (auto& imageUri : imageUris) {
129 LoadImage(imageUri);
130 }
131 const std::string& turboTexture = "OhosRawFile://assets/blue_ball_compressed.png";
132 if (imageUris.back().find("ball_compressed") != std::string::npos) {
133 LoadImage(turboTexture);
134 }
135 }
136
LoadImage(const std::string & imageUri)137 void LumeCustomRender::LoadImage(const std::string& imageUri)
138 {
139 auto& imageManager = engine_->GetImageLoaderManager();
140 auto& gpuResourceMgr = renderContext_->GetDevice().GetGpuResourceManager();
141 auto handleManager = CORE_NS::GetManager<CORE3D_NS::IRenderHandleComponentManager>(*ecs_);
142
143 auto result = imageManager.LoadImage(imageUri.c_str(), 0);
144 if (!result.success) {
145 WIDGET_LOGE("3D image update fail %s error", imageUri.c_str());
146 return;
147 }
148
149 RENDER_NS::GpuImageDesc gpuImageDesc = gpuResourceMgr.CreateGpuImageDesc(result.image->GetImageDesc());
150 std::string name = std::string(IMAGE_NAME) + "_" + std::to_string(images_.size());
151 auto handle = gpuResourceMgr.Create(name.c_str(), gpuImageDesc, std::move(result.image));
152
153 auto entity = ecs_->GetEntityManager().CreateReferenceCounted();
154 handleManager->Create(entity);
155 handleManager->Write(entity)->reference = BASE_NS::move(handle);
156 images_.push_back(std::make_pair(imageUri, entity));
157 }
158
UnloadImages()159 void LumeCustomRender::UnloadImages()
160 {
161 images_.clear();
162 }
163
DestroyRes()164 void LumeCustomRender::DestroyRes()
165 {
166 DestroyBuffer();
167 DestroyDataStorePod();
168 UnloadImages();
169 UnloadRenderNodeGraph();
170 }
171
~LumeCustomRender()172 LumeCustomRender::~LumeCustomRender()
173 {
174 DestroyRes();
175 }
176
OnSizeChange(int32_t width,int32_t height)177 void LumeCustomRender::OnSizeChange(int32_t width, int32_t height)
178 {
179 uint32_t floatSize = 2u;
180 if (width <= 0 || height <= 0) {
181 WIDGET_LOGE("width and height must be larger than zero");
182 return;
183 }
184 width_ = width;
185 height_ = height;
186 const float* buffer = resolutionBuffer_.Map(floatSize);
187 if (!buffer) {
188 WIDGET_LOGE("custom render resolution resolutionBuffer error!");
189 return;
190 }
191
192 auto bSize = resolutionBuffer_.ByteSize();
193 if (!resolutionBufferHandle_) {
194 RENDER_NS::GpuBufferDesc bufferDesc {
195 RENDER_NS::CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT | RENDER_NS::CORE_BUFFER_USAGE_TRANSFER_DST_BIT,
196 RENDER_NS::CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT | RENDER_NS::CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT,
197 RENDER_NS::CORE_ENGINE_BUFFER_CREATION_DYNAMIC_RING_BUFFER, 0u };
198 bufferDesc.byteSize = bSize;
199 resolutionBufferHandle_ =
200 renderContext_->GetDevice().GetGpuResourceManager().Create(RESOLUTION_BUFFER, bufferDesc);
201 WIDGET_LOGD("create resolution buffer handle");
202 }
203
204 auto fWidth = static_cast<float>(width);
205 auto fHeight = static_cast<float>(height);
206 if ((buffer[0] == fWidth) && (buffer[1] == fHeight)) {
207 return;
208 }
209
210 WIDGET_LOGD("update custom shader resolution %f X %f", fWidth, fHeight);
211 resolutionBuffer_.Update(fWidth, 0U);
212 resolutionBuffer_.Update(fHeight, 1U);
213 BASE_NS::array_view<const uint8_t> data(reinterpret_cast<const uint8_t*>(buffer), bSize);
214 const RENDER_NS::BufferCopy bufferCopy { 0, 0, bSize };
215 renderDataStoreDefaultStaging_->CopyDataToBufferOnCpu(data, resolutionBufferHandle_, bufferCopy);
216 }
217
GetRenderHandles()218 BASE_NS::vector<RENDER_NS::RenderHandleReference> LumeCustomRender::GetRenderHandles()
219 {
220 return { renderHandle_ };
221 }
222
GetRenderHandle()223 const RENDER_NS::RenderHandleReference LumeCustomRender::GetRenderHandle()
224 {
225 return renderHandle_;
226 }
227
LoadRenderNodeGraph(const std::string & rngUri,const RENDER_NS::RenderHandleReference & output)228 void LumeCustomRender::LoadRenderNodeGraph(const std::string& rngUri,
229 const RENDER_NS::RenderHandleReference& output)
230 {
231 RENDER_NS::IRenderNodeGraphManager& graphManager = renderContext_->GetRenderNodeGraphManager();
232 auto* loader = &graphManager.GetRenderNodeGraphLoader();
233 auto graphUri = BASE_NS::string_view(rngUri.c_str());
234
235 auto const result = loader->Load(graphUri);
236 if (!result.error.empty()) {
237 WIDGET_LOGE("3D render node graph load fail: %s, uri %s", result.error.c_str(),
238 rngUri.c_str());
239 return;
240 }
241
242 renderHandle_ = graphManager.Create(
243 RENDER_NS::IRenderNodeGraphManager::RenderNodeGraphUsageType::RENDER_NODE_GRAPH_STATIC, result.desc);
244 }
245
UnloadRenderNodeGraph()246 void LumeCustomRender::UnloadRenderNodeGraph()
247 {
248 renderHandle_ = {};
249 }
250
UpdateShaderInputBuffer(const std::shared_ptr<ShaderInputBuffer> & shaderInputBuffer)251 bool LumeCustomRender::UpdateShaderInputBuffer(const std::shared_ptr<ShaderInputBuffer>& shaderInputBuffer)
252 {
253 if (!shaderInputBuffer || !shaderInputBuffer->IsValid()) {
254 WIDGET_LOGE("3D shader input buffer update fail: invalid shaderInputBuffer");
255 return false;
256 }
257
258 if (renderContext_ == nullptr) {
259 WIDGET_LOGE("3D shader input buffer update fail: Call UpdateBuffer before Initiliaze error");
260 return false;
261 }
262
263 auto fSize = shaderInputBuffer->FloatSize();
264 auto bSize = shaderInputBuffer->ByteSize();
265 if (bufferDesc_.byteSize != bSize) {
266 bufferDesc_.byteSize = bSize;
267 shaderInputBufferHandle_ = renderContext_->GetDevice().GetGpuResourceManager().Create(INPUT_BUFFER,
268 bufferDesc_);
269 }
270
271 const float* buffer = shaderInputBuffer->Map(fSize);
272 if (!buffer) {
273 WIDGET_LOGE("3D shader input buffer update fail: map shaderInputBuffer error!");
274 return false;
275 }
276
277 BASE_NS::array_view<const uint8_t> data(reinterpret_cast<const uint8_t*>(buffer), bSize);
278 const RENDER_NS::BufferCopy bufferCopy{0, 0, bSize};
279
280 renderDataStoreDefaultStaging_->CopyDataToBufferOnCpu(data, shaderInputBufferHandle_, bufferCopy);
281 return true;
282 }
283
OnDrawFrame()284 void LumeCustomRender::OnDrawFrame()
285 {
286 }
287
288 } // namespace name
289