Incorporated patch from haixia@ changing the default implementation of

array index clamping to use the clamp intrinsic. This works more reliably on pure OpenGL ES devices and on Windows. Added a mechanism in ShBuiltInResources to choose the strategy for array index clamping. BUG=none TEST=various out-of-bounds array indexing tests and various WebGL content Review URL: https://codereview.appspot.com/7194051 git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1798 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 2f8524d3
...@@ -158,10 +158,21 @@ typedef enum { ...@@ -158,10 +158,21 @@ typedef enum {
// This flag ensures all indirect (expression-based) array indexing // This flag ensures all indirect (expression-based) array indexing
// is clamped to the bounds of the array. This ensures, for example, // 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 // that you cannot read off the end of a uniform, whether an array
// vec234, or mat234 type. // vec234, or mat234 type. The ShArrayIndexClampingStrategy enum,
// specified in the ShBuiltInResources when constructing the
// compiler, selects the strategy for the clamping implementation.
SH_CLAMP_INDIRECT_ARRAY_BOUNDS = 0x1000 SH_CLAMP_INDIRECT_ARRAY_BOUNDS = 0x1000
} ShCompileOptions; } ShCompileOptions;
// Defines alternate strategies for implementing array index clamping.
typedef enum {
// Use the clamp intrinsic for array index clamping.
SH_CLAMP_WITH_CLAMP_INTRINSIC = 1,
// Use a user-defined function for array index clamping.
SH_CLAMP_WITH_USER_DEFINED_INT_CLAMP_FUNCTION
} ShArrayIndexClampingStrategy;
// //
// Driver must call this first, once, before doing any other // Driver must call this first, once, before doing any other
// compiler operations. // compiler operations.
...@@ -204,6 +215,10 @@ typedef struct ...@@ -204,6 +215,10 @@ typedef struct
// Set a 64 bit hash function to enable user-defined name hashing. // Set a 64 bit hash function to enable user-defined name hashing.
// Default is NULL. // Default is NULL.
ShHashFunction64 HashFunction; ShHashFunction64 HashFunction;
// Selects a strategy to use when implementing array index clamping.
// Default is SH_CLAMP_WITH_CLAMP_INTRINSIC.
ShArrayIndexClampingStrategy ArrayIndexClampingStrategy;
} ShBuiltInResources; } ShBuiltInResources;
// //
......
#define MAJOR_VERSION 1 #define MAJOR_VERSION 1
#define MINOR_VERSION 1 #define MINOR_VERSION 1
#define BUILD_VERSION 0 #define BUILD_VERSION 0
#define BUILD_REVISION 1732 #define BUILD_REVISION 1733
#define STRINGIFY(x) #x #define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x) #define MACRO_STRINGIFY(x) STRINGIFY(x)
......
...@@ -102,6 +102,7 @@ TShHandleBase::~TShHandleBase() { ...@@ -102,6 +102,7 @@ TShHandleBase::~TShHandleBase() {
TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec) TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
: shaderType(type), : shaderType(type),
shaderSpec(spec), shaderSpec(spec),
clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
builtInFunctionEmulator(type) builtInFunctionEmulator(type)
{ {
longNameMap = LongNameMap::GetInstance(); longNameMap = LongNameMap::GetInstance();
...@@ -125,6 +126,9 @@ bool TCompiler::Init(const ShBuiltInResources& resources) ...@@ -125,6 +126,9 @@ bool TCompiler::Init(const ShBuiltInResources& resources)
return false; return false;
InitExtensionBehavior(resources, extensionBehavior); InitExtensionBehavior(resources, extensionBehavior);
arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy);
clampingStrategy = resources.ArrayIndexClampingStrategy;
hashFunction = resources.HashFunction; hashFunction = resources.HashFunction;
return true; return true;
...@@ -355,13 +359,17 @@ const TExtensionBehavior& TCompiler::getExtensionBehavior() const ...@@ -355,13 +359,17 @@ const TExtensionBehavior& TCompiler::getExtensionBehavior() const
return extensionBehavior; return extensionBehavior;
} }
const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const const ArrayBoundsClamper& TCompiler::getArrayBoundsClamper() const
{ {
return builtInFunctionEmulator; return arrayBoundsClamper;
} }
const ArrayBoundsClamper& TCompiler::getArrayBoundsClamper() const ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const
{ {
return arrayBoundsClamper; return clampingStrategy;
} }
const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const
{
return builtInFunctionEmulator;
}
...@@ -7,10 +7,11 @@ ...@@ -7,10 +7,11 @@
#include "compiler/OutputESSL.h" #include "compiler/OutputESSL.h"
TOutputESSL::TOutputESSL(TInfoSinkBase& objSink, TOutputESSL::TOutputESSL(TInfoSinkBase& objSink,
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction, ShHashFunction64 hashFunction,
NameMap& nameMap, NameMap& nameMap,
TSymbolTable& symbolTable) TSymbolTable& symbolTable)
: TOutputGLSLBase(objSink, hashFunction, nameMap, symbolTable) : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable)
{ {
} }
......
...@@ -13,6 +13,7 @@ class TOutputESSL : public TOutputGLSLBase ...@@ -13,6 +13,7 @@ class TOutputESSL : public TOutputGLSLBase
{ {
public: public:
TOutputESSL(TInfoSinkBase& objSink, TOutputESSL(TInfoSinkBase& objSink,
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction, ShHashFunction64 hashFunction,
NameMap& nameMap, NameMap& nameMap,
TSymbolTable& symbolTable); TSymbolTable& symbolTable);
......
...@@ -7,10 +7,11 @@ ...@@ -7,10 +7,11 @@
#include "compiler/OutputGLSL.h" #include "compiler/OutputGLSL.h"
TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink, TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink,
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction, ShHashFunction64 hashFunction,
NameMap& nameMap, NameMap& nameMap,
TSymbolTable& symbolTable) TSymbolTable& symbolTable)
: TOutputGLSLBase(objSink, hashFunction, nameMap, symbolTable) : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable)
{ {
} }
......
...@@ -13,6 +13,7 @@ class TOutputGLSL : public TOutputGLSLBase ...@@ -13,6 +13,7 @@ class TOutputGLSL : public TOutputGLSLBase
{ {
public: public:
TOutputGLSL(TInfoSinkBase& objSink, TOutputGLSL(TInfoSinkBase& objSink,
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction, ShHashFunction64 hashFunction,
NameMap& nameMap, NameMap& nameMap,
TSymbolTable& symbolTable); TSymbolTable& symbolTable);
......
...@@ -40,12 +40,14 @@ bool isSingleStatement(TIntermNode* node) { ...@@ -40,12 +40,14 @@ bool isSingleStatement(TIntermNode* node) {
} // namespace } // namespace
TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase& objSink, TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase& objSink,
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction, ShHashFunction64 hashFunction,
NameMap& nameMap, NameMap& nameMap,
TSymbolTable& symbolTable) TSymbolTable& symbolTable)
: TIntermTraverser(true, true, true), : TIntermTraverser(true, true, true),
mObjSink(objSink), mObjSink(objSink),
mDeclaringVariables(false), mDeclaringVariables(false),
mClampingStrategy(clampingStrategy),
mHashFunction(hashFunction), mHashFunction(hashFunction),
mNameMap(nameMap), mNameMap(nameMap),
mSymbolTable(symbolTable) mSymbolTable(symbolTable)
...@@ -221,7 +223,11 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node) ...@@ -221,7 +223,11 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
{ {
if (visit == InVisit) if (visit == InVisit)
{ {
out << "[webgl_int_clamp("; if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) {
out << "[int(clamp(float(";
} else {
out << "[webgl_int_clamp(";
}
} }
else if (visit == PostVisit) else if (visit == PostVisit)
{ {
...@@ -238,7 +244,12 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node) ...@@ -238,7 +244,12 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
{ {
maxSize = leftType.getNominalSize() - 1; maxSize = leftType.getNominalSize() - 1;
} }
out << ", 0, " << maxSize << ")]";
if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) {
out << "), 0.0, float(" << maxSize << ")))]";
} else {
out << ", 0, " << maxSize << ")]";
}
} }
} }
else else
......
...@@ -17,6 +17,7 @@ class TOutputGLSLBase : public TIntermTraverser ...@@ -17,6 +17,7 @@ class TOutputGLSLBase : public TIntermTraverser
{ {
public: public:
TOutputGLSLBase(TInfoSinkBase& objSink, TOutputGLSLBase(TInfoSinkBase& objSink,
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction, ShHashFunction64 hashFunction,
NameMap& nameMap, NameMap& nameMap,
TSymbolTable& symbolTable); TSymbolTable& symbolTable);
...@@ -62,8 +63,11 @@ private: ...@@ -62,8 +63,11 @@ private:
ForLoopUnroll mLoopUnroll; ForLoopUnroll mLoopUnroll;
ShArrayIndexClampingStrategy mClampingStrategy;
// name hashing. // name hashing.
ShHashFunction64 mHashFunction; ShHashFunction64 mHashFunction;
NameMap& mNameMap; NameMap& mNameMap;
TSymbolTable& mSymbolTable; TSymbolTable& mSymbolTable;
......
...@@ -110,6 +110,7 @@ protected: ...@@ -110,6 +110,7 @@ protected:
const TExtensionBehavior& getExtensionBehavior() const; const TExtensionBehavior& getExtensionBehavior() const;
const ArrayBoundsClamper& getArrayBoundsClamper() const; const ArrayBoundsClamper& getArrayBoundsClamper() const;
ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const;
const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const; const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const;
private: private:
...@@ -125,6 +126,7 @@ private: ...@@ -125,6 +126,7 @@ private:
TExtensionBehavior extensionBehavior; TExtensionBehavior extensionBehavior;
ArrayBoundsClamper arrayBoundsClamper; ArrayBoundsClamper arrayBoundsClamper;
ShArrayIndexClampingStrategy clampingStrategy;
BuiltInFunctionEmulator builtInFunctionEmulator; BuiltInFunctionEmulator builtInFunctionEmulator;
// Results of compilation. // Results of compilation.
......
...@@ -129,6 +129,8 @@ void ShInitBuiltInResources(ShBuiltInResources* resources) ...@@ -129,6 +129,8 @@ void ShInitBuiltInResources(ShBuiltInResources* resources)
// Disable name hashing by default. // Disable name hashing by default.
resources->HashFunction = NULL; resources->HashFunction = NULL;
resources->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC;
} }
// //
...@@ -363,4 +365,4 @@ void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params) ...@@ -363,4 +365,4 @@ void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params)
break; break;
default: UNREACHABLE(); default: UNREACHABLE();
} }
} }
\ No newline at end of file
...@@ -26,7 +26,7 @@ void TranslatorESSL::translate(TIntermNode* root) { ...@@ -26,7 +26,7 @@ void TranslatorESSL::translate(TIntermNode* root) {
getArrayBoundsClamper().OutputClampingFunctionDefinition(sink); getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
// Write translated shader. // Write translated shader.
TOutputESSL outputESSL(sink, getHashFunction(), getNameMap(), getSymbolTable()); TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable());
root->traverse(&outputESSL); root->traverse(&outputESSL);
} }
......
...@@ -39,6 +39,6 @@ void TranslatorGLSL::translate(TIntermNode* root) { ...@@ -39,6 +39,6 @@ void TranslatorGLSL::translate(TIntermNode* root) {
getArrayBoundsClamper().OutputClampingFunctionDefinition(sink); getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
// Write translated shader. // Write translated shader.
TOutputGLSL outputGLSL(sink, getHashFunction(), getNameMap(), getSymbolTable()); TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable());
root->traverse(&outputGLSL); root->traverse(&outputGLSL);
} }
...@@ -70,17 +70,14 @@ private: ...@@ -70,17 +70,14 @@ private:
} // anonymous namespace } // anonymous namespace
ArrayBoundsClamper::ArrayBoundsClamper() ArrayBoundsClamper::ArrayBoundsClamper()
: mArrayBoundsClampDefinitionNeeded(false) : mClampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC)
, mArrayBoundsClampDefinitionNeeded(false)
{ {
} }
void ArrayBoundsClamper::OutputClampingFunctionDefinition(TInfoSinkBase& out) const void ArrayBoundsClamper::SetClampingStrategy(ShArrayIndexClampingStrategy clampingStrategy)
{ {
if (!mArrayBoundsClampDefinitionNeeded) mClampingStrategy = clampingStrategy;
{
return;
}
out << kIntClampBegin << kIntClampDefinition << kIntClampEnd;
} }
void ArrayBoundsClamper::MarkIndirectArrayBoundsForClamping(TIntermNode* root) void ArrayBoundsClamper::MarkIndirectArrayBoundsForClamping(TIntermNode* root)
...@@ -95,3 +92,15 @@ void ArrayBoundsClamper::MarkIndirectArrayBoundsForClamping(TIntermNode* root) ...@@ -95,3 +92,15 @@ void ArrayBoundsClamper::MarkIndirectArrayBoundsForClamping(TIntermNode* root)
} }
} }
void ArrayBoundsClamper::OutputClampingFunctionDefinition(TInfoSinkBase& out) const
{
if (!mArrayBoundsClampDefinitionNeeded)
{
return;
}
if (mClampingStrategy != SH_CLAMP_WITH_USER_DEFINED_INT_CLAMP_FUNCTION)
{
return;
}
out << kIntClampBegin << kIntClampDefinition << kIntClampEnd;
}
...@@ -35,13 +35,17 @@ class ArrayBoundsClamper { ...@@ -35,13 +35,17 @@ class ArrayBoundsClamper {
public: public:
ArrayBoundsClamper(); ArrayBoundsClamper();
// Output array clamp function source into the shader source. // Must be set before compiling any shaders to ensure consistency
void OutputClampingFunctionDefinition(TInfoSinkBase& out) const; // between the translated shaders and any necessary prequel.
void SetClampingStrategy(ShArrayIndexClampingStrategy clampingStrategy);
// Marks nodes in the tree that index arrays indirectly as // Marks nodes in the tree that index arrays indirectly as
// requiring clamping. // requiring clamping.
void MarkIndirectArrayBoundsForClamping(TIntermNode* root); void MarkIndirectArrayBoundsForClamping(TIntermNode* root);
// If necessary, output array clamp function source into the shader source.
void OutputClampingFunctionDefinition(TInfoSinkBase& out) const;
void Cleanup() void Cleanup()
{ {
mArrayBoundsClampDefinitionNeeded = false; mArrayBoundsClampDefinitionNeeded = false;
...@@ -50,7 +54,8 @@ public: ...@@ -50,7 +54,8 @@ public:
private: private:
bool GetArrayBoundsClampDefinitionNeeded() const { return mArrayBoundsClampDefinitionNeeded; } bool GetArrayBoundsClampDefinitionNeeded() const { return mArrayBoundsClampDefinitionNeeded; }
void SetArrayBoundsClampDefinitionNeeded() { mArrayBoundsClampDefinitionNeeded = true; } void SetArrayBoundsClampDefinitionNeeded() { mArrayBoundsClampDefinitionNeeded = true; }
ShArrayIndexClampingStrategy mClampingStrategy;
bool mArrayBoundsClampDefinitionNeeded; bool mArrayBoundsClampDefinitionNeeded;
}; };
......
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