SPV: Handle stride decorations for arrays of arrays, and using multiple type instances when strides are used.

This commit is contained in:
John Kessenich
2015-12-29 21:27:24 -07:00
parent 4998789d4e
commit c9e0a42b92
5 changed files with 277 additions and 249 deletions

View File

@@ -1651,10 +1651,37 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
}
if (type.isArray()) {
int stride = 0; // keep this 0 unless doing an explicit layout; 0 will mean no decoration, no stride
// Do all but the outer dimension
for (int dim = type.getArraySizes()->getNumDims() - 1; dim > 0; --dim) {
assert(type.getArraySizes()->getDimSize(dim) > 0);
spvType = builder.makeArrayType(spvType, type.getArraySizes()->getDimSize(dim));
if (type.getArraySizes()->getNumDims() > 1) {
if (explicitLayout != glslang::ElpNone) {
// Use a dummy glslang type for querying internal strides of
// arrays of arrays, but using just a one-dimensional array.
glslang::TType simpleArrayType(type, 0); // deference type of the array
while (simpleArrayType.getArraySizes().getNumDims() > 1)
simpleArrayType.getArraySizes().dereference();
// Will compute the higher-order strides here, rather than making a whole
// pile of types and doing repetitive recursion on their contents.
stride = getArrayStride(simpleArrayType, explicitLayout, qualifier.layoutMatrix);
}
for (int dim = type.getArraySizes()->getNumDims() - 1; dim > 0; --dim) {
int size = type.getArraySizes()->getDimSize(dim);
assert(size > 0);
spvType = builder.makeArrayType(spvType, size, stride);
if (stride > 0)
builder.addDecoration(spvType, spv::DecorationArrayStride, stride);
stride *= size;
}
} else {
// single-dimensional array, and don't yet have stride
// We need to decorate array strides for types needing explicit layout,
// except for the very top if it is an array of blocks; that array is
// not laid out in memory in a way needing a stride.
if (explicitLayout != glslang::ElpNone && type.getBasicType() != glslang::EbtBlock)
stride = getArrayStride(type, explicitLayout, qualifier.layoutMatrix);
}
// Do the outer dimension, which might not be known for a runtime-sized array
@@ -1662,18 +1689,10 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
spvType = builder.makeRuntimeArray(spvType);
} else {
assert(type.getOuterArraySize() > 0);
spvType = builder.makeArrayType(spvType, type.getOuterArraySize());
spvType = builder.makeArrayType(spvType, type.getOuterArraySize(), stride);
}
// TODO: explicit layout still needs to be done hierarchically for arrays of arrays, which
// may still require additional "link time" support from the front-end
// for arrays of arrays
// We need to decorate array strides for types needing explicit layout,
// except for the very top if it is an array of blocks; that array is
// not laid out in memory in a way needing a stride.
if (explicitLayout && type.getBasicType() != glslang::EbtBlock)
builder.addDecoration(spvType, spv::DecorationArrayStride, getArrayStride(type, explicitLayout, qualifier.layoutMatrix));
if (stride > 0)
builder.addDecoration(spvType, spv::DecorationArrayStride, stride);
}
return spvType;

View File

@@ -281,18 +281,23 @@ Id Builder::makeMatrixType(Id component, int cols, int rows)
return type->getResultId();
}
Id Builder::makeArrayType(Id element, unsigned size)
// TODO: performance: track arrays per stride
// If a stride is supplied (non-zero) make an array.
// If no stride (0), reuse previous array types.
Id Builder::makeArrayType(Id element, unsigned size, int stride)
{
// First, we need a constant instruction for the size
Id sizeId = makeUintConstant(size);
// try to find existing type
Instruction* type;
for (int t = 0; t < (int)groupedTypes[OpTypeArray].size(); ++t) {
type = groupedTypes[OpTypeArray][t];
if (type->getIdOperand(0) == element &&
type->getIdOperand(1) == sizeId)
return type->getResultId();
if (stride == 0) {
// try to find existing type
for (int t = 0; t < (int)groupedTypes[OpTypeArray].size(); ++t) {
type = groupedTypes[OpTypeArray][t];
if (type->getIdOperand(0) == element &&
type->getIdOperand(1) == sizeId)
return type->getResultId();
}
}
// not found, make it

View File

@@ -102,7 +102,7 @@ public:
Id makeStructResultType(Id type0, Id type1);
Id makeVectorType(Id component, int size);
Id makeMatrixType(Id component, int cols, int rows);
Id makeArrayType(Id element, unsigned size);
Id makeArrayType(Id element, unsigned size, int stride); // 0 means no stride decoration
Id makeRuntimeArray(Id element);
Id makeFunctionType(Id returnType, std::vector<Id>& paramTypes);
Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format);