Commit fafd64a6 by Shahbaz Youssefi Committed by Angle LUCI CQ

Vulkan: SPIR-V Gen: Matrix decorations

Matrices in blocks require MatrixStride and one of ColMajor or RowMajor decorations. Bug: angleproject:4889 Change-Id: I14ddb32fd3dbc977bf41703b016dc6d1c0722475 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2930368 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent 349c0830
...@@ -321,13 +321,14 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const char *block ...@@ -321,13 +321,14 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const char *block
uint32_t baseAlignment = 4; uint32_t baseAlignment = 4;
uint32_t sizeInStorageBlock = 0; uint32_t sizeInStorageBlock = 0;
uint32_t matrixStride = 0;
// Calculate base alignment and sizes for types. Size for blocks are not calculated, as they // Calculate base alignment and sizes for types. Size for blocks are not calculated, as they
// are done later at the same time Offset decorations are written. // are done later at the same time Offset decorations are written.
const bool isOpaqueType = IsOpaqueType(type.type); const bool isOpaqueType = IsOpaqueType(type.type);
if (!isOpaqueType) if (!isOpaqueType)
{ {
baseAlignment = calculateBaseAlignmentAndSize(type, &sizeInStorageBlock); baseAlignment = calculateBaseAlignmentAndSize(type, &sizeInStorageBlock, &matrixStride);
} }
// Write decorations for interface block fields. // Write decorations for interface block fields.
...@@ -344,14 +345,11 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const char *block ...@@ -344,14 +345,11 @@ SpirvTypeData SPIRVBuilder::declareType(const SpirvType &type, const char *block
// Write the Offset decoration for interface blocks and structs in them. // Write the Offset decoration for interface blocks and structs in them.
sizeInStorageBlock = calculateSizeAndWriteOffsetDecorations(type, typeId); sizeInStorageBlock = calculateSizeAndWriteOffsetDecorations(type, typeId);
} }
// TODO: write the MatrixStride decoration. http://anglebug.com/4889.
} }
// TODO: handle row-major matrixes. http://anglebug.com/4889.
// TODO: handle RelaxedPrecision types. http://anglebug.com/4889. // TODO: handle RelaxedPrecision types. http://anglebug.com/4889.
return {typeId, baseAlignment, sizeInStorageBlock}; return {typeId, baseAlignment, sizeInStorageBlock, matrixStride};
} }
void SPIRVBuilder::getImageTypeParameters(TBasicType type, void SPIRVBuilder::getImageTypeParameters(TBasicType type,
...@@ -972,7 +970,8 @@ void SPIRVBuilder::writeInterfaceVariableDecorations(const TType &type, spirv::I ...@@ -972,7 +970,8 @@ void SPIRVBuilder::writeInterfaceVariableDecorations(const TType &type, spirv::I
} }
uint32_t SPIRVBuilder::calculateBaseAlignmentAndSize(const SpirvType &type, uint32_t SPIRVBuilder::calculateBaseAlignmentAndSize(const SpirvType &type,
uint32_t *sizeInStorageBlockOut) uint32_t *sizeInStorageBlockOut,
uint32_t *matrixStrideOut)
{ {
// Calculate the base alignment of a type according to the rules of std140 and std430 packing. // Calculate the base alignment of a type according to the rules of std140 and std430 packing.
// //
...@@ -1018,6 +1017,9 @@ uint32_t SPIRVBuilder::calculateBaseAlignmentAndSize(const SpirvType &type, ...@@ -1018,6 +1017,9 @@ uint32_t SPIRVBuilder::calculateBaseAlignmentAndSize(const SpirvType &type,
} }
*sizeInStorageBlockOut = baseTypeData.sizeInStorageBlock * arraySizeProduct; *sizeInStorageBlockOut = baseTypeData.sizeInStorageBlock * arraySizeProduct;
// Matrix is inherited from the non-array type.
*matrixStrideOut = baseTypeData.matrixStride;
return baseAlignment; return baseAlignment;
} }
...@@ -1087,6 +1089,9 @@ uint32_t SPIRVBuilder::calculateBaseAlignmentAndSize(const SpirvType &type, ...@@ -1087,6 +1089,9 @@ uint32_t SPIRVBuilder::calculateBaseAlignmentAndSize(const SpirvType &type,
*sizeInStorageBlockOut = vectorTypeData.sizeInStorageBlock * type.primarySize * *sizeInStorageBlockOut = vectorTypeData.sizeInStorageBlock * type.primarySize *
type.secondarySize / vectorType.primarySize; type.secondarySize / vectorType.primarySize;
// The matrix stride is simply the alignment of the vector constituting a column or row.
*matrixStrideOut = baseAlignment;
return baseAlignment; return baseAlignment;
} }
...@@ -1135,18 +1140,37 @@ uint32_t SPIRVBuilder::calculateSizeAndWriteOffsetDecorations(const SpirvType &t ...@@ -1135,18 +1140,37 @@ uint32_t SPIRVBuilder::calculateSizeAndWriteOffsetDecorations(const SpirvType &t
for (const TField *field : type.block->fields()) for (const TField *field : type.block->fields())
{ {
const TType &fieldType = *field->type();
// Round the offset up to the field's alignment. The spec says: // Round the offset up to the field's alignment. The spec says:
// //
// > A structure and each structure member have a base offset and a base alignment, from // > A structure and each structure member have a base offset and a base alignment, from
// > which an aligned offset is computed by rounding the base offset up to a multiple of the // > which an aligned offset is computed by rounding the base offset up to a multiple of the
// > base alignment. // > base alignment.
const SpirvTypeData &fieldTypeData = getTypeData(*field->type(), type.blockStorage); const SpirvTypeData &fieldTypeData = getTypeData(fieldType, type.blockStorage);
nextOffset = rx::roundUp(nextOffset, fieldTypeData.baseAlignment); nextOffset = rx::roundUp(nextOffset, fieldTypeData.baseAlignment);
// Write the Offset decoration. // Write the Offset decoration.
spirv::WriteMemberDecorate(&mSpirvDecorations, typeId, spirv::LiteralInteger(fieldIndex++), spirv::WriteMemberDecorate(&mSpirvDecorations, typeId, spirv::LiteralInteger(fieldIndex),
spv::DecorationOffset, {spirv::LiteralInteger(nextOffset)}); spv::DecorationOffset, {spirv::LiteralInteger(nextOffset)});
// While here, add matrix decorations if any.
if (fieldType.isMatrix())
{
ASSERT(fieldTypeData.matrixStride != 0);
// MatrixStride
spirv::WriteMemberDecorate(
&mSpirvDecorations, typeId, spirv::LiteralInteger(fieldIndex),
spv::DecorationMatrixStride, {spirv::LiteralInteger(fieldTypeData.matrixStride)});
// ColMajor or RowMajor
const bool isRowMajor = fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor;
spirv::WriteMemberDecorate(
&mSpirvDecorations, typeId, spirv::LiteralInteger(fieldIndex),
isRowMajor ? spv::DecorationRowMajor : spv::DecorationColMajor, {});
}
// Calculate the next offset. The next offset is the current offset plus the size of the // Calculate the next offset. The next offset is the current offset plus the size of the
// field, aligned to its base alignment. // field, aligned to its base alignment.
// //
...@@ -1157,6 +1181,8 @@ uint32_t SPIRVBuilder::calculateSizeAndWriteOffsetDecorations(const SpirvType &t ...@@ -1157,6 +1181,8 @@ uint32_t SPIRVBuilder::calculateSizeAndWriteOffsetDecorations(const SpirvType &t
// > the next multiple of the base alignment of the structure. // > the next multiple of the base alignment of the structure.
nextOffset = nextOffset + fieldTypeData.sizeInStorageBlock; nextOffset = nextOffset + fieldTypeData.sizeInStorageBlock;
nextOffset = rx::roundUp(nextOffset, fieldTypeData.baseAlignment); nextOffset = rx::roundUp(nextOffset, fieldTypeData.baseAlignment);
++fieldIndex;
} }
return nextOffset; return nextOffset;
......
...@@ -149,9 +149,11 @@ struct SpirvTypeData ...@@ -149,9 +149,11 @@ struct SpirvTypeData
// The SPIR-V id corresponding to the type. // The SPIR-V id corresponding to the type.
spirv::IdRef id; spirv::IdRef id;
// The base alignment and size of the type based on the storage block it's used in (if // The base alignment and size of the type based on the storage block it's used in (if
// applicable) // applicable).
uint32_t baseAlignment; uint32_t baseAlignment;
uint32_t sizeInStorageBlock; uint32_t sizeInStorageBlock;
// The matrix stride, if matrix or array of matrix.
uint32_t matrixStride;
}; };
// A block of code. SPIR-V produces forward references to blocks, such as OpBranchConditional // A block of code. SPIR-V produces forward references to blocks, such as OpBranchConditional
...@@ -231,7 +233,9 @@ class SPIRVBuilder : angle::NonCopyable ...@@ -231,7 +233,9 @@ class SPIRVBuilder : angle::NonCopyable
void writePerVertexBuiltIns(const TType &type, spirv::IdRef typeId); void writePerVertexBuiltIns(const TType &type, spirv::IdRef typeId);
void writeInterfaceVariableDecorations(const TType &type, spirv::IdRef variableId); void writeInterfaceVariableDecorations(const TType &type, spirv::IdRef variableId);
uint32_t calculateBaseAlignmentAndSize(const SpirvType &type, uint32_t *sizeInStorageBlockOut); uint32_t calculateBaseAlignmentAndSize(const SpirvType &type,
uint32_t *sizeInStorageBlockOut,
uint32_t *matrixStrideOut);
uint32_t calculateSizeAndWriteOffsetDecorations(const SpirvType &type, spirv::IdRef typeId); uint32_t calculateSizeAndWriteOffsetDecorations(const SpirvType &type, spirv::IdRef typeId);
spirv::IdRef getBoolConstant(bool value); spirv::IdRef getBoolConstant(bool value);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment