Commit 430f5e0c by maxvujovic@gmail.com

Add the SH_CSS_SHADERS_SPEC flag.

Review URL: https://codereview.appspot.com/6270050/ git-svn-id: https://angleproject.googlecode.com/svn/trunk@1145 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent ea09f9b4
...@@ -34,7 +34,7 @@ extern "C" { ...@@ -34,7 +34,7 @@ extern "C" {
// Version number for shader translation API. // Version number for shader translation API.
// It is incremented everytime the API changes. // It is incremented everytime the API changes.
#define SH_VERSION 106 #define SH_VERSION 107
// //
// The names of the following enums have been derived by replacing GL prefix // The names of the following enums have been derived by replacing GL prefix
...@@ -49,7 +49,29 @@ typedef enum { ...@@ -49,7 +49,29 @@ typedef enum {
typedef enum { typedef enum {
SH_GLES2_SPEC = 0x8B40, SH_GLES2_SPEC = 0x8B40,
SH_WEBGL_SPEC = 0x8B41 SH_WEBGL_SPEC = 0x8B41,
// The CSS Shaders spec is a subset of the WebGL spec.
//
// In both CSS vertex and fragment shaders, ANGLE:
// (1) Reserves the "css_" prefix.
// (2) Renames the main function to css_main.
// (3) Disables the gl_MaxDrawBuffers built-in.
//
// In CSS fragment shaders, ANGLE:
// (1) Disables the gl_FragColor built-in.
// (2) Disables the gl_FragData built-in.
// (3) Enables the css_MixColor built-in.
// (4) Enables the css_ColorMatrix built-in.
//
// After passing a CSS shader through ANGLE, the browser is expected to append
// a new main function to it.
// This new main function will call the css_main function.
// It may also perform additional operations like varying assignment, texture
// access, and gl_FragColor assignment in order to implement the CSS Shaders
// blend modes.
//
SH_CSS_SHADERS_SPEC = 0x8B42
} ShShaderSpec; } ShShaderSpec;
typedef enum { typedef enum {
......
...@@ -93,8 +93,11 @@ int main(int argc, char* argv[]) ...@@ -93,8 +93,11 @@ int main(int argc, char* argv[])
switch (argv[0][3]) { switch (argv[0][3]) {
case 'e': spec = SH_GLES2_SPEC; break; case 'e': spec = SH_GLES2_SPEC; break;
case 'w': spec = SH_WEBGL_SPEC; break; case 'w': spec = SH_WEBGL_SPEC; break;
case 'c': spec = SH_CSS_SHADERS_SPEC; break;
default: failCode = EFailUsage; default: failCode = EFailUsage;
} }
} else {
failCode = EFailUsage;
} }
break; break;
case 'b': case 'b':
...@@ -212,6 +215,7 @@ void usage() ...@@ -212,6 +215,7 @@ void usage()
" -d : print dependency graph used to enforce timing restrictions\n" " -d : print dependency graph used to enforce timing restrictions\n"
" -s=e : use GLES2 spec (this is by default)\n" " -s=e : use GLES2 spec (this is by default)\n"
" -s=w : use WebGL spec\n" " -s=w : use WebGL spec\n"
" -s=c : use CSS Shaders spec\n"
" -b=e : output GLSL ES code (this is by default)\n" " -b=e : output GLSL ES code (this is by default)\n"
" -b=g : output GLSL code\n" " -b=g : output GLSL code\n"
" -b=h : output HLSL code\n" " -b=h : output HLSL code\n"
......
...@@ -95,6 +95,7 @@ ...@@ -95,6 +95,7 @@
'compiler/QualifierAlive.h', 'compiler/QualifierAlive.h',
'compiler/RemoveTree.cpp', 'compiler/RemoveTree.cpp',
'compiler/RemoveTree.h', 'compiler/RemoveTree.h',
'compiler/RenameFunction.h',
'compiler/ShHandle.h', 'compiler/ShHandle.h',
'compiler/SymbolTable.cpp', 'compiler/SymbolTable.cpp',
'compiler/SymbolTable.h', 'compiler/SymbolTable.h',
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "compiler/Initialize.h" #include "compiler/Initialize.h"
#include "compiler/MapLongVariableNames.h" #include "compiler/MapLongVariableNames.h"
#include "compiler/ParseHelper.h" #include "compiler/ParseHelper.h"
#include "compiler/RenameFunction.h"
#include "compiler/ShHandle.h" #include "compiler/ShHandle.h"
#include "compiler/ValidateLimitations.h" #include "compiler/ValidateLimitations.h"
#include "compiler/depgraph/DependencyGraph.h" #include "compiler/depgraph/DependencyGraph.h"
...@@ -17,6 +18,11 @@ ...@@ -17,6 +18,11 @@
#include "compiler/timing/RestrictFragmentShaderTiming.h" #include "compiler/timing/RestrictFragmentShaderTiming.h"
#include "compiler/timing/RestrictVertexShaderTiming.h" #include "compiler/timing/RestrictVertexShaderTiming.h"
bool isWebGLBasedSpec(ShShaderSpec spec)
{
return spec == SH_WEBGL_SPEC || spec == SH_CSS_SHADERS_SPEC;
}
namespace { namespace {
bool InitializeSymbolTable( bool InitializeSymbolTable(
const TBuiltInStrings& builtInStrings, const TBuiltInStrings& builtInStrings,
...@@ -127,7 +133,7 @@ bool TCompiler::compile(const char* const shaderStrings[], ...@@ -127,7 +133,7 @@ bool TCompiler::compile(const char* const shaderStrings[],
return true; return true;
// If compiling for WebGL, validate loop and indexing as well. // If compiling for WebGL, validate loop and indexing as well.
if (shaderSpec == SH_WEBGL_SPEC) if (isWebGLBasedSpec(shaderSpec))
compileOptions |= SH_VALIDATE_LOOP_INDEXING; compileOptions |= SH_VALIDATE_LOOP_INDEXING;
// First string is path of source file if flag is set. The actual source follows. // First string is path of source file if flag is set. The actual source follows.
...@@ -168,6 +174,9 @@ bool TCompiler::compile(const char* const shaderStrings[], ...@@ -168,6 +174,9 @@ bool TCompiler::compile(const char* const shaderStrings[],
if (success && (compileOptions & SH_TIMING_RESTRICTIONS)) if (success && (compileOptions & SH_TIMING_RESTRICTIONS))
success = enforceTimingRestrictions(root, (compileOptions & SH_DEPENDENCY_GRAPH) != 0); success = enforceTimingRestrictions(root, (compileOptions & SH_DEPENDENCY_GRAPH) != 0);
if (success && shaderSpec == SH_CSS_SHADERS_SPEC)
rewriteCSSShader(root);
// Unroll for-loop markup needs to happen after validateLimitations pass. // Unroll for-loop markup needs to happen after validateLimitations pass.
if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX)) if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX))
ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling(root); ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling(root);
...@@ -242,6 +251,12 @@ bool TCompiler::detectRecursion(TIntermNode* root) ...@@ -242,6 +251,12 @@ bool TCompiler::detectRecursion(TIntermNode* root)
} }
} }
void TCompiler::rewriteCSSShader(TIntermNode* root)
{
RenameFunction renamer("main(", "css_main(");
root->traverse(&renamer);
}
bool TCompiler::validateLimitations(TIntermNode* root) { bool TCompiler::validateLimitations(TIntermNode* root) {
ValidateLimitations validate(shaderType, infoSink.info); ValidateLimitations validate(shaderType, infoSink.info);
root->traverse(&validate); root->traverse(&validate);
......
...@@ -475,7 +475,7 @@ static TString DefaultPrecisionFragment() ...@@ -475,7 +475,7 @@ static TString DefaultPrecisionFragment()
// Implementation dependent built-in constants. // Implementation dependent built-in constants.
// //
//============================================================================ //============================================================================
static TString BuiltInConstants(const ShBuiltInResources &resources) static TString BuiltInConstants(ShShaderSpec spec, const ShBuiltInResources &resources)
{ {
TStringStream s; TStringStream s;
...@@ -487,6 +487,8 @@ static TString BuiltInConstants(const ShBuiltInResources &resources) ...@@ -487,6 +487,8 @@ static TString BuiltInConstants(const ShBuiltInResources &resources)
s << "const int gl_MaxCombinedTextureImageUnits = " << resources.MaxCombinedTextureImageUnits << ";"; s << "const int gl_MaxCombinedTextureImageUnits = " << resources.MaxCombinedTextureImageUnits << ";";
s << "const int gl_MaxTextureImageUnits = " << resources.MaxTextureImageUnits << ";"; s << "const int gl_MaxTextureImageUnits = " << resources.MaxTextureImageUnits << ";";
s << "const int gl_MaxFragmentUniformVectors = " << resources.MaxFragmentUniformVectors << ";"; s << "const int gl_MaxFragmentUniformVectors = " << resources.MaxFragmentUniformVectors << ";";
if (spec != SH_CSS_SHADERS_SPEC)
s << "const int gl_MaxDrawBuffers = " << resources.MaxDrawBuffers << ";"; s << "const int gl_MaxDrawBuffers = " << resources.MaxDrawBuffers << ";";
return s.str(); return s.str();
...@@ -513,7 +515,7 @@ void TBuiltIns::initialize(ShShaderType type, ShShaderSpec spec, ...@@ -513,7 +515,7 @@ void TBuiltIns::initialize(ShShaderType type, ShShaderSpec spec,
default: assert(false && "Language not supported"); default: assert(false && "Language not supported");
} }
builtInStrings.push_back(BuiltInConstants(resources)); builtInStrings.push_back(BuiltInConstants(spec, resources));
} }
void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
...@@ -528,9 +530,20 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, ...@@ -528,9 +530,20 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
case SH_FRAGMENT_SHADER: case SH_FRAGMENT_SHADER:
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EbpMedium, EvqFragCoord, 4))); symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EbpMedium, EvqFragCoord, 4)));
symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EbpUndefined, EvqFrontFacing, 1))); symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EbpUndefined, EvqFrontFacing, 1)));
symbolTable.insert(*new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EbpMedium, EvqPointCoord, 2)));
//
// In CSS Shaders, gl_FragColor, gl_FragData, and gl_MaxDrawBuffers are not available.
// Instead, css_MixColor and css_ColorMatrix are available.
//
if (spec != SH_CSS_SHADERS_SPEC) {
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4))); symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4)));
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4))); symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4)));
symbolTable.insert(*new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EbpMedium, EvqPointCoord, 2))); } else {
symbolTable.insert(*new TVariable(NewPoolTString("css_MixColor"), TType(EbtFloat, EbpMedium, EvqGlobal, 4)));
symbolTable.insert(*new TVariable(NewPoolTString("css_ColorMatrix"), TType(EbtFloat, EbpMedium, EvqGlobal, 4, true)));
}
break; break;
case SH_VERTEX_SHADER: case SH_VERTEX_SHADER:
...@@ -620,7 +633,8 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, ...@@ -620,7 +633,8 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
// Finally add resource-specific variables. // Finally add resource-specific variables.
switch(type) { switch(type) {
case SH_FRAGMENT_SHADER: { case SH_FRAGMENT_SHADER:
if (spec != SH_CSS_SHADERS_SPEC) {
// Set up gl_FragData. The array size. // Set up gl_FragData. The array size.
TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, false, true); TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, false, true);
fragData.setArraySize(resources.MaxDrawBuffers); fragData.setArraySize(resources.MaxDrawBuffers);
......
...@@ -452,7 +452,7 @@ bool TParseContext::reservedErrorCheck(int line, const TString& identifier) ...@@ -452,7 +452,7 @@ bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
error(line, reservedErrMsg, "gl_", ""); error(line, reservedErrMsg, "gl_", "");
return true; return true;
} }
if (shaderSpec == SH_WEBGL_SPEC) { if (isWebGLBasedSpec(shaderSpec)) {
if (identifier.compare(0, 6, "webgl_") == 0) { if (identifier.compare(0, 6, "webgl_") == 0) {
error(line, reservedErrMsg, "webgl_", ""); error(line, reservedErrMsg, "webgl_", "");
return true; return true;
...@@ -461,6 +461,10 @@ bool TParseContext::reservedErrorCheck(int line, const TString& identifier) ...@@ -461,6 +461,10 @@ bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
error(line, reservedErrMsg, "_webgl_", ""); error(line, reservedErrMsg, "_webgl_", "");
return true; return true;
} }
if (shaderSpec == SH_CSS_SHADERS_SPEC && identifier.compare(0, 4, "css_") == 0) {
error(line, reservedErrMsg, "css_", "");
return true;
}
} }
if (identifier.find("__") != TString::npos) { if (identifier.find("__") != TString::npos) {
error(line, "identifiers containing two consecutive underscores (__) are reserved as possible future keywords", identifier.c_str(), "", ""); error(line, "identifiers containing two consecutive underscores (__) are reserved as possible future keywords", identifier.c_str(), "", "");
...@@ -1451,7 +1455,7 @@ const int kWebGLMaxStructNesting = 4; ...@@ -1451,7 +1455,7 @@ const int kWebGLMaxStructNesting = 4;
bool TParseContext::structNestingErrorCheck(TSourceLoc line, const TType& fieldType) bool TParseContext::structNestingErrorCheck(TSourceLoc line, const TType& fieldType)
{ {
if (shaderSpec != SH_WEBGL_SPEC) { if (!isWebGLBasedSpec(shaderSpec)) {
return false; return false;
} }
......
//
// Copyright (c) 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.
//
#ifndef COMPILER_RENAME_FUNCTION
#define COMPILER_RENAME_FUNCTION
#include "compiler/intermediate.h"
//
// Renames a function, including its declaration and any calls to it.
//
class RenameFunction : public TIntermTraverser
{
public:
RenameFunction(const TString& oldFunctionName, const TString& newFunctionName)
: TIntermTraverser(true, false, false)
, mOldFunctionName(oldFunctionName)
, mNewFunctionName(newFunctionName) {}
virtual bool visitAggregate(Visit visit, TIntermAggregate* node)
{
TOperator op = node->getOp();
if ((op == EOpFunction || op == EOpFunctionCall) && node->getName() == mOldFunctionName)
node->setName(mNewFunctionName);
return true;
}
private:
const TString& mOldFunctionName;
const TString& mNewFunctionName;
};
#endif // COMPILER_RENAME_FUNCTION
...@@ -27,6 +27,12 @@ class TCompiler; ...@@ -27,6 +27,12 @@ class TCompiler;
class TDependencyGraph; class TDependencyGraph;
// //
// Helper function to identify specs that are based on the WebGL spec,
// like the CSS Shaders spec.
//
bool isWebGLBasedSpec(ShShaderSpec spec);
//
// The base class used to back handles returned to the driver. // The base class used to back handles returned to the driver.
// //
class TShHandleBase { class TShHandleBase {
...@@ -71,6 +77,8 @@ protected: ...@@ -71,6 +77,8 @@ protected:
void clearResults(); void clearResults();
// Return true if function recursion is detected. // Return true if function recursion is detected.
bool detectRecursion(TIntermNode* root); bool detectRecursion(TIntermNode* root);
// Rewrites a shader's intermediate tree according to the CSS Shaders spec.
void rewriteCSSShader(TIntermNode* root);
// Returns true if the given shader does not exceed the minimum // Returns true if the given shader does not exceed the minimum
// functionality mandated in GLSL 1.0 spec Appendix A. // functionality mandated in GLSL 1.0 spec Appendix A.
bool validateLimitations(TIntermNode* root); bool validateLimitations(TIntermNode* root);
......
...@@ -641,6 +641,10 @@ ...@@ -641,6 +641,10 @@
> >
</File> </File>
<File <File
RelativePath=".\RenameFunction.h"
>
</File>
<File
RelativePath="..\..\include\GLSLANG\ResourceLimits.h" RelativePath="..\..\include\GLSLANG\ResourceLimits.h"
> >
</File> </File>
......
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