Remove dynamic indexing of matrices and vectors in HLSL
HLSL doesn't support dynamic indexing of matrices and vectors, so replace
that with helper functions that unroll dynamic indexing into switch/case
and static indexing.
Both the indexed vector/matrix expression and the index may have side
effects, and these will be evaluated correctly. If necessary, index
expressions that have side effects will be written to a temporary
variable that will replace the index.
Besides dEQP tests, this change is tested by a WebGL 2 conformance test.
In the case that a dynamic index is out-of-range, the base ESSL 3.00 spec
allows undefined behavior. KHR_robust_buffer_access_behavior adds the
requirement that program termination should not occur and that
out-of-range reads must return either a value from the active program's
memory or zero, and out-of-range writes should only affect the active
program's memory or do nothing. This patch clamps out-of-range indices so
that either the first or last item of the matrix/vector is accessed.
The code is not transformed in case the it fits within the limited subset
of ESSL 1.00 given in Appendix A of the spec. If the code isn't within
the restricted subset, even ESSL 1.00 shaders may require this
workaround.
BUG=angleproject:1116
TEST=dEQP-GLES3.functional.shaders.indexing.* (all pass after change)
WebGL 2 conformance tests (glsl3/vector-dynamic-indexing.html)
Change-Id: I024722ef4ca1e14d5ad47fdc540397e18858bed6
Reviewed-on: https://chromium-review.googlesource.com/290515
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
index 187ad14..e9665f9 100644
--- a/src/compiler/translator/IntermNode.cpp
+++ b/src/compiler/translator/IntermNode.cpp
@@ -311,17 +311,13 @@
bool TIntermAggregate::insertChildNodes(TIntermSequence::size_type position, TIntermSequence insertions)
{
- TIntermSequence::size_type itPosition = 0;
- for (auto it = mSequence.begin(); it < mSequence.end(); ++it)
+ if (position > mSequence.size())
{
- if (itPosition == position)
- {
- mSequence.insert(it, insertions.begin(), insertions.end());
- return true;
- }
- ++itPosition;
+ return false;
}
- return false;
+ auto it = mSequence.begin() + position;
+ mSequence.insert(it, insertions.begin(), insertions.end());
+ return true;
}
void TIntermAggregate::setPrecisionFromChildren()
@@ -2550,9 +2546,20 @@
{
const NodeInsertMultipleEntry &insertion = mInsertions[ii];
ASSERT(insertion.parent);
- bool inserted = insertion.parent->insertChildNodes(insertion.position, insertion.insertions);
- ASSERT(inserted);
- UNUSED_ASSERTION_VARIABLE(inserted);
+ if (!insertion.insertionsAfter.empty())
+ {
+ bool inserted = insertion.parent->insertChildNodes(insertion.position + 1,
+ insertion.insertionsAfter);
+ ASSERT(inserted);
+ UNUSED_ASSERTION_VARIABLE(inserted);
+ }
+ if (!insertion.insertionsBefore.empty())
+ {
+ bool inserted =
+ insertion.parent->insertChildNodes(insertion.position, insertion.insertionsBefore);
+ ASSERT(inserted);
+ UNUSED_ASSERTION_VARIABLE(inserted);
+ }
}
for (size_t ii = 0; ii < mReplacements.size(); ++ii)
{