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 WIDGET_LOGD("lume custom render load images");
129 for (auto& imageUri : imageUris) {
130 LoadImage(imageUri);
131 }
132 }
133
LoadImage(const std::string & imageUri)134 void LumeCustomRender::LoadImage(const std::string& imageUri)
135 {
136 auto find = std::find_if(images_.begin(), images_.end(),
137 [&imageUri](const std::pair<std::string, CORE_NS::EntityReference>& image) {
138 return image.first == imageUri;
139 });
140 if (find != images_.end()) {
141 return;
142 }
143 auto& imageManager = engine_->GetImageLoaderManager();
144 auto& gpuResourceMgr = renderContext_->GetDevice().GetGpuResourceManager();
145 auto handleManager = CORE_NS::GetManager<CORE3D_NS::IRenderHandleComponentManager>(*ecs_);
146
147 auto result = imageManager.LoadImage(imageUri.c_str(), 0);
148 if (!result.success) {
149 WIDGET_LOGE("3D image update fail %s error", imageUri.c_str());
150 return;
151 }
152
153 RENDER_NS::GpuImageDesc gpuImageDesc = gpuResourceMgr.CreateGpuImageDesc(result.image->GetImageDesc());
154 std::string name = std::string(IMAGE_NAME) + "_" + std::to_string(images_.size());
155 auto handle = gpuResourceMgr.Create(name.c_str(), gpuImageDesc, std::move(result.image));
156
157 auto entity = ecs_->GetEntityManager().CreateReferenceCounted();
158 handleManager->Create(entity);
159 handleManager->Write(entity)->reference = BASE_NS::move(handle);
160 images_.push_back(std::make_pair(imageUri, entity));
161 }
162
UnloadImages()163 void LumeCustomRender::UnloadImages()
164 {
165 images_.clear();
166 }
167
DestroyRes()168 void LumeCustomRender::DestroyRes()
169 {
170 DestroyBuffer();
171 DestroyDataStorePod();
172 UnloadImages();
173 UnloadRenderNodeGraph();
174 }
175
~LumeCustomRender()176 LumeCustomRender::~LumeCustomRender()
177 {
178 DestroyRes();
179 }
180
OnSizeChange(int32_t width,int32_t height)181 void LumeCustomRender::OnSizeChange(int32_t width, int32_t height)
182 {
183 uint32_t floatSize = 2u;
184 const float* buffer = resolutionBuffer_.Map(floatSize);
185 if (!buffer) {
186 WIDGET_LOGE("custom render resolution resolutionBuffer error!");
187 return;
188 }
189
190 auto bSize = resolutionBuffer_.ByteSize();
191 if (!resolutionBufferHandle_) {
192 RENDER_NS::GpuBufferDesc bufferDesc {
193 RENDER_NS::CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT | RENDER_NS::CORE_BUFFER_USAGE_TRANSFER_DST_BIT,
194 RENDER_NS::CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT | RENDER_NS::CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT,
195 RENDER_NS::CORE_ENGINE_BUFFER_CREATION_DYNAMIC_RING_BUFFER, 0u };
196 bufferDesc.byteSize = bSize;
197 resolutionBufferHandle_ =
198 renderContext_->GetDevice().GetGpuResourceManager().Create(RESOLUTION_BUFFER, bufferDesc);
199 WIDGET_LOGD("create resolution buffer handle");
200 }
201
202 auto fWidth = static_cast<float>(width);
203 auto fHeight = static_cast<float>(height);
204 if ((buffer[0] == fWidth) && (buffer[1] == fHeight)) {
205 return;
206 }
207
208 WIDGET_LOGD("update custom shader resolution %f X %f", fWidth, fHeight);
209 resolutionBuffer_.Update(fWidth, 0U);
210 resolutionBuffer_.Update(fHeight, 1U);
211 BASE_NS::array_view<const uint8_t> data(reinterpret_cast<const uint8_t*>(buffer), bSize);
212 const RENDER_NS::BufferCopy bufferCopy { 0, 0, bSize };
213 renderDataStoreDefaultStaging_->CopyDataToBufferOnCpu(data, resolutionBufferHandle_, bufferCopy);
214 }
215
GetRenderHandle()216 const RENDER_NS::RenderHandleReference LumeCustomRender::GetRenderHandle()
217 {
218 return renderHandle_;
219 }
220
LoadRenderNodeGraph(const std::string & rngUri,const RENDER_NS::RenderHandleReference & output)221 void LumeCustomRender::LoadRenderNodeGraph(const std::string& rngUri,
222 const RENDER_NS::RenderHandleReference& output)
223 {
224 RENDER_NS::IRenderNodeGraphManager& graphManager = renderContext_->GetRenderNodeGraphManager();
225 auto* loader = &graphManager.GetRenderNodeGraphLoader();
226 auto graphUri = BASE_NS::string_view(rngUri.c_str());
227
228 auto const result = loader->Load(graphUri);
229 if (!result.error.empty()) {
230 WIDGET_LOGE("3D render node graph load fail: %s, uri %s", result.error.c_str(),
231 rngUri.c_str());
232 return;
233 }
234
235 renderHandle_ = graphManager.Create(
236 RENDER_NS::IRenderNodeGraphManager::RenderNodeGraphUsageType::RENDER_NODE_GRAPH_STATIC, result.desc);
237 SetRenderOutput(output);
238 }
239
UnloadRenderNodeGraph()240 void LumeCustomRender::UnloadRenderNodeGraph()
241 {
242 renderHandle_ = {};
243 }
244
UpdateShaderInputBuffer(const std::shared_ptr<ShaderInputBuffer> & shaderInputBuffer)245 bool LumeCustomRender::UpdateShaderInputBuffer(const std::shared_ptr<ShaderInputBuffer>& shaderInputBuffer)
246 {
247 if (!shaderInputBuffer || !shaderInputBuffer->IsValid()) {
248 WIDGET_LOGE("3D shader input buffer update fail: invalid shaderInputBuffer");
249 return false;
250 }
251
252 if (renderContext_ == nullptr) {
253 WIDGET_LOGE("3D shader input buffer update fail: Call UpdateBuffer before Initiliaze error");
254 return false;
255 }
256
257 auto fSize = shaderInputBuffer->FloatSize();
258 auto bSize = shaderInputBuffer->ByteSize();
259 if (bufferDesc_.byteSize != bSize) {
260 bufferDesc_.byteSize = bSize;
261 shaderInputBufferHandle_ = renderContext_->GetDevice().GetGpuResourceManager().Create(INPUT_BUFFER,
262 bufferDesc_);
263 }
264
265 const float* buffer = shaderInputBuffer->Map(fSize);
266 if (!buffer) {
267 WIDGET_LOGE("3D shader input buffer update fail: map shaderInputBuffer error!");
268 return false;
269 }
270
271 BASE_NS::array_view<const uint8_t> data(reinterpret_cast<const uint8_t*>(buffer), bSize);
272 const RENDER_NS::BufferCopy bufferCopy{0, 0, bSize};
273
274 renderDataStoreDefaultStaging_->CopyDataToBufferOnCpu(data, shaderInputBufferHandle_, bufferCopy);
275 return true;
276 }
277
OnDrawFrame()278 void LumeCustomRender::OnDrawFrame()
279 {
280 }
281
282 } // namespace name
283