Bug 827106 - Cherry-pick ANGLE r1638 - r=jgilbert

This commit is contained in:
Benoit Jacob 2013-02-05 20:53:38 -05:00
Родитель 7235347b03
Коммит 17599d2cd7
17 изменённых файлов: 698 добавлений и 5 удалений

Просмотреть файл

@ -12,6 +12,7 @@ TransGaming Inc.
3DLabs Inc. Ltd.
Adobe Systems Inc.
Apple Inc.
Autodesk, Inc.
Cloud Party, Inc.
Intel Corporation

Просмотреть файл

@ -56,6 +56,7 @@ DEFINES += -DCOMPILER_IMPLEMENTATION
VPATH += $(srcdir)/src/compiler
# src/compiler:
CPPSRCS += \
ArrayBoundsClamper.cpp \
BuiltInFunctionEmulator.cpp \
Compiler.cpp \
compiler_debug.cpp \

Просмотреть файл

@ -26,6 +26,10 @@ In this order:
Adds emulation for faceforward(float,float,float), which is needed to
prevent crashing on Mac+Intel. See bug 771406.
angle-r1638.patch
Adds uniform array index clamping on non-Windows platforms.
Windows would require r1719, r1733, r1734.
In addition to these patches, the Makefile.in files are ours, they're not present in
upsteam ANGLE. Therefore, changes made to the Makefile.in files should not be stored
in the local .patch files.

475
gfx/angle/angle-r1638.patch Normal file
Просмотреть файл

@ -0,0 +1,475 @@
# HG changeset patch
# Parent faf255e4400222ee23c29ddcc76fb3dce56145f4
diff --git a/gfx/angle/AUTHORS b/gfx/angle/AUTHORS
--- a/gfx/angle/AUTHORS
+++ b/gfx/angle/AUTHORS
@@ -7,16 +7,17 @@
# Name or Organization
# Email addresses for individuals are tracked elsewhere to avoid spam.
Google Inc.
TransGaming Inc.
3DLabs Inc. Ltd.
Adobe Systems Inc.
+Apple Inc.
Autodesk, Inc.
Cloud Party, Inc.
Intel Corporation
Mozilla Corporation
Turbulenz
Klarälvdalens Datakonsult AB
Jacek Caban
diff --git a/gfx/angle/Makefile.in b/gfx/angle/Makefile.in
--- a/gfx/angle/Makefile.in
+++ b/gfx/angle/Makefile.in
@@ -51,16 +51,17 @@ LOCAL_INCLUDES += \
-I$(srcdir)/include/KHR \
-I$(srcdir)/src
DEFINES += -DCOMPILER_IMPLEMENTATION
VPATH += $(srcdir)/src/compiler
# src/compiler:
CPPSRCS += \
+ ArrayBoundsClamper.cpp \
BuiltInFunctionEmulator.cpp \
Compiler.cpp \
compiler_debug.cpp \
DetectRecursion.cpp \
Diagnostics.cpp \
DirectiveHandler.cpp \
ForLoopUnroll.cpp \
glslang_lex.cpp \
diff --git a/gfx/angle/README.mozilla b/gfx/angle/README.mozilla
--- a/gfx/angle/README.mozilla
+++ b/gfx/angle/README.mozilla
@@ -21,16 +21,20 @@ In this order:
angle-long-ident-spooky-hash.patch:
Use Spooky Hash for long identifier hashing. See bug 676071.
angle-faceforward-emu.patch:
Adds emulation for faceforward(float,float,float), which is needed to
prevent crashing on Mac+Intel. See bug 771406.
+ angle-r1638.patch
+ Adds uniform array index clamping on non-Windows platforms.
+ Windows would require r1719, r1733, r1734.
+
In addition to these patches, the Makefile.in files are ours, they're not present in
upsteam ANGLE. Therefore, changes made to the Makefile.in files should not be stored
in the local .patch files.
== How to do a clean-slate upgrade ==
1. Backup our moz-specific files:
README.mozilla
diff --git a/gfx/angle/include/GLSLANG/ShaderLang.h b/gfx/angle/include/GLSLANG/ShaderLang.h
--- a/gfx/angle/include/GLSLANG/ShaderLang.h
+++ b/gfx/angle/include/GLSLANG/ShaderLang.h
@@ -145,17 +145,23 @@ typedef enum {
// restrictions on fragment shaders.
// This flag only has an effect if all of the following are true:
// - The shader spec is SH_WEBGL_SPEC.
// - The compile options contain the SH_TIMING_RESTRICTIONS flag.
// - The shader type is SH_FRAGMENT_SHADER.
SH_DEPENDENCY_GRAPH = 0x0400,
// Enforce the GLSL 1.017 Appendix A section 7 packing restrictions.
- SH_ENFORCE_PACKING_RESTRICTIONS = 0x0800
+ SH_ENFORCE_PACKING_RESTRICTIONS = 0x0800,
+
+ // This flag ensures all indirect (expression-based) array indexing
+ // is clamped to the bounds of the array. This ensures, for example,
+ // that you cannot read off the end of a uniform, whether an array
+ // vec234, or mat234 type.
+ SH_CLAMP_INDIRECT_ARRAY_BOUNDS = 0x1000
} ShCompileOptions;
//
// Driver must call this first, once, before doing any other
// compiler operations.
// If the function succeeds, the return value is nonzero, else zero.
//
COMPILER_EXPORT int ShInitialize();
diff --git a/gfx/angle/src/build_angle.gypi b/gfx/angle/src/build_angle.gypi
--- a/gfx/angle/src/build_angle.gypi
+++ b/gfx/angle/src/build_angle.gypi
@@ -54,16 +54,18 @@
'include_dirs': [
'.',
'../include',
],
'defines': [
'COMPILER_IMPLEMENTATION',
],
'sources': [
+ 'compiler/ArrayBoundsClamper.cpp',
+ 'compiler/ArrayBoundsClamper.h',
'compiler/BaseTypes.h',
'compiler/BuiltInFunctionEmulator.cpp',
'compiler/BuiltInFunctionEmulator.h',
'compiler/Common.h',
'compiler/Compiler.cpp',
'compiler/ConstantUnion.h',
'compiler/debug.cpp',
'compiler/debug.h',
diff --git a/gfx/angle/src/compiler/Compiler.cpp b/gfx/angle/src/compiler/Compiler.cpp
--- a/gfx/angle/src/compiler/Compiler.cpp
+++ b/gfx/angle/src/compiler/Compiler.cpp
@@ -1,14 +1,15 @@
//
// Copyright (c) 2002-2012 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.
//
+#include "compiler/ArrayBoundsClamper.h"
#include "compiler/BuiltInFunctionEmulator.h"
#include "compiler/DetectRecursion.h"
#include "compiler/ForLoopUnroll.h"
#include "compiler/Initialize.h"
#include "compiler/InitializeParseContext.h"
#include "compiler/MapLongVariableNames.h"
#include "compiler/ParseHelper.h"
#include "compiler/RenameFunction.h"
@@ -187,16 +188,20 @@ bool TCompiler::compile(const char* cons
// Unroll for-loop markup needs to happen after validateLimitations pass.
if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX))
ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling(root);
// Built-in function emulation needs to happen after validateLimitations pass.
if (success && (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS))
builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root);
+ // Clamping uniform array bounds needs to happen after validateLimitations pass.
+ if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
+ arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
+
// Call mapLongVariableNames() before collectAttribsUniforms() so in
// collectAttribsUniforms() we already have the mapped symbol names and
// we could composite mapped and original variable names.
// Also, if we hash all the names, then no need to do this for long names.
if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) && hashFunction == NULL)
mapLongVariableNames(root);
if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) {
@@ -232,16 +237,17 @@ bool TCompiler::InitBuiltInSymbolTable(c
builtIns.initialize(shaderType, shaderSpec, resources);
return InitializeSymbolTable(builtIns.getBuiltInStrings(),
shaderType, shaderSpec, resources, infoSink, symbolTable);
}
void TCompiler::clearResults()
{
+ arrayBoundsClamper.Cleanup();
infoSink.info.erase();
infoSink.obj.erase();
infoSink.debug.erase();
attribs.clear();
uniforms.clear();
builtInFunctionEmulator.Cleanup();
@@ -348,8 +354,14 @@ const TExtensionBehavior& TCompiler::get
{
return extensionBehavior;
}
const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const
{
return builtInFunctionEmulator;
}
+
+const ArrayBoundsClamper& TCompiler::getArrayBoundsClamper() const
+{
+ return arrayBoundsClamper;
+}
+
diff --git a/gfx/angle/src/compiler/OutputGLSLBase.cpp b/gfx/angle/src/compiler/OutputGLSLBase.cpp
--- a/gfx/angle/src/compiler/OutputGLSLBase.cpp
+++ b/gfx/angle/src/compiler/OutputGLSLBase.cpp
@@ -207,18 +207,47 @@ bool TOutputGLSLBase::visitBinary(Visit
case EOpVectorTimesMatrixAssign:
case EOpVectorTimesScalarAssign:
case EOpMatrixTimesScalarAssign:
case EOpMatrixTimesMatrixAssign:
writeTriplet(visit, "(", " *= ", ")");
break;
case EOpIndexDirect:
+ writeTriplet(visit, NULL, "[", "]");
+ break;
case EOpIndexIndirect:
- writeTriplet(visit, NULL, "[", "]");
+ if (node->getAddIndexClamp())
+ {
+ if (visit == InVisit)
+ {
+ out << "[webgl_int_clamp(";
+ }
+ else if (visit == PostVisit)
+ {
+ int maxSize;
+ TIntermTyped *left = node->getLeft();
+ TType leftType = left->getType();
+
+ if (left->isArray())
+ {
+ // The shader will fail validation if the array length is not > 0.
+ maxSize = leftType.getArraySize() - 1;
+ }
+ else
+ {
+ maxSize = leftType.getNominalSize() - 1;
+ }
+ out << ", 0, " << maxSize << ")]";
+ }
+ }
+ else
+ {
+ writeTriplet(visit, NULL, "[", "]");
+ }
break;
case EOpIndexDirectStruct:
if (visit == InVisit)
{
out << ".";
// TODO(alokp): ASSERT
out << hashName(node->getType().getFieldName());
visitChildren = false;
diff --git a/gfx/angle/src/compiler/ShHandle.h b/gfx/angle/src/compiler/ShHandle.h
--- a/gfx/angle/src/compiler/ShHandle.h
+++ b/gfx/angle/src/compiler/ShHandle.h
@@ -11,16 +11,17 @@
// Machine independent part of the compiler private objects
// sent as ShHandle to the driver.
//
// This should not be included by driver code.
//
#include "GLSLANG/ShaderLang.h"
+#include "compiler/ArrayBoundsClamper.h"
#include "compiler/BuiltInFunctionEmulator.h"
#include "compiler/ExtensionBehavior.h"
#include "compiler/HashNames.h"
#include "compiler/InfoSink.h"
#include "compiler/SymbolTable.h"
#include "compiler/VariableInfo.h"
class LongNameMap;
@@ -101,30 +102,32 @@ protected:
// Returns true if the shader does not use samplers.
bool enforceVertexShaderTimingRestrictions(TIntermNode* root);
// Returns true if the shader does not use sampler dependent values to affect control
// flow or in operations whose time can depend on the input values.
bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph);
// Get built-in extensions with default behavior.
const TExtensionBehavior& getExtensionBehavior() const;
+ const ArrayBoundsClamper& getArrayBoundsClamper() const;
const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const;
private:
ShShaderType shaderType;
ShShaderSpec shaderSpec;
int maxUniformVectors;
// Built-in symbol table for the given language, spec, and resources.
// It is preserved from compile-to-compile.
TSymbolTable symbolTable;
// Built-in extensions with default behavior.
TExtensionBehavior extensionBehavior;
+ ArrayBoundsClamper arrayBoundsClamper;
BuiltInFunctionEmulator builtInFunctionEmulator;
// Results of compilation.
TInfoSink infoSink; // Output sink.
TVariableInfoList attribs; // Active attributes in the compiled shader.
TVariableInfoList uniforms; // Active uniforms in the compiled shader.
// Cached copy of the ref-counted singleton.
diff --git a/gfx/angle/src/compiler/TranslatorESSL.cpp b/gfx/angle/src/compiler/TranslatorESSL.cpp
--- a/gfx/angle/src/compiler/TranslatorESSL.cpp
+++ b/gfx/angle/src/compiler/TranslatorESSL.cpp
@@ -17,16 +17,19 @@ void TranslatorESSL::translate(TIntermNo
// Write built-in extension behaviors.
writeExtensionBehavior();
// Write emulated built-in functions if needed.
getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition(
sink, getShaderType() == SH_FRAGMENT_SHADER);
+ // Write array bounds clamping emulation if needed.
+ getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
+
// Write translated shader.
TOutputESSL outputESSL(sink, getHashFunction(), getNameMap(), getSymbolTable());
root->traverse(&outputESSL);
}
void TranslatorESSL::writeExtensionBehavior() {
TInfoSinkBase& sink = getInfoSink().obj;
const TExtensionBehavior& extensionBehavior = getExtensionBehavior();
diff --git a/gfx/angle/src/compiler/TranslatorGLSL.cpp b/gfx/angle/src/compiler/TranslatorGLSL.cpp
--- a/gfx/angle/src/compiler/TranslatorGLSL.cpp
+++ b/gfx/angle/src/compiler/TranslatorGLSL.cpp
@@ -30,12 +30,15 @@ void TranslatorGLSL::translate(TIntermNo
// Write GLSL version.
writeVersion(getShaderType(), root, sink);
// Write emulated built-in functions if needed.
getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition(
sink, false);
+ // Write array bounds clamping emulation if needed.
+ getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
+
// Write translated shader.
TOutputGLSL outputGLSL(sink, getHashFunction(), getNameMap(), getSymbolTable());
root->traverse(&outputGLSL);
}
diff --git a/gfx/angle/src/compiler/intermOut.cpp b/gfx/angle/src/compiler/intermOut.cpp
--- a/gfx/angle/src/compiler/intermOut.cpp
+++ b/gfx/angle/src/compiler/intermOut.cpp
@@ -37,17 +37,17 @@ protected:
TString TType::getCompleteString() const
{
TStringStream stream;
if (qualifier != EvqTemporary && qualifier != EvqGlobal)
stream << getQualifierString() << " " << getPrecisionString() << " ";
if (array)
- stream << "array of ";
+ stream << "array[" << getArraySize() << "] of ";
if (matrix)
stream << size << "X" << size << " matrix of ";
else if (size > 1)
stream << size << "-component vector of ";
stream << getBasicString();
return stream.str();
}
diff --git a/gfx/angle/src/compiler/intermediate.h b/gfx/angle/src/compiler/intermediate.h
--- a/gfx/angle/src/compiler/intermediate.h
+++ b/gfx/angle/src/compiler/intermediate.h
@@ -386,30 +386,36 @@ protected:
TOperator op;
};
//
// Nodes for all the basic binary math operators.
//
class TIntermBinary : public TIntermOperator {
public:
- TIntermBinary(TOperator o) : TIntermOperator(o) {}
+ TIntermBinary(TOperator o) : TIntermOperator(o), addIndexClamp(false) {}
virtual TIntermBinary* getAsBinaryNode() { return this; }
virtual void traverse(TIntermTraverser*);
void setLeft(TIntermTyped* n) { left = n; }
void setRight(TIntermTyped* n) { right = n; }
TIntermTyped* getLeft() const { return left; }
TIntermTyped* getRight() const { return right; }
bool promote(TInfoSink&);
+ void setAddIndexClamp() { addIndexClamp = true; }
+ bool getAddIndexClamp() { return addIndexClamp; }
+
protected:
TIntermTyped* left;
TIntermTyped* right;
+
+ // If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
+ bool addIndexClamp;
};
//
// Nodes for unary math operators.
//
class TIntermUnary : public TIntermOperator {
public:
TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0), useEmulatedFunction(false) {}
diff --git a/gfx/angle/src/compiler/translator_common.vcxproj b/gfx/angle/src/compiler/translator_common.vcxproj
--- a/gfx/angle/src/compiler/translator_common.vcxproj
+++ b/gfx/angle/src/compiler/translator_common.vcxproj
@@ -133,16 +133,17 @@
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4267;4512;4702;4718;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
+ <ClCompile Include="ArrayBoundsClamper.cpp" />
<ClCompile Include="BuiltInFunctionEmulator.cpp" />
<ClCompile Include="Compiler.cpp" />
<ClCompile Include="debug.cpp" />
<ClCompile Include="DetectRecursion.cpp" />
<ClCompile Include="Diagnostics.cpp" />
<ClCompile Include="DirectiveHandler.cpp" />
<ClCompile Include="ForLoopUnroll.cpp" />
<ClCompile Include="InfoSink.cpp" />
@@ -220,16 +221,17 @@
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</Message>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Outputs)</Outputs>
</CustomBuild>
</ItemGroup>
<ItemGroup>
+ <ClInclude Include="ArrayBoundsClamper.h" />
<ClInclude Include="BaseTypes.h" />
<ClInclude Include="BuiltInFunctionEmulator.h" />
<ClInclude Include="Common.h" />
<ClInclude Include="ConstantUnion.h" />
<ClInclude Include="debug.h" />
<ClInclude Include="DetectRecursion.h" />
<ClInclude Include="Diagnostics.h" />
<ClInclude Include="DirectiveHandler.h" />
@@ -274,9 +276,9 @@
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>true</UseLibraryDependencyInputs>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/gfx/angle/src/libGLESv2/Makefile.in b/gfx/angle/src/libGLESv2/Makefile.in
--- a/gfx/angle/src/libGLESv2/Makefile.in
+++ b/gfx/angle/src/libGLESv2/Makefile.in
@@ -64,16 +64,17 @@ LOCAL_INCLUDES = \
-I$(srcdir)/../../include/KHR \
-I$(srcdir)/..
DEFINES += -DCOMPILER_IMPLEMENTATION
VPATH += $(srcdir)/../compiler
# src/compiler:
CPPSRCS += \
+ ArrayBoundsClamper.cpp \
BuiltInFunctionEmulator.cpp \
Compiler.cpp \
compiler_debug.cpp \
DetectRecursion.cpp \
Diagnostics.cpp \
DirectiveHandler.cpp \
ForLoopUnroll.cpp \
glslang_lex.cpp \

Просмотреть файл

@ -150,7 +150,13 @@ typedef enum {
SH_DEPENDENCY_GRAPH = 0x0400,
// Enforce the GLSL 1.017 Appendix A section 7 packing restrictions.
SH_ENFORCE_PACKING_RESTRICTIONS = 0x0800
SH_ENFORCE_PACKING_RESTRICTIONS = 0x0800,
// This flag ensures all indirect (expression-based) array indexing
// is clamped to the bounds of the array. This ensures, for example,
// that you cannot read off the end of a uniform, whether an array
// vec234, or mat234 type.
SH_CLAMP_INDIRECT_ARRAY_BOUNDS = 0x1000
} ShCompileOptions;
//

Просмотреть файл

@ -59,6 +59,8 @@
'COMPILER_IMPLEMENTATION',
],
'sources': [
'compiler/ArrayBoundsClamper.cpp',
'compiler/ArrayBoundsClamper.h',
'compiler/BaseTypes.h',
'compiler/BuiltInFunctionEmulator.cpp',
'compiler/BuiltInFunctionEmulator.h',

Просмотреть файл

@ -0,0 +1,88 @@
/*
* Copyright (C) 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "compiler/ArrayBoundsClamper.h"
const char* kIntClampBegin = "// BEGIN: Generated code for array bounds clamping\n\n";
const char* kIntClampEnd = "// END: Generated code for array bounds clamping\n\n";
const char* kIntClampDefinition = "int webgl_int_clamp(int value, int minValue, int maxValue) { return ((value < minValue) ? minValue : ((value > maxValue) ? maxValue : value)); }\n\n";
namespace {
class ArrayBoundsClamperMarker : public TIntermTraverser {
public:
ArrayBoundsClamperMarker()
: mNeedsClamp(false)
{
}
virtual bool visitBinary(Visit visit, TIntermBinary* node)
{
if (node->getOp() == EOpIndexIndirect)
{
TIntermTyped* left = node->getLeft();
if (left->isArray() || left->isVector() || left->isMatrix())
{
node->setAddIndexClamp();
mNeedsClamp = true;
}
}
return true;
}
bool GetNeedsClamp() { return mNeedsClamp; }
private:
bool mNeedsClamp;
};
} // anonymous namespace
ArrayBoundsClamper::ArrayBoundsClamper()
: mArrayBoundsClampDefinitionNeeded(false)
{
}
void ArrayBoundsClamper::OutputClampingFunctionDefinition(TInfoSinkBase& out) const
{
if (!mArrayBoundsClampDefinitionNeeded)
{
return;
}
out << kIntClampBegin << kIntClampDefinition << kIntClampEnd;
}
void ArrayBoundsClamper::MarkIndirectArrayBoundsForClamping(TIntermNode* root)
{
ASSERT(root);
ArrayBoundsClamperMarker clamper;
root->traverse(&clamper);
if (clamper.GetNeedsClamp())
{
SetArrayBoundsClampDefinitionNeeded();
}
}

Просмотреть файл

@ -0,0 +1,57 @@
/*
* Copyright (C) 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef COMPILER_ARRAY_BOUNDS_CLAMPER_H_
#define COMPILER_ARRAY_BOUNDS_CLAMPER_H_
#include "GLSLANG/ShaderLang.h"
#include "compiler/InfoSink.h"
#include "compiler/intermediate.h"
class ArrayBoundsClamper {
public:
ArrayBoundsClamper();
// Output array clamp function source into the shader source.
void OutputClampingFunctionDefinition(TInfoSinkBase& out) const;
// Marks nodes in the tree that index arrays indirectly as
// requiring clamping.
void MarkIndirectArrayBoundsForClamping(TIntermNode* root);
void Cleanup()
{
mArrayBoundsClampDefinitionNeeded = false;
}
private:
bool GetArrayBoundsClampDefinitionNeeded() const { return mArrayBoundsClampDefinitionNeeded; }
void SetArrayBoundsClampDefinitionNeeded() { mArrayBoundsClampDefinitionNeeded = true; }
bool mArrayBoundsClampDefinitionNeeded;
};
#endif // COMPILER_ARRAY_BOUNDS_CLAMPER_H_

Просмотреть файл

@ -4,6 +4,7 @@
// found in the LICENSE file.
//
#include "compiler/ArrayBoundsClamper.h"
#include "compiler/BuiltInFunctionEmulator.h"
#include "compiler/DetectRecursion.h"
#include "compiler/ForLoopUnroll.h"
@ -192,6 +193,10 @@ bool TCompiler::compile(const char* const shaderStrings[],
if (success && (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS))
builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root);
// Clamping uniform array bounds needs to happen after validateLimitations pass.
if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
// Call mapLongVariableNames() before collectAttribsUniforms() so in
// collectAttribsUniforms() we already have the mapped symbol names and
// we could composite mapped and original variable names.
@ -237,6 +242,7 @@ bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources)
void TCompiler::clearResults()
{
arrayBoundsClamper.Cleanup();
infoSink.info.erase();
infoSink.obj.erase();
infoSink.debug.erase();
@ -353,3 +359,9 @@ const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const
{
return builtInFunctionEmulator;
}
const ArrayBoundsClamper& TCompiler::getArrayBoundsClamper() const
{
return arrayBoundsClamper;
}

Просмотреть файл

@ -212,9 +212,38 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
break;
case EOpIndexDirect:
case EOpIndexIndirect:
writeTriplet(visit, NULL, "[", "]");
break;
case EOpIndexIndirect:
if (node->getAddIndexClamp())
{
if (visit == InVisit)
{
out << "[webgl_int_clamp(";
}
else if (visit == PostVisit)
{
int maxSize;
TIntermTyped *left = node->getLeft();
TType leftType = left->getType();
if (left->isArray())
{
// The shader will fail validation if the array length is not > 0.
maxSize = leftType.getArraySize() - 1;
}
else
{
maxSize = leftType.getNominalSize() - 1;
}
out << ", 0, " << maxSize << ")]";
}
}
else
{
writeTriplet(visit, NULL, "[", "]");
}
break;
case EOpIndexDirectStruct:
if (visit == InVisit)
{

Просмотреть файл

@ -16,6 +16,7 @@
#include "GLSLANG/ShaderLang.h"
#include "compiler/ArrayBoundsClamper.h"
#include "compiler/BuiltInFunctionEmulator.h"
#include "compiler/ExtensionBehavior.h"
#include "compiler/HashNames.h"
@ -106,6 +107,7 @@ protected:
// Get built-in extensions with default behavior.
const TExtensionBehavior& getExtensionBehavior() const;
const ArrayBoundsClamper& getArrayBoundsClamper() const;
const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const;
private:
@ -120,6 +122,7 @@ private:
// Built-in extensions with default behavior.
TExtensionBehavior extensionBehavior;
ArrayBoundsClamper arrayBoundsClamper;
BuiltInFunctionEmulator builtInFunctionEmulator;
// Results of compilation.

Просмотреть файл

@ -22,6 +22,9 @@ void TranslatorESSL::translate(TIntermNode* root) {
getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition(
sink, getShaderType() == SH_FRAGMENT_SHADER);
// Write array bounds clamping emulation if needed.
getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
// Write translated shader.
TOutputESSL outputESSL(sink, getHashFunction(), getNameMap(), getSymbolTable());
root->traverse(&outputESSL);

Просмотреть файл

@ -35,6 +35,9 @@ void TranslatorGLSL::translate(TIntermNode* root) {
getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition(
sink, false);
// Write array bounds clamping emulation if needed.
getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
// Write translated shader.
TOutputGLSL outputGLSL(sink, getHashFunction(), getNameMap(), getSymbolTable());
root->traverse(&outputGLSL);

Просмотреть файл

@ -42,7 +42,7 @@ TString TType::getCompleteString() const
if (qualifier != EvqTemporary && qualifier != EvqGlobal)
stream << getQualifierString() << " " << getPrecisionString() << " ";
if (array)
stream << "array of ";
stream << "array[" << getArraySize() << "] of ";
if (matrix)
stream << size << "X" << size << " matrix of ";
else if (size > 1)

Просмотреть файл

@ -391,7 +391,7 @@ protected:
//
class TIntermBinary : public TIntermOperator {
public:
TIntermBinary(TOperator o) : TIntermOperator(o) {}
TIntermBinary(TOperator o) : TIntermOperator(o), addIndexClamp(false) {}
virtual TIntermBinary* getAsBinaryNode() { return this; }
virtual void traverse(TIntermTraverser*);
@ -402,9 +402,15 @@ public:
TIntermTyped* getRight() const { return right; }
bool promote(TInfoSink&);
void setAddIndexClamp() { addIndexClamp = true; }
bool getAddIndexClamp() { return addIndexClamp; }
protected:
TIntermTyped* left;
TIntermTyped* right;
// If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
bool addIndexClamp;
};
//

Просмотреть файл

@ -138,6 +138,7 @@
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="ArrayBoundsClamper.cpp" />
<ClCompile Include="BuiltInFunctionEmulator.cpp" />
<ClCompile Include="Compiler.cpp" />
<ClCompile Include="debug.cpp" />
@ -225,6 +226,7 @@
</CustomBuild>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ArrayBoundsClamper.h" />
<ClInclude Include="BaseTypes.h" />
<ClInclude Include="BuiltInFunctionEmulator.h" />
<ClInclude Include="Common.h" />
@ -279,4 +281,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

Просмотреть файл

@ -69,6 +69,7 @@ DEFINES += -DCOMPILER_IMPLEMENTATION
VPATH += $(srcdir)/../compiler
# src/compiler:
CPPSRCS += \
ArrayBoundsClamper.cpp \
BuiltInFunctionEmulator.cpp \
Compiler.cpp \
compiler_debug.cpp \