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