Commit d93b9559 by Xinghua Cao Committed by Commit Bot

Translate uniform block with large matrix array to StructuredBuffer

There is a slow compiling issue if translate a uniform block with a large matrix array member to cbuffer, so translate the uniform block to StructuredBuffer. But pack_matrix pragma directive is invalid for matrix element of StructuredBuffer, so pack the matrix into a structure firstly, and then specifies packing alignment for the matrix in this structure, last the structure is used as StructuredBuffer element. Bug: angleproject:4206 Change-Id: I5a2a512e57b37dcdb88c3060d0d078b46f72eb5e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2154525 Commit-Queue: Xinghua Cao <xinghua.cao@intel.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarKenneth Russell <kbr@chromium.org>
parent 853a03f9
......@@ -86,28 +86,31 @@ bool IsInStd140UniformBlock(TIntermTyped *node)
return false;
}
bool IsInstanceUniformBlock(TIntermTyped *node)
const TInterfaceBlock *GetInterfaceBlockOfUniformBlockNearestIndexOperator(TIntermTyped *node)
{
TIntermBinary *binaryNode = node->getAsBinaryNode();
const TIntermBinary *binaryNode = node->getAsBinaryNode();
if (binaryNode)
{
return IsInstanceUniformBlock(binaryNode->getLeft());
if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
{
return binaryNode->getLeft()->getType().getInterfaceBlock();
}
}
const TVariable &variable = node->getAsSymbolNode()->variable();
const TType &variableType = variable.getType();
const TType &type = node->getType();
if (type.getQualifier() == EvqUniform)
const TIntermSymbol *symbolNode = node->getAsSymbolNode();
if (symbolNode)
{
// determine if it is instance uniform block.
const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
return interfaceBlock && variableType.isInterfaceBlock();
const TVariable &variable = symbolNode->variable();
const TType &variableType = variable.getType();
if (variableType.getQualifier() == EvqUniform &&
variable.symbolType() == SymbolType::UserDefined)
{
return variableType.getInterfaceBlock();
}
}
return false;
return nullptr;
}
const char *GetHLSLAtomicFunctionStringAndLeftParenthesis(TOperator op)
......@@ -1634,6 +1637,21 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
else
{
outputTriplet(out, visit, "", "[", "]");
if (visit == PostVisit)
{
const TInterfaceBlock *interfaceBlock =
GetInterfaceBlockOfUniformBlockNearestIndexOperator(node->getLeft());
if (interfaceBlock &&
mResourcesHLSL->shouldTranslateUniformBlockToStructuredBuffer(
*interfaceBlock))
{
const TField *field = interfaceBlock->fields()[0];
if (field->type()->isMatrix())
{
out << "._matrix_" << Decorate(field->name());
}
}
}
}
}
break;
......@@ -1650,6 +1668,21 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
else
{
outputTriplet(out, visit, "", "[", "]");
if (visit == PostVisit)
{
const TInterfaceBlock *interfaceBlock =
GetInterfaceBlockOfUniformBlockNearestIndexOperator(node->getLeft());
if (interfaceBlock &&
mResourcesHLSL->shouldTranslateUniformBlockToStructuredBuffer(
*interfaceBlock))
{
const TField *field = interfaceBlock->fields()[0];
if (field->type()->isMatrix())
{
out << "._matrix_" << Decorate(field->name());
}
}
}
}
break;
}
......@@ -1707,11 +1740,8 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
node->getLeft()->getType().getInterfaceBlock();
const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
const TField *field = interfaceBlock->fields()[index->getIConst(0)];
bool instanceUniformBlock = IsInstanceUniformBlock(node->getLeft());
if (structInStd140UniformBlock ||
(instanceUniformBlock &&
mResourcesHLSL->shouldTranslateUniformBlockToStructuredBuffer(
*interfaceBlock)))
mResourcesHLSL->shouldTranslateUniformBlockToStructuredBuffer(*interfaceBlock))
{
out << "_";
}
......@@ -3621,5 +3651,4 @@ const char *OutputHLSL::generateOutputCall() const
return "generateOutput()";
}
}
} // namespace sh
......@@ -779,7 +779,17 @@ TString ResourcesHLSL::uniformBlockWithOneLargeArrayMemberString(
const TField &field = *interfaceBlock.fields()[0];
const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();
typeString = InterfaceBlockFieldTypeString(field, blockStorage, true);
typeString = InterfaceBlockFieldTypeString(field, blockStorage, true);
const TType &fieldType = *field.type();
if (fieldType.isMatrix())
{
if (arrayIndex == GL_INVALID_INDEX || arrayIndex == 0)
{
hlsl += "struct matrix" + Decorate(field.name()) + " { " + typeString + " _matrix_" +
Decorate(field.name()) + "; };\n";
}
typeString = "matrix" + Decorate(field.name());
}
if (instanceVariable != nullptr)
{
......@@ -879,11 +889,10 @@ bool ResourcesHLSL::shouldTranslateUniformBlockToStructuredBuffer(
{
const TType &fieldType = *interfaceBlock.fields()[0]->type();
// TODO(anglebug.com/4206): Support uniform block contains only a matrix array member,
// and fix row-major/column-major conversion issue.
return (mCompileOptions & SH_DONT_TRANSLATE_UNIFORM_BLOCK_TO_STRUCTUREDBUFFER) == 0 &&
mSRVRegister < kMaxInputResourceSlotCount && interfaceBlock.fields().size() == 1u &&
fieldType.getStruct() != nullptr && fieldType.getNumArraySizes() == 1u &&
(fieldType.getStruct() != nullptr || fieldType.isMatrix()) &&
fieldType.getNumArraySizes() == 1u &&
fieldType.getOutermostArraySize() >= kMinArraySizeUseStructuredBuffer;
}
} // namespace sh
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