зеркало из https://github.com/microsoft/angle.git
Incorporated BSD-licensed changes implementing array bounds clamping.
BUG=none TEST=ran associated WebKit layout tests in Chromium Review URL: https://codereview.appspot.com/6999052 git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1701 736b8ea6-26fd-11df-bfd4-992fa37f6226
This commit is contained in:
Родитель
761630a947
Коммит
4167cc9102
1
AUTHORS
1
AUTHORS
|
@ -12,6 +12,7 @@ TransGaming Inc.
|
|||
3DLabs Inc. Ltd.
|
||||
|
||||
Adobe Systems Inc.
|
||||
Apple Inc.
|
||||
Autodesk, Inc.
|
||||
Cloud Party, Inc.
|
||||
Intel Corporation
|
||||
|
|
|
@ -151,7 +151,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;
|
||||
|
||||
//
|
||||
|
|
|
@ -60,6 +60,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"
|
||||
|
@ -108,6 +109,7 @@ protected:
|
|||
// Get built-in extensions with default behavior.
|
||||
const TExtensionBehavior& getExtensionBehavior() const;
|
||||
|
||||
const ArrayBoundsClamper& getArrayBoundsClamper() const;
|
||||
const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const;
|
||||
|
||||
private:
|
||||
|
@ -122,6 +124,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)
|
||||
|
|
|
@ -395,7 +395,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*);
|
||||
|
@ -406,9 +406,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>
|
||||
|
|
Загрузка…
Ссылка в новой задаче