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