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 "render_data_store_post_process.h"
17 
18 #include <cinttypes>
19 #include <cstdint>
20 
21 #include <base/containers/fixed_string.h>
22 #include <base/math/matrix.h>
23 #include <render/datastore/render_data_store_render_pods.h>
24 #include <render/device/intf_shader_manager.h>
25 #include <render/intf_render_context.h>
26 
27 #include "datastore/render_data_store_manager.h"
28 #include "datastore/render_data_store_pod.h"
29 #include "loader/json_util.h"
30 #include "util/log.h"
31 
32 using namespace BASE_NS;
33 using namespace CORE_NS;
34 
35 RENDER_BEGIN_NAMESPACE()
36 namespace {
37 constexpr string_view RENDER_DATA_STORE_POST_PROCESS_TYPE_NAME { RenderDataStorePostProcess::TYPE_NAME };
38 constexpr string_view RENDER_DATA_STORE_POD_NAME { RenderDataStorePod::TYPE_NAME };
39 
40 constexpr string_view CUSTOM_PROPERTIES = "customProperties";
41 constexpr string_view GLOBAL_FACTOR = "globalFactor";
42 constexpr string_view CUSTOM_PROPERTY_DATA = "data";
43 
44 constexpr uint32_t SIZE_OF_FLOAT { sizeof(float) };
45 constexpr uint32_t SIZE_OF_VEC2 { sizeof(Math::Vec2) };
46 constexpr uint32_t SIZE_OF_VEC3 { sizeof(Math::Vec3) };
47 constexpr uint32_t SIZE_OF_VEC4 { sizeof(Math::Vec4) };
48 constexpr uint32_t SIZE_OF_MAT3X3 { sizeof(Math::Mat3X3) };
49 constexpr uint32_t SIZE_OF_MAT4X4 { sizeof(Math::Mat4X4) };
50 
51 constexpr uint32_t ALIGNMENT_OF_FLOAT { sizeof(float) };
52 constexpr uint32_t ALIGNMENT_OF_VEC2 { sizeof(float) * 2U };
53 constexpr uint32_t ALIGNMENT_OF_VEC3 { sizeof(float) * 4U };
54 constexpr uint32_t ALIGNMENT_OF_VEC4 { sizeof(float) * 4U };
55 constexpr uint32_t ALIGNMENT_OF_MAT3X3 { sizeof(float) * 4U * 3U };
56 constexpr uint32_t ALIGNMENT_OF_MAT4X4 { sizeof(float) * 4U * 4U };
57 
58 constexpr uint32_t MAX_LOCAL_DATA_BYTE_SIZE { PostProcessConstants::USER_LOCAL_FACTOR_BYTE_SIZE };
59 constexpr uint32_t MAX_GLOBAL_FACTOR_BYTE_SIZE { sizeof(Math::Vec4) };
60 
61 constexpr string_view TAA_SHADER_NAME { "rendershaders://shader/fullscreen_taa.shader" };
62 constexpr string_view FXAA_SHADER_NAME { "rendershaders://shader/fullscreen_fxaa.shader" };
63 constexpr string_view DOF_SHADER_NAME { "rendershaders://shader/depth_of_field.shader" };
64 constexpr string_view MB_SHADER_NAME { "rendershaders://shader/fullscreen_motion_blur.shader" };
65 
GetAlignment(uint32_t value,uint32_t align)66 inline constexpr uint32_t GetAlignment(uint32_t value, uint32_t align)
67 {
68     if (align == 0) {
69         return value;
70     } else {
71         return ((value + align - 1U) / align) * align;
72     }
73 }
74 
AppendValues(const uint32_t maxByteSize,const string_view type,const json::value * value,uint32_t & offset,uint8_t * data)75 void AppendValues(
76     const uint32_t maxByteSize, const string_view type, const json::value* value, uint32_t& offset, uint8_t* data)
77 {
78     if (type == "vec4") {
79         if ((offset + ALIGNMENT_OF_VEC4) <= maxByteSize) {
80             Math::Vec4* val = reinterpret_cast<Math::Vec4*>(data + offset);
81             FromJson(*value, *val);
82             offset = GetAlignment(offset + SIZE_OF_VEC4, ALIGNMENT_OF_VEC4);
83         }
84     } else if (type == "uvec4") {
85         if ((offset + ALIGNMENT_OF_VEC4) <= maxByteSize) {
86             Math::UVec4* val = reinterpret_cast<Math::UVec4*>(data + offset);
87             FromJson(*value, *val);
88             offset = GetAlignment(offset + SIZE_OF_VEC4, ALIGNMENT_OF_VEC4);
89         }
90     } else if (type == "ivec4") {
91         if ((offset + ALIGNMENT_OF_VEC4) <= maxByteSize) {
92             Math::UVec4* val = reinterpret_cast<Math::UVec4*>(data + offset);
93             FromJson(*value, *val);
94             offset = GetAlignment(offset + SIZE_OF_VEC4, ALIGNMENT_OF_VEC4);
95         }
96     } else if (type == "vec3") {
97         if ((offset + ALIGNMENT_OF_VEC3) <= maxByteSize) {
98             Math::Vec3* val = reinterpret_cast<Math::Vec3*>(data + offset);
99             FromJson(*value, *val);
100             offset = GetAlignment(offset + SIZE_OF_VEC3, ALIGNMENT_OF_VEC3);
101         }
102     } else if (type == "uvec3") {
103         if ((offset + ALIGNMENT_OF_VEC3) <= maxByteSize) {
104             Math::UVec3* val = reinterpret_cast<Math::UVec3*>(data + offset);
105             FromJson(*value, *val);
106             offset = GetAlignment(offset + SIZE_OF_VEC3, ALIGNMENT_OF_VEC3);
107         }
108     } else if (type == "ivec3") {
109         if ((offset + ALIGNMENT_OF_VEC3) <= maxByteSize) {
110             Math::UVec3* val = reinterpret_cast<Math::UVec3*>(data + offset);
111             FromJson(*value, *val);
112             offset = GetAlignment(offset + SIZE_OF_VEC3, ALIGNMENT_OF_VEC3);
113         }
114     } else if (type == "vec2") {
115         if ((offset + ALIGNMENT_OF_VEC2) <= maxByteSize) {
116             Math::Vec2* val = reinterpret_cast<Math::Vec2*>(data + offset);
117             FromJson(*value, *val);
118             offset = GetAlignment(offset + SIZE_OF_VEC2, ALIGNMENT_OF_VEC2);
119         }
120     } else if (type == "uvec2") {
121         if ((offset + ALIGNMENT_OF_VEC2) <= maxByteSize) {
122             Math::UVec2* val = reinterpret_cast<Math::UVec2*>(data + offset);
123             FromJson(*value, *val);
124             offset = GetAlignment(offset + SIZE_OF_VEC2, ALIGNMENT_OF_VEC2);
125         }
126     } else if (type == "ivec2") {
127         if ((offset + ALIGNMENT_OF_VEC2) <= maxByteSize) {
128             Math::UVec2* val = reinterpret_cast<Math::UVec2*>(data + offset);
129             FromJson(*value, *val);
130             offset = GetAlignment(offset + SIZE_OF_VEC2, ALIGNMENT_OF_VEC2);
131         }
132     } else if (type == "float") {
133         if ((offset + ALIGNMENT_OF_FLOAT) <= maxByteSize) {
134             float* val = reinterpret_cast<float*>(data + offset);
135             FromJson(*value, *val);
136             offset = GetAlignment(offset + SIZE_OF_FLOAT, ALIGNMENT_OF_FLOAT);
137         }
138     } else if (type == "uint") {
139         if ((offset + ALIGNMENT_OF_FLOAT) <= maxByteSize) {
140             uint32_t* val = reinterpret_cast<uint32_t*>(data + offset);
141             FromJson(*value, *val);
142             offset = GetAlignment(offset + SIZE_OF_FLOAT, ALIGNMENT_OF_FLOAT);
143         }
144     } else if (type == "int") {
145         if ((offset + ALIGNMENT_OF_FLOAT) <= maxByteSize) {
146             int32_t* val = reinterpret_cast<int32_t*>(data + offset);
147             FromJson(*value, *val);
148             offset = GetAlignment(offset + SIZE_OF_FLOAT, ALIGNMENT_OF_FLOAT);
149         }
150     } else if (type == "mat3x3") {
151         if ((offset + ALIGNMENT_OF_MAT3X3) <= maxByteSize) {
152             Math::Mat3X3* val = reinterpret_cast<Math::Mat3X3*>(data + offset);
153             FromJson(*value, *val);
154             offset = GetAlignment(offset + SIZE_OF_MAT3X3, ALIGNMENT_OF_MAT3X3);
155         }
156     } else if (type == "mat4x4") {
157         if ((offset + ALIGNMENT_OF_MAT4X4) <= maxByteSize) {
158             Math::Mat4X4* val = reinterpret_cast<Math::Mat4X4*>(data + offset);
159             FromJson(*value, *val);
160             offset = GetAlignment(offset + SIZE_OF_MAT4X4, ALIGNMENT_OF_MAT4X4);
161         }
162     } else {
163         PLUGIN_LOG_W("RENDER_VALIDATION: Invalid property type only int, uint, float, and XvecX variants, and mat3x3 "
164                      "and mat4x4 supported");
165     }
166     // NOTE: does not handle invalid types
167 }
168 } // namespace
169 
RenderDataStorePostProcess(const IRenderContext & renderContext,const string_view name)170 RenderDataStorePostProcess::RenderDataStorePostProcess(const IRenderContext& renderContext, const string_view name)
171     : renderContext_(renderContext), name_(name)
172 {}
173 
~RenderDataStorePostProcess()174 RenderDataStorePostProcess::~RenderDataStorePostProcess() {}
175 
Create(const string_view name)176 void RenderDataStorePostProcess::Create(const string_view name)
177 {
178     const auto lock = std::lock_guard(mutex_);
179 
180     if (!allPostProcesses_.contains(name)) {
181         CreateFromPod(name);
182     } else {
183         PLUGIN_LOG_I("Render data store post process with name (%s) already created.", name.data());
184     }
185 }
186 
Create(const string_view name,const string_view ppName,const RenderHandleReference & shader)187 void RenderDataStorePostProcess::Create(
188     const string_view name, const string_view ppName, const RenderHandleReference& shader)
189 {
190     const auto lock = std::lock_guard(mutex_);
191 
192     if (!allPostProcesses_.contains(name)) {
193         CreateFromPod(name);
194     }
195 
196     if (auto iter = allPostProcesses_.find(name); iter != allPostProcesses_.end()) {
197         auto& postProcesses = iter->second.postProcesses;
198         const uint32_t ppCount = static_cast<uint32_t>(postProcesses.size());
199         uint32_t ppIndex = ~0u;
200         for (uint32_t idx = 0; idx < ppCount; ++idx) {
201             if (postProcesses[idx].name == ppName) {
202                 ppIndex = idx;
203                 break;
204             }
205         }
206 
207         if (ppIndex < ppCount) {
208             // does not set variables
209             GetShaderProperties(shader, postProcesses[ppIndex].variables);
210             SetGlobalFactorsImpl(postProcesses[ppIndex].variables, ppIndex, iter->second);
211         } else {
212             PostProcess pp;
213             pp.id = static_cast<uint32_t>(postProcesses.size());
214             pp.name = ppName;
215             pp.shader = shader;
216             pp.variables = {}; // default variables, overwritten with shader default properties
217             GetShaderProperties(shader, pp.variables);
218             postProcesses.push_back(move(pp));
219             SetGlobalFactorsImpl(postProcesses[pp.id].variables, pp.id, iter->second);
220         }
221     } else {
222         PLUGIN_LOG_E("Post process creation error (name: %s, ppName: %s)", name.data(), ppName.data());
223     }
224 }
225 
Destroy(const string_view name)226 void RenderDataStorePostProcess::Destroy(const string_view name)
227 {
228     const auto lock = std::lock_guard(mutex_);
229 
230     if ((!name.empty()) && allPostProcesses_.contains(name)) {
231         allPostProcesses_.erase(name);
232         if (IRenderDataStorePod* dataStorePod = static_cast<IRenderDataStorePod*>(
233                 renderContext_.GetRenderDataStoreManager().GetRenderDataStore(RENDER_DATA_STORE_POD_NAME));
234             dataStorePod) {
235             dataStorePod->DestroyPod(RENDER_DATA_STORE_POST_PROCESS_TYPE_NAME, name);
236         }
237     } else {
238         PLUGIN_LOG_I("Post process not found: %s", name.data());
239     }
240 }
241 
Destroy(const string_view name,const string_view ppName)242 void RenderDataStorePostProcess::Destroy(const string_view name, const string_view ppName)
243 {
244     const auto lock = std::lock_guard(mutex_);
245 
246     if (auto iter = allPostProcesses_.find(name); iter != allPostProcesses_.end()) {
247         for (auto ppIter = iter->second.postProcesses.begin(); ppIter != iter->second.postProcesses.end(); ++ppIter) {
248             if (ppIter->name == ppName) {
249                 iter->second.postProcesses.erase(ppIter);
250                 break;
251             }
252         }
253     }
254 }
255 
Contains(const string_view name) const256 bool RenderDataStorePostProcess::Contains(const string_view name) const
257 {
258     const auto lock = std::lock_guard(mutex_);
259 
260     return allPostProcesses_.contains(name);
261 }
262 
Contains(const string_view name,const string_view ppName) const263 bool RenderDataStorePostProcess::Contains(const string_view name, const string_view ppName) const
264 {
265     const auto lock = std::lock_guard(mutex_);
266 
267     if (const auto iter = allPostProcesses_.find(name); iter != allPostProcesses_.cend()) {
268         for (const auto& ref : iter->second.postProcesses) {
269             if (ref.name == ppName) {
270                 return true;
271             }
272         }
273     }
274     return false;
275 }
276 
Set(const string_view name,const string_view ppName,const PostProcess::Variables & vars)277 void RenderDataStorePostProcess::Set(
278     const string_view name, const string_view ppName, const PostProcess::Variables& vars)
279 {
280     const auto lock = std::lock_guard(mutex_);
281 
282     if (auto iter = allPostProcesses_.find(name); iter != allPostProcesses_.end()) {
283         auto& postProcesses = iter->second.postProcesses;
284         const uint32_t ppCount = static_cast<uint32_t>(postProcesses.size());
285         for (uint32_t idx = 0; idx < ppCount; ++idx) {
286             if (postProcesses[idx].name == ppName) {
287                 SetImpl(vars, idx, iter->second);
288                 break;
289             }
290         }
291     }
292 }
293 
Set(const string_view name,const array_view<PostProcess::Variables> vars)294 void RenderDataStorePostProcess::Set(const string_view name, const array_view<PostProcess::Variables> vars)
295 {
296     const auto lock = std::lock_guard(mutex_);
297 
298     if (auto iter = allPostProcesses_.find(name); iter != allPostProcesses_.end()) {
299         const auto& postProcesses = iter->second.postProcesses;
300         const uint32_t ppCount =
301             Math::min(static_cast<uint32_t>(vars.size()), static_cast<uint32_t>(postProcesses.size()));
302         for (uint32_t idx = 0; idx < ppCount; ++idx) {
303             SetImpl(vars[idx], idx, iter->second);
304         }
305     }
306 }
307 
GetGlobalFactors(const string_view name) const308 RenderDataStorePostProcess::GlobalFactors RenderDataStorePostProcess::GetGlobalFactors(const string_view name) const
309 {
310     const auto lock = std::lock_guard(mutex_);
311 
312     if (auto iter = allPostProcesses_.find(name); iter != allPostProcesses_.end()) {
313         return iter->second.globalFactors;
314     } else {
315         return {};
316     }
317 }
318 
Get(const string_view name) const319 vector<RenderDataStorePostProcess::PostProcess> RenderDataStorePostProcess::Get(const string_view name) const
320 {
321     const auto lock = std::lock_guard(mutex_);
322 
323     if (const auto iter = allPostProcesses_.find(name); iter != allPostProcesses_.cend()) {
324         return iter->second.postProcesses;
325     }
326     return {};
327 }
328 
Get(const string_view name,const string_view ppName) const329 RenderDataStorePostProcess::PostProcess RenderDataStorePostProcess::Get(
330     const string_view name, const string_view ppName) const
331 {
332     const auto lock = std::lock_guard(mutex_);
333 
334     if (const auto iter = allPostProcesses_.find(name); iter != allPostProcesses_.cend()) {
335         for (const auto& ref : iter->second.postProcesses) {
336             if (ppName == ref.name) {
337                 return ref;
338             }
339         }
340     }
341     return {};
342 }
343 
CreateFromPod(const string_view name)344 void RenderDataStorePostProcess::CreateFromPod(const string_view name)
345 {
346     // create base post process render data store
347     if (IRenderDataStorePod* dataStorePod = static_cast<IRenderDataStorePod*>(
348             renderContext_.GetRenderDataStoreManager().GetRenderDataStore(RENDER_DATA_STORE_POD_NAME));
349         dataStorePod) {
350         PLUGIN_STATIC_ASSERT(
351             countof(PostProcessConstants::POST_PROCESS_NAMES) == PostProcessConstants::POST_PROCESS_COUNT);
352         auto& postProcessRef = allPostProcesses_[name];
353         // NOTE: needs to fetch the post process "properties" from shader custom properties
354         if (const auto arrView = dataStorePod->Get(name); arrView.size_bytes() == sizeof(PostProcessConfiguration)) {
355             // populate with built-in data and copy
356             PostProcessConfiguration ppConfig = *((const PostProcessConfiguration*)arrView.data());
357             FillDefaultPostProcessData(ppConfig, postProcessRef);
358         } else {
359             // create new
360             PostProcessConfiguration ppConfig;
361             dataStorePod->CreatePod(RENDER_DATA_STORE_POST_PROCESS_TYPE_NAME, name, arrayviewU8(ppConfig));
362             FillDefaultPostProcessData(ppConfig, postProcessRef);
363         }
364     }
365 }
366 
SetImpl(const PostProcess::Variables & vars,const uint32_t ppIndex,PostProcessStack & ppStack)367 void RenderDataStorePostProcess::SetImpl(
368     const PostProcess::Variables& vars, const uint32_t ppIndex, PostProcessStack& ppStack)
369 {
370     auto& postProcesses = ppStack.postProcesses;
371     PLUGIN_ASSERT(ppIndex < static_cast<uint32_t>(postProcesses.size()));
372     postProcesses[ppIndex].variables = vars;
373     SetGlobalFactorsImpl(vars, ppIndex, ppStack);
374 }
375 
SetGlobalFactorsImpl(const PostProcess::Variables & vars,const uint32_t ppIndex,PostProcessStack & ppStack)376 void RenderDataStorePostProcess::SetGlobalFactorsImpl(
377     const PostProcess::Variables& vars, const uint32_t ppIndex, PostProcessStack& ppStack)
378 {
379     PLUGIN_ASSERT(ppIndex < static_cast<uint32_t>(ppStack.postProcesses.size()));
380     // NOTE: does not copy vars
381     auto& globalFactors = ppStack.globalFactors;
382     if (ppIndex < PostProcessConstants::GLOBAL_FACTOR_COUNT) {
383         globalFactors.factors[ppIndex] = vars.factor;
384         globalFactors.enableFlags = (uint32_t(vars.enabled) << ppIndex);
385     } else if (vars.userFactorIndex < PostProcessConstants::USER_GLOBAL_FACTOR_COUNT) {
386         globalFactors.userFactors[vars.userFactorIndex] = vars.factor;
387     }
388 }
389 
FillDefaultPostProcessData(const PostProcessConfiguration & ppConfig,PostProcessStack & ppStack)390 void RenderDataStorePostProcess::FillDefaultPostProcessData(
391     const PostProcessConfiguration& ppConfig, PostProcessStack& ppStack)
392 {
393     const IShaderManager& shaderMgr = renderContext_.GetDevice().GetShaderManager();
394     auto FillBuiltInData = [&](const uint32_t idx, const uint32_t factorIndex, const uint32_t userFactorIndex,
395                                const Math::Vec4& factor, const string_view shaderName) {
396         PostProcess pp;
397         pp.id = idx;
398         pp.name = PostProcessConstants::POST_PROCESS_NAMES[pp.id];
399         pp.factorIndex = factorIndex;
400         pp.shader = shaderName.empty() ? RenderHandleReference {} : shaderMgr.GetShaderHandle(shaderName);
401         auto& vars = pp.variables;
402         vars.userFactorIndex = userFactorIndex;
403         vars.enabled = false;
404         vars.factor = factor;
405         ClearToValue(vars.customPropertyData, sizeof(vars.customPropertyData), 0x0, sizeof(vars.customPropertyData));
406         return pp;
407     };
408 
409     constexpr uint32_t defUserIdx { ~0u };
410     ppStack.postProcesses.push_back(FillBuiltInData(PostProcessConstants::RENDER_TONEMAP,
411         PostProcessConstants::RENDER_TONEMAP, defUserIdx, PostProcessConversionHelper::GetFactorTonemap(ppConfig), {}));
412     ppStack.postProcesses.push_back(
413         FillBuiltInData(PostProcessConstants::RENDER_VIGNETTE, PostProcessConstants::RENDER_VIGNETTE, defUserIdx,
414             PostProcessConversionHelper::GetFactorVignette(ppConfig), {}));
415     ppStack.postProcesses.push_back(FillBuiltInData(PostProcessConstants::RENDER_DITHER,
416         PostProcessConstants::RENDER_DITHER, defUserIdx, PostProcessConversionHelper::GetFactorDither(ppConfig), {}));
417     ppStack.postProcesses.push_back(
418         FillBuiltInData(PostProcessConstants::RENDER_COLOR_CONVERSION, PostProcessConstants::RENDER_COLOR_CONVERSION,
419             defUserIdx, PostProcessConversionHelper::GetFactorColorConversion(ppConfig), {}));
420     ppStack.postProcesses.push_back(
421         FillBuiltInData(PostProcessConstants::RENDER_COLOR_FRINGE_BIT, PostProcessConstants::RENDER_COLOR_FRINGE_BIT,
422             defUserIdx, PostProcessConversionHelper::GetFactorFringe(ppConfig), {}));
423 
424     ppStack.postProcesses.push_back(FillBuiltInData(
425         PostProcessConstants::RENDER_EMPTY_5, PostProcessConstants::RENDER_EMPTY_5, defUserIdx, {}, {}));
426     ppStack.postProcesses.push_back(FillBuiltInData(
427         PostProcessConstants::RENDER_EMPTY_6, PostProcessConstants::RENDER_EMPTY_6, defUserIdx, {}, {}));
428     ppStack.postProcesses.push_back(FillBuiltInData(
429         PostProcessConstants::RENDER_EMPTY_7, PostProcessConstants::RENDER_EMPTY_7, defUserIdx, {}, {}));
430 
431     ppStack.postProcesses.push_back(FillBuiltInData(PostProcessConstants::RENDER_BLUR,
432         PostProcessConfiguration::INDEX_BLUR, defUserIdx, PostProcessConversionHelper::GetFactorBlur(ppConfig), {}));
433     ppStack.postProcesses.push_back(FillBuiltInData(PostProcessConstants::RENDER_BLOOM,
434         PostProcessConfiguration::INDEX_BLOOM, defUserIdx, PostProcessConversionHelper::GetFactorBloom(ppConfig), {}));
435     ppStack.postProcesses.push_back(
436         FillBuiltInData(PostProcessConstants::RENDER_FXAA, PostProcessConfiguration::INDEX_FXAA, defUserIdx,
437             PostProcessConversionHelper::GetFactorFxaa(ppConfig), FXAA_SHADER_NAME));
438     ppStack.postProcesses.push_back(
439         FillBuiltInData(PostProcessConstants::RENDER_TAA, PostProcessConfiguration::INDEX_TAA, defUserIdx,
440             PostProcessConversionHelper::GetFactorTaa(ppConfig), TAA_SHADER_NAME));
441     {
442         auto& pp = ppStack.postProcesses.emplace_back();
443         pp.id = PostProcessConstants::RENDER_DOF;
444         pp.name = PostProcessConstants::POST_PROCESS_NAMES[pp.id];
445         pp.factorIndex = PostProcessConfiguration::INDEX_DOF;
446         pp.shader = shaderMgr.GetShaderHandle(DOF_SHADER_NAME);
447         auto& vars = pp.variables;
448         vars.userFactorIndex = defUserIdx;
449         vars.enabled = false;
450         auto factors = PostProcessConversionHelper::GetFactorDof(ppConfig);
451         CloneData(vars.customPropertyData, sizeof(vars.customPropertyData), &factors, sizeof(factors));
452         factors = PostProcessConversionHelper::GetFactorDof2(ppConfig);
453         CloneData(vars.customPropertyData + sizeof(factors), sizeof(vars.customPropertyData) - sizeof(factors),
454             &factors, sizeof(factors));
455     }
456 
457     ppStack.postProcesses.push_back(
458         FillBuiltInData(PostProcessConstants::RENDER_MOTION_BLUR, PostProcessConstants::RENDER_MOTION_BLUR, defUserIdx,
459             PostProcessConversionHelper::GetFactorMotionBlur(ppConfig), MB_SHADER_NAME));
460 
461     // fill global built-in factors
462     PLUGIN_ASSERT(PostProcessConstants::POST_PROCESS_COUNT == static_cast<uint32_t>(ppStack.postProcesses.size()));
463     for (size_t idx = 0; idx < ppStack.postProcesses.size(); ++idx) {
464         ppStack.globalFactors.factors[idx] = ppStack.postProcesses[idx].variables.factor;
465     }
466 }
467 
GetShaderProperties(const RenderHandleReference & shader,IRenderDataStorePostProcess::PostProcess::Variables & vars)468 void RenderDataStorePostProcess::GetShaderProperties(
469     const RenderHandleReference& shader, IRenderDataStorePostProcess::PostProcess::Variables& vars)
470 {
471     if (shader) {
472         const IShaderManager& shaderMgr = renderContext_.GetDevice().GetShaderManager();
473         if (const json::value* metaJson = shaderMgr.GetMaterialMetadata(shader); metaJson && metaJson->is_array()) {
474             for (const auto& ref : metaJson->array_) {
475                 if (const auto globalFactor = ref.find(GLOBAL_FACTOR); globalFactor && globalFactor->is_array()) {
476                     // process global factor "array", vec4
477                     uint32_t offset = 0;
478                     for (const auto& propRef : globalFactor->array_) {
479                         if (propRef.is_object()) {
480                             string_view type;
481                             const json::value* value = nullptr;
482                             for (const auto& dataObject : propRef.object_) {
483                                 if (dataObject.key == "type" && dataObject.value.is_string()) {
484                                     type = dataObject.value.string_;
485                                 } else if (dataObject.key == "value") {
486                                     value = &dataObject.value;
487                                 }
488                             }
489                             uint8_t* factorData = reinterpret_cast<uint8_t*>(&vars.factor);
490                             AppendValues(MAX_GLOBAL_FACTOR_BYTE_SIZE, type, value, offset, factorData);
491                         }
492                     }
493                 } else if (const auto customProps = ref.find(CUSTOM_PROPERTIES);
494                            customProps && customProps->is_array()) {
495                     // process custom properties i.e. local factors
496                     for (const auto& propRef : customProps->array_) {
497                         uint32_t offset = 0;
498                         if (const auto customData = propRef.find(CUSTOM_PROPERTY_DATA);
499                             customData && customData->is_array()) {
500                             if (offset >= MAX_LOCAL_DATA_BYTE_SIZE) {
501                                 break;
502                             }
503 
504                             for (const auto& dataValue : customData->array_) {
505                                 if (dataValue.is_object()) {
506                                     string_view type;
507                                     const json::value* value = nullptr;
508                                     for (const auto& dataObject : dataValue.object_) {
509                                         if (dataObject.key == "type" && dataObject.value.is_string()) {
510                                             type = dataObject.value.string_;
511                                         } else if (dataObject.key == "value") {
512                                             value = &dataObject.value;
513                                         }
514                                     }
515                                     AppendValues(
516                                         MAX_LOCAL_DATA_BYTE_SIZE, type, value, offset, vars.customPropertyData);
517                                 }
518                             }
519                         }
520                     }
521                 }
522             }
523         }
524     }
525 }
526 
527 // for plugin / factory interface
Create(IRenderContext & renderContext,char const * name)528 IRenderDataStore* RenderDataStorePostProcess::Create(IRenderContext& renderContext, char const* name)
529 {
530     // engine not used
531     return new RenderDataStorePostProcess(renderContext, name);
532 }
533 
Destroy(IRenderDataStore * aInstance)534 void RenderDataStorePostProcess::Destroy(IRenderDataStore* aInstance)
535 {
536     delete static_cast<RenderDataStorePostProcess*>(aInstance);
537 }
538 RENDER_END_NAMESPACE()
539