summaryrefslogtreecommitdiff
path: root/source/slang/slang-ir-layout.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2023-08-16 22:47:35 -0700
committerGitHub <noreply@github.com>2023-08-17 13:47:35 +0800
commit216fc18661fd6e05053b4cc864396e6017e85b04 (patch)
tree48dfd4aef767694f3063d3c79bcc0a1e3c184346 /source/slang/slang-ir-layout.cpp
parenta0ee2bf671d61d1e2b561db3966e57ffc802040f (diff)
Create storage types of different layouts for SPIRV emit. (#3116)
* Create storage types of different layouts for SPIRV emit. * Fix. * Fix. * Fix. * Update expected failure list. --------- Co-authored-by: Yong He <yhe@nvidia.com>
Diffstat (limited to 'source/slang/slang-ir-layout.cpp')
-rw-r--r--source/slang/slang-ir-layout.cpp561
1 files changed, 194 insertions, 367 deletions
diff --git a/source/slang/slang-ir-layout.cpp b/source/slang/slang-ir-layout.cpp
index df2f50b30..244ff2039 100644
--- a/source/slang/slang-ir-layout.cpp
+++ b/source/slang/slang-ir-layout.cpp
@@ -50,31 +50,29 @@
namespace Slang
{
-
-static Result _calcNaturalArraySizeAndAlignment(
- TargetRequest* target,
- IRType* elementType,
- IRInst* elementCountInst,
+static Result _calcArraySizeAndAlignment(
+ IRTypeLayoutRules* rules,
+ IRType* elementType,
+ IRInst* elementCountInst,
IRSizeAndAlignment* outSizeAndAlignment)
{
auto elementCountLit = as<IRIntLit>(elementCountInst);
- if(!elementCountLit)
+ if (!elementCountLit)
return SLANG_FAIL;
auto elementCount = elementCountLit->getValue();
- if( elementCount == 0 )
+ if (elementCount == 0)
{
*outSizeAndAlignment = IRSizeAndAlignment(0, 1);
return SLANG_OK;
}
IRSizeAndAlignment elementTypeLayout;
- SLANG_RETURN_ON_FAIL(getNaturalSizeAndAlignment(target, elementType, &elementTypeLayout));
-
- auto elementStride = elementTypeLayout.getStride();
+ SLANG_RETURN_ON_FAIL(getSizeAndAlignment(rules, elementType, &elementTypeLayout));
+ elementTypeLayout = rules->alignCompositeElement(elementTypeLayout);
*outSizeAndAlignment = IRSizeAndAlignment(
- elementStride * (elementCount - 1) + elementTypeLayout.size,
+ elementTypeLayout.getStride() * (elementCount - 1) + elementTypeLayout.size,
elementTypeLayout.alignment);
return SLANG_OK;
}
@@ -85,308 +83,8 @@ IRIntegerValue getIntegerValueFromInst(IRInst* inst)
return as<IRIntLit>(inst)->value.intVal;
}
-static Result _calcNaturalSizeAndAlignment(
- TargetRequest* target,
- IRType* type,
- IRSizeAndAlignment* outSizeAndAlignment)
-{
- switch( type->getOp() )
- {
-
-#define CASE(TYPE, SIZE, ALIGNMENT) \
- case kIROp_##TYPE##Type: \
- *outSizeAndAlignment = IRSizeAndAlignment(SIZE, ALIGNMENT); \
- return SLANG_OK \
- /* end */
-
- // Most base types are "naturally aligned" (meaning alignment and size are the same)
-#define BASE(TYPE, SIZE) CASE(TYPE, SIZE, SIZE)
-
- BASE(Int8, 1);
- BASE(UInt8, 1);
-
- BASE(Int16, 2);
- BASE(UInt16, 2);
- BASE(Half, 2);
-
- BASE(Int, 4);
- BASE(UInt, 4);
- BASE(Float, 4);
-
- BASE(Int64, 8);
- BASE(UInt64, 8);
- BASE(Double, 8);
-
- // We are currently handling `bool` following the HLSL
- // precednet of storing it in 4 bytes.
- //
- // TODO: It would be good to try to make this follow
- // per-platform conventions, or at least to be able
- // to use a 1-byte encoding where available.
- //
- BASE(Bool, 4);
-
- // The Slang `void` type is treated as a zero-byte
- // type, so that it does not influence layout at all.
- //
- CASE(Void, 0, 1);
-
-#undef CASE
-
-#undef CASE
-
- case kIROp_StructType:
- {
- auto structType = cast<IRStructType>(type);
- IRSizeAndAlignment structLayout;
- for( auto field : structType->getFields() )
- {
- IRSizeAndAlignment fieldTypeLayout;
- SLANG_RETURN_ON_FAIL(getNaturalSizeAndAlignment(target, field->getFieldType(), &fieldTypeLayout));
-
- structLayout.size = align(structLayout.size, fieldTypeLayout.alignment);
- structLayout.alignment = std::max(structLayout.alignment, fieldTypeLayout.alignment);
-
- IRIntegerValue fieldOffset = structLayout.size;
- if( auto module = type->getModule() )
- {
- // If we are in a situation where attaching new
- // decorations is possible, then we want to
- // cache the field offset on the IR field
- // instruction.
- //
- IRBuilder builder(module);
-
- auto intType = builder.getIntType();
- builder.addDecoration(
- field,
- kIROp_NaturalOffsetDecoration,
- builder.getIntValue(intType, fieldOffset));
- }
-
- structLayout.size += fieldTypeLayout.size;
- }
- *outSizeAndAlignment = structLayout;
- return SLANG_OK;
- }
- break;
-
- case kIROp_ArrayType:
- {
- auto arrayType = cast<IRArrayType>(type);
-
- return _calcNaturalArraySizeAndAlignment(
- target,
- arrayType->getElementType(),
- arrayType->getElementCount(),
- outSizeAndAlignment);
- }
- break;
-
- case kIROp_VectorType:
- {
- auto vecType = cast<IRVectorType>(type);
-
- return _calcNaturalArraySizeAndAlignment(
- target,
- vecType->getElementType(),
- vecType->getElementCount(),
- outSizeAndAlignment);
- }
- break;
- case kIROp_AnyValueType:
- {
- auto anyValType = cast<IRAnyValueType>(type);
- outSizeAndAlignment->size = getIntVal(anyValType->getSize());
- outSizeAndAlignment->alignment = 4;
- return SLANG_OK;
- }
- break;
- case kIROp_TupleType:
- {
- auto tupleType = cast<IRTupleType>(type);
- IRSizeAndAlignment resultLayout;
- for (UInt i = 0; i < tupleType->getOperandCount(); i++)
- {
- auto elementType = tupleType->getOperand(i);
- IRSizeAndAlignment fieldTypeLayout;
- SLANG_RETURN_ON_FAIL(getNaturalSizeAndAlignment(target, (IRType*)elementType, &fieldTypeLayout));
- resultLayout.size = align(resultLayout.size, fieldTypeLayout.alignment);
- resultLayout.alignment = std::max(resultLayout.alignment, fieldTypeLayout.alignment);
- }
- *outSizeAndAlignment = resultLayout;
- return SLANG_OK;
- }
- break;
- case kIROp_WitnessTableType:
- case kIROp_WitnessTableIDType:
- case kIROp_RTTIHandleType:
- {
- outSizeAndAlignment->size = kRTTIHandleSize;
- outSizeAndAlignment->alignment = 4;
- return SLANG_OK;
- }
- break;
- case kIROp_InterfaceType:
- {
- auto interfaceType = cast<IRInterfaceType>(type);
- auto size = SharedGenericsLoweringContext::getInterfaceAnyValueSize(interfaceType, interfaceType->sourceLoc);
- size += kRTTIHeaderSize;
- size = align(size, 4);
- IRSizeAndAlignment resultLayout;
- resultLayout.size = size;
- resultLayout.alignment = 4;
- *outSizeAndAlignment = resultLayout;
- return SLANG_OK;
- }
- break;
- case kIROp_MatrixType:
- {
- auto matType = cast<IRMatrixType>(type);
- auto rowCount = getIntegerValueFromInst(matType->getRowCount());
- auto colCount = getIntegerValueFromInst(matType->getColumnCount());
- IRBuilder builder(type->getModule());
-
- return _calcNaturalArraySizeAndAlignment(
- target, matType->getElementType(),
- builder.getIntValue(builder.getUIntType(), rowCount * colCount),
- outSizeAndAlignment);
- }
- break;
- case kIROp_OutType:
- case kIROp_InOutType:
- case kIROp_RefType:
- case kIROp_RawPointerType:
- case kIROp_PtrType:
- case kIROp_NativePtrType:
- case kIROp_ComPtrType:
- case kIROp_NativeStringType:
- {
- *outSizeAndAlignment = IRSizeAndAlignment(sizeof(void*), sizeof(void*));
- return SLANG_OK;
- }
- break;
- default:
- break;
- }
-
- if( areResourceTypesBindlessOnTarget(target) )
- {
- // TODO: need this to be based on target, instead of hard-coded
- int pointerSize = sizeof(void*);
-
- if(as<IRTextureType>(type) )
- {
- *outSizeAndAlignment = IRSizeAndAlignment(pointerSize, pointerSize);
- return SLANG_OK;
- }
- else if(as<IRSamplerStateTypeBase>(type) )
- {
- *outSizeAndAlignment = IRSizeAndAlignment(pointerSize, pointerSize);
- return SLANG_OK;
- }
- // TODO: the remaining cases for "bindless" resources on CPU/CUDA targets
- }
-
- return SLANG_FAIL;
-}
-
-Result getNaturalSizeAndAlignment(TargetRequest* target, IRType* type, IRSizeAndAlignment* outSizeAndAlignment)
-{
- if( auto decor = type->findDecoration<IRNaturalSizeAndAlignmentDecoration>() )
- {
- *outSizeAndAlignment = IRSizeAndAlignment(decor->getSize(), (int)decor->getAlignment());
- return SLANG_OK;
- }
-
- IRSizeAndAlignment sizeAndAlignment;
- SLANG_RETURN_ON_FAIL(_calcNaturalSizeAndAlignment(target, type, &sizeAndAlignment));
-
- if( auto module = type->getModule() )
- {
- IRBuilder builder(module);
-
- auto intType = builder.getIntType();
- builder.addDecoration(
- type,
- kIROp_NaturalSizeAndAlignmentDecoration,
- builder.getIntValue(intType, sizeAndAlignment.size),
- builder.getIntValue(intType, sizeAndAlignment.alignment));
- }
-
- *outSizeAndAlignment = sizeAndAlignment;
- return SLANG_OK;
-}
-
-
-Result getNaturalOffset(TargetRequest* target, IRStructField* field, IRIntegerValue* outOffset)
-{
- if( auto decor = field->findDecoration<IRNaturalOffsetDecoration>() )
- {
- *outOffset = decor->getOffset();
- return SLANG_OK;
- }
-
- // Offsets are computed as part of layout out types,
- // so we expect that layout of the "parent" type
- // of the field should add an offset to it if
- // possible.
-
- auto structType = as<IRStructType>(field->getParent());
- if(!structType)
- return SLANG_FAIL;
-
- IRSizeAndAlignment structTypeLayout;
- SLANG_RETURN_ON_FAIL(getNaturalSizeAndAlignment(target, structType, &structTypeLayout));
-
- if( auto decor = field->findDecoration<IRNaturalOffsetDecoration>() )
- {
- *outOffset = decor->getOffset();
- return SLANG_OK;
- }
-
- // If attempting to lay out the parent type didn't
- // cause the field to get an offset, then we are
- // in an unexpected case with no easy answer.
- //
- return SLANG_FAIL;
-}
-
-
-//////////////////////////
-// Std430 Layout
-//////////////////////////
-
-static Result _calcStd430ArraySizeAndAlignment(
- TargetRequest* target,
- IRType* elementType,
- IRInst* elementCountInst,
- IRSizeAndAlignment* outSizeAndAlignment)
-{
- auto elementCountLit = as<IRIntLit>(elementCountInst);
- if (!elementCountLit)
- return SLANG_FAIL;
- auto elementCount = elementCountLit->getValue();
-
- if (elementCount == 0)
- {
- *outSizeAndAlignment = IRSizeAndAlignment(0, 1);
- return SLANG_OK;
- }
-
- IRSizeAndAlignment elementTypeLayout;
- SLANG_RETURN_ON_FAIL(getStd430SizeAndAlignment(target, elementType, &elementTypeLayout));
-
- auto elementStride = elementTypeLayout.getStride();
-
- *outSizeAndAlignment = IRSizeAndAlignment(
- elementStride * (elementCount - 1) + elementTypeLayout.size,
- elementTypeLayout.alignment);
- return SLANG_OK;
-}
-
-static Result _calcStd430SizeAndAlignment(
- TargetRequest* target,
+static Result _calcSizeAndAlignment(
+ IRTypeLayoutRules* rules,
IRType* type,
IRSizeAndAlignment* outSizeAndAlignment)
{
@@ -394,12 +92,12 @@ static Result _calcStd430SizeAndAlignment(
{
#define CASE(TYPE, SIZE, ALIGNMENT) \
- case kIROp_##TYPE##Type: \
- *outSizeAndAlignment = IRSizeAndAlignment(SIZE, ALIGNMENT); \
- return SLANG_OK \
- /* end */
+case kIROp_##TYPE##Type: \
+ *outSizeAndAlignment = IRSizeAndAlignment(SIZE, ALIGNMENT); \
+ return SLANG_OK \
+ /* end */
- // Most base types are "std430 aligned" (meaning alignment and size are the same)
+ // Most base types are "naturally aligned" (meaning alignment and size are the same)
#define BASE(TYPE, SIZE) CASE(TYPE, SIZE, SIZE)
BASE(Int8, 1);
@@ -415,6 +113,8 @@ static Result _calcStd430SizeAndAlignment(
BASE(Int64, 8);
BASE(UInt64, 8);
+ BASE(IntPtr, 8);
+ BASE(UIntPtr, 8);
BASE(Double, 8);
// We are currently handling `bool` following the HLSL
@@ -442,8 +142,7 @@ static Result _calcStd430SizeAndAlignment(
for (auto field : structType->getFields())
{
IRSizeAndAlignment fieldTypeLayout;
- SLANG_RETURN_ON_FAIL(getStd430SizeAndAlignment(target, field->getFieldType(), &fieldTypeLayout));
-
+ SLANG_RETURN_ON_FAIL(getSizeAndAlignment(rules, field->getFieldType(), &fieldTypeLayout));
structLayout.size = align(structLayout.size, fieldTypeLayout.alignment);
structLayout.alignment = std::max(structLayout.alignment, fieldTypeLayout.alignment);
@@ -460,13 +159,14 @@ static Result _calcStd430SizeAndAlignment(
auto intType = builder.getIntType();
builder.addDecoration(
field,
- kIROp_Std430OffsetDecoration,
+ kIROp_OffsetDecoration,
+ builder.getIntValue(intType, (IRIntegerValue)rules->ruleName),
builder.getIntValue(intType, fieldOffset));
}
structLayout.size += fieldTypeLayout.size;
}
- *outSizeAndAlignment = structLayout;
+ *outSizeAndAlignment = rules->alignCompositeElement(structLayout);
return SLANG_OK;
}
break;
@@ -475,8 +175,8 @@ static Result _calcStd430SizeAndAlignment(
{
auto arrayType = cast<IRArrayType>(type);
- return _calcStd430ArraySizeAndAlignment(
- target,
+ return _calcArraySizeAndAlignment(
+ rules ,
arrayType->getElementType(),
arrayType->getElementCount(),
outSizeAndAlignment);
@@ -486,15 +186,9 @@ static Result _calcStd430SizeAndAlignment(
case kIROp_VectorType:
{
auto vecType = cast<IRVectorType>(type);
- auto elementCount = getIntegerValueFromInst(vecType->getElementCount());
- auto alignmentMultiplier = elementCount;
- if (elementCount == 3)
- alignmentMultiplier = 4;
- IRSizeAndAlignment sizeAndAlignment;
- SLANG_RETURN_ON_FAIL(getStd430SizeAndAlignment(target, vecType->getElementType(), &sizeAndAlignment));
- sizeAndAlignment.size *= (int)elementCount;
- sizeAndAlignment.alignment *= (int)alignmentMultiplier;
- *outSizeAndAlignment = sizeAndAlignment;
+ IRSizeAndAlignment elementTypeLayout;
+ getSizeAndAlignment(rules, vecType->getElementType(), &elementTypeLayout);
+ *outSizeAndAlignment = rules->getVectorSizeAndAlignment(elementTypeLayout, getIntegerValueFromInst(vecType->getElementCount()));
return SLANG_OK;
}
break;
@@ -503,6 +197,7 @@ static Result _calcStd430SizeAndAlignment(
auto anyValType = cast<IRAnyValueType>(type);
outSizeAndAlignment->size = getIntVal(anyValType->getSize());
outSizeAndAlignment->alignment = 4;
+ *outSizeAndAlignment = rules->alignCompositeElement(*outSizeAndAlignment);
return SLANG_OK;
}
break;
@@ -514,11 +209,11 @@ static Result _calcStd430SizeAndAlignment(
{
auto elementType = tupleType->getOperand(i);
IRSizeAndAlignment fieldTypeLayout;
- SLANG_RETURN_ON_FAIL(getStd430SizeAndAlignment(target, (IRType*)elementType, &fieldTypeLayout));
+ SLANG_RETURN_ON_FAIL(getSizeAndAlignment(rules, (IRType*)elementType, &fieldTypeLayout));
resultLayout.size = align(resultLayout.size, fieldTypeLayout.alignment);
resultLayout.alignment = std::max(resultLayout.alignment, fieldTypeLayout.alignment);
}
- *outSizeAndAlignment = resultLayout;
+ *outSizeAndAlignment = rules->alignCompositeElement(resultLayout);
return SLANG_OK;
}
break;
@@ -540,7 +235,7 @@ static Result _calcStd430SizeAndAlignment(
IRSizeAndAlignment resultLayout;
resultLayout.size = size;
resultLayout.alignment = 4;
- *outSizeAndAlignment = resultLayout;
+ *outSizeAndAlignment = rules->alignCompositeElement(resultLayout);
return SLANG_OK;
}
break;
@@ -548,12 +243,24 @@ static Result _calcStd430SizeAndAlignment(
{
auto matType = cast<IRMatrixType>(type);
IRBuilder builder(type->getModule());
- builder.setInsertBefore(matType);
- auto rowType = builder.getVectorType(matType->getElementType(), matType->getColumnCount());
- return _calcStd430ArraySizeAndAlignment(
- target, rowType,
- matType->getRowCount(),
- outSizeAndAlignment);
+ if (getIntegerValueFromInst(matType->getLayout()) == SLANG_MATRIX_LAYOUT_COLUMN_MAJOR)
+ {
+ auto colVector = builder.getVectorType(matType->getElementType(), matType->getRowCount());
+ return _calcArraySizeAndAlignment(
+ rules,
+ colVector,
+ matType->getColumnCount(),
+ outSizeAndAlignment);
+ }
+ else
+ {
+ auto rowVector = builder.getVectorType(matType->getElementType(), matType->getColumnCount());
+ return _calcArraySizeAndAlignment(
+ rules,
+ rowVector,
+ matType->getRowCount(),
+ outSizeAndAlignment);
+ }
}
break;
case kIROp_OutType:
@@ -564,46 +271,46 @@ static Result _calcStd430SizeAndAlignment(
case kIROp_NativePtrType:
case kIROp_ComPtrType:
case kIROp_NativeStringType:
+ case kIROp_HLSLConstBufferPointerType:
{
- *outSizeAndAlignment = IRSizeAndAlignment(sizeof(void*), sizeof(void*));
+ *outSizeAndAlignment = IRSizeAndAlignment(8, 8);
return SLANG_OK;
}
break;
default:
break;
}
-
- if (areResourceTypesBindlessOnTarget(target))
+ if (as<IRResourceTypeBase>(type) || as<IRSamplerStateTypeBase>(type))
{
- // TODO: need this to be based on target, instead of hard-coded
- int pointerSize = sizeof(void*);
+ *outSizeAndAlignment = IRSizeAndAlignment(8, 8);
+ return SLANG_OK;
+ }
+ return SLANG_FAIL;
+}
- if (as<IRTextureType>(type))
- {
- *outSizeAndAlignment = IRSizeAndAlignment(pointerSize, pointerSize);
- return SLANG_OK;
- }
- else if (as<IRSamplerStateTypeBase>(type))
+IRSizeAndAlignmentDecoration* findSizeAndAlignmentDecorationForLayout(IRType* type, IRTypeLayoutRuleName layoutName)
+{
+ for (auto decorInst : type->getDecorations())
+ {
+ if (auto decor = as<IRSizeAndAlignmentDecoration>(decorInst))
{
- *outSizeAndAlignment = IRSizeAndAlignment(pointerSize, pointerSize);
- return SLANG_OK;
+ if (decor->getLayoutName() == layoutName)
+ return decor;
}
- // TODO: the remaining cases for "bindless" resources on CPU/CUDA targets
}
-
- return SLANG_FAIL;
+ return nullptr;
}
-Result getStd430SizeAndAlignment(TargetRequest* target, IRType* type, IRSizeAndAlignment* outSizeAndAlignment)
+Result getSizeAndAlignment(IRTypeLayoutRules* rules, IRType* type, IRSizeAndAlignment* outSizeAndAlignment)
{
- if (auto decor = type->findDecoration<IRStd430SizeAndAlignmentDecoration>())
+ if (auto decor = findSizeAndAlignmentDecorationForLayout(type, rules->ruleName))
{
*outSizeAndAlignment = IRSizeAndAlignment(decor->getSize(), (int)decor->getAlignment());
return SLANG_OK;
}
IRSizeAndAlignment sizeAndAlignment;
- SLANG_RETURN_ON_FAIL(_calcStd430SizeAndAlignment(target, type, &sizeAndAlignment));
+ SLANG_RETURN_ON_FAIL(_calcSizeAndAlignment(rules, type, &sizeAndAlignment));
if (auto module = type->getModule())
{
@@ -612,7 +319,8 @@ Result getStd430SizeAndAlignment(TargetRequest* target, IRType* type, IRSizeAndA
auto intType = builder.getIntType();
builder.addDecoration(
type,
- kIROp_Std430SizeAndAlignmentDecoration,
+ kIROp_SizeAndAlignmentDecoration,
+ builder.getIntValue(intType, (IRIntegerValue)rules->ruleName),
builder.getIntValue(intType, sizeAndAlignment.size),
builder.getIntValue(intType, sizeAndAlignment.alignment));
}
@@ -620,11 +328,22 @@ Result getStd430SizeAndAlignment(TargetRequest* target, IRType* type, IRSizeAndA
*outSizeAndAlignment = sizeAndAlignment;
return SLANG_OK;
}
+IROffsetDecoration* findOffsetDecorationForLayout(IRStructField* field, IRTypeLayoutRuleName layoutName)
+{
+ for (auto decorInst : field->getDecorations())
+ {
+ if (auto decor = as<IROffsetDecoration>(decorInst))
+ {
+ if (decor->getLayoutName() == layoutName)
+ return decor;
+ }
+ }
+ return nullptr;
+}
-
-Result getStd430Offset(TargetRequest* target, IRStructField* field, IRIntegerValue* outOffset)
+Result getOffset(IRTypeLayoutRules* rules, IRStructField* field, IRIntegerValue* outOffset)
{
- if (auto decor = field->findDecoration<IRStd430OffsetDecoration>())
+ if (auto decor = findOffsetDecorationForLayout(field, rules->ruleName))
{
*outOffset = decor->getOffset();
return SLANG_OK;
@@ -640,9 +359,9 @@ Result getStd430Offset(TargetRequest* target, IRStructField* field, IRIntegerVal
return SLANG_FAIL;
IRSizeAndAlignment structTypeLayout;
- SLANG_RETURN_ON_FAIL(getStd430SizeAndAlignment(target, structType, &structTypeLayout));
+ SLANG_RETURN_ON_FAIL(getSizeAndAlignment(rules, structType, &structTypeLayout));
- if (auto decor = field->findDecoration<IRStd430OffsetDecoration>())
+ if (auto decor = findOffsetDecorationForLayout(field, rules->ruleName))
{
*outOffset = decor->getOffset();
return SLANG_OK;
@@ -655,5 +374,113 @@ Result getStd430Offset(TargetRequest* target, IRStructField* field, IRIntegerVal
return SLANG_FAIL;
}
+struct NaturalLayoutRules : IRTypeLayoutRules
+{
+ NaturalLayoutRules()
+ {
+ ruleName = IRTypeLayoutRuleName::Natural;
+ }
+
+ virtual IRSizeAndAlignment alignCompositeElement(IRSizeAndAlignment elementSize)
+ {
+ return elementSize;
+ }
+ virtual IRSizeAndAlignment getVectorSizeAndAlignment(IRSizeAndAlignment element, IRIntegerValue count)
+ {
+ return IRSizeAndAlignment(element.size * count, element.alignment);
+ }
+};
+
+struct Std430LayoutRules : IRTypeLayoutRules
+{
+ Std430LayoutRules()
+ {
+ ruleName = IRTypeLayoutRuleName::Std430;
+ }
+
+ virtual IRSizeAndAlignment alignCompositeElement(IRSizeAndAlignment elementSize)
+ {
+ return elementSize;
+ }
+ virtual IRSizeAndAlignment getVectorSizeAndAlignment(IRSizeAndAlignment element, IRIntegerValue count)
+ {
+ if (count == 3)
+ count = 4;
+ return IRSizeAndAlignment((int)(element.size * count), (int)(element.size * count));
+ }
+};
+
+struct Std140LayoutRules : IRTypeLayoutRules
+{
+ Std140LayoutRules()
+ {
+ ruleName = IRTypeLayoutRuleName::Std140;
+ }
+
+ virtual IRSizeAndAlignment alignCompositeElement(IRSizeAndAlignment elementSize)
+ {
+ elementSize.alignment = (int)align(elementSize.alignment, 16);
+ elementSize.size = align(elementSize.size, elementSize.alignment);
+ return elementSize;
+ }
+ virtual IRSizeAndAlignment getVectorSizeAndAlignment(IRSizeAndAlignment element, IRIntegerValue count)
+ {
+ if (count == 3)
+ count = 4;
+ return IRSizeAndAlignment((int)(element.size * count), (int)(element.size * count));
+ }
+};
+
+Result getNaturalSizeAndAlignment(IRType* type, IRSizeAndAlignment* outSizeAndAlignment)
+{
+ return getSizeAndAlignment(IRTypeLayoutRules::getNatural(), type, outSizeAndAlignment);
+
+}
+
+Result getNaturalOffset(IRStructField* field, IRIntegerValue* outOffset)
+{
+ return getOffset(IRTypeLayoutRules::getNatural(), field, outOffset);
+}
+
+
+//////////////////////////
+// Std430 Layout
+//////////////////////////
+
+Result getStd430SizeAndAlignment(IRType* type, IRSizeAndAlignment* outSizeAndAlignment)
+{
+ return getSizeAndAlignment(IRTypeLayoutRules::getStd430(), type, outSizeAndAlignment);
+}
+
+Result getStd430Offset(IRStructField* field, IRIntegerValue* outOffset)
+{
+ return getOffset(IRTypeLayoutRules::getStd430(), field, outOffset);
+}
+
+IRTypeLayoutRules* IRTypeLayoutRules::getStd430()
+{
+ static Std430LayoutRules rules;
+ return &rules;
+}
+IRTypeLayoutRules* IRTypeLayoutRules::getStd140()
+{
+ static Std140LayoutRules rules;
+ return &rules;
+}
+IRTypeLayoutRules* IRTypeLayoutRules::getNatural()
+{
+ static NaturalLayoutRules rules;
+ return &rules;
+}
+IRTypeLayoutRules* IRTypeLayoutRules::get(IRTypeLayoutRuleName name)
+{
+ switch (name)
+ {
+ case IRTypeLayoutRuleName::Std430: return getStd430();
+ case IRTypeLayoutRuleName::Std140: return getStd140();
+ case IRTypeLayoutRuleName::Natural: return getNatural();
+ default: return nullptr;
+ }
+}
}