18 bool isValid()
const {
return baseSize > 0 && baseAlignment > 0; }
26 bool isValid()
const {
return size > 0 && alignment > 0; }
36 int64_t innerCount{1};
39static constexpr inline int64_t alignUp(int64_t value, int64_t alignment)
43 return (value + alignment - 1) & ~(alignment - 1);
48static inline ArrayParseResult parseArrayType(
const QString& typeStr)
50 ArrayParseResult result;
51 const auto t = isf::parse_array_type(typeStr.toStdString());
52 result.baseType = QString::fromStdString(t.base);
57 for(std::size_t k = 1; k < t.extents.size(); k++)
58 inner = std::min<int64_t>(inner * std::max<int64_t>(1, t.extents[k]), INT32_MAX);
61 result.arrayCount = -1;
62 result.innerCount = inner;
66 result.arrayCount = (int)std::min<int64_t>(
67 std::max<int64_t>(1, t.extents[0]) * inner, INT32_MAX);
72static inline Std430TypeInfo getStd430BaseTypeInfo(
const QString& typeStr)
74 if(typeStr ==
"float" || typeStr ==
"int" || typeStr ==
"uint" || typeStr ==
"bool")
76 if(typeStr ==
"double")
79 if(typeStr ==
"vec2" || typeStr ==
"ivec2" || typeStr ==
"uvec2" || typeStr ==
"bvec2")
81 if(typeStr ==
"vec3" || typeStr ==
"ivec3" || typeStr ==
"uvec3" || typeStr ==
"bvec3")
83 if(typeStr ==
"vec4" || typeStr ==
"ivec4" || typeStr ==
"uvec4" || typeStr ==
"bvec4")
86 if(typeStr ==
"dvec2")
88 if(typeStr ==
"dvec3")
90 if(typeStr ==
"dvec4")
94 if(typeStr ==
"mat2" || typeStr ==
"mat2x2")
97 if(typeStr ==
"mat3" || typeStr ==
"mat3x3")
100 if(typeStr ==
"mat4" || typeStr ==
"mat4x4")
104 if(typeStr ==
"mat2x3")
107 if(typeStr ==
"mat2x4")
110 if(typeStr ==
"mat3x2")
113 if(typeStr ==
"mat3x4")
116 if(typeStr ==
"mat4x2")
119 if(typeStr ==
"mat4x3")
123 if(typeStr ==
"dmat2" || typeStr ==
"dmat2x2")
126 if(typeStr ==
"dmat3" || typeStr ==
"dmat3x3")
129 if(typeStr ==
"dmat4" || typeStr ==
"dmat4x4")
132 if(typeStr ==
"dmat2x3")
134 if(typeStr ==
"dmat2x4")
136 if(typeStr ==
"dmat3x2")
138 if(typeStr ==
"dmat3x4")
140 if(typeStr ==
"dmat4x2")
142 if(typeStr ==
"dmat4x3")
149static inline LayoutResult calculateStructLayout(
150 std::span<const isf::storage_input::layout_field> layout,
151 std::span<const isf::descriptor::type_definition> typeDefinitions)
159 int64_t currentOffset = 0;
160 int maxAlignment = 0;
162 for(
const auto& field : layout)
164 const ArrayParseResult parsed = parseArrayType(QString::fromStdString(field.type));
165 const QString baseType = parsed.baseType;
167 const bool isArray = (parsed.arrayCount != 0);
168 const bool isFlexibleArray = (parsed.arrayCount == -1);
169 const int arrayCount = (parsed.arrayCount > 0) ? parsed.arrayCount : 1;
173 qWarning() <<
"Flexible array found inside struct. Invalid GLSL, skipping:"
174 << QString::fromStdString(field.name);
181 const Std430TypeInfo info = getStd430BaseTypeInfo(baseType);
186 fieldSize = info.baseSize;
187 fieldAlign = info.baseAlignment;
193 for(
const auto& typeDef : typeDefinitions)
195 if(QString::fromStdString(typeDef.name) == baseType)
197 LayoutResult subStruct
198 = calculateStructLayout(typeDef.layout, typeDefinitions);
199 fieldSize = subStruct.size;
200 fieldAlign = subStruct.alignment;
207 qWarning() <<
"Unknown type, using fallback alignment:" << baseType;
214 int totalFieldSize = fieldSize;
215 if(isArray && arrayCount > 0)
218 int elementStride = alignUp(fieldSize, fieldAlign);
219 totalFieldSize = elementStride * arrayCount;
222 currentOffset = alignUp(currentOffset, fieldAlign);
223 currentOffset += totalFieldSize;
224 maxAlignment = std::max(maxAlignment, fieldAlign);
228 currentOffset = alignUp(currentOffset, maxAlignment);
232 if(currentOffset > (int64_t)std::numeric_limits<int>::max())
234 return {(int)currentOffset, maxAlignment};
252static constexpr int kStd140Vec4Alignment = 16;
259 bool isValid()
const {
return columns > 0; }
264static inline MatrixShape parseMatrixShape(
const QString& typeStr)
266 const bool isDouble = typeStr.startsWith(
"dmat");
267 if(!isDouble && !typeStr.startsWith(
"mat"))
270 const QString dims = typeStr.mid(isDouble ? 4 : 3);
274 int columns = 0, rows = 0;
275 const int x = dims.indexOf(
'x');
279 columns = rows = dims.toInt(&ok);
283 columns = dims.left(x).toInt(&ok);
285 rows = dims.mid(x + 1).toInt(&ok2);
288 if(!ok || columns < 2 || columns > 4 || rows < 2 || rows > 4)
291 return {columns, (isDouble ? QString(
"dvec") : QString(
"vec")) + QString::number(rows)};
294static inline Std430TypeInfo getStd140BaseTypeInfo(
const QString& typeStr)
296 if(
const MatrixShape m = parseMatrixShape(typeStr); m.isValid())
298 const Std430TypeInfo col = getStd430BaseTypeInfo(m.columnType);
301 const int align = (int)std::max<int64_t>(col.baseAlignment, kStd140Vec4Alignment);
302 const int stride = (int)alignUp(col.baseSize, align);
303 return {stride * m.columns, align};
307 return getStd430BaseTypeInfo(typeStr);
310static inline LayoutResult calculateStructLayout140(
311 std::span<const isf::storage_input::layout_field> layout,
312 std::span<const isf::descriptor::type_definition> typeDefinitions);
315static inline LayoutResult std140MemberInfo(
316 const QString& baseType,
317 std::span<const isf::descriptor::type_definition> typeDefinitions)
319 if(
const Std430TypeInfo info = getStd140BaseTypeInfo(baseType); info.isValid())
320 return {info.baseSize, info.baseAlignment};
322 for(
const auto& typeDef : typeDefinitions)
324 if(QString::fromStdString(typeDef.name) == baseType)
325 return calculateStructLayout140(typeDef.layout, typeDefinitions);
328 qWarning() <<
"Unknown type in uniform block layout:" << baseType;
329 return {kStd140Vec4Alignment, kStd140Vec4Alignment};
332static inline LayoutResult calculateStructLayout140(
333 std::span<const isf::storage_input::layout_field> layout,
334 std::span<const isf::descriptor::type_definition> typeDefinitions)
339 int64_t currentOffset = 0;
340 int64_t maxAlignment = kStd140Vec4Alignment;
342 for(
const auto& field : layout)
344 const ArrayParseResult parsed = parseArrayType(QString::fromStdString(field.type));
345 if(parsed.arrayCount == -1)
347 qWarning() <<
"Flexible array found inside std140 struct. Invalid GLSL, skipping:"
348 << QString::fromStdString(field.name);
352 const LayoutResult member = std140MemberInfo(parsed.baseType, typeDefinitions);
353 int64_t fieldAlign = member.alignment;
354 int64_t total = member.size;
356 if(parsed.arrayCount > 0)
358 fieldAlign = std::max<int64_t>(fieldAlign, kStd140Vec4Alignment);
359 total = alignUp(member.size, fieldAlign) * parsed.arrayCount;
362 currentOffset = alignUp(currentOffset, fieldAlign);
363 currentOffset += total;
364 maxAlignment = std::max(maxAlignment, fieldAlign);
367 return {(int)alignUp(currentOffset, maxAlignment), (int)maxAlignment};
381template <
typename Layout>
383calculateUniformBlockSize(
const Layout& layout,
int arrayCount,
const isf::descriptor& d)
385 if(std::empty(layout))
391 const auto& typeDefinitions = d.types;
393 int64_t currentOffset = 0;
394 int64_t maxBufferAlignment = kStd140Vec4Alignment;
396 for(
const auto& field : layout)
398 const ArrayParseResult parsed = parseArrayType(QString::fromStdString(field.type));
399 const LayoutResult member = std140MemberInfo(parsed.baseType, typeDefinitions);
401 const bool isFlexibleArray = (parsed.arrayCount == -1);
402 const bool isFixedArray = (parsed.arrayCount > 0);
404 int64_t fieldAlign = member.alignment;
405 if(isFlexibleArray || isFixedArray)
406 fieldAlign = std::max<int64_t>(fieldAlign, kStd140Vec4Alignment);
408 const int64_t elementStride = alignUp(member.size, fieldAlign);
410 currentOffset = alignUp(currentOffset, fieldAlign);
412 currentOffset += elementStride * parsed.innerCount * arrayCount;
413 else if(isFixedArray)
414 currentOffset += elementStride * parsed.arrayCount;
416 currentOffset += member.size;
418 maxBufferAlignment = std::max(maxBufferAlignment, fieldAlign);
421 return alignUp(currentOffset, maxBufferAlignment);
431template <
typename Layout>
433minimumUniformBlockSize(
const Layout& layout,
const isf::descriptor& d)
435 if(std::empty(layout))
437 const auto& typeDefinitions = d.types;
438 int64_t currentOffset = 0;
439 int64_t maxBufferAlignment = kStd140Vec4Alignment;
440 const auto last = std::prev(std::end(layout));
441 for(
auto it = std::begin(layout); it != std::end(layout); ++it)
443 const ArrayParseResult parsed = parseArrayType(QString::fromStdString(it->type));
444 const LayoutResult member = std140MemberInfo(parsed.baseType, typeDefinitions);
445 const bool isArray = parsed.arrayCount != 0;
446 int64_t fieldAlign = member.alignment;
448 fieldAlign = std::max<int64_t>(fieldAlign, kStd140Vec4Alignment);
449 const int64_t elementStride = alignUp(member.size, fieldAlign);
450 currentOffset = alignUp(currentOffset, fieldAlign);
451 if(isArray && it == last)
452 currentOffset += elementStride;
453 else if(parsed.arrayCount > 0)
454 currentOffset += elementStride * parsed.arrayCount;
456 currentOffset += member.size;
457 maxBufferAlignment = std::max(maxBufferAlignment, fieldAlign);
459 return alignUp(currentOffset, maxBufferAlignment);
462static inline int64_t calculateStorageBufferSize(
463 std::span<const isf::storage_input::layout_field> layout,
int arrayCount,
464 const isf::descriptor& d)
473 const auto& typeDefinitions = d.types;
475 int64_t currentOffset = 0;
476 int64_t maxBufferAlignment = 0;
478 for(
const auto& field : layout)
480 const ArrayParseResult parsed = parseArrayType(QString::fromStdString(field.type));
481 const QString baseType = parsed.baseType;
483 const bool isFlexibleArray = (parsed.arrayCount == -1);
484 const bool isFixedArray = (parsed.arrayCount > 0);
485 const int fixedArrayCount = isFixedArray ? parsed.arrayCount : 1;
488 int64_t fieldAlign = 0;
490 const Std430TypeInfo info = getStd430BaseTypeInfo(baseType);
495 fieldSize = info.baseSize;
496 fieldAlign = info.baseAlignment;
502 for(
const auto& typeDef : typeDefinitions)
504 if(QString::fromStdString(typeDef.name) == baseType)
506 const LayoutResult subRes
507 = calculateStructLayout(typeDef.layout, typeDefinitions);
508 fieldSize = subRes.size;
509 fieldAlign = subRes.alignment;
516 qWarning() <<
"Unknown type in buffer layout:" << baseType;
525 const int64_t elementStride = alignUp(fieldSize, fieldAlign);
526 currentOffset = alignUp(currentOffset, fieldAlign);
530 currentOffset += elementStride * parsed.innerCount * (int64_t)arrayCount;
532 else if(isFixedArray)
535 currentOffset += elementStride * (int64_t)fixedArrayCount;
540 currentOffset += fieldSize;
543 maxBufferAlignment = std::max(maxBufferAlignment, fieldAlign);
546 currentOffset = alignUp(currentOffset, maxBufferAlignment);
548 return currentOffset;
Graphics rendering pipeline for ossia score.
Definition Filter/PreviewWidget.hpp:11