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