Commit 311e8086 by Qin Jiajia Committed by Commit Bot

Do struct mapping under conditions

Struct mapping consumes lots of time when the array lengh is very large. And it's done unconditionally. This CL does struct mapping only if it's a struct assignment or passing the struct to a function. In the next step, we can use a function to do struct mapping instead of struct array initialization. Bug: angleproject:2967 Change-Id: Ie5a74fa05dbc0255ad664d6265dbb880a624f01e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1612978Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jiajia Qin <jiajia.qin@intel.com>
parent 6ddb7768
...@@ -173,6 +173,37 @@ TReferencedBlock::TReferencedBlock(const TInterfaceBlock *aBlock, ...@@ -173,6 +173,37 @@ TReferencedBlock::TReferencedBlock(const TInterfaceBlock *aBlock,
: block(aBlock), instanceVariable(aInstanceVariable) : block(aBlock), instanceVariable(aInstanceVariable)
{} {}
bool OutputHLSL::needStructMapping(TIntermTyped *node)
{
for (unsigned int n = 0u; getAncestorNode(n) != nullptr; ++n)
{
TIntermNode *ancestor = getAncestorNode(n);
const TIntermBinary *ancestorBinary = ancestor->getAsBinaryNode();
if (ancestorBinary && ancestorBinary->getLeft()->getBasicType() == EbtStruct)
{
switch (ancestorBinary->getOp())
{
case EOpIndexDirectStruct:
case EOpIndexDirect:
case EOpIndexIndirect:
break;
default:
return true;
}
}
else
{
const TIntermAggregate *ancestorAggregate = ancestor->getAsAggregate();
if (ancestorAggregate)
{
return true;
}
return false;
}
}
return true;
}
void OutputHLSL::writeFloat(TInfoSinkBase &out, float f) void OutputHLSL::writeFloat(TInfoSinkBase &out, float f)
{ {
// This is known not to work for NaN on all drivers but make the best effort to output NaNs // This is known not to work for NaN on all drivers but make the best effort to output NaNs
...@@ -253,7 +284,8 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType, ...@@ -253,7 +284,8 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType,
mMaxDualSourceDrawBuffers(maxDualSourceDrawBuffers), mMaxDualSourceDrawBuffers(maxDualSourceDrawBuffers),
mCurrentFunctionMetadata(nullptr), mCurrentFunctionMetadata(nullptr),
mWorkGroupSize(workGroupSize), mWorkGroupSize(workGroupSize),
mPerfDiagnostics(perfDiagnostics) mPerfDiagnostics(perfDiagnostics),
mNeedStructMapping(false)
{ {
mUsesFragColor = false; mUsesFragColor = false;
mUsesFragData = false; mUsesFragData = false;
...@@ -564,7 +596,11 @@ void OutputHLSL::header(TInfoSinkBase &out, ...@@ -564,7 +596,11 @@ void OutputHLSL::header(TInfoSinkBase &out,
const std::vector<MappedStruct> &std140Structs, const std::vector<MappedStruct> &std140Structs,
const BuiltInFunctionEmulator *builtInFunctionEmulator) const const BuiltInFunctionEmulator *builtInFunctionEmulator) const
{ {
TString mappedStructs = generateStructMapping(std140Structs); TString mappedStructs;
if (mNeedStructMapping)
{
mappedStructs = generateStructMapping(std140Structs);
}
out << mStructureHLSL->structsHeader(); out << mStructureHLSL->structsHeader();
...@@ -1054,8 +1090,10 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node) ...@@ -1054,8 +1090,10 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node)
TInfoSinkBase &out = getInfoSink(); TInfoSinkBase &out = getInfoSink();
// Handle accessing std140 structs by value // Handle accessing std140 structs by value
if (IsInStd140UniformBlock(node) && node->getBasicType() == EbtStruct) if (IsInStd140UniformBlock(node) && node->getBasicType() == EbtStruct &&
needStructMapping(node))
{ {
mNeedStructMapping = true;
out << "map"; out << "map";
} }
...@@ -1594,10 +1632,12 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) ...@@ -1594,10 +1632,12 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
case EOpIndexDirectInterfaceBlock: case EOpIndexDirectInterfaceBlock:
{ {
ASSERT(!IsInShaderStorageBlock(node->getLeft())); ASSERT(!IsInShaderStorageBlock(node->getLeft()));
bool structInStd140UniformBlock = bool structInStd140UniformBlock = node->getBasicType() == EbtStruct &&
node->getBasicType() == EbtStruct && IsInStd140UniformBlock(node->getLeft()); IsInStd140UniformBlock(node->getLeft()) &&
needStructMapping(node);
if (visit == PreVisit && structInStd140UniformBlock) if (visit == PreVisit && structInStd140UniformBlock)
{ {
mNeedStructMapping = true;
out << "map"; out << "map";
} }
if (visit == InVisit) if (visit == InVisit)
......
...@@ -267,7 +267,12 @@ class OutputHLSL : public TIntermTraverser ...@@ -267,7 +267,12 @@ class OutputHLSL : public TIntermTraverser
TString generateStructMapping(const std::vector<MappedStruct> &std140Structs) const; TString generateStructMapping(const std::vector<MappedStruct> &std140Structs) const;
ImmutableString samplerNamePrefixFromStruct(TIntermTyped *node); ImmutableString samplerNamePrefixFromStruct(TIntermTyped *node);
bool ancestorEvaluatesToSamplerInStruct(); bool ancestorEvaluatesToSamplerInStruct();
// We need to do struct mapping when pass the struct to a function or copy the struct via
// assignment.
bool needStructMapping(TIntermTyped *node);
ShaderStorageBlockOutputHLSL *mSSBOOutputHLSL; ShaderStorageBlockOutputHLSL *mSSBOOutputHLSL;
bool mNeedStructMapping;
}; };
} // namespace sh } // namespace sh
......
...@@ -2369,6 +2369,38 @@ void main() ...@@ -2369,6 +2369,38 @@ void main()
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
// Test that a large struct array in std140 uniform block won't consume too much time.
TEST_P(ComputeShaderTest, LargeStructArraySize)
{
constexpr char kComputeShaderSource[] = R"(#version 310 es
layout(local_size_x=8) in;
precision mediump float;
struct InstancingData
{
mat4 transformation;
};
#define MAX_INSTANCE_COUNT 800
layout(std140) uniform InstanceBlock
{
InstancingData instances[MAX_INSTANCE_COUNT];
};
layout(std140, binding = 1) buffer blockB {
mat4 v[];
} instanceB;
void main()
{
instanceB.v[gl_GlobalInvocationID.x] = instances[gl_GlobalInvocationID.x].transformation;
})";
ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
EXPECT_GL_NO_ERROR();
}
// Check that it is not possible to create a compute shader when the context does not support ES // Check that it is not possible to create a compute shader when the context does not support ES
// 3.10 // 3.10
TEST_P(ComputeShaderTestES3, NotSupported) TEST_P(ComputeShaderTestES3, NotSupported)
......
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