• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "util/property_util.h"
17 
18 #include <cinttypes>
19 
20 #include <base/math/vector.h>
21 #include <core/log.h>
22 #include <core/property/intf_property_handle.h>
23 #include <core/property/property_types.h>
24 #include <core/property_tools/core_metadata.inl>
25 #include <render/property/property_types.h>
26 
27 #include "util/json_util.h"
28 #include "util/log.h"
29 
30 RENDER_BEGIN_NAMESPACE()
31 using namespace BASE_NS;
32 using namespace CORE_NS;
33 
34 namespace {
35 constexpr size_t BUFFER_HANDLE_REF_BYTE_SIZE = sizeof(BindableBufferWithHandleReference);
36 constexpr size_t IMAGE_HANDLE_REF_BYTE_SIZE = sizeof(BindableImageWithHandleReference);
37 constexpr size_t SAMPLER_HANDLE_REF_BYTE_SIZE = sizeof(BindableSamplerWithHandleReference);
38 constexpr size_t MAX_STRUCT_HANDLE_REF_BYTE_SIZE =
39     Math::max(BUFFER_HANDLE_REF_BYTE_SIZE, Math::max(IMAGE_HANDLE_REF_BYTE_SIZE, SAMPLER_HANDLE_REF_BYTE_SIZE));
40 
GetPropertyTypeByteSize(const PropertyTypeDecl & typeDecl)41 uint32_t GetPropertyTypeByteSize(const PropertyTypeDecl& typeDecl)
42 {
43     uint32_t byteSize = 0; // zero means that un-supported property type
44     switch (typeDecl) {
45         case PropertyType::UINT32_T:
46         case PropertyType::INT32_T:
47         case PropertyType::FLOAT_T:
48         case PropertyType::BOOL_T:
49             byteSize = sizeof(uint32_t);
50             break;
51         case PropertyType::UVEC2_T:
52         case PropertyType::IVEC2_T:
53         case PropertyType::VEC2_T:
54             byteSize = sizeof(Math::UVec2);
55             break;
56         case PropertyType::UVEC3_T:
57         case PropertyType::IVEC3_T:
58         case PropertyType::VEC3_T:
59             byteSize = sizeof(Math::UVec3);
60             break;
61         case PropertyType::UVEC4_T:
62         case PropertyType::IVEC4_T:
63         case PropertyType::VEC4_T:
64             byteSize = sizeof(Math::UVec4);
65             break;
66         case PropertyType::MAT3X3_T:
67             byteSize = sizeof(Math::Mat3X3);
68             break;
69         case PropertyType::MAT4X4_T:
70             byteSize = sizeof(Math::Mat4X4);
71             break;
72     }
73     return byteSize;
74 }
75 
GetMetaData(const PropertyTypeDecl & typeDecl)76 constexpr MetaData GetMetaData(const PropertyTypeDecl& typeDecl)
77 {
78     switch (typeDecl) {
79         case PropertyType::UINT32_T:
80             return PropertyType::MetaDataFrom<uint32_t>();
81         case PropertyType::INT32_T:
82             return PropertyType::MetaDataFrom<int32_t>();
83         case PropertyType::FLOAT_T:
84             return PropertyType::MetaDataFrom<float>();
85 
86         case PropertyType::BOOL_T:
87             return PropertyType::MetaDataFrom<bool>();
88 
89         case PropertyType::UVEC2_T:
90             return PropertyType::MetaDataFrom<Math::UVec2>();
91         case PropertyType::IVEC2_T:
92             return PropertyType::MetaDataFrom<Math::IVec2>();
93         case PropertyType::VEC2_T:
94             return PropertyType::MetaDataFrom<Math::Vec2>();
95 
96         case PropertyType::UVEC3_T:
97             return PropertyType::MetaDataFrom<Math::UVec3>();
98         case PropertyType::IVEC3_T:
99             return PropertyType::MetaDataFrom<Math::IVec3>();
100         case PropertyType::VEC3_T:
101             return PropertyType::MetaDataFrom<Math::Vec3>();
102 
103         case PropertyType::UVEC4_T:
104             return PropertyType::MetaDataFrom<Math::UVec4>();
105         case PropertyType::IVEC4_T:
106             return PropertyType::MetaDataFrom<Math::IVec4>();
107         case PropertyType::VEC4_T:
108             return PropertyType::MetaDataFrom<Math::Vec4>();
109 
110         case PropertyType::MAT3X3_T:
111             return PropertyType::MetaDataFrom<Math::Mat3X3>();
112         case PropertyType::MAT4X4_T:
113             return PropertyType::MetaDataFrom<Math::Mat4X4>();
114     }
115     return {};
116 }
117 } // namespace
118 
CustomPropertyPodContainer(size_t reserveByteSize)119 CustomPropertyPodContainer::CustomPropertyPodContainer(size_t reserveByteSize)
120 {
121     data_.reserve(reserveByteSize);
122 }
123 
PropertyCount() const124 size_t CustomPropertyPodContainer::PropertyCount() const
125 {
126     return metaData_.size();
127 }
128 
MetaData(size_t index) const129 const Property* CustomPropertyPodContainer::MetaData(size_t index) const
130 {
131     if (index < metaData_.size()) {
132         return &metaData_[index];
133     }
134 
135     return nullptr;
136 }
137 
MetaData() const138 array_view<const Property> CustomPropertyPodContainer::MetaData() const
139 {
140     return { metaData_ };
141 }
142 
Type() const143 uint64_t CustomPropertyPodContainer::Type() const
144 {
145     return 0;
146 }
147 
Create() const148 IPropertyHandle* CustomPropertyPodContainer::Create() const
149 {
150     return nullptr;
151 }
152 
Clone(const IPropertyHandle * src) const153 IPropertyHandle* CustomPropertyPodContainer::Clone(const IPropertyHandle* src) const
154 {
155     return nullptr;
156 }
157 
Release(IPropertyHandle * handle) const158 void CustomPropertyPodContainer::Release(IPropertyHandle* handle) const {}
159 
Reset()160 void CustomPropertyPodContainer::Reset()
161 {
162     metaStrings_.clear();
163     metaData_.clear();
164     data_.clear();
165 }
166 
ReservePropertyCount(size_t propertyCount)167 void CustomPropertyPodContainer::ReservePropertyCount(size_t propertyCount)
168 {
169     reservePropertyCount_ = propertyCount;
170     metaStrings_.reserve(reservePropertyCount_);
171     metaData_.reserve(reservePropertyCount_);
172 }
173 
174 // CustomProperties IPropertyHandle
Owner() const175 const IPropertyApi* CustomPropertyPodContainer::Owner() const
176 {
177     return this;
178 }
179 
Size() const180 size_t CustomPropertyPodContainer::Size() const
181 {
182     return data_.size();
183 }
184 
RLock() const185 const void* CustomPropertyPodContainer::RLock() const
186 {
187     return data_.data();
188 }
189 
RUnlock() const190 void CustomPropertyPodContainer::RUnlock() const {}
191 
WLock()192 void* CustomPropertyPodContainer::WLock()
193 {
194     return data_.data();
195 }
196 
WUnlock()197 void CustomPropertyPodContainer::WUnlock() {}
198 
199 //
200 
AddOffsetProperty(const string_view propertyName,const string_view displayName,const uintptr_t offset,const PropertyTypeDecl & typeDecl)201 void CustomPropertyPodContainer::AddOffsetProperty(const string_view propertyName, const string_view displayName,
202     const uintptr_t offset, const PropertyTypeDecl& typeDecl)
203 {
204     const size_t byteSize = GetPropertyTypeByteSize(typeDecl);
205     const bool reserved = (metaStrings_.size() < reservePropertyCount_);
206     if ((byteSize > 0) && reserved) {
207         metaStrings_.push_back({ string { propertyName }, string { displayName } });
208         const auto& strings = metaStrings_.back();
209         const Property meta {
210             strings.name,                                        // name
211             FNV1aHash(strings.name.data(), strings.name.size()), // hash
212             typeDecl,                                            // type
213             1U,                                                  // count
214             byteSize,                                            // size
215             offset,                                              // offset
216             strings.displayName,                                 // displayName
217             0U,                                                  // flags
218             GetMetaData(typeDecl),                               // metaData
219         };
220         metaData_.push_back(meta);
221         data_.resize(Math::max(data_.size(), meta.offset + meta.size));
222     } else {
223         CORE_LOG_W("unsupported property addition for custom property POD container");
224     }
225 }
226 
AddOffsetProperty(const string_view propertyName,const string_view displayName,const uintptr_t offset,const PropertyTypeDecl & typeDecl,const array_view<const uint8_t> data)227 void CustomPropertyPodContainer::AddOffsetProperty(const string_view propertyName, const string_view displayName,
228     const uintptr_t offset, const PropertyTypeDecl& typeDecl, const array_view<const uint8_t> data)
229 {
230     const size_t byteSize = GetPropertyTypeByteSize(typeDecl);
231     const bool reserved = (metaStrings_.size() < reservePropertyCount_);
232     if ((byteSize > 0) && reserved) {
233         metaStrings_.push_back({ string { propertyName }, string { displayName } });
234         const auto& strings = metaStrings_.back();
235         const Property meta {
236             strings.name,                                        // name
237             FNV1aHash(strings.name.data(), strings.name.size()), // hash
238             typeDecl,                                            // type
239             1U,                                                  // count
240             byteSize,                                            // size
241             offset,                                              // offset
242             strings.displayName,                                 // displayName
243             0U,                                                  // flags
244             GetMetaData(typeDecl),                               // metaData
245         };
246         metaData_.push_back(meta);
247         data_.resize(data_.size() + meta.size);
248         if (data.size_bytes() == byteSize) {
249             CloneData(data_.data() + offset, data_.size_in_bytes(), data.data(), data.size_bytes());
250         }
251     } else {
252         CORE_LOG_W("unsupported property addition for custom property POD container");
253     }
254 }
255 
SetValue(const string_view propertyName,const array_view<uint8_t> data)256 bool CustomPropertyPodContainer::SetValue(const string_view propertyName, const array_view<uint8_t> data)
257 {
258     for (const auto& metaRef : metaData_) {
259         if ((metaRef.displayName == propertyName) && (metaRef.size == data.size_bytes())) {
260             const size_t endData = metaRef.offset + metaRef.size;
261             if (endData <= data_.size_in_bytes()) {
262                 CloneData(data_.data() + metaRef.offset, data_.size_in_bytes(), data.data(), data.size_bytes());
263                 return true;
264             }
265         }
266     }
267     return false;
268 }
269 
SetValue(const size_t byteOffset,const array_view<uint8_t> data)270 bool CustomPropertyPodContainer::SetValue(const size_t byteOffset, const array_view<uint8_t> data)
271 {
272     const size_t endData = byteOffset + data.size_bytes();
273     if (endData <= data_.size_in_bytes()) {
274         CloneData(data_.data() + byteOffset, data_.size_in_bytes(), data.data(), data.size_bytes());
275         return true;
276     }
277     return false;
278 }
279 
GetValue(const string_view propertyName) const280 array_view<const uint8_t> CustomPropertyPodContainer::GetValue(const string_view propertyName) const
281 {
282     for (const auto& metaRef : metaData_) {
283         if (metaRef.displayName == propertyName) {
284             const size_t endData = metaRef.offset + metaRef.size;
285             if (endData <= data_.size_in_bytes()) {
286                 return { data_.data() + metaRef.offset, metaRef.size };
287             }
288         }
289     }
290     return {};
291 }
292 
GetByteSize() const293 size_t CustomPropertyPodContainer::GetByteSize() const
294 {
295     return data_.size_in_bytes();
296 }
297 
GetData() const298 BASE_NS::array_view<const uint8_t> CustomPropertyPodContainer::GetData() const
299 {
300     return data_;
301 }
302 
303 //
304 
GetPropertyTypeDeclaration(const string_view type)305 PropertyTypeDecl CustomPropertyPodHelper::GetPropertyTypeDeclaration(const string_view type)
306 {
307     if (type == "vec4") {
308         return PropertyType::VEC4_T;
309     } else if (type == "uvec4") {
310         return PropertyType::UVEC4_T;
311     } else if (type == "ivec4") {
312         return PropertyType::IVEC4_T;
313     } else if (type == "vec3") {
314         return PropertyType::VEC3_T;
315     } else if (type == "uvec3") {
316         return PropertyType::UVEC3_T;
317     } else if (type == "ivec3") {
318         return PropertyType::IVEC3_T;
319     } else if (type == "vec2") {
320         return PropertyType::VEC2_T;
321     } else if (type == "uvec2") {
322         return PropertyType::UVEC2_T;
323     } else if (type == "ivec2") {
324         return PropertyType::IVEC2_T;
325     } else if (type == "float") {
326         return PropertyType::FLOAT_T;
327     } else if (type == "uint") {
328         return PropertyType::UINT32_T;
329     } else if (type == "int") {
330         return PropertyType::INT32_T;
331     } else if (type == "bool") {
332         return PropertyType::BOOL_T;
333     } else if (type == "mat3x3") {
334         return PropertyType::MAT3X3_T;
335     } else if (type == "mat4x4") {
336         return PropertyType::MAT4X4_T;
337     } else {
338         CORE_LOG_W("RENDER_VALIDATION: Invalid property type only int, uint, float, bool, and XvecX variants, and "
339                    "mat3x3 and mat4x4 are supported");
340     }
341     // NOTE: does not handle invalid types
342     return PropertyType::INVALID;
343 }
344 
GetPropertyTypeAlignment(const PropertyTypeDecl & propertyType)345 size_t CustomPropertyPodHelper::GetPropertyTypeAlignment(const PropertyTypeDecl& propertyType)
346 {
347     size_t align = 1U;
348     static_assert(sizeof(float) == sizeof(uint32_t) && sizeof(float) == sizeof(int32_t));
349     switch (propertyType) {
350         case PropertyType::FLOAT_T:
351             [[fallthrough]];
352         case PropertyType::UINT32_T:
353             [[fallthrough]];
354         case PropertyType::INT32_T:
355             [[fallthrough]];
356         case PropertyType::BOOL_T:
357             align = sizeof(float);
358             break;
359         case PropertyType::VEC2_T:
360             [[fallthrough]];
361         case PropertyType::UVEC2_T:
362             [[fallthrough]];
363         case PropertyType::IVEC2_T:
364             align = sizeof(float) * 2U;
365             break;
366         case PropertyType::VEC3_T:
367             [[fallthrough]];
368         case PropertyType::UVEC3_T:
369             [[fallthrough]];
370         case PropertyType::IVEC3_T:
371             [[fallthrough]];
372         case PropertyType::VEC4_T:
373             [[fallthrough]];
374         case PropertyType::UVEC4_T:
375             [[fallthrough]];
376         case PropertyType::IVEC4_T:
377             [[fallthrough]];
378         case PropertyType::MAT3X3_T:
379             [[fallthrough]];
380         case PropertyType::MAT4X4_T:
381             align = sizeof(float) * 4U;
382             break;
383     }
384     return align;
385 }
386 
387 template<typename T>
SafeFromJsonValue(const json::value * value,T & val)388 inline void SafeFromJsonValue(const json::value* value, T& val)
389 {
390     if (value) {
391         FromJson(*value, val);
392     }
393 }
394 
SetCustomPropertyBlobValue(const PropertyTypeDecl & propertyType,const json::value * value,CustomPropertyPodContainer & customProperties,const size_t offset)395 void CustomPropertyPodHelper::SetCustomPropertyBlobValue(const PropertyTypeDecl& propertyType, const json::value* value,
396     CustomPropertyPodContainer& customProperties, const size_t offset)
397 {
398     if (propertyType == PropertyType::VEC4_T) {
399         Math::Vec4 val;
400         SafeFromJsonValue(value, val);
401         customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec4) });
402     } else if (propertyType == PropertyType::UVEC4_T) {
403         Math::UVec4 val;
404         SafeFromJsonValue(value, val);
405         customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec4) });
406     } else if (propertyType == PropertyType::IVEC4_T) {
407         Math::IVec4 val;
408         SafeFromJsonValue(value, val);
409         customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec4) });
410     } else if (propertyType == PropertyType::VEC3_T) {
411         Math::Vec3 val;
412         SafeFromJsonValue(value, val);
413         customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec3) });
414     } else if (propertyType == PropertyType::UVEC3_T) {
415         Math::UVec3 val;
416         SafeFromJsonValue(value, val);
417         customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec3) });
418     } else if (propertyType == PropertyType::IVEC3_T) {
419         Math::IVec3 val;
420         SafeFromJsonValue(value, val);
421         customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec3) });
422     } else if (propertyType == PropertyType::VEC2_T) {
423         Math::Vec2 val;
424         SafeFromJsonValue(value, val);
425         customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec2) });
426     } else if (propertyType == PropertyType::UVEC2_T) {
427         Math::UVec2 val;
428         SafeFromJsonValue(value, val);
429         customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec2) });
430     } else if (propertyType == PropertyType::IVEC2_T) {
431         Math::IVec2 val;
432         SafeFromJsonValue(value, val);
433         customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec2) });
434     } else if (propertyType == PropertyType::FLOAT_T) {
435         float val;
436         SafeFromJsonValue(value, val);
437         customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(float) });
438     } else if (propertyType == PropertyType::UINT32_T) {
439         uint32_t val;
440         SafeFromJsonValue(value, val);
441         customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(float) });
442     } else if (propertyType == PropertyType::INT32_T) {
443         int32_t val;
444         SafeFromJsonValue(value, val);
445         customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(float) });
446     } else if (propertyType == PropertyType::BOOL_T) {
447         bool tmpVal;
448         SafeFromJsonValue(value, tmpVal);
449         uint32_t val = tmpVal;
450         customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(float) });
451     } else if (propertyType == PropertyType::MAT3X3_T) {
452         Math::Mat3X3 val;
453         SafeFromJsonValue(value, val);
454         customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Mat3X3) });
455     } else if (propertyType == PropertyType::MAT4X4_T) {
456         Math::Mat4X4 val;
457         SafeFromJsonValue(value, val);
458         customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Mat4X4) });
459     } else {
460         CORE_LOG_W("RENDER_VALIDATION: Invalid property type only int, uint, float, and XvecX variants supported");
461     }
462     // NOTE: does not handle invalid types
463 }
464 
465 // bindings
466 
467 template<typename T>
DestroyHelper(T & t)468 inline void DestroyHelper(T& t)
469 {
470     {
471         t.~T();
472     }
473 }
474 
CustomPropertyBindingContainer(CustomPropertyWriteSignal & writeSignal)475 CustomPropertyBindingContainer::CustomPropertyBindingContainer(CustomPropertyWriteSignal& writeSignal)
476     : writeSignal_(writeSignal)
477 {}
478 
~CustomPropertyBindingContainer()479 CustomPropertyBindingContainer::~CustomPropertyBindingContainer()
480 {
481     if (!data_.empty()) {
482         PLUGIN_ASSERT(metaData_.size() <= data_.size());
483         for (const auto& meta : metaData_) {
484             CORE_ASSERT(meta.offset < data_.size_in_bytes());
485             switch (meta.type) {
486                 case PropertyType::BINDABLE_BUFFER_WITH_HANDLE_REFERENCE_T: {
487                     PLUGIN_ASSERT(meta.size == BUFFER_HANDLE_REF_BYTE_SIZE);
488                     if (auto* resource = (BindableBufferWithHandleReference*)(data_.data() + meta.offset); resource) {
489                         DestroyHelper(*resource);
490                     }
491                     break;
492                 }
493                 case PropertyType::BINDABLE_IMAGE_WITH_HANDLE_REFERENCE_T: {
494                     PLUGIN_ASSERT(meta.size == IMAGE_HANDLE_REF_BYTE_SIZE);
495                     if (auto* resource = (BindableImageWithHandleReference*)(data_.data() + meta.offset); resource) {
496                         DestroyHelper(*resource);
497                     }
498                     break;
499                 }
500                 case PropertyType::BINDABLE_SAMPLER_WITH_HANDLE_REFERENCE_T: {
501                     PLUGIN_ASSERT(meta.size == SAMPLER_HANDLE_REF_BYTE_SIZE);
502                     if (auto* resource = (BindableSamplerWithHandleReference*)(data_.data() + meta.offset); resource) {
503                         DestroyHelper(*resource);
504                     }
505                     break;
506                 }
507                 default: {
508                     CORE_LOG_E("custom property binding destruction error");
509                     break;
510                 }
511             }
512         }
513     }
514 }
515 
PropertyCount() const516 size_t CustomPropertyBindingContainer::PropertyCount() const
517 {
518     return metaData_.size();
519 }
520 
MetaData(size_t index) const521 const Property* CustomPropertyBindingContainer::MetaData(size_t index) const
522 {
523     if (index < metaData_.size()) {
524         return &metaData_[index];
525     }
526 
527     return nullptr;
528 }
529 
MetaData() const530 array_view<const Property> CustomPropertyBindingContainer::MetaData() const
531 {
532     return { metaData_ };
533 }
534 
Type() const535 uint64_t CustomPropertyBindingContainer::Type() const
536 {
537     return 0;
538 }
539 
Create() const540 IPropertyHandle* CustomPropertyBindingContainer::Create() const
541 {
542     return nullptr;
543 }
544 
Clone(const IPropertyHandle * src) const545 IPropertyHandle* CustomPropertyBindingContainer::Clone(const IPropertyHandle* src) const
546 {
547     return nullptr;
548 }
549 
Release(IPropertyHandle * handle) const550 void CustomPropertyBindingContainer::Release(IPropertyHandle* handle) const {}
551 
ReservePropertyCount(size_t propertyCount)552 void CustomPropertyBindingContainer::ReservePropertyCount(size_t propertyCount)
553 {
554     reservePropertyCount_ = propertyCount;
555     metaStrings_.reserve(reservePropertyCount_);
556     metaData_.reserve(reservePropertyCount_);
557     // max size
558     data_.reserve(reservePropertyCount_ * MAX_STRUCT_HANDLE_REF_BYTE_SIZE);
559 }
560 
561 // CustomProperties IPropertyHandle
Owner() const562 const IPropertyApi* CustomPropertyBindingContainer::Owner() const
563 {
564     return this;
565 }
566 
Size() const567 size_t CustomPropertyBindingContainer::Size() const
568 {
569     return data_.size();
570 }
571 
RLock() const572 const void* CustomPropertyBindingContainer::RLock() const
573 {
574     return data_.data();
575 }
576 
RUnlock() const577 void CustomPropertyBindingContainer::RUnlock() const {}
578 
WLock()579 void* CustomPropertyBindingContainer::WLock()
580 {
581     return data_.data();
582 }
583 
WUnlock()584 void CustomPropertyBindingContainer::WUnlock()
585 {
586     // signal that properties have been written
587     writeSignal_.Signal();
588 }
589 
590 //
591 
AddOffsetProperty(const string_view propertyName,const string_view displayName,const uintptr_t offset,const PropertyTypeDecl & typeDecl)592 void CustomPropertyBindingContainer::AddOffsetProperty(const string_view propertyName, const string_view displayName,
593     const uintptr_t offset, const PropertyTypeDecl& typeDecl)
594 {
595     const bool reserved = (metaStrings_.size() < reservePropertyCount_);
596     size_t byteSize = 0;
597     switch (typeDecl) {
598         case PropertyType::BINDABLE_BUFFER_WITH_HANDLE_REFERENCE_T: {
599             byteSize = BUFFER_HANDLE_REF_BYTE_SIZE;
600             break;
601         }
602         case PropertyType::BINDABLE_IMAGE_WITH_HANDLE_REFERENCE_T: {
603             byteSize = IMAGE_HANDLE_REF_BYTE_SIZE;
604             break;
605         }
606         case PropertyType::BINDABLE_SAMPLER_WITH_HANDLE_REFERENCE_T: {
607             byteSize = SAMPLER_HANDLE_REF_BYTE_SIZE;
608             break;
609         }
610     }
611     if ((byteSize > 0) && reserved) {
612         metaStrings_.push_back({ string { propertyName }, string { displayName } });
613         const auto& strings = metaStrings_.back();
614         const Property meta {
615             strings.name,                                        // name
616             FNV1aHash(strings.name.data(), strings.name.size()), // hash
617             typeDecl,                                            // type
618             1U,                                                  // count
619             byteSize,                                            // size
620             offset,                                              // offset
621             strings.displayName,                                 // displayName
622             0U,                                                  // flags
623             GetMetaData(typeDecl),                               // metaData
624         };
625         metaData_.push_back(meta);
626         // the data has already been reserved in ReservePropertyCount()
627         data_.resize(Math::max(data_.size(), meta.offset + meta.size));
628         switch (meta.type) {
629             case PropertyType::BINDABLE_BUFFER_WITH_HANDLE_REFERENCE_T: {
630                 new (data_.data() + meta.offset) BindableBufferWithHandleReference;
631                 break;
632             }
633             case PropertyType::BINDABLE_IMAGE_WITH_HANDLE_REFERENCE_T: {
634                 new (data_.data() + meta.offset) BindableImageWithHandleReference;
635                 break;
636             }
637             case PropertyType::BINDABLE_SAMPLER_WITH_HANDLE_REFERENCE_T: {
638                 new (data_.data() + meta.offset) BindableSamplerWithHandleReference;
639                 break;
640             }
641         }
642     } else {
643         CORE_LOG_W("unsupported property addition for custom property binding container");
644     }
645 }
646 
GetByteSize() const647 size_t CustomPropertyBindingContainer::GetByteSize() const
648 {
649     return data_.size_in_bytes();
650 }
651 
652 // CustomPropertyBindingHelper
653 
GetPropertyTypeDeclaration(const string_view type)654 PropertyTypeDecl CustomPropertyBindingHelper::GetPropertyTypeDeclaration(const string_view type)
655 {
656     if (type == "buffer") {
657         return PropertyType::BINDABLE_BUFFER_WITH_HANDLE_REFERENCE_T;
658     } else if (type == "image") {
659         return PropertyType::BINDABLE_IMAGE_WITH_HANDLE_REFERENCE_T;
660     } else if (type == "sampler") {
661         return PropertyType::BINDABLE_SAMPLER_WITH_HANDLE_REFERENCE_T;
662     } else {
663         CORE_LOG_W("RENDER_VALIDATION: Invalid property type only buffer, image, and sampler supported (not %s)",
664             string(type).c_str());
665     }
666     // NOTE: does not handle invalid types
667     return PropertyType::INVALID;
668 }
669 
GetPropertyTypeAlignment(const PropertyTypeDecl & propertyType)670 size_t CustomPropertyBindingHelper::GetPropertyTypeAlignment(const PropertyTypeDecl& propertyType)
671 {
672     size_t align = 1U;
673     switch (propertyType) {
674         case PropertyType::BINDABLE_BUFFER_WITH_HANDLE_REFERENCE_T:
675             align = sizeof(BindableBufferWithHandleReference);
676             break;
677         case PropertyType::BINDABLE_IMAGE_WITH_HANDLE_REFERENCE_T:
678             align = sizeof(BindableImageWithHandleReference);
679             break;
680         case PropertyType::BINDABLE_SAMPLER_WITH_HANDLE_REFERENCE_T:
681             align = sizeof(BindableSamplerWithHandleReference);
682             break;
683     }
684     return align;
685 }
686 RENDER_END_NAMESPACE()
687