diff options
author | Andrew Knight <andrew.knight@digia.com> | 2013-09-18 11:51:20 +0300 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-19 08:53:35 +0200 |
commit | 1a334f8135d4be7b73b39ac736af0e722c864e83 (patch) | |
tree | cc0b7703b815e9fca858e8eecd7eb556e186998c /src/3rdparty | |
parent | d84ed9a92ae0ce96b843c9dd5c263c6a0925405b (diff) | |
download | qtbase-1a334f8135d4be7b73b39ac736af0e722c864e83.tar.gz |
ANGLE: Update to version 2446
Update ANGLE and reapply patches.
Patch changes:
"Dynamically resolve functions of dwmapi.dll"
Removed; ANGLE no longer uses DWM API
"Make it possible to link ANGLE statically for single-thread use"
Avoid name collision by using ANGLE-style getCurrent()
"Fix build when SSE2 is not available."
Added guard for __cpuid(), which is not available on ARM
"Make DX9/DX11 mutually exclusive"
Adjustments due to underlying code changes
"ANGLE: Avoid memory copies on buffers when data is null"
Removed; fixed upstream
"Add missing intrin.h include for __cpuid"
Removed; fixed upstream
Change-Id: I4f3d850fc555d3194ddc05e0b51c4966d33f7eaf
Reviewed-by: Oliver Wolff <oliver.wolff@digia.com>
Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
Reviewed-by: Kai Koehne <kai.koehne@digia.com>
Diffstat (limited to 'src/3rdparty')
124 files changed, 4866 insertions, 3476 deletions
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 @@ -109,12 +109,21 @@ typedef enum { } 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 SH_ACTIVE_UNIFORMS = 0x8B86, 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 <stddef.h> + // A macro to disallow the copy constructor and operator= functions // This must be used in the private: declarations for a class #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ 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 <d3d9.h> +#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 <char, std::char_traits<char>, TStringAllocator> TStri typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream; inline TString* NewPoolTString(const char* s) { - void* memory = GlobalPoolAllocator.allocate(sizeof(TString)); + void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TString)); return new(memory) TString(s); } 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<int>(i->size()); - if (builtInLengths <= 0) - continue; - - if (PaParseStrings(1, &builtInShaders, &builtInLengths, &parseContext) != 0) - { - infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins"); - return false; - } - } - - IdentifyBuiltIns(type, spec, resources, symbolTable); - - return true; -} - class TScopedPoolAllocator { public: - TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop) - : mAllocator(allocator), mPushPopAllocator(pushPop) { - if (mPushPopAllocator) mAllocator->push(); + TScopedPoolAllocator(TPoolAllocator* allocator) : mAllocator(allocator) { + mAllocator->push(); SetGlobalPoolAllocator(mAllocator); } ~TScopedPoolAllocator() { SetGlobalPoolAllocator(NULL); - if (mPushPopAllocator) mAllocator->pop(); + mAllocator->pop(); } private: TPoolAllocator* mAllocator; - bool mPushPopAllocator; +}; + +class TScopedSymbolTableLevel { +public: + TScopedSymbolTableLevel(TSymbolTable* table) : mTable(table) { + ASSERT(mTable->atBuiltInLevel()); + mTable->push(); + } + ~TScopedSymbolTableLevel() { + while (!mTable->atBuiltInLevel()) + mTable->pop(); + } + +private: + TSymbolTable* mTable; }; } // namespace @@ -103,6 +72,9 @@ TShHandleBase::~TShHandleBase() { TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec) : shaderType(type), shaderSpec(spec), + maxUniformVectors(0), + maxExpressionComplexity(0), + maxCallStackDepth(0), fragmentPrecisionHigh(false), clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC), builtInFunctionEmulator(type) @@ -121,7 +93,10 @@ bool TCompiler::Init(const ShBuiltInResources& resources) maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ? resources.MaxVertexUniformVectors : resources.MaxFragmentUniformVectors; - TScopedPoolAllocator scopedAlloc(&allocator, false); + maxExpressionComplexity = resources.MaxExpressionComplexity; + maxCallStackDepth = resources.MaxCallStackDepth; + + SetGlobalPoolAllocator(&allocator); // Generate built-in symbol table. if (!InitBuiltInSymbolTable(resources)) @@ -141,7 +116,7 @@ bool TCompiler::compile(const char* const shaderStrings[], size_t numStrings, int compileOptions) { - TScopedPoolAllocator scopedAlloc(&allocator, true); + TScopedPoolAllocator scopedAlloc(&allocator); clearResults(); if (numStrings == 0) @@ -165,13 +140,11 @@ bool TCompiler::compile(const char* const shaderStrings[], shaderType, shaderSpec, compileOptions, true, sourcePath, infoSink); parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh; - GlobalParseContext = &parseContext; + SetGlobalParseContext(&parseContext); // We preserve symbols at the built-in level from compile-to-compile. // Start pushing the user-defined symbols at global level. - symbolTable.push(); - if (!symbolTable.atGlobalLevel()) - infoSink.info.message(EPrefixInternalError, "Wrong symbol table level"); + TScopedSymbolTableLevel scopedSymbolLevel(&symbolTable); // Parse shader. bool success = @@ -182,7 +155,7 @@ bool TCompiler::compile(const char* const shaderStrings[], success = intermediate.postProcess(root); if (success) - success = detectRecursion(root); + success = detectCallDepth(root, infoSink, (compileOptions & SH_LIMIT_CALL_STACK_DEPTH) != 0); if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING)) success = validateLimitations(root); @@ -205,6 +178,10 @@ bool TCompiler::compile(const char* const shaderStrings[], if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS)) arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root); + // Disallow expressions deemed too complex. + if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY)) + success = limitExpressionComplexity(root); + // Call mapLongVariableNames() before collectAttribsUniforms() so in // collectAttribsUniforms() we already have the mapped symbol names and // we could composite mapped and original variable names. @@ -212,12 +189,18 @@ bool TCompiler::compile(const char* const shaderStrings[], if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) && hashFunction == NULL) mapLongVariableNames(root); - if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) { - collectAttribsUniforms(root); + if (success && shaderType == SH_VERTEX_SHADER && (compileOptions & SH_INIT_GL_POSITION)) { + InitializeGLPosition initGLPosition; + root->traverse(&initGLPosition); + } + + if (success && (compileOptions & SH_VARIABLES)) { + collectVariables(root); if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) { success = enforcePackingRestrictions(); if (!success) { - infoSink.info.message(EPrefixError, "too many uniforms"); + infoSink.info.prefix(EPrefixError); + infoSink.info << "too many uniforms"; } } } @@ -231,22 +214,58 @@ bool TCompiler::compile(const char* const shaderStrings[], // Cleanup memory. intermediate.remove(parseContext.treeRoot); - // Ensure symbol table is returned to the built-in level, - // throwing away all but the built-ins. - while (!symbolTable.atBuiltInLevel()) - symbolTable.pop(); return success; } -bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources) +bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources) { - TBuiltIns builtIns; - compileResources = resources; - builtIns.initialize(shaderType, shaderSpec, resources); - return InitializeSymbolTable(builtIns.getBuiltInStrings(), - shaderType, shaderSpec, resources, infoSink, symbolTable); + + assert(symbolTable.isEmpty()); + symbolTable.push(); + + TPublicType integer; + integer.type = EbtInt; + integer.size = 1; + integer.matrix = false; + integer.array = false; + + TPublicType floatingPoint; + floatingPoint.type = EbtFloat; + floatingPoint.size = 1; + floatingPoint.matrix = false; + floatingPoint.array = false; + + TPublicType sampler; + sampler.size = 1; + sampler.matrix = false; + sampler.array = false; + + switch(shaderType) + { + case SH_FRAGMENT_SHADER: + symbolTable.setDefaultPrecision(integer, EbpMedium); + break; + case SH_VERTEX_SHADER: + symbolTable.setDefaultPrecision(integer, EbpHigh); + symbolTable.setDefaultPrecision(floatingPoint, EbpHigh); + break; + default: assert(false && "Language not supported"); + } + // We set defaults for all the sampler types, even those that are + // only available if an extension exists. + for (int samplerType = EbtGuardSamplerBegin + 1; + samplerType < EbtGuardSamplerEnd; ++samplerType) { + sampler.type = static_cast<TBasicType>(samplerType); + symbolTable.setDefaultPrecision(sampler, EbpLow); + } + + InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable); + + IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable); + + return true; } void TCompiler::clearResults() @@ -258,24 +277,31 @@ void TCompiler::clearResults() attribs.clear(); uniforms.clear(); + varyings.clear(); builtInFunctionEmulator.Cleanup(); nameMap.clear(); } -bool TCompiler::detectRecursion(TIntermNode* root) +bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth) { - DetectRecursion detect; + DetectCallDepth detect(infoSink, limitCallStackDepth, maxCallStackDepth); root->traverse(&detect); - switch (detect.detectRecursion()) { - case DetectRecursion::kErrorNone: + switch (detect.detectCallDepth()) { + case DetectCallDepth::kErrorNone: return true; - case DetectRecursion::kErrorMissingMain: - infoSink.info.message(EPrefixError, "Missing main()"); + case DetectCallDepth::kErrorMissingMain: + infoSink.info.prefix(EPrefixError); + infoSink.info << "Missing main()"; + return false; + case DetectCallDepth::kErrorRecursion: + infoSink.info.prefix(EPrefixError); + infoSink.info << "Function recursion detected"; return false; - case DetectRecursion::kErrorRecursion: - infoSink.info.message(EPrefixError, "Function recursion detected"); + 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 <limits.h> +#include "compiler/intermediate.h" +#include "compiler/VariableInfo.h" + +class TInfoSink; + +// Traverses intermediate tree to detect function recursion. +class DetectCallDepth : public TIntermTraverser { +public: + enum ErrorCode { + kErrorMissingMain, + kErrorRecursion, + kErrorMaxDepthExceeded, + kErrorNone + }; + + DetectCallDepth(TInfoSink& infoSync, bool limitCallStackDepth, int maxCallStackDepth); + ~DetectCallDepth(); + + virtual bool visitAggregate(Visit, TIntermAggregate*); + + bool checkExceedsMaxDepth(int depth); + + ErrorCode detectCallDepth(); + +private: + class FunctionNode { + public: + static const int kInfiniteCallDepth = INT_MAX; + + FunctionNode(const TString& fname); + + const TString& getName() const; + + // If a function is already in the callee list, this becomes a no-op. + void addCallee(FunctionNode* callee); + + // Returns kInifinityCallDepth if recursive function calls are detected. + int detectCallDepth(DetectCallDepth* detectCallDepth, int depth); + + // Reset state. + void reset(); + + private: + // mangled function name is unique. + TString name; + + // functions that are directly called by this function. + TVector<FunctionNode*> callees; + + Visit visit; + }; + + ErrorCode detectCallDepthForFunction(FunctionNode* func); + FunctionNode* findFunctionByName(const TString& name); + void resetFunctionNodes(); + + TInfoSink& getInfoSink() { return infoSink; } + + TVector<FunctionNode*> functions; + FunctionNode* currentFunction; + TInfoSink& infoSink; + int maxDepth; + + DetectCallDepth(const DetectCallDepth&); + void operator=(const DetectCallDepth&); +}; + +#endif // COMPILER_DETECT_RECURSION_H_ 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);")); - - 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);")); - - 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);")); - - 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);")); - - 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);")); - - 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);")); - - 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);")); - - 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);")); - - 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, "radians", float1); + symbolTable.insertBuiltIn(float2, "radians", float2); + symbolTable.insertBuiltIn(float3, "radians", float3); + symbolTable.insertBuiltIn(float4, "radians", float4); + + symbolTable.insertBuiltIn(float1, "degrees", float1); + symbolTable.insertBuiltIn(float2, "degrees", float2); + symbolTable.insertBuiltIn(float3, "degrees", float3); + symbolTable.insertBuiltIn(float4, "degrees", float4); + + symbolTable.insertBuiltIn(float1, "sin", float1); + symbolTable.insertBuiltIn(float2, "sin", float2); + symbolTable.insertBuiltIn(float3, "sin", float3); + symbolTable.insertBuiltIn(float4, "sin", float4); + + symbolTable.insertBuiltIn(float1, "cos", float1); + symbolTable.insertBuiltIn(float2, "cos", float2); + symbolTable.insertBuiltIn(float3, "cos", float3); + symbolTable.insertBuiltIn(float4, "cos", float4); + + symbolTable.insertBuiltIn(float1, "tan", float1); + symbolTable.insertBuiltIn(float2, "tan", float2); + symbolTable.insertBuiltIn(float3, "tan", float3); + symbolTable.insertBuiltIn(float4, "tan", float4); + + symbolTable.insertBuiltIn(float1, "asin", float1); + symbolTable.insertBuiltIn(float2, "asin", float2); + symbolTable.insertBuiltIn(float3, "asin", float3); + symbolTable.insertBuiltIn(float4, "asin", float4); + + symbolTable.insertBuiltIn(float1, "acos", float1); + symbolTable.insertBuiltIn(float2, "acos", float2); + symbolTable.insertBuiltIn(float3, "acos", float3); + symbolTable.insertBuiltIn(float4, "acos", float4); + + symbolTable.insertBuiltIn(float1, "atan", float1, float1); + symbolTable.insertBuiltIn(float2, "atan", float2, float2); + symbolTable.insertBuiltIn(float3, "atan", float3, float3); + symbolTable.insertBuiltIn(float4, "atan", float4, float4); + + 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);")); - - 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);")); - - 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);")); - - 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);")); - - 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);")); - - 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);")); - - 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, "pow", float1, float1); + symbolTable.insertBuiltIn(float2, "pow", float2, float2); + symbolTable.insertBuiltIn(float3, "pow", float3, float3); + symbolTable.insertBuiltIn(float4, "pow", float4, float4); + + symbolTable.insertBuiltIn(float1, "exp", float1); + symbolTable.insertBuiltIn(float2, "exp", float2); + symbolTable.insertBuiltIn(float3, "exp", float3); + symbolTable.insertBuiltIn(float4, "exp", float4); + + symbolTable.insertBuiltIn(float1, "log", float1); + symbolTable.insertBuiltIn(float2, "log", float2); + symbolTable.insertBuiltIn(float3, "log", float3); + symbolTable.insertBuiltIn(float4, "log", float4); + + symbolTable.insertBuiltIn(float1, "exp2", float1); + symbolTable.insertBuiltIn(float2, "exp2", float2); + symbolTable.insertBuiltIn(float3, "exp2", float3); + symbolTable.insertBuiltIn(float4, "exp2", float4); + + symbolTable.insertBuiltIn(float1, "log2", float1); + symbolTable.insertBuiltIn(float2, "log2", float2); + symbolTable.insertBuiltIn(float3, "log2", float3); + symbolTable.insertBuiltIn(float4, "log2", float4); + + symbolTable.insertBuiltIn(float1, "sqrt", float1); + symbolTable.insertBuiltIn(float2, "sqrt", float2); + symbolTable.insertBuiltIn(float3, "sqrt", float3); + symbolTable.insertBuiltIn(float4, "sqrt", float4); + + 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);")); - - 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);")); - - 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);")); - - 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);")); - - 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);")); - - 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);")); - - 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);")); - - 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);")); - - 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);")); - - 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);")); - - 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);")); - - 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, "abs", float1); + symbolTable.insertBuiltIn(float2, "abs", float2); + symbolTable.insertBuiltIn(float3, "abs", float3); + symbolTable.insertBuiltIn(float4, "abs", float4); + + symbolTable.insertBuiltIn(float1, "sign", float1); + symbolTable.insertBuiltIn(float2, "sign", float2); + symbolTable.insertBuiltIn(float3, "sign", float3); + symbolTable.insertBuiltIn(float4, "sign", float4); + + symbolTable.insertBuiltIn(float1, "floor", float1); + symbolTable.insertBuiltIn(float2, "floor", float2); + symbolTable.insertBuiltIn(float3, "floor", float3); + symbolTable.insertBuiltIn(float4, "floor", float4); + + symbolTable.insertBuiltIn(float1, "ceil", float1); + symbolTable.insertBuiltIn(float2, "ceil", float2); + symbolTable.insertBuiltIn(float3, "ceil", float3); + symbolTable.insertBuiltIn(float4, "ceil", float4); + + symbolTable.insertBuiltIn(float1, "fract", float1); + symbolTable.insertBuiltIn(float2, "fract", float2); + symbolTable.insertBuiltIn(float3, "fract", float3); + symbolTable.insertBuiltIn(float4, "fract", float4); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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);")); - - 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);")); - - 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);")); - - 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);")); - - 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);")); - - 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);")); - - 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, "length", float1); + symbolTable.insertBuiltIn(float1, "length", float2); + symbolTable.insertBuiltIn(float1, "length", float3); + symbolTable.insertBuiltIn(float1, "length", float4); + + symbolTable.insertBuiltIn(float1, "distance", float1, float1); + symbolTable.insertBuiltIn(float1, "distance", float2, float2); + symbolTable.insertBuiltIn(float1, "distance", float3, float3); + symbolTable.insertBuiltIn(float1, "distance", float4, float4); + + symbolTable.insertBuiltIn(float1, "dot", float1, float1); + symbolTable.insertBuiltIn(float1, "dot", float2, float2); + symbolTable.insertBuiltIn(float1, "dot", float3, float3); + symbolTable.insertBuiltIn(float1, "dot", float4, float4); + + 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); + + 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); + + symbolTable.insertBuiltIn(float1, "reflect", float1, float1); + symbolTable.insertBuiltIn(float2, "reflect", float2, float2); + symbolTable.insertBuiltIn(float3, "reflect", float3, float3); + symbolTable.insertBuiltIn(float4, "reflect", float4, float4); + + 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);")); - - 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", float2, float2); + symbolTable.insertBuiltIn(bool3, "lessThan", float3, float3); + symbolTable.insertBuiltIn(bool4, "lessThan", float4, float4); - 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, "lessThan", int2, int2); + symbolTable.insertBuiltIn(bool3, "lessThan", int3, int3); + symbolTable.insertBuiltIn(bool4, "lessThan", int4, int4); - 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", float2, float2); + symbolTable.insertBuiltIn(bool3, "lessThanEqual", float3, float3); + symbolTable.insertBuiltIn(bool4, "lessThanEqual", float4, float4); - 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, "lessThanEqual", int2, int2); + symbolTable.insertBuiltIn(bool3, "lessThanEqual", int3, int3); + symbolTable.insertBuiltIn(bool4, "lessThanEqual", int4, int4); - 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", float2, float2); + symbolTable.insertBuiltIn(bool3, "greaterThan", float3, float3); + symbolTable.insertBuiltIn(bool4, "greaterThan", float4, float4); - 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, "greaterThan", int2, int2); + symbolTable.insertBuiltIn(bool3, "greaterThan", int3, int3); + symbolTable.insertBuiltIn(bool4, "greaterThan", int4, int4); - 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", float2, float2); + symbolTable.insertBuiltIn(bool3, "greaterThanEqual", float3, float3); + symbolTable.insertBuiltIn(bool4, "greaterThanEqual", float4, float4); - 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, "greaterThanEqual", int2, int2); + symbolTable.insertBuiltIn(bool3, "greaterThanEqual", int3, int3); + symbolTable.insertBuiltIn(bool4, "greaterThanEqual", int4, int4); - 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", float2, float2); + symbolTable.insertBuiltIn(bool3, "equal", float3, float3); + symbolTable.insertBuiltIn(bool4, "equal", float4, float4); - 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", int2, int2); + symbolTable.insertBuiltIn(bool3, "equal", int3, int3); + symbolTable.insertBuiltIn(bool4, "equal", int4, int4); - 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, "equal", bool2, bool2); + symbolTable.insertBuiltIn(bool3, "equal", bool3, bool3); + symbolTable.insertBuiltIn(bool4, "equal", bool4, bool4); - 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", float2, float2); + symbolTable.insertBuiltIn(bool3, "notEqual", float3, float3); + symbolTable.insertBuiltIn(bool4, "notEqual", float4, float4); - 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", int2, int2); + symbolTable.insertBuiltIn(bool3, "notEqual", int3, int3); + symbolTable.insertBuiltIn(bool4, "notEqual", int4, int4); - s.append(TString("bool any(bvec2 x);")); - s.append(TString("bool any(bvec3 x);")); - s.append(TString("bool any(bvec4 x);")); + symbolTable.insertBuiltIn(bool2, "notEqual", bool2, bool2); + symbolTable.insertBuiltIn(bool3, "notEqual", bool3, bool3); + symbolTable.insertBuiltIn(bool4, "notEqual", bool4, bool4); - s.append(TString("bool all(bvec2 x);")); - s.append(TString("bool all(bvec3 x);")); - s.append(TString("bool all(bvec4 x);")); - - s.append(TString("bvec2 not(bvec2 x);")); - s.append(TString("bvec3 not(bvec3 x);")); - s.append(TString("bvec4 not(bvec4 x);")); - - // - // Texture Functions. - // - 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);")); - - 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);")); - } + symbolTable.insertBuiltIn(bool1, "any", bool2); + symbolTable.insertBuiltIn(bool1, "any", bool3); + symbolTable.insertBuiltIn(bool1, "any", bool4); - 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);")); - } + symbolTable.insertBuiltIn(bool1, "all", bool2); + symbolTable.insertBuiltIn(bool1, "all", bool3); + symbolTable.insertBuiltIn(bool1, "all", bool4); - // - // 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);")); - - //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);")); - - //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);")); - - //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; -} + symbolTable.insertBuiltIn(bool2, "not", bool2); + symbolTable.insertBuiltIn(bool3, "not", bool3); + symbolTable.insertBuiltIn(bool4, "not", bool4); -//============================================================================ -// -// Prototypes for built-in functions seen by vertex shaders only. -// -//============================================================================ -static TString BuiltInFunctionsVertex(const ShBuiltInResources& resources) -{ - TString s; + TType *sampler2D = new TType(EbtSampler2D, EbpUndefined, EvqGlobal, 1); + TType *samplerCube = new TType(EbtSamplerCube, EbpUndefined, EvqGlobal, 1); // - // Geometric Functions. + // Texture Functions for GLSL ES 1.0 // - //s.append(TString("vec4 ftransform();")); + symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2); + symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3); + symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4); + symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3); - // - // 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);")); + if (resources.OES_EGL_image_external) + { + TType *samplerExternalOES = new TType(EbtSamplerExternalOES, EbpUndefined, EvqGlobal, 1); - return s; -} + symbolTable.insertBuiltIn(float4, "texture2D", samplerExternalOES, float2); + symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float3); + symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float4); + } -//============================================================================ -// -// Prototypes for built-in functions seen by fragment shaders only. -// -//============================================================================ -static TString BuiltInFunctionsFragment(const ShBuiltInResources& resources) -{ - TString s; + if (resources.ARB_texture_rectangle) + { + TType *sampler2DRect = new TType(EbtSampler2DRect, EbpUndefined, EvqGlobal, 1); - // - // 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(float4, "texture2DRect", sampler2DRect, float2); + symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float3); + symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float4); } - return s; -} + 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); + + 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); + + symbolTable.insertBuiltIn(float1, "dFdy", float1); + symbolTable.insertBuiltIn(float2, "dFdy", float2); + symbolTable.insertBuiltIn(float3, "dFdy", float3); + symbolTable.insertBuiltIn(float4, "dFdy", float4); + + symbolTable.insertBuiltIn(float1, "fwidth", float1); + symbolTable.insertBuiltIn(float2, "fwidth", float2); + symbolTable.insertBuiltIn(float3, "fwidth", float3); + symbolTable.insertBuiltIn(float4, "fwidth", float4); + } + } -//============================================================================ -// -// 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;")); - - 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; + 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); - 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<TString> TBuiltInStrings; - -class TBuiltIns { -public: - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) - - void initialize(ShShaderType type, ShShaderSpec spec, - const ShBuiltInResources& resources); - const TBuiltInStrings& getBuiltInStrings() { return builtInStrings; } - -protected: - TBuiltInStrings builtInStrings; -}; +void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &table); void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources, 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() -{ - if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalized"); - return false; - } - - TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex)); - if (lpParseContext != 0) { - assert(0 && "InitializeParseContextIndex(): Parse Context already initalized"); - return false; - } - - TThreadParseContext *lpThreadData = new TThreadParseContext(); - if (lpThreadData == 0) { - assert(0 && "InitializeGlobalParseContext(): Unable to create thread parse context"); - return false; - } - - lpThreadData->lpGlobalParseContext = 0; - OS_SetTLSValue(GlobalParseContextIndex, lpThreadData); - - return true; } -bool FreeParseContext() +void SetGlobalParseContext(TParseContext* context) { - if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "FreeParseContext(): Parse Context index not initalized"); - return false; - } - - TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex)); - if (lpParseContext) - delete lpParseContext; - - return true; + assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); + OS_SetTLSValue(GlobalParseContextIndex, context); } -TParseContextPointer& GetGlobalParseContext() +TParseContext* GetGlobalParseContext() { - // - // Minimal error checking for speed - // - - TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex)); - - return lpParseContext->lpGlobalParseContext; + assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); + return static_cast<TParseContext*>(OS_GetTLSValue(GlobalParseContextIndex)); } 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<float>(node->getFConst(i))); break; default: - infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); return 0; } break; @@ -1413,7 +1396,7 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i))); break; default: - infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); return 0; } break; @@ -1429,13 +1412,13 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f); break; default: - infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); return 0; } break; default: - infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine()); + infoSink.info.message(EPrefixInternalError, node->getLine(), "Incorrect data type found"); return 0; } 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<size_t>(parameter.getNominalSize())) { switch (remainingComponents) { @@ -2865,9 +2736,10 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI } else if (parameter.isMatrix() || parameter.getStruct()) { - ASSERT(remainingComponents == parameter.getObjectSize() || moreParameters); + ASSERT(remainingComponents == parameterSize || moreParameters); + ASSERT(parameterSize <= remainingComponents); - remainingComponents -= parameter.getObjectSize(); + remainingComponents -= parameterSize; } else UNREACHABLE(); @@ -2904,17 +2776,17 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con if (type.getBasicType() == EbtStruct) { - out << structLookup(type.getTypeName()) + "_ctor("; + out << structLookup(type.getStruct()->name()) + "_ctor("; - const TTypeList *structure = type.getStruct(); + const TFieldList &fields = type.getStruct()->fields(); - for (size_t i = 0; i < structure->size(); i++) + for (size_t i = 0; i < fields.size(); i++) { - const TType *fieldType = (*structure)[i].type; + const TType *fieldType = fields[i]->type(); constUnion = writeConstantUnion(*fieldType, constUnion); - if (i != structure->size() - 1) + if (i != fields.size() - 1) { out << ", "; } @@ -2924,7 +2796,7 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con } else { - int size = type.getObjectSize(); + size_t size = type.getObjectSize(); bool writeType = size > 1; if (writeType) @@ -2932,7 +2804,7 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con out << typeString(type) << "("; } - for (int i = 0; i < size; i++, constUnion++) + for (size_t i = 0; i < size; i++, constUnion++) { switch (constUnion->getType()) { @@ -3021,7 +2893,7 @@ TString OutputHLSL::decorateUniform(const TString &string, const TType &type) TString OutputHLSL::decorateField(const TString &string, const TType &structure) { - if (structure.getTypeName().compare(0, 3, "gl_") != 0) + if (structure.getStruct()->name().compare(0, 3, "gl_") != 0) { return decorate(string); } @@ -3069,7 +2941,7 @@ int OutputHLSL::uniformRegister(TIntermSymbol *uniform) void OutputHLSL::declareUniform(const TType &type, const TString &name, int index) { - const TTypeList *structure = type.getStruct(); + TStructure *structure = type.getStruct(); if (!structure) { @@ -3077,18 +2949,18 @@ void OutputHLSL::declareUniform(const TType &type, const TString &name, int inde } else { + const TFieldList &fields = structure->fields(); + if (type.isArray()) { int elementIndex = index; for (int i = 0; i < type.getArraySize(); i++) { - for (size_t j = 0; j < structure->size(); j++) + for (size_t j = 0; j < fields.size(); j++) { - const TType &fieldType = *(*structure)[j].type; - const TString &fieldName = fieldType.getFieldName(); - - const TString uniformName = name + "[" + str(i) + "]." + fieldName; + const TType &fieldType = *fields[j]->type(); + const TString uniformName = name + "[" + str(i) + "]." + fields[j]->name(); declareUniform(fieldType, uniformName, elementIndex); elementIndex += fieldType.totalRegisterCount(); } @@ -3098,12 +2970,10 @@ void OutputHLSL::declareUniform(const TType &type, const TString &name, int inde { int fieldIndex = index; - for (size_t i = 0; i < structure->size(); i++) + for (size_t i = 0; i < fields.size(); i++) { - const TType &fieldType = *(*structure)[i].type; - const TString &fieldName = fieldType.getFieldName(); - - const TString uniformName = name + "." + fieldName; + const TType &fieldType = *fields[i]->type(); + const TString uniformName = name + "." + fields[i]->name(); declareUniform(fieldType, uniformName, fieldIndex); fieldIndex += fieldType.totalRegisterCount(); } 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<TVariable*>(symbol); - - type->setArrayInformationType(variable->getArrayInformationType()); - variable->updateArrayInformationType(type); - - // special casing to test index value of gl_FragData. If the accessed index is >= gl_MaxDrawBuffers - // its an error - if (node->getSymbol() == "gl_FragData") { - TSymbol* fragData = symbolTable.find("gl_MaxDrawBuffers", &builtIn); - ASSERT(fragData); - - int fragDataValue = static_cast<TVariable*>(fragData)->getConstPointer()[0].getIConst(); - if (fragDataValue <= size) { - error(line, "", "[", "gl_FragData can only have a max array size of up to gl_MaxDrawBuffers"); - return true; - } - } - - // we dont want to update the maxArraySize when this flag is not set, we just want to include this - // node type in the chain of node types so that its updated when a higher maxArraySize comes in. - if (!updateFlag) - return false; - - size++; - variable->getType().setMaxArraySize(size); - type->setMaxArraySize(size); - TType* tt = type; - - while(tt->getArrayInformationType() != 0) { - tt = tt->getArrayInformationType(); - tt->setMaxArraySize(size); - } - - return false; -} - // // Enforce non-initializer type/qualifier rules. // // Returns true if there was an error. // -bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array) +bool TParseContext::nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array) { if (type.qualifier == EvqConst) { @@ -878,7 +825,7 @@ bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPubli // // Returns true if there was an error. // -bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable) +bool TParseContext::nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable) { if (reservedErrorCheck(line, identifier)) recover(); @@ -898,7 +845,7 @@ bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType return false; } -bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type) +bool TParseContext::paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type) { if (qualifier != EvqConst && qualifier != EvqTemporary) { error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier)); @@ -917,7 +864,7 @@ bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier p return false; } -bool TParseContext::extensionErrorCheck(int line, const TString& extension) +bool TParseContext::extensionErrorCheck(const TSourceLoc& line, const TString& extension) { const TExtensionBehavior& extBehavior = extensionBehavior(); TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str()); @@ -945,18 +892,17 @@ bool TParseContext::supportsExtension(const char* extension) return (iter != extbehavior.end()); } -void TParseContext::handleExtensionDirective(int line, const char* extName, const char* behavior) +bool TParseContext::isExtensionEnabled(const char* extension) const { - pp::SourceLocation loc; - DecodeSourceLoc(line, &loc.file, &loc.line); - directiveHandler.handleExtension(loc, extName, behavior); -} + const TExtensionBehavior& extbehavior = extensionBehavior(); + TExtensionBehavior::const_iterator iter = extbehavior.find(extension); -void TParseContext::handlePragmaDirective(int line, const char* name, const char* value) -{ - pp::SourceLocation loc; - DecodeSourceLoc(line, &loc.file, &loc.line); - directiveHandler.handlePragma(loc, name, value); + if (iter == extbehavior.end()) + { + return false; + } + + return (iter->second == EBhEnable || iter->second == EBhRequire); } ///////////////////////////////////////////////////////////////////////////////// @@ -970,12 +916,13 @@ void TParseContext::handlePragmaDirective(int line, const char* name, const char // // Return the function symbol if found, otherwise 0. // -const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *builtIn) +const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, bool *builtIn) { // First find by unmangled name to check whether the function name has been // hidden by a variable name or struct typename. + // If a function is found, check for one with a matching argument list. const TSymbol* symbol = symbolTable.find(call->getName(), builtIn); - if (symbol == 0) { + if (symbol == 0 || symbol->isFunction()) { symbol = symbolTable.find(call->getMangledName(), builtIn); } @@ -996,7 +943,7 @@ const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *bu // Initializers show up in several places in the grammar. Have one set of // code to handle them here. // -bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, +bool TParseContext::executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType, TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable) { TType type = TType(pType); @@ -1048,13 +995,7 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu return true; } if (initializer->getAsConstantUnion()) { - ConstantUnion* unionArray = variable->getConstPointer(); - - if (type.getObjectSize() == 1 && type.getBasicType() != EbtStruct) { - *unionArray = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0]; - } else { - variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer()); - } + variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer()); } else if (initializer->getAsSymbolNode()) { const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol()); const TVariable* tVar = static_cast<const TVariable*>(symbol); @@ -1108,16 +1049,16 @@ bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode) // // Returns 0 for an error or the constructed node (aggregate or typed) for no error. // -TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, TSourceLoc line) +TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, const TSourceLoc& line) { if (node == 0) return 0; TIntermAggregate* aggrNode = node->getAsAggregate(); - TTypeList::const_iterator memberTypes; + TFieldList::const_iterator memberFields; if (op == EOpConstructStruct) - memberTypes = type->getStruct()->begin(); + memberFields = type->getStruct()->fields().begin(); TType elementType = *type; if (type->isArray()) @@ -1139,7 +1080,7 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type if (type->isArray()) newNode = constructStruct(node, &elementType, 1, node->getLine(), false); else if (op == EOpConstructStruct) - newNode = constructStruct(node, (*memberTypes).type, 1, node->getLine(), false); + newNode = constructStruct(node, (*memberFields)->type(), 1, node->getLine(), false); else newNode = constructBuiltIn(type, op, node, node->getLine(), false); @@ -1170,7 +1111,7 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type if (type->isArray()) newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true); else if (op == EOpConstructStruct) - newNode = constructStruct(*p, (memberTypes[paramCount]).type, paramCount+1, node->getLine(), true); + newNode = constructStruct(*p, memberFields[paramCount]->type(), paramCount+1, node->getLine(), true); else newNode = constructBuiltIn(type, op, *p, node->getLine(), true); @@ -1216,7 +1157,7 @@ TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, co // // Returns 0 for an error or the constructed node. // -TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, TSourceLoc line, bool subset) +TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, const TSourceLoc& line, bool subset) { TIntermTyped* newNode; TOperator basicOp; @@ -1278,7 +1219,7 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, T // // Returns 0 for an error or the input node itself if the expected and the given parameter types match. // -TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, TSourceLoc line, bool subset) +TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, const TSourceLoc& line, bool subset) { if (*type == node->getAsTyped()->getType()) { if (subset) @@ -1305,7 +1246,7 @@ TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int // node or it could be the intermediate tree representation of accessing fields in a constant structure or column of // a constant matrix. // -TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc line) +TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc& line) { TIntermTyped* typedNode; TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); @@ -1327,7 +1268,7 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy ConstantUnion* constArray = new ConstantUnion[fields.num]; for (int i = 0; i < fields.num; i++) { - if (fields.offsets[i] >= node->getType().getObjectSize()) { + if (fields.offsets[i] >= node->getType().getNominalSize()) { std::stringstream extraInfoStream; extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'"; std::string extraInfo = extraInfoStream.str(); @@ -1349,7 +1290,7 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy // to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a // constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure) // -TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc line) +TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc& line) { TIntermTyped* typedNode; TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); @@ -1384,7 +1325,7 @@ TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, T // to the function could either be a symbol node (a[0] where a is a constant array)that represents a // constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure) // -TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line) +TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line) { TIntermTyped* typedNode; TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); @@ -1400,9 +1341,8 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS index = 0; } - int arrayElementSize = arrayElementType.getObjectSize(); - if (tempConstantNode) { + size_t arrayElementSize = arrayElementType.getObjectSize(); ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer(); typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line); } else { @@ -1421,22 +1361,21 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS // If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr // function and returns the parse-tree with the values of the embedded/nested struct. // -TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, TSourceLoc line) +TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, const TSourceLoc& line) { - const TTypeList* fields = node->getType().getStruct(); - TIntermTyped *typedNode; - int instanceSize = 0; - unsigned int index = 0; - TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion(); - - for ( index = 0; index < fields->size(); ++index) { - if ((*fields)[index].type->getFieldName() == identifier) { + const TFieldList& fields = node->getType().getStruct()->fields(); + + 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,24 +1416,26 @@ 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; } @@ -1502,6 +1443,140 @@ bool TParseContext::structNestingErrorCheck(TSourceLoc line, const TType& fieldT } // +// 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. // // Returns 0 for success. 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&); + 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(); } const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); } bool supportsExtension(const char* extension); - void handleExtensionDirective(int line, const char* extName, const char* behavior); - - const TPragma& pragma() const { return directiveHandler.pragma(); } - void handlePragmaDirective(int line, const char* name, const char* value); + 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<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex)); - if (globalPools) - return; - - TThreadGlobalPools* threadData = new TThreadGlobalPools(); - threadData->globalPoolAllocator = 0; - - OS_SetTLSValue(PoolIndex, threadData); -} - -void FreeGlobalPools() -{ - // Release the allocated memory for this thread. - TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex)); - if (!globalPools) - return; - - delete globalPools; -} - bool InitializePoolIndex() { - // Allocate a TLS index. - if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX) - return false; + assert(PoolIndex == OS_INVALID_TLS_INDEX); - return true; + PoolIndex = OS_AllocTLSIndex(); + return PoolIndex != OS_INVALID_TLS_INDEX; } void FreePoolIndex() { - // Release the TLS index. + assert(PoolIndex != OS_INVALID_TLS_INDEX); + OS_FreeTLSIndex(PoolIndex); + PoolIndex = OS_INVALID_TLS_INDEX; } -TPoolAllocator& GetGlobalPoolAllocator() +TPoolAllocator* GetGlobalPoolAllocator() { - TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex)); - - return *threadData->globalPoolAllocator; + assert(PoolIndex != OS_INVALID_TLS_INDEX); + return static_cast<TPoolAllocator*>(OS_GetTLSValue(PoolIndex)); } void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator) { - TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex)); - - threadData->globalPoolAllocator = poolAllocator; + assert(PoolIndex != OS_INVALID_TLS_INDEX); + OS_SetTLSValue(PoolIndex, poolAllocator); } // @@ -228,24 +205,27 @@ void TPoolAllocator::popAll() void* TPoolAllocator::allocate(size_t numBytes) { + // + // 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); - - // - // Just keep some interesting statistics. - // - ++numCalls; - totalBytes += numBytes; + // Detect integer overflow. + if (allocationSize < numBytes) + return 0; // // Do the allocation, most likely case first, for efficiency. // This step could be moved to be inline sometime. // - if (currentPageOffset + allocationSize <= pageSize) { + if (allocationSize <= pageSize - currentPageOffset) { // // Safe to allocate from currentPageOffset. // @@ -256,12 +236,16 @@ void* TPoolAllocator::allocate(size_t numBytes) return initializeAllocation(inUseList, memory, numBytes); } - if (allocationSize + headerSkip > pageSize) { + if (allocationSize > pageSize - headerSkip) { // // Do a multi-page allocation. Don't mix these with the others. // The OS is efficient and allocating and free-ing multiple pages. // size_t numBytesToAlloc = allocationSize + headerSkip; + // Detect integer overflow. + if (numBytesToAlloc < allocationSize) + return 0; + tHeader* memory = reinterpret_cast<tHeader*>(::new char[numBytesToAlloc]); if (memory == 0) return 0; 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<T>& 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<TShHandleBase*>(handle); - TCompiler* compiler = base->getAsCompiler(); - if (compiler == 0) - return; - - const TVariableInfoList& varList = varType == SH_ACTIVE_ATTRIBUTES ? - compiler->getAttribs() : compiler->getUniforms(); - if (index < 0 || index >= static_cast<int>(varList.size())) - return; - - const TVariableInfo& varInfo = varList[index]; - if (length) *length = varInfo.name.size(); - *size = varInfo.size; - *type = varInfo.type; - - // This size must match that queried by - // SH_ACTIVE_UNIFORM_MAX_LENGTH and SH_ACTIVE_ATTRIBUTE_MAX_LENGTH - // in ShGetInfo, below. - size_t activeUniformAndAttribLength = 1 + MAX_SYMBOL_NAME_LEN; - ASSERT(checkActiveUniformAndAttribMaxLengths(handle, activeUniformAndAttribLength)); - strncpy(name, varInfo.name.c_str(), activeUniformAndAttribLength); - name[activeUniformAndAttribLength - 1] = 0; - if (mappedName) { - // This size must match that queried by - // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below. - size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN; - ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength)); - strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength); - mappedName[maxMappedNameLength - 1] = 0; - } -} - // -// Driver must call this first, once, before doing any other -// compiler operations. +// Driver must call this first, once, before doing any other compiler operations. +// Subsequent calls to this function are no-op. // int ShInitialize() { - if (!InitProcess()) - return 0; - - return 1; + static const bool kInitialized = InitProcess(); + return kInitialized ? 1 : 0; } // @@ -101,9 +58,7 @@ int ShInitialize() // int ShFinalize() { - if (!DetachProcess()) - return 0; - + DetachProcess(); return 1; } @@ -127,6 +82,7 @@ void ShInitBuiltInResources(ShBuiltInResources* resources) resources->OES_EGL_image_external = 0; resources->ARB_texture_rectangle = 0; resources->EXT_draw_buffers = 0; + resources->EXT_frag_depth = 0; // Disable highp precision in fragment shader by default. resources->FragmentPrecisionHigh = 0; @@ -144,9 +100,6 @@ ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec, ShShaderOutput output, const ShBuiltInResources* resources) { - if (!InitThread()) - return 0; - TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output)); TCompiler* compiler = base->getAsCompiler(); if (compiler == 0) @@ -185,9 +138,6 @@ int ShCompile( size_t numStrings, int compileOptions) { - if (!InitThread()) - return 0; - if (handle == 0) return 0; @@ -229,6 +179,12 @@ void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params) case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: *params = 1 + MAX_SYMBOL_NAME_LEN; break; + case SH_VARYINGS: + *params = compiler->getVaryings().size(); + break; + case SH_VARYING_MAX_LENGTH: + *params = 1 + MAX_SYMBOL_NAME_LEN; + break; case SH_MAPPED_NAME_MAX_LENGTH: // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to // handle array and struct dereferences. @@ -286,28 +242,71 @@ void ShGetObjectCode(const ShHandle handle, char* objCode) strcpy(objCode, infoSink.obj.c_str()); } -void ShGetActiveAttrib(const ShHandle handle, +void ShGetVariableInfo(const ShHandle handle, + ShShaderInfo varType, int index, size_t* length, int* size, ShDataType* type, + ShPrecisionType* precision, + int* staticUse, char* name, char* mappedName) { - getVariableInfo(SH_ACTIVE_ATTRIBUTES, - handle, index, length, size, type, name, mappedName); -} + if (!handle || !size || !type || !precision || !staticUse || !name) + return; + ASSERT((varType == SH_ACTIVE_ATTRIBUTES) || + (varType == SH_ACTIVE_UNIFORMS) || + (varType == SH_VARYINGS)); -void ShGetActiveUniform(const ShHandle handle, - int index, - size_t* length, - int* size, - ShDataType* type, - char* name, - char* mappedName) -{ - getVariableInfo(SH_ACTIVE_UNIFORMS, - handle, index, length, size, type, name, mappedName); + TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle); + TCompiler* compiler = base->getAsCompiler(); + if (compiler == 0) + return; + + const TVariableInfoList& varList = + varType == SH_ACTIVE_ATTRIBUTES ? compiler->getAttribs() : + (varType == SH_ACTIVE_UNIFORMS ? compiler->getUniforms() : + compiler->getVaryings()); + if (index < 0 || index >= static_cast<int>(varList.size())) + return; + + const TVariableInfo& varInfo = varList[index]; + if (length) *length = varInfo.name.size(); + *size = varInfo.size; + *type = varInfo.type; + switch (varInfo.precision) { + case EbpLow: + *precision = SH_PRECISION_LOWP; + break; + case EbpMedium: + *precision = SH_PRECISION_MEDIUMP; + break; + case EbpHigh: + *precision = SH_PRECISION_HIGHP; + break; + default: + // Some types does not support precision, for example, boolean. + *precision = SH_PRECISION_UNDEFINED; + break; + } + *staticUse = varInfo.staticUse ? 1 : 0; + + // This size must match that queried by + // SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH + // in ShGetInfo, below. + size_t variableLength = 1 + MAX_SYMBOL_NAME_LEN; + ASSERT(checkVariableMaxLengths(handle, variableLength)); + strncpy(name, varInfo.name.c_str(), variableLength); + name[variableLength - 1] = 0; + if (mappedName) { + // This size must match that queried by + // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below. + size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN; + ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength)); + strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength); + mappedName[maxMappedNameLength - 1] = 0; + } } void ShGetNameHashingEntry(const ShHandle handle, @@ -370,3 +369,19 @@ void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params) default: UNREACHABLE(); } } + +int ShCheckVariablesWithinPackingLimits( + int maxVectors, ShVariableInfo* varInfoArray, size_t varInfoArraySize) +{ + if (varInfoArraySize == 0) + return 1; + ASSERT(varInfoArray); + TVariableInfoList variables; + for (size_t ii = 0; ii < varInfoArraySize; ++ii) + { + TVariableInfo var(varInfoArray[ii].type, varInfoArray[ii].size); + variables.push_back(var); + } + VariablePacker packer; + return packer.CheckVariablesWithinPackingLimits(maxVectors, variables) ? 1 : 0; +} 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 <stdio.h> #include <algorithm> - -#include "common/angleutils.h" +#include <climits> TType::TType(const TPublicType &p) : - type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize), - maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0) + type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize), structure(0) { - if (p.userDef) { + if (p.userDef) structure = p.userDef->getStruct(); - typeName = NewPoolTString(p.userDef->getTypeName().c_str()); - computeDeepestStructNesting(); - } } // // Recursively generate mangled names. // -void TType::buildMangledName(TString& mangledName) +TString TType::buildMangledName() const { + TString mangledName; if (isMatrix()) mangledName += 'm'; else if (isVector()) mangledName += 'v'; switch (type) { - case EbtFloat: mangledName += 'f'; break; - case EbtInt: mangledName += 'i'; break; - case EbtBool: mangledName += 'b'; break; - case EbtSampler2D: mangledName += "s2"; break; - case EbtSamplerCube: mangledName += "sC"; break; - case EbtStruct: - mangledName += "struct-"; - if (typeName) - mangledName += *typeName; - {// support MSVC++6.0 - for (unsigned int i = 0; i < structure->size(); ++i) { - mangledName += '-'; - (*structure)[i].type->buildMangledName(mangledName); - } - } - default: - break; + case EbtFloat: mangledName += 'f'; break; + case EbtInt: mangledName += 'i'; break; + case EbtBool: mangledName += 'b'; break; + case EbtSampler2D: mangledName += "s2"; break; + case EbtSamplerCube: mangledName += "sC"; break; + case EbtStruct: mangledName += structure->mangledName(); break; + default: break; } mangledName += static_cast<char>('0' + getNominalSize()); @@ -69,53 +55,72 @@ 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 (structureSize == 0) - for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++) - structureSize += ((*tl).type)->getObjectSize(); + 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; + } - return structureSize; + return totalSize; } -void TType::computeDeepestStructNesting() +bool TStructure::containsArrays() const { - if (!getStruct()) { - return; + for (size_t i = 0; i < mFields->size(); ++i) { + const TType* fieldType = (*mFields)[i]->type(); + if (fieldType->isArray() || fieldType->isStructureContainingArrays()) + return true; } + return false; +} - int maxNesting = 0; - for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); ++tl) { - maxNesting = std::max(maxNesting, ((*tl).type)->getDeepestStructNesting()); +TString TStructure::buildMangledName() const +{ + TString mangledName("struct-"); + mangledName += *mName; + for (size_t i = 0; i < mFields->size(); ++i) { + mangledName += '-'; + mangledName += (*mFields)[i]->type()->getMangledName(); } - - deepestStructNesting = 1 + maxNesting; + return mangledName; } -bool TType::isStructureContainingArrays() const +size_t TStructure::calculateObjectSize() const { - if (!structure) - { - return false; + 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; +} - for (TTypeList::const_iterator member = structure->begin(); member != structure->end(); member++) - { - if (member->type->isArray() || - member->type->isStructureContainingArrays()) - { - return true; - } +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 false; + return 1 + maxNesting; } // @@ -196,84 +201,16 @@ void TSymbolTableLevel::relateToOperator(const char* name, TOperator op) void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext) { for (tLevel::iterator it = level.begin(); it != level.end(); ++it) { - if (it->second->isFunction()) { - TFunction* function = static_cast<TFunction*>(it->second); - if (function->getName() == name) - function->relateToExtension(ext); - } + TSymbol* symbol = it->second; + if (symbol->getName() == name) + symbol->relateToExtension(ext); } } -TSymbol::TSymbol(const TSymbol& copyOf) -{ - name = NewPoolTString(copyOf.name->c_str()); - uniqueId = copyOf.uniqueId; -} - -TVariable::TVariable(const TVariable& copyOf, TStructureMap& remapper) : TSymbol(copyOf) +TSymbolTable::~TSymbolTable() { - 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 <assert.h> +#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<TParameter> TParamList; TParamList parameters; TType returnType; TString mangledName; TOperator op; - TString extension; bool defined; }; @@ -194,21 +187,24 @@ public: typedef const tLevel::value_type tLevelPair; typedef std::pair<tLevel::iterator, bool> tInsertResult; - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) TSymbolTableLevel() { } ~TSymbolTableLevel(); - bool insert(TSymbol& symbol) + bool insert(const TString &name, TSymbol &symbol) { // // returning true means symbol was added to the table // - tInsertResult result; - result = level.insert(tLevelPair(symbol.getMangledName(), &symbol)); + tInsertResult result = level.insert(tLevelPair(name, &symbol)); return result.second; } + bool insert(TSymbol &symbol) + { + return insert(symbol.getMangledName(), symbol); + } + TSymbol* find(const TString& name) const { tLevel::const_iterator it = level.find(name); @@ -231,7 +227,6 @@ public: void relateToOperator(const char* name, TOperator op); void relateToExtension(const char* name, const TString& ext); void dump(TInfoSink &infoSink) const; - TSymbolTableLevel* clone(TStructureMap& remapper); protected: tLevel level; @@ -247,13 +242,7 @@ public: // that the symbol table has not been preloaded with built-ins. // } - - ~TSymbolTable() - { - // level 0 is always built In symbols, so we never pop that out - while (table.size() > 1) - pop(); - } + ~TSymbolTable(); // // When the symbol table is initialized with the built-ins, there should @@ -266,13 +255,15 @@ public: void push() { table.push_back(new TSymbolTableLevel); - precisionStack.push_back( PrecisionStackLevel() ); + precisionStack.push_back(new PrecisionStackLevel); } void pop() - { - delete table[currentLevel()]; - 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<int>(precisionStack.size()) - 1; - precisionStack[indexOfLastElement][type.type] = prec; // Uses map operator [], overwrites the current value + (*precisionStack[indexOfLastElement])[type.type] = prec; // Uses map operator [], overwrites the current value return true; } // Searches down the precisionStack for a precision qualifier for the specified TBasicType - TPrecision getDefaultPrecision( TBasicType type){ - if( type != EbtFloat && type != EbtInt ) return EbpUndefined; + TPrecision getDefaultPrecision(TBasicType type) { + if (!supportsPrecision(type)) + return EbpUndefined; int level = static_cast<int>(precisionStack.size()) - 1; - assert( level >= 0); // Just to be safe. Should not happen. + assert(level >= 0); // Just to be safe. Should not happen. PrecisionStackLevel::iterator it; TPrecision prec = EbpUndefined; // If we dont find anything we return this. Should we error check this? - while( level >= 0 ){ - it = precisionStack[level].find( type ); - if( it != precisionStack[level].end() ){ + while (level >= 0) { + it = precisionStack[level]->find(type); + if (it != precisionStack[level]->end()) { prec = (*it).second; break; } @@ -353,13 +365,18 @@ public: return prec; } -protected: +private: int currentLevel() const { return static_cast<int>(table.size()) - 1; } - std::vector<TSymbolTableLevel*> table; - typedef std::map< TBasicType, TPrecision > PrecisionStackLevel; - std::vector< PrecisionStackLevel > precisionStack; + bool supportsPrecision(TBasicType type) { + // Only supports precision for int, float, and sampler types. + return type == EbtFloat || type == EbtInt || IsSampler(type); + } + int uniqueId; // for unique identification in code generation + std::vector<TSymbolTableLevel*> table; + typedef TMap<TBasicType, TPrecision> PrecisionStackLevel; + std::vector<PrecisionStackLevel*> precisionStack; }; #endif // _SYMBOL_TABLE_INCLUDED_ 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; +class TField +{ +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<TTypeLine> TTypeList; -inline TTypeList* NewPoolTTypeList() +typedef TVector<TField*> TFieldList; +inline TFieldList* NewPoolTFieldList() { - void* memory = GlobalPoolAllocator.allocate(sizeof(TTypeList)); - return new(memory) TTypeList; + void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList)); + return new(memory) TFieldList; } -typedef TMap<TTypeList*, TTypeList*> TStructureMap; -typedef TMap<TTypeList*, TTypeList*>::iterator TStructureMapIterator; +class TStructure +{ +public: + POOL_ALLOCATOR_NEW_DELETE(); + TStructure(TString* name, TFieldList* fields) + : mName(name), + mFields(fields), + mObjectSize(0), + mDeepestNesting(0) { + } + + const TString& name() const { return *mName; } + const TFieldList& fields() const { return *mFields; } + + const TString& mangledName() const { + if (mMangledName.empty()) + mMangledName = buildMangledName(); + return mMangledName; + } + size_t objectSize() const { + if (mObjectSize == 0) + mObjectSize = calculateObjectSize(); + return mObjectSize; + }; + int deepestNesting() const { + if (mDeepestNesting == 0) + mDeepestNesting = calculateDeepestNesting(); + return mDeepestNesting; + } + bool containsArrays() const; + +private: + DISALLOW_COPY_AND_ASSIGN(TStructure); + TString buildMangledName() const; + size_t calculateObjectSize() const; + int calculateDeepestNesting() const; + + TString* mName; + TFieldList* mFields; + + mutable TString mMangledName; + mutable size_t mObjectSize; + mutable int mDeepestNesting; +}; // // Base class for things that have a type. @@ -38,72 +93,16 @@ typedef TMap<TTypeList*, TTypeList*>::iterator TStructureMapIterator; class TType { public: - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) + POOL_ALLOCATOR_NEW_DELETE(); TType() {} TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) : - type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), - maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0) + type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), structure(0) { } explicit TType(const TPublicType &p); - TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) : - type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), - maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0) - { - typeName = NewPoolTString(n.c_str()); - } - - void copyType(const TType& copyOf, TStructureMap& remapper) + TType(TStructure* userDef, TPrecision p = EbpUndefined) : + type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), structure(userDef) { - 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(); } - - 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()); - } + TStructure* getStruct() const { return structure; } + void setStruct(TStructure* s) { structure = s; } - 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<TFunction*>(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*) -{ -} - -void CollectAttribsUniforms::visitConstantUnion(TIntermConstantUnion*) -{ -} - -bool CollectAttribsUniforms::visitBinary(Visit, TIntermBinary*) +// 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) { - return false; -} - -bool CollectAttribsUniforms::visitUnary(Visit, TIntermUnary*) -{ - return false; -} - -bool CollectAttribsUniforms::visitSelection(Visit, TIntermSelection*) -{ - return false; + 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; } -bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node) +bool CollectVariables::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<TVariableInfo> TVariableInfoList; -// Traverses intermediate tree to collect all attributes and uniforms. -class CollectAttribsUniforms : public TIntermTraverser { +// Traverses intermediate tree to collect all attributes, uniforms, varyings. +class CollectVariables : public TIntermTraverser { public: - CollectAttribsUniforms(TVariableInfoList& attribs, - TVariableInfoList& uniforms, - ShHashFunction64 hashFunction); + CollectVariables(TVariableInfoList& attribs, + TVariableInfoList& uniforms, + TVariableInfoList& varyings, + ShHashFunction64 hashFunction); virtual void visitSymbol(TIntermSymbol*); - virtual void visitConstantUnion(TIntermConstantUnion*); - virtual bool visitBinary(Visit, TIntermBinary*); - virtual bool visitUnary(Visit, TIntermUnary*); - virtual bool visitSelection(Visit, TIntermSelection*); virtual bool visitAggregate(Visit, TIntermAggregate*); - virtual bool visitLoop(Visit, TIntermLoop*); - virtual bool visitBranch(Visit, TIntermBranch*); private: TVariableInfoList& mAttribs; TVariableInfoList& mUniforms; + TVariableInfoList& mVaryings; + + bool mPointCoordAdded; + bool mFrontFacingAdded; + bool mFragCoordAdded; ShHashFunction64 mHashFunction; }; 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; -%} - - /* Single-line comments */ -"//"[^\n]* ; - - /* Multi-line comments */ -"/*" { yy_push_state(COMMENT, yyscanner); } -<COMMENT>. | -<COMMENT>\n ; -<COMMENT>"*/" { yy_pop_state(yyscanner); } - -"invariant" { return(INVARIANT); } -"highp" { return(HIGH_PRECISION); } -"mediump" { return(MEDIUM_PRECISION); } -"lowp" { return(LOW_PRECISION); } -"precision" { return(PRECISION); } - -"attribute" { return(ATTRIBUTE); } -"const" { return(CONST_QUAL); } -"uniform" { return(UNIFORM); } -"varying" { return(VARYING); } - -"break" { return(BREAK); } -"continue" { return(CONTINUE); } -"do" { return(DO); } -"for" { return(FOR); } -"while" { return(WHILE); } - -"if" { return(IF); } -"else" { return(ELSE); } - -"in" { return(IN_QUAL); } -"out" { return(OUT_QUAL); } -"inout" { return(INOUT_QUAL); } - -"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); } - -"discard" { return(DISCARD); } -"return" { return(RETURN); } - -"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); } +"invariant" { return INVARIANT; } +"highp" { return HIGH_PRECISION; } +"mediump" { return MEDIUM_PRECISION; } +"lowp" { return LOW_PRECISION; } +"precision" { return PRECISION; } + +"attribute" { return ATTRIBUTE; } +"const" { return CONST_QUAL; } +"uniform" { return UNIFORM; } +"varying" { return VARYING; } + +"break" { return BREAK; } +"continue" { return CONTINUE; } +"do" { return DO; } +"for" { return FOR; } +"while" { return WHILE; } + +"if" { return IF; } +"else" { return ELSE; } + +"in" { return IN_QUAL; } +"out" { return OUT_QUAL; } +"inout" { return INOUT_QUAL; } + +"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; } + +"discard" { return DISCARD; } +"return" { return RETURN; } + +"mat2" { return MATRIX2; } +"mat3" { return MATRIX3; } +"mat4" { return MATRIX4; } + +"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; } + +"sampler2D" { return SAMPLER2D; } +"samplerCube" { return SAMPLERCUBE; } +"samplerExternalOES" { return SAMPLER_EXTERNAL_OES; } +"sampler2DRect" { return SAMPLER2DRECT; } + +"struct" { return STRUCT; } "asm" { return reserved_word(yyscanner); } @@ -183,13 +173,11 @@ O [0-7] "fvec3" { return reserved_word(yyscanner); } "fvec4" { return reserved_word(yyscanner); } -"sampler1D" { return reserved_word(yyscanner); } -"sampler3D" { return reserved_word(yyscanner); } - -"sampler1DShadow" { return reserved_word(yyscanner); } -"sampler2DShadow" { return reserved_word(yyscanner); } - -"sampler3DRect" { return reserved_word(yyscanner); } +"sampler1D" { return reserved_word(yyscanner); } +"sampler3D" { return reserved_word(yyscanner); } +"sampler1DShadow" { return reserved_word(yyscanner); } +"sampler2DShadow" { return reserved_word(yyscanner); } +"sampler3DRect" { return reserved_word(yyscanner); } "sampler2DRectShadow" { return reserved_word(yyscanner); } "sizeof" { return reserved_word(yyscanner); } @@ -203,72 +191,64 @@ O [0-7] return check_type(yyscanner); } -0[xX]{H}+ { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return(INTCONSTANT); } -0{O}+ { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return(INTCONSTANT); } -0{D}+ { context->error(yylineno, "Invalid Octal number.", yytext); context->recover(); return 0;} -{D}+ { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return(INTCONSTANT); } - -{D}+{E} { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); } -{D}+"."{D}*({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); } -"."{D}+({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); } - -"+=" { 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); } - -<FIELDS>{L}({L}|{D})* { - BEGIN(INITIAL); - yylval->lex.string = NewPoolTString(yytext); - return FIELD_SELECTION; -} -<FIELDS>[ \t\v\f\r] {} - -[ \t\v\n\f\r] { } -<*><<EOF>> { context->AfterEOF = true; yyterminate(); } -<*>. { context->warning(yylineno, "Unknown char", yytext, ""); return 0; } +0[xX]{H}+ { return int_constant(yyscanner); } +0{O}+ { return int_constant(yyscanner); } +{D}+ { return int_constant(yyscanner); } + +{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 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; } + +[ \t\v\n\f\r] { } +<<EOF>> { yyterminate(); } +. { assert(false); return 0; } %% @@ -278,7 +258,8 @@ yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) { yy_size_t len = token.type == pp::Token::LAST ? 0 : token.text.size(); if (len < max_size) memcpy(buf, token.text.c_str(), len); - yyset_lineno(EncodeSourceLoc(token.location.file, token.location.line), yyscanner); + yyset_column(token.location.file, yyscanner); + yyset_lineno(token.location.line, yyscanner); if (len >= max_size) YY_FATAL_ERROR("Input buffer overflow"); @@ -292,12 +273,10 @@ int check_type(yyscan_t yyscanner) { int token = IDENTIFIER; TSymbol* symbol = yyextra->symbolTable.find(yytext); - if (yyextra->lexAfterType == false && symbol && symbol->isVariable()) { + if (symbol && symbol->isVariable()) { TVariable* variable = static_cast<TVariable*>(symbol); - if (variable->isUserType()) { - yyextra->lexAfterType = true; + if (variable->isUserType()) token = TYPE_NAME; - } } yylval->lex.symbol = symbol; return token; @@ -306,22 +285,32 @@ int check_type(yyscan_t yyscanner) { int reserved_word(yyscan_t yyscanner) { struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; - yyextra->error(yylineno, "Illegal use of reserved word", yytext, ""); + yyextra->error(*yylloc, "Illegal use of reserved word", yytext, ""); yyextra->recover(); return 0; } -void yyerror(TParseContext* context, const char* reason) { - struct yyguts_t* yyg = (struct yyguts_t*) context->scanner; - - if (context->AfterEOF) { - context->error(yylineno, reason, "unexpected EOF"); - } else { - context->error(yylineno, reason, yytext); - } +void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) { + context->error(*lloc, reason, yyget_text(context->scanner)); context->recover(); } +int int_constant(yyscan_t yyscanner) { + struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; + + if (!atoi_clamp(yytext, &(yylval->lex.i))) + yyextra->warning(*yylloc, "Integer overflow", yytext, ""); + return INTCONSTANT; +} + +int float_constant(yyscan_t yyscanner) { + struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; + + if (!atof_clamp(yytext, &(yylval->lex.f))) + yyextra->warning(*yylloc, "Float overflow", yytext, ""); + return FLOATCONSTANT; +} + int glslang_initialize(TParseContext* context) { yyscan_t scanner = NULL; if (yylex_init_extra(context, &scanner)) @@ -344,12 +333,13 @@ int glslang_finalize(TParseContext* context) { int glslang_scan(size_t count, const char* const string[], const int length[], TParseContext* context) { yyrestart(NULL, context->scanner); - yyset_lineno(EncodeSourceLoc(0, 1), context->scanner); - context->AfterEOF = false; + yyset_column(0, context->scanner); + yyset_lineno(1, context->scanner); // Initialize preprocessor. if (!context->preprocessor.init(count, string, length)) return 1; + context->preprocessor.setMaxTokenLength(SH_MAX_TOKEN_LENGTH); // Define extension macros. const TExtensionBehavior& extBehavior = context->extensionBehavior(); 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); - -#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(); \ - } \ -} +extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner); +extern void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason); + +#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 <lex> SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT %token <lex> IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT BOOLCONSTANT -%token <lex> FIELD_SELECTION %token <lex> LEFT_OP RIGHT_OP %token <lex> INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP %token <lex> 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 <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT %token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION +%type <lex> identifier %type <interm> assignment_operator unary_operator %type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression %type <interm.intermTypedNode> expression integer_expression assignment_expression @@ -154,8 +166,8 @@ extern void yyerror(TParseContext* context, const char* reason); %type <interm.type> type_qualifier fully_specified_type type_specifier %type <interm.type> type_specifier_no_prec type_specifier_nonarray %type <interm.type> struct_specifier -%type <interm.typeLine> struct_declarator -%type <interm.typeList> struct_declarator_list struct_declaration struct_declaration_list +%type <interm.field> struct_declarator +%type <interm.fieldList> struct_declarator_list struct_declaration struct_declaration_list %type <interm.function> function_header function_declarator function_identifier %type <interm.function> function_header_with_parameters function_call_header %type <interm> 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<const TVariable*>(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; - } + 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.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); + } + 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 { - context->error($2.line, " no such field in structure", $3.string->c_str()); - context->recover(); - $$ = $1; + 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<TIntermTyped*>($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<TFunction*>(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 <interm> buffer_declaration -//%type <interm.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<TVariable*>($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<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), $7, $1.line); + $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($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 <algorithm> #include "compiler/Common.h" #include "compiler/Types.h" #include "compiler/ConstantUnion.h" @@ -204,12 +205,17 @@ class TInfoSink; // class TIntermNode { public: - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) - - TIntermNode() : line(0) {} + 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() { } - TSourceLoc getLine() const { return line; } - void setLine(TSourceLoc l) { line = l; } + const TSourceLoc& getLine() const { return line; } + void setLine(const TSourceLoc& l) { line = l; } virtual void traverse(TIntermTraverser*) = 0; virtual TIntermTyped* getAsTyped() { return 0; } @@ -220,7 +226,6 @@ public: virtual TIntermSelection* getAsSelectionNode() { return 0; } virtual TIntermSymbol* getAsSymbolNode() { return 0; } virtual TIntermLoop* getAsLoopNode() { return 0; } - virtual ~TIntermNode() { } protected: TSourceLoc line; @@ -454,7 +459,7 @@ typedef TVector<int> TQualifierList; // class TIntermAggregate : public TIntermOperator { public: - TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), endLine(0), useEmulatedFunction(false) { } + TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), useEmulatedFunction(false) { } TIntermAggregate(TOperator o) : TIntermOperator(o), useEmulatedFunction(false) { } ~TIntermAggregate() { } @@ -474,9 +479,6 @@ public: void setDebug(bool d) { debug = d; } bool getDebug() { return debug; } - void setEndLine(TSourceLoc line) { endLine = line; } - TSourceLoc getEndLine() const { return endLine; } - void setUseEmulatedFunction() { useEmulatedFunction = true; } bool getUseEmulatedFunction() { return useEmulatedFunction; } @@ -489,7 +491,6 @@ protected: bool optimize; bool debug; - TSourceLoc endLine; // If set to true, replace the built-in function call with an emulated one // to work around driver bugs. @@ -538,14 +539,14 @@ enum Visit class TIntermTraverser { public: - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) - + POOL_ALLOCATOR_NEW_DELETE(); TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : preVisit(preVisit), inVisit(inVisit), postVisit(postVisit), rightToLeft(rightToLeft), - depth(0) {} + depth(0), + maxDepth(0) {} virtual ~TIntermTraverser() {}; virtual void visitSymbol(TIntermSymbol*) {} @@ -557,7 +558,8 @@ public: virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;} virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;} - void incrementDepth() {depth++;} + int getMaxDepth() const {return maxDepth;} + void incrementDepth() {depth++; maxDepth = std::max(maxDepth, depth); } void decrementDepth() {depth--;} // Return the original name if hash function pointer is NULL; @@ -571,6 +573,7 @@ public: protected: int depth; + int maxDepth; }; #endif // __INTERMEDIATE_H 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 <math.h> -#include <stdlib.h> +#include "compiler/util.h" -#include "util.h" +#include <limits> -#ifdef _MSC_VER - #include <locale.h> -#else - #include <sstream> -#endif +#include "compiler/preprocessor/numeric_lex.h" -double atof_dot(const char *str) +bool atof_clamp(const char *str, float *value) { -#ifdef _MSC_VER - _locale_t l = _create_locale(LC_NUMERIC, "C"); - double result = _atof_l(str, l); - _free_locale(l); - return result; -#else - double result; - std::istringstream s(str); - std::locale l("C"); - s.imbue(l); - s >> result; - return result; -#endif + bool success = pp::numeric_lex_float(str, value); + if (!success) + *value = std::numeric_limits<float>::max(); + return success; } + +bool atoi_clamp(const char *str, int *value) +{ + bool success = pp::numeric_lex_int(str, value); + if (!success) + *value = std::numeric_limits<int>::max(); + return success; +} + 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 <dwmapi.h> - namespace egl { @@ -71,44 +69,9 @@ Surface::~Surface() bool Surface::initialize() { - typedef HRESULT (STDAPICALLTYPE *PtrDwmIsCompositionEnabled)(BOOL*); - typedef HRESULT (STDAPICALLTYPE *PtrDwmSetPresentParameters)(HWND, DWM_PRESENT_PARAMETERS *); - if (!resetSwapChain()) return false; - // Modify present parameters for this window, if we are composited, - // to minimize the amount of queuing done by DWM between our calls to - // present and the actual screen. - if (mWindow && (getComparableOSVersion() >= versionWindowsVista)) { - // Resolve dwmapi.dll functions dynamically as the Library is - // not present on Windows XP. Alternatively, /DELAYLOAD could be used. - static PtrDwmIsCompositionEnabled dwmIsCompositionEnabled = 0; - static PtrDwmSetPresentParameters dwmSetPresentParameters = 0; - if (!dwmIsCompositionEnabled) { - if (const HMODULE dwmLibrary = LoadLibraryW(L"dwmapi.dll")) { - dwmIsCompositionEnabled = - (PtrDwmIsCompositionEnabled)GetProcAddress(dwmLibrary, "DwmIsCompositionEnabled"); - dwmSetPresentParameters = - (PtrDwmSetPresentParameters)GetProcAddress(dwmLibrary, "DwmSetPresentParameters"); - } - } - if (dwmIsCompositionEnabled && dwmSetPresentParameters) { - BOOL isComposited; - HRESULT result = dwmIsCompositionEnabled(&isComposited); - if (SUCCEEDED(result) && isComposited) { - DWM_PRESENT_PARAMETERS presentParams; - memset(&presentParams, 0, sizeof(presentParams)); - presentParams.cbSize = sizeof(DWM_PRESENT_PARAMETERS); - presentParams.cBuffer = 2; - - result = dwmSetPresentParameters(mWindow, &presentParams); - if (FAILED(result)) - ERR("Unable to set present parameters: 0x%08X", result); - } - } - } - return true; } 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<egl::Surface*>(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 +#endif // !QT_OPENGL_ES_2_ANGLE_STATIC -static egl::Current *current() +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 egl::Current curr = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE }; + static Current curr = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE }; return &curr; +#endif } -#endif // QT_OPENGL_ES_2_ANGLE_STATIC - -namespace egl -{ 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(renderTargetIndex) + " : " + targetSemantic + str(renderTargetIndex) + ";\n"; + } + + if (fragmentShader->mUsesFragDepth) { - pixelHLSL += " float4 gl_Color" + str(i) + " : " + targetSemantic + str(i) + ";\n"; + 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(renderTargetIndex) + " = gl_Color[" + str(sourceColorIndex) + "];\n"; + } - pixelHLSL += " output.gl_Color" + str(i) + " = gl_Color[" + str(sourceColor) + "];\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,36 +1941,48 @@ 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()) + if (!linkAttributes(infoLog, attributeBindings, fragmentShader, vertexShader)) { - std::string geometryHLSL = generateGeometryShaderHLSL(registers, packing, fragmentShader, vertexShader); - mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY); + success = false; } - if (!mVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable)) + if (!linkUniforms(infoLog, vertexShader->getUniforms(), fragmentShader->getUniforms())) { - 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)) + // special case for gl_DepthRange, the only built-in uniform (also a struct) + if (vertexShader->mUsesDepthRange || fragmentShader->mUsesDepthRange) { - success = false; + 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 (!linkUniforms(infoLog, vertexShader->getUniforms(), fragmentShader->getUniforms())) + if (success) { - success = false; + 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::sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const +void ProgramBinary::initAttributesByLayout() { - AttributeSorter sorter(mSemanticIndex); + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + mAttributesByLayout[i] = i; + } + + std::sort(&mAttributesByLayout[0], &mAttributesByLayout[MAX_VERTEX_ATTRIBS], AttributeSorter(mSemanticIndex)); +} - int oldIndices[MAX_VERTEX_ATTRIBS]; +void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const +{ 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 +#endif // !QT_OPENGL_ES_2_ANGLE_STATIC -static inline gl::Current *current() +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 } -#endif // QT_OPENGL_ES_2_ANGLE_STATIC - -namespace gl -{ 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 <unordered_map> #include <vector> -#if defined(ANGLE_ENABLE_D3D11) -# include <D3D11.h> -# include <dxgi.h> +#ifndef ANGLE_ENABLE_D3D11 +#include <d3d9.h> #else -# include <d3d9.h> +#include <D3D11.h> +#include <dxgi.h> #endif #include <D3Dcompiler.h> 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<char*>(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<const unsigned char*>(srcMapped.pData); unsigned char *destData = reinterpret_cast<unsigned char*>(destMapped.pData); @@ -171,7 +171,7 @@ void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei heig GLint unpackAlignment, const void *input) { D3D11_MAPPED_SUBRESOURCE mappedImage; - HRESULT result = map(&mappedImage); + HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); if (FAILED(result)) { ERR("Could not map image for loading."); @@ -194,7 +194,7 @@ void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei heig loadAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); break; case GL_LUMINANCE32F_EXT: - loadLuminanceFloatDataToRGB(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + loadLuminanceFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); break; case GL_ALPHA16F_EXT: loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); @@ -230,7 +230,7 @@ void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei heig loadBGRADataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); break; case GL_RGB32F_EXT: - loadRGBFloatDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); + loadRGBFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); break; case GL_RGB16F_EXT: loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); @@ -254,7 +254,7 @@ void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GL ASSERT(yoffset % 4 == 0); D3D11_MAPPED_SUBRESOURCE mappedImage; - HRESULT result = map(&mappedImage); + HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); if (FAILED(result)) { ERR("Could not map image for loading."); @@ -344,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<unsigned char*>(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) { + // Protect against integer overflow + if (mWritePosition + size < mWritePosition) + { + return false; + } + if (!mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory)) { - *outMappedMemory = NULL; - return -1; + if (outMappedMemory) + { + *outMappedMemory = NULL; + } + return false; } - int oldWritePos = static_cast<int>(mWritePosition); - mWritePosition += size; + if (streamOffset) + { + *streamOffset = mWritePosition; + } - return oldWritePos; + 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) -{ - IndexRange range = {offset, count}; - - std::map<IndexRange, IndexResult>::iterator res = mCache.find(range); - - if (res == mCache.end()) - { - return -1; - } - - *minIndex = res->second.minIndex; - *maxIndex = res->second.maxIndex; - return res->second.streamOffset; -} - -void StaticIndexBufferInterface::addRange(intptr_t offset, GLsizei count, unsigned int minIndex, unsigned int maxIndex, unsigned int streamOffset) +IndexRangeCache *StaticIndexBufferInterface::getIndexRangeCache() { - 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<IndexRange, IndexResult> 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<intptr_t>(indices); + unsigned int offset = 0; bool alignedOffset = false; BufferStorage *storage = NULL; if (buffer != NULL) { + if (reinterpret_cast<uintptr_t>(indices) > std::numeric_limits<unsigned int>::max()) + { + return GL_OUT_OF_MEMORY; + } + offset = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(indices)); + storage = buffer->getStorage(); switch (type) @@ -142,7 +138,16 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer default: UNREACHABLE(); alignedOffset = false; } - if (indexTypeSize(type) * count + offset > storage->getSize()) + unsigned int typeSize = gl::ComputeTypeSize(type); + + // check for integer overflows + if (static_cast<unsigned int>(count) > (std::numeric_limits<unsigned int>::max() / typeSize) || + typeSize * static_cast<unsigned int>(count) + offset < offset) + { + return GL_OUT_OF_MEMORY; + } + + if (typeSize * static_cast<unsigned int>(count) + offset > storage->getSize()) { return GL_INVALID_OPERATION; } @@ -156,37 +161,44 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer IndexBufferInterface *indexBuffer = streamingBuffer; bool directStorage = alignedOffset && storage && storage->supportsDirectBinding() && destinationIndexType == type; - UINT streamOffset = 0; + unsigned int streamOffset = 0; if (directStorage) { indexBuffer = streamingBuffer; streamOffset = offset; storage->markBufferUsage(); - computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); + + if (!buffer->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex, + &translated->maxIndex, NULL)) + { + computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); + buffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, + translated->maxIndex, offset); + } } else if (staticBuffer && staticBuffer->getBufferSize() != 0 && staticBuffer->getIndexType() == type && alignedOffset) { indexBuffer = staticBuffer; - streamOffset = staticBuffer->lookupRange(offset, count, &translated->minIndex, &translated->maxIndex); - - if (streamOffset == -1) + if (!staticBuffer->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex, + &translated->maxIndex, &streamOffset)) { - streamOffset = (offset / indexTypeSize(type)) * indexTypeSize(destinationIndexType); + streamOffset = (offset / gl::ComputeTypeSize(type)) * gl::ComputeTypeSize(destinationIndexType); computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); - staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset); + staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, + translated->maxIndex, streamOffset); } } else { - int convertCount = count; + unsigned int convertCount = count; if (staticBuffer) { if (staticBuffer->getBufferSize() == 0 && alignedOffset) { indexBuffer = staticBuffer; - convertCount = storage->getSize() / indexTypeSize(type); + convertCount = storage->getSize() / gl::ComputeTypeSize(type); } else { @@ -201,12 +213,22 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer return GL_INVALID_OPERATION; } - unsigned int bufferSizeRequired = convertCount * indexTypeSize(destinationIndexType); - indexBuffer->reserveBufferSpace(bufferSizeRequired, type); + unsigned int indexTypeSize = gl::ComputeTypeSize(destinationIndexType); + if (convertCount > std::numeric_limits<unsigned int>::max() / indexTypeSize) + { + ERR("Reserving %u indicies of %u bytes each exceeds the maximum buffer size.", convertCount, indexTypeSize); + return GL_OUT_OF_MEMORY; + } + + unsigned int bufferSizeRequired = convertCount * indexTypeSize; + if (!indexBuffer->reserveBufferSpace(bufferSizeRequired, type)) + { + ERR("Failed to reserve %u bytes in an index buffer.", bufferSizeRequired); + return GL_OUT_OF_MEMORY; + } void* output = NULL; - streamOffset = indexBuffer->mapBuffer(bufferSizeRequired, &output); - if (streamOffset == -1 || output == NULL) + if (!indexBuffer->mapBuffer(bufferSizeRequired, &output, &streamOffset)) { ERR("Failed to map index buffer."); return GL_OUT_OF_MEMORY; @@ -224,20 +246,21 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer if (staticBuffer) { - streamOffset = (offset / indexTypeSize(type)) * indexTypeSize(destinationIndexType); - staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset); + streamOffset = (offset / gl::ComputeTypeSize(type)) * gl::ComputeTypeSize(destinationIndexType); + staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, + translated->maxIndex, streamOffset); } } translated->storage = directStorage ? storage : NULL; translated->indexBuffer = indexBuffer->getIndexBuffer(); translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial(); - translated->startIndex = streamOffset / indexTypeSize(destinationIndexType); + translated->startIndex = streamOffset / gl::ComputeTypeSize(destinationIndexType); translated->startOffset = streamOffset; if (buffer) { - buffer->promoteStaticUsage(count * indexTypeSize(type)); + buffer->promoteStaticUsage(count * gl::ComputeTypeSize(type)); } return GL_NO_ERROR; @@ -256,7 +279,7 @@ StaticIndexBufferInterface *IndexDataManager::getCountingIndices(GLsizei count) mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT); void* mappedMemory = NULL; - if (mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory) == -1 || mappedMemory == NULL) + if (!mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory, NULL)) { ERR("Failed to map counting buffer."); return NULL; @@ -286,7 +309,7 @@ StaticIndexBufferInterface *IndexDataManager::getCountingIndices(GLsizei count) mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); void* mappedMemory = NULL; - if (mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory) == -1 || mappedMemory == NULL) + if (!mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory, NULL)) { ERR("Failed to map counting buffer."); return NULL; 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 <tuple> + +namespace rx +{ + +void IndexRangeCache::addRange(GLenum type, unsigned int offset, GLsizei count, unsigned int minIdx, unsigned int maxIdx, + unsigned int streamOffset) +{ + mIndexRangeCache[IndexRange(type, offset, count)] = IndexBounds(minIdx, maxIdx, streamOffset); +} + +void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size) +{ + unsigned int invalidateStart = offset; + unsigned int invalidateEnd = offset + size; + + IndexRangeMap::iterator i = mIndexRangeCache.begin(); + while (i != mIndexRangeCache.end()) + { + unsigned int rangeStart = i->second.streamOffset; + unsigned int rangeEnd = i->second.streamOffset + (gl::ComputeTypeSize(i->first.type) * i->first.count); + + if (invalidateEnd < rangeStart || invalidateStart > rangeEnd) + { + ++i; + } + else + { + i = mIndexRangeCache.erase(i); + } + } +} + +bool IndexRangeCache::findRange(GLenum type, unsigned int offset, GLsizei count, unsigned int *outMinIndex, + unsigned int *outMaxIndex, unsigned int *outStreamOffset) const +{ + IndexRangeMap::const_iterator i = mIndexRangeCache.find(IndexRange(type, offset, count)); + if (i != mIndexRangeCache.end()) + { + if (outMinIndex) *outMinIndex = i->second.minIndex; + if (outMaxIndex) *outMaxIndex = i->second.maxIndex; + if (outStreamOffset) *outStreamOffset = i->second.streamOffset; + return true; + } + else + { + if (outMinIndex) *outMinIndex = 0; + if (outMaxIndex) *outMaxIndex = 0; + if (outStreamOffset) *outStreamOffset = 0; + return false; + } +} + +void IndexRangeCache::clear() +{ + mIndexRangeCache.clear(); +} + +IndexRangeCache::IndexRange::IndexRange() + : type(GL_NONE), offset(0), count(0) +{ +} + +IndexRangeCache::IndexRange::IndexRange(GLenum typ, intptr_t off, GLsizei c) + : type(typ), offset(off), count(c) +{ +} + +bool IndexRangeCache::IndexRange::operator<(const IndexRange& rhs) const +{ + return std::make_tuple(type, offset, count) < std::make_tuple(rhs.type, rhs.offset, rhs.count); +} + +IndexRangeCache::IndexBounds::IndexBounds() + : minIndex(0), maxIndex(0), streamOffset(0) +{ +} + +IndexRangeCache::IndexBounds::IndexBounds(unsigned int minIdx, unsigned int maxIdx, unsigned int offset) + : minIndex(minIdx), maxIndex(maxIdx), streamOffset(offset) +{ +} + +} 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<IndexRange, IndexBounds> 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); - - 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; + programBinary->getActiveAttribute(ilKey.elementCount, 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL); + + 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<const char*>(&elementCount); + } + + const char *end() const + { + return reinterpret_cast<const char*>(&elements[elementCount]); + } }; struct InputLayoutCounterPair @@ -50,6 +66,11 @@ class InputLayoutCache unsigned long long lastUsedTime; }; + ID3D11InputLayout *mCurrentIL; + unsigned int mCurrentBuffers[gl::MAX_VERTEX_ATTRIBS]; + UINT mCurrentVertexStrides[gl::MAX_VERTEX_ATTRIBS]; + UINT mCurrentVertexOffsets[gl::MAX_VERTEX_ATTRIBS]; + static std::size_t hashInputLayout(const InputLayoutKey &inputLayout); static bool compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b); 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 <EGL/eglext.h> #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<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::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<unsigned int>(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<unsigned int*>(mappedMemory); - unsigned int indexBufferOffset = static_cast<unsigned int>(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<unsigned int>::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<unsigned int*>(mappedMemory); - unsigned int indexBufferOffset = static_cast<unsigned int>(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<const GLubyte*>(indices)[0]; data[i*3 + 1] = static_cast<const GLubyte*>(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<const GLushort*>(indices)[0]; data[i*3 + 1] = static_cast<const GLushort*>(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<const GLuint*>(indices)[0]; data[i*3 + 1] = static_cast<const GLuint*>(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 (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 (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; + } 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(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(mClearPS, "Renderer11 masked clear pixel shader"); + 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<void**>(&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)) - { - 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 + TRACE_EVENT0("gpu", "GetDeviceCaps"); + for (int i = 0; i < 10; ++i) { - 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; + TRACE_EVENT0("gpu", "getMultiSampleSupport2"); + 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; + 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) - { - if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max) + 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<const GLubyte*>(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<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::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<unsigned int>(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<UINT>(offset) / 4; + startIndex = static_cast<unsigned int>(offset) / 4; unsigned int *data = reinterpret_cast<unsigned int*>(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<unsigned int>(count) + 1 > (std::numeric_limits<unsigned short>::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<unsigned int>(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<UINT>(offset) / 2; + startIndex = static_cast<unsigned int>(offset) / 2; unsigned short *data = reinterpret_cast<unsigned short*>(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<int>(mWritePosition); - mWritePosition += mVertexBuffer->getSpaceRequired(attrib, count, instances); + if (outStreamOffset) + { + *outStreamOffset = mWritePosition; + } + + mWritePosition += spaceRequired; - return oldWritePos; + 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<int>(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<unsigned int>(instances) < std::numeric_limits<unsigned int>::max() - (attrib.mDivisor - 1)) + { + // Round up + elementCount = (static_cast<unsigned int>(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor; + } + else + { + elementCount = instances / attrib.mDivisor; + } + } + + if (elementSize <= std::numeric_limits<unsigned int>::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<unsigned int>(instances) < std::numeric_limits<unsigned int>::max() - (attrib.mDivisor - 1)) + { + // Round up + elementCount = (static_cast<unsigned int>(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor; + } + else + { + elementCount = static_cast<unsigned int>(instances) / attrib.mDivisor; + } + } + + if (elementSize <= std::numeric_limits<unsigned int>::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<unsigned int>(std::numeric_limits<int>::max())) + { + size = static_cast<unsigned int>(std::numeric_limits<int>::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 (!staticBuffer->storeVertexAttributes(attribs[i], -startIndex, totalCount, 0, &streamOffset)) + { + return GL_OUT_OF_MEMORY; + } } - if (streamOffset != -1) + 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) { - streamOffset += (attribs[i].mOffset / attribs[i].stride()) * outputElementSize; - - if (instances == 0 || attribs[i].mDivisor == 0) - { - streamOffset += start * outputElementSize; - } + 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 <string> + +#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<int>(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<int>(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<int>(value1_val), \ + value2_name, static_cast<int>(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<int>(value1_val), \ + value2_name, static_cast<int>(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<int>(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<int>(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<int>(value1_val), \ + value2_name, static_cast<int>(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<int>(value1_val), \ + value2_name, static_cast<int>(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<bucket_number> 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<bucket_number>::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<bucket_number>::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<bucket_number>::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<unsigned char>(0)) +#define TRACE_EVENT_FLAG_COPY (static_cast<unsigned char>(1 << 0)) +#define TRACE_EVENT_FLAG_HAS_ID (static_cast<unsigned char>(1 << 1)) +#define TRACE_EVENT_FLAG_MANGLE_ID (static_cast<unsigned char>(1 << 2)) + +// Type values for identifying types in the TraceValue union. +#define TRACE_VALUE_TYPE_BOOL (static_cast<unsigned char>(1)) +#define TRACE_VALUE_TYPE_UINT (static_cast<unsigned char>(2)) +#define TRACE_VALUE_TYPE_INT (static_cast<unsigned char>(3)) +#define TRACE_VALUE_TYPE_DOUBLE (static_cast<unsigned char>(4)) +#define TRACE_VALUE_TYPE_POINTER (static_cast<unsigned char>(5)) +#define TRACE_VALUE_TYPE_STRING (static_cast<unsigned char>(6)) +#define TRACE_VALUE_TYPE_COPY_STRING (static_cast<unsigned char>(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<unsigned long long>(reinterpret_cast<unsigned long>(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<unsigned long long>(id)) { (void)flags; } + explicit TraceID(long id, unsigned char* flags) : + m_data(static_cast<unsigned long long>(id)) { (void)flags; } + explicit TraceID(int id, unsigned char* flags) : + m_data(static_cast<unsigned long long>(id)) { (void)flags; } + explicit TraceID(short id, unsigned char* flags) : + m_data(static_cast<unsigned long long>(id)) { (void)flags; } + explicit TraceID(signed char id, unsigned char* flags) : + m_data(static_cast<unsigned long long>(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<unsigned long long>(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<class ARG1_TYPE> +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<class ARG1_TYPE, class ARG2_TYPE> +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<size_t BucketNumber> +class SamplingStateScope { +public: + SamplingStateScope(const char* categoryAndName) + { + m_previousState = SamplingStateScope<BucketNumber>::current(); + SamplingStateScope<BucketNumber>::set(categoryAndName); + } + + ~SamplingStateScope() + { + SamplingStateScope<BucketNumber>::set(m_previousState); + } + + // FIXME: Make load/store to traceSamplingState[] thread-safe and atomic. + static inline const char* current() + { + return reinterpret_cast<const char*>(*gl::traceSamplingState[BucketNumber]); + } + static inline void set(const char* categoryAndName) + { + *gl::traceSamplingState[BucketNumber] = reinterpret_cast<long>(const_cast<char*>(categoryAndName)); + } + +private: + const char* m_previousState; +}; + +} // namespace TraceEvent + +} // namespace gl + +#endif |