Commit fa886975 by Olli Etuaho Committed by Commit Bot

Fix handling array constructor statements in HLSL output

Array constructors that are used as a statement by themselves need to be pruned from the AST before writing HLSL output. This fixes an assert in OutputHLSL. BUG=angleproject:2307 TEST=angle_unittests Change-Id: Ib49461a4be173f3856f5a264ac0af8d818a61798 Reviewed-on: https://chromium-review.googlesource.com/874691 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent 2c9cc8b6
...@@ -230,6 +230,8 @@ ...@@ -230,6 +230,8 @@
'compiler/translator/RemoveSwitchFallThrough.h', 'compiler/translator/RemoveSwitchFallThrough.h',
'compiler/translator/RewriteElseBlocks.cpp', 'compiler/translator/RewriteElseBlocks.cpp',
'compiler/translator/RewriteElseBlocks.h', 'compiler/translator/RewriteElseBlocks.h',
'compiler/translator/SeparateArrayConstructorStatements.cpp',
'compiler/translator/SeparateArrayConstructorStatements.h',
'compiler/translator/SeparateArrayInitialization.cpp', 'compiler/translator/SeparateArrayInitialization.cpp',
'compiler/translator/SeparateArrayInitialization.h', 'compiler/translator/SeparateArrayInitialization.h',
'compiler/translator/SeparateExpressionsReturningArrays.cpp', 'compiler/translator/SeparateExpressionsReturningArrays.cpp',
......
//
// Copyright (c) 2018 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// SeparateArrayConstructorStatements splits statements that are array constructors and drops all of
// their constant arguments. For example, a statement like:
// int[2](0, i++);
// Will be changed to:
// i++;
#include "compiler/translator/SeparateArrayConstructorStatements.h"
#include "compiler/translator/IntermTraverse.h"
namespace sh
{
namespace
{
void SplitConstructorArgs(const TIntermSequence &originalArgs, TIntermSequence *argsOut)
{
for (TIntermNode *arg : originalArgs)
{
TIntermTyped *argTyped = arg->getAsTyped();
if (argTyped->hasSideEffects())
{
TIntermAggregate *argAggregate = argTyped->getAsAggregate();
if (argTyped->isArray() && argAggregate && argAggregate->isConstructor())
{
SplitConstructorArgs(*argAggregate->getSequence(), argsOut);
}
else
{
argsOut->push_back(argTyped);
}
}
}
}
class SeparateArrayConstructorStatementsTraverser : public TIntermTraverser
{
public:
SeparateArrayConstructorStatementsTraverser();
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
};
SeparateArrayConstructorStatementsTraverser::SeparateArrayConstructorStatementsTraverser()
: TIntermTraverser(true, false, false)
{
}
bool SeparateArrayConstructorStatementsTraverser::visitAggregate(Visit visit,
TIntermAggregate *node)
{
TIntermBlock *parentAsBlock = getParentNode()->getAsBlock();
if (!parentAsBlock)
{
return false;
}
if (!node->isArray() || !node->isConstructor())
{
return false;
}
TIntermSequence constructorArgs;
SplitConstructorArgs(*node->getSequence(), &constructorArgs);
mMultiReplacements.push_back(
NodeReplaceWithMultipleEntry(parentAsBlock, node, constructorArgs));
return false;
}
} // namespace
void SeparateArrayConstructorStatements(TIntermBlock *root)
{
SeparateArrayConstructorStatementsTraverser traverser;
root->traverse(&traverser);
traverser.updateTree();
}
} // namespace sh
//
// Copyright (c) 2018 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// SeparateArrayConstructorStatements splits statements that are array constructors and drops all of
// their constant arguments. For example, a statement like:
// int[2](0, i++);
// Will be changed to:
// i++;
#ifndef COMPILER_TRANSLATOR_SEPARATEARRAYCONSTRUCTORSTATEMENTS_H_
#define COMPILER_TRANSLATOR_SEPARATEARRAYCONSTRUCTORSTATEMENTS_H_
namespace sh
{
class TIntermBlock;
void SeparateArrayConstructorStatements(TIntermBlock *root);
} // namespace sh
#endif // COMPILER_TRANSLATOR_SEPARATEARRAYCONSTRUCTORSTATEMENTS_H_
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "compiler/translator/RewriteElseBlocks.h" #include "compiler/translator/RewriteElseBlocks.h"
#include "compiler/translator/RewriteTexelFetchOffset.h" #include "compiler/translator/RewriteTexelFetchOffset.h"
#include "compiler/translator/RewriteUnaryMinusOperatorInt.h" #include "compiler/translator/RewriteUnaryMinusOperatorInt.h"
#include "compiler/translator/SeparateArrayConstructorStatements.h"
#include "compiler/translator/SeparateArrayInitialization.h" #include "compiler/translator/SeparateArrayInitialization.h"
#include "compiler/translator/SeparateDeclarations.h" #include "compiler/translator/SeparateDeclarations.h"
#include "compiler/translator/SeparateExpressionsReturningArrays.h" #include "compiler/translator/SeparateExpressionsReturningArrays.h"
...@@ -61,6 +62,8 @@ void TranslatorHLSL::translate(TIntermBlock *root, ...@@ -61,6 +62,8 @@ void TranslatorHLSL::translate(TIntermBlock *root,
// Note that SeparateDeclarations needs to be run before UnfoldShortCircuitToIf. // Note that SeparateDeclarations needs to be run before UnfoldShortCircuitToIf.
UnfoldShortCircuitToIf(root, &getSymbolTable()); UnfoldShortCircuitToIf(root, &getSymbolTable());
SeparateArrayConstructorStatements(root);
SeparateExpressionsReturningArrays(root, &getSymbolTable()); SeparateExpressionsReturningArrays(root, &getSymbolTable());
// Note that SeparateDeclarations needs to be run before SeparateArrayInitialization. // Note that SeparateDeclarations needs to be run before SeparateArrayInitialization.
......
...@@ -72,3 +72,46 @@ TEST_F(HLSL30VertexOutputTest, RewriteElseBlockReturningStruct) ...@@ -72,3 +72,46 @@ TEST_F(HLSL30VertexOutputTest, RewriteElseBlockReturningStruct)
EXPECT_FALSE(foundInCode("(foo)")); EXPECT_FALSE(foundInCode("(foo)"));
EXPECT_FALSE(foundInCode(" foo")); EXPECT_FALSE(foundInCode(" foo"));
} }
// Test that having an array constructor as a statement doesn't trigger an assert in HLSL output.
// This test has a constant array constructor statement.
TEST_F(HLSLOutputTest, ConstArrayConstructorStatement)
{
const std::string &shaderString =
R"(#version 300 es
void main()
{
int[1](0);
})";
compile(shaderString);
}
// Test that having an array constructor as a statement doesn't trigger an assert in HLSL output.
TEST_F(HLSLOutputTest, ArrayConstructorStatement)
{
const std::string &shaderString =
R"(#version 300 es
precision mediump float;
out vec4 outColor;
void main()
{
outColor = vec4(0.0, 0.0, 0.0, 1.0);
float[1](outColor[1]++);
})";
compile(shaderString);
}
// Test an array of arrays constructor as a statement.
TEST_F(HLSLOutputTest, ArrayOfArraysStatement)
{
const std::string &shaderString =
R"(#version 310 es
precision mediump float;
out vec4 outColor;
void main()
{
outColor = vec4(0.0, 0.0, 0.0, 1.0);
float[2][2](float[2](outColor[1]++, 0.0), float[2](1.0, 2.0));
})";
compile(shaderString);
}
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