ES31: Add unsized array length support in SSBO
Bug: angleproject:1951
Change-Id: I10c798c62a741b156f5b614e0df0795c0e845108
Reviewed-on: https://chromium-review.googlesource.com/c/1365154
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Jiajia Qin <jiajia.qin@intel.com>
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index 07499a5..aa81c11 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -1837,6 +1837,13 @@
// tested in GLSLTest and results are consistent with GL.
outputTriplet(out, visit, "firstbithigh(", "", ")");
break;
+ case EOpArrayLength:
+ {
+ TIntermTyped *operand = node->getOperand();
+ ASSERT(IsInShaderStorageBlock(operand));
+ mSSBOOutputHLSL->outputLengthFunctionCall(operand);
+ return false;
+ }
default:
UNREACHABLE();
}
diff --git a/src/compiler/translator/ShaderStorageBlockFunctionHLSL.cpp b/src/compiler/translator/ShaderStorageBlockFunctionHLSL.cpp
index de59747..090292e 100644
--- a/src/compiler/translator/ShaderStorageBlockFunctionHLSL.cpp
+++ b/src/compiler/translator/ShaderStorageBlockFunctionHLSL.cpp
@@ -189,6 +189,15 @@
}
}
+// static
+void ShaderStorageBlockFunctionHLSL::OutputSSBOLengthFunctionBody(TInfoSinkBase &out,
+ int unsizedArrayStride)
+{
+ out << " uint dim = 0;\n";
+ out << " buffer.GetDimensions(dim);\n";
+ out << " return int((dim - loc)/uint(" << unsizedArrayStride << "));\n";
+}
+
bool ShaderStorageBlockFunctionHLSL::ShaderStorageBlockFunction::operator<(
const ShaderStorageBlockFunction &rhs) const
{
@@ -201,11 +210,30 @@
TLayoutBlockStorage storage,
bool rowMajor,
int matrixStride,
+ int unsizedArrayStride,
TIntermSwizzle *swizzleNode)
{
ShaderStorageBlockFunction ssboFunction;
- ssboFunction.typeString = TypeString(type);
ssboFunction.method = method;
+ switch (method)
+ {
+ case SSBOMethod::LOAD:
+ ssboFunction.functionName = "_Load_";
+ break;
+ case SSBOMethod::STORE:
+ ssboFunction.functionName = "_Store_";
+ break;
+ case SSBOMethod::LENGTH:
+ ssboFunction.unsizedArrayStride = unsizedArrayStride;
+ ssboFunction.functionName = "_Length_" + str(unsizedArrayStride);
+ mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
+ return ssboFunction.functionName;
+ default:
+ UNREACHABLE();
+ }
+
+ ssboFunction.typeString = TypeString(type);
+ ssboFunction.functionName += ssboFunction.typeString;
ssboFunction.type = type;
if (swizzleNode != nullptr)
{
@@ -230,20 +258,7 @@
}
ssboFunction.rowMajor = rowMajor;
ssboFunction.matrixStride = matrixStride;
- ssboFunction.functionName =
- TString(getBlockStorageString(storage)) + "_" + ssboFunction.typeString;
-
- switch (method)
- {
- case SSBOMethod::LOAD:
- ssboFunction.functionName += "_Load";
- break;
- case SSBOMethod::STORE:
- ssboFunction.functionName += "_Store";
- break;
- default:
- UNREACHABLE();
- }
+ ssboFunction.functionName += "_" + TString(getBlockStorageString(storage));
if (rowMajor)
{
@@ -291,7 +306,7 @@
out << "{\n";
OutputSSBOLoadFunctionBody(out, ssboFunction);
}
- else
+ else if (ssboFunction.method == SSBOMethod::STORE)
{
// Function header
out << "void " << ssboFunction.functionName << "(RWByteAddressBuffer buffer, uint loc, "
@@ -299,6 +314,14 @@
out << "{\n";
OutputSSBOStoreFunctionBody(out, ssboFunction);
}
+ else
+ {
+ ASSERT(ssboFunction.method == SSBOMethod::LENGTH);
+ out << "int " << ssboFunction.functionName
+ << "(RWByteAddressBuffer buffer, uint loc)\n";
+ out << "{\n";
+ OutputSSBOLengthFunctionBody(out, ssboFunction.unsizedArrayStride);
+ }
out << "}\n"
"\n";
diff --git a/src/compiler/translator/ShaderStorageBlockFunctionHLSL.h b/src/compiler/translator/ShaderStorageBlockFunctionHLSL.h
index d9e603d..7dba673 100644
--- a/src/compiler/translator/ShaderStorageBlockFunctionHLSL.h
+++ b/src/compiler/translator/ShaderStorageBlockFunctionHLSL.h
@@ -38,7 +38,8 @@
enum class SSBOMethod
{
LOAD,
- STORE
+ STORE,
+ LENGTH
};
class ShaderStorageBlockFunctionHLSL final : angle::NonCopyable
@@ -49,6 +50,7 @@
TLayoutBlockStorage storage,
bool rowMajor,
int matrixStride,
+ int unsizedArrayStride,
TIntermSwizzle *node);
void shaderStorageBlockFunctionHeader(TInfoSinkBase &out);
@@ -63,14 +65,16 @@
TType type;
bool rowMajor;
int matrixStride;
+ int unsizedArrayStride;
TVector<int> swizzleOffsets;
bool isDefaultSwizzle;
};
static void OutputSSBOLoadFunctionBody(TInfoSinkBase &out,
- const ShaderStorageBlockFunction &imageFunction);
+ const ShaderStorageBlockFunction &ssboFunction);
static void OutputSSBOStoreFunctionBody(TInfoSinkBase &out,
- const ShaderStorageBlockFunction &imageFunction);
+ const ShaderStorageBlockFunction &ssboFunction);
+ static void OutputSSBOLengthFunctionBody(TInfoSinkBase &out, int unsizedArrayStride);
using ShaderStorageBlockFunctionSet = std::set<ShaderStorageBlockFunction>;
ShaderStorageBlockFunctionSet mRegisteredShaderStorageBlockFunctions;
};
diff --git a/src/compiler/translator/ShaderStorageBlockOutputHLSL.cpp b/src/compiler/translator/ShaderStorageBlockOutputHLSL.cpp
index 323ece3..9a9bd62 100644
--- a/src/compiler/translator/ShaderStorageBlockOutputHLSL.cpp
+++ b/src/compiler/translator/ShaderStorageBlockOutputHLSL.cpp
@@ -87,8 +87,10 @@
}
// It's possible that the current type has lost the original layout information. So we should pass
-// the right layout information to GetMatrixStride.
-unsigned int GetMatrixStride(const TType &type, TLayoutBlockStorage storage, bool rowMajor)
+// the right layout information to GetBlockMemberInfoByType.
+const BlockMemberInfo GetBlockMemberInfoByType(const TType &type,
+ TLayoutBlockStorage storage,
+ bool rowMajor)
{
sh::Std140BlockEncoder std140Encoder;
sh::Std430BlockEncoder std430Encoder;
@@ -114,9 +116,7 @@
{
arraySizes.assign(typeArraySizes->begin(), typeArraySizes->end());
}
- const BlockMemberInfo &memberInfo =
- encoder->encodeType(GLVariableType(type), arraySizes, rowMajor);
- return memberInfo.matrixStride;
+ return encoder->encodeType(GLVariableType(type), arraySizes, rowMajor);
}
const TField *GetFieldMemberInShaderStorageBlock(const TInterfaceBlock *interfaceBlock,
@@ -299,7 +299,7 @@
: TIntermTraverser(true, true, true, symbolTable),
mMatrixStride(0),
mRowMajor(false),
- mIsLoadFunctionCall(false),
+ mLocationAsTheLastArgument(false),
mOutputHLSL(outputHLSL),
mResourcesHLSL(resourcesHLSL)
{
@@ -313,16 +313,22 @@
void ShaderStorageBlockOutputHLSL::outputStoreFunctionCallPrefix(TIntermTyped *node)
{
- mIsLoadFunctionCall = false;
+ mLocationAsTheLastArgument = false;
traverseSSBOAccess(node, SSBOMethod::STORE);
}
void ShaderStorageBlockOutputHLSL::outputLoadFunctionCall(TIntermTyped *node)
{
- mIsLoadFunctionCall = true;
+ mLocationAsTheLastArgument = true;
traverseSSBOAccess(node, SSBOMethod::LOAD);
}
+void ShaderStorageBlockOutputHLSL::outputLengthFunctionCall(TIntermTyped *node)
+{
+ mLocationAsTheLastArgument = true;
+ traverseSSBOAccess(node, SSBOMethod::LENGTH);
+}
+
// Note that we must calculate the matrix stride here instead of ShaderStorageBlockFunctionHLSL.
// It's because that if the current node's type is a vector which comes from a matrix, we will
// lose the matrix type info once we enter ShaderStorageBlockFunctionHLSL.
@@ -332,7 +338,7 @@
{
if (node->getType().isMatrix())
{
- mMatrixStride = GetMatrixStride(node->getType(), storage, rowMajor);
+ mMatrixStride = GetBlockMemberInfoByType(node->getType(), storage, rowMajor).matrixStride;
mRowMajor = rowMajor;
return;
}
@@ -366,10 +372,17 @@
TLayoutBlockStorage storage;
bool rowMajor;
GetBlockLayoutInfo(node, false, &storage, &rowMajor);
+ int unsizedArrayStride = 0;
+ if (node->getType().isUnsizedArray())
+ {
+ unsizedArrayStride =
+ GetBlockMemberInfoByType(node->getType(), storage, rowMajor).arrayStride;
+ }
setMatrixStride(node, storage, rowMajor);
const TString &functionName = mSSBOFunctionHLSL->registerShaderStorageBlockFunction(
- node->getType(), method, storage, mRowMajor, mMatrixStride, node->getAsSwizzleNode());
+ node->getType(), method, storage, mRowMajor, mMatrixStride, unsizedArrayStride,
+ node->getAsSwizzleNode());
TInfoSinkBase &out = mOutputHLSL->getInfoSink();
out << functionName;
out << "(";
@@ -488,7 +501,7 @@
TInfoSinkBase &out = mOutputHLSL->getInfoSink();
// TODO(jiajia.qin@intel.com): add swizzle process if the swizzle node is not the last node
// of ssbo access chain. Such as, data.xy[0]
- if (mIsLoadFunctionCall && isEndOfSSBOAccessChain())
+ if (mLocationAsTheLastArgument && isEndOfSSBOAccessChain())
{
out << ")";
}
@@ -657,7 +670,7 @@
{
out << ")";
}
- if (mIsLoadFunctionCall && isEndOfSSBOAccessChain())
+ if (mLocationAsTheLastArgument && isEndOfSSBOAccessChain())
{
out << ")";
}
@@ -683,7 +696,7 @@
out << " * (";
}
}
- if (mIsLoadFunctionCall && isEndOfSSBOAccessChain())
+ if (mLocationAsTheLastArgument && isEndOfSSBOAccessChain())
{
out << ")";
}
diff --git a/src/compiler/translator/ShaderStorageBlockOutputHLSL.h b/src/compiler/translator/ShaderStorageBlockOutputHLSL.h
index a44f173..527698f 100644
--- a/src/compiler/translator/ShaderStorageBlockOutputHLSL.h
+++ b/src/compiler/translator/ShaderStorageBlockOutputHLSL.h
@@ -47,8 +47,10 @@
// calling this, ", <stored value>)" should be written to the output stream to complete the
// function call.
void outputStoreFunctionCallPrefix(TIntermTyped *node);
- // This writes the funciton call to load a SSBO value to the output stream.
+ // This writes the function call to load a SSBO value to the output stream.
void outputLoadFunctionCall(TIntermTyped *node);
+ // This writes the function call to get the lengh of unsized array member of SSBO.
+ void outputLengthFunctionCall(TIntermTyped *node);
void writeShaderStorageBlocksHeader(TInfoSinkBase &out) const;
@@ -71,7 +73,7 @@
int mMatrixStride;
bool mRowMajor;
- bool mIsLoadFunctionCall;
+ bool mLocationAsTheLastArgument;
OutputHLSL *mOutputHLSL;
ShaderStorageBlockFunctionHLSL *mSSBOFunctionHLSL;
ResourcesHLSL *mResourcesHLSL;