diff options
author | Andrew Knight <andrew.knight@digia.com> | 2014-09-25 13:22:55 +0300 |
---|---|---|
committer | Andrew Knight <andrew.knight@digia.com> | 2014-09-29 16:09:29 +0200 |
commit | 311157c3c6849e8efccd88f7594bb34c570a6780 (patch) | |
tree | a50c252b638488326529c0e69aa05e42abce7462 | |
parent | 04d3a89e20d49a3b5015b071bfdedc81973b090c (diff) |
ANGLE: Upgrade to 2.1~abce76206141
Upgrade to address issues discovered since the last upgrade.
Patch notes:
0000-General-fixes-for-ANGLE-2.1.patch
added removal of the unused third-party tracing functions
0003-Fix-compilation-with-MinGW-gcc-64-bit.patch
removed as it is no longer needed
0011-ANGLE-Fix-compilation-error-on-MinGW-caused-by-trace.patch
removed as it is no longer needed
0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch
now supports MinGW 64-bit
[ChangeLog][Third-party libraries] ANGLE updated to 2.1~f8602ad91e4f
Task-number: QTBUG-40649
Task-number: QTBUG-40658
Task-number: QTBUG-41031
Task-number: QTBUG-41081
Task-number: QTBUG-41308
Task-number: QTBUG-41563
Change-Id: I9f776c8d5cb94ddb12d608a8d5630bfc54437bea
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: Oliver Wolff <oliver.wolff@digia.com>
Reviewed-by: Kai Koehne <kai.koehne@digia.com>
279 files changed, 18249 insertions, 16864 deletions
diff --git a/src/3rdparty/angle/AUTHORS b/src/3rdparty/angle/AUTHORS index 0bdb65ee9a..b79bb5d161 100644 --- a/src/3rdparty/angle/AUTHORS +++ b/src/3rdparty/angle/AUTHORS @@ -20,6 +20,7 @@ Intel Corporation Mozilla Corporation Turbulenz Klarälvdalens Datakonsult AB +Microsoft Open Technologies, Inc. Jacek Caban Mark Callow diff --git a/src/3rdparty/angle/CONTRIBUTORS b/src/3rdparty/angle/CONTRIBUTORS index 7d152e7abf..0cae10a0f6 100644 --- a/src/3rdparty/angle/CONTRIBUTORS +++ b/src/3rdparty/angle/CONTRIBUTORS @@ -59,6 +59,7 @@ Intel Corporation Jin Yang Andy Chen Josh Triplett + Sudarsana Nagineni Klarälvdalens Datakonsult AB Milian Wolff @@ -78,3 +79,6 @@ Ulrik Persson (ddefrostt) Mark Banner (standard8mbp) David Kilzer +Microsoft Open Technologies, Inc. +Cooper Partin +Austin Kinross diff --git a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h index 4b69fb1fb0..b7989f5f7e 100644 --- a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h +++ b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h @@ -23,9 +23,10 @@ #define COMPILER_EXPORT #endif -#include "KHR/khrplatform.h" #include <stddef.h> +#include "KHR/khrplatform.h" + // // This is the platform independent interface between an OGL driver // and the shading language compiler. @@ -37,13 +38,17 @@ namespace sh typedef unsigned int GLenum; } +// Must be included after GLenum proxy typedef +// Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h +#include "ShaderVars.h" + #ifdef __cplusplus extern "C" { #endif // Version number for shader translation API. // It is incremented every time the API changes. -#define ANGLE_SH_VERSION 128 +#define ANGLE_SH_VERSION 130 typedef enum { SH_GLES2_SPEC = 0x8B40, @@ -100,14 +105,9 @@ typedef enum { SH_NAME_MAX_LENGTH = 0x6001, SH_HASHED_NAME_MAX_LENGTH = 0x6002, SH_HASHED_NAMES_COUNT = 0x6003, - SH_ACTIVE_UNIFORMS_ARRAY = 0x6004, - SH_SHADER_VERSION = 0x6005, - SH_ACTIVE_INTERFACE_BLOCKS_ARRAY = 0x6006, - SH_ACTIVE_OUTPUT_VARIABLES_ARRAY = 0x6007, - SH_ACTIVE_ATTRIBUTES_ARRAY = 0x6008, - SH_ACTIVE_VARYINGS_ARRAY = 0x6009, - SH_RESOURCES_STRING_LENGTH = 0x600A, - SH_OUTPUT_TYPE = 0x600B + SH_SHADER_VERSION = 0x6004, + SH_RESOURCES_STRING_LENGTH = 0x6005, + SH_OUTPUT_TYPE = 0x6006 } ShShaderInfo; // Compile options. @@ -189,6 +189,11 @@ typedef enum { // This flag scalarizes vec/ivec/bvec/mat constructor args. // It is intended as a workaround for Linux/Mac driver bugs. SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS = 0x40000, + + // This flag overwrites a struct name with a unique prefix. + // It is intended as a workaround for drivers that do not handle + // struct scopes correctly, including all Mac drivers and Linux AMD. + SH_REGENERATE_STRUCT_NAMES = 0x80000, } ShCompileOptions; // Defines alternate strategies for implementing array index clamping. @@ -453,17 +458,17 @@ COMPILER_EXPORT void ShGetNameHashingEntry(const ShHandle handle, char* name, char* hashedName); -// Returns a parameter from a compiled shader. +// Shader variable inspection. +// Returns a pointer to a list of variables of the designated type. +// (See ShaderVars.h for type definitions, included above) +// Returns NULL on failure. // Parameters: // handle: Specifies the compiler -// pname: Specifies the parameter to query. -// The following parameters are defined: -// SH_ACTIVE_UNIFORMS_ARRAY: an STL vector of active uniforms. Valid only for -// HLSL output. -// params: Requested parameter -COMPILER_EXPORT void ShGetInfoPointer(const ShHandle handle, - ShShaderInfo pname, - void** params); +COMPILER_EXPORT const std::vector<sh::Uniform> *ShGetUniforms(const ShHandle handle); +COMPILER_EXPORT const std::vector<sh::Varying> *ShGetVaryings(const ShHandle handle); +COMPILER_EXPORT const std::vector<sh::Attribute> *ShGetAttributes(const ShHandle handle); +COMPILER_EXPORT const std::vector<sh::Attribute> *ShGetOutputVariables(const ShHandle handle); +COMPILER_EXPORT const std::vector<sh::InterfaceBlock> *ShGetInterfaceBlocks(const ShHandle handle); typedef struct { diff --git a/src/3rdparty/angle/include/GLSLANG/ShaderVars.h b/src/3rdparty/angle/include/GLSLANG/ShaderVars.h new file mode 100644 index 0000000000..9c38647dda --- /dev/null +++ b/src/3rdparty/angle/include/GLSLANG/ShaderVars.h @@ -0,0 +1,123 @@ +// +// Copyright (c) 2013-2014 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. +// +// ShaderVars.h: +// Types to represent GL variables (varyings, uniforms, etc) +// + +#ifndef _COMPILER_INTERFACE_VARIABLES_ +#define _COMPILER_INTERFACE_VARIABLES_ + +#include <string> +#include <vector> +#include <algorithm> + +// Assume ShaderLang.h is included before ShaderVars.h, for sh::GLenum +// Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h + +namespace sh +{ + +// Varying interpolation qualifier, see section 4.3.9 of the ESSL 3.00.4 spec +enum InterpolationType +{ + INTERPOLATION_SMOOTH, + INTERPOLATION_CENTROID, + INTERPOLATION_FLAT +}; + +// Uniform block layout qualifier, see section 4.3.8.3 of the ESSL 3.00.4 spec +enum BlockLayoutType +{ + BLOCKLAYOUT_STANDARD, + BLOCKLAYOUT_PACKED, + BLOCKLAYOUT_SHARED +}; + +// Base class for all variables defined in shaders, including Varyings, Uniforms, etc +// Note: we must override the copy constructor and assignment operator so we can +// work around excessive GCC binary bloating: +// See https://code.google.com/p/angleproject/issues/detail?id=697 +struct COMPILER_EXPORT ShaderVariable +{ + ShaderVariable(); + ShaderVariable(GLenum typeIn, unsigned int arraySizeIn); + ~ShaderVariable(); + ShaderVariable(const ShaderVariable &other); + ShaderVariable &operator=(const ShaderVariable &other); + + bool isArray() const { return arraySize > 0; } + unsigned int elementCount() const { return std::max(1u, arraySize); } + bool isStruct() const { return !fields.empty(); } + + GLenum type; + GLenum precision; + std::string name; + std::string mappedName; + unsigned int arraySize; + bool staticUse; + std::vector<ShaderVariable> fields; + std::string structName; +}; + +struct COMPILER_EXPORT Uniform : public ShaderVariable +{ + Uniform(); + ~Uniform(); + Uniform(const Uniform &other); + Uniform &operator=(const Uniform &other); +}; + +struct COMPILER_EXPORT Attribute : public ShaderVariable +{ + Attribute(); + ~Attribute(); + Attribute(const Attribute &other); + Attribute &operator=(const Attribute &other); + + int location; +}; + +struct COMPILER_EXPORT InterfaceBlockField : public ShaderVariable +{ + InterfaceBlockField(); + ~InterfaceBlockField(); + InterfaceBlockField(const InterfaceBlockField &other); + InterfaceBlockField &operator=(const InterfaceBlockField &other); + + bool isRowMajorLayout; +}; + +struct COMPILER_EXPORT Varying : public ShaderVariable +{ + Varying(); + ~Varying(); + Varying(const Varying &other); + Varying &operator=(const Varying &other); + + InterpolationType interpolation; + bool isInvariant; +}; + +struct COMPILER_EXPORT InterfaceBlock +{ + InterfaceBlock(); + ~InterfaceBlock(); + InterfaceBlock(const InterfaceBlock &other); + InterfaceBlock &operator=(const InterfaceBlock &other); + + std::string name; + std::string mappedName; + std::string instanceName; + unsigned int arraySize; + BlockLayoutType layout; + bool isRowMajorLayout; + bool staticUse; + std::vector<InterfaceBlockField> fields; +}; + +} + +#endif // _COMPILER_INTERFACE_VARIABLES_ diff --git a/src/3rdparty/angle/include/angle_gl.h b/src/3rdparty/angle/include/angle_gl.h index 663aa259ea..d093f75ee2 100644 --- a/src/3rdparty/angle/include/angle_gl.h +++ b/src/3rdparty/angle/include/angle_gl.h @@ -10,9 +10,6 @@ #ifndef ANGLE_GL_H_ #define ANGLE_GL_H_ -#define GL_GLEXT_PROTOTYPES -#define GL_APICALL - #include "GLES2/gl2.h" #include "GLES2/gl2ext.h" #include "GLES3/gl3.h" diff --git a/src/3rdparty/angle/src/commit.h b/src/3rdparty/angle/src/commit.h index e1378309a4..a2e761b131 100644 --- a/src/3rdparty/angle/src/commit.h +++ b/src/3rdparty/angle/src/commit.h @@ -7,6 +7,6 @@ // This is a default commit hash header, when git is not available. // -#define ANGLE_COMMIT_HASH "07d49ef5350a" +#define ANGLE_COMMIT_HASH "abce76206141" #define ANGLE_COMMIT_HASH_SIZE 12 -#define ANGLE_COMMIT_DATE "2014-07-25 16:01:42 +0000" +#define ANGLE_COMMIT_DATE "2014-09-23 19:37:05 +0000" diff --git a/src/3rdparty/angle/src/common/RefCountObject.h b/src/3rdparty/angle/src/common/RefCountObject.h index 8635aa59d8..6eeaee1928 100644 --- a/src/3rdparty/angle/src/common/RefCountObject.h +++ b/src/3rdparty/angle/src/common/RefCountObject.h @@ -12,11 +12,11 @@ #ifndef COMMON_REFCOUNTOBJECT_H_ #define COMMON_REFCOUNTOBJECT_H_ -#include <cstddef> +#include "common/debug.h" #include "angle_gl.h" -#include "common/debug.h" +#include <cstddef> class RefCountObject { diff --git a/src/3rdparty/angle/src/common/angleutils.cpp b/src/3rdparty/angle/src/common/angleutils.cpp new file mode 100644 index 0000000000..2673abf30a --- /dev/null +++ b/src/3rdparty/angle/src/common/angleutils.cpp @@ -0,0 +1,37 @@ +// +// Copyright (c) 2014 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/angleutils.h" + +#include <vector> + +std::string FormatString(const char *fmt, va_list vararg) +{ + static std::vector<char> buffer(512); + + // Attempt to just print to the current buffer + int len = vsnprintf(&buffer[0], buffer.size(), fmt, vararg); + if (len < 0 || static_cast<size_t>(len) >= buffer.size()) + { + // Buffer was not large enough, calculate the required size and resize the buffer + len = vsnprintf(NULL, 0, fmt, vararg); + buffer.resize(len + 1); + + // Print again + vsnprintf(&buffer[0], buffer.size(), fmt, vararg); + } + + return std::string(buffer.data(), len); +} + +std::string FormatString(const char *fmt, ...) +{ + va_list vararg; + va_start(vararg, fmt); + std::string result = FormatString(fmt, vararg); + va_end(vararg); + return result; +} diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h index d94b4f5ff9..ddbbd5f501 100644 --- a/src/3rdparty/angle/src/common/angleutils.h +++ b/src/3rdparty/angle/src/common/angleutils.h @@ -16,6 +16,7 @@ #include <string> #include <set> #include <sstream> +#include <cstdarg> // A macro to disallow the copy constructor and operator= functions // This must be used in the private: declarations for a class @@ -23,8 +24,8 @@ TypeName(const TypeName&); \ void operator=(const TypeName&) -template <typename T, unsigned int N> -inline unsigned int ArraySize(T(&)[N]) +template <typename T, size_t N> +inline size_t ArraySize(T(&)[N]) { return N; } @@ -131,6 +132,9 @@ inline std::string Str(int i) return strstr.str(); } +std::string FormatString(const char *fmt, va_list vararg); +std::string FormatString(const char *fmt, ...); + #if defined(_MSC_VER) && _MSC_VER < 1900 #define snprintf _snprintf #endif diff --git a/src/3rdparty/angle/src/common/blocklayout.cpp b/src/3rdparty/angle/src/common/blocklayout.cpp index 7db6e980f1..e3b2d43566 100644 --- a/src/3rdparty/angle/src/common/blocklayout.cpp +++ b/src/3rdparty/angle/src/common/blocklayout.cpp @@ -8,7 +8,6 @@ // #include "common/blocklayout.h" -#include "common/shadervars.h" #include "common/mathutil.h" #include "common/utilities.h" @@ -20,46 +19,7 @@ BlockLayoutEncoder::BlockLayoutEncoder() { } -void BlockLayoutEncoder::encodeInterfaceBlockFields(const std::vector<InterfaceBlockField> &fields) -{ - for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) - { - const InterfaceBlockField &variable = fields[fieldIndex]; - - if (variable.fields.size() > 0) - { - const unsigned int elementCount = std::max(1u, variable.arraySize); - - for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++) - { - enterAggregateType(); - encodeInterfaceBlockFields(variable.fields); - exitAggregateType(); - } - } - else - { - encodeInterfaceBlockField(variable); - } - } -} - -BlockMemberInfo BlockLayoutEncoder::encodeInterfaceBlockField(const InterfaceBlockField &field) -{ - int arrayStride; - int matrixStride; - - ASSERT(field.fields.empty()); - getBlockLayoutInfo(field.type, field.arraySize, field.isRowMajorMatrix, &arrayStride, &matrixStride); - - const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, field.isRowMajorMatrix); - - advanceOffset(field.type, field.arraySize, field.isRowMajorMatrix, arrayStride, matrixStride); - - return memberInfo; -} - -void BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix) +BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix) { int arrayStride; int matrixStride; @@ -69,6 +29,8 @@ void BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool is const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, isRowMajorMatrix); advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride); + + return memberInfo; } void BlockLayoutEncoder::nextRegister() diff --git a/src/3rdparty/angle/src/common/blocklayout.h b/src/3rdparty/angle/src/common/blocklayout.h index 3a1ab5ccb0..d46ac6e547 100644 --- a/src/3rdparty/angle/src/common/blocklayout.h +++ b/src/3rdparty/angle/src/common/blocklayout.h @@ -10,10 +10,11 @@ #ifndef COMMON_BLOCKLAYOUT_H_ #define COMMON_BLOCKLAYOUT_H_ +#include <cstddef> #include <vector> + #include "angle_gl.h" #include <GLSLANG/ShaderLang.h> -#include <cstddef> namespace sh { @@ -48,9 +49,7 @@ class BlockLayoutEncoder public: BlockLayoutEncoder(); - void encodeInterfaceBlockFields(const std::vector<InterfaceBlockField> &fields); - BlockMemberInfo encodeInterfaceBlockField(const InterfaceBlockField &field); - void encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix); + BlockMemberInfo encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix); size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; } size_t getCurrentRegister() const { return mCurrentOffset / ComponentsPerRegister; } diff --git a/src/3rdparty/angle/src/common/debug.cpp b/src/3rdparty/angle/src/common/debug.cpp index d6eecf7157..dcad327564 100644 --- a/src/3rdparty/angle/src/common/debug.cpp +++ b/src/3rdparty/angle/src/common/debug.cpp @@ -8,6 +8,7 @@ #include "common/debug.h" #include "common/platform.h" +#include "common/angleutils.h" #include <stdarg.h> #include <vector> @@ -25,22 +26,7 @@ typedef void (*PerfOutputFunction)(unsigned int, const wchar_t*); static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const char *format, va_list vararg) { #if defined(ANGLE_ENABLE_PERF) || defined(ANGLE_ENABLE_TRACE) - static std::vector<char> asciiMessageBuffer(512); - - // Attempt to just print to the current buffer - int len = vsnprintf(&asciiMessageBuffer[0], asciiMessageBuffer.size(), format, vararg); - if (len < 0 || static_cast<size_t>(len) >= asciiMessageBuffer.size()) - { - // Buffer was not large enough, calculate the required size and resize the buffer - len = vsnprintf(NULL, 0, format, vararg); - asciiMessageBuffer.resize(len + 1); - - // Print again - vsnprintf(&asciiMessageBuffer[0], asciiMessageBuffer.size(), format, vararg); - } - - // NULL terminate the buffer to be safe - asciiMessageBuffer[len] = '\0'; + std::string formattedMessage = FormatString(format, vararg); #endif #if defined(ANGLE_ENABLE_PERF) @@ -48,12 +34,12 @@ static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const c { // The perf function only accepts wide strings, widen the ascii message static std::wstring wideMessage; - if (wideMessage.capacity() < asciiMessageBuffer.size()) + if (wideMessage.capacity() < formattedMessage.length()) { - wideMessage.reserve(asciiMessageBuffer.size()); + wideMessage.reserve(formattedMessage.size()); } - wideMessage.assign(asciiMessageBuffer.begin(), asciiMessageBuffer.begin() + len); + wideMessage.assign(formattedMessage.begin(), formattedMessage.end()); perfFunc(0, wideMessage.c_str()); } @@ -70,7 +56,7 @@ static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const c static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app); if (file) { - file.write(&asciiMessageBuffer[0], len); + file.write(formattedMessage.c_str(), formattedMessage.length()); file.flush(); } diff --git a/src/3rdparty/angle/src/common/debug.h b/src/3rdparty/angle/src/common/debug.h index 997ebca6be..bf2bca8f24 100644 --- a/src/3rdparty/angle/src/common/debug.h +++ b/src/3rdparty/angle/src/common/debug.h @@ -91,6 +91,10 @@ namespace gl // A macro to indicate unimplemented functionality +#if defined (ANGLE_TEST_CONFIG) +#define NOASSERT_UNIMPLEMENTED 1 +#endif + // Define NOASSERT_UNIMPLEMENTED to non zero to skip the assert fail in the unimplemented checks // This will allow us to test with some automated test suites (eg dEQP) without crashing #ifndef NOASSERT_UNIMPLEMENTED diff --git a/src/3rdparty/angle/src/common/event_tracer.cpp b/src/3rdparty/angle/src/common/event_tracer.cpp deleted file mode 100644 index 353c69d05c..0000000000 --- a/src/3rdparty/angle/src/common/event_tracer.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// 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 TRACE_ENTRY 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 deleted file mode 100644 index fa97435faa..0000000000 --- a/src/3rdparty/angle/src/common/event_tracer.h +++ /dev/null @@ -1,43 +0,0 @@ -// 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_ - -#include "common/platform.h" - -#if !defined(TRACE_ENTRY) -# ifdef ANGLE_PLATFORM_WINDOWS -# define TRACE_ENTRY __stdcall -# else -# define TRACE_ENTRY -# endif // ANGLE_PLATFORM_WINDOWS -#endif //TRACE_ENTRY - -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 TRACE_ENTRY 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/mathutil.cpp b/src/3rdparty/angle/src/common/mathutil.cpp index 20b3f0c113..496633632b 100644 --- a/src/3rdparty/angle/src/common/mathutil.cpp +++ b/src/3rdparty/angle/src/common/mathutil.cpp @@ -7,6 +7,7 @@ // mathutil.cpp: Math and bit manipulation functions. #include "common/mathutil.h" + #include <algorithm> #include <math.h> diff --git a/src/3rdparty/angle/src/common/mathutil.h b/src/3rdparty/angle/src/common/mathutil.h index f32663fa02..52f2bc1c0e 100644 --- a/src/3rdparty/angle/src/common/mathutil.h +++ b/src/3rdparty/angle/src/common/mathutil.h @@ -505,21 +505,33 @@ inline unsigned int averageFloat10(unsigned int a, unsigned int b) namespace rx { +template <typename T> struct Range { Range() {} - Range(int lo, int hi) : start(lo), end(hi) { ASSERT(lo <= hi); } + Range(T lo, T hi) : start(lo), end(hi) { ASSERT(lo <= hi); } + + T start; + T end; - int start; - int end; + T length() const { return end - start; } }; +typedef Range<int> RangeI; +typedef Range<unsigned int> RangeUI; + template <typename T> T roundUp(const T value, const T alignment) { return value + alignment - 1 - (value - 1) % alignment; } +inline unsigned int UnsignedCeilDivide(unsigned int value, unsigned int divisor) +{ + unsigned int divided = value / divisor; + return (divided + ((value % divisor == 0) ? 0 : 1)); +} + template <class T> inline bool IsUnsignedAdditionSafe(T lhs, T rhs) { diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h index 44c5c7c03b..b53394f337 100644 --- a/src/3rdparty/angle/src/common/platform.h +++ b/src/3rdparty/angle/src/common/platform.h @@ -52,6 +52,9 @@ # if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_PERF) # include <d3d9.h> +# if !defined(COMPILER_IMPLEMENTATION) +# include <d3dcompiler.h> +# endif # endif # if defined(ANGLE_ENABLE_D3D11) @@ -61,16 +64,25 @@ # include <dxgi.h> # if _MSC_VER >= 1700 # include <dxgi1_2.h> +# endif +# if !defined(COMPILER_IMPLEMENTATION) # include <d3dcompiler.h> # endif +# if defined(__MINGW32__) +typedef enum D3D11_MAP_FLAG +{ + D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000L +} D3D11_MAP_FLAG; +typedef struct D3D11_QUERY_DATA_SO_STATISTICS +{ + UINT64 NumPrimitivesWritten; + UINT64 PrimitivesStorageNeeded; +} D3D11_QUERY_DATA_SO_STATISTICS; +# endif # endif # undef near # undef far -# undef NEAR -# define NEAR -# undef FAR -# define FAR #endif #endif // COMMON_PLATFORM_H_ diff --git a/src/3rdparty/angle/src/common/shadervars.h b/src/3rdparty/angle/src/common/shadervars.h deleted file mode 100644 index 0442d81500..0000000000 --- a/src/3rdparty/angle/src/common/shadervars.h +++ /dev/null @@ -1,157 +0,0 @@ -// -// Copyright (c) 2013-2014 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. -// -// shadervars.h: -// Types to represent GL variables (varyings, uniforms, etc) -// - -#ifndef COMMON_SHADERVARIABLE_H_ -#define COMMON_SHADERVARIABLE_H_ - -#include <string> -#include <vector> -#include <algorithm> -#include "GLSLANG/ShaderLang.h" - -namespace sh -{ - -// Varying interpolation qualifier, see section 4.3.9 of the ESSL 3.00.4 spec -enum InterpolationType -{ - INTERPOLATION_SMOOTH, - INTERPOLATION_CENTROID, - INTERPOLATION_FLAT -}; - -// Uniform block layout qualifier, see section 4.3.8.3 of the ESSL 3.00.4 spec -enum BlockLayoutType -{ - BLOCKLAYOUT_STANDARD, - BLOCKLAYOUT_PACKED, - BLOCKLAYOUT_SHARED -}; - -// Base class for all variables defined in shaders, including Varyings, Uniforms, etc -struct ShaderVariable -{ - ShaderVariable() - : type(0), - precision(0), - arraySize(0), - staticUse(false) - {} - - ShaderVariable(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn) - : type(typeIn), - precision(precisionIn), - name(nameIn), - arraySize(arraySizeIn), - staticUse(false) - {} - - bool isArray() const { return arraySize > 0; } - unsigned int elementCount() const { return std::max(1u, arraySize); } - - GLenum type; - GLenum precision; - std::string name; - std::string mappedName; - unsigned int arraySize; - bool staticUse; -}; - -struct Uniform : public ShaderVariable -{ - Uniform() - {} - - Uniform(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn) - : ShaderVariable(typeIn, precisionIn, nameIn, arraySizeIn) - {} - - bool isStruct() const { return !fields.empty(); } - - std::vector<Uniform> fields; -}; - -struct Attribute : public ShaderVariable -{ - Attribute() - : location(-1) - {} - - Attribute(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn, int locationIn) - : ShaderVariable(typeIn, precisionIn, nameIn, arraySizeIn), - location(locationIn) - {} - - int location; -}; - -struct InterfaceBlockField : public ShaderVariable -{ - InterfaceBlockField() - : isRowMajorMatrix(false) - {} - - InterfaceBlockField(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn, bool isRowMajorMatrix) - : ShaderVariable(typeIn, precisionIn, nameIn, arraySizeIn), - isRowMajorMatrix(isRowMajorMatrix) - {} - - bool isStruct() const { return !fields.empty(); } - - bool isRowMajorMatrix; - std::vector<InterfaceBlockField> fields; -}; - -struct Varying : public ShaderVariable -{ - Varying() - : interpolation(INTERPOLATION_SMOOTH) - {} - - Varying(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn, InterpolationType interpolationIn) - : ShaderVariable(typeIn, precisionIn, nameIn, arraySizeIn), - interpolation(interpolationIn) - {} - - bool isStruct() const { return !fields.empty(); } - - InterpolationType interpolation; - std::vector<Varying> fields; - std::string structName; -}; - -struct InterfaceBlock -{ - InterfaceBlock() - : arraySize(0), - layout(BLOCKLAYOUT_PACKED), - isRowMajorLayout(false), - staticUse(false) - {} - - InterfaceBlock(const char *name, unsigned int arraySize) - : name(name), - arraySize(arraySize), - layout(BLOCKLAYOUT_SHARED), - isRowMajorLayout(false), - staticUse(false) - {} - - std::string name; - std::string mappedName; - unsigned int arraySize; - BlockLayoutType layout; - bool isRowMajorLayout; - bool staticUse; - std::vector<InterfaceBlockField> fields; -}; - -} - -#endif // COMMON_SHADERVARIABLE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h index ba9ef5e609..324b0669f4 100644 --- a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h +++ b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h @@ -69,40 +69,9 @@ enum TBasicType EbtStruct, EbtInterfaceBlock, EbtAddress, // should be deprecated?? - EbtInvariant // used as a type when qualifying a previously declared variable as being invariant }; -inline const char* getBasicString(TBasicType t) -{ - switch (t) - { - case EbtVoid: return "void"; break; - case EbtFloat: return "float"; break; - case EbtInt: return "int"; break; - case EbtUInt: return "uint"; break; - case EbtBool: return "bool"; break; - case EbtSampler2D: return "sampler2D"; break; - case EbtSampler3D: return "sampler3D"; break; - case EbtSamplerCube: return "samplerCube"; break; - case EbtSamplerExternalOES: return "samplerExternalOES"; break; - case EbtSampler2DRect: return "sampler2DRect"; break; - case EbtSampler2DArray: return "sampler2DArray"; break; - case EbtISampler2D: return "isampler2D"; break; - case EbtISampler3D: return "isampler3D"; break; - case EbtISamplerCube: return "isamplerCube"; break; - case EbtISampler2DArray: return "isampler2DArray"; break; - case EbtUSampler2D: return "usampler2D"; break; - case EbtUSampler3D: return "usampler3D"; break; - case EbtUSamplerCube: return "usamplerCube"; break; - case EbtUSampler2DArray: return "usampler2DArray"; break; - case EbtSampler2DShadow: return "sampler2DShadow"; break; - case EbtSamplerCubeShadow: return "samplerCubeShadow"; break; - case EbtSampler2DArrayShadow: return "sampler2DArrayShadow"; break; - case EbtStruct: return "structure"; break; - case EbtInterfaceBlock: return "interface block"; break; - default: return "unknown type"; - } -} +const char* getBasicString(TBasicType t); inline bool IsSampler(TBasicType type) { diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h index 926b6bed69..c6bf77c386 100644 --- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h +++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h @@ -8,7 +8,7 @@ #define COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_ #include "compiler/translator/InfoSink.h" -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // // This class decides which built-in functions need to be replaced with the diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp index 0606c72e39..368cd2ae4a 100644 --- a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp @@ -12,6 +12,7 @@ #include "compiler/translator/InitializeParseContext.h" #include "compiler/translator/InitializeVariables.h" #include "compiler/translator/ParseContext.h" +#include "compiler/translator/RegenerateStructNames.h" #include "compiler/translator/RenameFunction.h" #include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h" #include "compiler/translator/UnfoldShortCircuitAST.h" @@ -257,10 +258,17 @@ bool TCompiler::compile(const char* const shaderStrings[], if (success && (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)) { - ScalarizeVecAndMatConstructorArgs scalarizer; + ScalarizeVecAndMatConstructorArgs scalarizer( + shaderType, fragmentPrecisionHigh); root->traverse(&scalarizer); } + if (success && (compileOptions & SH_REGENERATE_STRUCT_NAMES)) + { + RegenerateStructNames gen(symbolTable, shaderVersion); + root->traverse(&gen); + } + if (success && (compileOptions & SH_INTERMEDIATE_TREE)) intermediate.outputTree(root); @@ -494,18 +502,18 @@ bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root) void TCompiler::collectVariables(TIntermNode* root) { - CollectVariables collect(&attributes, - &outputVariables, - &uniforms, - &varyings, - &interfaceBlocks, - hashFunction); + sh::CollectVariables collect(&attributes, + &outputVariables, + &uniforms, + &varyings, + &interfaceBlocks, + hashFunction); root->traverse(&collect); // For backwards compatiblity with ShGetVariableInfo, expand struct // uniforms and varyings into separate variables for each field. - ExpandVariables(uniforms, &expandedUniforms); - ExpandVariables(varyings, &expandedVaryings); + sh::ExpandVariables(uniforms, &expandedUniforms); + sh::ExpandVariables(varyings, &expandedVaryings); } bool TCompiler::enforcePackingRestrictions() diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.h b/src/3rdparty/angle/src/compiler/translator/Compiler.h index 5eac2d89d1..ca0c157884 100644 --- a/src/3rdparty/angle/src/compiler/translator/Compiler.h +++ b/src/3rdparty/angle/src/compiler/translator/Compiler.h @@ -71,9 +71,9 @@ class TCompiler : public TShHandleBase const std::vector<sh::Attribute> &getAttributes() const { return attributes; } const std::vector<sh::Attribute> &getOutputVariables() const { return outputVariables; } const std::vector<sh::Uniform> &getUniforms() const { return uniforms; } - const std::vector<sh::Uniform> &getExpandedUniforms() const { return expandedUniforms; } + const std::vector<sh::ShaderVariable> &getExpandedUniforms() const { return expandedUniforms; } const std::vector<sh::Varying> &getVaryings() const { return varyings; } - const std::vector<sh::Varying> &getExpandedVaryings() const { return expandedVaryings; } + const std::vector<sh::ShaderVariable> &getExpandedVaryings() const { return expandedVaryings; } const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return interfaceBlocks; } ShHashFunction64 getHashFunction() const { return hashFunction; } @@ -83,6 +83,9 @@ class TCompiler : public TShHandleBase ShShaderOutput getOutputType() const { return outputType; } std::string getBuiltInResourcesString() const { return builtInResourcesString; } + // Get the resources set by InitBuiltInSymbolTable + const ShBuiltInResources& getResources() const; + protected: sh::GLenum getShaderType() const { return shaderType; } // Initialize symbol-table with built-in symbols. @@ -128,8 +131,6 @@ class TCompiler : public TShHandleBase bool limitExpressionComplexity(TIntermNode* root); // Get built-in extensions with default behavior. const TExtensionBehavior& getExtensionBehavior() const; - // Get the resources set by InitBuiltInSymbolTable - const ShBuiltInResources& getResources() const; const ArrayBoundsClamper& getArrayBoundsClamper() const; ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const; @@ -138,9 +139,9 @@ class TCompiler : public TShHandleBase std::vector<sh::Attribute> attributes; std::vector<sh::Attribute> outputVariables; std::vector<sh::Uniform> uniforms; - std::vector<sh::Uniform> expandedUniforms; + std::vector<sh::ShaderVariable> expandedUniforms; std::vector<sh::Varying> varyings; - std::vector<sh::Varying> expandedVaryings; + std::vector<sh::ShaderVariable> expandedVaryings; std::vector<sh::InterfaceBlock> interfaceBlocks; private: diff --git a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h index cb76f1de02..86810650dc 100644 --- a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h +++ b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h @@ -8,7 +8,7 @@ #define COMPILER_DETECT_RECURSION_H_ #include <limits.h> -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/VariableInfo.h" class TInfoSink; diff --git a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h index 1dd8be9233..35d66cbc2e 100644 --- a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h +++ b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h @@ -11,7 +11,7 @@ #ifndef COMPILER_DETECTDISCONTINUITY_H_ #define COMPILER_DETECTDISCONTINUITY_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" namespace sh { diff --git a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h index 610205eb92..c93a6f808e 100644 --- a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h +++ b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h @@ -7,7 +7,7 @@ #ifndef COMPILER_FLAGSTD140STRUCTS_H_ #define COMPILER_FLAGSTD140STRUCTS_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" namespace sh { diff --git a/src/3rdparty/angle/src/compiler/translator/HashNames.h b/src/3rdparty/angle/src/compiler/translator/HashNames.h index 85161428b2..26546a3e7b 100644 --- a/src/3rdparty/angle/src/compiler/translator/HashNames.h +++ b/src/3rdparty/angle/src/compiler/translator/HashNames.h @@ -9,7 +9,7 @@ #include <map> -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #define HASHED_NAME_PREFIX "webgl_" diff --git a/src/3rdparty/angle/src/compiler/translator/Initialize.cpp b/src/3rdparty/angle/src/compiler/translator/Initialize.cpp index e91d64f43b..10b21e6d28 100644 --- a/src/3rdparty/angle/src/compiler/translator/Initialize.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Initialize.cpp @@ -12,7 +12,7 @@ #include "compiler/translator/Initialize.h" -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "angle_gl.h" void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable) diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h index 81ab9fe90f..59c3ea0a39 100644 --- a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h +++ b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h @@ -7,7 +7,7 @@ #ifndef COMPILER_INITIALIZE_VARIABLES_H_ #define COMPILER_INITIALIZE_VARIABLES_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" class InitializeVariables : public TIntermTraverser { diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp new file mode 100644 index 0000000000..b155545ad2 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp @@ -0,0 +1,1107 @@ +// +// Copyright (c) 2002-2014 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. +// + +// +// Build the intermediate representation. +// + +#include <float.h> +#include <limits.h> +#include <algorithm> + +#include "compiler/translator/HashNames.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/SymbolTable.h" + +namespace +{ + +TPrecision GetHigherPrecision(TPrecision left, TPrecision right) +{ + return left > right ? left : right; +} + +bool ValidateMultiplication(TOperator op, const TType &left, const TType &right) +{ + switch (op) + { + case EOpMul: + case EOpMulAssign: + return left.getNominalSize() == right.getNominalSize() && + left.getSecondarySize() == right.getSecondarySize(); + case EOpVectorTimesScalar: + case EOpVectorTimesScalarAssign: + return true; + case EOpVectorTimesMatrix: + return left.getNominalSize() == right.getRows(); + case EOpVectorTimesMatrixAssign: + return left.getNominalSize() == right.getRows() && + left.getNominalSize() == right.getCols(); + case EOpMatrixTimesVector: + return left.getCols() == right.getNominalSize(); + case EOpMatrixTimesScalar: + case EOpMatrixTimesScalarAssign: + return true; + case EOpMatrixTimesMatrix: + return left.getCols() == right.getRows(); + case EOpMatrixTimesMatrixAssign: + return left.getCols() == right.getCols() && + left.getRows() == right.getRows(); + + default: + UNREACHABLE(); + return false; + } +} + +bool CompareStructure(const TType& leftNodeType, + ConstantUnion *rightUnionArray, + ConstantUnion *leftUnionArray); + +bool CompareStruct(const TType &leftNodeType, + ConstantUnion *rightUnionArray, + ConstantUnion *leftUnionArray) +{ + const TFieldList &fields = leftNodeType.getStruct()->fields(); + + size_t structSize = fields.size(); + size_t index = 0; + + for (size_t j = 0; j < structSize; j++) + { + 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; +} + +bool CompareStructure(const TType &leftNodeType, + ConstantUnion *rightUnionArray, + ConstantUnion *leftUnionArray) +{ + if (leftNodeType.isArray()) + { + TType typeWithoutArrayness = leftNodeType; + typeWithoutArrayness.clearArrayness(); + + size_t arraySize = leftNodeType.getArraySize(); + + for (size_t i = 0; i < arraySize; ++i) + { + size_t offset = typeWithoutArrayness.getObjectSize() * i; + if (!CompareStruct(typeWithoutArrayness, + &rightUnionArray[offset], + &leftUnionArray[offset])) + { + return false; + } + } + } + else + { + return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray); + } + return true; +} + +} // namespace anonymous + + +//////////////////////////////////////////////////////////////// +// +// Member functions of the nodes used for building the tree. +// +//////////////////////////////////////////////////////////////// + +#define REPLACE_IF_IS(node, type, original, replacement) \ + if (node == original) { \ + node = static_cast<type *>(replacement); \ + return true; \ + } + +bool TIntermLoop::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mInit, TIntermNode, original, replacement); + REPLACE_IF_IS(mCond, TIntermTyped, original, replacement); + REPLACE_IF_IS(mExpr, TIntermTyped, original, replacement); + REPLACE_IF_IS(mBody, TIntermNode, original, replacement); + return false; +} + +void TIntermLoop::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const +{ + if (mInit) + { + nodeQueue->push(mInit); + } + if (mCond) + { + nodeQueue->push(mCond); + } + if (mExpr) + { + nodeQueue->push(mExpr); + } + if (mBody) + { + nodeQueue->push(mBody); + } +} + +bool TIntermBranch::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement); + return false; +} + +void TIntermBranch::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const +{ + if (mExpression) + { + nodeQueue->push(mExpression); + } +} + +bool TIntermBinary::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement); + REPLACE_IF_IS(mRight, TIntermTyped, original, replacement); + return false; +} + +void TIntermBinary::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const +{ + if (mLeft) + { + nodeQueue->push(mLeft); + } + if (mRight) + { + nodeQueue->push(mRight); + } +} + +bool TIntermUnary::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement); + return false; +} + +void TIntermUnary::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const +{ + if (mOperand) + { + nodeQueue->push(mOperand); + } +} + +bool TIntermAggregate::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + for (size_t ii = 0; ii < mSequence.size(); ++ii) + { + REPLACE_IF_IS(mSequence[ii], TIntermNode, original, replacement); + } + return false; +} + +void TIntermAggregate::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const +{ + for (size_t childIndex = 0; childIndex < mSequence.size(); childIndex++) + { + nodeQueue->push(mSequence[childIndex]); + } +} + +bool TIntermSelection::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); + REPLACE_IF_IS(mTrueBlock, TIntermNode, original, replacement); + REPLACE_IF_IS(mFalseBlock, TIntermNode, original, replacement); + return false; +} + +void TIntermSelection::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const +{ + if (mCondition) + { + nodeQueue->push(mCondition); + } + if (mTrueBlock) + { + nodeQueue->push(mTrueBlock); + } + if (mFalseBlock) + { + nodeQueue->push(mFalseBlock); + } +} + +// +// Say whether or not an operation node changes the value of a variable. +// +bool TIntermOperator::isAssignment() const +{ + switch (mOp) + { + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + case EOpAssign: + case EOpAddAssign: + case EOpSubAssign: + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: + case EOpDivAssign: + return true; + default: + return false; + } +} + +// +// returns true if the operator is for one of the constructors +// +bool TIntermOperator::isConstructor() const +{ + switch (mOp) + { + case EOpConstructVec2: + case EOpConstructVec3: + case EOpConstructVec4: + case EOpConstructMat2: + case EOpConstructMat3: + case EOpConstructMat4: + case EOpConstructFloat: + case EOpConstructIVec2: + case EOpConstructIVec3: + case EOpConstructIVec4: + case EOpConstructInt: + case EOpConstructUVec2: + case EOpConstructUVec3: + case EOpConstructUVec4: + case EOpConstructUInt: + case EOpConstructBVec2: + case EOpConstructBVec3: + case EOpConstructBVec4: + case EOpConstructBool: + case EOpConstructStruct: + return true; + default: + return false; + } +} + +// +// Make sure the type of a unary operator is appropriate for its +// combination of operation and operand type. +// +// Returns false in nothing makes sense. +// +bool TIntermUnary::promote(TInfoSink &) +{ + switch (mOp) + { + case EOpLogicalNot: + if (mOperand->getBasicType() != EbtBool) + return false; + break; + case EOpNegative: + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + if (mOperand->getBasicType() == EbtBool) + return false; + break; + + // operators for built-ins are already type checked against their prototype + case EOpAny: + case EOpAll: + case EOpVectorLogicalNot: + return true; + + default: + if (mOperand->getBasicType() != EbtFloat) + return false; + } + + setType(mOperand->getType()); + mType.setQualifier(EvqTemporary); + + return true; +} + +// +// Establishes the type of the resultant operation, as well as +// makes the operator the correct one for the operands. +// +// Returns false if operator can't work on operands. +// +bool TIntermBinary::promote(TInfoSink &infoSink) +{ + // This function only handles scalars, vectors, and matrices. + if (mLeft->isArray() || mRight->isArray()) + { + infoSink.info.message(EPrefixInternalError, getLine(), + "Invalid operation for arrays"); + return false; + } + + // GLSL ES 2.0 does not support implicit type casting. + // So the basic type should always match. + if (mLeft->getBasicType() != mRight->getBasicType()) + { + return false; + } + + // + // Base assumption: just make the type the same as the left + // operand. Then only deviations from this need be coded. + // + setType(mLeft->getType()); + + // The result gets promoted to the highest precision. + TPrecision higherPrecision = GetHigherPrecision( + mLeft->getPrecision(), mRight->getPrecision()); + getTypePointer()->setPrecision(higherPrecision); + + // Binary operations results in temporary variables unless both + // operands are const. + if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst) + { + getTypePointer()->setQualifier(EvqTemporary); + } + + const int nominalSize = + std::max(mLeft->getNominalSize(), mRight->getNominalSize()); + + // + // All scalars or structs. Code after this test assumes this case is removed! + // + if (nominalSize == 1) + { + switch (mOp) + { + // + // Promote to conditional + // + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + setType(TType(EbtBool, EbpUndefined)); + break; + + // + // And and Or operate on conditionals + // + case EOpLogicalAnd: + case EOpLogicalOr: + // Both operands must be of type bool. + if (mLeft->getBasicType() != EbtBool || mRight->getBasicType() != EbtBool) + { + return false; + } + setType(TType(EbtBool, EbpUndefined)); + break; + + default: + break; + } + return true; + } + + // If we reach here, at least one of the operands is vector or matrix. + // The other operand could be a scalar, vector, or matrix. + // Can these two operands be combined? + // + TBasicType basicType = mLeft->getBasicType(); + switch (mOp) + { + case EOpMul: + if (!mLeft->isMatrix() && mRight->isMatrix()) + { + if (mLeft->isVector()) + { + mOp = EOpVectorTimesMatrix; + setType(TType(basicType, higherPrecision, EvqTemporary, + mRight->getCols(), 1)); + } + else + { + mOp = EOpMatrixTimesScalar; + setType(TType(basicType, higherPrecision, EvqTemporary, + mRight->getCols(), mRight->getRows())); + } + } + else if (mLeft->isMatrix() && !mRight->isMatrix()) + { + if (mRight->isVector()) + { + mOp = EOpMatrixTimesVector; + setType(TType(basicType, higherPrecision, EvqTemporary, + mLeft->getRows(), 1)); + } + else + { + mOp = EOpMatrixTimesScalar; + } + } + else if (mLeft->isMatrix() && mRight->isMatrix()) + { + mOp = EOpMatrixTimesMatrix; + setType(TType(basicType, higherPrecision, EvqTemporary, + mRight->getCols(), mLeft->getRows())); + } + else if (!mLeft->isMatrix() && !mRight->isMatrix()) + { + if (mLeft->isVector() && mRight->isVector()) + { + // leave as component product + } + else if (mLeft->isVector() || mRight->isVector()) + { + mOp = EOpVectorTimesScalar; + setType(TType(basicType, higherPrecision, EvqTemporary, + nominalSize, 1)); + } + } + else + { + infoSink.info.message(EPrefixInternalError, getLine(), + "Missing elses"); + return false; + } + + if (!ValidateMultiplication(mOp, mLeft->getType(), mRight->getType())) + { + return false; + } + break; + + case EOpMulAssign: + if (!mLeft->isMatrix() && mRight->isMatrix()) + { + if (mLeft->isVector()) + { + mOp = EOpVectorTimesMatrixAssign; + } + else + { + return false; + } + } + else if (mLeft->isMatrix() && !mRight->isMatrix()) + { + if (mRight->isVector()) + { + return false; + } + else + { + mOp = EOpMatrixTimesScalarAssign; + } + } + else if (mLeft->isMatrix() && mRight->isMatrix()) + { + mOp = EOpMatrixTimesMatrixAssign; + setType(TType(basicType, higherPrecision, EvqTemporary, + mRight->getCols(), mLeft->getRows())); + } + else if (!mLeft->isMatrix() && !mRight->isMatrix()) + { + if (mLeft->isVector() && mRight->isVector()) + { + // leave as component product + } + else if (mLeft->isVector() || mRight->isVector()) + { + if (!mLeft->isVector()) + return false; + mOp = EOpVectorTimesScalarAssign; + setType(TType(basicType, higherPrecision, EvqTemporary, + mLeft->getNominalSize(), 1)); + } + } + else + { + infoSink.info.message(EPrefixInternalError, getLine(), + "Missing elses"); + return false; + } + + if (!ValidateMultiplication(mOp, mLeft->getType(), mRight->getType())) + { + return false; + } + break; + + case EOpAssign: + case EOpInitialize: + case EOpAdd: + case EOpSub: + case EOpDiv: + case EOpAddAssign: + case EOpSubAssign: + case EOpDivAssign: + if ((mLeft->isMatrix() && mRight->isVector()) || + (mLeft->isVector() && mRight->isMatrix())) + { + return false; + } + + // Are the sizes compatible? + if (mLeft->getNominalSize() != mRight->getNominalSize() || + mLeft->getSecondarySize() != mRight->getSecondarySize()) + { + // If the nominal size of operands do not match: + // One of them must be scalar. + if (!mLeft->isScalar() && !mRight->isScalar()) + return false; + + // Operator cannot be of type pure assignment. + if (mOp == EOpAssign || mOp == EOpInitialize) + return false; + } + + { + const int secondarySize = std::max( + mLeft->getSecondarySize(), mRight->getSecondarySize()); + setType(TType(basicType, higherPrecision, EvqTemporary, + nominalSize, secondarySize)); + } + break; + + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + if ((mLeft->getNominalSize() != mRight->getNominalSize()) || + (mLeft->getSecondarySize() != mRight->getSecondarySize())) + { + return false; + } + setType(TType(EbtBool, EbpUndefined)); + break; + + default: + return false; + } + return true; +} + +// +// The fold functions see if an operation on a constant can be done in place, +// without generating run-time code. +// +// Returns the node to keep using, which may or may not be the node passed in. +// +TIntermTyped *TIntermConstantUnion::fold( + TOperator op, TIntermTyped *constantNode, TInfoSink &infoSink) +{ + ConstantUnion *unionArray = getUnionArrayPointer(); + + if (!unionArray) + return NULL; + + size_t objectSize = getType().getObjectSize(); + + if (constantNode) + { + // binary operations + TIntermConstantUnion *node = constantNode->getAsConstantUnion(); + ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); + TType returnType = getType(); + + if (!rightUnionArray) + return NULL; + + // 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 (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 (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i) + { + unionArray[i] = *getUnionArrayPointer(); + } + returnType = node->getType(); + objectSize = constantNode->getType().getObjectSize(); + } + + ConstantUnion *tempConstArray = NULL; + TIntermConstantUnion *tempNode; + + bool boolNodeFlag = false; + switch(op) + { + case EOpAdd: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] + rightUnionArray[i]; + break; + case EOpSub: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] - rightUnionArray[i]; + break; + + case EOpMul: + case EOpVectorTimesScalar: + case EOpMatrixTimesScalar: + tempConstArray = new ConstantUnion[objectSize]; + 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, getLine(), + "Constant Folding cannot be done for matrix multiply"); + return NULL; + } + + const int leftCols = getCols(); + const int leftRows = getRows(); + const int rightCols = constantNode->getType().getCols(); + const int rightRows = constantNode->getType().getRows(); + const int resultCols = rightCols; + const int resultRows = leftRows; + + tempConstArray = new ConstantUnion[resultCols*resultRows]; + for (int row = 0; row < resultRows; row++) + { + for (int column = 0; column < resultCols; column++) + { + tempConstArray[resultRows * column + row].setFConst(0.0f); + for (int i = 0; i < leftCols; i++) + { + tempConstArray[resultRows * column + row].setFConst( + tempConstArray[resultRows * column + row].getFConst() + + unionArray[i * leftRows + row].getFConst() * + rightUnionArray[column * rightRows + i].getFConst()); + } + } + } + + // update return type for matrix product + returnType.setPrimarySize(resultCols); + returnType.setSecondarySize(resultRows); + } + break; + + case EOpDiv: + { + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + switch (getType().getBasicType()) + { + case EbtFloat: + if (rightUnionArray[i] == 0.0f) + { + 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()); + } + break; + + case EbtInt: + if (rightUnionArray[i] == 0) + { + 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; + + case EbtUInt: + if (rightUnionArray[i] == 0) + { + infoSink.info.message( + EPrefixWarning, getLine(), + "Divide by zero error during constant folding"); + tempConstArray[i].setUConst(UINT_MAX); + } + else + { + tempConstArray[i].setUConst( + unionArray[i].getUConst() / + rightUnionArray[i].getUConst()); + } + break; + + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Constant folding cannot be done for \"/\""); + return NULL; + } + } + } + break; + + case EOpMatrixTimesVector: + { + if (node->getBasicType() != EbtFloat) + { + infoSink.info.message( + EPrefixInternalError, getLine(), + "Constant Folding cannot be done for matrix times vector"); + return NULL; + } + + const int matrixCols = getCols(); + const int matrixRows = getRows(); + + tempConstArray = new ConstantUnion[matrixRows]; + + for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++) + { + tempConstArray[matrixRow].setFConst(0.0f); + for (int col = 0; col < matrixCols; col++) + { + tempConstArray[matrixRow].setFConst( + tempConstArray[matrixRow].getFConst() + + unionArray[col * matrixRows + matrixRow].getFConst() * + rightUnionArray[col].getFConst()); + } + } + + returnType = node->getType(); + returnType.setPrimarySize(matrixRows); + + tempNode = new TIntermConstantUnion(tempConstArray, returnType); + tempNode->setLine(getLine()); + + return tempNode; + } + + case EOpVectorTimesMatrix: + { + if (getType().getBasicType() != EbtFloat) + { + infoSink.info.message( + EPrefixInternalError, getLine(), + "Constant Folding cannot be done for vector times matrix"); + return NULL; + } + + const int matrixCols = constantNode->getType().getCols(); + const int matrixRows = constantNode->getType().getRows(); + + tempConstArray = new ConstantUnion[matrixCols]; + + for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++) + { + tempConstArray[matrixCol].setFConst(0.0f); + for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++) + { + tempConstArray[matrixCol].setFConst( + tempConstArray[matrixCol].getFConst() + + unionArray[matrixRow].getFConst() * + rightUnionArray[matrixCol * matrixRows + matrixRow].getFConst()); + } + } + + returnType.setPrimarySize(matrixCols); + } + break; + + case EOpLogicalAnd: + // this code is written for possible future use, + // will not get executed currently + { + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + tempConstArray[i] = unionArray[i] && rightUnionArray[i]; + } + } + break; + + case EOpLogicalOr: + // this code is written for possible future use, + // will not get executed currently + { + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + tempConstArray[i] = unionArray[i] || rightUnionArray[i]; + } + } + break; + + case EOpLogicalXor: + { + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + switch (getType().getBasicType()) + { + case EbtBool: + tempConstArray[i].setBConst( + unionArray[i] == rightUnionArray[i] ? false : true); + break; + default: + UNREACHABLE(); + break; + } + } + } + break; + + case EOpLessThan: + ASSERT(objectSize == 1); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(*unionArray < *rightUnionArray); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + + case EOpGreaterThan: + ASSERT(objectSize == 1); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(*unionArray > *rightUnionArray); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + + case EOpLessThanEqual: + { + ASSERT(objectSize == 1); + ConstantUnion constant; + constant.setBConst(*unionArray > *rightUnionArray); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(!constant.getBConst()); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + } + + case EOpGreaterThanEqual: + { + ASSERT(objectSize == 1); + ConstantUnion constant; + constant.setBConst(*unionArray < *rightUnionArray); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(!constant.getBConst()); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + } + + case EOpEqual: + if (getType().getBasicType() == EbtStruct) + { + if (!CompareStructure(node->getType(), + node->getUnionArrayPointer(), + unionArray)) + { + boolNodeFlag = true; + } + } + else + { + for (size_t i = 0; i < objectSize; i++) + { + if (unionArray[i] != rightUnionArray[i]) + { + boolNodeFlag = true; + break; // break out of for loop + } + } + } + + tempConstArray = new ConstantUnion[1]; + if (!boolNodeFlag) + { + tempConstArray->setBConst(true); + } + else + { + tempConstArray->setBConst(false); + } + + tempNode = new TIntermConstantUnion( + tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); + tempNode->setLine(getLine()); + + return tempNode; + + case EOpNotEqual: + if (getType().getBasicType() == EbtStruct) + { + if (CompareStructure(node->getType(), + node->getUnionArrayPointer(), + unionArray)) + { + boolNodeFlag = true; + } + } + else + { + for (size_t i = 0; i < objectSize; i++) + { + if (unionArray[i] == rightUnionArray[i]) + { + boolNodeFlag = true; + break; // break out of for loop + } + } + } + + tempConstArray = new ConstantUnion[1]; + if (!boolNodeFlag) + { + tempConstArray->setBConst(true); + } + else + { + tempConstArray->setBConst(false); + } + + tempNode = new TIntermConstantUnion( + tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); + tempNode->setLine(getLine()); + + return tempNode; + + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Invalid operator for constant folding"); + return NULL; + } + tempNode = new TIntermConstantUnion(tempConstArray, returnType); + tempNode->setLine(getLine()); + + return tempNode; + } + else + { + // + // Do unary operations + // + TIntermConstantUnion *newNode = 0; + ConstantUnion* tempConstArray = new ConstantUnion[objectSize]; + 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; + case EbtUInt: + tempConstArray[i].setUConst(static_cast<unsigned int>( + -static_cast<int>(unionArray[i].getUConst()))); + break; + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return NULL; + } + break; + + case EOpLogicalNot: + // this code is written for possible future use, + // will not get executed currently + switch (getType().getBasicType()) + { + case EbtBool: + tempConstArray[i].setBConst(!unionArray[i].getBConst()); + break; + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return NULL; + } + break; + + default: + return NULL; + } + } + newNode = new TIntermConstantUnion(tempConstArray, getType()); + newNode->setLine(getLine()); + return newNode; + } +} + +// static +TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunction) +{ + if (hashFunction == NULL || name.empty()) + return name; + khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length()); + TStringStream stream; + stream << HASHED_NAME_PREFIX << std::hex << number; + TString hashedName = stream.str(); + return hashedName; +} diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.h b/src/3rdparty/angle/src/compiler/translator/IntermNode.h new file mode 100644 index 0000000000..ec440da010 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/IntermNode.h @@ -0,0 +1,772 @@ +// +// Copyright (c) 2002-2014 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. +// + +// +// Definition of the in-memory high-level intermediate representation +// of shaders. This is a tree that parser creates. +// +// Nodes in the tree are defined as a hierarchy of classes derived from +// TIntermNode. Each is a node in a tree. There is no preset branching factor; +// each node can have it's own type of list of children. +// + +#ifndef COMPILER_TRANSLATOR_INTERMEDIATE_H_ +#define COMPILER_TRANSLATOR_INTERMEDIATE_H_ + +#include "GLSLANG/ShaderLang.h" + +#include <algorithm> +#include <queue> + +#include "compiler/translator/Common.h" +#include "compiler/translator/Types.h" +#include "compiler/translator/ConstantUnion.h" + +// +// Operators used by the high-level (parse tree) representation. +// +enum TOperator +{ + EOpNull, // if in a node, should only mean a node is still being built + EOpSequence, // denotes a list of statements, or parameters, etc. + EOpFunctionCall, + EOpFunction, // For function definition + EOpParameters, // an aggregate listing the parameters to a function + + EOpDeclaration, + EOpInvariantDeclaration, // Specialized declarations for attributing invariance + EOpPrototype, + + // + // Unary operators + // + + EOpNegative, + EOpLogicalNot, + EOpVectorLogicalNot, + + EOpPostIncrement, + EOpPostDecrement, + EOpPreIncrement, + EOpPreDecrement, + + // + // binary operations + // + + EOpAdd, + EOpSub, + EOpMul, + EOpDiv, + EOpEqual, + EOpNotEqual, + EOpVectorEqual, + EOpVectorNotEqual, + EOpLessThan, + EOpGreaterThan, + EOpLessThanEqual, + EOpGreaterThanEqual, + EOpComma, + + EOpVectorTimesScalar, + EOpVectorTimesMatrix, + EOpMatrixTimesVector, + EOpMatrixTimesScalar, + + EOpLogicalOr, + EOpLogicalXor, + EOpLogicalAnd, + + EOpIndexDirect, + EOpIndexIndirect, + EOpIndexDirectStruct, + EOpIndexDirectInterfaceBlock, + + EOpVectorSwizzle, + + // + // Built-in functions potentially mapped to operators + // + + EOpRadians, + EOpDegrees, + EOpSin, + EOpCos, + EOpTan, + EOpAsin, + EOpAcos, + EOpAtan, + + EOpPow, + EOpExp, + EOpLog, + EOpExp2, + EOpLog2, + EOpSqrt, + EOpInverseSqrt, + + EOpAbs, + EOpSign, + EOpFloor, + EOpCeil, + EOpFract, + EOpMod, + EOpMin, + EOpMax, + EOpClamp, + EOpMix, + EOpStep, + EOpSmoothStep, + + EOpLength, + EOpDistance, + EOpDot, + EOpCross, + EOpNormalize, + EOpFaceForward, + EOpReflect, + EOpRefract, + + EOpDFdx, // Fragment only, OES_standard_derivatives extension + EOpDFdy, // Fragment only, OES_standard_derivatives extension + EOpFwidth, // Fragment only, OES_standard_derivatives extension + + EOpMatrixTimesMatrix, + + EOpAny, + EOpAll, + + // + // Branch + // + + EOpKill, // Fragment only + EOpReturn, + EOpBreak, + EOpContinue, + + // + // Constructors + // + + EOpConstructInt, + EOpConstructUInt, + EOpConstructBool, + EOpConstructFloat, + EOpConstructVec2, + EOpConstructVec3, + EOpConstructVec4, + EOpConstructBVec2, + EOpConstructBVec3, + EOpConstructBVec4, + EOpConstructIVec2, + EOpConstructIVec3, + EOpConstructIVec4, + EOpConstructUVec2, + EOpConstructUVec3, + EOpConstructUVec4, + EOpConstructMat2, + EOpConstructMat3, + EOpConstructMat4, + EOpConstructStruct, + + // + // moves + // + + EOpAssign, + EOpInitialize, + EOpAddAssign, + EOpSubAssign, + EOpMulAssign, + EOpVectorTimesMatrixAssign, + EOpVectorTimesScalarAssign, + EOpMatrixTimesScalarAssign, + EOpMatrixTimesMatrixAssign, + EOpDivAssign +}; + +class TIntermTraverser; +class TIntermAggregate; +class TIntermBinary; +class TIntermUnary; +class TIntermConstantUnion; +class TIntermSelection; +class TIntermTyped; +class TIntermSymbol; +class TIntermLoop; +class TInfoSink; +class TIntermRaw; + +// +// Base class for the tree nodes +// +class TIntermNode +{ + public: + POOL_ALLOCATOR_NEW_DELETE(); + TIntermNode() + { + // TODO: Move this to TSourceLoc constructor + // after getting rid of TPublicType. + mLine.first_file = mLine.last_file = 0; + mLine.first_line = mLine.last_line = 0; + } + virtual ~TIntermNode() { } + + const TSourceLoc &getLine() const { return mLine; } + void setLine(const TSourceLoc &l) { mLine = l; } + + virtual void traverse(TIntermTraverser *) = 0; + virtual TIntermTyped *getAsTyped() { return 0; } + virtual TIntermConstantUnion *getAsConstantUnion() { return 0; } + virtual TIntermAggregate *getAsAggregate() { return 0; } + virtual TIntermBinary *getAsBinaryNode() { return 0; } + virtual TIntermUnary *getAsUnaryNode() { return 0; } + virtual TIntermSelection *getAsSelectionNode() { return 0; } + virtual TIntermSymbol *getAsSymbolNode() { return 0; } + virtual TIntermLoop *getAsLoopNode() { return 0; } + virtual TIntermRaw *getAsRawNode() { return 0; } + + // Replace a child node. Return true if |original| is a child + // node and it is replaced; otherwise, return false. + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement) = 0; + + // For traversing a tree in no particular order, but using + // heap memory. + virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const = 0; + + protected: + TSourceLoc mLine; +}; + +// +// This is just to help yacc. +// +struct TIntermNodePair +{ + TIntermNode *node1; + TIntermNode *node2; +}; + +// +// Intermediate class for nodes that have a type. +// +class TIntermTyped : public TIntermNode +{ + public: + TIntermTyped(const TType &t) : mType(t) { } + virtual TIntermTyped *getAsTyped() { return this; } + + virtual bool hasSideEffects() const = 0; + + void setType(const TType &t) { mType = t; } + const TType &getType() const { return mType; } + TType *getTypePointer() { return &mType; } + + TBasicType getBasicType() const { return mType.getBasicType(); } + TQualifier getQualifier() const { return mType.getQualifier(); } + TPrecision getPrecision() const { return mType.getPrecision(); } + int getCols() const { return mType.getCols(); } + int getRows() const { return mType.getRows(); } + int getNominalSize() const { return mType.getNominalSize(); } + int getSecondarySize() const { return mType.getSecondarySize(); } + + bool isInterfaceBlock() const { return mType.isInterfaceBlock(); } + bool isMatrix() const { return mType.isMatrix(); } + bool isArray() const { return mType.isArray(); } + bool isVector() const { return mType.isVector(); } + bool isScalar() const { return mType.isScalar(); } + bool isScalarInt() const { return mType.isScalarInt(); } + const char *getBasicString() const { return mType.getBasicString(); } + const char *getQualifierString() const { return mType.getQualifierString(); } + TString getCompleteString() const { return mType.getCompleteString(); } + + int getArraySize() const { return mType.getArraySize(); } + + protected: + TType mType; +}; + +// +// Handle for, do-while, and while loops. +// +enum TLoopType +{ + ELoopFor, + ELoopWhile, + ELoopDoWhile +}; + +class TIntermLoop : public TIntermNode +{ + public: + TIntermLoop(TLoopType type, + TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr, + TIntermNode *body) + : mType(type), + mInit(init), + mCond(cond), + mExpr(expr), + mBody(body), + mUnrollFlag(false) { } + + virtual TIntermLoop *getAsLoopNode() { return this; } + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + TLoopType getType() const { return mType; } + TIntermNode *getInit() { return mInit; } + TIntermTyped *getCondition() { return mCond; } + TIntermTyped *getExpression() { return mExpr; } + TIntermNode *getBody() { return mBody; } + + void setUnrollFlag(bool flag) { mUnrollFlag = flag; } + bool getUnrollFlag() const { return mUnrollFlag; } + + virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const; + + protected: + TLoopType mType; + TIntermNode *mInit; // for-loop initialization + TIntermTyped *mCond; // loop exit condition + TIntermTyped *mExpr; // for-loop expression + TIntermNode *mBody; // loop body + + bool mUnrollFlag; // Whether the loop should be unrolled or not. +}; + +// +// Handle break, continue, return, and kill. +// +class TIntermBranch : public TIntermNode +{ + public: + TIntermBranch(TOperator op, TIntermTyped *e) + : mFlowOp(op), + mExpression(e) { } + + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + TOperator getFlowOp() { return mFlowOp; } + TIntermTyped* getExpression() { return mExpression; } + + virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const; + +protected: + TOperator mFlowOp; + TIntermTyped *mExpression; // non-zero except for "return exp;" statements +}; + +// +// Nodes that correspond to symbols or constants in the source code. +// +class TIntermSymbol : public TIntermTyped +{ + public: + // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. + // If sym comes from per process globalpoolallocator, then it causes increased memory usage + // per compile it is essential to use "symbol = sym" to assign to symbol + TIntermSymbol(int id, const TString &symbol, const TType &type) + : TIntermTyped(type), + mId(id) + { + mSymbol = symbol; + } + + virtual bool hasSideEffects() const { return false; } + + int getId() const { return mId; } + const TString &getSymbol() const { return mSymbol; } + + void setId(int newId) { mId = newId; } + + virtual void traverse(TIntermTraverser *); + virtual TIntermSymbol *getAsSymbolNode() { return this; } + virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } + + virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {} + + protected: + int mId; + TString mSymbol; +}; + +// A Raw node stores raw code, that the translator will insert verbatim +// into the output stream. Useful for transformation operations that make +// complex code that might not fit naturally into the GLSL model. +class TIntermRaw : public TIntermTyped +{ + public: + TIntermRaw(const TType &type, const TString &rawText) + : TIntermTyped(type), + mRawText(rawText) { } + + virtual bool hasSideEffects() const { return false; } + + TString getRawText() const { return mRawText; } + + virtual void traverse(TIntermTraverser *); + + virtual TIntermRaw *getAsRawNode() { return this; } + virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } + virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {} + + protected: + TString mRawText; +}; + +class TIntermConstantUnion : public TIntermTyped +{ + public: + TIntermConstantUnion(ConstantUnion *unionPointer, const TType &type) + : TIntermTyped(type), + mUnionArrayPointer(unionPointer) { } + + virtual bool hasSideEffects() const { return false; } + + ConstantUnion *getUnionArrayPointer() const { return mUnionArrayPointer; } + + int getIConst(size_t index) const + { + return mUnionArrayPointer ? mUnionArrayPointer[index].getIConst() : 0; + } + unsigned int getUConst(size_t index) const + { + return mUnionArrayPointer ? mUnionArrayPointer[index].getUConst() : 0; + } + float getFConst(size_t index) const + { + return mUnionArrayPointer ? mUnionArrayPointer[index].getFConst() : 0.0f; + } + bool getBConst(size_t index) const + { + return mUnionArrayPointer ? mUnionArrayPointer[index].getBConst() : false; + } + + virtual TIntermConstantUnion *getAsConstantUnion() { return this; } + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } + + TIntermTyped *fold(TOperator, TIntermTyped *, TInfoSink &); + + virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {} + + protected: + ConstantUnion *mUnionArrayPointer; +}; + +// +// Intermediate class for node types that hold operators. +// +class TIntermOperator : public TIntermTyped +{ + public: + TOperator getOp() const { return mOp; } + void setOp(TOperator op) { mOp = op; } + + bool isAssignment() const; + bool isConstructor() const; + + virtual bool hasSideEffects() const { return isAssignment(); } + + protected: + TIntermOperator(TOperator op) + : TIntermTyped(TType(EbtFloat, EbpUndefined)), + mOp(op) {} + TIntermOperator(TOperator op, const TType &type) + : TIntermTyped(type), + mOp(op) {} + + TOperator mOp; +}; + +// +// Nodes for all the basic binary math operators. +// +class TIntermBinary : public TIntermOperator +{ + public: + TIntermBinary(TOperator op) + : TIntermOperator(op), + mAddIndexClamp(false) {} + + virtual TIntermBinary *getAsBinaryNode() { return this; } + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + virtual bool hasSideEffects() const + { + return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects(); + } + + void setLeft(TIntermTyped *node) { mLeft = node; } + void setRight(TIntermTyped *node) { mRight = node; } + TIntermTyped *getLeft() const { return mLeft; } + TIntermTyped *getRight() const { return mRight; } + bool promote(TInfoSink &); + + void setAddIndexClamp() { mAddIndexClamp = true; } + bool getAddIndexClamp() { return mAddIndexClamp; } + + virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const; + + protected: + TIntermTyped* mLeft; + TIntermTyped* mRight; + + // If set to true, wrap any EOpIndexIndirect with a clamp to bounds. + bool mAddIndexClamp; +}; + +// +// Nodes for unary math operators. +// +class TIntermUnary : public TIntermOperator +{ + public: + TIntermUnary(TOperator op, const TType &type) + : TIntermOperator(op, type), + mOperand(NULL), + mUseEmulatedFunction(false) {} + TIntermUnary(TOperator op) + : TIntermOperator(op), + mOperand(NULL), + mUseEmulatedFunction(false) {} + + virtual void traverse(TIntermTraverser *); + virtual TIntermUnary *getAsUnaryNode() { return this; } + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + virtual bool hasSideEffects() const + { + return isAssignment() || mOperand->hasSideEffects(); + } + + void setOperand(TIntermTyped *operand) { mOperand = operand; } + TIntermTyped *getOperand() { return mOperand; } + bool promote(TInfoSink &); + + void setUseEmulatedFunction() { mUseEmulatedFunction = true; } + bool getUseEmulatedFunction() { return mUseEmulatedFunction; } + + virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const; + + protected: + TIntermTyped *mOperand; + + // If set to true, replace the built-in function call with an emulated one + // to work around driver bugs. + bool mUseEmulatedFunction; +}; + +typedef TVector<TIntermNode *> TIntermSequence; +typedef TVector<int> TQualifierList; + +// +// Nodes that operate on an arbitrary sized set of children. +// +class TIntermAggregate : public TIntermOperator +{ + public: + TIntermAggregate() + : TIntermOperator(EOpNull), + mUserDefined(false), + mUseEmulatedFunction(false) { } + TIntermAggregate(TOperator op) + : TIntermOperator(op), + mUseEmulatedFunction(false) { } + ~TIntermAggregate() { } + + virtual TIntermAggregate *getAsAggregate() { return this; } + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + // Conservatively assume function calls and other aggregate operators have side-effects + virtual bool hasSideEffects() const { return true; } + + TIntermSequence *getSequence() { return &mSequence; } + + void setName(const TString &name) { mName = name; } + const TString &getName() const { return mName; } + + void setUserDefined() { mUserDefined = true; } + bool isUserDefined() const { return mUserDefined; } + + void setOptimize(bool optimize) { mOptimize = optimize; } + bool getOptimize() const { return mOptimize; } + void setDebug(bool debug) { mDebug = debug; } + bool getDebug() const { return mDebug; } + + void setUseEmulatedFunction() { mUseEmulatedFunction = true; } + bool getUseEmulatedFunction() { return mUseEmulatedFunction; } + + virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const; + + protected: + TIntermAggregate(const TIntermAggregate &); // disallow copy constructor + TIntermAggregate &operator=(const TIntermAggregate &); // disallow assignment operator + TIntermSequence mSequence; + TString mName; + bool mUserDefined; // used for user defined function names + + bool mOptimize; + bool mDebug; + + // If set to true, replace the built-in function call with an emulated one + // to work around driver bugs. + bool mUseEmulatedFunction; +}; + +// +// For if tests. Simplified since there is no switch statement. +// +class TIntermSelection : public TIntermTyped +{ + public: + TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB) + : TIntermTyped(TType(EbtVoid, EbpUndefined)), + mCondition(cond), + mTrueBlock(trueB), + mFalseBlock(falseB) {} + TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB, + const TType &type) + : TIntermTyped(type), + mCondition(cond), + mTrueBlock(trueB), + mFalseBlock(falseB) {} + + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + // Conservatively assume selections have side-effects + virtual bool hasSideEffects() const { return true; } + + bool usesTernaryOperator() const { return getBasicType() != EbtVoid; } + TIntermNode *getCondition() const { return mCondition; } + TIntermNode *getTrueBlock() const { return mTrueBlock; } + TIntermNode *getFalseBlock() const { return mFalseBlock; } + TIntermSelection *getAsSelectionNode() { return this; } + + virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const; + +protected: + TIntermTyped *mCondition; + TIntermNode *mTrueBlock; + TIntermNode *mFalseBlock; +}; + +enum Visit +{ + PreVisit, + InVisit, + PostVisit +}; + +// +// For traversing the tree. User should derive from this, +// put their traversal specific data in it, and then pass +// it to a Traverse method. +// +// When using this, just fill in the methods for nodes you want visited. +// Return false from a pre-visit to skip visiting that node's subtree. +// +class TIntermTraverser +{ + public: + POOL_ALLOCATOR_NEW_DELETE(); + // TODO(zmo): remove default values. + TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, + bool rightToLeft = false) + : preVisit(preVisit), + inVisit(inVisit), + postVisit(postVisit), + rightToLeft(rightToLeft), + mDepth(0), + mMaxDepth(0) {} + virtual ~TIntermTraverser() {} + + virtual void visitSymbol(TIntermSymbol *) {} + virtual void visitRaw(TIntermRaw *) {} + virtual void visitConstantUnion(TIntermConstantUnion *) {} + virtual bool visitBinary(Visit, TIntermBinary *) { return true; } + virtual bool visitUnary(Visit, TIntermUnary *) { return true; } + virtual bool visitSelection(Visit, TIntermSelection *) { return true; } + virtual bool visitAggregate(Visit, TIntermAggregate *) { return true; } + virtual bool visitLoop(Visit, TIntermLoop *) { return true; } + virtual bool visitBranch(Visit, TIntermBranch *) { return true; } + + int getMaxDepth() const { return mMaxDepth; } + + void incrementDepth(TIntermNode *current) + { + mDepth++; + mMaxDepth = std::max(mMaxDepth, mDepth); + mPath.push_back(current); + } + + void decrementDepth() + { + mDepth--; + mPath.pop_back(); + } + + TIntermNode *getParentNode() + { + return mPath.size() == 0 ? NULL : mPath.back(); + } + + // Return the original name if hash function pointer is NULL; + // otherwise return the hashed name. + static TString hash(const TString& name, ShHashFunction64 hashFunction); + + const bool preVisit; + const bool inVisit; + const bool postVisit; + const bool rightToLeft; + + protected: + int mDepth; + int mMaxDepth; + + // All the nodes from root to the current node's parent during traversing. + TVector<TIntermNode *> mPath; +}; + +// +// For traversing the tree, and computing max depth. +// Takes a maximum depth limit to prevent stack overflow. +// +class TMaxDepthTraverser : public TIntermTraverser +{ + public: + POOL_ALLOCATOR_NEW_DELETE(); + TMaxDepthTraverser(int depthLimit) + : TIntermTraverser(true, true, false, false), + mDepthLimit(depthLimit) { } + + virtual bool visitBinary(Visit, TIntermBinary *) { return depthCheck(); } + virtual bool visitUnary(Visit, TIntermUnary *) { return depthCheck(); } + virtual bool visitSelection(Visit, TIntermSelection *) { return depthCheck(); } + virtual bool visitAggregate(Visit, TIntermAggregate *) { return depthCheck(); } + virtual bool visitLoop(Visit, TIntermLoop *) { return depthCheck(); } + virtual bool visitBranch(Visit, TIntermBranch *) { return depthCheck(); } + +protected: + bool depthCheck() const { return mMaxDepth < mDepthLimit; } + + int mDepthLimit; +}; + +#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp index 48d2013cc5..72b2033fb3 100644 --- a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp +++ b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // // Traverse the intermediate representation tree, and diff --git a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp index fa0c9f7748..ef4f83307c 100644 --- a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp @@ -12,122 +12,10 @@ #include <limits.h> #include <algorithm> -#include "compiler/translator/HashNames.h" -#include "compiler/translator/localintermediate.h" -#include "compiler/translator/QualifierAlive.h" +#include "compiler/translator/Intermediate.h" #include "compiler/translator/RemoveTree.h" #include "compiler/translator/SymbolTable.h" -namespace -{ - -TPrecision GetHigherPrecision(TPrecision left, TPrecision right) -{ - return left > right ? left : right; -} - -bool ValidateMultiplication(TOperator op, const TType &left, const TType &right) -{ - switch (op) - { - case EOpMul: - case EOpMulAssign: - return left.getNominalSize() == right.getNominalSize() && - left.getSecondarySize() == right.getSecondarySize(); - case EOpVectorTimesScalar: - case EOpVectorTimesScalarAssign: - return true; - case EOpVectorTimesMatrix: - return left.getNominalSize() == right.getRows(); - case EOpVectorTimesMatrixAssign: - return left.getNominalSize() == right.getRows() && - left.getNominalSize() == right.getCols(); - case EOpMatrixTimesVector: - return left.getCols() == right.getNominalSize(); - case EOpMatrixTimesScalar: - case EOpMatrixTimesScalarAssign: - return true; - case EOpMatrixTimesMatrix: - return left.getCols() == right.getRows(); - case EOpMatrixTimesMatrixAssign: - return left.getCols() == right.getCols() && - left.getRows() == right.getRows(); - - default: - UNREACHABLE(); - return false; - } -} - -bool CompareStructure(const TType& leftNodeType, - ConstantUnion *rightUnionArray, - ConstantUnion *leftUnionArray); - -bool CompareStruct(const TType &leftNodeType, - ConstantUnion *rightUnionArray, - ConstantUnion *leftUnionArray) -{ - const TFieldList &fields = leftNodeType.getStruct()->fields(); - - size_t structSize = fields.size(); - size_t index = 0; - - for (size_t j = 0; j < structSize; j++) - { - 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; -} - -bool CompareStructure(const TType &leftNodeType, - ConstantUnion *rightUnionArray, - ConstantUnion *leftUnionArray) -{ - if (leftNodeType.isArray()) - { - TType typeWithoutArrayness = leftNodeType; - typeWithoutArrayness.clearArrayness(); - - size_t arraySize = leftNodeType.getArraySize(); - - for (size_t i = 0; i < arraySize; ++i) - { - size_t offset = typeWithoutArrayness.getObjectSize() * i; - if (!CompareStruct(typeWithoutArrayness, - &rightUnionArray[offset], - &leftUnionArray[offset])) - { - return false; - } - } - } - else - { - return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray); - } - return true; -} - -} // namespace anonymous - //////////////////////////////////////////////////////////////////////////// // // First set of functions are to help build the intermediate representation. @@ -630,982 +518,3 @@ void TIntermediate::remove(TIntermNode *root) if (root) RemoveAllTreeNodes(root); } - -//////////////////////////////////////////////////////////////// -// -// Member functions of the nodes used for building the tree. -// -//////////////////////////////////////////////////////////////// - -#define REPLACE_IF_IS(node, type, original, replacement) \ - if (node == original) { \ - node = static_cast<type *>(replacement); \ - return true; \ - } - -bool TIntermLoop::replaceChildNode( - TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mInit, TIntermNode, original, replacement); - REPLACE_IF_IS(mCond, TIntermTyped, original, replacement); - REPLACE_IF_IS(mExpr, TIntermTyped, original, replacement); - REPLACE_IF_IS(mBody, TIntermNode, original, replacement); - return false; -} - -void TIntermLoop::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const -{ - if (mInit) - { - nodeQueue->push(mInit); - } - if (mCond) - { - nodeQueue->push(mCond); - } - if (mExpr) - { - nodeQueue->push(mExpr); - } - if (mBody) - { - nodeQueue->push(mBody); - } -} - -bool TIntermBranch::replaceChildNode( - TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement); - return false; -} - -void TIntermBranch::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const -{ - if (mExpression) - { - nodeQueue->push(mExpression); - } -} - -bool TIntermBinary::replaceChildNode( - TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement); - REPLACE_IF_IS(mRight, TIntermTyped, original, replacement); - return false; -} - -void TIntermBinary::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const -{ - if (mLeft) - { - nodeQueue->push(mLeft); - } - if (mRight) - { - nodeQueue->push(mRight); - } -} - -bool TIntermUnary::replaceChildNode( - TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement); - return false; -} - -void TIntermUnary::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const -{ - if (mOperand) - { - nodeQueue->push(mOperand); - } -} - -bool TIntermAggregate::replaceChildNode( - TIntermNode *original, TIntermNode *replacement) -{ - for (size_t ii = 0; ii < mSequence.size(); ++ii) - { - REPLACE_IF_IS(mSequence[ii], TIntermNode, original, replacement); - } - return false; -} - -void TIntermAggregate::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const -{ - for (size_t childIndex = 0; childIndex < mSequence.size(); childIndex++) - { - nodeQueue->push(mSequence[childIndex]); - } -} - -bool TIntermSelection::replaceChildNode( - TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); - REPLACE_IF_IS(mTrueBlock, TIntermNode, original, replacement); - REPLACE_IF_IS(mFalseBlock, TIntermNode, original, replacement); - return false; -} - -void TIntermSelection::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const -{ - if (mCondition) - { - nodeQueue->push(mCondition); - } - if (mTrueBlock) - { - nodeQueue->push(mTrueBlock); - } - if (mFalseBlock) - { - nodeQueue->push(mFalseBlock); - } -} - -// -// Say whether or not an operation node changes the value of a variable. -// -bool TIntermOperator::isAssignment() const -{ - switch (mOp) - { - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - case EOpAssign: - case EOpAddAssign: - case EOpSubAssign: - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - case EOpDivAssign: - return true; - default: - return false; - } -} - -// -// returns true if the operator is for one of the constructors -// -bool TIntermOperator::isConstructor() const -{ - switch (mOp) - { - case EOpConstructVec2: - case EOpConstructVec3: - case EOpConstructVec4: - case EOpConstructMat2: - case EOpConstructMat3: - case EOpConstructMat4: - case EOpConstructFloat: - case EOpConstructIVec2: - case EOpConstructIVec3: - case EOpConstructIVec4: - case EOpConstructInt: - case EOpConstructUVec2: - case EOpConstructUVec3: - case EOpConstructUVec4: - case EOpConstructUInt: - case EOpConstructBVec2: - case EOpConstructBVec3: - case EOpConstructBVec4: - case EOpConstructBool: - case EOpConstructStruct: - return true; - default: - return false; - } -} - -// -// Make sure the type of a unary operator is appropriate for its -// combination of operation and operand type. -// -// Returns false in nothing makes sense. -// -bool TIntermUnary::promote(TInfoSink &) -{ - switch (mOp) - { - case EOpLogicalNot: - if (mOperand->getBasicType() != EbtBool) - return false; - break; - case EOpNegative: - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - if (mOperand->getBasicType() == EbtBool) - return false; - break; - - // operators for built-ins are already type checked against their prototype - case EOpAny: - case EOpAll: - case EOpVectorLogicalNot: - return true; - - default: - if (mOperand->getBasicType() != EbtFloat) - return false; - } - - setType(mOperand->getType()); - mType.setQualifier(EvqTemporary); - - return true; -} - -// -// Establishes the type of the resultant operation, as well as -// makes the operator the correct one for the operands. -// -// Returns false if operator can't work on operands. -// -bool TIntermBinary::promote(TInfoSink &infoSink) -{ - // This function only handles scalars, vectors, and matrices. - if (mLeft->isArray() || mRight->isArray()) - { - infoSink.info.message(EPrefixInternalError, getLine(), - "Invalid operation for arrays"); - return false; - } - - // GLSL ES 2.0 does not support implicit type casting. - // So the basic type should always match. - if (mLeft->getBasicType() != mRight->getBasicType()) - { - return false; - } - - // - // Base assumption: just make the type the same as the left - // operand. Then only deviations from this need be coded. - // - setType(mLeft->getType()); - - // The result gets promoted to the highest precision. - TPrecision higherPrecision = GetHigherPrecision( - mLeft->getPrecision(), mRight->getPrecision()); - getTypePointer()->setPrecision(higherPrecision); - - // Binary operations results in temporary variables unless both - // operands are const. - if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst) - { - getTypePointer()->setQualifier(EvqTemporary); - } - - const int nominalSize = - std::max(mLeft->getNominalSize(), mRight->getNominalSize()); - - // - // All scalars or structs. Code after this test assumes this case is removed! - // - if (nominalSize == 1) - { - switch (mOp) - { - // - // Promote to conditional - // - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - setType(TType(EbtBool, EbpUndefined)); - break; - - // - // And and Or operate on conditionals - // - case EOpLogicalAnd: - case EOpLogicalOr: - // Both operands must be of type bool. - if (mLeft->getBasicType() != EbtBool || mRight->getBasicType() != EbtBool) - { - return false; - } - setType(TType(EbtBool, EbpUndefined)); - break; - - default: - break; - } - return true; - } - - // If we reach here, at least one of the operands is vector or matrix. - // The other operand could be a scalar, vector, or matrix. - // Can these two operands be combined? - // - TBasicType basicType = mLeft->getBasicType(); - switch (mOp) - { - case EOpMul: - if (!mLeft->isMatrix() && mRight->isMatrix()) - { - if (mLeft->isVector()) - { - mOp = EOpVectorTimesMatrix; - setType(TType(basicType, higherPrecision, EvqTemporary, - mRight->getCols(), 1)); - } - else - { - mOp = EOpMatrixTimesScalar; - setType(TType(basicType, higherPrecision, EvqTemporary, - mRight->getCols(), mRight->getRows())); - } - } - else if (mLeft->isMatrix() && !mRight->isMatrix()) - { - if (mRight->isVector()) - { - mOp = EOpMatrixTimesVector; - setType(TType(basicType, higherPrecision, EvqTemporary, - mLeft->getRows(), 1)); - } - else - { - mOp = EOpMatrixTimesScalar; - } - } - else if (mLeft->isMatrix() && mRight->isMatrix()) - { - mOp = EOpMatrixTimesMatrix; - setType(TType(basicType, higherPrecision, EvqTemporary, - mRight->getCols(), mLeft->getRows())); - } - else if (!mLeft->isMatrix() && !mRight->isMatrix()) - { - if (mLeft->isVector() && mRight->isVector()) - { - // leave as component product - } - else if (mLeft->isVector() || mRight->isVector()) - { - mOp = EOpVectorTimesScalar; - setType(TType(basicType, higherPrecision, EvqTemporary, - nominalSize, 1)); - } - } - else - { - infoSink.info.message(EPrefixInternalError, getLine(), - "Missing elses"); - return false; - } - - if (!ValidateMultiplication(mOp, mLeft->getType(), mRight->getType())) - { - return false; - } - break; - - case EOpMulAssign: - if (!mLeft->isMatrix() && mRight->isMatrix()) - { - if (mLeft->isVector()) - { - mOp = EOpVectorTimesMatrixAssign; - } - else - { - return false; - } - } - else if (mLeft->isMatrix() && !mRight->isMatrix()) - { - if (mRight->isVector()) - { - return false; - } - else - { - mOp = EOpMatrixTimesScalarAssign; - } - } - else if (mLeft->isMatrix() && mRight->isMatrix()) - { - mOp = EOpMatrixTimesMatrixAssign; - setType(TType(basicType, higherPrecision, EvqTemporary, - mRight->getCols(), mLeft->getRows())); - } - else if (!mLeft->isMatrix() && !mRight->isMatrix()) - { - if (mLeft->isVector() && mRight->isVector()) - { - // leave as component product - } - else if (mLeft->isVector() || mRight->isVector()) - { - if (!mLeft->isVector()) - return false; - mOp = EOpVectorTimesScalarAssign; - setType(TType(basicType, higherPrecision, EvqTemporary, - mLeft->getNominalSize(), 1)); - } - } - else - { - infoSink.info.message(EPrefixInternalError, getLine(), - "Missing elses"); - return false; - } - - if (!ValidateMultiplication(mOp, mLeft->getType(), mRight->getType())) - { - return false; - } - break; - - case EOpAssign: - case EOpInitialize: - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpAddAssign: - case EOpSubAssign: - case EOpDivAssign: - if ((mLeft->isMatrix() && mRight->isVector()) || - (mLeft->isVector() && mRight->isMatrix())) - { - return false; - } - - // Are the sizes compatible? - if (mLeft->getNominalSize() != mRight->getNominalSize() || - mLeft->getSecondarySize() != mRight->getSecondarySize()) - { - // If the nominal size of operands do not match: - // One of them must be scalar. - if (!mLeft->isScalar() && !mRight->isScalar()) - return false; - - // Operator cannot be of type pure assignment. - if (mOp == EOpAssign || mOp == EOpInitialize) - return false; - } - - { - const int secondarySize = std::max( - mLeft->getSecondarySize(), mRight->getSecondarySize()); - setType(TType(basicType, higherPrecision, EvqTemporary, - nominalSize, secondarySize)); - } - break; - - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - if ((mLeft->getNominalSize() != mRight->getNominalSize()) || - (mLeft->getSecondarySize() != mRight->getSecondarySize())) - { - return false; - } - setType(TType(EbtBool, EbpUndefined)); - break; - - default: - return false; - } - return true; -} - -// -// The fold functions see if an operation on a constant can be done in place, -// without generating run-time code. -// -// Returns the node to keep using, which may or may not be the node passed in. -// -TIntermTyped *TIntermConstantUnion::fold( - TOperator op, TIntermTyped *constantNode, TInfoSink &infoSink) -{ - ConstantUnion *unionArray = getUnionArrayPointer(); - - if (!unionArray) - return NULL; - - size_t objectSize = getType().getObjectSize(); - - if (constantNode) - { - // binary operations - TIntermConstantUnion *node = constantNode->getAsConstantUnion(); - ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); - TType returnType = getType(); - - if (!rightUnionArray) - return NULL; - - // 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 (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 (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i) - { - unionArray[i] = *getUnionArrayPointer(); - } - returnType = node->getType(); - objectSize = constantNode->getType().getObjectSize(); - } - - ConstantUnion *tempConstArray = NULL; - TIntermConstantUnion *tempNode; - - bool boolNodeFlag = false; - switch(op) - { - case EOpAdd: - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] + rightUnionArray[i]; - break; - case EOpSub: - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] - rightUnionArray[i]; - break; - - case EOpMul: - case EOpVectorTimesScalar: - case EOpMatrixTimesScalar: - tempConstArray = new ConstantUnion[objectSize]; - 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, getLine(), - "Constant Folding cannot be done for matrix multiply"); - return NULL; - } - - const int leftCols = getCols(); - const int leftRows = getRows(); - const int rightCols = constantNode->getType().getCols(); - const int rightRows = constantNode->getType().getRows(); - const int resultCols = rightCols; - const int resultRows = leftRows; - - tempConstArray = new ConstantUnion[resultCols*resultRows]; - for (int row = 0; row < resultRows; row++) - { - for (int column = 0; column < resultCols; column++) - { - tempConstArray[resultRows * column + row].setFConst(0.0f); - for (int i = 0; i < leftCols; i++) - { - tempConstArray[resultRows * column + row].setFConst( - tempConstArray[resultRows * column + row].getFConst() + - unionArray[i * leftRows + row].getFConst() * - rightUnionArray[column * rightRows + i].getFConst()); - } - } - } - - // update return type for matrix product - returnType.setPrimarySize(resultCols); - returnType.setSecondarySize(resultRows); - } - break; - - case EOpDiv: - { - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - switch (getType().getBasicType()) - { - case EbtFloat: - if (rightUnionArray[i] == 0.0f) - { - 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()); - } - break; - - case EbtInt: - if (rightUnionArray[i] == 0) - { - 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; - - case EbtUInt: - if (rightUnionArray[i] == 0) - { - infoSink.info.message( - EPrefixWarning, getLine(), - "Divide by zero error during constant folding"); - tempConstArray[i].setUConst(UINT_MAX); - } - else - { - tempConstArray[i].setUConst( - unionArray[i].getUConst() / - rightUnionArray[i].getUConst()); - } - break; - - default: - infoSink.info.message( - EPrefixInternalError, getLine(), - "Constant folding cannot be done for \"/\""); - return NULL; - } - } - } - break; - - case EOpMatrixTimesVector: - { - if (node->getBasicType() != EbtFloat) - { - infoSink.info.message( - EPrefixInternalError, getLine(), - "Constant Folding cannot be done for matrix times vector"); - return NULL; - } - - const int matrixCols = getCols(); - const int matrixRows = getRows(); - - tempConstArray = new ConstantUnion[matrixRows]; - - for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++) - { - tempConstArray[matrixRow].setFConst(0.0f); - for (int col = 0; col < matrixCols; col++) - { - tempConstArray[matrixRow].setFConst( - tempConstArray[matrixRow].getFConst() + - unionArray[col * matrixRows + matrixRow].getFConst() * - rightUnionArray[col].getFConst()); - } - } - - returnType = node->getType(); - returnType.setPrimarySize(matrixRows); - - tempNode = new TIntermConstantUnion(tempConstArray, returnType); - tempNode->setLine(getLine()); - - return tempNode; - } - - case EOpVectorTimesMatrix: - { - if (getType().getBasicType() != EbtFloat) - { - infoSink.info.message( - EPrefixInternalError, getLine(), - "Constant Folding cannot be done for vector times matrix"); - return NULL; - } - - const int matrixCols = constantNode->getType().getCols(); - const int matrixRows = constantNode->getType().getRows(); - - tempConstArray = new ConstantUnion[matrixCols]; - - for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++) - { - tempConstArray[matrixCol].setFConst(0.0f); - for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++) - { - tempConstArray[matrixCol].setFConst( - tempConstArray[matrixCol].getFConst() + - unionArray[matrixRow].getFConst() * - rightUnionArray[matrixCol * matrixRows + matrixRow].getFConst()); - } - } - - returnType.setPrimarySize(matrixCols); - } - break; - - case EOpLogicalAnd: - // this code is written for possible future use, - // will not get executed currently - { - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - tempConstArray[i] = unionArray[i] && rightUnionArray[i]; - } - } - break; - - case EOpLogicalOr: - // this code is written for possible future use, - // will not get executed currently - { - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - tempConstArray[i] = unionArray[i] || rightUnionArray[i]; - } - } - break; - - case EOpLogicalXor: - { - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - switch (getType().getBasicType()) - { - case EbtBool: - tempConstArray[i].setBConst( - unionArray[i] == rightUnionArray[i] ? false : true); - break; - default: - UNREACHABLE(); - break; - } - } - } - break; - - case EOpLessThan: - ASSERT(objectSize == 1); - tempConstArray = new ConstantUnion[1]; - tempConstArray->setBConst(*unionArray < *rightUnionArray); - returnType = TType(EbtBool, EbpUndefined, EvqConst); - break; - - case EOpGreaterThan: - ASSERT(objectSize == 1); - tempConstArray = new ConstantUnion[1]; - tempConstArray->setBConst(*unionArray > *rightUnionArray); - returnType = TType(EbtBool, EbpUndefined, EvqConst); - break; - - case EOpLessThanEqual: - { - ASSERT(objectSize == 1); - ConstantUnion constant; - constant.setBConst(*unionArray > *rightUnionArray); - tempConstArray = new ConstantUnion[1]; - tempConstArray->setBConst(!constant.getBConst()); - returnType = TType(EbtBool, EbpUndefined, EvqConst); - break; - } - - case EOpGreaterThanEqual: - { - ASSERT(objectSize == 1); - ConstantUnion constant; - constant.setBConst(*unionArray < *rightUnionArray); - tempConstArray = new ConstantUnion[1]; - tempConstArray->setBConst(!constant.getBConst()); - returnType = TType(EbtBool, EbpUndefined, EvqConst); - break; - } - - case EOpEqual: - if (getType().getBasicType() == EbtStruct) - { - if (!CompareStructure(node->getType(), - node->getUnionArrayPointer(), - unionArray)) - { - boolNodeFlag = true; - } - } - else - { - for (size_t i = 0; i < objectSize; i++) - { - if (unionArray[i] != rightUnionArray[i]) - { - boolNodeFlag = true; - break; // break out of for loop - } - } - } - - tempConstArray = new ConstantUnion[1]; - if (!boolNodeFlag) - { - tempConstArray->setBConst(true); - } - else - { - tempConstArray->setBConst(false); - } - - tempNode = new TIntermConstantUnion( - tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); - tempNode->setLine(getLine()); - - return tempNode; - - case EOpNotEqual: - if (getType().getBasicType() == EbtStruct) - { - if (CompareStructure(node->getType(), - node->getUnionArrayPointer(), - unionArray)) - { - boolNodeFlag = true; - } - } - else - { - for (size_t i = 0; i < objectSize; i++) - { - if (unionArray[i] == rightUnionArray[i]) - { - boolNodeFlag = true; - break; // break out of for loop - } - } - } - - tempConstArray = new ConstantUnion[1]; - if (!boolNodeFlag) - { - tempConstArray->setBConst(true); - } - else - { - tempConstArray->setBConst(false); - } - - tempNode = new TIntermConstantUnion( - tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); - tempNode->setLine(getLine()); - - return tempNode; - - default: - infoSink.info.message( - EPrefixInternalError, getLine(), - "Invalid operator for constant folding"); - return NULL; - } - tempNode = new TIntermConstantUnion(tempConstArray, returnType); - tempNode->setLine(getLine()); - - return tempNode; - } - else - { - // - // Do unary operations - // - TIntermConstantUnion *newNode = 0; - ConstantUnion* tempConstArray = new ConstantUnion[objectSize]; - 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; - case EbtUInt: - tempConstArray[i].setUConst(static_cast<unsigned int>( - -static_cast<int>(unionArray[i].getUConst()))); - break; - default: - infoSink.info.message( - EPrefixInternalError, getLine(), - "Unary operation not folded into constant"); - return NULL; - } - break; - - case EOpLogicalNot: - // this code is written for possible future use, - // will not get executed currently - switch (getType().getBasicType()) - { - case EbtBool: - tempConstArray[i].setBConst(!unionArray[i].getBConst()); - break; - default: - infoSink.info.message( - EPrefixInternalError, getLine(), - "Unary operation not folded into constant"); - return NULL; - } - break; - - default: - return NULL; - } - } - newNode = new TIntermConstantUnion(tempConstArray, getType()); - newNode->setLine(getLine()); - return newNode; - } -} - -// static -TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunction) -{ - if (hashFunction == NULL || name.empty()) - return name; - khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length()); - TStringStream stream; - stream << HASHED_NAME_PREFIX << std::hex << number; - TString hashedName = stream.str(); - return hashedName; -} diff --git a/src/3rdparty/angle/src/compiler/translator/LoopInfo.h b/src/3rdparty/angle/src/compiler/translator/LoopInfo.h index 5a140c339e..5f72a6e944 100644 --- a/src/3rdparty/angle/src/compiler/translator/LoopInfo.h +++ b/src/3rdparty/angle/src/compiler/translator/LoopInfo.h @@ -7,7 +7,7 @@ #ifndef COMPILER_TRANSLATOR_LOOP_INFO_H_ #define COMPILER_TRANSLATOR_LOOP_INFO_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" class TLoopIndexInfo { diff --git a/src/3rdparty/angle/src/compiler/translator/NodeSearch.h b/src/3rdparty/angle/src/compiler/translator/NodeSearch.h index b58c7ec689..60070c9d33 100644 --- a/src/3rdparty/angle/src/compiler/translator/NodeSearch.h +++ b/src/3rdparty/angle/src/compiler/translator/NodeSearch.h @@ -9,7 +9,7 @@ #ifndef TRANSLATOR_NODESEARCH_H_ #define TRANSLATOR_NODESEARCH_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" namespace sh { diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp index 7839c04852..6d07cccc04 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp @@ -81,9 +81,10 @@ void TOutputGLSLBase::writeVariableType(const TType &type) { TInfoSinkBase &out = objSink(); TQualifier qualifier = type.getQualifier(); - // TODO(alokp): Validate qualifier for variable declarations. if (qualifier != EvqTemporary && qualifier != EvqGlobal) + { out << type.getQualifierString() << " "; + } // Declare the struct if we have not done so already. if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct())) { @@ -648,6 +649,17 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) mDeclaringVariables = false; } break; + case EOpInvariantDeclaration: { + // Invariant declaration. + ASSERT(visit == PreVisit); + const TIntermSequence *sequence = node->getSequence(); + ASSERT(sequence && sequence->size() == 1); + const TIntermSymbol *symbol = sequence->front()->getAsSymbolNode(); + ASSERT(symbol); + out << "invariant " << symbol->getSymbol() << ";"; + visitChildren = false; + break; + } case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break; diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h index 42364de6f5..e5174f5660 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h @@ -9,7 +9,7 @@ #include <set> -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/LoopInfo.h" #include "compiler/translator/ParseContext.h" diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp index 1bf1181af0..a5ea71599d 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp @@ -21,6 +21,7 @@ #include "compiler/translator/util.h" #include "compiler/translator/UniformHLSL.h" #include "compiler/translator/StructureHLSL.h" +#include "compiler/translator/TranslatorHLSL.h" #include <algorithm> #include <cfloat> @@ -93,8 +94,10 @@ bool OutputHLSL::TextureFunction::operator<(const TextureFunction &rhs) const return false; } -OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType) - : TIntermTraverser(true, true, true), mContext(context), mOutputType(outputType) +OutputHLSL::OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator) + : TIntermTraverser(true, true, true), + mContext(context), + mOutputType(parentTranslator->getOutputType()) { mUnfoldShortCircuit = new UnfoldShortCircuit(context, this); mInsideFunction = false; @@ -126,6 +129,7 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc mUsesDiscardRewriting = false; mUsesNestedBreak = false; + const ShBuiltInResources &resources = parentTranslator->getResources(); mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1; mUniqueIndex = 0; @@ -138,7 +142,7 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc mExcessiveLoopIndex = NULL; mStructureHLSL = new StructureHLSL; - mUniformHLSL = new UniformHLSL(mStructureHLSL, mOutputType); + mUniformHLSL = new UniformHLSL(mStructureHLSL, parentTranslator); if (mOutputType == SH_HLSL9_OUTPUT) { @@ -212,31 +216,6 @@ TInfoSinkBase &OutputHLSL::getBodyStream() return mBody; } -const std::vector<sh::Uniform> &OutputHLSL::getUniforms() -{ - return mUniformHLSL->getUniforms(); -} - -const std::vector<sh::InterfaceBlock> &OutputHLSL::getInterfaceBlocks() const -{ - return mUniformHLSL->getInterfaceBlocks(); -} - -const std::vector<sh::Attribute> &OutputHLSL::getOutputVariables() const -{ - return mActiveOutputVariables; -} - -const std::vector<sh::Attribute> &OutputHLSL::getAttributes() const -{ - return mActiveAttributes; -} - -const std::vector<sh::Varying> &OutputHLSL::getVaryings() const -{ - return mActiveVaryings; -} - const std::map<std::string, unsigned int> &OutputHLSL::getInterfaceBlockRegisterMap() const { return mUniformHLSL->getInterfaceBlockRegisterMap(); @@ -324,8 +303,6 @@ void OutputHLSL::header() // Program linking depends on this exact format varyings += "static " + InterpolationString(type.getQualifier()) + " " + TypeString(type) + " " + Decorate(name) + ArrayString(type) + " = " + initializer(type) + ";\n"; - - declareVaryingToList(type, type.getQualifier(), name, mActiveVaryings); } for (ReferencedSymbols::const_iterator attribute = mReferencedAttributes.begin(); attribute != mReferencedAttributes.end(); attribute++) @@ -334,10 +311,6 @@ void OutputHLSL::header() const TString &name = attribute->second->getSymbol(); attributes += "static " + TypeString(type) + " " + Decorate(name) + ArrayString(type) + " = " + initializer(type) + ";\n"; - - sh::Attribute attributeVar(GLVariableType(type), GLVariablePrecision(type), name.c_str(), - (unsigned int)type.getArraySize(), type.getLayoutQualifier().location); - mActiveAttributes.push_back(attributeVar); } out << mStructureHLSL->structsHeader(); @@ -370,14 +343,9 @@ void OutputHLSL::header() { const TString &variableName = outputVariableIt->first; const TType &variableType = outputVariableIt->second->getType(); - const TLayoutQualifier &layoutQualifier = variableType.getLayoutQualifier(); out << "static " + TypeString(variableType) + " out_" + variableName + ArrayString(variableType) + " = " + initializer(variableType) + ";\n"; - - sh::Attribute outputVar(GLVariableType(variableType), GLVariablePrecision(variableType), variableName.c_str(), - (unsigned int)variableType.getArraySize(), layoutQualifier.location); - mActiveOutputVariables.push_back(outputVar); } } else @@ -1951,6 +1919,9 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) out << ", "; } break; + case EOpInvariantDeclaration: + // Do not do any translation + return false; case EOpPrototype: if (visit == PreVisit) { @@ -2910,29 +2881,4 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con return constUnion; } -class DeclareVaryingTraverser : public GetVariableTraverser<Varying> -{ - public: - DeclareVaryingTraverser(std::vector<Varying> *output, - InterpolationType interpolation) - : GetVariableTraverser(output), - mInterpolation(interpolation) - {} - - private: - void visitVariable(Varying *varying) - { - varying->interpolation = mInterpolation; - } - - InterpolationType mInterpolation; -}; - -void OutputHLSL::declareVaryingToList(const TType &type, TQualifier baseTypeQualifier, - const TString &name, std::vector<Varying> &fieldsOut) -{ - DeclareVaryingTraverser traverser(&fieldsOut, GetInterpolationType(baseTypeQualifier)); - traverser.traverse(type, name); -} - } diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h index 78bb741a11..bec02479bb 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h @@ -12,9 +12,9 @@ #include <map> #include "angle_gl.h" -#include "compiler/translator/intermediate.h" + +#include "compiler/translator/IntermNode.h" #include "compiler/translator/ParseContext.h" -#include "common/shadervars.h" namespace sh { @@ -27,17 +27,12 @@ typedef std::map<TString, TIntermSymbol*> ReferencedSymbols; class OutputHLSL : public TIntermTraverser { public: - OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType); + OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator); ~OutputHLSL(); void output(); TInfoSinkBase &getBodyStream(); - const std::vector<sh::Uniform> &getUniforms(); - const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const; - const std::vector<sh::Attribute> &getOutputVariables() const; - const std::vector<sh::Attribute> &getAttributes() const; - const std::vector<sh::Varying> &getVaryings() const; const std::map<std::string, unsigned int> &getInterfaceBlockRegisterMap() const; const std::map<std::string, unsigned int> &getUniformRegisterMap() const; @@ -155,13 +150,8 @@ class OutputHLSL : public TIntermTraverser TIntermSymbol *mExcessiveLoopIndex; - void declareVaryingToList(const TType &type, TQualifier baseTypeQualifier, const TString &name, std::vector<sh::Varying>& fieldsOut); - TString structInitializerString(int indent, const TStructure &structure, const TString &rhsStructName); - std::vector<sh::Attribute> mActiveOutputVariables; - std::vector<sh::Attribute> mActiveAttributes; - std::vector<sh::Varying> mActiveVaryings; std::map<TIntermTyped*, TString> mFlaggedStructMappedNames; std::map<TIntermTyped*, TString> mFlaggedStructOriginalNames; diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp index 605612ac37..ff0a49667c 100644 --- a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp @@ -1018,6 +1018,45 @@ void TParseContext::handlePragmaDirective(const TSourceLoc& loc, const char* nam // ///////////////////////////////////////////////////////////////////////////////// +const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location, + const TString *name, + const TSymbol *symbol) +{ + const TVariable *variable = NULL; + + if (!symbol) + { + error(location, "undeclared identifier", name->c_str()); + recover(); + } + else if (!symbol->isVariable()) + { + error(location, "variable expected", name->c_str()); + recover(); + } + else + { + variable = static_cast<const TVariable*>(symbol); + + if (symbolTable.findBuiltIn(variable->getName(), shaderVersion) && + !variable->getExtension().empty() && + extensionErrorCheck(location, variable->getExtension())) + { + recover(); + } + } + + if (!variable) + { + TType type(EbtFloat, EbpUndefined); + TVariable *fakeVariable = new TVariable(name, type); + symbolTable.declare(fakeVariable); + variable = fakeVariable; + } + + return variable; +} + // // Look up a function name in the symbol table, and make sure it is a function. // @@ -1050,6 +1089,8 @@ const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* // Initializers show up in several places in the grammar. Have one set of // code to handle them here. // +// Returns true on error, false if no error +// bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& identifier, TPublicType& pType, TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable) { @@ -1308,14 +1349,40 @@ TIntermAggregate* TParseContext::parseSingleInitDeclaration(TPublicType &publicT } } -TIntermAggregate* TParseContext::parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, TSymbol *identifierSymbol, const TSourceLoc& identifierLocation, const TString &identifier) +TIntermAggregate* TParseContext::parseInvariantDeclaration(const TSourceLoc &invariantLoc, + const TSourceLoc &identifierLoc, + const TString *identifier, + const TSymbol *symbol) { - if (publicType.type == EbtInvariant && !identifierSymbol) + // invariant declaration + if (globalErrorCheck(invariantLoc, symbolTable.atGlobalLevel(), "invariant varying")) + { + recover(); + } + + if (!symbol) { - error(identifierLocation, "undeclared identifier declared as invariant", identifier.c_str()); + error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str()); recover(); + + return NULL; } + else + { + const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol); + ASSERT(variable); + const TType &type = variable->getType(); + TIntermSymbol *intermSymbol = intermediate.addSymbol(variable->getUniqueId(), + *identifier, type, identifierLoc); + TIntermAggregate *aggregate = intermediate.makeAggregate(intermSymbol, identifierLoc); + aggregate->setOp(EOpInvariantDeclaration); + return aggregate; + } +} + +TIntermAggregate* TParseContext::parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, TSymbol *identifierSymbol, const TSourceLoc& identifierLocation, const TString &identifier) +{ TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation); TIntermAggregate* intermAggregate = intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation); @@ -1548,7 +1615,7 @@ TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, const TType for (size_t i = 0; i < fields.size(); i++) { - if ((*args)[i]->getAsTyped()->getType() != *fields[i]->type()) + if (i >= args->size() || (*args)[i]->getAsTyped()->getType() != *fields[i]->type()) { error(line, "Structure constructor arguments do not match structure fields", "Error"); recover(); diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.h b/src/3rdparty/angle/src/compiler/translator/ParseContext.h index a402eec78e..1f4cbdeba9 100644 --- a/src/3rdparty/angle/src/compiler/translator/ParseContext.h +++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.h @@ -9,7 +9,7 @@ #include "compiler/translator/Compiler.h" #include "compiler/translator/Diagnostics.h" #include "compiler/translator/DirectiveHandler.h" -#include "compiler/translator/localintermediate.h" +#include "compiler/translator/Intermediate.h" #include "compiler/translator/SymbolTable.h" #include "compiler/preprocessor/Preprocessor.h" @@ -77,6 +77,9 @@ struct TParseContext { void trace(const char* str); void recover(); + // This method is guaranteed to succeed, even if no variable with 'name' exists. + const TVariable *getNamedVariable(const TSourceLoc &location, const TString *name, const TSymbol *symbol); + bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc& line); bool parseMatrixFields(const TString&, int matCols, int matRows, TMatrixFields&, const TSourceLoc& line); @@ -126,6 +129,8 @@ struct TParseContext { TIntermAggregate* parseSingleDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier); TIntermAggregate* parseSingleArrayDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& indexLocation, TIntermTyped *indexExpression); TIntermAggregate* parseSingleInitDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& initLocation, TIntermTyped *initializer); + TIntermAggregate* parseInvariantDeclaration(const TSourceLoc &invariantLoc, const TSourceLoc &identifierLoc, const TString *identifier, const TSymbol *symbol); + TIntermAggregate* parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, TSymbol *identifierSymbol, const TSourceLoc& identifierLocation, const TString &identifier); TIntermAggregate* parseArrayDeclarator(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& arrayLocation, TIntermNode *declaratorList, TIntermTyped *indexExpression); TIntermAggregate* parseInitDeclarator(TPublicType &publicType, TIntermAggregate *declaratorList, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& initLocation, TIntermTyped *initializer); diff --git a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp index 1ba087e176..1f6fb75821 100644 --- a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp +++ b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" class TAliveTraverser : public TIntermTraverser { public: diff --git a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp new file mode 100644 index 0000000000..767b18085c --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp @@ -0,0 +1,82 @@ +// +// Copyright (c) 2002-2014 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/translator/RegenerateStructNames.h" +#include "compiler/translator/compilerdebug.h" + +void RegenerateStructNames::visitSymbol(TIntermSymbol *symbol) +{ + ASSERT(symbol); + TType *type = symbol->getTypePointer(); + ASSERT(type); + TStructure *userType = type->getStruct(); + if (!userType) + return; + + if (mSymbolTable.findBuiltIn(userType->name(), mShaderVersion)) + { + // Built-in struct, do not touch it. + return; + } + + int uniqueId = userType->uniqueId(); + + ASSERT(mScopeDepth > 0); + if (mScopeDepth == 1) + { + // If a struct is defined at global scope, we don't map its name. + // This is because at global level, the struct might be used to + // declare a uniform, so the same name needs to stay the same for + // vertex/fragment shaders. However, our mapping uses internal ID, + // which will be different for the same struct in vertex/fragment + // shaders. + // This is OK because names for any structs defined in other scopes + // will begin with "_webgl", which is reserved. So there will be + // no conflicts among unmapped struct names from global scope and + // mapped struct names from other scopes. + // However, we need to keep track of these global structs, so if a + // variable is used in a local scope, we don't try to modify the + // struct name through that variable. + mDeclaredGlobalStructs.insert(uniqueId); + return; + } + if (mDeclaredGlobalStructs.count(uniqueId) > 0) + return; + // Map {name} to _webgl_struct_{uniqueId}_{name}. + const char kPrefix[] = "_webgl_struct_"; + if (userType->name().find(kPrefix) == 0) + { + // The name has already been regenerated. + return; + } + std::string id = Str(uniqueId); + TString tmp = kPrefix + TString(id.c_str()); + tmp += "_" + userType->name(); + userType->setName(tmp); +} + +bool RegenerateStructNames::visitAggregate(Visit, TIntermAggregate *aggregate) +{ + ASSERT(aggregate); + switch (aggregate->getOp()) + { + case EOpSequence: + ++mScopeDepth; + { + TIntermSequence &sequence = *(aggregate->getSequence()); + for (size_t ii = 0; ii < sequence.size(); ++ii) + { + TIntermNode *node = sequence[ii]; + ASSERT(node != NULL); + node->traverse(this); + } + } + --mScopeDepth; + return false; + default: + return true; + } +} diff --git a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h new file mode 100644 index 0000000000..ac87600347 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h @@ -0,0 +1,40 @@ +// +// Copyright (c) 2002-2014 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_TRANSLATOR_REGENERATE_STRUCT_NAMES_H_ +#define COMPILER_TRANSLATOR_REGENERATE_STRUCT_NAMES_H_ + +#include "compiler/translator/Intermediate.h" +#include "compiler/translator/SymbolTable.h" + +#include <set> + +class RegenerateStructNames : public TIntermTraverser +{ + public: + RegenerateStructNames(const TSymbolTable &symbolTable, + int shaderVersion) + : mSymbolTable(symbolTable), + mShaderVersion(shaderVersion), + mScopeDepth(0) {} + + protected: + virtual void visitSymbol(TIntermSymbol *); + virtual bool visitAggregate(Visit, TIntermAggregate *); + + private: + const TSymbolTable &mSymbolTable; + int mShaderVersion; + + // Indicating the depth of the current scope. + // The global scope is 1. + int mScopeDepth; + + // If a struct's declared globally, push its ID in this set. + std::set<int> mDeclaredGlobalStructs; +}; + +#endif // COMPILER_TRANSLATOR_REGENERATE_STRUCT_NAMES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp index e381c32690..0cf6910aa2 100644 --- a/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp +++ b/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/RemoveTree.h" // diff --git a/src/3rdparty/angle/src/compiler/translator/RenameFunction.h b/src/3rdparty/angle/src/compiler/translator/RenameFunction.h index 1f7fb16c45..d43e6ef7be 100644 --- a/src/3rdparty/angle/src/compiler/translator/RenameFunction.h +++ b/src/3rdparty/angle/src/compiler/translator/RenameFunction.h @@ -7,7 +7,7 @@ #ifndef COMPILER_RENAME_FUNCTION #define COMPILER_RENAME_FUNCTION -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // // Renames a function, including its declaration and any calls to it. diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h index 39963d6a82..d87baea0fe 100644 --- a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h +++ b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h @@ -10,7 +10,7 @@ #ifndef COMPILER_REWRITE_ELSE_BLOCKS_H_ #define COMPILER_REWRITE_ELSE_BLOCKS_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" namespace sh { diff --git a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp index 3a179f7499..8857ad59bd 100644 --- a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp @@ -9,6 +9,7 @@ #include <algorithm> +#include "angle_gl.h" #include "common/angleutils.h" namespace @@ -249,6 +250,16 @@ TString ScalarizeVecAndMatConstructorArgs::createTempVariable(TIntermTyped *orig TType type = original->getType(); type.setQualifier(EvqTemporary); + if (mShaderType == GL_FRAGMENT_SHADER && + type.getBasicType() == EbtFloat && + type.getPrecision() == EbpUndefined) + { + // We use the highest available precision for the temporary variable + // to avoid computing the actual precision using the rules defined + // in GLSL ES 1.0 Section 4.5.2. + type.setPrecision(mFragmentPrecisionHigh ? EbpHigh : EbpMedium); + } + TIntermBinary *init = new TIntermBinary(EOpInitialize); TIntermSymbol *symbolNode = new TIntermSymbol(-1, tempVarName, type); init->setLeft(symbolNode); diff --git a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h index 6aeb0c4f60..7c6d09c1bb 100644 --- a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h +++ b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h @@ -7,13 +7,16 @@ #ifndef COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_ #define COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" class ScalarizeVecAndMatConstructorArgs : public TIntermTraverser { public: - ScalarizeVecAndMatConstructorArgs() - : mTempVarCount(0) {} + ScalarizeVecAndMatConstructorArgs(sh::GLenum shaderType, + bool fragmentPrecisionHigh) + : mTempVarCount(0), + mShaderType(shaderType), + mFragmentPrecisionHigh(fragmentPrecisionHigh) {} protected: virtual bool visitAggregate(Visit visit, TIntermAggregate *node); @@ -36,6 +39,9 @@ class ScalarizeVecAndMatConstructorArgs : public TIntermTraverser std::vector<TIntermSequence> mSequenceStack; int mTempVarCount; + + sh::GLenum mShaderType; + bool mFragmentPrecisionHigh; }; #endif // COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h index 8ddd3cb1ac..029ac30b9a 100644 --- a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h +++ b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h @@ -9,7 +9,7 @@ #ifndef COMPILER_SEARCHSYMBOL_H_ #define COMPILER_SEARCHSYMBOL_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/ParseContext.h" namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp index 6a801eacfe..20ce71605c 100644 --- a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp @@ -18,14 +18,26 @@ #include "compiler/translator/VariablePacker.h" #include "angle_gl.h" -static bool isInitialized = false; +namespace +{ + +enum ShaderVariableType +{ + SHADERVAR_UNIFORM, + SHADERVAR_VARYING, + SHADERVAR_ATTRIBUTE, + SHADERVAR_OUTPUTVARIABLE, + SHADERVAR_INTERFACEBLOCK +}; + +bool isInitialized = false; // // This is the platform independent interface between an OGL driver // and the shading language compiler. // -static bool checkVariableMaxLengths(const ShHandle handle, +static bool CheckVariableMaxLengths(const ShHandle handle, size_t expectedValue) { size_t activeUniformLimit = 0; @@ -39,7 +51,7 @@ static bool checkVariableMaxLengths(const ShHandle handle, expectedValue == varyingLimit); } -static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue) +bool CheckMappedNameMaxLength(const ShHandle handle, size_t expectedValue) { size_t mappedNameMaxLength = 0; ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength); @@ -47,7 +59,7 @@ static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue } template <typename VarT> -static const sh::ShaderVariable *ReturnVariable(const std::vector<VarT> &infoList, int index) +const sh::ShaderVariable *ReturnVariable(const std::vector<VarT> &infoList, int index) { if (index < 0 || static_cast<size_t>(index) >= infoList.size()) { @@ -57,7 +69,7 @@ static const sh::ShaderVariable *ReturnVariable(const std::vector<VarT> &infoLis return &infoList[index]; } -static const sh::ShaderVariable *GetVariable(const TCompiler *compiler, ShShaderInfo varType, int index) +const sh::ShaderVariable *GetVariable(const TCompiler *compiler, ShShaderInfo varType, int index) { switch (varType) { @@ -73,7 +85,7 @@ static const sh::ShaderVariable *GetVariable(const TCompiler *compiler, ShShader } } -static ShPrecisionType ConvertPrecision(sh::GLenum precision) +ShPrecisionType ConvertPrecision(sh::GLenum precision) { switch (precision) { @@ -91,6 +103,55 @@ static ShPrecisionType ConvertPrecision(sh::GLenum precision) } } +template <typename VarT> +const std::vector<VarT> *GetVariableList(const TCompiler *compiler, ShaderVariableType variableType); + +template <> +const std::vector<sh::Uniform> *GetVariableList(const TCompiler *compiler, ShaderVariableType) +{ + return &compiler->getUniforms(); +} + +template <> +const std::vector<sh::Varying> *GetVariableList(const TCompiler *compiler, ShaderVariableType) +{ + return &compiler->getVaryings(); +} + +template <> +const std::vector<sh::Attribute> *GetVariableList(const TCompiler *compiler, ShaderVariableType variableType) +{ + return (variableType == SHADERVAR_ATTRIBUTE ? + &compiler->getAttributes() : + &compiler->getOutputVariables()); +} + +template <> +const std::vector<sh::InterfaceBlock> *GetVariableList(const TCompiler *compiler, ShaderVariableType) +{ + return &compiler->getInterfaceBlocks(); +} + +template <typename VarT> +const std::vector<VarT> *GetShaderVariables(const ShHandle handle, ShaderVariableType variableType) +{ + if (!handle) + { + return NULL; + } + + TShHandleBase* base = static_cast<TShHandleBase*>(handle); + TCompiler* compiler = base->getAsCompiler(); + if (!compiler) + { + return NULL; + } + + return GetVariableList<VarT>(compiler, variableType); +} + +} + // // Driver must call this first, once, before doing any other compiler operations. // Subsequent calls to this function are no-op. @@ -372,7 +433,7 @@ void ShGetVariableInfo(const ShHandle handle, // SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH // in ShGetInfo, below. size_t variableLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); - ASSERT(checkVariableMaxLengths(handle, variableLength)); + ASSERT(CheckVariableMaxLengths(handle, variableLength)); strncpy(name, varInfo->name.c_str(), variableLength); name[variableLength - 1] = 0; if (mappedName) @@ -380,7 +441,7 @@ void ShGetVariableInfo(const ShHandle handle, // This size must match that queried by // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below. size_t maxMappedNameLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); - ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength)); + ASSERT(CheckMappedNameMaxLength(handle, maxMappedNameLength)); strncpy(mappedName, varInfo->mappedName.c_str(), maxMappedNameLength); mappedName[maxMappedNameLength - 1] = 0; } @@ -429,34 +490,29 @@ void ShGetNameHashingEntry(const ShHandle handle, hashedName[len - 1] = '\0'; } -void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params) +const std::vector<sh::Uniform> *ShGetUniforms(const ShHandle handle) { - if (!handle || !params) - return; + return GetShaderVariables<sh::Uniform>(handle, SHADERVAR_UNIFORM); +} - TShHandleBase* base = static_cast<TShHandleBase*>(handle); - TranslatorHLSL* translator = base->getAsTranslatorHLSL(); - if (!translator) return; +const std::vector<sh::Varying> *ShGetVaryings(const ShHandle handle) +{ + return GetShaderVariables<sh::Varying>(handle, SHADERVAR_VARYING); +} - switch(pname) - { - case SH_ACTIVE_UNIFORMS_ARRAY: - *params = (void*)&translator->getUniforms(); - break; - case SH_ACTIVE_INTERFACE_BLOCKS_ARRAY: - *params = (void*)&translator->getInterfaceBlocks(); - break; - case SH_ACTIVE_OUTPUT_VARIABLES_ARRAY: - *params = (void*)&translator->getOutputVariables(); - break; - case SH_ACTIVE_ATTRIBUTES_ARRAY: - *params = (void*)&translator->getAttributes(); - break; - case SH_ACTIVE_VARYINGS_ARRAY: - *params = (void*)&translator->getVaryings(); - break; - default: UNREACHABLE(); - } +const std::vector<sh::Attribute> *ShGetAttributes(const ShHandle handle) +{ + return GetShaderVariables<sh::Attribute>(handle, SHADERVAR_ATTRIBUTE); +} + +const std::vector<sh::Attribute> *ShGetOutputVariables(const ShHandle handle) +{ + return GetShaderVariables<sh::Attribute>(handle, SHADERVAR_OUTPUTVARIABLE); +} + +const std::vector<sh::InterfaceBlock> *ShGetInterfaceBlocks(const ShHandle handle) +{ + return GetShaderVariables<sh::InterfaceBlock>(handle, SHADERVAR_INTERFACEBLOCK); } int ShCheckVariablesWithinPackingLimits( @@ -468,7 +524,7 @@ int ShCheckVariablesWithinPackingLimits( std::vector<sh::ShaderVariable> variables; for (size_t ii = 0; ii < varInfoArraySize; ++ii) { - sh::ShaderVariable var(varInfoArray[ii].type, (sh::GLenum)0, "", varInfoArray[ii].size); + sh::ShaderVariable var(varInfoArray[ii].type, varInfoArray[ii].size); variables.push_back(var); } VariablePacker packer; diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp new file mode 100644 index 0000000000..822c558c9b --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp @@ -0,0 +1,166 @@ +// +// Copyright (c) 2014 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. +// +// ShaderVars.cpp: +// Methods for GL variable types (varyings, uniforms, etc) +// + +#include <GLSLANG/ShaderLang.h> + +namespace sh +{ + +ShaderVariable::ShaderVariable() + : type(0), + precision(0), + arraySize(0), + staticUse(false) +{} + +ShaderVariable::ShaderVariable(GLenum typeIn, unsigned int arraySizeIn) + : type(typeIn), + precision(0), + arraySize(arraySizeIn), + staticUse(false) +{} + +ShaderVariable::~ShaderVariable() +{} + +ShaderVariable::ShaderVariable(const ShaderVariable &other) + : type(other.type), + precision(other.precision), + name(other.name), + mappedName(other.mappedName), + arraySize(other.arraySize), + staticUse(other.staticUse), + fields(other.fields), + structName(other.structName) +{} + +ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other) +{ + type = other.type; + precision = other.precision; + name = other.name; + mappedName = other.mappedName; + arraySize = other.arraySize; + staticUse = other.staticUse; + fields = other.fields; + structName = other.structName; + return *this; +} + +Uniform::Uniform() +{} + +Uniform::~Uniform() +{} + +Uniform::Uniform(const Uniform &other) + : ShaderVariable(other) +{} + +Uniform &Uniform::operator=(const Uniform &other) +{ + ShaderVariable::operator=(other); + return *this; +} + +Attribute::Attribute() + : location(-1) +{} + +Attribute::~Attribute() +{} + +Attribute::Attribute(const Attribute &other) + : ShaderVariable(other), + location(other.location) +{} + +Attribute &Attribute::operator=(const Attribute &other) +{ + ShaderVariable::operator=(other); + location = other.location; + return *this; +} + +InterfaceBlockField::InterfaceBlockField() + : isRowMajorLayout(false) +{} + +InterfaceBlockField::~InterfaceBlockField() +{} + +InterfaceBlockField::InterfaceBlockField(const InterfaceBlockField &other) + : ShaderVariable(other), + isRowMajorLayout(other.isRowMajorLayout) +{} + +InterfaceBlockField &InterfaceBlockField::operator=(const InterfaceBlockField &other) +{ + ShaderVariable::operator=(other); + isRowMajorLayout = other.isRowMajorLayout; + return *this; +} + +Varying::Varying() + : interpolation(INTERPOLATION_SMOOTH), + isInvariant(false) +{} + +Varying::~Varying() +{} + +Varying::Varying(const Varying &other) + : ShaderVariable(other), + interpolation(other.interpolation), + isInvariant(other.isInvariant) +{} + +Varying &Varying::operator=(const Varying &other) +{ + ShaderVariable::operator=(other); + interpolation = other.interpolation; + isInvariant = other.isInvariant; + return *this; +} + +InterfaceBlock::InterfaceBlock() + : arraySize(0), + layout(BLOCKLAYOUT_PACKED), + isRowMajorLayout(false), + staticUse(false) +{} + +InterfaceBlock::~InterfaceBlock() +{} + +InterfaceBlock::InterfaceBlock(const InterfaceBlock &other) + : name(other.name), + mappedName(other.mappedName), + instanceName(other.instanceName), + arraySize(other.arraySize), + layout(other.layout), + isRowMajorLayout(other.isRowMajorLayout), + staticUse(other.staticUse), + fields(other.fields) +{} + +InterfaceBlock &InterfaceBlock::operator=(const InterfaceBlock &other) +{ + name = other.name; + mappedName = other.mappedName; + instanceName = other.instanceName; + arraySize = other.arraySize; + layout = other.layout; + isRowMajorLayout = other.isRowMajorLayout; + staticUse = other.staticUse; + fields = other.fields; + return *this; +} + +} diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp index 365985c852..48929affe6 100644 --- a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp @@ -17,12 +17,19 @@ namespace sh { -Std140PaddingHelper::Std140PaddingHelper(const std::map<TString, int> &structElementIndexes) - : mPaddingCounter(0), +Std140PaddingHelper::Std140PaddingHelper(const std::map<TString, int> &structElementIndexes, + unsigned *uniqueCounter) + : mPaddingCounter(uniqueCounter), mElementIndex(0), mStructElementIndexes(structElementIndexes) {} +TString Std140PaddingHelper::next() +{ + unsigned value = (*mPaddingCounter)++; + return str(value); +} + int Std140PaddingHelper::prePadding(const TType &type) { if (type.getBasicType() == EbtStruct || type.isMatrix() || type.isArray()) @@ -68,7 +75,7 @@ TString Std140PaddingHelper::prePaddingString(const TType &type) for (int paddingIndex = 0; paddingIndex < paddingCount; paddingIndex++) { - padding += " float pad_" + str(mPaddingCounter++) + ";\n"; + padding += " float pad_" + next() + ";\n"; } return padding; @@ -116,19 +123,25 @@ TString Std140PaddingHelper::postPaddingString(const TType &type, bool useHLSLRo TString padding; for (int paddingOffset = numComponents; paddingOffset < 4; paddingOffset++) { - padding += " float pad_" + str(mPaddingCounter++) + ";\n"; + padding += " float pad_" + next() + ";\n"; } return padding; } StructureHLSL::StructureHLSL() + : mUniquePaddingCounter(0) {} +Std140PaddingHelper StructureHLSL::getPaddingHelper() +{ + return Std140PaddingHelper(mStd140StructElementIndexes, &mUniquePaddingCounter); +} + TString StructureHLSL::defineQualified(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing) { if (useStd140Packing) { - Std140PaddingHelper padHelper(mStd140StructElementIndexes); + Std140PaddingHelper padHelper = getPaddingHelper(); return define(structure, useHLSLRowMajorPacking, useStd140Packing, &padHelper); } else @@ -291,9 +304,9 @@ void StructureHLSL::addConstructor(const TType &type, const TString &name, const if (parameter.isScalar()) { - for (int row = 0; row < rows; row++) + for (int col = 0; col < cols; col++) { - for (int col = 0; col < cols; col++) + for (int row = 0; row < rows; row++) { constructor += TString((row == col) ? "x0" : "0.0"); @@ -306,13 +319,13 @@ void StructureHLSL::addConstructor(const TType &type, const TString &name, const } else if (parameter.isMatrix()) { - for (int row = 0; row < rows; row++) + for (int col = 0; col < cols; col++) { - for (int col = 0; col < cols; col++) + for (int row = 0; row < rows; row++) { if (row < parameter.getRows() && col < parameter.getCols()) { - constructor += TString("x0") + "[" + str(row) + "][" + str(col) + "]"; + constructor += TString("x0") + "[" + str(col) + "][" + str(row) + "]"; } else { @@ -461,7 +474,7 @@ std::string StructureHLSL::structsHeader() const void StructureHLSL::storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking) { - Std140PaddingHelper padHelper(mStd140StructElementIndexes); + Std140PaddingHelper padHelper = getPaddingHelper(); const TFieldList &fields = structure.fields(); for (unsigned int i = 0; i < fields.size(); i++) diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h index 63fbaaaf8e..ed002fef30 100644 --- a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h @@ -11,7 +11,7 @@ #define TRANSLATOR_STRUCTUREHLSL_H_ #include "compiler/translator/Common.h" -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include <set> @@ -26,7 +26,8 @@ namespace sh class Std140PaddingHelper { public: - explicit Std140PaddingHelper(const std::map<TString, int> &structElementIndexes); + explicit Std140PaddingHelper(const std::map<TString, int> &structElementIndexes, + unsigned *uniqueCounter); int elementIndex() const { return mElementIndex; } int prePadding(const TType &type); @@ -34,7 +35,9 @@ class Std140PaddingHelper TString postPaddingString(const TType &type, bool useHLSLRowMajorPacking); private: - int mPaddingCounter; + TString next(); + + unsigned *mPaddingCounter; int mElementIndex; const std::map<TString, int> &mStructElementIndexes; }; @@ -50,9 +53,11 @@ class StructureHLSL TString defineQualified(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing); static TString defineNameless(const TStructure &structure); - Std140PaddingHelper getPaddingHelper() const { return Std140PaddingHelper(mStd140StructElementIndexes); } + Std140PaddingHelper getPaddingHelper(); private: + unsigned mUniquePaddingCounter; + std::map<TString, int> mStd140StructElementIndexes; typedef std::set<TString> StructNames; diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp index ae4fcaa6c3..028da21151 100644 --- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp +++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp @@ -98,7 +98,8 @@ TSymbol::TSymbol(const TSymbol ©Of) uniqueId = copyOf.uniqueId; } -TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtIn, bool *sameScope) +TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, + bool *builtIn, bool *sameScope) const { int level = currentLevel(); TSymbol *symbol; @@ -122,7 +123,8 @@ TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtI return symbol; } -TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion) +TSymbol *TSymbolTable::findBuiltIn( + const TString &name, int shaderVersion) const { for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--) { @@ -210,7 +212,7 @@ void TSymbolTable::insertBuiltIn( insert(level, function); } -TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) +TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const { if (!SupportsPrecision(type)) return EbpUndefined; diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h index d3ddf19e34..6b0e0c0a03 100644 --- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h +++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h @@ -34,7 +34,7 @@ #include "common/angleutils.h" #include "compiler/translator/InfoSink.h" -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // Symbol base class. (Can build functions or variables out of these...) class TSymbol @@ -323,15 +323,15 @@ class TSymbolTable // When the symbol table is initialized with the built-ins, there should // 'push' calls, so that built-ins are at level 0 and the shader // globals are at level 1. - bool isEmpty() + bool isEmpty() const { return table.empty(); } - bool atBuiltInLevel() + bool atBuiltInLevel() const { return currentLevel() <= LAST_BUILTIN_LEVEL; } - bool atGlobalLevel() + bool atGlobalLevel() const { return currentLevel() <= GLOBAL_LEVEL; } @@ -373,8 +373,8 @@ class TSymbolTable TType *ptype4 = 0, TType *ptype5 = 0); TSymbol *find(const TString &name, int shaderVersion, - bool *builtIn = NULL, bool *sameScope = NULL); - TSymbol *findBuiltIn(const TString &name, int shaderVersion); + bool *builtIn = NULL, bool *sameScope = NULL) const; + TSymbol *findBuiltIn(const TString &name, int shaderVersion) const; TSymbolTableLevel *getOuterLevel() { @@ -406,7 +406,7 @@ class TSymbolTable // Searches down the precisionStack for a precision qualifier // for the specified TBasicType - TPrecision getDefaultPrecision(TBasicType type); + TPrecision getDefaultPrecision(TBasicType type) const; static int nextUniqueId() { diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp index 52588e4626..22bf60e86e 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp @@ -17,16 +17,10 @@ TranslatorHLSL::TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutpu void TranslatorHLSL::translate(TIntermNode *root) { TParseContext& parseContext = *GetGlobalParseContext(); - sh::OutputHLSL outputHLSL(parseContext, getResources(), getOutputType()); + sh::OutputHLSL outputHLSL(parseContext, this); outputHLSL.output(); - attributes = outputHLSL.getAttributes(); - outputVariables = outputHLSL.getOutputVariables(); - uniforms = outputHLSL.getUniforms(); - varyings = outputHLSL.getVaryings(); - interfaceBlocks = outputHLSL.getInterfaceBlocks(); - mInterfaceBlockRegisterMap = outputHLSL.getInterfaceBlockRegisterMap(); mUniformRegisterMap = outputHLSL.getUniformRegisterMap(); } diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h index 598c8a7b30..11a042d83a 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h @@ -8,7 +8,6 @@ #define COMPILER_TRANSLATORHLSL_H_ #include "compiler/translator/Compiler.h" -#include "common/shadervars.h" class TranslatorHLSL : public TCompiler { diff --git a/src/3rdparty/angle/src/compiler/translator/Types.cpp b/src/3rdparty/angle/src/compiler/translator/Types.cpp index bafad0d64f..d36936fb23 100644 --- a/src/3rdparty/angle/src/compiler/translator/Types.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Types.cpp @@ -13,6 +13,38 @@ #include <algorithm> #include <climits> +const char* getBasicString(TBasicType t) +{ + switch (t) + { + case EbtVoid: return "void"; break; + case EbtFloat: return "float"; break; + case EbtInt: return "int"; break; + case EbtUInt: return "uint"; break; + case EbtBool: return "bool"; break; + case EbtSampler2D: return "sampler2D"; break; + case EbtSampler3D: return "sampler3D"; break; + case EbtSamplerCube: return "samplerCube"; break; + case EbtSamplerExternalOES: return "samplerExternalOES"; break; + case EbtSampler2DRect: return "sampler2DRect"; break; + case EbtSampler2DArray: return "sampler2DArray"; break; + case EbtISampler2D: return "isampler2D"; break; + case EbtISampler3D: return "isampler3D"; break; + case EbtISamplerCube: return "isamplerCube"; break; + case EbtISampler2DArray: return "isampler2DArray"; break; + case EbtUSampler2D: return "usampler2D"; break; + case EbtUSampler3D: return "usampler3D"; break; + case EbtUSamplerCube: return "usamplerCube"; break; + case EbtUSampler2DArray: return "usampler2DArray"; break; + case EbtSampler2DShadow: return "sampler2DShadow"; break; + case EbtSamplerCubeShadow: return "samplerCubeShadow"; break; + case EbtSampler2DArrayShadow: return "sampler2DArrayShadow"; break; + case EbtStruct: return "structure"; break; + case EbtInterfaceBlock: return "interface block"; break; + default: UNREACHABLE(); return "unknown type"; + } +} + TType::TType(const TPublicType &p) : type(p.type), precision(p.precision), qualifier(p.qualifier), layoutQualifier(p.layoutQualifier), primarySize(p.primarySize), secondarySize(p.secondarySize), array(p.array), arraySize(p.arraySize), diff --git a/src/3rdparty/angle/src/compiler/translator/Types.h b/src/3rdparty/angle/src/compiler/translator/Types.h index bc50a4dc64..075196daa3 100644 --- a/src/3rdparty/angle/src/compiler/translator/Types.h +++ b/src/3rdparty/angle/src/compiler/translator/Types.h @@ -140,6 +140,17 @@ class TStructure : public TFieldListCollection private: DISALLOW_COPY_AND_ASSIGN(TStructure); + + // TODO(zmo): Find a way to get rid of the const_cast in function + // setName(). At the moment keep this function private so only + // friend class RegenerateStructNames may call it. + friend class RegenerateStructNames; + void setName(const TString &name) + { + TString *mutableName = const_cast<TString *>(mName); + *mutableName = name; + } + virtual TString mangledNamePrefix() const { return "struct-"; diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h index 1e416bc04c..6fd3b457bd 100644 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h @@ -9,7 +9,7 @@ #ifndef COMPILER_UNFOLDSHORTCIRCUIT_H_ #define COMPILER_UNFOLDSHORTCIRCUIT_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/ParseContext.h" namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h index 24c14a60e3..3acaf7ee7c 100644 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h @@ -11,7 +11,7 @@ #define COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_ #include "common/angleutils.h" -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // This traverser identifies all the short circuit binary nodes that need to // be replaced, and creates the corresponding replacement nodes. However, diff --git a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp index 41a7d2c10b..61b6ed7455 100644 --- a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp @@ -14,6 +14,7 @@ #include "compiler/translator/StructureHLSL.h" #include "compiler/translator/util.h" #include "compiler/translator/UtilsHLSL.h" +#include "compiler/translator/TranslatorHLSL.h" namespace sh { @@ -30,18 +31,6 @@ static const char *UniformRegisterPrefix(const TType &type) } } -static TString InterfaceBlockFieldName(const TInterfaceBlock &interfaceBlock, const TField &field) -{ - if (interfaceBlock.hasInstanceName()) - { - return interfaceBlock.name() + "." + field.name(); - } - else - { - return field.name(); - } -} - static TString InterfaceBlockFieldTypeString(const TField &field, TLayoutBlockStorage blockStorage) { const TType &fieldType = *field.type(); @@ -72,12 +61,13 @@ static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock) return DecoratePrivate(interfaceBlock.name()) + "_type"; } -UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType) +UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, TranslatorHLSL *translator) : mUniformRegister(0), mInterfaceBlockRegister(0), mSamplerRegister(0), mStructureHLSL(structureHLSL), - mOutputType(outputType) + mOutputType(translator->getOutputType()), + mUniforms(translator->getUniforms()) {} void UniformHLSL::reserveUniformRegisters(unsigned int registerCount) @@ -90,18 +80,32 @@ void UniformHLSL::reserveInterfaceBlockRegisters(unsigned int registerCount) mInterfaceBlockRegister = registerCount; } +const Uniform *UniformHLSL::findUniformByName(const TString &name) const +{ + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex) + { + if (mUniforms[uniformIndex].name == name.c_str()) + { + return &mUniforms[uniformIndex]; + } + } + + UNREACHABLE(); + return NULL; +} + unsigned int UniformHLSL::declareUniformAndAssignRegister(const TType &type, const TString &name) { unsigned int registerIndex = (IsSampler(type.getBasicType()) ? mSamplerRegister : mUniformRegister); - GetVariableTraverser<Uniform> traverser(&mActiveUniforms); - traverser.traverse(type, name); + const Uniform *uniform = findUniformByName(name); + ASSERT(uniform); - const sh::Uniform &activeUniform = mActiveUniforms.back(); - mUniformRegisterMap[activeUniform.name] = registerIndex; + mUniformRegisterMap[uniform->name] = registerIndex; - unsigned int registerCount = HLSLVariableRegisterCount(activeUniform, mOutputType); - if (IsSampler(type.getBasicType())) + unsigned int registerCount = HLSLVariableRegisterCount(*uniform, mOutputType); + + if (gl::IsSampler(uniform->type)) { mSamplerRegister += registerCount; } @@ -137,7 +141,12 @@ TString UniformHLSL::uniformsHeader(ShShaderOutput outputType, const ReferencedS else { const TStructure *structure = type.getStruct(); - const TString &typeName = (structure ? QualifiedStructNameString(*structure, false, false) : TypeString(type)); + // If this is a nameless struct, we need to use its full definition, rather than its (empty) name. + // TypeString() will invoke defineNameless in this case; qualifier prefixes are unnecessary for + // nameless structs in ES, as nameless structs cannot be used anywhere that layout qualifiers are + // permitted. + const TString &typeName = ((structure && !structure->name().empty()) ? + QualifiedStructNameString(*structure, false, false) : TypeString(type)); const TString ®isterString = TString("register(") + UniformRegisterPrefix(type) + str(registerIndex) + ")"; @@ -157,33 +166,14 @@ TString UniformHLSL::interfaceBlocksHeader(const ReferencedSymbols &referencedIn { const TType &nodeType = interfaceBlockIt->second->getType(); const TInterfaceBlock &interfaceBlock = *nodeType.getInterfaceBlock(); - const TFieldList &fieldList = interfaceBlock.fields(); unsigned int arraySize = static_cast<unsigned int>(interfaceBlock.arraySize()); unsigned int activeRegister = mInterfaceBlockRegister; - InterfaceBlock activeBlock(interfaceBlock.name().c_str(), arraySize); - for (unsigned int typeIndex = 0; typeIndex < fieldList.size(); typeIndex++) - { - const TField &field = *fieldList[typeIndex]; - const TString &fullFieldName = InterfaceBlockFieldName(interfaceBlock, field); - - bool isRowMajor = (field.type()->getLayoutQualifier().matrixPacking == EmpRowMajor); - GetInterfaceBlockFieldTraverser traverser(&activeBlock.fields, isRowMajor); - traverser.traverse(*field.type(), fullFieldName); - } - - mInterfaceBlockRegisterMap[activeBlock.name] = activeRegister; + mInterfaceBlockRegisterMap[interfaceBlock.name().c_str()] = activeRegister; mInterfaceBlockRegister += std::max(1u, arraySize); - activeBlock.layout = GetBlockLayoutType(interfaceBlock.blockStorage()); - - if (interfaceBlock.matrixPacking() == EmpRowMajor) - { - activeBlock.isRowMajorLayout = true; - } - - mActiveInterfaceBlocks.push_back(activeBlock); + // FIXME: interface block field names if (interfaceBlock.hasInstanceName()) { @@ -261,7 +251,7 @@ TString UniformHLSL::interfaceBlockMembersString(const TInterfaceBlock &interfac if (blockStorage == EbsStd140) { // 2 and 3 component vector types in some cases need pre-padding - hlsl += padHelper.prePadding(fieldType); + hlsl += padHelper.prePaddingString(fieldType); } hlsl += " " + InterfaceBlockFieldTypeString(field, blockStorage) + diff --git a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h index 835b1ef2c8..91fa51588b 100644 --- a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h @@ -10,7 +10,6 @@ #ifndef TRANSLATOR_UNIFORMHLSL_H_ #define TRANSLATOR_UNIFORMHLSL_H_ -#include "common/shadervars.h" #include "compiler/translator/Types.h" namespace sh @@ -20,7 +19,7 @@ class StructureHLSL; class UniformHLSL { public: - UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType); + UniformHLSL(StructureHLSL *structureHLSL, TranslatorHLSL *translator); void reserveUniformRegisters(unsigned int registerCount); void reserveInterfaceBlockRegisters(unsigned int registerCount); @@ -30,8 +29,6 @@ class UniformHLSL // Used for direct index references static TString interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex); - const std::vector<Uniform> &getUniforms() const { return mActiveUniforms; } - const std::vector<InterfaceBlock> &getInterfaceBlocks() const { return mActiveInterfaceBlocks; } const std::map<std::string, unsigned int> &getInterfaceBlockRegisterMap() const { return mInterfaceBlockRegisterMap; @@ -45,6 +42,7 @@ class UniformHLSL TString interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex); TString interfaceBlockMembersString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage); TString interfaceBlockStructString(const TInterfaceBlock &interfaceBlock); + const Uniform *findUniformByName(const TString &name) const; // Returns the uniform's register index unsigned int declareUniformAndAssignRegister(const TType &type, const TString &name); @@ -55,8 +53,7 @@ class UniformHLSL StructureHLSL *mStructureHLSL; ShShaderOutput mOutputType; - std::vector<Uniform> mActiveUniforms; - std::vector<InterfaceBlock> mActiveInterfaceBlocks; + const std::vector<Uniform> &mUniforms; std::map<std::string, unsigned int> mInterfaceBlockRegisterMap; std::map<std::string, unsigned int> mUniformRegisterMap; }; diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h index 8c9ebf53ed..e6e8a9619f 100644 --- a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h +++ b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/LoopInfo.h" class TInfoSinkBase; diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h index e391ad9486..0f808dbb97 100644 --- a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h +++ b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include <set> diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp index 153455c4f1..f26c1566ac 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp @@ -9,20 +9,46 @@ #include "compiler/translator/util.h" #include "common/utilities.h" -template <typename VarT> -static void ExpandUserDefinedVariable(const VarT &variable, - const std::string &name, - const std::string &mappedName, - bool markStaticUse, - std::vector<VarT> *expanded); +namespace sh +{ -// Returns info for an attribute, uniform, or varying. -template <typename VarT> -static void ExpandVariable(const VarT &variable, - const std::string &name, - const std::string &mappedName, - bool markStaticUse, - std::vector<VarT> *expanded) +namespace +{ + +TString InterfaceBlockFieldName(const TInterfaceBlock &interfaceBlock, const TField &field) +{ + if (interfaceBlock.hasInstanceName()) + { + return interfaceBlock.name() + "." + field.name(); + } + else + { + return field.name(); + } +} + +BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage) +{ + switch (blockStorage) + { + case EbsPacked: return BLOCKLAYOUT_PACKED; + case EbsShared: return BLOCKLAYOUT_SHARED; + case EbsStd140: return BLOCKLAYOUT_STANDARD; + default: UNREACHABLE(); return BLOCKLAYOUT_SHARED; + } +} + +void ExpandUserDefinedVariable(const ShaderVariable &variable, + const std::string &name, + const std::string &mappedName, + bool markStaticUse, + std::vector<ShaderVariable> *expanded); + +void ExpandVariable(const ShaderVariable &variable, + const std::string &name, + const std::string &mappedName, + bool markStaticUse, + std::vector<ShaderVariable> *expanded) { if (variable.isStruct()) { @@ -30,8 +56,8 @@ static void ExpandVariable(const VarT &variable, { for (size_t elementIndex = 0; elementIndex < variable.elementCount(); elementIndex++) { - std::string lname = name + ArrayString(elementIndex); - std::string lmappedName = mappedName + ArrayString(elementIndex); + std::string lname = name + ::ArrayString(elementIndex); + std::string lmappedName = mappedName + ::ArrayString(elementIndex); ExpandUserDefinedVariable(variable, lname, lmappedName, markStaticUse, expanded); } } @@ -42,7 +68,7 @@ static void ExpandVariable(const VarT &variable, } else { - VarT expandedVar = variable; + ShaderVariable expandedVar = variable; expandedVar.name = name; expandedVar.mappedName = mappedName; @@ -63,20 +89,19 @@ static void ExpandVariable(const VarT &variable, } } -template <class VarT> -static void ExpandUserDefinedVariable(const VarT &variable, - const std::string &name, - const std::string &mappedName, - bool markStaticUse, - std::vector<VarT> *expanded) +void ExpandUserDefinedVariable(const ShaderVariable &variable, + const std::string &name, + const std::string &mappedName, + bool markStaticUse, + std::vector<ShaderVariable> *expanded) { ASSERT(variable.isStruct()); - const std::vector<VarT> &fields = variable.fields; + const std::vector<ShaderVariable> &fields = variable.fields; for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) { - const VarT &field = fields[fieldIndex]; + const ShaderVariable &field = fields[fieldIndex]; ExpandVariable(field, name + "." + field.name, mappedName + "." + field.mappedName, @@ -86,8 +111,8 @@ static void ExpandUserDefinedVariable(const VarT &variable, } template <class VarT> -static VarT *FindVariable(const TString &name, - std::vector<VarT> *infoList) +VarT *FindVariable(const TString &name, + std::vector<VarT> *infoList) { // TODO(zmo): optimize this function. for (size_t ii = 0; ii < infoList->size(); ++ii) @@ -99,6 +124,8 @@ static VarT *FindVariable(const TString &name, return NULL; } +} + CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs, std::vector<sh::Attribute> *outputVariables, std::vector<sh::Uniform> *uniforms, @@ -125,14 +152,18 @@ CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs, void CollectVariables::visitSymbol(TIntermSymbol *symbol) { ASSERT(symbol != NULL); - sh::ShaderVariable *var = NULL; + ShaderVariable *var = NULL; const TString &symbolName = symbol->getSymbol(); - if (sh::IsVarying(symbol->getQualifier())) + if (IsVarying(symbol->getQualifier())) { var = FindVariable(symbolName, mVaryings); } - else if (symbol->getType() != EbtInterfaceBlock) + else if (symbol->getType().getBasicType() == EbtInterfaceBlock) + { + UNREACHABLE(); + } + else { switch (symbol->getQualifier()) { @@ -148,12 +179,13 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock(); if (interfaceBlock) { - sh::InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks); + InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks); ASSERT(namedBlock); var = FindVariable(symbolName, &namedBlock->fields); // Set static use on the parent interface block here namedBlock->staticUse = true; + } else { @@ -167,7 +199,7 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) case EvqFragCoord: if (!mFragCoordAdded) { - sh::Varying info; + Varying info; info.name = "gl_FragCoord"; info.mappedName = "gl_FragCoord"; info.type = GL_FLOAT_VEC4; @@ -181,7 +213,7 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) case EvqFrontFacing: if (!mFrontFacingAdded) { - sh::Varying info; + Varying info; info.name = "gl_FrontFacing"; info.mappedName = "gl_FrontFacing"; info.type = GL_BOOL; @@ -195,7 +227,7 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) case EvqPointCoord: if (!mPointCoordAdded) { - sh::Varying info; + Varying info; info.name = "gl_PointCoord"; info.mappedName = "gl_PointCoord"; info.type = GL_FLOAT_VEC2; @@ -216,17 +248,17 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) } } -template <typename VarT> -class NameHashingTraverser : public sh::GetVariableTraverser<VarT> +class NameHashingTraverser : public GetVariableTraverser { public: - NameHashingTraverser(std::vector<VarT> *output, ShHashFunction64 hashFunction) - : sh::GetVariableTraverser<VarT>(output), - mHashFunction(hashFunction) + NameHashingTraverser(ShHashFunction64 hashFunction) + : mHashFunction(hashFunction) {} private: - void visitVariable(VarT *variable) + DISALLOW_COPY_AND_ASSIGN(NameHashingTraverser); + + virtual void visitVariable(ShaderVariable *variable) { TString stringName = TString(variable->name.c_str()); variable->mappedName = TIntermTraverser::hash(stringName, mHashFunction).c_str(); @@ -238,16 +270,16 @@ class NameHashingTraverser : public sh::GetVariableTraverser<VarT> // Attributes, which cannot have struct fields, are a special case template <> void CollectVariables::visitVariable(const TIntermSymbol *variable, - std::vector<sh::Attribute> *infoList) const + std::vector<Attribute> *infoList) const { ASSERT(variable); const TType &type = variable->getType(); ASSERT(!type.getStruct()); - sh::Attribute attribute; + Attribute attribute; - attribute.type = sh::GLVariableType(type); - attribute.precision = sh::GLVariablePrecision(type); + attribute.type = GLVariableType(type); + attribute.precision = GLVariablePrecision(type); attribute.name = variable->getSymbol().c_str(); attribute.arraySize = static_cast<unsigned int>(type.getArraySize()); attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str(); @@ -258,29 +290,32 @@ void CollectVariables::visitVariable(const TIntermSymbol *variable, template <> void CollectVariables::visitVariable(const TIntermSymbol *variable, - std::vector<sh::InterfaceBlock> *infoList) const + std::vector<InterfaceBlock> *infoList) const { - sh::InterfaceBlock interfaceBlock; + InterfaceBlock interfaceBlock; const TInterfaceBlock *blockType = variable->getType().getInterfaceBlock(); - - bool isRowMajor = (blockType->matrixPacking() == EmpRowMajor); + ASSERT(blockType); interfaceBlock.name = blockType->name().c_str(); interfaceBlock.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str(); + interfaceBlock.instanceName = (blockType->hasInstanceName() ? blockType->instanceName().c_str() : ""); interfaceBlock.arraySize = variable->getArraySize(); - interfaceBlock.isRowMajorLayout = isRowMajor; - interfaceBlock.layout = sh::GetBlockLayoutType(blockType->blockStorage()); + interfaceBlock.isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor); + interfaceBlock.layout = GetBlockLayoutType(blockType->blockStorage()); - ASSERT(blockType); - const TFieldList &blockFields = blockType->fields(); + // Gather field information + const TFieldList &fieldList = blockType->fields(); - for (size_t fieldIndex = 0; fieldIndex < blockFields.size(); fieldIndex++) + for (size_t fieldIndex = 0; fieldIndex < fieldList.size(); ++fieldIndex) { - const TField *field = blockFields[fieldIndex]; - ASSERT(field); + const TField &field = *fieldList[fieldIndex]; + const TString &fullFieldName = InterfaceBlockFieldName(*blockType, field); + const TType &fieldType = *field.type(); - sh::GetInterfaceBlockFieldTraverser traverser(&interfaceBlock.fields, isRowMajor); - traverser.traverse(*field->type(), field->name()); + GetVariableTraverser traverser; + traverser.traverse(fieldType, fullFieldName, &interfaceBlock.fields); + + interfaceBlock.fields.back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor); } infoList->push_back(interfaceBlock); @@ -290,8 +325,8 @@ template <typename VarT> void CollectVariables::visitVariable(const TIntermSymbol *variable, std::vector<VarT> *infoList) const { - NameHashingTraverser<VarT> traverser(infoList, mHashFunction); - traverser.traverse(variable->getType(), variable->getSymbol()); + NameHashingTraverser traverser(mHashFunction); + traverser.traverse(variable->getType(), variable->getSymbol(), infoList); } template <typename VarT> @@ -320,16 +355,19 @@ bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node) case EOpDeclaration: { const TIntermSequence &sequence = *(node->getSequence()); + ASSERT(!sequence.empty()); + const TIntermTyped &typedNode = *(sequence.front()->getAsTyped()); TQualifier qualifier = typedNode.getQualifier(); if (typedNode.getBasicType() == EbtInterfaceBlock) { visitInfoList(sequence, mInterfaceBlocks); + visitChildren = false; } else if (qualifier == EvqAttribute || qualifier == EvqVertexIn || qualifier == EvqFragmentOut || qualifier == EvqUniform || - sh::IsVarying(qualifier)) + IsVarying(qualifier)) { switch (qualifier) { @@ -348,10 +386,7 @@ bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node) break; } - if (!sequence.empty()) - { - visitChildren = false; - } + visitChildren = false; } break; } @@ -361,15 +396,43 @@ bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node) return visitChildren; } +bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode) +{ + if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock) + { + // NOTE: we do not determine static use for individual blocks of an array + TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped(); + ASSERT(blockNode); + + TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion(); + ASSERT(constantUnion); + + const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock(); + InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks); + ASSERT(namedBlock); + namedBlock->staticUse = true; + + unsigned int fieldIndex = constantUnion->getUConst(0); + ASSERT(fieldIndex < namedBlock->fields.size()); + namedBlock->fields[fieldIndex].staticUse = true; + return false; + } + + return true; +} + template <typename VarT> -void ExpandVariables(const std::vector<VarT> &compact, std::vector<VarT> *expanded) +void ExpandVariables(const std::vector<VarT> &compact, + std::vector<ShaderVariable> *expanded) { for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++) { - const VarT &variable = compact[variableIndex]; + const ShaderVariable &variable = compact[variableIndex]; ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse, expanded); } } -template void ExpandVariables(const std::vector<sh::Uniform> &, std::vector<sh::Uniform> *); -template void ExpandVariables(const std::vector<sh::Varying> &, std::vector<sh::Varying> *); +template void ExpandVariables(const std::vector<Uniform> &, std::vector<ShaderVariable> *); +template void ExpandVariables(const std::vector<Varying> &, std::vector<ShaderVariable> *); + +} diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h index 3771819c8b..5ac4c46baa 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h +++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h @@ -7,22 +7,27 @@ #ifndef COMPILER_VARIABLE_INFO_H_ #define COMPILER_VARIABLE_INFO_H_ -#include "compiler/translator/intermediate.h" -#include "common/shadervars.h" +#include <GLSLANG/ShaderLang.h> + +#include "compiler/translator/IntermNode.h" + +namespace sh +{ // Traverses intermediate tree to collect all attributes, uniforms, varyings. class CollectVariables : public TIntermTraverser { public: - CollectVariables(std::vector<sh::Attribute> *attribs, - std::vector<sh::Attribute> *outputVariables, - std::vector<sh::Uniform> *uniforms, - std::vector<sh::Varying> *varyings, - std::vector<sh::InterfaceBlock> *interfaceBlocks, + CollectVariables(std::vector<Attribute> *attribs, + std::vector<Attribute> *outputVariables, + std::vector<Uniform> *uniforms, + std::vector<Varying> *varyings, + std::vector<InterfaceBlock> *interfaceBlocks, ShHashFunction64 hashFunction); virtual void visitSymbol(TIntermSymbol *symbol); virtual bool visitAggregate(Visit, TIntermAggregate *node); + virtual bool visitBinary(Visit visit, TIntermBinary *binaryNode); private: template <typename VarT> @@ -31,13 +36,13 @@ class CollectVariables : public TIntermTraverser template <typename VarT> void visitInfoList(const TIntermSequence &sequence, std::vector<VarT> *infoList) const; - std::vector<sh::Attribute> *mAttribs; - std::vector<sh::Attribute> *mOutputVariables; - std::vector<sh::Uniform> *mUniforms; - std::vector<sh::Varying> *mVaryings; - std::vector<sh::InterfaceBlock> *mInterfaceBlocks; + std::vector<Attribute> *mAttribs; + std::vector<Attribute> *mOutputVariables; + std::vector<Uniform> *mUniforms; + std::vector<Varying> *mVaryings; + std::vector<InterfaceBlock> *mInterfaceBlocks; - std::map<std::string, sh::InterfaceBlockField *> mInterfaceBlockFields; + std::map<std::string, InterfaceBlockField *> mInterfaceBlockFields; bool mPointCoordAdded; bool mFrontFacingAdded; @@ -47,8 +52,10 @@ class CollectVariables : public TIntermTraverser }; // Expand struct variables to flattened lists of split variables -// Implemented for sh::Varying and sh::Uniform. template <typename VarT> -void ExpandVariables(const std::vector<VarT> &compact, std::vector<VarT> *expanded); +void ExpandVariables(const std::vector<VarT> &compact, + std::vector<ShaderVariable> *expanded); + +} #endif // COMPILER_VARIABLE_INFO_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp b/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp index faaf0115fc..e69052162a 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp @@ -3,12 +3,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -#include "compiler/translator/VariablePacker.h" -#include "angle_gl.h" -#include "common/utilities.h" #include <algorithm> +#include "angle_gl.h" + +#include "compiler/translator/VariablePacker.h" +#include "common/utilities.h" + int VariablePacker::GetNumComponentsPerRow(sh::GLenum type) { switch (type) diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp index 12dc9e0dad..8edbd009b0 100644 --- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp @@ -67,6 +67,9 @@ bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate *node) } break; } + case EOpInvariantDeclaration: + updateVersion(GLSL_VERSION_120); + break; case EOpParameters: { const TIntermSequence ¶ms = *(node->getSequence()); diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h index de4141d38c..30f5a138a0 100644 --- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h @@ -7,7 +7,7 @@ #ifndef COMPILER_TRANSLATOR_VERSIONGLSL_H_ #define COMPILER_TRANSLATOR_VERSIONGLSL_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // Traverses the intermediate tree to return the minimum GLSL version // required to legally access all built-in features used in the shader. diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h index 5ea1cbb837..bc25fe7cbc 100644 --- a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h @@ -7,7 +7,7 @@ #ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H #define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include <set> #include <stack> diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.y b/src/3rdparty/angle/src/compiler/translator/glslang.y index fb2d835368..5c945ad5ad 100644 --- a/src/3rdparty/angle/src/compiler/translator/glslang.y +++ b/src/3rdparty/angle/src/compiler/translator/glslang.y @@ -209,38 +209,7 @@ identifier variable_identifier : IDENTIFIER { // The symbol table search was done in the lexical phase - const TSymbol *symbol = $1.symbol; - const TVariable *variable = 0; - - if (!symbol) - { - context->error(@1, "undeclared identifier", $1.string->c_str()); - context->recover(); - } - else if (!symbol->isVariable()) - { - context->error(@1, "variable expected", $1.string->c_str()); - context->recover(); - } - else - { - variable = static_cast<const TVariable*>(symbol); - - if (context->symbolTable.findBuiltIn(variable->getName(), context->shaderVersion) && - !variable->getExtension().empty() && - context->extensionErrorCheck(@1, variable->getExtension())) - { - context->recover(); - } - } - - if (!variable) - { - TType type(EbtFloat, EbpUndefined); - TVariable *fakeVariable = new TVariable($1.string, type); - context->symbolTable.declare(fakeVariable); - variable = fakeVariable; - } + const TVariable *variable = context->getNamedVariable(@1, $1.string, $1.symbol); if (variable->getType().getQualifier() == EvqConst) { @@ -816,9 +785,10 @@ declaration context->symbolTable.pop(); } | init_declarator_list SEMICOLON { - if ($1.intermAggregate) - $1.intermAggregate->setOp(EOpDeclaration); - $$ = $1.intermAggregate; + TIntermAggregate *aggNode = $1.intermAggregate; + if (aggNode && aggNode->getOp() == EOpNull) + aggNode->setOp(EOpDeclaration); + $$ = aggNode; } | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON { if (($2 == EbpHigh) && (context->shaderType == GL_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) { @@ -1102,22 +1072,8 @@ single_declaration $$.intermAggregate = context->parseSingleInitDeclaration($$.type, @2, *$2.string, @3, $4); } | INVARIANT IDENTIFIER { - VERTEX_ONLY("invariant declaration", @1); - if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying")) - context->recover(); - $$.type.setBasic(EbtInvariant, EvqInvariantVaryingOut, @2); - if (!$2.symbol) - { - 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); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); - } + // $$.type is not used in invariant declarations. + $$.intermAggregate = context->parseInvariantDeclaration(@1, @2, $2.string, $2.symbol); } ; diff --git a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp index a6e7ab41a6..56340c6f9e 100644 --- a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp +++ b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/localintermediate.h" +#include "compiler/translator/Intermediate.h" #include "compiler/translator/SymbolTable.h" namespace @@ -342,6 +342,7 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) case EOpMul: out << "component-wise multiply"; break; case EOpDeclaration: out << "Declaration: "; break; + case EOpInvariantDeclaration: out << "Invariant Declaration: "; break; default: out.prefix(EPrefixError); diff --git a/src/3rdparty/angle/src/compiler/translator/intermediate.h b/src/3rdparty/angle/src/compiler/translator/intermediate.h index 892f2849e0..3b7e7bd802 100644 --- a/src/3rdparty/angle/src/compiler/translator/intermediate.h +++ b/src/3rdparty/angle/src/compiler/translator/intermediate.h @@ -4,768 +4,64 @@ // found in the LICENSE file. // -// -// Definition of the in-memory high-level intermediate representation -// of shaders. This is a tree that parser creates. -// -// Nodes in the tree are defined as a hierarchy of classes derived from -// TIntermNode. Each is a node in a tree. There is no preset branching factor; -// each node can have it's own type of list of children. -// - -#ifndef COMPILER_TRANSLATOR_INTERMEDIATE_H_ -#define COMPILER_TRANSLATOR_INTERMEDIATE_H_ - -#include "GLSLANG/ShaderLang.h" - -#include <algorithm> -#include <queue> - -#include "compiler/translator/Common.h" -#include "compiler/translator/Types.h" -#include "compiler/translator/ConstantUnion.h" - -// -// Operators used by the high-level (parse tree) representation. -// -enum TOperator -{ - EOpNull, // if in a node, should only mean a node is still being built - EOpSequence, // denotes a list of statements, or parameters, etc. - EOpFunctionCall, - EOpFunction, // For function definition - EOpParameters, // an aggregate listing the parameters to a function - - EOpDeclaration, - EOpPrototype, - - // - // Unary operators - // - - EOpNegative, - EOpLogicalNot, - EOpVectorLogicalNot, - - EOpPostIncrement, - EOpPostDecrement, - EOpPreIncrement, - EOpPreDecrement, - - // - // binary operations - // - - EOpAdd, - EOpSub, - EOpMul, - EOpDiv, - EOpEqual, - EOpNotEqual, - EOpVectorEqual, - EOpVectorNotEqual, - EOpLessThan, - EOpGreaterThan, - EOpLessThanEqual, - EOpGreaterThanEqual, - EOpComma, - - EOpVectorTimesScalar, - EOpVectorTimesMatrix, - EOpMatrixTimesVector, - EOpMatrixTimesScalar, - - EOpLogicalOr, - EOpLogicalXor, - EOpLogicalAnd, - - EOpIndexDirect, - EOpIndexIndirect, - EOpIndexDirectStruct, - EOpIndexDirectInterfaceBlock, - - EOpVectorSwizzle, - - // - // Built-in functions potentially mapped to operators - // - - EOpRadians, - EOpDegrees, - EOpSin, - EOpCos, - EOpTan, - EOpAsin, - EOpAcos, - EOpAtan, - - EOpPow, - EOpExp, - EOpLog, - EOpExp2, - EOpLog2, - EOpSqrt, - EOpInverseSqrt, - - EOpAbs, - EOpSign, - EOpFloor, - EOpCeil, - EOpFract, - EOpMod, - EOpMin, - EOpMax, - EOpClamp, - EOpMix, - EOpStep, - EOpSmoothStep, - - EOpLength, - EOpDistance, - EOpDot, - EOpCross, - EOpNormalize, - EOpFaceForward, - EOpReflect, - EOpRefract, - - EOpDFdx, // Fragment only, OES_standard_derivatives extension - EOpDFdy, // Fragment only, OES_standard_derivatives extension - EOpFwidth, // Fragment only, OES_standard_derivatives extension - - EOpMatrixTimesMatrix, - - EOpAny, - EOpAll, - - // - // Branch - // - - EOpKill, // Fragment only - EOpReturn, - EOpBreak, - EOpContinue, - - // - // Constructors - // - - EOpConstructInt, - EOpConstructUInt, - EOpConstructBool, - EOpConstructFloat, - EOpConstructVec2, - EOpConstructVec3, - EOpConstructVec4, - EOpConstructBVec2, - EOpConstructBVec3, - EOpConstructBVec4, - EOpConstructIVec2, - EOpConstructIVec3, - EOpConstructIVec4, - EOpConstructUVec2, - EOpConstructUVec3, - EOpConstructUVec4, - EOpConstructMat2, - EOpConstructMat3, - EOpConstructMat4, - EOpConstructStruct, - - // - // moves - // - - EOpAssign, - EOpInitialize, - EOpAddAssign, - EOpSubAssign, - EOpMulAssign, - EOpVectorTimesMatrixAssign, - EOpVectorTimesScalarAssign, - EOpMatrixTimesScalarAssign, - EOpMatrixTimesMatrixAssign, - EOpDivAssign -}; - -class TIntermTraverser; -class TIntermAggregate; -class TIntermBinary; -class TIntermUnary; -class TIntermConstantUnion; -class TIntermSelection; -class TIntermTyped; -class TIntermSymbol; -class TIntermLoop; -class TInfoSink; -class TIntermRaw; - -// -// Base class for the tree nodes -// -class TIntermNode -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TIntermNode() - { - // TODO: Move this to TSourceLoc constructor - // after getting rid of TPublicType. - mLine.first_file = mLine.last_file = 0; - mLine.first_line = mLine.last_line = 0; - } - virtual ~TIntermNode() { } - - const TSourceLoc &getLine() const { return mLine; } - void setLine(const TSourceLoc &l) { mLine = l; } - - virtual void traverse(TIntermTraverser *) = 0; - virtual TIntermTyped *getAsTyped() { return 0; } - virtual TIntermConstantUnion *getAsConstantUnion() { return 0; } - virtual TIntermAggregate *getAsAggregate() { return 0; } - virtual TIntermBinary *getAsBinaryNode() { return 0; } - virtual TIntermUnary *getAsUnaryNode() { return 0; } - virtual TIntermSelection *getAsSelectionNode() { return 0; } - virtual TIntermSymbol *getAsSymbolNode() { return 0; } - virtual TIntermLoop *getAsLoopNode() { return 0; } - virtual TIntermRaw *getAsRawNode() { return 0; } - - // Replace a child node. Return true if |original| is a child - // node and it is replaced; otherwise, return false. - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement) = 0; - - // For traversing a tree in no particular order, but using - // heap memory. - virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const = 0; - - protected: - TSourceLoc mLine; -}; - -// -// This is just to help yacc. -// -struct TIntermNodePair -{ - TIntermNode *node1; - TIntermNode *node2; -}; - -// -// Intermediate class for nodes that have a type. -// -class TIntermTyped : public TIntermNode -{ - public: - TIntermTyped(const TType &t) : mType(t) { } - virtual TIntermTyped *getAsTyped() { return this; } +#ifndef COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ +#define COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ - virtual bool hasSideEffects() const = 0; +#include "compiler/translator/IntermNode.h" - void setType(const TType &t) { mType = t; } - const TType &getType() const { return mType; } - TType *getTypePointer() { return &mType; } - - TBasicType getBasicType() const { return mType.getBasicType(); } - TQualifier getQualifier() const { return mType.getQualifier(); } - TPrecision getPrecision() const { return mType.getPrecision(); } - int getCols() const { return mType.getCols(); } - int getRows() const { return mType.getRows(); } - int getNominalSize() const { return mType.getNominalSize(); } - int getSecondarySize() const { return mType.getSecondarySize(); } - - bool isInterfaceBlock() const { return mType.isInterfaceBlock(); } - bool isMatrix() const { return mType.isMatrix(); } - bool isArray() const { return mType.isArray(); } - bool isVector() const { return mType.isVector(); } - bool isScalar() const { return mType.isScalar(); } - bool isScalarInt() const { return mType.isScalarInt(); } - const char *getBasicString() const { return mType.getBasicString(); } - const char *getQualifierString() const { return mType.getQualifierString(); } - TString getCompleteString() const { return mType.getCompleteString(); } - - int getArraySize() const { return mType.getArraySize(); } - - protected: - TType mType; -}; - -// -// Handle for, do-while, and while loops. -// -enum TLoopType +struct TVectorFields { - ELoopFor, - ELoopWhile, - ELoopDoWhile -}; - -class TIntermLoop : public TIntermNode -{ - public: - TIntermLoop(TLoopType type, - TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr, - TIntermNode *body) - : mType(type), - mInit(init), - mCond(cond), - mExpr(expr), - mBody(body), - mUnrollFlag(false) { } - - virtual TIntermLoop *getAsLoopNode() { return this; } - virtual void traverse(TIntermTraverser *); - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - TLoopType getType() const { return mType; } - TIntermNode *getInit() { return mInit; } - TIntermTyped *getCondition() { return mCond; } - TIntermTyped *getExpression() { return mExpr; } - TIntermNode *getBody() { return mBody; } - - void setUnrollFlag(bool flag) { mUnrollFlag = flag; } - bool getUnrollFlag() const { return mUnrollFlag; } - - virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const; - - protected: - TLoopType mType; - TIntermNode *mInit; // for-loop initialization - TIntermTyped *mCond; // loop exit condition - TIntermTyped *mExpr; // for-loop expression - TIntermNode *mBody; // loop body - - bool mUnrollFlag; // Whether the loop should be unrolled or not. + int offsets[4]; + int num; }; // -// Handle break, continue, return, and kill. +// Set of helper functions to help parse and build the tree. // -class TIntermBranch : public TIntermNode -{ - public: - TIntermBranch(TOperator op, TIntermTyped *e) - : mFlowOp(op), - mExpression(e) { } - - virtual void traverse(TIntermTraverser *); - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - TOperator getFlowOp() { return mFlowOp; } - TIntermTyped* getExpression() { return mExpression; } - - virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const; - -protected: - TOperator mFlowOp; - TIntermTyped *mExpression; // non-zero except for "return exp;" statements -}; - -// -// Nodes that correspond to symbols or constants in the source code. -// -class TIntermSymbol : public TIntermTyped -{ - public: - // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. - // If sym comes from per process globalpoolallocator, then it causes increased memory usage - // per compile it is essential to use "symbol = sym" to assign to symbol - TIntermSymbol(int id, const TString &symbol, const TType &type) - : TIntermTyped(type), - mId(id) - { - mSymbol = symbol; - } - - virtual bool hasSideEffects() const { return false; } - - int getId() const { return mId; } - const TString &getSymbol() const { return mSymbol; } - - void setId(int newId) { mId = newId; } - - virtual void traverse(TIntermTraverser *); - virtual TIntermSymbol *getAsSymbolNode() { return this; } - virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } - - virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {} - - protected: - int mId; - TString mSymbol; -}; - -// A Raw node stores raw code, that the translator will insert verbatim -// into the output stream. Useful for transformation operations that make -// complex code that might not fit naturally into the GLSL model. -class TIntermRaw : public TIntermTyped -{ - public: - TIntermRaw(const TType &type, const TString &rawText) - : TIntermTyped(type), - mRawText(rawText) { } - - virtual bool hasSideEffects() const { return false; } - - TString getRawText() const { return mRawText; } - - virtual void traverse(TIntermTraverser *); - - virtual TIntermRaw *getAsRawNode() { return this; } - virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } - virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {} - - protected: - TString mRawText; -}; - -class TIntermConstantUnion : public TIntermTyped -{ - public: - TIntermConstantUnion(ConstantUnion *unionPointer, const TType &type) - : TIntermTyped(type), - mUnionArrayPointer(unionPointer) { } - - virtual bool hasSideEffects() const { return false; } - - ConstantUnion *getUnionArrayPointer() const { return mUnionArrayPointer; } - - int getIConst(size_t index) const - { - return mUnionArrayPointer ? mUnionArrayPointer[index].getIConst() : 0; - } - unsigned int getUConst(size_t index) const - { - return mUnionArrayPointer ? mUnionArrayPointer[index].getUConst() : 0; - } - float getFConst(size_t index) const - { - return mUnionArrayPointer ? mUnionArrayPointer[index].getFConst() : 0.0f; - } - bool getBConst(size_t index) const - { - return mUnionArrayPointer ? mUnionArrayPointer[index].getBConst() : false; - } - - virtual TIntermConstantUnion *getAsConstantUnion() { return this; } - virtual void traverse(TIntermTraverser *); - virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } - - TIntermTyped *fold(TOperator, TIntermTyped *, TInfoSink &); - - virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {} - - protected: - ConstantUnion *mUnionArrayPointer; -}; - -// -// Intermediate class for node types that hold operators. -// -class TIntermOperator : public TIntermTyped -{ - public: - TOperator getOp() const { return mOp; } - void setOp(TOperator op) { mOp = op; } - - bool isAssignment() const; - bool isConstructor() const; - - virtual bool hasSideEffects() const { return isAssignment(); } - - protected: - TIntermOperator(TOperator op) - : TIntermTyped(TType(EbtFloat, EbpUndefined)), - mOp(op) {} - TIntermOperator(TOperator op, const TType &type) - : TIntermTyped(type), - mOp(op) {} - - TOperator mOp; -}; - -// -// Nodes for all the basic binary math operators. -// -class TIntermBinary : public TIntermOperator -{ - public: - TIntermBinary(TOperator op) - : TIntermOperator(op), - mAddIndexClamp(false) {} - - virtual TIntermBinary *getAsBinaryNode() { return this; } - virtual void traverse(TIntermTraverser *); - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - virtual bool hasSideEffects() const - { - return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects(); - } - - void setLeft(TIntermTyped *node) { mLeft = node; } - void setRight(TIntermTyped *node) { mRight = node; } - TIntermTyped *getLeft() const { return mLeft; } - TIntermTyped *getRight() const { return mRight; } - bool promote(TInfoSink &); - - void setAddIndexClamp() { mAddIndexClamp = true; } - bool getAddIndexClamp() { return mAddIndexClamp; } - - virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const; - - protected: - TIntermTyped* mLeft; - TIntermTyped* mRight; - - // If set to true, wrap any EOpIndexIndirect with a clamp to bounds. - bool mAddIndexClamp; -}; - -// -// Nodes for unary math operators. -// -class TIntermUnary : public TIntermOperator -{ - public: - TIntermUnary(TOperator op, const TType &type) - : TIntermOperator(op, type), - mOperand(NULL), - mUseEmulatedFunction(false) {} - TIntermUnary(TOperator op) - : TIntermOperator(op), - mOperand(NULL), - mUseEmulatedFunction(false) {} - - virtual void traverse(TIntermTraverser *); - virtual TIntermUnary *getAsUnaryNode() { return this; } - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - virtual bool hasSideEffects() const - { - return isAssignment() || mOperand->hasSideEffects(); - } - - void setOperand(TIntermTyped *operand) { mOperand = operand; } - TIntermTyped *getOperand() { return mOperand; } - bool promote(TInfoSink &); - - void setUseEmulatedFunction() { mUseEmulatedFunction = true; } - bool getUseEmulatedFunction() { return mUseEmulatedFunction; } - - virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const; - - protected: - TIntermTyped *mOperand; - - // If set to true, replace the built-in function call with an emulated one - // to work around driver bugs. - bool mUseEmulatedFunction; -}; - -typedef TVector<TIntermNode *> TIntermSequence; -typedef TVector<int> TQualifierList; - -// -// Nodes that operate on an arbitrary sized set of children. -// -class TIntermAggregate : public TIntermOperator -{ - public: - TIntermAggregate() - : TIntermOperator(EOpNull), - mUserDefined(false), - mUseEmulatedFunction(false) { } - TIntermAggregate(TOperator op) - : TIntermOperator(op), - mUseEmulatedFunction(false) { } - ~TIntermAggregate() { } - - virtual TIntermAggregate *getAsAggregate() { return this; } - virtual void traverse(TIntermTraverser *); - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - // Conservatively assume function calls and other aggregate operators have side-effects - virtual bool hasSideEffects() const { return true; } - - TIntermSequence *getSequence() { return &mSequence; } - - void setName(const TString &name) { mName = name; } - const TString &getName() const { return mName; } - - void setUserDefined() { mUserDefined = true; } - bool isUserDefined() const { return mUserDefined; } - - void setOptimize(bool optimize) { mOptimize = optimize; } - bool getOptimize() const { return mOptimize; } - void setDebug(bool debug) { mDebug = debug; } - bool getDebug() const { return mDebug; } - - void setUseEmulatedFunction() { mUseEmulatedFunction = true; } - bool getUseEmulatedFunction() { return mUseEmulatedFunction; } - - virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const; - - protected: - TIntermAggregate(const TIntermAggregate &); // disallow copy constructor - TIntermAggregate &operator=(const TIntermAggregate &); // disallow assignment operator - TIntermSequence mSequence; - TString mName; - bool mUserDefined; // used for user defined function names - - bool mOptimize; - bool mDebug; - - // If set to true, replace the built-in function call with an emulated one - // to work around driver bugs. - bool mUseEmulatedFunction; -}; - -// -// For if tests. Simplified since there is no switch statement. -// -class TIntermSelection : public TIntermTyped -{ - public: - TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB) - : TIntermTyped(TType(EbtVoid, EbpUndefined)), - mCondition(cond), - mTrueBlock(trueB), - mFalseBlock(falseB) {} - TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB, - const TType &type) - : TIntermTyped(type), - mCondition(cond), - mTrueBlock(trueB), - mFalseBlock(falseB) {} - - virtual void traverse(TIntermTraverser *); - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - // Conservatively assume selections have side-effects - virtual bool hasSideEffects() const { return true; } - - bool usesTernaryOperator() const { return getBasicType() != EbtVoid; } - TIntermNode *getCondition() const { return mCondition; } - TIntermNode *getTrueBlock() const { return mTrueBlock; } - TIntermNode *getFalseBlock() const { return mFalseBlock; } - TIntermSelection *getAsSelectionNode() { return this; } - - virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const; - -protected: - TIntermTyped *mCondition; - TIntermNode *mTrueBlock; - TIntermNode *mFalseBlock; -}; - -enum Visit -{ - PreVisit, - InVisit, - PostVisit -}; - -// -// For traversing the tree. User should derive from this, -// put their traversal specific data in it, and then pass -// it to a Traverse method. -// -// When using this, just fill in the methods for nodes you want visited. -// Return false from a pre-visit to skip visiting that node's subtree. -// -class TIntermTraverser -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - // TODO(zmo): remove default values. - TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, - bool rightToLeft = false) - : preVisit(preVisit), - inVisit(inVisit), - postVisit(postVisit), - rightToLeft(rightToLeft), - mDepth(0), - mMaxDepth(0) {} - virtual ~TIntermTraverser() {} - - virtual void visitSymbol(TIntermSymbol *) {} - virtual void visitRaw(TIntermRaw *) {} - virtual void visitConstantUnion(TIntermConstantUnion *) {} - virtual bool visitBinary(Visit, TIntermBinary *) { return true; } - virtual bool visitUnary(Visit, TIntermUnary *) { return true; } - virtual bool visitSelection(Visit, TIntermSelection *) { return true; } - virtual bool visitAggregate(Visit, TIntermAggregate *) { return true; } - virtual bool visitLoop(Visit, TIntermLoop *) { return true; } - virtual bool visitBranch(Visit, TIntermBranch *) { return true; } - - int getMaxDepth() const { return mMaxDepth; } - - void incrementDepth(TIntermNode *current) - { - mDepth++; - mMaxDepth = std::max(mMaxDepth, mDepth); - mPath.push_back(current); - } - - void decrementDepth() - { - mDepth--; - mPath.pop_back(); - } - - TIntermNode *getParentNode() - { - return mPath.size() == 0 ? NULL : mPath.back(); - } - - // Return the original name if hash function pointer is NULL; - // otherwise return the hashed name. - static TString hash(const TString& name, ShHashFunction64 hashFunction); - - const bool preVisit; - const bool inVisit; - const bool postVisit; - const bool rightToLeft; - - protected: - int mDepth; - int mMaxDepth; - - // All the nodes from root to the current node's parent during traversing. - TVector<TIntermNode *> mPath; -}; - -// -// For traversing the tree, and computing max depth. -// Takes a maximum depth limit to prevent stack overflow. -// -class TMaxDepthTraverser : public TIntermTraverser +class TInfoSink; +class TIntermediate { public: POOL_ALLOCATOR_NEW_DELETE(); - TMaxDepthTraverser(int depthLimit) - : TIntermTraverser(true, true, false, false), - mDepthLimit(depthLimit) { } - - virtual bool visitBinary(Visit, TIntermBinary *) { return depthCheck(); } - virtual bool visitUnary(Visit, TIntermUnary *) { return depthCheck(); } - virtual bool visitSelection(Visit, TIntermSelection *) { return depthCheck(); } - virtual bool visitAggregate(Visit, TIntermAggregate *) { return depthCheck(); } - virtual bool visitLoop(Visit, TIntermLoop *) { return depthCheck(); } - virtual bool visitBranch(Visit, TIntermBranch *) { return depthCheck(); } - -protected: - bool depthCheck() const { return mMaxDepth < mDepthLimit; } - - int mDepthLimit; -}; - -#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_ + TIntermediate(TInfoSink &i) + : mInfoSink(i) { } + + TIntermSymbol *addSymbol( + int id, const TString &, const TType &, const TSourceLoc &); + TIntermTyped *addBinaryMath( + TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &); + 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 &); + 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 &); + // TODO(zmo): Get rid of default value. + bool parseConstTree(const TSourceLoc &, TIntermNode *, ConstantUnion *, + TOperator, TType, bool singleConstantParam = false); + TIntermNode *addLoop(TLoopType, TIntermNode *, TIntermTyped *, TIntermTyped *, + TIntermNode *, const TSourceLoc &); + TIntermBranch *addBranch(TOperator, const TSourceLoc &); + TIntermBranch *addBranch(TOperator, TIntermTyped *, const TSourceLoc &); + TIntermTyped *addSwizzle(TVectorFields &, const TSourceLoc &); + bool postProcess(TIntermNode *); + void remove(TIntermNode *); + void outputTree(TIntermNode *); + + private: + void operator=(TIntermediate &); // prevent assignments + + TInfoSink & mInfoSink; +}; + +#endif // COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/localintermediate.h b/src/3rdparty/angle/src/compiler/translator/localintermediate.h deleted file mode 100644 index 0809bbd362..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/localintermediate.h +++ /dev/null @@ -1,67 +0,0 @@ -// -// Copyright (c) 2002-2014 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_TRANSLATOR_LOCAL_INTERMEDIATE_H_ -#define COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ - -#include "compiler/translator/intermediate.h" - -struct TVectorFields -{ - int offsets[4]; - int num; -}; - -// -// Set of helper functions to help parse and build the tree. -// -class TInfoSink; -class TIntermediate -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TIntermediate(TInfoSink &i) - : mInfoSink(i) { } - - TIntermSymbol *addSymbol( - int id, const TString &, const TType &, const TSourceLoc &); - TIntermTyped *addBinaryMath( - TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &); - 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 &); - 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 &); - // TODO(zmo): Get rid of default value. - bool parseConstTree(const TSourceLoc &, TIntermNode *, ConstantUnion *, - TOperator, TType, bool singleConstantParam = false); - TIntermNode *addLoop(TLoopType, TIntermNode *, TIntermTyped *, TIntermTyped *, - TIntermNode *, const TSourceLoc &); - TIntermBranch *addBranch(TOperator, const TSourceLoc &); - TIntermBranch *addBranch(TOperator, TIntermTyped *, const TSourceLoc &); - TIntermTyped *addSwizzle(TVectorFields &, const TSourceLoc &); - bool postProcess(TIntermNode *); - void remove(TIntermNode *); - void outputTree(TIntermNode *); - - private: - void operator=(TIntermediate &); // prevent assignments - - TInfoSink & mInfoSink; -}; - -#endif // COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h index e77d8c21cb..80d5f7fa7f 100644 --- a/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h +++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h @@ -7,7 +7,7 @@ #ifndef COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_ #define COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/depgraph/DependencyGraph.h" class TInfoSinkBase; diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h index d461fbdbfe..a6263567b4 100644 --- a/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h +++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h @@ -7,7 +7,7 @@ #ifndef COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_ #define COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/InfoSink.h" class TInfoSinkBase; diff --git a/src/3rdparty/angle/src/compiler/translator/util.cpp b/src/3rdparty/angle/src/compiler/translator/util.cpp index 561d4e007c..f74c7d1173 100644 --- a/src/3rdparty/angle/src/compiler/translator/util.cpp +++ b/src/3rdparty/angle/src/compiler/translator/util.cpp @@ -9,7 +9,6 @@ #include <limits> #include "compiler/preprocessor/numeric_lex.h" -#include "common/shadervars.h" #include "common/utilities.h" bool atof_clamp(const char *str, float *value) @@ -269,6 +268,8 @@ InterpolationType GetInterpolationType(TQualifier qualifier) case EvqFragmentIn: case EvqVaryingIn: case EvqVaryingOut: + case EvqInvariantVaryingIn: + case EvqInvariantVaryingOut: return INTERPOLATION_SMOOTH; case EvqCentroidIn: @@ -281,7 +282,7 @@ InterpolationType GetInterpolationType(TQualifier qualifier) } template <typename VarT> -void GetVariableTraverser<VarT>::traverse(const TType &type, const TString &name) +void GetVariableTraverser::traverse(const TType &type, const TString &name, std::vector<VarT> *output) { const TStructure *structure = type.getStruct(); @@ -296,61 +297,27 @@ void GetVariableTraverser<VarT>::traverse(const TType &type, const TString &name } else { + // Note: this enum value is not exposed outside ANGLE variable.type = GL_STRUCT_ANGLEX; - - mOutputStack.push(&variable.fields); + variable.structName = structure->name().c_str(); const TFieldList &fields = structure->fields(); for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) { TField *field = fields[fieldIndex]; - traverse(*field->type(), field->name()); + traverse(*field->type(), field->name(), &variable.fields); } - - mOutputStack.pop(); } visitVariable(&variable); - ASSERT(!mOutputStack.empty()); - mOutputStack.top()->push_back(variable); -} - -template <typename VarT> -GetVariableTraverser<VarT>::GetVariableTraverser(std::vector<VarT> *output) -{ ASSERT(output); - mOutputStack.push(output); + output->push_back(variable); } -template class GetVariableTraverser<Uniform>; -template class GetVariableTraverser<Varying>; -template class GetVariableTraverser<InterfaceBlockField>; - -GetInterfaceBlockFieldTraverser::GetInterfaceBlockFieldTraverser(std::vector<InterfaceBlockField> *output, bool isRowMajorMatrix) - : GetVariableTraverser(output), - mIsRowMajorMatrix(isRowMajorMatrix) -{ -} - -void GetInterfaceBlockFieldTraverser::visitVariable(InterfaceBlockField *newField) -{ - if (gl::IsMatrixType(newField->type)) - { - newField->isRowMajorMatrix = mIsRowMajorMatrix; - } -} - -BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage) -{ - switch (blockStorage) - { - case EbsPacked: return BLOCKLAYOUT_PACKED; - case EbsShared: return BLOCKLAYOUT_SHARED; - case EbsStd140: return BLOCKLAYOUT_STANDARD; - default: UNREACHABLE(); return BLOCKLAYOUT_SHARED; - } -} +template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Uniform> *); +template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Varying> *); +template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<InterfaceBlockField> *); } diff --git a/src/3rdparty/angle/src/compiler/translator/util.h b/src/3rdparty/angle/src/compiler/translator/util.h index 5c214dd4fb..241e2cc1c2 100644 --- a/src/3rdparty/angle/src/compiler/translator/util.h +++ b/src/3rdparty/angle/src/compiler/translator/util.h @@ -9,9 +9,10 @@ #include <stack> -#include "compiler/translator/Types.h" #include "angle_gl.h" -#include "common/shadervars.h" +#include <GLSLANG/ShaderLang.h> + +#include "compiler/translator/Types.h" // atof_clamp is like atof but // 1. it forces C locale, i.e. forcing '.' as decimal point. @@ -32,33 +33,22 @@ bool IsVaryingIn(TQualifier qualifier); bool IsVaryingOut(TQualifier qualifier); bool IsVarying(TQualifier qualifier); InterpolationType GetInterpolationType(TQualifier qualifier); -BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage); TString ArrayString(const TType &type); -template <typename VarT> class GetVariableTraverser { public: - GetVariableTraverser(std::vector<VarT> *output); - void traverse(const TType &type, const TString &name); + GetVariableTraverser() {} + + template <typename VarT> + void traverse(const TType &type, const TString &name, std::vector<VarT> *output); protected: // May be overloaded - virtual void visitVariable(VarT *newVar) {} + virtual void visitVariable(ShaderVariable *newVar) {} private: - std::stack<std::vector<VarT> *> mOutputStack; -}; - -struct GetInterfaceBlockFieldTraverser : public GetVariableTraverser<InterfaceBlockField> -{ - public: - GetInterfaceBlockFieldTraverser(std::vector<InterfaceBlockField> *output, bool isRowMajorMatrix); - - private: - virtual void visitVariable(InterfaceBlockField *newField); - - bool mIsRowMajorMatrix; + DISALLOW_COPY_AND_ASSIGN(GetVariableTraverser); }; } diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp index 7cd83c3db4..5a50e4baf5 100644 --- a/src/3rdparty/angle/src/libEGL/Display.cpp +++ b/src/3rdparty/angle/src/libEGL/Display.cpp @@ -561,8 +561,10 @@ void Display::initDisplayExtensionString() extensions.push_back("EGL_NV_post_sub_buffer"); } +#if defined (ANGLE_TEST_CONFIG) // TODO: complete support for the EGL_KHR_create_context extension - //extensions.push_back("EGL_KHR_create_context"); + extensions.push_back("EGL_KHR_create_context"); +#endif std::ostringstream stream; std::copy(extensions.begin(), extensions.end(), std::ostream_iterator<std::string>(stream, " ")); @@ -606,6 +608,7 @@ void Display::initVendorString() { char adapterLuidString[64]; snprintf(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart); + mVendorString += adapterLuidString; } } diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp index c236d52a4f..c2e0fd6d3d 100644 --- a/src/3rdparty/angle/src/libEGL/libEGL.cpp +++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp @@ -6,6 +6,9 @@ // libEGL.cpp: Implements the exported EGL functions. +#undef EGLAPI +#define EGLAPI + #include <exception> #include "common/debug.h" @@ -825,12 +828,19 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface egl::Display *display = static_cast<egl::Display*>(dpy); gl::Context *context = static_cast<gl::Context*>(ctx); + bool noContext = (ctx == EGL_NO_CONTEXT); + bool noSurface = (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE); + if (noContext != noSurface) + { + return egl::error(EGL_BAD_MATCH, EGL_FALSE); + } + if (ctx != EGL_NO_CONTEXT && !validateContext(display, context)) { return EGL_FALSE; } - if (dpy != EGL_NO_DISPLAY) + if (dpy != EGL_NO_DISPLAY && display->isInitialized()) { rx::Renderer *renderer = display->getRenderer(); if (renderer->testDeviceLost(true)) diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp index 5788af7827..e74737eaba 100644 --- a/src/3rdparty/angle/src/libEGL/main.cpp +++ b/src/3rdparty/angle/src/libEGL/main.cpp @@ -105,15 +105,15 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved break; case DLL_THREAD_DETACH: { +#if !defined(ANGLE_PLATFORM_WINRT) egl::DeallocateCurrent(); +#endif } break; case DLL_PROCESS_DETACH: { -#if !defined(ANGLE_PLATFORM_WINRT) egl::DeallocateCurrent(); DestroyTLSIndex(currentTLS); -#endif } break; default: diff --git a/src/3rdparty/angle/src/libEGL/main.h b/src/3rdparty/angle/src/libEGL/main.h index 6030fb6ad9..07f5b9e675 100644 --- a/src/3rdparty/angle/src/libEGL/main.h +++ b/src/3rdparty/angle/src/libEGL/main.h @@ -9,8 +9,6 @@ #ifndef LIBEGL_MAIN_H_ #define LIBEGL_MAIN_H_ -#undef EGLAPI -#define EGLAPI #include <EGL/egl.h> #include <EGL/eglext.h> diff --git a/src/3rdparty/angle/src/libGLESv2/BinaryStream.h b/src/3rdparty/angle/src/libGLESv2/BinaryStream.h index 1cbfc6751d..4d7dde04e1 100644 --- a/src/3rdparty/angle/src/libGLESv2/BinaryStream.h +++ b/src/3rdparty/angle/src/libGLESv2/BinaryStream.h @@ -12,6 +12,10 @@ #include "common/angleutils.h" #include "common/mathutil.h" +#include <cstddef> +#include <string> +#include <vector> + namespace gl { diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp b/src/3rdparty/angle/src/libGLESv2/Buffer.cpp index a47b8f402f..3b2a1a912a 100644 --- a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Buffer.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -31,59 +30,99 @@ Buffer::Buffer(rx::BufferImpl *impl, GLuint id) Buffer::~Buffer() { - delete mBuffer; + SafeDelete(mBuffer); } -void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage) +Error Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage) { + gl::Error error = mBuffer->setData(data, size, usage); + if (error.isError()) + { + return error; + } + + mIndexRangeCache.clear(); mUsage = usage; mSize = size; - mBuffer->setData(data, size, usage); + + return error; } -void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset) +Error Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset) { - mBuffer->setSubData(data, size, offset); + gl::Error error = mBuffer->setSubData(data, size, offset); + if (error.isError()) + { + return error; + } + + mIndexRangeCache.invalidateRange(offset, size); + + return error; } -void Buffer::copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) +Error Buffer::copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) { - mBuffer->copySubData(source->getImplementation(), size, sourceOffset, destOffset); + gl::Error error = mBuffer->copySubData(source->getImplementation(), sourceOffset, destOffset, size); + if (error.isError()) + { + return error; + } + + mIndexRangeCache.invalidateRange(destOffset, size); + + return error; } -GLvoid *Buffer::mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access) +Error Buffer::mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access) { ASSERT(!mMapped); ASSERT(offset + length <= mSize); - void *dataPointer = mBuffer->map(offset, length, access); + Error error = mBuffer->map(offset, length, access, &mMapPointer); + if (error.isError()) + { + mMapPointer = NULL; + return error; + } mMapped = GL_TRUE; - mMapPointer = static_cast<GLvoid*>(static_cast<GLubyte*>(dataPointer)); mMapOffset = static_cast<GLint64>(offset); mMapLength = static_cast<GLint64>(length); mAccessFlags = static_cast<GLint>(access); - return mMapPointer; + if ((access & GL_MAP_WRITE_BIT) > 0) + { + mIndexRangeCache.invalidateRange(offset, length); + } + + return error; } -void Buffer::unmap() +Error Buffer::unmap() { ASSERT(mMapped); - mBuffer->unmap(); + Error error = mBuffer->unmap(); + if (error.isError()) + { + return error; + } mMapped = GL_FALSE; mMapPointer = NULL; mMapOffset = 0; mMapLength = 0; mAccessFlags = 0; + + return error; } void Buffer::markTransformFeedbackUsage() { // TODO: Only used by the DX11 backend. Refactor to a more appropriate place. mBuffer->markTransformFeedbackUsage(); + mIndexRangeCache.clear(); } } diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.h b/src/3rdparty/angle/src/libGLESv2/Buffer.h index 389c3d4b00..35a6767502 100644 --- a/src/3rdparty/angle/src/libGLESv2/Buffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Buffer.h @@ -11,8 +11,11 @@ #ifndef LIBGLESV2_BUFFER_H_ #define LIBGLESV2_BUFFER_H_ +#include "libGLESv2/Error.h" + #include "common/angleutils.h" #include "common/RefCountObject.h" +#include "libGLESv2/renderer/IndexRangeCache.h" namespace rx { @@ -30,13 +33,13 @@ class Buffer : public RefCountObject virtual ~Buffer(); - void bufferData(const void *data, GLsizeiptr size, GLenum usage); - void bufferSubData(const void *data, GLsizeiptr size, GLintptr offset); - void copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); - GLvoid *mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access); - void unmap(); + Error bufferData(const void *data, GLsizeiptr size, GLenum usage); + Error bufferSubData(const void *data, GLsizeiptr size, GLintptr offset); + Error copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); + Error mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access); + Error unmap(); - GLenum getUsage() const { return mUsage; } + GLenum getUsage() const { return mUsage; } GLint getAccessFlags() const { return mAccessFlags; } GLboolean isMapped() const { return mMapped; } GLvoid *getMapPointer() const { return mMapPointer; } @@ -48,18 +51,23 @@ class Buffer : public RefCountObject void markTransformFeedbackUsage(); + rx::IndexRangeCache *getIndexRangeCache() { return &mIndexRangeCache; } + const rx::IndexRangeCache *getIndexRangeCache() const { return &mIndexRangeCache; } + private: DISALLOW_COPY_AND_ASSIGN(Buffer); rx::BufferImpl *mBuffer; GLenum mUsage; - GLsizeiptr mSize; + GLint64 mSize; GLint mAccessFlags; GLboolean mMapped; GLvoid *mMapPointer; GLint64 mMapOffset; GLint64 mMapLength; + + rx::IndexRangeCache mIndexRangeCache; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/Caps.cpp b/src/3rdparty/angle/src/libGLESv2/Caps.cpp index c1c4dc9ee7..983800c0e6 100644 --- a/src/3rdparty/angle/src/libGLESv2/Caps.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Caps.cpp @@ -24,6 +24,30 @@ TextureCaps::TextureCaps() { } +GLuint TextureCaps::getMaxSamples() const +{ + return !sampleCounts.empty() ? *sampleCounts.rbegin() : 0; +} + +GLuint TextureCaps::getNearestSamples(GLuint requestedSamples) const +{ + if (requestedSamples == 0) + { + return 0; + } + + for (SupportedSampleSet::const_iterator i = sampleCounts.begin(); i != sampleCounts.end(); i++) + { + GLuint samples = *i; + if (samples >= requestedSamples) + { + return samples; + } + } + + return 0; +} + void TextureCapsMap::insert(GLenum internalFormat, const TextureCaps &caps) { mCapsMap.insert(std::make_pair(internalFormat, caps)); @@ -158,12 +182,17 @@ std::vector<std::string> Extensions::getStrings() const } static bool GetFormatSupport(const TextureCapsMap &textureCaps, const std::vector<GLenum> &requiredFormats, - bool requiresFiltering, bool requiresRendering) + bool requiresTexturing, bool requiresFiltering, bool requiresRendering) { for (size_t i = 0; i < requiredFormats.size(); i++) { const TextureCaps &cap = textureCaps.get(requiredFormats[i]); + if (requiresTexturing && !cap.texturable) + { + return false; + } + if (requiresFiltering && !cap.filterable) { return false; @@ -185,7 +214,7 @@ static bool DetermineRGB8AndRGBA8TextureSupport(const TextureCapsMap &textureCap requiredFormats.push_back(GL_RGB8); requiredFormats.push_back(GL_RGBA8); - return GetFormatSupport(textureCaps, requiredFormats, true, true); + return GetFormatSupport(textureCaps, requiredFormats, true, true, true); } // Checks for GL_EXT_texture_format_BGRA8888 support @@ -194,7 +223,7 @@ static bool DetermineBGRA8TextureSupport(const TextureCapsMap &textureCaps) std::vector<GLenum> requiredFormats; requiredFormats.push_back(GL_BGRA8_EXT); - return GetFormatSupport(textureCaps, requiredFormats, true, true); + return GetFormatSupport(textureCaps, requiredFormats, true, true, true); } // Checks for GL_OES_texture_half_float support @@ -204,7 +233,7 @@ static bool DetermineHalfFloatTextureSupport(const TextureCapsMap &textureCaps) requiredFormats.push_back(GL_RGB16F); requiredFormats.push_back(GL_RGBA16F); - return GetFormatSupport(textureCaps, requiredFormats, false, true); + return GetFormatSupport(textureCaps, requiredFormats, true, false, true); } // Checks for GL_OES_texture_half_float_linear support @@ -214,7 +243,7 @@ static bool DetermineHalfFloatTextureFilteringSupport(const TextureCapsMap &text requiredFormats.push_back(GL_RGB16F); requiredFormats.push_back(GL_RGBA16F); - return GetFormatSupport(textureCaps, requiredFormats, true, false); + return GetFormatSupport(textureCaps, requiredFormats, true, true, false); } // Checks for GL_OES_texture_float support @@ -224,7 +253,7 @@ static bool DetermineFloatTextureSupport(const TextureCapsMap &textureCaps) requiredFormats.push_back(GL_RGB32F); requiredFormats.push_back(GL_RGBA32F); - return GetFormatSupport(textureCaps, requiredFormats, false, true); + return GetFormatSupport(textureCaps, requiredFormats, true, false, true); } // Checks for GL_OES_texture_float_linear support @@ -234,7 +263,7 @@ static bool DetermineFloatTextureFilteringSupport(const TextureCapsMap &textureC requiredFormats.push_back(GL_RGB32F); requiredFormats.push_back(GL_RGBA32F); - return GetFormatSupport(textureCaps, requiredFormats, true, false); + return GetFormatSupport(textureCaps, requiredFormats, true, true, false); } // Checks for GL_EXT_texture_rg support @@ -254,7 +283,7 @@ static bool DetermineRGTextureSupport(const TextureCapsMap &textureCaps, bool ch requiredFormats.push_back(GL_RG32F); } - return GetFormatSupport(textureCaps, requiredFormats, true, false); + return GetFormatSupport(textureCaps, requiredFormats, true, true, false); } // Check for GL_EXT_texture_compression_dxt1 @@ -264,7 +293,7 @@ static bool DetermineDXT1TextureSupport(const TextureCapsMap &textureCaps) requiredFormats.push_back(GL_COMPRESSED_RGB_S3TC_DXT1_EXT); requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); - return GetFormatSupport(textureCaps, requiredFormats, true, false); + return GetFormatSupport(textureCaps, requiredFormats, true, true, false); } // Check for GL_ANGLE_texture_compression_dxt3 @@ -273,7 +302,7 @@ static bool DetermineDXT3TextureSupport(const TextureCapsMap &textureCaps) std::vector<GLenum> requiredFormats; requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE); - return GetFormatSupport(textureCaps, requiredFormats, true, false); + return GetFormatSupport(textureCaps, requiredFormats, true, true, false); } // Check for GL_ANGLE_texture_compression_dxt5 @@ -282,7 +311,7 @@ static bool DetermineDXT5TextureSupport(const TextureCapsMap &textureCaps) std::vector<GLenum> requiredFormats; requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE); - return GetFormatSupport(textureCaps, requiredFormats, true, false); + return GetFormatSupport(textureCaps, requiredFormats, true, true, false); } // Check for GL_ANGLE_texture_compression_dxt5 @@ -295,8 +324,8 @@ static bool DetermineSRGBTextureSupport(const TextureCapsMap &textureCaps) std::vector<GLenum> requiredRenderFormats; requiredRenderFormats.push_back(GL_SRGB8_ALPHA8); - return GetFormatSupport(textureCaps, requiredFilterFormats, true, false) && - GetFormatSupport(textureCaps, requiredRenderFormats, false, true); + return GetFormatSupport(textureCaps, requiredFilterFormats, true, true, false) && + GetFormatSupport(textureCaps, requiredRenderFormats, true, false, true); } // Check for GL_ANGLE_depth_texture @@ -307,7 +336,7 @@ static bool DetermineDepthTextureSupport(const TextureCapsMap &textureCaps) requiredFormats.push_back(GL_DEPTH_COMPONENT32_OES); requiredFormats.push_back(GL_DEPTH24_STENCIL8_OES); - return GetFormatSupport(textureCaps, requiredFormats, true, true); + return GetFormatSupport(textureCaps, requiredFormats, true, true, true); } // Check for GL_EXT_color_buffer_float @@ -322,7 +351,7 @@ static bool DetermineColorBufferFloatSupport(const TextureCapsMap &textureCaps) requiredFormats.push_back(GL_RGBA32F); requiredFormats.push_back(GL_R11F_G11F_B10F); - return GetFormatSupport(textureCaps, requiredFormats, false, true); + return GetFormatSupport(textureCaps, requiredFormats, true, false, true); } void Extensions::setTextureExtensionSupport(const TextureCapsMap &textureCaps) @@ -356,7 +385,40 @@ Caps::Caps() maxViewportHeight(0), minAliasedPointSize(0), maxAliasedPointSize(0), - minAliasedLineWidth(0) + minAliasedLineWidth(0), + // Table 6.29 + maxElementsIndices(0), + maxElementsVertices(0), + maxServerWaitTimeout(0), + // Table 6.31 + maxVertexAttributes(0), + maxVertexUniformComponents(0), + maxVertexUniformVectors(0), + maxVertexUniformBlocks(0), + maxVertexOutputComponents(0), + maxVertexTextureImageUnits(0), + // Table 6.32 + maxFragmentUniformComponents(0), + maxFragmentUniformVectors(0), + maxFragmentUniformBlocks(0), + maxFragmentInputComponents(0), + maxTextureImageUnits(0), + minProgramTexelOffset(0), + maxProgramTexelOffset(0), + + maxUniformBufferBindings(0), + maxUniformBlockSize(0), + uniformBufferOffsetAlignment(0), + maxCombinedUniformBlocks(0), + maxCombinedVertexUniformComponents(0), + maxCombinedFragmentUniformComponents(0), + maxVaryingComponents(0), + maxVaryingVectors(0), + maxCombinedTextureImageUnits(0), + + maxTransformFeedbackInterleavedComponents(0), + maxTransformFeedbackSeparateAttributes(0), + maxTransformFeedbackSeparateComponents(0) { } diff --git a/src/3rdparty/angle/src/libGLESv2/Caps.h b/src/3rdparty/angle/src/libGLESv2/Caps.h index a08618ec9c..a00e554176 100644 --- a/src/3rdparty/angle/src/libGLESv2/Caps.h +++ b/src/3rdparty/angle/src/libGLESv2/Caps.h @@ -17,6 +17,8 @@ namespace gl { +typedef std::set<GLuint> SupportedSampleSet; + struct TextureCaps { TextureCaps(); @@ -30,7 +32,14 @@ struct TextureCaps // Support for being used as a framebuffer attachment or renderbuffer format bool renderable; - std::set<GLuint> sampleCounts; + SupportedSampleSet sampleCounts; + + // Get the maximum number of samples supported + GLuint getMaxSamples() const; + + // Get the number of supported samples that is at least as many as requested. Returns 0 if + // there are no sample counts available + GLuint getNearestSamples(GLuint requestedSamples) const; }; class TextureCapsMap @@ -68,6 +77,7 @@ struct Extensions // GL_OES_texture_float, GL_OES_texture_float_linear // GL_EXT_texture_rg // GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt3, GL_ANGLE_texture_compression_dxt5 + // GL_EXT_sRGB // GL_ANGLE_depth_texture // GL_EXT_color_buffer_float void setTextureExtensionSupport(const TextureCapsMap &textureCaps); @@ -166,6 +176,7 @@ struct Extensions // GL_ANGLE_framebuffer_multisample bool framebufferMultisample; + GLuint maxSamples; // GL_ANGLE_instanced_arrays bool instancedArrays; @@ -215,6 +226,46 @@ struct Caps GLfloat minAliasedLineWidth; GLfloat maxAliasedLineWidth; + // Table 6.29, implementation dependent values (cont.) + GLuint maxElementsIndices; + GLuint maxElementsVertices; + std::vector<GLenum> compressedTextureFormats; + std::vector<GLenum> programBinaryFormats; + std::vector<GLenum> shaderBinaryFormats; + GLuint64 maxServerWaitTimeout; + + // Table 6.31, implementation dependent vertex shader limits + GLuint maxVertexAttributes; + GLuint maxVertexUniformComponents; + GLuint maxVertexUniformVectors; + GLuint maxVertexUniformBlocks; + GLuint maxVertexOutputComponents; + GLuint maxVertexTextureImageUnits; + + // Table 6.32, implementation dependent fragment shader limits + GLuint maxFragmentUniformComponents; + GLuint maxFragmentUniformVectors; + GLuint maxFragmentUniformBlocks; + GLuint maxFragmentInputComponents; + GLuint maxTextureImageUnits; + GLint minProgramTexelOffset; + GLint maxProgramTexelOffset; + + // Table 6.33, implementation dependent aggregate shader limits + GLuint maxUniformBufferBindings; + GLuint64 maxUniformBlockSize; + GLuint uniformBufferOffsetAlignment; + GLuint maxCombinedUniformBlocks; + GLuint64 maxCombinedVertexUniformComponents; + GLuint64 maxCombinedFragmentUniformComponents; + GLuint maxVaryingComponents; + GLuint maxVaryingVectors; + GLuint maxCombinedTextureImageUnits; + + // Table 6.34, implementation dependent transform feedback limits + GLuint maxTransformFeedbackInterleavedComponents; + GLuint maxTransformFeedbackSeparateAttributes; + GLuint maxTransformFeedbackSeparateComponents; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp index 99df85b0d3..5342de1331 100644 --- a/src/3rdparty/angle/src/libGLESv2/Context.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -12,6 +11,7 @@ #include "libGLESv2/main.h" #include "common/utilities.h" +#include "common/platform.h" #include "libGLESv2/formatutils.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/Fence.h" @@ -24,7 +24,6 @@ #include "libGLESv2/Texture.h" #include "libGLESv2/ResourceManager.h" #include "libGLESv2/renderer/d3d/IndexDataManager.h" -#include "libGLESv2/renderer/RenderTarget.h" #include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/VertexArray.h" #include "libGLESv2/Sampler.h" @@ -33,8 +32,8 @@ #include "libEGL/Surface.h" -#undef near -#undef far +#include <sstream> +#include <iterator> namespace gl { @@ -45,6 +44,7 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere ASSERT(robustAccess == false); // Unimplemented initCaps(clientVersion); + mState.initialize(mCaps, clientVersion); mClientVersion = clientVersion; @@ -66,16 +66,26 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere // In order that access to these initial textures not be lost, they are treated as texture // objects all of whose names are 0. - mTexture2DZero.set(new Texture2D(mRenderer->createTexture2D(), 0)); - mTextureCubeMapZero.set(new TextureCubeMap(mRenderer->createTextureCube(), 0)); - mTexture3DZero.set(new Texture3D(mRenderer->createTexture3D(), 0)); - mTexture2DArrayZero.set(new Texture2DArray(mRenderer->createTexture2DArray(), 0)); + mZeroTextures[GL_TEXTURE_2D].set(new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), 0)); + bindTexture(GL_TEXTURE_2D, 0); + + mZeroTextures[GL_TEXTURE_CUBE_MAP].set(new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), 0)); + bindTexture(GL_TEXTURE_CUBE_MAP, 0); + + if (mClientVersion >= 3) + { + // TODO: These could also be enabled via extension + mZeroTextures[GL_TEXTURE_3D].set(new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), 0)); + bindTexture(GL_TEXTURE_3D, 0); + + mZeroTextures[GL_TEXTURE_2D_ARRAY].set(new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), 0)); + bindTexture(GL_TEXTURE_2D_ARRAY, 0); + } bindVertexArray(0); bindArrayBuffer(0); bindElementArrayBuffer(0); - bindTextureCubeMap(0); - bindTexture2D(0); + bindReadFramebuffer(0); bindDrawFramebuffer(0); bindRenderbuffer(0); @@ -101,23 +111,15 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere // In the initial state, a default transform feedback object is bound and treated as // a transform feedback object with a name of zero. That object is bound any time // BindTransformFeedback is called with id of zero - mTransformFeedbackZero.set(new TransformFeedback(0)); + mTransformFeedbackZero.set(new TransformFeedback(mRenderer->createTransformFeedback(), 0)); bindTransformFeedback(0); - mInvalidEnum = false; - mInvalidValue = false; - mInvalidOperation = false; - mOutOfMemory = false; - mInvalidFramebufferOperation = false; - mHasBeenCurrent = false; mContextLost = false; mResetStatus = GL_NO_ERROR; mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT); mRobustAccess = robustAccess; - mNumCompressedTextureFormats = 0; - mState.setContext(this); } @@ -161,15 +163,17 @@ Context::~Context() deleteTransformFeedback(mTransformFeedbackMap.begin()->first); } - for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) + for (TextureMap::iterator i = mIncompleteTextures.begin(); i != mIncompleteTextures.end(); i++) { - mIncompleteTextures[type].set(NULL); + i->second.set(NULL); } + mIncompleteTextures.clear(); - mTexture2DZero.set(NULL); - mTextureCubeMapZero.set(NULL); - mTexture3DZero.set(NULL); - mTexture2DArrayZero.set(NULL); + for (TextureMap::iterator i = mZeroTextures.begin(); i != mZeroTextures.end(); i++) + { + i->second.set(NULL); + } + mZeroTextures.clear(); mResourceManager->release(); } @@ -178,23 +182,6 @@ void Context::makeCurrent(egl::Surface *surface) { if (!mHasBeenCurrent) { - mMajorShaderModel = mRenderer->getMajorShaderModel(); - mSupportsVertexTexture = mRenderer->getVertexTextureSupport(); - - mNumCompressedTextureFormats = 0; - if (mExtensions.textureCompressionDXT1) - { - mNumCompressedTextureFormats += 2; - } - if (mExtensions.textureCompressionDXT3) - { - mNumCompressedTextureFormats += 1; - } - if (mExtensions.textureCompressionDXT5) - { - mNumCompressedTextureFormats += 1; - } - initRendererString(); initExtensionStrings(); @@ -287,7 +274,7 @@ GLuint Context::createSampler() GLuint Context::createTransformFeedback() { GLuint handle = mTransformFeedbackAllocator.allocate(); - TransformFeedback *transformFeedback = new TransformFeedback(handle); + TransformFeedback *transformFeedback = new TransformFeedback(mRenderer->createTransformFeedback(), handle); transformFeedback->addRef(); mTransformFeedbackMap[handle] = transformFeedback; return handle; @@ -528,32 +515,11 @@ void Context::bindElementArrayBuffer(unsigned int buffer) mState.getVertexArray()->setElementArrayBuffer(getBuffer(buffer)); } -void Context::bindTexture2D(GLuint texture) +void Context::bindTexture(GLenum target, GLuint texture) { - mResourceManager->checkTextureAllocation(texture, TEXTURE_2D); + mResourceManager->checkTextureAllocation(texture, target); - mState.setSamplerTexture(TEXTURE_2D, getTexture(texture)); -} - -void Context::bindTextureCubeMap(GLuint texture) -{ - mResourceManager->checkTextureAllocation(texture, TEXTURE_CUBE); - - mState.setSamplerTexture(TEXTURE_CUBE, getTexture(texture)); -} - -void Context::bindTexture3D(GLuint texture) -{ - mResourceManager->checkTextureAllocation(texture, TEXTURE_3D); - - mState.setSamplerTexture(TEXTURE_3D, getTexture(texture)); -} - -void Context::bindTexture2DArray(GLuint texture) -{ - mResourceManager->checkTextureAllocation(texture, TEXTURE_2D_ARRAY); - - mState.setSamplerTexture(TEXTURE_2D_ARRAY, getTexture(texture)); + mState.setSamplerTexture(target, getTexture(texture)); } void Context::bindReadFramebuffer(GLuint framebuffer) @@ -596,7 +562,7 @@ void Context::bindVertexArray(GLuint vertexArray) void Context::bindSampler(GLuint textureUnit, GLuint sampler) { - ASSERT(textureUnit < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS); // TODO: Update for backend-determined array size + ASSERT(textureUnit < mCaps.maxCombinedTextureImageUnits); mResourceManager->checkSamplerAllocation(sampler); mState.setSamplerBinding(textureUnit, getSampler(sampler)); @@ -678,7 +644,7 @@ void Context::linkProgram(GLuint program) { Program *programObject = mResourceManager->getProgram(program); - bool linked = programObject->link(); + bool linked = programObject->link(getCaps()); // if the current program was relinked successfully we // need to install the new executables @@ -688,11 +654,11 @@ void Context::linkProgram(GLuint program) } } -void Context::setProgramBinary(GLuint program, const void *binary, GLint length) +void Context::setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length) { Program *programObject = mResourceManager->getProgram(program); - bool loaded = programObject->setProgramBinary(binary, length); + bool loaded = programObject->setProgramBinary(binaryFormat, binary, length); // if the current program was reloaded successfully we // need to install the new executables @@ -708,26 +674,35 @@ void Context::bindTransformFeedback(GLuint transformFeedback) mState.setTransformFeedbackBinding(getTransformFeedback(transformFeedback)); } -void Context::beginQuery(GLenum target, GLuint query) +Error Context::beginQuery(GLenum target, GLuint query) { Query *queryObject = getQuery(query, true, target); ASSERT(queryObject); - // set query as active for specified target + // begin query + Error error = queryObject->begin(); + if (error.isError()) + { + return error; + } + + // set query as active for specified target only if begin succeeded mState.setActiveQuery(target, queryObject); - // begin query - queryObject->begin(); + return Error(GL_NO_ERROR); } -void Context::endQuery(GLenum target) +Error Context::endQuery(GLenum target) { Query *queryObject = mState.getActiveQuery(target); ASSERT(queryObject); - queryObject->end(); + gl::Error error = queryObject->end(); + // Always unbind the query, even if there was an error. This may delete the query object. mState.setActiveQuery(target, NULL); + + return error; } void Context::setFramebufferZero(Framebuffer *buffer) @@ -755,15 +730,16 @@ void Context::setRenderbufferStorage(GLsizei width, GLsizei height, GLenum inter RenderbufferStorage *renderbuffer = NULL; - if (GetDepthBits(internalformat) > 0 && GetStencilBits(internalformat) > 0) + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); + if (formatInfo.depthBits > 0 && formatInfo.stencilBits > 0) { renderbuffer = new gl::DepthStencilbuffer(mRenderer, width, height, samples); } - else if (GetDepthBits(internalformat) > 0) + else if (formatInfo.depthBits > 0) { renderbuffer = new gl::Depthbuffer(mRenderer, width, height, samples); } - else if (GetStencilBits(internalformat) > 0) + else if (formatInfo.stencilBits > 0) { renderbuffer = new gl::Stencilbuffer(mRenderer, width, height, samples); } @@ -815,7 +791,7 @@ Query *Context::getQuery(unsigned int handle, bool create, GLenum type) { if (!query->second && create) { - query->second = new Query(mRenderer, type, handle); + query->second = new Query(mRenderer->createQuery(type), handle); query->second->addRef(); } return query->second; @@ -841,36 +817,29 @@ Texture *Context::getTargetTexture(GLenum target) const Texture2D *Context::getTexture2D() const { - return static_cast<Texture2D*>(getSamplerTexture(mState.getActiveSampler(), TEXTURE_2D)); + return static_cast<Texture2D*>(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_2D)); } TextureCubeMap *Context::getTextureCubeMap() const { - return static_cast<TextureCubeMap*>(getSamplerTexture(mState.getActiveSampler(), TEXTURE_CUBE)); + return static_cast<TextureCubeMap*>(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_CUBE_MAP)); } Texture3D *Context::getTexture3D() const { - return static_cast<Texture3D*>(getSamplerTexture(mState.getActiveSampler(), TEXTURE_3D)); + return static_cast<Texture3D*>(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_3D)); } Texture2DArray *Context::getTexture2DArray() const { - return static_cast<Texture2DArray*>(getSamplerTexture(mState.getActiveSampler(), TEXTURE_2D_ARRAY)); + return static_cast<Texture2DArray*>(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_2D_ARRAY)); } -Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type) const +Texture *Context::getSamplerTexture(unsigned int sampler, GLenum type) const { if (mState.getSamplerTextureId(sampler, type) == 0) { - switch (type) - { - default: UNREACHABLE(); - case TEXTURE_2D: return mTexture2DZero.get(); - case TEXTURE_CUBE: return mTextureCubeMapZero.get(); - case TEXTURE_3D: return mTexture3DZero.get(); - case TEXTURE_2D_ARRAY: return mTexture2DArrayZero.get(); - } + return mZeroTextures.at(type).get(); } else { @@ -921,45 +890,39 @@ void Context::getIntegerv(GLenum pname, GLint *params) switch (pname) { - case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break; - case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = mRenderer->getMaxVertexUniformVectors(); break; - case GL_MAX_VERTEX_UNIFORM_COMPONENTS: *params = mRenderer->getMaxVertexUniformVectors() * 4; break; - case GL_MAX_VARYING_VECTORS: *params = mRenderer->getMaxVaryingVectors(); break; - case GL_MAX_VARYING_COMPONENTS: *params = mRenderer->getMaxVaryingVectors() * 4; break; - case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = mRenderer->getMaxCombinedTextureImageUnits(); break; - case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = mRenderer->getMaxVertexTextureImageUnits(); break; - case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break; - case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = mRenderer->getMaxFragmentUniformVectors(); break; - case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS: *params = mRenderer->getMaxFragmentUniformVectors() * 4; break; + case GL_MAX_VERTEX_ATTRIBS: *params = mCaps.maxVertexAttributes; break; + case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = mCaps.maxVertexUniformVectors; break; + case GL_MAX_VERTEX_UNIFORM_COMPONENTS: *params = mCaps.maxVertexUniformComponents; break; + case GL_MAX_VARYING_VECTORS: *params = mCaps.maxVaryingVectors; break; + case GL_MAX_VARYING_COMPONENTS: *params = mCaps.maxVertexOutputComponents; break; + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = mCaps.maxCombinedTextureImageUnits; break; + case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = mCaps.maxVertexTextureImageUnits; break; + case GL_MAX_TEXTURE_IMAGE_UNITS: *params = mCaps.maxTextureImageUnits; break; + case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = mCaps.maxFragmentUniformVectors; break; + case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS: *params = mCaps.maxFragmentInputComponents; break; case GL_MAX_RENDERBUFFER_SIZE: *params = mCaps.maxRenderbufferSize; break; case GL_MAX_COLOR_ATTACHMENTS_EXT: *params = mCaps.maxColorAttachments; break; case GL_MAX_DRAW_BUFFERS_EXT: *params = mCaps.maxDrawBuffers; break; - case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break; - case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break; //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE case GL_SUBPIXEL_BITS: *params = 4; break; case GL_MAX_TEXTURE_SIZE: *params = mCaps.max2DTextureSize; break; case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = mCaps.maxCubeMapTextureSize; break; case GL_MAX_3D_TEXTURE_SIZE: *params = mCaps.max3DTextureSize; break; case GL_MAX_ARRAY_TEXTURE_LAYERS: *params = mCaps.maxArrayTextureLayers; break; - case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: *params = getUniformBufferOffsetAlignment(); break; - case GL_MAX_UNIFORM_BUFFER_BINDINGS: *params = getMaximumCombinedUniformBufferBindings(); break; - case GL_MAX_VERTEX_UNIFORM_BLOCKS: *params = mRenderer->getMaxVertexShaderUniformBuffers(); break; - case GL_MAX_FRAGMENT_UNIFORM_BLOCKS: *params = mRenderer->getMaxFragmentShaderUniformBuffers(); break; - case GL_MAX_COMBINED_UNIFORM_BLOCKS: *params = getMaximumCombinedUniformBufferBindings(); break; + case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: *params = mCaps.uniformBufferOffsetAlignment; break; + case GL_MAX_UNIFORM_BUFFER_BINDINGS: *params = mCaps.maxUniformBufferBindings; break; + case GL_MAX_VERTEX_UNIFORM_BLOCKS: *params = mCaps.maxVertexUniformBlocks; break; + case GL_MAX_FRAGMENT_UNIFORM_BLOCKS: *params = mCaps.maxFragmentUniformBlocks; break; + case GL_MAX_COMBINED_UNIFORM_BLOCKS: *params = mCaps.maxCombinedTextureImageUnits; break; case GL_MAJOR_VERSION: *params = mClientVersion; break; case GL_MINOR_VERSION: *params = 0; break; - case GL_MAX_ELEMENTS_INDICES: *params = mRenderer->getMaxRecommendedElementsIndices(); break; - case GL_MAX_ELEMENTS_VERTICES: *params = mRenderer->getMaxRecommendedElementsVertices(); break; - case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: *params = mRenderer->getMaxTransformFeedbackInterleavedComponents(); break; - case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: *params = mRenderer->getMaxTransformFeedbackBuffers(); break; - case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: *params = mRenderer->getMaxTransformFeedbackSeparateComponents(); break; - case GL_NUM_COMPRESSED_TEXTURE_FORMATS: - params[0] = mNumCompressedTextureFormats; - break; - case GL_MAX_SAMPLES_ANGLE: - *params = static_cast<GLint>(getMaxSupportedSamples()); - break; + case GL_MAX_ELEMENTS_INDICES: *params = mCaps.maxElementsIndices; break; + case GL_MAX_ELEMENTS_VERTICES: *params = mCaps.maxElementsVertices; break; + case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: *params = mCaps.maxTransformFeedbackInterleavedComponents; break; + case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: *params = mCaps.maxTransformFeedbackSeparateAttributes; break; + case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: *params = mCaps.maxTransformFeedbackSeparateComponents; break; + case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = mCaps.compressedTextureFormats.size(); break; + case GL_MAX_SAMPLES_ANGLE: *params = mExtensions.maxSamples; break; case GL_IMPLEMENTATION_COLOR_READ_TYPE: case GL_IMPLEMENTATION_COLOR_READ_FORMAT: { @@ -978,30 +941,22 @@ void Context::getIntegerv(GLenum pname, GLint *params) } break; case GL_COMPRESSED_TEXTURE_FORMATS: - { - if (mExtensions.textureCompressionDXT1) - { - *params++ = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; - *params++ = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - } - if (mExtensions.textureCompressionDXT3) - { - *params++ = GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE; - } - if (mExtensions.textureCompressionDXT5) - { - *params++ = GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE; - } - } + std::copy(mCaps.compressedTextureFormats.begin(), mCaps.compressedTextureFormats.end(), params); break; case GL_RESET_NOTIFICATION_STRATEGY_EXT: *params = mResetStrategy; break; - case GL_NUM_PROGRAM_BINARY_FORMATS_OES: - *params = 1; + case GL_NUM_SHADER_BINARY_FORMATS: + *params = mCaps.shaderBinaryFormats.size(); break; - case GL_PROGRAM_BINARY_FORMATS_OES: - *params = GL_PROGRAM_BINARY_ANGLE; + case GL_SHADER_BINARY_FORMATS: + std::copy(mCaps.shaderBinaryFormats.begin(), mCaps.shaderBinaryFormats.end(), params); + break; + case GL_NUM_PROGRAM_BINARY_FORMATS: + *params = mCaps.programBinaryFormats.size(); + break; + case GL_PROGRAM_BINARY_FORMATS: + std::copy(mCaps.programBinaryFormats.begin(), mCaps.programBinaryFormats.end(), params); break; case GL_NUM_EXTENSIONS: *params = static_cast<GLint>(mExtensionStrings.size()); @@ -1022,25 +977,16 @@ void Context::getInteger64v(GLenum pname, GLint64 *params) *params = mCaps.maxElementIndex; break; case GL_MAX_UNIFORM_BLOCK_SIZE: - *params = static_cast<GLint64>(mRenderer->getMaxUniformBufferSize()); + *params = mCaps.maxUniformBlockSize; break; case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS: - { - GLint64 uniformBufferComponents = static_cast<GLint64>(mRenderer->getMaxVertexShaderUniformBuffers()) * static_cast<GLint64>(mRenderer->getMaxUniformBufferSize() / 4); - GLint64 defaultBufferComponents = static_cast<GLint64>(mRenderer->getMaxVertexUniformVectors() * 4); - *params = uniformBufferComponents + defaultBufferComponents; - } + *params = mCaps.maxCombinedVertexUniformComponents; break; case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS: - { - GLint64 uniformBufferComponents = static_cast<GLint64>(mRenderer->getMaxFragmentShaderUniformBuffers()) * static_cast<GLint64>(mRenderer->getMaxUniformBufferSize() / 4); - GLint64 defaultBufferComponents = static_cast<GLint64>(mRenderer->getMaxVertexUniformVectors() * 4); - *params = uniformBufferComponents + defaultBufferComponents; - } + *params = mCaps.maxCombinedFragmentUniformComponents; break; case GL_MAX_SERVER_WAIT_TIMEOUT: - // We do not wait for server fence objects internally, so report a max timeout of zero. - *params = 0; + *params = mCaps.maxServerWaitTimeout; break; default: UNREACHABLE(); @@ -1087,13 +1033,19 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu case GL_COMPRESSED_TEXTURE_FORMATS: { *type = GL_INT; - *numParams = mNumCompressedTextureFormats; + *numParams = mCaps.compressedTextureFormats.size(); + } + return true; + case GL_PROGRAM_BINARY_FORMATS_OES: + { + *type = GL_INT; + *numParams = mCaps.programBinaryFormats.size(); } return true; case GL_SHADER_BINARY_FORMATS: { *type = GL_INT; - *numParams = 0; + *numParams = mCaps.shaderBinaryFormats.size(); } return true; case GL_MAX_VERTEX_ATTRIBS: @@ -1162,7 +1114,6 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu case GL_TEXTURE_BINDING_CUBE_MAP: case GL_RESET_NOTIFICATION_STRATEGY_EXT: case GL_NUM_PROGRAM_BINARY_FORMATS_OES: - case GL_PROGRAM_BINARY_FORMATS_OES: { *type = GL_INT; *numParams = 1; @@ -1360,28 +1311,29 @@ bool Context::getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned // Applies the render target surface, depth stencil surface, viewport rectangle and // scissor rectangle to the renderer -bool Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport) +Error Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport) { Framebuffer *framebufferObject = mState.getDrawFramebuffer(); ASSERT(framebufferObject && framebufferObject->completeness() == GL_FRAMEBUFFER_COMPLETE); - mRenderer->applyRenderTarget(framebufferObject); + gl::Error error = mRenderer->applyRenderTarget(framebufferObject); + if (error.isError()) + { + return error; + } float nearZ, farZ; mState.getDepthRange(&nearZ, &farZ); - if (!mRenderer->setViewport(mState.getViewport(), nearZ, farZ, drawMode, mState.getRasterizerState().frontFace, - ignoreViewport)) - { - return false; - } + mRenderer->setViewport(mState.getViewport(), nearZ, farZ, drawMode, mState.getRasterizerState().frontFace, + ignoreViewport); mRenderer->setScissorRectangle(mState.getScissor(), mState.isScissorTestEnabled()); - return true; + return gl::Error(GL_NO_ERROR); } // Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device -void Context::applyState(GLenum drawMode) +Error Context::applyState(GLenum drawMode) { Framebuffer *framebufferObject = mState.getDrawFramebuffer(); int samples = framebufferObject->getSamples(); @@ -1390,7 +1342,11 @@ void Context::applyState(GLenum drawMode) rasterizer.pointDrawMode = (drawMode == GL_POINTS); rasterizer.multiSample = (samples != 0); - mRenderer->setRasterizerState(rasterizer); + Error error = mRenderer->setRasterizerState(rasterizer); + if (error.isError()) + { + return error; + } unsigned int mask = 0; if (mState.isSampleCoverageEnabled()) @@ -1400,7 +1356,6 @@ void Context::applyState(GLenum drawMode) mState.getSampleCoverageParams(&coverageValue, &coverageInvert); if (coverageValue != 0) { - float threshold = 0.5f; for (int i = 0; i < samples; ++i) @@ -1424,117 +1379,185 @@ void Context::applyState(GLenum drawMode) { mask = 0xFFFFFFFF; } - mRenderer->setBlendState(framebufferObject, mState.getBlendState(), mState.getBlendColor(), mask); + error = mRenderer->setBlendState(framebufferObject, mState.getBlendState(), mState.getBlendColor(), mask); + if (error.isError()) + { + return error; + } + + error = mRenderer->setDepthStencilState(mState.getDepthStencilState(), mState.getStencilRef(), mState.getStencilBackRef(), + rasterizer.frontFace == GL_CCW); + if (error.isError()) + { + return error; + } - mRenderer->setDepthStencilState(mState.getDepthStencilState(), mState.getStencilRef(), mState.getStencilBackRef(), - rasterizer.frontFace == GL_CCW); + return Error(GL_NO_ERROR); } // Applies the shaders and shader constants to the Direct3D 9 device -void Context::applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive) +Error Context::applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive) { const VertexAttribute *vertexAttributes = mState.getVertexArray()->getVertexAttributes(); - VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]; + VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]; VertexFormat::GetInputLayout(inputLayout, programBinary, vertexAttributes, mState.getVertexAttribCurrentValues()); const Framebuffer *fbo = mState.getDrawFramebuffer(); - mRenderer->applyShaders(programBinary, inputLayout, fbo, mState.getRasterizerState().rasterizerDiscard, transformFeedbackActive); + Error error = mRenderer->applyShaders(programBinary, inputLayout, fbo, mState.getRasterizerState().rasterizerDiscard, transformFeedbackActive); + if (error.isError()) + { + return error; + } - programBinary->applyUniforms(); + return programBinary->applyUniforms(); } -size_t Context::getCurrentTexturesAndSamplerStates(ProgramBinary *programBinary, SamplerType type, Texture **outTextures, - TextureType *outTextureTypes, SamplerState *outSamplers) +Error Context::generateSwizzles(ProgramBinary *programBinary, SamplerType type) { size_t samplerRange = programBinary->getUsedSamplerRange(type); + for (size_t i = 0; i < samplerRange; i++) { - outTextureTypes[i] = programBinary->getSamplerTextureType(type, i); - GLint textureUnit = programBinary->getSamplerMapping(type, i); // OpenGL texture image unit index + GLenum textureType = programBinary->getSamplerTextureType(type, i); + GLint textureUnit = programBinary->getSamplerMapping(type, i, getCaps()); if (textureUnit != -1) { - outTextures[i] = getSamplerTexture(textureUnit, outTextureTypes[i]); - outTextures[i]->getSamplerStateWithNativeOffset(&outSamplers[i]); - Sampler *samplerObject = mState.getSampler(textureUnit); - if (samplerObject) + Texture* texture = getSamplerTexture(textureUnit, textureType); + if (texture->getSamplerState().swizzleRequired()) { - samplerObject->getState(&outSamplers[i]); + Error error = mRenderer->generateSwizzle(texture); + if (error.isError()) + { + return error; + } } } - else - { - outTextures[i] = NULL; - } } - return samplerRange; + return Error(GL_NO_ERROR); } -void Context::generateSwizzles(Texture *textures[], size_t count) +Error Context::generateSwizzles(ProgramBinary *programBinary) { - for (size_t i = 0; i < count; i++) + Error error = generateSwizzles(programBinary, SAMPLER_VERTEX); + if (error.isError()) { - if (textures[i] && textures[i]->getSamplerState().swizzleRequired()) - { - mRenderer->generateSwizzle(textures[i]); - } + return error; } + + error = generateSwizzles(programBinary, SAMPLER_PIXEL); + if (error.isError()) + { + return error; + } + + return Error(GL_NO_ERROR); } // For each Direct3D sampler of either the pixel or vertex stage, // looks up the corresponding OpenGL texture image unit and texture type, // and sets the texture and its addressing/filtering state (or NULL when inactive). -void Context::applyTextures(SamplerType shaderType, Texture *textures[], TextureType *textureTypes, SamplerState *samplers, - size_t textureCount, const FramebufferTextureSerialArray& framebufferSerials, - size_t framebufferSerialCount) +Error Context::applyTextures(ProgramBinary *programBinary, SamplerType shaderType, + const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount) { - // Range of Direct3D samplers of given sampler type - size_t samplerCount = (shaderType == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS - : mRenderer->getMaxVertexTextureImageUnits(); - - for (size_t samplerIndex = 0; samplerIndex < textureCount; samplerIndex++) + size_t samplerRange = programBinary->getUsedSamplerRange(shaderType); + for (size_t samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++) { - Texture *texture = textures[samplerIndex]; - const SamplerState &sampler = samplers[samplerIndex]; - TextureType textureType = textureTypes[samplerIndex]; - - if (texture) + GLenum textureType = programBinary->getSamplerTextureType(shaderType, samplerIndex); + GLint textureUnit = programBinary->getSamplerMapping(shaderType, samplerIndex, getCaps()); + if (textureUnit != -1) { + SamplerState sampler; + Texture* texture = getSamplerTexture(textureUnit, textureType); + texture->getSamplerStateWithNativeOffset(&sampler); + + Sampler *samplerObject = mState.getSampler(textureUnit); + if (samplerObject) + { + samplerObject->getState(&sampler); + } + // TODO: std::binary_search may become unavailable using older versions of GCC - if (texture->isSamplerComplete(sampler) && + if (texture->isSamplerComplete(sampler, mTextureCaps, mExtensions, mClientVersion) && !std::binary_search(framebufferSerials.begin(), framebufferSerials.begin() + framebufferSerialCount, texture->getTextureSerial())) { - mRenderer->setSamplerState(shaderType, samplerIndex, sampler); - mRenderer->setTexture(shaderType, samplerIndex, texture); - texture->resetDirty(); + Error error = mRenderer->setSamplerState(shaderType, samplerIndex, sampler); + if (error.isError()) + { + return error; + } + + error = mRenderer->setTexture(shaderType, samplerIndex, texture); + if (error.isError()) + { + return error; + } } else { + // Texture is not sampler complete or it is in use by the framebuffer. Bind the incomplete texture. Texture *incompleteTexture = getIncompleteTexture(textureType); - mRenderer->setTexture(shaderType, samplerIndex, incompleteTexture); - incompleteTexture->resetDirty(); + gl::Error error = mRenderer->setTexture(shaderType, samplerIndex, incompleteTexture); + if (error.isError()) + { + return error; + } } } else { - mRenderer->setTexture(shaderType, samplerIndex, NULL); + // No texture bound to this slot even though it is used by the shader, bind a NULL texture + Error error = mRenderer->setTexture(shaderType, samplerIndex, NULL); + if (error.isError()) + { + return error; + } } } - for (size_t samplerIndex = textureCount; samplerIndex < samplerCount; samplerIndex++) + // Set all the remaining textures to NULL + size_t samplerCount = (shaderType == SAMPLER_PIXEL) ? mCaps.maxTextureImageUnits + : mCaps.maxVertexTextureImageUnits; + for (size_t samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++) { - mRenderer->setTexture(shaderType, samplerIndex, NULL); + Error error = mRenderer->setTexture(shaderType, samplerIndex, NULL); + if (error.isError()) + { + return error; + } } + + return Error(GL_NO_ERROR); } -bool Context::applyUniformBuffers() +Error Context::applyTextures(ProgramBinary *programBinary) +{ + FramebufferTextureSerialArray framebufferSerials; + size_t framebufferSerialCount = getBoundFramebufferTextureSerials(&framebufferSerials); + + Error error = applyTextures(programBinary, SAMPLER_VERTEX, framebufferSerials, framebufferSerialCount); + if (error.isError()) + { + return error; + } + + error = applyTextures(programBinary, SAMPLER_PIXEL, framebufferSerials, framebufferSerialCount); + if (error.isError()) + { + return error; + } + + return Error(GL_NO_ERROR); +} + +Error Context::applyUniformBuffers() { Program *programObject = getProgram(mState.getCurrentProgramId()); ProgramBinary *programBinary = programObject->getProgramBinary(); - std::vector<gl::Buffer*> boundBuffers; + std::vector<Buffer*> boundBuffers; for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < programBinary->getActiveUniformBlockCount(); uniformBlockIndex++) { @@ -1543,7 +1566,7 @@ bool Context::applyUniformBuffers() if (mState.getIndexedUniformBuffer(blockBinding)->id() == 0) { // undefined behaviour - return false; + return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to have a used but unbound uniform buffer."); } else { @@ -1553,7 +1576,7 @@ bool Context::applyUniformBuffers() } } - return programBinary->applyUniformBuffers(boundBuffers); + return programBinary->applyUniformBuffers(boundBuffers, getCaps()); } bool Context::applyTransformFeedbackBuffers() @@ -1589,28 +1612,25 @@ void Context::markTransformFeedbackUsage() } } -void Context::clear(GLbitfield mask) +Error Context::clear(GLbitfield mask) { if (mState.isRasterizerDiscardEnabled()) { - return; + return Error(GL_NO_ERROR); } ClearParameters clearParams = mState.getClearParameters(mask); - if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport - { - return; - } + applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport - mRenderer->clear(clearParams, mState.getDrawFramebuffer()); + return mRenderer->clear(clearParams, mState.getDrawFramebuffer()); } -void Context::clearBufferfv(GLenum buffer, int drawbuffer, const float *values) +Error Context::clearBufferfv(GLenum buffer, int drawbuffer, const float *values) { if (mState.isRasterizerDiscardEnabled()) { - return; + return Error(GL_NO_ERROR); } // glClearBufferfv can be called to clear the color buffer or depth buffer @@ -1632,19 +1652,16 @@ void Context::clearBufferfv(GLenum buffer, int drawbuffer, const float *values) clearParams.depthClearValue = values[0]; } - if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport - { - return; - } + applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport - mRenderer->clear(clearParams, mState.getDrawFramebuffer()); + return mRenderer->clear(clearParams, mState.getDrawFramebuffer()); } -void Context::clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values) +Error Context::clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values) { if (mState.isRasterizerDiscardEnabled()) { - return; + return Error(GL_NO_ERROR); } // glClearBufferuv can only be called to clear a color buffer @@ -1656,19 +1673,16 @@ void Context::clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int * clearParams.colorUIClearValue = ColorUI(values[0], values[1], values[2], values[3]); clearParams.colorClearType = GL_UNSIGNED_INT; - if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport - { - return; - } + applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport - mRenderer->clear(clearParams, mState.getDrawFramebuffer()); + return mRenderer->clear(clearParams, mState.getDrawFramebuffer()); } -void Context::clearBufferiv(GLenum buffer, int drawbuffer, const int *values) +Error Context::clearBufferiv(GLenum buffer, int drawbuffer, const int *values) { if (mState.isRasterizerDiscardEnabled()) { - return; + return Error(GL_NO_ERROR); } // glClearBufferfv can be called to clear the color buffer or stencil buffer @@ -1690,19 +1704,16 @@ void Context::clearBufferiv(GLenum buffer, int drawbuffer, const int *values) clearParams.stencilClearValue = values[1]; } - if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport - { - return; - } + applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport - mRenderer->clear(clearParams, mState.getDrawFramebuffer()); + return mRenderer->clear(clearParams, mState.getDrawFramebuffer()); } -void Context::clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil) +Error Context::clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil) { if (mState.isRasterizerDiscardEnabled()) { - return; + return Error(GL_NO_ERROR); } // glClearBufferfi can only be called to clear a depth stencil buffer @@ -1712,135 +1723,145 @@ void Context::clearBufferfi(GLenum buffer, int drawbuffer, float depth, int sten clearParams.clearStencil = true; clearParams.stencilClearValue = stencil; - if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport - { - return; - } + applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport - mRenderer->clear(clearParams, mState.getDrawFramebuffer()); + return mRenderer->clear(clearParams, mState.getDrawFramebuffer()); } -void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLsizei *bufSize, void* pixels) +Error Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLsizei *bufSize, void* pixels) { - gl::Framebuffer *framebuffer = mState.getReadFramebuffer(); + Framebuffer *framebuffer = mState.getReadFramebuffer(); - bool isSized = IsSizedInternalFormat(format); - GLenum sizedInternalFormat = (isSized ? format : GetSizedInternalFormat(format, type)); - GLuint outputPitch = GetRowPitch(sizedInternalFormat, type, width, mState.getPackAlignment()); + GLenum sizedInternalFormat = GetSizedInternalFormat(format, type); + const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat); + GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, width, mState.getPackAlignment()); - mRenderer->readPixels(framebuffer, x, y, width, height, format, type, outputPitch, mState.getPackState(), pixels); + return mRenderer->readPixels(framebuffer, x, y, width, height, format, type, outputPitch, mState.getPackState(), + reinterpret_cast<uint8_t*>(pixels)); } -void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances) +Error Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances) { ASSERT(mState.getCurrentProgramId() != 0); ProgramBinary *programBinary = mState.getCurrentProgramBinary(); programBinary->updateSamplerMapping(); - Texture *vsTextures[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - TextureType vsTextureTypes[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - SamplerState vsSamplers[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - size_t vsTextureCount = getCurrentTexturesAndSamplerStates(programBinary, SAMPLER_VERTEX, vsTextures, vsTextureTypes, vsSamplers); - - Texture *psTextures[MAX_TEXTURE_IMAGE_UNITS]; - TextureType psTextureTypes[MAX_TEXTURE_IMAGE_UNITS]; - SamplerState psSamplers[MAX_TEXTURE_IMAGE_UNITS]; - size_t psTextureCount = getCurrentTexturesAndSamplerStates(programBinary, SAMPLER_PIXEL, psTextures, psTextureTypes, psSamplers); - - generateSwizzles(vsTextures, vsTextureCount); - generateSwizzles(psTextures, psTextureCount); + Error error = generateSwizzles(programBinary); + if (error.isError()) + { + return error; + } if (!mRenderer->applyPrimitiveType(mode, count)) { - return; + return Error(GL_NO_ERROR); } - if (!applyRenderTarget(mode, false)) + error = applyRenderTarget(mode, false); + if (error.isError()) { - return; + return error; } - applyState(mode); + error = applyState(mode); + if (error.isError()) + { + return error; + } - GLenum err = mRenderer->applyVertexBuffer(programBinary, mState.getVertexArray()->getVertexAttributes(), mState.getVertexAttribCurrentValues(), first, count, instances); - if (err != GL_NO_ERROR) + error = mRenderer->applyVertexBuffer(programBinary, mState.getVertexArray()->getVertexAttributes(), mState.getVertexAttribCurrentValues(), first, count, instances); + if (error.isError()) { - return gl::error(err); + return error; } bool transformFeedbackActive = applyTransformFeedbackBuffers(); - applyShaders(programBinary, transformFeedbackActive); - - FramebufferTextureSerialArray frameBufferSerials; - size_t framebufferSerialCount = getBoundFramebufferTextureSerials(&frameBufferSerials); + error = applyShaders(programBinary, transformFeedbackActive); + if (error.isError()) + { + return error; + } - applyTextures(SAMPLER_VERTEX, vsTextures, vsTextureTypes, vsSamplers, vsTextureCount, frameBufferSerials, framebufferSerialCount); - applyTextures(SAMPLER_PIXEL, psTextures, psTextureTypes, psSamplers, psTextureCount, frameBufferSerials, framebufferSerialCount); + error = applyTextures(programBinary); + if (error.isError()) + { + return error; + } - if (!applyUniformBuffers()) + error = applyUniformBuffers(); + if (error.isError()) { - return; + return error; } if (!skipDraw(mode)) { - mRenderer->drawArrays(mode, count, instances, transformFeedbackActive); + error = mRenderer->drawArrays(mode, count, instances, transformFeedbackActive); + if (error.isError()) + { + return error; + } if (transformFeedbackActive) { markTransformFeedbackUsage(); } } + + return gl::Error(GL_NO_ERROR); } -void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances) +Error Context::drawElements(GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei instances, + const rx::RangeUI &indexRange) { ASSERT(mState.getCurrentProgramId() != 0); ProgramBinary *programBinary = mState.getCurrentProgramBinary(); programBinary->updateSamplerMapping(); - Texture *vsTextures[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - TextureType vsTextureTypes[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - SamplerState vsSamplers[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - size_t vsTextureCount = getCurrentTexturesAndSamplerStates(programBinary, SAMPLER_VERTEX, vsTextures, vsTextureTypes, vsSamplers); - - Texture *psTextures[MAX_TEXTURE_IMAGE_UNITS]; - TextureType psTextureTypes[MAX_TEXTURE_IMAGE_UNITS]; - SamplerState psSamplers[MAX_TEXTURE_IMAGE_UNITS]; - size_t psTextureCount = getCurrentTexturesAndSamplerStates(programBinary, SAMPLER_PIXEL, psTextures, psTextureTypes, psSamplers); - - generateSwizzles(vsTextures, vsTextureCount); - generateSwizzles(psTextures, psTextureCount); + Error error = generateSwizzles(programBinary); + if (error.isError()) + { + return error; + } if (!mRenderer->applyPrimitiveType(mode, count)) { - return; + return Error(GL_NO_ERROR); } - if (!applyRenderTarget(mode, false)) + error = applyRenderTarget(mode, false); + if (error.isError()) { - return; + return error; } - applyState(mode); + error = applyState(mode); + if (error.isError()) + { + return error; + } VertexArray *vao = mState.getVertexArray(); rx::TranslatedIndexData indexInfo; - GLenum err = mRenderer->applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo); - if (err != GL_NO_ERROR) + indexInfo.indexRange = indexRange; + error = mRenderer->applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo); + if (error.isError()) { - return gl::error(err); + return error; } - GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1; - err = mRenderer->applyVertexBuffer(programBinary, vao->getVertexAttributes(), mState.getVertexAttribCurrentValues(), indexInfo.minIndex, vertexCount, instances); - if (err != GL_NO_ERROR) + GLsizei vertexCount = indexInfo.indexRange.length() + 1; + error = mRenderer->applyVertexBuffer(programBinary, vao->getVertexAttributes(), + mState.getVertexAttribCurrentValues(), + indexInfo.indexRange.start, vertexCount, instances); + if (error.isError()) { - return gl::error(err); + return error; } bool transformFeedbackActive = applyTransformFeedbackBuffers(); @@ -1848,23 +1869,34 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid // layer. ASSERT(!transformFeedbackActive); - applyShaders(programBinary, transformFeedbackActive); - - FramebufferTextureSerialArray frameBufferSerials; - size_t framebufferSerialCount = getBoundFramebufferTextureSerials(&frameBufferSerials); + error = applyShaders(programBinary, transformFeedbackActive); + if (error.isError()) + { + return error; + } - applyTextures(SAMPLER_VERTEX, vsTextures, vsTextureTypes, vsSamplers, vsTextureCount, frameBufferSerials, framebufferSerialCount); - applyTextures(SAMPLER_PIXEL, psTextures, psTextureTypes, psSamplers, psTextureCount, frameBufferSerials, framebufferSerialCount); + error = applyTextures(programBinary); + if (error.isError()) + { + return error; + } - if (!applyUniformBuffers()) + error = applyUniformBuffers(); + if (error.isError()) { - return; + return error; } if (!skipDraw(mode)) { - mRenderer->drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances); + error = mRenderer->drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances); + if (error.isError()) + { + return error; + } } + + return Error(GL_NO_ERROR); } // Implements glFlush when block is false, glFinish when block is true @@ -1873,71 +1905,28 @@ void Context::sync(bool block) mRenderer->sync(block); } -void Context::recordInvalidEnum() -{ - mInvalidEnum = true; -} - -void Context::recordInvalidValue() -{ - mInvalidValue = true; -} - -void Context::recordInvalidOperation() -{ - mInvalidOperation = true; -} - -void Context::recordOutOfMemory() +void Context::recordError(const Error &error) { - mOutOfMemory = true; -} - -void Context::recordInvalidFramebufferOperation() -{ - mInvalidFramebufferOperation = true; + if (error.isError()) + { + mErrors.insert(error.getCode()); + } } // Get one of the recorded errors and clear its flag, if any. // [OpenGL ES 2.0.24] section 2.5 page 13. GLenum Context::getError() { - if (mInvalidEnum) - { - mInvalidEnum = false; - - return GL_INVALID_ENUM; - } - - if (mInvalidValue) + if (mErrors.empty()) { - mInvalidValue = false; - - return GL_INVALID_VALUE; - } - - if (mInvalidOperation) - { - mInvalidOperation = false; - - return GL_INVALID_OPERATION; - } - - if (mOutOfMemory) - { - mOutOfMemory = false; - - return GL_OUT_OF_MEMORY; + return GL_NO_ERROR; } - - if (mInvalidFramebufferOperation) + else { - mInvalidFramebufferOperation = false; - - return GL_INVALID_FRAMEBUFFER_OPERATION; + GLenum error = *mErrors.begin(); + mErrors.erase(mErrors.begin()); + return error; } - - return GL_NO_ERROR; } GLenum Context::getResetStatus() @@ -1989,53 +1978,6 @@ const Extensions &Context::getExtensions() const return mExtensions; } -int Context::getMajorShaderModel() const -{ - return mMajorShaderModel; -} - -unsigned int Context::getMaximumCombinedTextureImageUnits() const -{ - return mRenderer->getMaxCombinedTextureImageUnits(); -} - -unsigned int Context::getMaximumCombinedUniformBufferBindings() const -{ - return mRenderer->getMaxVertexShaderUniformBuffers() + - mRenderer->getMaxFragmentShaderUniformBuffers(); -} - -int Context::getMaxSupportedSamples() const -{ - return mRenderer->getMaxSupportedSamples(); -} - -GLsizei Context::getMaxSupportedFormatSamples(GLenum internalFormat) const -{ - return mRenderer->getMaxSupportedFormatSamples(internalFormat); -} - -GLsizei Context::getNumSampleCounts(GLenum internalFormat) const -{ - return mRenderer->getNumSampleCounts(internalFormat); -} - -void Context::getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const -{ - mRenderer->getSampleCounts(internalFormat, bufSize, params); -} - -unsigned int Context::getMaxTransformFeedbackBufferBindings() const -{ - return mRenderer->getMaxTransformFeedbackBuffers(); -} - -GLintptr Context::getUniformBufferOffsetAlignment() const -{ - // setting a large alignment forces uniform buffers to bind with zero offset - return static_cast<GLintptr>(std::numeric_limits<GLint>::max()); -} - void Context::getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type) { Framebuffer *framebuffer = mState.getReadFramebuffer(); @@ -2044,9 +1986,12 @@ void Context::getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, G FramebufferAttachment *attachment = framebuffer->getReadColorbuffer(); ASSERT(attachment); - *internalFormat = attachment->getActualFormat(); - *format = gl::GetFormat(attachment->getActualFormat()); - *type = gl::GetType(attachment->getActualFormat()); + GLenum actualFormat = attachment->getActualFormat(); + const InternalFormat &actualFormatInfo = GetInternalFormatInfo(actualFormat); + + *internalFormat = actualFormat; + *format = actualFormatInfo.format; + *type = actualFormatInfo.type; } void Context::detachTexture(GLuint texture) @@ -2127,32 +2072,31 @@ void Context::detachSampler(GLuint sampler) mState.detachSampler(sampler); } -Texture *Context::getIncompleteTexture(TextureType type) +Texture *Context::getIncompleteTexture(GLenum type) { - Texture *t = mIncompleteTextures[type].get(); - - if (t == NULL) + if (mIncompleteTextures.find(type) == mIncompleteTextures.end()) { const GLubyte color[] = { 0, 0, 0, 255 }; const PixelUnpackState incompleteUnpackState(1); + Texture* t = NULL; switch (type) { default: UNREACHABLE(); // default falls through to TEXTURE_2D - case TEXTURE_2D: + case GL_TEXTURE_2D: { - Texture2D *incomplete2d = new Texture2D(mRenderer->createTexture2D(), Texture::INCOMPLETE_TEXTURE_ID); + Texture2D *incomplete2d = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), Texture::INCOMPLETE_TEXTURE_ID); incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); t = incomplete2d; } break; - case TEXTURE_CUBE: + case GL_TEXTURE_CUBE_MAP: { - TextureCubeMap *incompleteCube = new TextureCubeMap(mRenderer->createTextureCube(), Texture::INCOMPLETE_TEXTURE_ID); + TextureCubeMap *incompleteCube = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), Texture::INCOMPLETE_TEXTURE_ID); incompleteCube->setImagePosX(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); incompleteCube->setImageNegX(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); @@ -2165,18 +2109,18 @@ Texture *Context::getIncompleteTexture(TextureType type) } break; - case TEXTURE_3D: + case GL_TEXTURE_3D: { - Texture3D *incomplete3d = new Texture3D(mRenderer->createTexture3D(), Texture::INCOMPLETE_TEXTURE_ID); + Texture3D *incomplete3d = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), Texture::INCOMPLETE_TEXTURE_ID); incomplete3d->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); t = incomplete3d; } break; - case TEXTURE_2D_ARRAY: + case GL_TEXTURE_2D_ARRAY: { - Texture2DArray *incomplete2darray = new Texture2DArray(mRenderer->createTexture2DArray(), Texture::INCOMPLETE_TEXTURE_ID); + Texture2DArray *incomplete2darray = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), Texture::INCOMPLETE_TEXTURE_ID); incomplete2darray->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); t = incomplete2darray; @@ -2187,7 +2131,7 @@ Texture *Context::getIncompleteTexture(TextureType type) mIncompleteTextures[type].set(t); } - return t; + return mIncompleteTextures[type].get(); } bool Context::skipDraw(GLenum drawMode) @@ -2359,14 +2303,16 @@ size_t Context::getBoundFramebufferTextureSerials(FramebufferTextureSerialArray FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i); if (attachment && attachment->isTexture()) { - (*outSerialArray)[serialCount++] = attachment->getTextureSerial(); + Texture *texture = attachment->getTexture(); + (*outSerialArray)[serialCount++] = texture->getTextureSerial(); } } FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer(); if (depthStencilAttachment && depthStencilAttachment->isTexture()) { - (*outSerialArray)[serialCount++] = depthStencilAttachment->getTextureSerial(); + Texture *depthStencilTexture = depthStencilAttachment->getTexture(); + (*outSerialArray)[serialCount++] = depthStencilTexture->getTextureSerial(); } std::sort(outSerialArray->begin(), outSerialArray->begin() + serialCount); @@ -2396,114 +2342,19 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 blitDepth = true; } - gl::Rectangle srcRect(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0); - gl::Rectangle dstRect(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0); + Rectangle srcRect(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0); + Rectangle dstRect(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0); if (blitRenderTarget || blitDepth || blitStencil) { - const gl::Rectangle *scissor = mState.isScissorTestEnabled() ? &mState.getScissor() : NULL; + const Rectangle *scissor = mState.isScissorTestEnabled() ? &mState.getScissor() : NULL; mRenderer->blitRect(readFramebuffer, srcRect, drawFramebuffer, dstRect, scissor, blitRenderTarget, blitDepth, blitStencil, filter); } } -void Context::invalidateFrameBuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, - GLint x, GLint y, GLsizei width, GLsizei height) -{ - Framebuffer *frameBuffer = NULL; - switch (target) - { - case GL_FRAMEBUFFER: - case GL_DRAW_FRAMEBUFFER: - frameBuffer = mState.getDrawFramebuffer(); - break; - case GL_READ_FRAMEBUFFER: - frameBuffer = mState.getReadFramebuffer(); - break; - default: - UNREACHABLE(); - } - - if (frameBuffer && frameBuffer->completeness() == GL_FRAMEBUFFER_COMPLETE) - { - for (int i = 0; i < numAttachments; ++i) - { - rx::RenderTarget *renderTarget = NULL; - - if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15) - { - gl::FramebufferAttachment *attachment = frameBuffer->getColorbuffer(attachments[i] - GL_COLOR_ATTACHMENT0); - if (attachment) - { - renderTarget = attachment->getRenderTarget(); - } - } - else if (attachments[i] == GL_COLOR) - { - gl::FramebufferAttachment *attachment = frameBuffer->getColorbuffer(0); - if (attachment) - { - renderTarget = attachment->getRenderTarget(); - } - } - else - { - gl::FramebufferAttachment *attachment = NULL; - switch (attachments[i]) - { - case GL_DEPTH_ATTACHMENT: - case GL_DEPTH: - attachment = frameBuffer->getDepthbuffer(); - break; - case GL_STENCIL_ATTACHMENT: - case GL_STENCIL: - attachment = frameBuffer->getStencilbuffer(); - break; - case GL_DEPTH_STENCIL_ATTACHMENT: - attachment = frameBuffer->getDepthOrStencilbuffer(); - break; - default: - UNREACHABLE(); - } - - if (attachment) - { - renderTarget = attachment->getDepthStencil(); - } - } - - if (renderTarget) - { - renderTarget->invalidate(x, y, width, height); - } - } - } -} - -bool Context::hasMappedBuffer(GLenum target) const +void Context::releaseShaderCompiler() { - if (target == GL_ARRAY_BUFFER) - { - for (unsigned int attribIndex = 0; attribIndex < gl::MAX_VERTEX_ATTRIBS; attribIndex++) - { - const gl::VertexAttribute &vertexAttrib = mState.getVertexAttribState(attribIndex); - gl::Buffer *boundBuffer = vertexAttrib.buffer.get(); - if (vertexAttrib.enabled && boundBuffer && boundBuffer->isMapped()) - { - return true; - } - } - } - else if (target == GL_ELEMENT_ARRAY_BUFFER) - { - Buffer *elementBuffer = mState.getTargetBuffer(target); - return (elementBuffer && elementBuffer->isMapped()); - } - else if (target == GL_TRANSFORM_FEEDBACK_BUFFER) - { - UNIMPLEMENTED(); - } - else UNREACHABLE(); - return false; + mRenderer->releaseShaderCompiler(); } void Context::initCaps(GLuint clientVersion) @@ -2524,20 +2375,45 @@ void Context::initCaps(GLuint clientVersion) //mExtensions.sRGB = false; } + // Apply implementation limits + mCaps.maxVertexAttributes = std::min<GLuint>(mCaps.maxVertexAttributes, MAX_VERTEX_ATTRIBS); + mCaps.maxVertexUniformBlocks = std::min<GLuint>(mCaps.maxVertexUniformBlocks, IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS); + mCaps.maxVertexOutputComponents = std::min<GLuint>(mCaps.maxVertexOutputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4); + + mCaps.maxFragmentInputComponents = std::min<GLuint>(mCaps.maxFragmentInputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4); + + GLuint maxSamples = 0; + mCaps.compressedTextureFormats.clear(); + const TextureCapsMap &rendererFormats = mRenderer->getRendererTextureCaps(); for (TextureCapsMap::const_iterator i = rendererFormats.begin(); i != rendererFormats.end(); i++) { GLenum format = i->first; TextureCaps formatCaps = i->second; - if (formatCaps.texturable && IsValidInternalFormat(format, mExtensions, clientVersion)) + const InternalFormat &formatInfo = GetInternalFormatInfo(format); + + // Update the format caps based on the client version and extensions + formatCaps.texturable = formatInfo.textureSupport(clientVersion, mExtensions); + formatCaps.renderable = formatInfo.renderSupport(clientVersion, mExtensions); + formatCaps.filterable = formatInfo.filterSupport(clientVersion, mExtensions); + + // OpenGL ES does not support multisampling with integer formats + if (!formatInfo.renderSupport || formatInfo.componentType == GL_INT || formatInfo.componentType == GL_UNSIGNED_INT) + { + formatCaps.sampleCounts.clear(); + } + maxSamples = std::max(maxSamples, formatCaps.getMaxSamples()); + + if (formatCaps.texturable && formatInfo.compressed) { - // Update the format caps based on the client version and extensions - formatCaps.renderable = IsRenderingSupported(format, mExtensions, clientVersion); - formatCaps.filterable = IsFilteringSupported(format, mExtensions, clientVersion); - mTextureCaps.insert(format, formatCaps); + mCaps.compressedTextureFormats.push_back(format); } + + mTextureCaps.insert(format, formatCaps); } + + mExtensions.maxSamples = maxSamples; } } diff --git a/src/3rdparty/angle/src/libGLESv2/Context.h b/src/3rdparty/angle/src/libGLESv2/Context.h index 6c93c74e79..1b888aec83 100644 --- a/src/3rdparty/angle/src/libGLESv2/Context.h +++ b/src/3rdparty/angle/src/libGLESv2/Context.h @@ -10,23 +10,24 @@ #ifndef LIBGLESV2_CONTEXT_H_ #define LIBGLESV2_CONTEXT_H_ -#include "angle_gl.h" - -#include <string> -#include <set> -#include <map> -#include <unordered_map> -#include <array> - #include "common/angleutils.h" #include "common/RefCountObject.h" #include "libGLESv2/Caps.h" +#include "libGLESv2/Error.h" #include "libGLESv2/HandleAllocator.h" #include "libGLESv2/angletypes.h" #include "libGLESv2/Constants.h" #include "libGLESv2/VertexAttribute.h" #include "libGLESv2/State.h" +#include "angle_gl.h" + +#include <string> +#include <set> +#include <map> +#include <unordered_map> +#include <array> + namespace rx { class Renderer; @@ -114,10 +115,7 @@ class Context void bindArrayBuffer(GLuint buffer); void bindElementArrayBuffer(GLuint buffer); - void bindTexture2D(GLuint texture); - void bindTextureCubeMap(GLuint texture); - void bindTexture3D(GLuint texture); - void bindTexture2DArray(GLuint texture); + void bindTexture(GLenum target, GLuint texture); void bindReadFramebuffer(GLuint framebuffer); void bindDrawFramebuffer(GLuint framebuffer); void bindRenderbuffer(GLuint renderbuffer); @@ -133,11 +131,11 @@ class Context void bindPixelUnpackBuffer(GLuint buffer); void useProgram(GLuint program); void linkProgram(GLuint program); - void setProgramBinary(GLuint program, const void *binary, GLint length); + void setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length); void bindTransformFeedback(GLuint transformFeedback); - void beginQuery(GLenum target, GLuint query); - void endQuery(GLenum target); + Error beginQuery(GLenum target, GLuint query); + Error endQuery(GLenum target); void setFramebufferZero(Framebuffer *framebuffer); @@ -169,7 +167,7 @@ class Context Texture3D *getTexture3D() const; Texture2DArray *getTexture2DArray() const; - Texture *getSamplerTexture(unsigned int sampler, TextureType type) const; + Texture *getSamplerTexture(unsigned int sampler, GLenum type) const; bool isSampler(GLuint samplerName) const; @@ -184,22 +182,20 @@ class Context bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams); bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams); - void clear(GLbitfield mask); - void clearBufferfv(GLenum buffer, int drawbuffer, const float *values); - void clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values); - void clearBufferiv(GLenum buffer, int drawbuffer, const int *values); - void clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil); - - void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels); - void drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances); - void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances); + Error clear(GLbitfield mask); + Error clearBufferfv(GLenum buffer, int drawbuffer, const float *values); + Error clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values); + Error clearBufferiv(GLenum buffer, int drawbuffer, const int *values); + Error clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil); + + Error readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels); + Error drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances); + Error drawElements(GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei instances, + const rx::RangeUI &indexRange); void sync(bool block); // flush/finish - void recordInvalidEnum(); - void recordInvalidValue(); - void recordInvalidOperation(); - void recordOutOfMemory(); - void recordInvalidFramebufferOperation(); + void recordError(const Error &error); GLenum getError(); GLenum getResetStatus(); @@ -211,15 +207,6 @@ class Context const TextureCapsMap &getTextureCaps() const; const Extensions &getExtensions() const; - int getMajorShaderModel() const; - unsigned int getMaximumCombinedTextureImageUnits() const; - unsigned int getMaximumCombinedUniformBufferBindings() const; - GLsizei getMaxSupportedSamples() const; - GLsizei getMaxSupportedFormatSamples(GLenum internalFormat) const; - GLsizei getNumSampleCounts(GLenum internalFormat) const; - void getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const; - unsigned int getMaxTransformFeedbackBufferBindings() const; - GLintptr getUniformBufferOffsetAlignment() const; const std::string &getRendererString() const; const std::string &getExtensionString() const; @@ -231,29 +218,26 @@ class Context void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); - void invalidateFrameBuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, - GLint x, GLint y, GLsizei width, GLsizei height); - - bool hasMappedBuffer(GLenum target) const; - rx::Renderer *getRenderer() { return mRenderer; } State &getState() { return mState; } const State &getState() const { return mState; } + void releaseShaderCompiler(); + private: DISALLOW_COPY_AND_ASSIGN(Context); // TODO: std::array may become unavailable using older versions of GCC typedef std::array<unsigned int, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS> FramebufferTextureSerialArray; - bool applyRenderTarget(GLenum drawMode, bool ignoreViewport); - void applyState(GLenum drawMode); - void applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive); - void applyTextures(SamplerType shaderType, Texture *textures[], TextureType *textureTypes, SamplerState *samplers, - size_t textureCount, const FramebufferTextureSerialArray& framebufferSerials, - size_t framebufferSerialCount); - bool applyUniformBuffers(); + Error applyRenderTarget(GLenum drawMode, bool ignoreViewport); + Error applyState(GLenum drawMode); + Error applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive); + Error applyTextures(ProgramBinary *programBinary, SamplerType shaderType, const FramebufferTextureSerialArray &framebufferSerials, + size_t framebufferSerialCount); + Error applyTextures(ProgramBinary *programBinary); + Error applyUniformBuffers(); bool applyTransformFeedbackBuffers(); void markTransformFeedbackUsage(); @@ -265,10 +249,10 @@ class Context void detachTransformFeedback(GLuint transformFeedback); void detachSampler(GLuint sampler); - void generateSwizzles(Texture *textures[], size_t count); - size_t getCurrentTexturesAndSamplerStates(ProgramBinary *programBinary, SamplerType type, Texture **outTextures, - TextureType *outTextureTypes, SamplerState *outSamplers); - Texture *getIncompleteTexture(TextureType type); + Error generateSwizzles(ProgramBinary *programBinary, SamplerType type); + Error generateSwizzles(ProgramBinary *programBinary); + + Texture *getIncompleteTexture(GLenum type); bool skipDraw(GLenum drawMode); @@ -289,10 +273,9 @@ class Context int mClientVersion; - BindingPointer<Texture2D> mTexture2DZero; - BindingPointer<TextureCubeMap> mTextureCubeMapZero; - BindingPointer<Texture3D> mTexture3DZero; - BindingPointer<Texture2DArray> mTexture2DArrayZero; + typedef std::map< GLenum, BindingPointer<Texture> > TextureMap; + TextureMap mZeroTextures; + TextureMap mIncompleteTextures; typedef std::unordered_map<GLuint, Framebuffer*> FramebufferMap; FramebufferMap mFramebufferMap; @@ -319,14 +302,9 @@ class Context std::string mExtensionString; std::vector<std::string> mExtensionStrings; - BindingPointer<Texture> mIncompleteTextures[TEXTURE_TYPE_COUNT]; - // Recorded errors - bool mInvalidEnum; - bool mInvalidValue; - bool mInvalidOperation; - bool mOutOfMemory; - bool mInvalidFramebufferOperation; + typedef std::set<GLenum> ErrorSet; + ErrorSet mErrors; // Current/lost context flags bool mHasBeenCurrent; @@ -335,10 +313,6 @@ class Context GLenum mResetStrategy; bool mRobustAccess; - int mMajorShaderModel; - bool mSupportsVertexTexture; - int mNumCompressedTextureFormats; - ResourceManager *mResourceManager; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/DynamicHLSL.h b/src/3rdparty/angle/src/libGLESv2/DynamicHLSL.h deleted file mode 100644 index 68abd6e1a4..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/DynamicHLSL.h +++ /dev/null @@ -1,96 +0,0 @@ -// -// Copyright (c) 2014 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. -// -// DynamicHLSL.h: Interface for link and run-time HLSL generation -// - -#ifndef LIBGLESV2_DYNAMIC_HLSL_H_ -#define LIBGLESV2_DYNAMIC_HLSL_H_ - -#include "common/angleutils.h" -#include "libGLESv2/constants.h" - -namespace rx -{ -class Renderer; -} - -namespace sh -{ -struct Attribute; -struct ShaderVariable; -} - -namespace gl -{ - -class InfoLog; -class FragmentShader; -class VertexShader; -struct VariableLocation; -struct LinkedVarying; -struct VertexAttribute; -struct VertexFormat; -struct PackedVarying; - -typedef const PackedVarying *VaryingPacking[IMPLEMENTATION_MAX_VARYING_VECTORS][4]; - -struct PixelShaderOuputVariable -{ - GLenum type; - std::string name; - std::string source; - size_t outputIndex; -}; - -class DynamicHLSL -{ - public: - explicit DynamicHLSL(rx::Renderer *const renderer); - - int packVaryings(InfoLog &infoLog, VaryingPacking packing, FragmentShader *fragmentShader, - VertexShader *vertexShader, const std::vector<std::string>& transformFeedbackVaryings); - std::string generateVertexShaderForInputLayout(const std::string &sourceShader, const VertexFormat inputLayout[], - const sh::Attribute shaderAttributes[]) const; - std::string generatePixelShaderForOutputSignature(const std::string &sourceShader, const std::vector<PixelShaderOuputVariable> &outputVariables, - bool usesFragDepth, const std::vector<GLenum> &outputLayout) const; - bool generateShaderLinkHLSL(InfoLog &infoLog, int registers, const VaryingPacking packing, - std::string& pixelHLSL, std::string& vertexHLSL, - FragmentShader *fragmentShader, VertexShader *vertexShader, - const std::vector<std::string>& transformFeedbackVaryings, - std::vector<LinkedVarying> *linkedVaryings, - std::map<int, VariableLocation> *programOutputVars, - std::vector<PixelShaderOuputVariable> *outPixelShaderKey, - bool *outUsesFragDepth) const; - - std::string generateGeometryShaderHLSL(int registers, FragmentShader *fragmentShader, VertexShader *vertexShader) const; - void getInputLayoutSignature(const VertexFormat inputLayout[], GLenum signature[]) const; - - private: - DISALLOW_COPY_AND_ASSIGN(DynamicHLSL); - - rx::Renderer *const mRenderer; - - struct SemanticInfo; - - std::string getVaryingSemantic(bool pointSize) const; - SemanticInfo getSemanticInfo(int startRegisters, bool fragCoord, bool pointCoord, bool pointSize, - bool pixelShader) const; - std::string generateVaryingLinkHLSL(const SemanticInfo &info, const std::string &varyingHLSL) const; - std::string generateVaryingHLSL(VertexShader *shader) const; - void storeUserLinkedVaryings(const VertexShader *vertexShader, std::vector<LinkedVarying> *linkedVaryings) const; - void storeBuiltinLinkedVaryings(const SemanticInfo &info, std::vector<LinkedVarying> *linkedVaryings) const; - void defineOutputVariables(FragmentShader *fragmentShader, std::map<int, VariableLocation> *programOutputVars) const; - std::string generatePointSpriteHLSL(int registers, FragmentShader *fragmentShader, VertexShader *vertexShader) const; - - // Prepend an underscore - static std::string decorateVariable(const std::string &name); - - std::string generateAttributeConversionHLSL(const VertexFormat &vertexFormat, const sh::ShaderVariable &shaderAttrib) const; -}; - -} - -#endif // LIBGLESV2_DYNAMIC_HLSL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Error.cpp b/src/3rdparty/angle/src/libGLESv2/Error.cpp new file mode 100644 index 0000000000..cc7d17eb37 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/Error.cpp @@ -0,0 +1,48 @@ +// +// Copyright (c) 2014 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. +// + +// Error.cpp: Implements the gl::Error class which encapsulates an OpenGL error +// and optional error message. + +#include "libGLESv2/Error.h" + +#include "common/angleutils.h" + +#include <cstdarg> + +namespace gl +{ + +Error::Error(GLenum errorCode) + : mCode(errorCode), + mMessage() +{ +} + +Error::Error(GLenum errorCode, const char *msg, ...) + : mCode(errorCode), + mMessage() +{ + va_list vararg; + va_start(vararg, msg); + mMessage = FormatString(msg, vararg); + va_end(vararg); +} + +Error::Error(const Error &other) + : mCode(other.mCode), + mMessage(other.mMessage) +{ +} + +Error &Error::operator=(const Error &other) +{ + mCode = other.mCode; + mMessage = other.mMessage; + return *this; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/Error.h b/src/3rdparty/angle/src/libGLESv2/Error.h new file mode 100644 index 0000000000..b70b5a531c --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/Error.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2014 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. + +// Error.h: Defines the gl::Error class which encapsulates an OpenGL error +// and optional error message. + +#ifndef LIBGLESV2_ERROR_H_ +#define LIBGLESV2_ERROR_H_ + +#include "angle_gl.h" + +#include <string> + +namespace gl +{ + +class Error +{ + public: + explicit Error(GLenum errorCode); + Error(GLenum errorCode, const char *msg, ...); + Error(const Error &other); + Error &operator=(const Error &other); + + GLenum getCode() const { return mCode; } + bool isError() const { return (mCode != GL_NO_ERROR); } + + const std::string &getMessage() const { return mMessage; } + + private: + GLenum mCode; + std::string mMessage; +}; + +} + +#endif // LIBGLESV2_ERROR_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Fence.cpp b/src/3rdparty/angle/src/libGLESv2/Fence.cpp index 31d149d629..ee9a07a5c4 100644 --- a/src/3rdparty/angle/src/libGLESv2/Fence.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Fence.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -23,6 +22,8 @@ #include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/main.h" +#include "angle_gl.h" + namespace gl { diff --git a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp b/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp index b90d2f6023..5bf7b3fce8 100644 --- a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp index f808175250..5b21433f90 100644 --- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -9,15 +8,60 @@ // objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105. #include "libGLESv2/Framebuffer.h" - #include "libGLESv2/main.h" -#include "common/utilities.h" #include "libGLESv2/formatutils.h" #include "libGLESv2/Texture.h" #include "libGLESv2/Context.h" -#include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/Renderbuffer.h" #include "libGLESv2/FramebufferAttachment.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/RenderTarget.h" +#include "libGLESv2/renderer/d3d/TextureD3D.h" + +#include "common/utilities.h" + +namespace rx +{ +RenderTarget *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment) +{ + if (attachment->isTexture()) + { + gl::Texture *texture = attachment->getTexture(); + ASSERT(texture); + TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation()); + const gl::ImageIndex *index = attachment->getTextureImageIndex(); + ASSERT(index); + return textureD3D->getRenderTarget(*index); + } + + gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer(); + ASSERT(renderbuffer); + + // TODO: cast to RenderbufferD3D + return renderbuffer->getStorage()->getRenderTarget(); +} + +// Note: RenderTarget serials should ideally be in the RenderTargets themselves. +unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment) +{ + if (attachment->isTexture()) + { + gl::Texture *texture = attachment->getTexture(); + ASSERT(texture); + TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation()); + const gl::ImageIndex *index = attachment->getTextureImageIndex(); + ASSERT(index); + return textureD3D->getRenderTargetSerial(*index); + } + + gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer(); + ASSERT(renderbuffer); + + // TODO: cast to RenderbufferD3D + return renderbuffer->getStorage()->getSerial(); +} + +} namespace gl { @@ -47,7 +91,7 @@ Framebuffer::~Framebuffer() SafeDelete(mStencilbuffer); } -FramebufferAttachment *Framebuffer::createAttachment(GLenum type, GLuint handle, GLint level, GLint layer) const +FramebufferAttachment *Framebuffer::createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const { if (handle == 0) { @@ -62,15 +106,14 @@ FramebufferAttachment *Framebuffer::createAttachment(GLenum type, GLuint handle, return NULL; case GL_RENDERBUFFER: - return new RenderbufferAttachment(context->getRenderbuffer(handle)); + return new RenderbufferAttachment(binding, context->getRenderbuffer(handle)); case GL_TEXTURE_2D: { Texture *texture = context->getTexture(handle); if (texture && texture->getTarget() == GL_TEXTURE_2D) { - Texture2D *tex2D = static_cast<Texture2D*>(texture); - return new Texture2DAttachment(tex2D, level); + return new TextureAttachment(binding, texture, ImageIndex::Make2D(level)); } else { @@ -88,8 +131,7 @@ FramebufferAttachment *Framebuffer::createAttachment(GLenum type, GLuint handle, Texture *texture = context->getTexture(handle); if (texture && texture->getTarget() == GL_TEXTURE_CUBE_MAP) { - TextureCubeMap *texCube = static_cast<TextureCubeMap*>(texture); - return new TextureCubeMapAttachment(texCube, type, level); + return new TextureAttachment(binding, texture, ImageIndex::MakeCube(type, level)); } else { @@ -102,8 +144,7 @@ FramebufferAttachment *Framebuffer::createAttachment(GLenum type, GLuint handle, Texture *texture = context->getTexture(handle); if (texture && texture->getTarget() == GL_TEXTURE_3D) { - Texture3D *tex3D = static_cast<Texture3D*>(texture); - return new Texture3DAttachment(tex3D, level, layer); + return new TextureAttachment(binding, texture, ImageIndex::Make3D(level, layer)); } else { @@ -116,8 +157,7 @@ FramebufferAttachment *Framebuffer::createAttachment(GLenum type, GLuint handle, Texture *texture = context->getTexture(handle); if (texture && texture->getTarget() == GL_TEXTURE_2D_ARRAY) { - Texture2DArray *tex2DArray = static_cast<Texture2DArray*>(texture); - return new Texture2DArrayAttachment(tex2DArray, level, layer); + return new TextureAttachment(binding, texture, ImageIndex::Make2DArray(level, layer)); } else { @@ -135,24 +175,25 @@ void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLui { ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); SafeDelete(mColorbuffers[colorAttachment]); - mColorbuffers[colorAttachment] = createAttachment(type, colorbuffer, level, layer); + GLenum binding = colorAttachment + GL_COLOR_ATTACHMENT0; + mColorbuffers[colorAttachment] = createAttachment(binding, type, colorbuffer, level, layer); } void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer) { SafeDelete(mDepthbuffer); - mDepthbuffer = createAttachment(type, depthbuffer, level, layer); + mDepthbuffer = createAttachment(GL_DEPTH_ATTACHMENT, type, depthbuffer, level, layer); } void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer) { SafeDelete(mStencilbuffer); - mStencilbuffer = createAttachment(type, stencilbuffer, level, layer); + mStencilbuffer = createAttachment(GL_STENCIL_ATTACHMENT, type, stencilbuffer, level, layer); } void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer) { - FramebufferAttachment *attachment = createAttachment(type, depthStencilBuffer, level, layer); + FramebufferAttachment *attachment = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer); SafeDelete(mDepthbuffer); SafeDelete(mStencilbuffer); @@ -164,7 +205,7 @@ void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, // Make a new attachment object to ensure we do not double-delete // See angle issue 686 - mStencilbuffer = createAttachment(type, depthStencilBuffer, level, layer); + mStencilbuffer = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer); } } @@ -364,6 +405,7 @@ GLenum Framebuffer::completeness() const GLenum internalformat = colorbuffer->getInternalFormat(); // TODO(geofflang): use context's texture caps const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat); + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); if (colorbuffer->isTexture()) { if (!formatCaps.renderable) @@ -371,14 +413,14 @@ GLenum Framebuffer::completeness() const return GL_FRAMEBUFFER_UNSUPPORTED; } - if (gl::GetDepthBits(internalformat) > 0 || gl::GetStencilBits(internalformat) > 0) + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } else { - if (!formatCaps.renderable || gl::GetDepthBits(internalformat) > 0 || gl::GetStencilBits(internalformat) > 0) + if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } @@ -403,7 +445,7 @@ GLenum Framebuffer::completeness() const // in GLES 3.0, there is no such restriction if (clientVersion < 3) { - if (gl::GetPixelBytes(colorbuffer->getInternalFormat()) != colorbufferSize) + if (formatInfo.pixelBytes != colorbufferSize) { return GL_FRAMEBUFFER_UNSUPPORTED; } @@ -427,7 +469,7 @@ GLenum Framebuffer::completeness() const width = colorbuffer->getWidth(); height = colorbuffer->getHeight(); samples = colorbuffer->getSamples(); - colorbufferSize = gl::GetPixelBytes(colorbuffer->getInternalFormat()); + colorbufferSize = formatInfo.pixelBytes; missingAttachment = false; } } @@ -443,10 +485,9 @@ GLenum Framebuffer::completeness() const GLenum internalformat = mDepthbuffer->getInternalFormat(); // TODO(geofflang): use context's texture caps const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat); + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); if (mDepthbuffer->isTexture()) { - GLenum internalformat = mDepthbuffer->getInternalFormat(); - // depth texture attachments require OES/ANGLE_depth_texture // TODO(geofflang): use context's extensions if (!mRenderer->getRendererExtensions().depthTextures) @@ -459,14 +500,14 @@ GLenum Framebuffer::completeness() const return GL_FRAMEBUFFER_UNSUPPORTED; } - if (gl::GetDepthBits(internalformat) == 0) + if (formatInfo.depthBits == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } else { - if (!formatCaps.renderable || gl::GetDepthBits(internalformat) == 0) + if (!formatCaps.renderable || formatInfo.depthBits == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } @@ -499,10 +540,9 @@ GLenum Framebuffer::completeness() const GLenum internalformat = mStencilbuffer->getInternalFormat(); // TODO(geofflang): use context's texture caps const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat); + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); if (mStencilbuffer->isTexture()) { - GLenum internalformat = mStencilbuffer->getInternalFormat(); - // texture stencil attachments come along as part // of OES_packed_depth_stencil + OES/ANGLE_depth_texture // TODO(geofflang): use context's extensions @@ -516,14 +556,14 @@ GLenum Framebuffer::completeness() const return GL_FRAMEBUFFER_UNSUPPORTED; } - if (gl::GetStencilBits(internalformat) == 0) + if (formatInfo.stencilBits == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } else { - if (!formatCaps.renderable || gl::GetStencilBits(internalformat) == 0) + if (!formatCaps.renderable || formatInfo.stencilBits == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } @@ -562,18 +602,47 @@ GLenum Framebuffer::completeness() const return GL_FRAMEBUFFER_COMPLETE; } +void Framebuffer::invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments) +{ + GLuint maxDimension = caps.maxRenderbufferSize; + invalidateSub(caps, numAttachments, attachments, 0, 0, maxDimension, maxDimension); +} + +void Framebuffer::invalidateSub(const Caps &caps, GLsizei numAttachments, const GLenum *attachments, + GLint x, GLint y, GLsizei width, GLsizei height) +{ + ASSERT(completeness() == GL_FRAMEBUFFER_COMPLETE); + for (GLsizei attachIndex = 0; attachIndex < numAttachments; ++attachIndex) + { + GLenum attachmentTarget = attachments[attachIndex]; + + gl::FramebufferAttachment *attachment = + (attachmentTarget == GL_DEPTH_STENCIL_ATTACHMENT) ? getDepthOrStencilbuffer() : + getAttachment(attachmentTarget); + + if (attachment) + { + rx::RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment); + if (renderTarget) + { + renderTarget->invalidate(x, y, width, height); + } + } + } +} + DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil) : Framebuffer(renderer, 0) { Renderbuffer *colorRenderbuffer = new Renderbuffer(0, colorbuffer); - mColorbuffers[0] = new RenderbufferAttachment(colorRenderbuffer); + mColorbuffers[0] = new RenderbufferAttachment(GL_BACK, colorRenderbuffer); Renderbuffer *depthStencilBuffer = new Renderbuffer(0, depthStencil); // Make a new attachment objects to ensure we do not double-delete // See angle issue 686 - mDepthbuffer = (depthStencilBuffer->getDepthSize() != 0 ? new RenderbufferAttachment(depthStencilBuffer) : NULL); - mStencilbuffer = (depthStencilBuffer->getStencilSize() != 0 ? new RenderbufferAttachment(depthStencilBuffer) : NULL); + mDepthbuffer = (depthStencilBuffer->getDepthSize() != 0 ? new RenderbufferAttachment(GL_DEPTH_ATTACHMENT, depthStencilBuffer) : NULL); + mStencilbuffer = (depthStencilBuffer->getStencilSize() != 0 ? new RenderbufferAttachment(GL_STENCIL_ATTACHMENT, depthStencilBuffer) : NULL); mDrawBufferStates[0] = GL_BACK; mReadBufferState = GL_BACK; @@ -606,6 +675,31 @@ bool Framebuffer::hasValidDepthStencil() const mDepthbuffer->id() == mStencilbuffer->id()); } +ColorbufferInfo Framebuffer::getColorbuffersForRender() const +{ + ColorbufferInfo colorbuffersForRender; + + for (size_t colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; ++colorAttachment) + { + GLenum drawBufferState = mDrawBufferStates[colorAttachment]; + FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment]; + + if (colorbuffer != NULL && drawBufferState != GL_NONE) + { + ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment)); + colorbuffersForRender.push_back(colorbuffer); + } +#if (ANGLE_MRT_PERF_WORKAROUND == ANGLE_WORKAROUND_DISABLED) + else + { + colorbuffersForRender.push_back(NULL); + } +#endif + } + + return colorbuffersForRender; +} + GLenum DefaultFramebuffer::completeness() const { // The default framebuffer *must* always be complete, though it may not be @@ -617,6 +711,7 @@ FramebufferAttachment *DefaultFramebuffer::getAttachment(GLenum attachment) cons { switch (attachment) { + case GL_COLOR: case GL_BACK: return getColorbuffer(0); case GL_DEPTH: diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h index 035e16fa45..cc12d22953 100644 --- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h @@ -10,6 +10,8 @@ #ifndef LIBGLESV2_FRAMEBUFFER_H_ #define LIBGLESV2_FRAMEBUFFER_H_ +#include <vector> + #include "common/angleutils.h" #include "common/RefCountObject.h" #include "constants.h" @@ -26,6 +28,9 @@ class Colorbuffer; class Depthbuffer; class Stencilbuffer; class DepthStencilbuffer; +struct Caps; + +typedef std::vector<FramebufferAttachment *> ColorbufferInfo; class Framebuffer { @@ -67,6 +72,15 @@ class Framebuffer virtual GLenum completeness() const; bool hasValidDepthStencil() const; + void invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments); + void invalidateSub(const Caps &caps, GLsizei numAttachments, const GLenum *attachments, + GLint x, GLint y, GLsizei width, GLsizei height); + + // Use this method to retrieve the color buffer map when doing rendering. + // It will apply a workaround for poor shader performance on some systems + // by compacting the list to skip NULL values. + ColorbufferInfo getColorbuffersForRender() const; + protected: rx::Renderer *mRenderer; @@ -79,10 +93,10 @@ class Framebuffer FramebufferAttachment *mDepthbuffer; FramebufferAttachment *mStencilbuffer; -private: + private: DISALLOW_COPY_AND_ASSIGN(Framebuffer); - FramebufferAttachment *createAttachment(GLenum type, GLuint handle, GLint level, GLint layer) const; + FramebufferAttachment *createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const; }; class DefaultFramebuffer : public Framebuffer @@ -99,4 +113,14 @@ class DefaultFramebuffer : public Framebuffer } +namespace rx +{ +class RenderTarget; + +// TODO: place this in FramebufferD3D.h +RenderTarget *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment); +unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment); + +} + #endif // LIBGLESV2_FRAMEBUFFER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp index 5855301c97..540ede1cd2 100644 --- a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp +++ b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -9,21 +8,22 @@ // objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. #include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/renderer/RenderTarget.h" - #include "libGLESv2/Texture.h" +#include "libGLESv2/formatutils.h" +#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/renderer/RenderTarget.h" #include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/renderer/d3d/TextureStorage.h" + #include "common/utilities.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/Renderbuffer.h" namespace gl { ////// FramebufferAttachment Implementation ////// -FramebufferAttachment::FramebufferAttachment() +FramebufferAttachment::FramebufferAttachment(GLenum binding) + : mBinding(binding) { } @@ -33,42 +33,42 @@ FramebufferAttachment::~FramebufferAttachment() GLuint FramebufferAttachment::getRedSize() const { - return (gl::GetRedBits(getInternalFormat()) > 0) ? gl::GetRedBits(getActualFormat()) : 0; + return (GetInternalFormatInfo(getInternalFormat()).redBits > 0) ? GetInternalFormatInfo(getActualFormat()).redBits : 0; } GLuint FramebufferAttachment::getGreenSize() const { - return (gl::GetGreenBits(getInternalFormat()) > 0) ? gl::GetGreenBits(getActualFormat()) : 0; + return (GetInternalFormatInfo(getInternalFormat()).greenBits > 0) ? GetInternalFormatInfo(getActualFormat()).greenBits : 0; } GLuint FramebufferAttachment::getBlueSize() const { - return (gl::GetBlueBits(getInternalFormat()) > 0) ? gl::GetBlueBits(getActualFormat()) : 0; + return (GetInternalFormatInfo(getInternalFormat()).blueBits > 0) ? GetInternalFormatInfo(getActualFormat()).blueBits : 0; } GLuint FramebufferAttachment::getAlphaSize() const { - return (gl::GetAlphaBits(getInternalFormat()) > 0) ? gl::GetAlphaBits(getActualFormat()) : 0; + return (GetInternalFormatInfo(getInternalFormat()).alphaBits > 0) ? GetInternalFormatInfo(getActualFormat()).alphaBits : 0; } GLuint FramebufferAttachment::getDepthSize() const { - return (gl::GetDepthBits(getInternalFormat()) > 0) ? gl::GetDepthBits(getActualFormat()) : 0; + return (GetInternalFormatInfo(getInternalFormat()).depthBits > 0) ? GetInternalFormatInfo(getActualFormat()).depthBits : 0; } GLuint FramebufferAttachment::getStencilSize() const { - return (gl::GetStencilBits(getInternalFormat()) > 0) ? gl::GetStencilBits(getActualFormat()) : 0; + return (GetInternalFormatInfo(getInternalFormat()).stencilBits > 0) ? GetInternalFormatInfo(getActualFormat()).stencilBits : 0; } GLenum FramebufferAttachment::getComponentType() const { - return gl::GetComponentType(getActualFormat()); + return GetInternalFormatInfo(getActualFormat()).componentType; } GLenum FramebufferAttachment::getColorEncoding() const { - return gl::GetColorEncoding(getActualFormat()); + return GetInternalFormatInfo(getActualFormat()).colorEncoding; } bool FramebufferAttachment::isTexture() const @@ -76,340 +76,85 @@ bool FramebufferAttachment::isTexture() const return (type() != GL_RENDERBUFFER); } -///// Texture2DAttachment Implementation //////// - -Texture2DAttachment::Texture2DAttachment(Texture2D *texture, GLint level) : mLevel(level) -{ - mTexture2D.set(texture); -} - -Texture2DAttachment::~Texture2DAttachment() -{ - mTexture2D.set(NULL); -} - -rx::RenderTarget *Texture2DAttachment::getRenderTarget() -{ - return mTexture2D->getRenderTarget(mLevel); -} - -rx::RenderTarget *Texture2DAttachment::getDepthStencil() -{ - return mTexture2D->getDepthSencil(mLevel); -} - -rx::TextureStorage *Texture2DAttachment::getTextureStorage() -{ - return mTexture2D->getNativeTexture()->getStorageInstance(); -} - -GLsizei Texture2DAttachment::getWidth() const -{ - return mTexture2D->getWidth(mLevel); -} - -GLsizei Texture2DAttachment::getHeight() const -{ - return mTexture2D->getHeight(mLevel); -} - -GLenum Texture2DAttachment::getInternalFormat() const -{ - return mTexture2D->getInternalFormat(mLevel); -} - -GLenum Texture2DAttachment::getActualFormat() const -{ - return mTexture2D->getActualFormat(mLevel); -} - -GLsizei Texture2DAttachment::getSamples() const -{ - return 0; -} - -unsigned int Texture2DAttachment::getSerial() const -{ - return mTexture2D->getRenderTargetSerial(mLevel); -} - -GLuint Texture2DAttachment::id() const -{ - return mTexture2D->id(); -} - -GLenum Texture2DAttachment::type() const -{ - return GL_TEXTURE_2D; -} - -GLint Texture2DAttachment::mipLevel() const -{ - return mLevel; -} - -GLint Texture2DAttachment::layer() const -{ - return 0; -} - -unsigned int Texture2DAttachment::getTextureSerial() const -{ - return mTexture2D->getTextureSerial(); -} - -///// TextureCubeMapAttachment Implementation //////// - -TextureCubeMapAttachment::TextureCubeMapAttachment(TextureCubeMap *texture, GLenum faceTarget, GLint level) - : mFaceTarget(faceTarget), mLevel(level) -{ - mTextureCubeMap.set(texture); -} - -TextureCubeMapAttachment::~TextureCubeMapAttachment() -{ - mTextureCubeMap.set(NULL); -} - -rx::RenderTarget *TextureCubeMapAttachment::getRenderTarget() -{ - return mTextureCubeMap->getRenderTarget(mFaceTarget, mLevel); -} - -rx::RenderTarget *TextureCubeMapAttachment::getDepthStencil() -{ - return mTextureCubeMap->getDepthStencil(mFaceTarget, mLevel); -} - -rx::TextureStorage *TextureCubeMapAttachment::getTextureStorage() -{ - return mTextureCubeMap->getNativeTexture()->getStorageInstance(); -} - -GLsizei TextureCubeMapAttachment::getWidth() const -{ - return mTextureCubeMap->getWidth(mFaceTarget, mLevel); -} - -GLsizei TextureCubeMapAttachment::getHeight() const -{ - return mTextureCubeMap->getHeight(mFaceTarget, mLevel); -} - -GLenum TextureCubeMapAttachment::getInternalFormat() const -{ - return mTextureCubeMap->getInternalFormat(mFaceTarget, mLevel); -} - -GLenum TextureCubeMapAttachment::getActualFormat() const -{ - return mTextureCubeMap->getActualFormat(mFaceTarget, mLevel); -} - -GLsizei TextureCubeMapAttachment::getSamples() const -{ - return 0; -} - -unsigned int TextureCubeMapAttachment::getSerial() const -{ - return mTextureCubeMap->getRenderTargetSerial(mFaceTarget, mLevel); -} - -GLuint TextureCubeMapAttachment::id() const -{ - return mTextureCubeMap->id(); -} - -GLenum TextureCubeMapAttachment::type() const -{ - return mFaceTarget; -} - -GLint TextureCubeMapAttachment::mipLevel() const -{ - return mLevel; -} - -GLint TextureCubeMapAttachment::layer() const -{ - return 0; -} - -unsigned int TextureCubeMapAttachment::getTextureSerial() const -{ - return mTextureCubeMap->getTextureSerial(); -} - -///// Texture3DAttachment Implementation //////// - -Texture3DAttachment::Texture3DAttachment(Texture3D *texture, GLint level, GLint layer) - : mLevel(level), mLayer(layer) -{ - mTexture3D.set(texture); -} - -Texture3DAttachment::~Texture3DAttachment() -{ - mTexture3D.set(NULL); -} - -rx::RenderTarget *Texture3DAttachment::getRenderTarget() -{ - return mTexture3D->getRenderTarget(mLevel, mLayer); -} - -rx::RenderTarget *Texture3DAttachment::getDepthStencil() -{ - return mTexture3D->getDepthStencil(mLevel, mLayer); -} - -rx::TextureStorage *Texture3DAttachment::getTextureStorage() -{ - return mTexture3D->getNativeTexture()->getStorageInstance(); -} - -GLsizei Texture3DAttachment::getWidth() const -{ - return mTexture3D->getWidth(mLevel); -} - -GLsizei Texture3DAttachment::getHeight() const -{ - return mTexture3D->getHeight(mLevel); -} +///// TextureAttachment Implementation //////// -GLenum Texture3DAttachment::getInternalFormat() const +TextureAttachment::TextureAttachment(GLenum binding, Texture *texture, const ImageIndex &index) + : FramebufferAttachment(binding), + mIndex(index) { - return mTexture3D->getInternalFormat(mLevel); + mTexture.set(texture); } -GLenum Texture3DAttachment::getActualFormat() const +TextureAttachment::~TextureAttachment() { - return mTexture3D->getActualFormat(mLevel); + mTexture.set(NULL); } -GLsizei Texture3DAttachment::getSamples() const +GLsizei TextureAttachment::getSamples() const { return 0; } -unsigned int Texture3DAttachment::getSerial() const -{ - return mTexture3D->getRenderTargetSerial(mLevel, mLayer); -} - -GLuint Texture3DAttachment::id() const -{ - return mTexture3D->id(); -} - -GLenum Texture3DAttachment::type() const -{ - return GL_TEXTURE_3D; -} - -GLint Texture3DAttachment::mipLevel() const -{ - return mLevel; -} - -GLint Texture3DAttachment::layer() const -{ - return mLayer; -} - -unsigned int Texture3DAttachment::getTextureSerial() const -{ - return mTexture3D->getTextureSerial(); -} - -////// Texture2DArrayAttachment Implementation ////// - -Texture2DArrayAttachment::Texture2DArrayAttachment(Texture2DArray *texture, GLint level, GLint layer) - : mLevel(level), mLayer(layer) -{ - mTexture2DArray.set(texture); -} - -Texture2DArrayAttachment::~Texture2DArrayAttachment() -{ - mTexture2DArray.set(NULL); -} - -rx::RenderTarget *Texture2DArrayAttachment::getRenderTarget() +GLuint TextureAttachment::id() const { - return mTexture2DArray->getRenderTarget(mLevel, mLayer); + return mTexture->id(); } -rx::RenderTarget *Texture2DArrayAttachment::getDepthStencil() +GLsizei TextureAttachment::getWidth() const { - return mTexture2DArray->getDepthStencil(mLevel, mLayer); + return mTexture->getWidth(mIndex); } -rx::TextureStorage *Texture2DArrayAttachment::getTextureStorage() +GLsizei TextureAttachment::getHeight() const { - return mTexture2DArray->getNativeTexture()->getStorageInstance(); + return mTexture->getHeight(mIndex); } -GLsizei Texture2DArrayAttachment::getWidth() const +GLenum TextureAttachment::getInternalFormat() const { - return mTexture2DArray->getWidth(mLevel); + return mTexture->getInternalFormat(mIndex); } -GLsizei Texture2DArrayAttachment::getHeight() const +GLenum TextureAttachment::getActualFormat() const { - return mTexture2DArray->getHeight(mLevel); + return mTexture->getActualFormat(mIndex); } -GLenum Texture2DArrayAttachment::getInternalFormat() const +GLenum TextureAttachment::type() const { - return mTexture2DArray->getInternalFormat(mLevel); + return mIndex.type; } -GLenum Texture2DArrayAttachment::getActualFormat() const +GLint TextureAttachment::mipLevel() const { - return mTexture2DArray->getActualFormat(mLevel); + return mIndex.mipIndex; } -GLsizei Texture2DArrayAttachment::getSamples() const +GLint TextureAttachment::layer() const { - return 0; -} - -unsigned int Texture2DArrayAttachment::getSerial() const -{ - return mTexture2DArray->getRenderTargetSerial(mLevel, mLayer); -} - -GLuint Texture2DArrayAttachment::id() const -{ - return mTexture2DArray->id(); -} - -GLenum Texture2DArrayAttachment::type() const -{ - return GL_TEXTURE_2D_ARRAY; + return mIndex.layerIndex; } -GLint Texture2DArrayAttachment::mipLevel() const +Texture *TextureAttachment::getTexture() { - return mLevel; + return mTexture.get(); } -GLint Texture2DArrayAttachment::layer() const +const ImageIndex *TextureAttachment::getTextureImageIndex() const { - return mLayer; + return &mIndex; } -unsigned int Texture2DArrayAttachment::getTextureSerial() const +Renderbuffer *TextureAttachment::getRenderbuffer() { - return mTexture2DArray->getTextureSerial(); + UNREACHABLE(); + return NULL; } ////// RenderbufferAttachment Implementation ////// -RenderbufferAttachment::RenderbufferAttachment(Renderbuffer *renderbuffer) +RenderbufferAttachment::RenderbufferAttachment(GLenum binding, Renderbuffer *renderbuffer) + : FramebufferAttachment(binding) { ASSERT(renderbuffer); mRenderbuffer.set(renderbuffer); @@ -420,22 +165,6 @@ RenderbufferAttachment::~RenderbufferAttachment() mRenderbuffer.set(NULL); } -rx::RenderTarget *RenderbufferAttachment::getRenderTarget() -{ - return mRenderbuffer->getStorage()->getRenderTarget(); -} - -rx::RenderTarget *RenderbufferAttachment::getDepthStencil() -{ - return mRenderbuffer->getStorage()->getDepthStencil(); -} - -rx::TextureStorage *RenderbufferAttachment::getTextureStorage() -{ - UNREACHABLE(); - return NULL; -} - GLsizei RenderbufferAttachment::getWidth() const { return mRenderbuffer->getWidth(); @@ -461,11 +190,6 @@ GLsizei RenderbufferAttachment::getSamples() const return mRenderbuffer->getStorage()->getSamples(); } -unsigned int RenderbufferAttachment::getSerial() const -{ - return mRenderbuffer->getStorage()->getSerial(); -} - GLuint RenderbufferAttachment::id() const { return mRenderbuffer->id(); @@ -486,10 +210,21 @@ GLint RenderbufferAttachment::layer() const return 0; } -unsigned int RenderbufferAttachment::getTextureSerial() const +Texture *RenderbufferAttachment::getTexture() { UNREACHABLE(); - return 0; + return NULL; +} + +const ImageIndex *RenderbufferAttachment::getTextureImageIndex() const +{ + UNREACHABLE(); + return NULL; +} + +Renderbuffer *RenderbufferAttachment::getRenderbuffer() +{ + return mRenderbuffer.get(); } } diff --git a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h index 18768f9831..c18ef7364d 100644 --- a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h +++ b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h @@ -10,10 +10,11 @@ #ifndef LIBGLESV2_FRAMEBUFFERATTACHMENT_H_ #define LIBGLESV2_FRAMEBUFFERATTACHMENT_H_ -#include "angle_gl.h" - #include "common/angleutils.h" #include "common/RefCountObject.h" +#include "Texture.h" + +#include "angle_gl.h" namespace rx { @@ -24,10 +25,6 @@ class TextureStorage; namespace gl { -class Texture2D; -class TextureCubeMap; -class Texture3D; -class Texture2DArray; class Renderbuffer; // FramebufferAttachment implements a GL framebuffer attachment. @@ -39,7 +36,7 @@ class Renderbuffer; class FramebufferAttachment { public: - FramebufferAttachment(); + explicit FramebufferAttachment(GLenum binding); virtual ~FramebufferAttachment(); // Helper methods @@ -56,184 +53,80 @@ class FramebufferAttachment bool isTextureWithId(GLuint textureId) const { return isTexture() && id() == textureId; } bool isRenderbufferWithId(GLuint renderbufferId) const { return !isTexture() && id() == renderbufferId; } - // Child class interface - virtual rx::RenderTarget *getRenderTarget() = 0; - virtual rx::RenderTarget *getDepthStencil() = 0; - virtual rx::TextureStorage *getTextureStorage() = 0; + GLenum getBinding() const { return mBinding; } + // Child class interface virtual GLsizei getWidth() const = 0; virtual GLsizei getHeight() const = 0; virtual GLenum getInternalFormat() const = 0; virtual GLenum getActualFormat() const = 0; virtual GLsizei getSamples() const = 0; - virtual unsigned int getSerial() const = 0; - virtual GLuint id() const = 0; virtual GLenum type() const = 0; virtual GLint mipLevel() const = 0; virtual GLint layer() const = 0; - virtual unsigned int getTextureSerial() const = 0; - private: - DISALLOW_COPY_AND_ASSIGN(FramebufferAttachment); -}; - -class Texture2DAttachment : public FramebufferAttachment -{ - public: - Texture2DAttachment(Texture2D *texture, GLint level); - - virtual ~Texture2DAttachment(); - - rx::RenderTarget *getRenderTarget(); - rx::RenderTarget *getDepthStencil(); - rx::TextureStorage *getTextureStorage(); - - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLenum getInternalFormat() const; - virtual GLenum getActualFormat() const; - virtual GLsizei getSamples() const; - - virtual unsigned int getSerial() const; - - virtual GLuint id() const; - virtual GLenum type() const; - virtual GLint mipLevel() const; - virtual GLint layer() const; - virtual unsigned int getTextureSerial() const; + virtual Texture *getTexture() = 0; + virtual const ImageIndex *getTextureImageIndex() const = 0; + virtual Renderbuffer *getRenderbuffer() = 0; private: - DISALLOW_COPY_AND_ASSIGN(Texture2DAttachment); + DISALLOW_COPY_AND_ASSIGN(FramebufferAttachment); - BindingPointer<Texture2D> mTexture2D; - const GLint mLevel; + GLenum mBinding; }; -class TextureCubeMapAttachment : public FramebufferAttachment +class TextureAttachment : public FramebufferAttachment { public: - TextureCubeMapAttachment(TextureCubeMap *texture, GLenum faceTarget, GLint level); + TextureAttachment(GLenum binding, Texture *texture, const ImageIndex &index); + virtual ~TextureAttachment(); - virtual ~TextureCubeMapAttachment(); - - rx::RenderTarget *getRenderTarget(); - rx::RenderTarget *getDepthStencil(); - rx::TextureStorage *getTextureStorage(); - - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLenum getInternalFormat() const; - virtual GLenum getActualFormat() const; virtual GLsizei getSamples() const; - - virtual unsigned int getSerial() const; - virtual GLuint id() const; - virtual GLenum type() const; - virtual GLint mipLevel() const; - virtual GLint layer() const; - virtual unsigned int getTextureSerial() const; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureCubeMapAttachment); - - BindingPointer<TextureCubeMap> mTextureCubeMap; - const GLint mLevel; - const GLenum mFaceTarget; -}; - -class Texture3DAttachment : public FramebufferAttachment -{ - public: - Texture3DAttachment(Texture3D *texture, GLint level, GLint layer); - - virtual ~Texture3DAttachment(); - - rx::RenderTarget *getRenderTarget(); - rx::RenderTarget *getDepthStencil(); - rx::TextureStorage *getTextureStorage(); virtual GLsizei getWidth() const; virtual GLsizei getHeight() const; virtual GLenum getInternalFormat() const; virtual GLenum getActualFormat() const; - virtual GLsizei getSamples() const; - - virtual unsigned int getSerial() const; - virtual GLuint id() const; virtual GLenum type() const; virtual GLint mipLevel() const; virtual GLint layer() const; - virtual unsigned int getTextureSerial() const; - private: - DISALLOW_COPY_AND_ASSIGN(Texture3DAttachment); - - BindingPointer<Texture3D> mTexture3D; - const GLint mLevel; - const GLint mLayer; -}; - -class Texture2DArrayAttachment : public FramebufferAttachment -{ - public: - Texture2DArrayAttachment(Texture2DArray *texture, GLint level, GLint layer); - - virtual ~Texture2DArrayAttachment(); - - rx::RenderTarget *getRenderTarget(); - rx::RenderTarget *getDepthStencil(); - rx::TextureStorage *getTextureStorage(); - - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLenum getInternalFormat() const; - virtual GLenum getActualFormat() const; - virtual GLsizei getSamples() const; - - virtual unsigned int getSerial() const; - - virtual GLuint id() const; - virtual GLenum type() const; - virtual GLint mipLevel() const; - virtual GLint layer() const; - virtual unsigned int getTextureSerial() const; + virtual Texture *getTexture(); + virtual const ImageIndex *getTextureImageIndex() const; + virtual Renderbuffer *getRenderbuffer(); private: - DISALLOW_COPY_AND_ASSIGN(Texture2DArrayAttachment); + DISALLOW_COPY_AND_ASSIGN(TextureAttachment); - BindingPointer<Texture2DArray> mTexture2DArray; - const GLint mLevel; - const GLint mLayer; + BindingPointer<Texture> mTexture; + ImageIndex mIndex; }; class RenderbufferAttachment : public FramebufferAttachment { public: - RenderbufferAttachment(Renderbuffer *renderbuffer); + RenderbufferAttachment(GLenum binding, Renderbuffer *renderbuffer); virtual ~RenderbufferAttachment(); - rx::RenderTarget *getRenderTarget(); - rx::RenderTarget *getDepthStencil(); - rx::TextureStorage *getTextureStorage(); - virtual GLsizei getWidth() const; virtual GLsizei getHeight() const; virtual GLenum getInternalFormat() const; virtual GLenum getActualFormat() const; virtual GLsizei getSamples() const; - virtual unsigned int getSerial() const; - virtual GLuint id() const; virtual GLenum type() const; virtual GLint mipLevel() const; virtual GLint layer() const; - virtual unsigned int getTextureSerial() const; + + virtual Texture *getTexture(); + virtual const ImageIndex *getTextureImageIndex() const; + virtual Renderbuffer *getRenderbuffer(); private: DISALLOW_COPY_AND_ASSIGN(RenderbufferAttachment); diff --git a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp index 37da99aa18..c498f8a178 100644 --- a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp +++ b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 diff --git a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h index bbded02f99..a89cc86775 100644 --- a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h +++ b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h @@ -10,12 +10,12 @@ #ifndef LIBGLESV2_HANDLEALLOCATOR_H_ #define LIBGLESV2_HANDLEALLOCATOR_H_ +#include "common/angleutils.h" + #include "angle_gl.h" #include <vector> -#include "common/angleutils.h" - namespace gl { diff --git a/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp b/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp new file mode 100644 index 0000000000..3522b997e8 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp @@ -0,0 +1,57 @@ +// +// Copyright 2014 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. +// + +// ImageIndex.cpp: Implementation for ImageIndex methods. + +#include "libGLESv2/ImageIndex.h" +#include "libGLESv2/Texture.h" +#include "common/utilities.h" + +namespace gl +{ + +ImageIndex::ImageIndex(const ImageIndex &other) + : type(other.type), + mipIndex(other.mipIndex), + layerIndex(other.layerIndex) +{} + +ImageIndex &ImageIndex::operator=(const ImageIndex &other) +{ + type = other.type; + mipIndex = other.mipIndex; + layerIndex = other.layerIndex; + return *this; +} + +ImageIndex ImageIndex::Make2D(GLint mipIndex) +{ + return ImageIndex(GL_TEXTURE_2D, mipIndex, ENTIRE_LEVEL); +} + +ImageIndex ImageIndex::MakeCube(GLenum target, GLint mipIndex) +{ + ASSERT(gl::IsCubemapTextureTarget(target)); + return ImageIndex(target, mipIndex, TextureCubeMap::targetToLayerIndex(target)); +} + +ImageIndex ImageIndex::Make2DArray(GLint mipIndex, GLint layerIndex) +{ + return ImageIndex(GL_TEXTURE_2D_ARRAY, mipIndex, layerIndex); +} + +ImageIndex ImageIndex::Make3D(GLint mipIndex, GLint layerIndex) +{ + return ImageIndex(GL_TEXTURE_3D, mipIndex, layerIndex); +} + +ImageIndex::ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn) + : type(typeIn), + mipIndex(mipIndexIn), + layerIndex(layerIndexIn) +{} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/ImageIndex.h b/src/3rdparty/angle/src/libGLESv2/ImageIndex.h new file mode 100644 index 0000000000..9f2df88061 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/ImageIndex.h @@ -0,0 +1,41 @@ +// +// Copyright 2014 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. +// + +// ImageIndex.h: A helper struct for indexing into an Image array + +#ifndef LIBGLESV2_IMAGE_INDEX_H_ +#define LIBGLESV2_IMAGE_INDEX_H_ + +#include "angle_gl.h" + +namespace gl +{ + +struct ImageIndex +{ + GLenum type; + GLint mipIndex; + GLint layerIndex; + + ImageIndex(const ImageIndex &other); + ImageIndex &operator=(const ImageIndex &other); + + bool hasLayer() const { return layerIndex != ENTIRE_LEVEL; } + + static ImageIndex Make2D(GLint mipIndex); + static ImageIndex MakeCube(GLenum target, GLint mipIndex); + static ImageIndex Make2DArray(GLint mipIndex, GLint layerIndex); + static ImageIndex Make3D(GLint mipIndex, GLint layerIndex = ENTIRE_LEVEL); + + static const GLint ENTIRE_LEVEL = static_cast<GLint>(-1); + + private: + ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn); +}; + +} + +#endif // LIBGLESV2_IMAGE_INDEX_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Program.cpp b/src/3rdparty/angle/src/libGLESv2/Program.cpp index 8a9fb04800..9bfda09a64 100644 --- a/src/3rdparty/angle/src/libGLESv2/Program.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Program.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -11,6 +10,7 @@ #include "libGLESv2/Program.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/ResourceManager.h" +#include "libGLESv2/renderer/Renderer.h" namespace gl { @@ -173,7 +173,7 @@ bool Program::attachShader(Shader *shader) return false; } - mVertexShader = (VertexShader*)shader; + mVertexShader = shader; mVertexShader->addRef(); } else if (shader->getType() == GL_FRAGMENT_SHADER) @@ -183,7 +183,7 @@ bool Program::attachShader(Shader *shader) return false; } - mFragmentShader = (FragmentShader*)shader; + mFragmentShader = shader; mFragmentShader->addRef(); } else UNREACHABLE(); @@ -244,16 +244,16 @@ void Program::bindAttributeLocation(GLuint index, const char *name) // Links the HLSL code of the vertex and pixel shader by matching up their varyings, // compiling them into binaries, determining the attribute mappings, and collecting // a list of uniforms -bool Program::link() +bool Program::link(const Caps &caps) { unlink(false); mInfoLog.reset(); resetUniformBlockBindings(); - mProgramBinary.set(new ProgramBinary(mRenderer)); + mProgramBinary.set(new ProgramBinary(mRenderer->createProgram())); mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader, - mTransformFeedbackVaryings, mTransformFeedbackBufferMode); + mTransformFeedbackVaryings, mTransformFeedbackBufferMode, caps); return mLinked; } @@ -303,14 +303,15 @@ ProgramBinary* Program::getProgramBinary() const return mProgramBinary.get(); } -bool Program::setProgramBinary(const void *binary, GLsizei length) +bool Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length) { unlink(false); mInfoLog.reset(); - mProgramBinary.set(new ProgramBinary(mRenderer)); - mLinked = mProgramBinary->load(mInfoLog, binary, length); + mProgramBinary.set(new ProgramBinary(mRenderer->createProgram())); + mLinked = mProgramBinary->load(mInfoLog, binaryFormat, binary, length); + if (!mLinked) { mProgramBinary.set(NULL); @@ -502,14 +503,14 @@ bool Program::isFlaggedForDeletion() const return mDeleteStatus; } -void Program::validate() +void Program::validate(const Caps &caps) { mInfoLog.reset(); ProgramBinary *programBinary = getProgramBinary(); if (isLinked() && programBinary) { - programBinary->validate(mInfoLog); + programBinary->validate(mInfoLog, caps); } else { diff --git a/src/3rdparty/angle/src/libGLESv2/Program.h b/src/3rdparty/angle/src/libGLESv2/Program.h index ce821a470b..6528dd1191 100644 --- a/src/3rdparty/angle/src/libGLESv2/Program.h +++ b/src/3rdparty/angle/src/libGLESv2/Program.h @@ -10,14 +10,17 @@ #ifndef LIBGLESV2_PROGRAM_H_ #define LIBGLESV2_PROGRAM_H_ -#include <string> -#include <set> - #include "common/angleutils.h" #include "common/RefCountObject.h" #include "libGLESv2/Constants.h" #include "libGLESv2/ProgramBinary.h" +#include <GLES2/gl2.h> + +#include <vector> +#include <string> +#include <set> + namespace rx { class Renderer; @@ -25,9 +28,8 @@ class Renderer; namespace gl { +struct Caps; class ResourceManager; -class FragmentShader; -class VertexShader; class Shader; extern const char * const g_fakepath; @@ -75,9 +77,9 @@ class Program void bindAttributeLocation(GLuint index, const char *name); - bool link(); + bool link(const Caps &caps); bool isLinked(); - bool setProgramBinary(const void *binary, GLsizei length); + bool setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length); ProgramBinary *getProgramBinary() const; int getInfoLogLength() const; @@ -110,7 +112,7 @@ class Program void flagForDeletion(); bool isFlaggedForDeletion() const; - void validate(); + void validate(const Caps &caps); bool isValidated() const; GLint getProgramBinaryLength() const; @@ -121,8 +123,8 @@ class Program void unlink(bool destroy = false); void resetUniformBlockBindings(); - FragmentShader *mFragmentShader; - VertexShader *mVertexShader; + Shader *mFragmentShader; + Shader *mVertexShader; AttributeBindings mAttributeBindings; diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp index 9fad5fbfc5..3f6d9e0ef9 100644 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp +++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -11,33 +10,34 @@ #include "libGLESv2/BinaryStream.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/Framebuffer.h" +#include "libGLESv2/FramebufferAttachment.h" #include "libGLESv2/Renderbuffer.h" #include "libGLESv2/renderer/ShaderExecutable.h" #include "common/debug.h" #include "common/version.h" #include "common/utilities.h" +#include "common/platform.h" #include "libGLESv2/main.h" #include "libGLESv2/Shader.h" #include "libGLESv2/Program.h" +#include "libGLESv2/renderer/ProgramImpl.h" #include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/d3d/DynamicHLSL.h" +#include "libGLESv2/renderer/d3d/ShaderD3D.h" #include "libGLESv2/renderer/d3d/VertexDataManager.h" #include "libGLESv2/Context.h" #include "libGLESv2/Buffer.h" -#include "libGLESv2/DynamicHLSL.h" #include "common/blocklayout.h" -#undef near -#undef far - namespace gl { namespace { -TextureType GetTextureType(GLenum samplerType) +GLenum GetTextureType(GLenum samplerType) { switch (samplerType) { @@ -45,26 +45,26 @@ TextureType GetTextureType(GLenum samplerType) case GL_INT_SAMPLER_2D: case GL_UNSIGNED_INT_SAMPLER_2D: case GL_SAMPLER_2D_SHADOW: - return TEXTURE_2D; + return GL_TEXTURE_2D; case GL_SAMPLER_3D: case GL_INT_SAMPLER_3D: case GL_UNSIGNED_INT_SAMPLER_3D: - return TEXTURE_3D; + return GL_TEXTURE_3D; case GL_SAMPLER_CUBE: case GL_SAMPLER_CUBE_SHADOW: - return TEXTURE_CUBE; + return GL_TEXTURE_CUBE_MAP; case GL_INT_SAMPLER_CUBE: case GL_UNSIGNED_INT_SAMPLER_CUBE: - return TEXTURE_CUBE; + return GL_TEXTURE_CUBE_MAP; case GL_SAMPLER_2D_ARRAY: case GL_INT_SAMPLER_2D_ARRAY: case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: case GL_SAMPLER_2D_ARRAY_SHADOW: - return TEXTURE_2D_ARRAY; + return GL_TEXTURE_2D_ARRAY; default: UNREACHABLE(); } - return TEXTURE_2D; + return GL_TEXTURE_2D; } unsigned int ParseAndStripArrayIndex(std::string* name) @@ -83,7 +83,7 @@ unsigned int ParseAndStripArrayIndex(std::string* name) return subscript; } -void GetInputLayoutFromShader(const std::vector<sh::Attribute> &shaderAttributes, VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]) +void GetDefaultInputLayoutFromShader(const std::vector<sh::Attribute> &shaderAttributes, VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]) { size_t layoutIndex = 0; for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) @@ -109,6 +109,26 @@ void GetInputLayoutFromShader(const std::vector<sh::Attribute> &shaderAttributes } } +std::vector<GLenum> GetDefaultOutputLayoutFromShader(const std::vector<rx::PixelShaderOutputVariable> &shaderOutputVars) +{ + std::vector<GLenum> defaultPixelOutput(1); + + ASSERT(!shaderOutputVars.empty()); + defaultPixelOutput[0] = GL_COLOR_ATTACHMENT0 + shaderOutputVars[0].outputIndex; + + return defaultPixelOutput; +} + +bool IsRowMajorLayout(const sh::InterfaceBlockField &var) +{ + return var.isRowMajorLayout; +} + +bool IsRowMajorLayout(const sh::ShaderVariable &var) +{ + return false; +} + } VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index) @@ -169,45 +189,30 @@ LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, unsigned int ProgramBinary::mCurrentSerial = 1; -ProgramBinary::ProgramBinary(rx::Renderer *renderer) +ProgramBinary::ProgramBinary(rx::ProgramImpl *impl) : RefCountObject(0), - mRenderer(renderer), - mDynamicHLSL(NULL), - mVertexWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE), - mPixelWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE), + mProgram(impl), mGeometryExecutable(NULL), mUsedVertexSamplerRange(0), mUsedPixelSamplerRange(0), mUsesPointSize(false), mShaderVersion(100), mDirtySamplerMapping(true), - mVertexUniformStorage(NULL), - mFragmentUniformStorage(NULL), mValidated(false), mSerial(issueSerial()) { + ASSERT(impl); + for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++) { mSemanticIndex[index] = -1; } - - for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++) - { - mSamplersPS[index].active = false; - } - - for (int index = 0; index < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; index++) - { - mSamplersVS[index].active = false; - } - - mDynamicHLSL = new DynamicHLSL(renderer); } ProgramBinary::~ProgramBinary() { reset(); - SafeDelete(mDynamicHLSL); + SafeDelete(mProgram); } unsigned int ProgramBinary::getSerial() const @@ -227,17 +232,21 @@ unsigned int ProgramBinary::issueSerial() rx::ShaderExecutable *ProgramBinary::getPixelExecutableForFramebuffer(const Framebuffer *fbo) { - std::vector<GLenum> outputs(IMPLEMENTATION_MAX_DRAW_BUFFERS); - for (size_t outputIndex = 0; outputIndex < IMPLEMENTATION_MAX_DRAW_BUFFERS; outputIndex++) + std::vector<GLenum> outputs; + + const gl::ColorbufferInfo &colorbuffers = fbo->getColorbuffersForRender(); + + for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) { - if (fbo->getColorbuffer(outputIndex) != NULL) + const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment]; + + if (colorbuffer) { - // Always output floats for now - outputs[outputIndex] = GL_FLOAT; + outputs.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding()); } else { - outputs[outputIndex] = GL_NONE; + outputs.push_back(GL_NONE); } } @@ -254,15 +263,9 @@ rx::ShaderExecutable *ProgramBinary::getPixelExecutableForOutputLayout(const std } } - std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth, - outputSignature); - - // Generate new pixel executable InfoLog tempInfoLog; - rx::ShaderExecutable *pixelExecutable = mRenderer->compileToExecutable(tempInfoLog, finalPixelHLSL.c_str(), rx::SHADER_PIXEL, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - mPixelWorkarounds); + rx::ShaderExecutable *pixelExecutable = mProgram->getPixelExecutableForOutputLayout(tempInfoLog, outputSignature, + mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); if (!pixelExecutable) { @@ -281,7 +284,7 @@ rx::ShaderExecutable *ProgramBinary::getPixelExecutableForOutputLayout(const std rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]) { GLenum signature[MAX_VERTEX_ATTRIBS]; - mDynamicHLSL->getInputLayoutSignature(inputLayout, signature); + mProgram->getDynamicHLSL()->getInputLayoutSignature(inputLayout, signature); for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++) { @@ -291,16 +294,9 @@ rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const Ver } } - // Generate new dynamic layout with attribute conversions - std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, mShaderAttributes); - - // Generate new vertex executable InfoLog tempInfoLog; - rx::ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(tempInfoLog, finalVertexHLSL.c_str(), - rx::SHADER_VERTEX, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - mVertexWorkarounds); + rx::ShaderExecutable *vertexExecutable = mProgram->getVertexExecutableForInputLayout(tempInfoLog, inputLayout, mShaderAttributes, + mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); if (!vertexExecutable) { @@ -366,7 +362,7 @@ bool ProgramBinary::usesPointSize() const bool ProgramBinary::usesPointSpriteEmulation() const { - return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4; + return mUsesPointSize && mProgram->getRenderer()->getMajorShaderModel() >= 4; } bool ProgramBinary::usesGeometryShader() const @@ -374,26 +370,22 @@ bool ProgramBinary::usesGeometryShader() const return usesPointSpriteEmulation(); } -// Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler -// index (0-15 for the pixel shader and 0-3 for the vertex shader). -GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex) +GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps) { GLint logicalTextureUnit = -1; switch (type) { case SAMPLER_PIXEL: - ASSERT(samplerIndex < ArraySize(mSamplersPS)); - - if (mSamplersPS[samplerIndex].active) + ASSERT(samplerIndex < caps.maxTextureImageUnits); + if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active) { logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit; } break; case SAMPLER_VERTEX: - ASSERT(samplerIndex < ArraySize(mSamplersVS)); - - if (mSamplersVS[samplerIndex].active) + ASSERT(samplerIndex < caps.maxVertexTextureImageUnits); + if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active) { logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit; } @@ -401,7 +393,7 @@ GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerInd default: UNREACHABLE(); } - if (logicalTextureUnit >= 0 && logicalTextureUnit < (GLint)mRenderer->getMaxCombinedTextureImageUnits()) + if (logicalTextureUnit >= 0 && logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits)) { return logicalTextureUnit; } @@ -411,22 +403,22 @@ GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerInd // Returns the texture type for a given Direct3D 9 sampler type and // index (0-15 for the pixel shader and 0-3 for the vertex shader). -TextureType ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex) +GLenum ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex) { switch (type) { case SAMPLER_PIXEL: - ASSERT(samplerIndex < ArraySize(mSamplersPS)); + ASSERT(samplerIndex < mSamplersPS.size()); ASSERT(mSamplersPS[samplerIndex].active); return mSamplersPS[samplerIndex].textureType; case SAMPLER_VERTEX: - ASSERT(samplerIndex < ArraySize(mSamplersVS)); + ASSERT(samplerIndex < mSamplersVS.size()); ASSERT(mSamplersVS[samplerIndex].active); return mSamplersVS[samplerIndex].textureType; default: UNREACHABLE(); } - return TEXTURE_2D; + return GL_TEXTURE_2D; } GLint ProgramBinary::getUniformLocation(std::string name) @@ -562,38 +554,64 @@ void ProgramBinary::setUniform(GLint location, GLsizei count, const T* v, GLenum if (targetUniform->type == targetUniformType) { - T *target = (T*)targetUniform->data + mUniformIndex[location].element * 4; + T *target = reinterpret_cast<T*>(targetUniform->data) + mUniformIndex[location].element * 4; for (int i = 0; i < count; i++) { + T *dest = target + (i * 4); + const T *source = v + (i * components); + for (int c = 0; c < components; c++) { - SetIfDirty(target + c, v[c], &targetUniform->dirty); + SetIfDirty(dest + c, source[c], &targetUniform->dirty); } for (int c = components; c < 4; c++) { - SetIfDirty(target + c, T(0), &targetUniform->dirty); + SetIfDirty(dest + c, T(0), &targetUniform->dirty); } - target += 4; - v += components; } } else if (targetUniform->type == targetBoolType) { - GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; + GLint *boolParams = reinterpret_cast<GLint*>(targetUniform->data) + mUniformIndex[location].element * 4; for (int i = 0; i < count; i++) { + GLint *dest = boolParams + (i * 4); + const T *source = v + (i * components); + for (int c = 0; c < components; c++) { - SetIfDirty(boolParams + c, (v[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty); + SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty); } for (int c = components; c < 4; c++) { - SetIfDirty(boolParams + c, GL_FALSE, &targetUniform->dirty); + SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty); } - boolParams += 4; - v += components; + } + } + else if (IsSampler(targetUniform->type)) + { + ASSERT(targetUniformType == GL_INT); + + GLint *target = reinterpret_cast<GLint*>(targetUniform->data) + mUniformIndex[location].element * 4; + + bool wasDirty = targetUniform->dirty; + + for (int i = 0; i < count; i++) + { + GLint *dest = target + (i * 4); + const GLint *source = reinterpret_cast<const GLint*>(v) + (i * components); + + SetIfDirty(dest + 0, source[0], &targetUniform->dirty); + SetIfDirty(dest + 1, 0, &targetUniform->dirty); + SetIfDirty(dest + 2, 0, &targetUniform->dirty); + SetIfDirty(dest + 3, 0, &targetUniform->dirty); + } + + if (!wasDirty && targetUniform->dirty) + { + mDirtySamplerMapping = true; } } else UNREACHABLE(); @@ -761,48 +779,7 @@ void ProgramBinary::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboole void ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v) { - LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index]; - - int elementCount = targetUniform->elementCount(); - - count = std::min(elementCount - (int)mUniformIndex[location].element, count); - - if (targetUniform->type == GL_INT || IsSampler(targetUniform->type)) - { - GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (int i = 0; i < count; i++) - { - SetIfDirty(target + 0, v[0], &targetUniform->dirty); - SetIfDirty(target + 1, 0, &targetUniform->dirty); - SetIfDirty(target + 2, 0, &targetUniform->dirty); - SetIfDirty(target + 3, 0, &targetUniform->dirty); - target += 4; - v += 1; - } - } - else if (targetUniform->type == GL_BOOL) - { - GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (int i = 0; i < count; i++) - { - SetIfDirty(boolParams + 0, (v[0] == 0) ? GL_FALSE : GL_TRUE, &targetUniform->dirty); - SetIfDirty(boolParams + 1, GL_FALSE, &targetUniform->dirty); - SetIfDirty(boolParams + 2, GL_FALSE, &targetUniform->dirty); - SetIfDirty(boolParams + 3, GL_FALSE, &targetUniform->dirty); - boolParams += 4; - v += 1; - } - } - else UNREACHABLE(); - - // Set a special flag if we change a sampler uniform - if (IsSampler(targetUniform->type) && - (memcmp(targetUniform->data, v, sizeof(GLint)) != 0)) - { - mDirtySamplerMapping = true; - } + setUniform(location, count, v, GL_INT); } void ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v) @@ -841,20 +818,10 @@ void ProgramBinary::setUniform4uiv(GLint location, GLsizei count, const GLuint * } template <typename T> -bool ProgramBinary::getUniformv(GLint location, GLsizei *bufSize, T *params, GLenum uniformType) +void ProgramBinary::getUniformv(GLint location, T *params, GLenum uniformType) { LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index]; - // sized queries -- ensure the provided buffer is large enough - if (bufSize) - { - int requiredBytes = VariableExternalSize(targetUniform->type); - if (*bufSize < requiredBytes) - { - return false; - } - } - if (IsMatrixType(targetUniform->type)) { const int rows = VariableRowCount(targetUniform->type); @@ -919,23 +886,21 @@ bool ProgramBinary::getUniformv(GLint location, GLsizei *bufSize, T *params, GLe default: UNREACHABLE(); } } - - return true; } -bool ProgramBinary::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params) +void ProgramBinary::getUniformfv(GLint location, GLfloat *params) { - return getUniformv(location, bufSize, params, GL_FLOAT); + getUniformv(location, params, GL_FLOAT); } -bool ProgramBinary::getUniformiv(GLint location, GLsizei *bufSize, GLint *params) +void ProgramBinary::getUniformiv(GLint location, GLint *params) { - return getUniformv(location, bufSize, params, GL_INT); + getUniformv(location, params, GL_INT); } -bool ProgramBinary::getUniformuiv(GLint location, GLsizei *bufSize, GLuint *params) +void ProgramBinary::getUniformuiv(GLint location, GLuint *params) { - return getUniformv(location, bufSize, params, GL_UNSIGNED_INT); + getUniformv(location, params, GL_UNSIGNED_INT); } void ProgramBinary::dirtyAllUniforms() @@ -976,7 +941,7 @@ void ProgramBinary::updateSamplerMapping() { unsigned int samplerIndex = firstIndex + i; - if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS) + if (samplerIndex < mSamplersPS.size()) { ASSERT(mSamplersPS[samplerIndex].active); mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0]; @@ -992,7 +957,7 @@ void ProgramBinary::updateSamplerMapping() { unsigned int samplerIndex = firstIndex + i; - if (samplerIndex < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS) + if (samplerIndex < mSamplersVS.size()) { ASSERT(mSamplersVS[samplerIndex].active); mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0]; @@ -1005,25 +970,31 @@ void ProgramBinary::updateSamplerMapping() } // Applies all the uniforms set for this program object to the renderer -void ProgramBinary::applyUniforms() +Error ProgramBinary::applyUniforms() { updateSamplerMapping(); - mRenderer->applyUniforms(*this); + Error error = mProgram->getRenderer()->applyUniforms(*this); + if (error.isError()) + { + return error; + } for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) { mUniforms[uniformIndex]->dirty = false; } + + return gl::Error(GL_NO_ERROR); } -bool ProgramBinary::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers) +Error ProgramBinary::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers, const Caps &caps) { const gl::Buffer *vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS] = {NULL}; const gl::Buffer *fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS] = {NULL}; - const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers(); - const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers(); + const unsigned int reservedBuffersInVS = mProgram->getRenderer()->getReservedVertexUniformBuffers(); + const unsigned int reservedBuffersInFS = mProgram->getRenderer()->getReservedFragmentUniformBuffers(); ASSERT(boundBuffers.size() == mUniformBlocks.size()); @@ -1037,16 +1008,20 @@ bool ProgramBinary::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuff if (uniformBuffer->getSize() < uniformBlock->dataSize) { // undefined behaviour - return false; + return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small."); } - ASSERT(uniformBlock->isReferencedByVertexShader() || uniformBlock->isReferencedByFragmentShader()); + // Unnecessary to apply an unreferenced standard or shared UBO + if (!uniformBlock->isReferencedByVertexShader() && !uniformBlock->isReferencedByFragmentShader()) + { + continue; + } if (uniformBlock->isReferencedByVertexShader()) { unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS; ASSERT(vertexUniformBuffers[registerIndex] == NULL); - ASSERT(registerIndex < mRenderer->getMaxVertexShaderUniformBuffers()); + ASSERT(registerIndex < caps.maxVertexUniformBlocks); vertexUniformBuffers[registerIndex] = uniformBuffer; } @@ -1054,15 +1029,15 @@ bool ProgramBinary::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuff { unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS; ASSERT(fragmentUniformBuffers[registerIndex] == NULL); - ASSERT(registerIndex < mRenderer->getMaxFragmentShaderUniformBuffers()); + ASSERT(registerIndex < caps.maxFragmentUniformBlocks); fragmentUniformBuffers[registerIndex] = uniformBuffer; } } - return mRenderer->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers); + return mProgram->getRenderer()->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers); } -bool ProgramBinary::linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShader, VertexShader *vertexShader) +bool ProgramBinary::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader) { std::vector<PackedVarying> &fragmentVaryings = fragmentShader->getVaryings(); std::vector<PackedVarying> &vertexVaryings = vertexShader->getVaryings(); @@ -1072,24 +1047,32 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShade PackedVarying *input = &fragmentVaryings[fragVaryingIndex]; bool matched = false; + // Built-in varyings obey special rules + if (input->isBuiltIn()) + { + continue; + } + for (size_t vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++) { PackedVarying *output = &vertexVaryings[vertVaryingIndex]; if (output->name == input->name) { - if (!linkValidateVariables(infoLog, output->name, *input, *output)) + if (!linkValidateVaryings(infoLog, output->name, *input, *output)) { return false; } output->registerIndex = input->registerIndex; + output->columnIndex = input->columnIndex; matched = true; break; } } - if (!matched) + // We permit unmatched, unreferenced varyings + if (!matched && input->staticUse) { infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str()); return false; @@ -1099,17 +1082,19 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShade return true; } -bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) +bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length) { #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD return false; #else + ASSERT(binaryFormat == mProgram->getBinaryFormat()); + reset(); BinaryInputStream stream(binary, length); - int format = stream.readInt<int>(); - if (format != GL_PROGRAM_BINARY_ANGLE) + GLenum format = stream.readInt<GLenum>(); + if (format != mProgram->getBinaryFormat()) { infoLog.append("Invalid program binary format."); return false; @@ -1149,18 +1134,23 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) initAttributesByLayout(); - for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i) + const unsigned int psSamplerCount = stream.readInt<unsigned int>(); + for (unsigned int i = 0; i < psSamplerCount; ++i) { - stream.readBool(&mSamplersPS[i].active); - stream.readInt(&mSamplersPS[i].logicalTextureUnit); - stream.readInt(&mSamplersPS[i].textureType); + Sampler sampler; + stream.readBool(&sampler.active); + stream.readInt(&sampler.logicalTextureUnit); + stream.readInt(&sampler.textureType); + mSamplersPS.push_back(sampler); } - - for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i) + const unsigned int vsSamplerCount = stream.readInt<unsigned int>(); + for (unsigned int i = 0; i < vsSamplerCount; ++i) { - stream.readBool(&mSamplersVS[i].active); - stream.readInt(&mSamplersVS[i].logicalTextureUnit); - stream.readInt(&mSamplersVS[i].textureType); + Sampler sampler; + stream.readBool(&sampler.active); + stream.readInt(&sampler.logicalTextureUnit); + stream.readInt(&sampler.textureType); + mSamplersVS.push_back(sampler); } stream.readInt(&mUsedVertexSamplerRange); @@ -1260,10 +1250,6 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) stream.readInt(&varying.semanticIndexCount); } - stream.readString(&mVertexHLSL); - - stream.readInt(&mVertexWorkarounds); - const unsigned int vertexShaderCount = stream.readInt<unsigned int>(); for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++) { @@ -1280,7 +1266,7 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) unsigned int vertexShaderSize = stream.readInt<unsigned int>(); const unsigned char *vertexShaderFunction = reinterpret_cast<const unsigned char*>(binary) + stream.offset(); - rx::ShaderExecutable *shaderExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(vertexShaderFunction), + rx::ShaderExecutable *shaderExecutable = mProgram->getRenderer()->loadExecutable(reinterpret_cast<const DWORD*>(vertexShaderFunction), vertexShaderSize, rx::SHADER_VERTEX, mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); @@ -1292,7 +1278,7 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) // generated converted input layout GLenum signature[MAX_VERTEX_ATTRIBS]; - mDynamicHLSL->getInputLayoutSignature(inputLayout, signature); + mProgram->getDynamicHLSL()->getInputLayoutSignature(inputLayout, signature); // add new binary mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable)); @@ -1300,20 +1286,6 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) stream.skip(vertexShaderSize); } - stream.readString(&mPixelHLSL); - stream.readInt(&mPixelWorkarounds); - stream.readBool(&mUsesFragDepth); - - const size_t pixelShaderKeySize = stream.readInt<unsigned int>(); - mPixelShaderKey.resize(pixelShaderKeySize); - for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++) - { - stream.readInt(&mPixelShaderKey[pixelShaderKeyIndex].type); - stream.readString(&mPixelShaderKey[pixelShaderKeyIndex].name); - stream.readString(&mPixelShaderKey[pixelShaderKeyIndex].source); - stream.readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex); - } - const size_t pixelShaderCount = stream.readInt<unsigned int>(); for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++) { @@ -1326,10 +1298,11 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) const size_t pixelShaderSize = stream.readInt<unsigned int>(); const unsigned char *pixelShaderFunction = reinterpret_cast<const unsigned char*>(binary) + stream.offset(); - rx::ShaderExecutable *shaderExecutable = mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize, - rx::SHADER_PIXEL, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); + rx::Renderer *renderer = mProgram->getRenderer(); + rx::ShaderExecutable *shaderExecutable = renderer->loadExecutable(pixelShaderFunction, pixelShaderSize, + rx::SHADER_PIXEL, mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); + if (!shaderExecutable) { infoLog.append("Could not create pixel shader."); @@ -1347,9 +1320,11 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) if (geometryShaderSize > 0) { const char *geometryShaderFunction = (const char*) binary + stream.offset(); - mGeometryExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(geometryShaderFunction), - geometryShaderSize, rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); + rx::Renderer *renderer = mProgram->getRenderer(); + mGeometryExecutable = renderer->loadExecutable(reinterpret_cast<const DWORD*>(geometryShaderFunction), + geometryShaderSize, rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); + if (!mGeometryExecutable) { infoLog.append("Could not create geometry shader."); @@ -1358,29 +1333,39 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) stream.skip(geometryShaderSize); } + if (!mProgram->load(infoLog, &stream)) + { + return false; + } + const char *ptr = (const char*) binary + stream.offset(); const GUID *binaryIdentifier = (const GUID *) ptr; ptr += sizeof(GUID); - GUID identifier = mRenderer->getAdapterIdentifier(); + GUID identifier = mProgram->getRenderer()->getAdapterIdentifier(); if (memcmp(&identifier, binaryIdentifier, sizeof(GUID)) != 0) { infoLog.append("Invalid program binary."); return false; } - initializeUniformStorage(); + mProgram->initializeUniformStorage(mUniforms); return true; #endif // #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD } -bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) +bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) { + if (binaryFormat) + { + *binaryFormat = mProgram->getBinaryFormat(); + } + BinaryOutputStream stream; - stream.writeInt(GL_PROGRAM_BINARY_ANGLE); + stream.writeInt(mProgram->getBinaryFormat()); stream.writeInt(ANGLE_MAJOR_VERSION); stream.writeInt(ANGLE_MINOR_VERSION); stream.writeBytes(reinterpret_cast<const unsigned char*>(ANGLE_COMMIT_HASH), ANGLE_COMMIT_HASH_SIZE); @@ -1395,14 +1380,16 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) stream.writeInt(mSemanticIndex[i]); } - for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i) + stream.writeInt(mSamplersPS.size()); + for (unsigned int i = 0; i < mSamplersPS.size(); ++i) { stream.writeInt(mSamplersPS[i].active); stream.writeInt(mSamplersPS[i].logicalTextureUnit); stream.writeInt(mSamplersPS[i].textureType); } - for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i) + stream.writeInt(mSamplersVS.size()); + for (unsigned int i = 0; i < mSamplersVS.size(); ++i) { stream.writeInt(mSamplersVS[i].active); stream.writeInt(mSamplersVS[i].logicalTextureUnit); @@ -1477,9 +1464,6 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) stream.writeInt(varying.semanticIndexCount); } - stream.writeString(mVertexHLSL); - stream.writeInt(mVertexWorkarounds); - stream.writeInt(mVertexExecutables.size()); for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++) { @@ -1501,20 +1485,6 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) stream.writeBytes(vertexBlob, vertexShaderSize); } - stream.writeString(mPixelHLSL); - stream.writeInt(mPixelWorkarounds); - stream.writeInt(mUsesFragDepth); - - stream.writeInt(mPixelShaderKey.size()); - for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < mPixelShaderKey.size(); pixelShaderKeyIndex++) - { - const PixelShaderOuputVariable &variable = mPixelShaderKey[pixelShaderKeyIndex]; - stream.writeInt(variable.type); - stream.writeString(variable.name); - stream.writeString(variable.source); - stream.writeInt(variable.outputIndex); - } - stream.writeInt(mPixelExecutables.size()); for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++) { @@ -1543,7 +1513,17 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) stream.writeBytes(geometryBlob, geometryShaderSize); } - GUID identifier = mRenderer->getAdapterIdentifier(); + if (!mProgram->save(&stream)) + { + if (length) + { + *length = 0; + } + + return false; + } + + GUID identifier = mProgram->getRenderer()->getAdapterIdentifier(); GLsizei streamLength = stream.length(); const void *streamData = stream.data(); @@ -1583,7 +1563,7 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) GLint ProgramBinary::getLength() { GLint length; - if (save(NULL, INT_MAX, &length)) + if (save(NULL, NULL, INT_MAX, &length)) { return length; } @@ -1593,68 +1573,56 @@ GLint ProgramBinary::getLength() } } -bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader, - const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode) +bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader, + const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps) { if (!fragmentShader || !fragmentShader->isCompiled()) { return false; } + ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER); if (!vertexShader || !vertexShader->isCompiled()) { return false; } + ASSERT(vertexShader->getType() == GL_VERTEX_SHADER); reset(); - mTransformFeedbackBufferMode = transformFeedbackBufferMode; - - mShaderVersion = vertexShader->getShaderVersion(); + mSamplersPS.resize(caps.maxTextureImageUnits); + mSamplersVS.resize(caps.maxVertexTextureImageUnits); - mPixelHLSL = fragmentShader->getHLSL(); - mPixelWorkarounds = fragmentShader->getD3DWorkarounds(); - - mVertexHLSL = vertexShader->getHLSL(); - mVertexWorkarounds = vertexShader->getD3DWorkarounds(); + mTransformFeedbackBufferMode = transformFeedbackBufferMode; - // Map the varyings to the register file - VaryingPacking packing = { NULL }; - int registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShader, vertexShader, transformFeedbackVaryings); + rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); + rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader->getImplementation()); - if (registers < 0) - { - return false; - } + mShaderVersion = vertexShaderD3D->getShaderVersion(); - if (!linkVaryings(infoLog, fragmentShader, vertexShader)) - { - return false; - } - - mUsesPointSize = vertexShader->usesPointSize(); + int registers; std::vector<LinkedVarying> linkedVaryings; - if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, registers, packing, mPixelHLSL, mVertexHLSL, - fragmentShader, vertexShader, transformFeedbackVaryings, - &linkedVaryings, &mOutputVariables, &mPixelShaderKey, &mUsesFragDepth)) + if (!mProgram->link(infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, ®isters, &linkedVaryings, &mOutputVariables)) { return false; } + mUsesPointSize = vertexShaderD3D->usesPointSize(); + bool success = true; - if (!linkAttributes(infoLog, attributeBindings, fragmentShader, vertexShader)) + if (!linkAttributes(infoLog, attributeBindings, vertexShader)) { success = false; } - if (!linkUniforms(infoLog, *vertexShader, *fragmentShader)) + if (!linkUniforms(infoLog, *vertexShader, *fragmentShader, caps)) { success = false; } // special case for gl_DepthRange, the only built-in uniform (also a struct) - if (vertexShader->usesDepthRange() || fragmentShader->usesDepthRange()) + if (vertexShaderD3D->usesDepthRange() || fragmentShaderD3D->usesDepthRange()) { const sh::BlockMemberInfo &defaultInfo = sh::BlockMemberInfo::getDefaultBlockInfo(); @@ -1663,13 +1631,13 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0, -1, defaultInfo)); } - if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader)) + if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader, caps)) { success = false; } if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings, - transformFeedbackBufferMode, &mTransformFeedbackLinkedVaryings)) + transformFeedbackBufferMode, &mTransformFeedbackLinkedVaryings, caps)) { success = false; } @@ -1677,23 +1645,19 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin if (success) { VertexFormat defaultInputLayout[MAX_VERTEX_ATTRIBS]; - GetInputLayoutFromShader(vertexShader->activeAttributes(), defaultInputLayout); + GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout); rx::ShaderExecutable *defaultVertexExecutable = getVertexExecutableForInputLayout(defaultInputLayout); - std::vector<GLenum> defaultPixelOutput(IMPLEMENTATION_MAX_DRAW_BUFFERS); - for (size_t i = 0; i < defaultPixelOutput.size(); i++) - { - defaultPixelOutput[i] = (i == 0) ? GL_FLOAT : GL_NONE; - } + std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(mProgram->getPixelShaderKey()); rx::ShaderExecutable *defaultPixelExecutable = getPixelExecutableForOutputLayout(defaultPixelOutput); if (usesGeometryShader()) { - std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShader, vertexShader); - mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - rx::ANGLE_D3D_WORKAROUND_NONE); + std::string geometryHLSL = mProgram->getDynamicHLSL()->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D); + mGeometryExecutable = mProgram->getRenderer()->compileToExecutable(infoLog, geometryHLSL.c_str(), + rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), + rx::ANGLE_D3D_WORKAROUND_NONE); } if (!defaultVertexExecutable || !defaultPixelExecutable || (usesGeometryShader() && !mGeometryExecutable)) @@ -1708,15 +1672,20 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin } // Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices -bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader) +bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader) { + const rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); + unsigned int usedLocations = 0; - const std::vector<sh::Attribute> &activeAttributes = vertexShader->activeAttributes(); + const std::vector<sh::Attribute> &shaderAttributes = vertexShader->getActiveAttributes(); // Link attributes that have a binding location - for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++) + for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) { - const sh::Attribute &attribute = activeAttributes[attributeIndex]; + const sh::Attribute &attribute = shaderAttributes[attributeIndex]; + + ASSERT(attribute.staticUse); + const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location; mShaderAttributes[attributeIndex] = attribute; @@ -1755,9 +1724,12 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at } // Link attributes that don't have a binding location - for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++) + for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) { - const sh::Attribute &attribute = activeAttributes[attributeIndex]; + const sh::Attribute &attribute = shaderAttributes[attributeIndex]; + + ASSERT(attribute.staticUse); + const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location; if (location == -1) // Not set by glBindAttribLocation or by location layout qualifier @@ -1778,7 +1750,7 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; ) { - int index = vertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name); + int index = vertexShaderD3D->getSemanticIndex(mLinkedAttribute[attributeIndex].name); int rows = VariableRegisterCount(mLinkedAttribute[attributeIndex].type); for (int r = 0; r < rows; r++) @@ -1811,32 +1783,29 @@ bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::strin return false; } - return true; -} - -template <class ShaderVarType> -bool ProgramBinary::linkValidateFields(InfoLog &infoLog, const std::string &varName, const ShaderVarType &vertexVar, const ShaderVarType &fragmentVar) -{ - if (vertexVar.fields.size() != fragmentVar.fields.size()) + if (vertexVariable.fields.size() != fragmentVariable.fields.size()) { - infoLog.append("Structure lengths for %s differ between vertex and fragment shaders", varName.c_str()); + infoLog.append("Structure lengths for %s differ between vertex and fragment shaders", variableName.c_str()); return false; } - const unsigned int numMembers = vertexVar.fields.size(); + const unsigned int numMembers = vertexVariable.fields.size(); for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++) { - const ShaderVarType &vertexMember = vertexVar.fields[memberIndex]; - const ShaderVarType &fragmentMember = fragmentVar.fields[memberIndex]; + const sh::ShaderVariable &vertexMember = vertexVariable.fields[memberIndex]; + const sh::ShaderVariable &fragmentMember = fragmentVariable.fields[memberIndex]; if (vertexMember.name != fragmentMember.name) { infoLog.append("Name mismatch for field '%d' of %s: (in vertex: '%s', in fragment: '%s')", - memberIndex, varName.c_str(), vertexMember.name.c_str(), fragmentMember.name.c_str()); + memberIndex, variableName.c_str(), + vertexMember.name.c_str(), fragmentMember.name.c_str()); return false; } - const std::string memberName = varName.substr(0, varName.length()-1) + "." + vertexVar.name + "'"; - if (!linkValidateVariables(infoLog, memberName, vertexMember, fragmentMember)) + const std::string memberName = variableName.substr(0, variableName.length() - 1) + "." + + vertexMember.name + "'"; + + if (!linkValidateVariablesBase(infoLog, vertexMember.name, vertexMember, fragmentMember, validatePrecision)) { return false; } @@ -1845,22 +1814,17 @@ bool ProgramBinary::linkValidateFields(InfoLog &infoLog, const std::string &varN return true; } -bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform) +bool ProgramBinary::linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform) { if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true)) { return false; } - if (!linkValidateFields<sh::Uniform>(infoLog, uniformName, vertexUniform, fragmentUniform)) - { - return false; - } - return true; } -bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying) +bool ProgramBinary::linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying) { if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false)) { @@ -1873,37 +1837,30 @@ bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &v return false; } - if (!linkValidateFields<sh::Varying>(infoLog, varyingName, vertexVarying, fragmentVarying)) - { - return false; - } - return true; } -bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform) +bool ProgramBinary::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform) { if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true)) { return false; } - if (vertexUniform.isRowMajorMatrix != fragmentUniform.isRowMajorMatrix) + if (vertexUniform.isRowMajorLayout != fragmentUniform.isRowMajorLayout) { infoLog.append("Matrix packings for %s differ between vertex and fragment shaders", uniformName.c_str()); return false; } - if (!linkValidateFields<sh::InterfaceBlockField>(infoLog, uniformName, vertexUniform, fragmentUniform)) - { - return false; - } - return true; } -bool ProgramBinary::linkUniforms(InfoLog &infoLog, const VertexShader &vertexShader, const FragmentShader &fragmentShader) +bool ProgramBinary::linkUniforms(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps) { + const rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader.getImplementation()); + const rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader.getImplementation()); + const std::vector<sh::Uniform> &vertexUniforms = vertexShader.getUniforms(); const std::vector<sh::Uniform> &fragmentUniforms = fragmentShader.getUniforms(); @@ -1925,7 +1882,7 @@ bool ProgramBinary::linkUniforms(InfoLog &infoLog, const VertexShader &vertexSha { const sh::Uniform &vertexUniform = *entry->second; const std::string &uniformName = "uniform '" + vertexUniform.name + "'"; - if (!linkValidateVariables(infoLog, uniformName, vertexUniform, fragmentUniform)) + if (!linkValidateUniforms(infoLog, uniformName, vertexUniform, fragmentUniform)) { return false; } @@ -1935,35 +1892,43 @@ bool ProgramBinary::linkUniforms(InfoLog &infoLog, const VertexShader &vertexSha for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++) { const sh::Uniform &uniform = vertexUniforms[uniformIndex]; - defineUniformBase(GL_VERTEX_SHADER, uniform, vertexShader.getUniformRegister(uniform.name)); + + if (uniform.staticUse) + { + defineUniformBase(GL_VERTEX_SHADER, uniform, vertexShaderD3D->getUniformRegister(uniform.name)); + } } for (unsigned int uniformIndex = 0; uniformIndex < fragmentUniforms.size(); uniformIndex++) { const sh::Uniform &uniform = fragmentUniforms[uniformIndex]; - defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShader.getUniformRegister(uniform.name)); + + if (uniform.staticUse) + { + defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShaderD3D->getUniformRegister(uniform.name)); + } } - if (!indexUniforms(infoLog)) + if (!indexUniforms(infoLog, caps)) { return false; } - initializeUniformStorage(); + mProgram->initializeUniformStorage(mUniforms); return true; } void ProgramBinary::defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister) { - ShShaderOutput outputType = Shader::getCompilerOutputType(shader); + ShShaderOutput outputType = rx::ShaderD3D::getCompilerOutputType(shader); sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType)); encoder.skipRegisters(uniformRegister); defineUniform(shader, uniform, uniform.name, &encoder); } -void ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &uniform, +void ProgramBinary::defineUniform(GLenum shader, const sh::ShaderVariable &uniform, const std::string &fullName, sh::HLSLBlockEncoder *encoder) { if (uniform.isStruct()) @@ -1976,7 +1941,7 @@ void ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &uniform, for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++) { - const sh::Uniform &field = uniform.fields[fieldIndex]; + const sh::ShaderVariable &field = uniform.fields[fieldIndex]; const std::string &fieldFullName = (fullName + elementString + "." + field.name); defineUniform(shader, field, fieldFullName, encoder); @@ -2027,7 +1992,7 @@ void ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &uniform, } } -bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog) +bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog, const Caps &caps) { ASSERT(IsSampler(uniform.type)); ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX); @@ -2035,19 +2000,18 @@ bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &i if (uniform.vsRegisterIndex != GL_INVALID_INDEX) { if (!assignSamplers(uniform.vsRegisterIndex, uniform.type, uniform.arraySize, mSamplersVS, - &mUsedVertexSamplerRange, mRenderer->getMaxVertexTextureImageUnits())) + &mUsedVertexSamplerRange)) { infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).", - mRenderer->getMaxVertexTextureImageUnits()); + mSamplersVS.size()); return false; } - unsigned int maxVertexVectors = mRenderer->getReservedVertexUniformVectors() + - mRenderer->getMaxVertexUniformVectors(); + unsigned int maxVertexVectors = mProgram->getRenderer()->getReservedVertexUniformVectors() + caps.maxVertexUniformVectors; if (uniform.vsRegisterIndex + uniform.registerCount > maxVertexVectors) { infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", - mRenderer->getMaxVertexUniformVectors()); + caps.maxVertexUniformVectors); return false; } } @@ -2055,19 +2019,18 @@ bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &i if (uniform.psRegisterIndex != GL_INVALID_INDEX) { if (!assignSamplers(uniform.psRegisterIndex, uniform.type, uniform.arraySize, mSamplersPS, - &mUsedPixelSamplerRange, MAX_TEXTURE_IMAGE_UNITS)) + &mUsedPixelSamplerRange)) { infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", - MAX_TEXTURE_IMAGE_UNITS); + mSamplersPS.size()); return false; } - unsigned int maxFragmentVectors = mRenderer->getReservedFragmentUniformVectors() + - mRenderer->getMaxFragmentUniformVectors(); + unsigned int maxFragmentVectors = mProgram->getRenderer()->getReservedFragmentUniformVectors() + caps.maxFragmentUniformVectors; if (uniform.psRegisterIndex + uniform.registerCount > maxFragmentVectors) { infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", - mRenderer->getMaxFragmentUniformVectors()); + caps.maxFragmentUniformVectors); return false; } } @@ -2075,7 +2038,7 @@ bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &i return true; } -bool ProgramBinary::indexUniforms(InfoLog &infoLog) +bool ProgramBinary::indexUniforms(InfoLog &infoLog, const Caps &caps) { for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) { @@ -2083,7 +2046,7 @@ bool ProgramBinary::indexUniforms(InfoLog &infoLog) if (IsSampler(uniform.type)) { - if (!indexSamplerUniform(uniform, infoLog)) + if (!indexSamplerUniform(uniform, infoLog, caps)) { return false; } @@ -2101,20 +2064,20 @@ bool ProgramBinary::indexUniforms(InfoLog &infoLog) bool ProgramBinary::assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount, - Sampler *outArray, - GLuint *usedRange, - unsigned int limit) + std::vector<Sampler> &outSamplers, + GLuint *outUsedRange) { unsigned int samplerIndex = startSamplerIndex; do { - if (samplerIndex < limit) + if (samplerIndex < outSamplers.size()) { - outArray[samplerIndex].active = true; - outArray[samplerIndex].textureType = GetTextureType(samplerType); - outArray[samplerIndex].logicalTextureUnit = 0; - *usedRange = std::max(samplerIndex + 1, *usedRange); + Sampler& sampler = outSamplers[samplerIndex]; + sampler.active = true; + sampler.textureType = GetTextureType(samplerType); + sampler.logicalTextureUnit = 0; + *outUsedRange = std::max(samplerIndex + 1, *outUsedRange); } else { @@ -2163,8 +2126,8 @@ bool ProgramBinary::areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::Inter return false; } - std::string uniformName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'"; - if (!linkValidateVariables(infoLog, uniformName, vertexMember, fragmentMember)) + std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'"; + if (!linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember)) { return false; } @@ -2173,8 +2136,7 @@ bool ProgramBinary::areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::Inter return true; } -bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const VertexShader &vertexShader, - const FragmentShader &fragmentShader) +bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps) { const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks = vertexShader.getInterfaceBlocks(); const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks(); @@ -2205,17 +2167,29 @@ bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const VertexShader &vert for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++) { - if (!defineUniformBlock(infoLog, vertexShader, vertexInterfaceBlocks[blockIndex])) + const sh::InterfaceBlock &interfaceBlock = vertexInterfaceBlocks[blockIndex]; + + // Note: shared and std140 layouts are always considered active + if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) { - return false; + if (!defineUniformBlock(infoLog, vertexShader, interfaceBlock, caps)) + { + return false; + } } } for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++) { - if (!defineUniformBlock(infoLog, fragmentShader, fragmentInterfaceBlocks[blockIndex])) + const sh::InterfaceBlock &interfaceBlock = fragmentInterfaceBlocks[blockIndex]; + + // Note: shared and std140 layouts are always considered active + if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) { - return false; + if (!defineUniformBlock(infoLog, fragmentShader, interfaceBlock, caps)) + { + return false; + } } } @@ -2225,11 +2199,10 @@ bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const VertexShader &vert bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings, const std::vector<std::string> &transformFeedbackVaryingNames, GLenum transformFeedbackBufferMode, - std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings) const + std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings, + const Caps &caps) const { size_t totalComponents = 0; - const size_t maxSeparateComponents = mRenderer->getMaxTransformFeedbackSeparateComponents(); - const size_t maxInterleavedComponents = mRenderer->getMaxTransformFeedbackInterleavedComponents(); // Gather the linked varyings that are used for transform feedback, they should all exist. outTransformFeedbackLinkedVaryings->clear(); @@ -2251,10 +2224,10 @@ bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, cons size_t componentCount = linkedVaryings[j].semanticIndexCount * 4; if (transformFeedbackBufferMode == GL_SEPARATE_ATTRIBS && - componentCount > maxSeparateComponents) + componentCount > caps.maxTransformFeedbackSeparateComponents) { infoLog.append("Transform feedback varying's %s components (%u) exceed the maximum separate components (%u).", - linkedVaryings[j].name.c_str(), componentCount, maxSeparateComponents); + linkedVaryings[j].name.c_str(), componentCount, caps.maxTransformFeedbackSeparateComponents); return false; } @@ -2270,39 +2243,45 @@ bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, cons ASSERT(found); } - if (transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS && totalComponents > maxInterleavedComponents) + if (transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS && totalComponents > caps.maxTransformFeedbackInterleavedComponents) { infoLog.append("Transform feedback varying total components (%u) exceed the maximum interleaved components (%u).", - totalComponents, maxInterleavedComponents); + totalComponents, caps.maxTransformFeedbackInterleavedComponents); return false; } return true; } -void ProgramBinary::defineUniformBlockMembers(const std::vector<sh::InterfaceBlockField> &fields, const std::string &prefix, int blockIndex, - sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes) +template <typename VarT> +void ProgramBinary::defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex, + sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes, + bool inRowMajorLayout) { for (unsigned int uniformIndex = 0; uniformIndex < fields.size(); uniformIndex++) { - const sh::InterfaceBlockField &field = fields[uniformIndex]; + const VarT &field = fields[uniformIndex]; const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name); if (field.isStruct()) { + bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field)); + for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++) { encoder->enterAggregateType(); const std::string uniformElementName = fieldName + (field.isArray() ? ArrayString(arrayElement) : ""); - defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, encoder, blockUniformIndexes); + defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, encoder, blockUniformIndexes, rowMajorLayout); encoder->exitAggregateType(); } } else { - sh::BlockMemberInfo memberInfo = encoder->encodeInterfaceBlockField(field); + bool isRowMajorMatrix = (IsMatrixType(field.type) && inRowMajorLayout); + + sh::BlockMemberInfo memberInfo = encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix); LinkedUniform *newUniform = new LinkedUniform(field.type, field.precision, fieldName, field.arraySize, blockIndex, memberInfo); @@ -2314,8 +2293,10 @@ void ProgramBinary::defineUniformBlockMembers(const std::vector<sh::InterfaceBlo } } -bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock) +bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock, const Caps &caps) { + const rx::ShaderD3D* shaderD3D = rx::ShaderD3D::makeShaderD3D(shader.getImplementation()); + // create uniform block entries if they do not exist if (getUniformBlockIndex(interfaceBlock.name) == GL_INVALID_INDEX) { @@ -2335,7 +2316,7 @@ bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, const Shader &shader, c } ASSERT(encoder); - defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, encoder, &blockUniformIndexes); + defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, encoder, &blockUniformIndexes, interfaceBlock.isRowMajorLayout); size_t dataSize = encoder->getBlockSize(); @@ -2357,50 +2338,49 @@ bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, const Shader &shader, c } } - // Assign registers to the uniform blocks - const GLuint blockIndex = getUniformBlockIndex(interfaceBlock.name); - const unsigned int elementCount = std::max(1u, interfaceBlock.arraySize); - ASSERT(blockIndex != GL_INVALID_INDEX); - ASSERT(blockIndex + elementCount <= mUniformBlocks.size()); - - unsigned int interfaceBlockRegister = shader.getInterfaceBlockRegister(interfaceBlock.name); - - for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++) + if (interfaceBlock.staticUse) { - UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement]; - ASSERT(uniformBlock->name == interfaceBlock.name); + // Assign registers to the uniform blocks + const GLuint blockIndex = getUniformBlockIndex(interfaceBlock.name); + const unsigned int elementCount = std::max(1u, interfaceBlock.arraySize); + ASSERT(blockIndex != GL_INVALID_INDEX); + ASSERT(blockIndex + elementCount <= mUniformBlocks.size()); + + unsigned int interfaceBlockRegister = shaderD3D->getInterfaceBlockRegister(interfaceBlock.name); - if (!assignUniformBlockRegister(infoLog, uniformBlock, shader.getType(), - interfaceBlockRegister + uniformBlockElement)) + for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++) { - return false; + UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement]; + ASSERT(uniformBlock->name == interfaceBlock.name); + + if (!assignUniformBlockRegister(infoLog, uniformBlock, shader.getType(), + interfaceBlockRegister + uniformBlockElement, caps)) + { + return false; + } } } return true; } -bool ProgramBinary::assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex) +bool ProgramBinary::assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps) { if (shader == GL_VERTEX_SHADER) { uniformBlock->vsRegisterIndex = registerIndex; - unsigned int maximumBlocks = mRenderer->getMaxVertexShaderUniformBuffers(); - - if (registerIndex - mRenderer->getReservedVertexUniformBuffers() >= maximumBlocks) + if (registerIndex - mProgram->getRenderer()->getReservedVertexUniformBuffers() >= caps.maxVertexUniformBlocks) { - infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", maximumBlocks); + infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", caps.maxVertexUniformBlocks); return false; } } else if (shader == GL_FRAGMENT_SHADER) { uniformBlock->psRegisterIndex = registerIndex; - unsigned int maximumBlocks = mRenderer->getMaxFragmentShaderUniformBuffers(); - - if (registerIndex - mRenderer->getReservedFragmentUniformBuffers() >= maximumBlocks) + if (registerIndex - mProgram->getRenderer()->getReservedFragmentUniformBuffers() >= caps.maxFragmentUniformBlocks) { - infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", maximumBlocks); + infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", caps.maxFragmentUniformBlocks); return false; } } @@ -2670,10 +2650,10 @@ GLuint ProgramBinary::getActiveUniformBlockMaxLength() const return maxLength; } -void ProgramBinary::validate(InfoLog &infoLog) +void ProgramBinary::validate(InfoLog &infoLog, const Caps &caps) { applyUniforms(); - if (!validateSamplers(&infoLog)) + if (!validateSamplers(&infoLog, caps)) { mValidated = false; } @@ -2683,20 +2663,14 @@ void ProgramBinary::validate(InfoLog &infoLog) } } -bool ProgramBinary::validateSamplers(InfoLog *infoLog) +bool ProgramBinary::validateSamplers(InfoLog *infoLog, const Caps &caps) { // if any two active samplers in a program are of different types, but refer to the same // texture image unit, and this is the current program, then ValidateProgram will fail, and // DrawArrays and DrawElements will issue the INVALID_OPERATION error. updateSamplerMapping(); - const unsigned int maxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits(); - TextureType textureUnitType[IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS]; - - for (unsigned int i = 0; i < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; ++i) - { - textureUnitType[i] = TEXTURE_UNKNOWN; - } + std::vector<GLenum> textureUnitTypes(caps.maxCombinedTextureImageUnits, GL_NONE); for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i) { @@ -2704,19 +2678,19 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) { unsigned int unit = mSamplersPS[i].logicalTextureUnit; - if (unit >= maxCombinedTextureImageUnits) + if (unit >= textureUnitTypes.size()) { if (infoLog) { - infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits); + infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size()); } return false; } - if (textureUnitType[unit] != TEXTURE_UNKNOWN) + if (textureUnitTypes[unit] != GL_NONE) { - if (mSamplersPS[i].textureType != textureUnitType[unit]) + if (mSamplersPS[i].textureType != textureUnitTypes[unit]) { if (infoLog) { @@ -2728,7 +2702,7 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) } else { - textureUnitType[unit] = mSamplersPS[i].textureType; + textureUnitTypes[unit] = mSamplersPS[i].textureType; } } } @@ -2739,19 +2713,19 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) { unsigned int unit = mSamplersVS[i].logicalTextureUnit; - if (unit >= maxCombinedTextureImageUnits) + if (unit >= textureUnitTypes.size()) { if (infoLog) { - infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits); + infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size()); } return false; } - if (textureUnitType[unit] != TEXTURE_UNKNOWN) + if (textureUnitTypes[unit] != GL_NONE) { - if (mSamplersVS[i].textureType != textureUnitType[unit]) + if (mSamplersVS[i].textureType != textureUnitTypes[unit]) { if (infoLog) { @@ -2763,7 +2737,7 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) } else { - textureUnitType[unit] = mSamplersVS[i].textureType; + textureUnitTypes[unit] = mSamplersVS[i].textureType; } } } @@ -2771,7 +2745,7 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) return true; } -ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(TEXTURE_2D) +ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D) { } @@ -2819,42 +2793,9 @@ void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MA } } -void ProgramBinary::initializeUniformStorage() -{ - // Compute total default block size - unsigned int vertexRegisters = 0; - unsigned int fragmentRegisters = 0; - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) - { - const LinkedUniform &uniform = *mUniforms[uniformIndex]; - - if (!IsSampler(uniform.type)) - { - if (uniform.isReferencedByVertexShader()) - { - vertexRegisters = std::max(vertexRegisters, uniform.vsRegisterIndex + uniform.registerCount); - } - if (uniform.isReferencedByFragmentShader()) - { - fragmentRegisters = std::max(fragmentRegisters, uniform.psRegisterIndex + uniform.registerCount); - } - } - } - - mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u); - mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u); -} - void ProgramBinary::reset() { - mVertexHLSL.clear(); - mVertexWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE; SafeDeleteContainer(mVertexExecutables); - - mPixelHLSL.clear(); - mPixelWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE; - mUsesFragDepth = false; - mPixelShaderKey.clear(); SafeDeleteContainer(mPixelExecutables); SafeDelete(mGeometryExecutable); @@ -2862,14 +2803,9 @@ void ProgramBinary::reset() mTransformFeedbackBufferMode = GL_NONE; mTransformFeedbackLinkedVaryings.clear(); - for (size_t i = 0; i < ArraySize(mSamplersPS); i++) - { - mSamplersPS[i] = Sampler(); - } - for (size_t i = 0; i < ArraySize(mSamplersVS); i++) - { - mSamplersVS[i] = Sampler(); - } + mSamplersPS.clear(); + mSamplersVS.clear(); + mUsedVertexSamplerRange = 0; mUsedPixelSamplerRange = 0; mUsesPointSize = false; @@ -2880,8 +2816,8 @@ void ProgramBinary::reset() SafeDeleteContainer(mUniformBlocks); mUniformIndex.clear(); mOutputVariables.clear(); - SafeDelete(mVertexUniformStorage); - SafeDelete(mFragmentUniformStorage); + + mProgram->reset(); mValidated = false; } diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h index f0fc431021..ad470d417b 100644 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h +++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h @@ -10,11 +10,6 @@ #ifndef LIBGLESV2_PROGRAM_BINARY_H_ #define LIBGLESV2_PROGRAM_BINARY_H_ -#include "angle_gl.h" - -#include <string> -#include <vector> - #include "common/RefCountObject.h" #include "angletypes.h" #include "common/mathutil.h" @@ -22,25 +17,43 @@ #include "libGLESv2/Shader.h" #include "libGLESv2/Constants.h" #include "libGLESv2/renderer/d3d/VertexDataManager.h" -#include "libGLESv2/DynamicHLSL.h" +#include "libGLESv2/renderer/d3d/DynamicHLSL.h" + +#include "angle_gl.h" + +#include <string> +#include <vector> + +// TODO(jmadill): place this in workarounds library +#define ANGLE_WORKAROUND_ENABLED 1 +#define ANGLE_WORKAROUND_DISABLED 2 +#define ANGLE_MRT_PERF_WORKAROUND ANGLE_WORKAROUND_ENABLED namespace sh { class HLSLBlockEncoder; } +#include <GLES3/gl3.h> +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +#include <string> +#include <vector> + namespace rx { class ShaderExecutable; class Renderer; struct TranslatedAttribute; class UniformStorage; +class ProgramImpl; } namespace gl { -class FragmentShader; -class VertexShader; +struct Caps; +class Shader; class InfoLog; class AttributeBindings; class Buffer; @@ -82,9 +95,12 @@ struct LinkedVarying class ProgramBinary : public RefCountObject { public: - explicit ProgramBinary(rx::Renderer *renderer); + explicit ProgramBinary(rx::ProgramImpl *impl); ~ProgramBinary(); + rx::ProgramImpl *getImplementation() { return mProgram; } + const rx::ProgramImpl *getImplementation() const { return mProgram; } + rx::ShaderExecutable *getPixelExecutableForFramebuffer(const Framebuffer *fbo); rx::ShaderExecutable *getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout); rx::ShaderExecutable *getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]); @@ -93,8 +109,8 @@ class ProgramBinary : public RefCountObject GLuint getAttributeLocation(const char *name); int getSemanticIndex(int attributeIndex); - GLint getSamplerMapping(SamplerType type, unsigned int samplerIndex); - TextureType getSamplerTextureType(SamplerType type, unsigned int samplerIndex); + GLint getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps); + GLenum getSamplerTextureType(SamplerType type, unsigned int samplerIndex); GLint getUsedSamplerRange(SamplerType type); bool usesPointSize() const; bool usesPointSpriteEmulation() const; @@ -125,20 +141,21 @@ class ProgramBinary : public RefCountObject void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - bool getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params); - bool getUniformiv(GLint location, GLsizei *bufSize, GLint *params); - bool getUniformuiv(GLint location, GLsizei *bufSize, GLuint *params); + void getUniformfv(GLint location, GLfloat *params); + void getUniformiv(GLint location, GLint *params); + void getUniformuiv(GLint location, GLuint *params); void dirtyAllUniforms(); - void applyUniforms(); - bool applyUniformBuffers(const std::vector<Buffer*> boundBuffers); - bool load(InfoLog &infoLog, const void *binary, GLsizei length); - bool save(void* binary, GLsizei bufSize, GLsizei *length); + Error applyUniforms(); + Error applyUniformBuffers(const std::vector<Buffer*> boundBuffers, const Caps &caps); + + bool load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length); + bool save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length); GLint getLength(); - bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader, - const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode); + bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader, + const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps); void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders); void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const; @@ -165,8 +182,8 @@ class ProgramBinary : public RefCountObject const LinkedVarying &getTransformFeedbackVarying(size_t idx) const; GLenum getTransformFeedbackBufferMode() const; - void validate(InfoLog &infoLog); - bool validateSamplers(InfoLog *infoLog); + void validate(InfoLog &infoLog, const Caps &caps); + bool validateSamplers(InfoLog *infoLog, const Caps &caps); bool isValidated() const; void updateSamplerMapping(); @@ -177,8 +194,8 @@ class ProgramBinary : public RefCountObject void sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const; const std::vector<LinkedUniform*> &getUniforms() const { return mUniforms; } - const rx::UniformStorage &getVertexUniformStorage() const { return *mVertexUniformStorage; } - const rx::UniformStorage &getFragmentUniformStorage() const { return *mFragmentUniformStorage; } + + static bool linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader); private: DISALLOW_COPY_AND_ASSIGN(ProgramBinary); @@ -189,40 +206,43 @@ class ProgramBinary : public RefCountObject bool active; GLint logicalTextureUnit; - TextureType textureType; + GLenum textureType; }; void reset(); - bool linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShader, VertexShader *vertexShader); - bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader); + bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader); - template <class ShaderVarType> - bool linkValidateFields(InfoLog &infoLog, const std::string &varName, const ShaderVarType &vertexVar, const ShaderVarType &fragmentVar); - bool linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable, const sh::ShaderVariable &fragmentVariable, bool validatePrecision); + static bool linkValidateVariablesBase(InfoLog &infoLog, + const std::string &variableName, + const sh::ShaderVariable &vertexVariable, + const sh::ShaderVariable &fragmentVariable, + bool validatePrecision); - bool linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform); - bool linkValidateVariables(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying); - bool linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform); - bool linkUniforms(InfoLog &infoLog, const VertexShader &vertexShader, const FragmentShader &fragmentShader); + static bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform); + static bool linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying); + static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform); + bool linkUniforms(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps); void defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister); - void defineUniform(GLenum shader, const sh::Uniform &uniform, const std::string &fullName, sh::HLSLBlockEncoder *encoder); - bool indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog); - bool indexUniforms(InfoLog &infoLog); + void defineUniform(GLenum shader, const sh::ShaderVariable &uniform, const std::string &fullName, sh::HLSLBlockEncoder *encoder); + bool indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog, const Caps &caps); + bool indexUniforms(InfoLog &infoLog, const Caps &caps); static bool assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount, - Sampler *outArray, GLuint *usedRange, unsigned int limit); + std::vector<Sampler> &outSamplers, GLuint *outUsedRange); bool areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock); - bool linkUniformBlocks(InfoLog &infoLog, const VertexShader &vertexShader, const FragmentShader &fragmentShader); + bool linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps); bool gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings, const std::vector<std::string> &transformFeedbackVaryingNames, GLenum transformFeedbackBufferMode, - std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings) const; - void defineUniformBlockMembers(const std::vector<sh::InterfaceBlockField> &fields, const std::string &prefix, int blockIndex, - sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes); - bool defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock); - bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex); - void defineOutputVariables(FragmentShader *fragmentShader); - void initializeUniformStorage(); + std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings, + const Caps &caps) const; + template <typename VarT> + void defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex, + sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes, + bool inRowMajorLayout); + bool defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock, const Caps &caps); + bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps); + void defineOutputVariables(Shader *fragmentShader); template <typename T> void setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType); @@ -231,7 +251,7 @@ class ProgramBinary : public RefCountObject void setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType); template <typename T> - bool getUniformv(GLint location, GLsizei *bufSize, T *params, GLenum uniformType); + void getUniformv(GLint location, T *params, GLenum uniformType); class VertexExecutable { @@ -259,8 +279,7 @@ class ProgramBinary : public RefCountObject PixelExecutable(const std::vector<GLenum> &outputSignature, rx::ShaderExecutable *shaderExecutable); ~PixelExecutable(); - // FIXME(geofflang): Work around NVIDIA driver bug by repacking buffers - bool matchesSignature(const std::vector<GLenum> &signature) const { return true; /* mOutputSignature == signature; */ } + bool matchesSignature(const std::vector<GLenum> &signature) const { return mOutputSignature == signature; } const std::vector<GLenum> &outputSignature() const { return mOutputSignature; } rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; } @@ -270,17 +289,9 @@ class ProgramBinary : public RefCountObject rx::ShaderExecutable *mShaderExecutable; }; - rx::Renderer *const mRenderer; - DynamicHLSL *mDynamicHLSL; + rx::ProgramImpl *mProgram; - std::string mVertexHLSL; - rx::D3DWorkaroundType mVertexWorkarounds; std::vector<VertexExecutable *> mVertexExecutables; - - std::string mPixelHLSL; - rx::D3DWorkaroundType mPixelWorkarounds; - bool mUsesFragDepth; - std::vector<PixelShaderOuputVariable> mPixelShaderKey; std::vector<PixelExecutable *> mPixelExecutables; rx::ShaderExecutable *mGeometryExecutable; @@ -293,8 +304,8 @@ class ProgramBinary : public RefCountObject GLenum mTransformFeedbackBufferMode; std::vector<LinkedVarying> mTransformFeedbackLinkedVaryings; - Sampler mSamplersPS[MAX_TEXTURE_IMAGE_UNITS]; - Sampler mSamplersVS[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; + std::vector<Sampler> mSamplersPS; + std::vector<Sampler> mSamplersVS; GLuint mUsedVertexSamplerRange; GLuint mUsedPixelSamplerRange; bool mUsesPointSize; @@ -305,8 +316,6 @@ class ProgramBinary : public RefCountObject std::vector<UniformBlock*> mUniformBlocks; std::vector<VariableLocation> mUniformIndex; std::map<int, VariableLocation> mOutputVariables; - rx::UniformStorage *mVertexUniformStorage; - rx::UniformStorage *mFragmentUniformStorage; bool mValidated; diff --git a/src/3rdparty/angle/src/libGLESv2/Query.cpp b/src/3rdparty/angle/src/libGLESv2/Query.cpp index 6546d06c34..4ee3525509 100644 --- a/src/3rdparty/angle/src/libGLESv2/Query.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Query.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -9,39 +8,38 @@ #include "libGLESv2/Query.h" #include "libGLESv2/renderer/QueryImpl.h" -#include "libGLESv2/renderer/Renderer.h" namespace gl { - -Query::Query(rx::Renderer *renderer, GLenum type, GLuint id) : RefCountObject(id) -{ - mQuery = renderer->createQuery(type); +Query::Query(rx::QueryImpl *impl, GLuint id) + : RefCountObject(id), + mQuery(impl) +{ } Query::~Query() { - delete mQuery; + SafeDelete(mQuery); } -void Query::begin() +Error Query::begin() { - mQuery->begin(); + return mQuery->begin(); } -void Query::end() +Error Query::end() { - mQuery->end(); + return mQuery->end(); } -GLuint Query::getResult() +Error Query::getResult(GLuint *params) { - return mQuery->getResult(); + return mQuery->getResult(params); } -GLboolean Query::isResultAvailable() +Error Query::isResultAvailable(GLuint *available) { - return mQuery->isResultAvailable(); + return mQuery->isResultAvailable(available); } GLenum Query::getType() const @@ -49,9 +47,4 @@ GLenum Query::getType() const return mQuery->getType(); } -bool Query::isStarted() const -{ - return mQuery->isStarted(); -} - } diff --git a/src/3rdparty/angle/src/libGLESv2/Query.h b/src/3rdparty/angle/src/libGLESv2/Query.h index a4726a8e73..a7ec404f85 100644 --- a/src/3rdparty/angle/src/libGLESv2/Query.h +++ b/src/3rdparty/angle/src/libGLESv2/Query.h @@ -9,14 +9,14 @@ #ifndef LIBGLESV2_QUERY_H_ #define LIBGLESV2_QUERY_H_ -#include "angle_gl.h" - +#include "libGLESv2/Error.h" #include "common/angleutils.h" #include "common/RefCountObject.h" +#include "angle_gl.h" + namespace rx { -class Renderer; class QueryImpl; } @@ -26,17 +26,16 @@ namespace gl class Query : public RefCountObject { public: - Query(rx::Renderer *renderer, GLenum type, GLuint id); + Query(rx::QueryImpl *impl, GLuint id); virtual ~Query(); - void begin(); - void end(); + Error begin(); + Error end(); - GLuint getResult(); - GLboolean isResultAvailable(); + Error getResult(GLuint *params); + Error isResultAvailable(GLuint *available); GLenum getType() const; - bool isStarted() const; private: DISALLOW_COPY_AND_ASSIGN(Query); diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp index d4bfaf27a1..9406fce58d 100644 --- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -10,13 +9,13 @@ // objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. #include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/renderer/RenderTarget.h" - #include "libGLESv2/Texture.h" -#include "libGLESv2/renderer/Renderer.h" -#include "common/utilities.h" #include "libGLESv2/formatutils.h" #include "libGLESv2/FramebufferAttachment.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/RenderTarget.h" + +#include "common/utilities.h" namespace gl { @@ -29,6 +28,11 @@ Renderbuffer::Renderbuffer(GLuint id, RenderbufferStorage *newStorage) ASSERT(mStorage); } +Renderbuffer::~Renderbuffer() +{ + SafeDelete(mStorage); +} + void Renderbuffer::setStorage(RenderbufferStorage *newStorage) { ASSERT(newStorage); @@ -75,32 +79,32 @@ GLsizei Renderbuffer::getSamples() const GLuint Renderbuffer::getRedSize() const { - return gl::GetRedBits(getActualFormat()); + return GetInternalFormatInfo(getActualFormat()).redBits; } GLuint Renderbuffer::getGreenSize() const { - return gl::GetGreenBits(getActualFormat()); + return GetInternalFormatInfo(getActualFormat()).greenBits; } GLuint Renderbuffer::getBlueSize() const { - return gl::GetBlueBits(getActualFormat()); + return GetInternalFormatInfo(getActualFormat()).blueBits; } GLuint Renderbuffer::getAlphaSize() const { - return gl::GetAlphaBits(getActualFormat()); + return GetInternalFormatInfo(getActualFormat()).alphaBits; } GLuint Renderbuffer::getDepthSize() const { - return gl::GetDepthBits(getActualFormat()); + return GetInternalFormatInfo(getActualFormat()).depthBits; } GLuint Renderbuffer::getStencilSize() const { - return gl::GetStencilBits(getActualFormat()); + return GetInternalFormatInfo(getActualFormat()).stencilBits; } RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerials(1)) @@ -121,11 +125,6 @@ rx::RenderTarget *RenderbufferStorage::getRenderTarget() return NULL; } -rx::RenderTarget *RenderbufferStorage::getDepthStencil() -{ - return NULL; -} - GLsizei RenderbufferStorage::getWidth() const { return mWidth; @@ -156,7 +155,7 @@ unsigned int RenderbufferStorage::getSerial() const return mSerial; } -unsigned int RenderbufferStorage::issueSerials(GLuint count) +unsigned int RenderbufferStorage::issueSerials(unsigned int count) { unsigned int firstSerial = mCurrentSerial; mCurrentSerial += count; @@ -247,7 +246,7 @@ DepthStencilbuffer::~DepthStencilbuffer() } } -rx::RenderTarget *DepthStencilbuffer::getDepthStencil() +rx::RenderTarget *DepthStencilbuffer::getRenderTarget() { return mDepthStencil; } diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h index e2d0c6b0fd..71bcb0e1f8 100644 --- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h @@ -39,6 +39,7 @@ class Renderbuffer : public RefCountObject { public: Renderbuffer(GLuint id, RenderbufferStorage *newStorage); + virtual ~Renderbuffer(); void setStorage(RenderbufferStorage *newStorage); RenderbufferStorage *getStorage(); @@ -70,7 +71,6 @@ class RenderbufferStorage virtual ~RenderbufferStorage() = 0; virtual rx::RenderTarget *getRenderTarget(); - virtual rx::RenderTarget *getDepthStencil(); virtual GLsizei getWidth() const; virtual GLsizei getHeight() const; @@ -83,7 +83,7 @@ class RenderbufferStorage virtual bool isTexture() const; virtual unsigned int getTextureSerial() const; - static unsigned int issueSerials(GLuint count); + static unsigned int issueSerials(unsigned int count); protected: GLsizei mWidth; @@ -124,7 +124,7 @@ class DepthStencilbuffer : public RenderbufferStorage ~DepthStencilbuffer(); - virtual rx::RenderTarget *getDepthStencil(); + virtual rx::RenderTarget *getRenderTarget(); protected: rx::RenderTarget *mDepthStencil; diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp b/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp index 3606532404..9121de1750 100644 --- a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp +++ b/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -93,13 +92,9 @@ GLuint ResourceManager::createShader(GLenum type) { GLuint handle = mProgramShaderHandleAllocator.allocate(); - if (type == GL_VERTEX_SHADER) + if (type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER) { - mShaderMap[handle] = new VertexShader(this, mRenderer, handle); - } - else if (type == GL_FRAGMENT_SHADER) - { - mShaderMap[handle] = new FragmentShader(this, mRenderer, handle); + mShaderMap[handle] = new Shader(this, mRenderer->createShader(type), type, handle); } else UNREACHABLE(); @@ -151,7 +146,9 @@ GLuint ResourceManager::createFenceSync() { GLuint handle = mFenceSyncHandleAllocator.allocate(); - mFenceSyncMap[handle] = new FenceSync(mRenderer, handle); + FenceSync *fenceSync = new FenceSync(mRenderer, handle); + fenceSync->addRef(); + mFenceSyncMap[handle] = fenceSync; return handle; } @@ -369,27 +366,27 @@ void ResourceManager::checkBufferAllocation(unsigned int buffer) } } -void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type) +void ResourceManager::checkTextureAllocation(GLuint texture, GLenum type) { if (!getTexture(texture) && texture != 0) { Texture *textureObject; - if (type == TEXTURE_2D) + if (type == GL_TEXTURE_2D) { - textureObject = new Texture2D(mRenderer->createTexture2D(), texture); + textureObject = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), texture); } - else if (type == TEXTURE_CUBE) + else if (type == GL_TEXTURE_CUBE_MAP) { - textureObject = new TextureCubeMap(mRenderer->createTextureCube(), texture); + textureObject = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), texture); } - else if (type == TEXTURE_3D) + else if (type == GL_TEXTURE_3D) { - textureObject = new Texture3D(mRenderer->createTexture3D(), texture); + textureObject = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), texture); } - else if (type == TEXTURE_2D_ARRAY) + else if (type == GL_TEXTURE_2D_ARRAY) { - textureObject = new Texture2DArray(mRenderer->createTexture2DArray(), texture); + textureObject = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), texture); } else { diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h b/src/3rdparty/angle/src/libGLESv2/ResourceManager.h index d646c0d3cf..7d53bd4854 100644 --- a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h +++ b/src/3rdparty/angle/src/libGLESv2/ResourceManager.h @@ -10,14 +10,14 @@ #ifndef LIBGLESV2_RESOURCEMANAGER_H_ #define LIBGLESV2_RESOURCEMANAGER_H_ -#include "angle_gl.h" - -#include <unordered_map> - #include "common/angleutils.h" #include "libGLESv2/angletypes.h" #include "libGLESv2/HandleAllocator.h" +#include "angle_gl.h" + +#include <unordered_map> + namespace rx { class Renderer; @@ -65,11 +65,11 @@ class ResourceManager Renderbuffer *getRenderbuffer(GLuint handle); Sampler *getSampler(GLuint handle); FenceSync *getFenceSync(GLuint handle); - + void setRenderbuffer(GLuint handle, Renderbuffer *renderbuffer); void checkBufferAllocation(unsigned int buffer); - void checkTextureAllocation(GLuint texture, TextureType type); + void checkTextureAllocation(GLuint texture, GLenum type); void checkRenderbufferAllocation(GLuint renderbuffer); void checkSamplerAllocation(GLuint sampler); diff --git a/src/3rdparty/angle/src/libGLESv2/Sampler.cpp b/src/3rdparty/angle/src/libGLESv2/Sampler.cpp index ed6e29f89e..b906e65557 100644 --- a/src/3rdparty/angle/src/libGLESv2/Sampler.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Sampler.cpp @@ -1,4 +1,3 @@ -#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 diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.cpp b/src/3rdparty/angle/src/libGLESv2/Shader.cpp index eda0298e87..e3da2b1a9e 100644 --- a/src/3rdparty/angle/src/libGLESv2/Shader.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Shader.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -10,27 +9,30 @@ // functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84. #include "libGLESv2/Shader.h" - -#include "GLSLANG/ShaderLang.h" -#include "common/utilities.h" #include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/ShaderImpl.h" #include "libGLESv2/Constants.h" #include "libGLESv2/ResourceManager.h" +#include "common/utilities.h" + +#include "GLSLANG/ShaderLang.h" + +#include <sstream> + namespace gl { -void *Shader::mFragmentCompiler = NULL; -void *Shader::mVertexCompiler = NULL; -Shader::Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) - : mHandle(handle), mRenderer(renderer), mResourceManager(manager) +Shader::Shader(ResourceManager *manager, rx::ShaderImpl *impl, GLenum type, GLuint handle) + : mShader(impl), + mType(type), + mHandle(handle), + mResourceManager(manager), + mRefCount(0), + mDeleteStatus(false), + mCompiled(false) { - uncompile(); - initializeCompiler(); - - mRefCount = 0; - mDeleteStatus = false; - mShaderVersion = 100; + ASSERT(impl); } Shader::~Shader() @@ -56,7 +58,7 @@ void Shader::setSource(GLsizei count, const char *const *string, const GLint *le int Shader::getInfoLogLength() const { - return mInfoLog.empty() ? 0 : (mInfoLog.length() + 1); + return mShader->getInfoLog().empty() ? 0 : (mShader->getInfoLog().length() + 1); } void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const @@ -65,8 +67,8 @@ void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const if (bufSize > 0) { - index = std::min(bufSize - 1, static_cast<GLsizei>(mInfoLog.length())); - memcpy(infoLog, mInfoLog.c_str(), index); + index = std::min(bufSize - 1, static_cast<GLsizei>(mShader->getInfoLog().length())); + memcpy(infoLog, mShader->getInfoLog().c_str(), index); infoLog[index] = '\0'; } @@ -84,10 +86,10 @@ int Shader::getSourceLength() const int Shader::getTranslatedSourceLength() const { - return mHlsl.empty() ? 0 : (mHlsl.length() + 1); + return mShader->getTranslatedSource().empty() ? 0 : (mShader->getTranslatedSource().length() + 1); } -void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer) const +void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer) { int index = 0; @@ -112,44 +114,12 @@ void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) const void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const { - getSourceImpl(mHlsl, bufSize, length, buffer); + getSourceImpl(mShader->getTranslatedSource(), bufSize, length, buffer); } -unsigned int Shader::getUniformRegister(const std::string &uniformName) const +void Shader::compile() { - ASSERT(mUniformRegisterMap.count(uniformName) > 0); - return mUniformRegisterMap.find(uniformName)->second; -} - -unsigned int Shader::getInterfaceBlockRegister(const std::string &blockName) const -{ - ASSERT(mInterfaceBlockRegisterMap.count(blockName) > 0); - return mInterfaceBlockRegisterMap.find(blockName)->second; -} - -const std::vector<sh::Uniform> &Shader::getUniforms() const -{ - return mActiveUniforms; -} - -const std::vector<sh::InterfaceBlock> &Shader::getInterfaceBlocks() const -{ - return mActiveInterfaceBlocks; -} - -std::vector<PackedVarying> &Shader::getVaryings() -{ - return mVaryings; -} - -bool Shader::isCompiled() const -{ - return !mHlsl.empty(); -} - -const std::string &Shader::getHLSL() const -{ - return mHlsl; + mCompiled = mShader->compile(mSource); } void Shader::addRef() @@ -182,412 +152,54 @@ void Shader::flagForDeletion() mDeleteStatus = true; } -// Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler) -void Shader::initializeCompiler() -{ - if (!mFragmentCompiler) - { - int result = ShInitialize(); - - if (result) - { - ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT; - - ShBuiltInResources resources; - ShInitBuiltInResources(&resources); - - // TODO(geofflang): use context's caps - const gl::Caps &caps = mRenderer->getRendererCaps(); - const gl::Extensions &extensions = mRenderer->getRendererExtensions(); - - resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS; - resources.MaxVertexUniformVectors = mRenderer->getMaxVertexUniformVectors(); - resources.MaxVaryingVectors = mRenderer->getMaxVaryingVectors(); - resources.MaxVertexTextureImageUnits = mRenderer->getMaxVertexTextureImageUnits(); - resources.MaxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits(); - resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; - resources.MaxFragmentUniformVectors = mRenderer->getMaxFragmentUniformVectors(); - resources.MaxDrawBuffers = caps.maxDrawBuffers; - resources.OES_standard_derivatives = extensions.standardDerivatives; - resources.EXT_draw_buffers = extensions.drawBuffers; - resources.EXT_shader_texture_lod = 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 - // GLSL ES 3.0 constants - resources.MaxVertexOutputVectors = mRenderer->getMaxVaryingVectors(); - resources.MaxFragmentInputVectors = mRenderer->getMaxVaryingVectors(); - resources.MinProgramTexelOffset = -8; // D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE - resources.MaxProgramTexelOffset = 7; // D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE - - mFragmentCompiler = ShConstructCompiler(GL_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources); - mVertexCompiler = ShConstructCompiler(GL_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources); - } - } -} - -void Shader::releaseCompiler() +const std::vector<gl::PackedVarying> &Shader::getVaryings() const { - ShDestruct(mFragmentCompiler); - ShDestruct(mVertexCompiler); - - mFragmentCompiler = NULL; - mVertexCompiler = NULL; - - ShFinalize(); + return mShader->getVaryings(); } -void Shader::parseVaryings(void *compiler) -{ - if (!mHlsl.empty()) - { - std::vector<sh::Varying> *activeVaryings; - ShGetInfoPointer(compiler, SH_ACTIVE_VARYINGS_ARRAY, reinterpret_cast<void**>(&activeVaryings)); - - for (size_t varyingIndex = 0; varyingIndex < activeVaryings->size(); varyingIndex++) - { - mVaryings.push_back(PackedVarying((*activeVaryings)[varyingIndex])); - } - - mUsesMultipleRenderTargets = mHlsl.find("GL_USES_MRT") != std::string::npos; - mUsesFragColor = mHlsl.find("GL_USES_FRAG_COLOR") != std::string::npos; - mUsesFragData = mHlsl.find("GL_USES_FRAG_DATA") != std::string::npos; - mUsesFragCoord = mHlsl.find("GL_USES_FRAG_COORD") != std::string::npos; - mUsesFrontFacing = mHlsl.find("GL_USES_FRONT_FACING") != std::string::npos; - mUsesPointSize = mHlsl.find("GL_USES_POINT_SIZE") != std::string::npos; - mUsesPointCoord = mHlsl.find("GL_USES_POINT_COORD") != std::string::npos; - mUsesDepthRange = mHlsl.find("GL_USES_DEPTH_RANGE") != std::string::npos; - mUsesFragDepth = mHlsl.find("GL_USES_FRAG_DEPTH") != std::string::npos; - mUsesDiscardRewriting = mHlsl.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos; - mUsesNestedBreak = mHlsl.find("ANGLE_USES_NESTED_BREAK") != std::string::npos; - } -} - -void Shader::resetVaryingsRegisterAssignment() -{ - for (unsigned int varyingIndex = 0; varyingIndex < mVaryings.size(); varyingIndex++) - { - mVaryings[varyingIndex].resetRegisterAssignment(); - } -} - -// initialize/clean up previous state -void Shader::uncompile() -{ - // set by compileToHLSL - mHlsl.clear(); - mInfoLog.clear(); - - // set by parseVaryings - mVaryings.clear(); - - mUsesMultipleRenderTargets = false; - mUsesFragColor = false; - mUsesFragData = false; - mUsesFragCoord = false; - mUsesFrontFacing = false; - mUsesPointSize = false; - mUsesPointCoord = false; - mUsesDepthRange = false; - mUsesFragDepth = false; - mShaderVersion = 100; - mUsesDiscardRewriting = false; - mUsesNestedBreak = false; - - mActiveUniforms.clear(); - mActiveInterfaceBlocks.clear(); -} - -void Shader::compileToHLSL(void *compiler) -{ - // ensure the compiler is loaded - initializeCompiler(); - - int compileOptions = SH_OBJECT_CODE; - std::string sourcePath; - if (perfActive()) - { - sourcePath = getTempPath(); - writeFile(sourcePath.c_str(), mSource.c_str(), mSource.length()); - compileOptions |= SH_LINE_DIRECTIVES; - } - - int result; - if (sourcePath.empty()) - { - const char* sourceStrings[] = - { - mSource.c_str(), - }; - - result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions); - } - else - { - const char* sourceStrings[] = - { - sourcePath.c_str(), - mSource.c_str(), - }; - - result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH); - } - - size_t shaderVersion = 100; - ShGetInfo(compiler, SH_SHADER_VERSION, &shaderVersion); - - mShaderVersion = static_cast<int>(shaderVersion); - - if (shaderVersion == 300 && mRenderer->getCurrentClientVersion() < 3) - { - mInfoLog = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts"; - TRACE("\n%s", mInfoLog.c_str()); - } - else if (result) - { - size_t objCodeLen = 0; - ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen); - - char* outputHLSL = new char[objCodeLen]; - ShGetObjectCode(compiler, outputHLSL); - -#ifdef _DEBUG - std::ostringstream hlslStream; - hlslStream << "// GLSL\n"; - hlslStream << "//\n"; - - size_t curPos = 0; - while (curPos != std::string::npos) - { - size_t nextLine = mSource.find("\n", curPos); - size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1); - - hlslStream << "// " << mSource.substr(curPos, len); - - curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1); - } - hlslStream << "\n\n"; - hlslStream << outputHLSL; - mHlsl = hlslStream.str(); -#else - mHlsl = outputHLSL; -#endif - - delete[] outputHLSL; - - void *activeUniforms; - ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms); - mActiveUniforms = *(std::vector<sh::Uniform>*)activeUniforms; - - for (size_t uniformIndex = 0; uniformIndex < mActiveUniforms.size(); uniformIndex++) - { - const sh::Uniform &uniform = mActiveUniforms[uniformIndex]; - - unsigned int index = -1; - bool result = ShGetUniformRegister(compiler, uniform.name.c_str(), &index); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(result); - - mUniformRegisterMap[uniform.name] = index; - } - - void *activeInterfaceBlocks; - ShGetInfoPointer(compiler, SH_ACTIVE_INTERFACE_BLOCKS_ARRAY, &activeInterfaceBlocks); - mActiveInterfaceBlocks = *(std::vector<sh::InterfaceBlock>*)activeInterfaceBlocks; - - for (size_t blockIndex = 0; blockIndex < mActiveInterfaceBlocks.size(); blockIndex++) - { - const sh::InterfaceBlock &interfaceBlock = mActiveInterfaceBlocks[blockIndex]; - - unsigned int index = -1; - bool result = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name.c_str(), &index); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(result); - - mInterfaceBlockRegisterMap[interfaceBlock.name] = index; - } - } - else - { - size_t infoLogLen = 0; - ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen); - - char* infoLog = new char[infoLogLen]; - ShGetInfoLog(compiler, infoLog); - mInfoLog = infoLog; - - TRACE("\n%s", mInfoLog.c_str()); - } -} - -rx::D3DWorkaroundType Shader::getD3DWorkarounds() const -{ - if (mUsesDiscardRewriting) - { - // ANGLE issue 486: - // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization - return rx::ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION; - } - - if (mUsesNestedBreak) - { - // ANGLE issue 603: - // Work-around a D3D9 compiler bug that presents itself when using break in a nested loop, by maximizing optimization - // We want to keep the use of ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes precedence - return rx::ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION; - } - - return rx::ANGLE_D3D_WORKAROUND_NONE; -} - -// true if varying x has a higher priority in packing than y -bool Shader::compareVarying(const PackedVarying &x, const PackedVarying &y) -{ - if (x.type == y.type) - { - return x.arraySize > y.arraySize; - } - - // Special case for handling structs: we sort these to the end of the list - if (x.type == GL_STRUCT_ANGLEX) - { - return false; - } - - if (y.type == GL_STRUCT_ANGLEX) - { - return true; - } - - return gl::VariableSortOrder(x.type) <= gl::VariableSortOrder(y.type); -} - -int Shader::getShaderVersion() const -{ - return mShaderVersion; -} - -VertexShader::VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) - : Shader(manager, renderer, handle) -{ -} - -VertexShader::~VertexShader() -{ -} - -GLenum VertexShader::getType() const -{ - return GL_VERTEX_SHADER; -} - -void VertexShader::uncompile() -{ - Shader::uncompile(); - - // set by ParseAttributes - mActiveAttributes.clear(); -} - -void VertexShader::compile() -{ - uncompile(); - - compileToHLSL(mVertexCompiler); - parseAttributes(); - parseVaryings(mVertexCompiler); -} - -int VertexShader::getSemanticIndex(const std::string &attributeName) +const std::vector<sh::Uniform> &Shader::getUniforms() const { - if (!attributeName.empty()) - { - int semanticIndex = 0; - for (unsigned int attributeIndex = 0; attributeIndex < mActiveAttributes.size(); attributeIndex++) - { - const sh::ShaderVariable &attribute = mActiveAttributes[attributeIndex]; - - if (attribute.name == attributeName) - { - return semanticIndex; - } - - semanticIndex += VariableRegisterCount(attribute.type); - } - } - - return -1; + return mShader->getUniforms(); } -void VertexShader::parseAttributes() +const std::vector<sh::InterfaceBlock> &Shader::getInterfaceBlocks() const { - const std::string &hlsl = getHLSL(); - if (!hlsl.empty()) - { - void *activeAttributes; - ShGetInfoPointer(mVertexCompiler, SH_ACTIVE_ATTRIBUTES_ARRAY, &activeAttributes); - mActiveAttributes = *(std::vector<sh::Attribute>*)activeAttributes; - } + return mShader->getInterfaceBlocks(); } -FragmentShader::FragmentShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) - : Shader(manager, renderer, handle) +const std::vector<sh::Attribute> &Shader::getActiveAttributes() const { + return mShader->getActiveAttributes(); } -FragmentShader::~FragmentShader() +const std::vector<sh::Attribute> &Shader::getActiveOutputVariables() const { + return mShader->getActiveOutputVariables(); } -GLenum FragmentShader::getType() const +std::vector<gl::PackedVarying> &Shader::getVaryings() { - return GL_FRAGMENT_SHADER; + return mShader->getVaryings(); } -void FragmentShader::compile() +std::vector<sh::Uniform> &Shader::getUniforms() { - uncompile(); - - compileToHLSL(mFragmentCompiler); - parseVaryings(mFragmentCompiler); - std::sort(mVaryings.begin(), mVaryings.end(), compareVarying); - - const std::string &hlsl = getHLSL(); - if (!hlsl.empty()) - { - void *activeOutputVariables; - ShGetInfoPointer(mFragmentCompiler, SH_ACTIVE_OUTPUT_VARIABLES_ARRAY, &activeOutputVariables); - mActiveOutputVariables = *(std::vector<sh::Attribute>*)activeOutputVariables; - } + return mShader->getUniforms(); } -void FragmentShader::uncompile() +std::vector<sh::InterfaceBlock> &Shader::getInterfaceBlocks() { - Shader::uncompile(); - - mActiveOutputVariables.clear(); + return mShader->getInterfaceBlocks(); } -const std::vector<sh::Attribute> &FragmentShader::getOutputVariables() const +std::vector<sh::Attribute> &Shader::getActiveAttributes() { - return mActiveOutputVariables; + return mShader->getActiveAttributes(); } -ShShaderOutput Shader::getCompilerOutputType(GLenum shader) +std::vector<sh::Attribute> &Shader::getActiveOutputVariables() { - void *compiler = NULL; - - switch (shader) - { - case GL_VERTEX_SHADER: compiler = mVertexCompiler; break; - case GL_FRAGMENT_SHADER: compiler = mFragmentCompiler; break; - default: UNREACHABLE(); return SH_HLSL9_OUTPUT; - } - - size_t outputType = 0; - ShGetInfo(compiler, SH_OUTPUT_TYPE, &outputType); - - return static_cast<ShShaderOutput>(outputType); + return mShader->getActiveOutputVariables(); } } diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.h b/src/3rdparty/angle/src/libGLESv2/Shader.h index a40f415c1e..7ba3bd165c 100644 --- a/src/3rdparty/angle/src/libGLESv2/Shader.h +++ b/src/3rdparty/angle/src/libGLESv2/Shader.h @@ -12,19 +12,20 @@ #ifndef LIBGLESV2_SHADER_H_ #define LIBGLESV2_SHADER_H_ -#include "angle_gl.h" + #include <string> #include <list> #include <vector> -#include "common/shadervars.h" +#include "angle_gl.h" +#include <GLSLANG/ShaderLang.h> + #include "common/angleutils.h" #include "libGLESv2/angletypes.h" -#include "GLSLANG/ShaderLang.h" namespace rx { -class Renderer; +class ShaderImpl; } namespace gl @@ -34,13 +35,16 @@ class ResourceManager; struct PackedVarying : public sh::Varying { unsigned int registerIndex; // Assigned during link + unsigned int columnIndex; // Assigned during link, defaults to 0 PackedVarying(const sh::Varying &varying) : sh::Varying(varying), - registerIndex(GL_INVALID_INDEX) + registerIndex(GL_INVALID_INDEX), + columnIndex(0) {} bool registerAssigned() const { return registerIndex != GL_INVALID_INDEX; } + bool isBuiltIn() const { return name.compare(0, 3, "gl_") == 0; } void resetRegisterAssignment() { @@ -50,16 +54,17 @@ struct PackedVarying : public sh::Varying class Shader { - friend class DynamicHLSL; - public: - Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle); + Shader(ResourceManager *manager, rx::ShaderImpl *impl, GLenum type, GLuint handle); virtual ~Shader(); - virtual GLenum getType() const = 0; + GLenum getType() const { return mType; } GLuint getHandle() const; + rx::ShaderImpl *getImplementation() { return mShader; } + const rx::ShaderImpl *getImplementation() const { return mShader; } + void deleteSource(); void setSource(GLsizei count, const char *const *string, const GLint *length); int getInfoLogLength() const; @@ -68,122 +73,44 @@ class Shader void getSource(GLsizei bufSize, GLsizei *length, char *buffer) const; int getTranslatedSourceLength() const; void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const; - const std::vector<sh::Uniform> &getUniforms() const; - const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const; - std::vector<PackedVarying> &getVaryings(); - virtual void compile() = 0; - virtual void uncompile(); - bool isCompiled() const; - const std::string &getHLSL() const; + void compile(); + bool isCompiled() const { return mCompiled; } void addRef(); void release(); unsigned int getRefCount() const; bool isFlaggedForDeletion() const; void flagForDeletion(); - int getShaderVersion() const; - void resetVaryingsRegisterAssignment(); - - static void releaseCompiler(); - static ShShaderOutput getCompilerOutputType(GLenum shader); - unsigned int getUniformRegister(const std::string &uniformName) const; - unsigned int getInterfaceBlockRegister(const std::string &blockName) const; - - bool usesDepthRange() const { return mUsesDepthRange; } - bool usesPointSize() const { return mUsesPointSize; } - rx::D3DWorkaroundType getD3DWorkarounds() const; - - protected: - void parseVaryings(void *compiler); - void compileToHLSL(void *compiler); - - void getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer) const; - - static bool compareVarying(const PackedVarying &x, const PackedVarying &y); - - const rx::Renderer *const mRenderer; - - std::vector<PackedVarying> mVaryings; - - bool mUsesMultipleRenderTargets; - bool mUsesFragColor; - bool mUsesFragData; - bool mUsesFragCoord; - bool mUsesFrontFacing; - bool mUsesPointSize; - bool mUsesPointCoord; - bool mUsesDepthRange; - bool mUsesFragDepth; - int mShaderVersion; - bool mUsesDiscardRewriting; - bool mUsesNestedBreak; + const std::vector<gl::PackedVarying> &getVaryings() const; + const std::vector<sh::Uniform> &getUniforms() const; + const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const; + const std::vector<sh::Attribute> &getActiveAttributes() const; + const std::vector<sh::Attribute> &getActiveOutputVariables() const; - static void *mFragmentCompiler; - static void *mVertexCompiler; + std::vector<gl::PackedVarying> &getVaryings(); + std::vector<sh::Uniform> &getUniforms(); + std::vector<sh::InterfaceBlock> &getInterfaceBlocks(); + std::vector<sh::Attribute> &getActiveAttributes(); + std::vector<sh::Attribute> &getActiveOutputVariables(); private: DISALLOW_COPY_AND_ASSIGN(Shader); - void initializeCompiler(); + static void getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer); + rx::ShaderImpl *mShader; const GLuint mHandle; + const GLenum mType; + std::string mSource; unsigned int mRefCount; // Number of program objects this shader is attached to bool mDeleteStatus; // Flag to indicate that the shader can be deleted when no longer in use - - std::string mSource; - std::string mHlsl; - std::string mInfoLog; - std::vector<sh::Uniform> mActiveUniforms; - std::vector<sh::InterfaceBlock> mActiveInterfaceBlocks; - std::map<std::string, unsigned int> mUniformRegisterMap; - std::map<std::string, unsigned int> mInterfaceBlockRegisterMap; + bool mCompiled; // Indicates if this shader has been successfully compiled ResourceManager *mResourceManager; }; -class VertexShader : public Shader -{ - friend class DynamicHLSL; - - public: - VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle); - - ~VertexShader(); - - virtual GLenum getType() const; - virtual void compile(); - virtual void uncompile(); - int getSemanticIndex(const std::string &attributeName); - - const std::vector<sh::Attribute> &activeAttributes() const { return mActiveAttributes; } - - private: - DISALLOW_COPY_AND_ASSIGN(VertexShader); - - void parseAttributes(); - - std::vector<sh::Attribute> mActiveAttributes; -}; - -class FragmentShader : public Shader -{ - public: - FragmentShader(ResourceManager *manager,const rx::Renderer *renderer, GLuint handle); - - ~FragmentShader(); - - virtual GLenum getType() const; - virtual void compile(); - virtual void uncompile(); - const std::vector<sh::Attribute> &getOutputVariables() const; - - private: - DISALLOW_COPY_AND_ASSIGN(FragmentShader); - - std::vector<sh::Attribute> mActiveOutputVariables; -}; } #endif // LIBGLESV2_SHADER_H_ |