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