diff --git a/src/3rdparty/angle/.gitignore b/src/3rdparty/angle/.gitignore index c53d356b04..b108d54d93 100644 --- a/src/3rdparty/angle/.gitignore +++ b/src/3rdparty/angle/.gitignore @@ -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 diff --git a/src/3rdparty/angle/AUTHORS b/src/3rdparty/angle/AUTHORS index 10e60d85b6..a2ce91575a 100644 --- a/src/3rdparty/angle/AUTHORS +++ b/src/3rdparty/angle/AUTHORS @@ -17,6 +17,7 @@ Cloud Party, Inc. Intel Corporation Mozilla Corporation Turbulenz +Klarälvdalens Datakonsult AB Jacek Caban Mark Callow diff --git a/src/3rdparty/angle/CONTRIBUTORS b/src/3rdparty/angle/CONTRIBUTORS index 29f9ad3faf..fcb6315234 100644 --- a/src/3rdparty/angle/CONTRIBUTORS +++ b/src/3rdparty/angle/CONTRIBUTORS @@ -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 diff --git a/src/3rdparty/angle/LICENSE b/src/3rdparty/angle/LICENSE index 0513b7d0f9..9980c2f298 100644 --- a/src/3rdparty/angle/LICENSE +++ b/src/3rdparty/angle/LICENSE @@ -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 diff --git a/src/3rdparty/angle/include/EGL/eglext.h b/src/3rdparty/angle/include/EGL/eglext.h index b670840d12..c06d4c0850 100644 --- a/src/3rdparty/angle/include/EGL/eglext.h +++ b/src/3rdparty/angle/include/EGL/eglext.h @@ -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 diff --git a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h index da0f87aed9..28bf516f7f 100644 --- a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h +++ b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h @@ -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 diff --git a/src/3rdparty/angle/include/KHR/khrplatform.h b/src/3rdparty/angle/include/KHR/khrplatform.h index 18a104ea1f..001e925f46 100644 --- a/src/3rdparty/angle/include/KHR/khrplatform.h +++ b/src/3rdparty/angle/include/KHR/khrplatform.h @@ -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__) diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h index 31ac559279..9761567fb2 100644 --- a/src/3rdparty/angle/src/common/angleutils.h +++ b/src/3rdparty/angle/src/common/angleutils.h @@ -9,6 +9,8 @@ #ifndef COMMON_ANGLEUTILS_H_ #define COMMON_ANGLEUTILS_H_ +#include + // 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) \ diff --git a/src/3rdparty/angle/src/common/debug.cpp b/src/3rdparty/angle/src/common/debug.cpp index 438d3975e8..9b932567b0 100644 --- a/src/3rdparty/angle/src/common/debug.cpp +++ b/src/3rdparty/angle/src/common/debug.cpp @@ -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 +#else +typedef DWORD D3DCOLOR; #endif namespace gl diff --git a/src/3rdparty/angle/src/common/event_tracer.cpp b/src/3rdparty/angle/src/common/event_tracer.cpp new file mode 100644 index 0000000000..96cbb01061 --- /dev/null +++ b/src/3rdparty/angle/src/common/event_tracer.cpp @@ -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 diff --git a/src/3rdparty/angle/src/common/event_tracer.h b/src/3rdparty/angle/src/common/event_tracer.h new file mode 100644 index 0000000000..ae397e7db9 --- /dev/null +++ b/src/3rdparty/angle/src/common/event_tracer.h @@ -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_ diff --git a/src/3rdparty/angle/src/common/version.h b/src/3rdparty/angle/src/common/version.h index 7913851e6a..7a4942ad88 100644 --- a/src/3rdparty/angle/src/common/version.h +++ b/src/3rdparty/angle/src/common/version.h @@ -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) diff --git a/src/3rdparty/angle/src/compiler/BaseTypes.h b/src/3rdparty/angle/src/compiler/BaseTypes.h index af4c7e3ed9..1631f4f779 100644 --- a/src/3rdparty/angle/src/compiler/BaseTypes.h +++ b/src/3rdparty/angle/src/compiler/BaseTypes.h @@ -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"; } } diff --git a/src/3rdparty/angle/src/compiler/Common.h b/src/3rdparty/angle/src/compiler/Common.h index 27a5598290..46f9440fff 100644 --- a/src/3rdparty/angle/src/compiler/Common.h +++ b/src/3rdparty/angle/src/compiler/Common.h @@ -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 , TStringAllocator> TStri typedef std::basic_ostringstream, 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); } diff --git a/src/3rdparty/angle/src/compiler/Compiler.cpp b/src/3rdparty/angle/src/compiler/Compiler.cpp index c8c79e7147..ee64057ac4 100644 --- a/src/3rdparty/angle/src/compiler/Compiler.cpp +++ b/src/3rdparty/angle/src/compiler/Compiler.cpp @@ -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(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(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); } diff --git a/src/3rdparty/angle/src/compiler/ConstantUnion.h b/src/3rdparty/angle/src/compiler/ConstantUnion.h index 32af4d38b0..b1e37885f9 100644 --- a/src/3rdparty/angle/src/compiler/ConstantUnion.h +++ b/src/3rdparty/angle/src/compiler/ConstantUnion.h @@ -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; } diff --git a/src/3rdparty/angle/src/compiler/DetectCallDepth.cpp b/src/3rdparty/angle/src/compiler/DetectCallDepth.cpp new file mode 100644 index 0000000000..60df52c715 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/DetectCallDepth.cpp @@ -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; +} + diff --git a/src/3rdparty/angle/src/compiler/DetectCallDepth.h b/src/3rdparty/angle/src/compiler/DetectCallDepth.h new file mode 100644 index 0000000000..89e85f88f6 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/DetectCallDepth.h @@ -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 +#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 callees; + + Visit visit; + }; + + ErrorCode detectCallDepthForFunction(FunctionNode* func); + FunctionNode* findFunctionByName(const TString& name); + void resetFunctionNodes(); + + TInfoSink& getInfoSink() { return infoSink; } + + TVector functions; + FunctionNode* currentFunction; + TInfoSink& infoSink; + int maxDepth; + + DetectCallDepth(const DetectCallDepth&); + void operator=(const DetectCallDepth&); +}; + +#endif // COMPILER_DETECT_RECURSION_H_ diff --git a/src/3rdparty/angle/src/compiler/Diagnostics.cpp b/src/3rdparty/angle/src/compiler/Diagnostics.cpp index 06f370dbe5..8a38c41a65 100644 --- a/src/3rdparty/angle/src/compiler/Diagnostics.cpp +++ b/src/3rdparty/angle/src/compiler/Diagnostics.cpp @@ -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"; } diff --git a/src/3rdparty/angle/src/compiler/InfoSink.cpp b/src/3rdparty/angle/src/compiler/InfoSink.cpp index ba32f781f5..d20a6c0175 100644 --- a/src/3rdparty/angle/src/compiler/InfoSink.cpp +++ b/src/3rdparty/angle/src/compiler/InfoSink.cpp @@ -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"); } diff --git a/src/3rdparty/angle/src/compiler/InfoSink.h b/src/3rdparty/angle/src/compiler/InfoSink.h index e2224e918d..6888838142 100644 --- a/src/3rdparty/angle/src/compiler/InfoSink.h +++ b/src/3rdparty/angle/src/compiler/InfoSink.h @@ -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; diff --git a/src/3rdparty/angle/src/compiler/Initialize.cpp b/src/3rdparty/angle/src/compiler/Initialize.cpp index 97b46f898e..236383d874 100644 --- a/src/3rdparty/angle/src/compiler/Initialize.cpp +++ b/src/3rdparty/angle/src/compiler/Initialize.cpp @@ -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; } diff --git a/src/3rdparty/angle/src/compiler/Initialize.h b/src/3rdparty/angle/src/compiler/Initialize.h index 8b0adc6b4c..4aa13466ac 100644 --- a/src/3rdparty/angle/src/compiler/Initialize.h +++ b/src/3rdparty/angle/src/compiler/Initialize.h @@ -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 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, diff --git a/src/3rdparty/angle/src/compiler/InitializeDll.cpp b/src/3rdparty/angle/src/compiler/InitializeDll.cpp index 8763cfeea8..6c7f27fced 100644 --- a/src/3rdparty/angle/src/compiler/InitializeDll.cpp +++ b/src/3rdparty/angle/src/compiler/InitializeDll.cpp @@ -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(); } - diff --git a/src/3rdparty/angle/src/compiler/InitializeDll.h b/src/3rdparty/angle/src/compiler/InitializeDll.h index 857238eeae..43070cc3ff 100644 --- a/src/3rdparty/angle/src/compiler/InitializeDll.h +++ b/src/3rdparty/angle/src/compiler/InitializeDll.h @@ -7,10 +7,7 @@ #define __INITIALIZEDLL_H bool InitProcess(); -bool DetachProcess(); - -bool InitThread(); -bool DetachThread(); +void DetachProcess(); #endif // __INITIALIZEDLL_H diff --git a/src/3rdparty/angle/src/compiler/InitializeGLPosition.cpp b/src/3rdparty/angle/src/compiler/InitializeGLPosition.cpp new file mode 100644 index 0000000000..e0193e39d2 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/InitializeGLPosition.cpp @@ -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); +} diff --git a/src/3rdparty/angle/src/compiler/InitializeGLPosition.h b/src/3rdparty/angle/src/compiler/InitializeGLPosition.h new file mode 100644 index 0000000000..1b11075a13 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/InitializeGLPosition.h @@ -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_ diff --git a/src/3rdparty/angle/src/compiler/InitializeGlobals.h b/src/3rdparty/angle/src/compiler/InitializeGlobals.h index 842a45281d..0715941424 100644 --- a/src/3rdparty/angle/src/compiler/InitializeGlobals.h +++ b/src/3rdparty/angle/src/compiler/InitializeGlobals.h @@ -7,8 +7,6 @@ #ifndef __INITIALIZE_GLOBALS_INCLUDED_ #define __INITIALIZE_GLOBALS_INCLUDED_ -void InitializeGlobalPools(); -void FreeGlobalPools(); bool InitializePoolIndex(); void FreePoolIndex(); diff --git a/src/3rdparty/angle/src/compiler/InitializeParseContext.cpp b/src/3rdparty/angle/src/compiler/InitializeParseContext.cpp index 1f40cf5800..dfab027330 100644 --- a/src/3rdparty/angle/src/compiler/InitializeParseContext.cpp +++ b/src/3rdparty/angle/src/compiler/InitializeParseContext.cpp @@ -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(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(OS_GetTLSValue(GlobalParseContextIndex)); - if (lpParseContext) - delete lpParseContext; - - return true; -} - -TParseContextPointer& GetGlobalParseContext() -{ - // - // Minimal error checking for speed - // - - TThreadParseContext *lpParseContext = static_cast(OS_GetTLSValue(GlobalParseContextIndex)); - - return lpParseContext->lpGlobalParseContext; + assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); + return static_cast(OS_GetTLSValue(GlobalParseContextIndex)); } diff --git a/src/3rdparty/angle/src/compiler/InitializeParseContext.h b/src/3rdparty/angle/src/compiler/InitializeParseContext.h index aa53b735d4..bffbab87d0 100644 --- a/src/3rdparty/angle/src/compiler/InitializeParseContext.h +++ b/src/3rdparty/angle/src/compiler/InitializeParseContext.h @@ -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_ diff --git a/src/3rdparty/angle/src/compiler/Intermediate.cpp b/src/3rdparty/angle/src/compiler/Intermediate.cpp index edf279ef67..3b6622185d 100644 --- a/src/3rdparty/angle/src/compiler/Intermediate.cpp +++ b/src/3rdparty/angle/src/compiler/Intermediate.cpp @@ -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(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(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; } diff --git a/src/3rdparty/angle/src/compiler/OutputGLSL.cpp b/src/3rdparty/angle/src/compiler/OutputGLSL.cpp index 206f403408..10a451c0d7 100644 --- a/src/3rdparty/angle/src/compiler/OutputGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/OutputGLSL.cpp @@ -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); + } +} diff --git a/src/3rdparty/angle/src/compiler/OutputGLSL.h b/src/3rdparty/angle/src/compiler/OutputGLSL.h index 199b6f3e46..fa68ac8103 100644 --- a/src/3rdparty/angle/src/compiler/OutputGLSL.h +++ b/src/3rdparty/angle/src/compiler/OutputGLSL.h @@ -20,6 +20,7 @@ public: protected: virtual bool writeVariablePrecision(TPrecision); + virtual void visitSymbol(TIntermSymbol* node); }; #endif // CROSSCOMPILERGLSL_OUTPUTGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp index 1b9a10deaa..d677c75633 100644 --- a/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp +++ b/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp @@ -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()); +} diff --git a/src/3rdparty/angle/src/compiler/OutputGLSLBase.h b/src/3rdparty/angle/src/compiler/OutputGLSLBase.h index c9f72d5631..df4ad68c2c 100644 --- a/src/3rdparty/angle/src/compiler/OutputGLSLBase.h +++ b/src/3rdparty/angle/src/compiler/OutputGLSLBase.h @@ -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; diff --git a/src/3rdparty/angle/src/compiler/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/OutputHLSL.cpp index f6a984148b..79a373ebab 100644 --- a/src/3rdparty/angle/src/compiler/OutputHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/OutputHLSL.cpp @@ -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 ¶meter = 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(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(); } diff --git a/src/3rdparty/angle/src/compiler/OutputHLSL.h b/src/3rdparty/angle/src/compiler/OutputHLSL.h index 749a3461b3..cde4120718 100644 --- a/src/3rdparty/angle/src/compiler/OutputHLSL.h +++ b/src/3rdparty/angle/src/compiler/OutputHLSL.h @@ -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; diff --git a/src/3rdparty/angle/src/compiler/ParseHelper.cpp b/src/3rdparty/angle/src/compiler/ParseHelper.cpp index 441ff35e00..1f8538e6a4 100644 --- a/src/3rdparty/angle/src/compiler/ParseHelper.cpp +++ b/src/3rdparty/angle/src/compiler/ParseHelper.cpp @@ -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(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(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(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. // diff --git a/src/3rdparty/angle/src/compiler/ParseHelper.h b/src/3rdparty/angle/src/compiler/ParseHelper.h index 26a3ea1308..c2b3c3f7ec 100644 --- a/src/3rdparty/angle/src/compiler/ParseHelper.h +++ b/src/3rdparty/angle/src/compiler/ParseHelper.h @@ -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[], diff --git a/src/3rdparty/angle/src/compiler/PoolAlloc.cpp b/src/3rdparty/angle/src/compiler/PoolAlloc.cpp index 9ef4f59f5c..eb993567b3 100644 --- a/src/3rdparty/angle/src/compiler/PoolAlloc.cpp +++ b/src/3rdparty/angle/src/compiler/PoolAlloc.cpp @@ -17,55 +17,32 @@ OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX; -void InitializeGlobalPools() -{ - TThreadGlobalPools* globalPools= static_cast(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(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(OS_GetTLSValue(PoolIndex)); - - return *threadData->globalPoolAllocator; + assert(PoolIndex != OS_INVALID_TLS_INDEX); + return static_cast(OS_GetTLSValue(PoolIndex)); } void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator) { - TThreadGlobalPools* threadData = static_cast(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(::new char[numBytesToAlloc]); if (memory == 0) return 0; diff --git a/src/3rdparty/angle/src/compiler/PoolAlloc.h b/src/3rdparty/angle/src/compiler/PoolAlloc.h index a8a59c69ac..edd249c4d3 100644 --- a/src/3rdparty/angle/src/compiler/PoolAlloc.h +++ b/src/3rdparty/angle/src/compiler/PoolAlloc.h @@ -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& p) : allocator(p.allocator) { } diff --git a/src/3rdparty/angle/src/compiler/ShHandle.h b/src/3rdparty/angle/src/compiler/ShHandle.h index 28049305e0..873580a99c 100644 --- a/src/3rdparty/angle/src/compiler/ShHandle.h +++ b/src/3rdparty/angle/src/compiler/ShHandle.h @@ -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; diff --git a/src/3rdparty/angle/src/compiler/ShaderLang.cpp b/src/3rdparty/angle/src/compiler/ShaderLang.cpp index 92f39311c2..42cd5cc5c1 100644 --- a/src/3rdparty/angle/src/compiler/ShaderLang.cpp +++ b/src/3rdparty/angle/src/compiler/ShaderLang.cpp @@ -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(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(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(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(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(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; +} diff --git a/src/3rdparty/angle/src/compiler/SymbolTable.cpp b/src/3rdparty/angle/src/compiler/SymbolTable.cpp index 847c1e4085..a7ce21680f 100644 --- a/src/3rdparty/angle/src/compiler/SymbolTable.cpp +++ b/src/3rdparty/angle/src/compiler/SymbolTable.cpp @@ -17,48 +17,34 @@ #include #include - -#include "common/angleutils.h" +#include 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('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(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]; } diff --git a/src/3rdparty/angle/src/compiler/SymbolTable.h b/src/3rdparty/angle/src/compiler/SymbolTable.h index d27aa332b7..bebad4b92e 100644 --- a/src/3rdparty/angle/src/compiler/SymbolTable.h +++ b/src/3rdparty/angle/src/compiler/SymbolTable.h @@ -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 +#include "common/angleutils.h" #include "compiler/InfoSink.h" #include "compiler/intermediate.h" @@ -40,22 +41,26 @@ // 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; } virtual bool isVariable() const { return false; } 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; + virtual void dump(TInfoSink &infoSink) const = 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 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 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()]; - table.pop_back(); + { + 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(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(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(table.size()) - 1; } - std::vector 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 table; + typedef TMap PrecisionStackLevel; + std::vector precisionStack; }; #endif // _SYMBOL_TABLE_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/Types.h b/src/3rdparty/angle/src/compiler/Types.h index 854bb44c07..505fa8e3bf 100644 --- a/src/3rdparty/angle/src/compiler/Types.h +++ b/src/3rdparty/angle/src/compiler/Types.h @@ -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 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 TFieldList; +inline TFieldList* NewPoolTFieldList() +{ + void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList)); + return new(memory) TFieldList; } -typedef TMap TStructureMap; -typedef TMap::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::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; diff --git a/src/3rdparty/angle/src/compiler/ValidateLimitations.cpp b/src/3rdparty/angle/src/compiler/ValidateLimitations.cpp index a5562d09a4..736ceeaefc 100644 --- a/src/3rdparty/angle/src/compiler/ValidateLimitations.cpp +++ b/src/3rdparty/angle/src/compiler/ValidateLimitations.cpp @@ -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(symbol); diff --git a/src/3rdparty/angle/src/compiler/VariableInfo.cpp b/src/3rdparty/angle/src/compiler/VariableInfo.cpp index eb6bea9b0f..f3f7b1ef35 100644 --- a/src/3rdparty/angle/src/compiler/VariableInfo.cpp +++ b/src/3rdparty/angle/src/compiler/VariableInfo.cpp @@ -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; -} - diff --git a/src/3rdparty/angle/src/compiler/VariableInfo.h b/src/3rdparty/angle/src/compiler/VariableInfo.h index 4130a589f5..3c7f2a5f84 100644 --- a/src/3rdparty/angle/src/compiler/VariableInfo.h +++ b/src/3rdparty/angle/src/compiler/VariableInfo.h @@ -20,28 +20,30 @@ struct TVariableInfo { TPersistString mappedName; ShDataType type; int size; + TPrecision precision; + bool staticUse; }; typedef std::vector 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; }; diff --git a/src/3rdparty/angle/src/compiler/glslang.l b/src/3rdparty/angle/src/compiler/glslang.l index 140a9aeb2d..60663f9a6b 100644 --- a/src/3rdparty/angle/src/compiler/glslang.l +++ b/src/3rdparty/angle/src/compiler/glslang.l @@ -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); } -. | -\n ; -"*/" { 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(strtol(yytext, 0, 0)); return(INTCONSTANT); } -0{O}+ { yylval->lex.i = static_cast(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(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(atof_dot(yytext)); return(FLOATCONSTANT); } -{D}+"."{D}*({E})? { yylval->lex.f = static_cast(atof_dot(yytext)); return(FLOATCONSTANT); } -"."{D}+({E})? { yylval->lex.f = static_cast(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; } -{L}({L}|{D})* { - BEGIN(INITIAL); - yylval->lex.string = NewPoolTString(yytext); - return FIELD_SELECTION; -} -[ \t\v\f\r] {} - -[ \t\v\n\f\r] { } -<*><> { context->AfterEOF = true; yyterminate(); } -<*>. { context->warning(yylineno, "Unknown char", yytext, ""); return 0; } +[ \t\v\n\f\r] { } +<> { 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(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(); diff --git a/src/3rdparty/angle/src/compiler/glslang.y b/src/3rdparty/angle/src/compiler/glslang.y index 8dbcee32ef..c64f736f41 100644 --- a/src/3rdparty/angle/src/compiler/glslang.y +++ b/src/3rdparty/angle/src/compiler/glslang.y @@ -39,7 +39,6 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). #include "GLSLANG/ShaderLang.h" #define YYENABLE_NLS 0 -#define YYLTYPE_IS_TRIVIAL 1 #define YYLEX_PARAM context->scanner %} @@ -47,10 +46,16 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). %expect 1 /* One shift reduce conflict because of if | else */ %pure-parser %parse-param {TParseContext* context} +%locations + +%code requires { +#define YYLTYPE TSourceLoc +#define YYLTYPE_IS_DECLARED 1 +#define SH_MAX_TOKEN_LENGTH 256 // WebGL spec. +} %union { struct { - TSourceLoc line; union { TString *string; float f; @@ -60,7 +65,6 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). TSymbol* symbol; } lex; struct { - TSourceLoc line; TOperator op; union { TIntermNode* intermNode; @@ -74,23 +78,31 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). TQualifier qualifier; TFunction* function; TParameter param; - TTypeLine typeLine; - TTypeList* typeList; + TField* field; + TFieldList* fieldList; }; } interm; } %{ -extern int yylex(YYSTYPE* yylval_param, void* yyscanner); -extern void yyerror(TParseContext* context, const char* reason); +extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner); +extern void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason); -#define FRAG_VERT_ONLY(S, L) { \ - if (context->shaderType != SH_FRAGMENT_SHADER && \ - context->shaderType != SH_VERTEX_SHADER) { \ - context->error(L, " supported in vertex/fragment shaders only ", S); \ - context->recover(); \ - } \ -} +#define YYLLOC_DEFAULT(Current, Rhs, N) \ + do { \ + if (YYID(N)) { \ + (Current).first_file = YYRHSLOC(Rhs, 1).first_file; \ + (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \ + (Current).last_file = YYRHSLOC(Rhs, N).last_file; \ + (Current).last_line = YYRHSLOC(Rhs, N).last_line; \ + } \ + else { \ + (Current).first_file = YYRHSLOC(Rhs, 0).last_file; \ + (Current).first_line = YYRHSLOC(Rhs, 0).last_line; \ + (Current).last_file = YYRHSLOC(Rhs, 0).last_file; \ + (Current).last_line = YYRHSLOC(Rhs, 0).last_line; \ + } \ + } while (0) #define VERTEX_ONLY(S, L) { \ if (context->shaderType != SH_VERTEX_SHADER) { \ @@ -116,7 +128,6 @@ extern void yyerror(TParseContext* context, const char* reason); %token SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT %token IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT BOOLCONSTANT -%token FIELD_SELECTION %token LEFT_OP RIGHT_OP %token INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP %token AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN @@ -127,6 +138,7 @@ extern void yyerror(TParseContext* context, const char* reason); %token COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT %token LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION +%type identifier %type assignment_operator unary_operator %type variable_identifier primary_expression postfix_expression %type expression integer_expression assignment_expression @@ -154,8 +166,8 @@ extern void yyerror(TParseContext* context, const char* reason); %type type_qualifier fully_specified_type type_specifier %type type_specifier_no_prec type_specifier_nonarray %type struct_specifier -%type struct_declarator -%type struct_declarator_list struct_declaration struct_declaration_list +%type struct_declarator +%type struct_declarator_list struct_declaration struct_declaration_list %type function_header function_declarator function_identifier %type function_header_with_parameters function_call_header %type function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype @@ -164,13 +176,17 @@ extern void yyerror(TParseContext* context, const char* reason); %start translation_unit %% +identifier + : IDENTIFIER + | TYPE_NAME + variable_identifier : IDENTIFIER { // The symbol table search was done in the lexical phase const TSymbol* symbol = $1.symbol; const TVariable* variable; if (symbol == 0) { - context->error($1.line, "undeclared identifier", $1.string->c_str()); + context->error(@1, "undeclared identifier", $1.string->c_str()); context->recover(); TType type(EbtFloat, EbpUndefined); TVariable* fakeVariable = new TVariable($1.string, type); @@ -179,10 +195,17 @@ variable_identifier } else { // This identifier can only be a variable type symbol if (! symbol->isVariable()) { - context->error($1.line, "variable expected", $1.string->c_str()); + context->error(@1, "variable expected", $1.string->c_str()); context->recover(); } + variable = static_cast(symbol); + + if (context->symbolTable.findBuiltIn(variable->getName()) && + !variable->getExtension().empty() && + context->extensionErrorCheck(@1, variable->getExtension())) { + context->recover(); + } } // don't delete $1.string, it's used by error recovery, and the pool @@ -191,11 +214,12 @@ variable_identifier if (variable->getType().getQualifier() == EvqConst ) { ConstantUnion* constArray = variable->getConstPointer(); TType t(variable->getType()); - $$ = context->intermediate.addConstantUnion(constArray, t, $1.line); + $$ = context->intermediate.addConstantUnion(constArray, t, @1); } else $$ = context->intermediate.addSymbol(variable->getUniqueId(), - variable->getName(), - variable->getType(), $1.line); + variable->getName(), + variable->getType(), + @1); } ; @@ -204,27 +228,19 @@ primary_expression $$ = $1; } | INTCONSTANT { - // - // INT_TYPE is only 16-bit plus sign bit for vertex/fragment shaders, - // check for overflow for constants - // - if (abs($1.i) >= (1 << 16)) { - context->error($1.line, " integer constant overflow", ""); - context->recover(); - } ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setIConst($1.i); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $1.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @1); } | FLOATCONSTANT { ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setFConst($1.f); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1); } | BOOLCONSTANT { ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst($1.b); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $1.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @1); } | LEFT_PAREN expression RIGHT_PAREN { $$ = $2; @@ -236,103 +252,27 @@ postfix_expression $$ = $1; } | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET { - if (!$1->isArray() && !$1->isMatrix() && !$1->isVector()) { - if ($1->getAsSymbolNode()) - context->error($2.line, " left of '[' is not of type array, matrix, or vector ", $1->getAsSymbolNode()->getSymbol().c_str()); - else - context->error($2.line, " left of '[' is not of type array, matrix, or vector ", "expression"); - context->recover(); - } - if ($1->getType().getQualifier() == EvqConst && $3->getQualifier() == EvqConst) { - if ($1->isArray()) { // constant folding for arrays - $$ = context->addConstArrayNode($3->getAsConstantUnion()->getIConst(0), $1, $2.line); - } else if ($1->isVector()) { // constant folding for vectors - TVectorFields fields; - fields.num = 1; - fields.offsets[0] = $3->getAsConstantUnion()->getIConst(0); // need to do it this way because v.xy sends fields integer array - $$ = context->addConstVectorNode(fields, $1, $2.line); - } else if ($1->isMatrix()) { // constant folding for matrices - $$ = context->addConstMatrixNode($3->getAsConstantUnion()->getIConst(0), $1, $2.line); - } - } else { - if ($3->getQualifier() == EvqConst) { - if (($1->isVector() || $1->isMatrix()) && $1->getType().getNominalSize() <= $3->getAsConstantUnion()->getIConst(0) && !$1->isArray() ) { - std::stringstream extraInfoStream; - extraInfoStream << "field selection out of range '" << $3->getAsConstantUnion()->getIConst(0) << "'"; - std::string extraInfo = extraInfoStream.str(); - context->error($2.line, "", "[", extraInfo.c_str()); - context->recover(); - } else { - if ($1->isArray()) { - if ($1->getType().getArraySize() == 0) { - if ($1->getType().getMaxArraySize() <= $3->getAsConstantUnion()->getIConst(0)) { - if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getIConst(0), true, $2.line)) - context->recover(); - } else { - if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line)) - context->recover(); - } - } else if ( $3->getAsConstantUnion()->getIConst(0) >= $1->getType().getArraySize()) { - std::stringstream extraInfoStream; - extraInfoStream << "array index out of range '" << $3->getAsConstantUnion()->getIConst(0) << "'"; - std::string extraInfo = extraInfoStream.str(); - context->error($2.line, "", "[", extraInfo.c_str()); - context->recover(); - } - } - $$ = context->intermediate.addIndex(EOpIndexDirect, $1, $3, $2.line); - } - } else { - if ($1->isArray() && $1->getType().getArraySize() == 0) { - context->error($2.line, "", "[", "array must be redeclared with a size before being indexed with a variable"); - context->recover(); - } - - $$ = context->intermediate.addIndex(EOpIndexIndirect, $1, $3, $2.line); - } - } - if ($$ == 0) { - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setFConst(0.0f); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), $2.line); - } else if ($1->isArray()) { - if ($1->getType().getStruct()) - $$->setType(TType($1->getType().getStruct(), $1->getType().getTypeName())); - else - $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize(), $1->isMatrix())); - - if ($1->getType().getQualifier() == EvqConst) - $$->getTypePointer()->setQualifier(EvqConst); - } else if ($1->isMatrix() && $1->getType().getQualifier() == EvqConst) - $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, $1->getNominalSize())); - else if ($1->isMatrix()) - $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize())); - else if ($1->isVector() && $1->getType().getQualifier() == EvqConst) - $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst)); - else if ($1->isVector()) - $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary)); - else - $$->setType($1->getType()); + $$ = context->addIndexExpression($1, @2, $3); } | function_call { $$ = $1; } - | postfix_expression DOT FIELD_SELECTION { + | postfix_expression DOT identifier { if ($1->isArray()) { - context->error($3.line, "cannot apply dot operator to an array", "."); + context->error(@3, "cannot apply dot operator to an array", "."); context->recover(); } if ($1->isVector()) { TVectorFields fields; - if (! context->parseVectorFields(*$3.string, $1->getNominalSize(), fields, $3.line)) { + if (! context->parseVectorFields(*$3.string, $1->getNominalSize(), fields, @3)) { fields.num = 1; fields.offsets[0] = 0; context->recover(); } if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields - $$ = context->addConstVectorNode(fields, $1, $3.line); + $$ = context->addConstVectorNode(fields, $1, @3); if ($$ == 0) { context->recover(); $$ = $1; @@ -341,13 +281,13 @@ postfix_expression $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, (int) (*$3.string).size())); } else { TString vectorString = *$3.string; - TIntermTyped* index = context->intermediate.addSwizzle(fields, $3.line); - $$ = context->intermediate.addIndex(EOpVectorSwizzle, $1, index, $2.line); + TIntermTyped* index = context->intermediate.addSwizzle(fields, @3); + $$ = context->intermediate.addIndex(EOpVectorSwizzle, $1, index, @2); $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, (int) vectorString.size())); } } else if ($1->isMatrix()) { TMatrixFields fields; - if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, $3.line)) { + if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, @3)) { fields.wholeRow = false; fields.wholeCol = false; fields.row = 0; @@ -356,84 +296,78 @@ postfix_expression } if (fields.wholeRow || fields.wholeCol) { - context->error($2.line, " non-scalar fields not implemented yet", "."); + context->error(@2, " non-scalar fields not implemented yet", "."); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setIConst(0); - TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line); - $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @3); + $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, @2); $$->setType(TType($1->getBasicType(), $1->getPrecision(),EvqTemporary, $1->getNominalSize())); } else { ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setIConst(fields.col * $1->getNominalSize() + fields.row); - TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line); - $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @3); + $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, @2); $$->setType(TType($1->getBasicType(), $1->getPrecision())); } } else if ($1->getBasicType() == EbtStruct) { bool fieldFound = false; - const TTypeList* fields = $1->getType().getStruct(); - if (fields == 0) { - context->error($2.line, "structure has no fields", "Internal Error"); - context->recover(); - $$ = $1; - } else { - unsigned int i; - for (i = 0; i < fields->size(); ++i) { - if ((*fields)[i].type->getFieldName() == *$3.string) { - fieldFound = true; - break; - } - } - if (fieldFound) { - if ($1->getType().getQualifier() == EvqConst) { - $$ = context->addConstStruct(*$3.string, $1, $2.line); - if ($$ == 0) { - context->recover(); - $$ = $1; - } - else { - $$->setType(*(*fields)[i].type); - // change the qualifier of the return type, not of the structure field - // as the structure definition is shared between various structures. - $$->getTypePointer()->setQualifier(EvqConst); - } - } else { - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setIConst(i); - TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *(*fields)[i].type, $3.line); - $$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, $2.line); - $$->setType(*(*fields)[i].type); - } - } else { - context->error($2.line, " no such field in structure", $3.string->c_str()); - context->recover(); - $$ = $1; + const TFieldList& fields = $1->getType().getStruct()->fields(); + unsigned int i; + for (i = 0; i < fields.size(); ++i) { + if (fields[i]->name() == *$3.string) { + fieldFound = true; + break; } } + if (fieldFound) { + if ($1->getType().getQualifier() == EvqConst) { + $$ = context->addConstStruct(*$3.string, $1, @2); + if ($$ == 0) { + context->recover(); + $$ = $1; + } + else { + $$->setType(*fields[i]->type()); + // change the qualifier of the return type, not of the structure field + // as the structure definition is shared between various structures. + $$->getTypePointer()->setQualifier(EvqConst); + } + } else { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setIConst(i); + TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *fields[i]->type(), @3); + $$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, @2); + $$->setType(*fields[i]->type()); + } + } else { + context->error(@2, " no such field in structure", $3.string->c_str()); + context->recover(); + $$ = $1; + } } else { - context->error($2.line, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str()); + context->error(@2, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str()); context->recover(); $$ = $1; } // don't delete $3.string, it's from the pool } | postfix_expression INC_OP { - if (context->lValueErrorCheck($2.line, "++", $1)) + if (context->lValueErrorCheck(@2, "++", $1)) context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, $2.line, context->symbolTable); + $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, @2, context->symbolTable); if ($$ == 0) { - context->unaryOpError($2.line, "++", $1->getCompleteString()); + context->unaryOpError(@2, "++", $1->getCompleteString()); context->recover(); $$ = $1; } } | postfix_expression DEC_OP { - if (context->lValueErrorCheck($2.line, "--", $1)) + if (context->lValueErrorCheck(@2, "--", $1)) context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, $2.line, context->symbolTable); + $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, @2, context->symbolTable); if ($$ == 0) { - context->unaryOpError($2.line, "--", $1->getCompleteString()); + context->unaryOpError(@2, "--", $1->getCompleteString()); context->recover(); $$ = $1; } @@ -461,18 +395,18 @@ function_call // Their parameters will be verified algorithmically. // TType type(EbtVoid, EbpUndefined); // use this to get the type back - if (context->constructorErrorCheck($1.line, $1.intermNode, *fnCall, op, &type)) { + if (context->constructorErrorCheck(@1, $1.intermNode, *fnCall, op, &type)) { $$ = 0; } else { // // It's a constructor, of type 'type'. // - $$ = context->addConstructor($1.intermNode, &type, op, fnCall, $1.line); + $$ = context->addConstructor($1.intermNode, &type, op, fnCall, @1); } if ($$ == 0) { context->recover(); - $$ = context->intermediate.setAggregateOperator(0, op, $1.line); + $$ = context->intermediate.setAggregateOperator(0, op, @1); } $$->setType(type); } else { @@ -481,13 +415,13 @@ function_call // const TFunction* fnCandidate; bool builtIn; - fnCandidate = context->findFunction($1.line, fnCall, &builtIn); + fnCandidate = context->findFunction(@1, fnCall, &builtIn); if (fnCandidate) { // // A declared function. // if (builtIn && !fnCandidate->getExtension().empty() && - context->extensionErrorCheck($1.line, fnCandidate->getExtension())) { + context->extensionErrorCheck(@1, fnCandidate->getExtension())) { context->recover(); } op = fnCandidate->getBuiltInOp(); @@ -499,7 +433,7 @@ function_call // // Treat it like a built-in unary operator. // - $$ = context->intermediate.addUnaryMath(op, $1.intermNode, 0, context->symbolTable); + $$ = context->intermediate.addUnaryMath(op, $1.intermNode, @1, context->symbolTable); if ($$ == 0) { std::stringstream extraInfoStream; extraInfoStream << "built in unary operator function. Type: " << static_cast($1.intermNode)->getCompleteString(); @@ -508,12 +442,12 @@ function_call YYERROR; } } else { - $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, $1.line); + $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1); } } else { // This is a real function call - $$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, $1.line); + $$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1); $$->setType(fnCandidate->getReturnType()); // this is how we know whether the given function is a builtIn function or a user defined function @@ -540,7 +474,7 @@ function_call // Put on a dummy node for error recovery ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setFConst(0.0f); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1); context->recover(); } } @@ -553,7 +487,7 @@ function_call_or_method $$ = $1; } | postfix_expression DOT function_call_generic { - context->error($3.line, "methods are not supported", ""); + context->error(@3, "methods are not supported", ""); context->recover(); $$ = $3; } @@ -562,11 +496,9 @@ function_call_or_method function_call_generic : function_call_header_with_parameters RIGHT_PAREN { $$ = $1; - $$.line = $2.line; } | function_call_header_no_parameters RIGHT_PAREN { $$ = $1; - $$.line = $2.line; } ; @@ -592,7 +524,7 @@ function_call_header_with_parameters TParameter param = { 0, new TType($3->getType()) }; $1.function->addParameter(param); $$.function = $1.function; - $$.intermNode = context->intermediate.growAggregate($1.intermNode, $3, $2.line); + $$.intermNode = context->intermediate.growAggregate($1.intermNode, $3, @2); } ; @@ -617,39 +549,39 @@ function_identifier case EbtFloat: if ($1.matrix) { switch($1.size) { - case 2: op = EOpConstructMat2; break; - case 3: op = EOpConstructMat3; break; - case 4: op = EOpConstructMat4; break; + case 2: op = EOpConstructMat2; break; + case 3: op = EOpConstructMat3; break; + case 4: op = EOpConstructMat4; break; } } else { switch($1.size) { - case 1: op = EOpConstructFloat; break; - case 2: op = EOpConstructVec2; break; - case 3: op = EOpConstructVec3; break; - case 4: op = EOpConstructVec4; break; + case 1: op = EOpConstructFloat; break; + case 2: op = EOpConstructVec2; break; + case 3: op = EOpConstructVec3; break; + case 4: op = EOpConstructVec4; break; } } break; case EbtInt: switch($1.size) { - case 1: op = EOpConstructInt; break; - case 2: FRAG_VERT_ONLY("ivec2", $1.line); op = EOpConstructIVec2; break; - case 3: FRAG_VERT_ONLY("ivec3", $1.line); op = EOpConstructIVec3; break; - case 4: FRAG_VERT_ONLY("ivec4", $1.line); op = EOpConstructIVec4; break; + case 1: op = EOpConstructInt; break; + case 2: op = EOpConstructIVec2; break; + case 3: op = EOpConstructIVec3; break; + case 4: op = EOpConstructIVec4; break; } break; case EbtBool: switch($1.size) { - case 1: op = EOpConstructBool; break; - case 2: FRAG_VERT_ONLY("bvec2", $1.line); op = EOpConstructBVec2; break; - case 3: FRAG_VERT_ONLY("bvec3", $1.line); op = EOpConstructBVec3; break; - case 4: FRAG_VERT_ONLY("bvec4", $1.line); op = EOpConstructBVec4; break; + case 1: op = EOpConstructBool; break; + case 2: op = EOpConstructBVec2; break; + case 3: op = EOpConstructBVec3; break; + case 4: op = EOpConstructBVec4; break; } break; default: break; } if (op == EOpNull) { - context->error($1.line, "cannot construct this type", getBasicString($1.type)); + context->error(@1, "cannot construct this type", getBasicString($1.type)); context->recover(); $1.type = EbtFloat; op = EOpConstructFloat; @@ -661,14 +593,7 @@ function_identifier $$ = function; } | IDENTIFIER { - if (context->reservedErrorCheck($1.line, *$1.string)) - context->recover(); - TType type(EbtVoid, EbpUndefined); - TFunction *function = new TFunction($1.string, type); - $$ = function; - } - | FIELD_SELECTION { - if (context->reservedErrorCheck($1.line, *$1.string)) + if (context->reservedErrorCheck(@1, *$1.string)) context->recover(); TType type(EbtVoid, EbpUndefined); TFunction *function = new TFunction($1.string, type); @@ -681,28 +606,28 @@ unary_expression $$ = $1; } | INC_OP unary_expression { - if (context->lValueErrorCheck($1.line, "++", $2)) + if (context->lValueErrorCheck(@1, "++", $2)) context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, $1.line, context->symbolTable); + $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, @1, context->symbolTable); if ($$ == 0) { - context->unaryOpError($1.line, "++", $2->getCompleteString()); + context->unaryOpError(@1, "++", $2->getCompleteString()); context->recover(); $$ = $2; } } | DEC_OP unary_expression { - if (context->lValueErrorCheck($1.line, "--", $2)) + if (context->lValueErrorCheck(@1, "--", $2)) context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, $1.line, context->symbolTable); + $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, @1, context->symbolTable); if ($$ == 0) { - context->unaryOpError($1.line, "--", $2->getCompleteString()); + context->unaryOpError(@1, "--", $2->getCompleteString()); context->recover(); $$ = $2; } } | unary_operator unary_expression { if ($1.op != EOpNull) { - $$ = context->intermediate.addUnaryMath($1.op, $2, $1.line, context->symbolTable); + $$ = context->intermediate.addUnaryMath($1.op, $2, @1, context->symbolTable); if ($$ == 0) { const char* errorOp = ""; switch($1.op) { @@ -710,7 +635,7 @@ unary_expression case EOpLogicalNot: errorOp = "!"; break; default: break; } - context->unaryOpError($1.line, errorOp, $2->getCompleteString()); + context->unaryOpError(@1, errorOp, $2->getCompleteString()); context->recover(); $$ = $2; } @@ -721,28 +646,26 @@ unary_expression // Grammar Note: No traditional style type casts. unary_operator - : PLUS { $$.line = $1.line; $$.op = EOpNull; } - | DASH { $$.line = $1.line; $$.op = EOpNegative; } - | BANG { $$.line = $1.line; $$.op = EOpLogicalNot; } + : PLUS { $$.op = EOpNull; } + | DASH { $$.op = EOpNegative; } + | BANG { $$.op = EOpLogicalNot; } ; // Grammar Note: No '*' or '&' unary ops. Pointers are not supported. multiplicative_expression : unary_expression { $$ = $1; } | multiplicative_expression STAR unary_expression { - FRAG_VERT_ONLY("*", $2.line); - $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "*", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "*", $1->getCompleteString(), $3->getCompleteString()); context->recover(); $$ = $1; } } | multiplicative_expression SLASH unary_expression { - FRAG_VERT_ONLY("/", $2.line); - $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "/", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "/", $1->getCompleteString(), $3->getCompleteString()); context->recover(); $$ = $1; } @@ -752,17 +675,17 @@ multiplicative_expression additive_expression : multiplicative_expression { $$ = $1; } | additive_expression PLUS multiplicative_expression { - $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "+", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "+", $1->getCompleteString(), $3->getCompleteString()); context->recover(); $$ = $1; } } | additive_expression DASH multiplicative_expression { - $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "-", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "-", $1->getCompleteString(), $3->getCompleteString()); context->recover(); $$ = $1; } @@ -776,43 +699,43 @@ shift_expression relational_expression : shift_expression { $$ = $1; } | relational_expression LEFT_ANGLE shift_expression { - $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "<", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "<", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } | relational_expression RIGHT_ANGLE shift_expression { - $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, ">", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, ">", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } | relational_expression LE_OP shift_expression { - $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "<=", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "<=", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } | relational_expression GE_OP shift_expression { - $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, ">=", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, ">=", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } ; @@ -820,23 +743,23 @@ relational_expression equality_expression : relational_expression { $$ = $1; } | equality_expression EQ_OP relational_expression { - $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "==", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "==", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } | equality_expression NE_OP relational_expression { - $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "!=", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "!=", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } ; @@ -856,13 +779,13 @@ inclusive_or_expression logical_and_expression : inclusive_or_expression { $$ = $1; } | logical_and_expression AND_OP inclusive_or_expression { - $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "&&", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "&&", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } ; @@ -870,13 +793,13 @@ logical_and_expression logical_xor_expression : logical_and_expression { $$ = $1; } | logical_xor_expression XOR_OP logical_and_expression { - $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "^^", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "^^", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } ; @@ -884,13 +807,13 @@ logical_xor_expression logical_or_expression : logical_xor_expression { $$ = $1; } | logical_or_expression OR_OP logical_xor_expression { - $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, $2.line, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, @2, context->symbolTable); if ($$ == 0) { - context->binaryOpError($2.line, "||", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, "||", $1->getCompleteString(), $3->getCompleteString()); context->recover(); ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); } } ; @@ -898,15 +821,15 @@ logical_or_expression conditional_expression : logical_or_expression { $$ = $1; } | logical_or_expression QUESTION expression COLON assignment_expression { - if (context->boolErrorCheck($2.line, $1)) + if (context->boolErrorCheck(@2, $1)) context->recover(); - $$ = context->intermediate.addSelection($1, $3, $5, $2.line); + $$ = context->intermediate.addSelection($1, $3, $5, @2); if ($3->getType() != $5->getType()) $$ = 0; if ($$ == 0) { - context->binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString()); + context->binaryOpError(@2, ":", $3->getCompleteString(), $5->getCompleteString()); context->recover(); $$ = $5; } @@ -916,11 +839,11 @@ conditional_expression assignment_expression : conditional_expression { $$ = $1; } | unary_expression assignment_operator assignment_expression { - if (context->lValueErrorCheck($2.line, "assign", $1)) + if (context->lValueErrorCheck(@2, "assign", $1)) context->recover(); - $$ = context->intermediate.addAssign($2.op, $1, $3, $2.line); + $$ = context->intermediate.addAssign($2.op, $1, $3, @2); if ($$ == 0) { - context->assignError($2.line, "assign", $1->getCompleteString(), $3->getCompleteString()); + context->assignError(@2, "assign", $1->getCompleteString(), $3->getCompleteString()); context->recover(); $$ = $1; } @@ -928,11 +851,11 @@ assignment_expression ; assignment_operator - : EQUAL { $$.line = $1.line; $$.op = EOpAssign; } - | MUL_ASSIGN { FRAG_VERT_ONLY("*=", $1.line); $$.line = $1.line; $$.op = EOpMulAssign; } - | DIV_ASSIGN { FRAG_VERT_ONLY("/=", $1.line); $$.line = $1.line; $$.op = EOpDivAssign; } - | ADD_ASSIGN { $$.line = $1.line; $$.op = EOpAddAssign; } - | SUB_ASSIGN { $$.line = $1.line; $$.op = EOpSubAssign; } + : EQUAL { $$.op = EOpAssign; } + | MUL_ASSIGN { $$.op = EOpMulAssign; } + | DIV_ASSIGN { $$.op = EOpDivAssign; } + | ADD_ASSIGN { $$.op = EOpAddAssign; } + | SUB_ASSIGN { $$.op = EOpSubAssign; } ; expression @@ -940,9 +863,9 @@ expression $$ = $1; } | expression COMMA assignment_expression { - $$ = context->intermediate.addComma($1, $3, $2.line); + $$ = context->intermediate.addComma($1, $3, @2); if ($$ == 0) { - context->binaryOpError($2.line, ",", $1->getCompleteString(), $3->getCompleteString()); + context->binaryOpError(@2, ",", $1->getCompleteString(), $3->getCompleteString()); context->recover(); $$ = $3; } @@ -970,13 +893,13 @@ declaration const TParameter ¶m = function.getParam(i); if (param.name != 0) { - TVariable *variable = new TVariable(param.name, *param.type); + TVariable variable(param.name, *param.type); - prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), $1.line), $1.line); + prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), @1), @1); } else { - prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line); + prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, @1), @1); } } @@ -992,11 +915,11 @@ declaration } | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON { if (($2 == EbpHigh) && (context->shaderType == SH_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) { - context->error($1.line, "precision is not supported in fragment shader", "highp"); + context->error(@1, "precision is not supported in fragment shader", "highp"); context->recover(); } if (!context->symbolTable.setDefaultPrecision( $3, $2 )) { - context->error($1.line, "illegal type argument for default precision qualifier", getBasicString($3.type)); + context->error(@1, "illegal type argument for default precision qualifier", getBasicString($3.type)); context->recover(); } $$ = 0; @@ -1016,24 +939,41 @@ function_prototype TFunction* prevDec = static_cast(context->symbolTable.find($1->getMangledName())); if (prevDec) { if (prevDec->getReturnType() != $1->getReturnType()) { - context->error($2.line, "overloaded functions must have the same return type", $1->getReturnType().getBasicString()); + context->error(@2, "overloaded functions must have the same return type", $1->getReturnType().getBasicString()); context->recover(); } for (size_t i = 0; i < prevDec->getParamCount(); ++i) { if (prevDec->getParam(i).type->getQualifier() != $1->getParam(i).type->getQualifier()) { - context->error($2.line, "overloaded functions must have the same parameter qualifiers", $1->getParam(i).type->getQualifierString()); + context->error(@2, "overloaded functions must have the same parameter qualifiers", $1->getParam(i).type->getQualifierString()); context->recover(); } } } + // + // Check for previously declared variables using the same name. + // + TSymbol *prevSym = context->symbolTable.find($1->getName()); + if (prevSym) + { + if (!prevSym->isFunction()) + { + context->error(@2, "redefinition", $1->getName().c_str(), "function"); + context->recover(); + } + } + else + { + // Insert the unmangled name to detect potential future redefinition as a variable. + context->symbolTable.getOuterLevel()->insert($1->getName(), *$1); + } + // // If this is a redeclaration, it could also be a definition, // in which case, we want to use the variable names from this one, and not the one that's // being redeclared. So, pass back up this declaration, not the one in the symbol table. // $$.function = $1; - $$.line = $2.line; // We're at the inner scope level of the function's arguments and body statement. // Add the function prototype to the surrounding scope instead. @@ -1069,7 +1009,7 @@ function_header_with_parameters // // This parameter > first is void // - context->error($2.line, "cannot be an argument type except for '(void)'", "void"); + context->error(@2, "cannot be an argument type except for '(void)'", "void"); context->recover(); delete $3.param.type; } else { @@ -1083,11 +1023,11 @@ function_header_with_parameters function_header : fully_specified_type IDENTIFIER LEFT_PAREN { if ($1.qualifier != EvqGlobal && $1.qualifier != EvqTemporary) { - context->error($2.line, "no qualifiers allowed for function return", getQualifierString($1.qualifier)); + context->error(@2, "no qualifiers allowed for function return", getQualifierString($1.qualifier)); context->recover(); } // make sure a sampler is not involved as well... - if (context->structQualifierErrorCheck($2.line, $1)) + if (context->structQualifierErrorCheck(@2, $1)) context->recover(); // Add the function as a prototype after parsing it (we do not support recursion) @@ -1102,33 +1042,31 @@ function_header parameter_declarator // Type + name - : type_specifier IDENTIFIER { + : type_specifier identifier { if ($1.type == EbtVoid) { - context->error($2.line, "illegal use of type 'void'", $2.string->c_str()); + context->error(@2, "illegal use of type 'void'", $2.string->c_str()); context->recover(); } - if (context->reservedErrorCheck($2.line, *$2.string)) + if (context->reservedErrorCheck(@2, *$2.string)) context->recover(); TParameter param = {$2.string, new TType($1)}; - $$.line = $2.line; $$.param = param; } - | type_specifier IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET { + | type_specifier identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { // Check that we can make an array out of this type - if (context->arrayTypeErrorCheck($3.line, $1)) + if (context->arrayTypeErrorCheck(@3, $1)) context->recover(); - if (context->reservedErrorCheck($2.line, *$2.string)) + if (context->reservedErrorCheck(@2, *$2.string)) context->recover(); int size; - if (context->arraySizeErrorCheck($3.line, $4, size)) + if (context->arraySizeErrorCheck(@3, $4, size)) context->recover(); $1.setArray(true, size); TType* type = new TType($1); TParameter param = { $2.string, type }; - $$.line = $2.line; $$.param = param; } ; @@ -1144,14 +1082,14 @@ parameter_declaration // : type_qualifier parameter_qualifier parameter_declarator { $$ = $3; - if (context->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type)) + if (context->paramErrorCheck(@3, $1.qualifier, $2, $$.param.type)) context->recover(); } | parameter_qualifier parameter_declarator { $$ = $2; - if (context->parameterSamplerErrorCheck($2.line, $1, *$2.param.type)) + if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type)) context->recover(); - if (context->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type)) + if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type)) context->recover(); } // @@ -1159,14 +1097,14 @@ parameter_declaration // | type_qualifier parameter_qualifier parameter_type_specifier { $$ = $3; - if (context->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type)) + if (context->paramErrorCheck(@3, $1.qualifier, $2, $$.param.type)) context->recover(); } | parameter_qualifier parameter_type_specifier { $$ = $2; - if (context->parameterSamplerErrorCheck($2.line, $1, *$2.param.type)) + if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type)) context->recover(); - if (context->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type)) + if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type)) context->recover(); } ; @@ -1197,83 +1135,83 @@ init_declarator_list : single_declaration { $$ = $1; } - | init_declarator_list COMMA IDENTIFIER { + | init_declarator_list COMMA identifier { if ($1.type.type == EbtInvariant && !$3.symbol) { - context->error($3.line, "undeclared identifier declared as invariant", $3.string->c_str()); + context->error(@3, "undeclared identifier declared as invariant", $3.string->c_str()); context->recover(); } - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$3.string, TType($1.type), $3.line); - $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, symbol, $3.line); + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$3.string, TType($1.type), @3); + $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, symbol, @3); - if (context->structQualifierErrorCheck($3.line, $$.type)) + if (context->structQualifierErrorCheck(@3, $$.type)) context->recover(); - if (context->nonInitConstErrorCheck($3.line, *$3.string, $$.type, false)) + if (context->nonInitConstErrorCheck(@3, *$3.string, $$.type, false)) context->recover(); TVariable* variable = 0; - if (context->nonInitErrorCheck($3.line, *$3.string, $$.type, variable)) + if (context->nonInitErrorCheck(@3, *$3.string, $$.type, variable)) context->recover(); if (symbol && variable) symbol->setId(variable->getUniqueId()); } - | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET { - if (context->structQualifierErrorCheck($3.line, $1.type)) + | init_declarator_list COMMA identifier LEFT_BRACKET RIGHT_BRACKET { + if (context->structQualifierErrorCheck(@3, $1.type)) context->recover(); - if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type, true)) + if (context->nonInitConstErrorCheck(@3, *$3.string, $1.type, true)) context->recover(); $$ = $1; - if (context->arrayTypeErrorCheck($4.line, $1.type) || context->arrayQualifierErrorCheck($4.line, $1.type)) + if (context->arrayTypeErrorCheck(@4, $1.type) || context->arrayQualifierErrorCheck(@4, $1.type)) context->recover(); else { $1.type.setArray(true); TVariable* variable; - if (context->arrayErrorCheck($4.line, *$3.string, $1.type, variable)) + if (context->arrayErrorCheck(@4, *$3.string, $1.type, variable)) context->recover(); } } - | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET { - if (context->structQualifierErrorCheck($3.line, $1.type)) + | init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { + if (context->structQualifierErrorCheck(@3, $1.type)) context->recover(); - if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type, true)) + if (context->nonInitConstErrorCheck(@3, *$3.string, $1.type, true)) context->recover(); $$ = $1; - if (context->arrayTypeErrorCheck($4.line, $1.type) || context->arrayQualifierErrorCheck($4.line, $1.type)) + if (context->arrayTypeErrorCheck(@4, $1.type) || context->arrayQualifierErrorCheck(@4, $1.type)) context->recover(); else { int size; - if (context->arraySizeErrorCheck($4.line, $5, size)) + if (context->arraySizeErrorCheck(@4, $5, size)) context->recover(); $1.type.setArray(true, size); TVariable* variable = 0; - if (context->arrayErrorCheck($4.line, *$3.string, $1.type, variable)) + if (context->arrayErrorCheck(@4, *$3.string, $1.type, variable)) context->recover(); TType type = TType($1.type); type.setArraySize(size); - $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *$3.string, type, $3.line), $3.line); + $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *$3.string, type, @3), @3); } } - | init_declarator_list COMMA IDENTIFIER EQUAL initializer { - if (context->structQualifierErrorCheck($3.line, $1.type)) + | init_declarator_list COMMA identifier EQUAL initializer { + if (context->structQualifierErrorCheck(@3, $1.type)) context->recover(); $$ = $1; TIntermNode* intermNode; - if (!context->executeInitializer($3.line, *$3.string, $1.type, $5, intermNode)) { + if (!context->executeInitializer(@3, *$3.string, $1.type, $5, intermNode)) { // // build the intermediate representation // if (intermNode) - $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, intermNode, $4.line); + $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, intermNode, @4); else $$.intermAggregate = $1.intermAggregate; } else { @@ -1286,79 +1224,79 @@ init_declarator_list single_declaration : fully_specified_type { $$.type = $1; - $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), $1.line), $1.line); + $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), @1), @1); } - | fully_specified_type IDENTIFIER { - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line); + | fully_specified_type identifier { + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), @2); + $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); - if (context->structQualifierErrorCheck($2.line, $$.type)) + if (context->structQualifierErrorCheck(@2, $$.type)) context->recover(); - if (context->nonInitConstErrorCheck($2.line, *$2.string, $$.type, false)) + if (context->nonInitConstErrorCheck(@2, *$2.string, $$.type, false)) context->recover(); $$.type = $1; TVariable* variable = 0; - if (context->nonInitErrorCheck($2.line, *$2.string, $$.type, variable)) + if (context->nonInitErrorCheck(@2, *$2.string, $$.type, variable)) context->recover(); if (variable && symbol) symbol->setId(variable->getUniqueId()); } - | fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET { - context->error($2.line, "unsized array declarations not supported", $2.string->c_str()); + | fully_specified_type identifier LEFT_BRACKET RIGHT_BRACKET { + context->error(@2, "unsized array declarations not supported", $2.string->c_str()); context->recover(); - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line); + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), @2); + $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); $$.type = $1; } - | fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET { + | fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { TType type = TType($1); int size; - if (context->arraySizeErrorCheck($2.line, $4, size)) + if (context->arraySizeErrorCheck(@2, $4, size)) context->recover(); type.setArraySize(size); - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, type, $2.line); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line); + TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, type, @2); + $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); - if (context->structQualifierErrorCheck($2.line, $1)) + if (context->structQualifierErrorCheck(@2, $1)) context->recover(); - if (context->nonInitConstErrorCheck($2.line, *$2.string, $1, true)) + if (context->nonInitConstErrorCheck(@2, *$2.string, $1, true)) context->recover(); $$.type = $1; - if (context->arrayTypeErrorCheck($3.line, $1) || context->arrayQualifierErrorCheck($3.line, $1)) + if (context->arrayTypeErrorCheck(@3, $1) || context->arrayQualifierErrorCheck(@3, $1)) context->recover(); else { int size; - if (context->arraySizeErrorCheck($3.line, $4, size)) + if (context->arraySizeErrorCheck(@3, $4, size)) context->recover(); $1.setArray(true, size); TVariable* variable = 0; - if (context->arrayErrorCheck($3.line, *$2.string, $1, variable)) + if (context->arrayErrorCheck(@3, *$2.string, $1, variable)) context->recover(); if (variable && symbol) symbol->setId(variable->getUniqueId()); } } - | fully_specified_type IDENTIFIER EQUAL initializer { - if (context->structQualifierErrorCheck($2.line, $1)) + | fully_specified_type identifier EQUAL initializer { + if (context->structQualifierErrorCheck(@2, $1)) context->recover(); $$.type = $1; TIntermNode* intermNode; - if (!context->executeInitializer($2.line, *$2.string, $1, $4, intermNode)) { + if (!context->executeInitializer(@2, *$2.string, $1, $4, intermNode)) { // // Build intermediate representation // if(intermNode) - $$.intermAggregate = context->intermediate.makeAggregate(intermNode, $3.line); + $$.intermAggregate = context->intermediate.makeAggregate(intermNode, @3); else $$.intermAggregate = 0; } else { @@ -1367,118 +1305,50 @@ single_declaration } } | INVARIANT IDENTIFIER { - VERTEX_ONLY("invariant declaration", $1.line); - if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "invariant varying")) + VERTEX_ONLY("invariant declaration", @1); + if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying")) context->recover(); - $$.type.setBasic(EbtInvariant, EvqInvariantVaryingOut, $2.line); + $$.type.setBasic(EbtInvariant, EvqInvariantVaryingOut, @2); if (!$2.symbol) { - context->error($2.line, "undeclared identifier declared as invariant", $2.string->c_str()); + context->error(@2, "undeclared identifier declared as invariant", $2.string->c_str()); context->recover(); $$.intermAggregate = 0; } else { - TIntermSymbol *symbol = context->intermediate.addSymbol(0, *$2.string, TType($$.type), $2.line); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line); + TIntermSymbol *symbol = context->intermediate.addSymbol(0, *$2.string, TType($$.type), @2); + $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); } } - -// -// Place holder for the pack/unpack languages. -// -// | buffer_specifier { -// $$.intermAggregate = 0; -// } ; -// Grammar Note: No 'enum', or 'typedef'. - -// -// Place holder for the pack/unpack languages. -// -//%type buffer_declaration -//%type buffer_specifier input_or_output buffer_declaration_list -//buffer_specifier -// : input_or_output LEFT_BRACE buffer_declaration_list RIGHT_BRACE { -// } -// ; -// -//input_or_output -// : INPUT { -// if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "input")) -// context->recover(); -// UNPACK_ONLY("input", $1.line); -// $$.qualifier = EvqInput; -// } -// | OUTPUT { -// if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "output")) -// context->recover(); -// PACK_ONLY("output", $1.line); -// $$.qualifier = EvqOutput; -// } -// ; - -// -// Place holder for the pack/unpack languages. -// -//buffer_declaration_list -// : buffer_declaration { -// } -// | buffer_declaration_list buffer_declaration { -// } -// ; - -// -// Input/output semantics: -// float must be 16 or 32 bits -// float alignment restrictions? -// check for only one input and only one output -// sum of bitfields has to be multiple of 32 -// - -// -// Place holder for the pack/unpack languages. -// -//buffer_declaration -// : type_specifier IDENTIFIER COLON constant_expression SEMICOLON { -// if (context->reservedErrorCheck($2.line, *$2.string, context)) -// context->recover(); -// $$.variable = new TVariable($2.string, $1); -// if (! context->symbolTable.insert(*$$.variable)) { -// context->error($2.line, "redefinition", $$.variable->getName().c_str()); -// context->recover(); -// // don't have to delete $$.variable, the pool pop will take care of it -// } -// } -// ; - fully_specified_type : type_specifier { $$ = $1; if ($1.array) { - context->error($1.line, "not supported", "first-class array"); + context->error(@1, "not supported", "first-class array"); context->recover(); $1.setArray(false); } } | type_qualifier type_specifier { if ($2.array) { - context->error($2.line, "not supported", "first-class array"); + context->error(@2, "not supported", "first-class array"); context->recover(); $2.setArray(false); } if ($1.qualifier == EvqAttribute && ($2.type == EbtBool || $2.type == EbtInt)) { - context->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier)); + context->error(@2, "cannot be bool or int", getQualifierString($1.qualifier)); context->recover(); } if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) && ($2.type == EbtBool || $2.type == EbtInt)) { - context->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier)); + context->error(@2, "cannot be bool or int", getQualifierString($1.qualifier)); context->recover(); } $$ = $2; @@ -1488,34 +1358,34 @@ fully_specified_type type_qualifier : CONST_QUAL { - $$.setBasic(EbtVoid, EvqConst, $1.line); + $$.setBasic(EbtVoid, EvqConst, @1); } | ATTRIBUTE { - VERTEX_ONLY("attribute", $1.line); - if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "attribute")) + VERTEX_ONLY("attribute", @1); + if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "attribute")) context->recover(); - $$.setBasic(EbtVoid, EvqAttribute, $1.line); + $$.setBasic(EbtVoid, EvqAttribute, @1); } | VARYING { - if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "varying")) + if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "varying")) context->recover(); if (context->shaderType == SH_VERTEX_SHADER) - $$.setBasic(EbtVoid, EvqVaryingOut, $1.line); + $$.setBasic(EbtVoid, EvqVaryingOut, @1); else - $$.setBasic(EbtVoid, EvqVaryingIn, $1.line); + $$.setBasic(EbtVoid, EvqVaryingIn, @1); } | INVARIANT VARYING { - if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "invariant varying")) + if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying")) context->recover(); if (context->shaderType == SH_VERTEX_SHADER) - $$.setBasic(EbtVoid, EvqInvariantVaryingOut, $1.line); + $$.setBasic(EbtVoid, EvqInvariantVaryingOut, @1); else - $$.setBasic(EbtVoid, EvqInvariantVaryingIn, $1.line); + $$.setBasic(EbtVoid, EvqInvariantVaryingIn, @1); } | UNIFORM { - if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "uniform")) + if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "uniform")) context->recover(); - $$.setBasic(EbtVoid, EvqUniform, $1.line); + $$.setBasic(EbtVoid, EvqUniform, @1); } ; @@ -1525,7 +1395,7 @@ type_specifier if ($$.precision == EbpUndefined) { $$.precision = context->symbolTable.getDefaultPrecision($1.type); - if (context->precisionErrorCheck($1.line, $$.precision, $1.type)) { + if (context->precisionErrorCheck(@1, $$.precision, $1.type)) { context->recover(); } } @@ -1555,11 +1425,11 @@ type_specifier_no_prec | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET { $$ = $1; - if (context->arrayTypeErrorCheck($2.line, $1)) + if (context->arrayTypeErrorCheck(@2, $1)) context->recover(); else { int size; - if (context->arraySizeErrorCheck($2.line, $3, size)) + if (context->arraySizeErrorCheck(@2, $3, size)) context->recover(); $$.setArray(true, size); } @@ -1569,118 +1439,105 @@ type_specifier_no_prec type_specifier_nonarray : VOID_TYPE { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtVoid, qual, $1.line); + $$.setBasic(EbtVoid, qual, @1); } | FLOAT_TYPE { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, $1.line); + $$.setBasic(EbtFloat, qual, @1); } | INT_TYPE { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtInt, qual, $1.line); + $$.setBasic(EbtInt, qual, @1); } | BOOL_TYPE { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtBool, qual, $1.line); + $$.setBasic(EbtBool, qual, @1); } -// | UNSIGNED INT_TYPE { -// PACK_UNPACK_ONLY("unsigned", $1.line); -// TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; -// $$.setBasic(EbtInt, qual, $1.line); -// } | VEC2 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, $1.line); + $$.setBasic(EbtFloat, qual, @1); $$.setAggregate(2); } | VEC3 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, $1.line); + $$.setBasic(EbtFloat, qual, @1); $$.setAggregate(3); } | VEC4 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, $1.line); + $$.setBasic(EbtFloat, qual, @1); $$.setAggregate(4); } | BVEC2 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtBool, qual, $1.line); + $$.setBasic(EbtBool, qual, @1); $$.setAggregate(2); } | BVEC3 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtBool, qual, $1.line); + $$.setBasic(EbtBool, qual, @1); $$.setAggregate(3); } | BVEC4 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtBool, qual, $1.line); + $$.setBasic(EbtBool, qual, @1); $$.setAggregate(4); } | IVEC2 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtInt, qual, $1.line); + $$.setBasic(EbtInt, qual, @1); $$.setAggregate(2); } | IVEC3 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtInt, qual, $1.line); + $$.setBasic(EbtInt, qual, @1); $$.setAggregate(3); } | IVEC4 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtInt, qual, $1.line); + $$.setBasic(EbtInt, qual, @1); $$.setAggregate(4); } | MATRIX2 { - FRAG_VERT_ONLY("mat2", $1.line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, $1.line); + $$.setBasic(EbtFloat, qual, @1); $$.setAggregate(2, true); } | MATRIX3 { - FRAG_VERT_ONLY("mat3", $1.line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, $1.line); + $$.setBasic(EbtFloat, qual, @1); $$.setAggregate(3, true); } | MATRIX4 { - FRAG_VERT_ONLY("mat4", $1.line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtFloat, qual, $1.line); + $$.setBasic(EbtFloat, qual, @1); $$.setAggregate(4, true); } | SAMPLER2D { - FRAG_VERT_ONLY("sampler2D", $1.line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtSampler2D, qual, $1.line); + $$.setBasic(EbtSampler2D, qual, @1); } | SAMPLERCUBE { - FRAG_VERT_ONLY("samplerCube", $1.line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtSamplerCube, qual, $1.line); + $$.setBasic(EbtSamplerCube, qual, @1); } | SAMPLER_EXTERNAL_OES { if (!context->supportsExtension("GL_OES_EGL_image_external")) { - context->error($1.line, "unsupported type", "samplerExternalOES"); + context->error(@1, "unsupported type", "samplerExternalOES"); context->recover(); } - FRAG_VERT_ONLY("samplerExternalOES", $1.line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtSamplerExternalOES, qual, $1.line); + $$.setBasic(EbtSamplerExternalOES, qual, @1); } | SAMPLER2DRECT { if (!context->supportsExtension("GL_ARB_texture_rectangle")) { - context->error($1.line, "unsupported type", "sampler2DRect"); + context->error(@1, "unsupported type", "sampler2DRect"); context->recover(); } - FRAG_VERT_ONLY("sampler2DRect", $1.line); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtSampler2DRect, qual, $1.line); + $$.setBasic(EbtSampler2DRect, qual, @1); } | struct_specifier { - FRAG_VERT_ONLY("struct", $1.line); $$ = $1; $$.qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; } @@ -1691,29 +1548,29 @@ type_specifier_nonarray // TType& structure = static_cast($1.symbol)->getType(); TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - $$.setBasic(EbtStruct, qual, $1.line); + $$.setBasic(EbtStruct, qual, @1); $$.userDef = &structure; } ; struct_specifier - : STRUCT IDENTIFIER LEFT_BRACE { if (context->enterStructDeclaration($2.line, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE { - if (context->reservedErrorCheck($2.line, *$2.string)) + : STRUCT identifier LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE { + if (context->reservedErrorCheck(@2, *$2.string)) context->recover(); - TType* structure = new TType($5, *$2.string); + TType* structure = new TType(new TStructure($2.string, $5)); TVariable* userTypeDef = new TVariable($2.string, *structure, true); if (! context->symbolTable.insert(*userTypeDef)) { - context->error($2.line, "redefinition", $2.string->c_str(), "struct"); + context->error(@2, "redefinition", $2.string->c_str(), "struct"); context->recover(); } - $$.setBasic(EbtStruct, EvqTemporary, $1.line); + $$.setBasic(EbtStruct, EvqTemporary, @1); $$.userDef = structure; context->exitStructDeclaration(); } - | STRUCT LEFT_BRACE { if (context->enterStructDeclaration($2.line, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE { - TType* structure = new TType($4, TString("")); - $$.setBasic(EbtStruct, EvqTemporary, $1.line); + | STRUCT LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE { + TType* structure = new TType(new TStructure(NewPoolTString(""), $4)); + $$.setBasic(EbtStruct, EvqTemporary, @1); $$.userDef = structure; context->exitStructDeclaration(); } @@ -1725,14 +1582,15 @@ struct_declaration_list } | struct_declaration_list struct_declaration { $$ = $1; - for (unsigned int i = 0; i < $2->size(); ++i) { - for (unsigned int j = 0; j < $$->size(); ++j) { - if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName()) { - context->error((*$2)[i].line, "duplicate field name in structure:", "struct", (*$2)[i].type->getFieldName().c_str()); + for (size_t i = 0; i < $2->size(); ++i) { + TField* field = (*$2)[i]; + for (size_t j = 0; j < $$->size(); ++j) { + if ((*$$)[j]->name() == field->name()) { + context->error(@2, "duplicate field name in structure:", "struct", field->name().c_str()); context->recover(); } } - $$->push_back((*$2)[i]); + $$->push_back(field); } } ; @@ -1741,14 +1599,14 @@ struct_declaration : type_specifier struct_declarator_list SEMICOLON { $$ = $2; - if (context->voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) { + if (context->voidErrorCheck(@1, (*$2)[0]->name(), $1)) { context->recover(); } for (unsigned int i = 0; i < $$->size(); ++i) { // // Careful not to replace already known aspects of type, like array-ness // - TType* type = (*$$)[i].type; + TType* type = (*$$)[i]->type(); type->setBasicType($1.type); type->setNominalSize($1.size); type->setMatrix($1.matrix); @@ -1756,26 +1614,23 @@ struct_declaration // don't allow arrays of arrays if (type->isArray()) { - if (context->arrayTypeErrorCheck($1.line, $1)) + if (context->arrayTypeErrorCheck(@1, $1)) context->recover(); } if ($1.array) type->setArraySize($1.arraySize); - if ($1.userDef) { + if ($1.userDef) type->setStruct($1.userDef->getStruct()); - type->setTypeName($1.userDef->getTypeName()); - } - if (context->structNestingErrorCheck($1.line, *type)) { + if (context->structNestingErrorCheck(@1, *(*$$)[i])) context->recover(); - } } } ; struct_declarator_list : struct_declarator { - $$ = NewPoolTTypeList(); + $$ = NewPoolTFieldList(); $$->push_back($1); } | struct_declarator_list COMMA struct_declarator { @@ -1784,26 +1639,24 @@ struct_declarator_list ; struct_declarator - : IDENTIFIER { - if (context->reservedErrorCheck($1.line, *$1.string)) + : identifier { + if (context->reservedErrorCheck(@1, *$1.string)) context->recover(); - $$.type = new TType(EbtVoid, EbpUndefined); - $$.line = $1.line; - $$.type->setFieldName(*$1.string); + TType* type = new TType(EbtVoid, EbpUndefined); + $$ = new TField(type, $1.string); } - | IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET { - if (context->reservedErrorCheck($1.line, *$1.string)) + | identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { + if (context->reservedErrorCheck(@1, *$1.string)) context->recover(); - $$.type = new TType(EbtVoid, EbpUndefined); - $$.line = $1.line; - $$.type->setFieldName(*$1.string); - - int size; - if (context->arraySizeErrorCheck($2.line, $3, size)) + TType* type = new TType(EbtVoid, EbpUndefined); + int size = 0; + if (context->arraySizeErrorCheck(@3, $3, size)) context->recover(); - $$.type->setArraySize(size); + type->setArraySize(size); + + $$ = new TField(type, $1.string); } ; @@ -1835,7 +1688,7 @@ compound_statement | LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE { if ($3 != 0) { $3->setOp(EOpSequence); - $3->setEndLine($5.line); + $3->setLine(@$); } $$ = $3; } @@ -1859,7 +1712,7 @@ compound_statement_no_new_scope | LEFT_BRACE statement_list RIGHT_BRACE { if ($2) { $2->setOp(EOpSequence); - $2->setEndLine($3.line); + $2->setLine(@$); } $$ = $2; } @@ -1867,10 +1720,10 @@ compound_statement_no_new_scope statement_list : statement { - $$ = context->intermediate.makeAggregate($1, 0); + $$ = context->intermediate.makeAggregate($1, @$); } | statement_list statement { - $$ = context->intermediate.growAggregate($1, $2, 0); + $$ = context->intermediate.growAggregate($1, $2, @$); } ; @@ -1881,9 +1734,9 @@ expression_statement selection_statement : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement { - if (context->boolErrorCheck($1.line, $3)) + if (context->boolErrorCheck(@1, $3)) context->recover(); - $$ = context->intermediate.addSelection($3, $5, $1.line); + $$ = context->intermediate.addSelection($3, $5, @1); } ; @@ -1907,14 +1760,14 @@ condition if (context->boolErrorCheck($1->getLine(), $1)) context->recover(); } - | fully_specified_type IDENTIFIER EQUAL initializer { + | fully_specified_type identifier EQUAL initializer { TIntermNode* intermNode; - if (context->structQualifierErrorCheck($2.line, $1)) + if (context->structQualifierErrorCheck(@2, $1)) context->recover(); - if (context->boolErrorCheck($2.line, $1)) + if (context->boolErrorCheck(@2, $1)) context->recover(); - if (!context->executeInitializer($2.line, *$2.string, $1, $4, intermNode)) + if (!context->executeInitializer(@2, *$2.string, $1, $4, intermNode)) $$ = $4; else { context->recover(); @@ -1926,19 +1779,19 @@ condition iteration_statement : WHILE LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope { context->symbolTable.pop(); - $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, $1.line); + $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, @1); --context->loopNestingLevel; } | DO { ++context->loopNestingLevel; } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON { - if (context->boolErrorCheck($8.line, $6)) + if (context->boolErrorCheck(@8, $6)) context->recover(); - $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, $4.line); + $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, @4); --context->loopNestingLevel; } | FOR LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope { context->symbolTable.pop(); - $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast($5.node1), reinterpret_cast($5.node2), $7, $1.line); + $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast($5.node1), reinterpret_cast($5.node2), $7, @1); --context->loopNestingLevel; } ; @@ -1975,39 +1828,39 @@ for_rest_statement jump_statement : CONTINUE SEMICOLON { if (context->loopNestingLevel <= 0) { - context->error($1.line, "continue statement only allowed in loops", ""); + context->error(@1, "continue statement only allowed in loops", ""); context->recover(); } - $$ = context->intermediate.addBranch(EOpContinue, $1.line); + $$ = context->intermediate.addBranch(EOpContinue, @1); } | BREAK SEMICOLON { if (context->loopNestingLevel <= 0) { - context->error($1.line, "break statement only allowed in loops", ""); + context->error(@1, "break statement only allowed in loops", ""); context->recover(); } - $$ = context->intermediate.addBranch(EOpBreak, $1.line); + $$ = context->intermediate.addBranch(EOpBreak, @1); } | RETURN SEMICOLON { - $$ = context->intermediate.addBranch(EOpReturn, $1.line); + $$ = context->intermediate.addBranch(EOpReturn, @1); if (context->currentFunctionType->getBasicType() != EbtVoid) { - context->error($1.line, "non-void function must return a value", "return"); + context->error(@1, "non-void function must return a value", "return"); context->recover(); } } | RETURN expression SEMICOLON { - $$ = context->intermediate.addBranch(EOpReturn, $2, $1.line); + $$ = context->intermediate.addBranch(EOpReturn, $2, @1); context->functionReturnsValue = true; if (context->currentFunctionType->getBasicType() == EbtVoid) { - context->error($1.line, "void function cannot return a value", "return"); + context->error(@1, "void function cannot return a value", "return"); context->recover(); } else if (*(context->currentFunctionType) != $2->getType()) { - context->error($1.line, "function return is not matching type:", "return"); + context->error(@1, "function return is not matching type:", "return"); context->recover(); } } | DISCARD SEMICOLON { - FRAG_ONLY("discard", $1.line); - $$ = context->intermediate.addBranch(EOpKill, $1.line); + FRAG_ONLY("discard", @1); + $$ = context->intermediate.addBranch(EOpKill, @1); } ; @@ -2019,7 +1872,7 @@ translation_unit context->treeRoot = $$; } | translation_unit external_declaration { - $$ = context->intermediate.growAggregate($1, $2, 0); + $$ = context->intermediate.growAggregate($1, $2, @$); context->treeRoot = $$; } ; @@ -2041,7 +1894,7 @@ function_definition if (builtIn) { - context->error($1.line, "built-in functions cannot be redefined", function->getName().c_str()); + context->error(@1, "built-in functions cannot be redefined", function->getName().c_str()); context->recover(); } @@ -2055,7 +1908,7 @@ function_definition // // Then this function already has a body. // - context->error($1.line, "function already has a body", function->getName().c_str()); + context->error(@1, "function already has a body", function->getName().c_str()); context->recover(); } prevDec->setDefined(); @@ -2065,11 +1918,11 @@ function_definition // if (function->getName() == "main") { if (function->getParamCount() > 0) { - context->error($1.line, "function cannot take any parameter(s)", function->getName().c_str()); + context->error(@1, "function cannot take any parameter(s)", function->getName().c_str()); context->recover(); } if (function->getReturnType().getBasicType() != EbtVoid) { - context->error($1.line, "", function->getReturnType().getBasicString(), "main function cannot return a value"); + context->error(@1, "", function->getReturnType().getBasicString(), "main function cannot return a value"); context->recover(); } } @@ -2097,7 +1950,7 @@ function_definition // Insert the parameters with name in the symbol table. // if (! context->symbolTable.insert(*variable)) { - context->error($1.line, "redefinition", variable->getName().c_str()); + context->error(@1, "redefinition", variable->getName().c_str()); context->recover(); delete variable; } @@ -2108,14 +1961,15 @@ function_definition paramNodes = context->intermediate.growAggregate( paramNodes, context->intermediate.addSymbol(variable->getUniqueId(), - variable->getName(), - variable->getType(), $1.line), - $1.line); + variable->getName(), + variable->getType(), + @1), + @1); } else { - paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line); + paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, @1), @1); } } - context->intermediate.setAggregateOperator(paramNodes, EOpParameters, $1.line); + context->intermediate.setAggregateOperator(paramNodes, EOpParameters, @1); $1.intermAggregate = paramNodes; context->loopNestingLevel = 0; } @@ -2123,12 +1977,12 @@ function_definition //?? Check that all paths return a value if return type != void ? // May be best done as post process phase on intermediate code if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) { - context->error($1.line, "function does not return a value:", "", $1.function->getName().c_str()); + context->error(@1, "function does not return a value:", "", $1.function->getName().c_str()); context->recover(); } - $$ = context->intermediate.growAggregate($1.intermAggregate, $3, 0); - context->intermediate.setAggregateOperator($$, EOpFunction, $1.line); + $$ = context->intermediate.growAggregate($1.intermAggregate, $3, @$); + context->intermediate.setAggregateOperator($$, EOpFunction, @1); $$->getAsAggregate()->setName($1.function->getMangledName().c_str()); $$->getAsAggregate()->setType($1.function->getReturnType()); @@ -2137,9 +1991,6 @@ function_definition $$->getAsAggregate()->setOptimize(context->pragma().optimize); $$->getAsAggregate()->setDebug(context->pragma().debug); - if ($3 && $3->getAsAggregate()) - $$->getAsAggregate()->setEndLine($3->getAsAggregate()->getEndLine()); - context->symbolTable.pop(); } ; diff --git a/src/3rdparty/angle/src/compiler/intermOut.cpp b/src/3rdparty/angle/src/compiler/intermOut.cpp index f48a049c63..13aa96af6d 100644 --- a/src/3rdparty/angle/src/compiler/intermOut.cpp +++ b/src/3rdparty/angle/src/compiler/intermOut.cpp @@ -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; } } diff --git a/src/3rdparty/angle/src/compiler/intermediate.h b/src/3rdparty/angle/src/compiler/intermediate.h index 8e76ef921f..738621fe70 100644 --- a/src/3rdparty/angle/src/compiler/intermediate.h +++ b/src/3rdparty/angle/src/compiler/intermediate.h @@ -18,6 +18,7 @@ #include "GLSLANG/ShaderLang.h" +#include #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 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 diff --git a/src/3rdparty/angle/src/compiler/localintermediate.h b/src/3rdparty/angle/src/compiler/localintermediate.h index 56890bd569..1214d821eb 100644 --- a/src/3rdparty/angle/src/compiler/localintermediate.h +++ b/src/3rdparty/angle/src/compiler/localintermediate.h @@ -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); + + TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const 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* 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(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 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 remove(TIntermNode*); void outputTree(TIntermNode*); - -protected: - TInfoSink& infoSink; private: void operator=(TIntermediate&); // prevent assignments + + TInfoSink& infoSink; }; #endif // _LOCAL_INTERMEDIATE_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/parseConst.cpp b/src/3rdparty/angle/src/compiler/parseConst.cpp index 421d31f586..1cc5db8d77 100644 --- a/src/3rdparty/angle/src/compiler/parseConst.cpp +++ b/src/3rdparty/angle/src/compiler/parseConst.cpp @@ -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; diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp index 5ffc6420bc..b615c85dce 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp +++ b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp @@ -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); diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h index 7b70180fc8..9a90d79a1a 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h @@ -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); diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h index 7a6fa87b04..9d131f865a 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h @@ -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 diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l index fc81d84f37..01f0177b6c 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l +++ b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l @@ -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; diff --git a/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp b/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp index 524c6cf53a..355eb62d65 100644 --- a/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp +++ b/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp @@ -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"); } } diff --git a/src/3rdparty/angle/src/compiler/util.cpp b/src/3rdparty/angle/src/compiler/util.cpp index b46e4d0e34..d6e5eeed91 100644 --- a/src/3rdparty/angle/src/compiler/util.cpp +++ b/src/3rdparty/angle/src/compiler/util.cpp @@ -4,30 +4,25 @@ // found in the LICENSE file. // -#include -#include +#include "compiler/util.h" -#include "util.h" +#include -#ifdef _MSC_VER - #include -#else - #include -#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::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::max(); + return success; +} + diff --git a/src/3rdparty/angle/src/compiler/util.h b/src/3rdparty/angle/src/compiler/util.h index 35288b7396..dc69f39060 100644 --- a/src/3rdparty/angle/src/compiler/util.h +++ b/src/3rdparty/angle/src/compiler/util.h @@ -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 diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp index d5d0f0f831..a382c3b1eb 100644 --- a/src/3rdparty/angle/src/libEGL/Display.cpp +++ b/src/3rdparty/angle/src/libEGL/Display.cpp @@ -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(); +} } diff --git a/src/3rdparty/angle/src/libEGL/Display.h b/src/3rdparty/angle/src/libEGL/Display.h index 8c71e51b7a..58c3940331 100644 --- a/src/3rdparty/angle/src/libEGL/Display.h +++ b/src/3rdparty/angle/src/libEGL/Display.h @@ -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; }; } diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp index a430a3530f..b47a7bcc20 100644 --- a/src/3rdparty/angle/src/libEGL/Surface.cpp +++ b/src/3rdparty/angle/src/libEGL/Surface.cpp @@ -20,8 +20,6 @@ #include "libEGL/main.h" #include "libEGL/Display.h" -#include - 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; } diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp index 7fca456cf5..6e10c3926d 100644 --- a/src/3rdparty/angle/src/libEGL/libEGL.cpp +++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp @@ -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(draw))) || diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp index 7ba77f08d1..7dea5fc74b 100644 --- a/src/3rdparty/angle/src/libEGL/main.cpp +++ b/src/3rdparty/angle/src/libEGL/main.cpp @@ -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) diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp b/src/3rdparty/angle/src/libGLESv2/Buffer.cpp index 8d5b4ef2a1..c007d5d9e9 100644 --- a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Buffer.cpp @@ -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; +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.h b/src/3rdparty/angle/src/libGLESv2/Buffer.h index 4376ada5c0..4048f4b906 100644 --- a/src/3rdparty/angle/src/libGLESv2/Buffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Buffer.h @@ -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; diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp index 90ba2539d8..e829d508a6 100644 --- a/src/3rdparty/angle/src/libGLESv2/Context.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp @@ -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()) diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp index 42fee3bbad..b0abba0ac4 100644 --- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp @@ -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; diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h index 66acdc4c37..b54e008dd8 100644 --- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h @@ -68,6 +68,7 @@ class Framebuffer bool hasEnabledColorAttachment() const; bool hasStencil() const; int getSamples() const; + bool usingExtendedDrawBuffers() const; virtual GLenum completeness() const; diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp index 14e6c94ca4..bcd04b7157 100644 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp +++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp @@ -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]; } } diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h index 2386c0bd6f..d6320863f2 100644 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h +++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h @@ -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 { diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.cpp b/src/3rdparty/angle/src/libGLESv2/Shader.cpp index abddab427b..7dfdd0ba3a 100644 --- a/src/3rdparty/angle/src/libGLESv2/Shader.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Shader.cpp @@ -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(); } diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.h b/src/3rdparty/angle/src/libGLESv2/Shader.h index f471968550..2afe2976c3 100644 --- a/src/3rdparty/angle/src/libGLESv2/Shader.h +++ b/src/3rdparty/angle/src/libGLESv2/Shader.h @@ -105,6 +105,8 @@ class Shader bool mUsesFrontFacing; bool mUsesPointSize; bool mUsesPointCoord; + bool mUsesDepthRange; + bool mUsesFragDepth; static void *mFragmentCompiler; static void *mVertexCompiler; diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.cpp b/src/3rdparty/angle/src/libGLESv2/Texture.cpp index 461357a1ce..72c0a8ab79 100644 --- a/src/3rdparty/angle/src/libGLESv2/Texture.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Texture.cpp @@ -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" diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.h b/src/3rdparty/angle/src/libGLESv2/angletypes.h index 37f67f41ac..b2f0cad265 100644 --- a/src/3rdparty/angle/src/libGLESv2/angletypes.h +++ b/src/3rdparty/angle/src/libGLESv2/angletypes.h @@ -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 diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp index 64f67d7d6d..320bbccc27 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp @@ -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&) diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def index 71398b3142..b8320c8f25 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def @@ -182,4 +182,7 @@ EXPORTS glGetProcAddress @148 NONAME glBindTexImage @158 NONAME glCreateRenderer @177 NONAME - glDestroyRenderer @178 NONAME \ No newline at end of file + glDestroyRenderer @178 NONAME + + ; Setting up TRACE macro callbacks + SetTraceFunctionPointers @180 diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def index 0f6caf17a3..ef44917d71 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def @@ -172,6 +172,7 @@ EXPORTS glDrawElementsInstancedANGLE@20 @174 glProgramBinaryOES@16 @175 glGetProgramBinaryOES@20 @176 + glDrawBuffersEXT@8 @179 ; EGL dependencies glCreateContext @144 NONAME @@ -181,4 +182,7 @@ EXPORTS glGetProcAddress@4 @148 NONAME glBindTexImage@4 @158 NONAME glCreateRenderer @177 NONAME - glDestroyRenderer @178 NONAME \ No newline at end of file + glDestroyRenderer @178 NONAME + + ; Setting up TRACE macro callbacks + SetTraceFunctionPointers@8 @180 diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def index 2b3b34009e..3dd5683b5f 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def @@ -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 diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def index dd92a2a12b..6c8d3ed630 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def @@ -172,6 +172,7 @@ EXPORTS glDrawElementsInstancedANGLE@20 @174 glProgramBinaryOES@16 @175 glGetProgramBinaryOES@20 @176 + glDrawBuffersEXT@8 @179 ; EGL dependencies glCreateContext @144 NONAME @@ -181,4 +182,7 @@ EXPORTS glGetProcAddress@4 @148 NONAME glBindTexImage@4 @158 NONAME glCreateRenderer @177 NONAME - glDestroyRenderer @178 NONAME \ No newline at end of file + glDestroyRenderer @178 NONAME + + ; Setting up TRACE macro callbacks + SetTraceFunctionPointers@8 @180 diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp index 5d23e8e70f..730a6ac022 100644 --- a/src/3rdparty/angle/src/libGLESv2/main.cpp +++ b/src/3rdparty/angle/src/libGLESv2/main.cpp @@ -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 diff --git a/src/3rdparty/angle/src/libGLESv2/main.h b/src/3rdparty/angle/src/libGLESv2/main.h index 9168a2212e..196afaeab6 100644 --- a/src/3rdparty/angle/src/libGLESv2/main.h +++ b/src/3rdparty/angle/src/libGLESv2/main.h @@ -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); diff --git a/src/3rdparty/angle/src/libGLESv2/mathutil.h b/src/3rdparty/angle/src/libGLESv2/mathutil.h index bb48b94eaf..083548669a 100644 --- a/src/3rdparty/angle/src/libGLESv2/mathutil.h +++ b/src/3rdparty/angle/src/libGLESv2/mathutil.h @@ -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; diff --git a/src/3rdparty/angle/src/libGLESv2/precompiled.h b/src/3rdparty/angle/src/libGLESv2/precompiled.h index b8b043c964..50dec6b084 100644 --- a/src/3rdparty/angle/src/libGLESv2/precompiled.h +++ b/src/3rdparty/angle/src/libGLESv2/precompiled.h @@ -32,11 +32,11 @@ #include #include -#if defined(ANGLE_ENABLE_D3D11) -# include -# include +#ifndef ANGLE_ENABLE_D3D11 +#include #else -# include +#include +#include #endif #include diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp index 7fe9e6b762..3647d8a898 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp @@ -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; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp index 4468461871..e69e7a8921 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp @@ -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(mMemory) + offset, data, size); + } } void BufferStorage9::clear() diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp index 8c78c7d750..09c8922d07 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp @@ -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(srcMapped.pData); unsigned char *destData = reinterpret_cast(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,8 +344,8 @@ 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; void *dataOffset = static_cast(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset; @@ -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)) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image11.h b/src/3rdparty/angle/src/libGLESv2/renderer/Image11.h index 4d5f1c1780..11a6492dc8 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Image11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Image11.h @@ -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: diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.cpp index 16fd782315..37dbd3e195 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.cpp @@ -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(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::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; } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.h index 1afbd626fa..6fb885a1cd 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.h @@ -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 mCache; + IndexRangeCache mIndexRangeCache; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp index 2a442ecd1a..66604c4558 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp @@ -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; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.cpp index 84b79b4109..49bace8193 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.cpp @@ -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(indices); + unsigned int offset = 0; bool alignedOffset = false; BufferStorage *storage = NULL; if (buffer != NULL) { + if (reinterpret_cast(indices) > std::numeric_limits::max()) + { + return GL_OUT_OF_MEMORY; + } + offset = static_cast(reinterpret_cast(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(count) > (std::numeric_limits::max() / typeSize) || + typeSize * static_cast(count) + offset < offset) + { + return GL_OUT_OF_MEMORY; + } + + if (typeSize * static_cast(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::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; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp new file mode 100644 index 0000000000..610a5efb9c --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp @@ -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 + +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) +{ +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h new file mode 100644 index 0000000000..56834306f2 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h @@ -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 IndexRangeMap; + IndexRangeMap mIndexRangeCache; +}; + +} + +#endif LIBGLESV2_RENDERER_INDEXRANGECACHE_H diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.cpp index 0402bb35ac..1552f3a326 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.cpp @@ -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()); } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.h index d95f39fae4..bb1a8eebcf 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.h @@ -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(&elementCount); + } + + const char *end() const + { + return reinterpret_cast(&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); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp index f60a88f97a..b3111af72b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp @@ -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; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.cpp index cf226de17b..2667cc6fa7 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.cpp @@ -329,44 +329,21 @@ RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTarget *target) ID3D11Texture2D *RenderTarget11::getTexture() const { - if (mTexture) - { - mTexture->AddRef(); - } - return mTexture; } -// Adds reference, caller must call Release ID3D11RenderTargetView *RenderTarget11::getRenderTargetView() const { - if (mRenderTarget) - { - mRenderTarget->AddRef(); - } - return mRenderTarget; } -// Adds reference, caller must call Release ID3D11DepthStencilView *RenderTarget11::getDepthStencilView() const { - if (mDepthStencil) - { - mDepthStencil->AddRef(); - } - return mDepthStencil; } -// Adds reference, caller must call Release ID3D11ShaderResourceView *RenderTarget11::getShaderResourceView() const { - if (mShaderResource) - { - mShaderResource->AddRef(); - } - return mShaderResource; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.h b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.h index dc697cf0e3..97827f2639 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.h @@ -27,16 +27,9 @@ class RenderTarget11 : public RenderTarget static RenderTarget11 *makeRenderTarget11(RenderTarget *renderTarget); - // Adds reference, caller must call Release ID3D11Texture2D *getTexture() const; - - // Adds reference, caller must call Release ID3D11RenderTargetView *getRenderTargetView() const; - - // Adds reference, caller must call Release ID3D11DepthStencilView *getDepthStencilView() const; - - // Adds reference, caller must call Release ID3D11ShaderResourceView *getShaderResourceView() const; unsigned int getSubresourceIndex() const; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp index 218356c59b..21ad223467 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp @@ -7,19 +7,25 @@ // Renderer.cpp: Implements EGL dependencies for creating and destroying Renderer instances. +#include #include "libGLESv2/main.h" #include "libGLESv2/Program.h" #include "libGLESv2/renderer/Renderer.h" -#if defined(ANGLE_ENABLE_D3D11) -# include "libGLESv2/renderer/Renderer11.h" -# define D3DERR_OUTOFVIDEOMEMORY MAKE_HRESULT( 1, 0x876, 380 ) +#ifndef ANGLE_ENABLE_D3D11 +#include "libGLESv2/renderer/Renderer9.h" #else -# include "libGLESv2/renderer/Renderer9.h" +#include "libGLESv2/renderer/Renderer11.h" #endif #include "libGLESv2/utilities.h" +#include "third_party/trace_event/trace_event.h" -#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) -#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 +#if !defined(ANGLE_ENABLE_D3D11) +// Enables use of the Direct3D 11 API for a default display, when available +#define ANGLE_ENABLE_D3D11 0 +#endif + +#ifndef D3DERR_OUTOFVIDEOMEMORY +#define D3DERR_OUTOFVIDEOMEMORY MAKE_HRESULT(1, 0x876, 380) #endif #ifdef __MINGW32__ @@ -61,6 +67,7 @@ Renderer::~Renderer() bool Renderer::initializeCompiler() { + TRACE_EVENT0("gpu", "initializeCompiler"); #if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES) // Find a D3DCompiler module that had already been loaded based on a predefined list of versions. static TCHAR* d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES; @@ -188,14 +195,15 @@ ShaderBlob *Renderer::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, co extern "C" { -rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, bool softwareDevice) +rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayType displayId) { rx::Renderer *renderer = NULL; EGLint status = EGL_BAD_ALLOC; -#if defined(ANGLE_ENABLE_D3D11) +#if ANGLE_ENABLE_D3D11 renderer = new rx::Renderer11(display, hDc); #else + bool softwareDevice = (displayId == EGL_SOFTWARE_DISPLAY_ANGLE); renderer = new rx::Renderer9(display, hDc, softwareDevice); #endif @@ -217,4 +225,4 @@ void glDestroyRenderer(rx::Renderer *renderer) delete renderer; } -} +} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h index 656cb0f1bf..04e877ba9e 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h @@ -13,6 +13,10 @@ #include "libGLESv2/Uniform.h" #include "libGLESv2/angletypes.h" +#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) +#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 +#endif + const int versionWindowsVista = MAKEWORD(0x00, 0x06); const int versionWindows7 = MAKEWORD(0x01, 0x06); @@ -221,6 +225,8 @@ class Renderer virtual QueryImpl *createQuery(GLenum type) = 0; virtual FenceImpl *createFence() = 0; + virtual bool getLUID(LUID *adapterLuid) const = 0; + protected: bool initializeCompiler(); ShaderBlob *compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, UINT optimizationFlags, bool alternateFlags); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp index cf083963e1..a43101807a 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp @@ -35,7 +35,8 @@ #include "libGLESv2/renderer/shaders/compiled/passthroughlumalpha11ps.h" #include "libGLESv2/renderer/shaders/compiled/clear11vs.h" -#include "libGLESv2/renderer/shaders/compiled/clear11ps.h" +#include "libGLESv2/renderer/shaders/compiled/clearsingle11ps.h" +#include "libGLESv2/renderer/shaders/compiled/clearmultiple11ps.h" #include "libEGL/Display.h" @@ -87,7 +88,8 @@ Renderer11::Renderer11(egl::Display *display, HDC hDc) : Renderer(display), mDc( mClearVB = NULL; mClearIL = NULL; mClearVS = NULL; - mClearPS = NULL; + mClearSinglePS = NULL; + mClearMultiplePS = NULL; mClearScissorRS = NULL; mClearNoScissorRS = NULL; @@ -161,25 +163,44 @@ EGLint Renderer11::initialize() D3D_FEATURE_LEVEL_10_0, }; - HRESULT result = D3D11CreateDevice(NULL, - D3D_DRIVER_TYPE_HARDWARE, - NULL, - #if defined(_DEBUG) - D3D11_CREATE_DEVICE_DEBUG, - #else - 0, - #endif - featureLevels, - ArraySize(featureLevels), - D3D11_SDK_VERSION, - &mDevice, - &mFeatureLevel, - &mDeviceContext); + HRESULT result = S_OK; + +#ifdef _DEBUG + result = D3D11CreateDevice(NULL, + D3D_DRIVER_TYPE_HARDWARE, + NULL, + D3D11_CREATE_DEVICE_DEBUG, + featureLevels, + ArraySize(featureLevels), + D3D11_SDK_VERSION, + &mDevice, + &mFeatureLevel, + &mDeviceContext); if (!mDevice || FAILED(result)) { - ERR("Could not create D3D11 device - aborting!\n"); - return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer + ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n"); + } + + if (!mDevice || FAILED(result)) +#endif + { + result = D3D11CreateDevice(NULL, + D3D_DRIVER_TYPE_HARDWARE, + NULL, + 0, + featureLevels, + ArraySize(featureLevels), + D3D11_SDK_VERSION, + &mDevice, + &mFeatureLevel, + &mDeviceContext); + + if (!mDevice || FAILED(result)) + { + ERR("Could not create D3D11 device - aborting!\n"); + return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer + } } IDXGIDevice *dxgiDevice = NULL; @@ -301,7 +322,6 @@ EGLint Renderer11::initialize() { DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, - DXGI_FORMAT_R32G32B32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, }; @@ -655,7 +675,23 @@ void Renderer11::setBlendState(const gl::BlendState &blendState, const gl::Color "blend state."); } - const float blendColors[] = { blendColor.red, blendColor.green, blendColor.blue, blendColor.alpha }; + float blendColors[4] = {0.0f}; + if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && + blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) + { + blendColors[0] = blendColor.red; + blendColors[1] = blendColor.green; + blendColors[2] = blendColor.blue; + blendColors[3] = blendColor.alpha; + } + else + { + blendColors[0] = blendColor.alpha; + blendColors[1] = blendColor.alpha; + blendColors[2] = blendColor.alpha; + blendColors[3] = blendColor.alpha; + } + mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask); mCurBlendState = blendState; @@ -798,23 +834,29 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count) { D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; + GLsizei minCount = 0; + switch (mode) { - case GL_POINTS: primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; break; - case GL_LINES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; break; - case GL_LINE_LOOP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; break; - case GL_LINE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; break; - case GL_TRIANGLES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; break; - case GL_TRIANGLE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; break; + case GL_POINTS: primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; minCount = 1; break; + case GL_LINES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; minCount = 2; break; + case GL_LINE_LOOP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break; + case GL_LINE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break; + case GL_TRIANGLES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; + case GL_TRIANGLE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; minCount = 3; break; // emulate fans via rewriting index buffer - case GL_TRIANGLE_FAN: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; break; + case GL_TRIANGLE_FAN: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; default: return gl::error(GL_INVALID_ENUM, false); } - mDeviceContext->IASetPrimitiveTopology(primitiveTopology); + if (primitiveTopology != mCurrentPrimitiveTopology) + { + mDeviceContext->IASetPrimitiveTopology(primitiveTopology); + mCurrentPrimitiveTopology = primitiveTopology; + } - return count > 0; + return count >= minCount; } bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) @@ -976,9 +1018,6 @@ bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) mDepthStencilInitialized = true; } - SafeRelease(framebufferRTVs); - SafeRelease(framebufferDSV); - return true; } @@ -1093,7 +1132,16 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, } } - const int spaceNeeded = (count + 1) * sizeof(unsigned int); + // Checked by Renderer11::applyPrimitiveType + ASSERT(count >= 0); + + if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned int))) + { + ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); + return gl::error(GL_OUT_OF_MEMORY); + } + + const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned int); if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) { ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); @@ -1101,15 +1149,15 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, } void* mappedMemory = NULL; - int offset = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory); - if (offset == -1 || mappedMemory == NULL) + unsigned int offset; + if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) { ERR("Could not map index buffer for GL_LINE_LOOP."); return gl::error(GL_OUT_OF_MEMORY); } unsigned int *data = reinterpret_cast(mappedMemory); - unsigned int indexBufferOffset = static_cast(offset); + unsigned int indexBufferOffset = offset; switch (type) { @@ -1187,8 +1235,18 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic } } - const int numTris = count - 2; - const int spaceNeeded = (numTris * 3) * sizeof(unsigned int); + // Checked by Renderer11::applyPrimitiveType + ASSERT(count >= 3); + + const unsigned int numTris = count - 2; + + if (numTris > (std::numeric_limits::max() / (sizeof(unsigned int) * 3))) + { + ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required."); + return gl::error(GL_OUT_OF_MEMORY); + } + + const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int); if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) { ERR("Could not reserve enough space in scratch index buffer for GL_TRIANGLE_FAN."); @@ -1196,20 +1254,20 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic } void* mappedMemory = NULL; - int offset = mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory); - if (offset == -1 || mappedMemory == NULL) + unsigned int offset; + if (!mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) { ERR("Could not map scratch index buffer for GL_TRIANGLE_FAN."); return gl::error(GL_OUT_OF_MEMORY); } unsigned int *data = reinterpret_cast(mappedMemory); - unsigned int indexBufferOffset = static_cast(offset); + unsigned int indexBufferOffset = offset; switch (type) { case GL_NONE: // Non-indexed draw - for (int i = 0; i < numTris; i++) + for (unsigned int i = 0; i < numTris; i++) { data[i*3 + 0] = 0; data[i*3 + 1] = i + 1; @@ -1217,7 +1275,7 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic } break; case GL_UNSIGNED_BYTE: - for (int i = 0; i < numTris; i++) + for (unsigned int i = 0; i < numTris; i++) { data[i*3 + 0] = static_cast(indices)[0]; data[i*3 + 1] = static_cast(indices)[i + 1]; @@ -1225,7 +1283,7 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic } break; case GL_UNSIGNED_SHORT: - for (int i = 0; i < numTris; i++) + for (unsigned int i = 0; i < numTris; i++) { data[i*3 + 0] = static_cast(indices)[0]; data[i*3 + 1] = static_cast(indices)[i + 1]; @@ -1233,7 +1291,7 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic } break; case GL_UNSIGNED_INT: - for (int i = 0; i < numTris; i++) + for (unsigned int i = 0; i < numTris; i++) { data[i*3 + 0] = static_cast(indices)[0]; data[i*3 + 1] = static_cast(indices)[i + 1]; @@ -1347,21 +1405,21 @@ void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArra float (*mapVS)[4] = NULL; float (*mapPS)[4] = NULL; - if (totalRegisterCountVS > 0 && vertexUniformsDirty) - { - D3D11_MAPPED_SUBRESOURCE map = {0}; - HRESULT result = mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); - ASSERT(SUCCEEDED(result)); - mapVS = (float(*)[4])map.pData; - } + if (totalRegisterCountVS > 0 && vertexUniformsDirty) + { + D3D11_MAPPED_SUBRESOURCE map = {0}; + HRESULT result = mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); + ASSERT(SUCCEEDED(result)); + mapVS = (float(*)[4])map.pData; + } - if (totalRegisterCountPS > 0 && pixelUniformsDirty) - { - D3D11_MAPPED_SUBRESOURCE map = {0}; - HRESULT result = mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); - ASSERT(SUCCEEDED(result)); - mapPS = (float(*)[4])map.pData; - } + if (totalRegisterCountPS > 0 && pixelUniformsDirty) + { + D3D11_MAPPED_SUBRESOURCE map = {0}; + HRESULT result = mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); + ASSERT(SUCCEEDED(result)); + mapPS = (float(*)[4])map.pData; + } for (gl::UniformArray::iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++) { @@ -1392,9 +1450,18 @@ void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArra { mDeviceContext->Unmap(pixelConstantBuffer, 0); } - - mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer); - mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer); + + if (mCurrentVertexConstantBuffer != vertexConstantBuffer) + { + mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer); + mCurrentVertexConstantBuffer = vertexConstantBuffer; + } + + if (mCurrentPixelConstantBuffer != pixelConstantBuffer) + { + mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer); + mCurrentPixelConstantBuffer = pixelConstantBuffer; + } // Driver uniforms if (!mDriverConstantBufferVS) @@ -1442,7 +1509,11 @@ void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArra } // needed for the point sprite geometry shader - mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); + if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) + { + mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); + mCurrentGeometryConstantBuffer = mDriverConstantBufferPS; + } } void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) @@ -1467,7 +1538,7 @@ void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer * if (needMaskedColorClear || needMaskedStencilClear || needScissoredClear) { - maskedClear(clearParams); + maskedClear(clearParams, frameBuffer->usingExtendedDrawBuffers()); } else { @@ -1499,8 +1570,6 @@ void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer * clearParams.colorClearValue.blue, clearParams.colorClearValue.alpha }; mDeviceContext->ClearRenderTargetView(framebufferRTV, clearValues); - - framebufferRTV->Release(); } } } @@ -1538,20 +1607,18 @@ void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer * UINT8 stencilClear = clearParams.stencilClearValue & 0x000000FF; mDeviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear); - - framebufferDSV->Release(); } } } } -void Renderer11::maskedClear(const gl::ClearParameters &clearParams) +void Renderer11::maskedClear(const gl::ClearParameters &clearParams, bool usingExtendedDrawBuffers) { HRESULT result; if (!mClearResourcesInitialized) { - ASSERT(!mClearVB && !mClearVS && !mClearPS && !mClearScissorRS && !mClearNoScissorRS); + ASSERT(!mClearVB && !mClearVS && !mClearSinglePS && !mClearMultiplePS && !mClearScissorRS && !mClearNoScissorRS); D3D11_BUFFER_DESC vbDesc; vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex) * 4; @@ -1579,9 +1646,13 @@ void Renderer11::maskedClear(const gl::ClearParameters &clearParams) ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mClearVS, "Renderer11 masked clear vertex shader"); - result = mDevice->CreatePixelShader(g_PS_Clear, sizeof(g_PS_Clear), NULL, &mClearPS); + result = mDevice->CreatePixelShader(g_PS_ClearSingle, sizeof(g_PS_ClearSingle), NULL, &mClearSinglePS); ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mClearPS, "Renderer11 masked clear pixel shader"); + d3d11::SetDebugName(mClearSinglePS, "Renderer11 masked clear pixel shader (1 RT)"); + + result = mDevice->CreatePixelShader(g_PS_ClearMultiple, sizeof(g_PS_ClearMultiple), NULL, &mClearMultiplePS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mClearMultiplePS, "Renderer11 masked clear pixel shader (MRT)"); D3D11_RASTERIZER_DESC rsScissorDesc; rsScissorDesc.FillMode = D3D11_FILL_SOLID; @@ -1688,9 +1759,11 @@ void Renderer11::maskedClear(const gl::ClearParameters &clearParams) mDeviceContext->RSSetState(mScissorEnabled ? mClearScissorRS : mClearNoScissorRS); // Apply shaders + ID3D11PixelShader *pixelShader = usingExtendedDrawBuffers ? mClearMultiplePS : mClearSinglePS; + mDeviceContext->IASetInputLayout(mClearIL); mDeviceContext->VSSetShader(mClearVS, NULL, 0); - mDeviceContext->PSSetShader(mClearPS, NULL, 0); + mDeviceContext->PSSetShader(pixelShader, NULL, 0); mDeviceContext->GSSetShader(NULL, NULL, 0); // Apply vertex buffer @@ -1741,6 +1814,14 @@ void Renderer11::markAllStateDirty() mAppliedProgramBinarySerial = 0; memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants)); memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants)); + + mInputLayoutCache.markDirty(); + + mCurrentVertexConstantBuffer = NULL; + mCurrentPixelConstantBuffer = NULL; + mCurrentGeometryConstantBuffer = NULL; + + mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; } void Renderer11::releaseDeviceResources() @@ -1760,111 +1841,31 @@ void Renderer11::releaseDeviceResources() delete mTriangleFanIB; mTriangleFanIB = NULL; - if (mCopyVB) - { - mCopyVB->Release(); - mCopyVB = NULL; - } - - if (mCopySampler) - { - mCopySampler->Release(); - mCopySampler = NULL; - } - - if (mCopyIL) - { - mCopyIL->Release(); - mCopyIL = NULL; - } - - if (mCopyVS) - { - mCopyVS->Release(); - mCopyVS = NULL; - } - - if (mCopyRGBAPS) - { - mCopyRGBAPS->Release(); - mCopyRGBAPS = NULL; - } - - if (mCopyRGBPS) - { - mCopyRGBPS->Release(); - mCopyRGBPS = NULL; - } - - if (mCopyLumPS) - { - mCopyLumPS->Release(); - mCopyLumPS = NULL; - } - - if (mCopyLumAlphaPS) - { - mCopyLumAlphaPS->Release(); - mCopyLumAlphaPS = NULL; - } + SafeRelease(mCopyVB); + SafeRelease(mCopySampler); + SafeRelease(mCopyIL); + SafeRelease(mCopyIL); + SafeRelease(mCopyVS); + SafeRelease(mCopyRGBAPS); + SafeRelease(mCopyRGBPS); + SafeRelease(mCopyLumPS); + SafeRelease(mCopyLumAlphaPS); mCopyResourcesInitialized = false; - if (mClearVB) - { - mClearVB->Release(); - mClearVB = NULL; - } - - if (mClearIL) - { - mClearIL->Release(); - mClearIL = NULL; - } - - if (mClearVS) - { - mClearVS->Release(); - mClearVS = NULL; - } - - if (mClearPS) - { - mClearPS->Release(); - mClearPS = NULL; - } - - if (mClearScissorRS) - { - mClearScissorRS->Release(); - mClearScissorRS = NULL; - } - - if (mClearNoScissorRS) - { - mClearNoScissorRS->Release(); - mClearNoScissorRS = NULL; - } + SafeRelease(mClearVB); + SafeRelease(mClearIL); + SafeRelease(mClearVS); + SafeRelease(mClearSinglePS); + SafeRelease(mClearMultiplePS); + SafeRelease(mClearScissorRS); + SafeRelease(mClearNoScissorRS); mClearResourcesInitialized = false; - if (mDriverConstantBufferVS) - { - mDriverConstantBufferVS->Release(); - mDriverConstantBufferVS = NULL; - } - - if (mDriverConstantBufferPS) - { - mDriverConstantBufferPS->Release(); - mDriverConstantBufferPS = NULL; - } - - if (mSyncQuery) - { - mSyncQuery->Release(); - mSyncQuery = NULL; - } + SafeRelease(mDriverConstantBufferVS); + SafeRelease(mDriverConstantBufferPS); + SafeRelease(mSyncQuery); } void Renderer11::notifyDeviceLost() @@ -2153,12 +2154,12 @@ unsigned int Renderer11::getMaxCombinedTextureImageUnits() const unsigned int Renderer11::getReservedVertexUniformVectors() const { - return 0; // Driver uniforms are stored in a separate constant buffer + return 0; // Driver uniforms are stored in a separate constant buffer } unsigned int Renderer11::getReservedFragmentUniformVectors() const { - return 0; // Driver uniforms are stored in a separate constant buffer + return 0; // Driver uniforms are stored in a separate constant buffer } unsigned int Renderer11::getMaxVertexUniformVectors() const @@ -2448,7 +2449,6 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance()); if (!storage11) { - source->Release(); ERR("Failed to retrieve the texture storage from the destination."); return gl::error(GL_OUT_OF_MEMORY, false); } @@ -2456,7 +2456,6 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(level)); if (!destRenderTarget) { - source->Release(); ERR("Failed to retrieve the render target from the destination storage."); return gl::error(GL_OUT_OF_MEMORY, false); } @@ -2464,7 +2463,6 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); if (!dest) { - source->Release(); ERR("Failed to retrieve the render target view from the destination render target."); return gl::error(GL_OUT_OF_MEMORY, false); } @@ -2478,9 +2476,6 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat); - source->Release(); - dest->Release(); - return ret; } @@ -2511,7 +2506,6 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance()); if (!storage11) { - source->Release(); ERR("Failed to retrieve the texture storage from the destination."); return gl::error(GL_OUT_OF_MEMORY, false); } @@ -2519,7 +2513,6 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(target, level)); if (!destRenderTarget) { - source->Release(); ERR("Failed to retrieve the render target from the destination storage."); return gl::error(GL_OUT_OF_MEMORY, false); } @@ -2527,7 +2520,6 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); if (!dest) { - source->Release(); ERR("Failed to retrieve the render target view from the destination render target."); return gl::error(GL_OUT_OF_MEMORY, false); } @@ -2541,9 +2533,6 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat); - source->Release(); - dest->Release(); - return ret; } @@ -2893,7 +2882,6 @@ bool Renderer11::getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned { ID3D11Resource *textureResource = NULL; colorBufferRTV->GetResource(&textureResource); - colorBufferRTV->Release(); if (textureResource) { @@ -3428,6 +3416,16 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R { ASSERT(readRect.width == drawRect.width && readRect.height == drawRect.height); + RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget); + if (!drawRenderTarget) + { + ERR("Failed to retrieve the draw render target from the draw framebuffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11Texture2D *drawTexture = drawRenderTarget11->getTexture(); + unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex(); + RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget); if (!readRenderTarget) { @@ -3439,16 +3437,13 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R unsigned int readSubresource = 0; if (readRenderTarget->getSamples() > 0) { - ID3D11Texture2D *unresolvedTexture = readRenderTarget11->getTexture(); - - readTexture = resolveMultisampledTexture(unresolvedTexture, readRenderTarget11->getSubresourceIndex()); + readTexture = resolveMultisampledTexture(readRenderTarget11->getTexture(), readRenderTarget11->getSubresourceIndex()); readSubresource = 0; - - unresolvedTexture->Release(); } else { readTexture = readRenderTarget11->getTexture(); + readTexture->AddRef(); readSubresource = readRenderTarget11->getSubresourceIndex(); } @@ -3458,17 +3453,6 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R return gl::error(GL_OUT_OF_MEMORY, false); } - RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget); - if (!drawRenderTarget) - { - readTexture->Release(); - ERR("Failed to retrieve the draw render target from the draw framebuffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - ID3D11Texture2D *drawTexture = drawRenderTarget11->getTexture(); - unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex(); - D3D11_BOX readBox; readBox.left = readRect.x; readBox.right = readRect.x + readRect.width; @@ -3484,8 +3468,7 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, drawRect.x, drawRect.y, 0, readTexture, readSubresource, pSrcBox); - readTexture->Release(); - drawTexture->Release(); + SafeRelease(readTexture); return true; } @@ -3528,4 +3511,24 @@ ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, } } +bool Renderer11::getLUID(LUID *adapterLuid) const +{ + adapterLuid->HighPart = 0; + adapterLuid->LowPart = 0; + + if (!mDxgiAdapter) + { + return false; + } + + DXGI_ADAPTER_DESC adapterDesc; + if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc))) + { + return false; + } + + *adapterLuid = adapterDesc.AdapterLuid; + return true; +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h index a3e42e9048..f024855f97 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h @@ -182,6 +182,8 @@ class Renderer11 : public Renderer void unapplyRenderTargets(); void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView); + virtual bool getLUID(LUID *adapterLuid) const; + private: DISALLOW_COPY_AND_ASSIGN(Renderer11); @@ -192,7 +194,7 @@ class Renderer11 : public Renderer GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void *pixels); - void maskedClear(const gl::ClearParameters &clearParams); + void maskedClear(const gl::ClearParameters &clearParams, bool usingExtendedDrawBuffers); rx::Range getViewportBounds() const; bool blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, @@ -286,6 +288,9 @@ class Renderer11 : public Renderer float mCurNear; float mCurFar; + // Currently applied primitive topology + D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology; + unsigned int mAppliedIBSerial; unsigned int mAppliedStorageIBSerial; unsigned int mAppliedIBOffset; @@ -296,10 +301,14 @@ class Renderer11 : public Renderer dx_VertexConstants mVertexConstants; dx_VertexConstants mAppliedVertexConstants; ID3D11Buffer *mDriverConstantBufferVS; + ID3D11Buffer *mCurrentVertexConstantBuffer; dx_PixelConstants mPixelConstants; dx_PixelConstants mAppliedPixelConstants; ID3D11Buffer *mDriverConstantBufferPS; + ID3D11Buffer *mCurrentPixelConstantBuffer; + + ID3D11Buffer *mCurrentGeometryConstantBuffer; // Vertex, index and input layouts VertexDataManager *mVertexDataManager; @@ -325,7 +334,8 @@ class Renderer11 : public Renderer ID3D11Buffer *mClearVB; ID3D11InputLayout *mClearIL; ID3D11VertexShader *mClearVS; - ID3D11PixelShader *mClearPS; + ID3D11PixelShader *mClearSinglePS; + ID3D11PixelShader *mClearMultiplePS; ID3D11RasterizerState *mClearScissorRS; ID3D11RasterizerState *mClearNoScissorRS; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.cpp index 8acbce4be7..d3f3814ae5 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.cpp @@ -30,6 +30,8 @@ #include "libEGL/Display.h" +#include "third_party/trace_event/trace_event.h" + // Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros #define REF_RAST 0 @@ -41,10 +43,6 @@ #define ANGLE_ENABLE_D3D9EX 1 #endif // !defined(ANGLE_ENABLE_D3D9EX) -#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) -#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 -#endif - namespace rx { static const D3DFORMAT RenderTargetFormats[] = @@ -188,10 +186,12 @@ EGLint Renderer9::initialize() if (mSoftwareDevice) { + TRACE_EVENT0("gpu", "GetModuleHandle_swiftshader"); mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); } else { + TRACE_EVENT0("gpu", "GetModuleHandle_d3d9"); mD3d9Module = GetModuleHandle(TEXT("d3d9.dll")); } @@ -209,12 +209,14 @@ EGLint Renderer9::initialize() // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available. if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) { + TRACE_EVENT0("gpu", "D3d9Ex_QueryInterface"); ASSERT(mD3d9Ex); mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast(&mD3d9)); ASSERT(mD3d9); } else { + TRACE_EVENT0("gpu", "Direct3DCreate9"); mD3d9 = Direct3DCreate9(D3D_SDK_VERSION); } @@ -232,21 +234,24 @@ EGLint Renderer9::initialize() HRESULT result; // Give up on getting device caps after about one second. - for (int i = 0; i < 10; ++i) { - result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps); - if (SUCCEEDED(result)) + TRACE_EVENT0("gpu", "GetDeviceCaps"); + for (int i = 0; i < 10; ++i) { - break; - } - else if (result == D3DERR_NOTAVAILABLE) - { - Sleep(100); // Give the driver some time to initialize/recover - } - else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from - { - ERR("failed to get device caps (0x%x)\n", result); - return EGL_NOT_INITIALIZED; + result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps); + if (SUCCEEDED(result)) + { + break; + } + else if (result == D3DERR_NOTAVAILABLE) + { + Sleep(100); // Give the driver some time to initialize/recover + } + else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from + { + ERR("failed to get device caps (0x%x)\n", result); + return EGL_NOT_INITIALIZED; + } } } @@ -264,7 +269,10 @@ EGLint Renderer9::initialize() return EGL_NOT_INITIALIZED; } - mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier); + { + TRACE_EVENT0("gpu", "GetAdapterIdentifier"); + mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier); + } // ATI cards on XP have problems with non-power-of-two textures. mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) && @@ -305,35 +313,41 @@ EGLint Renderer9::initialize() } int max = 0; - for (unsigned int i = 0; i < ArraySize(RenderTargetFormats); ++i) { - bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1]; - getMultiSampleSupport(RenderTargetFormats[i], multisampleArray); - mMultiSampleSupport[RenderTargetFormats[i]] = multisampleArray; - - for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j) + TRACE_EVENT0("gpu", "getMultiSampleSupport"); + for (unsigned int i = 0; i < ArraySize(RenderTargetFormats); ++i) { - if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max) + bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1]; + getMultiSampleSupport(RenderTargetFormats[i], multisampleArray); + mMultiSampleSupport[RenderTargetFormats[i]] = multisampleArray; + + for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j) { - max = j; + if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max) + { + max = j; + } } } } - for (unsigned int i = 0; i < ArraySize(DepthStencilFormats); ++i) { - if (DepthStencilFormats[i] == D3DFMT_UNKNOWN) - continue; - - bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1]; - getMultiSampleSupport(DepthStencilFormats[i], multisampleArray); - mMultiSampleSupport[DepthStencilFormats[i]] = multisampleArray; - - for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j) + TRACE_EVENT0("gpu", "getMultiSampleSupport2"); + for (unsigned int i = 0; i < ArraySize(DepthStencilFormats); ++i) { - if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max) + if (DepthStencilFormats[i] == D3DFMT_UNKNOWN) + continue; + + bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1]; + getMultiSampleSupport(DepthStencilFormats[i], multisampleArray); + mMultiSampleSupport[DepthStencilFormats[i]] = multisampleArray; + + for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j) { - max = j; + if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max) + { + max = j; + } } } } @@ -343,12 +357,18 @@ EGLint Renderer9::initialize() static const TCHAR windowName[] = TEXT("AngleHiddenWindow"); static const TCHAR className[] = TEXT("STATIC"); - mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL); + { + TRACE_EVENT0("gpu", "CreateWindowEx"); + mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL); + } D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES; - result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice); + { + TRACE_EVENT0("gpu", "D3d9_CreateDevice"); + result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice); + } if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST) { return EGL_BAD_ALLOC; @@ -356,6 +376,7 @@ EGLint Renderer9::initialize() if (FAILED(result)) { + TRACE_EVENT0("gpu", "D3d9_CreateDevice2"); result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice); if (FAILED(result)) @@ -367,35 +388,45 @@ EGLint Renderer9::initialize() if (mD3d9Ex) { + TRACE_EVENT0("gpu", "mDevice_QueryInterface"); result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx); ASSERT(SUCCEEDED(result)); } - mVertexShaderCache.initialize(mDevice); - mPixelShaderCache.initialize(mDevice); + { + TRACE_EVENT0("gpu", "ShaderCache initialize"); + mVertexShaderCache.initialize(mDevice); + mPixelShaderCache.initialize(mDevice); + } // Check occlusion query support IDirect3DQuery9 *occlusionQuery = NULL; - if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery) { - occlusionQuery->Release(); - mOcclusionQuerySupport = true; - } - else - { - mOcclusionQuerySupport = false; + TRACE_EVENT0("gpu", "device_CreateQuery"); + if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery) + { + occlusionQuery->Release(); + mOcclusionQuerySupport = true; + } + else + { + mOcclusionQuerySupport = false; + } } // Check event query support IDirect3DQuery9 *eventQuery = NULL; - if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery) { - eventQuery->Release(); - mEventQuerySupport = true; - } - else - { - mEventQuerySupport = false; + TRACE_EVENT0("gpu", "device_CreateQuery2"); + if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery) + { + eventQuery->Release(); + mEventQuerySupport = true; + } + else + { + mEventQuerySupport = false; + } } D3DDISPLAYMODE currentDisplayMode; @@ -1080,8 +1111,10 @@ bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zF return false; // Nothing to render } + float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f); + bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || - actualZNear != mCurNear || actualZFar != mCurFar; + actualZNear != mCurNear || actualZFar != mCurFar || mCurDepthFront != depthFront; if (viewportChanged) { mDevice->SetViewport(&dxViewport); @@ -1089,6 +1122,7 @@ bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zF mCurViewport = actualViewport; mCurNear = actualZNear; mCurFar = actualZFar; + mCurDepthFront = depthFront; dx_VertexConstants vc = {0}; dx_PixelConstants pc = {0}; @@ -1105,7 +1139,7 @@ bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zF pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f; pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f; - pc.depthFront[2] = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f);; + pc.depthFront[2] = depthFront; vc.depthRange[0] = actualZNear; vc.depthRange[1] = actualZFar; @@ -1458,7 +1492,7 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, indices = static_cast(storage->getData()) + offset; } - UINT startIndex = 0; + unsigned int startIndex = 0; if (get32BitIndexSupport()) { @@ -1475,7 +1509,16 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, } } - const int spaceNeeded = (count + 1) * sizeof(unsigned int); + if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned int))) + { + ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); + return gl::error(GL_OUT_OF_MEMORY); + } + + // Checked by Renderer9::applyPrimitiveType + ASSERT(count >= 0); + + const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned int); if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) { ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); @@ -1483,14 +1526,14 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, } void* mappedMemory = NULL; - int offset = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory); - if (offset == -1 || mappedMemory == NULL) + unsigned int offset = 0; + if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) { ERR("Could not map index buffer for GL_LINE_LOOP."); return gl::error(GL_OUT_OF_MEMORY); } - startIndex = static_cast(offset) / 4; + startIndex = static_cast(offset) / 4; unsigned int *data = reinterpret_cast(mappedMemory); switch (type) @@ -1547,7 +1590,16 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, } } - const int spaceNeeded = (count + 1) * sizeof(unsigned short); + // Checked by Renderer9::applyPrimitiveType + ASSERT(count >= 0); + + if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned short))) + { + ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP, too many indices required."); + return gl::error(GL_OUT_OF_MEMORY); + } + + const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned short); if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT)) { ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); @@ -1555,14 +1607,14 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, } void* mappedMemory = NULL; - int offset = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory); - if (offset == -1 || mappedMemory == NULL) + unsigned int offset; + if (mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) { ERR("Could not map index buffer for GL_LINE_LOOP."); return gl::error(GL_OUT_OF_MEMORY); } - startIndex = static_cast(offset) / 2; + startIndex = static_cast(offset) / 2; unsigned short *data = reinterpret_cast(mappedMemory); switch (type) @@ -2042,23 +2094,6 @@ bool Renderer9::testDeviceLost(bool notify) if (mDeviceEx) { status = mDeviceEx->CheckDeviceState(NULL); - - if (status == S_PRESENT_MODE_CHANGED) - { - // Reset the device so that D3D stops reporting S_PRESENT_MODE_CHANGED. Otherwise it will report - // it continuously, potentially masking a lost device. D3D resources are not lost on a mode change with WDDM. - D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); - mDeviceEx->Reset(&presentParameters); - - // Existing swap chains sometimes crash on the next present after a reset. - mDisplay->recreateSwapChains(); - - // Reset will not always cause the device loss to be reported so issue a dummy present. - mDeviceEx->Present(NULL, NULL, NULL, NULL); - - // Retest the device status to see if the mode change really indicated a lost device. - status = mDeviceEx->CheckDeviceState(NULL); - } } else if (mDevice) { @@ -3208,4 +3243,18 @@ TextureStorage *Renderer9::createTextureStorageCube(int levels, GLenum internalf return new TextureStorage9_Cube(this, levels, internalformat, usage, forceRenderable, size); } -} \ No newline at end of file +bool Renderer9::getLUID(LUID *adapterLuid) const +{ + adapterLuid->HighPart = 0; + adapterLuid->LowPart = 0; + + if (mD3d9Ex) + { + mD3d9Ex->GetAdapterLUID(mAdapter, adapterLuid); + return true; + } + + return false; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.h index 527a5010ae..f8932c4fd4 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.h @@ -193,6 +193,8 @@ class Renderer9 : public Renderer D3DPOOL getTexturePool(DWORD usage) const; + virtual bool getLUID(LUID *adapterLuid) const; + private: DISALLOW_COPY_AND_ASSIGN(Renderer9); @@ -296,6 +298,7 @@ class Renderer9 : public Renderer gl::Rectangle mCurViewport; float mCurNear; float mCurFar; + float mCurDepthFront; bool mForceSetBlendState; gl::BlendState mCurBlendState; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h index 128d123fbe..293e340845 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h @@ -26,7 +26,7 @@ class ShaderExecutable virtual ~ShaderExecutable() { - delete mFunction; + delete[] mFunction; } void *getFunction() const diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp index 98f887587c..0da58cbe2e 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp @@ -275,6 +275,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei else { result = offscreenTextureResource->GetSharedHandle(&mShareHandle); + offscreenTextureResource->Release(); if (FAILED(result)) { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp index 667dbff175..408b48ebab 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp @@ -69,7 +69,6 @@ bool TextureStorage11::IsTextureFormatRenderable(DXGI_FORMAT format) case DXGI_FORMAT_R8G8B8A8_UNORM: case DXGI_FORMAT_A8_UNORM: case DXGI_FORMAT_R32G32B32A32_FLOAT: - case DXGI_FORMAT_R32G32B32_FLOAT: case DXGI_FORMAT_R16G16B16A16_FLOAT: case DXGI_FORMAT_B8G8R8A8_UNORM: case DXGI_FORMAT_R8_UNORM: @@ -80,6 +79,7 @@ bool TextureStorage11::IsTextureFormatRenderable(DXGI_FORMAT format) case DXGI_FORMAT_BC1_UNORM: case DXGI_FORMAT_BC2_UNORM: case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_R32G32B32_FLOAT: // not renderable on all devices return false; default: UNREACHABLE(); @@ -187,15 +187,6 @@ void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget1 destRTV, destArea, dest->getWidth(), dest->getHeight(), GL_RGBA); } - - if (sourceSRV) - { - sourceSRV->Release(); - } - if (destRTV) - { - destRTV->Release(); - } } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.cpp index 16e1486511..a073d95033 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.cpp @@ -87,52 +87,97 @@ bool VertexBufferInterface::discard() return mVertexBuffer->discard(); } -int VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances) +bool VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, + unsigned int *outStreamOffset) { + unsigned int spaceRequired; + if (!mVertexBuffer->getSpaceRequired(attrib, count, instances, &spaceRequired)) + { + return false; + } + + if (mWritePosition + spaceRequired < mWritePosition) + { + return false; + } + if (!reserveSpace(mReservedSpace)) { - return -1; + return false; } mReservedSpace = 0; if (!mVertexBuffer->storeVertexAttributes(attrib, start, count, instances, mWritePosition)) { - return -1; + return false; } - int oldWritePos = static_cast(mWritePosition); - mWritePosition += mVertexBuffer->getSpaceRequired(attrib, count, instances); + if (outStreamOffset) + { + *outStreamOffset = mWritePosition; + } - return oldWritePos; + mWritePosition += spaceRequired; + + return true; } -int VertexBufferInterface::storeRawData(const void* data, unsigned int size) +bool VertexBufferInterface::storeRawData(const void* data, unsigned int size, unsigned int *outStreamOffset) { + if (mWritePosition + size < mWritePosition) + { + return false; + } + if (!reserveSpace(mReservedSpace)) { - return -1; + return false; } mReservedSpace = 0; if (!mVertexBuffer->storeRawData(data, size, mWritePosition)) { - return -1; + return false; + } + + if (outStreamOffset) + { + *outStreamOffset = mWritePosition; } - int oldWritePos = static_cast(mWritePosition); mWritePosition += size; - return oldWritePos; + return true; } -void VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances) +bool VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances) { - mReservedSpace += mVertexBuffer->getSpaceRequired(attribute, count, instances); + unsigned int requiredSpace; + if (!mVertexBuffer->getSpaceRequired(attribute, count, instances, &requiredSpace)) + { + return false; + } + + // Protect against integer overflow + if (mReservedSpace + requiredSpace < mReservedSpace) + { + return false; + } + + mReservedSpace += requiredSpace; + return true; } -void VertexBufferInterface::reserveRawDataSpace(unsigned int size) +bool VertexBufferInterface::reserveRawDataSpace(unsigned int size) { + // Protect against integer overflow + if (mReservedSpace + size < mReservedSpace) + { + return false; + } + mReservedSpace += size; + return true; } VertexBuffer* VertexBufferInterface::getVertexBuffer() const @@ -179,7 +224,7 @@ StaticVertexBufferInterface::~StaticVertexBufferInterface() { } -int StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attribute) +bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attribute, unsigned int *outStreamOffset) { for (unsigned int element = 0; element < mCache.size(); element++) { @@ -190,12 +235,16 @@ int StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attr { if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride()) { - return mCache[element].streamOffset; + if (outStreamOffset) + { + *outStreamOffset = mCache[element].streamOffset; + } + return true; } } } - return -1; + return false; } bool StaticVertexBufferInterface::reserveSpace(unsigned int size) @@ -217,13 +266,27 @@ bool StaticVertexBufferInterface::reserveSpace(unsigned int size) } } -int StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances) +bool StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, + unsigned int *outStreamOffset) { - int attributeOffset = attrib.mOffset % attrib.stride(); - VertexElement element = { attrib.mType, attrib.mSize, attrib.stride(), attrib.mNormalized, attributeOffset, getWritePosition() }; - mCache.push_back(element); + unsigned int streamOffset; + if (VertexBufferInterface::storeVertexAttributes(attrib, start, count, instances, &streamOffset)) + { + int attributeOffset = attrib.mOffset % attrib.stride(); + VertexElement element = { attrib.mType, attrib.mSize, attrib.stride(), attrib.mNormalized, attributeOffset, streamOffset }; + mCache.push_back(element); - return VertexBufferInterface::storeVertexAttributes(attrib, start, count, instances); + if (outStreamOffset) + { + *outStreamOffset = streamOffset; + } + + return true; + } + else + { + return false; + } } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.h index 6ecffd0c0b..cbafdd20f6 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.h @@ -33,8 +33,8 @@ class VertexBuffer GLsizei instances, unsigned int offset) = 0; virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset) = 0; - virtual unsigned int getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, - GLsizei instances) const = 0; + virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, + unsigned int *outSpaceRequired) const = 0; virtual bool requiresConversion(const gl::VertexAttribute &attrib) const = 0; @@ -60,15 +60,16 @@ class VertexBufferInterface VertexBufferInterface(rx::Renderer *renderer, bool dynamic); virtual ~VertexBufferInterface(); - void reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances); - void reserveRawDataSpace(unsigned int size); + bool reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances); + bool reserveRawDataSpace(unsigned int size); unsigned int getBufferSize() const; unsigned int getSerial() const; - virtual int storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances); - virtual int storeRawData(const void* data, unsigned int size); + virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, + unsigned int *outStreamOffset); + virtual bool storeRawData(const void* data, unsigned int size, unsigned int *outStreamOffset); VertexBuffer* getVertexBuffer() const; @@ -110,10 +111,10 @@ class StaticVertexBufferInterface : public VertexBufferInterface explicit StaticVertexBufferInterface(rx::Renderer *renderer); ~StaticVertexBufferInterface(); - int storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances); + bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, + unsigned int *outStreamOffset); - // Returns the offset into the vertex buffer, or -1 if not found - int lookupAttribute(const gl::VertexAttribute &attribute); + bool lookupAttribute(const gl::VertexAttribute &attribute, unsigned int* outStreamOffset); protected: bool reserveSpace(unsigned int size); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.cpp index 92c8755e22..521da80c3d 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.cpp @@ -152,18 +152,40 @@ bool VertexBuffer11::storeRawData(const void* data, unsigned int size, unsigned } } -unsigned int VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, - GLsizei instances) const +bool VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, + GLsizei instances, unsigned int *outSpaceRequired) const { unsigned int elementSize = getVertexConversion(attrib).outputElementSize; + unsigned int elementCount = 0; if (instances == 0 || attrib.mDivisor == 0) { - return elementSize * count; + elementCount = count; } else { - return elementSize * ((instances + attrib.mDivisor - 1) / attrib.mDivisor); + if (static_cast(instances) < std::numeric_limits::max() - (attrib.mDivisor - 1)) + { + // Round up + elementCount = (static_cast(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor; + } + else + { + elementCount = instances / attrib.mDivisor; + } + } + + if (elementSize <= std::numeric_limits::max() / elementCount) + { + if (outSpaceRequired) + { + *outSpaceRequired = elementSize * elementCount; + } + return true; + } + else + { + return false; } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.h index 75e025075e..eceb426e82 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.h @@ -26,10 +26,11 @@ class VertexBuffer11 : public VertexBuffer static VertexBuffer11 *makeVertexBuffer11(VertexBuffer *vetexBuffer); virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, - unsigned int offset); + unsigned int offset); virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset); - virtual unsigned int getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances) const; + virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, + unsigned int *outSpaceRequired) const; virtual bool requiresConversion(const gl::VertexAttribute &attrib) const; @@ -70,4 +71,4 @@ class VertexBuffer11 : public VertexBuffer } -#endif // LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ \ No newline at end of file +#endif // LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.cpp index 76dc73e391..b017b3af33 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.cpp @@ -95,7 +95,14 @@ bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, GLi DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; void *mapPtr = NULL; - HRESULT result = mVertexBuffer->Lock(offset, spaceRequired(attrib, count, instances), &mapPtr, lockFlags); + + unsigned int mapSize; + if (!spaceRequired(attrib, count, instances, &mapSize)) + { + return false; + } + + HRESULT result = mVertexBuffer->Lock(offset, mapSize, &mapPtr, lockFlags); if (FAILED(result)) { @@ -167,9 +174,10 @@ bool VertexBuffer9::storeRawData(const void* data, unsigned int size, unsigned i } } -unsigned int VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances) const +bool VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, + unsigned int *outSpaceRequired) const { - return spaceRequired(attrib, count, instances); + return spaceRequired(attrib, count, instances, outSpaceRequired); } bool VertexBuffer9::requiresConversion(const gl::VertexAttribute &attrib) const @@ -179,7 +187,8 @@ bool VertexBuffer9::requiresConversion(const gl::VertexAttribute &attrib) const unsigned int VertexBuffer9::getVertexSize(const gl::VertexAttribute &attrib) const { - return spaceRequired(attrib, 1, 0); + unsigned int spaceRequired; + return getSpaceRequired(attrib, 1, 0, &spaceRequired) ? spaceRequired : 0; } D3DDECLTYPE VertexBuffer9::getDeclType(const gl::VertexAttribute &attrib) const @@ -469,17 +478,52 @@ const VertexBuffer9::FormatConverter &VertexBuffer9::formatConverter(const gl::V return mFormatConverters[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1]; } -unsigned int VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances) +bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, + unsigned int *outSpaceRequired) { unsigned int elementSize = formatConverter(attrib).outputElementSize; - if (instances == 0 || attrib.mDivisor == 0) + if (attrib.mArrayEnabled) { - return elementSize * count; + unsigned int elementCount = 0; + if (instances == 0 || attrib.mDivisor == 0) + { + elementCount = count; + } + else + { + if (static_cast(instances) < std::numeric_limits::max() - (attrib.mDivisor - 1)) + { + // Round up + elementCount = (static_cast(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor; + } + else + { + elementCount = static_cast(instances) / attrib.mDivisor; + } + } + + if (elementSize <= std::numeric_limits::max() / elementCount) + { + if (outSpaceRequired) + { + *outSpaceRequired = elementSize * elementCount; + } + return true; + } + else + { + return false; + } } else { - return elementSize * ((instances + attrib.mDivisor - 1) / attrib.mDivisor); + const unsigned int elementSize = 4; + if (outSpaceRequired) + { + *outSpaceRequired = elementSize * 4; + } + return true; } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.h index f771635bda..2f88117bda 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.h @@ -29,7 +29,7 @@ class VertexBuffer9 : public VertexBuffer unsigned int offset); virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset); - virtual unsigned int getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances) const; + virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, unsigned int *outSpaceRequired) const; virtual bool requiresConversion(const gl::VertexAttribute &attrib) const; @@ -82,7 +82,8 @@ class VertexBuffer9 : public VertexBuffer static unsigned int typeIndex(GLenum type); static const FormatConverter &formatConverter(const gl::VertexAttribute &attribute); - static unsigned int spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances); + static bool spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, + unsigned int *outSpaceRequired); }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp index ec85857264..7ff5171fca 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp @@ -26,12 +26,32 @@ namespace namespace rx { -static int elementsInBuffer(const gl::VertexAttribute &attribute, int size) +static int elementsInBuffer(const gl::VertexAttribute &attribute, unsigned int size) { - int stride = attribute.stride(); + // Size cannot be larger than a GLsizei + if (size > static_cast(std::numeric_limits::max())) + { + size = static_cast(std::numeric_limits::max()); + } + + GLsizei stride = attribute.stride(); return (size - attribute.mOffset % stride + (stride - attribute.typeSize())) / stride; } +static int StreamingBufferElementCount(const gl::VertexAttribute &attribute, int vertexDrawCount, int instanceDrawCount) +{ + // For instanced rendering, we draw "instanceDrawCount" sets of "vertexDrawCount" vertices. + // + // A vertex attribute with a positive divisor loads one instanced vertex for every set of + // non-instanced vertices, and the instanced vertex index advances once every "mDivisor" instances. + if (instanceDrawCount > 0 && attribute.mDivisor > 0) + { + return instanceDrawCount / attribute.mDivisor; + } + + return vertexDrawCount; +} + VertexDataManager::VertexDataManager(Renderer *renderer) : mRenderer(renderer) { for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) @@ -92,7 +112,7 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], gl::Buffer *buffer = attribs[i].mBoundBuffer.get(); StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; - if (staticBuffer && staticBuffer->getBufferSize() > 0 && staticBuffer->lookupAttribute(attribs[i]) == -1 && + if (staticBuffer && staticBuffer->getBufferSize() > 0 && !staticBuffer->lookupAttribute(attribs[i], NULL) && !directStoragePossible(staticBuffer, attribs[i])) { buffer->invalidateStaticData(); @@ -116,12 +136,27 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], if (staticBuffer->getBufferSize() == 0) { int totalCount = elementsInBuffer(attribs[i], buffer->size()); - staticBuffer->reserveVertexSpace(attribs[i], totalCount, 0); + if (!staticBuffer->reserveVertexSpace(attribs[i], totalCount, 0)) + { + return GL_OUT_OF_MEMORY; + } } } else { - mStreamingBuffer->reserveVertexSpace(attribs[i], count, instances); + int totalCount = StreamingBufferElementCount(attribs[i], count, instances); + + // Undefined behaviour: + // We can return INVALID_OPERATION if our vertex attribute does not have enough backing data. + if (buffer && elementsInBuffer(attribs[i], buffer->size()) < totalCount) + { + return GL_INVALID_OPERATION; + } + + if (!mStreamingBuffer->reserveVertexSpace(attribs[i], totalCount, instances)) + { + return GL_OUT_OF_MEMORY; + } } } } @@ -149,7 +184,7 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], BufferStorage *storage = buffer ? buffer->getStorage() : NULL; bool directStorage = directStoragePossible(vertexBuffer, attribs[i]); - std::size_t streamOffset = -1; + unsigned int streamOffset = 0; unsigned int outputElementSize = 0; if (directStorage) @@ -160,37 +195,40 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], } else if (staticBuffer) { - streamOffset = staticBuffer->lookupAttribute(attribs[i]); - outputElementSize = staticBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0); + if (!staticBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0, &outputElementSize)) + { + return GL_OUT_OF_MEMORY; + } - if (streamOffset == -1) + if (!staticBuffer->lookupAttribute(attribs[i], &streamOffset)) { // Convert the entire buffer int totalCount = elementsInBuffer(attribs[i], storage->getSize()); int startIndex = attribs[i].mOffset / attribs[i].stride(); - streamOffset = staticBuffer->storeVertexAttributes(attribs[i], -startIndex, totalCount, 0); - } - - if (streamOffset != -1) - { - streamOffset += (attribs[i].mOffset / attribs[i].stride()) * outputElementSize; - - if (instances == 0 || attribs[i].mDivisor == 0) + if (!staticBuffer->storeVertexAttributes(attribs[i], -startIndex, totalCount, 0, &streamOffset)) { - streamOffset += start * outputElementSize; + return GL_OUT_OF_MEMORY; } } + + unsigned int firstElementOffset = (attribs[i].mOffset / attribs[i].stride()) * outputElementSize; + unsigned int startOffset = (instances == 0 || attribs[i].mDivisor == 0) ? start * outputElementSize : 0; + if (streamOffset + firstElementOffset + startOffset < streamOffset) + { + return GL_OUT_OF_MEMORY; + } + + streamOffset += firstElementOffset + startOffset; } else { - outputElementSize = mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0); - streamOffset = mStreamingBuffer->storeVertexAttributes(attribs[i], start, count, instances); - } - - if (streamOffset == -1) - { - return GL_OUT_OF_MEMORY; + int totalCount = StreamingBufferElementCount(attribs[i], count, instances); + if (!mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0, &outputElementSize) || + !mStreamingBuffer->storeVertexAttributes(attribs[i], start, totalCount, instances, &streamOffset)) + { + return GL_OUT_OF_MEMORY; + } } translated[i].storage = directStorage ? storage : NULL; @@ -217,9 +255,13 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], mCurrentValue[i][3] != attribs[i].mCurrentValue[3]) { unsigned int requiredSpace = sizeof(float) * 4; - buffer->reserveRawDataSpace(requiredSpace); - int streamOffset = buffer->storeRawData(attribs[i].mCurrentValue, requiredSpace); - if (streamOffset == -1) + if (!buffer->reserveRawDataSpace(requiredSpace)) + { + return GL_OUT_OF_MEMORY; + } + + unsigned int streamOffset; + if (!buffer->storeRawData(attribs[i].mCurrentValue, requiredSpace, &streamOffset)) { return GL_OUT_OF_MEMORY; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h index 28387e6baf..1a8786552a 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h @@ -31,8 +31,8 @@ struct TranslatedAttribute bool active; const gl::VertexAttribute *attribute; - UINT offset; - UINT stride; // 0 means not to advance the read pointer at all + unsigned int offset; + unsigned int stride; // 0 means not to advance the read pointer at all VertexBuffer *vertexBuffer; BufferStorage *storage; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp index 5f01dc12ed..13800da258 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp @@ -356,7 +356,7 @@ DXGI_FORMAT ConvertTextureFormat(GLenum internalformat) return DXGI_FORMAT_R32G32B32A32_FLOAT; case GL_RGB32F_EXT: case GL_LUMINANCE32F_EXT: - return DXGI_FORMAT_R32G32B32_FLOAT; + return DXGI_FORMAT_R32G32B32A32_FLOAT; case GL_RGBA16F_EXT: case GL_ALPHA16F_EXT: case GL_LUMINANCE_ALPHA16F_EXT: diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl index d2752601e9..042ac699b6 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl +++ b/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl @@ -6,7 +6,7 @@ void VS_Clear( in float3 inPosition : POSITION, in float4 inColor : COLOR, } // Assume we are in SM4+, which has 8 color outputs -struct PS_Output +struct PS_OutputMultiple { float4 color0 : SV_TARGET0; float4 color1 : SV_TARGET1; @@ -18,9 +18,9 @@ struct PS_Output float4 color7 : SV_TARGET7; }; -PS_Output PS_Clear(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) +PS_OutputMultiple PS_ClearMultiple(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) { - PS_Output outColor; + PS_OutputMultiple outColor; outColor.color0 = inColor; outColor.color1 = inColor; outColor.color2 = inColor; @@ -31,3 +31,8 @@ PS_Output PS_Clear(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR outColor.color7 = inColor; return outColor; } + +float4 PS_ClearSingle(in float4 inPosition : SV_Position, in float4 inColor : COLOR) : SV_Target0 +{ + return inColor; +} diff --git a/src/3rdparty/angle/src/libGLESv2/utilities.cpp b/src/3rdparty/angle/src/libGLESv2/utilities.cpp index 9809b9d8e8..32df49e672 100644 --- a/src/3rdparty/angle/src/libGLESv2/utilities.cpp +++ b/src/3rdparty/angle/src/libGLESv2/utilities.cpp @@ -218,6 +218,29 @@ GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum internalform } } +GLsizei ComputeTypeSize(GLenum type) +{ + switch (type) + { + case GL_BYTE: return 1; + case GL_UNSIGNED_BYTE: return 1; + case GL_SHORT: return 2; + case GL_UNSIGNED_SHORT: return 2; + case GL_INT: return 4; + case GL_UNSIGNED_INT: return 4; + case GL_FLOAT: return 4; + case GL_HALF_FLOAT_OES: return 2; + case GL_UNSIGNED_SHORT_5_6_5: return 2; + case GL_UNSIGNED_SHORT_4_4_4_4: return 2; + case GL_UNSIGNED_SHORT_5_5_5_1: return 2; + case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: return 2; + case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: return 2; + case GL_UNSIGNED_INT_2_10_10_10_REV_EXT: return 4; + case GL_UNSIGNED_INT_24_8_OES: return 4; + default: UNREACHABLE(); return 0; + } +} + bool IsCompressed(GLenum format) { if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || diff --git a/src/3rdparty/angle/src/libGLESv2/utilities.h b/src/3rdparty/angle/src/libGLESv2/utilities.h index 7a10767086..ed663ebca2 100644 --- a/src/3rdparty/angle/src/libGLESv2/utilities.h +++ b/src/3rdparty/angle/src/libGLESv2/utilities.h @@ -34,6 +34,7 @@ int ComputePixelSize(GLint internalformat); GLsizei ComputePitch(GLsizei width, GLint internalformat, GLint alignment); GLsizei ComputeCompressedPitch(GLsizei width, GLenum format); GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format); +GLsizei ComputeTypeSize(GLenum type); bool IsCompressed(GLenum format); bool IsDepthTexture(GLenum format); bool IsStencilTexture(GLenum format); diff --git a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h new file mode 100644 index 0000000000..113b126a77 --- /dev/null +++ b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h @@ -0,0 +1,828 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Trace events are for tracking application performance and resource usage. +// Macros are provided to track: +// Begin and end of function calls +// Counters +// +// Events are issued against categories. Whereas LOG's +// categories are statically defined, TRACE categories are created +// implicitly with a string. For example: +// TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent") +// +// Events can be INSTANT, or can be pairs of BEGIN and END in the same scope: +// TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly") +// doSomethingCostly() +// TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly") +// Note: our tools can't always determine the correct BEGIN/END pairs unless +// these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you need them +// to be in separate scopes. +// +// A common use case is to trace entire function scopes. This +// issues a trace BEGIN and END automatically: +// void doSomethingCostly() { +// TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly"); +// ... +// } +// +// Additional parameters can be associated with an event: +// void doSomethingCostly2(int howMuch) { +// TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly", +// "howMuch", howMuch); +// ... +// } +// +// The trace system will automatically add to this information the +// current process id, thread id, and a timestamp in microseconds. +// +// To trace an asynchronous procedure such as an IPC send/receive, use ASYNC_BEGIN and +// ASYNC_END: +// [single threaded sender code] +// static int send_count = 0; +// ++send_count; +// TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count); +// Send(new MyMessage(send_count)); +// [receive code] +// void OnMyMessage(send_count) { +// TRACE_EVENT_ASYNC_END0("ipc", "message", send_count); +// } +// The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs. +// ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process. Pointers can +// be used for the ID parameter, and they will be mangled internally so that +// the same pointer on two different processes will not match. For example: +// class MyTracedClass { +// public: +// MyTracedClass() { +// TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this); +// } +// ~MyTracedClass() { +// TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this); +// } +// } +// +// Trace event also supports counters, which is a way to track a quantity +// as it varies over time. Counters are created with the following macro: +// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue); +// +// Counters are process-specific. The macro itself can be issued from any +// thread, however. +// +// Sometimes, you want to track two counters at once. You can do this with two +// counter macros: +// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]); +// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]); +// Or you can do it with a combined macro: +// TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter", +// "bytesPinned", g_myCounterValue[0], +// "bytesAllocated", g_myCounterValue[1]); +// This indicates to the tracing UI that these counters should be displayed +// in a single graph, as a summed area chart. +// +// Since counters are in a global namespace, you may want to disembiguate with a +// unique ID, by using the TRACE_COUNTER_ID* variations. +// +// By default, trace collection is compiled in, but turned off at runtime. +// Collecting trace data is the responsibility of the embedding +// application. In Chrome's case, navigating to about:tracing will turn on +// tracing and display data collected across all active processes. +// +// +// Memory scoping note: +// Tracing copies the pointers, not the string content, of the strings passed +// in for category, name, and arg_names. Thus, the following code will +// cause problems: +// char* str = strdup("impprtantName"); +// TRACE_EVENT_INSTANT0("SUBSYSTEM", str); // BAD! +// free(str); // Trace system now has dangling pointer +// +// To avoid this issue with the |name| and |arg_name| parameters, use the +// TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime overhead. +// Notes: The category must always be in a long-lived char* (i.e. static const). +// The |arg_values|, when used, are always deep copied with the _COPY +// macros. +// +// When are string argument values copied: +// const char* arg_values are only referenced by default: +// TRACE_EVENT1("category", "name", +// "arg1", "literal string is only referenced"); +// Use TRACE_STR_COPY to force copying of a const char*: +// TRACE_EVENT1("category", "name", +// "arg1", TRACE_STR_COPY("string will be copied")); +// std::string arg_values are always copied: +// TRACE_EVENT1("category", "name", +// "arg1", std::string("string will be copied")); +// +// +// Thread Safety: +// A thread safe singleton and mutex are used for thread safety. Category +// enabled flags are used to limit the performance impact when the system +// is not enabled. +// +// TRACE_EVENT macros first cache a pointer to a category. The categories are +// statically allocated and safe at all times, even after exit. Fetching a +// category is protected by the TraceLog::lock_. Multiple threads initializing +// the static variable is safe, as they will be serialized by the lock and +// multiple calls will return the same pointer to the category. +// +// Then the category_enabled flag is checked. This is a unsigned char, and +// not intended to be multithread safe. It optimizes access to addTraceEvent +// which is threadsafe internally via TraceLog::lock_. The enabled flag may +// cause some threads to incorrectly call or skip calling addTraceEvent near +// the time of the system being enabled or disabled. This is acceptable as +// we tolerate some data loss while the system is being enabled/disabled and +// because addTraceEvent is threadsafe internally and checks the enabled state +// again under lock. +// +// Without the use of these static category pointers and enabled flags all +// trace points would carry a significant performance cost of aquiring a lock +// and resolving the category. + +#ifndef COMMON_TRACE_EVENT_H_ +#define COMMON_TRACE_EVENT_H_ + +#include + +#include "common/event_tracer.h" + +// By default, const char* argument values are assumed to have long-lived scope +// and will not be copied. Use this macro to force a const char* to be copied. +#define TRACE_STR_COPY(str) \ + WebCore::TraceEvent::TraceStringWithCopy(str) + +// Records a pair of begin and end events called "name" for the current +// scope, with 0, 1 or 2 associated arguments. If the category is not +// enabled, then this does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_EVENT0(category, name) \ + INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name) +#define TRACE_EVENT1(category, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, arg1_name, arg1_val) +#define TRACE_EVENT2(category, name, arg1_name, arg1_val, arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) + +// Records a single event called "name" immediately, with 0, 1 or 2 +// associated arguments. If the category is not enabled, then this +// does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_EVENT_INSTANT0(category, name) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category, name, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_INSTANT1(category, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) +#define TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ + arg2_name, arg2_val) +#define TRACE_EVENT_COPY_INSTANT0(category, name) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category, name, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_INSTANT1(category, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) +#define TRACE_EVENT_COPY_INSTANT2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \ + arg2_name, arg2_val) + +// Records a single BEGIN event called "name" immediately, with 0, 1 or 2 +// associated arguments. If the category is not enabled, then this +// does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_EVENT_BEGIN0(category, name) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category, name, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_BEGIN1(category, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) +#define TRACE_EVENT_BEGIN2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ + arg2_name, arg2_val) +#define TRACE_EVENT_COPY_BEGIN0(category, name) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category, name, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_BEGIN1(category, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) +#define TRACE_EVENT_COPY_BEGIN2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \ + arg2_name, arg2_val) + +// Records a single END event for "name" immediately. If the category +// is not enabled, then this does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_EVENT_END0(category, name) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category, name, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_END1(category, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) +#define TRACE_EVENT_END2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ + arg2_name, arg2_val) +#define TRACE_EVENT_COPY_END0(category, name) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category, name, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_END1(category, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) +#define TRACE_EVENT_COPY_END2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \ + arg2_name, arg2_val) + +// Records the value of a counter called "name" immediately. Value +// must be representable as a 32 bit integer. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_COUNTER1(category, name, value) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ + category, name, TRACE_EVENT_FLAG_NONE, \ + "value", static_cast(value)) +#define TRACE_COPY_COUNTER1(category, name, value) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ + category, name, TRACE_EVENT_FLAG_COPY, \ + "value", static_cast(value)) + +// Records the values of a multi-parted counter called "name" immediately. +// The UI will treat value1 and value2 as parts of a whole, displaying their +// values as a stacked-bar chart. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_COUNTER2(category, name, value1_name, value1_val, \ + value2_name, value2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ + category, name, TRACE_EVENT_FLAG_NONE, \ + value1_name, static_cast(value1_val), \ + value2_name, static_cast(value2_val)) +#define TRACE_COPY_COUNTER2(category, name, value1_name, value1_val, \ + value2_name, value2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ + category, name, TRACE_EVENT_FLAG_COPY, \ + value1_name, static_cast(value1_val), \ + value2_name, static_cast(value2_val)) + +// Records the value of a counter called "name" immediately. Value +// must be representable as a 32 bit integer. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +// - |id| is used to disambiguate counters with the same name. It must either +// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits +// will be xored with a hash of the process ID so that the same pointer on +// two different processes will not collide. +#define TRACE_COUNTER_ID1(category, name, id, value) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ + category, name, id, TRACE_EVENT_FLAG_NONE, \ + "value", static_cast(value)) +#define TRACE_COPY_COUNTER_ID1(category, name, id, value) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ + category, name, id, TRACE_EVENT_FLAG_COPY, \ + "value", static_cast(value)) + +// Records the values of a multi-parted counter called "name" immediately. +// The UI will treat value1 and value2 as parts of a whole, displaying their +// values as a stacked-bar chart. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +// - |id| is used to disambiguate counters with the same name. It must either +// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits +// will be xored with a hash of the process ID so that the same pointer on +// two different processes will not collide. +#define TRACE_COUNTER_ID2(category, name, id, value1_name, value1_val, \ + value2_name, value2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ + category, name, id, TRACE_EVENT_FLAG_NONE, \ + value1_name, static_cast(value1_val), \ + value2_name, static_cast(value2_val)) +#define TRACE_COPY_COUNTER_ID2(category, name, id, value1_name, value1_val, \ + value2_name, value2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ + category, name, id, TRACE_EVENT_FLAG_COPY, \ + value1_name, static_cast(value1_val), \ + value2_name, static_cast(value2_val)) + +// Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2 +// associated arguments. If the category is not enabled, then this +// does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +// - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event. ASYNC +// events are considered to match if their category, name and id values all +// match. |id| must either be a pointer or an integer value up to 64 bits. If +// it's a pointer, the bits will be xored with a hash of the process ID so +// that the same pointer on two different processes will not collide. +// An asynchronous operation can consist of multiple phases. The first phase is +// defined by the ASYNC_BEGIN calls. Additional phases can be defined using the +// ASYNC_STEP_BEGIN macros. When the operation completes, call ASYNC_END. +// An async operation can span threads and processes, but all events in that +// operation must use the same |name| and |id|. Each event can have its own +// args. +#define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category, name, id, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) +#define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category, name, id, TRACE_EVENT_FLAG_NONE, \ + arg1_name, arg1_val, arg2_name, arg2_val) +#define TRACE_EVENT_COPY_ASYNC_BEGIN0(category, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category, name, id, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category, name, id, TRACE_EVENT_FLAG_COPY, \ + arg1_name, arg1_val) +#define TRACE_EVENT_COPY_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category, name, id, TRACE_EVENT_FLAG_COPY, \ + arg1_name, arg1_val, arg2_name, arg2_val) + +// Records a single ASYNC_STEP event for |step| immediately. If the category +// is not enabled, then this does nothing. The |name| and |id| must match the +// ASYNC_BEGIN event above. The |step| param identifies this step within the +// async event. This should be called at the beginning of the next phase of an +// asynchronous operation. +#define TRACE_EVENT_ASYNC_STEP0(category, name, id, step) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \ + category, name, id, TRACE_EVENT_FLAG_NONE, "step", step) +#define TRACE_EVENT_ASYNC_STEP1(category, name, id, step, \ + arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \ + category, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \ + arg1_name, arg1_val) +#define TRACE_EVENT_COPY_ASYNC_STEP0(category, name, id, step) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \ + category, name, id, TRACE_EVENT_FLAG_COPY, "step", step) +#define TRACE_EVENT_COPY_ASYNC_STEP1(category, name, id, step, \ + arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \ + category, name, id, TRACE_EVENT_FLAG_COPY, "step", step, \ + arg1_name, arg1_val) + +// Records a single ASYNC_END event for "name" immediately. If the category +// is not enabled, then this does nothing. +#define TRACE_EVENT_ASYNC_END0(category, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category, name, id, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) +#define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category, name, id, TRACE_EVENT_FLAG_NONE, \ + arg1_name, arg1_val, arg2_name, arg2_val) +#define TRACE_EVENT_COPY_ASYNC_END0(category, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category, name, id, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_ASYNC_END1(category, name, id, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category, name, id, TRACE_EVENT_FLAG_COPY, \ + arg1_name, arg1_val) +#define TRACE_EVENT_COPY_ASYNC_END2(category, name, id, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category, name, id, TRACE_EVENT_FLAG_COPY, \ + arg1_name, arg1_val, arg2_name, arg2_val) + +// Creates a scope of a sampling state with the given category and name (both must +// be constant strings). These states are intended for a sampling profiler. +// Implementation note: we store category and name together because we don't +// want the inconsistency/expense of storing two pointers. +// |thread_bucket| is [0..2] and is used to statically isolate samples in one +// thread from others. +// +// { // The sampling state is set within this scope. +// TRACE_EVENT_SAMPLING_STATE_SCOPE_FOR_BUCKET(0, "category", "name"); +// ...; +// } +#define TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \ + TraceEvent::SamplingStateScope traceEventSamplingScope(category "\0" name); + +// Returns a current sampling state of the given bucket. +// The format of the returned string is "category\0name". +#define TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(bucket_number) \ + TraceEvent::SamplingStateScope::current() + +// Sets a current sampling state of the given bucket. +// |category| and |name| have to be constant strings. +#define TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \ + TraceEvent::SamplingStateScope::set(category "\0" name) + +// Sets a current sampling state of the given bucket. +// |categoryAndName| doesn't need to be a constant string. +// The format of the string is "category\0name". +#define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(bucket_number, categoryAndName) \ + TraceEvent::SamplingStateScope::set(categoryAndName) + +// Syntactic sugars for the sampling tracing in the main thread. +#define TRACE_EVENT_SCOPED_SAMPLING_STATE(category, name) \ + TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(0, category, name) +#define TRACE_EVENT_GET_SAMPLING_STATE() \ + TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(0) +#define TRACE_EVENT_SET_SAMPLING_STATE(category, name) \ + TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(0, category, name) +#define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(categoryAndName) \ + TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(0, categoryAndName) + +//////////////////////////////////////////////////////////////////////////////// +// Implementation specific tracing API definitions. + +// Get a pointer to the enabled state of the given trace category. Only +// long-lived literal strings should be given as the category name. The returned +// pointer can be held permanently in a local static for example. If the +// unsigned char is non-zero, tracing is enabled. If tracing is enabled, +// TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled +// between the load of the tracing state and the call to +// TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out +// for best performance when tracing is disabled. +// const unsigned char* +// TRACE_EVENT_API_GET_CATEGORY_ENABLED(const char* category_name) +#define TRACE_EVENT_API_GET_CATEGORY_ENABLED \ + gl::TraceGetTraceCategoryEnabledFlag + +// Add a trace event to the platform tracing system. +// void TRACE_EVENT_API_ADD_TRACE_EVENT( +// char phase, +// const unsigned char* category_enabled, +// const char* name, +// unsigned long long id, +// int num_args, +// const char** arg_names, +// const unsigned char* arg_types, +// const unsigned long long* arg_values, +// unsigned char flags) +#define TRACE_EVENT_API_ADD_TRACE_EVENT \ + gl::TraceAddTraceEvent + +//////////////////////////////////////////////////////////////////////////////// + +// Implementation detail: trace event macros create temporary variables +// to keep instrumentation overhead low. These macros give each temporary +// variable a unique name based on the line number to prevent name collissions. +#define INTERNAL_TRACE_EVENT_UID3(a, b) \ + trace_event_unique_##a##b +#define INTERNAL_TRACE_EVENT_UID2(a, b) \ + INTERNAL_TRACE_EVENT_UID3(a, b) +#define INTERNALTRACEEVENTUID(name_prefix) \ + INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__) + +// Implementation detail: internal macro to create static category. +#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category) \ + static const unsigned char* INTERNALTRACEEVENTUID(catstatic) = 0; \ + if (!INTERNALTRACEEVENTUID(catstatic)) \ + INTERNALTRACEEVENTUID(catstatic) = \ + TRACE_EVENT_API_GET_CATEGORY_ENABLED(category); + +// Implementation detail: internal macro to create static category and add +// event if the category is enabled. +#define INTERNAL_TRACE_EVENT_ADD(phase, category, name, flags, ...) \ + do { \ + INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \ + if (*INTERNALTRACEEVENTUID(catstatic)) { \ + gl::TraceEvent::addTraceEvent( \ + phase, INTERNALTRACEEVENTUID(catstatic), name, \ + gl::TraceEvent::noEventId, flags, ##__VA_ARGS__); \ + } \ + } while (0) + +// Implementation detail: internal macro to create static category and add begin +// event if the category is enabled. Also adds the end event when the scope +// ends. +#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, ...) \ + INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \ + gl::TraceEvent::TraceEndOnScopeClose \ + INTERNALTRACEEVENTUID(profileScope); \ + if (*INTERNALTRACEEVENTUID(catstatic)) { \ + gl::TraceEvent::addTraceEvent( \ + TRACE_EVENT_PHASE_BEGIN, \ + INTERNALTRACEEVENTUID(catstatic), \ + name, gl::TraceEvent::noEventId, \ + TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \ + INTERNALTRACEEVENTUID(profileScope).initialize( \ + INTERNALTRACEEVENTUID(catstatic), name); \ + } + +// Implementation detail: internal macro to create static category and add +// event if the category is enabled. +#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category, name, id, flags, \ + ...) \ + do { \ + INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \ + if (*INTERNALTRACEEVENTUID(catstatic)) { \ + unsigned char traceEventFlags = flags | TRACE_EVENT_FLAG_HAS_ID; \ + gl::TraceEvent::TraceID traceEventTraceID( \ + id, &traceEventFlags); \ + gl::TraceEvent::addTraceEvent( \ + phase, INTERNALTRACEEVENTUID(catstatic), \ + name, traceEventTraceID.data(), traceEventFlags, \ + ##__VA_ARGS__); \ + } \ + } while (0) + +// Notes regarding the following definitions: +// New values can be added and propagated to third party libraries, but existing +// definitions must never be changed, because third party libraries may use old +// definitions. + +// Phase indicates the nature of an event entry. E.g. part of a begin/end pair. +#define TRACE_EVENT_PHASE_BEGIN ('B') +#define TRACE_EVENT_PHASE_END ('E') +#define TRACE_EVENT_PHASE_INSTANT ('I') +#define TRACE_EVENT_PHASE_ASYNC_BEGIN ('S') +#define TRACE_EVENT_PHASE_ASYNC_STEP ('T') +#define TRACE_EVENT_PHASE_ASYNC_END ('F') +#define TRACE_EVENT_PHASE_METADATA ('M') +#define TRACE_EVENT_PHASE_COUNTER ('C') +#define TRACE_EVENT_PHASE_SAMPLE ('P') + +// Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT. +#define TRACE_EVENT_FLAG_NONE (static_cast(0)) +#define TRACE_EVENT_FLAG_COPY (static_cast(1 << 0)) +#define TRACE_EVENT_FLAG_HAS_ID (static_cast(1 << 1)) +#define TRACE_EVENT_FLAG_MANGLE_ID (static_cast(1 << 2)) + +// Type values for identifying types in the TraceValue union. +#define TRACE_VALUE_TYPE_BOOL (static_cast(1)) +#define TRACE_VALUE_TYPE_UINT (static_cast(2)) +#define TRACE_VALUE_TYPE_INT (static_cast(3)) +#define TRACE_VALUE_TYPE_DOUBLE (static_cast(4)) +#define TRACE_VALUE_TYPE_POINTER (static_cast(5)) +#define TRACE_VALUE_TYPE_STRING (static_cast(6)) +#define TRACE_VALUE_TYPE_COPY_STRING (static_cast(7)) + + +namespace gl { + +extern long **traceSamplingState; + +namespace TraceEvent { + +// Specify these values when the corresponding argument of addTraceEvent is not +// used. +const int zeroNumArgs = 0; +const unsigned long long noEventId = 0; + +// TraceID encapsulates an ID that can either be an integer or pointer. Pointers +// are mangled with the Process ID so that they are unlikely to collide when the +// same pointer is used on different processes. +class TraceID { +public: + explicit TraceID(const void* id, unsigned char* flags) : + m_data(static_cast(reinterpret_cast(id))) + { + *flags |= TRACE_EVENT_FLAG_MANGLE_ID; + } + explicit TraceID(unsigned long long id, unsigned char* flags) : m_data(id) { (void)flags; } + explicit TraceID(unsigned long id, unsigned char* flags) : m_data(id) { (void)flags; } + explicit TraceID(unsigned int id, unsigned char* flags) : m_data(id) { (void)flags; } + explicit TraceID(unsigned short id, unsigned char* flags) : m_data(id) { (void)flags; } + explicit TraceID(unsigned char id, unsigned char* flags) : m_data(id) { (void)flags; } + explicit TraceID(long long id, unsigned char* flags) : + m_data(static_cast(id)) { (void)flags; } + explicit TraceID(long id, unsigned char* flags) : + m_data(static_cast(id)) { (void)flags; } + explicit TraceID(int id, unsigned char* flags) : + m_data(static_cast(id)) { (void)flags; } + explicit TraceID(short id, unsigned char* flags) : + m_data(static_cast(id)) { (void)flags; } + explicit TraceID(signed char id, unsigned char* flags) : + m_data(static_cast(id)) { (void)flags; } + + unsigned long long data() const { return m_data; } + +private: + unsigned long long m_data; +}; + +// Simple union to store various types as unsigned long long. +union TraceValueUnion { + bool m_bool; + unsigned long long m_uint; + long long m_int; + double m_double; + const void* m_pointer; + const char* m_string; +}; + +// Simple container for const char* that should be copied instead of retained. +class TraceStringWithCopy { +public: + explicit TraceStringWithCopy(const char* str) : m_str(str) { } + operator const char* () const { return m_str; } +private: + const char* m_str; +}; + +// Define setTraceValue for each allowed type. It stores the type and +// value in the return arguments. This allows this API to avoid declaring any +// structures so that it is portable to third_party libraries. +#define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, \ + union_member, \ + value_type_id) \ + static inline void setTraceValue(actual_type arg, \ + unsigned char* type, \ + unsigned long long* value) { \ + TraceValueUnion typeValue; \ + typeValue.union_member = arg; \ + *type = value_type_id; \ + *value = typeValue.m_uint; \ + } +// Simpler form for int types that can be safely casted. +#define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, \ + value_type_id) \ + static inline void setTraceValue(actual_type arg, \ + unsigned char* type, \ + unsigned long long* value) { \ + *type = value_type_id; \ + *value = static_cast(arg); \ + } + +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT) +INTERNAL_DECLARE_SET_TRACE_VALUE(bool, m_bool, TRACE_VALUE_TYPE_BOOL) +INTERNAL_DECLARE_SET_TRACE_VALUE(double, m_double, TRACE_VALUE_TYPE_DOUBLE) +INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, m_pointer, + TRACE_VALUE_TYPE_POINTER) +INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, m_string, + TRACE_VALUE_TYPE_STRING) +INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, m_string, + TRACE_VALUE_TYPE_COPY_STRING) + +#undef INTERNAL_DECLARE_SET_TRACE_VALUE +#undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT + +static inline void setTraceValue(const std::string& arg, + unsigned char* type, + unsigned long long* value) { + TraceValueUnion typeValue; + typeValue.m_string = arg.data(); + *type = TRACE_VALUE_TYPE_COPY_STRING; + *value = typeValue.m_uint; +} + +// These addTraceEvent template functions are defined here instead of in the +// macro, because the arg values could be temporary string objects. In order to +// store pointers to the internal c_str and pass through to the tracing API, the +// arg values must live throughout these procedures. + +static inline void addTraceEvent(char phase, + const unsigned char* categoryEnabled, + const char* name, + unsigned long long id, + unsigned char flags) { + TRACE_EVENT_API_ADD_TRACE_EVENT( + phase, categoryEnabled, name, id, + zeroNumArgs, 0, 0, 0, + flags); +} + +template +static inline void addTraceEvent(char phase, + const unsigned char* categoryEnabled, + const char* name, + unsigned long long id, + unsigned char flags, + const char* arg1Name, + const ARG1_TYPE& arg1Val) { + const int numArgs = 1; + unsigned char argTypes[1]; + unsigned long long argValues[1]; + setTraceValue(arg1Val, &argTypes[0], &argValues[0]); + TRACE_EVENT_API_ADD_TRACE_EVENT( + phase, categoryEnabled, name, id, + numArgs, &arg1Name, argTypes, argValues, + flags); +} + +template +static inline void addTraceEvent(char phase, + const unsigned char* categoryEnabled, + const char* name, + unsigned long long id, + unsigned char flags, + const char* arg1Name, + const ARG1_TYPE& arg1Val, + const char* arg2Name, + const ARG2_TYPE& arg2Val) { + const int numArgs = 2; + const char* argNames[2] = { arg1Name, arg2Name }; + unsigned char argTypes[2]; + unsigned long long argValues[2]; + setTraceValue(arg1Val, &argTypes[0], &argValues[0]); + setTraceValue(arg2Val, &argTypes[1], &argValues[1]); + return TRACE_EVENT_API_ADD_TRACE_EVENT( + phase, categoryEnabled, name, id, + numArgs, argNames, argTypes, argValues, + flags); +} + +// Used by TRACE_EVENTx macro. Do not use directly. +class TraceEndOnScopeClose { +public: + // Note: members of m_data intentionally left uninitialized. See initialize. + TraceEndOnScopeClose() : m_pdata(0) { } + ~TraceEndOnScopeClose() + { + if (m_pdata) + addEventIfEnabled(); + } + + void initialize(const unsigned char* categoryEnabled, + const char* name) + { + m_data.categoryEnabled = categoryEnabled; + m_data.name = name; + m_pdata = &m_data; + } + +private: + // Add the end event if the category is still enabled. + void addEventIfEnabled() + { + // Only called when m_pdata is non-null. + if (*m_pdata->categoryEnabled) { + TRACE_EVENT_API_ADD_TRACE_EVENT( + TRACE_EVENT_PHASE_END, + m_pdata->categoryEnabled, + m_pdata->name, noEventId, + zeroNumArgs, 0, 0, 0, + TRACE_EVENT_FLAG_NONE); + } + } + + // This Data struct workaround is to avoid initializing all the members + // in Data during construction of this object, since this object is always + // constructed, even when tracing is disabled. If the members of Data were + // members of this class instead, compiler warnings occur about potential + // uninitialized accesses. + struct Data { + const unsigned char* categoryEnabled; + const char* name; + }; + Data* m_pdata; + Data m_data; +}; + +// TraceEventSamplingStateScope records the current sampling state +// and sets a new sampling state. When the scope exists, it restores +// the sampling state having recorded. +template +class SamplingStateScope { +public: + SamplingStateScope(const char* categoryAndName) + { + m_previousState = SamplingStateScope::current(); + SamplingStateScope::set(categoryAndName); + } + + ~SamplingStateScope() + { + SamplingStateScope::set(m_previousState); + } + + // FIXME: Make load/store to traceSamplingState[] thread-safe and atomic. + static inline const char* current() + { + return reinterpret_cast(*gl::traceSamplingState[BucketNumber]); + } + static inline void set(const char* categoryAndName) + { + *gl::traceSamplingState[BucketNumber] = reinterpret_cast(const_cast(categoryAndName)); + } + +private: + const char* m_previousState; +}; + +} // namespace TraceEvent + +} // namespace gl + +#endif diff --git a/src/angle/patches/0001-Dynamically-resolve-functions-of-dwmapi.dll.patch b/src/angle/patches/0001-Dynamically-resolve-functions-of-dwmapi.dll.patch deleted file mode 100644 index b259aa3f80..0000000000 --- a/src/angle/patches/0001-Dynamically-resolve-functions-of-dwmapi.dll.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 211954dffc6a0ee52db130017ae4bea00e80748f Mon Sep 17 00:00:00 2001 -From: Friedemann Kleint -Date: Mon, 18 Mar 2013 15:35:13 +0200 -Subject: [PATCH 1/6] Dynamically resolve functions of dwmapi.dll. - -The library is not present on Windows XP, for which /DELAYLOAD -is used in ANGLE. However, as this causes problems with MinGW, -use dynamic resolution. - -Task-number: QTBUG-27741 -Change-Id: I16214d6f98a184d89858c50ee5306371ea25469e ---- - src/3rdparty/angle/src/libEGL/Surface.cpp | 39 ++++++++++++++++++++++++++++----------- - 1 file changed, 28 insertions(+), 11 deletions(-) - -diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp -index 78203b0..5ece724 100644 ---- a/src/3rdparty/angle/src/libEGL/Surface.cpp -+++ b/src/3rdparty/angle/src/libEGL/Surface.cpp -@@ -71,6 +71,9 @@ Surface::~Surface() - - bool Surface::initialize() - { -+ typedef HRESULT (STDAPICALLTYPE *PtrDwmIsCompositionEnabled)(BOOL*); -+ typedef HRESULT (STDAPICALLTYPE *PtrDwmSetPresentParameters)(HWND, DWM_PRESENT_PARAMETERS *); -+ - if (!resetSwapChain()) - return false; - -@@ -78,17 +81,31 @@ bool Surface::initialize() - // to minimize the amount of queuing done by DWM between our calls to - // present and the actual screen. - if (mWindow && (getComparableOSVersion() >= versionWindowsVista)) { -- 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); -+ // 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); -+ } - } - } - --- -1.8.1.msysgit.1 - diff --git a/src/angle/patches/0001-Make-it-possible-to-link-ANGLE-statically-for-single.patch b/src/angle/patches/0001-Make-it-possible-to-link-ANGLE-statically-for-single.patch index 9133ac73ae..9de8c54fb6 100644 --- a/src/angle/patches/0001-Make-it-possible-to-link-ANGLE-statically-for-single.patch +++ b/src/angle/patches/0001-Make-it-possible-to-link-ANGLE-statically-for-single.patch @@ -1,35 +1,34 @@ -From cbe9afef7cd467c41353e8a41544d86807be7dd2 Mon Sep 17 00:00:00 2001 +From f1eeb288ae18f3015f435fc2df25ec1eb0f15e1a Mon Sep 17 00:00:00 2001 From: Friedemann Kleint -Date: Thu, 14 Feb 2013 09:40:30 +0100 -Subject: [PATCH] Make it possible to link ANGLE statically for single-thread - use. +Date: Sat, 14 Sep 2013 11:07:17 +0300 +Subject: [PATCH] Make it possible to link ANGLE statically for + single-thread use. Fix exports and provide static instances of thread-local data depending on QT_OPENGL_ES_2_ANGLE_STATIC. Change-Id: Ifab25a820adf5953bb3b09036de53dbf7f1a7fd5 --- - src/3rdparty/angle/include/KHR/khrplatform.h | 3 +- - src/3rdparty/angle/src/libEGL/main.cpp | 58 ++++++++++++++-------------- - src/3rdparty/angle/src/libGLESv2/main.cpp | 32 ++++++++++----- - 3 files changed, 53 insertions(+), 40 deletions(-) + src/3rdparty/angle/include/KHR/khrplatform.h | 2 +- + src/3rdparty/angle/src/libEGL/main.cpp | 35 ++++++++++++++++++++-------- + src/3rdparty/angle/src/libGLESv2/main.cpp | 21 ++++++++++++++--- + 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/src/3rdparty/angle/include/KHR/khrplatform.h b/src/3rdparty/angle/include/KHR/khrplatform.h -index 56c676c..18a104e 100644 +index 8ec0d19..541bfa9 100644 --- a/src/3rdparty/angle/include/KHR/khrplatform.h +++ b/src/3rdparty/angle/include/KHR/khrplatform.h -@@ -97,7 +97,8 @@ +@@ -97,7 +97,7 @@ *------------------------------------------------------------------------- * This precedes the return type of the function in the function prototype. */ -#if defined(_WIN32) && !defined(__SCITECH_SNAP__) -+ +#if defined(_WIN32) && !defined(__SCITECH_SNAP__) && !defined(QT_OPENGL_ES_2_ANGLE_STATIC) # define KHRONOS_APICALL __declspec(dllimport) #elif defined (__SYMBIAN32__) # define KHRONOS_APICALL IMPORT_C diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp -index dc24c4f..614bcf6 100644 +index 424ec3f..7dea5fc 100644 --- a/src/3rdparty/angle/src/libEGL/main.cpp +++ b/src/3rdparty/angle/src/libEGL/main.cpp @@ -10,6 +10,8 @@ @@ -41,178 +40,161 @@ index dc24c4f..614bcf6 100644 static DWORD currentTLS = TLS_OUT_OF_INDEXES; extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) -@@ -86,76 +88,72 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved +@@ -86,74 +88,87 @@ 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 *current = (Current*)TlsGetValue(currentTLS); -- -- current->error = error; -+ current()->error = error; ++ Current *current = getCurrent(); + + current->error = error; } EGLint getCurrentError() { - Current *current = (Current*)TlsGetValue(currentTLS); -- -- return current->error; -+ return current()->error; ++ Current *current = getCurrent(); + + return current->error; } void setCurrentAPI(EGLenum API) { - Current *current = (Current*)TlsGetValue(currentTLS); -- -- current->API = API; -+ current()->API = API; ++ Current *current = getCurrent(); + + current->API = API; } EGLenum getCurrentAPI() { - Current *current = (Current*)TlsGetValue(currentTLS); -- -- return current->API; -+ return current()->API; ++ Current *current = getCurrent(); + + return current->API; } void setCurrentDisplay(EGLDisplay dpy) { - Current *current = (Current*)TlsGetValue(currentTLS); -- -- current->display = dpy; -+ current()->display = dpy; ++ Current *current = getCurrent(); + + current->display = dpy; } EGLDisplay getCurrentDisplay() { - Current *current = (Current*)TlsGetValue(currentTLS); -- -- return current->display; -+ return current()->display; ++ Current *current = getCurrent(); + + return current->display; } void setCurrentDrawSurface(EGLSurface surface) { - Current *current = (Current*)TlsGetValue(currentTLS); -- -- current->drawSurface = surface; -+ current()->drawSurface = surface; ++ Current *current = getCurrent(); + + current->drawSurface = surface; } EGLSurface getCurrentDrawSurface() { - Current *current = (Current*)TlsGetValue(currentTLS); -- -- return current->drawSurface; -+ return current()->drawSurface; ++ Current *current = getCurrent(); + + return current->drawSurface; } void setCurrentReadSurface(EGLSurface surface) { - Current *current = (Current*)TlsGetValue(currentTLS); -- -- current->readSurface = surface; -+ current()->readSurface = surface; ++ Current *current = getCurrent(); + + current->readSurface = surface; } EGLSurface getCurrentReadSurface() { - Current *current = (Current*)TlsGetValue(currentTLS); -- -- return current->readSurface; -+ return current()->readSurface; - } - } ++ Current *current = getCurrent(); + return current->readSurface; + } diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp -index 6e678c2..3853e41 100644 +index 6d7a241..730a6ac 100644 --- a/src/3rdparty/angle/src/libGLESv2/main.cpp +++ b/src/3rdparty/angle/src/libGLESv2/main.cpp -@@ -14,6 +14,8 @@ +@@ -11,6 +11,8 @@ - #include "libGLESv2/Framebuffer.h" + #include "libGLESv2/Context.h" +#ifndef QT_OPENGL_ES_2_ANGLE_STATIC + static DWORD currentTLS = TLS_OUT_OF_INDEXES; extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) -@@ -72,14 +74,30 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved +@@ -69,11 +71,24 @@ 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 *current = (Current*)TlsGetValue(currentTLS); -+ Current *curr = current(); ++ Current *current = getCurrent(); -- current->context = context; -- current->display = display; -+ curr->context = context; -+ curr->display = display; - - if (context && display && surface) - { -@@ -89,9 +107,7 @@ void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface) + current->context = context; + current->display = display; +@@ -86,7 +101,7 @@ void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface) Context *getContext() { - Current *current = (Current*)TlsGetValue(currentTLS); -- -- return current->context; -+ return current()->context; - } ++ Current *current = getCurrent(); - Context *getNonLostContext() -@@ -115,9 +131,7 @@ Context *getNonLostContext() + return current->context; + } +@@ -112,7 +127,7 @@ Context *getNonLostContext() egl::Display *getDisplay() { - Current *current = (Current*)TlsGetValue(currentTLS); -- -- return current->display; -+ return current()->display; - } ++ Current *current = getCurrent(); - IDirect3DDevice9 *getDevice() + return current->display; + } -- -1.8.0.msysgit.0 +1.8.1.msysgit.1 diff --git a/src/angle/patches/0004-Fix-black-screen-after-minimizing-OpenGL-window-with.patch b/src/angle/patches/0004-Fix-black-screen-after-minimizing-OpenGL-window-with.patch index 29852c57fa..6eb84fd02e 100644 --- a/src/angle/patches/0004-Fix-black-screen-after-minimizing-OpenGL-window-with.patch +++ b/src/angle/patches/0004-Fix-black-screen-after-minimizing-OpenGL-window-with.patch @@ -1,7 +1,7 @@ -From 0b8f4889511d7aa8f9f07b16dbf204f378e127a6 Mon Sep 17 00:00:00 2001 +From 991dfbdfc018cb30bc1ac4df429411680b47d674 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen -Date: Mon, 18 Mar 2013 16:27:07 +0200 -Subject: [PATCH 3/6] Fix black screen after minimizing OpenGL window with +Date: Sat, 14 Sep 2013 11:07:45 +0300 +Subject: [PATCH] Fix black screen after minimizing OpenGL window with ANGLE CreateTexture will fail on zero dimensions, so just release old target diff --git a/src/angle/patches/0005-Fix-build-when-SSE2-is-not-available.patch b/src/angle/patches/0005-Fix-build-when-SSE2-is-not-available.patch index 72211aeee0..840f6dc36e 100644 --- a/src/angle/patches/0005-Fix-build-when-SSE2-is-not-available.patch +++ b/src/angle/patches/0005-Fix-build-when-SSE2-is-not-available.patch @@ -1,7 +1,7 @@ -From 61abac6f8da2ed1ca3ab74c8c65e5fd1be3d85ad Mon Sep 17 00:00:00 2001 +From af7cb8e35774f5cba15256cb463da8c1c4d533f3 Mon Sep 17 00:00:00 2001 From: Andy Shaw -Date: Mon, 18 Mar 2013 16:36:40 +0200 -Subject: [PATCH 4/6] Fix build when SSE2 is not available. +Date: Sat, 14 Sep 2013 11:25:53 +0300 +Subject: [PATCH] Fix build when SSE2 is not available. Although SSE2 support is detected at runtime it still may not be available at build time, so we have to ensure it only uses SSE2 @@ -9,9 +9,30 @@ when it is available at build time too. Change-Id: I86c45a6466ab4cec79aa0f62b0d5230a78ad825a --- + src/3rdparty/angle/src/libGLESv2/mathutil.h | 2 ++ src/3rdparty/angle/src/libGLESv2/renderer/Image9.cpp | 4 ++++ - 1 file changed, 4 insertions(+) + 2 files changed, 6 insertions(+) +diff --git a/src/3rdparty/angle/src/libGLESv2/mathutil.h b/src/3rdparty/angle/src/libGLESv2/mathutil.h +index bb48b94..0835486 100644 +--- a/src/3rdparty/angle/src/libGLESv2/mathutil.h ++++ b/src/3rdparty/angle/src/libGLESv2/mathutil.h +@@ -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; + diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Image9.cpp index b3dcc59..53030b7 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Image9.cpp diff --git a/src/angle/patches/0006-Make-DX9-DX11-mutually-exclusive.patch b/src/angle/patches/0006-Make-DX9-DX11-mutually-exclusive.patch index 1e7ab82771..1e618d43c7 100644 --- a/src/angle/patches/0006-Make-DX9-DX11-mutually-exclusive.patch +++ b/src/angle/patches/0006-Make-DX9-DX11-mutually-exclusive.patch @@ -1,19 +1,22 @@ -From a5c113dda327ad3015312c2836b794929d4771ff Mon Sep 17 00:00:00 2001 +From c2eb5746cdf65091932558ac48ae1e6175d45a3c Mon Sep 17 00:00:00 2001 From: Andrew Knight -Date: Thu, 21 Mar 2013 17:12:02 +0200 -Subject: [PATCH 5/6] Make DX9/DX11 mutually exclusive +Date: Sat, 14 Sep 2013 12:01:19 +0300 +Subject: [PATCH] Make DX9/DX11 mutually exclusive -ANGLE dx11proto supports DX9 fallback when DX11 is unavailable. This -patch removes the fallback mechanism and requires that the library be -chosen at build time (by defining ANGLE_ENABLE_D3D11). This is required -for WinRT, because d3d9 is not a support library on that platform. +ANGLE supports selecting the renderer on creation, choosing between +D3D11 and D3D9 backends. This patch removes that feature, and makes the +D3D version a compile-time decision. This makes the binary size smaller +(no extra render is built) and ensures compatibility with Windows Runtime, +which supports only Direct3D 11. + +Change-Id: Id9473e0e631721083fe4026d475e37603a144c37 --- - src/3rdparty/angle/src/common/RefCountObject.cpp | 1 - - src/3rdparty/angle/src/common/debug.cpp | 4 ++++ - src/3rdparty/angle/src/libGLESv2/Texture.cpp | 6 +++++- - src/3rdparty/angle/src/libGLESv2/precompiled.h | 9 ++++++--- - src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp | 37 +++++++++++-------------------------- - 5 files changed, 26 insertions(+), 31 deletions(-) + src/3rdparty/angle/src/common/RefCountObject.cpp | 1 - + src/3rdparty/angle/src/common/debug.cpp | 4 +++ + src/3rdparty/angle/src/libGLESv2/Texture.cpp | 6 +++- + src/3rdparty/angle/src/libGLESv2/precompiled.h | 3 ++ + .../angle/src/libGLESv2/renderer/Renderer.cpp | 37 +++++++--------------- + 5 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/3rdparty/angle/src/common/RefCountObject.cpp b/src/3rdparty/angle/src/common/RefCountObject.cpp index 0364adf..c1ef90c 100644 @@ -25,23 +28,23 @@ index 0364adf..c1ef90c 100644 // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be diff --git a/src/3rdparty/angle/src/common/debug.cpp b/src/3rdparty/angle/src/common/debug.cpp -index 2333740..438d397 100644 +index 2333740..9b93256 100644 --- a/src/3rdparty/angle/src/common/debug.cpp +++ b/src/3rdparty/angle/src/common/debug.cpp @@ -8,7 +8,11 @@ #include "common/debug.h" #include "common/system.h" -+#ifdef ANGLE_ENABLE_D3D11 -+typedef DWORD D3DCOLOR; -+#else ++#ifndef ANGLE_ENABLE_D3D11 #include ++#else ++typedef DWORD D3DCOLOR; +#endif namespace gl { diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.cpp b/src/3rdparty/angle/src/libGLESv2/Texture.cpp -index ae83037..461357a 100644 +index ae83037..72c0a8a 100644 --- a/src/3rdparty/angle/src/libGLESv2/Texture.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Texture.cpp @@ -14,7 +14,11 @@ @@ -49,65 +52,66 @@ index ae83037..461357a 100644 #include "libGLESv2/mathutil.h" #include "libGLESv2/utilities.h" -#include "libGLESv2/renderer/Blit.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" #include "libGLESv2/renderer/Renderer.h" diff --git a/src/3rdparty/angle/src/libGLESv2/precompiled.h b/src/3rdparty/angle/src/libGLESv2/precompiled.h -index a850d57..b8b043c 100644 +index a850d57..50dec6b 100644 --- a/src/3rdparty/angle/src/libGLESv2/precompiled.h +++ b/src/3rdparty/angle/src/libGLESv2/precompiled.h @@ -32,9 +32,12 @@ #include #include --#include --#include --#include -+#if defined(ANGLE_ENABLE_D3D11) -+# include -+# include ++#ifndef ANGLE_ENABLE_D3D11 + #include +#else -+# include + #include + #include +#endif #include #ifdef _MSC_VER diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp -index 8fd3425..64e52c1 100644 +index d1d234b..21ad223 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp -@@ -10,14 +10,13 @@ +@@ -11,8 +11,11 @@ #include "libGLESv2/main.h" #include "libGLESv2/Program.h" #include "libGLESv2/renderer/Renderer.h" --#include "libGLESv2/renderer/Renderer9.h" --#include "libGLESv2/renderer/Renderer11.h" --#include "libGLESv2/utilities.h" -- --#if !defined(ANGLE_ENABLE_D3D11) --// Enables use of the Direct3D 11 API, when available --#define ANGLE_ENABLE_D3D11 0 -+#if defined(ANGLE_ENABLE_D3D11) -+# include "libGLESv2/renderer/Renderer11.h" -+# define D3DERR_OUTOFVIDEOMEMORY MAKE_HRESULT( 1, 0x876, 380 ) ++#ifndef ANGLE_ENABLE_D3D11 + #include "libGLESv2/renderer/Renderer9.h" +#else -+# include "libGLESv2/renderer/Renderer9.h" - #endif -+#include "libGLESv2/utilities.h" + #include "libGLESv2/renderer/Renderer11.h" ++#endif + #include "libGLESv2/utilities.h" + #include "third_party/trace_event/trace_event.h" - #if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) - #define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 -@@ -174,27 +173,13 @@ rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, bool softwareDevi +@@ -21,6 +24,10 @@ + #define ANGLE_ENABLE_D3D11 0 + #endif + ++#ifndef D3DERR_OUTOFVIDEOMEMORY ++#define D3DERR_OUTOFVIDEOMEMORY MAKE_HRESULT(1, 0x876, 380) ++#endif ++ + #ifdef __MINGW32__ + + #ifndef D3DCOMPILER_DLL +@@ -192,34 +199,14 @@ rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayT { rx::Renderer *renderer = NULL; EGLint status = EGL_BAD_ALLOC; - -- if (ANGLE_ENABLE_D3D11) +- if (ANGLE_ENABLE_D3D11 || +- displayId == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || +- displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE) - { - renderer = new rx::Renderer11(display, hDc); - @@ -120,14 +124,19 @@ index 8fd3425..64e52c1 100644 - { - return renderer; - } +- else if (displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE) +- { +- return NULL; +- } - - // Failed to create a D3D11 renderer, try creating a D3D9 renderer - delete renderer; - } -+#if defined(ANGLE_ENABLE_D3D11) ++#if ANGLE_ENABLE_D3D11 + renderer = new rx::Renderer11(display, hDc); +#else + bool softwareDevice = (displayId == EGL_SOFTWARE_DISPLAY_ANGLE); renderer = new rx::Renderer9(display, hDc, softwareDevice); - +#endif diff --git a/src/angle/patches/0007-ANGLE-Fix-typedefs-for-Win64.patch b/src/angle/patches/0007-ANGLE-Fix-typedefs-for-Win64.patch index 63e5bd635b..5779d68e70 100644 --- a/src/angle/patches/0007-ANGLE-Fix-typedefs-for-Win64.patch +++ b/src/angle/patches/0007-ANGLE-Fix-typedefs-for-Win64.patch @@ -1,19 +1,21 @@ -From a8f8f0858f59e6b8e344dfb0bb87e264aac0a13f Mon Sep 17 00:00:00 2001 +From 2c7319083bc7bac6faafdf29b3a1d5440abf1313 Mon Sep 17 00:00:00 2001 From: Jonathan Liu -Date: Thu, 21 Mar 2013 17:28:54 +0200 -Subject: [PATCH 6/6] ANGLE: Fix typedefs for Win64 +Date: Sat, 14 Sep 2013 11:32:01 +0300 +Subject: [PATCH] ANGLE: Fix typedefs for Win64 The long int type is incorrect for Windows 64-bit as LLP64 is used there. + +Change-Id: Ibbe6f94bffd511ab1285020c89874021a762c2af --- src/3rdparty/angle/include/KHR/khrplatform.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/3rdparty/angle/include/KHR/khrplatform.h b/src/3rdparty/angle/include/KHR/khrplatform.h -index b169773..18a104e 100644 +index 541bfa9..001e925 100644 --- a/src/3rdparty/angle/include/KHR/khrplatform.h +++ b/src/3rdparty/angle/include/KHR/khrplatform.h -@@ -222,10 +222,17 @@ typedef signed char khronos_int8_t; +@@ -221,10 +221,17 @@ typedef signed char khronos_int8_t; typedef unsigned char khronos_uint8_t; typedef signed short int khronos_int16_t; typedef unsigned short int khronos_uint16_t; diff --git a/src/angle/patches/0008-ANGLE-DX11-Prevent-assert-when-view-is-minimized-or-.patch b/src/angle/patches/0008-ANGLE-DX11-Prevent-assert-when-view-is-minimized-or-.patch index 47ecc25f0c..10b36c2096 100644 --- a/src/angle/patches/0008-ANGLE-DX11-Prevent-assert-when-view-is-minimized-or-.patch +++ b/src/angle/patches/0008-ANGLE-DX11-Prevent-assert-when-view-is-minimized-or-.patch @@ -1,6 +1,6 @@ -From 654677720bd856b59387cfd034f441eba8c0e97f Mon Sep 17 00:00:00 2001 +From 6f4600a842bbc7438c8d330305de82b960598ad3 Mon Sep 17 00:00:00 2001 From: Andrew Knight -Date: Thu, 4 Apr 2013 14:21:58 +0300 +Date: Sun, 15 Sep 2013 00:18:44 +0300 Subject: [PATCH] ANGLE DX11: Prevent assert when view is minimized or size goes to 0x0 @@ -18,10 +18,10 @@ Change-Id: Ia60c4c694090d03c1da7f43c56e90b925c8eab6d 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp -index 5ece724..8387443 100644 +index 311790c..b47a7bc 100644 --- a/src/3rdparty/angle/src/libEGL/Surface.cpp +++ b/src/3rdparty/angle/src/libEGL/Surface.cpp -@@ -172,9 +172,16 @@ bool Surface::resetSwapChain() +@@ -135,9 +135,16 @@ bool Surface::resetSwapChain() bool Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight) { @@ -40,10 +40,10 @@ index 5ece724..8387443 100644 if (status == EGL_CONTEXT_LOST) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp -index 87422be..98f8875 100644 +index a50db3b..0da58cb 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp -@@ -368,6 +368,9 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) +@@ -369,6 +369,9 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) return EGL_BAD_ACCESS; } diff --git a/src/angle/patches/0009-ANGLE-Avoid-memory-copies-on-buffers-when-data-is-nu.patch b/src/angle/patches/0009-ANGLE-Avoid-memory-copies-on-buffers-when-data-is-nu.patch deleted file mode 100644 index cecff5c0e8..0000000000 --- a/src/angle/patches/0009-ANGLE-Avoid-memory-copies-on-buffers-when-data-is-nu.patch +++ /dev/null @@ -1,72 +0,0 @@ -From cde4cd6155791355872f635491630c21c791e7f4 Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Fri, 5 Apr 2013 15:11:59 +0300 -Subject: [PATCH] ANGLE: Avoid memory copies on buffers when data is null - -With data=0, ANGLE can crash when setting the buffer data. As this -should be a legal operation, don't perform a memcpy when data is null. - -Change-Id: I3fa1260482549b1da50d7a68001a65decb98f258 ---- - src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp | 22 ++++++++++++++++------ - src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp | 3 ++- - 2 files changed, 18 insertions(+), 7 deletions(-) - -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp -index 4c37bdb..7fe9e6b 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp -@@ -182,7 +182,8 @@ void BufferStorage11::setData(const void* data, unsigned int size, unsigned int - return gl::error(GL_OUT_OF_MEMORY); - } - -- memcpy(mappedResource.pData, data, size); -+ if (data) -+ memcpy(mappedResource.pData, data, size); - - context->Unmap(mStagingBuffer, 0); - } -@@ -211,12 +212,21 @@ void BufferStorage11::setData(const void* data, unsigned int size, unsigned int - mBufferSize = 0; - } - -- D3D11_SUBRESOURCE_DATA initialData; -- initialData.pSysMem = data; -- initialData.SysMemPitch = size; -- initialData.SysMemSlicePitch = 0; - -- result = device->CreateBuffer(&bufferDesc, &initialData, &mBuffer); -+ if (data) -+ { -+ D3D11_SUBRESOURCE_DATA initialData; -+ initialData.pSysMem = data; -+ initialData.SysMemPitch = size; -+ initialData.SysMemSlicePitch = 0; -+ -+ result = device->CreateBuffer(&bufferDesc, &initialData, &mBuffer); -+ } -+ else -+ { -+ result = device->CreateBuffer(&bufferDesc, NULL, &mBuffer); -+ } -+ - if (FAILED(result)) - { - return gl::error(GL_OUT_OF_MEMORY); -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp -index 7fc14fc..4468461 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp -@@ -54,7 +54,8 @@ void BufferStorage9::setData(const void* data, unsigned int size, unsigned int o - } - - mSize = std::max(mSize, offset + size); -- memcpy(reinterpret_cast(mMemory) + offset, data, size); -+ if (data) -+ memcpy(reinterpret_cast(mMemory) + offset, data, size); - } - - void BufferStorage9::clear() --- -1.8.1.msysgit.1 - diff --git a/src/angle/patches/0010-Add-missing-intrin.h-include-for-__cpuid.patch b/src/angle/patches/0010-Add-missing-intrin.h-include-for-__cpuid.patch deleted file mode 100644 index ebe3de4dc9..0000000000 --- a/src/angle/patches/0010-Add-missing-intrin.h-include-for-__cpuid.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 142312b5cbea10257b6d3693b48817ae657018eb Mon Sep 17 00:00:00 2001 -From: Kai Koehne -Date: Mon, 22 Apr 2013 16:36:17 +0200 -Subject: [PATCH] Add missing intrin.h include for __cpuid - -This is already fixed upstream in - -https://codereview.appspot.com/8615046/patch/1/2 - -Change-Id: I4b9e865f6b5622c484418a8381334381bc256887 ---- - src/3rdparty/angle/src/libGLESv2/mathutil.h | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/3rdparty/angle/src/libGLESv2/mathutil.h b/src/3rdparty/angle/src/libGLESv2/mathutil.h -index 672c443..bb48b94 100644 ---- a/src/3rdparty/angle/src/libGLESv2/mathutil.h -+++ b/src/3rdparty/angle/src/libGLESv2/mathutil.h -@@ -9,6 +9,8 @@ - #ifndef LIBGLESV2_MATHUTIL_H_ - #define LIBGLESV2_MATHUTIL_H_ - -+#include -+ - #include "common/system.h" - #include "common/debug.h" - --- -1.8.1.msysgit.1 - diff --git a/src/angle/patches/0011-Fix-compilation-of-libGLESv2-with-older-MinGW-w64-he.patch b/src/angle/patches/0011-Fix-compilation-of-libGLESv2-with-older-MinGW-w64-he.patch index f104a273cc..9189501b59 100644 --- a/src/angle/patches/0011-Fix-compilation-of-libGLESv2-with-older-MinGW-w64-he.patch +++ b/src/angle/patches/0011-Fix-compilation-of-libGLESv2-with-older-MinGW-w64-he.patch @@ -1,6 +1,6 @@ -From 82fd5de3ae5e242730fdaf8044f17227337d881c Mon Sep 17 00:00:00 2001 +From 6d8be1da6a5a5177289200247f98e0200e0e3df3 Mon Sep 17 00:00:00 2001 From: Kai Koehne -Date: Wed, 10 Jul 2013 14:00:13 +0200 +Date: Sat, 14 Sep 2013 11:38:47 +0300 Subject: [PATCH] Fix compilation of libGLESv2 with older MinGW-w64 headers Fix compilation of libGLESv2 for mingw-headers predating MinGW-w64 @@ -18,11 +18,11 @@ Change-Id: I31272a1a991c4fc0f1611f8fb7510be51d6bb925 1 file changed, 19 insertions(+) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp -index 41cdb8b..218356c 100644 +index 70b9326..d1d234b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp -@@ -22,6 +22,25 @@ - #define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 +@@ -21,6 +21,25 @@ + #define ANGLE_ENABLE_D3D11 0 #endif +#ifdef __MINGW32__ @@ -48,5 +48,5 @@ index 41cdb8b..218356c 100644 { -- -1.8.3.msysgit.0 +1.8.1.msysgit.1 diff --git a/src/angle/src/common/common.pri b/src/angle/src/common/common.pri index d16202b6d6..a94b9a6fc3 100644 --- a/src/angle/src/common/common.pri +++ b/src/angle/src/common/common.pri @@ -45,10 +45,12 @@ static: DEFINES *= QT_OPENGL_ES_2_ANGLE_STATIC HEADERS += \ $$ANGLE_DIR/src/common/angleutils.h \ $$ANGLE_DIR/src/common/debug.h \ + $$ANGLE_DIR/src/common/event_tracer.h \ $$ANGLE_DIR/src/common/RefCountObject.h \ $$ANGLE_DIR/src/common/version.h SOURCES += \ $$ANGLE_DIR/src/common/debug.cpp \ + $$ANGLE_DIR/src/common/event_tracer.cpp \ $$ANGLE_DIR/src/common/RefCountObject.cpp diff --git a/src/angle/src/compiler/translator_common.pro b/src/angle/src/compiler/translator_common.pro index cafbb1595d..b2812158e1 100644 --- a/src/angle/src/compiler/translator_common.pro +++ b/src/angle/src/compiler/translator_common.pro @@ -4,6 +4,9 @@ TARGET = $$qtLibraryTarget(translator_common) include(../config.pri) +# Mingw 4.7 chokes on implicit move semantics, so disable C++11 here +win32-g++*: CONFIG -= c++11 + INCLUDEPATH += \ $$ANGLE_DIR/src \ $$ANGLE_DIR/include @@ -20,6 +23,7 @@ HEADERS += \ $$ANGLE_DIR/src/compiler/ConstantUnion.h \ $$ANGLE_DIR/src/compiler/debug.h \ $$ANGLE_DIR/src/compiler/DetectRecursion.h \ + $$ANGLE_DIR/src/compiler/DetectCallDepth.h \ $$ANGLE_DIR/src/compiler/Diagnostics.h \ $$ANGLE_DIR/src/compiler/DirectiveHandler.h \ $$ANGLE_DIR/src/compiler/ForLoopUnroll.h \ @@ -27,6 +31,7 @@ HEADERS += \ $$ANGLE_DIR/src/compiler/Initialize.h \ $$ANGLE_DIR/src/compiler/InitializeDll.h \ $$ANGLE_DIR/src/compiler/InitializeGlobals.h \ + $$ANGLE_DIR/src/compiler/InitializeGLPosition.h \ $$ANGLE_DIR/src/compiler/InitializeParseContext.h \ $$ANGLE_DIR/src/compiler/intermediate.h \ $$ANGLE_DIR/src/compiler/localintermediate.h \ @@ -59,6 +64,7 @@ SOURCES += \ $$ANGLE_DIR/src/compiler/BuiltInFunctionEmulator.cpp \ $$ANGLE_DIR/src/compiler/Compiler.cpp \ $$ANGLE_DIR/src/compiler/debug.cpp \ + $$ANGLE_DIR/src/compiler/DetectCallDepth.cpp \ $$ANGLE_DIR/src/compiler/DetectRecursion.cpp \ $$ANGLE_DIR/src/compiler/Diagnostics.cpp \ $$ANGLE_DIR/src/compiler/DirectiveHandler.cpp \ @@ -66,6 +72,7 @@ SOURCES += \ $$ANGLE_DIR/src/compiler/InfoSink.cpp \ $$ANGLE_DIR/src/compiler/Initialize.cpp \ $$ANGLE_DIR/src/compiler/InitializeDll.cpp \ + $$ANGLE_DIR/src/compiler/InitializeGLPosition.cpp \ $$ANGLE_DIR/src/compiler/InitializeParseContext.cpp \ $$ANGLE_DIR/src/compiler/Intermediate.cpp \ $$ANGLE_DIR/src/compiler/intermOut.cpp \ diff --git a/src/angle/src/compiler/translator_hlsl.pro b/src/angle/src/compiler/translator_hlsl.pro index 6b17f14d2e..1c31cad297 100644 --- a/src/angle/src/compiler/translator_hlsl.pro +++ b/src/angle/src/compiler/translator_hlsl.pro @@ -4,6 +4,9 @@ TARGET = $$qtLibraryTarget(translator_hlsl) include(../config.pri) +# Mingw 4.7 chokes on implicit move semantics, so disable C++11 here +win32-g++*: CONFIG -= c++11 + INCLUDEPATH += $$ANGLE_DIR/src \ $$ANGLE_DIR/include diff --git a/src/angle/src/libEGL/libEGL.pro b/src/angle/src/libEGL/libEGL.pro index 1a338ef0d2..3781bd7868 100644 --- a/src/angle/src/libEGL/libEGL.pro +++ b/src/angle/src/libEGL/libEGL.pro @@ -3,10 +3,6 @@ TARGET = $$qtLibraryTarget(libEGL) include(../common/common.pri) -# Note: ANGLE is patched to dynamically resolve DwmIsCompositionEnabled DwmSetPresentParameters -# in Surface.cpp, which would otherwise require -ldwmapi, which does not exist on Windows XP -# (QTBUG-27741). - angle_d3d11 { LIBS += -ld3d11 } else { diff --git a/src/angle/src/libGLESv2/libGLESv2.pro b/src/angle/src/libGLESv2/libGLESv2.pro index ba1f226143..ff2f888b1d 100644 --- a/src/angle/src/libGLESv2/libGLESv2.pro +++ b/src/angle/src/libGLESv2/libGLESv2.pro @@ -12,7 +12,7 @@ angle_d3d11 { } else { LIBS += -ld3d9 } -LIBS += -ldxguid -ld3dcompiler +LIBS += -ldxguid STATICLIBS = translator_common translator_hlsl preprocessor for(libname, STATICLIBS) { @@ -49,6 +49,7 @@ HEADERS += \ $$ANGLE_DIR/src/libGLESv2/renderer/Image.h \ $$ANGLE_DIR/src/libGLESv2/renderer/IndexBuffer.h \ $$ANGLE_DIR/src/libGLESv2/renderer/IndexDataManager.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/IndexCacheRange.h \ $$ANGLE_DIR/src/libGLESv2/renderer/Renderer.h \ $$ANGLE_DIR/src/libGLESv2/renderer/RenderTarget.h \ $$ANGLE_DIR/src/libGLESv2/renderer/ShaderExecutable.h \ @@ -82,6 +83,7 @@ SOURCES += \ $$ANGLE_DIR/src/libGLESv2/renderer/Image.cpp \ $$ANGLE_DIR/src/libGLESv2/renderer/IndexBuffer.cpp \ $$ANGLE_DIR/src/libGLESv2/renderer/IndexDataManager.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/IndexRangeCache.cpp \ $$ANGLE_DIR/src/libGLESv2/renderer/Renderer.cpp \ $$ANGLE_DIR/src/libGLESv2/renderer/TextureStorage.cpp \ $$ANGLE_DIR/src/libGLESv2/renderer/VertexBuffer.cpp \ @@ -165,22 +167,23 @@ float_converter.commands = python $$ANGLE_DIR/src/libGLESv2/Float16ToFloat32.py QMAKE_EXTRA_TARGETS += float_converter # Generate the shader header files. -PS_INPUT = $$ANGLE_DIR/src/libGLESv2/renderer/shaders/Blit.ps -VS_INPUT = $$ANGLE_DIR/src/libGLESv2/renderer/shaders/Blit.vs +PS_BLIT_INPUT = $$ANGLE_DIR/src/libGLESv2/renderer/shaders/Blit.ps +VS_BLIT_INPUT = $$ANGLE_DIR/src/libGLESv2/renderer/shaders/Blit.vs PASSTHROUGH_INPUT = $$ANGLE_DIR/src/libGLESv2/renderer/shaders/Passthrough11.hlsl CLEAR_INPUT = $$ANGLE_DIR/src/libGLESv2/renderer/shaders/Clear11.hlsl -PIXEL_SHADERS = passthroughps luminanceps componentmaskps +PIXEL_SHADERS_BLIT = passthroughps luminanceps componentmaskps PIXEL_SHADERS_PASSTHROUGH = PassthroughRGBA PassthroughRGB \ PassthroughLum PassthroughLumAlpha -VERTEX_SHADERS = standardvs flipyvs +PIXEL_SHADERS_CLEAR = ClearSingle ClearMultiple +VERTEX_SHADERS_BLIT = standardvs flipyvs VERTEX_SHADERS_PASSTHROUGH = Passthrough -CLEAR_SHADERS = Clear +VERTEX_SHADERS_CLEAR = Clear SHADER_DIR = $$OUT_PWD/renderer/shaders/compiled -for (ps, PIXEL_SHADERS) { +for (ps, PIXEL_SHADERS_BLIT) { fxc_ps_$${ps}.commands = $$FXC /nologo /E $$ps /T ps_2_0 /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} fxc_ps_$${ps}.output = $$SHADER_DIR/$${ps}.h - fxc_ps_$${ps}.input = PS_INPUT + fxc_ps_$${ps}.input = PS_BLIT_INPUT fxc_ps_$${ps}.dependency_type = TYPE_C fxc_ps_$${ps}.variable_out = HEADERS fxc_ps_$${ps}.CONFIG += target_predeps @@ -195,7 +198,7 @@ for (ps, PIXEL_SHADERS_PASSTHROUGH) { fxc_ps_$${ps}.CONFIG += target_predeps QMAKE_EXTRA_COMPILERS += fxc_ps_$${ps} } -for (ps, CLEAR_SHADERS) { +for (ps, PIXEL_SHADERS_CLEAR) { fxc_ps_$${ps}.commands = $$FXC /nologo /E PS_$$ps /T ps_4_0 /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} fxc_ps_$${ps}.output = $$SHADER_DIR/$${ps}11ps.h fxc_ps_$${ps}.input = CLEAR_INPUT @@ -204,10 +207,10 @@ for (ps, CLEAR_SHADERS) { fxc_ps_$${ps}.CONFIG += target_predeps QMAKE_EXTRA_COMPILERS += fxc_ps_$${ps} } -for (vs, VERTEX_SHADERS) { +for (vs, VERTEX_SHADERS_BLIT) { fxc_vs_$${vs}.commands = $$FXC /nologo /E $$vs /T vs_2_0 /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} fxc_vs_$${vs}.output = $$SHADER_DIR/$${vs}.h - fxc_vs_$${vs}.input = VS_INPUT + fxc_vs_$${vs}.input = VS_BLIT_INPUT fxc_vs_$${vs}.dependency_type = TYPE_C fxc_vs_$${vs}.variable_out = HEADERS fxc_vs_$${vs}.CONFIG += target_predeps @@ -222,7 +225,7 @@ for (vs, VERTEX_SHADERS_PASSTHROUGH) { fxc_vs_$${vs}.CONFIG += target_predeps QMAKE_EXTRA_COMPILERS += fxc_vs_$${vs} } -for (vs, CLEAR_SHADERS) { +for (vs, VERTEX_SHADERS_CLEAR) { fxc_vs_$${vs}.commands = $$FXC /nologo /E VS_$$vs /T vs_4_0 /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} fxc_vs_$${vs}.output = $$SHADER_DIR/$${vs}11vs.h fxc_vs_$${vs}.input = CLEAR_INPUT