ANGLE: Update to version 2446

Update ANGLE and reapply patches.

Patch changes:
"Dynamically resolve functions of dwmapi.dll"
  Removed; ANGLE no longer uses DWM API
"Make it possible to link ANGLE statically for single-thread use"
  Avoid name collision by using ANGLE-style getCurrent()
"Fix build when SSE2 is not available."
  Added guard for __cpuid(), which is not available on ARM
"Make DX9/DX11 mutually exclusive"
  Adjustments due to underlying code changes
"ANGLE: Avoid memory copies on buffers when data is null"
  Removed; fixed upstream
"Add missing intrin.h include for __cpuid"
  Removed; fixed upstream

Change-Id: I4f3d850fc555d3194ddc05e0b51c4966d33f7eaf
Reviewed-by: Oliver Wolff <oliver.wolff@digia.com>
Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
Reviewed-by: Kai Koehne <kai.koehne@digia.com>
This commit is contained in:
Andrew Knight 2013-09-18 11:51:20 +03:00 committed by The Qt Project
parent d84ed9a92a
commit 1a334f8135
139 changed files with 5055 additions and 3817 deletions

View File

@ -36,7 +36,8 @@ src/libGLESv2/renderer/shaders/compiled/PassthroughRGB11ps.h
src/libGLESv2/renderer/shaders/compiled/PassthroughLumAlpha11ps.h
src/libGLESv2/renderer/shaders/compiled/PassthroughLum11ps.h
src/libGLESv2/renderer/shaders/compiled/Passthrough11vs.h
src/libGLESv2/renderer/shaders/compiled/Clear11ps.h
src/libGLESv2/renderer/shaders/compiled/Clear11vs.h
src/libGLESv2/renderer/shaders/compiled/clear11vs.h
src/libGLESv2/renderer/shaders/compiled/clearmultiple11ps.h
src/libGLESv2/renderer/shaders/compiled/clearsingle11ps.h

View File

@ -17,6 +17,7 @@ Cloud Party, Inc.
Intel Corporation
Mozilla Corporation
Turbulenz
Klarälvdalens Datakonsult AB
Jacek Caban
Mark Callow

View File

@ -9,7 +9,9 @@
TransGaming Inc.
Nicolas Capens
Daniel Koch
Geoff Lang
Andrew Lewycky
Jamie Madill
Gavriel State
Shannon Woods
@ -36,6 +38,8 @@ Google Inc.
Ben Vanik
Adrienne Walker
thestig@chromium.org
Justin Schuh
Scott Graham
Adobe Systems Inc.
Alexandru Chiculita
@ -53,6 +57,9 @@ Intel Corporation
Andy Chen
Josh Triplett
Klarälvdalens Datakonsult AB
Milian Wolff
Mozilla Corp.
Ehsan Akhgari
Jeff Gilbert

View File

@ -1,4 +1,4 @@
// Copyright (C) 2002-2010 The ANGLE Project Authors.
// Copyright (C) 2002-2013 The ANGLE Project Authors.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without

View File

@ -306,6 +306,12 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay
#define EGL_SOFTWARE_DISPLAY_ANGLE ((EGLNativeDisplayType)-1)
#endif
#ifndef EGL_ANGLE_direct3d_display
#define EGL_ANGLE_direct3d_display 1
#define EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ((EGLNativeDisplayType)-2)
#define EGL_D3D11_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-3)
#endif
#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle
#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200

View File

@ -37,7 +37,7 @@ extern "C" {
// Version number for shader translation API.
// It is incremented everytime the API changes.
#define ANGLE_SH_VERSION 110
#define ANGLE_SH_VERSION 112
//
// The names of the following enums have been derived by replacing GL prefix
@ -108,6 +108,13 @@ typedef enum {
SH_SAMPLER_EXTERNAL_OES = 0x8D66
} ShDataType;
typedef enum {
SH_PRECISION_HIGHP = 0x5001,
SH_PRECISION_MEDIUMP = 0x5002,
SH_PRECISION_LOWP = 0x5003,
SH_PRECISION_UNDEFINED = 0
} ShPrecisionType;
typedef enum {
SH_INFO_LOG_LENGTH = 0x8B84,
SH_OBJECT_CODE_LENGTH = 0x8B88, // GL_SHADER_SOURCE_LENGTH
@ -115,6 +122,8 @@ typedef enum {
SH_ACTIVE_UNIFORM_MAX_LENGTH = 0x8B87,
SH_ACTIVE_ATTRIBUTES = 0x8B89,
SH_ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A,
SH_VARYINGS = 0x8BBB,
SH_VARYING_MAX_LENGTH = 0x8BBC,
SH_MAPPED_NAME_MAX_LENGTH = 0x6000,
SH_NAME_MAX_LENGTH = 0x6001,
SH_HASHED_NAME_MAX_LENGTH = 0x6002,
@ -128,7 +137,7 @@ typedef enum {
SH_VALIDATE_LOOP_INDEXING = 0x0001,
SH_INTERMEDIATE_TREE = 0x0002,
SH_OBJECT_CODE = 0x0004,
SH_ATTRIBUTES_UNIFORMS = 0x0008,
SH_VARIABLES = 0x0008,
SH_LINE_DIRECTIVES = 0x0010,
SH_SOURCE_PATH = 0x0020,
SH_MAP_LONG_VARIABLE_NAMES = 0x0040,
@ -154,6 +163,11 @@ typedef enum {
SH_DEPENDENCY_GRAPH = 0x0400,
// Enforce the GLSL 1.017 Appendix A section 7 packing restrictions.
// This flag only enforces (and can only enforce) the packing
// restrictions for uniform variables in both vertex and fragment
// shaders. ShCheckVariablesWithinPackingLimits() lets embedders
// enforce the packing restrictions for varying variables during
// program link time.
SH_ENFORCE_PACKING_RESTRICTIONS = 0x0800,
// This flag ensures all indirect (expression-based) array indexing
@ -162,7 +176,19 @@ typedef enum {
// 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,
// This flag limits the complexity of an expression.
SH_LIMIT_EXPRESSION_COMPLEXITY = 0x2000,
// This flag limits the depth of the call stack.
SH_LIMIT_CALL_STACK_DEPTH = 0x4000,
// This flag initializes gl_Position to vec4(0.0, 0.0, 0.0, 1.0) at
// the beginning of the vertex shader, and has no effect in the
// fragment shader. It is intended as a workaround for drivers which
// incorrectly fail to link programs if gl_Position is not written.
SH_INIT_GL_POSITION = 0x8000,
} ShCompileOptions;
// Defines alternate strategies for implementing array index clamping.
@ -212,6 +238,7 @@ typedef struct
int OES_EGL_image_external;
int ARB_texture_rectangle;
int EXT_draw_buffers;
int EXT_frag_depth;
// Set to 1 if highp precision is supported in the fragment language.
// Default is 0.
@ -225,6 +252,12 @@ typedef struct
// Selects a strategy to use when implementing array index clamping.
// Default is SH_CLAMP_WITH_CLAMP_INTRINSIC.
ShArrayIndexClampingStrategy ArrayIndexClampingStrategy;
// The maximum complexity an expression can be.
int MaxExpressionComplexity;
// The maximum depth a call stack can be.
int MaxCallStackDepth;
} ShBuiltInResources;
//
@ -281,9 +314,8 @@ COMPILER_EXPORT void ShDestruct(ShHandle handle);
// Can be queried by calling ShGetInfoLog().
// SH_OBJECT_CODE: Translates intermediate tree to glsl or hlsl shader.
// Can be queried by calling ShGetObjectCode().
// SH_ATTRIBUTES_UNIFORMS: Extracts attributes and uniforms.
// Can be queried by calling ShGetActiveAttrib() and
// ShGetActiveUniform().
// SH_VARIABLES: Extracts attributes, uniforms, and varyings.
// Can be queried by calling ShGetVariableInfo().
//
COMPILER_EXPORT int ShCompile(
const ShHandle handle,
@ -309,6 +341,9 @@ COMPILER_EXPORT int ShCompile(
// SH_ACTIVE_UNIFORM_MAX_LENGTH: the length of the longest active uniform
// variable name including the null
// termination character.
// SH_VARYINGS: the number of varying variables.
// SH_VARYING_MAX_LENGTH: the length of the longest varying variable name
// including the null termination character.
// SH_MAPPED_NAME_MAX_LENGTH: the length of the mapped variable name including
// the null termination character.
// SH_NAME_MAX_LENGTH: the max length of a user-defined name including the
@ -342,60 +377,44 @@ COMPILER_EXPORT void ShGetInfoLog(const ShHandle handle, char* infoLog);
// ShGetInfo with SH_OBJECT_CODE_LENGTH.
COMPILER_EXPORT void ShGetObjectCode(const ShHandle handle, char* objCode);
// Returns information about an active attribute variable.
// Returns information about a shader variable.
// Parameters:
// handle: Specifies the compiler
// index: Specifies the index of the attribute variable to be queried.
// variableType: Specifies the variable type; options include
// SH_ACTIVE_ATTRIBUTES, SH_ACTIVE_UNIFORMS, SH_VARYINGS.
// index: Specifies the index of the variable to be queried.
// length: Returns the number of characters actually written in the string
// indicated by name (excluding the null terminator) if a value other
// than NULL is passed.
// size: Returns the size of the attribute variable.
// type: Returns the data type of the attribute variable.
// size: Returns the size of the variable.
// type: Returns the data type of the variable.
// precision: Returns the precision of the variable.
// staticUse: Returns 1 if the variable is accessed in a statement after
// pre-processing, whether or not run-time flow of control will
// cause that statement to be executed.
// Returns 0 otherwise.
// name: Returns a null terminated string containing the name of the
// attribute variable. It is assumed that name has enough memory to
// accomodate the attribute variable name. The size of the buffer
// required to store the attribute variable name can be obtained by
// calling ShGetInfo with SH_ACTIVE_ATTRIBUTE_MAX_LENGTH.
// variable. It is assumed that name has enough memory to accormodate
// the variable name. The size of the buffer required to store the
// variable name can be obtained by calling ShGetInfo with
// SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_ACTIVE_UNIFORM_MAX_LENGTH,
// SH_VARYING_MAX_LENGTH.
// mappedName: Returns a null terminated string containing the mapped name of
// the attribute variable, It is assumed that mappedName has enough
// memory (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care
// about the mapped name. If the name is not mapped, then name and
// mappedName are the same.
COMPILER_EXPORT void ShGetActiveAttrib(const ShHandle handle,
// the variable, It is assumed that mappedName has enough memory
// (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care about the
// mapped name. If the name is not mapped, then name and mappedName
// are the same.
COMPILER_EXPORT void ShGetVariableInfo(const ShHandle handle,
ShShaderInfo variableType,
int index,
size_t* length,
int* size,
ShDataType* type,
ShPrecisionType* precision,
int* staticUse,
char* name,
char* mappedName);
// Returns information about an active uniform variable.
// Parameters:
// handle: Specifies the compiler
// index: Specifies the index of the uniform variable to be queried.
// length: Returns the number of characters actually written in the string
// indicated by name (excluding the null terminator) if a value
// other than NULL is passed.
// size: Returns the size of the uniform variable.
// type: Returns the data type of the uniform variable.
// name: Returns a null terminated string containing the name of the
// uniform variable. It is assumed that name has enough memory to
// accomodate the uniform variable name. The size of the buffer required
// to store the uniform variable name can be obtained by calling
// ShGetInfo with SH_ACTIVE_UNIFORMS_MAX_LENGTH.
// mappedName: Returns a null terminated string containing the mapped name of
// the uniform variable, It is assumed that mappedName has enough
// memory (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care
// about the mapped name. If the name is not mapped, then name and
// mappedName are the same.
COMPILER_EXPORT void ShGetActiveUniform(const ShHandle handle,
int index,
size_t* length,
int* size,
ShDataType* type,
char* name,
char* mappedName);
// Returns information about a name hashing entry from the latest compile.
// Parameters:
// handle: Specifies the compiler
@ -426,6 +445,25 @@ COMPILER_EXPORT void ShGetInfoPointer(const ShHandle handle,
ShShaderInfo pname,
void** params);
typedef struct
{
ShDataType type;
int size;
} ShVariableInfo;
// Returns 1 if the passed in variables pack in maxVectors following
// the packing rules from the GLSL 1.017 spec, Appendix A, section 7.
// Returns 0 otherwise. Also look at the SH_ENFORCE_PACKING_RESTRICTIONS
// flag above.
// Parameters:
// maxVectors: the available rows of registers.
// varInfoArray: an array of variable info (types and sizes).
// varInfoArraySize: the size of the variable array.
COMPILER_EXPORT int ShCheckVariablesWithinPackingLimits(
int maxVectors,
ShVariableInfo* varInfoArray,
size_t varInfoArraySize);
#ifdef __cplusplus
}
#endif

View File

@ -97,7 +97,6 @@
*-------------------------------------------------------------------------
* This precedes the return type of the function in the function prototype.
*/
#if defined(_WIN32) && !defined(__SCITECH_SNAP__) && !defined(QT_OPENGL_ES_2_ANGLE_STATIC)
# define KHRONOS_APICALL __declspec(dllimport)
#elif defined (__SYMBIAN32__)

View File

@ -9,6 +9,8 @@
#ifndef COMMON_ANGLEUTILS_H_
#define COMMON_ANGLEUTILS_H_
#include <stddef.h>
// A macro to disallow the copy constructor and operator= functions
// This must be used in the private: declarations for a class
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \

View File

@ -8,10 +8,10 @@
#include "common/debug.h"
#include "common/system.h"
#ifdef ANGLE_ENABLE_D3D11
typedef DWORD D3DCOLOR;
#else
#ifndef ANGLE_ENABLE_D3D11
#include <d3d9.h>
#else
typedef DWORD D3DCOLOR;
#endif
namespace gl

View File

@ -0,0 +1,49 @@
// 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.
#include "common/event_tracer.h"
namespace gl
{
GetCategoryEnabledFlagFunc g_getCategoryEnabledFlag;
AddTraceEventFunc g_addTraceEvent;
} // namespace gl
extern "C" {
void __stdcall SetTraceFunctionPointers(GetCategoryEnabledFlagFunc getCategoryEnabledFlag,
AddTraceEventFunc addTraceEvent)
{
gl::g_getCategoryEnabledFlag = getCategoryEnabledFlag;
gl::g_addTraceEvent = addTraceEvent;
}
} // extern "C"
namespace gl
{
const unsigned char* TraceGetTraceCategoryEnabledFlag(const char* name)
{
if (g_getCategoryEnabledFlag)
{
return g_getCategoryEnabledFlag(name);
}
static unsigned char disabled = 0;
return &disabled;
}
void TraceAddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id,
int numArgs, const char** argNames, const unsigned char* argTypes,
const unsigned long long* argValues, unsigned char flags)
{
if (g_addTraceEvent)
{
g_addTraceEvent(phase, categoryGroupEnabled, name, id, numArgs, argNames, argTypes, argValues, flags);
}
}
} // namespace gl

View File

@ -0,0 +1,33 @@
// 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 COMMON_EVENT_TRACER_H_
#define COMMON_EVENT_TRACER_H_
extern "C" {
typedef const unsigned char* (*GetCategoryEnabledFlagFunc)(const char* name);
typedef void (*AddTraceEventFunc)(char phase, const unsigned char* categoryGroupEnabled, const char* name,
unsigned long long id, int numArgs, const char** argNames,
const unsigned char* argTypes, const unsigned long long* argValues,
unsigned char flags);
// extern "C" so that it has a reasonable name for GetProcAddress.
void __stdcall SetTraceFunctionPointers(GetCategoryEnabledFlagFunc get_category_enabled_flag,
AddTraceEventFunc add_trace_event_func);
}
namespace gl
{
const unsigned char* TraceGetTraceCategoryEnabledFlag(const char* name);
void TraceAddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id,
int numArgs, const char** argNames, const unsigned char* argTypes,
const unsigned long long* argValues, unsigned char flags);
}
#endif // COMMON_EVENT_TRACER_H_

View File

@ -1,7 +1,7 @@
#define MAJOR_VERSION 1
#define MINOR_VERSION 1
#define MINOR_VERSION 2
#define BUILD_VERSION 0
#define BUILD_REVISION 2037
#define BUILD_REVISION 2446
#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)

View File

@ -90,10 +90,6 @@ enum TQualifier
EvqInvariantVaryingOut, // vertex shaders only read/write
EvqUniform, // Readonly, vertex and fragment
// pack/unpack input and output
EvqInput,
EvqOutput,
// parameters
EvqIn,
EvqOut,
@ -112,6 +108,7 @@ enum TQualifier
// built-ins written by fragment shader
EvqFragColor,
EvqFragData,
EvqFragDepth,
// end of list
EvqLast
@ -137,14 +134,13 @@ inline const char* getQualifierString(TQualifier q)
case EvqIn: return "in"; break;
case EvqOut: return "out"; break;
case EvqInOut: return "inout"; break;
case EvqInput: return "input"; break;
case EvqOutput: return "output"; break;
case EvqPosition: return "Position"; break;
case EvqPointSize: return "PointSize"; break;
case EvqFragCoord: return "FragCoord"; break;
case EvqFrontFacing: return "FrontFacing"; break;
case EvqFragColor: return "FragColor"; break;
case EvqFragData: return "FragData"; break;
case EvqFragDepth: return "FragDepth"; break;
default: return "unknown qualifier";
}
}

View File

@ -14,36 +14,24 @@
#include "compiler/PoolAlloc.h"
// We need two pieces of information to report errors/warnings - string and
// line number. We encode these into a single int so that it can be easily
// incremented/decremented by lexer. The right SOURCE_LOC_LINE_SIZE bits store
// line number while the rest store the string number. Since the shaders are
// usually small, we should not run out of memory. SOURCE_LOC_LINE_SIZE
// can be increased to alleviate this issue.
typedef int TSourceLoc;
const unsigned int SOURCE_LOC_LINE_SIZE = 16; // in bits.
const unsigned int SOURCE_LOC_LINE_MASK = (1 << SOURCE_LOC_LINE_SIZE) - 1;
inline TSourceLoc EncodeSourceLoc(int string, int line) {
return (string << SOURCE_LOC_LINE_SIZE) | (line & SOURCE_LOC_LINE_MASK);
}
inline void DecodeSourceLoc(TSourceLoc loc, int* string, int* line) {
if (string) *string = loc >> SOURCE_LOC_LINE_SIZE;
if (line) *line = loc & SOURCE_LOC_LINE_MASK;
}
struct TSourceLoc {
int first_file;
int first_line;
int last_file;
int last_line;
};
//
// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme.
//
#define POOL_ALLOCATOR_NEW_DELETE(A) \
void* operator new(size_t s) { return (A).allocate(s); } \
void* operator new(size_t, void *_Where) { return (_Where); } \
void operator delete(void*) { } \
void operator delete(void *, void *) { } \
void* operator new[](size_t s) { return (A).allocate(s); } \
void* operator new[](size_t, void *_Where) { return (_Where); } \
void operator delete[](void*) { } \
#define POOL_ALLOCATOR_NEW_DELETE() \
void* operator new(size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \
void* operator new(size_t, void *_Where) { return (_Where); } \
void operator delete(void*) { } \
void operator delete(void *, void *) { } \
void* operator new[](size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \
void* operator new[](size_t, void *_Where) { return (_Where); } \
void operator delete[](void*) { } \
void operator delete[](void *, void *) { }
//
@ -54,7 +42,7 @@ typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TStri
typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream;
inline TString* NewPoolTString(const char* s)
{
void* memory = GlobalPoolAllocator.allocate(sizeof(TString));
void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TString));
return new(memory) TString(s);
}

View File

@ -1,13 +1,14 @@
//
// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2013 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/BuiltInFunctionEmulator.h"
#include "compiler/DetectRecursion.h"
#include "compiler/DetectCallDepth.h"
#include "compiler/ForLoopUnroll.h"
#include "compiler/Initialize.h"
#include "compiler/InitializeGLPosition.h"
#include "compiler/InitializeParseContext.h"
#include "compiler/MapLongVariableNames.h"
#include "compiler/ParseHelper.h"
@ -27,66 +28,34 @@ bool isWebGLBasedSpec(ShShaderSpec spec)
}
namespace {
bool InitializeSymbolTable(
const TBuiltInStrings& builtInStrings,
ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources,
TInfoSink& infoSink, TSymbolTable& symbolTable)
{
TIntermediate intermediate(infoSink);
TExtensionBehavior extBehavior;
InitExtensionBehavior(resources, extBehavior);
// The builtins deliberately don't specify precisions for the function
// arguments and return types. For that reason we don't try to check them.
TParseContext parseContext(symbolTable, extBehavior, intermediate, type, spec, 0, false, NULL, infoSink);
parseContext.fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1;
GlobalParseContext = &parseContext;
assert(symbolTable.isEmpty());
//
// Parse the built-ins. This should only happen once per
// language symbol table.
//
// Push the symbol table to give it an initial scope. This
// push should not have a corresponding pop, so that built-ins
// are preserved, and the test for an empty table fails.
//
symbolTable.push();
for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i)
{
const char* builtInShaders = i->c_str();
int builtInLengths = static_cast<int>(i->size());
if (builtInLengths <= 0)
continue;
if (PaParseStrings(1, &builtInShaders, &builtInLengths, &parseContext) != 0)
{
infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
return false;
}
}
IdentifyBuiltIns(type, spec, resources, symbolTable);
return true;
}
class TScopedPoolAllocator {
public:
TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop)
: mAllocator(allocator), mPushPopAllocator(pushPop) {
if (mPushPopAllocator) mAllocator->push();
TScopedPoolAllocator(TPoolAllocator* allocator) : mAllocator(allocator) {
mAllocator->push();
SetGlobalPoolAllocator(mAllocator);
}
~TScopedPoolAllocator() {
SetGlobalPoolAllocator(NULL);
if (mPushPopAllocator) mAllocator->pop();
mAllocator->pop();
}
private:
TPoolAllocator* mAllocator;
bool mPushPopAllocator;
};
class TScopedSymbolTableLevel {
public:
TScopedSymbolTableLevel(TSymbolTable* table) : mTable(table) {
ASSERT(mTable->atBuiltInLevel());
mTable->push();
}
~TScopedSymbolTableLevel() {
while (!mTable->atBuiltInLevel())
mTable->pop();
}
private:
TSymbolTable* mTable;
};
} // namespace
@ -103,6 +72,9 @@ TShHandleBase::~TShHandleBase() {
TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
: shaderType(type),
shaderSpec(spec),
maxUniformVectors(0),
maxExpressionComplexity(0),
maxCallStackDepth(0),
fragmentPrecisionHigh(false),
clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
builtInFunctionEmulator(type)
@ -121,7 +93,10 @@ bool TCompiler::Init(const ShBuiltInResources& resources)
maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ?
resources.MaxVertexUniformVectors :
resources.MaxFragmentUniformVectors;
TScopedPoolAllocator scopedAlloc(&allocator, false);
maxExpressionComplexity = resources.MaxExpressionComplexity;
maxCallStackDepth = resources.MaxCallStackDepth;
SetGlobalPoolAllocator(&allocator);
// Generate built-in symbol table.
if (!InitBuiltInSymbolTable(resources))
@ -141,7 +116,7 @@ bool TCompiler::compile(const char* const shaderStrings[],
size_t numStrings,
int compileOptions)
{
TScopedPoolAllocator scopedAlloc(&allocator, true);
TScopedPoolAllocator scopedAlloc(&allocator);
clearResults();
if (numStrings == 0)
@ -165,13 +140,11 @@ bool TCompiler::compile(const char* const shaderStrings[],
shaderType, shaderSpec, compileOptions, true,
sourcePath, infoSink);
parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh;
GlobalParseContext = &parseContext;
SetGlobalParseContext(&parseContext);
// We preserve symbols at the built-in level from compile-to-compile.
// Start pushing the user-defined symbols at global level.
symbolTable.push();
if (!symbolTable.atGlobalLevel())
infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
TScopedSymbolTableLevel scopedSymbolLevel(&symbolTable);
// Parse shader.
bool success =
@ -182,7 +155,7 @@ bool TCompiler::compile(const char* const shaderStrings[],
success = intermediate.postProcess(root);
if (success)
success = detectRecursion(root);
success = detectCallDepth(root, infoSink, (compileOptions & SH_LIMIT_CALL_STACK_DEPTH) != 0);
if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
success = validateLimitations(root);
@ -205,6 +178,10 @@ bool TCompiler::compile(const char* const shaderStrings[],
if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
// Disallow expressions deemed too complex.
if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY))
success = limitExpressionComplexity(root);
// Call mapLongVariableNames() before collectAttribsUniforms() so in
// collectAttribsUniforms() we already have the mapped symbol names and
// we could composite mapped and original variable names.
@ -212,12 +189,18 @@ bool TCompiler::compile(const char* const shaderStrings[],
if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) && hashFunction == NULL)
mapLongVariableNames(root);
if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) {
collectAttribsUniforms(root);
if (success && shaderType == SH_VERTEX_SHADER && (compileOptions & SH_INIT_GL_POSITION)) {
InitializeGLPosition initGLPosition;
root->traverse(&initGLPosition);
}
if (success && (compileOptions & SH_VARIABLES)) {
collectVariables(root);
if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) {
success = enforcePackingRestrictions();
if (!success) {
infoSink.info.message(EPrefixError, "too many uniforms");
infoSink.info.prefix(EPrefixError);
infoSink.info << "too many uniforms";
}
}
}
@ -231,22 +214,58 @@ bool TCompiler::compile(const char* const shaderStrings[],
// Cleanup memory.
intermediate.remove(parseContext.treeRoot);
// Ensure symbol table is returned to the built-in level,
// throwing away all but the built-ins.
while (!symbolTable.atBuiltInLevel())
symbolTable.pop();
return success;
}
bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources)
bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
{
TBuiltIns builtIns;
compileResources = resources;
builtIns.initialize(shaderType, shaderSpec, resources);
return InitializeSymbolTable(builtIns.getBuiltInStrings(),
shaderType, shaderSpec, resources, infoSink, symbolTable);
assert(symbolTable.isEmpty());
symbolTable.push();
TPublicType integer;
integer.type = EbtInt;
integer.size = 1;
integer.matrix = false;
integer.array = false;
TPublicType floatingPoint;
floatingPoint.type = EbtFloat;
floatingPoint.size = 1;
floatingPoint.matrix = false;
floatingPoint.array = false;
TPublicType sampler;
sampler.size = 1;
sampler.matrix = false;
sampler.array = false;
switch(shaderType)
{
case SH_FRAGMENT_SHADER:
symbolTable.setDefaultPrecision(integer, EbpMedium);
break;
case SH_VERTEX_SHADER:
symbolTable.setDefaultPrecision(integer, EbpHigh);
symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
break;
default: assert(false && "Language not supported");
}
// We set defaults for all the sampler types, even those that are
// only available if an extension exists.
for (int samplerType = EbtGuardSamplerBegin + 1;
samplerType < EbtGuardSamplerEnd; ++samplerType) {
sampler.type = static_cast<TBasicType>(samplerType);
symbolTable.setDefaultPrecision(sampler, EbpLow);
}
InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable);
IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable);
return true;
}
void TCompiler::clearResults()
@ -258,24 +277,31 @@ void TCompiler::clearResults()
attribs.clear();
uniforms.clear();
varyings.clear();
builtInFunctionEmulator.Cleanup();
nameMap.clear();
}
bool TCompiler::detectRecursion(TIntermNode* root)
bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth)
{
DetectRecursion detect;
DetectCallDepth detect(infoSink, limitCallStackDepth, maxCallStackDepth);
root->traverse(&detect);
switch (detect.detectRecursion()) {
case DetectRecursion::kErrorNone:
switch (detect.detectCallDepth()) {
case DetectCallDepth::kErrorNone:
return true;
case DetectRecursion::kErrorMissingMain:
infoSink.info.message(EPrefixError, "Missing main()");
case DetectCallDepth::kErrorMissingMain:
infoSink.info.prefix(EPrefixError);
infoSink.info << "Missing main()";
return false;
case DetectRecursion::kErrorRecursion:
infoSink.info.message(EPrefixError, "Function recursion detected");
case DetectCallDepth::kErrorRecursion:
infoSink.info.prefix(EPrefixError);
infoSink.info << "Function recursion detected";
return false;
case DetectCallDepth::kErrorMaxDepthExceeded:
infoSink.info.prefix(EPrefixError);
infoSink.info << "Function call stack too deep";
return false;
default:
UNREACHABLE();
@ -321,6 +347,28 @@ bool TCompiler::enforceTimingRestrictions(TIntermNode* root, bool outputGraph)
}
}
bool TCompiler::limitExpressionComplexity(TIntermNode* root)
{
TIntermTraverser traverser;
root->traverse(&traverser);
TDependencyGraph graph(root);
for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls();
iter != graph.endUserDefinedFunctionCalls();
++iter)
{
TGraphFunctionCall* samplerSymbol = *iter;
TDependencyGraphTraverser graphTraverser;
samplerSymbol->traverse(&graphTraverser);
}
if (traverser.getMaxDepth() > maxExpressionComplexity) {
infoSink.info << "Expression too complex.";
return false;
}
return true;
}
bool TCompiler::enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph)
{
RestrictFragmentShaderTiming restrictor(infoSink.info);
@ -335,9 +383,9 @@ bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root)
return restrictor.numErrors() == 0;
}
void TCompiler::collectAttribsUniforms(TIntermNode* root)
void TCompiler::collectVariables(TIntermNode* root)
{
CollectAttribsUniforms collect(attribs, uniforms, hashFunction);
CollectVariables collect(attribs, uniforms, varyings, hashFunction);
root->traverse(&collect);
}

View File

@ -11,13 +11,13 @@
class ConstantUnion {
public:
POOL_ALLOCATOR_NEW_DELETE();
ConstantUnion()
{
iConst = 0;
type = EbtVoid;
}
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
void setIConst(int i) {iConst = i; type = EbtInt; }
void setFConst(float f) {fConst = f; type = EbtFloat; }
void setBConst(bool b) {bConst = b; type = EbtBool; }

View File

@ -0,0 +1,185 @@
//
// Copyright (c) 2002-2011 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/DetectCallDepth.h"
#include "compiler/InfoSink.h"
DetectCallDepth::FunctionNode::FunctionNode(const TString& fname)
: name(fname),
visit(PreVisit)
{
}
const TString& DetectCallDepth::FunctionNode::getName() const
{
return name;
}
void DetectCallDepth::FunctionNode::addCallee(
DetectCallDepth::FunctionNode* callee)
{
for (size_t i = 0; i < callees.size(); ++i) {
if (callees[i] == callee)
return;
}
callees.push_back(callee);
}
int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDepth, int depth)
{
ASSERT(visit == PreVisit);
ASSERT(detectCallDepth);
int maxDepth = depth;
visit = InVisit;
for (size_t i = 0; i < callees.size(); ++i) {
switch (callees[i]->visit) {
case InVisit:
// cycle detected, i.e., recursion detected.
return kInfiniteCallDepth;
case PostVisit:
break;
case PreVisit: {
// Check before we recurse so we don't go too depth
if (detectCallDepth->checkExceedsMaxDepth(depth))
return depth;
int callDepth = callees[i]->detectCallDepth(detectCallDepth, depth + 1);
// Check after we recurse so we can exit immediately and provide info.
if (detectCallDepth->checkExceedsMaxDepth(callDepth)) {
detectCallDepth->getInfoSink().info << "<-" << callees[i]->getName();
return callDepth;
}
maxDepth = std::max(callDepth, maxDepth);
break;
}
default:
UNREACHABLE();
break;
}
}
visit = PostVisit;
return maxDepth;
}
void DetectCallDepth::FunctionNode::reset()
{
visit = PreVisit;
}
DetectCallDepth::DetectCallDepth(TInfoSink& infoSink, bool limitCallStackDepth, int maxCallStackDepth)
: TIntermTraverser(true, false, true, false),
currentFunction(NULL),
infoSink(infoSink),
maxDepth(limitCallStackDepth ? maxCallStackDepth : FunctionNode::kInfiniteCallDepth)
{
}
DetectCallDepth::~DetectCallDepth()
{
for (size_t i = 0; i < functions.size(); ++i)
delete functions[i];
}
bool DetectCallDepth::visitAggregate(Visit visit, TIntermAggregate* node)
{
switch (node->getOp())
{
case EOpPrototype:
// Function declaration.
// Don't add FunctionNode here because node->getName() is the
// unmangled function name.
break;
case EOpFunction: {
// Function definition.
if (visit == PreVisit) {
currentFunction = findFunctionByName(node->getName());
if (currentFunction == NULL) {
currentFunction = new FunctionNode(node->getName());
functions.push_back(currentFunction);
}
} else if (visit == PostVisit) {
currentFunction = NULL;
}
break;
}
case EOpFunctionCall: {
// Function call.
if (visit == PreVisit) {
FunctionNode* func = findFunctionByName(node->getName());
if (func == NULL) {
func = new FunctionNode(node->getName());
functions.push_back(func);
}
if (currentFunction)
currentFunction->addCallee(func);
}
break;
}
default:
break;
}
return true;
}
bool DetectCallDepth::checkExceedsMaxDepth(int depth)
{
return depth >= maxDepth;
}
void DetectCallDepth::resetFunctionNodes()
{
for (size_t i = 0; i < functions.size(); ++i) {
functions[i]->reset();
}
}
DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepthForFunction(FunctionNode* func)
{
currentFunction = NULL;
resetFunctionNodes();
int maxCallDepth = func->detectCallDepth(this, 1);
if (maxCallDepth == FunctionNode::kInfiniteCallDepth)
return kErrorRecursion;
if (maxCallDepth >= maxDepth)
return kErrorMaxDepthExceeded;
return kErrorNone;
}
DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepth()
{
if (maxDepth != FunctionNode::kInfiniteCallDepth) {
// Check all functions because the driver may fail on them
// TODO: Before detectingRecursion, strip unused functions.
for (size_t i = 0; i < functions.size(); ++i) {
ErrorCode error = detectCallDepthForFunction(functions[i]);
if (error != kErrorNone)
return error;
}
} else {
FunctionNode* main = findFunctionByName("main(");
if (main == NULL)
return kErrorMissingMain;
return detectCallDepthForFunction(main);
}
return kErrorNone;
}
DetectCallDepth::FunctionNode* DetectCallDepth::findFunctionByName(
const TString& name)
{
for (size_t i = 0; i < functions.size(); ++i) {
if (functions[i]->getName() == name)
return functions[i];
}
return NULL;
}

View File

@ -0,0 +1,80 @@
//
// Copyright (c) 2002-2011 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_DETECT_RECURSION_H_
#define COMPILER_DETECT_RECURSION_H_
#include "GLSLANG/ShaderLang.h"
#include <limits.h>
#include "compiler/intermediate.h"
#include "compiler/VariableInfo.h"
class TInfoSink;
// Traverses intermediate tree to detect function recursion.
class DetectCallDepth : public TIntermTraverser {
public:
enum ErrorCode {
kErrorMissingMain,
kErrorRecursion,
kErrorMaxDepthExceeded,
kErrorNone
};
DetectCallDepth(TInfoSink& infoSync, bool limitCallStackDepth, int maxCallStackDepth);
~DetectCallDepth();
virtual bool visitAggregate(Visit, TIntermAggregate*);
bool checkExceedsMaxDepth(int depth);
ErrorCode detectCallDepth();
private:
class FunctionNode {
public:
static const int kInfiniteCallDepth = INT_MAX;
FunctionNode(const TString& fname);
const TString& getName() const;
// If a function is already in the callee list, this becomes a no-op.
void addCallee(FunctionNode* callee);
// Returns kInifinityCallDepth if recursive function calls are detected.
int detectCallDepth(DetectCallDepth* detectCallDepth, int depth);
// Reset state.
void reset();
private:
// mangled function name is unique.
TString name;
// functions that are directly called by this function.
TVector<FunctionNode*> callees;
Visit visit;
};
ErrorCode detectCallDepthForFunction(FunctionNode* func);
FunctionNode* findFunctionByName(const TString& name);
void resetFunctionNodes();
TInfoSink& getInfoSink() { return infoSink; }
TVector<FunctionNode*> functions;
FunctionNode* currentFunction;
TInfoSink& infoSink;
int maxDepth;
DetectCallDepth(const DetectCallDepth&);
void operator=(const DetectCallDepth&);
};
#endif // COMPILER_DETECT_RECURSION_H_

View File

@ -46,7 +46,7 @@ void TDiagnostics::writeInfo(Severity severity,
TInfoSinkBase& sink = mInfoSink.info;
/* VC++ format: file(linenum) : error #: 'token' : extrainfo */
sink.prefix(prefix);
sink.location(EncodeSourceLoc(loc.file, loc.line));
sink.location(loc.file, loc.line);
sink << "'" << token << "' : " << reason << " " << extra << "\n";
}

View File

@ -6,8 +6,8 @@
#include "compiler/InfoSink.h"
void TInfoSinkBase::prefix(TPrefixType message) {
switch(message) {
void TInfoSinkBase::prefix(TPrefixType p) {
switch(p) {
case EPrefixNone:
break;
case EPrefixWarning:
@ -31,29 +31,24 @@ void TInfoSinkBase::prefix(TPrefixType message) {
}
}
void TInfoSinkBase::location(TSourceLoc loc) {
int string = 0, line = 0;
DecodeSourceLoc(loc, &string, &line);
void TInfoSinkBase::location(int file, int line) {
TPersistStringStream stream;
if (line)
stream << string << ":" << line;
stream << file << ":" << line;
else
stream << string << ":? ";
stream << file << ":? ";
stream << ": ";
sink.append(stream.str());
}
void TInfoSinkBase::message(TPrefixType message, const char* s) {
prefix(message);
sink.append(s);
sink.append("\n");
void TInfoSinkBase::location(const TSourceLoc& loc) {
location(loc.first_file, loc.first_line);
}
void TInfoSinkBase::message(TPrefixType message, const char* s, TSourceLoc loc) {
prefix(message);
void TInfoSinkBase::message(TPrefixType p, const TSourceLoc& loc, const char* m) {
prefix(p);
location(loc);
sink.append(s);
sink.append(m);
sink.append("\n");
}

View File

@ -96,10 +96,10 @@ public:
const TPersistString& str() const { return sink; }
const char* c_str() const { return sink.c_str(); }
void prefix(TPrefixType message);
void location(TSourceLoc loc);
void message(TPrefixType message, const char* s);
void message(TPrefixType message, const char* s, TSourceLoc loc);
void prefix(TPrefixType p);
void location(int file, int line);
void location(const TSourceLoc& loc);
void message(TPrefixType p, const TSourceLoc& loc, const char* m);
private:
TPersistString sink;

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2013 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.
//
@ -14,513 +14,413 @@
#include "compiler/intermediate.h"
//============================================================================
//
// Prototypes for built-in functions seen by both vertex and fragment shaders.
//
//============================================================================
static TString BuiltInFunctionsCommon(const ShBuiltInResources& resources)
void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable)
{
TString s;
TType *float1 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 1);
TType *float2 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 2);
TType *float3 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 3);
TType *float4 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 4);
TType *int2 = new TType(EbtInt, EbpUndefined, EvqGlobal, 2);
TType *int3 = new TType(EbtInt, EbpUndefined, EvqGlobal, 3);
TType *int4 = new TType(EbtInt, EbpUndefined, EvqGlobal, 4);
//
// Angle and Trigonometric Functions.
//
s.append(TString("float radians(float degrees);"));
s.append(TString("vec2 radians(vec2 degrees);"));
s.append(TString("vec3 radians(vec3 degrees);"));
s.append(TString("vec4 radians(vec4 degrees);"));
symbolTable.insertBuiltIn(float1, "radians", float1);
symbolTable.insertBuiltIn(float2, "radians", float2);
symbolTable.insertBuiltIn(float3, "radians", float3);
symbolTable.insertBuiltIn(float4, "radians", float4);
s.append(TString("float degrees(float radians);"));
s.append(TString("vec2 degrees(vec2 radians);"));
s.append(TString("vec3 degrees(vec3 radians);"));
s.append(TString("vec4 degrees(vec4 radians);"));
symbolTable.insertBuiltIn(float1, "degrees", float1);
symbolTable.insertBuiltIn(float2, "degrees", float2);
symbolTable.insertBuiltIn(float3, "degrees", float3);
symbolTable.insertBuiltIn(float4, "degrees", float4);
s.append(TString("float sin(float angle);"));
s.append(TString("vec2 sin(vec2 angle);"));
s.append(TString("vec3 sin(vec3 angle);"));
s.append(TString("vec4 sin(vec4 angle);"));
symbolTable.insertBuiltIn(float1, "sin", float1);
symbolTable.insertBuiltIn(float2, "sin", float2);
symbolTable.insertBuiltIn(float3, "sin", float3);
symbolTable.insertBuiltIn(float4, "sin", float4);
s.append(TString("float cos(float angle);"));
s.append(TString("vec2 cos(vec2 angle);"));
s.append(TString("vec3 cos(vec3 angle);"));
s.append(TString("vec4 cos(vec4 angle);"));
symbolTable.insertBuiltIn(float1, "cos", float1);
symbolTable.insertBuiltIn(float2, "cos", float2);
symbolTable.insertBuiltIn(float3, "cos", float3);
symbolTable.insertBuiltIn(float4, "cos", float4);
s.append(TString("float tan(float angle);"));
s.append(TString("vec2 tan(vec2 angle);"));
s.append(TString("vec3 tan(vec3 angle);"));
s.append(TString("vec4 tan(vec4 angle);"));
symbolTable.insertBuiltIn(float1, "tan", float1);
symbolTable.insertBuiltIn(float2, "tan", float2);
symbolTable.insertBuiltIn(float3, "tan", float3);
symbolTable.insertBuiltIn(float4, "tan", float4);
s.append(TString("float asin(float x);"));
s.append(TString("vec2 asin(vec2 x);"));
s.append(TString("vec3 asin(vec3 x);"));
s.append(TString("vec4 asin(vec4 x);"));
symbolTable.insertBuiltIn(float1, "asin", float1);
symbolTable.insertBuiltIn(float2, "asin", float2);
symbolTable.insertBuiltIn(float3, "asin", float3);
symbolTable.insertBuiltIn(float4, "asin", float4);
s.append(TString("float acos(float x);"));
s.append(TString("vec2 acos(vec2 x);"));
s.append(TString("vec3 acos(vec3 x);"));
s.append(TString("vec4 acos(vec4 x);"));
symbolTable.insertBuiltIn(float1, "acos", float1);
symbolTable.insertBuiltIn(float2, "acos", float2);
symbolTable.insertBuiltIn(float3, "acos", float3);
symbolTable.insertBuiltIn(float4, "acos", float4);
s.append(TString("float atan(float y, float x);"));
s.append(TString("vec2 atan(vec2 y, vec2 x);"));
s.append(TString("vec3 atan(vec3 y, vec3 x);"));
s.append(TString("vec4 atan(vec4 y, vec4 x);"));
symbolTable.insertBuiltIn(float1, "atan", float1, float1);
symbolTable.insertBuiltIn(float2, "atan", float2, float2);
symbolTable.insertBuiltIn(float3, "atan", float3, float3);
symbolTable.insertBuiltIn(float4, "atan", float4, float4);
s.append(TString("float atan(float y_over_x);"));
s.append(TString("vec2 atan(vec2 y_over_x);"));
s.append(TString("vec3 atan(vec3 y_over_x);"));
s.append(TString("vec4 atan(vec4 y_over_x);"));
symbolTable.insertBuiltIn(float1, "atan", float1);
symbolTable.insertBuiltIn(float2, "atan", float2);
symbolTable.insertBuiltIn(float3, "atan", float3);
symbolTable.insertBuiltIn(float4, "atan", float4);
//
// Exponential Functions.
//
s.append(TString("float pow(float x, float y);"));
s.append(TString("vec2 pow(vec2 x, vec2 y);"));
s.append(TString("vec3 pow(vec3 x, vec3 y);"));
s.append(TString("vec4 pow(vec4 x, vec4 y);"));
symbolTable.insertBuiltIn(float1, "pow", float1, float1);
symbolTable.insertBuiltIn(float2, "pow", float2, float2);
symbolTable.insertBuiltIn(float3, "pow", float3, float3);
symbolTable.insertBuiltIn(float4, "pow", float4, float4);
s.append(TString("float exp(float x);"));
s.append(TString("vec2 exp(vec2 x);"));
s.append(TString("vec3 exp(vec3 x);"));
s.append(TString("vec4 exp(vec4 x);"));
symbolTable.insertBuiltIn(float1, "exp", float1);
symbolTable.insertBuiltIn(float2, "exp", float2);
symbolTable.insertBuiltIn(float3, "exp", float3);
symbolTable.insertBuiltIn(float4, "exp", float4);
s.append(TString("float log(float x);"));
s.append(TString("vec2 log(vec2 x);"));
s.append(TString("vec3 log(vec3 x);"));
s.append(TString("vec4 log(vec4 x);"));
symbolTable.insertBuiltIn(float1, "log", float1);
symbolTable.insertBuiltIn(float2, "log", float2);
symbolTable.insertBuiltIn(float3, "log", float3);
symbolTable.insertBuiltIn(float4, "log", float4);
s.append(TString("float exp2(float x);"));
s.append(TString("vec2 exp2(vec2 x);"));
s.append(TString("vec3 exp2(vec3 x);"));
s.append(TString("vec4 exp2(vec4 x);"));
symbolTable.insertBuiltIn(float1, "exp2", float1);
symbolTable.insertBuiltIn(float2, "exp2", float2);
symbolTable.insertBuiltIn(float3, "exp2", float3);
symbolTable.insertBuiltIn(float4, "exp2", float4);
s.append(TString("float log2(float x);"));
s.append(TString("vec2 log2(vec2 x);"));
s.append(TString("vec3 log2(vec3 x);"));
s.append(TString("vec4 log2(vec4 x);"));
symbolTable.insertBuiltIn(float1, "log2", float1);
symbolTable.insertBuiltIn(float2, "log2", float2);
symbolTable.insertBuiltIn(float3, "log2", float3);
symbolTable.insertBuiltIn(float4, "log2", float4);
s.append(TString("float sqrt(float x);"));
s.append(TString("vec2 sqrt(vec2 x);"));
s.append(TString("vec3 sqrt(vec3 x);"));
s.append(TString("vec4 sqrt(vec4 x);"));
symbolTable.insertBuiltIn(float1, "sqrt", float1);
symbolTable.insertBuiltIn(float2, "sqrt", float2);
symbolTable.insertBuiltIn(float3, "sqrt", float3);
symbolTable.insertBuiltIn(float4, "sqrt", float4);
s.append(TString("float inversesqrt(float x);"));
s.append(TString("vec2 inversesqrt(vec2 x);"));
s.append(TString("vec3 inversesqrt(vec3 x);"));
s.append(TString("vec4 inversesqrt(vec4 x);"));
symbolTable.insertBuiltIn(float1, "inversesqrt", float1);
symbolTable.insertBuiltIn(float2, "inversesqrt", float2);
symbolTable.insertBuiltIn(float3, "inversesqrt", float3);
symbolTable.insertBuiltIn(float4, "inversesqrt", float4);
//
// Common Functions.
//
s.append(TString("float abs(float x);"));
s.append(TString("vec2 abs(vec2 x);"));
s.append(TString("vec3 abs(vec3 x);"));
s.append(TString("vec4 abs(vec4 x);"));
symbolTable.insertBuiltIn(float1, "abs", float1);
symbolTable.insertBuiltIn(float2, "abs", float2);
symbolTable.insertBuiltIn(float3, "abs", float3);
symbolTable.insertBuiltIn(float4, "abs", float4);
s.append(TString("float sign(float x);"));
s.append(TString("vec2 sign(vec2 x);"));
s.append(TString("vec3 sign(vec3 x);"));
s.append(TString("vec4 sign(vec4 x);"));
symbolTable.insertBuiltIn(float1, "sign", float1);
symbolTable.insertBuiltIn(float2, "sign", float2);
symbolTable.insertBuiltIn(float3, "sign", float3);
symbolTable.insertBuiltIn(float4, "sign", float4);
s.append(TString("float floor(float x);"));
s.append(TString("vec2 floor(vec2 x);"));
s.append(TString("vec3 floor(vec3 x);"));
s.append(TString("vec4 floor(vec4 x);"));
symbolTable.insertBuiltIn(float1, "floor", float1);
symbolTable.insertBuiltIn(float2, "floor", float2);
symbolTable.insertBuiltIn(float3, "floor", float3);
symbolTable.insertBuiltIn(float4, "floor", float4);
s.append(TString("float ceil(float x);"));
s.append(TString("vec2 ceil(vec2 x);"));
s.append(TString("vec3 ceil(vec3 x);"));
s.append(TString("vec4 ceil(vec4 x);"));
symbolTable.insertBuiltIn(float1, "ceil", float1);
symbolTable.insertBuiltIn(float2, "ceil", float2);
symbolTable.insertBuiltIn(float3, "ceil", float3);
symbolTable.insertBuiltIn(float4, "ceil", float4);
s.append(TString("float fract(float x);"));
s.append(TString("vec2 fract(vec2 x);"));
s.append(TString("vec3 fract(vec3 x);"));
s.append(TString("vec4 fract(vec4 x);"));
symbolTable.insertBuiltIn(float1, "fract", float1);
symbolTable.insertBuiltIn(float2, "fract", float2);
symbolTable.insertBuiltIn(float3, "fract", float3);
symbolTable.insertBuiltIn(float4, "fract", float4);
s.append(TString("float mod(float x, float y);"));
s.append(TString("vec2 mod(vec2 x, float y);"));
s.append(TString("vec3 mod(vec3 x, float y);"));
s.append(TString("vec4 mod(vec4 x, float y);"));
s.append(TString("vec2 mod(vec2 x, vec2 y);"));
s.append(TString("vec3 mod(vec3 x, vec3 y);"));
s.append(TString("vec4 mod(vec4 x, vec4 y);"));
symbolTable.insertBuiltIn(float1, "mod", float1, float1);
symbolTable.insertBuiltIn(float2, "mod", float2, float1);
symbolTable.insertBuiltIn(float3, "mod", float3, float1);
symbolTable.insertBuiltIn(float4, "mod", float4, float1);
symbolTable.insertBuiltIn(float2, "mod", float2, float2);
symbolTable.insertBuiltIn(float3, "mod", float3, float3);
symbolTable.insertBuiltIn(float4, "mod", float4, float4);
s.append(TString("float min(float x, float y);"));
s.append(TString("vec2 min(vec2 x, float y);"));
s.append(TString("vec3 min(vec3 x, float y);"));
s.append(TString("vec4 min(vec4 x, float y);"));
s.append(TString("vec2 min(vec2 x, vec2 y);"));
s.append(TString("vec3 min(vec3 x, vec3 y);"));
s.append(TString("vec4 min(vec4 x, vec4 y);"));
symbolTable.insertBuiltIn(float1, "min", float1, float1);
symbolTable.insertBuiltIn(float2, "min", float2, float1);
symbolTable.insertBuiltIn(float3, "min", float3, float1);
symbolTable.insertBuiltIn(float4, "min", float4, float1);
symbolTable.insertBuiltIn(float2, "min", float2, float2);
symbolTable.insertBuiltIn(float3, "min", float3, float3);
symbolTable.insertBuiltIn(float4, "min", float4, float4);
s.append(TString("float max(float x, float y);"));
s.append(TString("vec2 max(vec2 x, float y);"));
s.append(TString("vec3 max(vec3 x, float y);"));
s.append(TString("vec4 max(vec4 x, float y);"));
s.append(TString("vec2 max(vec2 x, vec2 y);"));
s.append(TString("vec3 max(vec3 x, vec3 y);"));
s.append(TString("vec4 max(vec4 x, vec4 y);"));
symbolTable.insertBuiltIn(float1, "max", float1, float1);
symbolTable.insertBuiltIn(float2, "max", float2, float1);
symbolTable.insertBuiltIn(float3, "max", float3, float1);
symbolTable.insertBuiltIn(float4, "max", float4, float1);
symbolTable.insertBuiltIn(float2, "max", float2, float2);
symbolTable.insertBuiltIn(float3, "max", float3, float3);
symbolTable.insertBuiltIn(float4, "max", float4, float4);
s.append(TString("float clamp(float x, float minVal, float maxVal);"));
s.append(TString("vec2 clamp(vec2 x, float minVal, float maxVal);"));
s.append(TString("vec3 clamp(vec3 x, float minVal, float maxVal);"));
s.append(TString("vec4 clamp(vec4 x, float minVal, float maxVal);"));
s.append(TString("vec2 clamp(vec2 x, vec2 minVal, vec2 maxVal);"));
s.append(TString("vec3 clamp(vec3 x, vec3 minVal, vec3 maxVal);"));
s.append(TString("vec4 clamp(vec4 x, vec4 minVal, vec4 maxVal);"));
symbolTable.insertBuiltIn(float1, "clamp", float1, float1, float1);
symbolTable.insertBuiltIn(float2, "clamp", float2, float1, float1);
symbolTable.insertBuiltIn(float3, "clamp", float3, float1, float1);
symbolTable.insertBuiltIn(float4, "clamp", float4, float1, float1);
symbolTable.insertBuiltIn(float2, "clamp", float2, float2, float2);
symbolTable.insertBuiltIn(float3, "clamp", float3, float3, float3);
symbolTable.insertBuiltIn(float4, "clamp", float4, float4, float4);
s.append(TString("float mix(float x, float y, float a);"));
s.append(TString("vec2 mix(vec2 x, vec2 y, float a);"));
s.append(TString("vec3 mix(vec3 x, vec3 y, float a);"));
s.append(TString("vec4 mix(vec4 x, vec4 y, float a);"));
s.append(TString("vec2 mix(vec2 x, vec2 y, vec2 a);"));
s.append(TString("vec3 mix(vec3 x, vec3 y, vec3 a);"));
s.append(TString("vec4 mix(vec4 x, vec4 y, vec4 a);"));
symbolTable.insertBuiltIn(float1, "mix", float1, float1, float1);
symbolTable.insertBuiltIn(float2, "mix", float2, float2, float1);
symbolTable.insertBuiltIn(float3, "mix", float3, float3, float1);
symbolTable.insertBuiltIn(float4, "mix", float4, float4, float1);
symbolTable.insertBuiltIn(float2, "mix", float2, float2, float2);
symbolTable.insertBuiltIn(float3, "mix", float3, float3, float3);
symbolTable.insertBuiltIn(float4, "mix", float4, float4, float4);
s.append(TString("float step(float edge, float x);"));
s.append(TString("vec2 step(vec2 edge, vec2 x);"));
s.append(TString("vec3 step(vec3 edge, vec3 x);"));
s.append(TString("vec4 step(vec4 edge, vec4 x);"));
s.append(TString("vec2 step(float edge, vec2 x);"));
s.append(TString("vec3 step(float edge, vec3 x);"));
s.append(TString("vec4 step(float edge, vec4 x);"));
symbolTable.insertBuiltIn(float1, "step", float1, float1);
symbolTable.insertBuiltIn(float2, "step", float2, float2);
symbolTable.insertBuiltIn(float3, "step", float3, float3);
symbolTable.insertBuiltIn(float4, "step", float4, float4);
symbolTable.insertBuiltIn(float2, "step", float1, float2);
symbolTable.insertBuiltIn(float3, "step", float1, float3);
symbolTable.insertBuiltIn(float4, "step", float1, float4);
s.append(TString("float smoothstep(float edge0, float edge1, float x);"));
s.append(TString("vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x);"));
s.append(TString("vec3 smoothstep(vec3 edge0, vec3 edge1, vec3 x);"));
s.append(TString("vec4 smoothstep(vec4 edge0, vec4 edge1, vec4 x);"));
s.append(TString("vec2 smoothstep(float edge0, float edge1, vec2 x);"));
s.append(TString("vec3 smoothstep(float edge0, float edge1, vec3 x);"));
s.append(TString("vec4 smoothstep(float edge0, float edge1, vec4 x);"));
symbolTable.insertBuiltIn(float1, "smoothstep", float1, float1, float1);
symbolTable.insertBuiltIn(float2, "smoothstep", float2, float2, float2);
symbolTable.insertBuiltIn(float3, "smoothstep", float3, float3, float3);
symbolTable.insertBuiltIn(float4, "smoothstep", float4, float4, float4);
symbolTable.insertBuiltIn(float2, "smoothstep", float1, float1, float2);
symbolTable.insertBuiltIn(float3, "smoothstep", float1, float1, float3);
symbolTable.insertBuiltIn(float4, "smoothstep", float1, float1, float4);
//
// Geometric Functions.
//
s.append(TString("float length(float x);"));
s.append(TString("float length(vec2 x);"));
s.append(TString("float length(vec3 x);"));
s.append(TString("float length(vec4 x);"));
symbolTable.insertBuiltIn(float1, "length", float1);
symbolTable.insertBuiltIn(float1, "length", float2);
symbolTable.insertBuiltIn(float1, "length", float3);
symbolTable.insertBuiltIn(float1, "length", float4);
s.append(TString("float distance(float p0, float p1);"));
s.append(TString("float distance(vec2 p0, vec2 p1);"));
s.append(TString("float distance(vec3 p0, vec3 p1);"));
s.append(TString("float distance(vec4 p0, vec4 p1);"));
symbolTable.insertBuiltIn(float1, "distance", float1, float1);
symbolTable.insertBuiltIn(float1, "distance", float2, float2);
symbolTable.insertBuiltIn(float1, "distance", float3, float3);
symbolTable.insertBuiltIn(float1, "distance", float4, float4);
s.append(TString("float dot(float x, float y);"));
s.append(TString("float dot(vec2 x, vec2 y);"));
s.append(TString("float dot(vec3 x, vec3 y);"));
s.append(TString("float dot(vec4 x, vec4 y);"));
symbolTable.insertBuiltIn(float1, "dot", float1, float1);
symbolTable.insertBuiltIn(float1, "dot", float2, float2);
symbolTable.insertBuiltIn(float1, "dot", float3, float3);
symbolTable.insertBuiltIn(float1, "dot", float4, float4);
s.append(TString("vec3 cross(vec3 x, vec3 y);"));
s.append(TString("float normalize(float x);"));
s.append(TString("vec2 normalize(vec2 x);"));
s.append(TString("vec3 normalize(vec3 x);"));
s.append(TString("vec4 normalize(vec4 x);"));
symbolTable.insertBuiltIn(float3, "cross", float3, float3);
symbolTable.insertBuiltIn(float1, "normalize", float1);
symbolTable.insertBuiltIn(float2, "normalize", float2);
symbolTable.insertBuiltIn(float3, "normalize", float3);
symbolTable.insertBuiltIn(float4, "normalize", float4);
s.append(TString("float faceforward(float N, float I, float Nref);"));
s.append(TString("vec2 faceforward(vec2 N, vec2 I, vec2 Nref);"));
s.append(TString("vec3 faceforward(vec3 N, vec3 I, vec3 Nref);"));
s.append(TString("vec4 faceforward(vec4 N, vec4 I, vec4 Nref);"));
symbolTable.insertBuiltIn(float1, "faceforward", float1, float1, float1);
symbolTable.insertBuiltIn(float2, "faceforward", float2, float2, float2);
symbolTable.insertBuiltIn(float3, "faceforward", float3, float3, float3);
symbolTable.insertBuiltIn(float4, "faceforward", float4, float4, float4);
s.append(TString("float reflect(float I, float N);"));
s.append(TString("vec2 reflect(vec2 I, vec2 N);"));
s.append(TString("vec3 reflect(vec3 I, vec3 N);"));
s.append(TString("vec4 reflect(vec4 I, vec4 N);"));
symbolTable.insertBuiltIn(float1, "reflect", float1, float1);
symbolTable.insertBuiltIn(float2, "reflect", float2, float2);
symbolTable.insertBuiltIn(float3, "reflect", float3, float3);
symbolTable.insertBuiltIn(float4, "reflect", float4, float4);
s.append(TString("float refract(float I, float N, float eta);"));
s.append(TString("vec2 refract(vec2 I, vec2 N, float eta);"));
s.append(TString("vec3 refract(vec3 I, vec3 N, float eta);"));
s.append(TString("vec4 refract(vec4 I, vec4 N, float eta);"));
symbolTable.insertBuiltIn(float1, "refract", float1, float1, float1);
symbolTable.insertBuiltIn(float2, "refract", float2, float2, float1);
symbolTable.insertBuiltIn(float3, "refract", float3, float3, float1);
symbolTable.insertBuiltIn(float4, "refract", float4, float4, float1);
TType *mat2 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 2, true);
TType *mat3 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 3, true);
TType *mat4 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 4, true);
//
// Matrix Functions.
//
s.append(TString("mat2 matrixCompMult(mat2 x, mat2 y);"));
s.append(TString("mat3 matrixCompMult(mat3 x, mat3 y);"));
s.append(TString("mat4 matrixCompMult(mat4 x, mat4 y);"));
symbolTable.insertBuiltIn(mat2, "matrixCompMult", mat2, mat2);
symbolTable.insertBuiltIn(mat3, "matrixCompMult", mat3, mat3);
symbolTable.insertBuiltIn(mat4, "matrixCompMult", mat4, mat4);
TType *bool1 = new TType(EbtBool, EbpUndefined, EvqGlobal, 1);
TType *bool2 = new TType(EbtBool, EbpUndefined, EvqGlobal, 2);
TType *bool3 = new TType(EbtBool, EbpUndefined, EvqGlobal, 3);
TType *bool4 = new TType(EbtBool, EbpUndefined, EvqGlobal, 4);
//
// Vector relational functions.
//
s.append(TString("bvec2 lessThan(vec2 x, vec2 y);"));
s.append(TString("bvec3 lessThan(vec3 x, vec3 y);"));
s.append(TString("bvec4 lessThan(vec4 x, vec4 y);"));
symbolTable.insertBuiltIn(bool2, "lessThan", float2, float2);
symbolTable.insertBuiltIn(bool3, "lessThan", float3, float3);
symbolTable.insertBuiltIn(bool4, "lessThan", float4, float4);
s.append(TString("bvec2 lessThan(ivec2 x, ivec2 y);"));
s.append(TString("bvec3 lessThan(ivec3 x, ivec3 y);"));
s.append(TString("bvec4 lessThan(ivec4 x, ivec4 y);"));
symbolTable.insertBuiltIn(bool2, "lessThan", int2, int2);
symbolTable.insertBuiltIn(bool3, "lessThan", int3, int3);
symbolTable.insertBuiltIn(bool4, "lessThan", int4, int4);
s.append(TString("bvec2 lessThanEqual(vec2 x, vec2 y);"));
s.append(TString("bvec3 lessThanEqual(vec3 x, vec3 y);"));
s.append(TString("bvec4 lessThanEqual(vec4 x, vec4 y);"));
symbolTable.insertBuiltIn(bool2, "lessThanEqual", float2, float2);
symbolTable.insertBuiltIn(bool3, "lessThanEqual", float3, float3);
symbolTable.insertBuiltIn(bool4, "lessThanEqual", float4, float4);
s.append(TString("bvec2 lessThanEqual(ivec2 x, ivec2 y);"));
s.append(TString("bvec3 lessThanEqual(ivec3 x, ivec3 y);"));
s.append(TString("bvec4 lessThanEqual(ivec4 x, ivec4 y);"));
symbolTable.insertBuiltIn(bool2, "lessThanEqual", int2, int2);
symbolTable.insertBuiltIn(bool3, "lessThanEqual", int3, int3);
symbolTable.insertBuiltIn(bool4, "lessThanEqual", int4, int4);
s.append(TString("bvec2 greaterThan(vec2 x, vec2 y);"));
s.append(TString("bvec3 greaterThan(vec3 x, vec3 y);"));
s.append(TString("bvec4 greaterThan(vec4 x, vec4 y);"));
symbolTable.insertBuiltIn(bool2, "greaterThan", float2, float2);
symbolTable.insertBuiltIn(bool3, "greaterThan", float3, float3);
symbolTable.insertBuiltIn(bool4, "greaterThan", float4, float4);
s.append(TString("bvec2 greaterThan(ivec2 x, ivec2 y);"));
s.append(TString("bvec3 greaterThan(ivec3 x, ivec3 y);"));
s.append(TString("bvec4 greaterThan(ivec4 x, ivec4 y);"));
symbolTable.insertBuiltIn(bool2, "greaterThan", int2, int2);
symbolTable.insertBuiltIn(bool3, "greaterThan", int3, int3);
symbolTable.insertBuiltIn(bool4, "greaterThan", int4, int4);
s.append(TString("bvec2 greaterThanEqual(vec2 x, vec2 y);"));
s.append(TString("bvec3 greaterThanEqual(vec3 x, vec3 y);"));
s.append(TString("bvec4 greaterThanEqual(vec4 x, vec4 y);"));
symbolTable.insertBuiltIn(bool2, "greaterThanEqual", float2, float2);
symbolTable.insertBuiltIn(bool3, "greaterThanEqual", float3, float3);
symbolTable.insertBuiltIn(bool4, "greaterThanEqual", float4, float4);
s.append(TString("bvec2 greaterThanEqual(ivec2 x, ivec2 y);"));
s.append(TString("bvec3 greaterThanEqual(ivec3 x, ivec3 y);"));
s.append(TString("bvec4 greaterThanEqual(ivec4 x, ivec4 y);"));
symbolTable.insertBuiltIn(bool2, "greaterThanEqual", int2, int2);
symbolTable.insertBuiltIn(bool3, "greaterThanEqual", int3, int3);
symbolTable.insertBuiltIn(bool4, "greaterThanEqual", int4, int4);
s.append(TString("bvec2 equal(vec2 x, vec2 y);"));
s.append(TString("bvec3 equal(vec3 x, vec3 y);"));
s.append(TString("bvec4 equal(vec4 x, vec4 y);"));
symbolTable.insertBuiltIn(bool2, "equal", float2, float2);
symbolTable.insertBuiltIn(bool3, "equal", float3, float3);
symbolTable.insertBuiltIn(bool4, "equal", float4, float4);
s.append(TString("bvec2 equal(ivec2 x, ivec2 y);"));
s.append(TString("bvec3 equal(ivec3 x, ivec3 y);"));
s.append(TString("bvec4 equal(ivec4 x, ivec4 y);"));
symbolTable.insertBuiltIn(bool2, "equal", int2, int2);
symbolTable.insertBuiltIn(bool3, "equal", int3, int3);
symbolTable.insertBuiltIn(bool4, "equal", int4, int4);
s.append(TString("bvec2 equal(bvec2 x, bvec2 y);"));
s.append(TString("bvec3 equal(bvec3 x, bvec3 y);"));
s.append(TString("bvec4 equal(bvec4 x, bvec4 y);"));
symbolTable.insertBuiltIn(bool2, "equal", bool2, bool2);
symbolTable.insertBuiltIn(bool3, "equal", bool3, bool3);
symbolTable.insertBuiltIn(bool4, "equal", bool4, bool4);
s.append(TString("bvec2 notEqual(vec2 x, vec2 y);"));
s.append(TString("bvec3 notEqual(vec3 x, vec3 y);"));
s.append(TString("bvec4 notEqual(vec4 x, vec4 y);"));
symbolTable.insertBuiltIn(bool2, "notEqual", float2, float2);
symbolTable.insertBuiltIn(bool3, "notEqual", float3, float3);
symbolTable.insertBuiltIn(bool4, "notEqual", float4, float4);
s.append(TString("bvec2 notEqual(ivec2 x, ivec2 y);"));
s.append(TString("bvec3 notEqual(ivec3 x, ivec3 y);"));
s.append(TString("bvec4 notEqual(ivec4 x, ivec4 y);"));
symbolTable.insertBuiltIn(bool2, "notEqual", int2, int2);
symbolTable.insertBuiltIn(bool3, "notEqual", int3, int3);
symbolTable.insertBuiltIn(bool4, "notEqual", int4, int4);
s.append(TString("bvec2 notEqual(bvec2 x, bvec2 y);"));
s.append(TString("bvec3 notEqual(bvec3 x, bvec3 y);"));
s.append(TString("bvec4 notEqual(bvec4 x, bvec4 y);"));
symbolTable.insertBuiltIn(bool2, "notEqual", bool2, bool2);
symbolTable.insertBuiltIn(bool3, "notEqual", bool3, bool3);
symbolTable.insertBuiltIn(bool4, "notEqual", bool4, bool4);
s.append(TString("bool any(bvec2 x);"));
s.append(TString("bool any(bvec3 x);"));
s.append(TString("bool any(bvec4 x);"));
symbolTable.insertBuiltIn(bool1, "any", bool2);
symbolTable.insertBuiltIn(bool1, "any", bool3);
symbolTable.insertBuiltIn(bool1, "any", bool4);
s.append(TString("bool all(bvec2 x);"));
s.append(TString("bool all(bvec3 x);"));
s.append(TString("bool all(bvec4 x);"));
symbolTable.insertBuiltIn(bool1, "all", bool2);
symbolTable.insertBuiltIn(bool1, "all", bool3);
symbolTable.insertBuiltIn(bool1, "all", bool4);
s.append(TString("bvec2 not(bvec2 x);"));
s.append(TString("bvec3 not(bvec3 x);"));
s.append(TString("bvec4 not(bvec4 x);"));
symbolTable.insertBuiltIn(bool2, "not", bool2);
symbolTable.insertBuiltIn(bool3, "not", bool3);
symbolTable.insertBuiltIn(bool4, "not", bool4);
TType *sampler2D = new TType(EbtSampler2D, EbpUndefined, EvqGlobal, 1);
TType *samplerCube = new TType(EbtSamplerCube, EbpUndefined, EvqGlobal, 1);
//
// Texture Functions.
// Texture Functions for GLSL ES 1.0
//
s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord);"));
s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord);"));
s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord);"));
s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord);"));
symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2);
symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3);
symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4);
symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3);
if (resources.OES_EGL_image_external) {
s.append(TString("vec4 texture2D(samplerExternalOES sampler, vec2 coord);"));
s.append(TString("vec4 texture2DProj(samplerExternalOES sampler, vec3 coord);"));
s.append(TString("vec4 texture2DProj(samplerExternalOES sampler, vec4 coord);"));
if (resources.OES_EGL_image_external)
{
TType *samplerExternalOES = new TType(EbtSamplerExternalOES, EbpUndefined, EvqGlobal, 1);
symbolTable.insertBuiltIn(float4, "texture2D", samplerExternalOES, float2);
symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float3);
symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float4);
}
if (resources.ARB_texture_rectangle) {
s.append(TString("vec4 texture2DRect(sampler2DRect sampler, vec2 coord);"));
s.append(TString("vec4 texture2DRectProj(sampler2DRect sampler, vec3 coord);"));
s.append(TString("vec4 texture2DRectProj(sampler2DRect sampler, vec4 coord);"));
if (resources.ARB_texture_rectangle)
{
TType *sampler2DRect = new TType(EbtSampler2DRect, EbpUndefined, EvqGlobal, 1);
symbolTable.insertBuiltIn(float4, "texture2DRect", sampler2DRect, float2);
symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float3);
symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float4);
}
//
// Noise functions.
//
//s.append(TString("float noise1(float x);"));
//s.append(TString("float noise1(vec2 x);"));
//s.append(TString("float noise1(vec3 x);"));
//s.append(TString("float noise1(vec4 x);"));
if (type == SH_FRAGMENT_SHADER)
{
symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2, float1);
symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3, float1);
symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4, float1);
symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3, float1);
//s.append(TString("vec2 noise2(float x);"));
//s.append(TString("vec2 noise2(vec2 x);"));
//s.append(TString("vec2 noise2(vec3 x);"));
//s.append(TString("vec2 noise2(vec4 x);"));
if (resources.OES_standard_derivatives)
{
symbolTable.insertBuiltIn(float1, "dFdx", float1);
symbolTable.insertBuiltIn(float2, "dFdx", float2);
symbolTable.insertBuiltIn(float3, "dFdx", float3);
symbolTable.insertBuiltIn(float4, "dFdx", float4);
//s.append(TString("vec3 noise3(float x);"));
//s.append(TString("vec3 noise3(vec2 x);"));
//s.append(TString("vec3 noise3(vec3 x);"));
//s.append(TString("vec3 noise3(vec4 x);"));
symbolTable.insertBuiltIn(float1, "dFdy", float1);
symbolTable.insertBuiltIn(float2, "dFdy", float2);
symbolTable.insertBuiltIn(float3, "dFdy", float3);
symbolTable.insertBuiltIn(float4, "dFdy", float4);
//s.append(TString("vec4 noise4(float x);"));
//s.append(TString("vec4 noise4(vec2 x);"));
//s.append(TString("vec4 noise4(vec3 x);"));
//s.append(TString("vec4 noise4(vec4 x);"));
return s;
}
//============================================================================
//
// Prototypes for built-in functions seen by vertex shaders only.
//
//============================================================================
static TString BuiltInFunctionsVertex(const ShBuiltInResources& resources)
{
TString s;
//
// Geometric Functions.
//
//s.append(TString("vec4 ftransform();"));
//
// Texture Functions.
//
s.append(TString("vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod);"));
s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);"));
s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);"));
s.append(TString("vec4 textureCubeLod(samplerCube sampler, vec3 coord, float lod);"));
return s;
}
//============================================================================
//
// Prototypes for built-in functions seen by fragment shaders only.
//
//============================================================================
static TString BuiltInFunctionsFragment(const ShBuiltInResources& resources)
{
TString s;
//
// Texture Functions.
//
s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord, float bias);"));
s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias);"));
s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord, float bias);"));
s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord, float bias);"));
if (resources.OES_standard_derivatives) {
s.append(TString("float dFdx(float p);"));
s.append(TString("vec2 dFdx(vec2 p);"));
s.append(TString("vec3 dFdx(vec3 p);"));
s.append(TString("vec4 dFdx(vec4 p);"));
s.append(TString("float dFdy(float p);"));
s.append(TString("vec2 dFdy(vec2 p);"));
s.append(TString("vec3 dFdy(vec3 p);"));
s.append(TString("vec4 dFdy(vec4 p);"));
s.append(TString("float fwidth(float p);"));
s.append(TString("vec2 fwidth(vec2 p);"));
s.append(TString("vec3 fwidth(vec3 p);"));
s.append(TString("vec4 fwidth(vec4 p);"));
symbolTable.insertBuiltIn(float1, "fwidth", float1);
symbolTable.insertBuiltIn(float2, "fwidth", float2);
symbolTable.insertBuiltIn(float3, "fwidth", float3);
symbolTable.insertBuiltIn(float4, "fwidth", float4);
}
}
return s;
}
//============================================================================
//
// Standard uniforms.
//
//============================================================================
static TString StandardUniforms()
{
TString s;
if(type == SH_VERTEX_SHADER)
{
symbolTable.insertBuiltIn(float4, "texture2DLod", sampler2D, float2, float1);
symbolTable.insertBuiltIn(float4, "texture2DProjLod", sampler2D, float3, float1);
symbolTable.insertBuiltIn(float4, "texture2DProjLod", sampler2D, float4, float1);
symbolTable.insertBuiltIn(float4, "textureCubeLod", samplerCube, float3, float1);
}
//
// Depth range in window coordinates
//
s.append(TString("struct gl_DepthRangeParameters {"));
s.append(TString(" highp float near;")); // n
s.append(TString(" highp float far;")); // f
s.append(TString(" highp float diff;")); // f - n
s.append(TString("};"));
s.append(TString("uniform gl_DepthRangeParameters gl_DepthRange;"));
TFieldList *fields = NewPoolTFieldList();
TField *near = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("near"));
TField *far = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("far"));
TField *diff = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("diff"));
fields->push_back(near);
fields->push_back(far);
fields->push_back(diff);
TStructure *depthRangeStruct = new TStructure(NewPoolTString("gl_DepthRangeParameters"), fields);
TVariable *depthRangeParameters = new TVariable(&depthRangeStruct->name(), depthRangeStruct, true);
symbolTable.insert(*depthRangeParameters);
TVariable *depthRange = new TVariable(NewPoolTString("gl_DepthRange"), TType(depthRangeStruct));
depthRange->setQualifier(EvqUniform);
symbolTable.insert(*depthRange);
return s;
}
//============================================================================
//
// Default precision for vertex shaders.
//
//============================================================================
static TString DefaultPrecisionVertex()
{
TString s;
s.append(TString("precision highp int;"));
s.append(TString("precision highp float;"));
return s;
}
//============================================================================
//
// Default precision for fragment shaders.
//
//============================================================================
static TString DefaultPrecisionFragment()
{
TString s;
s.append(TString("precision mediump int;"));
// No default precision for float in fragment shaders
return s;
}
//============================================================================
//
// Implementation dependent built-in constants.
//
//============================================================================
static TString BuiltInConstants(ShShaderSpec spec, const ShBuiltInResources &resources)
{
TStringStream s;
s << "const int gl_MaxVertexAttribs = " << resources.MaxVertexAttribs << ";";
s << "const int gl_MaxVertexUniformVectors = " << resources.MaxVertexUniformVectors << ";";
s << "const int gl_MaxVaryingVectors = " << resources.MaxVaryingVectors << ";";
s << "const int gl_MaxVertexTextureImageUnits = " << resources.MaxVertexTextureImageUnits << ";";
s << "const int gl_MaxCombinedTextureImageUnits = " << resources.MaxCombinedTextureImageUnits << ";";
s << "const int gl_MaxTextureImageUnits = " << resources.MaxTextureImageUnits << ";";
s << "const int gl_MaxFragmentUniformVectors = " << resources.MaxFragmentUniformVectors << ";";
//
// Implementation dependent built-in constants.
//
symbolTable.insertConstInt("gl_MaxVertexAttribs", resources.MaxVertexAttribs);
symbolTable.insertConstInt("gl_MaxVertexUniformVectors", resources.MaxVertexUniformVectors);
symbolTable.insertConstInt("gl_MaxVaryingVectors", resources.MaxVaryingVectors);
symbolTable.insertConstInt("gl_MaxVertexTextureImageUnits", resources.MaxVertexTextureImageUnits);
symbolTable.insertConstInt("gl_MaxCombinedTextureImageUnits", resources.MaxCombinedTextureImageUnits);
symbolTable.insertConstInt("gl_MaxTextureImageUnits", resources.MaxTextureImageUnits);
symbolTable.insertConstInt("gl_MaxFragmentUniformVectors", resources.MaxFragmentUniformVectors);
if (spec != SH_CSS_SHADERS_SPEC)
s << "const int gl_MaxDrawBuffers = " << resources.MaxDrawBuffers << ";";
return s.str();
}
void TBuiltIns::initialize(ShShaderType type, ShShaderSpec spec,
const ShBuiltInResources& resources)
{
switch (type) {
case SH_FRAGMENT_SHADER:
builtInStrings.push_back(DefaultPrecisionFragment());
builtInStrings.push_back(BuiltInFunctionsCommon(resources));
builtInStrings.push_back(BuiltInFunctionsFragment(resources));
builtInStrings.push_back(StandardUniforms());
break;
case SH_VERTEX_SHADER:
builtInStrings.push_back(DefaultPrecisionVertex());
builtInStrings.push_back(BuiltInFunctionsCommon(resources));
builtInStrings.push_back(BuiltInFunctionsVertex(resources));
builtInStrings.push_back(StandardUniforms());
break;
default: assert(false && "Language not supported");
{
symbolTable.insertConstInt("gl_MaxDrawBuffers", resources.MaxDrawBuffers);
}
builtInStrings.push_back(BuiltInConstants(spec, resources));
}
void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
const ShBuiltInResources& resources,
TSymbolTable& symbolTable)
const ShBuiltInResources &resources,
TSymbolTable &symbolTable)
{
//
// First, insert some special built-in variables that are not in
@ -539,6 +439,10 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
if (spec != SH_CSS_SHADERS_SPEC) {
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)));
if (resources.EXT_frag_depth) {
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragDepthEXT"), TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1)));
symbolTable.relateToExtension("gl_FragDepthEXT", "GL_EXT_frag_depth");
}
} 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)));
@ -560,8 +464,6 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
// expected to be resolved through a library of functions, versus as
// operations.
//
symbolTable.relateToOperator("not", EOpVectorLogicalNot);
symbolTable.relateToOperator("matrixCompMult", EOpMul);
symbolTable.relateToOperator("equal", EOpVectorEqual);
@ -612,6 +514,7 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
symbolTable.relateToOperator("any", EOpAny);
symbolTable.relateToOperator("all", EOpAll);
symbolTable.relateToOperator("not", EOpVectorLogicalNot);
// Map language-specific operators.
switch(type) {
@ -656,4 +559,6 @@ void InitExtensionBehavior(const ShBuiltInResources& resources,
extBehavior["GL_ARB_texture_rectangle"] = EBhUndefined;
if (resources.EXT_draw_buffers)
extBehavior["GL_EXT_draw_buffers"] = EBhUndefined;
if (resources.EXT_frag_depth)
extBehavior["GL_EXT_frag_depth"] = EBhUndefined;
}

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2013 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.
//
@ -11,19 +11,7 @@
#include "compiler/ShHandle.h"
#include "compiler/SymbolTable.h"
typedef TVector<TString> TBuiltInStrings;
class TBuiltIns {
public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
void initialize(ShShaderType type, ShShaderSpec spec,
const ShBuiltInResources& resources);
const TBuiltInStrings& getBuiltInStrings() { return builtInStrings; }
protected:
TBuiltInStrings builtInStrings;
};
void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &table);
void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
const ShBuiltInResources& resources,

View File

@ -10,25 +10,8 @@
#include "compiler/InitializeParseContext.h"
#include "compiler/osinclude.h"
OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
bool InitProcess()
{
if (ThreadInitializeIndex != OS_INVALID_TLS_INDEX) {
//
// Function is re-entrant.
//
return true;
}
ThreadInitializeIndex = OS_AllocTLSIndex();
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
assert(0 && "InitProcess(): Failed to allocate TLS area for init flag");
return false;
}
if (!InitializePoolIndex()) {
assert(0 && "InitProcess(): Failed to initalize global pool");
return false;
@ -39,77 +22,11 @@ bool InitProcess()
return false;
}
return InitThread();
}
bool DetachProcess()
{
bool success = true;
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
return true;
success = DetachThread();
if (!FreeParseContextIndex())
success = false;
FreePoolIndex();
OS_FreeTLSIndex(ThreadInitializeIndex);
ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
return success;
}
bool InitThread()
{
//
// This function is re-entrant
//
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
assert(0 && "InitThread(): Process hasn't been initalised.");
return false;
}
if (OS_GetTLSValue(ThreadInitializeIndex) != 0)
return true;
InitializeGlobalPools();
if (!InitializeGlobalParseContext())
return false;
if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) {
assert(0 && "InitThread(): Unable to set init flag.");
return false;
}
return true;
}
bool DetachThread()
void DetachProcess()
{
bool success = true;
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
return true;
//
// Function is re-entrant and this thread may not have been initalised.
//
if (OS_GetTLSValue(ThreadInitializeIndex) != 0) {
if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)0)) {
assert(0 && "DetachThread(): Unable to clear init flag.");
success = false;
}
if (!FreeParseContext())
success = false;
FreeGlobalPools();
}
return success;
FreeParseContextIndex();
FreePoolIndex();
}

View File

@ -7,10 +7,7 @@
#define __INITIALIZEDLL_H
bool InitProcess();
bool DetachProcess();
bool InitThread();
bool DetachThread();
void DetachProcess();
#endif // __INITIALIZEDLL_H

View File

@ -0,0 +1,61 @@
//
// Copyright (c) 2002-2013 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/InitializeGLPosition.h"
#include "compiler/debug.h"
bool InitializeGLPosition::visitAggregate(Visit visit, TIntermAggregate* node)
{
bool visitChildren = !mCodeInserted;
switch (node->getOp())
{
case EOpSequence: break;
case EOpFunction:
{
// Function definition.
ASSERT(visit == PreVisit);
if (node->getName() == "main(")
{
TIntermSequence &sequence = node->getSequence();
ASSERT((sequence.size() == 1) || (sequence.size() == 2));
TIntermAggregate *body = NULL;
if (sequence.size() == 1)
{
body = new TIntermAggregate(EOpSequence);
sequence.push_back(body);
}
else
{
body = sequence[1]->getAsAggregate();
}
ASSERT(body);
insertCode(body->getSequence());
mCodeInserted = true;
}
break;
}
default: visitChildren = false; break;
}
return visitChildren;
}
void InitializeGLPosition::insertCode(TIntermSequence& sequence)
{
TIntermBinary *binary = new TIntermBinary(EOpAssign);
sequence.insert(sequence.begin(), binary);
TIntermSymbol *left = new TIntermSymbol(
0, "gl_Position", TType(EbtFloat, EbpUndefined, EvqPosition, 4));
binary->setLeft(left);
ConstantUnion *u = new ConstantUnion[4];
for (int ii = 0; ii < 3; ++ii)
u[ii].setFConst(0.0f);
u[3].setFConst(1.0f);
TIntermConstantUnion *right = new TIntermConstantUnion(
u, TType(EbtFloat, EbpUndefined, EvqConst, 4));
binary->setRight(right);
}

View File

@ -0,0 +1,33 @@
//
// Copyright (c) 2002-2013 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_INITIALIZE_GL_POSITION_H_
#define COMPILER_INITIALIZE_GL_POSITION_H_
#include "compiler/intermediate.h"
class InitializeGLPosition : public TIntermTraverser
{
public:
InitializeGLPosition() : mCodeInserted(false) { }
protected:
virtual bool visitBinary(Visit visit, TIntermBinary* node) { return false; }
virtual bool visitUnary(Visit visit, TIntermUnary* node) { return false; }
virtual bool visitSelection(Visit visit, TIntermSelection* node) { return false; }
virtual bool visitLoop(Visit visit, TIntermLoop* node) { return false; }
virtual bool visitBranch(Visit visit, TIntermBranch* node) { return false; }
virtual bool visitAggregate(Visit visit, TIntermAggregate* node);
private:
// Insert AST node in the beginning of main() for "gl_Position = vec4(0.0, 0.0, 0.0, 1.0);".
void insertCode(TIntermSequence& sequence);
bool mCodeInserted;
};
#endif // COMPILER_INITIALIZE_GL_POSITION_H_

View File

@ -7,8 +7,6 @@
#ifndef __INITIALIZE_GLOBALS_INCLUDED_
#define __INITIALIZE_GLOBALS_INCLUDED_
void InitializeGlobalPools();
void FreeGlobalPools();
bool InitializePoolIndex();
void FreePoolIndex();

View File

@ -12,85 +12,29 @@ OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
bool InitializeParseContextIndex()
{
if (GlobalParseContextIndex != OS_INVALID_TLS_INDEX) {
assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
return false;
}
assert(GlobalParseContextIndex == OS_INVALID_TLS_INDEX);
//
// Allocate a TLS index.
//
GlobalParseContextIndex = OS_AllocTLSIndex();
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
return false;
}
return true;
return GlobalParseContextIndex != OS_INVALID_TLS_INDEX;
}
bool FreeParseContextIndex()
void FreeParseContextIndex()
{
OS_TLSIndex tlsiIndex = GlobalParseContextIndex;
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
assert(0 && "FreeParseContextIndex(): Parse Context index not initalized");
return false;
}
assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
OS_FreeTLSIndex(GlobalParseContextIndex);
GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
return OS_FreeTLSIndex(tlsiIndex);
}
bool InitializeGlobalParseContext()
void SetGlobalParseContext(TParseContext* context)
{
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalized");
return false;
}
TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
if (lpParseContext != 0) {
assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
return false;
}
TThreadParseContext *lpThreadData = new TThreadParseContext();
if (lpThreadData == 0) {
assert(0 && "InitializeGlobalParseContext(): Unable to create thread parse context");
return false;
}
lpThreadData->lpGlobalParseContext = 0;
OS_SetTLSValue(GlobalParseContextIndex, lpThreadData);
return true;
assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
OS_SetTLSValue(GlobalParseContextIndex, context);
}
bool FreeParseContext()
TParseContext* GetGlobalParseContext()
{
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
assert(0 && "FreeParseContext(): Parse Context index not initalized");
return false;
}
TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
if (lpParseContext)
delete lpParseContext;
return true;
}
TParseContextPointer& GetGlobalParseContext()
{
//
// Minimal error checking for speed
//
TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
return lpParseContext->lpGlobalParseContext;
assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
return static_cast<TParseContext*>(OS_GetTLSValue(GlobalParseContextIndex));
}

View File

@ -8,19 +8,10 @@
#define __INITIALIZE_PARSE_CONTEXT_INCLUDED_
bool InitializeParseContextIndex();
bool FreeParseContextIndex();
bool InitializeGlobalParseContext();
bool FreeParseContext();
void FreeParseContextIndex();
struct TParseContext;
typedef TParseContext* TParseContextPointer;
extern TParseContextPointer& GetGlobalParseContext();
#define GlobalParseContext GetGlobalParseContext()
typedef struct TThreadParseContextRec
{
TParseContext *lpGlobalParseContext;
} TThreadParseContext;
extern void SetGlobalParseContext(TParseContext* context);
extern TParseContext* GetGlobalParseContext();
#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_

View File

@ -131,7 +131,7 @@ const char* getOperatorString(TOperator op) {
//
// Returns the added node.
//
TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, TSourceLoc line)
TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc& line)
{
TIntermSymbol* node = new TIntermSymbol(id, name, type);
node->setLine(line);
@ -144,7 +144,7 @@ TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType
//
// Returns the added node.
//
TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TSymbolTable& symbolTable)
TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line, TSymbolTable& symbolTable)
{
switch (op) {
case EOpEqual:
@ -200,8 +200,6 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
// one and promote it to the right type.
//
TIntermBinary* node = new TIntermBinary(op);
if (line == 0)
line = right->getLine();
node->setLine(line);
node->setLeft(left);
@ -230,15 +228,13 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
//
// Returns the added node.
//
TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line)
{
//
// Like adding binary math, except the conversion can only go
// from right to left.
//
TIntermBinary* node = new TIntermBinary(op);
if (line == 0)
line = left->getLine();
node->setLine(line);
TIntermTyped* child = addConversion(op, left->getType(), right);
@ -260,11 +256,9 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm
// Returns the added node.
// The caller should set the type of the returned node.
//
TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc line)
TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc& line)
{
TIntermBinary* node = new TIntermBinary(op);
if (line == 0)
line = index->getLine();
node->setLine(line);
node->setLeft(base);
node->setRight(index);
@ -279,13 +273,13 @@ TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermT
//
// Returns the added node.
//
TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line, TSymbolTable& symbolTable)
TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, const TSourceLoc& line, TSymbolTable& symbolTable)
{
TIntermUnary* node;
TIntermTyped* child = childNode->getAsTyped();
if (child == 0) {
infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
infoSink.info.message(EPrefixInternalError, line, "Bad type in AddUnaryMath");
return 0;
}
@ -348,8 +342,6 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode,
// Make a new node for the operator.
//
node = new TIntermUnary(op);
if (line == 0)
line = child->getLine();
node->setLine(line);
node->setOperand(child);
@ -376,7 +368,7 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode,
// Returns an aggregate node, which could be the one passed in if
// it was already an aggregate but no operator was set.
//
TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, TSourceLoc line)
TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc& line)
{
TIntermAggregate* aggNode;
@ -391,8 +383,6 @@ TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperat
//
aggNode = new TIntermAggregate();
aggNode->getSequence().push_back(node);
if (line == 0)
line = node->getLine();
}
} else
aggNode = new TIntermAggregate();
@ -401,8 +391,7 @@ TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperat
// Set the operator.
//
aggNode->setOp(op);
if (line != 0)
aggNode->setLine(line);
aggNode->setLine(line);
return aggNode;
}
@ -491,7 +480,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
case EbtInt: newOp = EOpConvIntToFloat; break;
case EbtBool: newOp = EOpConvBoolToFloat; break;
default:
infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
return 0;
}
break;
@ -500,7 +489,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
case EbtInt: newOp = EOpConvIntToBool; break;
case EbtFloat: newOp = EOpConvFloatToBool; break;
default:
infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
return 0;
}
break;
@ -509,12 +498,12 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
case EbtBool: newOp = EOpConvBoolToInt; break;
case EbtFloat: newOp = EOpConvFloatToInt; break;
default:
infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
return 0;
}
break;
default:
infoSink.info.message(EPrefixInternalError, "Bad promotion type", node->getLine());
infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion type");
return 0;
}
@ -534,7 +523,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
// Returns the resulting aggregate, unless 0 was passed in for
// both existing nodes.
//
TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc line)
TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& line)
{
if (left == 0 && right == 0)
return 0;
@ -551,8 +540,7 @@ TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* r
if (right)
aggNode->getSequence().push_back(right);
if (line != 0)
aggNode->setLine(line);
aggNode->setLine(line);
return aggNode;
}
@ -562,18 +550,14 @@ TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* r
//
// Returns an aggregate, unless 0 was passed in for the existing node.
//
TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc line)
TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& line)
{
if (node == 0)
return 0;
TIntermAggregate* aggNode = new TIntermAggregate;
aggNode->getSequence().push_back(node);
if (line != 0)
aggNode->setLine(line);
else
aggNode->setLine(node->getLine());
aggNode->setLine(line);
return aggNode;
}
@ -585,7 +569,7 @@ TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc lin
//
// Returns the selection node created.
//
TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, TSourceLoc line)
TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& line)
{
//
// For compile time constant selections, prune the code and
@ -606,7 +590,7 @@ TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nod
}
TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line)
{
if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) {
return right;
@ -626,7 +610,7 @@ TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, T
//
// Returns the selection node created, or 0 if one could not be.
//
TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc line)
TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& line)
{
//
// Get compatible types.
@ -669,7 +653,7 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true
// Returns the constant union node created.
//
TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, TSourceLoc line)
TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc& line)
{
TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
node->setLine(line);
@ -677,7 +661,7 @@ TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayP
return node;
}
TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line)
TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& line)
{
TIntermAggregate* node = new TIntermAggregate(EOpSequence);
@ -700,7 +684,7 @@ TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line)
//
// Create loop nodes.
//
TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, TSourceLoc line)
TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc& line)
{
TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
node->setLine(line);
@ -711,12 +695,12 @@ TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTy
//
// Add branches.
//
TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TSourceLoc line)
TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& line)
{
return addBranch(branchOp, 0, line);
}
TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, TSourceLoc line)
TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& line)
{
TIntermBranch* node = new TIntermBranch(branchOp, expression);
node->setLine(line);
@ -861,7 +845,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
{
// This function only handles scalars, vectors, and matrices.
if (left->isArray() || right->isArray()) {
infoSink.info.message(EPrefixInternalError, "Invalid operation for arrays", getLine());
infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operation for arrays");
return false;
}
@ -966,7 +950,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
}
} else {
infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses");
return false;
}
break;
@ -995,7 +979,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
}
} else {
infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses");
return false;
}
break;
@ -1035,23 +1019,22 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
{
const TTypeList* fields = leftNodeType.getStruct();
const TFieldList& fields = leftNodeType.getStruct()->fields();
size_t structSize = fields->size();
int index = 0;
size_t structSize = fields.size();
size_t index = 0;
for (size_t j = 0; j < structSize; j++) {
int size = (*fields)[j].type->getObjectSize();
for (int i = 0; i < size; i++) {
if ((*fields)[j].type->getBasicType() == EbtStruct) {
if (!CompareStructure(*(*fields)[j].type, &rightUnionArray[index], &leftUnionArray[index]))
size_t size = fields[j]->type()->getObjectSize();
for (size_t i = 0; i < size; i++) {
if (fields[j]->type()->getBasicType() == EbtStruct) {
if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index]))
return false;
} else {
if (leftUnionArray[index] != rightUnionArray[index])
return false;
index++;
}
}
}
return true;
@ -1063,10 +1046,10 @@ bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray,
TType typeWithoutArrayness = leftNodeType;
typeWithoutArrayness.clearArrayness();
int arraySize = leftNodeType.getArraySize();
size_t arraySize = leftNodeType.getArraySize();
for (int i = 0; i < arraySize; ++i) {
int offset = typeWithoutArrayness.getObjectSize() * i;
for (size_t i = 0; i < arraySize; ++i) {
size_t offset = typeWithoutArrayness.getObjectSize() * i;
if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
return false;
}
@ -1086,7 +1069,7 @@ bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray,
TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
{
ConstantUnion *unionArray = getUnionArrayPointer();
int objectSize = getType().getObjectSize();
size_t objectSize = getType().getObjectSize();
if (constantNode) { // binary operations
TIntermConstantUnion *node = constantNode->getAsConstantUnion();
@ -1096,13 +1079,13 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
// for a case like float f = 1.2 + vec4(2,3,4,5);
if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
rightUnionArray = new ConstantUnion[objectSize];
for (int i = 0; i < objectSize; ++i)
for (size_t i = 0; i < objectSize; ++i)
rightUnionArray[i] = *node->getUnionArrayPointer();
returnType = getType();
} else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
// for a case like float f = vec4(2,3,4,5) + 1.2;
unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i)
unionArray[i] = *getUnionArrayPointer();
returnType = node->getType();
objectSize = constantNode->getType().getObjectSize();
@ -1116,14 +1099,14 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
case EOpAdd:
tempConstArray = new ConstantUnion[objectSize];
{// support MSVC++6.0
for (int i = 0; i < objectSize; i++)
for (size_t i = 0; i < objectSize; i++)
tempConstArray[i] = unionArray[i] + rightUnionArray[i];
}
break;
case EOpSub:
tempConstArray = new ConstantUnion[objectSize];
{// support MSVC++6.0
for (int i = 0; i < objectSize; i++)
for (size_t i = 0; i < objectSize; i++)
tempConstArray[i] = unionArray[i] - rightUnionArray[i];
}
break;
@ -1133,13 +1116,13 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
case EOpMatrixTimesScalar:
tempConstArray = new ConstantUnion[objectSize];
{// support MSVC++6.0
for (int i = 0; i < objectSize; i++)
for (size_t i = 0; i < objectSize; i++)
tempConstArray[i] = unionArray[i] * rightUnionArray[i];
}
break;
case EOpMatrixTimesMatrix:
if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix multiply");
return 0;
}
{// support MSVC++6.0
@ -1158,11 +1141,11 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
case EOpDiv:
tempConstArray = new ConstantUnion[objectSize];
{// support MSVC++6.0
for (int i = 0; i < objectSize; i++) {
for (size_t i = 0; i < objectSize; i++) {
switch (getType().getBasicType()) {
case EbtFloat:
if (rightUnionArray[i] == 0.0f) {
infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding");
tempConstArray[i].setFConst(unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX);
} else
tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
@ -1170,13 +1153,13 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
case EbtInt:
if (rightUnionArray[i] == 0) {
infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding");
tempConstArray[i].setIConst(INT_MAX);
} else
tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
break;
default:
infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
infoSink.info.message(EPrefixInternalError, getLine(), "Constant folding cannot be done for \"/\"");
return 0;
}
}
@ -1185,7 +1168,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
case EOpMatrixTimesVector:
if (node->getBasicType() != EbtFloat) {
infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix times vector");
return 0;
}
tempConstArray = new ConstantUnion[getNominalSize()];
@ -1206,7 +1189,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
case EOpVectorTimesMatrix:
if (getType().getBasicType() != EbtFloat) {
infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for vector times matrix");
return 0;
}
@ -1224,7 +1207,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
tempConstArray = new ConstantUnion[objectSize];
{// support MSVC++6.0
for (int i = 0; i < objectSize; i++)
for (size_t i = 0; i < objectSize; i++)
tempConstArray[i] = unionArray[i] && rightUnionArray[i];
}
break;
@ -1232,7 +1215,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
tempConstArray = new ConstantUnion[objectSize];
{// support MSVC++6.0
for (int i = 0; i < objectSize; i++)
for (size_t i = 0; i < objectSize; i++)
tempConstArray[i] = unionArray[i] || rightUnionArray[i];
}
break;
@ -1240,7 +1223,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
case EOpLogicalXor:
tempConstArray = new ConstantUnion[objectSize];
{// support MSVC++6.0
for (int i = 0; i < objectSize; i++)
for (size_t i = 0; i < objectSize; i++)
switch (getType().getBasicType()) {
case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
default: assert(false && "Default missing");
@ -1286,7 +1269,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
boolNodeFlag = true;
} else {
for (int i = 0; i < objectSize; i++) {
for (size_t i = 0; i < objectSize; i++) {
if (unionArray[i] != rightUnionArray[i]) {
boolNodeFlag = true;
break; // break out of for loop
@ -1312,7 +1295,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
boolNodeFlag = true;
} else {
for (int i = 0; i < objectSize; i++) {
for (size_t i = 0; i < objectSize; i++) {
if (unionArray[i] == rightUnionArray[i]) {
boolNodeFlag = true;
break; // break out of for loop
@ -1334,7 +1317,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
return tempNode;
default:
infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine());
infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operator for constant folding");
return 0;
}
tempNode = new TIntermConstantUnion(tempConstArray, returnType);
@ -1347,14 +1330,14 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
//
TIntermConstantUnion *newNode = 0;
ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
for (int i = 0; i < objectSize; i++) {
for (size_t i = 0; i < objectSize; i++) {
switch(op) {
case EOpNegative:
switch (getType().getBasicType()) {
case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return 0;
}
break;
@ -1362,7 +1345,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
switch (getType().getBasicType()) {
case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return 0;
}
break;
@ -1378,11 +1361,11 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
{
int size = node->getType().getObjectSize();
size_t size = node->getType().getObjectSize();
ConstantUnion *leftUnionArray = new ConstantUnion[size];
for (int i=0; i < size; i++) {
for (size_t i = 0; i < size; i++) {
switch (promoteTo) {
case EbtFloat:
@ -1397,7 +1380,7 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC
leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
break;
default:
infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
return 0;
}
break;
@ -1413,7 +1396,7 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC
leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
break;
default:
infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
return 0;
}
break;
@ -1429,13 +1412,13 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC
leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
break;
default:
infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
return 0;
}
break;
default:
infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
infoSink.info.message(EPrefixInternalError, node->getLine(), "Incorrect data type found");
return 0;
}

View File

@ -19,3 +19,17 @@ bool TOutputGLSL::writeVariablePrecision(TPrecision)
{
return false;
}
void TOutputGLSL::visitSymbol(TIntermSymbol* node)
{
TInfoSinkBase& out = objSink();
if (node->getSymbol() == "gl_FragDepthEXT")
{
out << "gl_FragDepth";
}
else
{
TOutputGLSLBase::visitSymbol(node);
}
}

View File

@ -20,6 +20,7 @@ public:
protected:
virtual bool writeVariablePrecision(TPrecision);
virtual void visitSymbol(TIntermSymbol* node);
};
#endif // CROSSCOMPILERGLSL_OUTPUTGLSL_H_

View File

@ -79,25 +79,9 @@ void TOutputGLSLBase::writeVariableType(const TType& type)
if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal))
out << type.getQualifierString() << " ";
// Declare the struct if we have not done so already.
if ((type.getBasicType() == EbtStruct) &&
(mDeclaredStructs.find(type.getTypeName()) == mDeclaredStructs.end()))
if ((type.getBasicType() == EbtStruct) && !structDeclared(type.getStruct()))
{
out << "struct " << hashName(type.getTypeName()) << "{\n";
const TTypeList* structure = type.getStruct();
ASSERT(structure != NULL);
for (size_t i = 0; i < structure->size(); ++i)
{
const TType* fieldType = (*structure)[i].type;
ASSERT(fieldType != NULL);
if (writeVariablePrecision(fieldType->getPrecision()))
out << " ";
out << getTypeName(*fieldType) << " " << hashName(fieldType->getFieldName());
if (fieldType->isArray())
out << arrayBrackets(*fieldType);
out << ";\n";
}
out << "}";
mDeclaredStructs.insert(type.getTypeName());
declareStruct(type.getStruct());
}
else
{
@ -138,24 +122,25 @@ const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type,
if (type.getBasicType() == EbtStruct)
{
out << hashName(type.getTypeName()) << "(";
const TTypeList* structure = type.getStruct();
ASSERT(structure != NULL);
for (size_t i = 0; i < structure->size(); ++i)
const TStructure* structure = type.getStruct();
out << hashName(structure->name()) << "(";
const TFieldList& fields = structure->fields();
for (size_t i = 0; i < fields.size(); ++i)
{
const TType* fieldType = (*structure)[i].type;
const TType* fieldType = fields[i]->type();
ASSERT(fieldType != NULL);
pConstUnion = writeConstantUnion(*fieldType, pConstUnion);
if (i != structure->size() - 1) out << ", ";
if (i != fields.size() - 1) out << ", ";
}
out << ")";
}
else
{
int size = type.getObjectSize();
size_t size = type.getObjectSize();
bool writeType = size > 1;
if (writeType) out << getTypeName(type) << "(";
for (int i = 0; i < size; ++i, ++pConstUnion)
for (size_t i = 0; i < size; ++i, ++pConstUnion)
{
switch (pConstUnion->getType())
{
@ -260,12 +245,18 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
case EOpIndexDirectStruct:
if (visit == InVisit)
{
// Here we are writing out "foo.bar", where "foo" is struct
// and "bar" is field. In AST, it is represented as a binary
// node, where left child represents "foo" and right child "bar".
// The node itself represents ".". The struct field "bar" is
// actually stored as an index into TStructure::fields.
out << ".";
// TODO(alokp): ASSERT
TString fieldName = node->getType().getFieldName();
const TStructure* structure = node->getLeft()->getType().getStruct();
const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion();
const TField* field = structure->fields()[index->getIConst(0)];
const TType& structType = node->getLeft()->getType();
if (!mSymbolTable.findBuiltIn(structType.getTypeName()))
TString fieldName = field->name();
if (!mSymbolTable.findBuiltIn(structure->name()))
fieldName = hashName(fieldName);
out << fieldName;
@ -596,7 +587,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node)
{
const TType& type = node->getType();
ASSERT(type.getBasicType() == EbtStruct);
out << hashName(type.getTypeName()) << "(";
out << hashName(type.getStruct()->name()) << "(";
}
else if (visit == InVisit)
{
@ -765,7 +756,7 @@ TString TOutputGLSLBase::getTypeName(const TType& type)
else
{
if (type.getBasicType() == EbtStruct)
out << hashName(type.getTypeName());
out << hashName(type.getStruct()->name());
else
out << type.getBasicString();
}
@ -798,3 +789,29 @@ TString TOutputGLSLBase::hashFunctionName(const TString& mangled_name)
return name;
return hashName(name);
}
bool TOutputGLSLBase::structDeclared(const TStructure* structure) const
{
return mDeclaredStructs.find(structure->name()) != mDeclaredStructs.end();
}
void TOutputGLSLBase::declareStruct(const TStructure* structure)
{
TInfoSinkBase& out = objSink();
out << "struct " << hashName(structure->name()) << "{\n";
const TFieldList& fields = structure->fields();
for (size_t i = 0; i < fields.size(); ++i)
{
const TField* field = fields[i];
if (writeVariablePrecision(field->type()->getPrecision()))
out << " ";
out << getTypeName(*field->type()) << " " << hashName(field->name());
if (field->type()->isArray())
out << arrayBrackets(*field->type());
out << ";\n";
}
out << "}";
mDeclaredStructs.insert(structure->name());
}

View File

@ -52,6 +52,9 @@ protected:
TString hashFunctionName(const TString& mangled_name);
private:
bool structDeclared(const TStructure* structure) const;
void declareStruct(const TStructure* structure);
TInfoSinkBase& mObjSink;
bool mDeclaringVariables;

View File

@ -55,6 +55,7 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc
mUsesPointCoord = false;
mUsesFrontFacing = false;
mUsesPointSize = false;
mUsesFragDepth = false;
mUsesXor = false;
mUsesMod1 = false;
mUsesMod2v = false;
@ -67,18 +68,6 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc
mUsesFaceforward2 = false;
mUsesFaceforward3 = false;
mUsesFaceforward4 = false;
mUsesEqualMat2 = false;
mUsesEqualMat3 = false;
mUsesEqualMat4 = false;
mUsesEqualVec2 = false;
mUsesEqualVec3 = false;
mUsesEqualVec4 = false;
mUsesEqualIVec2 = false;
mUsesEqualIVec3 = false;
mUsesEqualIVec4 = false;
mUsesEqualBVec2 = false;
mUsesEqualBVec3 = false;
mUsesEqualBVec4 = false;
mUsesAtan2_1 = false;
mUsesAtan2_2 = false;
mUsesAtan2_3 = false;
@ -210,9 +199,9 @@ void OutputHLSL::header()
if (shaderType == SH_FRAGMENT_SHADER)
{
TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers");
bool usingMRTExtension = iter != mContext.extensionBehavior().end() && iter->second == EBhEnable;
const bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire));
unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1;
const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1;
out << "// Varyings\n";
out << varyings;
@ -230,6 +219,11 @@ void OutputHLSL::header()
}
out << "};\n";
if (mUsesFragDepth)
{
out << "static float gl_Depth = 0.0;\n";
}
if (mUsesFragCoord)
{
out << "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n";
@ -844,6 +838,16 @@ void OutputHLSL::header()
out << "#define GL_USES_POINT_SIZE\n";
}
if (mUsesFragDepth)
{
out << "#define GL_USES_FRAG_DEPTH\n";
}
if (mUsesDepthRange)
{
out << "#define GL_USES_DEPTH_RANGE\n";
}
if (mUsesXor)
{
out << "bool xor(bool p, bool q)\n"
@ -980,108 +984,6 @@ void OutputHLSL::header()
"\n";
}
if (mUsesEqualMat2)
{
out << "bool equal(float2x2 m, float2x2 n)\n"
"{\n"
" return m[0][0] == n[0][0] && m[0][1] == n[0][1] &&\n"
" m[1][0] == n[1][0] && m[1][1] == n[1][1];\n"
"}\n";
}
if (mUsesEqualMat3)
{
out << "bool equal(float3x3 m, float3x3 n)\n"
"{\n"
" return m[0][0] == n[0][0] && m[0][1] == n[0][1] && m[0][2] == n[0][2] &&\n"
" m[1][0] == n[1][0] && m[1][1] == n[1][1] && m[1][2] == n[1][2] &&\n"
" m[2][0] == n[2][0] && m[2][1] == n[2][1] && m[2][2] == n[2][2];\n"
"}\n";
}
if (mUsesEqualMat4)
{
out << "bool equal(float4x4 m, float4x4 n)\n"
"{\n"
" return m[0][0] == n[0][0] && m[0][1] == n[0][1] && m[0][2] == n[0][2] && m[0][3] == n[0][3] &&\n"
" m[1][0] == n[1][0] && m[1][1] == n[1][1] && m[1][2] == n[1][2] && m[1][3] == n[1][3] &&\n"
" m[2][0] == n[2][0] && m[2][1] == n[2][1] && m[2][2] == n[2][2] && m[2][3] == n[2][3] &&\n"
" m[3][0] == n[3][0] && m[3][1] == n[3][1] && m[3][2] == n[3][2] && m[3][3] == n[3][3];\n"
"}\n";
}
if (mUsesEqualVec2)
{
out << "bool equal(float2 v, float2 u)\n"
"{\n"
" return v.x == u.x && v.y == u.y;\n"
"}\n";
}
if (mUsesEqualVec3)
{
out << "bool equal(float3 v, float3 u)\n"
"{\n"
" return v.x == u.x && v.y == u.y && v.z == u.z;\n"
"}\n";
}
if (mUsesEqualVec4)
{
out << "bool equal(float4 v, float4 u)\n"
"{\n"
" return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
"}\n";
}
if (mUsesEqualIVec2)
{
out << "bool equal(int2 v, int2 u)\n"
"{\n"
" return v.x == u.x && v.y == u.y;\n"
"}\n";
}
if (mUsesEqualIVec3)
{
out << "bool equal(int3 v, int3 u)\n"
"{\n"
" return v.x == u.x && v.y == u.y && v.z == u.z;\n"
"}\n";
}
if (mUsesEqualIVec4)
{
out << "bool equal(int4 v, int4 u)\n"
"{\n"
" return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
"}\n";
}
if (mUsesEqualBVec2)
{
out << "bool equal(bool2 v, bool2 u)\n"
"{\n"
" return v.x == u.x && v.y == u.y;\n"
"}\n";
}
if (mUsesEqualBVec3)
{
out << "bool equal(bool3 v, bool3 u)\n"
"{\n"
" return v.x == u.x && v.y == u.y && v.z == u.z;\n"
"}\n";
}
if (mUsesEqualBVec4)
{
out << "bool equal(bool4 v, bool4 u)\n"
"{\n"
" return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
"}\n";
}
if (mUsesAtan2_1)
{
out << "float atanyx(float y, float x)\n"
@ -1166,6 +1068,11 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node)
mUsesPointSize = true;
out << name;
}
else if (name == "gl_FragDepthEXT")
{
mUsesFragDepth = true;
out << "gl_Depth";
}
else
{
TQualifier qualifier = node->getQualifier();
@ -1275,7 +1182,10 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
case EOpIndexDirectStruct:
if (visit == InVisit)
{
out << "." + decorateField(node->getType().getFieldName(), node->getLeft()->getType());
const TStructure* structure = node->getLeft()->getType().getStruct();
const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion();
const TField* field = structure->fields()[index->getIConst(0)];
out << "." + decorateField(field->name(), node->getLeft()->getType());
return false;
}
@ -1344,18 +1254,18 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
out << "!(";
}
const TTypeList *fields = node->getLeft()->getType().getStruct();
const TFieldList &fields = node->getLeft()->getType().getStruct()->fields();
for (size_t i = 0; i < fields->size(); i++)
for (size_t i = 0; i < fields.size(); i++)
{
const TType *fieldType = (*fields)[i].type;
const TField *field = fields[i];
node->getLeft()->traverse(this);
out << "." + decorateField(fieldType->getFieldName(), node->getLeft()->getType()) + " == ";
out << "." + decorateField(field->name(), node->getLeft()->getType()) + " == ";
node->getRight()->traverse(this);
out << "." + decorateField(fieldType->getFieldName(), node->getLeft()->getType());
out << "." + decorateField(field->name(), node->getLeft()->getType());
if (i < fields->size() - 1)
if (i < fields.size() - 1)
{
out << " && ";
}
@ -1367,59 +1277,15 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
}
else
{
if (node->getLeft()->isMatrix())
{
switch (node->getLeft()->getNominalSize())
{
case 2: mUsesEqualMat2 = true; break;
case 3: mUsesEqualMat3 = true; break;
case 4: mUsesEqualMat4 = true; break;
default: UNREACHABLE();
}
}
else if (node->getLeft()->isVector())
{
switch (node->getLeft()->getBasicType())
{
case EbtFloat:
switch (node->getLeft()->getNominalSize())
{
case 2: mUsesEqualVec2 = true; break;
case 3: mUsesEqualVec3 = true; break;
case 4: mUsesEqualVec4 = true; break;
default: UNREACHABLE();
}
break;
case EbtInt:
switch (node->getLeft()->getNominalSize())
{
case 2: mUsesEqualIVec2 = true; break;
case 3: mUsesEqualIVec3 = true; break;
case 4: mUsesEqualIVec4 = true; break;
default: UNREACHABLE();
}
break;
case EbtBool:
switch (node->getLeft()->getNominalSize())
{
case 2: mUsesEqualBVec2 = true; break;
case 3: mUsesEqualBVec3 = true; break;
case 4: mUsesEqualBVec4 = true; break;
default: UNREACHABLE();
}
break;
default: UNREACHABLE();
}
}
else UNREACHABLE();
ASSERT(node->getLeft()->isMatrix() || node->getLeft()->isVector());
if (node->getOp() == EOpEqual)
{
outputTriplet(visit, "equal(", ", ", ")");
outputTriplet(visit, "all(", " == ", ")");
}
else
{
outputTriplet(visit, "!equal(", ", ", ")");
outputTriplet(visit, "!all(", " == ", ")");
}
}
break;
@ -1561,7 +1427,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
{
if (mInsideFunction)
{
outputLineDirective(node->getLine());
outputLineDirective(node->getLine().first_line);
out << "{\n";
mScopeDepth++;
@ -1578,7 +1444,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++)
{
outputLineDirective((*sit)->getLine());
outputLineDirective((*sit)->getLine().first_line);
traverseStatements(*sit);
@ -1587,7 +1453,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
if (mInsideFunction)
{
outputLineDirective(node->getEndLine());
outputLineDirective(node->getLine().last_line);
out << "}\n";
mScopeDepth--;
@ -1605,7 +1471,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
{
if (variable->getType().getStruct())
{
addConstructor(variable->getType(), scopedStruct(variable->getType().getTypeName()), NULL);
addConstructor(variable->getType(), scopedStruct(variable->getType().getStruct()->name()), NULL);
}
if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration
@ -1732,7 +1598,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
{
if (symbol->getType().getStruct())
{
addConstructor(symbol->getType(), scopedStruct(symbol->getType().getTypeName()), NULL);
addConstructor(symbol->getType(), scopedStruct(symbol->getType().getStruct()->name()), NULL);
}
out << argumentString(symbol);
@ -1993,8 +1859,8 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
outputTriplet(visit, "mat4(", ", ", ")");
break;
case EOpConstructStruct:
addConstructor(node->getType(), scopedStruct(node->getType().getTypeName()), &node->getSequence());
outputTriplet(visit, structLookup(node->getType().getTypeName()) + "_ctor(", ", ", ")");
addConstructor(node->getType(), scopedStruct(node->getType().getStruct()->name()), &node->getSequence());
outputTriplet(visit, structLookup(node->getType().getStruct()->name()) + "_ctor(", ", ", ")");
break;
case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break;
case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break;
@ -2084,7 +1950,7 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
out << ")\n";
outputLineDirective(node->getLine());
outputLineDirective(node->getLine().first_line);
out << "{\n";
if (node->getTrueBlock())
@ -2092,20 +1958,20 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
traverseStatements(node->getTrueBlock());
}
outputLineDirective(node->getLine());
outputLineDirective(node->getLine().first_line);
out << ";\n}\n";
if (node->getFalseBlock())
{
out << "else\n";
outputLineDirective(node->getFalseBlock()->getLine());
outputLineDirective(node->getFalseBlock()->getLine().first_line);
out << "{\n";
outputLineDirective(node->getFalseBlock()->getLine());
outputLineDirective(node->getFalseBlock()->getLine().first_line);
traverseStatements(node->getFalseBlock());
outputLineDirective(node->getFalseBlock()->getLine());
outputLineDirective(node->getFalseBlock()->getLine().first_line);
out << ";\n}\n";
}
}
@ -2141,7 +2007,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
{
out << "{do\n";
outputLineDirective(node->getLine());
outputLineDirective(node->getLine().first_line);
out << "{\n";
}
else
@ -2169,7 +2035,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
out << ")\n";
outputLineDirective(node->getLine());
outputLineDirective(node->getLine().first_line);
out << "{\n";
}
@ -2178,12 +2044,12 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
traverseStatements(node->getBody());
}
outputLineDirective(node->getLine());
outputLineDirective(node->getLine().first_line);
out << ";}\n";
if (node->getType() == ELoopDoWhile)
{
outputLineDirective(node->getCondition()->getLine());
outputLineDirective(node->getCondition()->getLine().first_line);
out << "while(\n";
node->getCondition()->traverse(this);
@ -2455,7 +2321,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
out << increment;
out << ")\n";
outputLineDirective(node->getLine());
outputLineDirective(node->getLine().first_line);
out << "{\n";
if (node->getBody())
@ -2463,7 +2329,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
node->getBody()->traverse(this);
}
outputLineDirective(node->getLine());
outputLineDirective(node->getLine().first_line);
out << ";}\n";
if (!firstLoopFragment)
@ -2565,22 +2431,23 @@ TString OutputHLSL::typeString(const TType &type)
{
if (type.getBasicType() == EbtStruct)
{
if (type.getTypeName() != "")
const TString& typeName = type.getStruct()->name();
if (typeName != "")
{
return structLookup(type.getTypeName());
return structLookup(typeName);
}
else // Nameless structure, define in place
{
const TTypeList &fields = *type.getStruct();
const TFieldList &fields = type.getStruct()->fields();
TString string = "struct\n"
"{\n";
for (unsigned int i = 0; i < fields.size(); i++)
{
const TType &field = *fields[i].type;
const TField *field = fields[i];
string += " " + typeString(field) + " " + decorate(field.getFieldName()) + arrayString(field) + ";\n";
string += " " + typeString(*field->type()) + " " + decorate(field->name()) + arrayString(*field->type()) + ";\n";
}
string += "} ";
@ -2674,11 +2541,12 @@ TString OutputHLSL::initializer(const TType &type)
{
TString string;
for (int component = 0; component < type.getObjectSize(); component++)
size_t size = type.getObjectSize();
for (size_t component = 0; component < size; component++)
{
string += "0";
if (component < type.getObjectSize() - 1)
if (component + 1 < size)
{
string += ", ";
}
@ -2717,13 +2585,13 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI
structure += "struct " + decorate(name) + "\n"
"{\n";
const TTypeList &fields = *type.getStruct();
const TFieldList &fields = type.getStruct()->fields();
for (unsigned int i = 0; i < fields.size(); i++)
{
const TType &field = *fields[i].type;
const TField *field = fields[i];
structure += " " + typeString(field) + " " + decorateField(field.getFieldName(), type) + arrayString(field) + ";\n";
structure += " " + typeString(*field->type()) + " " + decorateField(field->name(), type) + arrayString(*field->type()) + ";\n";
}
structure += "};\n";
@ -2735,7 +2603,7 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI
for (unsigned int i = 0; i < fields.size(); i++)
{
ctorParameters.push_back(*fields[i].type);
ctorParameters.push_back(*fields[i]->type());
}
}
else if (parameters)
@ -2828,27 +2696,30 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI
}
else
{
int remainingComponents = ctorType.getObjectSize();
int parameterIndex = 0;
size_t remainingComponents = ctorType.getObjectSize();
size_t parameterIndex = 0;
while (remainingComponents > 0)
{
const TType &parameter = ctorParameters[parameterIndex];
bool moreParameters = parameterIndex < (int)ctorParameters.size() - 1;
const size_t parameterSize = parameter.getObjectSize();
bool moreParameters = parameterIndex + 1 < ctorParameters.size();
constructor += "x" + str(parameterIndex);
if (parameter.isScalar())
{
remainingComponents -= parameter.getObjectSize();
ASSERT(parameterSize <= remainingComponents);
remainingComponents -= parameterSize;
}
else if (parameter.isVector())
{
if (remainingComponents == parameter.getObjectSize() || moreParameters)
if (remainingComponents == parameterSize || moreParameters)
{
remainingComponents -= parameter.getObjectSize();
ASSERT(parameterSize <= remainingComponents);
remainingComponents -= parameterSize;
}
else if (remainingComponents < parameter.getNominalSize())
else if (remainingComponents < static_cast<size_t>(parameter.getNominalSize()))
{
switch (remainingComponents)
{
@ -2865,9 +2736,10 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI
}
else if (parameter.isMatrix() || parameter.getStruct())
{
ASSERT(remainingComponents == parameter.getObjectSize() || moreParameters);
ASSERT(remainingComponents == parameterSize || moreParameters);
ASSERT(parameterSize <= remainingComponents);
remainingComponents -= parameter.getObjectSize();
remainingComponents -= parameterSize;
}
else UNREACHABLE();
@ -2904,17 +2776,17 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con
if (type.getBasicType() == EbtStruct)
{
out << structLookup(type.getTypeName()) + "_ctor(";
out << structLookup(type.getStruct()->name()) + "_ctor(";
const TTypeList *structure = type.getStruct();
const TFieldList &fields = type.getStruct()->fields();
for (size_t i = 0; i < structure->size(); i++)
for (size_t i = 0; i < fields.size(); i++)
{
const TType *fieldType = (*structure)[i].type;
const TType *fieldType = fields[i]->type();
constUnion = writeConstantUnion(*fieldType, constUnion);
if (i != structure->size() - 1)
if (i != fields.size() - 1)
{
out << ", ";
}
@ -2924,7 +2796,7 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con
}
else
{
int size = type.getObjectSize();
size_t size = type.getObjectSize();
bool writeType = size > 1;
if (writeType)
@ -2932,7 +2804,7 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con
out << typeString(type) << "(";
}
for (int i = 0; i < size; i++, constUnion++)
for (size_t i = 0; i < size; i++, constUnion++)
{
switch (constUnion->getType())
{
@ -3021,7 +2893,7 @@ TString OutputHLSL::decorateUniform(const TString &string, const TType &type)
TString OutputHLSL::decorateField(const TString &string, const TType &structure)
{
if (structure.getTypeName().compare(0, 3, "gl_") != 0)
if (structure.getStruct()->name().compare(0, 3, "gl_") != 0)
{
return decorate(string);
}
@ -3069,7 +2941,7 @@ int OutputHLSL::uniformRegister(TIntermSymbol *uniform)
void OutputHLSL::declareUniform(const TType &type, const TString &name, int index)
{
const TTypeList *structure = type.getStruct();
TStructure *structure = type.getStruct();
if (!structure)
{
@ -3077,18 +2949,18 @@ void OutputHLSL::declareUniform(const TType &type, const TString &name, int inde
}
else
{
const TFieldList &fields = structure->fields();
if (type.isArray())
{
int elementIndex = index;
for (int i = 0; i < type.getArraySize(); i++)
{
for (size_t j = 0; j < structure->size(); j++)
for (size_t j = 0; j < fields.size(); j++)
{
const TType &fieldType = *(*structure)[j].type;
const TString &fieldName = fieldType.getFieldName();
const TString uniformName = name + "[" + str(i) + "]." + fieldName;
const TType &fieldType = *fields[j]->type();
const TString uniformName = name + "[" + str(i) + "]." + fields[j]->name();
declareUniform(fieldType, uniformName, elementIndex);
elementIndex += fieldType.totalRegisterCount();
}
@ -3098,12 +2970,10 @@ void OutputHLSL::declareUniform(const TType &type, const TString &name, int inde
{
int fieldIndex = index;
for (size_t i = 0; i < structure->size(); i++)
for (size_t i = 0; i < fields.size(); i++)
{
const TType &fieldType = *(*structure)[i].type;
const TString &fieldName = fieldType.getFieldName();
const TString uniformName = name + "." + fieldName;
const TType &fieldType = *fields[i]->type();
const TString uniformName = name + "." + fields[i]->name();
declareUniform(fieldType, uniformName, fieldIndex);
fieldIndex += fieldType.totalRegisterCount();
}

View File

@ -108,6 +108,7 @@ class OutputHLSL : public TIntermTraverser
bool mUsesPointCoord;
bool mUsesFrontFacing;
bool mUsesPointSize;
bool mUsesFragDepth;
bool mUsesXor;
bool mUsesMod1;
bool mUsesMod2v;
@ -120,18 +121,6 @@ class OutputHLSL : public TIntermTraverser
bool mUsesFaceforward2;
bool mUsesFaceforward3;
bool mUsesFaceforward4;
bool mUsesEqualMat2;
bool mUsesEqualMat3;
bool mUsesEqualMat4;
bool mUsesEqualVec2;
bool mUsesEqualVec3;
bool mUsesEqualVec4;
bool mUsesEqualIVec2;
bool mUsesEqualIVec3;
bool mUsesEqualIVec4;
bool mUsesEqualBVec2;
bool mUsesEqualBVec3;
bool mUsesEqualBVec4;
bool mUsesAtan2_1;
bool mUsesAtan2_2;
bool mUsesAtan2_3;

View File

@ -22,7 +22,7 @@
// Look at a '.' field selector string and change it into offsets
// for a vector.
//
bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, int line)
bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, const TSourceLoc& line)
{
fields.num = (int) compString.size();
if (fields.num > 4) {
@ -115,7 +115,7 @@ bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TV
// Look at a '.' field selector string and change it into offsets
// for a matrix.
//
bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, int line)
bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, const TSourceLoc& line)
{
fields.wholeRow = false;
fields.wholeCol = false;
@ -175,22 +175,24 @@ void TParseContext::recover()
//
// Used by flex/bison to output all syntax and parsing errors.
//
void TParseContext::error(TSourceLoc loc,
void TParseContext::error(const TSourceLoc& loc,
const char* reason, const char* token,
const char* extraInfo)
{
pp::SourceLocation srcLoc;
DecodeSourceLoc(loc, &srcLoc.file, &srcLoc.line);
srcLoc.file = loc.first_file;
srcLoc.line = loc.first_line;
diagnostics.writeInfo(pp::Diagnostics::ERROR,
srcLoc, reason, token, extraInfo);
}
void TParseContext::warning(TSourceLoc loc,
void TParseContext::warning(const TSourceLoc& loc,
const char* reason, const char* token,
const char* extraInfo) {
pp::SourceLocation srcLoc;
DecodeSourceLoc(loc, &srcLoc.file, &srcLoc.line);
srcLoc.file = loc.first_file;
srcLoc.line = loc.first_line;
diagnostics.writeInfo(pp::Diagnostics::WARNING,
srcLoc, reason, token, extraInfo);
}
@ -203,7 +205,7 @@ void TParseContext::trace(const char* str)
//
// Same error message for all places assignments don't work.
//
void TParseContext::assignError(int line, const char* op, TString left, TString right)
void TParseContext::assignError(const TSourceLoc& line, const char* op, TString left, TString right)
{
std::stringstream extraInfoStream;
extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'";
@ -214,7 +216,7 @@ void TParseContext::assignError(int line, const char* op, TString left, TString
//
// Same error message for all places unary operations don't work.
//
void TParseContext::unaryOpError(int line, const char* op, TString operand)
void TParseContext::unaryOpError(const TSourceLoc& line, const char* op, TString operand)
{
std::stringstream extraInfoStream;
extraInfoStream << "no operation '" << op << "' exists that takes an operand of type " << operand
@ -226,7 +228,7 @@ void TParseContext::unaryOpError(int line, const char* op, TString operand)
//
// Same error message for all binary operations don't work.
//
void TParseContext::binaryOpError(int line, const char* op, TString left, TString right)
void TParseContext::binaryOpError(const TSourceLoc& line, const char* op, TString left, TString right)
{
std::stringstream extraInfoStream;
extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left
@ -235,7 +237,7 @@ void TParseContext::binaryOpError(int line, const char* op, TString left, TStrin
error(line, " wrong operand types ", op, extraInfo.c_str());
}
bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicType type){
bool TParseContext::precisionErrorCheck(const TSourceLoc& line, TPrecision precision, TBasicType type){
if (!checksPrecisionErrors)
return false;
switch( type ){
@ -263,7 +265,7 @@ bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicTy
//
// Returns true if the was an error.
//
bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* node)
bool TParseContext::lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped* node)
{
TIntermSymbol* symNode = node->getAsSymbolNode();
TIntermBinary* binaryNode = node->getAsBinaryNode();
@ -317,7 +319,6 @@ bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* nod
case EvqAttribute: message = "can't modify an attribute"; break;
case EvqUniform: message = "can't modify a uniform"; break;
case EvqVaryingIn: message = "can't modify a varying"; break;
case EvqInput: message = "can't modify an input"; break;
case EvqFragCoord: message = "can't modify gl_FragCoord"; break;
case EvqFrontFacing: message = "can't modify gl_FrontFacing"; break;
case EvqPointCoord: message = "can't modify gl_PointCoord"; break;
@ -409,7 +410,7 @@ bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token)
//
// Returns true if the was an error.
//
bool TParseContext::globalErrorCheck(int line, bool global, const char* token)
bool TParseContext::globalErrorCheck(const TSourceLoc& line, bool global, const char* token)
{
if (global)
return false;
@ -428,7 +429,7 @@ bool TParseContext::globalErrorCheck(int line, bool global, const char* token)
//
// Returns true if there was an error.
//
bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
bool TParseContext::reservedErrorCheck(const TSourceLoc& line, const TString& identifier)
{
static const char* reservedErrMsg = "reserved built-in name";
if (!symbolTable.atBuiltInLevel()) {
@ -466,7 +467,7 @@ bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
//
// Returns true if there was an error in construction.
//
bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
bool TParseContext::constructorErrorCheck(const TSourceLoc& line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
{
*type = function.getReturnType();
@ -487,7 +488,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction
// again, there is an extra argument, so 'overfull' will become true.
//
int size = 0;
size_t size = 0;
bool constType = true;
bool full = false;
bool overFull = false;
@ -534,7 +535,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction
return true;
}
if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->size()) != function.getParamCount()) {
if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->fields().size()) != function.getParamCount()) {
error(line, "Number of constructor parameters does not match the number of structure fields", "constructor");
return true;
}
@ -568,7 +569,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction
//
// returns true in case of an error
//
bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TPublicType& pubType)
bool TParseContext::voidErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType& pubType)
{
if (pubType.type == EbtVoid) {
error(line, "illegal use of type 'void'", identifier.c_str());
@ -582,7 +583,7 @@ bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TP
//
// returns true in case of an error
//
bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type)
bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TIntermTyped* type)
{
if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
error(line, "boolean expression expected", "");
@ -596,7 +597,7 @@ bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type)
//
// returns true in case of an error
//
bool TParseContext::boolErrorCheck(int line, const TPublicType& pType)
bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TPublicType& pType)
{
if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) {
error(line, "boolean expression expected", "");
@ -606,7 +607,7 @@ bool TParseContext::boolErrorCheck(int line, const TPublicType& pType)
return false;
}
bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const char* reason)
bool TParseContext::samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason)
{
if (pType.type == EbtStruct) {
if (containsSampler(*pType.userDef)) {
@ -625,7 +626,7 @@ bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const
return false;
}
bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType)
bool TParseContext::structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType)
{
if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) &&
pType.type == EbtStruct) {
@ -640,7 +641,7 @@ bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType
return false;
}
bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type)
bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type)
{
if ((qualifier == EvqOut || qualifier == EvqInOut) &&
type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
@ -657,9 +658,9 @@ bool TParseContext::containsSampler(TType& type)
return true;
if (type.getBasicType() == EbtStruct) {
TTypeList& structure = *type.getStruct();
for (unsigned int i = 0; i < structure.size(); ++i) {
if (containsSampler(*structure[i].type))
const TFieldList& fields = type.getStruct()->fields();
for (unsigned int i = 0; i < fields.size(); ++i) {
if (containsSampler(*fields[i]->type()))
return true;
}
}
@ -672,7 +673,7 @@ bool TParseContext::containsSampler(TType& type)
//
// Returns true if there was an error.
//
bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
bool TParseContext::arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size)
{
TIntermConstantUnion* constant = expr->getAsConstantUnion();
if (constant == 0 || constant->getBasicType() != EbtInt) {
@ -696,7 +697,7 @@ bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
//
// Returns true if there is an error.
//
bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type)
bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type)
{
if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqConst)) {
error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str());
@ -711,7 +712,7 @@ bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type)
//
// Returns true if there is an error.
//
bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type)
bool TParseContext::arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type)
{
//
// Can the type be an array?
@ -732,7 +733,7 @@ bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type)
//
// Returns true if there was an error.
//
bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable)
bool TParseContext::arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable)
{
//
// Don't check for reserved word use until after we know it's not in the symbol table,
@ -777,16 +778,6 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType t
return true;
}
TType* t = variable->getArrayInformationType();
while (t != 0) {
if (t->getMaxArraySize() > type.arraySize) {
error(line, "higher index value already used for the array", identifier.c_str());
return true;
}
t->setArraySize(type.arraySize);
t = t->getArrayInformationType();
}
if (type.arraySize)
variable->getType().setArraySize(type.arraySize);
}
@ -797,56 +788,12 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType t
return false;
}
bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line)
{
bool builtIn = false;
TSymbol* symbol = symbolTable.find(node->getSymbol(), &builtIn);
if (symbol == 0) {
error(line, " undeclared identifier", node->getSymbol().c_str());
return true;
}
TVariable* variable = static_cast<TVariable*>(symbol);
type->setArrayInformationType(variable->getArrayInformationType());
variable->updateArrayInformationType(type);
// special casing to test index value of gl_FragData. If the accessed index is >= gl_MaxDrawBuffers
// its an error
if (node->getSymbol() == "gl_FragData") {
TSymbol* fragData = symbolTable.find("gl_MaxDrawBuffers", &builtIn);
ASSERT(fragData);
int fragDataValue = static_cast<TVariable*>(fragData)->getConstPointer()[0].getIConst();
if (fragDataValue <= size) {
error(line, "", "[", "gl_FragData can only have a max array size of up to gl_MaxDrawBuffers");
return true;
}
}
// we dont want to update the maxArraySize when this flag is not set, we just want to include this
// node type in the chain of node types so that its updated when a higher maxArraySize comes in.
if (!updateFlag)
return false;
size++;
variable->getType().setMaxArraySize(size);
type->setMaxArraySize(size);
TType* tt = type;
while(tt->getArrayInformationType() != 0) {
tt = tt->getArrayInformationType();
tt->setMaxArraySize(size);
}
return false;
}
//
// Enforce non-initializer type/qualifier rules.
//
// Returns true if there was an error.
//
bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array)
bool TParseContext::nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array)
{
if (type.qualifier == EvqConst)
{
@ -878,7 +825,7 @@ bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPubli
//
// Returns true if there was an error.
//
bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable)
bool TParseContext::nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable)
{
if (reservedErrorCheck(line, identifier))
recover();
@ -898,7 +845,7 @@ bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType
return false;
}
bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
bool TParseContext::paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
{
if (qualifier != EvqConst && qualifier != EvqTemporary) {
error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
@ -917,7 +864,7 @@ bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier p
return false;
}
bool TParseContext::extensionErrorCheck(int line, const TString& extension)
bool TParseContext::extensionErrorCheck(const TSourceLoc& line, const TString& extension)
{
const TExtensionBehavior& extBehavior = extensionBehavior();
TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
@ -945,18 +892,17 @@ bool TParseContext::supportsExtension(const char* extension)
return (iter != extbehavior.end());
}
void TParseContext::handleExtensionDirective(int line, const char* extName, const char* behavior)
bool TParseContext::isExtensionEnabled(const char* extension) const
{
pp::SourceLocation loc;
DecodeSourceLoc(line, &loc.file, &loc.line);
directiveHandler.handleExtension(loc, extName, behavior);
}
const TExtensionBehavior& extbehavior = extensionBehavior();
TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
void TParseContext::handlePragmaDirective(int line, const char* name, const char* value)
{
pp::SourceLocation loc;
DecodeSourceLoc(line, &loc.file, &loc.line);
directiveHandler.handlePragma(loc, name, value);
if (iter == extbehavior.end())
{
return false;
}
return (iter->second == EBhEnable || iter->second == EBhRequire);
}
/////////////////////////////////////////////////////////////////////////////////
@ -970,12 +916,13 @@ void TParseContext::handlePragmaDirective(int line, const char* name, const char
//
// Return the function symbol if found, otherwise 0.
//
const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *builtIn)
const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, bool *builtIn)
{
// First find by unmangled name to check whether the function name has been
// hidden by a variable name or struct typename.
// If a function is found, check for one with a matching argument list.
const TSymbol* symbol = symbolTable.find(call->getName(), builtIn);
if (symbol == 0) {
if (symbol == 0 || symbol->isFunction()) {
symbol = symbolTable.find(call->getMangledName(), builtIn);
}
@ -996,7 +943,7 @@ const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *bu
// Initializers show up in several places in the grammar. Have one set of
// code to handle them here.
//
bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
bool TParseContext::executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType,
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
{
TType type = TType(pType);
@ -1048,13 +995,7 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu
return true;
}
if (initializer->getAsConstantUnion()) {
ConstantUnion* unionArray = variable->getConstPointer();
if (type.getObjectSize() == 1 && type.getBasicType() != EbtStruct) {
*unionArray = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0];
} else {
variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
}
variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
} else if (initializer->getAsSymbolNode()) {
const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol());
const TVariable* tVar = static_cast<const TVariable*>(symbol);
@ -1108,16 +1049,16 @@ bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode)
//
// Returns 0 for an error or the constructed node (aggregate or typed) for no error.
//
TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, TSourceLoc line)
TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, const TSourceLoc& line)
{
if (node == 0)
return 0;
TIntermAggregate* aggrNode = node->getAsAggregate();
TTypeList::const_iterator memberTypes;
TFieldList::const_iterator memberFields;
if (op == EOpConstructStruct)
memberTypes = type->getStruct()->begin();
memberFields = type->getStruct()->fields().begin();
TType elementType = *type;
if (type->isArray())
@ -1139,7 +1080,7 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type
if (type->isArray())
newNode = constructStruct(node, &elementType, 1, node->getLine(), false);
else if (op == EOpConstructStruct)
newNode = constructStruct(node, (*memberTypes).type, 1, node->getLine(), false);
newNode = constructStruct(node, (*memberFields)->type(), 1, node->getLine(), false);
else
newNode = constructBuiltIn(type, op, node, node->getLine(), false);
@ -1170,7 +1111,7 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type
if (type->isArray())
newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true);
else if (op == EOpConstructStruct)
newNode = constructStruct(*p, (memberTypes[paramCount]).type, paramCount+1, node->getLine(), true);
newNode = constructStruct(*p, memberFields[paramCount]->type(), paramCount+1, node->getLine(), true);
else
newNode = constructBuiltIn(type, op, *p, node->getLine(), true);
@ -1216,7 +1157,7 @@ TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, co
//
// Returns 0 for an error or the constructed node.
//
TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, TSourceLoc line, bool subset)
TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, const TSourceLoc& line, bool subset)
{
TIntermTyped* newNode;
TOperator basicOp;
@ -1278,7 +1219,7 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, T
//
// Returns 0 for an error or the input node itself if the expected and the given parameter types match.
//
TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, TSourceLoc line, bool subset)
TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, const TSourceLoc& line, bool subset)
{
if (*type == node->getAsTyped()->getType()) {
if (subset)
@ -1305,7 +1246,7 @@ TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int
// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of
// a constant matrix.
//
TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc line)
TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc& line)
{
TIntermTyped* typedNode;
TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
@ -1327,7 +1268,7 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy
ConstantUnion* constArray = new ConstantUnion[fields.num];
for (int i = 0; i < fields.num; i++) {
if (fields.offsets[i] >= node->getType().getObjectSize()) {
if (fields.offsets[i] >= node->getType().getNominalSize()) {
std::stringstream extraInfoStream;
extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'";
std::string extraInfo = extraInfoStream.str();
@ -1349,7 +1290,7 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy
// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a
// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
//
TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc line)
TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc& line)
{
TIntermTyped* typedNode;
TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
@ -1384,7 +1325,7 @@ TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, T
// to the function could either be a symbol node (a[0] where a is a constant array)that represents a
// constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure)
//
TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line)
TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line)
{
TIntermTyped* typedNode;
TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
@ -1400,9 +1341,8 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS
index = 0;
}
int arrayElementSize = arrayElementType.getObjectSize();
if (tempConstantNode) {
size_t arrayElementSize = arrayElementType.getObjectSize();
ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line);
} else {
@ -1421,22 +1361,21 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS
// If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
// function and returns the parse-tree with the values of the embedded/nested struct.
//
TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, TSourceLoc line)
TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, const TSourceLoc& line)
{
const TTypeList* fields = node->getType().getStruct();
TIntermTyped *typedNode;
int instanceSize = 0;
unsigned int index = 0;
TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
const TFieldList& fields = node->getType().getStruct()->fields();
for ( index = 0; index < fields->size(); ++index) {
if ((*fields)[index].type->getFieldName() == identifier) {
size_t instanceSize = 0;
for (size_t index = 0; index < fields.size(); ++index) {
if (fields[index]->name() == identifier) {
break;
} else {
instanceSize += (*fields)[index].type->getObjectSize();
instanceSize += fields[index]->type()->getObjectSize();
}
}
TIntermTyped* typedNode = 0;
TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
if (tempConstantNode) {
ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer();
@ -1451,7 +1390,7 @@ TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* n
return typedNode;
}
bool TParseContext::enterStructDeclaration(int line, const TString& identifier)
bool TParseContext::enterStructDeclaration(const TSourceLoc& line, const TString& identifier)
{
++structNestingLevel;
@ -1477,30 +1416,166 @@ const int kWebGLMaxStructNesting = 4;
} // namespace
bool TParseContext::structNestingErrorCheck(TSourceLoc line, const TType& fieldType)
bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TField& field)
{
if (!isWebGLBasedSpec(shaderSpec)) {
return false;
}
if (fieldType.getBasicType() != EbtStruct) {
if (field.type()->getBasicType() != EbtStruct) {
return false;
}
// We're already inside a structure definition at this point, so add
// one to the field's struct nesting.
if (1 + fieldType.getDeepestStructNesting() > kWebGLMaxStructNesting) {
std::stringstream extraInfoStream;
extraInfoStream << "Reference of struct type " << fieldType.getTypeName()
<< " exceeds maximum struct nesting of " << kWebGLMaxStructNesting;
std::string extraInfo = extraInfoStream.str();
error(line, "", "", extraInfo.c_str());
if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) {
std::stringstream reasonStream;
reasonStream << "Reference of struct type "
<< field.type()->getStruct()->name().c_str()
<< " exceeds maximum allowed nesting level of "
<< kWebGLMaxStructNesting;
std::string reason = reasonStream.str();
error(line, reason.c_str(), field.name().c_str(), "");
return true;
}
return false;
}
//
// Parse an array index expression
//
TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression)
{
TIntermTyped *indexedExpression = NULL;
if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
{
if (baseExpression->getAsSymbolNode())
{
error(location, " left of '[' is not of type array, matrix, or vector ", baseExpression->getAsSymbolNode()->getSymbol().c_str());
}
else
{
error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
}
recover();
}
if (indexExpression->getQualifier() == EvqConst)
{
int index = indexExpression->getAsConstantUnion()->getIConst(0);
if (index < 0)
{
std::stringstream infoStream;
infoStream << index;
std::string info = infoStream.str();
error(location, "negative index", info.c_str());
recover();
index = 0;
}
if (baseExpression->getType().getQualifier() == EvqConst)
{
if (baseExpression->isArray())
{
// constant folding for arrays
indexedExpression = addConstArrayNode(index, baseExpression, location);
}
else if (baseExpression->isVector())
{
// constant folding for vectors
TVectorFields fields;
fields.num = 1;
fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array
indexedExpression = addConstVectorNode(fields, baseExpression, location);
}
else if (baseExpression->isMatrix())
{
// constant folding for matrices
indexedExpression = addConstMatrixNode(index, baseExpression, location);
}
}
else
{
if (baseExpression->isArray())
{
if (index >= baseExpression->getType().getArraySize())
{
std::stringstream extraInfoStream;
extraInfoStream << "array index out of range '" << index << "'";
std::string extraInfo = extraInfoStream.str();
error(location, "", "[", extraInfo.c_str());
recover();
index = baseExpression->getType().getArraySize() - 1;
}
else if (baseExpression->getQualifier() == EvqFragData && index > 0 && !isExtensionEnabled("GL_EXT_draw_buffers"))
{
error(location, "", "[", "array indexes for gl_FragData must be zero when GL_EXT_draw_buffers is disabled");
recover();
index = 0;
}
}
else if ((baseExpression->isVector() || baseExpression->isMatrix()) && baseExpression->getType().getNominalSize() <= index)
{
std::stringstream extraInfoStream;
extraInfoStream << "field selection out of range '" << index << "'";
std::string extraInfo = extraInfoStream.str();
error(location, "", "[", extraInfo.c_str());
recover();
index = baseExpression->getType().getNominalSize() - 1;
}
indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index);
indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
}
}
else
{
indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
}
if (indexedExpression == 0)
{
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setFConst(0.0f);
indexedExpression = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location);
}
else if (baseExpression->isArray())
{
const TType &baseType = baseExpression->getType();
if (baseType.getStruct())
{
TType copyOfType(baseType.getStruct());
indexedExpression->setType(copyOfType);
}
else
{
indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize(), baseExpression->isMatrix()));
}
if (baseExpression->getType().getQualifier() == EvqConst)
{
indexedExpression->getTypePointer()->setQualifier(EvqConst);
}
}
else if (baseExpression->isMatrix())
{
TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier, baseExpression->getNominalSize()));
}
else if (baseExpression->isVector())
{
TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier));
}
else
{
indexedExpression->setType(baseExpression->getType());
}
return indexedExpression;
}
//
// Parse an array of strings using yyparse.
//

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2013 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.
//
@ -33,10 +33,8 @@ struct TParseContext {
compileOptions(options),
sourcePath(sourcePath),
treeRoot(0),
lexAfterType(false),
loopNestingLevel(0),
structNestingLevel(0),
inTypeParen(false),
currentFunctionType(NULL),
functionReturnsValue(false),
checksPrecisionErrors(checksPrecErrors),
@ -51,16 +49,13 @@ struct TParseContext {
int compileOptions;
const char* sourcePath; // Path of source file or NULL.
TIntermNode* treeRoot; // root of parse tree being created
bool lexAfterType; // true if we've recognized a type, so can only be looking for an identifier
int loopNestingLevel; // 0 if outside all loops
int structNestingLevel; // incremented while parsing a struct declaration
bool inTypeParen; // true if in parentheses, looking only for an identifier
const TType* currentFunctionType; // the return type of the function that's currently being parsed
bool functionReturnsValue; // true if a non-void function has a return
bool checksPrecisionErrors; // true if an error will be generated when a variable is declared without precision, explicit or implicit.
bool fragmentPrecisionHigh; // true if highp precision is supported in the fragment language.
TString HashErrMsg;
bool AfterEOF;
TDiagnostics diagnostics;
TDirectiveHandler directiveHandler;
pp::Preprocessor preprocessor;
@ -68,71 +63,69 @@ struct TParseContext {
int numErrors() const { return diagnostics.numErrors(); }
TInfoSink& infoSink() { return diagnostics.infoSink(); }
void error(TSourceLoc loc, const char *reason, const char* token,
void error(const TSourceLoc& loc, const char *reason, const char* token,
const char* extraInfo="");
void warning(TSourceLoc loc, const char* reason, const char* token,
void warning(const TSourceLoc& loc, const char* reason, const char* token,
const char* extraInfo="");
void trace(const char* str);
void recover();
bool parseVectorFields(const TString&, int vecSize, TVectorFields&, int line);
bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, int line);
bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc& line);
bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, const TSourceLoc& line);
bool reservedErrorCheck(int line, const TString& identifier);
void assignError(int line, const char* op, TString left, TString right);
void unaryOpError(int line, const char* op, TString operand);
void binaryOpError(int line, const char* op, TString left, TString right);
bool precisionErrorCheck(int line, TPrecision precision, TBasicType type);
bool lValueErrorCheck(int line, const char* op, TIntermTyped*);
bool reservedErrorCheck(const TSourceLoc& line, const TString& identifier);
void assignError(const TSourceLoc& line, const char* op, TString left, TString right);
void unaryOpError(const TSourceLoc& line, const char* op, TString operand);
void binaryOpError(const TSourceLoc& line, const char* op, TString left, TString right);
bool precisionErrorCheck(const TSourceLoc& line, TPrecision precision, TBasicType type);
bool lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped*);
bool constErrorCheck(TIntermTyped* node);
bool integerErrorCheck(TIntermTyped* node, const char* token);
bool globalErrorCheck(int line, bool global, const char* token);
bool constructorErrorCheck(int line, TIntermNode*, TFunction&, TOperator, TType*);
bool arraySizeErrorCheck(int line, TIntermTyped* expr, int& size);
bool arrayQualifierErrorCheck(int line, TPublicType type);
bool arrayTypeErrorCheck(int line, TPublicType type);
bool arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable);
bool voidErrorCheck(int, const TString&, const TPublicType&);
bool boolErrorCheck(int, const TIntermTyped*);
bool boolErrorCheck(int, const TPublicType&);
bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason);
bool structQualifierErrorCheck(int line, const TPublicType& pType);
bool parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type);
bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array);
bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable);
bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
bool extensionErrorCheck(int line, const TString&);
const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); }
bool supportsExtension(const char* extension);
void handleExtensionDirective(int line, const char* extName, const char* behavior);
bool globalErrorCheck(const TSourceLoc& line, bool global, const char* token);
bool constructorErrorCheck(const TSourceLoc& line, TIntermNode*, TFunction&, TOperator, TType*);
bool arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size);
bool arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type);
bool arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type);
bool arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable);
bool voidErrorCheck(const TSourceLoc&, const TString&, const TPublicType&);
bool boolErrorCheck(const TSourceLoc&, const TIntermTyped*);
bool boolErrorCheck(const TSourceLoc&, const TPublicType&);
bool samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason);
bool structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType);
bool parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type);
bool nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array);
bool nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable);
bool paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
bool extensionErrorCheck(const TSourceLoc& line, const TString&);
const TPragma& pragma() const { return directiveHandler.pragma(); }
void handlePragmaDirective(int line, const char* name, const char* value);
const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); }
bool supportsExtension(const char* extension);
bool isExtensionEnabled(const char* extension) const;
bool containsSampler(TType& type);
bool areAllChildConst(TIntermAggregate* aggrNode);
const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0);
bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
const TFunction* findFunction(const TSourceLoc& line, TFunction* pfnCall, bool *builtIn = 0);
bool executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType,
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc);
TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, TSourceLoc);
TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, const TSourceLoc&);
TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type);
TIntermTyped* constructStruct(TIntermNode*, TType*, int, TSourceLoc, bool subset);
TIntermTyped* constructBuiltIn(const TType*, TOperator, TIntermNode*, TSourceLoc, bool subset);
TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, TSourceLoc);
TIntermTyped* addConstMatrixNode(int , TIntermTyped*, TSourceLoc);
TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line);
TIntermTyped* addConstStruct(TString& , TIntermTyped*, TSourceLoc);
TIntermTyped* constructStruct(TIntermNode*, TType*, int, const TSourceLoc&, bool subset);
TIntermTyped* constructBuiltIn(const TType*, TOperator, TIntermNode*, const TSourceLoc&, bool subset);
TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, const TSourceLoc&);
TIntermTyped* addConstMatrixNode(int , TIntermTyped*, const TSourceLoc&);
TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line);
TIntermTyped* addConstStruct(TString& , TIntermTyped*, const TSourceLoc&);
TIntermTyped* addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression);
// Performs an error check for embedded struct declarations.
// Returns true if an error was raised due to the declaration of
// this struct.
bool enterStructDeclaration(TSourceLoc line, const TString& identifier);
bool enterStructDeclaration(const TSourceLoc& line, const TString& identifier);
void exitStructDeclaration();
bool structNestingErrorCheck(TSourceLoc line, const TType& fieldType);
bool structNestingErrorCheck(const TSourceLoc& line, const TField& field);
};
int PaParseStrings(size_t count, const char* const string[], const int length[],

View File

@ -17,55 +17,32 @@
OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX;
void InitializeGlobalPools()
{
TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
if (globalPools)
return;
TThreadGlobalPools* threadData = new TThreadGlobalPools();
threadData->globalPoolAllocator = 0;
OS_SetTLSValue(PoolIndex, threadData);
}
void FreeGlobalPools()
{
// Release the allocated memory for this thread.
TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
if (!globalPools)
return;
delete globalPools;
}
bool InitializePoolIndex()
{
// Allocate a TLS index.
if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX)
return false;
assert(PoolIndex == OS_INVALID_TLS_INDEX);
return true;
PoolIndex = OS_AllocTLSIndex();
return PoolIndex != OS_INVALID_TLS_INDEX;
}
void FreePoolIndex()
{
// Release the TLS index.
assert(PoolIndex != OS_INVALID_TLS_INDEX);
OS_FreeTLSIndex(PoolIndex);
PoolIndex = OS_INVALID_TLS_INDEX;
}
TPoolAllocator& GetGlobalPoolAllocator()
TPoolAllocator* GetGlobalPoolAllocator()
{
TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
return *threadData->globalPoolAllocator;
assert(PoolIndex != OS_INVALID_TLS_INDEX);
return static_cast<TPoolAllocator*>(OS_GetTLSValue(PoolIndex));
}
void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator)
{
TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
threadData->globalPoolAllocator = poolAllocator;
assert(PoolIndex != OS_INVALID_TLS_INDEX);
OS_SetTLSValue(PoolIndex, poolAllocator);
}
//
@ -228,24 +205,27 @@ void TPoolAllocator::popAll()
void* TPoolAllocator::allocate(size_t numBytes)
{
// If we are using guard blocks, all allocations are bracketed by
// them: [guardblock][allocation][guardblock]. numBytes is how
// much memory the caller asked for. allocationSize is the total
// size including guard blocks. In release build,
// guardBlockSize=0 and this all gets optimized away.
size_t allocationSize = TAllocation::allocationSize(numBytes);
//
// Just keep some interesting statistics.
//
++numCalls;
totalBytes += numBytes;
// If we are using guard blocks, all allocations are bracketed by
// them: [guardblock][allocation][guardblock]. numBytes is how
// much memory the caller asked for. allocationSize is the total
// size including guard blocks. In release build,
// guardBlockSize=0 and this all gets optimized away.
size_t allocationSize = TAllocation::allocationSize(numBytes);
// Detect integer overflow.
if (allocationSize < numBytes)
return 0;
//
// Do the allocation, most likely case first, for efficiency.
// This step could be moved to be inline sometime.
//
if (currentPageOffset + allocationSize <= pageSize) {
if (allocationSize <= pageSize - currentPageOffset) {
//
// Safe to allocate from currentPageOffset.
//
@ -256,12 +236,16 @@ void* TPoolAllocator::allocate(size_t numBytes)
return initializeAllocation(inUseList, memory, numBytes);
}
if (allocationSize + headerSkip > pageSize) {
if (allocationSize > pageSize - headerSkip) {
//
// Do a multi-page allocation. Don't mix these with the others.
// The OS is efficient and allocating and free-ing multiple pages.
//
size_t numBytesToAlloc = allocationSize + headerSkip;
// Detect integer overflow.
if (numBytesToAlloc < allocationSize)
return 0;
tHeader* memory = reinterpret_cast<tHeader*>(::new char[numBytesToAlloc]);
if (memory == 0)
return 0;

View File

@ -219,14 +219,8 @@ private:
// different times. But a simple use is to have a global pop
// with everyone using the same global allocator.
//
extern TPoolAllocator& GetGlobalPoolAllocator();
extern TPoolAllocator* GetGlobalPoolAllocator();
extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator);
#define GlobalPoolAllocator GetGlobalPoolAllocator()
struct TThreadGlobalPools
{
TPoolAllocator* globalPoolAllocator;
};
//
// This STL compatible allocator is intended to be used as the allocator
@ -253,7 +247,7 @@ public:
pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) const { return &x; }
pool_allocator() : allocator(&GlobalPoolAllocator) { }
pool_allocator() : allocator(GetGlobalPoolAllocator()) { }
pool_allocator(TPoolAllocator& a) : allocator(&a) { }
pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { }

View File

@ -70,6 +70,7 @@ public:
TInfoSink& getInfoSink() { return infoSink; }
const TVariableInfoList& getAttribs() const { return attribs; }
const TVariableInfoList& getUniforms() const { return uniforms; }
const TVariableInfoList& getVaryings() const { return varyings; }
int getMappedNameMaxLength() const;
ShHashFunction64 getHashFunction() const { return hashFunction; }
@ -83,15 +84,15 @@ protected:
bool InitBuiltInSymbolTable(const ShBuiltInResources& resources);
// Clears the results from the previous compilation.
void clearResults();
// Return true if function recursion is detected.
bool detectRecursion(TIntermNode* root);
// Return true if function recursion is detected or call depth exceeded.
bool detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth);
// 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
// functionality mandated in GLSL 1.0 spec Appendix A.
bool validateLimitations(TIntermNode* root);
// Collect info for all attribs and uniforms.
void collectAttribsUniforms(TIntermNode* root);
// Collect info for all attribs, uniforms, varyings.
void collectVariables(TIntermNode* root);
// Map long variable names into shorter ones.
void mapLongVariableNames(TIntermNode* root);
// Translate to object code.
@ -106,6 +107,8 @@ protected:
// 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);
// Return true if the maximum expression complexity below the limit.
bool limitExpressionComplexity(TIntermNode* root);
// Get built-in extensions with default behavior.
const TExtensionBehavior& getExtensionBehavior() const;
// Get the resources set by InitBuiltInSymbolTable
@ -120,6 +123,8 @@ private:
ShShaderSpec shaderSpec;
int maxUniformVectors;
int maxExpressionComplexity;
int maxCallStackDepth;
ShBuiltInResources compileResources;
@ -138,6 +143,7 @@ private:
TInfoSink infoSink; // Output sink.
TVariableInfoList attribs; // Active attributes in the compiled shader.
TVariableInfoList uniforms; // Active uniforms in the compiled shader.
TVariableInfoList varyings; // Varyings in the compiled shader.
// Cached copy of the ref-counted singleton.
LongNameMap* longNameMap;

View File

@ -15,20 +15,25 @@
#include "compiler/preprocessor/length_limits.h"
#include "compiler/ShHandle.h"
#include "compiler/TranslatorHLSL.h"
#include "compiler/VariablePacker.h"
//
// This is the platform independent interface between an OGL driver
// and the shading language compiler.
//
static bool checkActiveUniformAndAttribMaxLengths(const ShHandle handle,
size_t expectedValue)
static bool checkVariableMaxLengths(const ShHandle handle,
size_t expectedValue)
{
size_t activeUniformLimit = 0;
ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit);
size_t activeAttribLimit = 0;
ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit);
return (expectedValue == activeUniformLimit && expectedValue == activeAttribLimit);
size_t varyingLimit = 0;
ShGetInfo(handle, SH_VARYING_MAX_LENGTH, &varyingLimit);
return (expectedValue == activeUniformLimit &&
expectedValue == activeAttribLimit &&
expectedValue == varyingLimit);
}
static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue)
@ -38,62 +43,14 @@ static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue
return (expectedValue == mappedNameMaxLength);
}
static void getVariableInfo(ShShaderInfo varType,
const ShHandle handle,
int index,
size_t* length,
int* size,
ShDataType* type,
char* name,
char* mappedName)
{
if (!handle || !size || !type || !name)
return;
ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
(varType == SH_ACTIVE_UNIFORMS));
TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
TCompiler* compiler = base->getAsCompiler();
if (compiler == 0)
return;
const TVariableInfoList& varList = varType == SH_ACTIVE_ATTRIBUTES ?
compiler->getAttribs() : compiler->getUniforms();
if (index < 0 || index >= static_cast<int>(varList.size()))
return;
const TVariableInfo& varInfo = varList[index];
if (length) *length = varInfo.name.size();
*size = varInfo.size;
*type = varInfo.type;
// This size must match that queried by
// SH_ACTIVE_UNIFORM_MAX_LENGTH and SH_ACTIVE_ATTRIBUTE_MAX_LENGTH
// in ShGetInfo, below.
size_t activeUniformAndAttribLength = 1 + MAX_SYMBOL_NAME_LEN;
ASSERT(checkActiveUniformAndAttribMaxLengths(handle, activeUniformAndAttribLength));
strncpy(name, varInfo.name.c_str(), activeUniformAndAttribLength);
name[activeUniformAndAttribLength - 1] = 0;
if (mappedName) {
// This size must match that queried by
// SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below.
size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN;
ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength));
strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength);
mappedName[maxMappedNameLength - 1] = 0;
}
}
//
// Driver must call this first, once, before doing any other
// compiler operations.
// Driver must call this first, once, before doing any other compiler operations.
// Subsequent calls to this function are no-op.
//
int ShInitialize()
{
if (!InitProcess())
return 0;
return 1;
static const bool kInitialized = InitProcess();
return kInitialized ? 1 : 0;
}
//
@ -101,9 +58,7 @@ int ShInitialize()
//
int ShFinalize()
{
if (!DetachProcess())
return 0;
DetachProcess();
return 1;
}
@ -127,6 +82,7 @@ void ShInitBuiltInResources(ShBuiltInResources* resources)
resources->OES_EGL_image_external = 0;
resources->ARB_texture_rectangle = 0;
resources->EXT_draw_buffers = 0;
resources->EXT_frag_depth = 0;
// Disable highp precision in fragment shader by default.
resources->FragmentPrecisionHigh = 0;
@ -144,9 +100,6 @@ ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec,
ShShaderOutput output,
const ShBuiltInResources* resources)
{
if (!InitThread())
return 0;
TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output));
TCompiler* compiler = base->getAsCompiler();
if (compiler == 0)
@ -185,9 +138,6 @@ int ShCompile(
size_t numStrings,
int compileOptions)
{
if (!InitThread())
return 0;
if (handle == 0)
return 0;
@ -229,6 +179,12 @@ void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params)
case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
*params = 1 + MAX_SYMBOL_NAME_LEN;
break;
case SH_VARYINGS:
*params = compiler->getVaryings().size();
break;
case SH_VARYING_MAX_LENGTH:
*params = 1 + MAX_SYMBOL_NAME_LEN;
break;
case SH_MAPPED_NAME_MAX_LENGTH:
// Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to
// handle array and struct dereferences.
@ -286,28 +242,71 @@ void ShGetObjectCode(const ShHandle handle, char* objCode)
strcpy(objCode, infoSink.obj.c_str());
}
void ShGetActiveAttrib(const ShHandle handle,
void ShGetVariableInfo(const ShHandle handle,
ShShaderInfo varType,
int index,
size_t* length,
int* size,
ShDataType* type,
ShPrecisionType* precision,
int* staticUse,
char* name,
char* mappedName)
{
getVariableInfo(SH_ACTIVE_ATTRIBUTES,
handle, index, length, size, type, name, mappedName);
}
if (!handle || !size || !type || !precision || !staticUse || !name)
return;
ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
(varType == SH_ACTIVE_UNIFORMS) ||
(varType == SH_VARYINGS));
void ShGetActiveUniform(const ShHandle handle,
int index,
size_t* length,
int* size,
ShDataType* type,
char* name,
char* mappedName)
{
getVariableInfo(SH_ACTIVE_UNIFORMS,
handle, index, length, size, type, name, mappedName);
TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
TCompiler* compiler = base->getAsCompiler();
if (compiler == 0)
return;
const TVariableInfoList& varList =
varType == SH_ACTIVE_ATTRIBUTES ? compiler->getAttribs() :
(varType == SH_ACTIVE_UNIFORMS ? compiler->getUniforms() :
compiler->getVaryings());
if (index < 0 || index >= static_cast<int>(varList.size()))
return;
const TVariableInfo& varInfo = varList[index];
if (length) *length = varInfo.name.size();
*size = varInfo.size;
*type = varInfo.type;
switch (varInfo.precision) {
case EbpLow:
*precision = SH_PRECISION_LOWP;
break;
case EbpMedium:
*precision = SH_PRECISION_MEDIUMP;
break;
case EbpHigh:
*precision = SH_PRECISION_HIGHP;
break;
default:
// Some types does not support precision, for example, boolean.
*precision = SH_PRECISION_UNDEFINED;
break;
}
*staticUse = varInfo.staticUse ? 1 : 0;
// This size must match that queried by
// SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH
// in ShGetInfo, below.
size_t variableLength = 1 + MAX_SYMBOL_NAME_LEN;
ASSERT(checkVariableMaxLengths(handle, variableLength));
strncpy(name, varInfo.name.c_str(), variableLength);
name[variableLength - 1] = 0;
if (mappedName) {
// This size must match that queried by
// SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below.
size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN;
ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength));
strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength);
mappedName[maxMappedNameLength - 1] = 0;
}
}
void ShGetNameHashingEntry(const ShHandle handle,
@ -370,3 +369,19 @@ void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params)
default: UNREACHABLE();
}
}
int ShCheckVariablesWithinPackingLimits(
int maxVectors, ShVariableInfo* varInfoArray, size_t varInfoArraySize)
{
if (varInfoArraySize == 0)
return 1;
ASSERT(varInfoArray);
TVariableInfoList variables;
for (size_t ii = 0; ii < varInfoArraySize; ++ii)
{
TVariableInfo var(varInfoArray[ii].type, varInfoArray[ii].size);
variables.push_back(var);
}
VariablePacker packer;
return packer.CheckVariablesWithinPackingLimits(maxVectors, variables) ? 1 : 0;
}

View File

@ -17,48 +17,34 @@
#include <stdio.h>
#include <algorithm>
#include "common/angleutils.h"
#include <climits>
TType::TType(const TPublicType &p) :
type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize),
maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize), structure(0)
{
if (p.userDef) {
if (p.userDef)
structure = p.userDef->getStruct();
typeName = NewPoolTString(p.userDef->getTypeName().c_str());
computeDeepestStructNesting();
}
}
//
// Recursively generate mangled names.
//
void TType::buildMangledName(TString& mangledName)
TString TType::buildMangledName() const
{
TString mangledName;
if (isMatrix())
mangledName += 'm';
else if (isVector())
mangledName += 'v';
switch (type) {
case EbtFloat: mangledName += 'f'; break;
case EbtInt: mangledName += 'i'; break;
case EbtBool: mangledName += 'b'; break;
case EbtSampler2D: mangledName += "s2"; break;
case EbtSamplerCube: mangledName += "sC"; break;
case EbtStruct:
mangledName += "struct-";
if (typeName)
mangledName += *typeName;
{// support MSVC++6.0
for (unsigned int i = 0; i < structure->size(); ++i) {
mangledName += '-';
(*structure)[i].type->buildMangledName(mangledName);
}
}
default:
break;
case EbtFloat: mangledName += 'f'; break;
case EbtInt: mangledName += 'i'; break;
case EbtBool: mangledName += 'b'; break;
case EbtSampler2D: mangledName += "s2"; break;
case EbtSamplerCube: mangledName += "sC"; break;
case EbtStruct: mangledName += structure->mangledName(); break;
default: break;
}
mangledName += static_cast<char>('0' + getNominalSize());
@ -69,55 +55,74 @@ void TType::buildMangledName(TString& mangledName)
mangledName += buf;
mangledName += ']';
}
return mangledName;
}
int TType::getStructSize() const
size_t TType::getObjectSize() const
{
if (!getStruct()) {
assert(false && "Not a struct");
return 0;
size_t totalSize = 0;
if (getBasicType() == EbtStruct)
totalSize = structure->objectSize();
else if (matrix)
totalSize = size * size;
else
totalSize = size;
if (isArray()) {
size_t arraySize = getArraySize();
if (arraySize > INT_MAX / totalSize)
totalSize = INT_MAX;
else
totalSize *= arraySize;
}
if (structureSize == 0)
for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++)
structureSize += ((*tl).type)->getObjectSize();
return structureSize;
return totalSize;
}
void TType::computeDeepestStructNesting()
bool TStructure::containsArrays() const
{
if (!getStruct()) {
return;
}
int maxNesting = 0;
for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); ++tl) {
maxNesting = std::max(maxNesting, ((*tl).type)->getDeepestStructNesting());
}
deepestStructNesting = 1 + maxNesting;
}
bool TType::isStructureContainingArrays() const
{
if (!structure)
{
return false;
}
for (TTypeList::const_iterator member = structure->begin(); member != structure->end(); member++)
{
if (member->type->isArray() ||
member->type->isStructureContainingArrays())
{
for (size_t i = 0; i < mFields->size(); ++i) {
const TType* fieldType = (*mFields)[i]->type();
if (fieldType->isArray() || fieldType->isStructureContainingArrays())
return true;
}
}
return false;
}
TString TStructure::buildMangledName() const
{
TString mangledName("struct-");
mangledName += *mName;
for (size_t i = 0; i < mFields->size(); ++i) {
mangledName += '-';
mangledName += (*mFields)[i]->type()->getMangledName();
}
return mangledName;
}
size_t TStructure::calculateObjectSize() const
{
size_t size = 0;
for (size_t i = 0; i < mFields->size(); ++i) {
size_t fieldSize = (*mFields)[i]->type()->getObjectSize();
if (fieldSize > INT_MAX - size)
size = INT_MAX;
else
size += fieldSize;
}
return size;
}
int TStructure::calculateDeepestNesting() const
{
int maxNesting = 0;
for (size_t i = 0; i < mFields->size(); ++i) {
maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting());
}
return 1 + maxNesting;
}
//
// Dump functions.
//
@ -196,84 +201,16 @@ void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext)
{
for (tLevel::iterator it = level.begin(); it != level.end(); ++it) {
if (it->second->isFunction()) {
TFunction* function = static_cast<TFunction*>(it->second);
if (function->getName() == name)
function->relateToExtension(ext);
}
TSymbol* symbol = it->second;
if (symbol->getName() == name)
symbol->relateToExtension(ext);
}
}
TSymbol::TSymbol(const TSymbol& copyOf)
TSymbolTable::~TSymbolTable()
{
name = NewPoolTString(copyOf.name->c_str());
uniqueId = copyOf.uniqueId;
}
TVariable::TVariable(const TVariable& copyOf, TStructureMap& remapper) : TSymbol(copyOf)
{
type.copyType(copyOf.type, remapper);
userType = copyOf.userType;
// for builtIn symbol table level, unionArray and arrayInformation pointers should be NULL
assert(copyOf.arrayInformationType == 0);
arrayInformationType = 0;
if (copyOf.unionArray) {
assert(!copyOf.type.getStruct());
assert(copyOf.type.getObjectSize() == 1);
unionArray = new ConstantUnion[1];
unionArray[0] = copyOf.unionArray[0];
} else
unionArray = 0;
}
TVariable* TVariable::clone(TStructureMap& remapper)
{
TVariable *variable = new TVariable(*this, remapper);
return variable;
}
TFunction::TFunction(const TFunction& copyOf, TStructureMap& remapper) : TSymbol(copyOf)
{
for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) {
TParameter param;
parameters.push_back(param);
parameters.back().copyParam(copyOf.parameters[i], remapper);
}
returnType.copyType(copyOf.returnType, remapper);
mangledName = copyOf.mangledName;
op = copyOf.op;
defined = copyOf.defined;
}
TFunction* TFunction::clone(TStructureMap& remapper)
{
TFunction *function = new TFunction(*this, remapper);
return function;
}
TSymbolTableLevel* TSymbolTableLevel::clone(TStructureMap& remapper)
{
TSymbolTableLevel *symTableLevel = new TSymbolTableLevel();
tLevel::iterator iter;
for (iter = level.begin(); iter != level.end(); ++iter) {
symTableLevel->insert(*iter->second->clone(remapper));
}
return symTableLevel;
}
void TSymbolTable::copyTable(const TSymbolTable& copyOf)
{
TStructureMap remapper;
uniqueId = copyOf.uniqueId;
for (unsigned int i = 0; i < copyOf.table.size(); ++i) {
table.push_back(copyOf.table[i]->clone(remapper));
}
for( unsigned int i = 0; i < copyOf.precisionStack.size(); i++) {
precisionStack.push_back( copyOf.precisionStack[i] );
}
for (size_t i = 0; i < table.size(); ++i)
delete table[i];
for (size_t i = 0; i < precisionStack.size(); ++i)
delete precisionStack[i];
}

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2013 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.
//
@ -32,6 +32,7 @@
#include <assert.h>
#include "common/angleutils.h"
#include "compiler/InfoSink.h"
#include "compiler/intermediate.h"
@ -40,9 +41,10 @@
//
class TSymbol {
public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
TSymbol(const TString *n) : name(n) { }
POOL_ALLOCATOR_NEW_DELETE();
TSymbol(const TString* n) : uniqueId(0), name(n) { }
virtual ~TSymbol() { /* don't delete name, it's from the pool */ }
const TString& getName() const { return *name; }
virtual const TString& getMangledName() const { return getName(); }
virtual bool isFunction() const { return false; }
@ -50,12 +52,15 @@ public:
void setUniqueId(int id) { uniqueId = id; }
int getUniqueId() const { return uniqueId; }
virtual void dump(TInfoSink &infoSink) const = 0;
TSymbol(const TSymbol&);
virtual TSymbol* clone(TStructureMap& remapper) = 0;
void relateToExtension(const TString& ext) { extension = ext; }
const TString& getExtension() const { return extension; }
protected:
private:
DISALLOW_COPY_AND_ASSIGN(TSymbol);
int uniqueId; // For real comparing during code generation
const TString *name;
unsigned int uniqueId; // For real comparing during code generation
TString extension;
};
//
@ -70,15 +75,13 @@ protected:
//
class TVariable : public TSymbol {
public:
TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0), arrayInformationType(0) { }
TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0) { }
virtual ~TVariable() { }
virtual bool isVariable() const { return true; }
TType& getType() { return type; }
const TType& getType() const { return type; }
bool isUserType() const { return userType; }
void setQualifier(TQualifier qualifier) { type.setQualifier(qualifier); }
void updateArrayInformationType(TType *t) { arrayInformationType = t; }
TType* getArrayInformationType() { return arrayInformationType; }
virtual void dump(TInfoSink &infoSink) const;
@ -100,16 +103,15 @@ public:
delete[] unionArray;
unionArray = constArray;
}
TVariable(const TVariable&, TStructureMap& remapper); // copy constructor
virtual TVariable* clone(TStructureMap& remapper);
protected:
private:
DISALLOW_COPY_AND_ASSIGN(TVariable);
TType type;
bool userType;
// we are assuming that Pool Allocator will free the memory allocated to unionArray
// when this object is destroyed
ConstantUnion *unionArray;
TType *arrayInformationType; // this is used for updating maxArraySize in all the references to a given symbol
};
//
@ -119,11 +121,6 @@ protected:
struct TParameter {
TString *name;
TType* type;
void copyParam(const TParameter& param, TStructureMap& remapper)
{
name = NewPoolTString(param.name->c_str());
type = param.type->clone(remapper);
}
};
//
@ -163,9 +160,6 @@ public:
void relateToOperator(TOperator o) { op = o; }
TOperator getBuiltInOp() const { return op; }
void relateToExtension(const TString& ext) { extension = ext; }
const TString& getExtension() const { return extension; }
void setDefined() { defined = true; }
bool isDefined() { return defined; }
@ -173,16 +167,15 @@ public:
const TParameter& getParam(size_t i) const { return parameters[i]; }
virtual void dump(TInfoSink &infoSink) const;
TFunction(const TFunction&, TStructureMap& remapper);
virtual TFunction* clone(TStructureMap& remapper);
protected:
private:
DISALLOW_COPY_AND_ASSIGN(TFunction);
typedef TVector<TParameter> TParamList;
TParamList parameters;
TType returnType;
TString mangledName;
TOperator op;
TString extension;
bool defined;
};
@ -194,21 +187,24 @@ public:
typedef const tLevel::value_type tLevelPair;
typedef std::pair<tLevel::iterator, bool> tInsertResult;
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
TSymbolTableLevel() { }
~TSymbolTableLevel();
bool insert(TSymbol& symbol)
bool insert(const TString &name, TSymbol &symbol)
{
//
// returning true means symbol was added to the table
//
tInsertResult result;
result = level.insert(tLevelPair(symbol.getMangledName(), &symbol));
tInsertResult result = level.insert(tLevelPair(name, &symbol));
return result.second;
}
bool insert(TSymbol &symbol)
{
return insert(symbol.getMangledName(), symbol);
}
TSymbol* find(const TString& name) const
{
tLevel::const_iterator it = level.find(name);
@ -231,7 +227,6 @@ public:
void relateToOperator(const char* name, TOperator op);
void relateToExtension(const char* name, const TString& ext);
void dump(TInfoSink &infoSink) const;
TSymbolTableLevel* clone(TStructureMap& remapper);
protected:
tLevel level;
@ -247,13 +242,7 @@ public:
// that the symbol table has not been preloaded with built-ins.
//
}
~TSymbolTable()
{
// level 0 is always built In symbols, so we never pop that out
while (table.size() > 1)
pop();
}
~TSymbolTable();
//
// When the symbol table is initialized with the built-ins, there should
@ -266,13 +255,15 @@ public:
void push()
{
table.push_back(new TSymbolTableLevel);
precisionStack.push_back( PrecisionStackLevel() );
precisionStack.push_back(new PrecisionStackLevel);
}
void pop()
{
delete table[currentLevel()];
delete table.back();
table.pop_back();
delete precisionStack.back();
precisionStack.pop_back();
}
@ -282,6 +273,35 @@ public:
return table[currentLevel()]->insert(symbol);
}
bool insertConstInt(const char *name, int value)
{
TVariable *constant = new TVariable(NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1));
constant->getConstPointer()->setIConst(value);
return insert(*constant);
}
bool insertBuiltIn(TType *rvalue, const char *name, TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0)
{
TFunction *function = new TFunction(NewPoolTString(name), *rvalue);
TParameter param1 = {NULL, ptype1};
function->addParameter(param1);
if(ptype2)
{
TParameter param2 = {NULL, ptype2};
function->addParameter(param2);
}
if(ptype3)
{
TParameter param3 = {NULL, ptype3};
function->addParameter(param3);
}
return insert(*function);
}
TSymbol* find(const TString& name, bool* builtIn = 0, bool *sameScope = 0)
{
int level = currentLevel();
@ -298,16 +318,11 @@ public:
return symbol;
}
TSymbol *findBuiltIn(const TString &name)
TSymbol* findBuiltIn(const TString &name)
{
return table[0]->find(name);
}
TSymbolTableLevel* getGlobalLevel() {
assert(table.size() >= 2);
return table[1];
}
TSymbolTableLevel* getOuterLevel() {
assert(table.size() >= 2);
return table[currentLevel() - 1];
@ -319,32 +334,29 @@ public:
void relateToExtension(const char* name, const TString& ext) {
table[0]->relateToExtension(name, ext);
}
int getMaxSymbolId() { return uniqueId; }
void dump(TInfoSink &infoSink) const;
void copyTable(const TSymbolTable& copyOf);
bool setDefaultPrecision( const TPublicType& type, TPrecision prec ){
if (IsSampler(type.type))
return true; // Skip sampler types for the time being
if (type.type != EbtFloat && type.type != EbtInt)
return false; // Only set default precision for int/float
bool setDefaultPrecision(const TPublicType& type, TPrecision prec) {
if (!supportsPrecision(type.type))
return false;
if (type.size != 1 || type.matrix || type.array)
return false; // Not allowed to set for aggregate types
int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
precisionStack[indexOfLastElement][type.type] = prec; // Uses map operator [], overwrites the current value
(*precisionStack[indexOfLastElement])[type.type] = prec; // Uses map operator [], overwrites the current value
return true;
}
// Searches down the precisionStack for a precision qualifier for the specified TBasicType
TPrecision getDefaultPrecision( TBasicType type){
if( type != EbtFloat && type != EbtInt ) return EbpUndefined;
TPrecision getDefaultPrecision(TBasicType type) {
if (!supportsPrecision(type))
return EbpUndefined;
int level = static_cast<int>(precisionStack.size()) - 1;
assert( level >= 0); // Just to be safe. Should not happen.
assert(level >= 0); // Just to be safe. Should not happen.
PrecisionStackLevel::iterator it;
TPrecision prec = EbpUndefined; // If we dont find anything we return this. Should we error check this?
while( level >= 0 ){
it = precisionStack[level].find( type );
if( it != precisionStack[level].end() ){
while (level >= 0) {
it = precisionStack[level]->find(type);
if (it != precisionStack[level]->end()) {
prec = (*it).second;
break;
}
@ -353,13 +365,18 @@ public:
return prec;
}
protected:
private:
int currentLevel() const { return static_cast<int>(table.size()) - 1; }
std::vector<TSymbolTableLevel*> table;
typedef std::map< TBasicType, TPrecision > PrecisionStackLevel;
std::vector< PrecisionStackLevel > precisionStack;
bool supportsPrecision(TBasicType type) {
// Only supports precision for int, float, and sampler types.
return type == EbtFloat || type == EbtInt || IsSampler(type);
}
int uniqueId; // for unique identification in code generation
std::vector<TSymbolTableLevel*> table;
typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
std::vector<PrecisionStackLevel*> precisionStack;
};
#endif // _SYMBOL_TABLE_INCLUDED_

View File

@ -7,30 +7,85 @@
#ifndef _TYPES_INCLUDED
#define _TYPES_INCLUDED
#include "common/angleutils.h"
#include "compiler/BaseTypes.h"
#include "compiler/Common.h"
#include "compiler/debug.h"
class TType;
struct TPublicType;
class TType;
//
// Need to have association of line numbers to types in a list for building structs.
//
struct TTypeLine {
TType* type;
int line;
};
typedef TVector<TTypeLine> TTypeList;
inline TTypeList* NewPoolTTypeList()
class TField
{
void* memory = GlobalPoolAllocator.allocate(sizeof(TTypeList));
return new(memory) TTypeList;
public:
POOL_ALLOCATOR_NEW_DELETE();
TField(TType* type, TString* name) : mType(type), mName(name) {}
// TODO(alokp): We should only return const type.
// Fix it by tweaking grammar.
TType* type() { return mType; }
const TType* type() const { return mType; }
const TString& name() const { return *mName; }
private:
DISALLOW_COPY_AND_ASSIGN(TField);
TType* mType;
TString* mName;
};
typedef TVector<TField*> TFieldList;
inline TFieldList* NewPoolTFieldList()
{
void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList));
return new(memory) TFieldList;
}
typedef TMap<TTypeList*, TTypeList*> TStructureMap;
typedef TMap<TTypeList*, TTypeList*>::iterator TStructureMapIterator;
class TStructure
{
public:
POOL_ALLOCATOR_NEW_DELETE();
TStructure(TString* name, TFieldList* fields)
: mName(name),
mFields(fields),
mObjectSize(0),
mDeepestNesting(0) {
}
const TString& name() const { return *mName; }
const TFieldList& fields() const { return *mFields; }
const TString& mangledName() const {
if (mMangledName.empty())
mMangledName = buildMangledName();
return mMangledName;
}
size_t objectSize() const {
if (mObjectSize == 0)
mObjectSize = calculateObjectSize();
return mObjectSize;
};
int deepestNesting() const {
if (mDeepestNesting == 0)
mDeepestNesting = calculateDeepestNesting();
return mDeepestNesting;
}
bool containsArrays() const;
private:
DISALLOW_COPY_AND_ASSIGN(TStructure);
TString buildMangledName() const;
size_t calculateObjectSize() const;
int calculateDeepestNesting() const;
TString* mName;
TFieldList* mFields;
mutable TString mMangledName;
mutable size_t mObjectSize;
mutable int mDeepestNesting;
};
//
// Base class for things that have a type.
@ -38,72 +93,16 @@ typedef TMap<TTypeList*, TTypeList*>::iterator TStructureMapIterator;
class TType
{
public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
POOL_ALLOCATOR_NEW_DELETE();
TType() {}
TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) :
type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0),
maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), structure(0)
{
}
explicit TType(const TPublicType &p);
TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) :
type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0),
maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0)
TType(TStructure* userDef, TPrecision p = EbpUndefined) :
type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), structure(userDef)
{
typeName = NewPoolTString(n.c_str());
}
void copyType(const TType& copyOf, TStructureMap& remapper)
{
type = copyOf.type;
precision = copyOf.precision;
qualifier = copyOf.qualifier;
size = copyOf.size;
matrix = copyOf.matrix;
array = copyOf.array;
arraySize = copyOf.arraySize;
TStructureMapIterator iter;
if (copyOf.structure) {
if ((iter = remapper.find(structure)) == remapper.end()) {
// create the new structure here
structure = NewPoolTTypeList();
for (unsigned int i = 0; i < copyOf.structure->size(); ++i) {
TTypeLine typeLine;
typeLine.line = (*copyOf.structure)[i].line;
typeLine.type = (*copyOf.structure)[i].type->clone(remapper);
structure->push_back(typeLine);
}
} else {
structure = iter->second;
}
} else
structure = 0;
fieldName = 0;
if (copyOf.fieldName)
fieldName = NewPoolTString(copyOf.fieldName->c_str());
typeName = 0;
if (copyOf.typeName)
typeName = NewPoolTString(copyOf.typeName->c_str());
mangled = 0;
if (copyOf.mangled)
mangled = NewPoolTString(copyOf.mangled->c_str());
structureSize = copyOf.structureSize;
maxArraySize = copyOf.maxArraySize;
deepestStructNesting = copyOf.deepestStructNesting;
assert(copyOf.arrayInformationType == 0);
arrayInformationType = 0; // arrayInformationType should not be set for builtIn symbol table level
}
TType* clone(TStructureMap& remapper)
{
TType *newType = new TType();
newType->copyType(*this, remapper);
return newType;
}
TBasicType getBasicType() const { return type; }
@ -119,34 +118,18 @@ public:
int getNominalSize() const { return size; }
void setNominalSize(int s) { size = s; }
// Full size of single instance of type
int getObjectSize() const
{
int totalSize;
if (getBasicType() == EbtStruct)
totalSize = getStructSize();
else if (matrix)
totalSize = size * size;
else
totalSize = size;
if (isArray())
totalSize *= std::max(getArraySize(), getMaxArraySize());
return totalSize;
}
size_t getObjectSize() const;
int elementRegisterCount() const
{
TTypeList *structure = getStruct();
if (structure)
{
const TFieldList &fields = getStruct()->fields();
int registerCount = 0;
for (size_t i = 0; i < structure->size(); i++)
for (size_t i = 0; i < fields.size(); i++)
{
registerCount += (*structure)[i].type->totalRegisterCount();
registerCount += fields[i]->type()->totalRegisterCount();
}
return registerCount;
@ -179,47 +162,20 @@ public:
bool isArray() const { return array ? true : false; }
int getArraySize() const { return arraySize; }
void setArraySize(int s) { array = true; arraySize = s; }
int getMaxArraySize () const { return maxArraySize; }
void setMaxArraySize (int s) { maxArraySize = s; }
void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; }
void setArrayInformationType(TType* t) { arrayInformationType = t; }
TType* getArrayInformationType() const { return arrayInformationType; }
void clearArrayness() { array = false; arraySize = 0; }
bool isVector() const { return size > 1 && !matrix; }
bool isScalar() const { return size == 1 && !matrix && !structure; }
TTypeList* getStruct() const { return structure; }
void setStruct(TTypeList* s) { structure = s; computeDeepestStructNesting(); }
TStructure* getStruct() const { return structure; }
void setStruct(TStructure* s) { structure = s; }
const TString& getTypeName() const
{
assert(typeName);
return *typeName;
}
void setTypeName(const TString& n)
{
typeName = NewPoolTString(n.c_str());
}
bool isField() const { return fieldName != 0; }
const TString& getFieldName() const
{
assert(fieldName);
return *fieldName;
}
void setFieldName(const TString& n)
{
fieldName = NewPoolTString(n.c_str());
}
TString& getMangledName() {
if (!mangled) {
mangled = NewPoolTString("");
buildMangledName(*mangled);
*mangled += ';' ;
const TString& getMangledName() const {
if (mangled.empty()) {
mangled = buildMangledName();
mangled += ';';
}
return *mangled;
return mangled;
}
bool sameElementType(const TType& right) const {
@ -267,14 +223,16 @@ public:
// For type "nesting2", this method would return 2 -- the number
// of structures through which indirection must occur to reach the
// deepest field (nesting2.field1.position).
int getDeepestStructNesting() const { return deepestStructNesting; }
int getDeepestStructNesting() const {
return structure ? structure->deepestNesting() : 0;
}
bool isStructureContainingArrays() const;
bool isStructureContainingArrays() const {
return structure ? structure->containsArrays() : false;
}
protected:
void buildMangledName(TString&);
int getStructSize() const;
void computeDeepestStructNesting();
private:
TString buildMangledName() const;
TBasicType type : 6;
TPrecision precision;
@ -283,16 +241,10 @@ protected:
unsigned int matrix : 1;
unsigned int array : 1;
int arraySize;
int maxArraySize;
TType* arrayInformationType;
TTypeList* structure; // 0 unless this is a struct
mutable int structureSize;
int deepestStructNesting;
TStructure* structure; // 0 unless this is a struct
TString *fieldName; // for structure field names
TString *mangled;
TString *typeName; // for structure field type name
mutable TString mangled;
};
//
@ -314,9 +266,9 @@ struct TPublicType
bool array;
int arraySize;
TType* userDef;
int line;
TSourceLoc line;
void setBasic(TBasicType bt, TQualifier q, int ln = 0)
void setBasic(TBasicType bt, TQualifier q, const TSourceLoc& ln)
{
type = bt;
qualifier = q;

View File

@ -435,7 +435,7 @@ bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node)
return true;
bool valid = true;
TSymbolTable& symbolTable = GlobalParseContext->symbolTable;
TSymbolTable& symbolTable = GetGlobalParseContext()->symbolTable;
TSymbol* symbol = symbolTable.find(node->getName());
ASSERT(symbol && symbol->isFunction());
TFunction* function = static_cast<TFunction*>(symbol);

View File

@ -6,15 +6,17 @@
#include "compiler/VariableInfo.h"
static TString arrayBrackets(int index)
namespace {
TString arrayBrackets(int index)
{
TStringStream stream;
stream << "[" << index << "]";
return stream.str();
}
// Returns the data type for an attribute or uniform.
static ShDataType getVariableDataType(const TType& type)
// Returns the data type for an attribute, uniform, or varying.
ShDataType getVariableDataType(const TType& type)
{
switch (type.getBasicType()) {
case EbtFloat:
@ -70,22 +72,22 @@ static ShDataType getVariableDataType(const TType& type)
return SH_NONE;
}
static void getBuiltInVariableInfo(const TType& type,
const TString& name,
const TString& mappedName,
TVariableInfoList& infoList);
static void getUserDefinedVariableInfo(const TType& type,
const TString& name,
const TString& mappedName,
TVariableInfoList& infoList,
ShHashFunction64 hashFunction);
// Returns info for an attribute or uniform.
static void getVariableInfo(const TType& type,
void getBuiltInVariableInfo(const TType& type,
const TString& name,
const TString& mappedName,
TVariableInfoList& infoList,
ShHashFunction64 hashFunction)
TVariableInfoList& infoList);
void getUserDefinedVariableInfo(const TType& type,
const TString& name,
const TString& mappedName,
TVariableInfoList& infoList,
ShHashFunction64 hashFunction);
// Returns info for an attribute, uniform, or varying.
void getVariableInfo(const TType& type,
const TString& name,
const TString& mappedName,
TVariableInfoList& infoList,
ShHashFunction64 hashFunction)
{
if (type.getBasicType() == EbtStruct) {
if (type.isArray()) {
@ -119,6 +121,7 @@ void getBuiltInVariableInfo(const TType& type,
varInfo.mappedName = mappedName.c_str();
varInfo.size = 1;
}
varInfo.precision = type.getPrecision();
varInfo.type = getVariableDataType(type);
infoList.push_back(varInfo);
}
@ -131,86 +134,156 @@ void getUserDefinedVariableInfo(const TType& type,
{
ASSERT(type.getBasicType() == EbtStruct);
const TTypeList* structure = type.getStruct();
for (size_t i = 0; i < structure->size(); ++i) {
const TType* fieldType = (*structure)[i].type;
getVariableInfo(*fieldType,
name + "." + fieldType->getFieldName(),
mappedName + "." + TIntermTraverser::hash(fieldType->getFieldName(), hashFunction),
const TFieldList& fields = type.getStruct()->fields();
for (size_t i = 0; i < fields.size(); ++i) {
const TType& fieldType = *(fields[i]->type());
const TString& fieldName = fields[i]->name();
getVariableInfo(fieldType,
name + "." + fieldName,
mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction),
infoList,
hashFunction);
}
}
TVariableInfo* findVariable(const TType& type,
const TString& name,
TVariableInfoList& infoList)
{
// TODO(zmo): optimize this function.
TString myName = name;
if (type.isArray())
myName += "[0]";
for (size_t ii = 0; ii < infoList.size(); ++ii)
{
if (infoList[ii].name.c_str() == myName)
return &(infoList[ii]);
}
return NULL;
}
} // namespace anonymous
TVariableInfo::TVariableInfo()
: type(SH_NONE),
size(0),
precision(EbpUndefined),
staticUse(false)
{
}
TVariableInfo::TVariableInfo(ShDataType type, int size)
: type(type),
size(size)
size(size),
precision(EbpUndefined),
staticUse(false)
{
}
CollectAttribsUniforms::CollectAttribsUniforms(TVariableInfoList& attribs,
TVariableInfoList& uniforms,
ShHashFunction64 hashFunction)
CollectVariables::CollectVariables(TVariableInfoList& attribs,
TVariableInfoList& uniforms,
TVariableInfoList& varyings,
ShHashFunction64 hashFunction)
: mAttribs(attribs),
mUniforms(uniforms),
mVaryings(varyings),
mPointCoordAdded(false),
mFrontFacingAdded(false),
mFragCoordAdded(false),
mHashFunction(hashFunction)
{
}
// We are only interested in attribute and uniform variable declaration.
void CollectAttribsUniforms::visitSymbol(TIntermSymbol*)
// We want to check whether a uniform/varying is statically used
// because we only count the used ones in packing computing.
// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
// toward varying counting if they are statically used in a fragment
// shader.
void CollectVariables::visitSymbol(TIntermSymbol* symbol)
{
ASSERT(symbol != NULL);
TVariableInfo* var = NULL;
switch (symbol->getQualifier())
{
case EvqVaryingOut:
case EvqInvariantVaryingOut:
case EvqVaryingIn:
case EvqInvariantVaryingIn:
var = findVariable(symbol->getType(), symbol->getSymbol(), mVaryings);
break;
case EvqUniform:
var = findVariable(symbol->getType(), symbol->getSymbol(), mUniforms);
break;
case EvqFragCoord:
if (!mFragCoordAdded) {
TVariableInfo info;
info.name = "gl_FragCoord";
info.mappedName = "gl_FragCoord";
info.type = SH_FLOAT_VEC4;
info.size = 1;
info.precision = EbpMedium; // Use mediump as it doesn't really matter.
info.staticUse = true;
mVaryings.push_back(info);
mFragCoordAdded = true;
}
return;
case EvqFrontFacing:
if (!mFrontFacingAdded) {
TVariableInfo info;
info.name = "gl_FrontFacing";
info.mappedName = "gl_FrontFacing";
info.type = SH_BOOL;
info.size = 1;
info.precision = EbpUndefined;
info.staticUse = true;
mVaryings.push_back(info);
mFrontFacingAdded = true;
}
return;
case EvqPointCoord:
if (!mPointCoordAdded) {
TVariableInfo info;
info.name = "gl_PointCoord";
info.mappedName = "gl_PointCoord";
info.type = SH_FLOAT_VEC2;
info.size = 1;
info.precision = EbpMedium; // Use mediump as it doesn't really matter.
info.staticUse = true;
mVaryings.push_back(info);
mPointCoordAdded = true;
}
return;
default:
break;
}
if (var)
var->staticUse = true;
}
void CollectAttribsUniforms::visitConstantUnion(TIntermConstantUnion*)
bool CollectVariables::visitAggregate(Visit, TIntermAggregate* node)
{
}
bool CollectAttribsUniforms::visitBinary(Visit, TIntermBinary*)
{
return false;
}
bool CollectAttribsUniforms::visitUnary(Visit, TIntermUnary*)
{
return false;
}
bool CollectAttribsUniforms::visitSelection(Visit, TIntermSelection*)
{
return false;
}
bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node)
{
bool visitChildren = false;
bool visitChildren = true;
switch (node->getOp())
{
case EOpSequence:
// We need to visit sequence children to get to variable declarations.
visitChildren = true;
break;
case EOpDeclaration: {
const TIntermSequence& sequence = node->getSequence();
TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
if (qualifier == EvqAttribute || qualifier == EvqUniform)
if (qualifier == EvqAttribute || qualifier == EvqUniform ||
qualifier == EvqVaryingIn || qualifier == EvqVaryingOut ||
qualifier == EvqInvariantVaryingIn || qualifier == EvqInvariantVaryingOut)
{
TVariableInfoList& infoList = qualifier == EvqAttribute ?
mAttribs : mUniforms;
TVariableInfoList& infoList = qualifier == EvqAttribute ? mAttribs :
(qualifier == EvqUniform ? mUniforms : mVaryings);
for (TIntermSequence::const_iterator i = sequence.begin();
i != sequence.end(); ++i)
{
const TIntermSymbol* variable = (*i)->getAsSymbolNode();
// The only case in which the sequence will not contain a
// TIntermSymbol node is initialization. It will contain a
// TInterBinary node in that case. Since attributes and unifroms
// cannot be initialized in a shader, we must have only
// TIntermSymbol nodes in the sequence.
// TInterBinary node in that case. Since attributes, uniforms,
// and varyings cannot be initialized in a shader, we must have
// only TIntermSymbol nodes in the sequence.
ASSERT(variable != NULL);
TString processedSymbol;
if (mHashFunction == NULL)
@ -222,6 +295,7 @@ bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node)
processedSymbol,
infoList,
mHashFunction);
visitChildren = false;
}
}
break;
@ -232,13 +306,3 @@ bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node)
return visitChildren;
}
bool CollectAttribsUniforms::visitLoop(Visit, TIntermLoop*)
{
return false;
}
bool CollectAttribsUniforms::visitBranch(Visit, TIntermBranch*)
{
return false;
}

View File

@ -20,28 +20,30 @@ struct TVariableInfo {
TPersistString mappedName;
ShDataType type;
int size;
TPrecision precision;
bool staticUse;
};
typedef std::vector<TVariableInfo> TVariableInfoList;
// Traverses intermediate tree to collect all attributes and uniforms.
class CollectAttribsUniforms : public TIntermTraverser {
// Traverses intermediate tree to collect all attributes, uniforms, varyings.
class CollectVariables : public TIntermTraverser {
public:
CollectAttribsUniforms(TVariableInfoList& attribs,
TVariableInfoList& uniforms,
ShHashFunction64 hashFunction);
CollectVariables(TVariableInfoList& attribs,
TVariableInfoList& uniforms,
TVariableInfoList& varyings,
ShHashFunction64 hashFunction);
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*);
private:
TVariableInfoList& mAttribs;
TVariableInfoList& mUniforms;
TVariableInfoList& mVaryings;
bool mPointCoordAdded;
bool mFrontFacingAdded;
bool mFragCoordAdded;
ShHashFunction64 mHashFunction;
};

View File

@ -47,20 +47,23 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp).
#pragma warning(disable : 4102)
#endif
#define YY_USER_ACTION yylval->lex.line = yylineno;
#define YY_USER_ACTION \
yylloc->first_file = yylloc->last_file = yycolumn; \
yylloc->first_line = yylloc->last_line = yylineno;
#define YY_INPUT(buf, result, max_size) \
result = string_input(buf, max_size, yyscanner);
static yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner);
static int check_type(yyscan_t yyscanner);
static int reserved_word(yyscan_t yyscanner);
static int int_constant(yyscan_t yyscanner);
static int float_constant(yyscan_t yyscanner);
%}
%option noyywrap nounput never-interactive
%option yylineno reentrant bison-bridge
%option stack
%option yylineno reentrant bison-bridge bison-locations
%option extra-type="TParseContext*"
%x COMMENT FIELDS
D [0-9]
L [a-zA-Z_]
@ -70,73 +73,60 @@ O [0-7]
%%
%{
TParseContext* context = yyextra;
%}
"invariant" { return INVARIANT; }
"highp" { return HIGH_PRECISION; }
"mediump" { return MEDIUM_PRECISION; }
"lowp" { return LOW_PRECISION; }
"precision" { return PRECISION; }
/* Single-line comments */
"//"[^\n]* ;
"attribute" { return ATTRIBUTE; }
"const" { return CONST_QUAL; }
"uniform" { return UNIFORM; }
"varying" { return VARYING; }
/* Multi-line comments */
"/*" { yy_push_state(COMMENT, yyscanner); }
<COMMENT>. |
<COMMENT>\n ;
<COMMENT>"*/" { yy_pop_state(yyscanner); }
"break" { return BREAK; }
"continue" { return CONTINUE; }
"do" { return DO; }
"for" { return FOR; }
"while" { return WHILE; }
"invariant" { return(INVARIANT); }
"highp" { return(HIGH_PRECISION); }
"mediump" { return(MEDIUM_PRECISION); }
"lowp" { return(LOW_PRECISION); }
"precision" { return(PRECISION); }
"if" { return IF; }
"else" { return ELSE; }
"attribute" { return(ATTRIBUTE); }
"const" { return(CONST_QUAL); }
"uniform" { return(UNIFORM); }
"varying" { return(VARYING); }
"in" { return IN_QUAL; }
"out" { return OUT_QUAL; }
"inout" { return INOUT_QUAL; }
"break" { return(BREAK); }
"continue" { return(CONTINUE); }
"do" { return(DO); }
"for" { return(FOR); }
"while" { return(WHILE); }
"float" { return FLOAT_TYPE; }
"int" { return INT_TYPE; }
"void" { return VOID_TYPE; }
"bool" { return BOOL_TYPE; }
"true" { yylval->lex.b = true; return BOOLCONSTANT; }
"false" { yylval->lex.b = false; return BOOLCONSTANT; }
"if" { return(IF); }
"else" { return(ELSE); }
"discard" { return DISCARD; }
"return" { return RETURN; }
"in" { return(IN_QUAL); }
"out" { return(OUT_QUAL); }
"inout" { return(INOUT_QUAL); }
"mat2" { return MATRIX2; }
"mat3" { return MATRIX3; }
"mat4" { return MATRIX4; }
"float" { context->lexAfterType = true; return(FLOAT_TYPE); }
"int" { context->lexAfterType = true; return(INT_TYPE); }
"void" { context->lexAfterType = true; return(VOID_TYPE); }
"bool" { context->lexAfterType = true; return(BOOL_TYPE); }
"true" { yylval->lex.b = true; return(BOOLCONSTANT); }
"false" { yylval->lex.b = false; return(BOOLCONSTANT); }
"vec2" { return VEC2; }
"vec3" { return VEC3; }
"vec4" { return VEC4; }
"ivec2" { return IVEC2; }
"ivec3" { return IVEC3; }
"ivec4" { return IVEC4; }
"bvec2" { return BVEC2; }
"bvec3" { return BVEC3; }
"bvec4" { return BVEC4; }
"discard" { return(DISCARD); }
"return" { return(RETURN); }
"sampler2D" { return SAMPLER2D; }
"samplerCube" { return SAMPLERCUBE; }
"samplerExternalOES" { return SAMPLER_EXTERNAL_OES; }
"sampler2DRect" { return SAMPLER2DRECT; }
"mat2" { context->lexAfterType = true; return(MATRIX2); }
"mat3" { context->lexAfterType = true; return(MATRIX3); }
"mat4" { context->lexAfterType = true; return(MATRIX4); }
"vec2" { context->lexAfterType = true; return (VEC2); }
"vec3" { context->lexAfterType = true; return (VEC3); }
"vec4" { context->lexAfterType = true; return (VEC4); }
"ivec2" { context->lexAfterType = true; return (IVEC2); }
"ivec3" { context->lexAfterType = true; return (IVEC3); }
"ivec4" { context->lexAfterType = true; return (IVEC4); }
"bvec2" { context->lexAfterType = true; return (BVEC2); }
"bvec3" { context->lexAfterType = true; return (BVEC3); }
"bvec4" { context->lexAfterType = true; return (BVEC4); }
"sampler2D" { context->lexAfterType = true; return SAMPLER2D; }
"samplerCube" { context->lexAfterType = true; return SAMPLERCUBE; }
"samplerExternalOES" { context->lexAfterType = true; return SAMPLER_EXTERNAL_OES; }
"sampler2DRect" { context->lexAfterType = true; return SAMPLER2DRECT; }
"struct" { context->lexAfterType = true; return(STRUCT); }
"struct" { return STRUCT; }
"asm" { return reserved_word(yyscanner); }
@ -183,13 +173,11 @@ O [0-7]
"fvec3" { return reserved_word(yyscanner); }
"fvec4" { return reserved_word(yyscanner); }
"sampler1D" { return reserved_word(yyscanner); }
"sampler3D" { return reserved_word(yyscanner); }
"sampler1DShadow" { return reserved_word(yyscanner); }
"sampler2DShadow" { return reserved_word(yyscanner); }
"sampler3DRect" { return reserved_word(yyscanner); }
"sampler1D" { return reserved_word(yyscanner); }
"sampler3D" { return reserved_word(yyscanner); }
"sampler1DShadow" { return reserved_word(yyscanner); }
"sampler2DShadow" { return reserved_word(yyscanner); }
"sampler3DRect" { return reserved_word(yyscanner); }
"sampler2DRectShadow" { return reserved_word(yyscanner); }
"sizeof" { return reserved_word(yyscanner); }
@ -203,72 +191,64 @@ O [0-7]
return check_type(yyscanner);
}
0[xX]{H}+ { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return(INTCONSTANT); }
0{O}+ { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return(INTCONSTANT); }
0{D}+ { context->error(yylineno, "Invalid Octal number.", yytext); context->recover(); return 0;}
{D}+ { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return(INTCONSTANT); }
0[xX]{H}+ { return int_constant(yyscanner); }
0{O}+ { return int_constant(yyscanner); }
{D}+ { return int_constant(yyscanner); }
{D}+{E} { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
{D}+"."{D}*({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
"."{D}+({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
{D}+{E} { return float_constant(yyscanner); }
{D}+"."{D}*({E})? { return float_constant(yyscanner); }
"."{D}+({E})? { return float_constant(yyscanner); }
"+=" { return(ADD_ASSIGN); }
"-=" { return(SUB_ASSIGN); }
"*=" { return(MUL_ASSIGN); }
"/=" { return(DIV_ASSIGN); }
"%=" { return(MOD_ASSIGN); }
"<<=" { return(LEFT_ASSIGN); }
">>=" { return(RIGHT_ASSIGN); }
"&=" { return(AND_ASSIGN); }
"^=" { return(XOR_ASSIGN); }
"|=" { return(OR_ASSIGN); }
"+=" { return ADD_ASSIGN; }
"-=" { return SUB_ASSIGN; }
"*=" { return MUL_ASSIGN; }
"/=" { return DIV_ASSIGN; }
"%=" { return MOD_ASSIGN; }
"<<=" { return LEFT_ASSIGN; }
">>=" { return RIGHT_ASSIGN; }
"&=" { return AND_ASSIGN; }
"^=" { return XOR_ASSIGN; }
"|=" { return OR_ASSIGN; }
"++" { return(INC_OP); }
"--" { return(DEC_OP); }
"&&" { return(AND_OP); }
"||" { return(OR_OP); }
"^^" { return(XOR_OP); }
"<=" { return(LE_OP); }
">=" { return(GE_OP); }
"==" { return(EQ_OP); }
"!=" { return(NE_OP); }
"<<" { return(LEFT_OP); }
">>" { return(RIGHT_OP); }
";" { context->lexAfterType = false; return(SEMICOLON); }
("{"|"<%") { context->lexAfterType = false; return(LEFT_BRACE); }
("}"|"%>") { return(RIGHT_BRACE); }
"," { if (context->inTypeParen) context->lexAfterType = false; return(COMMA); }
":" { return(COLON); }
"=" { context->lexAfterType = false; return(EQUAL); }
"(" { context->lexAfterType = false; context->inTypeParen = true; return(LEFT_PAREN); }
")" { context->inTypeParen = false; return(RIGHT_PAREN); }
("["|"<:") { return(LEFT_BRACKET); }
("]"|":>") { return(RIGHT_BRACKET); }
"." { BEGIN(FIELDS); return(DOT); }
"!" { return(BANG); }
"-" { return(DASH); }
"~" { return(TILDE); }
"+" { return(PLUS); }
"*" { return(STAR); }
"/" { return(SLASH); }
"%" { return(PERCENT); }
"<" { return(LEFT_ANGLE); }
">" { return(RIGHT_ANGLE); }
"|" { return(VERTICAL_BAR); }
"^" { return(CARET); }
"&" { return(AMPERSAND); }
"?" { return(QUESTION); }
"++" { return INC_OP; }
"--" { return DEC_OP; }
"&&" { return AND_OP; }
"||" { return OR_OP; }
"^^" { return XOR_OP; }
"<=" { return LE_OP; }
">=" { return GE_OP; }
"==" { return EQ_OP; }
"!=" { return NE_OP; }
"<<" { return LEFT_OP; }
">>" { return RIGHT_OP; }
";" { return SEMICOLON; }
("{"|"<%") { return LEFT_BRACE; }
("}"|"%>") { return RIGHT_BRACE; }
"," { return COMMA; }
":" { return COLON; }
"=" { return EQUAL; }
"(" { return LEFT_PAREN; }
")" { return RIGHT_PAREN; }
("["|"<:") { return LEFT_BRACKET; }
("]"|":>") { return RIGHT_BRACKET; }
"." { return DOT; }
"!" { return BANG; }
"-" { return DASH; }
"~" { return TILDE; }
"+" { return PLUS; }
"*" { return STAR; }
"/" { return SLASH; }
"%" { return PERCENT; }
"<" { return LEFT_ANGLE; }
">" { return RIGHT_ANGLE; }
"|" { return VERTICAL_BAR; }
"^" { return CARET; }
"&" { return AMPERSAND; }
"?" { return QUESTION; }
<FIELDS>{L}({L}|{D})* {
BEGIN(INITIAL);
yylval->lex.string = NewPoolTString(yytext);
return FIELD_SELECTION;
}
<FIELDS>[ \t\v\f\r] {}
[ \t\v\n\f\r] { }
<*><<EOF>> { context->AfterEOF = true; yyterminate(); }
<*>. { context->warning(yylineno, "Unknown char", yytext, ""); return 0; }
[ \t\v\n\f\r] { }
<<EOF>> { yyterminate(); }
. { assert(false); return 0; }
%%
@ -278,7 +258,8 @@ yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) {
yy_size_t len = token.type == pp::Token::LAST ? 0 : token.text.size();
if (len < max_size)
memcpy(buf, token.text.c_str(), len);
yyset_lineno(EncodeSourceLoc(token.location.file, token.location.line), yyscanner);
yyset_column(token.location.file, yyscanner);
yyset_lineno(token.location.line, yyscanner);
if (len >= max_size)
YY_FATAL_ERROR("Input buffer overflow");
@ -292,12 +273,10 @@ int check_type(yyscan_t yyscanner) {
int token = IDENTIFIER;
TSymbol* symbol = yyextra->symbolTable.find(yytext);
if (yyextra->lexAfterType == false && symbol && symbol->isVariable()) {
if (symbol && symbol->isVariable()) {
TVariable* variable = static_cast<TVariable*>(symbol);
if (variable->isUserType()) {
yyextra->lexAfterType = true;
if (variable->isUserType())
token = TYPE_NAME;
}
}
yylval->lex.symbol = symbol;
return token;
@ -306,22 +285,32 @@ int check_type(yyscan_t yyscanner) {
int reserved_word(yyscan_t yyscanner) {
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
yyextra->error(yylineno, "Illegal use of reserved word", yytext, "");
yyextra->error(*yylloc, "Illegal use of reserved word", yytext, "");
yyextra->recover();
return 0;
}
void yyerror(TParseContext* context, const char* reason) {
struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
if (context->AfterEOF) {
context->error(yylineno, reason, "unexpected EOF");
} else {
context->error(yylineno, reason, yytext);
}
void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) {
context->error(*lloc, reason, yyget_text(context->scanner));
context->recover();
}
int int_constant(yyscan_t yyscanner) {
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
if (!atoi_clamp(yytext, &(yylval->lex.i)))
yyextra->warning(*yylloc, "Integer overflow", yytext, "");
return INTCONSTANT;
}
int float_constant(yyscan_t yyscanner) {
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
if (!atof_clamp(yytext, &(yylval->lex.f)))
yyextra->warning(*yylloc, "Float overflow", yytext, "");
return FLOATCONSTANT;
}
int glslang_initialize(TParseContext* context) {
yyscan_t scanner = NULL;
if (yylex_init_extra(context, &scanner))
@ -344,12 +333,13 @@ int glslang_finalize(TParseContext* context) {
int glslang_scan(size_t count, const char* const string[], const int length[],
TParseContext* context) {
yyrestart(NULL, context->scanner);
yyset_lineno(EncodeSourceLoc(0, 1), context->scanner);
context->AfterEOF = false;
yyset_column(0, context->scanner);
yyset_lineno(1, context->scanner);
// Initialize preprocessor.
if (!context->preprocessor.init(count, string, length))
return 1;
context->preprocessor.setMaxTokenLength(SH_MAX_TOKEN_LENGTH);
// Define extension macros.
const TExtensionBehavior& extBehavior = context->extensionBehavior();

File diff suppressed because it is too large Load Diff

View File

@ -189,7 +189,9 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node)
case EOpAny: out << "any"; break;
case EOpAll: out << "all"; break;
default: out.message(EPrefixError, "Bad unary op");
default:
out.prefix(EPrefixError);
out << "Bad unary op";
}
out << " (" << node->getCompleteString() << ")";
@ -204,7 +206,8 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
TInfoSinkBase& out = sink;
if (node->getOp() == EOpNull) {
out.message(EPrefixError, "node is still EOpNull!");
out.prefix(EPrefixError);
out << "node is still EOpNull!";
return true;
}
@ -263,7 +266,9 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
case EOpDeclaration: out << "Declaration: "; break;
default: out.message(EPrefixError, "Bad aggregation op");
default:
out.prefix(EPrefixError);
out << "Bad aggregation op";
}
if (node->getOp() != EOpSequence && node->getOp() != EOpParameters)
@ -311,9 +316,9 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
{
TInfoSinkBase& out = sink;
int size = node->getType().getObjectSize();
size_t size = node->getType().getObjectSize();
for (int i = 0; i < size; i++) {
for (size_t i = 0; i < size; i++) {
OutputTreeText(out, node, depth);
switch (node->getUnionArrayPointer()[i].getType()) {
case EbtBool:
@ -334,7 +339,7 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
out << " (const int)\n";
break;
default:
out.message(EPrefixInternalError, "Unknown constant", node->getLine());
out.message(EPrefixInternalError, node->getLine(), "Unknown constant");
break;
}
}

View File

@ -18,6 +18,7 @@
#include "GLSLANG/ShaderLang.h"
#include <algorithm>
#include "compiler/Common.h"
#include "compiler/Types.h"
#include "compiler/ConstantUnion.h"
@ -204,12 +205,17 @@ class TInfoSink;
//
class TIntermNode {
public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
POOL_ALLOCATOR_NEW_DELETE();
TIntermNode() {
// TODO: Move this to TSourceLoc constructor
// after getting rid of TPublicType.
line.first_file = line.last_file = 0;
line.first_line = line.last_line = 0;
}
virtual ~TIntermNode() { }
TIntermNode() : line(0) {}
TSourceLoc getLine() const { return line; }
void setLine(TSourceLoc l) { line = l; }
const TSourceLoc& getLine() const { return line; }
void setLine(const TSourceLoc& l) { line = l; }
virtual void traverse(TIntermTraverser*) = 0;
virtual TIntermTyped* getAsTyped() { return 0; }
@ -220,7 +226,6 @@ public:
virtual TIntermSelection* getAsSelectionNode() { return 0; }
virtual TIntermSymbol* getAsSymbolNode() { return 0; }
virtual TIntermLoop* getAsLoopNode() { return 0; }
virtual ~TIntermNode() { }
protected:
TSourceLoc line;
@ -454,7 +459,7 @@ typedef TVector<int> TQualifierList;
//
class TIntermAggregate : public TIntermOperator {
public:
TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), endLine(0), useEmulatedFunction(false) { }
TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), useEmulatedFunction(false) { }
TIntermAggregate(TOperator o) : TIntermOperator(o), useEmulatedFunction(false) { }
~TIntermAggregate() { }
@ -474,9 +479,6 @@ public:
void setDebug(bool d) { debug = d; }
bool getDebug() { return debug; }
void setEndLine(TSourceLoc line) { endLine = line; }
TSourceLoc getEndLine() const { return endLine; }
void setUseEmulatedFunction() { useEmulatedFunction = true; }
bool getUseEmulatedFunction() { return useEmulatedFunction; }
@ -489,7 +491,6 @@ protected:
bool optimize;
bool debug;
TSourceLoc endLine;
// If set to true, replace the built-in function call with an emulated one
// to work around driver bugs.
@ -538,14 +539,14 @@ enum Visit
class TIntermTraverser
{
public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
POOL_ALLOCATOR_NEW_DELETE();
TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
preVisit(preVisit),
inVisit(inVisit),
postVisit(postVisit),
rightToLeft(rightToLeft),
depth(0) {}
depth(0),
maxDepth(0) {}
virtual ~TIntermTraverser() {};
virtual void visitSymbol(TIntermSymbol*) {}
@ -557,7 +558,8 @@ public:
virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;}
virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;}
void incrementDepth() {depth++;}
int getMaxDepth() const {return maxDepth;}
void incrementDepth() {depth++; maxDepth = std::max(maxDepth, depth); }
void decrementDepth() {depth--;}
// Return the original name if hash function pointer is NULL;
@ -571,6 +573,7 @@ public:
protected:
int depth;
int maxDepth;
};
#endif // __INTERMEDIATE_H

View File

@ -22,37 +22,36 @@ struct TVectorFields {
class TInfoSink;
class TIntermediate {
public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
POOL_ALLOCATOR_NEW_DELETE();
TIntermediate(TInfoSink& i) : infoSink(i) { }
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc);
TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, TSymbolTable&);
TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, TSourceLoc, TSymbolTable&);
TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc);
TIntermAggregate* makeAggregate(TIntermNode* node, TSourceLoc);
TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, TSourceLoc);
TIntermNode* addSelection(TIntermTyped* cond, TIntermNodePair code, TSourceLoc);
TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc);
TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc);
TIntermConstantUnion* addConstantUnion(ConstantUnion*, const TType&, TSourceLoc);
TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ;
bool parseConstTree(TSourceLoc, TIntermNode*, ConstantUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false);
TIntermNode* addLoop(TLoopType, TIntermNode*, TIntermTyped*, TIntermTyped*, TIntermNode*, TSourceLoc);
TIntermBranch* addBranch(TOperator, TSourceLoc);
TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc);
TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc);
bool postProcess(TIntermNode*);
void remove(TIntermNode*);
void outputTree(TIntermNode*);
protected:
TInfoSink& infoSink;
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TSourceLoc&);
TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&, TSymbolTable&);
TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&);
TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, const TSourceLoc&, TSymbolTable&);
TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&);
TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&);
TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, const TSourceLoc&);
TIntermNode* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&);
TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&);
TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
TIntermConstantUnion* addConstantUnion(ConstantUnion*, const TType&, const TSourceLoc&);
TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ;
bool parseConstTree(const TSourceLoc&, TIntermNode*, ConstantUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false);
TIntermNode* addLoop(TLoopType, TIntermNode*, TIntermTyped*, TIntermTyped*, TIntermNode*, const TSourceLoc&);
TIntermBranch* addBranch(TOperator, const TSourceLoc&);
TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
TIntermTyped* addSwizzle(TVectorFields&, const TSourceLoc&);
bool postProcess(TIntermNode*);
void remove(TIntermNode*);
void outputTree(TIntermNode*);
private:
void operator=(TIntermediate&); // prevent assignments
TInfoSink& infoSink;
};
#endif // _LOCAL_INTERMEDIATE_INCLUDED_

View File

@ -38,16 +38,16 @@ protected:
bool visitLoop(Visit visit, TIntermLoop*);
bool visitBranch(Visit visit, TIntermBranch*);
int index;
size_t index;
ConstantUnion *unionArray;
TType type;
TOperator constructorType;
bool singleConstantParam;
TInfoSink& infoSink;
TSymbolTable& symbolTable;
int size; // size of the constructor ( 4 for vec4)
size_t size; // size of the constructor ( 4 for vec4)
bool isMatrix;
int matrixSize; // dimension of the matrix (nominal size and not the instance size)
size_t matrixSize; // dimension of the matrix (nominal size and not the instance size)
};
//
@ -61,7 +61,7 @@ protected:
void TConstTraverser::visitSymbol(TIntermSymbol* node)
{
infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine());
infoSink.info.message(EPrefixInternalError, node->getLine(), "Symbol Node found in constant constructor");
return;
}
@ -74,12 +74,12 @@ bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
TString buf;
buf.append("'constructor' : assigning non-constant to ");
buf.append(type.getCompleteString());
infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
error = true;
return false;
}
infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine());
infoSink.info.message(EPrefixInternalError, node->getLine(), "Binary Node found in constant constructor");
return false;
}
@ -89,7 +89,7 @@ bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
TString buf;
buf.append("'constructor' : assigning non-constant to ");
buf.append(type.getCompleteString());
infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
error = true;
return false;
}
@ -100,7 +100,7 @@ bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
TString buf;
buf.append("'constructor' : assigning non-constant to ");
buf.append(type.getCompleteString());
infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
error = true;
return false;
}
@ -144,7 +144,7 @@ bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node)
{
infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine());
infoSink.info.message(EPrefixInternalError, node->getLine(), "Selection Node found in constant constructor");
error = true;
return false;
}
@ -159,16 +159,16 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
}
ConstantUnion* leftUnionArray = unionArray;
int instanceSize = type.getObjectSize();
size_t instanceSize = type.getObjectSize();
if (index >= instanceSize)
return;
if (!singleConstantParam) {
int size = node->getType().getObjectSize();
size_t size = node->getType().getObjectSize();
ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
for (int i=0; i < size; i++) {
for (size_t i = 0; i < size; i++) {
if (index >= instanceSize)
return;
leftUnionArray[index] = rightUnionArray[i];
@ -176,11 +176,11 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
(index)++;
}
} else {
int totalSize = index + size;
size_t totalSize = index + size;
ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
if (!isMatrix) {
int count = 0;
for (int i = index; i < totalSize; i++) {
size_t count = 0;
for (size_t i = index; i < totalSize; i++) {
if (i >= instanceSize)
return;
@ -192,9 +192,9 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
count++;
}
} else { // for matrix constructors
int count = 0;
int element = index;
for (int i = index; i < totalSize; i++) {
size_t count = 0;
size_t element = index;
for (size_t i = index; i < totalSize; i++) {
if (i >= instanceSize)
return;
if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 )
@ -213,14 +213,14 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node)
{
infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
infoSink.info.message(EPrefixInternalError, node->getLine(), "Loop Node found in constant constructor");
error = true;
return false;
}
bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
{
infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
infoSink.info.message(EPrefixInternalError, node->getLine(), "Branch Node found in constant constructor");
error = true;
return false;
}
@ -230,7 +230,7 @@ bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
// Individual functions can be initialized to 0 to skip processing of that
// type of node. It's children will still be processed.
//
bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam)
bool TIntermediate::parseConstTree(const TSourceLoc& line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam)
{
if (root == 0)
return false;

View File

@ -81,6 +81,11 @@ void Preprocessor::predefineMacro(const char* name, int value)
mImpl->macroSet[name] = macro;
}
void Preprocessor::setMaxTokenLength(size_t maxLength)
{
mImpl->tokenizer.setMaxTokenLength(maxLength);
}
void Preprocessor::lex(Token* token)
{
bool validToken = false;
@ -95,34 +100,6 @@ void Preprocessor::lex(Token* token)
case Token::PP_HASH:
assert(false);
break;
case Token::CONST_INT:
{
int val = 0;
if (!token->iValue(&val))
{
// Do not mark the token as invalid.
// Just emit the diagnostic and reset value to 0.
mImpl->diagnostics->report(Diagnostics::INTEGER_OVERFLOW,
token->location, token->text);
token->text.assign("0");
}
validToken = true;
break;
}
case Token::CONST_FLOAT:
{
float val = 0;
if (!token->fValue(&val))
{
// Do not mark the token as invalid.
// Just emit the diagnostic and reset value to 0.0.
mImpl->diagnostics->report(Diagnostics::FLOAT_OVERFLOW,
token->location, token->text);
token->text.assign("0.0");
}
validToken = true;
break;
}
case Token::PP_NUMBER:
mImpl->diagnostics->report(Diagnostics::INVALID_NUMBER,
token->location, token->text);

View File

@ -37,6 +37,12 @@ class Preprocessor
bool init(size_t count, const char* const string[], const int length[]);
// Adds a pre-defined macro.
void predefineMacro(const char* name, int value);
// Sets maximum allowed token length.
// If token length exceeds this limit,
// the token text will be truncated to the given maximum length, and
// TOKEN_TOO_LONG diagnostic will be generated.
// The maximum length defaults to 256.
void setMaxTokenLength(size_t maxLength);
void lex(Token* token);

View File

@ -32,13 +32,13 @@ class Tokenizer : public Lexer
bool leadingSpace;
bool lineStart;
};
static const std::size_t kMaxTokenLength;
Tokenizer(Diagnostics* diagnostics);
~Tokenizer();
bool init(size_t count, const char* const string[], const int length[]);
void setMaxTokenLength(size_t maxLength) { mMaxTokenLength = maxLength; }
void setFileNumber(int file);
void setLineNumber(int line);
@ -51,6 +51,7 @@ class Tokenizer : public Lexer
void* mHandle; // Scanner handle.
Context mContext; // Scanner extra.
size_t mMaxTokenLength;
};
} // namespace pp

View File

@ -267,11 +267,9 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
namespace pp {
// TODO(alokp): Maximum token length should ideally be specified by
// the preprocessor client, i.e., the compiler.
const size_t Tokenizer::kMaxTokenLength = 256;
Tokenizer::Tokenizer(Diagnostics* diagnostics) : mHandle(0)
Tokenizer::Tokenizer(Diagnostics* diagnostics)
: mHandle(0),
mMaxTokenLength(256)
{
mContext.diagnostics = diagnostics;
}
@ -304,11 +302,11 @@ void Tokenizer::setLineNumber(int line)
void Tokenizer::lex(Token* token)
{
token->type = yylex(&token->text, &token->location, mHandle);
if (token->text.size() > kMaxTokenLength)
if (token->text.size() > mMaxTokenLength)
{
mContext.diagnostics->report(Diagnostics::TOKEN_TOO_LONG,
token->location, token->text);
token->text.erase(kMaxTokenLength);
token->text.erase(mMaxTokenLength);
}
token->flags = 0;

View File

@ -10,8 +10,8 @@ void RestrictVertexShaderTiming::visitSymbol(TIntermSymbol* node)
{
if (IsSampler(node->getBasicType())) {
++mNumErrors;
mSink.prefix(EPrefixError);
mSink.location(node->getLine());
mSink << "Samplers are not permitted in vertex shaders.\n";
mSink.message(EPrefixError,
node->getLine(),
"Samplers are not permitted in vertex shaders");
}
}

View File

@ -4,30 +4,25 @@
// found in the LICENSE file.
//
#include <math.h>
#include <stdlib.h>
#include "compiler/util.h"
#include "util.h"
#include <limits>
#ifdef _MSC_VER
#include <locale.h>
#else
#include <sstream>
#endif
#include "compiler/preprocessor/numeric_lex.h"
double atof_dot(const char *str)
bool atof_clamp(const char *str, float *value)
{
#ifdef _MSC_VER
_locale_t l = _create_locale(LC_NUMERIC, "C");
double result = _atof_l(str, l);
_free_locale(l);
return result;
#else
double result;
std::istringstream s(str);
std::locale l("C");
s.imbue(l);
s >> result;
return result;
#endif
bool success = pp::numeric_lex_float(str, value);
if (!success)
*value = std::numeric_limits<float>::max();
return success;
}
bool atoi_clamp(const char *str, int *value)
{
bool success = pp::numeric_lex_int(str, value);
if (!success)
*value = std::numeric_limits<int>::max();
return success;
}

View File

@ -7,15 +7,14 @@
#ifndef COMPILER_UTIL_H
#define COMPILER_UTIL_H
#ifdef __cplusplus
extern "C" {
#endif
// atof_clamp is like atof but
// 1. it forces C locale, i.e. forcing '.' as decimal point.
// 2. it clamps the value to -FLT_MAX or FLT_MAX if overflow happens.
// Return false if overflow happens.
extern bool atof_clamp(const char *str, float *value);
// atof_dot is like atof but forcing C locale, i.e. forcing '.' as decimal point.
double atof_dot(const char *str);
#ifdef __cplusplus
} // end extern "C"
#endif
// If overflow happens, clamp the value to INT_MIN or INT_MAX.
// Return false if overflow happens.
extern bool atoi_clamp(const char *str, int *value);
#endif // COMPILER_UTIL_H

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2013 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.
//
@ -38,31 +38,16 @@ egl::Display *Display::getDisplay(EGLNativeDisplayType displayId)
return displays[displayId];
}
egl::Display *display = NULL;
// FIXME: Check if displayId is a valid display device context
if (displayId == EGL_DEFAULT_DISPLAY)
{
display = new egl::Display(displayId, (HDC)NULL, false);
}
else if (displayId == EGL_SOFTWARE_DISPLAY_ANGLE)
{
display = new egl::Display(displayId, (HDC)NULL, true);
}
else
{
// FIXME: Check if displayId is a valid display device context
display = new egl::Display(displayId, (HDC)displayId, false);
}
egl::Display *display = new egl::Display(displayId, (HDC)displayId);
displays[displayId] = display;
return display;
}
Display::Display(EGLNativeDisplayType displayId, HDC deviceContext, bool software) : mDc(deviceContext)
Display::Display(EGLNativeDisplayType displayId, HDC deviceContext) : mDc(deviceContext)
{
mSoftwareDevice = software;
mDisplayId = displayId;
mRenderer = NULL;
}
@ -86,7 +71,7 @@ bool Display::initialize()
return true;
}
mRenderer = glCreateRenderer(this, mDc, mSoftwareDevice);
mRenderer = glCreateRenderer(this, mDc, mDisplayId);
if (!mRenderer)
{
@ -128,6 +113,7 @@ bool Display::initialize()
}
initExtensionString();
initVendorString();
return true;
}
@ -528,5 +514,24 @@ const char *Display::getExtensionString() const
return mExtensionString.c_str();
}
void Display::initVendorString()
{
mVendorString = "Google Inc.";
LUID adapterLuid = {0};
if (mRenderer && mRenderer->getLUID(&adapterLuid))
{
char adapterLuidString[64];
sprintf_s(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart);
mVendorString += adapterLuidString;
}
}
const char *Display::getVendorString() const
{
return mVendorString.c_str();
}
}

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2013 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.
//
@ -60,11 +60,12 @@ class Display
virtual void recreateSwapChains();
const char *getExtensionString() const;
const char *getVendorString() const;
private:
DISALLOW_COPY_AND_ASSIGN(Display);
Display(EGLNativeDisplayType displayId, HDC deviceContext, bool software);
Display(EGLNativeDisplayType displayId, HDC deviceContext);
bool restoreLostDevice();
@ -84,7 +85,9 @@ class Display
rx::Renderer *mRenderer;
void initExtensionString();
void initVendorString();
std::string mExtensionString;
std::string mVendorString;
};
}

View File

@ -20,8 +20,6 @@
#include "libEGL/main.h"
#include "libEGL/Display.h"
#include <dwmapi.h>
namespace egl
{
@ -71,44 +69,9 @@ Surface::~Surface()
bool Surface::initialize()
{
typedef HRESULT (STDAPICALLTYPE *PtrDwmIsCompositionEnabled)(BOOL*);
typedef HRESULT (STDAPICALLTYPE *PtrDwmSetPresentParameters)(HWND, DWM_PRESENT_PARAMETERS *);
if (!resetSwapChain())
return false;
// Modify present parameters for this window, if we are composited,
// to minimize the amount of queuing done by DWM between our calls to
// present and the actual screen.
if (mWindow && (getComparableOSVersion() >= versionWindowsVista)) {
// Resolve dwmapi.dll functions dynamically as the Library is
// not present on Windows XP. Alternatively, /DELAYLOAD could be used.
static PtrDwmIsCompositionEnabled dwmIsCompositionEnabled = 0;
static PtrDwmSetPresentParameters dwmSetPresentParameters = 0;
if (!dwmIsCompositionEnabled) {
if (const HMODULE dwmLibrary = LoadLibraryW(L"dwmapi.dll")) {
dwmIsCompositionEnabled =
(PtrDwmIsCompositionEnabled)GetProcAddress(dwmLibrary, "DwmIsCompositionEnabled");
dwmSetPresentParameters =
(PtrDwmSetPresentParameters)GetProcAddress(dwmLibrary, "DwmSetPresentParameters");
}
}
if (dwmIsCompositionEnabled && dwmSetPresentParameters) {
BOOL isComposited;
HRESULT result = dwmIsCompositionEnabled(&isComposited);
if (SUCCEEDED(result) && isComposited) {
DWM_PRESENT_PARAMETERS presentParams;
memset(&presentParams, 0, sizeof(presentParams));
presentParams.cbSize = sizeof(DWM_PRESENT_PARAMETERS);
presentParams.cBuffer = 2;
result = dwmSetPresentParameters(mWindow, &presentParams);
if (FAILED(result))
ERR("Unable to set present parameters: 0x%08X", result);
}
}
}
return true;
}

View File

@ -180,9 +180,9 @@ const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name)
case EGL_CLIENT_APIS:
return egl::success("OpenGL_ES");
case EGL_EXTENSIONS:
return display->getExtensionString();
return egl::success(display->getExtensionString());
case EGL_VENDOR:
return egl::success("Google Inc.");
return egl::success(display->getVendorString());
case EGL_VERSION:
return egl::success("1.4 (ANGLE " VERSION_STRING ")");
}
@ -888,15 +888,18 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface
return EGL_FALSE;
}
rx::Renderer *renderer = display->getRenderer();
if (renderer->testDeviceLost(true))
if (dpy != EGL_NO_DISPLAY)
{
return EGL_FALSE;
}
rx::Renderer *renderer = display->getRenderer();
if (renderer->testDeviceLost(true))
{
return EGL_FALSE;
}
if (renderer->isDeviceLost())
{
return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
if (renderer->isDeviceLost())
{
return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
}
}
if ((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(draw))) ||

View File

@ -88,72 +88,89 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
return TRUE;
}
static inline egl::Current *current()
{
return (egl::Current*)TlsGetValue(currentTLS);
}
#else // !QT_OPENGL_ES_2_ANGLE_STATIC
static egl::Current *current()
{
// No precautions for thread safety taken as ANGLE is used single-threaded in Qt.
static egl::Current curr = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE };
return &curr;
}
#endif // QT_OPENGL_ES_2_ANGLE_STATIC
#endif // !QT_OPENGL_ES_2_ANGLE_STATIC
namespace egl
{
Current *getCurrent()
{
#ifndef QT_OPENGL_ES_2_ANGLE_STATIC
return (Current*)TlsGetValue(currentTLS);
#else
// No precautions for thread safety taken as ANGLE is used single-threaded in Qt.
static Current curr = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE };
return &curr;
#endif
}
void setCurrentError(EGLint error)
{
current()->error = error;
Current *current = getCurrent();
current->error = error;
}
EGLint getCurrentError()
{
return current()->error;
Current *current = getCurrent();
return current->error;
}
void setCurrentAPI(EGLenum API)
{
current()->API = API;
Current *current = getCurrent();
current->API = API;
}
EGLenum getCurrentAPI()
{
return current()->API;
Current *current = getCurrent();
return current->API;
}
void setCurrentDisplay(EGLDisplay dpy)
{
current()->display = dpy;
Current *current = getCurrent();
current->display = dpy;
}
EGLDisplay getCurrentDisplay()
{
return current()->display;
Current *current = getCurrent();
return current->display;
}
void setCurrentDrawSurface(EGLSurface surface)
{
current()->drawSurface = surface;
Current *current = getCurrent();
current->drawSurface = surface;
}
EGLSurface getCurrentDrawSurface()
{
return current()->drawSurface;
Current *current = getCurrent();
return current->drawSurface;
}
void setCurrentReadSurface(EGLSurface surface)
{
current()->readSurface = surface;
Current *current = getCurrent();
current->readSurface = surface;
}
EGLSurface getCurrentReadSurface()
{
return current()->readSurface;
Current *current = getCurrent();
return current->readSurface;
}
void error(EGLint errorCode)

View File

@ -40,6 +40,7 @@ Buffer::~Buffer()
void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
{
mBufferStorage->clear();
mIndexRangeCache.clear();
mBufferStorage->setData(data, size, 0);
mUsage = usage;
@ -56,6 +57,7 @@ void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset)
{
mBufferStorage->setData(data, size, offset);
mIndexRangeCache.invalidateRange(offset, size);
if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0))
{
@ -70,7 +72,7 @@ rx::BufferStorage *Buffer::getStorage() const
return mBufferStorage;
}
unsigned int Buffer::size()
unsigned int Buffer::size() const
{
return mBufferStorage->getSize();
}
@ -116,4 +118,9 @@ void Buffer::promoteStaticUsage(int dataSize)
}
}
rx::IndexRangeCache *Buffer::getIndexRangeCache()
{
return &mIndexRangeCache;
}
}

View File

@ -13,6 +13,7 @@
#include "common/angleutils.h"
#include "common/RefCountObject.h"
#include "libGLESv2/renderer/IndexRangeCache.h"
namespace rx
{
@ -38,13 +39,15 @@ class Buffer : public RefCountObject
GLenum usage() const;
rx::BufferStorage *getStorage() const;
unsigned int size();
unsigned int size() const;
rx::StaticVertexBufferInterface *getStaticVertexBuffer();
rx::StaticIndexBufferInterface *getStaticIndexBuffer();
void invalidateStaticData();
void promoteStaticUsage(int dataSize);
rx::IndexRangeCache *getIndexRangeCache();
private:
DISALLOW_COPY_AND_ASSIGN(Buffer);
@ -53,6 +56,8 @@ class Buffer : public RefCountObject
rx::BufferStorage *mBufferStorage;
rx::IndexRangeCache mIndexRangeCache;
rx::StaticVertexBufferInterface *mStaticVertexBuffer;
rx::StaticIndexBufferInterface *mStaticIndexBuffer;
unsigned int mUnmodifiedDataUse;

View File

@ -60,6 +60,7 @@ Context::Context(const gl::Context *shareContext, rx::Renderer *renderer, bool n
mState.rasterizer.polygonOffsetFactor = 0.0f;
mState.rasterizer.polygonOffsetUnits = 0.0f;
mState.rasterizer.pointDrawMode = false;
mState.rasterizer.multiSample = false;
mState.scissorTest = false;
mState.scissor.x = 0;
mState.scissor.y = 0;
@ -1075,6 +1076,7 @@ void Context::setRenderbufferStorage(GLsizei width, GLsizei height, GLenum inter
case GL_RGB565:
case GL_RGB8_OES:
case GL_RGBA8_OES:
case GL_BGRA8_EXT:
renderbuffer = new gl::Colorbuffer(mRenderer,width, height, internalformat, samples);
break;
case GL_STENCIL_INDEX8:
@ -1741,7 +1743,11 @@ bool Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport)
// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
void Context::applyState(GLenum drawMode)
{
Framebuffer *framebufferObject = getDrawFramebuffer();
int samples = framebufferObject->getSamples();
mState.rasterizer.pointDrawMode = (drawMode == GL_POINTS);
mState.rasterizer.multiSample = (samples != 0);
mRenderer->setRasterizerState(mState.rasterizer);
unsigned int mask = 0;
@ -1749,10 +1755,10 @@ void Context::applyState(GLenum drawMode)
{
if (mState.sampleCoverageValue != 0)
{
Framebuffer *framebufferObject = getDrawFramebuffer();
float threshold = 0.5f;
for (int i = 0; i < framebufferObject->getSamples(); ++i)
for (int i = 0; i < samples; ++i)
{
mask <<= 1;
@ -2582,6 +2588,7 @@ void Context::initExtensionString()
}
extensionString += "GL_EXT_texture_storage ";
extensionString += "GL_EXT_frag_depth ";
// ANGLE-specific extensions
if (supportsDepthTextures())

View File

@ -303,6 +303,19 @@ bool Framebuffer::hasStencil() const
return false;
}
bool Framebuffer::usingExtendedDrawBuffers() const
{
for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
{
if (isEnabledColorAttachment(colorAttachment))
{
return true;
}
}
return false;
}
GLenum Framebuffer::completeness() const
{
int width = 0;

View File

@ -68,6 +68,7 @@ class Framebuffer
bool hasEnabledColorAttachment() const;
bool hasStencil() const;
int getSamples() const;
bool usingExtendedDrawBuffers() const;
virtual GLenum completeness() const;

View File

@ -1165,7 +1165,7 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying
bool usesMRT = fragmentShader->mUsesMultipleRenderTargets;
bool usesFragColor = fragmentShader->mUsesFragColor;
bool usesFragData = fragmentShader->mUsesFragData;
if (usesMRT && usesFragColor && usesFragData)
if (usesFragColor && usesFragData)
{
infoLog.append("Cannot use both gl_FragColor and gl_FragData in the same fragment shader.");
return false;
@ -1177,6 +1177,10 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying
const int registersNeeded = registers + (fragmentShader->mUsesFragCoord ? 1 : 0) + (fragmentShader->mUsesPointCoord ? 1 : 0);
// The output color is broadcast to all enabled draw buffers when writing to gl_FragColor
const bool broadcast = fragmentShader->mUsesFragColor;
const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getMaxRenderTargets() : 1);
if (registersNeeded > maxVaryingVectors)
{
infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord");
@ -1221,8 +1225,7 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying
std::string varyingSemantic = (mUsesPointSize && shaderModel == 3) ? "COLOR" : "TEXCOORD";
std::string targetSemantic = (shaderModel >= 4) ? "SV_Target" : "COLOR";
std::string positionSemantic = (shaderModel >= 4) ? "SV_Position" : "POSITION";
const unsigned int renderTargetCount = usesMRT ? mRenderer->getMaxRenderTargets() : 1;
std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
// special varyings that use reserved registers
int reservedRegisterIndex = registers;
@ -1472,9 +1475,14 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying
"struct PS_OUTPUT\n"
"{\n";
for (unsigned int i = 0; i < renderTargetCount; i++)
for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
{
pixelHLSL += " float4 gl_Color" + str(i) + " : " + targetSemantic + str(i) + ";\n";
pixelHLSL += " float4 gl_Color" + str(renderTargetIndex) + " : " + targetSemantic + str(renderTargetIndex) + ";\n";
}
if (fragmentShader->mUsesFragDepth)
{
pixelHLSL += " float gl_Depth : " + depthSemantic + ";\n";
}
pixelHLSL += "};\n"
@ -1583,11 +1591,16 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying
"\n"
" PS_OUTPUT output;\n";
for (unsigned int i = 0; i < renderTargetCount; i++)
for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
{
unsigned int sourceColor = fragmentShader->mUsesFragData ? i : 0;
unsigned int sourceColorIndex = broadcast ? 0 : renderTargetIndex;
pixelHLSL += " output.gl_Color" + str(i) + " = gl_Color[" + str(sourceColor) + "];\n";
pixelHLSL += " output.gl_Color" + str(renderTargetIndex) + " = gl_Color[" + str(sourceColorIndex) + "];\n";
}
if (fragmentShader->mUsesFragDepth)
{
pixelHLSL += " output.gl_Depth = gl_Depth;\n";
}
pixelHLSL += "\n"
@ -1617,6 +1630,14 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
return false;
}
int compileFlags = 0;
stream.read(&compileFlags);
if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
{
infoLog.append("Mismatched compilation flags.");
return false;
}
for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
{
stream.read(&mLinkedAttribute[i].type);
@ -1626,6 +1647,8 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
stream.read(&mSemanticIndex[i]);
}
initAttributesByLayout();
for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
{
stream.read(&mSamplersPS[i].active);
@ -1769,6 +1792,7 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length)
stream.write(GL_PROGRAM_BINARY_ANGLE);
stream.write(VERSION_DWORD);
stream.write(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
{
@ -1917,27 +1941,6 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
}
bool success = true;
mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX);
mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL);
if (usesGeometryShader())
{
std::string geometryHLSL = generateGeometryShaderHLSL(registers, packing, fragmentShader, vertexShader);
mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY);
}
if (!mVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable))
{
infoLog.append("Failed to create D3D shaders.");
success = false;
delete mVertexExecutable;
mVertexExecutable = NULL;
delete mPixelExecutable;
mPixelExecutable = NULL;
delete mGeometryExecutable;
mGeometryExecutable = NULL;
}
if (!linkAttributes(infoLog, attributeBindings, fragmentShader, vertexShader))
{
@ -1949,6 +1952,39 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
success = false;
}
// special case for gl_DepthRange, the only built-in uniform (also a struct)
if (vertexShader->mUsesDepthRange || fragmentShader->mUsesDepthRange)
{
mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0));
mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0));
mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0));
}
if (success)
{
mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX);
mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL);
if (usesGeometryShader())
{
std::string geometryHLSL = generateGeometryShaderHLSL(registers, packing, fragmentShader, vertexShader);
mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY);
}
if (!mVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable))
{
infoLog.append("Failed to create D3D shaders.");
success = false;
delete mVertexExecutable;
mVertexExecutable = NULL;
delete mPixelExecutable;
mPixelExecutable = NULL;
delete mGeometryExecutable;
mGeometryExecutable = NULL;
}
}
return success;
}
@ -2019,6 +2055,8 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at
}
}
initAttributesByLayout();
return true;
}
@ -2545,12 +2583,6 @@ struct AttributeSorter
AttributeSorter(const int (&semanticIndices)[MAX_VERTEX_ATTRIBS])
: originalIndices(semanticIndices)
{
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
indices[i] = i;
}
std::sort(&indices[0], &indices[MAX_VERTEX_ATTRIBS], *this);
}
bool operator()(int a, int b)
@ -2558,27 +2590,32 @@ struct AttributeSorter
return originalIndices[a] == -1 ? false : originalIndices[a] < originalIndices[b];
}
int indices[MAX_VERTEX_ATTRIBS];
const int (&originalIndices)[MAX_VERTEX_ATTRIBS];
};
void ProgramBinary::initAttributesByLayout()
{
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
mAttributesByLayout[i] = i;
}
std::sort(&mAttributesByLayout[0], &mAttributesByLayout[MAX_VERTEX_ATTRIBS], AttributeSorter(mSemanticIndex));
}
void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const
{
AttributeSorter sorter(mSemanticIndex);
int oldIndices[MAX_VERTEX_ATTRIBS];
rx::TranslatedAttribute oldTranslatedAttributes[MAX_VERTEX_ATTRIBS];
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
oldIndices[i] = mSemanticIndex[i];
oldTranslatedAttributes[i] = attributes[i];
}
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
int oldIndex = sorter.indices[i];
sortedSemanticIndices[i] = oldIndices[oldIndex];
int oldIndex = mAttributesByLayout[i];
sortedSemanticIndices[i] = mSemanticIndex[oldIndex];
attributes[i] = oldTranslatedAttributes[oldIndex];
}
}

View File

@ -114,6 +114,7 @@ class ProgramBinary : public RefCountObject
unsigned int getSerial() const;
void initAttributesByLayout();
void sortAttributesByLayout(rx::TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const;
static std::string decorateAttribute(const std::string &name); // Prepend an underscore
@ -142,6 +143,7 @@ class ProgramBinary : public RefCountObject
Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS];
int mSemanticIndex[MAX_VERTEX_ATTRIBS];
int mAttributesByLayout[MAX_VERTEX_ATTRIBS];
struct Sampler
{

View File

@ -247,6 +247,7 @@ void Shader::initializeCompiler()
resources.EXT_draw_buffers = mRenderer->getMaxRenderTargets() > 1;
// resources.OES_EGL_image_external = mRenderer->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported.
resources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp
resources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output
mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
@ -304,6 +305,8 @@ void Shader::parseVaryings()
mUsesFrontFacing = strstr(mHlsl, "GL_USES_FRONT_FACING") != NULL;
mUsesPointSize = strstr(mHlsl, "GL_USES_POINT_SIZE") != NULL;
mUsesPointCoord = strstr(mHlsl, "GL_USES_POINT_COORD") != NULL;
mUsesDepthRange = strstr(mHlsl, "GL_USES_DEPTH_RANGE") != NULL;
mUsesFragDepth = strstr(mHlsl, "GL_USES_FRAG_DEPTH") != NULL;
}
}
@ -335,6 +338,8 @@ void Shader::uncompile()
mUsesFrontFacing = false;
mUsesPointSize = false;
mUsesPointCoord = false;
mUsesDepthRange = false;
mUsesFragDepth = false;
mActiveUniforms.clear();
}

View File

@ -105,6 +105,8 @@ class Shader
bool mUsesFrontFacing;
bool mUsesPointSize;
bool mUsesPointCoord;
bool mUsesDepthRange;
bool mUsesFragDepth;
static void *mFragmentCompiler;
static void *mVertexCompiler;

View File

@ -14,10 +14,10 @@
#include "libGLESv2/main.h"
#include "libGLESv2/mathutil.h"
#include "libGLESv2/utilities.h"
#if defined(ANGLE_ENABLE_D3D11)
# define D3DFMT_UNKNOWN DXGI_FORMAT_UNKNOWN
#ifndef ANGLE_ENABLE_D3D11
# include "libGLESv2/renderer/Blit.h"
#else
# include "libGLESv2/renderer/Blit.h"
# define D3DFMT_UNKNOWN DXGI_FORMAT_UNKNOWN
#endif
#include "libGLESv2/Renderbuffer.h"
#include "libGLESv2/renderer/Image.h"

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2012-2013 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.
//
@ -54,6 +54,7 @@ struct RasterizerState
GLfloat polygonOffsetUnits;
bool pointDrawMode;
bool multiSample;
};
struct BlendState

View File

@ -4893,6 +4893,7 @@ void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samp
case GL_RGB565:
case GL_RGB8_OES:
case GL_RGBA8_OES:
case GL_BGRA8_EXT:
case GL_STENCIL_INDEX8:
case GL_DEPTH24_STENCIL8_OES:
context->setRenderbufferStorage(width, height, internalformat, samples);
@ -6977,17 +6978,14 @@ void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs)
if (context->getDrawFramebufferHandle() == 0)
{
if (n > 1)
if (n != 1)
{
return gl::error(GL_INVALID_OPERATION);
}
if (n == 1)
if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
{
if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
{
return gl::error(GL_INVALID_OPERATION);
}
return gl::error(GL_INVALID_OPERATION);
}
}
else
@ -7008,6 +7006,11 @@ void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs)
{
framebuffer->setDrawBufferState(colorAttachment, bufs[colorAttachment]);
}
for (int colorAttachment = n; colorAttachment < (int)context->getMaximumRenderTargets(); colorAttachment++)
{
framebuffer->setDrawBufferState(colorAttachment, GL_NONE);
}
}
}
catch (std::bad_alloc&)

View File

@ -183,3 +183,6 @@ EXPORTS
glBindTexImage @158 NONAME
glCreateRenderer @177 NONAME
glDestroyRenderer @178 NONAME
; Setting up TRACE macro callbacks
SetTraceFunctionPointers @180

View File

@ -172,6 +172,7 @@ EXPORTS
glDrawElementsInstancedANGLE@20 @174
glProgramBinaryOES@16 @175
glGetProgramBinaryOES@20 @176
glDrawBuffersEXT@8 @179
; EGL dependencies
glCreateContext @144 NONAME
@ -182,3 +183,6 @@ EXPORTS
glBindTexImage@4 @158 NONAME
glCreateRenderer @177 NONAME
glDestroyRenderer @178 NONAME
; Setting up TRACE macro callbacks
SetTraceFunctionPointers@8 @180

View File

@ -172,6 +172,7 @@ EXPORTS
glDrawElementsInstancedANGLE @174
glProgramBinaryOES @175
glGetProgramBinaryOES @176
glDrawBuffersEXT @179
; EGL dependencies
glCreateContext @144 NONAME
@ -182,3 +183,6 @@ EXPORTS
glBindTexImage @158 NONAME
glCreateRenderer @177 NONAME
glDestroyRenderer @178 NONAME
; Setting up TRACE macro callbacks
SetTraceFunctionPointers @180

View File

@ -172,6 +172,7 @@ EXPORTS
glDrawElementsInstancedANGLE@20 @174
glProgramBinaryOES@16 @175
glGetProgramBinaryOES@20 @176
glDrawBuffersEXT@8 @179
; EGL dependencies
glCreateContext @144 NONAME
@ -182,3 +183,6 @@ EXPORTS
glBindTexImage@4 @158 NONAME
glCreateRenderer @177 NONAME
glDestroyRenderer @178 NONAME
; Setting up TRACE macro callbacks
SetTraceFunctionPointers@8 @180

View File

@ -71,30 +71,27 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
return TRUE;
}
static gl::Current *current()
{
return (gl::Current*)TlsGetValue(currentTLS);
}
#else // !QT_OPENGL_ES_2_ANGLE_STATIC
static inline gl::Current *current()
{
// No precautions for thread safety taken as ANGLE is used single-threaded in Qt.
static gl::Current curr = { 0, 0 };
return &curr;
}
#endif // QT_OPENGL_ES_2_ANGLE_STATIC
#endif // !QT_OPENGL_ES_2_ANGLE_STATIC
namespace gl
{
Current *getCurrent()
{
#ifndef QT_OPENGL_ES_2_ANGLE_STATIC
return (Current*)TlsGetValue(currentTLS);
#else
// No precautions for thread safety taken as ANGLE is used single-threaded in Qt.
static gl::Current curr = { 0, 0 };
return &curr;
#endif
}
void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface)
{
Current *curr = current();
Current *current = getCurrent();
curr->context = context;
curr->display = display;
current->context = context;
current->display = display;
if (context && display && surface)
{
@ -104,7 +101,9 @@ void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface)
Context *getContext()
{
return current()->context;
Current *current = getCurrent();
return current->context;
}
Context *getNonLostContext()
@ -128,7 +127,9 @@ Context *getNonLostContext()
egl::Display *getDisplay()
{
return current()->display;
Current *current = getCurrent();
return current->display;
}
// Records an error code

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2013 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.
//
@ -58,7 +58,7 @@ gl::Context *glCreateContext(const gl::Context *shareContext, rx::Renderer *rend
void glDestroyContext(gl::Context *context);
void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface);
gl::Context *glGetCurrentContext();
rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, bool softwareDevice);
rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayType displayId);
void glDestroyRenderer(rx::Renderer *renderer);
__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname);

View File

@ -93,6 +93,7 @@ inline bool supportsSSE2()
return supports;
}
#if defined(_M_IX86) || defined(_M_AMD64) // ARM doesn't provide __cpuid()
int info[4];
__cpuid(info, 0);
@ -102,6 +103,7 @@ inline bool supportsSSE2()
supports = (info[3] >> 26) & 1;
}
#endif
checked = true;

View File

@ -32,11 +32,11 @@
#include <unordered_map>
#include <vector>
#if defined(ANGLE_ENABLE_D3D11)
# include <D3D11.h>
# include <dxgi.h>
#ifndef ANGLE_ENABLE_D3D11
#include <d3d9.h>
#else
# include <d3d9.h>
#include <D3D11.h>
#include <dxgi.h>
#endif
#include <D3Dcompiler.h>

View File

@ -160,12 +160,20 @@ void BufferStorage11::setData(const void* data, unsigned int size, unsigned int
bufferDesc.MiscFlags = 0;
bufferDesc.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA initialData;
initialData.pSysMem = data;
initialData.SysMemPitch = size;
initialData.SysMemSlicePitch = 0;
if (data)
{
D3D11_SUBRESOURCE_DATA initialData;
initialData.pSysMem = data;
initialData.SysMemPitch = size;
initialData.SysMemSlicePitch = 0;
result = device->CreateBuffer(&bufferDesc, &initialData, &mStagingBuffer);
}
else
{
result = device->CreateBuffer(&bufferDesc, NULL, &mStagingBuffer);
}
result = device->CreateBuffer(&bufferDesc, &initialData, &mStagingBuffer);
if (FAILED(result))
{
return gl::error(GL_OUT_OF_MEMORY);
@ -173,7 +181,7 @@ void BufferStorage11::setData(const void* data, unsigned int size, unsigned int
mStagingBufferSize = size;
}
else
else if (data)
{
D3D11_MAPPED_SUBRESOURCE mappedResource;
result = context->Map(mStagingBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource);
@ -182,8 +190,7 @@ void BufferStorage11::setData(const void* data, unsigned int size, unsigned int
return gl::error(GL_OUT_OF_MEMORY);
}
if (data)
memcpy(mappedResource.pData, data, size);
memcpy(mappedResource.pData, data, size);
context->Unmap(mStagingBuffer, 0);
}
@ -212,7 +219,6 @@ void BufferStorage11::setData(const void* data, unsigned int size, unsigned int
mBufferSize = 0;
}
if (data)
{
D3D11_SUBRESOURCE_DATA initialData;

View File

@ -55,7 +55,9 @@ void BufferStorage9::setData(const void* data, unsigned int size, unsigned int o
mSize = std::max(mSize, offset + size);
if (data)
{
memcpy(reinterpret_cast<char*>(mMemory) + offset, data, size);
}
}
void BufferStorage9::clear()

View File

@ -50,8 +50,8 @@ void Image11::generateMipmap(Image11 *dest, Image11 *src)
ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight());
D3D11_MAPPED_SUBRESOURCE destMapped, srcMapped;
dest->map(&destMapped);
src->map(&srcMapped);
dest->map(D3D11_MAP_WRITE, &destMapped);
src->map(D3D11_MAP_READ, &srcMapped);
const unsigned char *sourceData = reinterpret_cast<const unsigned char*>(srcMapped.pData);
unsigned char *destData = reinterpret_cast<unsigned char*>(destMapped.pData);
@ -171,7 +171,7 @@ void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei heig
GLint unpackAlignment, const void *input)
{
D3D11_MAPPED_SUBRESOURCE mappedImage;
HRESULT result = map(&mappedImage);
HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
if (FAILED(result))
{
ERR("Could not map image for loading.");
@ -194,7 +194,7 @@ void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei heig
loadAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
break;
case GL_LUMINANCE32F_EXT:
loadLuminanceFloatDataToRGB(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
loadLuminanceFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
break;
case GL_ALPHA16F_EXT:
loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
@ -230,7 +230,7 @@ void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei heig
loadBGRADataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
break;
case GL_RGB32F_EXT:
loadRGBFloatDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
loadRGBFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
break;
case GL_RGB16F_EXT:
loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
@ -254,7 +254,7 @@ void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GL
ASSERT(yoffset % 4 == 0);
D3D11_MAPPED_SUBRESOURCE mappedImage;
HRESULT result = map(&mappedImage);
HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
if (FAILED(result))
{
ERR("Could not map image for loading.");
@ -344,7 +344,7 @@ void Image11::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width
{
// This format requires conversion, so we must copy the texture to staging and manually convert via readPixels
D3D11_MAPPED_SUBRESOURCE mappedImage;
HRESULT result = map(&mappedImage);
HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
// determine the offset coordinate into the destination buffer
GLsizei rowOffset = gl::ComputePixelSize(mActualFormat) * xoffset;
@ -402,7 +402,7 @@ void Image11::createStagingTexture()
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_STAGING;
desc.BindFlags = 0;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
HRESULT result = device->CreateTexture2D(&desc, NULL, &newTexture);
@ -420,7 +420,7 @@ void Image11::createStagingTexture()
mDirty = false;
}
HRESULT Image11::map(D3D11_MAPPED_SUBRESOURCE *map)
HRESULT Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map)
{
createStagingTexture();
@ -429,7 +429,7 @@ HRESULT Image11::map(D3D11_MAPPED_SUBRESOURCE *map)
if (mStagingTexture)
{
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
result = deviceContext->Map(mStagingTexture, mStagingSubresource, D3D11_MAP_WRITE, 0, map);
result = deviceContext->Map(mStagingTexture, mStagingSubresource, mapType, 0, map);
// this can fail if the device is removed (from TDR)
if (d3d11::isDeviceLostError(result))

View File

@ -54,7 +54,7 @@ class Image11 : public Image
virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
protected:
HRESULT map(D3D11_MAPPED_SUBRESOURCE *map);
HRESULT map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map);
void unmap();
private:

View File

@ -67,18 +67,30 @@ unsigned int IndexBufferInterface::getSerial() const
return mIndexBuffer->getSerial();
}
int IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory)
bool IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset)
{
if (!mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory))
// Protect against integer overflow
if (mWritePosition + size < mWritePosition)
{
*outMappedMemory = NULL;
return -1;
return false;
}
int oldWritePos = static_cast<int>(mWritePosition);
mWritePosition += size;
if (!mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory))
{
if (outMappedMemory)
{
*outMappedMemory = NULL;
}
return false;
}
return oldWritePos;
if (streamOffset)
{
*streamOffset = mWritePosition;
}
mWritePosition += size;
return true;
}
bool IndexBufferInterface::unmapBuffer()
@ -130,12 +142,13 @@ bool StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum
{
bool result = true;
unsigned int curBufferSize = getBufferSize();
unsigned int writePos = getWritePosition();
if (size > curBufferSize)
{
result = setBufferSize(std::max(size, 2 * curBufferSize), indexType);
setWritePosition(0);
}
else if (getWritePosition() + size > curBufferSize)
else if (writePos + size > curBufferSize || writePos + size < writePos)
{
if (!discard())
{
@ -175,27 +188,9 @@ bool StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum in
}
}
unsigned int StaticIndexBufferInterface::lookupRange(intptr_t offset, GLsizei count, unsigned int *minIndex, unsigned int *maxIndex)
IndexRangeCache *StaticIndexBufferInterface::getIndexRangeCache()
{
IndexRange range = {offset, count};
std::map<IndexRange, IndexResult>::iterator res = mCache.find(range);
if (res == mCache.end())
{
return -1;
}
*minIndex = res->second.minIndex;
*maxIndex = res->second.maxIndex;
return res->second.streamOffset;
}
void StaticIndexBufferInterface::addRange(intptr_t offset, GLsizei count, unsigned int minIndex, unsigned int maxIndex, unsigned int streamOffset)
{
IndexRange indexRange = {offset, count};
IndexResult indexResult = {minIndex, maxIndex, streamOffset};
mCache[indexRange] = indexResult;
return &mIndexRangeCache;
}
}

View File

@ -11,6 +11,7 @@
#define LIBGLESV2_RENDERER_INDEXBUFFER_H_
#include "common/angleutils.h"
#include "libGLESv2/renderer/IndexRangeCache.h"
namespace rx
{
@ -58,7 +59,7 @@ class IndexBufferInterface
unsigned int getSerial() const;
int mapBuffer(unsigned int size, void** outMappedMemory);
bool mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset);
bool unmapBuffer();
IndexBuffer *getIndexBuffer() const;
@ -99,37 +100,10 @@ class StaticIndexBufferInterface : public IndexBufferInterface
virtual bool reserveBufferSpace(unsigned int size, GLenum indexType);
unsigned int lookupRange(intptr_t offset, GLsizei count, unsigned int *minIndex, unsigned int *maxIndex); // Returns the offset into the index buffer, or -1 if not found
void addRange(intptr_t offset, GLsizei count, unsigned int minIndex, unsigned int maxIndex, unsigned int streamOffset);
IndexRangeCache *getIndexRangeCache();
private:
struct IndexRange
{
intptr_t offset;
GLsizei count;
bool operator<(const IndexRange& rhs) const
{
if (offset != rhs.offset)
{
return offset < rhs.offset;
}
if (count != rhs.count)
{
return count < rhs.count;
}
return false;
}
};
struct IndexResult
{
unsigned int minIndex;
unsigned int maxIndex;
unsigned int streamOffset;
};
std::map<IndexRange, IndexResult> mCache;
IndexRangeCache mIndexRangeCache;
};
}

View File

@ -75,7 +75,8 @@ bool IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** out
{
if (mBuffer)
{
if (offset + size > mBufferSize)
// Check for integer overflows and out-out-bounds map requests
if (offset + size < offset || offset + size > mBufferSize)
{
ERR("Index buffer map range is not inside the buffer.");
return false;

View File

@ -13,6 +13,7 @@
#include "libGLESv2/Buffer.h"
#include "libGLESv2/main.h"
#include "libGLESv2/utilities.h"
#include "libGLESv2/renderer/IndexBuffer.h"
namespace rx
@ -53,17 +54,6 @@ IndexDataManager::~IndexDataManager()
delete mCountingBuffer;
}
static unsigned int indexTypeSize(GLenum type)
{
switch (type)
{
case GL_UNSIGNED_INT: return sizeof(GLuint);
case GL_UNSIGNED_SHORT: return sizeof(GLushort);
case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
default: UNREACHABLE(); return sizeof(GLushort);
}
}
static void convertIndices(GLenum type, const void *input, GLsizei count, void *output)
{
if (type == GL_UNSIGNED_BYTE)
@ -125,13 +115,19 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
}
GLenum destinationIndexType = (type == GL_UNSIGNED_INT) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
intptr_t offset = reinterpret_cast<intptr_t>(indices);
unsigned int offset = 0;
bool alignedOffset = false;
BufferStorage *storage = NULL;
if (buffer != NULL)
{
if (reinterpret_cast<uintptr_t>(indices) > std::numeric_limits<unsigned int>::max())
{
return GL_OUT_OF_MEMORY;
}
offset = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(indices));
storage = buffer->getStorage();
switch (type)
@ -142,7 +138,16 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
default: UNREACHABLE(); alignedOffset = false;
}
if (indexTypeSize(type) * count + offset > storage->getSize())
unsigned int typeSize = gl::ComputeTypeSize(type);
// check for integer overflows
if (static_cast<unsigned int>(count) > (std::numeric_limits<unsigned int>::max() / typeSize) ||
typeSize * static_cast<unsigned int>(count) + offset < offset)
{
return GL_OUT_OF_MEMORY;
}
if (typeSize * static_cast<unsigned int>(count) + offset > storage->getSize())
{
return GL_INVALID_OPERATION;
}
@ -156,37 +161,44 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
IndexBufferInterface *indexBuffer = streamingBuffer;
bool directStorage = alignedOffset && storage && storage->supportsDirectBinding() &&
destinationIndexType == type;
UINT streamOffset = 0;
unsigned int streamOffset = 0;
if (directStorage)
{
indexBuffer = streamingBuffer;
streamOffset = offset;
storage->markBufferUsage();
computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
if (!buffer->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex,
&translated->maxIndex, NULL))
{
computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
buffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex,
translated->maxIndex, offset);
}
}
else if (staticBuffer && staticBuffer->getBufferSize() != 0 && staticBuffer->getIndexType() == type && alignedOffset)
{
indexBuffer = staticBuffer;
streamOffset = staticBuffer->lookupRange(offset, count, &translated->minIndex, &translated->maxIndex);
if (streamOffset == -1)
if (!staticBuffer->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex,
&translated->maxIndex, &streamOffset))
{
streamOffset = (offset / indexTypeSize(type)) * indexTypeSize(destinationIndexType);
streamOffset = (offset / gl::ComputeTypeSize(type)) * gl::ComputeTypeSize(destinationIndexType);
computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex,
translated->maxIndex, streamOffset);
}
}
else
{
int convertCount = count;
unsigned int convertCount = count;
if (staticBuffer)
{
if (staticBuffer->getBufferSize() == 0 && alignedOffset)
{
indexBuffer = staticBuffer;
convertCount = storage->getSize() / indexTypeSize(type);
convertCount = storage->getSize() / gl::ComputeTypeSize(type);
}
else
{
@ -201,12 +213,22 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
return GL_INVALID_OPERATION;
}
unsigned int bufferSizeRequired = convertCount * indexTypeSize(destinationIndexType);
indexBuffer->reserveBufferSpace(bufferSizeRequired, type);
unsigned int indexTypeSize = gl::ComputeTypeSize(destinationIndexType);
if (convertCount > std::numeric_limits<unsigned int>::max() / indexTypeSize)
{
ERR("Reserving %u indicies of %u bytes each exceeds the maximum buffer size.", convertCount, indexTypeSize);
return GL_OUT_OF_MEMORY;
}
unsigned int bufferSizeRequired = convertCount * indexTypeSize;
if (!indexBuffer->reserveBufferSpace(bufferSizeRequired, type))
{
ERR("Failed to reserve %u bytes in an index buffer.", bufferSizeRequired);
return GL_OUT_OF_MEMORY;
}
void* output = NULL;
streamOffset = indexBuffer->mapBuffer(bufferSizeRequired, &output);
if (streamOffset == -1 || output == NULL)
if (!indexBuffer->mapBuffer(bufferSizeRequired, &output, &streamOffset))
{
ERR("Failed to map index buffer.");
return GL_OUT_OF_MEMORY;
@ -224,20 +246,21 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
if (staticBuffer)
{
streamOffset = (offset / indexTypeSize(type)) * indexTypeSize(destinationIndexType);
staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
streamOffset = (offset / gl::ComputeTypeSize(type)) * gl::ComputeTypeSize(destinationIndexType);
staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex,
translated->maxIndex, streamOffset);
}
}
translated->storage = directStorage ? storage : NULL;
translated->indexBuffer = indexBuffer->getIndexBuffer();
translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial();
translated->startIndex = streamOffset / indexTypeSize(destinationIndexType);
translated->startIndex = streamOffset / gl::ComputeTypeSize(destinationIndexType);
translated->startOffset = streamOffset;
if (buffer)
{
buffer->promoteStaticUsage(count * indexTypeSize(type));
buffer->promoteStaticUsage(count * gl::ComputeTypeSize(type));
}
return GL_NO_ERROR;
@ -256,7 +279,7 @@ StaticIndexBufferInterface *IndexDataManager::getCountingIndices(GLsizei count)
mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT);
void* mappedMemory = NULL;
if (mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory) == -1 || mappedMemory == NULL)
if (!mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory, NULL))
{
ERR("Failed to map counting buffer.");
return NULL;
@ -286,7 +309,7 @@ StaticIndexBufferInterface *IndexDataManager::getCountingIndices(GLsizei count)
mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT);
void* mappedMemory = NULL;
if (mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory) == -1 || mappedMemory == NULL)
if (!mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory, NULL))
{
ERR("Failed to map counting buffer.");
return NULL;

View File

@ -0,0 +1,97 @@
#include "precompiled.h"
//
// Copyright (c) 2013 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.
//
// IndexRangeCache.cpp: Defines the rx::IndexRangeCache class which stores information about
// ranges of indices.
#include "libGLESv2/renderer/IndexRangeCache.h"
#include "common/debug.h"
#include "libGLESv2/utilities.h"
#include <tuple>
namespace rx
{
void IndexRangeCache::addRange(GLenum type, unsigned int offset, GLsizei count, unsigned int minIdx, unsigned int maxIdx,
unsigned int streamOffset)
{
mIndexRangeCache[IndexRange(type, offset, count)] = IndexBounds(minIdx, maxIdx, streamOffset);
}
void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size)
{
unsigned int invalidateStart = offset;
unsigned int invalidateEnd = offset + size;
IndexRangeMap::iterator i = mIndexRangeCache.begin();
while (i != mIndexRangeCache.end())
{
unsigned int rangeStart = i->second.streamOffset;
unsigned int rangeEnd = i->second.streamOffset + (gl::ComputeTypeSize(i->first.type) * i->first.count);
if (invalidateEnd < rangeStart || invalidateStart > rangeEnd)
{
++i;
}
else
{
i = mIndexRangeCache.erase(i);
}
}
}
bool IndexRangeCache::findRange(GLenum type, unsigned int offset, GLsizei count, unsigned int *outMinIndex,
unsigned int *outMaxIndex, unsigned int *outStreamOffset) const
{
IndexRangeMap::const_iterator i = mIndexRangeCache.find(IndexRange(type, offset, count));
if (i != mIndexRangeCache.end())
{
if (outMinIndex) *outMinIndex = i->second.minIndex;
if (outMaxIndex) *outMaxIndex = i->second.maxIndex;
if (outStreamOffset) *outStreamOffset = i->second.streamOffset;
return true;
}
else
{
if (outMinIndex) *outMinIndex = 0;
if (outMaxIndex) *outMaxIndex = 0;
if (outStreamOffset) *outStreamOffset = 0;
return false;
}
}
void IndexRangeCache::clear()
{
mIndexRangeCache.clear();
}
IndexRangeCache::IndexRange::IndexRange()
: type(GL_NONE), offset(0), count(0)
{
}
IndexRangeCache::IndexRange::IndexRange(GLenum typ, intptr_t off, GLsizei c)
: type(typ), offset(off), count(c)
{
}
bool IndexRangeCache::IndexRange::operator<(const IndexRange& rhs) const
{
return std::make_tuple(type, offset, count) < std::make_tuple(rhs.type, rhs.offset, rhs.count);
}
IndexRangeCache::IndexBounds::IndexBounds()
: minIndex(0), maxIndex(0), streamOffset(0)
{
}
IndexRangeCache::IndexBounds::IndexBounds(unsigned int minIdx, unsigned int maxIdx, unsigned int offset)
: minIndex(minIdx), maxIndex(maxIdx), streamOffset(offset)
{
}
}

View File

@ -0,0 +1,58 @@
//
// Copyright (c) 2013 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.
//
// IndexRangeCache.h: Defines the rx::IndexRangeCache class which stores information about
// ranges of indices.
#ifndef LIBGLESV2_RENDERER_INDEXRANGECACHE_H_
#define LIBGLESV2_RENDERER_INDEXRANGECACHE_H_
#include "common/angleutils.h"
namespace rx
{
class IndexRangeCache
{
public:
void addRange(GLenum type, unsigned int offset, GLsizei count, unsigned int minIdx, unsigned int maxIdx,
unsigned int streamOffset);
bool findRange(GLenum type, unsigned int offset, GLsizei count, unsigned int *outMinIndex,
unsigned int *outMaxIndex, unsigned int *outStreamOffset) const;
void invalidateRange(unsigned int offset, unsigned int size);
void clear();
private:
struct IndexRange
{
GLenum type;
unsigned int offset;
GLsizei count;
IndexRange();
IndexRange(GLenum type, intptr_t offset, GLsizei count);
bool operator<(const IndexRange& rhs) const;
};
struct IndexBounds
{
unsigned int minIndex;
unsigned int maxIndex;
unsigned int streamOffset;
IndexBounds();
IndexBounds(unsigned int minIdx, unsigned int maxIdx, unsigned int offset);
};
typedef std::map<IndexRange, IndexBounds> IndexRangeMap;
IndexRangeMap mIndexRangeCache;
};
}
#endif LIBGLESV2_RENDERER_INDEXRANGECACHE_H

View File

@ -28,6 +28,13 @@ InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInp
mCounter = 0;
mDevice = NULL;
mDeviceContext = NULL;
mCurrentIL = NULL;
for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
mCurrentBuffers[i] = -1;
mCurrentVertexStrides[i] = -1;
mCurrentVertexOffsets[i] = -1;
}
}
InputLayoutCache::~InputLayoutCache()
@ -49,6 +56,18 @@ void InputLayoutCache::clear()
i->second.inputLayout->Release();
}
mInputLayoutMap.clear();
markDirty();
}
void InputLayoutCache::markDirty()
{
mCurrentIL = NULL;
for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
mCurrentBuffers[i] = -1;
mCurrentVertexStrides[i] = -1;
mCurrentVertexOffsets[i] = -1;
}
}
GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
@ -66,6 +85,7 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M
InputLayoutKey ilKey = { 0 };
ID3D11Buffer *vertexBuffers[gl::MAX_VERTEX_ATTRIBS] = { NULL };
unsigned int vertexBufferSerials[gl::MAX_VERTEX_ATTRIBS] = { 0 };
UINT vertexStrides[gl::MAX_VERTEX_ATTRIBS] = { 0 };
UINT vertexOffsets[gl::MAX_VERTEX_ATTRIBS] = { 0 };
@ -83,18 +103,19 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M
// Record the type of the associated vertex shader vector in our key
// This will prevent mismatched vertex shaders from using the same input layout
GLint attributeSize;
programBinary->getActiveAttribute(ilKey.elementCount, 0, NULL, &attributeSize, &ilKey.glslElementType[ilKey.elementCount], NULL);
programBinary->getActiveAttribute(ilKey.elementCount, 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL);
ilKey.elements[ilKey.elementCount].SemanticName = semanticName;
ilKey.elements[ilKey.elementCount].SemanticIndex = sortedSemanticIndices[i];
ilKey.elements[ilKey.elementCount].Format = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDXGIFormat(*attributes[i].attribute) : DXGI_FORMAT_R32G32B32A32_FLOAT;
ilKey.elements[ilKey.elementCount].InputSlot = i;
ilKey.elements[ilKey.elementCount].AlignedByteOffset = 0;
ilKey.elements[ilKey.elementCount].InputSlotClass = inputClass;
ilKey.elements[ilKey.elementCount].InstanceDataStepRate = attributes[i].divisor;
ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName;
ilKey.elements[ilKey.elementCount].desc.SemanticIndex = sortedSemanticIndices[i];
ilKey.elements[ilKey.elementCount].desc.Format = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDXGIFormat(*attributes[i].attribute) : DXGI_FORMAT_R32G32B32A32_FLOAT;
ilKey.elements[ilKey.elementCount].desc.InputSlot = i;
ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0;
ilKey.elements[ilKey.elementCount].desc.InputSlotClass = inputClass;
ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = attributes[i].divisor;
ilKey.elementCount++;
vertexBuffers[i] = bufferStorage ? bufferStorage->getBuffer() : vertexBuffer->getBuffer();
vertexBufferSerials[i] = bufferStorage ? bufferStorage->getSerial() : vertexBuffer->getSerial();
vertexStrides[i] = attributes[i].stride;
vertexOffsets[i] = attributes[i].offset;
}
@ -112,7 +133,13 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M
{
ShaderExecutable11 *shader = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable());
HRESULT result = mDevice->CreateInputLayout(ilKey.elements, ilKey.elementCount, shader->getFunction(), shader->getLength(), &inputLayout);
D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS];
for (unsigned int j = 0; j < ilKey.elementCount; ++j)
{
descs[j] = ilKey.elements[j].desc;
}
HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader->getFunction(), shader->getLength(), &inputLayout);
if (FAILED(result))
{
ERR("Failed to crate input layout, result: 0x%08x", result);
@ -143,8 +170,23 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M
mInputLayoutMap.insert(std::make_pair(ilKey, inputCounterPair));
}
mDeviceContext->IASetInputLayout(inputLayout);
mDeviceContext->IASetVertexBuffers(0, gl::MAX_VERTEX_ATTRIBS, vertexBuffers, vertexStrides, vertexOffsets);
if (inputLayout != mCurrentIL)
{
mDeviceContext->IASetInputLayout(inputLayout);
mCurrentIL = inputLayout;
}
for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
if (vertexBufferSerials[i] != mCurrentBuffers[i] || vertexStrides[i] != mCurrentVertexStrides[i] ||
vertexOffsets[i] != mCurrentVertexOffsets[i])
{
mDeviceContext->IASetVertexBuffers(i, 1, &vertexBuffers[i], &vertexStrides[i], &vertexOffsets[i]);
mCurrentBuffers[i] = vertexBufferSerials[i];
mCurrentVertexStrides[i] = vertexStrides[i];
mCurrentVertexOffsets[i] = vertexOffsets[i];
}
}
return GL_NO_ERROR;
}
@ -154,13 +196,18 @@ std::size_t InputLayoutCache::hashInputLayout(const InputLayoutKey &inputLayout)
static const unsigned int seed = 0xDEADBEEF;
std::size_t hash = 0;
MurmurHash3_x86_32(&inputLayout, sizeof(InputLayoutKey), seed, &hash);
MurmurHash3_x86_32(inputLayout.begin(), inputLayout.end() - inputLayout.begin(), seed, &hash);
return hash;
}
bool InputLayoutCache::compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b)
{
return memcmp(&a, &b, sizeof(InputLayoutKey)) == 0;
if (a.elementCount != b.elementCount)
{
return false;
}
return std::equal(a.begin(), a.end(), b.begin());
}
}

View File

@ -30,6 +30,7 @@ class InputLayoutCache
void initialize(ID3D11Device *device, ID3D11DeviceContext *context);
void clear();
void markDirty();
GLenum applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
gl::ProgramBinary *programBinary);
@ -37,11 +38,26 @@ class InputLayoutCache
private:
DISALLOW_COPY_AND_ASSIGN(InputLayoutCache);
struct InputLayoutElement
{
D3D11_INPUT_ELEMENT_DESC desc;
GLenum glslElementType;
};
struct InputLayoutKey
{
unsigned int elementCount;
D3D11_INPUT_ELEMENT_DESC elements[gl::MAX_VERTEX_ATTRIBS];
GLenum glslElementType[gl::MAX_VERTEX_ATTRIBS];
InputLayoutElement elements[gl::MAX_VERTEX_ATTRIBS];
const char *begin() const
{
return reinterpret_cast<const char*>(&elementCount);
}
const char *end() const
{
return reinterpret_cast<const char*>(&elements[elementCount]);
}
};
struct InputLayoutCounterPair
@ -50,6 +66,11 @@ class InputLayoutCache
unsigned long long lastUsedTime;
};
ID3D11InputLayout *mCurrentIL;
unsigned int mCurrentBuffers[gl::MAX_VERTEX_ATTRIBS];
UINT mCurrentVertexStrides[gl::MAX_VERTEX_ATTRIBS];
UINT mCurrentVertexOffsets[gl::MAX_VERTEX_ATTRIBS];
static std::size_t hashInputLayout(const InputLayoutKey &inputLayout);
static bool compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b);

View File

@ -231,7 +231,7 @@ ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::Rasterizer
rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor;
rasterDesc.DepthClipEnable = TRUE;
rasterDesc.ScissorEnable = scissorEnabled ? TRUE : FALSE;
rasterDesc.MultisampleEnable = TRUE;
rasterDesc.MultisampleEnable = rasterState.multiSample;
rasterDesc.AntialiasedLineEnable = FALSE;
ID3D11RasterizerState *dx11RasterizerState = NULL;

Some files were not shown because too many files have changed in this diff Show More