Commit 9ecf3950 by alokp@chromium.org

GLSL backend now emits "#version 120" to legally access invariant keyword and…

GLSL backend now emits "#version 120" to legally access invariant keyword and gl_PointCoord built-in variable. BUG=35 Review URL: http://codereview.appspot.com/2341043 git-svn-id: https://angleproject.googlecode.com/svn/trunk@448 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 5d752f29
...@@ -133,6 +133,8 @@ ...@@ -133,6 +133,8 @@
'compiler/OutputGLSL.h', 'compiler/OutputGLSL.h',
'compiler/TranslatorGLSL.cpp', 'compiler/TranslatorGLSL.cpp',
'compiler/TranslatorGLSL.h', 'compiler/TranslatorGLSL.h',
'compiler/VersionGLSL.cpp',
'compiler/VersionGLSL.h',
], ],
}, },
{ {
......
...@@ -54,6 +54,8 @@ public: ...@@ -54,6 +54,8 @@ public:
const TVariableInfoList& getUniforms() const { return uniforms; } const TVariableInfoList& getUniforms() const { return uniforms; }
protected: protected:
ShShaderType getShaderType() const { return shaderType; }
ShShaderSpec getShaderSpec() const { return shaderSpec; }
// Initialize symbol-table with built-in symbols. // Initialize symbol-table with built-in symbols.
bool InitBuiltInSymbolTable(const ShBuiltInResources& resources); bool InitBuiltInSymbolTable(const ShBuiltInResources& resources);
// Clears the results from the previous compilation. // Clears the results from the previous compilation.
......
...@@ -7,12 +7,31 @@ ...@@ -7,12 +7,31 @@
#include "compiler/TranslatorGLSL.h" #include "compiler/TranslatorGLSL.h"
#include "compiler/OutputGLSL.h" #include "compiler/OutputGLSL.h"
#include "compiler/VersionGLSL.h"
static void writeVersion(ShShaderType type, TIntermNode* root,
TInfoSinkBase& sink) {
TVersionGLSL versionGLSL(type);
root->traverse(&versionGLSL);
int version = versionGLSL.getVersion();
// We need to write version directive only if it is greater than 110.
// If there is no version directive in the shader, 110 is implied.
if (version > 110) {
sink << "#version " << version << "\n";
}
}
TranslatorGLSL::TranslatorGLSL(ShShaderType type, ShShaderSpec spec) TranslatorGLSL::TranslatorGLSL(ShShaderType type, ShShaderSpec spec)
: TCompiler(type, spec) { : TCompiler(type, spec) {
} }
void TranslatorGLSL::translate(TIntermNode* root) { void TranslatorGLSL::translate(TIntermNode* root) {
TOutputGLSL outputGLSL(getInfoSink().obj); TInfoSinkBase& sink = getInfoSink().obj;
// Write GLSL version.
writeVersion(getShaderType(), root, sink);
// Write translated shader.
TOutputGLSL outputGLSL(sink);
root->traverse(&outputGLSL); root->traverse(&outputGLSL);
} }
//
// Copyright (c) 2002-2010 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/VersionGLSL.h"
static const int GLSL_VERSION_110 = 110;
static const int GLSL_VERSION_120 = 120;
// We need to scan for two things:
// 1. "invariant" keyword: This can occur in both - vertex and fragment shaders
// but only at the global scope.
// 2. "gl_PointCoord" built-in variable: This can only occur in fragment shader
// but inside any scope.
// So we need to scan the entire fragment shader but only the global scope
// of vertex shader.
//
// TODO(alokp): The following two cases of invariant decalaration get lost
// during parsing - they do not get carried over to the intermediate tree.
// Handle these cases:
// 1. When a pragma is used to force all output variables to be invariant:
// - #pragma STDGL invariant(all)
// 2. When a previously decalared or built-in variable is marked invariant:
// - invariant gl_Position;
// - varying vec3 color; invariant color;
//
TVersionGLSL::TVersionGLSL(ShShaderType type)
: mShaderType(type),
mVersion(GLSL_VERSION_110)
{
}
void TVersionGLSL::visitSymbol(TIntermSymbol* node)
{
ASSERT(mShaderType == SH_FRAGMENT_SHADER);
if (node->getSymbol() == "gl_PointCoord")
updateVersion(GLSL_VERSION_120);
}
void TVersionGLSL::visitConstantUnion(TIntermConstantUnion*)
{
ASSERT(mShaderType == SH_FRAGMENT_SHADER);
}
bool TVersionGLSL::visitBinary(Visit, TIntermBinary*)
{
ASSERT(mShaderType == SH_FRAGMENT_SHADER);
return true;
}
bool TVersionGLSL::visitUnary(Visit, TIntermUnary*)
{
ASSERT(mShaderType == SH_FRAGMENT_SHADER);
return true;
}
bool TVersionGLSL::visitSelection(Visit, TIntermSelection*)
{
ASSERT(mShaderType == SH_FRAGMENT_SHADER);
return true;
}
bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate* node)
{
// We need to scan the entire fragment shader but only the global scope
// of vertex shader.
bool visitChildren = mShaderType == SH_FRAGMENT_SHADER ? true : false;
switch (node->getOp()) {
case EOpSequence:
// We need to visit sequence children to get to global or inner scope.
visitChildren = true;
break;
case EOpDeclaration: {
const TIntermSequence& sequence = node->getSequence();
TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
if ((qualifier == EvqInvariantVaryingIn) ||
(qualifier == EvqInvariantVaryingOut)) {
updateVersion(GLSL_VERSION_120);
}
break;
}
default: break;
}
return visitChildren;
}
bool TVersionGLSL::visitLoop(Visit, TIntermLoop*)
{
ASSERT(mShaderType == SH_FRAGMENT_SHADER);
return true;
}
bool TVersionGLSL::visitBranch(Visit, TIntermBranch*)
{
ASSERT(mShaderType == SH_FRAGMENT_SHADER);
return true;
}
void TVersionGLSL::updateVersion(int version)
{
mVersion = std::max(version, mVersion);
}
//
// Copyright (c) 2002-2010 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_VERSIONGLSL_H_
#define COMPILER_VERSIONGLSL_H_
#include "GLSLANG/ShaderLang.h"
#include "compiler/intermediate.h"
// Traverses the intermediate tree to return the minimum GLSL version
// required to legally access all built-in features used in the shader.
// GLSL 1.1 which is mandated by OpenGL 2.0 provides:
// - #version and #extension to declare version and extensions.
// - built-in functions refract, exp, and log.
// - updated step() to compare x < edge instead of x <= edge.
// GLSL 1.2 which is mandated by OpenGL 2.1 provides:
// - many changes to reduce differences when compared to the ES specification.
// - invariant keyword and its support.
// - c++ style name hiding rules.
// - built-in variable gl_PointCoord for fragment shaders.
//
class TVersionGLSL : public TIntermTraverser {
public:
TVersionGLSL(ShShaderType type);
// Returns 120 if "invariant" keyword or "gl_PointCoord" is used
// in the shader. Else 110 is returned.
int getVersion() { return mVersion; }
virtual void visitSymbol(TIntermSymbol*);
virtual void visitConstantUnion(TIntermConstantUnion*);
virtual bool visitBinary(Visit, TIntermBinary*);
virtual bool visitUnary(Visit, TIntermUnary*);
virtual bool visitSelection(Visit, TIntermSelection*);
virtual bool visitAggregate(Visit, TIntermAggregate*);
virtual bool visitLoop(Visit, TIntermLoop*);
virtual bool visitBranch(Visit, TIntermBranch*);
protected:
void updateVersion(int version);
private:
ShShaderType mShaderType;
int mVersion;
};
#endif // COMPILER_VERSIONGLSL_H_
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