summaryrefslogtreecommitdiff
path: root/source/slang/type-layout.h
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/type-layout.h')
-rw-r--r--source/slang/type-layout.h170
1 files changed, 155 insertions, 15 deletions
diff --git a/source/slang/type-layout.h b/source/slang/type-layout.h
index 7f662bdee..32ee41784 100644
--- a/source/slang/type-layout.h
+++ b/source/slang/type-layout.h
@@ -36,12 +36,152 @@ enum class LayoutRulesFamily
};
#endif
+// A "size" that can either be a simple finite size or
+// the special case of an infinite/unbounded size.
+//
+struct LayoutSize
+{
+ typedef size_t RawValue;
+
+ LayoutSize()
+ : raw(0)
+ {}
+
+ LayoutSize(RawValue size)
+ : raw(size)
+ {
+ SLANG_ASSERT(size != RawValue(-1));
+ }
+
+ static LayoutSize infinite()
+ {
+ LayoutSize result;
+ result.raw = RawValue(-1);
+ return result;
+ }
+
+ bool isInfinite() const { return raw == RawValue(-1); }
+
+ bool isFinite() const { return raw != RawValue(-1); }
+ RawValue getFiniteValue() const { SLANG_ASSERT(isFinite()); return raw; }
+
+ bool operator==(LayoutSize that) const
+ {
+ return raw == that.raw;
+ }
+
+ bool operator!=(LayoutSize that) const
+ {
+ return raw != that.raw;
+ }
+
+ void operator+=(LayoutSize right)
+ {
+ if( isInfinite() ) {}
+ else if( right.isInfinite() )
+ {
+ *this = LayoutSize::infinite();
+ }
+ else
+ {
+ *this = LayoutSize(raw + right.raw);
+ }
+ }
+
+ void operator*=(LayoutSize right)
+ {
+ // Deal with zero first, so that anything (even the "infinite" value) times zero is zero.
+ if( raw == 0 )
+ {
+ return;
+ }
+
+ if( right.raw == 0 )
+ {
+ raw = 0;
+ return;
+ }
+
+ // Next we deal with infinite cases, so that infinite times anything non-zero is infinite
+ if( isInfinite() )
+ {
+ return;
+ }
+
+ if( right.isInfinite() )
+ {
+ *this = LayoutSize::infinite();
+ return;
+ }
+
+ // Finally deal with the case where both sides are finite
+ *this = LayoutSize(raw * right.raw);
+ }
+
+ void operator-=(RawValue right)
+ {
+ if( isInfinite() ) {}
+ else
+ {
+ *this = LayoutSize(raw - right);
+ }
+ }
+
+ void operator/=(RawValue right)
+ {
+ if( isInfinite() ) {}
+ else
+ {
+ *this = LayoutSize(raw / right);
+ }
+ }
+ RawValue raw;
+};
+
+inline LayoutSize operator+(LayoutSize left, LayoutSize right)
+{
+ LayoutSize result(left);
+ result += right;
+ return result;
+}
+
+inline LayoutSize operator*(LayoutSize left, LayoutSize right)
+{
+ LayoutSize result(left);
+ result *= right;
+ return result;
+}
+
+inline LayoutSize operator-(LayoutSize left, LayoutSize::RawValue right)
+{
+ LayoutSize result(left);
+ result -= right;
+ return result;
+}
+
+inline LayoutSize operator/(LayoutSize left, LayoutSize::RawValue right)
+{
+ LayoutSize result(left);
+ result /= right;
+ return result;
+}
+
+inline LayoutSize maximum(LayoutSize left, LayoutSize right)
+{
+ if(left.isInfinite() || right.isInfinite())
+ return LayoutSize::infinite();
+
+ return LayoutSize(Math::Max(
+ left.getFiniteValue(),
+ right.getFiniteValue()));
+}
+
// Layout appropriate to "just memory" scenarios,
// such as laying out the members of a constant buffer.
struct UniformLayoutInfo
{
- size_t size;
- size_t alignment;
+ LayoutSize size;
+ size_t alignment;
UniformLayoutInfo()
: size(0)
@@ -49,8 +189,8 @@ struct UniformLayoutInfo
{}
UniformLayoutInfo(
- size_t size,
- size_t alignment)
+ LayoutSize size,
+ size_t alignment)
: size(size)
, alignment(alignment)
{}
@@ -68,9 +208,9 @@ struct UniformArrayLayoutInfo : UniformLayoutInfo
{}
UniformArrayLayoutInfo(
- size_t size,
- size_t alignment,
- size_t elementStride)
+ LayoutSize size,
+ size_t alignment,
+ size_t elementStride)
: UniformLayoutInfo(size, alignment)
, elementStride(elementStride)
{}
@@ -86,7 +226,7 @@ struct SimpleLayoutInfo
LayoutResourceKind kind;
// How many resources of that kind?
- size_t size;
+ LayoutSize size;
// only useful in the uniform case
size_t alignment;
@@ -104,7 +244,7 @@ struct SimpleLayoutInfo
, alignment(uniformInfo.alignment)
{}
- SimpleLayoutInfo(LayoutResourceKind kind, size_t size, size_t alignment=1)
+ SimpleLayoutInfo(LayoutResourceKind kind, LayoutSize size, size_t alignment=1)
: kind(kind)
, size(size)
, alignment(alignment)
@@ -168,7 +308,7 @@ public:
LayoutResourceKind kind = LayoutResourceKind::None;
// How many registers of the above kind did we use?
- UInt count;
+ LayoutSize count;
};
List<ResourceInfo> resourceInfos;
@@ -207,7 +347,7 @@ public:
findOrAddResourceInfo(info.kind)->count += info.count;
}
- void addResourceUsage(LayoutResourceKind kind, UInt count)
+ void addResourceUsage(LayoutResourceKind kind, LayoutSize count)
{
ResourceInfo info;
info.kind = kind;
@@ -507,7 +647,7 @@ struct SimpleLayoutRulesImpl
virtual SimpleLayoutInfo GetScalarLayout(BaseType baseType) = 0;
// Get size and alignment for an array of elements
- virtual SimpleArrayLayoutInfo GetArrayLayout(SimpleLayoutInfo elementInfo, size_t elementCount) = 0;
+ virtual SimpleArrayLayoutInfo GetArrayLayout(SimpleLayoutInfo elementInfo, LayoutSize elementCount) = 0;
// Get layout for a vector or matrix type
virtual SimpleLayoutInfo GetVectorLayout(SimpleLayoutInfo elementInfo, size_t elementCount) = 0;
@@ -517,7 +657,7 @@ struct SimpleLayoutRulesImpl
virtual UniformLayoutInfo BeginStructLayout() = 0;
// Add a field to a `struct` type, and return the offset for the field
- virtual size_t AddStructField(UniformLayoutInfo* ioStructInfo, UniformLayoutInfo fieldInfo) = 0;
+ virtual LayoutSize AddStructField(UniformLayoutInfo* ioStructInfo, UniformLayoutInfo fieldInfo) = 0;
// End layout for a struct, and finalize its size/alignment.
virtual void EndStructLayout(UniformLayoutInfo* ioStructInfo) = 0;
@@ -542,7 +682,7 @@ struct LayoutRulesImpl
return simpleRules->GetScalarLayout(baseType);
}
- SimpleArrayLayoutInfo GetArrayLayout(SimpleLayoutInfo elementInfo, size_t elementCount)
+ SimpleArrayLayoutInfo GetArrayLayout(SimpleLayoutInfo elementInfo, LayoutSize elementCount)
{
return simpleRules->GetArrayLayout(elementInfo, elementCount);
}
@@ -562,7 +702,7 @@ struct LayoutRulesImpl
return simpleRules->BeginStructLayout();
}
- size_t AddStructField(UniformLayoutInfo* ioStructInfo, UniformLayoutInfo fieldInfo)
+ LayoutSize AddStructField(UniformLayoutInfo* ioStructInfo, UniformLayoutInfo fieldInfo)
{
return simpleRules->AddStructField(ioStructInfo, fieldInfo);
}