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 <3d/ecs/components/post_process_configuration_component.h>
17 #include <3d/ecs/components/render_handle_component.h>
18 #include <base/containers/array_view.h>
19 #include <base/containers/string.h>
20 #include <base/containers/type_traits.h>
21 #include <core/ecs/intf_ecs.h>
22 #include <core/intf_engine.h>
23 #include <render/datastore/intf_render_data_store_post_process.h>
24 #include <render/datastore/render_data_store_render_pods.h>
25 #include <render/device/intf_shader_manager.h>
26 #include <render/implementation_uids.h>
27 #include <render/intf_render_context.h>
28
29 #include "ComponentTools/base_manager.h"
30 #include "ComponentTools/base_manager.inl"
31 #include "util/json_util.h"
32 #include "util/property_util.h"
33
34 #define IMPLEMENT_MANAGER
35 #include "PropertyTools/property_macros.h"
36
37 CORE_BEGIN_NAMESPACE()
38 using CORE3D_NS::PostProcessConfigurationComponent;
39
40 DECLARE_PROPERTY_TYPE(CORE_NS::IPropertyHandle*);
41 DECLARE_PROPERTY_TYPE(RENDER_NS::RenderHandle);
42 DECLARE_PROPERTY_TYPE(RENDER_NS::RenderHandleReference);
43 DECLARE_PROPERTY_TYPE(PostProcessConfigurationComponent::PostProcessEffect);
44 DECLARE_PROPERTY_TYPE(BASE_NS::vector<PostProcessConfigurationComponent::PostProcessEffect>);
45
46 BEGIN_METADATA(
47 PostProcessConfigurationComponentPostProcessEffectMetaData, PostProcessConfigurationComponent::PostProcessEffect)
48 DECL_PROPERTY2(PostProcessConfigurationComponent::PostProcessEffect, name, "Effect Name", 0)
49 DECL_PROPERTY2(
50 PostProcessConfigurationComponent::PostProcessEffect, globalUserFactorIndex, "Global User Factor Index", 0)
51 DECL_PROPERTY2(PostProcessConfigurationComponent::PostProcessEffect, shader, "Shader", 0)
52 DECL_PROPERTY2(PostProcessConfigurationComponent::PostProcessEffect, enabled, "Enabled", 0)
53 DECL_PROPERTY2(PostProcessConfigurationComponent::PostProcessEffect, flags, "Additional Non Typed Flags", 0)
54 DECL_PROPERTY2(PostProcessConfigurationComponent::PostProcessEffect, factor, "Global Factor", 0)
55 DECL_PROPERTY2(PostProcessConfigurationComponent::PostProcessEffect, customProperties, "Custom Properties", 0)
56 END_METADATA(
57 PostProcessConfigurationComponentPostProcessEffectMetaData, PostProcessConfigurationComponent::PostProcessEffect)
58
59 // Needed to get containerMethods through MetaData() -> Property -> metaData -> containerMethods
60 DECLARE_CONTAINER_API(PPCC_PPE, PostProcessConfigurationComponent::PostProcessEffect);
61 CORE_END_NAMESPACE()
62
63 CORE3D_BEGIN_NAMESPACE()
64 using namespace BASE_NS;
65 using namespace CORE_NS;
66 using namespace RENDER_NS;
67
68 namespace {
69 constexpr uint32_t CUSTOM_PROPERTY_POD_CONTAINER_BYTE_SIZE { PostProcessConstants::USER_LOCAL_FACTOR_BYTE_SIZE };
70 constexpr string_view CUSTOM_PROPERTIES = "customProperties";
71 constexpr string_view CUSTOM_PROPERTY_DATA = "data";
72 constexpr string_view NAME = "name";
73 constexpr string_view DISPLAY_NAME = "displayName";
74
UpdateCustomPropertyMetadata(const json::value & customProperties,CustomPropertyPodContainer & properties)75 void UpdateCustomPropertyMetadata(const json::value& customProperties, CustomPropertyPodContainer& properties)
76 {
77 if (customProperties && customProperties.is_array()) {
78 for (const auto& ref : customProperties.array_) {
79 if (const auto customProps = ref.find(CUSTOM_PROPERTIES); customProps && customProps->is_array()) {
80 // process custom properties i.e. local factors
81 for (const auto& propRef : customProps->array_) {
82 if (const auto customData = propRef.find(CUSTOM_PROPERTY_DATA); customData) {
83 // reserve the property count
84 properties.ReservePropertyCount(customData->array_.size());
85 for (const auto& dataValue : customData->array_) {
86 if (dataValue.is_object()) {
87 string_view name;
88 string_view displayName;
89 string_view type;
90 const json::value* value = nullptr;
91 for (const auto& dataObject : dataValue.object_) {
92 if (dataObject.key == NAME && dataObject.value.is_string()) {
93 name = dataObject.value.string_;
94 } else if (dataObject.key == DISPLAY_NAME && dataObject.value.is_string()) {
95 displayName = dataObject.value.string_;
96 } else if (dataObject.key == "type" && dataObject.value.is_string()) {
97 type = dataObject.value.string_;
98 } else if (dataObject.key == "value") {
99 value = &dataObject.value;
100 }
101 }
102
103 const PropertyTypeDecl typeDecl =
104 CustomPropertyPodHelper::GetPropertyTypeDeclaration(type);
105 const size_t align = CustomPropertyPodHelper::GetPropertyTypeAlignment(typeDecl);
106 const size_t offset = [](size_t value, size_t align) -> size_t {
107 if (align == 0U) {
108 return value;
109 }
110 return ((value + align - 1U) / align) * align;
111 }(properties.GetByteSize(), align);
112 properties.AddOffsetProperty(name, displayName, offset, typeDecl);
113 CustomPropertyPodHelper::SetCustomPropertyBlobValue(
114 typeDecl, value, properties, offset);
115 }
116 }
117 }
118 }
119 }
120 }
121 }
122 }
123 } // namespace
124
125 class PostProcessConfigurationComponentManager final : public IPostProcessConfigurationComponentManager,
126 public IPropertyApi {
127 using ComponentId = IComponentManager::ComponentId;
128
129 public:
130 explicit PostProcessConfigurationComponentManager(IEcs& ecs) noexcept;
131 ~PostProcessConfigurationComponentManager() override;
132
133 // IPropertyApi
134 size_t PropertyCount() const override;
135 const Property* MetaData(size_t index) const override;
136 array_view<const Property> MetaData() const override;
137 IPropertyHandle* Create() const override;
138 IPropertyHandle* Clone(const IPropertyHandle*) const override;
139 void Release(IPropertyHandle*) const override;
140 uint64_t Type() const override;
141
142 // IComponentManager
143 virtual string_view GetName() const override;
144 virtual Uid GetUid() const override;
145 size_t GetComponentCount() const override;
146 const IPropertyApi& GetPropertyApi() const override;
147 Entity GetEntity(ComponentId index) const override;
148 uint32_t GetComponentGeneration(ComponentId index) const override;
149 bool HasComponent(Entity entity) const override;
150 IComponentManager::ComponentId GetComponentId(Entity entity) const override;
151 void Create(Entity entity) override;
152 bool Destroy(Entity entity) override;
153 void Gc() override;
154 void Destroy(array_view<const Entity> gcList) override;
155 vector<Entity> GetAddedComponents() override;
156 vector<Entity> GetRemovedComponents() override;
157 vector<Entity> GetUpdatedComponents() override;
158 CORE_NS::ComponentManagerModifiedFlags GetModifiedFlags() const override;
159 void ClearModifiedFlags() override;
160 uint32_t GetGenerationCounter() const override;
161 void SetData(Entity entity, const IPropertyHandle& dataHandle) override;
162 const IPropertyHandle* GetData(Entity entity) const override;
163 IPropertyHandle* GetData(Entity entity) override;
164 void SetData(ComponentId index, const IPropertyHandle& dataHandle) override;
165 const IPropertyHandle* GetData(ComponentId index) const override;
166 IPropertyHandle* GetData(ComponentId index) override;
167 IEcs& GetEcs() const override;
168
169 // IPostProcessConfigurationComponentManager
170 PostProcessConfigurationComponent Get(ComponentId index) const override;
171 PostProcessConfigurationComponent Get(Entity entity) const override;
172 void Set(ComponentId index, const PostProcessConfigurationComponent& aData) override;
173 void Set(Entity entity, const PostProcessConfigurationComponent& aData) override;
174 ScopedHandle<const PostProcessConfigurationComponent> Read(ComponentId index) const override;
175 ScopedHandle<const PostProcessConfigurationComponent> Read(Entity entity) const override;
176 ScopedHandle<PostProcessConfigurationComponent> Write(ComponentId index) override;
177 ScopedHandle<PostProcessConfigurationComponent> Write(Entity entity) override;
178
179 // internal, non-public
180 void Updated(Entity entity);
181
182 private:
183 BEGIN_PROPERTY(PostProcessConfigurationComponent, componentProperties_)
184 #include <3d/ecs/components/post_process_configuration_component.h>
185 END_PROPERTY();
186 static constexpr array_view<const Property> componentMetaData_ { componentProperties_,
187 countof(componentProperties_) };
188
189 bool IsMatchingHandle(const IPropertyHandle& handle);
190
191 static constexpr uint64_t typeHash_ =
192 BASE_NS::CompileTime::FNV1aHash(CORE_NS::GetName<PostProcessConfigurationComponent>().data(),
193 CORE_NS::GetName<PostProcessConfigurationComponent>().size());
194
195 class ComponentHandle : public IPropertyHandle, IPropertyApi {
196 public:
197 ComponentHandle() = delete;
198 ComponentHandle(PostProcessConfigurationComponentManager* owner, Entity entity) noexcept;
199 ComponentHandle(PostProcessConfigurationComponentManager* owner, Entity entity,
200 const PostProcessConfigurationComponent& data) noexcept;
201 ~ComponentHandle() override = default;
202 ComponentHandle(const ComponentHandle& other) = delete;
203 ComponentHandle(ComponentHandle&& other) noexcept;
204 ComponentHandle& operator=(const ComponentHandle& other) = delete;
205 ComponentHandle& operator=(ComponentHandle&& other) noexcept;
206
207 // IPropertyHandle
208 const IPropertyApi* Owner() const override;
209 size_t Size() const override;
210 const void* RLock() const override;
211 void RUnlock() const override;
212 void* WLock() override;
213 void WUnlock() override;
214
215 // IPropertyApi
216 size_t PropertyCount() const override;
217 const Property* MetaData(size_t index) const override;
218 array_view<const Property> MetaData() const override;
219 uint64_t Type() const override;
220 IPropertyHandle* Create() const override;
221 IPropertyHandle* Clone(const IPropertyHandle* src) const override;
222 void Release(IPropertyHandle* handle) const override;
223
224 void UpdateMetadata();
225
226 PostProcessConfigurationComponentManager* manager_ { nullptr };
227 Entity entity_;
228 uint32_t generation_ { 0u };
229 bool dirty_ { false };
230 mutable std::atomic_int32_t rLocked_ { 0 };
231 mutable bool wLocked_ { false };
232 PostProcessConfigurationComponent data_;
233
234 // shader per single post process
235 vector<Entity> effectShaders_;
236 // custom property blob per single post process shader
237 vector<unique_ptr<CustomPropertyPodContainer>> customProperties_;
238 };
239
240 IEcs& ecs_;
241 IShaderManager& shaderManager_;
242 IRenderHandleComponentManager* renderHandleManager_ { nullptr };
243
244 uint32_t generationCounter_ { 0u };
245 uint32_t modifiedFlags_ { 0u };
246 unordered_map<Entity, ComponentId> entityComponent_;
247 vector<ComponentHandle> components_;
248 BASE_NS::vector<Entity> added_;
249 BASE_NS::vector<Entity> removed_;
250 BASE_NS::vector<Entity> updated_;
251 };
252
PostProcessConfigurationComponentManager(IEcs & ecs)253 PostProcessConfigurationComponentManager::PostProcessConfigurationComponentManager(IEcs& ecs) noexcept
254 : ecs_(ecs), shaderManager_(GetInstance<IRenderContext>(
255 *ecs.GetClassFactory().GetInterface<IClassRegister>(), UID_RENDER_CONTEXT)
256 ->GetDevice()
257 .GetShaderManager()),
258 renderHandleManager_(GetManager<IRenderHandleComponentManager>(ecs))
259 {}
260
261 PostProcessConfigurationComponentManager::~PostProcessConfigurationComponentManager() = default;
262
263 // IPropertyApi
PropertyCount() const264 size_t PostProcessConfigurationComponentManager::PropertyCount() const
265 {
266 return componentMetaData_.size();
267 }
268
MetaData(size_t index) const269 const Property* PostProcessConfigurationComponentManager::MetaData(size_t index) const
270 {
271 if (index < componentMetaData_.size()) {
272 return &componentMetaData_[index];
273 }
274 return nullptr;
275 }
276
MetaData() const277 array_view<const Property> PostProcessConfigurationComponentManager::MetaData() const
278 {
279 return componentMetaData_;
280 }
281
Create() const282 IPropertyHandle* PostProcessConfigurationComponentManager::Create() const
283 {
284 return new ComponentHandle(const_cast<PostProcessConfigurationComponentManager*>(this), {}, {});
285 }
286
Clone(const IPropertyHandle * src) const287 IPropertyHandle* PostProcessConfigurationComponentManager::Clone(const IPropertyHandle* src) const
288 {
289 if (src) {
290 auto owner = src->Owner();
291 if (owner == this) {
292 auto* h = static_cast<const ComponentHandle*>(src);
293 return new ComponentHandle(const_cast<PostProcessConfigurationComponentManager*>(this), {}, h->data_);
294 } else if (owner) {
295 return owner->Clone(src);
296 }
297 }
298 return nullptr;
299 }
300
Release(IPropertyHandle * dst) const301 void PostProcessConfigurationComponentManager::Release(IPropertyHandle* dst) const
302 {
303 if (dst) {
304 auto owner = dst->Owner();
305 if (owner == this) {
306 // we can only destroy things we "own" (know)
307 auto* handle = static_cast<ComponentHandle*>(dst);
308 if (auto id = GetComponentId(handle->entity_); id != IComponentManager::INVALID_COMPONENT_ID) {
309 if (&components_[id] == handle) {
310 // This is one of the components (bound to an entity) so do nothing
311 return;
312 }
313 }
314 delete handle;
315 } else if (owner) {
316 owner->Release(dst);
317 }
318 }
319 }
320
Type() const321 uint64_t PostProcessConfigurationComponentManager::Type() const
322 {
323 return typeHash_;
324 }
325
326 // IComponentManager
GetName() const327 string_view PostProcessConfigurationComponentManager::GetName() const
328 {
329 constexpr auto name = CORE_NS::GetName<PostProcessConfigurationComponent>();
330 return name;
331 }
332
GetUid() const333 Uid PostProcessConfigurationComponentManager::GetUid() const
334 {
335 return IPostProcessConfigurationComponentManager::UID;
336 }
337
GetComponentCount() const338 size_t PostProcessConfigurationComponentManager::GetComponentCount() const
339 {
340 return components_.size();
341 }
342
GetPropertyApi() const343 const IPropertyApi& PostProcessConfigurationComponentManager::GetPropertyApi() const
344 {
345 return *this;
346 }
347
GetEntity(ComponentId index) const348 Entity PostProcessConfigurationComponentManager::GetEntity(ComponentId index) const
349 {
350 if (index < components_.size()) {
351 return components_[index].entity_;
352 }
353 return Entity();
354 }
355
GetComponentGeneration(ComponentId index) const356 uint32_t PostProcessConfigurationComponentManager::GetComponentGeneration(ComponentId index) const
357 {
358 if (index < components_.size()) {
359 return components_[index].generation_;
360 }
361 return 0;
362 }
363
HasComponent(Entity entity) const364 bool PostProcessConfigurationComponentManager::HasComponent(Entity entity) const
365 {
366 return GetComponentId(entity) != IComponentManager::INVALID_COMPONENT_ID;
367 }
368
GetComponentId(Entity entity) const369 IComponentManager::ComponentId PostProcessConfigurationComponentManager::GetComponentId(Entity entity) const
370 {
371 if (auto it = entityComponent_.find(entity); it != entityComponent_.end()) {
372 return it->second;
373 }
374 return IComponentManager::INVALID_COMPONENT_ID;
375 }
376
Create(Entity entity)377 void PostProcessConfigurationComponentManager::Create(Entity entity)
378 {
379 if (CORE_NS::EntityUtil::IsValid(entity)) {
380 if (auto it = entityComponent_.find(entity); it == entityComponent_.end()) {
381 entityComponent_.insert({ entity, static_cast<ComponentId>(components_.size()) });
382 auto& component = components_.emplace_back(this, entity);
383 added_.push_back(entity);
384 modifiedFlags_ |= CORE_NS::CORE_COMPONENT_MANAGER_COMPONENT_ADDED_BIT;
385 generationCounter_++;
386
387 // lock/unlock for toggling component updated behavior.
388 component.WLock();
389 component.WUnlock();
390 } else {
391 if (auto dst = ScopedHandle<PostProcessConfigurationComponent>(&components_[it->second]); dst) {
392 *dst = {};
393 }
394 }
395 }
396 }
397
Destroy(Entity entity)398 bool PostProcessConfigurationComponentManager::Destroy(Entity entity)
399 {
400 if (CORE_NS::EntityUtil::IsValid(entity)) {
401 if (auto it = entityComponent_.find(entity); it != entityComponent_.end()) {
402 components_[it->second].entity_ = {}; // invalid entity. (marks it as ready for re-use)
403 entityComponent_.erase(it);
404 removed_.push_back(entity);
405 modifiedFlags_ |= CORE_NS::CORE_COMPONENT_MANAGER_COMPONENT_REMOVED_BIT;
406 generationCounter_++;
407 return true;
408 }
409 }
410 return false;
411 }
412
Gc()413 void PostProcessConfigurationComponentManager::Gc()
414 {
415 const bool hasRemovedComponents = modifiedFlags_ & CORE_NS::CORE_COMPONENT_MANAGER_COMPONENT_REMOVED_BIT;
416 if (!hasRemovedComponents) {
417 return;
418 }
419 ComponentId componentCount = static_cast<ComponentId>(components_.size());
420 for (ComponentId id = 0; id < componentCount;) {
421 auto* it = &components_[id];
422 // invalid entity, if so clean garbage
423 if (!CORE_NS::EntityUtil::IsValid(it->entity_)) {
424 // find last valid and swap with it
425 for (ComponentId rid = componentCount - 1; rid > id; rid--) {
426 auto* rit = &components_[rid];
427 // valid entity? if so swap the components.
428 if (CORE_NS::EntityUtil::IsValid(rit->entity_)) {
429 // fix the entityComponent_ map (update the component id for the entity)
430 entityComponent_[rit->entity_] = id;
431 *it = move(*rit);
432 break;
433 }
434 }
435 componentCount--;
436 continue;
437 }
438 id++;
439 }
440 if (components_.size() > componentCount) {
441 auto diff = static_cast<typename decltype(components_)::difference_type>(componentCount);
442 components_.erase(components_.cbegin() + diff, components_.cend());
443 }
444 }
445
Destroy(const array_view<const Entity> gcList)446 void PostProcessConfigurationComponentManager::Destroy(const array_view<const Entity> gcList)
447 {
448 for (const Entity e : gcList) {
449 Destroy(e);
450 }
451 }
452
GetAddedComponents()453 vector<Entity> PostProcessConfigurationComponentManager::GetAddedComponents()
454 {
455 return BASE_NS::move(added_);
456 }
457
GetRemovedComponents()458 vector<Entity> PostProcessConfigurationComponentManager::GetRemovedComponents()
459 {
460 return BASE_NS::move(removed_);
461 }
462
GetUpdatedComponents()463 vector<Entity> PostProcessConfigurationComponentManager::GetUpdatedComponents()
464 {
465 vector<Entity> updated;
466 if (modifiedFlags_ & MODIFIED) {
467 modifiedFlags_ &= ~MODIFIED;
468 updated.reserve(components_.size() / 2); // 2: half
469 for (auto& handle : components_) {
470 if (handle.dirty_) {
471 handle.dirty_ = false;
472 updated.push_back(handle.entity_);
473 }
474 }
475 }
476 return updated;
477 }
478
GetModifiedFlags() const479 CORE_NS::ComponentManagerModifiedFlags PostProcessConfigurationComponentManager::GetModifiedFlags() const
480 {
481 return modifiedFlags_ & ~MODIFIED;
482 }
483
ClearModifiedFlags()484 void PostProcessConfigurationComponentManager::ClearModifiedFlags()
485 {
486 modifiedFlags_ &= MODIFIED;
487 }
488
GetGenerationCounter() const489 uint32_t PostProcessConfigurationComponentManager::GetGenerationCounter() const
490 {
491 return generationCounter_;
492 }
493
SetData(Entity entity,const IPropertyHandle & dataHandle)494 void PostProcessConfigurationComponentManager::SetData(Entity entity, const IPropertyHandle& dataHandle)
495 {
496 if (!IsMatchingHandle(dataHandle)) {
497 return;
498 }
499 if (const auto src = ScopedHandle<const PostProcessConfigurationComponent>(&dataHandle); src) {
500 if (const auto it = entityComponent_.find(entity); it != entityComponent_.end()) {
501 if (auto dst = ScopedHandle<PostProcessConfigurationComponent>(&components_[it->second]); dst) {
502 *dst = *src;
503 }
504 }
505 }
506 }
507
GetData(Entity entity) const508 const IPropertyHandle* PostProcessConfigurationComponentManager::GetData(Entity entity) const
509 {
510 if (CORE_NS::EntityUtil::IsValid(entity)) {
511 if (const auto it = entityComponent_.find(entity); it != entityComponent_.end()) {
512 if (it->second < components_.size()) {
513 return &components_[it->second];
514 }
515 }
516 }
517 return nullptr;
518 }
519
GetData(Entity entity)520 IPropertyHandle* PostProcessConfigurationComponentManager::GetData(Entity entity)
521 {
522 if (CORE_NS::EntityUtil::IsValid(entity)) {
523 if (const auto it = entityComponent_.find(entity); it != entityComponent_.end()) {
524 if (it->second < components_.size()) {
525 return &components_[it->second];
526 }
527 }
528 }
529 return nullptr;
530 }
531
SetData(ComponentId index,const IPropertyHandle & dataHandle)532 void PostProcessConfigurationComponentManager::SetData(ComponentId index, const IPropertyHandle& dataHandle)
533 {
534 if (!IsMatchingHandle(dataHandle)) {
535 // We could verify the metadata here.
536 // And in copy only the matching properties one-by-one also.
537 return;
538 }
539 if (index < components_.size()) {
540 if (const auto src = ScopedHandle<const PostProcessConfigurationComponent>(&dataHandle); src) {
541 if (auto dst = ScopedHandle<PostProcessConfigurationComponent>(&components_[index]); dst) {
542 *dst = *src;
543 }
544 }
545 }
546 }
547
GetData(ComponentId index) const548 const IPropertyHandle* PostProcessConfigurationComponentManager::GetData(ComponentId index) const
549 {
550 if (index < components_.size()) {
551 return &components_[index];
552 }
553 return nullptr;
554 }
555
GetData(ComponentId index)556 IPropertyHandle* PostProcessConfigurationComponentManager::GetData(ComponentId index)
557 {
558 if (index < components_.size()) {
559 return &components_[index];
560 }
561 return nullptr;
562 }
563
GetEcs() const564 IEcs& PostProcessConfigurationComponentManager::GetEcs() const
565 {
566 return ecs_;
567 }
568
569 // IPostProcessConfigurationComponentManager
Get(ComponentId index) const570 PostProcessConfigurationComponent PostProcessConfigurationComponentManager::Get(ComponentId index) const
571 {
572 if (auto handle = Read(index); handle) {
573 return *handle;
574 }
575 return PostProcessConfigurationComponent {};
576 }
577
Get(Entity entity) const578 PostProcessConfigurationComponent PostProcessConfigurationComponentManager::Get(Entity entity) const
579 {
580 if (auto handle = Read(entity); handle) {
581 return *handle;
582 }
583 return PostProcessConfigurationComponent {};
584 }
585
Set(ComponentId index,const PostProcessConfigurationComponent & data)586 void PostProcessConfigurationComponentManager::Set(ComponentId index, const PostProcessConfigurationComponent& data)
587 {
588 if (auto handle = Write(index); handle) {
589 *handle = data;
590 }
591 }
592
Set(Entity entity,const PostProcessConfigurationComponent & data)593 void PostProcessConfigurationComponentManager::Set(Entity entity, const PostProcessConfigurationComponent& data)
594 {
595 if (CORE_NS::EntityUtil::IsValid(entity)) {
596 if (auto handle = Write(entity); handle) {
597 *handle = data;
598 } else {
599 entityComponent_.insert({ entity, static_cast<ComponentId>(components_.size()) });
600 auto& component = components_.emplace_back(this, entity, data);
601 added_.push_back(entity);
602 modifiedFlags_ |= CORE_NS::CORE_COMPONENT_MANAGER_COMPONENT_ADDED_BIT;
603 generationCounter_++;
604
605 // lock/unlock for toggling component updated behavior.
606 component.WLock();
607 component.WUnlock();
608 }
609 }
610 }
611
Read(ComponentId index) const612 ScopedHandle<const PostProcessConfigurationComponent> PostProcessConfigurationComponentManager::Read(
613 ComponentId index) const
614 {
615 return ScopedHandle<const PostProcessConfigurationComponent> { GetData(index) };
616 }
617
Read(Entity entity) const618 ScopedHandle<const PostProcessConfigurationComponent> PostProcessConfigurationComponentManager::Read(
619 Entity entity) const
620 {
621 return ScopedHandle<const PostProcessConfigurationComponent> { GetData(entity) };
622 }
623
Write(ComponentId index)624 ScopedHandle<PostProcessConfigurationComponent> PostProcessConfigurationComponentManager::Write(ComponentId index)
625 {
626 return ScopedHandle<PostProcessConfigurationComponent> { GetData(index) };
627 }
628
Write(Entity entity)629 ScopedHandle<PostProcessConfigurationComponent> PostProcessConfigurationComponentManager::Write(Entity entity)
630 {
631 return ScopedHandle<PostProcessConfigurationComponent> { GetData(entity) };
632 }
633
634 // Internal
Updated(Entity entity)635 void PostProcessConfigurationComponentManager::Updated(Entity entity)
636 {
637 CORE_ASSERT_MSG(CORE_NS::EntityUtil::IsValid(entity), "Invalid ComponentId, bound to INVALID_ENTITY");
638 modifiedFlags_ |= CORE_NS::CORE_COMPONENT_MANAGER_COMPONENT_UPDATED_BIT | MODIFIED;
639 generationCounter_++;
640 }
641
IsMatchingHandle(const IPropertyHandle & dataHandle)642 bool PostProcessConfigurationComponentManager::IsMatchingHandle(const IPropertyHandle& dataHandle)
643 {
644 if (dataHandle.Owner() == this) {
645 return true;
646 }
647 if (dataHandle.Owner()->Type() == typeHash_) {
648 return true;
649 }
650 return false;
651 }
652
653 // Handle implementation
ComponentHandle(PostProcessConfigurationComponentManager * owner,Entity entity)654 PostProcessConfigurationComponentManager::ComponentHandle::ComponentHandle(
655 PostProcessConfigurationComponentManager* owner, Entity entity) noexcept
656 : ComponentHandle(owner, entity, {})
657 {}
658
ComponentHandle(PostProcessConfigurationComponentManager * owner,Entity entity,const PostProcessConfigurationComponent & data)659 PostProcessConfigurationComponentManager::ComponentHandle::ComponentHandle(
660 PostProcessConfigurationComponentManager* owner, Entity entity,
661 const PostProcessConfigurationComponent& data) noexcept
662 : manager_(owner), entity_(entity), data_(data)
663 {}
664
ComponentHandle(ComponentHandle && other)665 PostProcessConfigurationComponentManager::ComponentHandle::ComponentHandle(ComponentHandle&& other) noexcept
666 : manager_(other.manager_), entity_(exchange(other.entity_, {})), generation_(exchange(other.generation_, 0u)),
667 rLocked_(other.rLocked_.exchange(0)), wLocked_(exchange(other.wLocked_, false)), data_(exchange(other.data_, {})),
668 customProperties_(exchange(other.customProperties_, {}))
669 {}
670
671 typename PostProcessConfigurationComponentManager::ComponentHandle&
operator =(ComponentHandle && other)672 PostProcessConfigurationComponentManager::ComponentHandle::operator=(ComponentHandle&& other) noexcept
673 {
674 if (this != &other) {
675 CORE_ASSERT(manager_ == other.manager_);
676 entity_ = exchange(other.entity_, {});
677 generation_ = exchange(other.generation_, 0u);
678 dirty_ = exchange(other.dirty_, false);
679 rLocked_ = other.rLocked_.exchange(0);
680 wLocked_ = exchange(other.wLocked_, false);
681 data_ = exchange(other.data_, {});
682 effectShaders_ = exchange(other.effectShaders_, {});
683 customProperties_ = exchange(other.customProperties_, {});
684 }
685 return *this;
686 }
687
688 // ComponentHandle IPropertyHandle
Owner() const689 const IPropertyApi* PostProcessConfigurationComponentManager::ComponentHandle::Owner() const
690 {
691 return this;
692 }
693
Size() const694 size_t PostProcessConfigurationComponentManager::ComponentHandle::Size() const
695 {
696 return sizeof(PostProcessConfigurationComponent);
697 }
698
RLock() const699 const void* PostProcessConfigurationComponentManager::ComponentHandle::RLock() const
700 {
701 CORE_ASSERT(manager_);
702 CORE_ASSERT(!wLocked_);
703 rLocked_++;
704 return &data_;
705 }
706
RUnlock() const707 void PostProcessConfigurationComponentManager::ComponentHandle::RUnlock() const
708 {
709 CORE_ASSERT(manager_);
710 CORE_ASSERT(rLocked_ > 0);
711 rLocked_--;
712 }
713
WLock()714 void* PostProcessConfigurationComponentManager::ComponentHandle::WLock()
715 {
716 CORE_ASSERT(manager_);
717 CORE_ASSERT(rLocked_ <= 1 && !wLocked_);
718 wLocked_ = true;
719 return &data_;
720 }
721
WUnlock()722 void PostProcessConfigurationComponentManager::ComponentHandle::WUnlock()
723 {
724 CORE_ASSERT(manager_);
725 CORE_ASSERT(wLocked_);
726 wLocked_ = false;
727 // update generation etc..
728 generation_++;
729 if (CORE_NS::EntityUtil::IsValid(entity_)) {
730 dirty_ = true;
731 UpdateMetadata();
732 manager_->Updated(entity_);
733 }
734 }
735
736 // ComponentHandle IPropertyApi
PropertyCount() const737 size_t PostProcessConfigurationComponentManager::ComponentHandle::PropertyCount() const
738 {
739 return manager_->PropertyCount();
740 }
741
MetaData(size_t index) const742 const Property* PostProcessConfigurationComponentManager::ComponentHandle::MetaData(size_t index) const
743 {
744 return manager_->MetaData(index);
745 }
746
MetaData() const747 array_view<const Property> PostProcessConfigurationComponentManager::ComponentHandle::MetaData() const
748 {
749 return manager_->MetaData();
750 }
751
Type() const752 uint64_t PostProcessConfigurationComponentManager::ComponentHandle::Type() const
753 {
754 return manager_->Type();
755 }
756
Create() const757 IPropertyHandle* PostProcessConfigurationComponentManager::ComponentHandle::Create() const
758 {
759 return new ComponentHandle(manager_, {}, {});
760 }
761
Clone(const IPropertyHandle * src) const762 IPropertyHandle* PostProcessConfigurationComponentManager::ComponentHandle::Clone(const IPropertyHandle* src) const
763 {
764 if (src) {
765 auto owner = src->Owner();
766 if (owner == this) {
767 auto* h = static_cast<const ComponentHandle*>(src);
768 return new ComponentHandle(h->manager_, {}, h->data_);
769 } else if (owner) {
770 return owner->Clone(src);
771 }
772 return manager_->Clone(src);
773 }
774 return nullptr;
775 }
776
Release(IPropertyHandle * handle) const777 void PostProcessConfigurationComponentManager::ComponentHandle::Release(IPropertyHandle* handle) const
778 {
779 if (handle) {
780 auto owner = handle->Owner();
781 if (owner == this) {
782 auto* componentHandle = static_cast<ComponentHandle*>(handle);
783 if (auto id = manager_->GetComponentId(componentHandle->entity_);
784 id != IComponentManager::INVALID_COMPONENT_ID) {
785 if (manager_->GetData(id) == componentHandle) {
786 // This is one of the components (bound to an entity) so do nothing
787 return;
788 }
789 }
790 delete componentHandle;
791 } else if (owner) {
792 owner->Release(handle);
793 }
794 }
795 }
796
UpdateMetadata()797 void PostProcessConfigurationComponentManager::ComponentHandle::UpdateMetadata()
798 {
799 if (!manager_->renderHandleManager_) {
800 if (manager_->renderHandleManager_ = GetManager<IRenderHandleComponentManager>(manager_->ecs_);
801 !manager_->renderHandleManager_) {
802 return;
803 }
804 }
805 // resize for all single post processes
806 effectShaders_.resize(data_.postProcesses.size());
807 customProperties_.resize(data_.postProcesses.size());
808 // loop through all post process effects for new shaders
809 // NOTE: could cache shaders and/or check which single post processes are actually changed
810 for (size_t idx = 0; idx < data_.postProcesses.size(); ++idx) {
811 if (effectShaders_[idx] != data_.postProcesses[idx].shader) {
812 effectShaders_[idx] = data_.postProcesses[idx].shader;
813 const auto currentShader = manager_->renderHandleManager_->GetRenderHandleReference(effectShaders_[idx]);
814
815 auto newPod = make_unique<CustomPropertyPodContainer>(CUSTOM_PROPERTY_POD_CONTAINER_BYTE_SIZE);
816 if (currentShader) {
817 if (const json::value* metaJson = manager_->shaderManager_.GetMaterialMetadata(currentShader);
818 metaJson && metaJson->is_array()) {
819 UpdateCustomPropertyMetadata(*metaJson, *newPod);
820 }
821 }
822
823 auto& properties = customProperties_[idx];
824 if (properties) {
825 newPod->CopyValues(*properties);
826 }
827 properties = BASE_NS::move(newPod);
828 }
829
830 // re-fetch the property always
831 data_.postProcesses[idx].customProperties = customProperties_[idx].get();
832 }
833 }
834
835 //
836
IPostProcessConfigurationComponentManagerInstance(IEcs & ecs)837 IComponentManager* IPostProcessConfigurationComponentManagerInstance(IEcs& ecs)
838 {
839 return new PostProcessConfigurationComponentManager(ecs);
840 }
841
IPostProcessConfigurationComponentManagerDestroy(IComponentManager * instance)842 void IPostProcessConfigurationComponentManagerDestroy(IComponentManager* instance)
843 {
844 delete static_cast<PostProcessConfigurationComponentManager*>(instance);
845 }
846
847 CORE3D_END_NAMESPACE()
848