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 "util/property_util.h"
17
18 #include <PropertyTools/core_metadata.inl>
19 #include <cinttypes>
20
21 #include <base/math/vector.h>
22 #include <core/log.h>
23 #include <core/property/intf_property_handle.h>
24 #include <core/property/property_types.h>
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>(nullptr);
81 case PropertyType::INT32_T:
82 return PropertyType::MetaDataFrom<int32_t>(nullptr);
83 case PropertyType::FLOAT_T:
84 return PropertyType::MetaDataFrom<float>(nullptr);
85
86 case PropertyType::BOOL_T:
87 return PropertyType::MetaDataFrom<bool>(nullptr);
88
89 case PropertyType::UVEC2_T:
90 return PropertyType::MetaDataFrom<Math::UVec2>(nullptr);
91 case PropertyType::IVEC2_T:
92 return PropertyType::MetaDataFrom<Math::IVec2>(nullptr);
93 case PropertyType::VEC2_T:
94 return PropertyType::MetaDataFrom<Math::Vec2>(nullptr);
95
96 case PropertyType::UVEC3_T:
97 return PropertyType::MetaDataFrom<Math::UVec3>(nullptr);
98 case PropertyType::IVEC3_T:
99 return PropertyType::MetaDataFrom<Math::IVec3>(nullptr);
100 case PropertyType::VEC3_T:
101 return PropertyType::MetaDataFrom<Math::Vec3>(nullptr);
102
103 case PropertyType::UVEC4_T:
104 return PropertyType::MetaDataFrom<Math::UVec4>(nullptr);
105 case PropertyType::IVEC4_T:
106 return PropertyType::MetaDataFrom<Math::IVec4>(nullptr);
107 case PropertyType::VEC4_T:
108 return PropertyType::MetaDataFrom<Math::Vec4>(nullptr);
109
110 case PropertyType::MAT3X3_T:
111 return PropertyType::MetaDataFrom<Math::Mat3X3>(nullptr);
112 case PropertyType::MAT4X4_T:
113 return PropertyType::MetaDataFrom<Math::Mat4X4>(nullptr);
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 align = sizeof(float) * 4U;
378 break;
379 case PropertyType::MAT3X3_T:
380 align = sizeof(float) * 4U * 3U;
381 break;
382 case PropertyType::MAT4X4_T:
383 align = sizeof(float) * 4U * 4U;
384 break;
385 }
386 return align;
387 }
388
SetCustomPropertyBlobValue(const PropertyTypeDecl & propertyType,const json::value * value,CustomPropertyPodContainer & customProperties,const size_t offset)389 void CustomPropertyPodHelper::SetCustomPropertyBlobValue(const PropertyTypeDecl& propertyType, const json::value* value,
390 CustomPropertyPodContainer& customProperties, const size_t offset)
391 {
392 if (propertyType == PropertyType::VEC4_T) {
393 Math::Vec4 val;
394 FromJson(*value, val);
395 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec4) });
396 } else if (propertyType == PropertyType::UVEC4_T) {
397 Math::UVec4 val;
398 FromJson(*value, val);
399 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec4) });
400 } else if (propertyType == PropertyType::IVEC4_T) {
401 Math::IVec4 val;
402 FromJson(*value, val);
403 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec4) });
404 } else if (propertyType == PropertyType::VEC3_T) {
405 Math::Vec3 val;
406 FromJson(*value, val);
407 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec3) });
408 } else if (propertyType == PropertyType::UVEC3_T) {
409 Math::UVec3 val;
410 FromJson(*value, val);
411 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec3) });
412 } else if (propertyType == PropertyType::IVEC3_T) {
413 Math::IVec3 val;
414 FromJson(*value, val);
415 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec3) });
416 } else if (propertyType == PropertyType::VEC2_T) {
417 Math::Vec2 val;
418 FromJson(*value, val);
419 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec2) });
420 } else if (propertyType == PropertyType::UVEC2_T) {
421 Math::UVec2 val;
422 FromJson(*value, val);
423 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec2) });
424 } else if (propertyType == PropertyType::IVEC2_T) {
425 Math::IVec2 val;
426 FromJson(*value, val);
427 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Vec2) });
428 } else if (propertyType == PropertyType::FLOAT_T) {
429 float val;
430 FromJson(*value, val);
431 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(float) });
432 } else if (propertyType == PropertyType::UINT32_T) {
433 uint32_t val;
434 FromJson(*value, val);
435 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(float) });
436 } else if (propertyType == PropertyType::INT32_T) {
437 int32_t val;
438 FromJson(*value, val);
439 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(float) });
440 } else if (propertyType == PropertyType::BOOL_T) {
441 bool tmpVal;
442 FromJson(*value, tmpVal);
443 uint32_t val = tmpVal;
444 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(float) });
445 } else if (propertyType == PropertyType::MAT3X3_T) {
446 Math::Mat3X3 val;
447 FromJson(*value, val);
448 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Mat3X3) });
449 } else if (propertyType == PropertyType::MAT4X4_T) {
450 Math::Mat4X4 val;
451 FromJson(*value, val);
452 customProperties.SetValue(offset, array_view { reinterpret_cast<uint8_t*>(&val), sizeof(Math::Mat4X4) });
453 } else {
454 CORE_LOG_W("RENDER_VALIDATION: Invalid property type only int, uint, float, and XvecX variants supported");
455 }
456 // NOTE: does not handle invalid types
457 }
458
459 // bindings
460
461 template<typename T>
DestroyHelper(T & t)462 inline void DestroyHelper(T& t)
463 {
464 {
465 t.~T();
466 }
467 }
468
CustomPropertyBindingContainer(CustomPropertyWriteSignal & writeSignal)469 CustomPropertyBindingContainer::CustomPropertyBindingContainer(CustomPropertyWriteSignal& writeSignal)
470 : writeSignal_(writeSignal)
471 {}
472
~CustomPropertyBindingContainer()473 CustomPropertyBindingContainer::~CustomPropertyBindingContainer()
474 {
475 if (!data_.empty()) {
476 const uint32_t tmp = MAX_STRUCT_HANDLE_REF_BYTE_SIZE;
477 PLUGIN_ASSERT(metaData_.size() <= data_.size());
478 for (size_t idx = 0; idx < metaData_.size(); ++idx) {
479 const auto& meta = metaData_[idx];
480 CORE_ASSERT(meta.offset < data_.size_in_bytes());
481 switch (meta.type) {
482 case PropertyType::BINDABLE_BUFFER_WITH_HANDLE_REFERENCE_T: {
483 PLUGIN_ASSERT(meta.size == BUFFER_HANDLE_REF_BYTE_SIZE);
484 if (BindableBufferWithHandleReference* resource =
485 (BindableBufferWithHandleReference*)(data_.data() + meta.offset);
486 resource) {
487 DestroyHelper(*resource);
488 }
489 }
490 break;
491 case PropertyType::BINDABLE_IMAGE_WITH_HANDLE_REFERENCE_T: {
492 PLUGIN_ASSERT(meta.size == IMAGE_HANDLE_REF_BYTE_SIZE);
493 if (BindableImageWithHandleReference* resource =
494 (BindableImageWithHandleReference*)(data_.data() + meta.offset);
495 resource) {
496 DestroyHelper(*resource);
497 }
498 }
499 break;
500 case PropertyType::BINDABLE_SAMPLER_WITH_HANDLE_REFERENCE_T: {
501 PLUGIN_ASSERT(meta.size == SAMPLER_HANDLE_REF_BYTE_SIZE);
502 if (BindableSamplerWithHandleReference* resource =
503 (BindableSamplerWithHandleReference*)(data_.data() + meta.offset);
504 resource) {
505 DestroyHelper(*resource);
506 }
507 }
508 break;
509 default: {
510 CORE_LOG_E("custom property binding destruction error");
511 }
512 break;
513 }
514 }
515 }
516 }
517
PropertyCount() const518 size_t CustomPropertyBindingContainer::PropertyCount() const
519 {
520 return metaData_.size();
521 }
522
MetaData(size_t index) const523 const Property* CustomPropertyBindingContainer::MetaData(size_t index) const
524 {
525 if (index < metaData_.size()) {
526 return &metaData_[index];
527 }
528
529 return nullptr;
530 }
531
MetaData() const532 array_view<const Property> CustomPropertyBindingContainer::MetaData() const
533 {
534 return { metaData_ };
535 }
536
Type() const537 uint64_t CustomPropertyBindingContainer::Type() const
538 {
539 return 0;
540 }
541
Create() const542 IPropertyHandle* CustomPropertyBindingContainer::Create() const
543 {
544 return nullptr;
545 }
546
Clone(const IPropertyHandle * src) const547 IPropertyHandle* CustomPropertyBindingContainer::Clone(const IPropertyHandle* src) const
548 {
549 return nullptr;
550 }
551
Release(IPropertyHandle * handle) const552 void CustomPropertyBindingContainer::Release(IPropertyHandle* handle) const {}
553
ReservePropertyCount(size_t propertyCount)554 void CustomPropertyBindingContainer::ReservePropertyCount(size_t propertyCount)
555 {
556 reservePropertyCount_ = propertyCount;
557 metaStrings_.reserve(reservePropertyCount_);
558 metaData_.reserve(reservePropertyCount_);
559 // max size
560 data_.reserve(reservePropertyCount_ * MAX_STRUCT_HANDLE_REF_BYTE_SIZE);
561 }
562
563 // CustomProperties IPropertyHandle
Owner() const564 const IPropertyApi* CustomPropertyBindingContainer::Owner() const
565 {
566 return this;
567 }
568
Size() const569 size_t CustomPropertyBindingContainer::Size() const
570 {
571 return data_.size();
572 }
573
RLock() const574 const void* CustomPropertyBindingContainer::RLock() const
575 {
576 return data_.data();
577 }
578
RUnlock() const579 void CustomPropertyBindingContainer::RUnlock() const {}
580
WLock()581 void* CustomPropertyBindingContainer::WLock()
582 {
583 return data_.data();
584 }
585
WUnlock()586 void CustomPropertyBindingContainer::WUnlock()
587 {
588 // signal that properties have been written
589 writeSignal_.Signal();
590 }
591
592 //
593
AddOffsetProperty(const string_view propertyName,const string_view displayName,const uintptr_t offset,const PropertyTypeDecl & typeDecl)594 void CustomPropertyBindingContainer::AddOffsetProperty(const string_view propertyName, const string_view displayName,
595 const uintptr_t offset, const PropertyTypeDecl& typeDecl)
596 {
597 const bool reserved = (metaStrings_.size() < reservePropertyCount_);
598 size_t byteSize = 0;
599 switch (typeDecl) {
600 case PropertyType::BINDABLE_BUFFER_WITH_HANDLE_REFERENCE_T: {
601 byteSize = BUFFER_HANDLE_REF_BYTE_SIZE;
602 }
603 break;
604 case PropertyType::BINDABLE_IMAGE_WITH_HANDLE_REFERENCE_T: {
605 byteSize = IMAGE_HANDLE_REF_BYTE_SIZE;
606 }
607 break;
608 case PropertyType::BINDABLE_SAMPLER_WITH_HANDLE_REFERENCE_T: {
609 byteSize = SAMPLER_HANDLE_REF_BYTE_SIZE;
610 }
611 break;
612 }
613 if ((byteSize > 0) && reserved) {
614 metaStrings_.push_back({ string { propertyName }, string { displayName } });
615 const auto& strings = metaStrings_.back();
616 const Property meta {
617 strings.name, // name
618 FNV1aHash(strings.name.data(), strings.name.size()), // hash
619 typeDecl, // type
620 1U, // count
621 byteSize, // size
622 offset, // offset
623 strings.displayName, // displayName
624 0U, // flags
625 GetMetaData(typeDecl), // metaData
626 };
627 metaData_.push_back(meta);
628 // the data has already been reserved in ReservePropertyCount()
629 data_.resize(Math::max(data_.size(), meta.offset + meta.size));
630 switch (meta.type) {
631 case PropertyType::BINDABLE_BUFFER_WITH_HANDLE_REFERENCE_T: {
632 new (data_.data() + meta.offset) BindableBufferWithHandleReference;
633 }
634 break;
635 case PropertyType::BINDABLE_IMAGE_WITH_HANDLE_REFERENCE_T: {
636 new (data_.data() + meta.offset) BindableImageWithHandleReference;
637 }
638 break;
639 case PropertyType::BINDABLE_SAMPLER_WITH_HANDLE_REFERENCE_T: {
640 new (data_.data() + meta.offset) BindableSamplerWithHandleReference;
641 }
642 break;
643 }
644 } else {
645 CORE_LOG_W("unsupported property addition for custom property binding container");
646 }
647 }
648
GetByteSize() const649 size_t CustomPropertyBindingContainer::GetByteSize() const
650 {
651 return data_.size_in_bytes();
652 }
653
654 // CustomPropertyBindingHelper
655
GetPropertyTypeDeclaration(const string_view type)656 PropertyTypeDecl CustomPropertyBindingHelper::GetPropertyTypeDeclaration(const string_view type)
657 {
658 if (type == "buffer") {
659 return PropertyType::BINDABLE_BUFFER_WITH_HANDLE_REFERENCE_T;
660 } else if (type == "image") {
661 return PropertyType::BINDABLE_IMAGE_WITH_HANDLE_REFERENCE_T;
662 } else if (type == "sampler") {
663 return PropertyType::BINDABLE_SAMPLER_WITH_HANDLE_REFERENCE_T;
664 } else {
665 CORE_LOG_W("RENDER_VALIDATION: Invalid property type only buffer, image, and sampler supported");
666 }
667 // NOTE: does not handle invalid types
668 return PropertyType::INVALID;
669 }
670
GetPropertyTypeAlignment(const PropertyTypeDecl & propertyType)671 size_t CustomPropertyBindingHelper::GetPropertyTypeAlignment(const PropertyTypeDecl& propertyType)
672 {
673 size_t align = 1U;
674 switch (propertyType) {
675 case PropertyType::BINDABLE_BUFFER_WITH_HANDLE_REFERENCE_T:
676 align = sizeof(BindableBufferWithHandleReference);
677 break;
678 case PropertyType::BINDABLE_IMAGE_WITH_HANDLE_REFERENCE_T:
679 align = sizeof(BindableImageWithHandleReference);
680 break;
681 case PropertyType::BINDABLE_SAMPLER_WITH_HANDLE_REFERENCE_T:
682 align = sizeof(BindableSamplerWithHandleReference);
683 break;
684 }
685 return align;
686 }
687 RENDER_END_NAMESPACE()