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