1 /*
2 * Copyright (c) 2022 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