summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src')
-rw-r--r--src/3rdparty/angle/src/common/angleutils.h2
-rw-r--r--src/3rdparty/angle/src/common/debug.cpp6
-rw-r--r--src/3rdparty/angle/src/common/event_tracer.cpp49
-rw-r--r--src/3rdparty/angle/src/common/event_tracer.h33
-rw-r--r--src/3rdparty/angle/src/common/version.h4
-rw-r--r--src/3rdparty/angle/src/compiler/BaseTypes.h8
-rw-r--r--src/3rdparty/angle/src/compiler/Common.h42
-rw-r--r--src/3rdparty/angle/src/compiler/Compiler.cpp212
-rw-r--r--src/3rdparty/angle/src/compiler/ConstantUnion.h2
-rw-r--r--src/3rdparty/angle/src/compiler/DetectCallDepth.cpp185
-rw-r--r--src/3rdparty/angle/src/compiler/DetectCallDepth.h80
-rw-r--r--src/3rdparty/angle/src/compiler/Diagnostics.cpp2
-rw-r--r--src/3rdparty/angle/src/compiler/InfoSink.cpp25
-rw-r--r--src/3rdparty/angle/src/compiler/InfoSink.h8
-rw-r--r--src/3rdparty/angle/src/compiler/Initialize.cpp799
-rw-r--r--src/3rdparty/angle/src/compiler/Initialize.h16
-rw-r--r--src/3rdparty/angle/src/compiler/InitializeDll.cpp89
-rw-r--r--src/3rdparty/angle/src/compiler/InitializeDll.h5
-rw-r--r--src/3rdparty/angle/src/compiler/InitializeGLPosition.cpp61
-rw-r--r--src/3rdparty/angle/src/compiler/InitializeGLPosition.h33
-rw-r--r--src/3rdparty/angle/src/compiler/InitializeGlobals.h2
-rw-r--r--src/3rdparty/angle/src/compiler/InitializeParseContext.cpp78
-rw-r--r--src/3rdparty/angle/src/compiler/InitializeParseContext.h15
-rw-r--r--src/3rdparty/angle/src/compiler/Intermediate.cpp147
-rw-r--r--src/3rdparty/angle/src/compiler/OutputGLSL.cpp14
-rw-r--r--src/3rdparty/angle/src/compiler/OutputGLSL.h1
-rw-r--r--src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp81
-rw-r--r--src/3rdparty/angle/src/compiler/OutputGLSLBase.h3
-rw-r--r--src/3rdparty/angle/src/compiler/OutputHLSL.cpp324
-rw-r--r--src/3rdparty/angle/src/compiler/OutputHLSL.h13
-rw-r--r--src/3rdparty/angle/src/compiler/ParseHelper.cpp355
-rw-r--r--src/3rdparty/angle/src/compiler/ParseHelper.h89
-rw-r--r--src/3rdparty/angle/src/compiler/PoolAlloc.cpp68
-rw-r--r--src/3rdparty/angle/src/compiler/PoolAlloc.h10
-rw-r--r--src/3rdparty/angle/src/compiler/ShHandle.h14
-rw-r--r--src/3rdparty/angle/src/compiler/ShaderLang.cpp171
-rw-r--r--src/3rdparty/angle/src/compiler/SymbolTable.cpp201
-rw-r--r--src/3rdparty/angle/src/compiler/SymbolTable.h151
-rw-r--r--src/3rdparty/angle/src/compiler/Types.h240
-rw-r--r--src/3rdparty/angle/src/compiler/ValidateLimitations.cpp2
-rw-r--r--src/3rdparty/angle/src/compiler/VariableInfo.cpp204
-rw-r--r--src/3rdparty/angle/src/compiler/VariableInfo.h24
-rw-r--r--src/3rdparty/angle/src/compiler/glslang.l310
-rw-r--r--src/3rdparty/angle/src/compiler/glslang.y935
-rw-r--r--src/3rdparty/angle/src/compiler/intermOut.cpp17
-rw-r--r--src/3rdparty/angle/src/compiler/intermediate.h33
-rw-r--r--src/3rdparty/angle/src/compiler/localintermediate.h45
-rw-r--r--src/3rdparty/angle/src/compiler/parseConst.cpp42
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp33
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h6
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h3
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l12
-rw-r--r--src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp6
-rw-r--r--src/3rdparty/angle/src/compiler/util.cpp39
-rw-r--r--src/3rdparty/angle/src/compiler/util.h17
-rw-r--r--src/3rdparty/angle/src/libEGL/Display.cpp45
-rw-r--r--src/3rdparty/angle/src/libEGL/Display.h7
-rw-r--r--src/3rdparty/angle/src/libEGL/Surface.cpp37
-rw-r--r--src/3rdparty/angle/src/libEGL/libEGL.cpp21
-rw-r--r--src/3rdparty/angle/src/libEGL/main.cpp61
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Buffer.cpp9
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Buffer.h7
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Context.cpp11
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp13
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Framebuffer.h1
-rw-r--r--src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp115
-rw-r--r--src/3rdparty/angle/src/libGLESv2/ProgramBinary.h2
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Shader.cpp5
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Shader.h2
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Texture.cpp6
-rw-r--r--src/3rdparty/angle/src/libGLESv2/angletypes.h3
-rw-r--r--src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp15
-rw-r--r--src/3rdparty/angle/src/libGLESv2/libGLESv2.def5
-rw-r--r--src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def6
-rw-r--r--src/3rdparty/angle/src/libGLESv2/libGLESv2d.def4
-rw-r--r--src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def6
-rw-r--r--src/3rdparty/angle/src/libGLESv2/main.cpp33
-rw-r--r--src/3rdparty/angle/src/libGLESv2/main.h4
-rw-r--r--src/3rdparty/angle/src/libGLESv2/mathutil.h2
-rw-r--r--src/3rdparty/angle/src/libGLESv2/precompiled.h8
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp24
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp2
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp22
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/Image11.h2
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.cpp49
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.h34
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp3
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.cpp87
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp97
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h58
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.cpp75
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.h25
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp2
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.cpp23
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.h7
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp26
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h6
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp415
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h14
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.cpp215
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.h3
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h2
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp1
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp11
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.cpp107
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.h19
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.cpp30
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.h7
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.cpp60
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.h5
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp96
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h4
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp2
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl11
-rw-r--r--src/3rdparty/angle/src/libGLESv2/utilities.cpp23
-rw-r--r--src/3rdparty/angle/src/libGLESv2/utilities.h1
-rw-r--r--src/3rdparty/angle/src/third_party/trace_event/trace_event.h828
117 files changed, 4764 insertions, 3426 deletions
diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h
index 31ac559279..9761567fb2 100644
--- a/src/3rdparty/angle/src/common/angleutils.h
+++ b/src/3rdparty/angle/src/common/angleutils.h
@@ -9,6 +9,8 @@
#ifndef COMMON_ANGLEUTILS_H_
#define COMMON_ANGLEUTILS_H_
+#include <stddef.h>
+
// A macro to disallow the copy constructor and operator= functions
// This must be used in the private: declarations for a class
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
diff --git a/src/3rdparty/angle/src/common/debug.cpp b/src/3rdparty/angle/src/common/debug.cpp
index 438d3975e8..9b932567b0 100644
--- a/src/3rdparty/angle/src/common/debug.cpp
+++ b/src/3rdparty/angle/src/common/debug.cpp
@@ -8,10 +8,10 @@
#include "common/debug.h"
#include "common/system.h"
-#ifdef ANGLE_ENABLE_D3D11
-typedef DWORD D3DCOLOR;
-#else
+#ifndef ANGLE_ENABLE_D3D11
#include <d3d9.h>
+#else
+typedef DWORD D3DCOLOR;
#endif
namespace gl
diff --git a/src/3rdparty/angle/src/common/event_tracer.cpp b/src/3rdparty/angle/src/common/event_tracer.cpp
new file mode 100644
index 0000000000..96cbb01061
--- /dev/null
+++ b/src/3rdparty/angle/src/common/event_tracer.cpp
@@ -0,0 +1,49 @@
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "common/event_tracer.h"
+
+namespace gl
+{
+
+GetCategoryEnabledFlagFunc g_getCategoryEnabledFlag;
+AddTraceEventFunc g_addTraceEvent;
+
+} // namespace gl
+
+extern "C" {
+
+void __stdcall SetTraceFunctionPointers(GetCategoryEnabledFlagFunc getCategoryEnabledFlag,
+ AddTraceEventFunc addTraceEvent)
+{
+ gl::g_getCategoryEnabledFlag = getCategoryEnabledFlag;
+ gl::g_addTraceEvent = addTraceEvent;
+}
+
+} // extern "C"
+
+namespace gl
+{
+
+const unsigned char* TraceGetTraceCategoryEnabledFlag(const char* name)
+{
+ if (g_getCategoryEnabledFlag)
+ {
+ return g_getCategoryEnabledFlag(name);
+ }
+ static unsigned char disabled = 0;
+ return &disabled;
+}
+
+void TraceAddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id,
+ int numArgs, const char** argNames, const unsigned char* argTypes,
+ const unsigned long long* argValues, unsigned char flags)
+{
+ if (g_addTraceEvent)
+ {
+ g_addTraceEvent(phase, categoryGroupEnabled, name, id, numArgs, argNames, argTypes, argValues, flags);
+ }
+}
+
+} // namespace gl
diff --git a/src/3rdparty/angle/src/common/event_tracer.h b/src/3rdparty/angle/src/common/event_tracer.h
new file mode 100644
index 0000000000..ae397e7db9
--- /dev/null
+++ b/src/3rdparty/angle/src/common/event_tracer.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_EVENT_TRACER_H_
+#define COMMON_EVENT_TRACER_H_
+
+extern "C" {
+
+typedef const unsigned char* (*GetCategoryEnabledFlagFunc)(const char* name);
+typedef void (*AddTraceEventFunc)(char phase, const unsigned char* categoryGroupEnabled, const char* name,
+ unsigned long long id, int numArgs, const char** argNames,
+ const unsigned char* argTypes, const unsigned long long* argValues,
+ unsigned char flags);
+
+// extern "C" so that it has a reasonable name for GetProcAddress.
+void __stdcall SetTraceFunctionPointers(GetCategoryEnabledFlagFunc get_category_enabled_flag,
+ AddTraceEventFunc add_trace_event_func);
+
+}
+
+namespace gl
+{
+
+const unsigned char* TraceGetTraceCategoryEnabledFlag(const char* name);
+
+void TraceAddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id,
+ int numArgs, const char** argNames, const unsigned char* argTypes,
+ const unsigned long long* argValues, unsigned char flags);
+
+}
+
+#endif // COMMON_EVENT_TRACER_H_
diff --git a/src/3rdparty/angle/src/common/version.h b/src/3rdparty/angle/src/common/version.h
index 7913851e6a..7a4942ad88 100644
--- a/src/3rdparty/angle/src/common/version.h
+++ b/src/3rdparty/angle/src/common/version.h
@@ -1,7 +1,7 @@
#define MAJOR_VERSION 1
-#define MINOR_VERSION 1
+#define MINOR_VERSION 2
#define BUILD_VERSION 0
-#define BUILD_REVISION 2037
+#define BUILD_REVISION 2446
#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)
diff --git a/src/3rdparty/angle/src/compiler/BaseTypes.h b/src/3rdparty/angle/src/compiler/BaseTypes.h
index af4c7e3ed9..1631f4f779 100644
--- a/src/3rdparty/angle/src/compiler/BaseTypes.h
+++ b/src/3rdparty/angle/src/compiler/BaseTypes.h
@@ -90,10 +90,6 @@ enum TQualifier
EvqInvariantVaryingOut, // vertex shaders only read/write
EvqUniform, // Readonly, vertex and fragment
- // pack/unpack input and output
- EvqInput,
- EvqOutput,
-
// parameters
EvqIn,
EvqOut,
@@ -112,6 +108,7 @@ enum TQualifier
// built-ins written by fragment shader
EvqFragColor,
EvqFragData,
+ EvqFragDepth,
// end of list
EvqLast
@@ -137,14 +134,13 @@ inline const char* getQualifierString(TQualifier q)
case EvqIn: return "in"; break;
case EvqOut: return "out"; break;
case EvqInOut: return "inout"; break;
- case EvqInput: return "input"; break;
- case EvqOutput: return "output"; break;
case EvqPosition: return "Position"; break;
case EvqPointSize: return "PointSize"; break;
case EvqFragCoord: return "FragCoord"; break;
case EvqFrontFacing: return "FrontFacing"; break;
case EvqFragColor: return "FragColor"; break;
case EvqFragData: return "FragData"; break;
+ case EvqFragDepth: return "FragDepth"; break;
default: return "unknown qualifier";
}
}
diff --git a/src/3rdparty/angle/src/compiler/Common.h b/src/3rdparty/angle/src/compiler/Common.h
index 27a5598290..46f9440fff 100644
--- a/src/3rdparty/angle/src/compiler/Common.h
+++ b/src/3rdparty/angle/src/compiler/Common.h
@@ -14,36 +14,24 @@
#include "compiler/PoolAlloc.h"
-// We need two pieces of information to report errors/warnings - string and
-// line number. We encode these into a single int so that it can be easily
-// incremented/decremented by lexer. The right SOURCE_LOC_LINE_SIZE bits store
-// line number while the rest store the string number. Since the shaders are
-// usually small, we should not run out of memory. SOURCE_LOC_LINE_SIZE
-// can be increased to alleviate this issue.
-typedef int TSourceLoc;
-const unsigned int SOURCE_LOC_LINE_SIZE = 16; // in bits.
-const unsigned int SOURCE_LOC_LINE_MASK = (1 << SOURCE_LOC_LINE_SIZE) - 1;
-
-inline TSourceLoc EncodeSourceLoc(int string, int line) {
- return (string << SOURCE_LOC_LINE_SIZE) | (line & SOURCE_LOC_LINE_MASK);
-}
-
-inline void DecodeSourceLoc(TSourceLoc loc, int* string, int* line) {
- if (string) *string = loc >> SOURCE_LOC_LINE_SIZE;
- if (line) *line = loc & SOURCE_LOC_LINE_MASK;
-}
+struct TSourceLoc {
+ int first_file;
+ int first_line;
+ int last_file;
+ int last_line;
+};
//
// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme.
//
-#define POOL_ALLOCATOR_NEW_DELETE(A) \
- void* operator new(size_t s) { return (A).allocate(s); } \
- void* operator new(size_t, void *_Where) { return (_Where); } \
- void operator delete(void*) { } \
- void operator delete(void *, void *) { } \
- void* operator new[](size_t s) { return (A).allocate(s); } \
- void* operator new[](size_t, void *_Where) { return (_Where); } \
- void operator delete[](void*) { } \
+#define POOL_ALLOCATOR_NEW_DELETE() \
+ void* operator new(size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \
+ void* operator new(size_t, void *_Where) { return (_Where); } \
+ void operator delete(void*) { } \
+ void operator delete(void *, void *) { } \
+ void* operator new[](size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \
+ void* operator new[](size_t, void *_Where) { return (_Where); } \
+ void operator delete[](void*) { } \
void operator delete[](void *, void *) { }
//
@@ -54,7 +42,7 @@ typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TStri
typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream;
inline TString* NewPoolTString(const char* s)
{
- void* memory = GlobalPoolAllocator.allocate(sizeof(TString));
+ void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TString));
return new(memory) TString(s);
}
diff --git a/src/3rdparty/angle/src/compiler/Compiler.cpp b/src/3rdparty/angle/src/compiler/Compiler.cpp
index c8c79e7147..ee64057ac4 100644
--- a/src/3rdparty/angle/src/compiler/Compiler.cpp
+++ b/src/3rdparty/angle/src/compiler/Compiler.cpp
@@ -1,13 +1,14 @@
//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "compiler/BuiltInFunctionEmulator.h"
-#include "compiler/DetectRecursion.h"
+#include "compiler/DetectCallDepth.h"
#include "compiler/ForLoopUnroll.h"
#include "compiler/Initialize.h"
+#include "compiler/InitializeGLPosition.h"
#include "compiler/InitializeParseContext.h"
#include "compiler/MapLongVariableNames.h"
#include "compiler/ParseHelper.h"
@@ -27,66 +28,34 @@ bool isWebGLBasedSpec(ShShaderSpec spec)
}
namespace {
-bool InitializeSymbolTable(
- const TBuiltInStrings& builtInStrings,
- ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources,
- TInfoSink& infoSink, TSymbolTable& symbolTable)
-{
- TIntermediate intermediate(infoSink);
- TExtensionBehavior extBehavior;
- InitExtensionBehavior(resources, extBehavior);
- // The builtins deliberately don't specify precisions for the function
- // arguments and return types. For that reason we don't try to check them.
- TParseContext parseContext(symbolTable, extBehavior, intermediate, type, spec, 0, false, NULL, infoSink);
- parseContext.fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1;
-
- GlobalParseContext = &parseContext;
-
- assert(symbolTable.isEmpty());
- //
- // Parse the built-ins. This should only happen once per
- // language symbol table.
- //
- // Push the symbol table to give it an initial scope. This
- // push should not have a corresponding pop, so that built-ins
- // are preserved, and the test for an empty table fails.
- //
- symbolTable.push();
-
- for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i)
- {
- const char* builtInShaders = i->c_str();
- int builtInLengths = static_cast<int>(i->size());
- if (builtInLengths <= 0)
- continue;
-
- if (PaParseStrings(1, &builtInShaders, &builtInLengths, &parseContext) != 0)
- {
- infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
- return false;
- }
- }
-
- IdentifyBuiltIns(type, spec, resources, symbolTable);
-
- return true;
-}
-
class TScopedPoolAllocator {
public:
- TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop)
- : mAllocator(allocator), mPushPopAllocator(pushPop) {
- if (mPushPopAllocator) mAllocator->push();
+ TScopedPoolAllocator(TPoolAllocator* allocator) : mAllocator(allocator) {
+ mAllocator->push();
SetGlobalPoolAllocator(mAllocator);
}
~TScopedPoolAllocator() {
SetGlobalPoolAllocator(NULL);
- if (mPushPopAllocator) mAllocator->pop();
+ mAllocator->pop();
}
private:
TPoolAllocator* mAllocator;
- bool mPushPopAllocator;
+};
+
+class TScopedSymbolTableLevel {
+public:
+ TScopedSymbolTableLevel(TSymbolTable* table) : mTable(table) {
+ ASSERT(mTable->atBuiltInLevel());
+ mTable->push();
+ }
+ ~TScopedSymbolTableLevel() {
+ while (!mTable->atBuiltInLevel())
+ mTable->pop();
+ }
+
+private:
+ TSymbolTable* mTable;
};
} // namespace
@@ -103,6 +72,9 @@ TShHandleBase::~TShHandleBase() {
TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
: shaderType(type),
shaderSpec(spec),
+ maxUniformVectors(0),
+ maxExpressionComplexity(0),
+ maxCallStackDepth(0),
fragmentPrecisionHigh(false),
clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
builtInFunctionEmulator(type)
@@ -121,7 +93,10 @@ bool TCompiler::Init(const ShBuiltInResources& resources)
maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ?
resources.MaxVertexUniformVectors :
resources.MaxFragmentUniformVectors;
- TScopedPoolAllocator scopedAlloc(&allocator, false);
+ maxExpressionComplexity = resources.MaxExpressionComplexity;
+ maxCallStackDepth = resources.MaxCallStackDepth;
+
+ SetGlobalPoolAllocator(&allocator);
// Generate built-in symbol table.
if (!InitBuiltInSymbolTable(resources))
@@ -141,7 +116,7 @@ bool TCompiler::compile(const char* const shaderStrings[],
size_t numStrings,
int compileOptions)
{
- TScopedPoolAllocator scopedAlloc(&allocator, true);
+ TScopedPoolAllocator scopedAlloc(&allocator);
clearResults();
if (numStrings == 0)
@@ -165,13 +140,11 @@ bool TCompiler::compile(const char* const shaderStrings[],
shaderType, shaderSpec, compileOptions, true,
sourcePath, infoSink);
parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh;
- GlobalParseContext = &parseContext;
+ SetGlobalParseContext(&parseContext);
// We preserve symbols at the built-in level from compile-to-compile.
// Start pushing the user-defined symbols at global level.
- symbolTable.push();
- if (!symbolTable.atGlobalLevel())
- infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
+ TScopedSymbolTableLevel scopedSymbolLevel(&symbolTable);
// Parse shader.
bool success =
@@ -182,7 +155,7 @@ bool TCompiler::compile(const char* const shaderStrings[],
success = intermediate.postProcess(root);
if (success)
- success = detectRecursion(root);
+ success = detectCallDepth(root, infoSink, (compileOptions & SH_LIMIT_CALL_STACK_DEPTH) != 0);
if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
success = validateLimitations(root);
@@ -205,6 +178,10 @@ bool TCompiler::compile(const char* const shaderStrings[],
if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
+ // Disallow expressions deemed too complex.
+ if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY))
+ success = limitExpressionComplexity(root);
+
// Call mapLongVariableNames() before collectAttribsUniforms() so in
// collectAttribsUniforms() we already have the mapped symbol names and
// we could composite mapped and original variable names.
@@ -212,12 +189,18 @@ bool TCompiler::compile(const char* const shaderStrings[],
if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) && hashFunction == NULL)
mapLongVariableNames(root);
- if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) {
- collectAttribsUniforms(root);
+ if (success && shaderType == SH_VERTEX_SHADER && (compileOptions & SH_INIT_GL_POSITION)) {
+ InitializeGLPosition initGLPosition;
+ root->traverse(&initGLPosition);
+ }
+
+ if (success && (compileOptions & SH_VARIABLES)) {
+ collectVariables(root);
if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) {
success = enforcePackingRestrictions();
if (!success) {
- infoSink.info.message(EPrefixError, "too many uniforms");
+ infoSink.info.prefix(EPrefixError);
+ infoSink.info << "too many uniforms";
}
}
}
@@ -231,22 +214,58 @@ bool TCompiler::compile(const char* const shaderStrings[],
// Cleanup memory.
intermediate.remove(parseContext.treeRoot);
- // Ensure symbol table is returned to the built-in level,
- // throwing away all but the built-ins.
- while (!symbolTable.atBuiltInLevel())
- symbolTable.pop();
return success;
}
-bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources)
+bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
{
- TBuiltIns builtIns;
-
compileResources = resources;
- builtIns.initialize(shaderType, shaderSpec, resources);
- return InitializeSymbolTable(builtIns.getBuiltInStrings(),
- shaderType, shaderSpec, resources, infoSink, symbolTable);
+
+ assert(symbolTable.isEmpty());
+ symbolTable.push();
+
+ TPublicType integer;
+ integer.type = EbtInt;
+ integer.size = 1;
+ integer.matrix = false;
+ integer.array = false;
+
+ TPublicType floatingPoint;
+ floatingPoint.type = EbtFloat;
+ floatingPoint.size = 1;
+ floatingPoint.matrix = false;
+ floatingPoint.array = false;
+
+ TPublicType sampler;
+ sampler.size = 1;
+ sampler.matrix = false;
+ sampler.array = false;
+
+ switch(shaderType)
+ {
+ case SH_FRAGMENT_SHADER:
+ symbolTable.setDefaultPrecision(integer, EbpMedium);
+ break;
+ case SH_VERTEX_SHADER:
+ symbolTable.setDefaultPrecision(integer, EbpHigh);
+ symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
+ break;
+ default: assert(false && "Language not supported");
+ }
+ // We set defaults for all the sampler types, even those that are
+ // only available if an extension exists.
+ for (int samplerType = EbtGuardSamplerBegin + 1;
+ samplerType < EbtGuardSamplerEnd; ++samplerType) {
+ sampler.type = static_cast<TBasicType>(samplerType);
+ symbolTable.setDefaultPrecision(sampler, EbpLow);
+ }
+
+ InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable);
+
+ IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable);
+
+ return true;
}
void TCompiler::clearResults()
@@ -258,24 +277,31 @@ void TCompiler::clearResults()
attribs.clear();
uniforms.clear();
+ varyings.clear();
builtInFunctionEmulator.Cleanup();
nameMap.clear();
}
-bool TCompiler::detectRecursion(TIntermNode* root)
+bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth)
{
- DetectRecursion detect;
+ DetectCallDepth detect(infoSink, limitCallStackDepth, maxCallStackDepth);
root->traverse(&detect);
- switch (detect.detectRecursion()) {
- case DetectRecursion::kErrorNone:
+ switch (detect.detectCallDepth()) {
+ case DetectCallDepth::kErrorNone:
return true;
- case DetectRecursion::kErrorMissingMain:
- infoSink.info.message(EPrefixError, "Missing main()");
+ case DetectCallDepth::kErrorMissingMain:
+ infoSink.info.prefix(EPrefixError);
+ infoSink.info << "Missing main()";
+ return false;
+ case DetectCallDepth::kErrorRecursion:
+ infoSink.info.prefix(EPrefixError);
+ infoSink.info << "Function recursion detected";
return false;
- case DetectRecursion::kErrorRecursion:
- infoSink.info.message(EPrefixError, "Function recursion detected");
+ case DetectCallDepth::kErrorMaxDepthExceeded:
+ infoSink.info.prefix(EPrefixError);
+ infoSink.info << "Function call stack too deep";
return false;
default:
UNREACHABLE();
@@ -321,6 +347,28 @@ bool TCompiler::enforceTimingRestrictions(TIntermNode* root, bool outputGraph)
}
}
+bool TCompiler::limitExpressionComplexity(TIntermNode* root)
+{
+ TIntermTraverser traverser;
+ root->traverse(&traverser);
+ TDependencyGraph graph(root);
+
+ for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls();
+ iter != graph.endUserDefinedFunctionCalls();
+ ++iter)
+ {
+ TGraphFunctionCall* samplerSymbol = *iter;
+ TDependencyGraphTraverser graphTraverser;
+ samplerSymbol->traverse(&graphTraverser);
+ }
+
+ if (traverser.getMaxDepth() > maxExpressionComplexity) {
+ infoSink.info << "Expression too complex.";
+ return false;
+ }
+ return true;
+}
+
bool TCompiler::enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph)
{
RestrictFragmentShaderTiming restrictor(infoSink.info);
@@ -335,9 +383,9 @@ bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root)
return restrictor.numErrors() == 0;
}
-void TCompiler::collectAttribsUniforms(TIntermNode* root)
+void TCompiler::collectVariables(TIntermNode* root)
{
- CollectAttribsUniforms collect(attribs, uniforms, hashFunction);
+ CollectVariables collect(attribs, uniforms, varyings, hashFunction);
root->traverse(&collect);
}
diff --git a/src/3rdparty/angle/src/compiler/ConstantUnion.h b/src/3rdparty/angle/src/compiler/ConstantUnion.h
index 32af4d38b0..b1e37885f9 100644
--- a/src/3rdparty/angle/src/compiler/ConstantUnion.h
+++ b/src/3rdparty/angle/src/compiler/ConstantUnion.h
@@ -11,13 +11,13 @@
class ConstantUnion {
public:
+ POOL_ALLOCATOR_NEW_DELETE();
ConstantUnion()
{
iConst = 0;
type = EbtVoid;
}
- POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
void setIConst(int i) {iConst = i; type = EbtInt; }
void setFConst(float f) {fConst = f; type = EbtFloat; }
void setBConst(bool b) {bConst = b; type = EbtBool; }
diff --git a/src/3rdparty/angle/src/compiler/DetectCallDepth.cpp b/src/3rdparty/angle/src/compiler/DetectCallDepth.cpp
new file mode 100644
index 0000000000..60df52c715
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/DetectCallDepth.cpp
@@ -0,0 +1,185 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/DetectCallDepth.h"
+#include "compiler/InfoSink.h"
+
+DetectCallDepth::FunctionNode::FunctionNode(const TString& fname)
+ : name(fname),
+ visit(PreVisit)
+{
+}
+
+const TString& DetectCallDepth::FunctionNode::getName() const
+{
+ return name;
+}
+
+void DetectCallDepth::FunctionNode::addCallee(
+ DetectCallDepth::FunctionNode* callee)
+{
+ for (size_t i = 0; i < callees.size(); ++i) {
+ if (callees[i] == callee)
+ return;
+ }
+ callees.push_back(callee);
+}
+
+int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDepth, int depth)
+{
+ ASSERT(visit == PreVisit);
+ ASSERT(detectCallDepth);
+
+ int maxDepth = depth;
+ visit = InVisit;
+ for (size_t i = 0; i < callees.size(); ++i) {
+ switch (callees[i]->visit) {
+ case InVisit:
+ // cycle detected, i.e., recursion detected.
+ return kInfiniteCallDepth;
+ case PostVisit:
+ break;
+ case PreVisit: {
+ // Check before we recurse so we don't go too depth
+ if (detectCallDepth->checkExceedsMaxDepth(depth))
+ return depth;
+ int callDepth = callees[i]->detectCallDepth(detectCallDepth, depth + 1);
+ // Check after we recurse so we can exit immediately and provide info.
+ if (detectCallDepth->checkExceedsMaxDepth(callDepth)) {
+ detectCallDepth->getInfoSink().info << "<-" << callees[i]->getName();
+ return callDepth;
+ }
+ maxDepth = std::max(callDepth, maxDepth);
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+ visit = PostVisit;
+ return maxDepth;
+}
+
+void DetectCallDepth::FunctionNode::reset()
+{
+ visit = PreVisit;
+}
+
+DetectCallDepth::DetectCallDepth(TInfoSink& infoSink, bool limitCallStackDepth, int maxCallStackDepth)
+ : TIntermTraverser(true, false, true, false),
+ currentFunction(NULL),
+ infoSink(infoSink),
+ maxDepth(limitCallStackDepth ? maxCallStackDepth : FunctionNode::kInfiniteCallDepth)
+{
+}
+
+DetectCallDepth::~DetectCallDepth()
+{
+ for (size_t i = 0; i < functions.size(); ++i)
+ delete functions[i];
+}
+
+bool DetectCallDepth::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+ switch (node->getOp())
+ {
+ case EOpPrototype:
+ // Function declaration.
+ // Don't add FunctionNode here because node->getName() is the
+ // unmangled function name.
+ break;
+ case EOpFunction: {
+ // Function definition.
+ if (visit == PreVisit) {
+ currentFunction = findFunctionByName(node->getName());
+ if (currentFunction == NULL) {
+ currentFunction = new FunctionNode(node->getName());
+ functions.push_back(currentFunction);
+ }
+ } else if (visit == PostVisit) {
+ currentFunction = NULL;
+ }
+ break;
+ }
+ case EOpFunctionCall: {
+ // Function call.
+ if (visit == PreVisit) {
+ FunctionNode* func = findFunctionByName(node->getName());
+ if (func == NULL) {
+ func = new FunctionNode(node->getName());
+ functions.push_back(func);
+ }
+ if (currentFunction)
+ currentFunction->addCallee(func);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return true;
+}
+
+bool DetectCallDepth::checkExceedsMaxDepth(int depth)
+{
+ return depth >= maxDepth;
+}
+
+void DetectCallDepth::resetFunctionNodes()
+{
+ for (size_t i = 0; i < functions.size(); ++i) {
+ functions[i]->reset();
+ }
+}
+
+DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepthForFunction(FunctionNode* func)
+{
+ currentFunction = NULL;
+ resetFunctionNodes();
+
+ int maxCallDepth = func->detectCallDepth(this, 1);
+
+ if (maxCallDepth == FunctionNode::kInfiniteCallDepth)
+ return kErrorRecursion;
+
+ if (maxCallDepth >= maxDepth)
+ return kErrorMaxDepthExceeded;
+
+ return kErrorNone;
+}
+
+DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepth()
+{
+ if (maxDepth != FunctionNode::kInfiniteCallDepth) {
+ // Check all functions because the driver may fail on them
+ // TODO: Before detectingRecursion, strip unused functions.
+ for (size_t i = 0; i < functions.size(); ++i) {
+ ErrorCode error = detectCallDepthForFunction(functions[i]);
+ if (error != kErrorNone)
+ return error;
+ }
+ } else {
+ FunctionNode* main = findFunctionByName("main(");
+ if (main == NULL)
+ return kErrorMissingMain;
+
+ return detectCallDepthForFunction(main);
+ }
+
+ return kErrorNone;
+}
+
+DetectCallDepth::FunctionNode* DetectCallDepth::findFunctionByName(
+ const TString& name)
+{
+ for (size_t i = 0; i < functions.size(); ++i) {
+ if (functions[i]->getName() == name)
+ return functions[i];
+ }
+ return NULL;
+}
+
diff --git a/src/3rdparty/angle/src/compiler/DetectCallDepth.h b/src/3rdparty/angle/src/compiler/DetectCallDepth.h
new file mode 100644
index 0000000000..89e85f88f6
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/DetectCallDepth.h
@@ -0,0 +1,80 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_DETECT_RECURSION_H_
+#define COMPILER_DETECT_RECURSION_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+#include <limits.h>
+#include "compiler/intermediate.h"
+#include "compiler/VariableInfo.h"
+
+class TInfoSink;
+
+// Traverses intermediate tree to detect function recursion.
+class DetectCallDepth : public TIntermTraverser {
+public:
+ enum ErrorCode {
+ kErrorMissingMain,
+ kErrorRecursion,
+ kErrorMaxDepthExceeded,
+ kErrorNone
+ };
+
+ DetectCallDepth(TInfoSink& infoSync, bool limitCallStackDepth, int maxCallStackDepth);
+ ~DetectCallDepth();
+
+ virtual bool visitAggregate(Visit, TIntermAggregate*);
+
+ bool checkExceedsMaxDepth(int depth);
+
+ ErrorCode detectCallDepth();
+
+private:
+ class FunctionNode {
+ public:
+ static const int kInfiniteCallDepth = INT_MAX;
+
+ FunctionNode(const TString& fname);
+
+ const TString& getName() const;
+
+ // If a function is already in the callee list, this becomes a no-op.
+ void addCallee(FunctionNode* callee);
+
+ // Returns kInifinityCallDepth if recursive function calls are detected.
+ int detectCallDepth(DetectCallDepth* detectCallDepth, int depth);
+
+ // Reset state.
+ void reset();
+
+ private:
+ // mangled function name is unique.
+ TString name;
+
+ // functions that are directly called by this function.
+ TVector<FunctionNode*> callees;
+
+ Visit visit;
+ };
+
+ ErrorCode detectCallDepthForFunction(FunctionNode* func);
+ FunctionNode* findFunctionByName(const TString& name);
+ void resetFunctionNodes();
+
+ TInfoSink& getInfoSink() { return infoSink; }
+
+ TVector<FunctionNode*> functions;
+ FunctionNode* currentFunction;
+ TInfoSink& infoSink;
+ int maxDepth;
+
+ DetectCallDepth(const DetectCallDepth&);
+ void operator=(const DetectCallDepth&);
+};
+
+#endif // COMPILER_DETECT_RECURSION_H_
diff --git a/src/3rdparty/angle/src/compiler/Diagnostics.cpp b/src/3rdparty/angle/src/compiler/Diagnostics.cpp
index 06f370dbe5..8a38c41a65 100644
--- a/src/3rdparty/angle/src/compiler/Diagnostics.cpp
+++ b/src/3rdparty/angle/src/compiler/Diagnostics.cpp
@@ -46,7 +46,7 @@ void TDiagnostics::writeInfo(Severity severity,
TInfoSinkBase& sink = mInfoSink.info;
/* VC++ format: file(linenum) : error #: 'token' : extrainfo */
sink.prefix(prefix);
- sink.location(EncodeSourceLoc(loc.file, loc.line));
+ sink.location(loc.file, loc.line);
sink << "'" << token << "' : " << reason << " " << extra << "\n";
}
diff --git a/src/3rdparty/angle/src/compiler/InfoSink.cpp b/src/3rdparty/angle/src/compiler/InfoSink.cpp
index ba32f781f5..d20a6c0175 100644
--- a/src/3rdparty/angle/src/compiler/InfoSink.cpp
+++ b/src/3rdparty/angle/src/compiler/InfoSink.cpp
@@ -6,8 +6,8 @@
#include "compiler/InfoSink.h"
-void TInfoSinkBase::prefix(TPrefixType message) {
- switch(message) {
+void TInfoSinkBase::prefix(TPrefixType p) {
+ switch(p) {
case EPrefixNone:
break;
case EPrefixWarning:
@@ -31,29 +31,24 @@ void TInfoSinkBase::prefix(TPrefixType message) {
}
}
-void TInfoSinkBase::location(TSourceLoc loc) {
- int string = 0, line = 0;
- DecodeSourceLoc(loc, &string, &line);
-
+void TInfoSinkBase::location(int file, int line) {
TPersistStringStream stream;
if (line)
- stream << string << ":" << line;
+ stream << file << ":" << line;
else
- stream << string << ":? ";
+ stream << file << ":? ";
stream << ": ";
sink.append(stream.str());
}
-void TInfoSinkBase::message(TPrefixType message, const char* s) {
- prefix(message);
- sink.append(s);
- sink.append("\n");
+void TInfoSinkBase::location(const TSourceLoc& loc) {
+ location(loc.first_file, loc.first_line);
}
-void TInfoSinkBase::message(TPrefixType message, const char* s, TSourceLoc loc) {
- prefix(message);
+void TInfoSinkBase::message(TPrefixType p, const TSourceLoc& loc, const char* m) {
+ prefix(p);
location(loc);
- sink.append(s);
+ sink.append(m);
sink.append("\n");
}
diff --git a/src/3rdparty/angle/src/compiler/InfoSink.h b/src/3rdparty/angle/src/compiler/InfoSink.h
index e2224e918d..6888838142 100644
--- a/src/3rdparty/angle/src/compiler/InfoSink.h
+++ b/src/3rdparty/angle/src/compiler/InfoSink.h
@@ -96,10 +96,10 @@ public:
const TPersistString& str() const { return sink; }
const char* c_str() const { return sink.c_str(); }
- void prefix(TPrefixType message);
- void location(TSourceLoc loc);
- void message(TPrefixType message, const char* s);
- void message(TPrefixType message, const char* s, TSourceLoc loc);
+ void prefix(TPrefixType p);
+ void location(int file, int line);
+ void location(const TSourceLoc& loc);
+ void message(TPrefixType p, const TSourceLoc& loc, const char* m);
private:
TPersistString sink;
diff --git a/src/3rdparty/angle/src/compiler/Initialize.cpp b/src/3rdparty/angle/src/compiler/Initialize.cpp
index 97b46f898e..236383d874 100644
--- a/src/3rdparty/angle/src/compiler/Initialize.cpp
+++ b/src/3rdparty/angle/src/compiler/Initialize.cpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -14,513 +14,413 @@
#include "compiler/intermediate.h"
-//============================================================================
-//
-// Prototypes for built-in functions seen by both vertex and fragment shaders.
-//
-//============================================================================
-static TString BuiltInFunctionsCommon(const ShBuiltInResources& resources)
+void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable)
{
- TString s;
+ TType *float1 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 1);
+ TType *float2 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 2);
+ TType *float3 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 3);
+ TType *float4 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 4);
+
+ TType *int2 = new TType(EbtInt, EbpUndefined, EvqGlobal, 2);
+ TType *int3 = new TType(EbtInt, EbpUndefined, EvqGlobal, 3);
+ TType *int4 = new TType(EbtInt, EbpUndefined, EvqGlobal, 4);
//
// Angle and Trigonometric Functions.
//
- s.append(TString("float radians(float degrees);"));
- s.append(TString("vec2 radians(vec2 degrees);"));
- s.append(TString("vec3 radians(vec3 degrees);"));
- s.append(TString("vec4 radians(vec4 degrees);"));
-
- s.append(TString("float degrees(float radians);"));
- s.append(TString("vec2 degrees(vec2 radians);"));
- s.append(TString("vec3 degrees(vec3 radians);"));
- s.append(TString("vec4 degrees(vec4 radians);"));
-
- s.append(TString("float sin(float angle);"));
- s.append(TString("vec2 sin(vec2 angle);"));
- s.append(TString("vec3 sin(vec3 angle);"));
- s.append(TString("vec4 sin(vec4 angle);"));
-
- s.append(TString("float cos(float angle);"));
- s.append(TString("vec2 cos(vec2 angle);"));
- s.append(TString("vec3 cos(vec3 angle);"));
- s.append(TString("vec4 cos(vec4 angle);"));
-
- s.append(TString("float tan(float angle);"));
- s.append(TString("vec2 tan(vec2 angle);"));
- s.append(TString("vec3 tan(vec3 angle);"));
- s.append(TString("vec4 tan(vec4 angle);"));
-
- s.append(TString("float asin(float x);"));
- s.append(TString("vec2 asin(vec2 x);"));
- s.append(TString("vec3 asin(vec3 x);"));
- s.append(TString("vec4 asin(vec4 x);"));
-
- s.append(TString("float acos(float x);"));
- s.append(TString("vec2 acos(vec2 x);"));
- s.append(TString("vec3 acos(vec3 x);"));
- s.append(TString("vec4 acos(vec4 x);"));
-
- s.append(TString("float atan(float y, float x);"));
- s.append(TString("vec2 atan(vec2 y, vec2 x);"));
- s.append(TString("vec3 atan(vec3 y, vec3 x);"));
- s.append(TString("vec4 atan(vec4 y, vec4 x);"));
-
- s.append(TString("float atan(float y_over_x);"));
- s.append(TString("vec2 atan(vec2 y_over_x);"));
- s.append(TString("vec3 atan(vec3 y_over_x);"));
- s.append(TString("vec4 atan(vec4 y_over_x);"));
+ symbolTable.insertBuiltIn(float1, "radians", float1);
+ symbolTable.insertBuiltIn(float2, "radians", float2);
+ symbolTable.insertBuiltIn(float3, "radians", float3);
+ symbolTable.insertBuiltIn(float4, "radians", float4);
+
+ symbolTable.insertBuiltIn(float1, "degrees", float1);
+ symbolTable.insertBuiltIn(float2, "degrees", float2);
+ symbolTable.insertBuiltIn(float3, "degrees", float3);
+ symbolTable.insertBuiltIn(float4, "degrees", float4);
+
+ symbolTable.insertBuiltIn(float1, "sin", float1);
+ symbolTable.insertBuiltIn(float2, "sin", float2);
+ symbolTable.insertBuiltIn(float3, "sin", float3);
+ symbolTable.insertBuiltIn(float4, "sin", float4);
+
+ symbolTable.insertBuiltIn(float1, "cos", float1);
+ symbolTable.insertBuiltIn(float2, "cos", float2);
+ symbolTable.insertBuiltIn(float3, "cos", float3);
+ symbolTable.insertBuiltIn(float4, "cos", float4);
+
+ symbolTable.insertBuiltIn(float1, "tan", float1);
+ symbolTable.insertBuiltIn(float2, "tan", float2);
+ symbolTable.insertBuiltIn(float3, "tan", float3);
+ symbolTable.insertBuiltIn(float4, "tan", float4);
+
+ symbolTable.insertBuiltIn(float1, "asin", float1);
+ symbolTable.insertBuiltIn(float2, "asin", float2);
+ symbolTable.insertBuiltIn(float3, "asin", float3);
+ symbolTable.insertBuiltIn(float4, "asin", float4);
+
+ symbolTable.insertBuiltIn(float1, "acos", float1);
+ symbolTable.insertBuiltIn(float2, "acos", float2);
+ symbolTable.insertBuiltIn(float3, "acos", float3);
+ symbolTable.insertBuiltIn(float4, "acos", float4);
+
+ symbolTable.insertBuiltIn(float1, "atan", float1, float1);
+ symbolTable.insertBuiltIn(float2, "atan", float2, float2);
+ symbolTable.insertBuiltIn(float3, "atan", float3, float3);
+ symbolTable.insertBuiltIn(float4, "atan", float4, float4);
+
+ symbolTable.insertBuiltIn(float1, "atan", float1);
+ symbolTable.insertBuiltIn(float2, "atan", float2);
+ symbolTable.insertBuiltIn(float3, "atan", float3);
+ symbolTable.insertBuiltIn(float4, "atan", float4);
//
// Exponential Functions.
//
- s.append(TString("float pow(float x, float y);"));
- s.append(TString("vec2 pow(vec2 x, vec2 y);"));
- s.append(TString("vec3 pow(vec3 x, vec3 y);"));
- s.append(TString("vec4 pow(vec4 x, vec4 y);"));
-
- s.append(TString("float exp(float x);"));
- s.append(TString("vec2 exp(vec2 x);"));
- s.append(TString("vec3 exp(vec3 x);"));
- s.append(TString("vec4 exp(vec4 x);"));
-
- s.append(TString("float log(float x);"));
- s.append(TString("vec2 log(vec2 x);"));
- s.append(TString("vec3 log(vec3 x);"));
- s.append(TString("vec4 log(vec4 x);"));
-
- s.append(TString("float exp2(float x);"));
- s.append(TString("vec2 exp2(vec2 x);"));
- s.append(TString("vec3 exp2(vec3 x);"));
- s.append(TString("vec4 exp2(vec4 x);"));
-
- s.append(TString("float log2(float x);"));
- s.append(TString("vec2 log2(vec2 x);"));
- s.append(TString("vec3 log2(vec3 x);"));
- s.append(TString("vec4 log2(vec4 x);"));
-
- s.append(TString("float sqrt(float x);"));
- s.append(TString("vec2 sqrt(vec2 x);"));
- s.append(TString("vec3 sqrt(vec3 x);"));
- s.append(TString("vec4 sqrt(vec4 x);"));
-
- s.append(TString("float inversesqrt(float x);"));
- s.append(TString("vec2 inversesqrt(vec2 x);"));
- s.append(TString("vec3 inversesqrt(vec3 x);"));
- s.append(TString("vec4 inversesqrt(vec4 x);"));
+ symbolTable.insertBuiltIn(float1, "pow", float1, float1);
+ symbolTable.insertBuiltIn(float2, "pow", float2, float2);
+ symbolTable.insertBuiltIn(float3, "pow", float3, float3);
+ symbolTable.insertBuiltIn(float4, "pow", float4, float4);
+
+ symbolTable.insertBuiltIn(float1, "exp", float1);
+ symbolTable.insertBuiltIn(float2, "exp", float2);
+ symbolTable.insertBuiltIn(float3, "exp", float3);
+ symbolTable.insertBuiltIn(float4, "exp", float4);
+
+ symbolTable.insertBuiltIn(float1, "log", float1);
+ symbolTable.insertBuiltIn(float2, "log", float2);
+ symbolTable.insertBuiltIn(float3, "log", float3);
+ symbolTable.insertBuiltIn(float4, "log", float4);
+
+ symbolTable.insertBuiltIn(float1, "exp2", float1);
+ symbolTable.insertBuiltIn(float2, "exp2", float2);
+ symbolTable.insertBuiltIn(float3, "exp2", float3);
+ symbolTable.insertBuiltIn(float4, "exp2", float4);
+
+ symbolTable.insertBuiltIn(float1, "log2", float1);
+ symbolTable.insertBuiltIn(float2, "log2", float2);
+ symbolTable.insertBuiltIn(float3, "log2", float3);
+ symbolTable.insertBuiltIn(float4, "log2", float4);
+
+ symbolTable.insertBuiltIn(float1, "sqrt", float1);
+ symbolTable.insertBuiltIn(float2, "sqrt", float2);
+ symbolTable.insertBuiltIn(float3, "sqrt", float3);
+ symbolTable.insertBuiltIn(float4, "sqrt", float4);
+
+ symbolTable.insertBuiltIn(float1, "inversesqrt", float1);
+ symbolTable.insertBuiltIn(float2, "inversesqrt", float2);
+ symbolTable.insertBuiltIn(float3, "inversesqrt", float3);
+ symbolTable.insertBuiltIn(float4, "inversesqrt", float4);
//
// Common Functions.
//
- s.append(TString("float abs(float x);"));
- s.append(TString("vec2 abs(vec2 x);"));
- s.append(TString("vec3 abs(vec3 x);"));
- s.append(TString("vec4 abs(vec4 x);"));
-
- s.append(TString("float sign(float x);"));
- s.append(TString("vec2 sign(vec2 x);"));
- s.append(TString("vec3 sign(vec3 x);"));
- s.append(TString("vec4 sign(vec4 x);"));
-
- s.append(TString("float floor(float x);"));
- s.append(TString("vec2 floor(vec2 x);"));
- s.append(TString("vec3 floor(vec3 x);"));
- s.append(TString("vec4 floor(vec4 x);"));
-
- s.append(TString("float ceil(float x);"));
- s.append(TString("vec2 ceil(vec2 x);"));
- s.append(TString("vec3 ceil(vec3 x);"));
- s.append(TString("vec4 ceil(vec4 x);"));
-
- s.append(TString("float fract(float x);"));
- s.append(TString("vec2 fract(vec2 x);"));
- s.append(TString("vec3 fract(vec3 x);"));
- s.append(TString("vec4 fract(vec4 x);"));
-
- s.append(TString("float mod(float x, float y);"));
- s.append(TString("vec2 mod(vec2 x, float y);"));
- s.append(TString("vec3 mod(vec3 x, float y);"));
- s.append(TString("vec4 mod(vec4 x, float y);"));
- s.append(TString("vec2 mod(vec2 x, vec2 y);"));
- s.append(TString("vec3 mod(vec3 x, vec3 y);"));
- s.append(TString("vec4 mod(vec4 x, vec4 y);"));
-
- s.append(TString("float min(float x, float y);"));
- s.append(TString("vec2 min(vec2 x, float y);"));
- s.append(TString("vec3 min(vec3 x, float y);"));
- s.append(TString("vec4 min(vec4 x, float y);"));
- s.append(TString("vec2 min(vec2 x, vec2 y);"));
- s.append(TString("vec3 min(vec3 x, vec3 y);"));
- s.append(TString("vec4 min(vec4 x, vec4 y);"));
-
- s.append(TString("float max(float x, float y);"));
- s.append(TString("vec2 max(vec2 x, float y);"));
- s.append(TString("vec3 max(vec3 x, float y);"));
- s.append(TString("vec4 max(vec4 x, float y);"));
- s.append(TString("vec2 max(vec2 x, vec2 y);"));
- s.append(TString("vec3 max(vec3 x, vec3 y);"));
- s.append(TString("vec4 max(vec4 x, vec4 y);"));
-
- s.append(TString("float clamp(float x, float minVal, float maxVal);"));
- s.append(TString("vec2 clamp(vec2 x, float minVal, float maxVal);"));
- s.append(TString("vec3 clamp(vec3 x, float minVal, float maxVal);"));
- s.append(TString("vec4 clamp(vec4 x, float minVal, float maxVal);"));
- s.append(TString("vec2 clamp(vec2 x, vec2 minVal, vec2 maxVal);"));
- s.append(TString("vec3 clamp(vec3 x, vec3 minVal, vec3 maxVal);"));
- s.append(TString("vec4 clamp(vec4 x, vec4 minVal, vec4 maxVal);"));
-
- s.append(TString("float mix(float x, float y, float a);"));
- s.append(TString("vec2 mix(vec2 x, vec2 y, float a);"));
- s.append(TString("vec3 mix(vec3 x, vec3 y, float a);"));
- s.append(TString("vec4 mix(vec4 x, vec4 y, float a);"));
- s.append(TString("vec2 mix(vec2 x, vec2 y, vec2 a);"));
- s.append(TString("vec3 mix(vec3 x, vec3 y, vec3 a);"));
- s.append(TString("vec4 mix(vec4 x, vec4 y, vec4 a);"));
-
- s.append(TString("float step(float edge, float x);"));
- s.append(TString("vec2 step(vec2 edge, vec2 x);"));
- s.append(TString("vec3 step(vec3 edge, vec3 x);"));
- s.append(TString("vec4 step(vec4 edge, vec4 x);"));
- s.append(TString("vec2 step(float edge, vec2 x);"));
- s.append(TString("vec3 step(float edge, vec3 x);"));
- s.append(TString("vec4 step(float edge, vec4 x);"));
-
- s.append(TString("float smoothstep(float edge0, float edge1, float x);"));
- s.append(TString("vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x);"));
- s.append(TString("vec3 smoothstep(vec3 edge0, vec3 edge1, vec3 x);"));
- s.append(TString("vec4 smoothstep(vec4 edge0, vec4 edge1, vec4 x);"));
- s.append(TString("vec2 smoothstep(float edge0, float edge1, vec2 x);"));
- s.append(TString("vec3 smoothstep(float edge0, float edge1, vec3 x);"));
- s.append(TString("vec4 smoothstep(float edge0, float edge1, vec4 x);"));
+ symbolTable.insertBuiltIn(float1, "abs", float1);
+ symbolTable.insertBuiltIn(float2, "abs", float2);
+ symbolTable.insertBuiltIn(float3, "abs", float3);
+ symbolTable.insertBuiltIn(float4, "abs", float4);
+
+ symbolTable.insertBuiltIn(float1, "sign", float1);
+ symbolTable.insertBuiltIn(float2, "sign", float2);
+ symbolTable.insertBuiltIn(float3, "sign", float3);
+ symbolTable.insertBuiltIn(float4, "sign", float4);
+
+ symbolTable.insertBuiltIn(float1, "floor", float1);
+ symbolTable.insertBuiltIn(float2, "floor", float2);
+ symbolTable.insertBuiltIn(float3, "floor", float3);
+ symbolTable.insertBuiltIn(float4, "floor", float4);
+
+ symbolTable.insertBuiltIn(float1, "ceil", float1);
+ symbolTable.insertBuiltIn(float2, "ceil", float2);
+ symbolTable.insertBuiltIn(float3, "ceil", float3);
+ symbolTable.insertBuiltIn(float4, "ceil", float4);
+
+ symbolTable.insertBuiltIn(float1, "fract", float1);
+ symbolTable.insertBuiltIn(float2, "fract", float2);
+ symbolTable.insertBuiltIn(float3, "fract", float3);
+ symbolTable.insertBuiltIn(float4, "fract", float4);
+
+ symbolTable.insertBuiltIn(float1, "mod", float1, float1);
+ symbolTable.insertBuiltIn(float2, "mod", float2, float1);
+ symbolTable.insertBuiltIn(float3, "mod", float3, float1);
+ symbolTable.insertBuiltIn(float4, "mod", float4, float1);
+ symbolTable.insertBuiltIn(float2, "mod", float2, float2);
+ symbolTable.insertBuiltIn(float3, "mod", float3, float3);
+ symbolTable.insertBuiltIn(float4, "mod", float4, float4);
+
+ symbolTable.insertBuiltIn(float1, "min", float1, float1);
+ symbolTable.insertBuiltIn(float2, "min", float2, float1);
+ symbolTable.insertBuiltIn(float3, "min", float3, float1);
+ symbolTable.insertBuiltIn(float4, "min", float4, float1);
+ symbolTable.insertBuiltIn(float2, "min", float2, float2);
+ symbolTable.insertBuiltIn(float3, "min", float3, float3);
+ symbolTable.insertBuiltIn(float4, "min", float4, float4);
+
+ symbolTable.insertBuiltIn(float1, "max", float1, float1);
+ symbolTable.insertBuiltIn(float2, "max", float2, float1);
+ symbolTable.insertBuiltIn(float3, "max", float3, float1);
+ symbolTable.insertBuiltIn(float4, "max", float4, float1);
+ symbolTable.insertBuiltIn(float2, "max", float2, float2);
+ symbolTable.insertBuiltIn(float3, "max", float3, float3);
+ symbolTable.insertBuiltIn(float4, "max", float4, float4);
+
+ symbolTable.insertBuiltIn(float1, "clamp", float1, float1, float1);
+ symbolTable.insertBuiltIn(float2, "clamp", float2, float1, float1);
+ symbolTable.insertBuiltIn(float3, "clamp", float3, float1, float1);
+ symbolTable.insertBuiltIn(float4, "clamp", float4, float1, float1);
+ symbolTable.insertBuiltIn(float2, "clamp", float2, float2, float2);
+ symbolTable.insertBuiltIn(float3, "clamp", float3, float3, float3);
+ symbolTable.insertBuiltIn(float4, "clamp", float4, float4, float4);
+
+ symbolTable.insertBuiltIn(float1, "mix", float1, float1, float1);
+ symbolTable.insertBuiltIn(float2, "mix", float2, float2, float1);
+ symbolTable.insertBuiltIn(float3, "mix", float3, float3, float1);
+ symbolTable.insertBuiltIn(float4, "mix", float4, float4, float1);
+ symbolTable.insertBuiltIn(float2, "mix", float2, float2, float2);
+ symbolTable.insertBuiltIn(float3, "mix", float3, float3, float3);
+ symbolTable.insertBuiltIn(float4, "mix", float4, float4, float4);
+
+ symbolTable.insertBuiltIn(float1, "step", float1, float1);
+ symbolTable.insertBuiltIn(float2, "step", float2, float2);
+ symbolTable.insertBuiltIn(float3, "step", float3, float3);
+ symbolTable.insertBuiltIn(float4, "step", float4, float4);
+ symbolTable.insertBuiltIn(float2, "step", float1, float2);
+ symbolTable.insertBuiltIn(float3, "step", float1, float3);
+ symbolTable.insertBuiltIn(float4, "step", float1, float4);
+
+ symbolTable.insertBuiltIn(float1, "smoothstep", float1, float1, float1);
+ symbolTable.insertBuiltIn(float2, "smoothstep", float2, float2, float2);
+ symbolTable.insertBuiltIn(float3, "smoothstep", float3, float3, float3);
+ symbolTable.insertBuiltIn(float4, "smoothstep", float4, float4, float4);
+ symbolTable.insertBuiltIn(float2, "smoothstep", float1, float1, float2);
+ symbolTable.insertBuiltIn(float3, "smoothstep", float1, float1, float3);
+ symbolTable.insertBuiltIn(float4, "smoothstep", float1, float1, float4);
//
// Geometric Functions.
//
- s.append(TString("float length(float x);"));
- s.append(TString("float length(vec2 x);"));
- s.append(TString("float length(vec3 x);"));
- s.append(TString("float length(vec4 x);"));
-
- s.append(TString("float distance(float p0, float p1);"));
- s.append(TString("float distance(vec2 p0, vec2 p1);"));
- s.append(TString("float distance(vec3 p0, vec3 p1);"));
- s.append(TString("float distance(vec4 p0, vec4 p1);"));
-
- s.append(TString("float dot(float x, float y);"));
- s.append(TString("float dot(vec2 x, vec2 y);"));
- s.append(TString("float dot(vec3 x, vec3 y);"));
- s.append(TString("float dot(vec4 x, vec4 y);"));
-
- s.append(TString("vec3 cross(vec3 x, vec3 y);"));
- s.append(TString("float normalize(float x);"));
- s.append(TString("vec2 normalize(vec2 x);"));
- s.append(TString("vec3 normalize(vec3 x);"));
- s.append(TString("vec4 normalize(vec4 x);"));
-
- s.append(TString("float faceforward(float N, float I, float Nref);"));
- s.append(TString("vec2 faceforward(vec2 N, vec2 I, vec2 Nref);"));
- s.append(TString("vec3 faceforward(vec3 N, vec3 I, vec3 Nref);"));
- s.append(TString("vec4 faceforward(vec4 N, vec4 I, vec4 Nref);"));
-
- s.append(TString("float reflect(float I, float N);"));
- s.append(TString("vec2 reflect(vec2 I, vec2 N);"));
- s.append(TString("vec3 reflect(vec3 I, vec3 N);"));
- s.append(TString("vec4 reflect(vec4 I, vec4 N);"));
-
- s.append(TString("float refract(float I, float N, float eta);"));
- s.append(TString("vec2 refract(vec2 I, vec2 N, float eta);"));
- s.append(TString("vec3 refract(vec3 I, vec3 N, float eta);"));
- s.append(TString("vec4 refract(vec4 I, vec4 N, float eta);"));
+ symbolTable.insertBuiltIn(float1, "length", float1);
+ symbolTable.insertBuiltIn(float1, "length", float2);
+ symbolTable.insertBuiltIn(float1, "length", float3);
+ symbolTable.insertBuiltIn(float1, "length", float4);
+
+ symbolTable.insertBuiltIn(float1, "distance", float1, float1);
+ symbolTable.insertBuiltIn(float1, "distance", float2, float2);
+ symbolTable.insertBuiltIn(float1, "distance", float3, float3);
+ symbolTable.insertBuiltIn(float1, "distance", float4, float4);
+
+ symbolTable.insertBuiltIn(float1, "dot", float1, float1);
+ symbolTable.insertBuiltIn(float1, "dot", float2, float2);
+ symbolTable.insertBuiltIn(float1, "dot", float3, float3);
+ symbolTable.insertBuiltIn(float1, "dot", float4, float4);
+
+ symbolTable.insertBuiltIn(float3, "cross", float3, float3);
+ symbolTable.insertBuiltIn(float1, "normalize", float1);
+ symbolTable.insertBuiltIn(float2, "normalize", float2);
+ symbolTable.insertBuiltIn(float3, "normalize", float3);
+ symbolTable.insertBuiltIn(float4, "normalize", float4);
+
+ symbolTable.insertBuiltIn(float1, "faceforward", float1, float1, float1);
+ symbolTable.insertBuiltIn(float2, "faceforward", float2, float2, float2);
+ symbolTable.insertBuiltIn(float3, "faceforward", float3, float3, float3);
+ symbolTable.insertBuiltIn(float4, "faceforward", float4, float4, float4);
+
+ symbolTable.insertBuiltIn(float1, "reflect", float1, float1);
+ symbolTable.insertBuiltIn(float2, "reflect", float2, float2);
+ symbolTable.insertBuiltIn(float3, "reflect", float3, float3);
+ symbolTable.insertBuiltIn(float4, "reflect", float4, float4);
+
+ symbolTable.insertBuiltIn(float1, "refract", float1, float1, float1);
+ symbolTable.insertBuiltIn(float2, "refract", float2, float2, float1);
+ symbolTable.insertBuiltIn(float3, "refract", float3, float3, float1);
+ symbolTable.insertBuiltIn(float4, "refract", float4, float4, float1);
+
+ TType *mat2 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 2, true);
+ TType *mat3 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 3, true);
+ TType *mat4 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 4, true);
//
// Matrix Functions.
//
- s.append(TString("mat2 matrixCompMult(mat2 x, mat2 y);"));
- s.append(TString("mat3 matrixCompMult(mat3 x, mat3 y);"));
- s.append(TString("mat4 matrixCompMult(mat4 x, mat4 y);"));
+ symbolTable.insertBuiltIn(mat2, "matrixCompMult", mat2, mat2);
+ symbolTable.insertBuiltIn(mat3, "matrixCompMult", mat3, mat3);
+ symbolTable.insertBuiltIn(mat4, "matrixCompMult", mat4, mat4);
+
+ TType *bool1 = new TType(EbtBool, EbpUndefined, EvqGlobal, 1);
+ TType *bool2 = new TType(EbtBool, EbpUndefined, EvqGlobal, 2);
+ TType *bool3 = new TType(EbtBool, EbpUndefined, EvqGlobal, 3);
+ TType *bool4 = new TType(EbtBool, EbpUndefined, EvqGlobal, 4);
//
// Vector relational functions.
//
- s.append(TString("bvec2 lessThan(vec2 x, vec2 y);"));
- s.append(TString("bvec3 lessThan(vec3 x, vec3 y);"));
- s.append(TString("bvec4 lessThan(vec4 x, vec4 y);"));
-
- s.append(TString("bvec2 lessThan(ivec2 x, ivec2 y);"));
- s.append(TString("bvec3 lessThan(ivec3 x, ivec3 y);"));
- s.append(TString("bvec4 lessThan(ivec4 x, ivec4 y);"));
+ symbolTable.insertBuiltIn(bool2, "lessThan", float2, float2);
+ symbolTable.insertBuiltIn(bool3, "lessThan", float3, float3);
+ symbolTable.insertBuiltIn(bool4, "lessThan", float4, float4);
- s.append(TString("bvec2 lessThanEqual(vec2 x, vec2 y);"));
- s.append(TString("bvec3 lessThanEqual(vec3 x, vec3 y);"));
- s.append(TString("bvec4 lessThanEqual(vec4 x, vec4 y);"));
+ symbolTable.insertBuiltIn(bool2, "lessThan", int2, int2);
+ symbolTable.insertBuiltIn(bool3, "lessThan", int3, int3);
+ symbolTable.insertBuiltIn(bool4, "lessThan", int4, int4);
- s.append(TString("bvec2 lessThanEqual(ivec2 x, ivec2 y);"));
- s.append(TString("bvec3 lessThanEqual(ivec3 x, ivec3 y);"));
- s.append(TString("bvec4 lessThanEqual(ivec4 x, ivec4 y);"));
+ symbolTable.insertBuiltIn(bool2, "lessThanEqual", float2, float2);
+ symbolTable.insertBuiltIn(bool3, "lessThanEqual", float3, float3);
+ symbolTable.insertBuiltIn(bool4, "lessThanEqual", float4, float4);
- s.append(TString("bvec2 greaterThan(vec2 x, vec2 y);"));
- s.append(TString("bvec3 greaterThan(vec3 x, vec3 y);"));
- s.append(TString("bvec4 greaterThan(vec4 x, vec4 y);"));
+ symbolTable.insertBuiltIn(bool2, "lessThanEqual", int2, int2);
+ symbolTable.insertBuiltIn(bool3, "lessThanEqual", int3, int3);
+ symbolTable.insertBuiltIn(bool4, "lessThanEqual", int4, int4);
- s.append(TString("bvec2 greaterThan(ivec2 x, ivec2 y);"));
- s.append(TString("bvec3 greaterThan(ivec3 x, ivec3 y);"));
- s.append(TString("bvec4 greaterThan(ivec4 x, ivec4 y);"));
+ symbolTable.insertBuiltIn(bool2, "greaterThan", float2, float2);
+ symbolTable.insertBuiltIn(bool3, "greaterThan", float3, float3);
+ symbolTable.insertBuiltIn(bool4, "greaterThan", float4, float4);
- s.append(TString("bvec2 greaterThanEqual(vec2 x, vec2 y);"));
- s.append(TString("bvec3 greaterThanEqual(vec3 x, vec3 y);"));
- s.append(TString("bvec4 greaterThanEqual(vec4 x, vec4 y);"));
+ symbolTable.insertBuiltIn(bool2, "greaterThan", int2, int2);
+ symbolTable.insertBuiltIn(bool3, "greaterThan", int3, int3);
+ symbolTable.insertBuiltIn(bool4, "greaterThan", int4, int4);
- s.append(TString("bvec2 greaterThanEqual(ivec2 x, ivec2 y);"));
- s.append(TString("bvec3 greaterThanEqual(ivec3 x, ivec3 y);"));
- s.append(TString("bvec4 greaterThanEqual(ivec4 x, ivec4 y);"));
+ symbolTable.insertBuiltIn(bool2, "greaterThanEqual", float2, float2);
+ symbolTable.insertBuiltIn(bool3, "greaterThanEqual", float3, float3);
+ symbolTable.insertBuiltIn(bool4, "greaterThanEqual", float4, float4);
- s.append(TString("bvec2 equal(vec2 x, vec2 y);"));
- s.append(TString("bvec3 equal(vec3 x, vec3 y);"));
- s.append(TString("bvec4 equal(vec4 x, vec4 y);"));
+ symbolTable.insertBuiltIn(bool2, "greaterThanEqual", int2, int2);
+ symbolTable.insertBuiltIn(bool3, "greaterThanEqual", int3, int3);
+ symbolTable.insertBuiltIn(bool4, "greaterThanEqual", int4, int4);
- s.append(TString("bvec2 equal(ivec2 x, ivec2 y);"));
- s.append(TString("bvec3 equal(ivec3 x, ivec3 y);"));
- s.append(TString("bvec4 equal(ivec4 x, ivec4 y);"));
+ symbolTable.insertBuiltIn(bool2, "equal", float2, float2);
+ symbolTable.insertBuiltIn(bool3, "equal", float3, float3);
+ symbolTable.insertBuiltIn(bool4, "equal", float4, float4);
- s.append(TString("bvec2 equal(bvec2 x, bvec2 y);"));
- s.append(TString("bvec3 equal(bvec3 x, bvec3 y);"));
- s.append(TString("bvec4 equal(bvec4 x, bvec4 y);"));
+ symbolTable.insertBuiltIn(bool2, "equal", int2, int2);
+ symbolTable.insertBuiltIn(bool3, "equal", int3, int3);
+ symbolTable.insertBuiltIn(bool4, "equal", int4, int4);
- s.append(TString("bvec2 notEqual(vec2 x, vec2 y);"));
- s.append(TString("bvec3 notEqual(vec3 x, vec3 y);"));
- s.append(TString("bvec4 notEqual(vec4 x, vec4 y);"));
+ symbolTable.insertBuiltIn(bool2, "equal", bool2, bool2);
+ symbolTable.insertBuiltIn(bool3, "equal", bool3, bool3);
+ symbolTable.insertBuiltIn(bool4, "equal", bool4, bool4);
- s.append(TString("bvec2 notEqual(ivec2 x, ivec2 y);"));
- s.append(TString("bvec3 notEqual(ivec3 x, ivec3 y);"));
- s.append(TString("bvec4 notEqual(ivec4 x, ivec4 y);"));
+ symbolTable.insertBuiltIn(bool2, "notEqual", float2, float2);
+ symbolTable.insertBuiltIn(bool3, "notEqual", float3, float3);
+ symbolTable.insertBuiltIn(bool4, "notEqual", float4, float4);
- s.append(TString("bvec2 notEqual(bvec2 x, bvec2 y);"));
- s.append(TString("bvec3 notEqual(bvec3 x, bvec3 y);"));
- s.append(TString("bvec4 notEqual(bvec4 x, bvec4 y);"));
+ symbolTable.insertBuiltIn(bool2, "notEqual", int2, int2);
+ symbolTable.insertBuiltIn(bool3, "notEqual", int3, int3);
+ symbolTable.insertBuiltIn(bool4, "notEqual", int4, int4);
- s.append(TString("bool any(bvec2 x);"));
- s.append(TString("bool any(bvec3 x);"));
- s.append(TString("bool any(bvec4 x);"));
+ symbolTable.insertBuiltIn(bool2, "notEqual", bool2, bool2);
+ symbolTable.insertBuiltIn(bool3, "notEqual", bool3, bool3);
+ symbolTable.insertBuiltIn(bool4, "notEqual", bool4, bool4);
- s.append(TString("bool all(bvec2 x);"));
- s.append(TString("bool all(bvec3 x);"));
- s.append(TString("bool all(bvec4 x);"));
-
- s.append(TString("bvec2 not(bvec2 x);"));
- s.append(TString("bvec3 not(bvec3 x);"));
- s.append(TString("bvec4 not(bvec4 x);"));
-
- //
- // Texture Functions.
- //
- s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord);"));
- s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord);"));
- s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord);"));
- s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord);"));
-
- if (resources.OES_EGL_image_external) {
- s.append(TString("vec4 texture2D(samplerExternalOES sampler, vec2 coord);"));
- s.append(TString("vec4 texture2DProj(samplerExternalOES sampler, vec3 coord);"));
- s.append(TString("vec4 texture2DProj(samplerExternalOES sampler, vec4 coord);"));
- }
+ symbolTable.insertBuiltIn(bool1, "any", bool2);
+ symbolTable.insertBuiltIn(bool1, "any", bool3);
+ symbolTable.insertBuiltIn(bool1, "any", bool4);
- if (resources.ARB_texture_rectangle) {
- s.append(TString("vec4 texture2DRect(sampler2DRect sampler, vec2 coord);"));
- s.append(TString("vec4 texture2DRectProj(sampler2DRect sampler, vec3 coord);"));
- s.append(TString("vec4 texture2DRectProj(sampler2DRect sampler, vec4 coord);"));
- }
+ symbolTable.insertBuiltIn(bool1, "all", bool2);
+ symbolTable.insertBuiltIn(bool1, "all", bool3);
+ symbolTable.insertBuiltIn(bool1, "all", bool4);
- //
- // Noise functions.
- //
- //s.append(TString("float noise1(float x);"));
- //s.append(TString("float noise1(vec2 x);"));
- //s.append(TString("float noise1(vec3 x);"));
- //s.append(TString("float noise1(vec4 x);"));
-
- //s.append(TString("vec2 noise2(float x);"));
- //s.append(TString("vec2 noise2(vec2 x);"));
- //s.append(TString("vec2 noise2(vec3 x);"));
- //s.append(TString("vec2 noise2(vec4 x);"));
-
- //s.append(TString("vec3 noise3(float x);"));
- //s.append(TString("vec3 noise3(vec2 x);"));
- //s.append(TString("vec3 noise3(vec3 x);"));
- //s.append(TString("vec3 noise3(vec4 x);"));
-
- //s.append(TString("vec4 noise4(float x);"));
- //s.append(TString("vec4 noise4(vec2 x);"));
- //s.append(TString("vec4 noise4(vec3 x);"));
- //s.append(TString("vec4 noise4(vec4 x);"));
-
- return s;
-}
+ symbolTable.insertBuiltIn(bool2, "not", bool2);
+ symbolTable.insertBuiltIn(bool3, "not", bool3);
+ symbolTable.insertBuiltIn(bool4, "not", bool4);
-//============================================================================
-//
-// Prototypes for built-in functions seen by vertex shaders only.
-//
-//============================================================================
-static TString BuiltInFunctionsVertex(const ShBuiltInResources& resources)
-{
- TString s;
+ TType *sampler2D = new TType(EbtSampler2D, EbpUndefined, EvqGlobal, 1);
+ TType *samplerCube = new TType(EbtSamplerCube, EbpUndefined, EvqGlobal, 1);
//
- // Geometric Functions.
+ // Texture Functions for GLSL ES 1.0
//
- //s.append(TString("vec4 ftransform();"));
+ symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2);
+ symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3);
+ symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4);
+ symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3);
- //
- // Texture Functions.
- //
- s.append(TString("vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod);"));
- s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);"));
- s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);"));
- s.append(TString("vec4 textureCubeLod(samplerCube sampler, vec3 coord, float lod);"));
+ if (resources.OES_EGL_image_external)
+ {
+ TType *samplerExternalOES = new TType(EbtSamplerExternalOES, EbpUndefined, EvqGlobal, 1);
- return s;
-}
+ symbolTable.insertBuiltIn(float4, "texture2D", samplerExternalOES, float2);
+ symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float3);
+ symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float4);
+ }
-//============================================================================
-//
-// Prototypes for built-in functions seen by fragment shaders only.
-//
-//============================================================================
-static TString BuiltInFunctionsFragment(const ShBuiltInResources& resources)
-{
- TString s;
+ if (resources.ARB_texture_rectangle)
+ {
+ TType *sampler2DRect = new TType(EbtSampler2DRect, EbpUndefined, EvqGlobal, 1);
- //
- // Texture Functions.
- //
- s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord, float bias);"));
- s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias);"));
- s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord, float bias);"));
- s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord, float bias);"));
-
- if (resources.OES_standard_derivatives) {
- s.append(TString("float dFdx(float p);"));
- s.append(TString("vec2 dFdx(vec2 p);"));
- s.append(TString("vec3 dFdx(vec3 p);"));
- s.append(TString("vec4 dFdx(vec4 p);"));
-
- s.append(TString("float dFdy(float p);"));
- s.append(TString("vec2 dFdy(vec2 p);"));
- s.append(TString("vec3 dFdy(vec3 p);"));
- s.append(TString("vec4 dFdy(vec4 p);"));
-
- s.append(TString("float fwidth(float p);"));
- s.append(TString("vec2 fwidth(vec2 p);"));
- s.append(TString("vec3 fwidth(vec3 p);"));
- s.append(TString("vec4 fwidth(vec4 p);"));
+ symbolTable.insertBuiltIn(float4, "texture2DRect", sampler2DRect, float2);
+ symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float3);
+ symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float4);
}
- return s;
-}
+ if (type == SH_FRAGMENT_SHADER)
+ {
+ symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2, float1);
+ symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3, float1);
+ symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4, float1);
+ symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3, float1);
+
+ if (resources.OES_standard_derivatives)
+ {
+ symbolTable.insertBuiltIn(float1, "dFdx", float1);
+ symbolTable.insertBuiltIn(float2, "dFdx", float2);
+ symbolTable.insertBuiltIn(float3, "dFdx", float3);
+ symbolTable.insertBuiltIn(float4, "dFdx", float4);
+
+ symbolTable.insertBuiltIn(float1, "dFdy", float1);
+ symbolTable.insertBuiltIn(float2, "dFdy", float2);
+ symbolTable.insertBuiltIn(float3, "dFdy", float3);
+ symbolTable.insertBuiltIn(float4, "dFdy", float4);
+
+ symbolTable.insertBuiltIn(float1, "fwidth", float1);
+ symbolTable.insertBuiltIn(float2, "fwidth", float2);
+ symbolTable.insertBuiltIn(float3, "fwidth", float3);
+ symbolTable.insertBuiltIn(float4, "fwidth", float4);
+ }
+ }
-//============================================================================
-//
-// Standard uniforms.
-//
-//============================================================================
-static TString StandardUniforms()
-{
- TString s;
+ if(type == SH_VERTEX_SHADER)
+ {
+ symbolTable.insertBuiltIn(float4, "texture2DLod", sampler2D, float2, float1);
+ symbolTable.insertBuiltIn(float4, "texture2DProjLod", sampler2D, float3, float1);
+ symbolTable.insertBuiltIn(float4, "texture2DProjLod", sampler2D, float4, float1);
+ symbolTable.insertBuiltIn(float4, "textureCubeLod", samplerCube, float3, float1);
+ }
//
// Depth range in window coordinates
//
- s.append(TString("struct gl_DepthRangeParameters {"));
- s.append(TString(" highp float near;")); // n
- s.append(TString(" highp float far;")); // f
- s.append(TString(" highp float diff;")); // f - n
- s.append(TString("};"));
- s.append(TString("uniform gl_DepthRangeParameters gl_DepthRange;"));
-
- return s;
-}
-
-//============================================================================
-//
-// Default precision for vertex shaders.
-//
-//============================================================================
-static TString DefaultPrecisionVertex()
-{
- TString s;
-
- s.append(TString("precision highp int;"));
- s.append(TString("precision highp float;"));
-
- return s;
-}
-
-//============================================================================
-//
-// Default precision for fragment shaders.
-//
-//============================================================================
-static TString DefaultPrecisionFragment()
-{
- TString s;
+ TFieldList *fields = NewPoolTFieldList();
+ TField *near = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("near"));
+ TField *far = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("far"));
+ TField *diff = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("diff"));
+ fields->push_back(near);
+ fields->push_back(far);
+ fields->push_back(diff);
+ TStructure *depthRangeStruct = new TStructure(NewPoolTString("gl_DepthRangeParameters"), fields);
+ TVariable *depthRangeParameters = new TVariable(&depthRangeStruct->name(), depthRangeStruct, true);
+ symbolTable.insert(*depthRangeParameters);
+ TVariable *depthRange = new TVariable(NewPoolTString("gl_DepthRange"), TType(depthRangeStruct));
+ depthRange->setQualifier(EvqUniform);
+ symbolTable.insert(*depthRange);
- s.append(TString("precision mediump int;"));
- // No default precision for float in fragment shaders
-
- return s;
-}
-
-//============================================================================
-//
-// Implementation dependent built-in constants.
-//
-//============================================================================
-static TString BuiltInConstants(ShShaderSpec spec, const ShBuiltInResources &resources)
-{
- TStringStream s;
-
- s << "const int gl_MaxVertexAttribs = " << resources.MaxVertexAttribs << ";";
- s << "const int gl_MaxVertexUniformVectors = " << resources.MaxVertexUniformVectors << ";";
-
- s << "const int gl_MaxVaryingVectors = " << resources.MaxVaryingVectors << ";";
- s << "const int gl_MaxVertexTextureImageUnits = " << resources.MaxVertexTextureImageUnits << ";";
- s << "const int gl_MaxCombinedTextureImageUnits = " << resources.MaxCombinedTextureImageUnits << ";";
- s << "const int gl_MaxTextureImageUnits = " << resources.MaxTextureImageUnits << ";";
- s << "const int gl_MaxFragmentUniformVectors = " << resources.MaxFragmentUniformVectors << ";";
+ //
+ // Implementation dependent built-in constants.
+ //
+ symbolTable.insertConstInt("gl_MaxVertexAttribs", resources.MaxVertexAttribs);
+ symbolTable.insertConstInt("gl_MaxVertexUniformVectors", resources.MaxVertexUniformVectors);
+ symbolTable.insertConstInt("gl_MaxVaryingVectors", resources.MaxVaryingVectors);
+ symbolTable.insertConstInt("gl_MaxVertexTextureImageUnits", resources.MaxVertexTextureImageUnits);
+ symbolTable.insertConstInt("gl_MaxCombinedTextureImageUnits", resources.MaxCombinedTextureImageUnits);
+ symbolTable.insertConstInt("gl_MaxTextureImageUnits", resources.MaxTextureImageUnits);
+ symbolTable.insertConstInt("gl_MaxFragmentUniformVectors", resources.MaxFragmentUniformVectors);
if (spec != SH_CSS_SHADERS_SPEC)
- s << "const int gl_MaxDrawBuffers = " << resources.MaxDrawBuffers << ";";
-
- return s.str();
-}
-
-void TBuiltIns::initialize(ShShaderType type, ShShaderSpec spec,
- const ShBuiltInResources& resources)
-{
- switch (type) {
- case SH_FRAGMENT_SHADER:
- builtInStrings.push_back(DefaultPrecisionFragment());
- builtInStrings.push_back(BuiltInFunctionsCommon(resources));
- builtInStrings.push_back(BuiltInFunctionsFragment(resources));
- builtInStrings.push_back(StandardUniforms());
- break;
-
- case SH_VERTEX_SHADER:
- builtInStrings.push_back(DefaultPrecisionVertex());
- builtInStrings.push_back(BuiltInFunctionsCommon(resources));
- builtInStrings.push_back(BuiltInFunctionsVertex(resources));
- builtInStrings.push_back(StandardUniforms());
- break;
-
- default: assert(false && "Language not supported");
+ {
+ symbolTable.insertConstInt("gl_MaxDrawBuffers", resources.MaxDrawBuffers);
}
-
- builtInStrings.push_back(BuiltInConstants(spec, resources));
}
void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
- const ShBuiltInResources& resources,
- TSymbolTable& symbolTable)
+ const ShBuiltInResources &resources,
+ TSymbolTable &symbolTable)
{
//
// First, insert some special built-in variables that are not in
@@ -539,6 +439,10 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
if (spec != SH_CSS_SHADERS_SPEC) {
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4)));
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4)));
+ if (resources.EXT_frag_depth) {
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FragDepthEXT"), TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1)));
+ symbolTable.relateToExtension("gl_FragDepthEXT", "GL_EXT_frag_depth");
+ }
} else {
symbolTable.insert(*new TVariable(NewPoolTString("css_MixColor"), TType(EbtFloat, EbpMedium, EvqGlobal, 4)));
symbolTable.insert(*new TVariable(NewPoolTString("css_ColorMatrix"), TType(EbtFloat, EbpMedium, EvqGlobal, 4, true)));
@@ -560,8 +464,6 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
// expected to be resolved through a library of functions, versus as
// operations.
//
- symbolTable.relateToOperator("not", EOpVectorLogicalNot);
-
symbolTable.relateToOperator("matrixCompMult", EOpMul);
symbolTable.relateToOperator("equal", EOpVectorEqual);
@@ -612,6 +514,7 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
symbolTable.relateToOperator("any", EOpAny);
symbolTable.relateToOperator("all", EOpAll);
+ symbolTable.relateToOperator("not", EOpVectorLogicalNot);
// Map language-specific operators.
switch(type) {
@@ -656,4 +559,6 @@ void InitExtensionBehavior(const ShBuiltInResources& resources,
extBehavior["GL_ARB_texture_rectangle"] = EBhUndefined;
if (resources.EXT_draw_buffers)
extBehavior["GL_EXT_draw_buffers"] = EBhUndefined;
+ if (resources.EXT_frag_depth)
+ extBehavior["GL_EXT_frag_depth"] = EBhUndefined;
}
diff --git a/src/3rdparty/angle/src/compiler/Initialize.h b/src/3rdparty/angle/src/compiler/Initialize.h
index 8b0adc6b4c..4aa13466ac 100644
--- a/src/3rdparty/angle/src/compiler/Initialize.h
+++ b/src/3rdparty/angle/src/compiler/Initialize.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -11,19 +11,7 @@
#include "compiler/ShHandle.h"
#include "compiler/SymbolTable.h"
-typedef TVector<TString> TBuiltInStrings;
-
-class TBuiltIns {
-public:
- POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
-
- void initialize(ShShaderType type, ShShaderSpec spec,
- const ShBuiltInResources& resources);
- const TBuiltInStrings& getBuiltInStrings() { return builtInStrings; }
-
-protected:
- TBuiltInStrings builtInStrings;
-};
+void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &table);
void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
const ShBuiltInResources& resources,
diff --git a/src/3rdparty/angle/src/compiler/InitializeDll.cpp b/src/3rdparty/angle/src/compiler/InitializeDll.cpp
index 8763cfeea8..6c7f27fced 100644
--- a/src/3rdparty/angle/src/compiler/InitializeDll.cpp
+++ b/src/3rdparty/angle/src/compiler/InitializeDll.cpp
@@ -10,25 +10,8 @@
#include "compiler/InitializeParseContext.h"
#include "compiler/osinclude.h"
-OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
-
bool InitProcess()
{
- if (ThreadInitializeIndex != OS_INVALID_TLS_INDEX) {
- //
- // Function is re-entrant.
- //
- return true;
- }
-
- ThreadInitializeIndex = OS_AllocTLSIndex();
-
- if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
- assert(0 && "InitProcess(): Failed to allocate TLS area for init flag");
- return false;
- }
-
-
if (!InitializePoolIndex()) {
assert(0 && "InitProcess(): Failed to initalize global pool");
return false;
@@ -39,77 +22,11 @@ bool InitProcess()
return false;
}
- return InitThread();
-}
-
-bool DetachProcess()
-{
- bool success = true;
-
- if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
- return true;
-
- success = DetachThread();
-
- if (!FreeParseContextIndex())
- success = false;
-
- FreePoolIndex();
-
- OS_FreeTLSIndex(ThreadInitializeIndex);
- ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
-
- return success;
-}
-
-bool InitThread()
-{
- //
- // This function is re-entrant
- //
- if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
- assert(0 && "InitThread(): Process hasn't been initalised.");
- return false;
- }
-
- if (OS_GetTLSValue(ThreadInitializeIndex) != 0)
- return true;
-
- InitializeGlobalPools();
-
- if (!InitializeGlobalParseContext())
- return false;
-
- if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) {
- assert(0 && "InitThread(): Unable to set init flag.");
- return false;
- }
-
return true;
}
-bool DetachThread()
+void DetachProcess()
{
- bool success = true;
-
- if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
- return true;
-
- //
- // Function is re-entrant and this thread may not have been initalised.
- //
- if (OS_GetTLSValue(ThreadInitializeIndex) != 0) {
- if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)0)) {
- assert(0 && "DetachThread(): Unable to clear init flag.");
- success = false;
- }
-
- if (!FreeParseContext())
- success = false;
-
- FreeGlobalPools();
- }
-
- return success;
+ FreeParseContextIndex();
+ FreePoolIndex();
}
-
diff --git a/src/3rdparty/angle/src/compiler/InitializeDll.h b/src/3rdparty/angle/src/compiler/InitializeDll.h
index 857238eeae..43070cc3ff 100644
--- a/src/3rdparty/angle/src/compiler/InitializeDll.h
+++ b/src/3rdparty/angle/src/compiler/InitializeDll.h
@@ -7,10 +7,7 @@
#define __INITIALIZEDLL_H
bool InitProcess();
-bool DetachProcess();
-
-bool InitThread();
-bool DetachThread();
+void DetachProcess();
#endif // __INITIALIZEDLL_H
diff --git a/src/3rdparty/angle/src/compiler/InitializeGLPosition.cpp b/src/3rdparty/angle/src/compiler/InitializeGLPosition.cpp
new file mode 100644
index 0000000000..e0193e39d2
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/InitializeGLPosition.cpp
@@ -0,0 +1,61 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/InitializeGLPosition.h"
+#include "compiler/debug.h"
+
+bool InitializeGLPosition::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+ bool visitChildren = !mCodeInserted;
+ switch (node->getOp())
+ {
+ case EOpSequence: break;
+ case EOpFunction:
+ {
+ // Function definition.
+ ASSERT(visit == PreVisit);
+ if (node->getName() == "main(")
+ {
+ TIntermSequence &sequence = node->getSequence();
+ ASSERT((sequence.size() == 1) || (sequence.size() == 2));
+ TIntermAggregate *body = NULL;
+ if (sequence.size() == 1)
+ {
+ body = new TIntermAggregate(EOpSequence);
+ sequence.push_back(body);
+ }
+ else
+ {
+ body = sequence[1]->getAsAggregate();
+ }
+ ASSERT(body);
+ insertCode(body->getSequence());
+ mCodeInserted = true;
+ }
+ break;
+ }
+ default: visitChildren = false; break;
+ }
+ return visitChildren;
+}
+
+void InitializeGLPosition::insertCode(TIntermSequence& sequence)
+{
+ TIntermBinary *binary = new TIntermBinary(EOpAssign);
+ sequence.insert(sequence.begin(), binary);
+
+ TIntermSymbol *left = new TIntermSymbol(
+ 0, "gl_Position", TType(EbtFloat, EbpUndefined, EvqPosition, 4));
+ binary->setLeft(left);
+
+ ConstantUnion *u = new ConstantUnion[4];
+ for (int ii = 0; ii < 3; ++ii)
+ u[ii].setFConst(0.0f);
+ u[3].setFConst(1.0f);
+ TIntermConstantUnion *right = new TIntermConstantUnion(
+ u, TType(EbtFloat, EbpUndefined, EvqConst, 4));
+ binary->setRight(right);
+}
diff --git a/src/3rdparty/angle/src/compiler/InitializeGLPosition.h b/src/3rdparty/angle/src/compiler/InitializeGLPosition.h
new file mode 100644
index 0000000000..1b11075a13
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/InitializeGLPosition.h
@@ -0,0 +1,33 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_INITIALIZE_GL_POSITION_H_
+#define COMPILER_INITIALIZE_GL_POSITION_H_
+
+#include "compiler/intermediate.h"
+
+class InitializeGLPosition : public TIntermTraverser
+{
+public:
+ InitializeGLPosition() : mCodeInserted(false) { }
+
+protected:
+ virtual bool visitBinary(Visit visit, TIntermBinary* node) { return false; }
+ virtual bool visitUnary(Visit visit, TIntermUnary* node) { return false; }
+ virtual bool visitSelection(Visit visit, TIntermSelection* node) { return false; }
+ virtual bool visitLoop(Visit visit, TIntermLoop* node) { return false; }
+ virtual bool visitBranch(Visit visit, TIntermBranch* node) { return false; }
+
+ virtual bool visitAggregate(Visit visit, TIntermAggregate* node);
+
+private:
+ // Insert AST node in the beginning of main() for "gl_Position = vec4(0.0, 0.0, 0.0, 1.0);".
+ void insertCode(TIntermSequence& sequence);
+
+ bool mCodeInserted;
+};
+
+#endif // COMPILER_INITIALIZE_GL_POSITION_H_
diff --git a/src/3rdparty/angle/src/compiler/InitializeGlobals.h b/src/3rdparty/angle/src/compiler/InitializeGlobals.h
index 842a45281d..0715941424 100644
--- a/src/3rdparty/angle/src/compiler/InitializeGlobals.h
+++ b/src/3rdparty/angle/src/compiler/InitializeGlobals.h
@@ -7,8 +7,6 @@
#ifndef __INITIALIZE_GLOBALS_INCLUDED_
#define __INITIALIZE_GLOBALS_INCLUDED_
-void InitializeGlobalPools();
-void FreeGlobalPools();
bool InitializePoolIndex();
void FreePoolIndex();
diff --git a/src/3rdparty/angle/src/compiler/InitializeParseContext.cpp b/src/3rdparty/angle/src/compiler/InitializeParseContext.cpp
index 1f40cf5800..dfab027330 100644
--- a/src/3rdparty/angle/src/compiler/InitializeParseContext.cpp
+++ b/src/3rdparty/angle/src/compiler/InitializeParseContext.cpp
@@ -12,85 +12,29 @@ OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
bool InitializeParseContextIndex()
{
- if (GlobalParseContextIndex != OS_INVALID_TLS_INDEX) {
- assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
- return false;
- }
+ assert(GlobalParseContextIndex == OS_INVALID_TLS_INDEX);
- //
- // Allocate a TLS index.
- //
GlobalParseContextIndex = OS_AllocTLSIndex();
-
- if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
- assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
- return false;
- }
-
- return true;
+ return GlobalParseContextIndex != OS_INVALID_TLS_INDEX;
}
-bool FreeParseContextIndex()
+void FreeParseContextIndex()
{
- OS_TLSIndex tlsiIndex = GlobalParseContextIndex;
-
- if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
- assert(0 && "FreeParseContextIndex(): Parse Context index not initalized");
- return false;
- }
+ assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
+ OS_FreeTLSIndex(GlobalParseContextIndex);
GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
-
- return OS_FreeTLSIndex(tlsiIndex);
-}
-
-bool InitializeGlobalParseContext()
-{
- if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
- assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalized");
- return false;
- }
-
- TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
- if (lpParseContext != 0) {
- assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
- return false;
- }
-
- TThreadParseContext *lpThreadData = new TThreadParseContext();
- if (lpThreadData == 0) {
- assert(0 && "InitializeGlobalParseContext(): Unable to create thread parse context");
- return false;
- }
-
- lpThreadData->lpGlobalParseContext = 0;
- OS_SetTLSValue(GlobalParseContextIndex, lpThreadData);
-
- return true;
}
-bool FreeParseContext()
+void SetGlobalParseContext(TParseContext* context)
{
- if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
- assert(0 && "FreeParseContext(): Parse Context index not initalized");
- return false;
- }
-
- TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
- if (lpParseContext)
- delete lpParseContext;
-
- return true;
+ assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
+ OS_SetTLSValue(GlobalParseContextIndex, context);
}
-TParseContextPointer& GetGlobalParseContext()
+TParseContext* GetGlobalParseContext()
{
- //
- // Minimal error checking for speed
- //
-
- TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
-
- return lpParseContext->lpGlobalParseContext;
+ assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
+ return static_cast<TParseContext*>(OS_GetTLSValue(GlobalParseContextIndex));
}
diff --git a/src/3rdparty/angle/src/compiler/InitializeParseContext.h b/src/3rdparty/angle/src/compiler/InitializeParseContext.h
index aa53b735d4..bffbab87d0 100644
--- a/src/3rdparty/angle/src/compiler/InitializeParseContext.h
+++ b/src/3rdparty/angle/src/compiler/InitializeParseContext.h
@@ -8,19 +8,10 @@
#define __INITIALIZE_PARSE_CONTEXT_INCLUDED_
bool InitializeParseContextIndex();
-bool FreeParseContextIndex();
-
-bool InitializeGlobalParseContext();
-bool FreeParseContext();
+void FreeParseContextIndex();
struct TParseContext;
-typedef TParseContext* TParseContextPointer;
-extern TParseContextPointer& GetGlobalParseContext();
-#define GlobalParseContext GetGlobalParseContext()
-
-typedef struct TThreadParseContextRec
-{
- TParseContext *lpGlobalParseContext;
-} TThreadParseContext;
+extern void SetGlobalParseContext(TParseContext* context);
+extern TParseContext* GetGlobalParseContext();
#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_
diff --git a/src/3rdparty/angle/src/compiler/Intermediate.cpp b/src/3rdparty/angle/src/compiler/Intermediate.cpp
index edf279ef67..3b6622185d 100644
--- a/src/3rdparty/angle/src/compiler/Intermediate.cpp
+++ b/src/3rdparty/angle/src/compiler/Intermediate.cpp
@@ -131,7 +131,7 @@ const char* getOperatorString(TOperator op) {
//
// Returns the added node.
//
-TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, TSourceLoc line)
+TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc& line)
{
TIntermSymbol* node = new TIntermSymbol(id, name, type);
node->setLine(line);
@@ -144,7 +144,7 @@ TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType
//
// Returns the added node.
//
-TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TSymbolTable& symbolTable)
+TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line, TSymbolTable& symbolTable)
{
switch (op) {
case EOpEqual:
@@ -200,8 +200,6 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
// one and promote it to the right type.
//
TIntermBinary* node = new TIntermBinary(op);
- if (line == 0)
- line = right->getLine();
node->setLine(line);
node->setLeft(left);
@@ -230,15 +228,13 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
//
// Returns the added node.
//
-TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
+TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line)
{
//
// Like adding binary math, except the conversion can only go
// from right to left.
//
TIntermBinary* node = new TIntermBinary(op);
- if (line == 0)
- line = left->getLine();
node->setLine(line);
TIntermTyped* child = addConversion(op, left->getType(), right);
@@ -260,11 +256,9 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm
// Returns the added node.
// The caller should set the type of the returned node.
//
-TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc line)
+TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc& line)
{
TIntermBinary* node = new TIntermBinary(op);
- if (line == 0)
- line = index->getLine();
node->setLine(line);
node->setLeft(base);
node->setRight(index);
@@ -279,13 +273,13 @@ TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermT
//
// Returns the added node.
//
-TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line, TSymbolTable& symbolTable)
+TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, const TSourceLoc& line, TSymbolTable& symbolTable)
{
TIntermUnary* node;
TIntermTyped* child = childNode->getAsTyped();
if (child == 0) {
- infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
+ infoSink.info.message(EPrefixInternalError, line, "Bad type in AddUnaryMath");
return 0;
}
@@ -348,8 +342,6 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode,
// Make a new node for the operator.
//
node = new TIntermUnary(op);
- if (line == 0)
- line = child->getLine();
node->setLine(line);
node->setOperand(child);
@@ -376,7 +368,7 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode,
// Returns an aggregate node, which could be the one passed in if
// it was already an aggregate but no operator was set.
//
-TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, TSourceLoc line)
+TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc& line)
{
TIntermAggregate* aggNode;
@@ -391,8 +383,6 @@ TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperat
//
aggNode = new TIntermAggregate();
aggNode->getSequence().push_back(node);
- if (line == 0)
- line = node->getLine();
}
} else
aggNode = new TIntermAggregate();
@@ -401,8 +391,7 @@ TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperat
// Set the operator.
//
aggNode->setOp(op);
- if (line != 0)
- aggNode->setLine(line);
+ aggNode->setLine(line);
return aggNode;
}
@@ -491,7 +480,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
case EbtInt: newOp = EOpConvIntToFloat; break;
case EbtBool: newOp = EOpConvBoolToFloat; break;
default:
- infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
return 0;
}
break;
@@ -500,7 +489,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
case EbtInt: newOp = EOpConvIntToBool; break;
case EbtFloat: newOp = EOpConvFloatToBool; break;
default:
- infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
return 0;
}
break;
@@ -509,12 +498,12 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
case EbtBool: newOp = EOpConvBoolToInt; break;
case EbtFloat: newOp = EOpConvFloatToInt; break;
default:
- infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
return 0;
}
break;
default:
- infoSink.info.message(EPrefixInternalError, "Bad promotion type", node->getLine());
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion type");
return 0;
}
@@ -534,7 +523,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
// Returns the resulting aggregate, unless 0 was passed in for
// both existing nodes.
//
-TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc line)
+TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& line)
{
if (left == 0 && right == 0)
return 0;
@@ -551,8 +540,7 @@ TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* r
if (right)
aggNode->getSequence().push_back(right);
- if (line != 0)
- aggNode->setLine(line);
+ aggNode->setLine(line);
return aggNode;
}
@@ -562,18 +550,14 @@ TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* r
//
// Returns an aggregate, unless 0 was passed in for the existing node.
//
-TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc line)
+TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& line)
{
if (node == 0)
return 0;
TIntermAggregate* aggNode = new TIntermAggregate;
aggNode->getSequence().push_back(node);
-
- if (line != 0)
- aggNode->setLine(line);
- else
- aggNode->setLine(node->getLine());
+ aggNode->setLine(line);
return aggNode;
}
@@ -585,7 +569,7 @@ TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc lin
//
// Returns the selection node created.
//
-TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, TSourceLoc line)
+TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& line)
{
//
// For compile time constant selections, prune the code and
@@ -606,7 +590,7 @@ TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nod
}
-TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
+TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line)
{
if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) {
return right;
@@ -626,7 +610,7 @@ TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, T
//
// Returns the selection node created, or 0 if one could not be.
//
-TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc line)
+TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& line)
{
//
// Get compatible types.
@@ -669,7 +653,7 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true
// Returns the constant union node created.
//
-TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, TSourceLoc line)
+TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc& line)
{
TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
node->setLine(line);
@@ -677,7 +661,7 @@ TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayP
return node;
}
-TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line)
+TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& line)
{
TIntermAggregate* node = new TIntermAggregate(EOpSequence);
@@ -700,7 +684,7 @@ TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line)
//
// Create loop nodes.
//
-TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, TSourceLoc line)
+TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc& line)
{
TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
node->setLine(line);
@@ -711,12 +695,12 @@ TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTy
//
// Add branches.
//
-TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TSourceLoc line)
+TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& line)
{
return addBranch(branchOp, 0, line);
}
-TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, TSourceLoc line)
+TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& line)
{
TIntermBranch* node = new TIntermBranch(branchOp, expression);
node->setLine(line);
@@ -861,7 +845,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
{
// This function only handles scalars, vectors, and matrices.
if (left->isArray() || right->isArray()) {
- infoSink.info.message(EPrefixInternalError, "Invalid operation for arrays", getLine());
+ infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operation for arrays");
return false;
}
@@ -966,7 +950,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
}
} else {
- infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
+ infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses");
return false;
}
break;
@@ -995,7 +979,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
}
} else {
- infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
+ infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses");
return false;
}
break;
@@ -1035,23 +1019,22 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
{
- const TTypeList* fields = leftNodeType.getStruct();
+ const TFieldList& fields = leftNodeType.getStruct()->fields();
- size_t structSize = fields->size();
- int index = 0;
+ size_t structSize = fields.size();
+ size_t index = 0;
for (size_t j = 0; j < structSize; j++) {
- int size = (*fields)[j].type->getObjectSize();
- for (int i = 0; i < size; i++) {
- if ((*fields)[j].type->getBasicType() == EbtStruct) {
- if (!CompareStructure(*(*fields)[j].type, &rightUnionArray[index], &leftUnionArray[index]))
+ size_t size = fields[j]->type()->getObjectSize();
+ for (size_t i = 0; i < size; i++) {
+ if (fields[j]->type()->getBasicType() == EbtStruct) {
+ if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index]))
return false;
} else {
if (leftUnionArray[index] != rightUnionArray[index])
return false;
index++;
}
-
}
}
return true;
@@ -1063,10 +1046,10 @@ bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray,
TType typeWithoutArrayness = leftNodeType;
typeWithoutArrayness.clearArrayness();
- int arraySize = leftNodeType.getArraySize();
+ size_t arraySize = leftNodeType.getArraySize();
- for (int i = 0; i < arraySize; ++i) {
- int offset = typeWithoutArrayness.getObjectSize() * i;
+ for (size_t i = 0; i < arraySize; ++i) {
+ size_t offset = typeWithoutArrayness.getObjectSize() * i;
if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
return false;
}
@@ -1086,7 +1069,7 @@ bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray,
TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
{
ConstantUnion *unionArray = getUnionArrayPointer();
- int objectSize = getType().getObjectSize();
+ size_t objectSize = getType().getObjectSize();
if (constantNode) { // binary operations
TIntermConstantUnion *node = constantNode->getAsConstantUnion();
@@ -1096,13 +1079,13 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
// for a case like float f = 1.2 + vec4(2,3,4,5);
if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
rightUnionArray = new ConstantUnion[objectSize];
- for (int i = 0; i < objectSize; ++i)
+ for (size_t i = 0; i < objectSize; ++i)
rightUnionArray[i] = *node->getUnionArrayPointer();
returnType = getType();
} else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
// for a case like float f = vec4(2,3,4,5) + 1.2;
unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
- for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
+ for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i)
unionArray[i] = *getUnionArrayPointer();
returnType = node->getType();
objectSize = constantNode->getType().getObjectSize();
@@ -1116,14 +1099,14 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
case EOpAdd:
tempConstArray = new ConstantUnion[objectSize];
{// support MSVC++6.0
- for (int i = 0; i < objectSize; i++)
+ for (size_t i = 0; i < objectSize; i++)
tempConstArray[i] = unionArray[i] + rightUnionArray[i];
}
break;
case EOpSub:
tempConstArray = new ConstantUnion[objectSize];
{// support MSVC++6.0
- for (int i = 0; i < objectSize; i++)
+ for (size_t i = 0; i < objectSize; i++)
tempConstArray[i] = unionArray[i] - rightUnionArray[i];
}
break;
@@ -1133,13 +1116,13 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
case EOpMatrixTimesScalar:
tempConstArray = new ConstantUnion[objectSize];
{// support MSVC++6.0
- for (int i = 0; i < objectSize; i++)
+ for (size_t i = 0; i < objectSize; i++)
tempConstArray[i] = unionArray[i] * rightUnionArray[i];
}
break;
case EOpMatrixTimesMatrix:
if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
- infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
+ infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix multiply");
return 0;
}
{// support MSVC++6.0
@@ -1158,11 +1141,11 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
case EOpDiv:
tempConstArray = new ConstantUnion[objectSize];
{// support MSVC++6.0
- for (int i = 0; i < objectSize; i++) {
+ for (size_t i = 0; i < objectSize; i++) {
switch (getType().getBasicType()) {
case EbtFloat:
if (rightUnionArray[i] == 0.0f) {
- infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
+ infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding");
tempConstArray[i].setFConst(unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX);
} else
tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
@@ -1170,13 +1153,13 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
case EbtInt:
if (rightUnionArray[i] == 0) {
- infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
+ infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding");
tempConstArray[i].setIConst(INT_MAX);
} else
tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
break;
default:
- infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
+ infoSink.info.message(EPrefixInternalError, getLine(), "Constant folding cannot be done for \"/\"");
return 0;
}
}
@@ -1185,7 +1168,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
case EOpMatrixTimesVector:
if (node->getBasicType() != EbtFloat) {
- infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
+ infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix times vector");
return 0;
}
tempConstArray = new ConstantUnion[getNominalSize()];
@@ -1206,7 +1189,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
case EOpVectorTimesMatrix:
if (getType().getBasicType() != EbtFloat) {
- infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
+ infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for vector times matrix");
return 0;
}
@@ -1224,7 +1207,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
tempConstArray = new ConstantUnion[objectSize];
{// support MSVC++6.0
- for (int i = 0; i < objectSize; i++)
+ for (size_t i = 0; i < objectSize; i++)
tempConstArray[i] = unionArray[i] && rightUnionArray[i];
}
break;
@@ -1232,7 +1215,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
tempConstArray = new ConstantUnion[objectSize];
{// support MSVC++6.0
- for (int i = 0; i < objectSize; i++)
+ for (size_t i = 0; i < objectSize; i++)
tempConstArray[i] = unionArray[i] || rightUnionArray[i];
}
break;
@@ -1240,7 +1223,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
case EOpLogicalXor:
tempConstArray = new ConstantUnion[objectSize];
{// support MSVC++6.0
- for (int i = 0; i < objectSize; i++)
+ for (size_t i = 0; i < objectSize; i++)
switch (getType().getBasicType()) {
case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
default: assert(false && "Default missing");
@@ -1286,7 +1269,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
boolNodeFlag = true;
} else {
- for (int i = 0; i < objectSize; i++) {
+ for (size_t i = 0; i < objectSize; i++) {
if (unionArray[i] != rightUnionArray[i]) {
boolNodeFlag = true;
break; // break out of for loop
@@ -1312,7 +1295,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
boolNodeFlag = true;
} else {
- for (int i = 0; i < objectSize; i++) {
+ for (size_t i = 0; i < objectSize; i++) {
if (unionArray[i] == rightUnionArray[i]) {
boolNodeFlag = true;
break; // break out of for loop
@@ -1334,7 +1317,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
return tempNode;
default:
- infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine());
+ infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operator for constant folding");
return 0;
}
tempNode = new TIntermConstantUnion(tempConstArray, returnType);
@@ -1347,14 +1330,14 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
//
TIntermConstantUnion *newNode = 0;
ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
- for (int i = 0; i < objectSize; i++) {
+ for (size_t i = 0; i < objectSize; i++) {
switch(op) {
case EOpNegative:
switch (getType().getBasicType()) {
case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
default:
- infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
+ infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return 0;
}
break;
@@ -1362,7 +1345,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
switch (getType().getBasicType()) {
case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
default:
- infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
+ infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return 0;
}
break;
@@ -1378,11 +1361,11 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
{
- int size = node->getType().getObjectSize();
+ size_t size = node->getType().getObjectSize();
ConstantUnion *leftUnionArray = new ConstantUnion[size];
- for (int i=0; i < size; i++) {
+ for (size_t i = 0; i < size; i++) {
switch (promoteTo) {
case EbtFloat:
@@ -1397,7 +1380,7 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC
leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
break;
default:
- infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
return 0;
}
break;
@@ -1413,7 +1396,7 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC
leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
break;
default:
- infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
return 0;
}
break;
@@ -1429,13 +1412,13 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC
leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
break;
default:
- infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
return 0;
}
break;
default:
- infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Incorrect data type found");
return 0;
}
diff --git a/src/3rdparty/angle/src/compiler/OutputGLSL.cpp b/src/3rdparty/angle/src/compiler/OutputGLSL.cpp
index 206f403408..10a451c0d7 100644
--- a/src/3rdparty/angle/src/compiler/OutputGLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/OutputGLSL.cpp
@@ -19,3 +19,17 @@ bool TOutputGLSL::writeVariablePrecision(TPrecision)
{
return false;
}
+
+void TOutputGLSL::visitSymbol(TIntermSymbol* node)
+{
+ TInfoSinkBase& out = objSink();
+
+ if (node->getSymbol() == "gl_FragDepthEXT")
+ {
+ out << "gl_FragDepth";
+ }
+ else
+ {
+ TOutputGLSLBase::visitSymbol(node);
+ }
+}
diff --git a/src/3rdparty/angle/src/compiler/OutputGLSL.h b/src/3rdparty/angle/src/compiler/OutputGLSL.h
index 199b6f3e46..fa68ac8103 100644
--- a/src/3rdparty/angle/src/compiler/OutputGLSL.h
+++ b/src/3rdparty/angle/src/compiler/OutputGLSL.h
@@ -20,6 +20,7 @@ public:
protected:
virtual bool writeVariablePrecision(TPrecision);
+ virtual void visitSymbol(TIntermSymbol* node);
};
#endif // CROSSCOMPILERGLSL_OUTPUTGLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp
index 1b9a10deaa..d677c75633 100644
--- a/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp
+++ b/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp
@@ -79,25 +79,9 @@ void TOutputGLSLBase::writeVariableType(const TType& type)
if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal))
out << type.getQualifierString() << " ";
// Declare the struct if we have not done so already.
- if ((type.getBasicType() == EbtStruct) &&
- (mDeclaredStructs.find(type.getTypeName()) == mDeclaredStructs.end()))
+ if ((type.getBasicType() == EbtStruct) && !structDeclared(type.getStruct()))
{
- out << "struct " << hashName(type.getTypeName()) << "{\n";
- const TTypeList* structure = type.getStruct();
- ASSERT(structure != NULL);
- for (size_t i = 0; i < structure->size(); ++i)
- {
- const TType* fieldType = (*structure)[i].type;
- ASSERT(fieldType != NULL);
- if (writeVariablePrecision(fieldType->getPrecision()))
- out << " ";
- out << getTypeName(*fieldType) << " " << hashName(fieldType->getFieldName());
- if (fieldType->isArray())
- out << arrayBrackets(*fieldType);
- out << ";\n";
- }
- out << "}";
- mDeclaredStructs.insert(type.getTypeName());
+ declareStruct(type.getStruct());
}
else
{
@@ -138,24 +122,25 @@ const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type,
if (type.getBasicType() == EbtStruct)
{
- out << hashName(type.getTypeName()) << "(";
- const TTypeList* structure = type.getStruct();
- ASSERT(structure != NULL);
- for (size_t i = 0; i < structure->size(); ++i)
+ const TStructure* structure = type.getStruct();
+ out << hashName(structure->name()) << "(";
+
+ const TFieldList& fields = structure->fields();
+ for (size_t i = 0; i < fields.size(); ++i)
{
- const TType* fieldType = (*structure)[i].type;
+ const TType* fieldType = fields[i]->type();
ASSERT(fieldType != NULL);
pConstUnion = writeConstantUnion(*fieldType, pConstUnion);
- if (i != structure->size() - 1) out << ", ";
+ if (i != fields.size() - 1) out << ", ";
}
out << ")";
}
else
{
- int size = type.getObjectSize();
+ size_t size = type.getObjectSize();
bool writeType = size > 1;
if (writeType) out << getTypeName(type) << "(";
- for (int i = 0; i < size; ++i, ++pConstUnion)
+ for (size_t i = 0; i < size; ++i, ++pConstUnion)
{
switch (pConstUnion->getType())
{
@@ -260,12 +245,18 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
case EOpIndexDirectStruct:
if (visit == InVisit)
{
+ // Here we are writing out "foo.bar", where "foo" is struct
+ // and "bar" is field. In AST, it is represented as a binary
+ // node, where left child represents "foo" and right child "bar".
+ // The node itself represents ".". The struct field "bar" is
+ // actually stored as an index into TStructure::fields.
out << ".";
- // TODO(alokp): ASSERT
- TString fieldName = node->getType().getFieldName();
+ const TStructure* structure = node->getLeft()->getType().getStruct();
+ const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion();
+ const TField* field = structure->fields()[index->getIConst(0)];
- const TType& structType = node->getLeft()->getType();
- if (!mSymbolTable.findBuiltIn(structType.getTypeName()))
+ TString fieldName = field->name();
+ if (!mSymbolTable.findBuiltIn(structure->name()))
fieldName = hashName(fieldName);
out << fieldName;
@@ -596,7 +587,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node)
{
const TType& type = node->getType();
ASSERT(type.getBasicType() == EbtStruct);
- out << hashName(type.getTypeName()) << "(";
+ out << hashName(type.getStruct()->name()) << "(";
}
else if (visit == InVisit)
{
@@ -765,7 +756,7 @@ TString TOutputGLSLBase::getTypeName(const TType& type)
else
{
if (type.getBasicType() == EbtStruct)
- out << hashName(type.getTypeName());
+ out << hashName(type.getStruct()->name());
else
out << type.getBasicString();
}
@@ -798,3 +789,29 @@ TString TOutputGLSLBase::hashFunctionName(const TString& mangled_name)
return name;
return hashName(name);
}
+
+bool TOutputGLSLBase::structDeclared(const TStructure* structure) const
+{
+ return mDeclaredStructs.find(structure->name()) != mDeclaredStructs.end();
+}
+
+void TOutputGLSLBase::declareStruct(const TStructure* structure)
+{
+ TInfoSinkBase& out = objSink();
+
+ out << "struct " << hashName(structure->name()) << "{\n";
+ const TFieldList& fields = structure->fields();
+ for (size_t i = 0; i < fields.size(); ++i)
+ {
+ const TField* field = fields[i];
+ if (writeVariablePrecision(field->type()->getPrecision()))
+ out << " ";
+ out << getTypeName(*field->type()) << " " << hashName(field->name());
+ if (field->type()->isArray())
+ out << arrayBrackets(*field->type());
+ out << ";\n";
+ }
+ out << "}";
+
+ mDeclaredStructs.insert(structure->name());
+}
diff --git a/src/3rdparty/angle/src/compiler/OutputGLSLBase.h b/src/3rdparty/angle/src/compiler/OutputGLSLBase.h
index c9f72d5631..df4ad68c2c 100644
--- a/src/3rdparty/angle/src/compiler/OutputGLSLBase.h
+++ b/src/3rdparty/angle/src/compiler/OutputGLSLBase.h
@@ -52,6 +52,9 @@ protected:
TString hashFunctionName(const TString& mangled_name);
private:
+ bool structDeclared(const TStructure* structure) const;
+ void declareStruct(const TStructure* structure);
+
TInfoSinkBase& mObjSink;
bool mDeclaringVariables;
diff --git a/src/3rdparty/angle/src/compiler/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/OutputHLSL.cpp
index f6a984148b..79a373ebab 100644
--- a/src/3rdparty/angle/src/compiler/OutputHLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/OutputHLSL.cpp
@@ -55,6 +55,7 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc
mUsesPointCoord = false;
mUsesFrontFacing = false;
mUsesPointSize = false;
+ mUsesFragDepth = false;
mUsesXor = false;
mUsesMod1 = false;
mUsesMod2v = false;
@@ -67,18 +68,6 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc
mUsesFaceforward2 = false;
mUsesFaceforward3 = false;
mUsesFaceforward4 = false;
- mUsesEqualMat2 = false;
- mUsesEqualMat3 = false;
- mUsesEqualMat4 = false;
- mUsesEqualVec2 = false;
- mUsesEqualVec3 = false;
- mUsesEqualVec4 = false;
- mUsesEqualIVec2 = false;
- mUsesEqualIVec3 = false;
- mUsesEqualIVec4 = false;
- mUsesEqualBVec2 = false;
- mUsesEqualBVec3 = false;
- mUsesEqualBVec4 = false;
mUsesAtan2_1 = false;
mUsesAtan2_2 = false;
mUsesAtan2_3 = false;
@@ -210,9 +199,9 @@ void OutputHLSL::header()
if (shaderType == SH_FRAGMENT_SHADER)
{
TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers");
- bool usingMRTExtension = iter != mContext.extensionBehavior().end() && iter->second == EBhEnable;
+ const bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire));
- unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1;
+ const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1;
out << "// Varyings\n";
out << varyings;
@@ -230,6 +219,11 @@ void OutputHLSL::header()
}
out << "};\n";
+ if (mUsesFragDepth)
+ {
+ out << "static float gl_Depth = 0.0;\n";
+ }
+
if (mUsesFragCoord)
{
out << "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n";
@@ -844,6 +838,16 @@ void OutputHLSL::header()
out << "#define GL_USES_POINT_SIZE\n";
}
+ if (mUsesFragDepth)
+ {
+ out << "#define GL_USES_FRAG_DEPTH\n";
+ }
+
+ if (mUsesDepthRange)
+ {
+ out << "#define GL_USES_DEPTH_RANGE\n";
+ }
+
if (mUsesXor)
{
out << "bool xor(bool p, bool q)\n"
@@ -980,108 +984,6 @@ void OutputHLSL::header()
"\n";
}
- if (mUsesEqualMat2)
- {
- out << "bool equal(float2x2 m, float2x2 n)\n"
- "{\n"
- " return m[0][0] == n[0][0] && m[0][1] == n[0][1] &&\n"
- " m[1][0] == n[1][0] && m[1][1] == n[1][1];\n"
- "}\n";
- }
-
- if (mUsesEqualMat3)
- {
- out << "bool equal(float3x3 m, float3x3 n)\n"
- "{\n"
- " return m[0][0] == n[0][0] && m[0][1] == n[0][1] && m[0][2] == n[0][2] &&\n"
- " m[1][0] == n[1][0] && m[1][1] == n[1][1] && m[1][2] == n[1][2] &&\n"
- " m[2][0] == n[2][0] && m[2][1] == n[2][1] && m[2][2] == n[2][2];\n"
- "}\n";
- }
-
- if (mUsesEqualMat4)
- {
- out << "bool equal(float4x4 m, float4x4 n)\n"
- "{\n"
- " return m[0][0] == n[0][0] && m[0][1] == n[0][1] && m[0][2] == n[0][2] && m[0][3] == n[0][3] &&\n"
- " m[1][0] == n[1][0] && m[1][1] == n[1][1] && m[1][2] == n[1][2] && m[1][3] == n[1][3] &&\n"
- " m[2][0] == n[2][0] && m[2][1] == n[2][1] && m[2][2] == n[2][2] && m[2][3] == n[2][3] &&\n"
- " m[3][0] == n[3][0] && m[3][1] == n[3][1] && m[3][2] == n[3][2] && m[3][3] == n[3][3];\n"
- "}\n";
- }
-
- if (mUsesEqualVec2)
- {
- out << "bool equal(float2 v, float2 u)\n"
- "{\n"
- " return v.x == u.x && v.y == u.y;\n"
- "}\n";
- }
-
- if (mUsesEqualVec3)
- {
- out << "bool equal(float3 v, float3 u)\n"
- "{\n"
- " return v.x == u.x && v.y == u.y && v.z == u.z;\n"
- "}\n";
- }
-
- if (mUsesEqualVec4)
- {
- out << "bool equal(float4 v, float4 u)\n"
- "{\n"
- " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
- "}\n";
- }
-
- if (mUsesEqualIVec2)
- {
- out << "bool equal(int2 v, int2 u)\n"
- "{\n"
- " return v.x == u.x && v.y == u.y;\n"
- "}\n";
- }
-
- if (mUsesEqualIVec3)
- {
- out << "bool equal(int3 v, int3 u)\n"
- "{\n"
- " return v.x == u.x && v.y == u.y && v.z == u.z;\n"
- "}\n";
- }
-
- if (mUsesEqualIVec4)
- {
- out << "bool equal(int4 v, int4 u)\n"
- "{\n"
- " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
- "}\n";
- }
-
- if (mUsesEqualBVec2)
- {
- out << "bool equal(bool2 v, bool2 u)\n"
- "{\n"
- " return v.x == u.x && v.y == u.y;\n"
- "}\n";
- }
-
- if (mUsesEqualBVec3)
- {
- out << "bool equal(bool3 v, bool3 u)\n"
- "{\n"
- " return v.x == u.x && v.y == u.y && v.z == u.z;\n"
- "}\n";
- }
-
- if (mUsesEqualBVec4)
- {
- out << "bool equal(bool4 v, bool4 u)\n"
- "{\n"
- " return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
- "}\n";
- }
-
if (mUsesAtan2_1)
{
out << "float atanyx(float y, float x)\n"
@@ -1166,6 +1068,11 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node)
mUsesPointSize = true;
out << name;
}
+ else if (name == "gl_FragDepthEXT")
+ {
+ mUsesFragDepth = true;
+ out << "gl_Depth";
+ }
else
{
TQualifier qualifier = node->getQualifier();
@@ -1275,7 +1182,10 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
case EOpIndexDirectStruct:
if (visit == InVisit)
{
- out << "." + decorateField(node->getType().getFieldName(), node->getLeft()->getType());
+ const TStructure* structure = node->getLeft()->getType().getStruct();
+ const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion();
+ const TField* field = structure->fields()[index->getIConst(0)];
+ out << "." + decorateField(field->name(), node->getLeft()->getType());
return false;
}
@@ -1344,18 +1254,18 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
out << "!(";
}
- const TTypeList *fields = node->getLeft()->getType().getStruct();
+ const TFieldList &fields = node->getLeft()->getType().getStruct()->fields();
- for (size_t i = 0; i < fields->size(); i++)
+ for (size_t i = 0; i < fields.size(); i++)
{
- const TType *fieldType = (*fields)[i].type;
+ const TField *field = fields[i];
node->getLeft()->traverse(this);
- out << "." + decorateField(fieldType->getFieldName(), node->getLeft()->getType()) + " == ";
+ out << "." + decorateField(field->name(), node->getLeft()->getType()) + " == ";
node->getRight()->traverse(this);
- out << "." + decorateField(fieldType->getFieldName(), node->getLeft()->getType());
+ out << "." + decorateField(field->name(), node->getLeft()->getType());
- if (i < fields->size() - 1)
+ if (i < fields.size() - 1)
{
out << " && ";
}
@@ -1367,59 +1277,15 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
}
else
{
- if (node->getLeft()->isMatrix())
- {
- switch (node->getLeft()->getNominalSize())
- {
- case 2: mUsesEqualMat2 = true; break;
- case 3: mUsesEqualMat3 = true; break;
- case 4: mUsesEqualMat4 = true; break;
- default: UNREACHABLE();
- }
- }
- else if (node->getLeft()->isVector())
- {
- switch (node->getLeft()->getBasicType())
- {
- case EbtFloat:
- switch (node->getLeft()->getNominalSize())
- {
- case 2: mUsesEqualVec2 = true; break;
- case 3: mUsesEqualVec3 = true; break;
- case 4: mUsesEqualVec4 = true; break;
- default: UNREACHABLE();
- }
- break;
- case EbtInt:
- switch (node->getLeft()->getNominalSize())
- {
- case 2: mUsesEqualIVec2 = true; break;
- case 3: mUsesEqualIVec3 = true; break;
- case 4: mUsesEqualIVec4 = true; break;
- default: UNREACHABLE();
- }
- break;
- case EbtBool:
- switch (node->getLeft()->getNominalSize())
- {
- case 2: mUsesEqualBVec2 = true; break;
- case 3: mUsesEqualBVec3 = true; break;
- case 4: mUsesEqualBVec4 = true; break;
- default: UNREACHABLE();
- }
- break;
- default: UNREACHABLE();
- }
- }
- else UNREACHABLE();
+ ASSERT(node->getLeft()->isMatrix() || node->getLeft()->isVector());
if (node->getOp() == EOpEqual)
{
- outputTriplet(visit, "equal(", ", ", ")");
+ outputTriplet(visit, "all(", " == ", ")");
}
else
{
- outputTriplet(visit, "!equal(", ", ", ")");
+ outputTriplet(visit, "!all(", " == ", ")");
}
}
break;
@@ -1561,7 +1427,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
{
if (mInsideFunction)
{
- outputLineDirective(node->getLine());
+ outputLineDirective(node->getLine().first_line);
out << "{\n";
mScopeDepth++;
@@ -1578,7 +1444,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++)
{
- outputLineDirective((*sit)->getLine());
+ outputLineDirective((*sit)->getLine().first_line);
traverseStatements(*sit);
@@ -1587,7 +1453,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
if (mInsideFunction)
{
- outputLineDirective(node->getEndLine());
+ outputLineDirective(node->getLine().last_line);
out << "}\n";
mScopeDepth--;
@@ -1605,7 +1471,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
{
if (variable->getType().getStruct())
{
- addConstructor(variable->getType(), scopedStruct(variable->getType().getTypeName()), NULL);
+ addConstructor(variable->getType(), scopedStruct(variable->getType().getStruct()->name()), NULL);
}
if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration
@@ -1732,7 +1598,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
{
if (symbol->getType().getStruct())
{
- addConstructor(symbol->getType(), scopedStruct(symbol->getType().getTypeName()), NULL);
+ addConstructor(symbol->getType(), scopedStruct(symbol->getType().getStruct()->name()), NULL);
}
out << argumentString(symbol);
@@ -1993,8 +1859,8 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
outputTriplet(visit, "mat4(", ", ", ")");
break;
case EOpConstructStruct:
- addConstructor(node->getType(), scopedStruct(node->getType().getTypeName()), &node->getSequence());
- outputTriplet(visit, structLookup(node->getType().getTypeName()) + "_ctor(", ", ", ")");
+ addConstructor(node->getType(), scopedStruct(node->getType().getStruct()->name()), &node->getSequence());
+ outputTriplet(visit, structLookup(node->getType().getStruct()->name()) + "_ctor(", ", ", ")");
break;
case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break;
case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break;
@@ -2084,7 +1950,7 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
out << ")\n";
- outputLineDirective(node->getLine());
+ outputLineDirective(node->getLine().first_line);
out << "{\n";
if (node->getTrueBlock())
@@ -2092,20 +1958,20 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
traverseStatements(node->getTrueBlock());
}
- outputLineDirective(node->getLine());
+ outputLineDirective(node->getLine().first_line);
out << ";\n}\n";
if (node->getFalseBlock())
{
out << "else\n";
- outputLineDirective(node->getFalseBlock()->getLine());
+ outputLineDirective(node->getFalseBlock()->getLine().first_line);
out << "{\n";
- outputLineDirective(node->getFalseBlock()->getLine());
+ outputLineDirective(node->getFalseBlock()->getLine().first_line);
traverseStatements(node->getFalseBlock());
- outputLineDirective(node->getFalseBlock()->getLine());
+ outputLineDirective(node->getFalseBlock()->getLine().first_line);
out << ";\n}\n";
}
}
@@ -2141,7 +2007,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
{
out << "{do\n";
- outputLineDirective(node->getLine());
+ outputLineDirective(node->getLine().first_line);
out << "{\n";
}
else
@@ -2169,7 +2035,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
out << ")\n";
- outputLineDirective(node->getLine());
+ outputLineDirective(node->getLine().first_line);
out << "{\n";
}
@@ -2178,12 +2044,12 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
traverseStatements(node->getBody());
}
- outputLineDirective(node->getLine());
+ outputLineDirective(node->getLine().first_line);
out << ";}\n";
if (node->getType() == ELoopDoWhile)
{
- outputLineDirective(node->getCondition()->getLine());
+ outputLineDirective(node->getCondition()->getLine().first_line);
out << "while(\n";
node->getCondition()->traverse(this);
@@ -2455,7 +2321,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
out << increment;
out << ")\n";
- outputLineDirective(node->getLine());
+ outputLineDirective(node->getLine().first_line);
out << "{\n";
if (node->getBody())
@@ -2463,7 +2329,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
node->getBody()->traverse(this);
}
- outputLineDirective(node->getLine());
+ outputLineDirective(node->getLine().first_line);
out << ";}\n";
if (!firstLoopFragment)
@@ -2565,22 +2431,23 @@ TString OutputHLSL::typeString(const TType &type)
{
if (type.getBasicType() == EbtStruct)
{
- if (type.getTypeName() != "")
+ const TString& typeName = type.getStruct()->name();
+ if (typeName != "")
{
- return structLookup(type.getTypeName());
+ return structLookup(typeName);
}
else // Nameless structure, define in place
{
- const TTypeList &fields = *type.getStruct();
+ const TFieldList &fields = type.getStruct()->fields();
TString string = "struct\n"
"{\n";
for (unsigned int i = 0; i < fields.size(); i++)
{
- const TType &field = *fields[i].type;
+ const TField *field = fields[i];
- string += " " + typeString(field) + " " + decorate(field.getFieldName()) + arrayString(field) + ";\n";
+ string += " " + typeString(*field->type()) + " " + decorate(field->name()) + arrayString(*field->type()) + ";\n";
}
string += "} ";
@@ -2674,11 +2541,12 @@ TString OutputHLSL::initializer(const TType &type)
{
TString string;
- for (int component = 0; component < type.getObjectSize(); component++)
+ size_t size = type.getObjectSize();
+ for (size_t component = 0; component < size; component++)
{
string += "0";
- if (component < type.getObjectSize() - 1)
+ if (component + 1 < size)
{
string += ", ";
}
@@ -2717,13 +2585,13 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI
structure += "struct " + decorate(name) + "\n"
"{\n";
- const TTypeList &fields = *type.getStruct();
+ const TFieldList &fields = type.getStruct()->fields();
for (unsigned int i = 0; i < fields.size(); i++)
{
- const TType &field = *fields[i].type;
+ const TField *field = fields[i];
- structure += " " + typeString(field) + " " + decorateField(field.getFieldName(), type) + arrayString(field) + ";\n";
+ structure += " " + typeString(*field->type()) + " " + decorateField(field->name(), type) + arrayString(*field->type()) + ";\n";
}
structure += "};\n";
@@ -2735,7 +2603,7 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI
for (unsigned int i = 0; i < fields.size(); i++)
{
- ctorParameters.push_back(*fields[i].type);
+ ctorParameters.push_back(*fields[i]->type());
}
}
else if (parameters)
@@ -2828,27 +2696,30 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI
}
else
{
- int remainingComponents = ctorType.getObjectSize();
- int parameterIndex = 0;
+ size_t remainingComponents = ctorType.getObjectSize();
+ size_t parameterIndex = 0;
while (remainingComponents > 0)
{
const TType &parameter = ctorParameters[parameterIndex];
- bool moreParameters = parameterIndex < (int)ctorParameters.size() - 1;
+ const size_t parameterSize = parameter.getObjectSize();
+ bool moreParameters = parameterIndex + 1 < ctorParameters.size();
constructor += "x" + str(parameterIndex);
if (parameter.isScalar())
{
- remainingComponents -= parameter.getObjectSize();
+ ASSERT(parameterSize <= remainingComponents);
+ remainingComponents -= parameterSize;
}
else if (parameter.isVector())
{
- if (remainingComponents == parameter.getObjectSize() || moreParameters)
+ if (remainingComponents == parameterSize || moreParameters)
{
- remainingComponents -= parameter.getObjectSize();
+ ASSERT(parameterSize <= remainingComponents);
+ remainingComponents -= parameterSize;
}
- else if (remainingComponents < parameter.getNominalSize())
+ else if (remainingComponents < static_cast<size_t>(parameter.getNominalSize()))
{
switch (remainingComponents)
{
@@ -2865,9 +2736,10 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI
}
else if (parameter.isMatrix() || parameter.getStruct())
{
- ASSERT(remainingComponents == parameter.getObjectSize() || moreParameters);
+ ASSERT(remainingComponents == parameterSize || moreParameters);
+ ASSERT(parameterSize <= remainingComponents);
- remainingComponents -= parameter.getObjectSize();
+ remainingComponents -= parameterSize;
}
else UNREACHABLE();
@@ -2904,17 +2776,17 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con
if (type.getBasicType() == EbtStruct)
{
- out << structLookup(type.getTypeName()) + "_ctor(";
+ out << structLookup(type.getStruct()->name()) + "_ctor(";
- const TTypeList *structure = type.getStruct();
+ const TFieldList &fields = type.getStruct()->fields();
- for (size_t i = 0; i < structure->size(); i++)
+ for (size_t i = 0; i < fields.size(); i++)
{
- const TType *fieldType = (*structure)[i].type;
+ const TType *fieldType = fields[i]->type();
constUnion = writeConstantUnion(*fieldType, constUnion);
- if (i != structure->size() - 1)
+ if (i != fields.size() - 1)
{
out << ", ";
}
@@ -2924,7 +2796,7 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con
}
else
{
- int size = type.getObjectSize();
+ size_t size = type.getObjectSize();
bool writeType = size > 1;
if (writeType)
@@ -2932,7 +2804,7 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con
out << typeString(type) << "(";
}
- for (int i = 0; i < size; i++, constUnion++)
+ for (size_t i = 0; i < size; i++, constUnion++)
{
switch (constUnion->getType())
{
@@ -3021,7 +2893,7 @@ TString OutputHLSL::decorateUniform(const TString &string, const TType &type)
TString OutputHLSL::decorateField(const TString &string, const TType &structure)
{
- if (structure.getTypeName().compare(0, 3, "gl_") != 0)
+ if (structure.getStruct()->name().compare(0, 3, "gl_") != 0)
{
return decorate(string);
}
@@ -3069,7 +2941,7 @@ int OutputHLSL::uniformRegister(TIntermSymbol *uniform)
void OutputHLSL::declareUniform(const TType &type, const TString &name, int index)
{
- const TTypeList *structure = type.getStruct();
+ TStructure *structure = type.getStruct();
if (!structure)
{
@@ -3077,18 +2949,18 @@ void OutputHLSL::declareUniform(const TType &type, const TString &name, int inde
}
else
{
+ const TFieldList &fields = structure->fields();
+
if (type.isArray())
{
int elementIndex = index;
for (int i = 0; i < type.getArraySize(); i++)
{
- for (size_t j = 0; j < structure->size(); j++)
+ for (size_t j = 0; j < fields.size(); j++)
{
- const TType &fieldType = *(*structure)[j].type;
- const TString &fieldName = fieldType.getFieldName();
-
- const TString uniformName = name + "[" + str(i) + "]." + fieldName;
+ const TType &fieldType = *fields[j]->type();
+ const TString uniformName = name + "[" + str(i) + "]." + fields[j]->name();
declareUniform(fieldType, uniformName, elementIndex);
elementIndex += fieldType.totalRegisterCount();
}
@@ -3098,12 +2970,10 @@ void OutputHLSL::declareUniform(const TType &type, const TString &name, int inde
{
int fieldIndex = index;
- for (size_t i = 0; i < structure->size(); i++)
+ for (size_t i = 0; i < fields.size(); i++)
{
- const TType &fieldType = *(*structure)[i].type;
- const TString &fieldName = fieldType.getFieldName();
-
- const TString uniformName = name + "." + fieldName;
+ const TType &fieldType = *fields[i]->type();
+ const TString uniformName = name + "." + fields[i]->name();
declareUniform(fieldType, uniformName, fieldIndex);
fieldIndex += fieldType.totalRegisterCount();
}
diff --git a/src/3rdparty/angle/src/compiler/OutputHLSL.h b/src/3rdparty/angle/src/compiler/OutputHLSL.h
index 749a3461b3..cde4120718 100644
--- a/src/3rdparty/angle/src/compiler/OutputHLSL.h
+++ b/src/3rdparty/angle/src/compiler/OutputHLSL.h
@@ -108,6 +108,7 @@ class OutputHLSL : public TIntermTraverser
bool mUsesPointCoord;
bool mUsesFrontFacing;
bool mUsesPointSize;
+ bool mUsesFragDepth;
bool mUsesXor;
bool mUsesMod1;
bool mUsesMod2v;
@@ -120,18 +121,6 @@ class OutputHLSL : public TIntermTraverser
bool mUsesFaceforward2;
bool mUsesFaceforward3;
bool mUsesFaceforward4;
- bool mUsesEqualMat2;
- bool mUsesEqualMat3;
- bool mUsesEqualMat4;
- bool mUsesEqualVec2;
- bool mUsesEqualVec3;
- bool mUsesEqualVec4;
- bool mUsesEqualIVec2;
- bool mUsesEqualIVec3;
- bool mUsesEqualIVec4;
- bool mUsesEqualBVec2;
- bool mUsesEqualBVec3;
- bool mUsesEqualBVec4;
bool mUsesAtan2_1;
bool mUsesAtan2_2;
bool mUsesAtan2_3;
diff --git a/src/3rdparty/angle/src/compiler/ParseHelper.cpp b/src/3rdparty/angle/src/compiler/ParseHelper.cpp
index 441ff35e00..1f8538e6a4 100644
--- a/src/3rdparty/angle/src/compiler/ParseHelper.cpp
+++ b/src/3rdparty/angle/src/compiler/ParseHelper.cpp
@@ -22,7 +22,7 @@
// Look at a '.' field selector string and change it into offsets
// for a vector.
//
-bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, int line)
+bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, const TSourceLoc& line)
{
fields.num = (int) compString.size();
if (fields.num > 4) {
@@ -115,7 +115,7 @@ bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TV
// Look at a '.' field selector string and change it into offsets
// for a matrix.
//
-bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, int line)
+bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, const TSourceLoc& line)
{
fields.wholeRow = false;
fields.wholeCol = false;
@@ -175,22 +175,24 @@ void TParseContext::recover()
//
// Used by flex/bison to output all syntax and parsing errors.
//
-void TParseContext::error(TSourceLoc loc,
+void TParseContext::error(const TSourceLoc& loc,
const char* reason, const char* token,
const char* extraInfo)
{
pp::SourceLocation srcLoc;
- DecodeSourceLoc(loc, &srcLoc.file, &srcLoc.line);
+ srcLoc.file = loc.first_file;
+ srcLoc.line = loc.first_line;
diagnostics.writeInfo(pp::Diagnostics::ERROR,
srcLoc, reason, token, extraInfo);
}
-void TParseContext::warning(TSourceLoc loc,
+void TParseContext::warning(const TSourceLoc& loc,
const char* reason, const char* token,
const char* extraInfo) {
pp::SourceLocation srcLoc;
- DecodeSourceLoc(loc, &srcLoc.file, &srcLoc.line);
+ srcLoc.file = loc.first_file;
+ srcLoc.line = loc.first_line;
diagnostics.writeInfo(pp::Diagnostics::WARNING,
srcLoc, reason, token, extraInfo);
}
@@ -203,7 +205,7 @@ void TParseContext::trace(const char* str)
//
// Same error message for all places assignments don't work.
//
-void TParseContext::assignError(int line, const char* op, TString left, TString right)
+void TParseContext::assignError(const TSourceLoc& line, const char* op, TString left, TString right)
{
std::stringstream extraInfoStream;
extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'";
@@ -214,7 +216,7 @@ void TParseContext::assignError(int line, const char* op, TString left, TString
//
// Same error message for all places unary operations don't work.
//
-void TParseContext::unaryOpError(int line, const char* op, TString operand)
+void TParseContext::unaryOpError(const TSourceLoc& line, const char* op, TString operand)
{
std::stringstream extraInfoStream;
extraInfoStream << "no operation '" << op << "' exists that takes an operand of type " << operand
@@ -226,7 +228,7 @@ void TParseContext::unaryOpError(int line, const char* op, TString operand)
//
// Same error message for all binary operations don't work.
//
-void TParseContext::binaryOpError(int line, const char* op, TString left, TString right)
+void TParseContext::binaryOpError(const TSourceLoc& line, const char* op, TString left, TString right)
{
std::stringstream extraInfoStream;
extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left
@@ -235,7 +237,7 @@ void TParseContext::binaryOpError(int line, const char* op, TString left, TStrin
error(line, " wrong operand types ", op, extraInfo.c_str());
}
-bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicType type){
+bool TParseContext::precisionErrorCheck(const TSourceLoc& line, TPrecision precision, TBasicType type){
if (!checksPrecisionErrors)
return false;
switch( type ){
@@ -263,7 +265,7 @@ bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicTy
//
// Returns true if the was an error.
//
-bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* node)
+bool TParseContext::lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped* node)
{
TIntermSymbol* symNode = node->getAsSymbolNode();
TIntermBinary* binaryNode = node->getAsBinaryNode();
@@ -317,7 +319,6 @@ bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* nod
case EvqAttribute: message = "can't modify an attribute"; break;
case EvqUniform: message = "can't modify a uniform"; break;
case EvqVaryingIn: message = "can't modify a varying"; break;
- case EvqInput: message = "can't modify an input"; break;
case EvqFragCoord: message = "can't modify gl_FragCoord"; break;
case EvqFrontFacing: message = "can't modify gl_FrontFacing"; break;
case EvqPointCoord: message = "can't modify gl_PointCoord"; break;
@@ -409,7 +410,7 @@ bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token)
//
// Returns true if the was an error.
//
-bool TParseContext::globalErrorCheck(int line, bool global, const char* token)
+bool TParseContext::globalErrorCheck(const TSourceLoc& line, bool global, const char* token)
{
if (global)
return false;
@@ -428,7 +429,7 @@ bool TParseContext::globalErrorCheck(int line, bool global, const char* token)
//
// Returns true if there was an error.
//
-bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
+bool TParseContext::reservedErrorCheck(const TSourceLoc& line, const TString& identifier)
{
static const char* reservedErrMsg = "reserved built-in name";
if (!symbolTable.atBuiltInLevel()) {
@@ -466,7 +467,7 @@ bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
//
// Returns true if there was an error in construction.
//
-bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
+bool TParseContext::constructorErrorCheck(const TSourceLoc& line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
{
*type = function.getReturnType();
@@ -487,7 +488,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction
// again, there is an extra argument, so 'overfull' will become true.
//
- int size = 0;
+ size_t size = 0;
bool constType = true;
bool full = false;
bool overFull = false;
@@ -534,7 +535,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction
return true;
}
- if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->size()) != function.getParamCount()) {
+ if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->fields().size()) != function.getParamCount()) {
error(line, "Number of constructor parameters does not match the number of structure fields", "constructor");
return true;
}
@@ -568,7 +569,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction
//
// returns true in case of an error
//
-bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TPublicType& pubType)
+bool TParseContext::voidErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType& pubType)
{
if (pubType.type == EbtVoid) {
error(line, "illegal use of type 'void'", identifier.c_str());
@@ -582,7 +583,7 @@ bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TP
//
// returns true in case of an error
//
-bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type)
+bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TIntermTyped* type)
{
if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
error(line, "boolean expression expected", "");
@@ -596,7 +597,7 @@ bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type)
//
// returns true in case of an error
//
-bool TParseContext::boolErrorCheck(int line, const TPublicType& pType)
+bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TPublicType& pType)
{
if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) {
error(line, "boolean expression expected", "");
@@ -606,7 +607,7 @@ bool TParseContext::boolErrorCheck(int line, const TPublicType& pType)
return false;
}
-bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const char* reason)
+bool TParseContext::samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason)
{
if (pType.type == EbtStruct) {
if (containsSampler(*pType.userDef)) {
@@ -625,7 +626,7 @@ bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const
return false;
}
-bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType)
+bool TParseContext::structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType)
{
if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) &&
pType.type == EbtStruct) {
@@ -640,7 +641,7 @@ bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType
return false;
}
-bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type)
+bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type)
{
if ((qualifier == EvqOut || qualifier == EvqInOut) &&
type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
@@ -657,9 +658,9 @@ bool TParseContext::containsSampler(TType& type)
return true;
if (type.getBasicType() == EbtStruct) {
- TTypeList& structure = *type.getStruct();
- for (unsigned int i = 0; i < structure.size(); ++i) {
- if (containsSampler(*structure[i].type))
+ const TFieldList& fields = type.getStruct()->fields();
+ for (unsigned int i = 0; i < fields.size(); ++i) {
+ if (containsSampler(*fields[i]->type()))
return true;
}
}
@@ -672,7 +673,7 @@ bool TParseContext::containsSampler(TType& type)
//
// Returns true if there was an error.
//
-bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
+bool TParseContext::arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size)
{
TIntermConstantUnion* constant = expr->getAsConstantUnion();
if (constant == 0 || constant->getBasicType() != EbtInt) {
@@ -696,7 +697,7 @@ bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
//
// Returns true if there is an error.
//
-bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type)
+bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type)
{
if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqConst)) {
error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str());
@@ -711,7 +712,7 @@ bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type)
//
// Returns true if there is an error.
//
-bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type)
+bool TParseContext::arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type)
{
//
// Can the type be an array?
@@ -732,7 +733,7 @@ bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type)
//
// Returns true if there was an error.
//
-bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable)
+bool TParseContext::arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable)
{
//
// Don't check for reserved word use until after we know it's not in the symbol table,
@@ -777,16 +778,6 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType t
return true;
}
- TType* t = variable->getArrayInformationType();
- while (t != 0) {
- if (t->getMaxArraySize() > type.arraySize) {
- error(line, "higher index value already used for the array", identifier.c_str());
- return true;
- }
- t->setArraySize(type.arraySize);
- t = t->getArrayInformationType();
- }
-
if (type.arraySize)
variable->getType().setArraySize(type.arraySize);
}
@@ -797,56 +788,12 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType t
return false;
}
-bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line)
-{
- bool builtIn = false;
- TSymbol* symbol = symbolTable.find(node->getSymbol(), &builtIn);
- if (symbol == 0) {
- error(line, " undeclared identifier", node->getSymbol().c_str());
- return true;
- }
- TVariable* variable = static_cast<TVariable*>(symbol);
-
- type->setArrayInformationType(variable->getArrayInformationType());
- variable->updateArrayInformationType(type);
-
- // special casing to test index value of gl_FragData. If the accessed index is >= gl_MaxDrawBuffers
- // its an error
- if (node->getSymbol() == "gl_FragData") {
- TSymbol* fragData = symbolTable.find("gl_MaxDrawBuffers", &builtIn);
- ASSERT(fragData);
-
- int fragDataValue = static_cast<TVariable*>(fragData)->getConstPointer()[0].getIConst();
- if (fragDataValue <= size) {
- error(line, "", "[", "gl_FragData can only have a max array size of up to gl_MaxDrawBuffers");
- return true;
- }
- }
-
- // we dont want to update the maxArraySize when this flag is not set, we just want to include this
- // node type in the chain of node types so that its updated when a higher maxArraySize comes in.
- if (!updateFlag)
- return false;
-
- size++;
- variable->getType().setMaxArraySize(size);
- type->setMaxArraySize(size);
- TType* tt = type;
-
- while(tt->getArrayInformationType() != 0) {
- tt = tt->getArrayInformationType();
- tt->setMaxArraySize(size);
- }
-
- return false;
-}
-
//
// Enforce non-initializer type/qualifier rules.
//
// Returns true if there was an error.
//
-bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array)
+bool TParseContext::nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array)
{
if (type.qualifier == EvqConst)
{
@@ -878,7 +825,7 @@ bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPubli
//
// Returns true if there was an error.
//
-bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable)
+bool TParseContext::nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable)
{
if (reservedErrorCheck(line, identifier))
recover();
@@ -898,7 +845,7 @@ bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType
return false;
}
-bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
+bool TParseContext::paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
{
if (qualifier != EvqConst && qualifier != EvqTemporary) {
error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
@@ -917,7 +864,7 @@ bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier p
return false;
}
-bool TParseContext::extensionErrorCheck(int line, const TString& extension)
+bool TParseContext::extensionErrorCheck(const TSourceLoc& line, const TString& extension)
{
const TExtensionBehavior& extBehavior = extensionBehavior();
TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
@@ -945,18 +892,17 @@ bool TParseContext::supportsExtension(const char* extension)
return (iter != extbehavior.end());
}
-void TParseContext::handleExtensionDirective(int line, const char* extName, const char* behavior)
+bool TParseContext::isExtensionEnabled(const char* extension) const
{
- pp::SourceLocation loc;
- DecodeSourceLoc(line, &loc.file, &loc.line);
- directiveHandler.handleExtension(loc, extName, behavior);
-}
+ const TExtensionBehavior& extbehavior = extensionBehavior();
+ TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
-void TParseContext::handlePragmaDirective(int line, const char* name, const char* value)
-{
- pp::SourceLocation loc;
- DecodeSourceLoc(line, &loc.file, &loc.line);
- directiveHandler.handlePragma(loc, name, value);
+ if (iter == extbehavior.end())
+ {
+ return false;
+ }
+
+ return (iter->second == EBhEnable || iter->second == EBhRequire);
}
/////////////////////////////////////////////////////////////////////////////////
@@ -970,12 +916,13 @@ void TParseContext::handlePragmaDirective(int line, const char* name, const char
//
// Return the function symbol if found, otherwise 0.
//
-const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *builtIn)
+const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, bool *builtIn)
{
// First find by unmangled name to check whether the function name has been
// hidden by a variable name or struct typename.
+ // If a function is found, check for one with a matching argument list.
const TSymbol* symbol = symbolTable.find(call->getName(), builtIn);
- if (symbol == 0) {
+ if (symbol == 0 || symbol->isFunction()) {
symbol = symbolTable.find(call->getMangledName(), builtIn);
}
@@ -996,7 +943,7 @@ const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *bu
// Initializers show up in several places in the grammar. Have one set of
// code to handle them here.
//
-bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
+bool TParseContext::executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType,
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
{
TType type = TType(pType);
@@ -1048,13 +995,7 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu
return true;
}
if (initializer->getAsConstantUnion()) {
- ConstantUnion* unionArray = variable->getConstPointer();
-
- if (type.getObjectSize() == 1 && type.getBasicType() != EbtStruct) {
- *unionArray = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0];
- } else {
- variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
- }
+ variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
} else if (initializer->getAsSymbolNode()) {
const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol());
const TVariable* tVar = static_cast<const TVariable*>(symbol);
@@ -1108,16 +1049,16 @@ bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode)
//
// Returns 0 for an error or the constructed node (aggregate or typed) for no error.
//
-TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, TSourceLoc line)
+TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, const TSourceLoc& line)
{
if (node == 0)
return 0;
TIntermAggregate* aggrNode = node->getAsAggregate();
- TTypeList::const_iterator memberTypes;
+ TFieldList::const_iterator memberFields;
if (op == EOpConstructStruct)
- memberTypes = type->getStruct()->begin();
+ memberFields = type->getStruct()->fields().begin();
TType elementType = *type;
if (type->isArray())
@@ -1139,7 +1080,7 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type
if (type->isArray())
newNode = constructStruct(node, &elementType, 1, node->getLine(), false);
else if (op == EOpConstructStruct)
- newNode = constructStruct(node, (*memberTypes).type, 1, node->getLine(), false);
+ newNode = constructStruct(node, (*memberFields)->type(), 1, node->getLine(), false);
else
newNode = constructBuiltIn(type, op, node, node->getLine(), false);
@@ -1170,7 +1111,7 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type
if (type->isArray())
newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true);
else if (op == EOpConstructStruct)
- newNode = constructStruct(*p, (memberTypes[paramCount]).type, paramCount+1, node->getLine(), true);
+ newNode = constructStruct(*p, memberFields[paramCount]->type(), paramCount+1, node->getLine(), true);
else
newNode = constructBuiltIn(type, op, *p, node->getLine(), true);
@@ -1216,7 +1157,7 @@ TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, co
//
// Returns 0 for an error or the constructed node.
//
-TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, TSourceLoc line, bool subset)
+TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, const TSourceLoc& line, bool subset)
{
TIntermTyped* newNode;
TOperator basicOp;
@@ -1278,7 +1219,7 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, T
//
// Returns 0 for an error or the input node itself if the expected and the given parameter types match.
//
-TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, TSourceLoc line, bool subset)
+TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, const TSourceLoc& line, bool subset)
{
if (*type == node->getAsTyped()->getType()) {
if (subset)
@@ -1305,7 +1246,7 @@ TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int
// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of
// a constant matrix.
//
-TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc line)
+TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc& line)
{
TIntermTyped* typedNode;
TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
@@ -1327,7 +1268,7 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy
ConstantUnion* constArray = new ConstantUnion[fields.num];
for (int i = 0; i < fields.num; i++) {
- if (fields.offsets[i] >= node->getType().getObjectSize()) {
+ if (fields.offsets[i] >= node->getType().getNominalSize()) {
std::stringstream extraInfoStream;
extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'";
std::string extraInfo = extraInfoStream.str();
@@ -1349,7 +1290,7 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy
// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a
// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
//
-TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc line)
+TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc& line)
{
TIntermTyped* typedNode;
TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
@@ -1384,7 +1325,7 @@ TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, T
// to the function could either be a symbol node (a[0] where a is a constant array)that represents a
// constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure)
//
-TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line)
+TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line)
{
TIntermTyped* typedNode;
TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
@@ -1400,9 +1341,8 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS
index = 0;
}
- int arrayElementSize = arrayElementType.getObjectSize();
-
if (tempConstantNode) {
+ size_t arrayElementSize = arrayElementType.getObjectSize();
ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line);
} else {
@@ -1421,22 +1361,21 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS
// If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
// function and returns the parse-tree with the values of the embedded/nested struct.
//
-TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, TSourceLoc line)
+TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, const TSourceLoc& line)
{
- const TTypeList* fields = node->getType().getStruct();
- TIntermTyped *typedNode;
- int instanceSize = 0;
- unsigned int index = 0;
- TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
-
- for ( index = 0; index < fields->size(); ++index) {
- if ((*fields)[index].type->getFieldName() == identifier) {
+ const TFieldList& fields = node->getType().getStruct()->fields();
+
+ size_t instanceSize = 0;
+ for (size_t index = 0; index < fields.size(); ++index) {
+ if (fields[index]->name() == identifier) {
break;
} else {
- instanceSize += (*fields)[index].type->getObjectSize();
+ instanceSize += fields[index]->type()->getObjectSize();
}
}
+ TIntermTyped* typedNode = 0;
+ TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
if (tempConstantNode) {
ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer();
@@ -1451,7 +1390,7 @@ TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* n
return typedNode;
}
-bool TParseContext::enterStructDeclaration(int line, const TString& identifier)
+bool TParseContext::enterStructDeclaration(const TSourceLoc& line, const TString& identifier)
{
++structNestingLevel;
@@ -1477,24 +1416,26 @@ const int kWebGLMaxStructNesting = 4;
} // namespace
-bool TParseContext::structNestingErrorCheck(TSourceLoc line, const TType& fieldType)
+bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TField& field)
{
if (!isWebGLBasedSpec(shaderSpec)) {
return false;
}
- if (fieldType.getBasicType() != EbtStruct) {
+ if (field.type()->getBasicType() != EbtStruct) {
return false;
}
// We're already inside a structure definition at this point, so add
// one to the field's struct nesting.
- if (1 + fieldType.getDeepestStructNesting() > kWebGLMaxStructNesting) {
- std::stringstream extraInfoStream;
- extraInfoStream << "Reference of struct type " << fieldType.getTypeName()
- << " exceeds maximum struct nesting of " << kWebGLMaxStructNesting;
- std::string extraInfo = extraInfoStream.str();
- error(line, "", "", extraInfo.c_str());
+ if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) {
+ std::stringstream reasonStream;
+ reasonStream << "Reference of struct type "
+ << field.type()->getStruct()->name().c_str()
+ << " exceeds maximum allowed nesting level of "
+ << kWebGLMaxStructNesting;
+ std::string reason = reasonStream.str();
+ error(line, reason.c_str(), field.name().c_str(), "");
return true;
}
@@ -1502,6 +1443,140 @@ bool TParseContext::structNestingErrorCheck(TSourceLoc line, const TType& fieldT
}
//
+// Parse an array index expression
+//
+TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression)
+{
+ TIntermTyped *indexedExpression = NULL;
+
+ if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
+ {
+ if (baseExpression->getAsSymbolNode())
+ {
+ error(location, " left of '[' is not of type array, matrix, or vector ", baseExpression->getAsSymbolNode()->getSymbol().c_str());
+ }
+ else
+ {
+ error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
+ }
+ recover();
+ }
+
+ if (indexExpression->getQualifier() == EvqConst)
+ {
+ int index = indexExpression->getAsConstantUnion()->getIConst(0);
+ if (index < 0)
+ {
+ std::stringstream infoStream;
+ infoStream << index;
+ std::string info = infoStream.str();
+ error(location, "negative index", info.c_str());
+ recover();
+ index = 0;
+ }
+ if (baseExpression->getType().getQualifier() == EvqConst)
+ {
+ if (baseExpression->isArray())
+ {
+ // constant folding for arrays
+ indexedExpression = addConstArrayNode(index, baseExpression, location);
+ }
+ else if (baseExpression->isVector())
+ {
+ // constant folding for vectors
+ TVectorFields fields;
+ fields.num = 1;
+ fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array
+ indexedExpression = addConstVectorNode(fields, baseExpression, location);
+ }
+ else if (baseExpression->isMatrix())
+ {
+ // constant folding for matrices
+ indexedExpression = addConstMatrixNode(index, baseExpression, location);
+ }
+ }
+ else
+ {
+ if (baseExpression->isArray())
+ {
+ if (index >= baseExpression->getType().getArraySize())
+ {
+ std::stringstream extraInfoStream;
+ extraInfoStream << "array index out of range '" << index << "'";
+ std::string extraInfo = extraInfoStream.str();
+ error(location, "", "[", extraInfo.c_str());
+ recover();
+ index = baseExpression->getType().getArraySize() - 1;
+ }
+ else if (baseExpression->getQualifier() == EvqFragData && index > 0 && !isExtensionEnabled("GL_EXT_draw_buffers"))
+ {
+ error(location, "", "[", "array indexes for gl_FragData must be zero when GL_EXT_draw_buffers is disabled");
+ recover();
+ index = 0;
+ }
+ }
+ else if ((baseExpression->isVector() || baseExpression->isMatrix()) && baseExpression->getType().getNominalSize() <= index)
+ {
+ std::stringstream extraInfoStream;
+ extraInfoStream << "field selection out of range '" << index << "'";
+ std::string extraInfo = extraInfoStream.str();
+ error(location, "", "[", extraInfo.c_str());
+ recover();
+ index = baseExpression->getType().getNominalSize() - 1;
+ }
+
+ indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index);
+ indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
+ }
+ }
+ else
+ {
+ indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
+ }
+
+ if (indexedExpression == 0)
+ {
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setFConst(0.0f);
+ indexedExpression = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location);
+ }
+ else if (baseExpression->isArray())
+ {
+ const TType &baseType = baseExpression->getType();
+ if (baseType.getStruct())
+ {
+ TType copyOfType(baseType.getStruct());
+ indexedExpression->setType(copyOfType);
+ }
+ else
+ {
+ indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize(), baseExpression->isMatrix()));
+ }
+
+ if (baseExpression->getType().getQualifier() == EvqConst)
+ {
+ indexedExpression->getTypePointer()->setQualifier(EvqConst);
+ }
+ }
+ else if (baseExpression->isMatrix())
+ {
+ TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
+ indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier, baseExpression->getNominalSize()));
+ }
+ else if (baseExpression->isVector())
+ {
+ TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
+ indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier));
+ }
+ else
+ {
+ indexedExpression->setType(baseExpression->getType());
+ }
+
+ return indexedExpression;
+}
+
+//
// Parse an array of strings using yyparse.
//
// Returns 0 for success.
diff --git a/src/3rdparty/angle/src/compiler/ParseHelper.h b/src/3rdparty/angle/src/compiler/ParseHelper.h
index 26a3ea1308..c2b3c3f7ec 100644
--- a/src/3rdparty/angle/src/compiler/ParseHelper.h
+++ b/src/3rdparty/angle/src/compiler/ParseHelper.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -33,10 +33,8 @@ struct TParseContext {
compileOptions(options),
sourcePath(sourcePath),
treeRoot(0),
- lexAfterType(false),
loopNestingLevel(0),
structNestingLevel(0),
- inTypeParen(false),
currentFunctionType(NULL),
functionReturnsValue(false),
checksPrecisionErrors(checksPrecErrors),
@@ -51,16 +49,13 @@ struct TParseContext {
int compileOptions;
const char* sourcePath; // Path of source file or NULL.
TIntermNode* treeRoot; // root of parse tree being created
- bool lexAfterType; // true if we've recognized a type, so can only be looking for an identifier
int loopNestingLevel; // 0 if outside all loops
int structNestingLevel; // incremented while parsing a struct declaration
- bool inTypeParen; // true if in parentheses, looking only for an identifier
const TType* currentFunctionType; // the return type of the function that's currently being parsed
bool functionReturnsValue; // true if a non-void function has a return
bool checksPrecisionErrors; // true if an error will be generated when a variable is declared without precision, explicit or implicit.
bool fragmentPrecisionHigh; // true if highp precision is supported in the fragment language.
TString HashErrMsg;
- bool AfterEOF;
TDiagnostics diagnostics;
TDirectiveHandler directiveHandler;
pp::Preprocessor preprocessor;
@@ -68,71 +63,69 @@ struct TParseContext {
int numErrors() const { return diagnostics.numErrors(); }
TInfoSink& infoSink() { return diagnostics.infoSink(); }
- void error(TSourceLoc loc, const char *reason, const char* token,
+ void error(const TSourceLoc& loc, const char *reason, const char* token,
const char* extraInfo="");
- void warning(TSourceLoc loc, const char* reason, const char* token,
+ void warning(const TSourceLoc& loc, const char* reason, const char* token,
const char* extraInfo="");
void trace(const char* str);
void recover();
- bool parseVectorFields(const TString&, int vecSize, TVectorFields&, int line);
- bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, int line);
+ bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc& line);
+ bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, const TSourceLoc& line);
- bool reservedErrorCheck(int line, const TString& identifier);
- void assignError(int line, const char* op, TString left, TString right);
- void unaryOpError(int line, const char* op, TString operand);
- void binaryOpError(int line, const char* op, TString left, TString right);
- bool precisionErrorCheck(int line, TPrecision precision, TBasicType type);
- bool lValueErrorCheck(int line, const char* op, TIntermTyped*);
+ bool reservedErrorCheck(const TSourceLoc& line, const TString& identifier);
+ void assignError(const TSourceLoc& line, const char* op, TString left, TString right);
+ void unaryOpError(const TSourceLoc& line, const char* op, TString operand);
+ void binaryOpError(const TSourceLoc& line, const char* op, TString left, TString right);
+ bool precisionErrorCheck(const TSourceLoc& line, TPrecision precision, TBasicType type);
+ bool lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped*);
bool constErrorCheck(TIntermTyped* node);
bool integerErrorCheck(TIntermTyped* node, const char* token);
- bool globalErrorCheck(int line, bool global, const char* token);
- bool constructorErrorCheck(int line, TIntermNode*, TFunction&, TOperator, TType*);
- bool arraySizeErrorCheck(int line, TIntermTyped* expr, int& size);
- bool arrayQualifierErrorCheck(int line, TPublicType type);
- bool arrayTypeErrorCheck(int line, TPublicType type);
- bool arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable);
- bool voidErrorCheck(int, const TString&, const TPublicType&);
- bool boolErrorCheck(int, const TIntermTyped*);
- bool boolErrorCheck(int, const TPublicType&);
- bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason);
- bool structQualifierErrorCheck(int line, const TPublicType& pType);
- bool parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type);
- bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array);
- bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable);
- bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
- bool extensionErrorCheck(int line, const TString&);
+ bool globalErrorCheck(const TSourceLoc& line, bool global, const char* token);
+ bool constructorErrorCheck(const TSourceLoc& line, TIntermNode*, TFunction&, TOperator, TType*);
+ bool arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size);
+ bool arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type);
+ bool arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type);
+ bool arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable);
+ bool voidErrorCheck(const TSourceLoc&, const TString&, const TPublicType&);
+ bool boolErrorCheck(const TSourceLoc&, const TIntermTyped*);
+ bool boolErrorCheck(const TSourceLoc&, const TPublicType&);
+ bool samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason);
+ bool structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType);
+ bool parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type);
+ bool nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array);
+ bool nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable);
+ bool paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
+ bool extensionErrorCheck(const TSourceLoc& line, const TString&);
+ const TPragma& pragma() const { return directiveHandler.pragma(); }
const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); }
bool supportsExtension(const char* extension);
- void handleExtensionDirective(int line, const char* extName, const char* behavior);
-
- const TPragma& pragma() const { return directiveHandler.pragma(); }
- void handlePragmaDirective(int line, const char* name, const char* value);
+ bool isExtensionEnabled(const char* extension) const;
bool containsSampler(TType& type);
bool areAllChildConst(TIntermAggregate* aggrNode);
- const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0);
- bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
+ const TFunction* findFunction(const TSourceLoc& line, TFunction* pfnCall, bool *builtIn = 0);
+ bool executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType,
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
- bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc);
- TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, TSourceLoc);
+ TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, const TSourceLoc&);
TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type);
- TIntermTyped* constructStruct(TIntermNode*, TType*, int, TSourceLoc, bool subset);
- TIntermTyped* constructBuiltIn(const TType*, TOperator, TIntermNode*, TSourceLoc, bool subset);
- TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, TSourceLoc);
- TIntermTyped* addConstMatrixNode(int , TIntermTyped*, TSourceLoc);
- TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line);
- TIntermTyped* addConstStruct(TString& , TIntermTyped*, TSourceLoc);
+ TIntermTyped* constructStruct(TIntermNode*, TType*, int, const TSourceLoc&, bool subset);
+ TIntermTyped* constructBuiltIn(const TType*, TOperator, TIntermNode*, const TSourceLoc&, bool subset);
+ TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, const TSourceLoc&);
+ TIntermTyped* addConstMatrixNode(int , TIntermTyped*, const TSourceLoc&);
+ TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line);
+ TIntermTyped* addConstStruct(TString& , TIntermTyped*, const TSourceLoc&);
+ TIntermTyped* addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression);
// Performs an error check for embedded struct declarations.
// Returns true if an error was raised due to the declaration of
// this struct.
- bool enterStructDeclaration(TSourceLoc line, const TString& identifier);
+ bool enterStructDeclaration(const TSourceLoc& line, const TString& identifier);
void exitStructDeclaration();
- bool structNestingErrorCheck(TSourceLoc line, const TType& fieldType);
+ bool structNestingErrorCheck(const TSourceLoc& line, const TField& field);
};
int PaParseStrings(size_t count, const char* const string[], const int length[],
diff --git a/src/3rdparty/angle/src/compiler/PoolAlloc.cpp b/src/3rdparty/angle/src/compiler/PoolAlloc.cpp
index 9ef4f59f5c..eb993567b3 100644
--- a/src/3rdparty/angle/src/compiler/PoolAlloc.cpp
+++ b/src/3rdparty/angle/src/compiler/PoolAlloc.cpp
@@ -17,55 +17,32 @@
OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX;
-void InitializeGlobalPools()
-{
- TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
- if (globalPools)
- return;
-
- TThreadGlobalPools* threadData = new TThreadGlobalPools();
- threadData->globalPoolAllocator = 0;
-
- OS_SetTLSValue(PoolIndex, threadData);
-}
-
-void FreeGlobalPools()
-{
- // Release the allocated memory for this thread.
- TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
- if (!globalPools)
- return;
-
- delete globalPools;
-}
-
bool InitializePoolIndex()
{
- // Allocate a TLS index.
- if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX)
- return false;
+ assert(PoolIndex == OS_INVALID_TLS_INDEX);
- return true;
+ PoolIndex = OS_AllocTLSIndex();
+ return PoolIndex != OS_INVALID_TLS_INDEX;
}
void FreePoolIndex()
{
- // Release the TLS index.
+ assert(PoolIndex != OS_INVALID_TLS_INDEX);
+
OS_FreeTLSIndex(PoolIndex);
+ PoolIndex = OS_INVALID_TLS_INDEX;
}
-TPoolAllocator& GetGlobalPoolAllocator()
+TPoolAllocator* GetGlobalPoolAllocator()
{
- TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
-
- return *threadData->globalPoolAllocator;
+ assert(PoolIndex != OS_INVALID_TLS_INDEX);
+ return static_cast<TPoolAllocator*>(OS_GetTLSValue(PoolIndex));
}
void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator)
{
- TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
-
- threadData->globalPoolAllocator = poolAllocator;
+ assert(PoolIndex != OS_INVALID_TLS_INDEX);
+ OS_SetTLSValue(PoolIndex, poolAllocator);
}
//
@@ -228,24 +205,27 @@ void TPoolAllocator::popAll()
void* TPoolAllocator::allocate(size_t numBytes)
{
+ //
+ // Just keep some interesting statistics.
+ //
+ ++numCalls;
+ totalBytes += numBytes;
+
// If we are using guard blocks, all allocations are bracketed by
// them: [guardblock][allocation][guardblock]. numBytes is how
// much memory the caller asked for. allocationSize is the total
// size including guard blocks. In release build,
// guardBlockSize=0 and this all gets optimized away.
size_t allocationSize = TAllocation::allocationSize(numBytes);
-
- //
- // Just keep some interesting statistics.
- //
- ++numCalls;
- totalBytes += numBytes;
+ // Detect integer overflow.
+ if (allocationSize < numBytes)
+ return 0;
//
// Do the allocation, most likely case first, for efficiency.
// This step could be moved to be inline sometime.
//
- if (currentPageOffset + allocationSize <= pageSize) {
+ if (allocationSize <= pageSize - currentPageOffset) {
//
// Safe to allocate from currentPageOffset.
//
@@ -256,12 +236,16 @@ void* TPoolAllocator::allocate(size_t numBytes)
return initializeAllocation(inUseList, memory, numBytes);
}
- if (allocationSize + headerSkip > pageSize) {
+ if (allocationSize > pageSize - headerSkip) {
//
// Do a multi-page allocation. Don't mix these with the others.
// The OS is efficient and allocating and free-ing multiple pages.
//
size_t numBytesToAlloc = allocationSize + headerSkip;
+ // Detect integer overflow.
+ if (numBytesToAlloc < allocationSize)
+ return 0;
+
tHeader* memory = reinterpret_cast<tHeader*>(::new char[numBytesToAlloc]);
if (memory == 0)
return 0;
diff --git a/src/3rdparty/angle/src/compiler/PoolAlloc.h b/src/3rdparty/angle/src/compiler/PoolAlloc.h
index a8a59c69ac..edd249c4d3 100644
--- a/src/3rdparty/angle/src/compiler/PoolAlloc.h
+++ b/src/3rdparty/angle/src/compiler/PoolAlloc.h
@@ -219,14 +219,8 @@ private:
// different times. But a simple use is to have a global pop
// with everyone using the same global allocator.
//
-extern TPoolAllocator& GetGlobalPoolAllocator();
+extern TPoolAllocator* GetGlobalPoolAllocator();
extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator);
-#define GlobalPoolAllocator GetGlobalPoolAllocator()
-
-struct TThreadGlobalPools
-{
- TPoolAllocator* globalPoolAllocator;
-};
//
// This STL compatible allocator is intended to be used as the allocator
@@ -253,7 +247,7 @@ public:
pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) const { return &x; }
- pool_allocator() : allocator(&GlobalPoolAllocator) { }
+ pool_allocator() : allocator(GetGlobalPoolAllocator()) { }
pool_allocator(TPoolAllocator& a) : allocator(&a) { }
pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { }
diff --git a/src/3rdparty/angle/src/compiler/ShHandle.h b/src/3rdparty/angle/src/compiler/ShHandle.h
index 28049305e0..873580a99c 100644
--- a/src/3rdparty/angle/src/compiler/ShHandle.h
+++ b/src/3rdparty/angle/src/compiler/ShHandle.h
@@ -70,6 +70,7 @@ public:
TInfoSink& getInfoSink() { return infoSink; }
const TVariableInfoList& getAttribs() const { return attribs; }
const TVariableInfoList& getUniforms() const { return uniforms; }
+ const TVariableInfoList& getVaryings() const { return varyings; }
int getMappedNameMaxLength() const;
ShHashFunction64 getHashFunction() const { return hashFunction; }
@@ -83,15 +84,15 @@ protected:
bool InitBuiltInSymbolTable(const ShBuiltInResources& resources);
// Clears the results from the previous compilation.
void clearResults();
- // Return true if function recursion is detected.
- bool detectRecursion(TIntermNode* root);
+ // Return true if function recursion is detected or call depth exceeded.
+ bool detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth);
// Rewrites a shader's intermediate tree according to the CSS Shaders spec.
void rewriteCSSShader(TIntermNode* root);
// Returns true if the given shader does not exceed the minimum
// functionality mandated in GLSL 1.0 spec Appendix A.
bool validateLimitations(TIntermNode* root);
- // Collect info for all attribs and uniforms.
- void collectAttribsUniforms(TIntermNode* root);
+ // Collect info for all attribs, uniforms, varyings.
+ void collectVariables(TIntermNode* root);
// Map long variable names into shorter ones.
void mapLongVariableNames(TIntermNode* root);
// Translate to object code.
@@ -106,6 +107,8 @@ protected:
// Returns true if the shader does not use sampler dependent values to affect control
// flow or in operations whose time can depend on the input values.
bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph);
+ // Return true if the maximum expression complexity below the limit.
+ bool limitExpressionComplexity(TIntermNode* root);
// Get built-in extensions with default behavior.
const TExtensionBehavior& getExtensionBehavior() const;
// Get the resources set by InitBuiltInSymbolTable
@@ -120,6 +123,8 @@ private:
ShShaderSpec shaderSpec;
int maxUniformVectors;
+ int maxExpressionComplexity;
+ int maxCallStackDepth;
ShBuiltInResources compileResources;
@@ -138,6 +143,7 @@ private:
TInfoSink infoSink; // Output sink.
TVariableInfoList attribs; // Active attributes in the compiled shader.
TVariableInfoList uniforms; // Active uniforms in the compiled shader.
+ TVariableInfoList varyings; // Varyings in the compiled shader.
// Cached copy of the ref-counted singleton.
LongNameMap* longNameMap;
diff --git a/src/3rdparty/angle/src/compiler/ShaderLang.cpp b/src/3rdparty/angle/src/compiler/ShaderLang.cpp
index 92f39311c2..42cd5cc5c1 100644
--- a/src/3rdparty/angle/src/compiler/ShaderLang.cpp
+++ b/src/3rdparty/angle/src/compiler/ShaderLang.cpp
@@ -15,20 +15,25 @@
#include "compiler/preprocessor/length_limits.h"
#include "compiler/ShHandle.h"
#include "compiler/TranslatorHLSL.h"
+#include "compiler/VariablePacker.h"
//
// This is the platform independent interface between an OGL driver
// and the shading language compiler.
//
-static bool checkActiveUniformAndAttribMaxLengths(const ShHandle handle,
- size_t expectedValue)
+static bool checkVariableMaxLengths(const ShHandle handle,
+ size_t expectedValue)
{
size_t activeUniformLimit = 0;
ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit);
size_t activeAttribLimit = 0;
ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit);
- return (expectedValue == activeUniformLimit && expectedValue == activeAttribLimit);
+ size_t varyingLimit = 0;
+ ShGetInfo(handle, SH_VARYING_MAX_LENGTH, &varyingLimit);
+ return (expectedValue == activeUniformLimit &&
+ expectedValue == activeAttribLimit &&
+ expectedValue == varyingLimit);
}
static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue)
@@ -38,62 +43,14 @@ static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue
return (expectedValue == mappedNameMaxLength);
}
-static void getVariableInfo(ShShaderInfo varType,
- const ShHandle handle,
- int index,
- size_t* length,
- int* size,
- ShDataType* type,
- char* name,
- char* mappedName)
-{
- if (!handle || !size || !type || !name)
- return;
- ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
- (varType == SH_ACTIVE_UNIFORMS));
-
- TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
- TCompiler* compiler = base->getAsCompiler();
- if (compiler == 0)
- return;
-
- const TVariableInfoList& varList = varType == SH_ACTIVE_ATTRIBUTES ?
- compiler->getAttribs() : compiler->getUniforms();
- if (index < 0 || index >= static_cast<int>(varList.size()))
- return;
-
- const TVariableInfo& varInfo = varList[index];
- if (length) *length = varInfo.name.size();
- *size = varInfo.size;
- *type = varInfo.type;
-
- // This size must match that queried by
- // SH_ACTIVE_UNIFORM_MAX_LENGTH and SH_ACTIVE_ATTRIBUTE_MAX_LENGTH
- // in ShGetInfo, below.
- size_t activeUniformAndAttribLength = 1 + MAX_SYMBOL_NAME_LEN;
- ASSERT(checkActiveUniformAndAttribMaxLengths(handle, activeUniformAndAttribLength));
- strncpy(name, varInfo.name.c_str(), activeUniformAndAttribLength);
- name[activeUniformAndAttribLength - 1] = 0;
- if (mappedName) {
- // This size must match that queried by
- // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below.
- size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN;
- ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength));
- strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength);
- mappedName[maxMappedNameLength - 1] = 0;
- }
-}
-
//
-// Driver must call this first, once, before doing any other
-// compiler operations.
+// Driver must call this first, once, before doing any other compiler operations.
+// Subsequent calls to this function are no-op.
//
int ShInitialize()
{
- if (!InitProcess())
- return 0;
-
- return 1;
+ static const bool kInitialized = InitProcess();
+ return kInitialized ? 1 : 0;
}
//
@@ -101,9 +58,7 @@ int ShInitialize()
//
int ShFinalize()
{
- if (!DetachProcess())
- return 0;
-
+ DetachProcess();
return 1;
}
@@ -127,6 +82,7 @@ void ShInitBuiltInResources(ShBuiltInResources* resources)
resources->OES_EGL_image_external = 0;
resources->ARB_texture_rectangle = 0;
resources->EXT_draw_buffers = 0;
+ resources->EXT_frag_depth = 0;
// Disable highp precision in fragment shader by default.
resources->FragmentPrecisionHigh = 0;
@@ -144,9 +100,6 @@ ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec,
ShShaderOutput output,
const ShBuiltInResources* resources)
{
- if (!InitThread())
- return 0;
-
TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output));
TCompiler* compiler = base->getAsCompiler();
if (compiler == 0)
@@ -185,9 +138,6 @@ int ShCompile(
size_t numStrings,
int compileOptions)
{
- if (!InitThread())
- return 0;
-
if (handle == 0)
return 0;
@@ -229,6 +179,12 @@ void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params)
case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
*params = 1 + MAX_SYMBOL_NAME_LEN;
break;
+ case SH_VARYINGS:
+ *params = compiler->getVaryings().size();
+ break;
+ case SH_VARYING_MAX_LENGTH:
+ *params = 1 + MAX_SYMBOL_NAME_LEN;
+ break;
case SH_MAPPED_NAME_MAX_LENGTH:
// Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to
// handle array and struct dereferences.
@@ -286,28 +242,71 @@ void ShGetObjectCode(const ShHandle handle, char* objCode)
strcpy(objCode, infoSink.obj.c_str());
}
-void ShGetActiveAttrib(const ShHandle handle,
+void ShGetVariableInfo(const ShHandle handle,
+ ShShaderInfo varType,
int index,
size_t* length,
int* size,
ShDataType* type,
+ ShPrecisionType* precision,
+ int* staticUse,
char* name,
char* mappedName)
{
- getVariableInfo(SH_ACTIVE_ATTRIBUTES,
- handle, index, length, size, type, name, mappedName);
-}
+ if (!handle || !size || !type || !precision || !staticUse || !name)
+ return;
+ ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
+ (varType == SH_ACTIVE_UNIFORMS) ||
+ (varType == SH_VARYINGS));
-void ShGetActiveUniform(const ShHandle handle,
- int index,
- size_t* length,
- int* size,
- ShDataType* type,
- char* name,
- char* mappedName)
-{
- getVariableInfo(SH_ACTIVE_UNIFORMS,
- handle, index, length, size, type, name, mappedName);
+ TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+ TCompiler* compiler = base->getAsCompiler();
+ if (compiler == 0)
+ return;
+
+ const TVariableInfoList& varList =
+ varType == SH_ACTIVE_ATTRIBUTES ? compiler->getAttribs() :
+ (varType == SH_ACTIVE_UNIFORMS ? compiler->getUniforms() :
+ compiler->getVaryings());
+ if (index < 0 || index >= static_cast<int>(varList.size()))
+ return;
+
+ const TVariableInfo& varInfo = varList[index];
+ if (length) *length = varInfo.name.size();
+ *size = varInfo.size;
+ *type = varInfo.type;
+ switch (varInfo.precision) {
+ case EbpLow:
+ *precision = SH_PRECISION_LOWP;
+ break;
+ case EbpMedium:
+ *precision = SH_PRECISION_MEDIUMP;
+ break;
+ case EbpHigh:
+ *precision = SH_PRECISION_HIGHP;
+ break;
+ default:
+ // Some types does not support precision, for example, boolean.
+ *precision = SH_PRECISION_UNDEFINED;
+ break;
+ }
+ *staticUse = varInfo.staticUse ? 1 : 0;
+
+ // This size must match that queried by
+ // SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH
+ // in ShGetInfo, below.
+ size_t variableLength = 1 + MAX_SYMBOL_NAME_LEN;
+ ASSERT(checkVariableMaxLengths(handle, variableLength));
+ strncpy(name, varInfo.name.c_str(), variableLength);
+ name[variableLength - 1] = 0;
+ if (mappedName) {
+ // This size must match that queried by
+ // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below.
+ size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN;
+ ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength));
+ strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength);
+ mappedName[maxMappedNameLength - 1] = 0;
+ }
}
void ShGetNameHashingEntry(const ShHandle handle,
@@ -370,3 +369,19 @@ void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params)
default: UNREACHABLE();
}
}
+
+int ShCheckVariablesWithinPackingLimits(
+ int maxVectors, ShVariableInfo* varInfoArray, size_t varInfoArraySize)
+{
+ if (varInfoArraySize == 0)
+ return 1;
+ ASSERT(varInfoArray);
+ TVariableInfoList variables;
+ for (size_t ii = 0; ii < varInfoArraySize; ++ii)
+ {
+ TVariableInfo var(varInfoArray[ii].type, varInfoArray[ii].size);
+ variables.push_back(var);
+ }
+ VariablePacker packer;
+ return packer.CheckVariablesWithinPackingLimits(maxVectors, variables) ? 1 : 0;
+}
diff --git a/src/3rdparty/angle/src/compiler/SymbolTable.cpp b/src/3rdparty/angle/src/compiler/SymbolTable.cpp
index 847c1e4085..a7ce21680f 100644
--- a/src/3rdparty/angle/src/compiler/SymbolTable.cpp
+++ b/src/3rdparty/angle/src/compiler/SymbolTable.cpp
@@ -17,48 +17,34 @@
#include <stdio.h>
#include <algorithm>
-
-#include "common/angleutils.h"
+#include <climits>
TType::TType(const TPublicType &p) :
- type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize),
- maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
+ type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize), structure(0)
{
- if (p.userDef) {
+ if (p.userDef)
structure = p.userDef->getStruct();
- typeName = NewPoolTString(p.userDef->getTypeName().c_str());
- computeDeepestStructNesting();
- }
}
//
// Recursively generate mangled names.
//
-void TType::buildMangledName(TString& mangledName)
+TString TType::buildMangledName() const
{
+ TString mangledName;
if (isMatrix())
mangledName += 'm';
else if (isVector())
mangledName += 'v';
switch (type) {
- case EbtFloat: mangledName += 'f'; break;
- case EbtInt: mangledName += 'i'; break;
- case EbtBool: mangledName += 'b'; break;
- case EbtSampler2D: mangledName += "s2"; break;
- case EbtSamplerCube: mangledName += "sC"; break;
- case EbtStruct:
- mangledName += "struct-";
- if (typeName)
- mangledName += *typeName;
- {// support MSVC++6.0
- for (unsigned int i = 0; i < structure->size(); ++i) {
- mangledName += '-';
- (*structure)[i].type->buildMangledName(mangledName);
- }
- }
- default:
- break;
+ case EbtFloat: mangledName += 'f'; break;
+ case EbtInt: mangledName += 'i'; break;
+ case EbtBool: mangledName += 'b'; break;
+ case EbtSampler2D: mangledName += "s2"; break;
+ case EbtSamplerCube: mangledName += "sC"; break;
+ case EbtStruct: mangledName += structure->mangledName(); break;
+ default: break;
}
mangledName += static_cast<char>('0' + getNominalSize());
@@ -69,53 +55,72 @@ void TType::buildMangledName(TString& mangledName)
mangledName += buf;
mangledName += ']';
}
+ return mangledName;
}
-int TType::getStructSize() const
+size_t TType::getObjectSize() const
{
- if (!getStruct()) {
- assert(false && "Not a struct");
- return 0;
- }
+ size_t totalSize = 0;
- if (structureSize == 0)
- for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++)
- structureSize += ((*tl).type)->getObjectSize();
+ if (getBasicType() == EbtStruct)
+ totalSize = structure->objectSize();
+ else if (matrix)
+ totalSize = size * size;
+ else
+ totalSize = size;
+
+ if (isArray()) {
+ size_t arraySize = getArraySize();
+ if (arraySize > INT_MAX / totalSize)
+ totalSize = INT_MAX;
+ else
+ totalSize *= arraySize;
+ }
- return structureSize;
+ return totalSize;
}
-void TType::computeDeepestStructNesting()
+bool TStructure::containsArrays() const
{
- if (!getStruct()) {
- return;
+ for (size_t i = 0; i < mFields->size(); ++i) {
+ const TType* fieldType = (*mFields)[i]->type();
+ if (fieldType->isArray() || fieldType->isStructureContainingArrays())
+ return true;
}
+ return false;
+}
- int maxNesting = 0;
- for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); ++tl) {
- maxNesting = std::max(maxNesting, ((*tl).type)->getDeepestStructNesting());
+TString TStructure::buildMangledName() const
+{
+ TString mangledName("struct-");
+ mangledName += *mName;
+ for (size_t i = 0; i < mFields->size(); ++i) {
+ mangledName += '-';
+ mangledName += (*mFields)[i]->type()->getMangledName();
}
-
- deepestStructNesting = 1 + maxNesting;
+ return mangledName;
}
-bool TType::isStructureContainingArrays() const
+size_t TStructure::calculateObjectSize() const
{
- if (!structure)
- {
- return false;
+ size_t size = 0;
+ for (size_t i = 0; i < mFields->size(); ++i) {
+ size_t fieldSize = (*mFields)[i]->type()->getObjectSize();
+ if (fieldSize > INT_MAX - size)
+ size = INT_MAX;
+ else
+ size += fieldSize;
}
+ return size;
+}
- for (TTypeList::const_iterator member = structure->begin(); member != structure->end(); member++)
- {
- if (member->type->isArray() ||
- member->type->isStructureContainingArrays())
- {
- return true;
- }
+int TStructure::calculateDeepestNesting() const
+{
+ int maxNesting = 0;
+ for (size_t i = 0; i < mFields->size(); ++i) {
+ maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting());
}
-
- return false;
+ return 1 + maxNesting;
}
//
@@ -196,84 +201,16 @@ void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext)
{
for (tLevel::iterator it = level.begin(); it != level.end(); ++it) {
- if (it->second->isFunction()) {
- TFunction* function = static_cast<TFunction*>(it->second);
- if (function->getName() == name)
- function->relateToExtension(ext);
- }
+ TSymbol* symbol = it->second;
+ if (symbol->getName() == name)
+ symbol->relateToExtension(ext);
}
}
-TSymbol::TSymbol(const TSymbol& copyOf)
-{
- name = NewPoolTString(copyOf.name->c_str());
- uniqueId = copyOf.uniqueId;
-}
-
-TVariable::TVariable(const TVariable& copyOf, TStructureMap& remapper) : TSymbol(copyOf)
+TSymbolTable::~TSymbolTable()
{
- type.copyType(copyOf.type, remapper);
- userType = copyOf.userType;
- // for builtIn symbol table level, unionArray and arrayInformation pointers should be NULL
- assert(copyOf.arrayInformationType == 0);
- arrayInformationType = 0;
-
- if (copyOf.unionArray) {
- assert(!copyOf.type.getStruct());
- assert(copyOf.type.getObjectSize() == 1);
- unionArray = new ConstantUnion[1];
- unionArray[0] = copyOf.unionArray[0];
- } else
- unionArray = 0;
-}
-
-TVariable* TVariable::clone(TStructureMap& remapper)
-{
- TVariable *variable = new TVariable(*this, remapper);
-
- return variable;
-}
-
-TFunction::TFunction(const TFunction& copyOf, TStructureMap& remapper) : TSymbol(copyOf)
-{
- for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) {
- TParameter param;
- parameters.push_back(param);
- parameters.back().copyParam(copyOf.parameters[i], remapper);
- }
-
- returnType.copyType(copyOf.returnType, remapper);
- mangledName = copyOf.mangledName;
- op = copyOf.op;
- defined = copyOf.defined;
-}
-
-TFunction* TFunction::clone(TStructureMap& remapper)
-{
- TFunction *function = new TFunction(*this, remapper);
-
- return function;
-}
-
-TSymbolTableLevel* TSymbolTableLevel::clone(TStructureMap& remapper)
-{
- TSymbolTableLevel *symTableLevel = new TSymbolTableLevel();
- tLevel::iterator iter;
- for (iter = level.begin(); iter != level.end(); ++iter) {
- symTableLevel->insert(*iter->second->clone(remapper));
- }
-
- return symTableLevel;
-}
-
-void TSymbolTable::copyTable(const TSymbolTable& copyOf)
-{
- TStructureMap remapper;
- uniqueId = copyOf.uniqueId;
- for (unsigned int i = 0; i < copyOf.table.size(); ++i) {
- table.push_back(copyOf.table[i]->clone(remapper));
- }
- for( unsigned int i = 0; i < copyOf.precisionStack.size(); i++) {
- precisionStack.push_back( copyOf.precisionStack[i] );
- }
+ for (size_t i = 0; i < table.size(); ++i)
+ delete table[i];
+ for (size_t i = 0; i < precisionStack.size(); ++i)
+ delete precisionStack[i];
}
diff --git a/src/3rdparty/angle/src/compiler/SymbolTable.h b/src/3rdparty/angle/src/compiler/SymbolTable.h
index d27aa332b7..bebad4b92e 100644
--- a/src/3rdparty/angle/src/compiler/SymbolTable.h
+++ b/src/3rdparty/angle/src/compiler/SymbolTable.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -32,6 +32,7 @@
#include <assert.h>
+#include "common/angleutils.h"
#include "compiler/InfoSink.h"
#include "compiler/intermediate.h"
@@ -40,22 +41,26 @@
//
class TSymbol {
public:
- POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
- TSymbol(const TString *n) : name(n) { }
+ POOL_ALLOCATOR_NEW_DELETE();
+ TSymbol(const TString* n) : uniqueId(0), name(n) { }
virtual ~TSymbol() { /* don't delete name, it's from the pool */ }
+
const TString& getName() const { return *name; }
virtual const TString& getMangledName() const { return getName(); }
virtual bool isFunction() const { return false; }
virtual bool isVariable() const { return false; }
void setUniqueId(int id) { uniqueId = id; }
int getUniqueId() const { return uniqueId; }
- virtual void dump(TInfoSink &infoSink) const = 0;
- TSymbol(const TSymbol&);
- virtual TSymbol* clone(TStructureMap& remapper) = 0;
+ virtual void dump(TInfoSink &infoSink) const = 0;
+ void relateToExtension(const TString& ext) { extension = ext; }
+ const TString& getExtension() const { return extension; }
-protected:
+private:
+ DISALLOW_COPY_AND_ASSIGN(TSymbol);
+
+ int uniqueId; // For real comparing during code generation
const TString *name;
- unsigned int uniqueId; // For real comparing during code generation
+ TString extension;
};
//
@@ -70,15 +75,13 @@ protected:
//
class TVariable : public TSymbol {
public:
- TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0), arrayInformationType(0) { }
+ TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0) { }
virtual ~TVariable() { }
virtual bool isVariable() const { return true; }
TType& getType() { return type; }
const TType& getType() const { return type; }
bool isUserType() const { return userType; }
void setQualifier(TQualifier qualifier) { type.setQualifier(qualifier); }
- void updateArrayInformationType(TType *t) { arrayInformationType = t; }
- TType* getArrayInformationType() { return arrayInformationType; }
virtual void dump(TInfoSink &infoSink) const;
@@ -100,16 +103,15 @@ public:
delete[] unionArray;
unionArray = constArray;
}
- TVariable(const TVariable&, TStructureMap& remapper); // copy constructor
- virtual TVariable* clone(TStructureMap& remapper);
-protected:
+private:
+ DISALLOW_COPY_AND_ASSIGN(TVariable);
+
TType type;
bool userType;
// we are assuming that Pool Allocator will free the memory allocated to unionArray
// when this object is destroyed
ConstantUnion *unionArray;
- TType *arrayInformationType; // this is used for updating maxArraySize in all the references to a given symbol
};
//
@@ -119,11 +121,6 @@ protected:
struct TParameter {
TString *name;
TType* type;
- void copyParam(const TParameter& param, TStructureMap& remapper)
- {
- name = NewPoolTString(param.name->c_str());
- type = param.type->clone(remapper);
- }
};
//
@@ -163,9 +160,6 @@ public:
void relateToOperator(TOperator o) { op = o; }
TOperator getBuiltInOp() const { return op; }
- void relateToExtension(const TString& ext) { extension = ext; }
- const TString& getExtension() const { return extension; }
-
void setDefined() { defined = true; }
bool isDefined() { return defined; }
@@ -173,16 +167,15 @@ public:
const TParameter& getParam(size_t i) const { return parameters[i]; }
virtual void dump(TInfoSink &infoSink) const;
- TFunction(const TFunction&, TStructureMap& remapper);
- virtual TFunction* clone(TStructureMap& remapper);
-protected:
+private:
+ DISALLOW_COPY_AND_ASSIGN(TFunction);
+
typedef TVector<TParameter> TParamList;
TParamList parameters;
TType returnType;
TString mangledName;
TOperator op;
- TString extension;
bool defined;
};
@@ -194,21 +187,24 @@ public:
typedef const tLevel::value_type tLevelPair;
typedef std::pair<tLevel::iterator, bool> tInsertResult;
- POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
TSymbolTableLevel() { }
~TSymbolTableLevel();
- bool insert(TSymbol& symbol)
+ bool insert(const TString &name, TSymbol &symbol)
{
//
// returning true means symbol was added to the table
//
- tInsertResult result;
- result = level.insert(tLevelPair(symbol.getMangledName(), &symbol));
+ tInsertResult result = level.insert(tLevelPair(name, &symbol));
return result.second;
}
+ bool insert(TSymbol &symbol)
+ {
+ return insert(symbol.getMangledName(), symbol);
+ }
+
TSymbol* find(const TString& name) const
{
tLevel::const_iterator it = level.find(name);
@@ -231,7 +227,6 @@ public:
void relateToOperator(const char* name, TOperator op);
void relateToExtension(const char* name, const TString& ext);
void dump(TInfoSink &infoSink) const;
- TSymbolTableLevel* clone(TStructureMap& remapper);
protected:
tLevel level;
@@ -247,13 +242,7 @@ public:
// that the symbol table has not been preloaded with built-ins.
//
}
-
- ~TSymbolTable()
- {
- // level 0 is always built In symbols, so we never pop that out
- while (table.size() > 1)
- pop();
- }
+ ~TSymbolTable();
//
// When the symbol table is initialized with the built-ins, there should
@@ -266,13 +255,15 @@ public:
void push()
{
table.push_back(new TSymbolTableLevel);
- precisionStack.push_back( PrecisionStackLevel() );
+ precisionStack.push_back(new PrecisionStackLevel);
}
void pop()
- {
- delete table[currentLevel()];
- table.pop_back();
+ {
+ delete table.back();
+ table.pop_back();
+
+ delete precisionStack.back();
precisionStack.pop_back();
}
@@ -282,6 +273,35 @@ public:
return table[currentLevel()]->insert(symbol);
}
+ bool insertConstInt(const char *name, int value)
+ {
+ TVariable *constant = new TVariable(NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1));
+ constant->getConstPointer()->setIConst(value);
+ return insert(*constant);
+ }
+
+ bool insertBuiltIn(TType *rvalue, const char *name, TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0)
+ {
+ TFunction *function = new TFunction(NewPoolTString(name), *rvalue);
+
+ TParameter param1 = {NULL, ptype1};
+ function->addParameter(param1);
+
+ if(ptype2)
+ {
+ TParameter param2 = {NULL, ptype2};
+ function->addParameter(param2);
+ }
+
+ if(ptype3)
+ {
+ TParameter param3 = {NULL, ptype3};
+ function->addParameter(param3);
+ }
+
+ return insert(*function);
+ }
+
TSymbol* find(const TString& name, bool* builtIn = 0, bool *sameScope = 0)
{
int level = currentLevel();
@@ -298,16 +318,11 @@ public:
return symbol;
}
- TSymbol *findBuiltIn(const TString &name)
+ TSymbol* findBuiltIn(const TString &name)
{
return table[0]->find(name);
}
- TSymbolTableLevel* getGlobalLevel() {
- assert(table.size() >= 2);
- return table[1];
- }
-
TSymbolTableLevel* getOuterLevel() {
assert(table.size() >= 2);
return table[currentLevel() - 1];
@@ -319,32 +334,29 @@ public:
void relateToExtension(const char* name, const TString& ext) {
table[0]->relateToExtension(name, ext);
}
- int getMaxSymbolId() { return uniqueId; }
void dump(TInfoSink &infoSink) const;
- void copyTable(const TSymbolTable& copyOf);
- bool setDefaultPrecision( const TPublicType& type, TPrecision prec ){
- if (IsSampler(type.type))
- return true; // Skip sampler types for the time being
- if (type.type != EbtFloat && type.type != EbtInt)
- return false; // Only set default precision for int/float
+ bool setDefaultPrecision(const TPublicType& type, TPrecision prec) {
+ if (!supportsPrecision(type.type))
+ return false;
if (type.size != 1 || type.matrix || type.array)
return false; // Not allowed to set for aggregate types
int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
- precisionStack[indexOfLastElement][type.type] = prec; // Uses map operator [], overwrites the current value
+ (*precisionStack[indexOfLastElement])[type.type] = prec; // Uses map operator [], overwrites the current value
return true;
}
// Searches down the precisionStack for a precision qualifier for the specified TBasicType
- TPrecision getDefaultPrecision( TBasicType type){
- if( type != EbtFloat && type != EbtInt ) return EbpUndefined;
+ TPrecision getDefaultPrecision(TBasicType type) {
+ if (!supportsPrecision(type))
+ return EbpUndefined;
int level = static_cast<int>(precisionStack.size()) - 1;
- assert( level >= 0); // Just to be safe. Should not happen.
+ assert(level >= 0); // Just to be safe. Should not happen.
PrecisionStackLevel::iterator it;
TPrecision prec = EbpUndefined; // If we dont find anything we return this. Should we error check this?
- while( level >= 0 ){
- it = precisionStack[level].find( type );
- if( it != precisionStack[level].end() ){
+ while (level >= 0) {
+ it = precisionStack[level]->find(type);
+ if (it != precisionStack[level]->end()) {
prec = (*it).second;
break;
}
@@ -353,13 +365,18 @@ public:
return prec;
}
-protected:
+private:
int currentLevel() const { return static_cast<int>(table.size()) - 1; }
- std::vector<TSymbolTableLevel*> table;
- typedef std::map< TBasicType, TPrecision > PrecisionStackLevel;
- std::vector< PrecisionStackLevel > precisionStack;
+ bool supportsPrecision(TBasicType type) {
+ // Only supports precision for int, float, and sampler types.
+ return type == EbtFloat || type == EbtInt || IsSampler(type);
+ }
+
int uniqueId; // for unique identification in code generation
+ std::vector<TSymbolTableLevel*> table;
+ typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
+ std::vector<PrecisionStackLevel*> precisionStack;
};
#endif // _SYMBOL_TABLE_INCLUDED_
diff --git a/src/3rdparty/angle/src/compiler/Types.h b/src/3rdparty/angle/src/compiler/Types.h
index 854bb44c07..505fa8e3bf 100644
--- a/src/3rdparty/angle/src/compiler/Types.h
+++ b/src/3rdparty/angle/src/compiler/Types.h
@@ -7,30 +7,85 @@
#ifndef _TYPES_INCLUDED
#define _TYPES_INCLUDED
+#include "common/angleutils.h"
+
#include "compiler/BaseTypes.h"
#include "compiler/Common.h"
#include "compiler/debug.h"
-class TType;
struct TPublicType;
+class TType;
-//
-// Need to have association of line numbers to types in a list for building structs.
-//
-struct TTypeLine {
- TType* type;
- int line;
+class TField
+{
+public:
+ POOL_ALLOCATOR_NEW_DELETE();
+ TField(TType* type, TString* name) : mType(type), mName(name) {}
+
+ // TODO(alokp): We should only return const type.
+ // Fix it by tweaking grammar.
+ TType* type() { return mType; }
+ const TType* type() const { return mType; }
+
+ const TString& name() const { return *mName; }
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(TField);
+ TType* mType;
+ TString* mName;
};
-typedef TVector<TTypeLine> TTypeList;
-inline TTypeList* NewPoolTTypeList()
+typedef TVector<TField*> TFieldList;
+inline TFieldList* NewPoolTFieldList()
{
- void* memory = GlobalPoolAllocator.allocate(sizeof(TTypeList));
- return new(memory) TTypeList;
+ void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList));
+ return new(memory) TFieldList;
}
-typedef TMap<TTypeList*, TTypeList*> TStructureMap;
-typedef TMap<TTypeList*, TTypeList*>::iterator TStructureMapIterator;
+class TStructure
+{
+public:
+ POOL_ALLOCATOR_NEW_DELETE();
+ TStructure(TString* name, TFieldList* fields)
+ : mName(name),
+ mFields(fields),
+ mObjectSize(0),
+ mDeepestNesting(0) {
+ }
+
+ const TString& name() const { return *mName; }
+ const TFieldList& fields() const { return *mFields; }
+
+ const TString& mangledName() const {
+ if (mMangledName.empty())
+ mMangledName = buildMangledName();
+ return mMangledName;
+ }
+ size_t objectSize() const {
+ if (mObjectSize == 0)
+ mObjectSize = calculateObjectSize();
+ return mObjectSize;
+ };
+ int deepestNesting() const {
+ if (mDeepestNesting == 0)
+ mDeepestNesting = calculateDeepestNesting();
+ return mDeepestNesting;
+ }
+ bool containsArrays() const;
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(TStructure);
+ TString buildMangledName() const;
+ size_t calculateObjectSize() const;
+ int calculateDeepestNesting() const;
+
+ TString* mName;
+ TFieldList* mFields;
+
+ mutable TString mMangledName;
+ mutable size_t mObjectSize;
+ mutable int mDeepestNesting;
+};
//
// Base class for things that have a type.
@@ -38,72 +93,16 @@ typedef TMap<TTypeList*, TTypeList*>::iterator TStructureMapIterator;
class TType
{
public:
- POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+ POOL_ALLOCATOR_NEW_DELETE();
TType() {}
TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) :
- type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0),
- maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
+ type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), structure(0)
{
}
explicit TType(const TPublicType &p);
- TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) :
- type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0),
- maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0)
- {
- typeName = NewPoolTString(n.c_str());
- }
-
- void copyType(const TType& copyOf, TStructureMap& remapper)
+ TType(TStructure* userDef, TPrecision p = EbpUndefined) :
+ type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), structure(userDef)
{
- type = copyOf.type;
- precision = copyOf.precision;
- qualifier = copyOf.qualifier;
- size = copyOf.size;
- matrix = copyOf.matrix;
- array = copyOf.array;
- arraySize = copyOf.arraySize;
-
- TStructureMapIterator iter;
- if (copyOf.structure) {
- if ((iter = remapper.find(structure)) == remapper.end()) {
- // create the new structure here
- structure = NewPoolTTypeList();
- for (unsigned int i = 0; i < copyOf.structure->size(); ++i) {
- TTypeLine typeLine;
- typeLine.line = (*copyOf.structure)[i].line;
- typeLine.type = (*copyOf.structure)[i].type->clone(remapper);
- structure->push_back(typeLine);
- }
- } else {
- structure = iter->second;
- }
- } else
- structure = 0;
-
- fieldName = 0;
- if (copyOf.fieldName)
- fieldName = NewPoolTString(copyOf.fieldName->c_str());
- typeName = 0;
- if (copyOf.typeName)
- typeName = NewPoolTString(copyOf.typeName->c_str());
-
- mangled = 0;
- if (copyOf.mangled)
- mangled = NewPoolTString(copyOf.mangled->c_str());
-
- structureSize = copyOf.structureSize;
- maxArraySize = copyOf.maxArraySize;
- deepestStructNesting = copyOf.deepestStructNesting;
- assert(copyOf.arrayInformationType == 0);
- arrayInformationType = 0; // arrayInformationType should not be set for builtIn symbol table level
- }
-
- TType* clone(TStructureMap& remapper)
- {
- TType *newType = new TType();
- newType->copyType(*this, remapper);
-
- return newType;
}
TBasicType getBasicType() const { return type; }
@@ -119,34 +118,18 @@ public:
int getNominalSize() const { return size; }
void setNominalSize(int s) { size = s; }
// Full size of single instance of type
- int getObjectSize() const
- {
- int totalSize;
-
- if (getBasicType() == EbtStruct)
- totalSize = getStructSize();
- else if (matrix)
- totalSize = size * size;
- else
- totalSize = size;
-
- if (isArray())
- totalSize *= std::max(getArraySize(), getMaxArraySize());
-
- return totalSize;
- }
+ size_t getObjectSize() const;
int elementRegisterCount() const
{
- TTypeList *structure = getStruct();
-
if (structure)
{
+ const TFieldList &fields = getStruct()->fields();
int registerCount = 0;
- for (size_t i = 0; i < structure->size(); i++)
+ for (size_t i = 0; i < fields.size(); i++)
{
- registerCount += (*structure)[i].type->totalRegisterCount();
+ registerCount += fields[i]->type()->totalRegisterCount();
}
return registerCount;
@@ -179,47 +162,20 @@ public:
bool isArray() const { return array ? true : false; }
int getArraySize() const { return arraySize; }
void setArraySize(int s) { array = true; arraySize = s; }
- int getMaxArraySize () const { return maxArraySize; }
- void setMaxArraySize (int s) { maxArraySize = s; }
- void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; }
- void setArrayInformationType(TType* t) { arrayInformationType = t; }
- TType* getArrayInformationType() const { return arrayInformationType; }
+ void clearArrayness() { array = false; arraySize = 0; }
bool isVector() const { return size > 1 && !matrix; }
bool isScalar() const { return size == 1 && !matrix && !structure; }
- TTypeList* getStruct() const { return structure; }
- void setStruct(TTypeList* s) { structure = s; computeDeepestStructNesting(); }
-
- const TString& getTypeName() const
- {
- assert(typeName);
- return *typeName;
- }
- void setTypeName(const TString& n)
- {
- typeName = NewPoolTString(n.c_str());
- }
-
- bool isField() const { return fieldName != 0; }
- const TString& getFieldName() const
- {
- assert(fieldName);
- return *fieldName;
- }
- void setFieldName(const TString& n)
- {
- fieldName = NewPoolTString(n.c_str());
- }
+ TStructure* getStruct() const { return structure; }
+ void setStruct(TStructure* s) { structure = s; }
- TString& getMangledName() {
- if (!mangled) {
- mangled = NewPoolTString("");
- buildMangledName(*mangled);
- *mangled += ';' ;
+ const TString& getMangledName() const {
+ if (mangled.empty()) {
+ mangled = buildMangledName();
+ mangled += ';';
}
-
- return *mangled;
+ return mangled;
}
bool sameElementType(const TType& right) const {
@@ -267,14 +223,16 @@ public:
// For type "nesting2", this method would return 2 -- the number
// of structures through which indirection must occur to reach the
// deepest field (nesting2.field1.position).
- int getDeepestStructNesting() const { return deepestStructNesting; }
+ int getDeepestStructNesting() const {
+ return structure ? structure->deepestNesting() : 0;
+ }
- bool isStructureContainingArrays() const;
+ bool isStructureContainingArrays() const {
+ return structure ? structure->containsArrays() : false;
+ }
-protected:
- void buildMangledName(TString&);
- int getStructSize() const;
- void computeDeepestStructNesting();
+private:
+ TString buildMangledName() const;
TBasicType type : 6;
TPrecision precision;
@@ -283,16 +241,10 @@ protected:
unsigned int matrix : 1;
unsigned int array : 1;
int arraySize;
- int maxArraySize;
- TType* arrayInformationType;
- TTypeList* structure; // 0 unless this is a struct
- mutable int structureSize;
- int deepestStructNesting;
+ TStructure* structure; // 0 unless this is a struct
- TString *fieldName; // for structure field names
- TString *mangled;
- TString *typeName; // for structure field type name
+ mutable TString mangled;
};
//
@@ -314,9 +266,9 @@ struct TPublicType
bool array;
int arraySize;
TType* userDef;
- int line;
+ TSourceLoc line;
- void setBasic(TBasicType bt, TQualifier q, int ln = 0)
+ void setBasic(TBasicType bt, TQualifier q, const TSourceLoc& ln)
{
type = bt;
qualifier = q;
diff --git a/src/3rdparty/angle/src/compiler/ValidateLimitations.cpp b/src/3rdparty/angle/src/compiler/ValidateLimitations.cpp
index a5562d09a4..736ceeaefc 100644
--- a/src/3rdparty/angle/src/compiler/ValidateLimitations.cpp
+++ b/src/3rdparty/angle/src/compiler/ValidateLimitations.cpp
@@ -435,7 +435,7 @@ bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node)
return true;
bool valid = true;
- TSymbolTable& symbolTable = GlobalParseContext->symbolTable;
+ TSymbolTable& symbolTable = GetGlobalParseContext()->symbolTable;
TSymbol* symbol = symbolTable.find(node->getName());
ASSERT(symbol && symbol->isFunction());
TFunction* function = static_cast<TFunction*>(symbol);
diff --git a/src/3rdparty/angle/src/compiler/VariableInfo.cpp b/src/3rdparty/angle/src/compiler/VariableInfo.cpp
index eb6bea9b0f..f3f7b1ef35 100644
--- a/src/3rdparty/angle/src/compiler/VariableInfo.cpp
+++ b/src/3rdparty/angle/src/compiler/VariableInfo.cpp
@@ -6,15 +6,17 @@
#include "compiler/VariableInfo.h"
-static TString arrayBrackets(int index)
+namespace {
+
+TString arrayBrackets(int index)
{
TStringStream stream;
stream << "[" << index << "]";
return stream.str();
}
-// Returns the data type for an attribute or uniform.
-static ShDataType getVariableDataType(const TType& type)
+// Returns the data type for an attribute, uniform, or varying.
+ShDataType getVariableDataType(const TType& type)
{
switch (type.getBasicType()) {
case EbtFloat:
@@ -70,22 +72,22 @@ static ShDataType getVariableDataType(const TType& type)
return SH_NONE;
}
-static void getBuiltInVariableInfo(const TType& type,
- const TString& name,
- const TString& mappedName,
- TVariableInfoList& infoList);
-static void getUserDefinedVariableInfo(const TType& type,
- const TString& name,
- const TString& mappedName,
- TVariableInfoList& infoList,
- ShHashFunction64 hashFunction);
-
-// Returns info for an attribute or uniform.
-static void getVariableInfo(const TType& type,
+void getBuiltInVariableInfo(const TType& type,
const TString& name,
const TString& mappedName,
- TVariableInfoList& infoList,
- ShHashFunction64 hashFunction)
+ TVariableInfoList& infoList);
+void getUserDefinedVariableInfo(const TType& type,
+ const TString& name,
+ const TString& mappedName,
+ TVariableInfoList& infoList,
+ ShHashFunction64 hashFunction);
+
+// Returns info for an attribute, uniform, or varying.
+void getVariableInfo(const TType& type,
+ const TString& name,
+ const TString& mappedName,
+ TVariableInfoList& infoList,
+ ShHashFunction64 hashFunction)
{
if (type.getBasicType() == EbtStruct) {
if (type.isArray()) {
@@ -119,6 +121,7 @@ void getBuiltInVariableInfo(const TType& type,
varInfo.mappedName = mappedName.c_str();
varInfo.size = 1;
}
+ varInfo.precision = type.getPrecision();
varInfo.type = getVariableDataType(type);
infoList.push_back(varInfo);
}
@@ -131,86 +134,156 @@ void getUserDefinedVariableInfo(const TType& type,
{
ASSERT(type.getBasicType() == EbtStruct);
- const TTypeList* structure = type.getStruct();
- for (size_t i = 0; i < structure->size(); ++i) {
- const TType* fieldType = (*structure)[i].type;
- getVariableInfo(*fieldType,
- name + "." + fieldType->getFieldName(),
- mappedName + "." + TIntermTraverser::hash(fieldType->getFieldName(), hashFunction),
+ const TFieldList& fields = type.getStruct()->fields();
+ for (size_t i = 0; i < fields.size(); ++i) {
+ const TType& fieldType = *(fields[i]->type());
+ const TString& fieldName = fields[i]->name();
+ getVariableInfo(fieldType,
+ name + "." + fieldName,
+ mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction),
infoList,
hashFunction);
}
}
+TVariableInfo* findVariable(const TType& type,
+ const TString& name,
+ TVariableInfoList& infoList)
+{
+ // TODO(zmo): optimize this function.
+ TString myName = name;
+ if (type.isArray())
+ myName += "[0]";
+ for (size_t ii = 0; ii < infoList.size(); ++ii)
+ {
+ if (infoList[ii].name.c_str() == myName)
+ return &(infoList[ii]);
+ }
+ return NULL;
+}
+
+} // namespace anonymous
+
TVariableInfo::TVariableInfo()
+ : type(SH_NONE),
+ size(0),
+ precision(EbpUndefined),
+ staticUse(false)
{
}
TVariableInfo::TVariableInfo(ShDataType type, int size)
: type(type),
- size(size)
+ size(size),
+ precision(EbpUndefined),
+ staticUse(false)
{
}
-CollectAttribsUniforms::CollectAttribsUniforms(TVariableInfoList& attribs,
- TVariableInfoList& uniforms,
- ShHashFunction64 hashFunction)
+CollectVariables::CollectVariables(TVariableInfoList& attribs,
+ TVariableInfoList& uniforms,
+ TVariableInfoList& varyings,
+ ShHashFunction64 hashFunction)
: mAttribs(attribs),
mUniforms(uniforms),
+ mVaryings(varyings),
+ mPointCoordAdded(false),
+ mFrontFacingAdded(false),
+ mFragCoordAdded(false),
mHashFunction(hashFunction)
{
}
-// We are only interested in attribute and uniform variable declaration.
-void CollectAttribsUniforms::visitSymbol(TIntermSymbol*)
-{
-}
-
-void CollectAttribsUniforms::visitConstantUnion(TIntermConstantUnion*)
-{
-}
-
-bool CollectAttribsUniforms::visitBinary(Visit, TIntermBinary*)
+// We want to check whether a uniform/varying is statically used
+// because we only count the used ones in packing computing.
+// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
+// toward varying counting if they are statically used in a fragment
+// shader.
+void CollectVariables::visitSymbol(TIntermSymbol* symbol)
{
- return false;
-}
-
-bool CollectAttribsUniforms::visitUnary(Visit, TIntermUnary*)
-{
- return false;
-}
-
-bool CollectAttribsUniforms::visitSelection(Visit, TIntermSelection*)
-{
- return false;
+ ASSERT(symbol != NULL);
+ TVariableInfo* var = NULL;
+ switch (symbol->getQualifier())
+ {
+ case EvqVaryingOut:
+ case EvqInvariantVaryingOut:
+ case EvqVaryingIn:
+ case EvqInvariantVaryingIn:
+ var = findVariable(symbol->getType(), symbol->getSymbol(), mVaryings);
+ break;
+ case EvqUniform:
+ var = findVariable(symbol->getType(), symbol->getSymbol(), mUniforms);
+ break;
+ case EvqFragCoord:
+ if (!mFragCoordAdded) {
+ TVariableInfo info;
+ info.name = "gl_FragCoord";
+ info.mappedName = "gl_FragCoord";
+ info.type = SH_FLOAT_VEC4;
+ info.size = 1;
+ info.precision = EbpMedium; // Use mediump as it doesn't really matter.
+ info.staticUse = true;
+ mVaryings.push_back(info);
+ mFragCoordAdded = true;
+ }
+ return;
+ case EvqFrontFacing:
+ if (!mFrontFacingAdded) {
+ TVariableInfo info;
+ info.name = "gl_FrontFacing";
+ info.mappedName = "gl_FrontFacing";
+ info.type = SH_BOOL;
+ info.size = 1;
+ info.precision = EbpUndefined;
+ info.staticUse = true;
+ mVaryings.push_back(info);
+ mFrontFacingAdded = true;
+ }
+ return;
+ case EvqPointCoord:
+ if (!mPointCoordAdded) {
+ TVariableInfo info;
+ info.name = "gl_PointCoord";
+ info.mappedName = "gl_PointCoord";
+ info.type = SH_FLOAT_VEC2;
+ info.size = 1;
+ info.precision = EbpMedium; // Use mediump as it doesn't really matter.
+ info.staticUse = true;
+ mVaryings.push_back(info);
+ mPointCoordAdded = true;
+ }
+ return;
+ default:
+ break;
+ }
+ if (var)
+ var->staticUse = true;
}
-bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node)
+bool CollectVariables::visitAggregate(Visit, TIntermAggregate* node)
{
- bool visitChildren = false;
+ bool visitChildren = true;
switch (node->getOp())
{
- case EOpSequence:
- // We need to visit sequence children to get to variable declarations.
- visitChildren = true;
- break;
case EOpDeclaration: {
const TIntermSequence& sequence = node->getSequence();
TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
- if (qualifier == EvqAttribute || qualifier == EvqUniform)
+ if (qualifier == EvqAttribute || qualifier == EvqUniform ||
+ qualifier == EvqVaryingIn || qualifier == EvqVaryingOut ||
+ qualifier == EvqInvariantVaryingIn || qualifier == EvqInvariantVaryingOut)
{
- TVariableInfoList& infoList = qualifier == EvqAttribute ?
- mAttribs : mUniforms;
+ TVariableInfoList& infoList = qualifier == EvqAttribute ? mAttribs :
+ (qualifier == EvqUniform ? mUniforms : mVaryings);
for (TIntermSequence::const_iterator i = sequence.begin();
i != sequence.end(); ++i)
{
const TIntermSymbol* variable = (*i)->getAsSymbolNode();
// The only case in which the sequence will not contain a
// TIntermSymbol node is initialization. It will contain a
- // TInterBinary node in that case. Since attributes and unifroms
- // cannot be initialized in a shader, we must have only
- // TIntermSymbol nodes in the sequence.
+ // TInterBinary node in that case. Since attributes, uniforms,
+ // and varyings cannot be initialized in a shader, we must have
+ // only TIntermSymbol nodes in the sequence.
ASSERT(variable != NULL);
TString processedSymbol;
if (mHashFunction == NULL)
@@ -222,6 +295,7 @@ bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node)
processedSymbol,
infoList,
mHashFunction);
+ visitChildren = false;
}
}
break;
@@ -232,13 +306,3 @@ bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node)
return visitChildren;
}
-bool CollectAttribsUniforms::visitLoop(Visit, TIntermLoop*)
-{
- return false;
-}
-
-bool CollectAttribsUniforms::visitBranch(Visit, TIntermBranch*)
-{
- return false;
-}
-
diff --git a/src/3rdparty/angle/src/compiler/VariableInfo.h b/src/3rdparty/angle/src/compiler/VariableInfo.h
index 4130a589f5..3c7f2a5f84 100644
--- a/src/3rdparty/angle/src/compiler/VariableInfo.h
+++ b/src/3rdparty/angle/src/compiler/VariableInfo.h
@@ -20,28 +20,30 @@ struct TVariableInfo {
TPersistString mappedName;
ShDataType type;
int size;
+ TPrecision precision;
+ bool staticUse;
};
typedef std::vector<TVariableInfo> TVariableInfoList;
-// Traverses intermediate tree to collect all attributes and uniforms.
-class CollectAttribsUniforms : public TIntermTraverser {
+// Traverses intermediate tree to collect all attributes, uniforms, varyings.
+class CollectVariables : public TIntermTraverser {
public:
- CollectAttribsUniforms(TVariableInfoList& attribs,
- TVariableInfoList& uniforms,
- ShHashFunction64 hashFunction);
+ CollectVariables(TVariableInfoList& attribs,
+ TVariableInfoList& uniforms,
+ TVariableInfoList& varyings,
+ ShHashFunction64 hashFunction);
virtual void visitSymbol(TIntermSymbol*);
- virtual void visitConstantUnion(TIntermConstantUnion*);
- virtual bool visitBinary(Visit, TIntermBinary*);
- virtual bool visitUnary(Visit, TIntermUnary*);
- virtual bool visitSelection(Visit, TIntermSelection*);
virtual bool visitAggregate(Visit, TIntermAggregate*);
- virtual bool visitLoop(Visit, TIntermLoop*);
- virtual bool visitBranch(Visit, TIntermBranch*);
private:
TVariableInfoList& mAttribs;
TVariableInfoList& mUniforms;
+ TVariableInfoList& mVaryings;
+
+ bool mPointCoordAdded;
+ bool mFrontFacingAdded;
+ bool mFragCoordAdded;
ShHashFunction64 mHashFunction;
};
diff --git a/src/3rdparty/angle/src/compiler/glslang.l b/src/3rdparty/angle/src/compiler/glslang.l
index 140a9aeb2d..60663f9a6b 100644
--- a/src/3rdparty/angle/src/compiler/glslang.l
+++ b/src/3rdparty/angle/src/compiler/glslang.l
@@ -47,20 +47,23 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp).
#pragma warning(disable : 4102)
#endif
-#define YY_USER_ACTION yylval->lex.line = yylineno;
+#define YY_USER_ACTION \
+ yylloc->first_file = yylloc->last_file = yycolumn; \
+ yylloc->first_line = yylloc->last_line = yylineno;
+
#define YY_INPUT(buf, result, max_size) \
result = string_input(buf, max_size, yyscanner);
static yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner);
static int check_type(yyscan_t yyscanner);
static int reserved_word(yyscan_t yyscanner);
+static int int_constant(yyscan_t yyscanner);
+static int float_constant(yyscan_t yyscanner);
%}
%option noyywrap nounput never-interactive
-%option yylineno reentrant bison-bridge
-%option stack
+%option yylineno reentrant bison-bridge bison-locations
%option extra-type="TParseContext*"
-%x COMMENT FIELDS
D [0-9]
L [a-zA-Z_]
@@ -70,73 +73,60 @@ O [0-7]
%%
-%{
- TParseContext* context = yyextra;
-%}
-
- /* Single-line comments */
-"//"[^\n]* ;
-
- /* Multi-line comments */
-"/*" { yy_push_state(COMMENT, yyscanner); }
-<COMMENT>. |
-<COMMENT>\n ;
-<COMMENT>"*/" { yy_pop_state(yyscanner); }
-
-"invariant" { return(INVARIANT); }
-"highp" { return(HIGH_PRECISION); }
-"mediump" { return(MEDIUM_PRECISION); }
-"lowp" { return(LOW_PRECISION); }
-"precision" { return(PRECISION); }
-
-"attribute" { return(ATTRIBUTE); }
-"const" { return(CONST_QUAL); }
-"uniform" { return(UNIFORM); }
-"varying" { return(VARYING); }
-
-"break" { return(BREAK); }
-"continue" { return(CONTINUE); }
-"do" { return(DO); }
-"for" { return(FOR); }
-"while" { return(WHILE); }
-
-"if" { return(IF); }
-"else" { return(ELSE); }
-
-"in" { return(IN_QUAL); }
-"out" { return(OUT_QUAL); }
-"inout" { return(INOUT_QUAL); }
-
-"float" { context->lexAfterType = true; return(FLOAT_TYPE); }
-"int" { context->lexAfterType = true; return(INT_TYPE); }
-"void" { context->lexAfterType = true; return(VOID_TYPE); }
-"bool" { context->lexAfterType = true; return(BOOL_TYPE); }
-"true" { yylval->lex.b = true; return(BOOLCONSTANT); }
-"false" { yylval->lex.b = false; return(BOOLCONSTANT); }
-
-"discard" { return(DISCARD); }
-"return" { return(RETURN); }
-
-"mat2" { context->lexAfterType = true; return(MATRIX2); }
-"mat3" { context->lexAfterType = true; return(MATRIX3); }
-"mat4" { context->lexAfterType = true; return(MATRIX4); }
-
-"vec2" { context->lexAfterType = true; return (VEC2); }
-"vec3" { context->lexAfterType = true; return (VEC3); }
-"vec4" { context->lexAfterType = true; return (VEC4); }
-"ivec2" { context->lexAfterType = true; return (IVEC2); }
-"ivec3" { context->lexAfterType = true; return (IVEC3); }
-"ivec4" { context->lexAfterType = true; return (IVEC4); }
-"bvec2" { context->lexAfterType = true; return (BVEC2); }
-"bvec3" { context->lexAfterType = true; return (BVEC3); }
-"bvec4" { context->lexAfterType = true; return (BVEC4); }
-
-"sampler2D" { context->lexAfterType = true; return SAMPLER2D; }
-"samplerCube" { context->lexAfterType = true; return SAMPLERCUBE; }
-"samplerExternalOES" { context->lexAfterType = true; return SAMPLER_EXTERNAL_OES; }
-"sampler2DRect" { context->lexAfterType = true; return SAMPLER2DRECT; }
-
-"struct" { context->lexAfterType = true; return(STRUCT); }
+"invariant" { return INVARIANT; }
+"highp" { return HIGH_PRECISION; }
+"mediump" { return MEDIUM_PRECISION; }
+"lowp" { return LOW_PRECISION; }
+"precision" { return PRECISION; }
+
+"attribute" { return ATTRIBUTE; }
+"const" { return CONST_QUAL; }
+"uniform" { return UNIFORM; }
+"varying" { return VARYING; }
+
+"break" { return BREAK; }
+"continue" { return CONTINUE; }
+"do" { return DO; }
+"for" { return FOR; }
+"while" { return WHILE; }
+
+"if" { return IF; }
+"else" { return ELSE; }
+
+"in" { return IN_QUAL; }
+"out" { return OUT_QUAL; }
+"inout" { return INOUT_QUAL; }
+
+"float" { return FLOAT_TYPE; }
+"int" { return INT_TYPE; }
+"void" { return VOID_TYPE; }
+"bool" { return BOOL_TYPE; }
+"true" { yylval->lex.b = true; return BOOLCONSTANT; }
+"false" { yylval->lex.b = false; return BOOLCONSTANT; }
+
+"discard" { return DISCARD; }
+"return" { return RETURN; }
+
+"mat2" { return MATRIX2; }
+"mat3" { return MATRIX3; }
+"mat4" { return MATRIX4; }
+
+"vec2" { return VEC2; }
+"vec3" { return VEC3; }
+"vec4" { return VEC4; }
+"ivec2" { return IVEC2; }
+"ivec3" { return IVEC3; }
+"ivec4" { return IVEC4; }
+"bvec2" { return BVEC2; }
+"bvec3" { return BVEC3; }
+"bvec4" { return BVEC4; }
+
+"sampler2D" { return SAMPLER2D; }
+"samplerCube" { return SAMPLERCUBE; }
+"samplerExternalOES" { return SAMPLER_EXTERNAL_OES; }
+"sampler2DRect" { return SAMPLER2DRECT; }
+
+"struct" { return STRUCT; }
"asm" { return reserved_word(yyscanner); }
@@ -183,13 +173,11 @@ O [0-7]
"fvec3" { return reserved_word(yyscanner); }
"fvec4" { return reserved_word(yyscanner); }
-"sampler1D" { return reserved_word(yyscanner); }
-"sampler3D" { return reserved_word(yyscanner); }
-
-"sampler1DShadow" { return reserved_word(yyscanner); }
-"sampler2DShadow" { return reserved_word(yyscanner); }
-
-"sampler3DRect" { return reserved_word(yyscanner); }
+"sampler1D" { return reserved_word(yyscanner); }
+"sampler3D" { return reserved_word(yyscanner); }
+"sampler1DShadow" { return reserved_word(yyscanner); }
+"sampler2DShadow" { return reserved_word(yyscanner); }
+"sampler3DRect" { return reserved_word(yyscanner); }
"sampler2DRectShadow" { return reserved_word(yyscanner); }
"sizeof" { return reserved_word(yyscanner); }
@@ -203,72 +191,64 @@ O [0-7]
return check_type(yyscanner);
}
-0[xX]{H}+ { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return(INTCONSTANT); }
-0{O}+ { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return(INTCONSTANT); }
-0{D}+ { context->error(yylineno, "Invalid Octal number.", yytext); context->recover(); return 0;}
-{D}+ { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return(INTCONSTANT); }
-
-{D}+{E} { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
-{D}+"."{D}*({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
-"."{D}+({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
-
-"+=" { return(ADD_ASSIGN); }
-"-=" { return(SUB_ASSIGN); }
-"*=" { return(MUL_ASSIGN); }
-"/=" { return(DIV_ASSIGN); }
-"%=" { return(MOD_ASSIGN); }
-"<<=" { return(LEFT_ASSIGN); }
-">>=" { return(RIGHT_ASSIGN); }
-"&=" { return(AND_ASSIGN); }
-"^=" { return(XOR_ASSIGN); }
-"|=" { return(OR_ASSIGN); }
-
-"++" { return(INC_OP); }
-"--" { return(DEC_OP); }
-"&&" { return(AND_OP); }
-"||" { return(OR_OP); }
-"^^" { return(XOR_OP); }
-"<=" { return(LE_OP); }
-">=" { return(GE_OP); }
-"==" { return(EQ_OP); }
-"!=" { return(NE_OP); }
-"<<" { return(LEFT_OP); }
-">>" { return(RIGHT_OP); }
-";" { context->lexAfterType = false; return(SEMICOLON); }
-("{"|"<%") { context->lexAfterType = false; return(LEFT_BRACE); }
-("}"|"%>") { return(RIGHT_BRACE); }
-"," { if (context->inTypeParen) context->lexAfterType = false; return(COMMA); }
-":" { return(COLON); }
-"=" { context->lexAfterType = false; return(EQUAL); }
-"(" { context->lexAfterType = false; context->inTypeParen = true; return(LEFT_PAREN); }
-")" { context->inTypeParen = false; return(RIGHT_PAREN); }
-("["|"<:") { return(LEFT_BRACKET); }
-("]"|":>") { return(RIGHT_BRACKET); }
-"." { BEGIN(FIELDS); return(DOT); }
-"!" { return(BANG); }
-"-" { return(DASH); }
-"~" { return(TILDE); }
-"+" { return(PLUS); }
-"*" { return(STAR); }
-"/" { return(SLASH); }
-"%" { return(PERCENT); }
-"<" { return(LEFT_ANGLE); }
-">" { return(RIGHT_ANGLE); }
-"|" { return(VERTICAL_BAR); }
-"^" { return(CARET); }
-"&" { return(AMPERSAND); }
-"?" { return(QUESTION); }
-
-<FIELDS>{L}({L}|{D})* {
- BEGIN(INITIAL);
- yylval->lex.string = NewPoolTString(yytext);
- return FIELD_SELECTION;
-}
-<FIELDS>[ \t\v\f\r] {}
-
-[ \t\v\n\f\r] { }
-<*><<EOF>> { context->AfterEOF = true; yyterminate(); }
-<*>. { context->warning(yylineno, "Unknown char", yytext, ""); return 0; }
+0[xX]{H}+ { return int_constant(yyscanner); }
+0{O}+ { return int_constant(yyscanner); }
+{D}+ { return int_constant(yyscanner); }
+
+{D}+{E} { return float_constant(yyscanner); }
+{D}+"."{D}*({E})? { return float_constant(yyscanner); }
+"."{D}+({E})? { return float_constant(yyscanner); }
+
+"+=" { return ADD_ASSIGN; }
+"-=" { return SUB_ASSIGN; }
+"*=" { return MUL_ASSIGN; }
+"/=" { return DIV_ASSIGN; }
+"%=" { return MOD_ASSIGN; }
+"<<=" { return LEFT_ASSIGN; }
+">>=" { return RIGHT_ASSIGN; }
+"&=" { return AND_ASSIGN; }
+"^=" { return XOR_ASSIGN; }
+"|=" { return OR_ASSIGN; }
+
+"++" { return INC_OP; }
+"--" { return DEC_OP; }
+"&&" { return AND_OP; }
+"||" { return OR_OP; }
+"^^" { return XOR_OP; }
+"<=" { return LE_OP; }
+">=" { return GE_OP; }
+"==" { return EQ_OP; }
+"!=" { return NE_OP; }
+"<<" { return LEFT_OP; }
+">>" { return RIGHT_OP; }
+";" { return SEMICOLON; }
+("{"|"<%") { return LEFT_BRACE; }
+("}"|"%>") { return RIGHT_BRACE; }
+"," { return COMMA; }
+":" { return COLON; }
+"=" { return EQUAL; }
+"(" { return LEFT_PAREN; }
+")" { return RIGHT_PAREN; }
+("["|"<:") { return LEFT_BRACKET; }
+("]"|":>") { return RIGHT_BRACKET; }
+"." { return DOT; }
+"!" { return BANG; }
+"-" { return DASH; }
+"~" { return TILDE; }
+"+" { return PLUS; }
+"*" { return STAR; }
+"/" { return SLASH; }
+"%" { return PERCENT; }
+"<" { return LEFT_ANGLE; }
+">" { return RIGHT_ANGLE; }
+"|" { return VERTICAL_BAR; }
+"^" { return CARET; }
+"&" { return AMPERSAND; }
+"?" { return QUESTION; }
+
+[ \t\v\n\f\r] { }
+<<EOF>> { yyterminate(); }
+. { assert(false); return 0; }
%%
@@ -278,7 +258,8 @@ yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) {
yy_size_t len = token.type == pp::Token::LAST ? 0 : token.text.size();
if (len < max_size)
memcpy(buf, token.text.c_str(), len);
- yyset_lineno(EncodeSourceLoc(token.location.file, token.location.line), yyscanner);
+ yyset_column(token.location.file, yyscanner);
+ yyset_lineno(token.location.line, yyscanner);
if (len >= max_size)
YY_FATAL_ERROR("Input buffer overflow");
@@ -292,12 +273,10 @@ int check_type(yyscan_t yyscanner) {
int token = IDENTIFIER;
TSymbol* symbol = yyextra->symbolTable.find(yytext);
- if (yyextra->lexAfterType == false && symbol && symbol->isVariable()) {
+ if (symbol && symbol->isVariable()) {
TVariable* variable = static_cast<TVariable*>(symbol);
- if (variable->isUserType()) {
- yyextra->lexAfterType = true;
+ if (variable->isUserType())
token = TYPE_NAME;
- }
}
yylval->lex.symbol = symbol;
return token;
@@ -306,22 +285,32 @@ int check_type(yyscan_t yyscanner) {
int reserved_word(yyscan_t yyscanner) {
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
- yyextra->error(yylineno, "Illegal use of reserved word", yytext, "");
+ yyextra->error(*yylloc, "Illegal use of reserved word", yytext, "");
yyextra->recover();
return 0;
}
-void yyerror(TParseContext* context, const char* reason) {
- struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
-
- if (context->AfterEOF) {
- context->error(yylineno, reason, "unexpected EOF");
- } else {
- context->error(yylineno, reason, yytext);
- }
+void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) {
+ context->error(*lloc, reason, yyget_text(context->scanner));
context->recover();
}
+int int_constant(yyscan_t yyscanner) {
+ struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+
+ if (!atoi_clamp(yytext, &(yylval->lex.i)))
+ yyextra->warning(*yylloc, "Integer overflow", yytext, "");
+ return INTCONSTANT;
+}
+
+int float_constant(yyscan_t yyscanner) {
+ struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+
+ if (!atof_clamp(yytext, &(yylval->lex.f)))
+ yyextra->warning(*yylloc, "Float overflow", yytext, "");
+ return FLOATCONSTANT;
+}
+
int glslang_initialize(TParseContext* context) {
yyscan_t scanner = NULL;
if (yylex_init_extra(context, &scanner))
@@ -344,12 +333,13 @@ int glslang_finalize(TParseContext* context) {
int glslang_scan(size_t count, const char* const string[], const int length[],
TParseContext* context) {
yyrestart(NULL, context->scanner);
- yyset_lineno(EncodeSourceLoc(0, 1), context->scanner);
- context->AfterEOF = false;
+ yyset_column(0, context->scanner);
+ yyset_lineno(1, context->scanner);
// Initialize preprocessor.
if (!context->preprocessor.init(count, string, length))
return 1;
+ context->preprocessor.setMaxTokenLength(SH_MAX_TOKEN_LENGTH);
// Define extension macros.
const TExtensionBehavior& extBehavior = context->extensionBehavior();
diff --git a/src/3rdparty/angle/src/compiler/glslang.y b/src/3rdparty/angle/src/compiler/glslang.y
index 8dbcee32ef..c64f736f41 100644
--- a/src/3rdparty/angle/src/compiler/glslang.y
+++ b/src/3rdparty/angle/src/compiler/glslang.y
@@ -39,7 +39,6 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
#include "GLSLANG/ShaderLang.h"
#define YYENABLE_NLS 0
-#define YYLTYPE_IS_TRIVIAL 1
#define YYLEX_PARAM context->scanner
%}
@@ -47,10 +46,16 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
%expect 1 /* One shift reduce conflict because of if | else */
%pure-parser
%parse-param {TParseContext* context}
+%locations
+
+%code requires {
+#define YYLTYPE TSourceLoc
+#define YYLTYPE_IS_DECLARED 1
+#define SH_MAX_TOKEN_LENGTH 256 // WebGL spec.
+}
%union {
struct {
- TSourceLoc line;
union {
TString *string;
float f;
@@ -60,7 +65,6 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
TSymbol* symbol;
} lex;
struct {
- TSourceLoc line;
TOperator op;
union {
TIntermNode* intermNode;
@@ -74,23 +78,31 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
TQualifier qualifier;
TFunction* function;
TParameter param;
- TTypeLine typeLine;
- TTypeList* typeList;
+ TField* field;
+ TFieldList* fieldList;
};
} interm;
}
%{
-extern int yylex(YYSTYPE* yylval_param, void* yyscanner);
-extern void yyerror(TParseContext* context, const char* reason);
-
-#define FRAG_VERT_ONLY(S, L) { \
- if (context->shaderType != SH_FRAGMENT_SHADER && \
- context->shaderType != SH_VERTEX_SHADER) { \
- context->error(L, " supported in vertex/fragment shaders only ", S); \
- context->recover(); \
- } \
-}
+extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner);
+extern void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason);
+
+#define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do { \
+ if (YYID(N)) { \
+ (Current).first_file = YYRHSLOC(Rhs, 1).first_file; \
+ (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \
+ (Current).last_file = YYRHSLOC(Rhs, N).last_file; \
+ (Current).last_line = YYRHSLOC(Rhs, N).last_line; \
+ } \
+ else { \
+ (Current).first_file = YYRHSLOC(Rhs, 0).last_file; \
+ (Current).first_line = YYRHSLOC(Rhs, 0).last_line; \
+ (Current).last_file = YYRHSLOC(Rhs, 0).last_file; \
+ (Current).last_line = YYRHSLOC(Rhs, 0).last_line; \
+ } \
+ } while (0)
#define VERTEX_ONLY(S, L) { \
if (context->shaderType != SH_VERTEX_SHADER) { \
@@ -116,7 +128,6 @@ extern void yyerror(TParseContext* context, const char* reason);
%token <lex> SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT
%token <lex> IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT BOOLCONSTANT
-%token <lex> FIELD_SELECTION
%token <lex> LEFT_OP RIGHT_OP
%token <lex> INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
%token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
@@ -127,6 +138,7 @@ extern void yyerror(TParseContext* context, const char* reason);
%token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
%token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION
+%type <lex> identifier
%type <interm> assignment_operator unary_operator
%type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression
%type <interm.intermTypedNode> expression integer_expression assignment_expression
@@ -154,8 +166,8 @@ extern void yyerror(TParseContext* context, const char* reason);
%type <interm.type> type_qualifier fully_specified_type type_specifier
%type <interm.type> type_specifier_no_prec type_specifier_nonarray
%type <interm.type> struct_specifier
-%type <interm.typeLine> struct_declarator
-%type <interm.typeList> struct_declarator_list struct_declaration struct_declaration_list
+%type <interm.field> struct_declarator
+%type <interm.fieldList> struct_declarator_list struct_declaration struct_declaration_list
%type <interm.function> function_header function_declarator function_identifier
%type <interm.function> function_header_with_parameters function_call_header
%type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
@@ -164,13 +176,17 @@ extern void yyerror(TParseContext* context, const char* reason);
%start translation_unit
%%
+identifier
+ : IDENTIFIER
+ | TYPE_NAME
+
variable_identifier
: IDENTIFIER {
// The symbol table search was done in the lexical phase
const TSymbol* symbol = $1.symbol;
const TVariable* variable;
if (symbol == 0) {
- context->error($1.line, "undeclared identifier", $1.string->c_str());
+ context->error(@1, "undeclared identifier", $1.string->c_str());
context->recover();
TType type(EbtFloat, EbpUndefined);
TVariable* fakeVariable = new TVariable($1.string, type);
@@ -179,10 +195,17 @@ variable_identifier
} else {
// This identifier can only be a variable type symbol
if (! symbol->isVariable()) {
- context->error($1.line, "variable expected", $1.string->c_str());
+ context->error(@1, "variable expected", $1.string->c_str());
context->recover();
}
+
variable = static_cast<const TVariable*>(symbol);
+
+ if (context->symbolTable.findBuiltIn(variable->getName()) &&
+ !variable->getExtension().empty() &&
+ context->extensionErrorCheck(@1, variable->getExtension())) {
+ context->recover();
+ }
}
// don't delete $1.string, it's used by error recovery, and the pool
@@ -191,11 +214,12 @@ variable_identifier
if (variable->getType().getQualifier() == EvqConst ) {
ConstantUnion* constArray = variable->getConstPointer();
TType t(variable->getType());
- $$ = context->intermediate.addConstantUnion(constArray, t, $1.line);
+ $$ = context->intermediate.addConstantUnion(constArray, t, @1);
} else
$$ = context->intermediate.addSymbol(variable->getUniqueId(),
- variable->getName(),
- variable->getType(), $1.line);
+ variable->getName(),
+ variable->getType(),
+ @1);
}
;
@@ -204,27 +228,19 @@ primary_expression
$$ = $1;
}
| INTCONSTANT {
- //
- // INT_TYPE is only 16-bit plus sign bit for vertex/fragment shaders,
- // check for overflow for constants
- //
- if (abs($1.i) >= (1 << 16)) {
- context->error($1.line, " integer constant overflow", "");
- context->recover();
- }
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setIConst($1.i);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $1.line);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @1);
}
| FLOATCONSTANT {
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setFConst($1.f);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1);
}
| BOOLCONSTANT {
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setBConst($1.b);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $1.line);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @1);
}
| LEFT_PAREN expression RIGHT_PAREN {
$$ = $2;
@@ -236,103 +252,27 @@ postfix_expression
$$ = $1;
}
| postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET {
- if (!$1->isArray() && !$1->isMatrix() && !$1->isVector()) {
- if ($1->getAsSymbolNode())
- context->error($2.line, " left of '[' is not of type array, matrix, or vector ", $1->getAsSymbolNode()->getSymbol().c_str());
- else
- context->error($2.line, " left of '[' is not of type array, matrix, or vector ", "expression");
- context->recover();
- }
- if ($1->getType().getQualifier() == EvqConst && $3->getQualifier() == EvqConst) {
- if ($1->isArray()) { // constant folding for arrays
- $$ = context->addConstArrayNode($3->getAsConstantUnion()->getIConst(0), $1, $2.line);
- } else if ($1->isVector()) { // constant folding for vectors
- TVectorFields fields;
- fields.num = 1;
- fields.offsets[0] = $3->getAsConstantUnion()->getIConst(0); // need to do it this way because v.xy sends fields integer array
- $$ = context->addConstVectorNode(fields, $1, $2.line);
- } else if ($1->isMatrix()) { // constant folding for matrices
- $$ = context->addConstMatrixNode($3->getAsConstantUnion()->getIConst(0), $1, $2.line);
- }
- } else {
- if ($3->getQualifier() == EvqConst) {
- if (($1->isVector() || $1->isMatrix()) && $1->getType().getNominalSize() <= $3->getAsConstantUnion()->getIConst(0) && !$1->isArray() ) {
- std::stringstream extraInfoStream;
- extraInfoStream << "field selection out of range '" << $3->getAsConstantUnion()->getIConst(0) << "'";
- std::string extraInfo = extraInfoStream.str();
- context->error($2.line, "", "[", extraInfo.c_str());
- context->recover();
- } else {
- if ($1->isArray()) {
- if ($1->getType().getArraySize() == 0) {
- if ($1->getType().getMaxArraySize() <= $3->getAsConstantUnion()->getIConst(0)) {
- if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getIConst(0), true, $2.line))
- context->recover();
- } else {
- if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line))
- context->recover();
- }
- } else if ( $3->getAsConstantUnion()->getIConst(0) >= $1->getType().getArraySize()) {
- std::stringstream extraInfoStream;
- extraInfoStream << "array index out of range '" << $3->getAsConstantUnion()->getIConst(0) << "'";
- std::string extraInfo = extraInfoStream.str();
- context->error($2.line, "", "[", extraInfo.c_str());
- context->recover();
- }
- }
- $$ = context->intermediate.addIndex(EOpIndexDirect, $1, $3, $2.line);
- }
- } else {
- if ($1->isArray() && $1->getType().getArraySize() == 0) {
- context->error($2.line, "", "[", "array must be redeclared with a size before being indexed with a variable");
- context->recover();
- }
-
- $$ = context->intermediate.addIndex(EOpIndexIndirect, $1, $3, $2.line);
- }
- }
- if ($$ == 0) {
- ConstantUnion *unionArray = new ConstantUnion[1];
- unionArray->setFConst(0.0f);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), $2.line);
- } else if ($1->isArray()) {
- if ($1->getType().getStruct())
- $$->setType(TType($1->getType().getStruct(), $1->getType().getTypeName()));
- else
- $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize(), $1->isMatrix()));
-
- if ($1->getType().getQualifier() == EvqConst)
- $$->getTypePointer()->setQualifier(EvqConst);
- } else if ($1->isMatrix() && $1->getType().getQualifier() == EvqConst)
- $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, $1->getNominalSize()));
- else if ($1->isMatrix())
- $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize()));
- else if ($1->isVector() && $1->getType().getQualifier() == EvqConst)
- $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst));
- else if ($1->isVector())
- $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary));
- else
- $$->setType($1->getType());
+ $$ = context->addIndexExpression($1, @2, $3);
}
| function_call {
$$ = $1;
}
- | postfix_expression DOT FIELD_SELECTION {
+ | postfix_expression DOT identifier {
if ($1->isArray()) {
- context->error($3.line, "cannot apply dot operator to an array", ".");
+ context->error(@3, "cannot apply dot operator to an array", ".");
context->recover();
}
if ($1->isVector()) {
TVectorFields fields;
- if (! context->parseVectorFields(*$3.string, $1->getNominalSize(), fields, $3.line)) {
+ if (! context->parseVectorFields(*$3.string, $1->getNominalSize(), fields, @3)) {
fields.num = 1;
fields.offsets[0] = 0;
context->recover();
}
if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields
- $$ = context->addConstVectorNode(fields, $1, $3.line);
+ $$ = context->addConstVectorNode(fields, $1, @3);
if ($$ == 0) {
context->recover();
$$ = $1;
@@ -341,13 +281,13 @@ postfix_expression
$$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, (int) (*$3.string).size()));
} else {
TString vectorString = *$3.string;
- TIntermTyped* index = context->intermediate.addSwizzle(fields, $3.line);
- $$ = context->intermediate.addIndex(EOpVectorSwizzle, $1, index, $2.line);
+ TIntermTyped* index = context->intermediate.addSwizzle(fields, @3);
+ $$ = context->intermediate.addIndex(EOpVectorSwizzle, $1, index, @2);
$$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, (int) vectorString.size()));
}
} else if ($1->isMatrix()) {
TMatrixFields fields;
- if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, $3.line)) {
+ if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, @3)) {
fields.wholeRow = false;
fields.wholeCol = false;
fields.row = 0;
@@ -356,84 +296,78 @@ postfix_expression
}
if (fields.wholeRow || fields.wholeCol) {
- context->error($2.line, " non-scalar fields not implemented yet", ".");
+ context->error(@2, " non-scalar fields not implemented yet", ".");
context->recover();
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setIConst(0);
- TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line);
- $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
+ TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @3);
+ $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, @2);
$$->setType(TType($1->getBasicType(), $1->getPrecision(),EvqTemporary, $1->getNominalSize()));
} else {
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setIConst(fields.col * $1->getNominalSize() + fields.row);
- TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line);
- $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
+ TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @3);
+ $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, @2);
$$->setType(TType($1->getBasicType(), $1->getPrecision()));
}
} else if ($1->getBasicType() == EbtStruct) {
bool fieldFound = false;
- const TTypeList* fields = $1->getType().getStruct();
- if (fields == 0) {
- context->error($2.line, "structure has no fields", "Internal Error");
- context->recover();
- $$ = $1;
- } else {
- unsigned int i;
- for (i = 0; i < fields->size(); ++i) {
- if ((*fields)[i].type->getFieldName() == *$3.string) {
- fieldFound = true;
- break;
- }
+ const TFieldList& fields = $1->getType().getStruct()->fields();
+ unsigned int i;
+ for (i = 0; i < fields.size(); ++i) {
+ if (fields[i]->name() == *$3.string) {
+ fieldFound = true;
+ break;
}
- if (fieldFound) {
- if ($1->getType().getQualifier() == EvqConst) {
- $$ = context->addConstStruct(*$3.string, $1, $2.line);
- if ($$ == 0) {
- context->recover();
- $$ = $1;
- }
- else {
- $$->setType(*(*fields)[i].type);
- // change the qualifier of the return type, not of the structure field
- // as the structure definition is shared between various structures.
- $$->getTypePointer()->setQualifier(EvqConst);
- }
- } else {
- ConstantUnion *unionArray = new ConstantUnion[1];
- unionArray->setIConst(i);
- TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *(*fields)[i].type, $3.line);
- $$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, $2.line);
- $$->setType(*(*fields)[i].type);
+ }
+ if (fieldFound) {
+ if ($1->getType().getQualifier() == EvqConst) {
+ $$ = context->addConstStruct(*$3.string, $1, @2);
+ if ($$ == 0) {
+ context->recover();
+ $$ = $1;
+ }
+ else {
+ $$->setType(*fields[i]->type());
+ // change the qualifier of the return type, not of the structure field
+ // as the structure definition is shared between various structures.
+ $$->getTypePointer()->setQualifier(EvqConst);
}
} else {
- context->error($2.line, " no such field in structure", $3.string->c_str());
- context->recover();
- $$ = $1;
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setIConst(i);
+ TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *fields[i]->type(), @3);
+ $$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, @2);
+ $$->setType(*fields[i]->type());
}
+ } else {
+ context->error(@2, " no such field in structure", $3.string->c_str());
+ context->recover();
+ $$ = $1;
}
} else {
- context->error($2.line, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str());
+ context->error(@2, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str());
context->recover();
$$ = $1;
}
// don't delete $3.string, it's from the pool
}
| postfix_expression INC_OP {
- if (context->lValueErrorCheck($2.line, "++", $1))
+ if (context->lValueErrorCheck(@2, "++", $1))
context->recover();
- $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, $2.line, context->symbolTable);
+ $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, @2, context->symbolTable);
if ($$ == 0) {
- context->unaryOpError($2.line, "++", $1->getCompleteString());
+ context->unaryOpError(@2, "++", $1->getCompleteString());
context->recover();
$$ = $1;
}
}
| postfix_expression DEC_OP {
- if (context->lValueErrorCheck($2.line, "--", $1))
+ if (context->lValueErrorCheck(@2, "--", $1))
context->recover();
- $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, $2.line, context->symbolTable);
+ $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, @2, context->symbolTable);
if ($$ == 0) {
- context->unaryOpError($2.line, "--", $1->getCompleteString());
+ context->unaryOpError(@2, "--", $1->getCompleteString());
context->recover();
$$ = $1;
}
@@ -461,18 +395,18 @@ function_call
// Their parameters will be verified algorithmically.
//
TType type(EbtVoid, EbpUndefined); // use this to get the type back
- if (context->constructorErrorCheck($1.line, $1.intermNode, *fnCall, op, &type)) {
+ if (context->constructorErrorCheck(@1, $1.intermNode, *fnCall, op, &type)) {
$$ = 0;
} else {
//
// It's a constructor, of type 'type'.
//
- $$ = context->addConstructor($1.intermNode, &type, op, fnCall, $1.line);
+ $$ = context->addConstructor($1.intermNode, &type, op, fnCall, @1);
}
if ($$ == 0) {
context->recover();
- $$ = context->intermediate.setAggregateOperator(0, op, $1.line);
+ $$ = context->intermediate.setAggregateOperator(0, op, @1);
}
$$->setType(type);
} else {
@@ -481,13 +415,13 @@ function_call
//
const TFunction* fnCandidate;
bool builtIn;
- fnCandidate = context->findFunction($1.line, fnCall, &builtIn);
+ fnCandidate = context->findFunction(@1, fnCall, &builtIn);
if (fnCandidate) {
//
// A declared function.
//
if (builtIn && !fnCandidate->getExtension().empty() &&
- context->extensionErrorCheck($1.line, fnCandidate->getExtension())) {
+ context->extensionErrorCheck(@1, fnCandidate->getExtension())) {
context->recover();
}
op = fnCandidate->getBuiltInOp();
@@ -499,7 +433,7 @@ function_call
//
// Treat it like a built-in unary operator.
//
- $$ = context->intermediate.addUnaryMath(op, $1.intermNode, 0, context->symbolTable);
+ $$ = context->intermediate.addUnaryMath(op, $1.intermNode, @1, context->symbolTable);
if ($$ == 0) {
std::stringstream extraInfoStream;
extraInfoStream << "built in unary operator function. Type: " << static_cast<TIntermTyped*>($1.intermNode)->getCompleteString();
@@ -508,12 +442,12 @@ function_call
YYERROR;
}
} else {
- $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, $1.line);
+ $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1);
}
} else {
// This is a real function call
- $$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, $1.line);
+ $$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1);
$$->setType(fnCandidate->getReturnType());
// this is how we know whether the given function is a builtIn function or a user defined function
@@ -540,7 +474,7 @@ function_call
// Put on a dummy node for error recovery
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setFConst(0.0f);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1);
context->recover();
}
}
@@ -553,7 +487,7 @@ function_call_or_method
$$ = $1;
}
| postfix_expression DOT function_call_generic {
- context->error($3.line, "methods are not supported", "");
+ context->error(@3, "methods are not supported", "");
context->recover();
$$ = $3;
}
@@ -562,11 +496,9 @@ function_call_or_method
function_call_generic
: function_call_header_with_parameters RIGHT_PAREN {
$$ = $1;
- $$.line = $2.line;
}
| function_call_header_no_parameters RIGHT_PAREN {
$$ = $1;
- $$.line = $2.line;
}
;
@@ -592,7 +524,7 @@ function_call_header_with_parameters
TParameter param = { 0, new TType($3->getType()) };
$1.function->addParameter(param);
$$.function = $1.function;
- $$.intermNode = context->intermediate.growAggregate($1.intermNode, $3, $2.line);
+ $$.intermNode = context->intermediate.growAggregate($1.intermNode, $3, @2);
}
;
@@ -617,39 +549,39 @@ function_identifier
case EbtFloat:
if ($1.matrix) {
switch($1.size) {
- case 2: op = EOpConstructMat2; break;
- case 3: op = EOpConstructMat3; break;
- case 4: op = EOpConstructMat4; break;
+ case 2: op = EOpConstructMat2; break;
+ case 3: op = EOpConstructMat3; break;
+ case 4: op = EOpConstructMat4; break;
}
} else {
switch($1.size) {
- case 1: op = EOpConstructFloat; break;
- case 2: op = EOpConstructVec2; break;
- case 3: op = EOpConstructVec3; break;
- case 4: op = EOpConstructVec4; break;
+ case 1: op = EOpConstructFloat; break;
+ case 2: op = EOpConstructVec2; break;
+ case 3: op = EOpConstructVec3; break;
+ case 4: op = EOpConstructVec4; break;
}
}
break;
case EbtInt:
switch($1.size) {
- case 1: op = EOpConstructInt; break;
- case 2: FRAG_VERT_ONLY("ivec2", $1.line); op = EOpConstructIVec2; break;
- case 3: FRAG_VERT_ONLY("ivec3", $1.line); op = EOpConstructIVec3; break;
- case 4: FRAG_VERT_ONLY("ivec4", $1.line); op = EOpConstructIVec4; break;
+ case 1: op = EOpConstructInt; break;
+ case 2: op = EOpConstructIVec2; break;
+ case 3: op = EOpConstructIVec3; break;
+ case 4: op = EOpConstructIVec4; break;
}
break;
case EbtBool:
switch($1.size) {
- case 1: op = EOpConstructBool; break;
- case 2: FRAG_VERT_ONLY("bvec2", $1.line); op = EOpConstructBVec2; break;
- case 3: FRAG_VERT_ONLY("bvec3", $1.line); op = EOpConstructBVec3; break;
- case 4: FRAG_VERT_ONLY("bvec4", $1.line); op = EOpConstructBVec4; break;
+ case 1: op = EOpConstructBool; break;
+ case 2: op = EOpConstructBVec2; break;
+ case 3: op = EOpConstructBVec3; break;
+ case 4: op = EOpConstructBVec4; break;
}
break;
default: break;
}
if (op == EOpNull) {
- context->error($1.line, "cannot construct this type", getBasicString($1.type));
+ context->error(@1, "cannot construct this type", getBasicString($1.type));
context->recover();
$1.type = EbtFloat;
op = EOpConstructFloat;
@@ -661,14 +593,7 @@ function_identifier
$$ = function;
}
| IDENTIFIER {
- if (context->reservedErrorCheck($1.line, *$1.string))
- context->recover();
- TType type(EbtVoid, EbpUndefined);
- TFunction *function = new TFunction($1.string, type);
- $$ = function;
- }
- | FIELD_SELECTION {
- if (context->reservedErrorCheck($1.line, *$1.string))
+ if (context->reservedErrorCheck(@1, *$1.string))
context->recover();
TType type(EbtVoid, EbpUndefined);
TFunction *function = new TFunction($1.string, type);
@@ -681,28 +606,28 @@ unary_expression
$$ = $1;
}
| INC_OP unary_expression {
- if (context->lValueErrorCheck($1.line, "++", $2))
+ if (context->lValueErrorCheck(@1, "++", $2))
context->recover();
- $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, $1.line, context->symbolTable);
+ $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, @1, context->symbolTable);
if ($$ == 0) {
- context->unaryOpError($1.line, "++", $2->getCompleteString());
+ context->unaryOpError(@1, "++", $2->getCompleteString());
context->recover();
$$ = $2;
}
}
| DEC_OP unary_expression {
- if (context->lValueErrorCheck($1.line, "--", $2))
+ if (context->lValueErrorCheck(@1, "--", $2))
context->recover();
- $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, $1.line, context->symbolTable);
+ $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, @1, context->symbolTable);
if ($$ == 0) {
- context->unaryOpError($1.line, "--", $2->getCompleteString());
+ context->unaryOpError(@1, "--", $2->getCompleteString());
context->recover();
$$ = $2;
}
}
| unary_operator unary_expression {
if ($1.op != EOpNull) {
- $$ = context->intermediate.addUnaryMath($1.op, $2, $1.line, context->symbolTable);
+ $$ = context->intermediate.addUnaryMath($1.op, $2, @1, context->symbolTable);
if ($$ == 0) {
const char* errorOp = "";
switch($1.op) {
@@ -710,7 +635,7 @@ unary_expression
case EOpLogicalNot: errorOp = "!"; break;
default: break;
}
- context->unaryOpError($1.line, errorOp, $2->getCompleteString());
+ context->unaryOpError(@1, errorOp, $2->getCompleteString());
context->recover();
$$ = $2;
}
@@ -721,28 +646,26 @@ unary_expression
// Grammar Note: No traditional style type casts.
unary_operator
- : PLUS { $$.line = $1.line; $$.op = EOpNull; }
- | DASH { $$.line = $1.line; $$.op = EOpNegative; }
- | BANG { $$.line = $1.line; $$.op = EOpLogicalNot; }
+ : PLUS { $$.op = EOpNull; }
+ | DASH { $$.op = EOpNegative; }
+ | BANG { $$.op = EOpLogicalNot; }
;
// Grammar Note: No '*' or '&' unary ops. Pointers are not supported.
multiplicative_expression
: unary_expression { $$ = $1; }
| multiplicative_expression STAR unary_expression {
- FRAG_VERT_ONLY("*", $2.line);
- $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, $2.line, context->symbolTable);
+ $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, @2, context->symbolTable);
if ($$ == 0) {
- context->binaryOpError($2.line, "*", $1->getCompleteString(), $3->getCompleteString());
+ context->binaryOpError(@2, "*", $1->getCompleteString(), $3->getCompleteString());
context->recover();
$$ = $1;
}
}
| multiplicative_expression SLASH unary_expression {
- FRAG_VERT_ONLY("/", $2.line);
- $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, $2.line, context->symbolTable);
+ $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, @2, context->symbolTable);
if ($$ == 0) {
- context->binaryOpError($2.line, "/", $1->getCompleteString(), $3->getCompleteString());
+ context->binaryOpError(@2, "/", $1->getCompleteString(), $3->getCompleteString());
context->recover();
$$ = $1;
}
@@ -752,17 +675,17 @@ multiplicative_expression
additive_expression
: multiplicative_expression { $$ = $1; }
| additive_expression PLUS multiplicative_expression {
- $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, $2.line, context->symbolTable);
+ $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, @2, context->symbolTable);
if ($$ == 0) {
- context->binaryOpError($2.line, "+", $1->getCompleteString(), $3->getCompleteString());
+ context->binaryOpError(@2, "+", $1->getCompleteString(), $3->getCompleteString());
context->recover();
$$ = $1;
}
}
| additive_expression DASH multiplicative_expression {
- $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, $2.line, context->symbolTable);
+ $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, @2, context->symbolTable);
if ($$ == 0) {
- context->binaryOpError($2.line, "-", $1->getCompleteString(), $3->getCompleteString());
+ context->binaryOpError(@2, "-", $1->getCompleteString(), $3->getCompleteString());
context->recover();
$$ = $1;
}
@@ -776,43 +699,43 @@ shift_expression
relational_expression
: shift_expression { $$ = $1; }
| relational_expression LEFT_ANGLE shift_expression {
- $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, $2.line, context->symbolTable);
+ $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, @2, context->symbolTable);
if ($$ == 0) {
- context->binaryOpError($2.line, "<", $1->getCompleteString(), $3->getCompleteString());
+ context->binaryOpError(@2, "<", $1->getCompleteString(), $3->getCompleteString());
context->recover();
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setBConst(false);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
}
}
| relational_expression RIGHT_ANGLE shift_expression {
- $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, $2.line, context->symbolTable);
+ $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, @2, context->symbolTable);
if ($$ == 0) {
- context->binaryOpError($2.line, ">", $1->getCompleteString(), $3->getCompleteString());
+ context->binaryOpError(@2, ">", $1->getCompleteString(), $3->getCompleteString());
context->recover();
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setBConst(false);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
}
}
| relational_expression LE_OP shift_expression {
- $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, $2.line, context->symbolTable);
+ $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, @2, context->symbolTable);
if ($$ == 0) {
- context->binaryOpError($2.line, "<=", $1->getCompleteString(), $3->getCompleteString());
+ context->binaryOpError(@2, "<=", $1->getCompleteString(), $3->getCompleteString());
context->recover();
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setBConst(false);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
}
}
| relational_expression GE_OP shift_expression {
- $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, $2.line, context->symbolTable);
+ $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, @2, context->symbolTable);
if ($$ == 0) {
- context->binaryOpError($2.line, ">=", $1->getCompleteString(), $3->getCompleteString());
+ context->binaryOpError(@2, ">=", $1->getCompleteString(), $3->getCompleteString());
context->recover();
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setBConst(false);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
}
}
;
@@ -820,23 +743,23 @@ relational_expression
equality_expression
: relational_expression { $$ = $1; }
| equality_expression EQ_OP relational_expression {
- $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, $2.line, context->symbolTable);
+ $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, @2, context->symbolTable);
if ($$ == 0) {
- context->binaryOpError($2.line, "==", $1->getCompleteString(), $3->getCompleteString());
+ context->binaryOpError(@2, "==", $1->getCompleteString(), $3->getCompleteString());
context->recover();
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setBConst(false);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
}
}
| equality_expression NE_OP relational_expression {
- $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line, context->symbolTable);
+ $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, @2, context->symbolTable);
if ($$ == 0) {
- context->binaryOpError($2.line, "!=", $1->getCompleteString(), $3->getCompleteString());
+ context->binaryOpError(@2, "!=", $1->getCompleteString(), $3->getCompleteString());
context->recover();
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setBConst(false);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
}
}
;
@@ -856,13 +779,13 @@ inclusive_or_expression
logical_and_expression
: inclusive_or_expression { $$ = $1; }
| logical_and_expression AND_OP inclusive_or_expression {
- $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, $2.line, context->symbolTable);
+ $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, @2, context->symbolTable);
if ($$ == 0) {
- context->binaryOpError($2.line, "&&", $1->getCompleteString(), $3->getCompleteString());
+ context->binaryOpError(@2, "&&", $1->getCompleteString(), $3->getCompleteString());
context->recover();
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setBConst(false);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
}
}
;
@@ -870,13 +793,13 @@ logical_and_expression
logical_xor_expression
: logical_and_expression { $$ = $1; }
| logical_xor_expression XOR_OP logical_and_expression {
- $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, $2.line, context->symbolTable);
+ $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, @2, context->symbolTable);
if ($$ == 0) {
- context->binaryOpError($2.line, "^^", $1->getCompleteString(), $3->getCompleteString());
+ context->binaryOpError(@2, "^^", $1->getCompleteString(), $3->getCompleteString());
context->recover();
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setBConst(false);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
}
}
;
@@ -884,13 +807,13 @@ logical_xor_expression
logical_or_expression
: logical_xor_expression { $$ = $1; }
| logical_or_expression OR_OP logical_xor_expression {
- $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, $2.line, context->symbolTable);
+ $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, @2, context->symbolTable);
if ($$ == 0) {
- context->binaryOpError($2.line, "||", $1->getCompleteString(), $3->getCompleteString());
+ context->binaryOpError(@2, "||", $1->getCompleteString(), $3->getCompleteString());
context->recover();
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setBConst(false);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
}
}
;
@@ -898,15 +821,15 @@ logical_or_expression
conditional_expression
: logical_or_expression { $$ = $1; }
| logical_or_expression QUESTION expression COLON assignment_expression {
- if (context->boolErrorCheck($2.line, $1))
+ if (context->boolErrorCheck(@2, $1))
context->recover();
- $$ = context->intermediate.addSelection($1, $3, $5, $2.line);
+ $$ = context->intermediate.addSelection($1, $3, $5, @2);
if ($3->getType() != $5->getType())
$$ = 0;
if ($$ == 0) {
- context->binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString());
+ context->binaryOpError(@2, ":", $3->getCompleteString(), $5->getCompleteString());
context->recover();
$$ = $5;
}
@@ -916,11 +839,11 @@ conditional_expression
assignment_expression
: conditional_expression { $$ = $1; }
| unary_expression assignment_operator assignment_expression {
- if (context->lValueErrorCheck($2.line, "assign", $1))
+ if (context->lValueErrorCheck(@2, "assign", $1))
context->recover();
- $$ = context->intermediate.addAssign($2.op, $1, $3, $2.line);
+ $$ = context->intermediate.addAssign($2.op, $1, $3, @2);
if ($$ == 0) {
- context->assignError($2.line, "assign", $1->getCompleteString(), $3->getCompleteString());
+ context->assignError(@2, "assign", $1->getCompleteString(), $3->getCompleteString());
context->recover();
$$ = $1;
}
@@ -928,11 +851,11 @@ assignment_expression
;
assignment_operator
- : EQUAL { $$.line = $1.line; $$.op = EOpAssign; }
- | MUL_ASSIGN { FRAG_VERT_ONLY("*=", $1.line); $$.line = $1.line; $$.op = EOpMulAssign; }
- | DIV_ASSIGN { FRAG_VERT_ONLY("/=", $1.line); $$.line = $1.line; $$.op = EOpDivAssign; }
- | ADD_ASSIGN { $$.line = $1.line; $$.op = EOpAddAssign; }
- | SUB_ASSIGN { $$.line = $1.line; $$.op = EOpSubAssign; }
+ : EQUAL { $$.op = EOpAssign; }
+ | MUL_ASSIGN { $$.op = EOpMulAssign; }
+ | DIV_ASSIGN { $$.op = EOpDivAssign; }
+ | ADD_ASSIGN { $$.op = EOpAddAssign; }
+ | SUB_ASSIGN { $$.op = EOpSubAssign; }
;
expression
@@ -940,9 +863,9 @@ expression
$$ = $1;
}
| expression COMMA assignment_expression {
- $$ = context->intermediate.addComma($1, $3, $2.line);
+ $$ = context->intermediate.addComma($1, $3, @2);
if ($$ == 0) {
- context->binaryOpError($2.line, ",", $1->getCompleteString(), $3->getCompleteString());
+ context->binaryOpError(@2, ",", $1->getCompleteString(), $3->getCompleteString());
context->recover();
$$ = $3;
}
@@ -970,13 +893,13 @@ declaration
const TParameter &param = function.getParam(i);
if (param.name != 0)
{
- TVariable *variable = new TVariable(param.name, *param.type);
+ TVariable variable(param.name, *param.type);
- prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), $1.line), $1.line);
+ prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), @1), @1);
}
else
{
- prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line);
+ prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, @1), @1);
}
}
@@ -992,11 +915,11 @@ declaration
}
| PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
if (($2 == EbpHigh) && (context->shaderType == SH_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) {
- context->error($1.line, "precision is not supported in fragment shader", "highp");
+ context->error(@1, "precision is not supported in fragment shader", "highp");
context->recover();
}
if (!context->symbolTable.setDefaultPrecision( $3, $2 )) {
- context->error($1.line, "illegal type argument for default precision qualifier", getBasicString($3.type));
+ context->error(@1, "illegal type argument for default precision qualifier", getBasicString($3.type));
context->recover();
}
$$ = 0;
@@ -1016,24 +939,41 @@ function_prototype
TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find($1->getMangledName()));
if (prevDec) {
if (prevDec->getReturnType() != $1->getReturnType()) {
- context->error($2.line, "overloaded functions must have the same return type", $1->getReturnType().getBasicString());
+ context->error(@2, "overloaded functions must have the same return type", $1->getReturnType().getBasicString());
context->recover();
}
for (size_t i = 0; i < prevDec->getParamCount(); ++i) {
if (prevDec->getParam(i).type->getQualifier() != $1->getParam(i).type->getQualifier()) {
- context->error($2.line, "overloaded functions must have the same parameter qualifiers", $1->getParam(i).type->getQualifierString());
+ context->error(@2, "overloaded functions must have the same parameter qualifiers", $1->getParam(i).type->getQualifierString());
context->recover();
}
}
}
//
+ // Check for previously declared variables using the same name.
+ //
+ TSymbol *prevSym = context->symbolTable.find($1->getName());
+ if (prevSym)
+ {
+ if (!prevSym->isFunction())
+ {
+ context->error(@2, "redefinition", $1->getName().c_str(), "function");
+ context->recover();
+ }
+ }
+ else
+ {
+ // Insert the unmangled name to detect potential future redefinition as a variable.
+ context->symbolTable.getOuterLevel()->insert($1->getName(), *$1);
+ }
+
+ //
// If this is a redeclaration, it could also be a definition,
// in which case, we want to use the variable names from this one, and not the one that's
// being redeclared. So, pass back up this declaration, not the one in the symbol table.
//
$$.function = $1;
- $$.line = $2.line;
// We're at the inner scope level of the function's arguments and body statement.
// Add the function prototype to the surrounding scope instead.
@@ -1069,7 +1009,7 @@ function_header_with_parameters
//
// This parameter > first is void
//
- context->error($2.line, "cannot be an argument type except for '(void)'", "void");
+ context->error(@2, "cannot be an argument type except for '(void)'", "void");
context->recover();
delete $3.param.type;
} else {
@@ -1083,11 +1023,11 @@ function_header_with_parameters
function_header
: fully_specified_type IDENTIFIER LEFT_PAREN {
if ($1.qualifier != EvqGlobal && $1.qualifier != EvqTemporary) {
- context->error($2.line, "no qualifiers allowed for function return", getQualifierString($1.qualifier));
+ context->error(@2, "no qualifiers allowed for function return", getQualifierString($1.qualifier));
context->recover();
}
// make sure a sampler is not involved as well...
- if (context->structQualifierErrorCheck($2.line, $1))
+ if (context->structQualifierErrorCheck(@2, $1))
context->recover();
// Add the function as a prototype after parsing it (we do not support recursion)
@@ -1102,33 +1042,31 @@ function_header
parameter_declarator
// Type + name
- : type_specifier IDENTIFIER {
+ : type_specifier identifier {
if ($1.type == EbtVoid) {
- context->error($2.line, "illegal use of type 'void'", $2.string->c_str());
+ context->error(@2, "illegal use of type 'void'", $2.string->c_str());
context->recover();
}
- if (context->reservedErrorCheck($2.line, *$2.string))
+ if (context->reservedErrorCheck(@2, *$2.string))
context->recover();
TParameter param = {$2.string, new TType($1)};
- $$.line = $2.line;
$$.param = param;
}
- | type_specifier IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+ | type_specifier identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
// Check that we can make an array out of this type
- if (context->arrayTypeErrorCheck($3.line, $1))
+ if (context->arrayTypeErrorCheck(@3, $1))
context->recover();
- if (context->reservedErrorCheck($2.line, *$2.string))
+ if (context->reservedErrorCheck(@2, *$2.string))
context->recover();
int size;
- if (context->arraySizeErrorCheck($3.line, $4, size))
+ if (context->arraySizeErrorCheck(@3, $4, size))
context->recover();
$1.setArray(true, size);
TType* type = new TType($1);
TParameter param = { $2.string, type };
- $$.line = $2.line;
$$.param = param;
}
;
@@ -1144,14 +1082,14 @@ parameter_declaration
//
: type_qualifier parameter_qualifier parameter_declarator {
$$ = $3;
- if (context->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type))
+ if (context->paramErrorCheck(@3, $1.qualifier, $2, $$.param.type))
context->recover();
}
| parameter_qualifier parameter_declarator {
$$ = $2;
- if (context->parameterSamplerErrorCheck($2.line, $1, *$2.param.type))
+ if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type))
context->recover();
- if (context->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type))
+ if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type))
context->recover();
}
//
@@ -1159,14 +1097,14 @@ parameter_declaration
//
| type_qualifier parameter_qualifier parameter_type_specifier {
$$ = $3;
- if (context->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type))
+ if (context->paramErrorCheck(@3, $1.qualifier, $2, $$.param.type))
context->recover();
}
| parameter_qualifier parameter_type_specifier {
$$ = $2;
- if (context->parameterSamplerErrorCheck($2.line, $1, *$2.param.type))
+ if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type))
context->recover();
- if (context->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type))
+ if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type))
context->recover();
}
;
@@ -1197,83 +1135,83 @@ init_declarator_list
: single_declaration {
$$ = $1;
}
- | init_declarator_list COMMA IDENTIFIER {
+ | init_declarator_list COMMA identifier {
if ($1.type.type == EbtInvariant && !$3.symbol)
{
- context->error($3.line, "undeclared identifier declared as invariant", $3.string->c_str());
+ context->error(@3, "undeclared identifier declared as invariant", $3.string->c_str());
context->recover();
}
- TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$3.string, TType($1.type), $3.line);
- $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, symbol, $3.line);
+ TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$3.string, TType($1.type), @3);
+ $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, symbol, @3);
- if (context->structQualifierErrorCheck($3.line, $$.type))
+ if (context->structQualifierErrorCheck(@3, $$.type))
context->recover();
- if (context->nonInitConstErrorCheck($3.line, *$3.string, $$.type, false))
+ if (context->nonInitConstErrorCheck(@3, *$3.string, $$.type, false))
context->recover();
TVariable* variable = 0;
- if (context->nonInitErrorCheck($3.line, *$3.string, $$.type, variable))
+ if (context->nonInitErrorCheck(@3, *$3.string, $$.type, variable))
context->recover();
if (symbol && variable)
symbol->setId(variable->getUniqueId());
}
- | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
- if (context->structQualifierErrorCheck($3.line, $1.type))
+ | init_declarator_list COMMA identifier LEFT_BRACKET RIGHT_BRACKET {
+ if (context->structQualifierErrorCheck(@3, $1.type))
context->recover();
- if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type, true))
+ if (context->nonInitConstErrorCheck(@3, *$3.string, $1.type, true))
context->recover();
$$ = $1;
- if (context->arrayTypeErrorCheck($4.line, $1.type) || context->arrayQualifierErrorCheck($4.line, $1.type))
+ if (context->arrayTypeErrorCheck(@4, $1.type) || context->arrayQualifierErrorCheck(@4, $1.type))
context->recover();
else {
$1.type.setArray(true);
TVariable* variable;
- if (context->arrayErrorCheck($4.line, *$3.string, $1.type, variable))
+ if (context->arrayErrorCheck(@4, *$3.string, $1.type, variable))
context->recover();
}
}
- | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
- if (context->structQualifierErrorCheck($3.line, $1.type))
+ | init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
+ if (context->structQualifierErrorCheck(@3, $1.type))
context->recover();
- if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type, true))
+ if (context->nonInitConstErrorCheck(@3, *$3.string, $1.type, true))
context->recover();
$$ = $1;
- if (context->arrayTypeErrorCheck($4.line, $1.type) || context->arrayQualifierErrorCheck($4.line, $1.type))
+ if (context->arrayTypeErrorCheck(@4, $1.type) || context->arrayQualifierErrorCheck(@4, $1.type))
context->recover();
else {
int size;
- if (context->arraySizeErrorCheck($4.line, $5, size))
+ if (context->arraySizeErrorCheck(@4, $5, size))
context->recover();
$1.type.setArray(true, size);
TVariable* variable = 0;
- if (context->arrayErrorCheck($4.line, *$3.string, $1.type, variable))
+ if (context->arrayErrorCheck(@4, *$3.string, $1.type, variable))
context->recover();
TType type = TType($1.type);
type.setArraySize(size);
- $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *$3.string, type, $3.line), $3.line);
+ $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *$3.string, type, @3), @3);
}
}
- | init_declarator_list COMMA IDENTIFIER EQUAL initializer {
- if (context->structQualifierErrorCheck($3.line, $1.type))
+ | init_declarator_list COMMA identifier EQUAL initializer {
+ if (context->structQualifierErrorCheck(@3, $1.type))
context->recover();
$$ = $1;
TIntermNode* intermNode;
- if (!context->executeInitializer($3.line, *$3.string, $1.type, $5, intermNode)) {
+ if (!context->executeInitializer(@3, *$3.string, $1.type, $5, intermNode)) {
//
// build the intermediate representation
//
if (intermNode)
- $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, intermNode, $4.line);
+ $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, intermNode, @4);
else
$$.intermAggregate = $1.intermAggregate;
} else {
@@ -1286,79 +1224,79 @@ init_declarator_list
single_declaration
: fully_specified_type {
$$.type = $1;
- $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), $1.line), $1.line);
+ $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), @1), @1);
}
- | fully_specified_type IDENTIFIER {
- TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line);
- $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
+ | fully_specified_type identifier {
+ TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), @2);
+ $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2);
- if (context->structQualifierErrorCheck($2.line, $$.type))
+ if (context->structQualifierErrorCheck(@2, $$.type))
context->recover();
- if (context->nonInitConstErrorCheck($2.line, *$2.string, $$.type, false))
+ if (context->nonInitConstErrorCheck(@2, *$2.string, $$.type, false))
context->recover();
$$.type = $1;
TVariable* variable = 0;
- if (context->nonInitErrorCheck($2.line, *$2.string, $$.type, variable))
+ if (context->nonInitErrorCheck(@2, *$2.string, $$.type, variable))
context->recover();
if (variable && symbol)
symbol->setId(variable->getUniqueId());
}
- | fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
- context->error($2.line, "unsized array declarations not supported", $2.string->c_str());
+ | fully_specified_type identifier LEFT_BRACKET RIGHT_BRACKET {
+ context->error(@2, "unsized array declarations not supported", $2.string->c_str());
context->recover();
- TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line);
- $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
+ TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), @2);
+ $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2);
$$.type = $1;
}
- | fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+ | fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
TType type = TType($1);
int size;
- if (context->arraySizeErrorCheck($2.line, $4, size))
+ if (context->arraySizeErrorCheck(@2, $4, size))
context->recover();
type.setArraySize(size);
- TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, type, $2.line);
- $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
+ TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, type, @2);
+ $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2);
- if (context->structQualifierErrorCheck($2.line, $1))
+ if (context->structQualifierErrorCheck(@2, $1))
context->recover();
- if (context->nonInitConstErrorCheck($2.line, *$2.string, $1, true))
+ if (context->nonInitConstErrorCheck(@2, *$2.string, $1, true))
context->recover();
$$.type = $1;
- if (context->arrayTypeErrorCheck($3.line, $1) || context->arrayQualifierErrorCheck($3.line, $1))
+ if (context->arrayTypeErrorCheck(@3, $1) || context->arrayQualifierErrorCheck(@3, $1))
context->recover();
else {
int size;
- if (context->arraySizeErrorCheck($3.line, $4, size))
+ if (context->arraySizeErrorCheck(@3, $4, size))
context->recover();
$1.setArray(true, size);
TVariable* variable = 0;
- if (context->arrayErrorCheck($3.line, *$2.string, $1, variable))
+ if (context->arrayErrorCheck(@3, *$2.string, $1, variable))
context->recover();
if (variable && symbol)
symbol->setId(variable->getUniqueId());
}
}
- | fully_specified_type IDENTIFIER EQUAL initializer {
- if (context->structQualifierErrorCheck($2.line, $1))
+ | fully_specified_type identifier EQUAL initializer {
+ if (context->structQualifierErrorCheck(@2, $1))
context->recover();
$$.type = $1;
TIntermNode* intermNode;
- if (!context->executeInitializer($2.line, *$2.string, $1, $4, intermNode)) {
+ if (!context->executeInitializer(@2, *$2.string, $1, $4, intermNode)) {
//
// Build intermediate representation
//
if(intermNode)
- $$.intermAggregate = context->intermediate.makeAggregate(intermNode, $3.line);
+ $$.intermAggregate = context->intermediate.makeAggregate(intermNode, @3);
else
$$.intermAggregate = 0;
} else {
@@ -1367,118 +1305,50 @@ single_declaration
}
}
| INVARIANT IDENTIFIER {
- VERTEX_ONLY("invariant declaration", $1.line);
- if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "invariant varying"))
+ VERTEX_ONLY("invariant declaration", @1);
+ if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying"))
context->recover();
- $$.type.setBasic(EbtInvariant, EvqInvariantVaryingOut, $2.line);
+ $$.type.setBasic(EbtInvariant, EvqInvariantVaryingOut, @2);
if (!$2.symbol)
{
- context->error($2.line, "undeclared identifier declared as invariant", $2.string->c_str());
+ context->error(@2, "undeclared identifier declared as invariant", $2.string->c_str());
context->recover();
$$.intermAggregate = 0;
}
else
{
- TIntermSymbol *symbol = context->intermediate.addSymbol(0, *$2.string, TType($$.type), $2.line);
- $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
+ TIntermSymbol *symbol = context->intermediate.addSymbol(0, *$2.string, TType($$.type), @2);
+ $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2);
}
}
-
-//
-// Place holder for the pack/unpack languages.
-//
-// | buffer_specifier {
-// $$.intermAggregate = 0;
-// }
;
-// Grammar Note: No 'enum', or 'typedef'.
-
-//
-// Place holder for the pack/unpack languages.
-//
-//%type <interm> buffer_declaration
-//%type <interm.type> buffer_specifier input_or_output buffer_declaration_list
-//buffer_specifier
-// : input_or_output LEFT_BRACE buffer_declaration_list RIGHT_BRACE {
-// }
-// ;
-//
-//input_or_output
-// : INPUT {
-// if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "input"))
-// context->recover();
-// UNPACK_ONLY("input", $1.line);
-// $$.qualifier = EvqInput;
-// }
-// | OUTPUT {
-// if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "output"))
-// context->recover();
-// PACK_ONLY("output", $1.line);
-// $$.qualifier = EvqOutput;
-// }
-// ;
-
-//
-// Place holder for the pack/unpack languages.
-//
-//buffer_declaration_list
-// : buffer_declaration {
-// }
-// | buffer_declaration_list buffer_declaration {
-// }
-// ;
-
-//
-// Input/output semantics:
-// float must be 16 or 32 bits
-// float alignment restrictions?
-// check for only one input and only one output
-// sum of bitfields has to be multiple of 32
-//
-
-//
-// Place holder for the pack/unpack languages.
-//
-//buffer_declaration
-// : type_specifier IDENTIFIER COLON constant_expression SEMICOLON {
-// if (context->reservedErrorCheck($2.line, *$2.string, context))
-// context->recover();
-// $$.variable = new TVariable($2.string, $1);
-// if (! context->symbolTable.insert(*$$.variable)) {
-// context->error($2.line, "redefinition", $$.variable->getName().c_str());
-// context->recover();
-// // don't have to delete $$.variable, the pool pop will take care of it
-// }
-// }
-// ;
-
fully_specified_type
: type_specifier {
$$ = $1;
if ($1.array) {
- context->error($1.line, "not supported", "first-class array");
+ context->error(@1, "not supported", "first-class array");
context->recover();
$1.setArray(false);
}
}
| type_qualifier type_specifier {
if ($2.array) {
- context->error($2.line, "not supported", "first-class array");
+ context->error(@2, "not supported", "first-class array");
context->recover();
$2.setArray(false);
}
if ($1.qualifier == EvqAttribute &&
($2.type == EbtBool || $2.type == EbtInt)) {
- context->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier));
+ context->error(@2, "cannot be bool or int", getQualifierString($1.qualifier));
context->recover();
}
if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) &&
($2.type == EbtBool || $2.type == EbtInt)) {
- context->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier));
+ context->error(@2, "cannot be bool or int", getQualifierString($1.qualifier));
context->recover();
}
$$ = $2;
@@ -1488,34 +1358,34 @@ fully_specified_type
type_qualifier
: CONST_QUAL {
- $$.setBasic(EbtVoid, EvqConst, $1.line);
+ $$.setBasic(EbtVoid, EvqConst, @1);
}
| ATTRIBUTE {
- VERTEX_ONLY("attribute", $1.line);
- if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "attribute"))
+ VERTEX_ONLY("attribute", @1);
+ if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "attribute"))
context->recover();
- $$.setBasic(EbtVoid, EvqAttribute, $1.line);
+ $$.setBasic(EbtVoid, EvqAttribute, @1);
}
| VARYING {
- if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "varying"))
+ if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "varying"))
context->recover();
if (context->shaderType == SH_VERTEX_SHADER)
- $$.setBasic(EbtVoid, EvqVaryingOut, $1.line);
+ $$.setBasic(EbtVoid, EvqVaryingOut, @1);
else
- $$.setBasic(EbtVoid, EvqVaryingIn, $1.line);
+ $$.setBasic(EbtVoid, EvqVaryingIn, @1);
}
| INVARIANT VARYING {
- if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "invariant varying"))
+ if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying"))
context->recover();
if (context->shaderType == SH_VERTEX_SHADER)
- $$.setBasic(EbtVoid, EvqInvariantVaryingOut, $1.line);
+ $$.setBasic(EbtVoid, EvqInvariantVaryingOut, @1);
else
- $$.setBasic(EbtVoid, EvqInvariantVaryingIn, $1.line);
+ $$.setBasic(EbtVoid, EvqInvariantVaryingIn, @1);
}
| UNIFORM {
- if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "uniform"))
+ if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "uniform"))
context->recover();
- $$.setBasic(EbtVoid, EvqUniform, $1.line);
+ $$.setBasic(EbtVoid, EvqUniform, @1);
}
;
@@ -1525,7 +1395,7 @@ type_specifier
if ($$.precision == EbpUndefined) {
$$.precision = context->symbolTable.getDefaultPrecision($1.type);
- if (context->precisionErrorCheck($1.line, $$.precision, $1.type)) {
+ if (context->precisionErrorCheck(@1, $$.precision, $1.type)) {
context->recover();
}
}
@@ -1555,11 +1425,11 @@ type_specifier_no_prec
| type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET {
$$ = $1;
- if (context->arrayTypeErrorCheck($2.line, $1))
+ if (context->arrayTypeErrorCheck(@2, $1))
context->recover();
else {
int size;
- if (context->arraySizeErrorCheck($2.line, $3, size))
+ if (context->arraySizeErrorCheck(@2, $3, size))
context->recover();
$$.setArray(true, size);
}
@@ -1569,118 +1439,105 @@ type_specifier_no_prec
type_specifier_nonarray
: VOID_TYPE {
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtVoid, qual, $1.line);
+ $$.setBasic(EbtVoid, qual, @1);
}
| FLOAT_TYPE {
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtFloat, qual, $1.line);
+ $$.setBasic(EbtFloat, qual, @1);
}
| INT_TYPE {
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtInt, qual, $1.line);
+ $$.setBasic(EbtInt, qual, @1);
}
| BOOL_TYPE {
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtBool, qual, $1.line);
+ $$.setBasic(EbtBool, qual, @1);
}
-// | UNSIGNED INT_TYPE {
-// PACK_UNPACK_ONLY("unsigned", $1.line);
-// TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
-// $$.setBasic(EbtInt, qual, $1.line);
-// }
| VEC2 {
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtFloat, qual, $1.line);
+ $$.setBasic(EbtFloat, qual, @1);
$$.setAggregate(2);
}
| VEC3 {
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtFloat, qual, $1.line);
+ $$.setBasic(EbtFloat, qual, @1);
$$.setAggregate(3);
}
| VEC4 {
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtFloat, qual, $1.line);
+ $$.setBasic(EbtFloat, qual, @1);
$$.setAggregate(4);
}
| BVEC2 {
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtBool, qual, $1.line);
+ $$.setBasic(EbtBool, qual, @1);
$$.setAggregate(2);
}
| BVEC3 {
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtBool, qual, $1.line);
+ $$.setBasic(EbtBool, qual, @1);
$$.setAggregate(3);
}
| BVEC4 {
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtBool, qual, $1.line);
+ $$.setBasic(EbtBool, qual, @1);
$$.setAggregate(4);
}
| IVEC2 {
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtInt, qual, $1.line);
+ $$.setBasic(EbtInt, qual, @1);
$$.setAggregate(2);
}
| IVEC3 {
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtInt, qual, $1.line);
+ $$.setBasic(EbtInt, qual, @1);
$$.setAggregate(3);
}
| IVEC4 {
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtInt, qual, $1.line);
+ $$.setBasic(EbtInt, qual, @1);
$$.setAggregate(4);
}
| MATRIX2 {
- FRAG_VERT_ONLY("mat2", $1.line);
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtFloat, qual, $1.line);
+ $$.setBasic(EbtFloat, qual, @1);
$$.setAggregate(2, true);
}
| MATRIX3 {
- FRAG_VERT_ONLY("mat3", $1.line);
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtFloat, qual, $1.line);
+ $$.setBasic(EbtFloat, qual, @1);
$$.setAggregate(3, true);
}
| MATRIX4 {
- FRAG_VERT_ONLY("mat4", $1.line);
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtFloat, qual, $1.line);
+ $$.setBasic(EbtFloat, qual, @1);
$$.setAggregate(4, true);
}
| SAMPLER2D {
- FRAG_VERT_ONLY("sampler2D", $1.line);
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtSampler2D, qual, $1.line);
+ $$.setBasic(EbtSampler2D, qual, @1);
}
| SAMPLERCUBE {
- FRAG_VERT_ONLY("samplerCube", $1.line);
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtSamplerCube, qual, $1.line);
+ $$.setBasic(EbtSamplerCube, qual, @1);
}
| SAMPLER_EXTERNAL_OES {
if (!context->supportsExtension("GL_OES_EGL_image_external")) {
- context->error($1.line, "unsupported type", "samplerExternalOES");
+ context->error(@1, "unsupported type", "samplerExternalOES");
context->recover();
}
- FRAG_VERT_ONLY("samplerExternalOES", $1.line);
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtSamplerExternalOES, qual, $1.line);
+ $$.setBasic(EbtSamplerExternalOES, qual, @1);
}
| SAMPLER2DRECT {
if (!context->supportsExtension("GL_ARB_texture_rectangle")) {
- context->error($1.line, "unsupported type", "sampler2DRect");
+ context->error(@1, "unsupported type", "sampler2DRect");
context->recover();
}
- FRAG_VERT_ONLY("sampler2DRect", $1.line);
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtSampler2DRect, qual, $1.line);
+ $$.setBasic(EbtSampler2DRect, qual, @1);
}
| struct_specifier {
- FRAG_VERT_ONLY("struct", $1.line);
$$ = $1;
$$.qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
}
@@ -1691,29 +1548,29 @@ type_specifier_nonarray
//
TType& structure = static_cast<TVariable*>($1.symbol)->getType();
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtStruct, qual, $1.line);
+ $$.setBasic(EbtStruct, qual, @1);
$$.userDef = &structure;
}
;
struct_specifier
- : STRUCT IDENTIFIER LEFT_BRACE { if (context->enterStructDeclaration($2.line, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
- if (context->reservedErrorCheck($2.line, *$2.string))
+ : STRUCT identifier LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
+ if (context->reservedErrorCheck(@2, *$2.string))
context->recover();
- TType* structure = new TType($5, *$2.string);
+ TType* structure = new TType(new TStructure($2.string, $5));
TVariable* userTypeDef = new TVariable($2.string, *structure, true);
if (! context->symbolTable.insert(*userTypeDef)) {
- context->error($2.line, "redefinition", $2.string->c_str(), "struct");
+ context->error(@2, "redefinition", $2.string->c_str(), "struct");
context->recover();
}
- $$.setBasic(EbtStruct, EvqTemporary, $1.line);
+ $$.setBasic(EbtStruct, EvqTemporary, @1);
$$.userDef = structure;
context->exitStructDeclaration();
}
- | STRUCT LEFT_BRACE { if (context->enterStructDeclaration($2.line, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
- TType* structure = new TType($4, TString(""));
- $$.setBasic(EbtStruct, EvqTemporary, $1.line);
+ | STRUCT LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
+ TType* structure = new TType(new TStructure(NewPoolTString(""), $4));
+ $$.setBasic(EbtStruct, EvqTemporary, @1);
$$.userDef = structure;
context->exitStructDeclaration();
}
@@ -1725,14 +1582,15 @@ struct_declaration_list
}
| struct_declaration_list struct_declaration {
$$ = $1;
- for (unsigned int i = 0; i < $2->size(); ++i) {
- for (unsigned int j = 0; j < $$->size(); ++j) {
- if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName()) {
- context->error((*$2)[i].line, "duplicate field name in structure:", "struct", (*$2)[i].type->getFieldName().c_str());
+ for (size_t i = 0; i < $2->size(); ++i) {
+ TField* field = (*$2)[i];
+ for (size_t j = 0; j < $$->size(); ++j) {
+ if ((*$$)[j]->name() == field->name()) {
+ context->error(@2, "duplicate field name in structure:", "struct", field->name().c_str());
context->recover();
}
}
- $$->push_back((*$2)[i]);
+ $$->push_back(field);
}
}
;
@@ -1741,14 +1599,14 @@ struct_declaration
: type_specifier struct_declarator_list SEMICOLON {
$$ = $2;
- if (context->voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) {
+ if (context->voidErrorCheck(@1, (*$2)[0]->name(), $1)) {
context->recover();
}
for (unsigned int i = 0; i < $$->size(); ++i) {
//
// Careful not to replace already known aspects of type, like array-ness
//
- TType* type = (*$$)[i].type;
+ TType* type = (*$$)[i]->type();
type->setBasicType($1.type);
type->setNominalSize($1.size);
type->setMatrix($1.matrix);
@@ -1756,26 +1614,23 @@ struct_declaration
// don't allow arrays of arrays
if (type->isArray()) {
- if (context->arrayTypeErrorCheck($1.line, $1))
+ if (context->arrayTypeErrorCheck(@1, $1))
context->recover();
}
if ($1.array)
type->setArraySize($1.arraySize);
- if ($1.userDef) {
+ if ($1.userDef)
type->setStruct($1.userDef->getStruct());
- type->setTypeName($1.userDef->getTypeName());
- }
- if (context->structNestingErrorCheck($1.line, *type)) {
+ if (context->structNestingErrorCheck(@1, *(*$$)[i]))
context->recover();
- }
}
}
;
struct_declarator_list
: struct_declarator {
- $$ = NewPoolTTypeList();
+ $$ = NewPoolTFieldList();
$$->push_back($1);
}
| struct_declarator_list COMMA struct_declarator {
@@ -1784,26 +1639,24 @@ struct_declarator_list
;
struct_declarator
- : IDENTIFIER {
- if (context->reservedErrorCheck($1.line, *$1.string))
+ : identifier {
+ if (context->reservedErrorCheck(@1, *$1.string))
context->recover();
- $$.type = new TType(EbtVoid, EbpUndefined);
- $$.line = $1.line;
- $$.type->setFieldName(*$1.string);
+ TType* type = new TType(EbtVoid, EbpUndefined);
+ $$ = new TField(type, $1.string);
}
- | IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
- if (context->reservedErrorCheck($1.line, *$1.string))
+ | identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
+ if (context->reservedErrorCheck(@1, *$1.string))
context->recover();
- $$.type = new TType(EbtVoid, EbpUndefined);
- $$.line = $1.line;
- $$.type->setFieldName(*$1.string);
-
- int size;
- if (context->arraySizeErrorCheck($2.line, $3, size))
+ TType* type = new TType(EbtVoid, EbpUndefined);
+ int size = 0;
+ if (context->arraySizeErrorCheck(@3, $3, size))
context->recover();
- $$.type->setArraySize(size);
+ type->setArraySize(size);
+
+ $$ = new TField(type, $1.string);
}
;
@@ -1835,7 +1688,7 @@ compound_statement
| LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE {
if ($3 != 0) {
$3->setOp(EOpSequence);
- $3->setEndLine($5.line);
+ $3->setLine(@$);
}
$$ = $3;
}
@@ -1859,7 +1712,7 @@ compound_statement_no_new_scope
| LEFT_BRACE statement_list RIGHT_BRACE {
if ($2) {
$2->setOp(EOpSequence);
- $2->setEndLine($3.line);
+ $2->setLine(@$);
}
$$ = $2;
}
@@ -1867,10 +1720,10 @@ compound_statement_no_new_scope
statement_list
: statement {
- $$ = context->intermediate.makeAggregate($1, 0);
+ $$ = context->intermediate.makeAggregate($1, @$);
}
| statement_list statement {
- $$ = context->intermediate.growAggregate($1, $2, 0);
+ $$ = context->intermediate.growAggregate($1, $2, @$);
}
;
@@ -1881,9 +1734,9 @@ expression_statement
selection_statement
: IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
- if (context->boolErrorCheck($1.line, $3))
+ if (context->boolErrorCheck(@1, $3))
context->recover();
- $$ = context->intermediate.addSelection($3, $5, $1.line);
+ $$ = context->intermediate.addSelection($3, $5, @1);
}
;
@@ -1907,14 +1760,14 @@ condition
if (context->boolErrorCheck($1->getLine(), $1))
context->recover();
}
- | fully_specified_type IDENTIFIER EQUAL initializer {
+ | fully_specified_type identifier EQUAL initializer {
TIntermNode* intermNode;
- if (context->structQualifierErrorCheck($2.line, $1))
+ if (context->structQualifierErrorCheck(@2, $1))
context->recover();
- if (context->boolErrorCheck($2.line, $1))
+ if (context->boolErrorCheck(@2, $1))
context->recover();
- if (!context->executeInitializer($2.line, *$2.string, $1, $4, intermNode))
+ if (!context->executeInitializer(@2, *$2.string, $1, $4, intermNode))
$$ = $4;
else {
context->recover();
@@ -1926,19 +1779,19 @@ condition
iteration_statement
: WHILE LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope {
context->symbolTable.pop();
- $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, $1.line);
+ $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, @1);
--context->loopNestingLevel;
}
| DO { ++context->loopNestingLevel; } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
- if (context->boolErrorCheck($8.line, $6))
+ if (context->boolErrorCheck(@8, $6))
context->recover();
- $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, $4.line);
+ $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, @4);
--context->loopNestingLevel;
}
| FOR LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
context->symbolTable.pop();
- $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), $7, $1.line);
+ $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), $7, @1);
--context->loopNestingLevel;
}
;
@@ -1975,39 +1828,39 @@ for_rest_statement
jump_statement
: CONTINUE SEMICOLON {
if (context->loopNestingLevel <= 0) {
- context->error($1.line, "continue statement only allowed in loops", "");
+ context->error(@1, "continue statement only allowed in loops", "");
context->recover();
}
- $$ = context->intermediate.addBranch(EOpContinue, $1.line);
+ $$ = context->intermediate.addBranch(EOpContinue, @1);
}
| BREAK SEMICOLON {
if (context->loopNestingLevel <= 0) {
- context->error($1.line, "break statement only allowed in loops", "");
+ context->error(@1, "break statement only allowed in loops", "");
context->recover();
}
- $$ = context->intermediate.addBranch(EOpBreak, $1.line);
+ $$ = context->intermediate.addBranch(EOpBreak, @1);
}
| RETURN SEMICOLON {
- $$ = context->intermediate.addBranch(EOpReturn, $1.line);
+ $$ = context->intermediate.addBranch(EOpReturn, @1);
if (context->currentFunctionType->getBasicType() != EbtVoid) {
- context->error($1.line, "non-void function must return a value", "return");
+ context->error(@1, "non-void function must return a value", "return");
context->recover();
}
}
| RETURN expression SEMICOLON {
- $$ = context->intermediate.addBranch(EOpReturn, $2, $1.line);
+ $$ = context->intermediate.addBranch(EOpReturn, $2, @1);
context->functionReturnsValue = true;
if (context->currentFunctionType->getBasicType() == EbtVoid) {
- context->error($1.line, "void function cannot return a value", "return");
+ context->error(@1, "void function cannot return a value", "return");
context->recover();
} else if (*(context->currentFunctionType) != $2->getType()) {
- context->error($1.line, "function return is not matching type:", "return");
+ context->error(@1, "function return is not matching type:", "return");
context->recover();
}
}
| DISCARD SEMICOLON {
- FRAG_ONLY("discard", $1.line);
- $$ = context->intermediate.addBranch(EOpKill, $1.line);
+ FRAG_ONLY("discard", @1);
+ $$ = context->intermediate.addBranch(EOpKill, @1);
}
;
@@ -2019,7 +1872,7 @@ translation_unit
context->treeRoot = $$;
}
| translation_unit external_declaration {
- $$ = context->intermediate.growAggregate($1, $2, 0);
+ $$ = context->intermediate.growAggregate($1, $2, @$);
context->treeRoot = $$;
}
;
@@ -2041,7 +1894,7 @@ function_definition
if (builtIn)
{
- context->error($1.line, "built-in functions cannot be redefined", function->getName().c_str());
+ context->error(@1, "built-in functions cannot be redefined", function->getName().c_str());
context->recover();
}
@@ -2055,7 +1908,7 @@ function_definition
//
// Then this function already has a body.
//
- context->error($1.line, "function already has a body", function->getName().c_str());
+ context->error(@1, "function already has a body", function->getName().c_str());
context->recover();
}
prevDec->setDefined();
@@ -2065,11 +1918,11 @@ function_definition
//
if (function->getName() == "main") {
if (function->getParamCount() > 0) {
- context->error($1.line, "function cannot take any parameter(s)", function->getName().c_str());
+ context->error(@1, "function cannot take any parameter(s)", function->getName().c_str());
context->recover();
}
if (function->getReturnType().getBasicType() != EbtVoid) {
- context->error($1.line, "", function->getReturnType().getBasicString(), "main function cannot return a value");
+ context->error(@1, "", function->getReturnType().getBasicString(), "main function cannot return a value");
context->recover();
}
}
@@ -2097,7 +1950,7 @@ function_definition
// Insert the parameters with name in the symbol table.
//
if (! context->symbolTable.insert(*variable)) {
- context->error($1.line, "redefinition", variable->getName().c_str());
+ context->error(@1, "redefinition", variable->getName().c_str());
context->recover();
delete variable;
}
@@ -2108,14 +1961,15 @@ function_definition
paramNodes = context->intermediate.growAggregate(
paramNodes,
context->intermediate.addSymbol(variable->getUniqueId(),
- variable->getName(),
- variable->getType(), $1.line),
- $1.line);
+ variable->getName(),
+ variable->getType(),
+ @1),
+ @1);
} else {
- paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line);
+ paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, @1), @1);
}
}
- context->intermediate.setAggregateOperator(paramNodes, EOpParameters, $1.line);
+ context->intermediate.setAggregateOperator(paramNodes, EOpParameters, @1);
$1.intermAggregate = paramNodes;
context->loopNestingLevel = 0;
}
@@ -2123,12 +1977,12 @@ function_definition
//?? Check that all paths return a value if return type != void ?
// May be best done as post process phase on intermediate code
if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) {
- context->error($1.line, "function does not return a value:", "", $1.function->getName().c_str());
+ context->error(@1, "function does not return a value:", "", $1.function->getName().c_str());
context->recover();
}
- $$ = context->intermediate.growAggregate($1.intermAggregate, $3, 0);
- context->intermediate.setAggregateOperator($$, EOpFunction, $1.line);
+ $$ = context->intermediate.growAggregate($1.intermAggregate, $3, @$);
+ context->intermediate.setAggregateOperator($$, EOpFunction, @1);
$$->getAsAggregate()->setName($1.function->getMangledName().c_str());
$$->getAsAggregate()->setType($1.function->getReturnType());
@@ -2137,9 +1991,6 @@ function_definition
$$->getAsAggregate()->setOptimize(context->pragma().optimize);
$$->getAsAggregate()->setDebug(context->pragma().debug);
- if ($3 && $3->getAsAggregate())
- $$->getAsAggregate()->setEndLine($3->getAsAggregate()->getEndLine());
-
context->symbolTable.pop();
}
;
diff --git a/src/3rdparty/angle/src/compiler/intermOut.cpp b/src/3rdparty/angle/src/compiler/intermOut.cpp
index f48a049c63..13aa96af6d 100644
--- a/src/3rdparty/angle/src/compiler/intermOut.cpp
+++ b/src/3rdparty/angle/src/compiler/intermOut.cpp
@@ -189,7 +189,9 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node)
case EOpAny: out << "any"; break;
case EOpAll: out << "all"; break;
- default: out.message(EPrefixError, "Bad unary op");
+ default:
+ out.prefix(EPrefixError);
+ out << "Bad unary op";
}
out << " (" << node->getCompleteString() << ")";
@@ -204,7 +206,8 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
TInfoSinkBase& out = sink;
if (node->getOp() == EOpNull) {
- out.message(EPrefixError, "node is still EOpNull!");
+ out.prefix(EPrefixError);
+ out << "node is still EOpNull!";
return true;
}
@@ -263,7 +266,9 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
case EOpDeclaration: out << "Declaration: "; break;
- default: out.message(EPrefixError, "Bad aggregation op");
+ default:
+ out.prefix(EPrefixError);
+ out << "Bad aggregation op";
}
if (node->getOp() != EOpSequence && node->getOp() != EOpParameters)
@@ -311,9 +316,9 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
{
TInfoSinkBase& out = sink;
- int size = node->getType().getObjectSize();
+ size_t size = node->getType().getObjectSize();
- for (int i = 0; i < size; i++) {
+ for (size_t i = 0; i < size; i++) {
OutputTreeText(out, node, depth);
switch (node->getUnionArrayPointer()[i].getType()) {
case EbtBool:
@@ -334,7 +339,7 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
out << " (const int)\n";
break;
default:
- out.message(EPrefixInternalError, "Unknown constant", node->getLine());
+ out.message(EPrefixInternalError, node->getLine(), "Unknown constant");
break;
}
}
diff --git a/src/3rdparty/angle/src/compiler/intermediate.h b/src/3rdparty/angle/src/compiler/intermediate.h
index 8e76ef921f..738621fe70 100644
--- a/src/3rdparty/angle/src/compiler/intermediate.h
+++ b/src/3rdparty/angle/src/compiler/intermediate.h
@@ -18,6 +18,7 @@
#include "GLSLANG/ShaderLang.h"
+#include <algorithm>
#include "compiler/Common.h"
#include "compiler/Types.h"
#include "compiler/ConstantUnion.h"
@@ -204,12 +205,17 @@ class TInfoSink;
//
class TIntermNode {
public:
- POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
-
- TIntermNode() : line(0) {}
+ POOL_ALLOCATOR_NEW_DELETE();
+ TIntermNode() {
+ // TODO: Move this to TSourceLoc constructor
+ // after getting rid of TPublicType.
+ line.first_file = line.last_file = 0;
+ line.first_line = line.last_line = 0;
+ }
+ virtual ~TIntermNode() { }
- TSourceLoc getLine() const { return line; }
- void setLine(TSourceLoc l) { line = l; }
+ const TSourceLoc& getLine() const { return line; }
+ void setLine(const TSourceLoc& l) { line = l; }
virtual void traverse(TIntermTraverser*) = 0;
virtual TIntermTyped* getAsTyped() { return 0; }
@@ -220,7 +226,6 @@ public:
virtual TIntermSelection* getAsSelectionNode() { return 0; }
virtual TIntermSymbol* getAsSymbolNode() { return 0; }
virtual TIntermLoop* getAsLoopNode() { return 0; }
- virtual ~TIntermNode() { }
protected:
TSourceLoc line;
@@ -454,7 +459,7 @@ typedef TVector<int> TQualifierList;
//
class TIntermAggregate : public TIntermOperator {
public:
- TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), endLine(0), useEmulatedFunction(false) { }
+ TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), useEmulatedFunction(false) { }
TIntermAggregate(TOperator o) : TIntermOperator(o), useEmulatedFunction(false) { }
~TIntermAggregate() { }
@@ -474,9 +479,6 @@ public:
void setDebug(bool d) { debug = d; }
bool getDebug() { return debug; }
- void setEndLine(TSourceLoc line) { endLine = line; }
- TSourceLoc getEndLine() const { return endLine; }
-
void setUseEmulatedFunction() { useEmulatedFunction = true; }
bool getUseEmulatedFunction() { return useEmulatedFunction; }
@@ -489,7 +491,6 @@ protected:
bool optimize;
bool debug;
- TSourceLoc endLine;
// If set to true, replace the built-in function call with an emulated one
// to work around driver bugs.
@@ -538,14 +539,14 @@ enum Visit
class TIntermTraverser
{
public:
- POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
-
+ POOL_ALLOCATOR_NEW_DELETE();
TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
preVisit(preVisit),
inVisit(inVisit),
postVisit(postVisit),
rightToLeft(rightToLeft),
- depth(0) {}
+ depth(0),
+ maxDepth(0) {}
virtual ~TIntermTraverser() {};
virtual void visitSymbol(TIntermSymbol*) {}
@@ -557,7 +558,8 @@ public:
virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;}
virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;}
- void incrementDepth() {depth++;}
+ int getMaxDepth() const {return maxDepth;}
+ void incrementDepth() {depth++; maxDepth = std::max(maxDepth, depth); }
void decrementDepth() {depth--;}
// Return the original name if hash function pointer is NULL;
@@ -571,6 +573,7 @@ public:
protected:
int depth;
+ int maxDepth;
};
#endif // __INTERMEDIATE_H
diff --git a/src/3rdparty/angle/src/compiler/localintermediate.h b/src/3rdparty/angle/src/compiler/localintermediate.h
index 56890bd569..1214d821eb 100644
--- a/src/3rdparty/angle/src/compiler/localintermediate.h
+++ b/src/3rdparty/angle/src/compiler/localintermediate.h
@@ -22,37 +22,36 @@ struct TVectorFields {
class TInfoSink;
class TIntermediate {
public:
- POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
-
+ POOL_ALLOCATOR_NEW_DELETE();
TIntermediate(TInfoSink& i) : infoSink(i) { }
- TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc);
+
+ TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TSourceLoc&);
TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
- TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, TSymbolTable&);
- TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
- TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
- TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, TSourceLoc, TSymbolTable&);
- TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc);
- TIntermAggregate* makeAggregate(TIntermNode* node, TSourceLoc);
- TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, TSourceLoc);
- TIntermNode* addSelection(TIntermTyped* cond, TIntermNodePair code, TSourceLoc);
- TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc);
- TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc);
- TIntermConstantUnion* addConstantUnion(ConstantUnion*, const TType&, TSourceLoc);
+ TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&, TSymbolTable&);
+ TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
+ TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&);
+ TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, const TSourceLoc&, TSymbolTable&);
+ TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&);
+ TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&);
+ TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, const TSourceLoc&);
+ TIntermNode* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&);
+ TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&);
+ TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
+ TIntermConstantUnion* addConstantUnion(ConstantUnion*, const TType&, const TSourceLoc&);
TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ;
- bool parseConstTree(TSourceLoc, TIntermNode*, ConstantUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false);
- TIntermNode* addLoop(TLoopType, TIntermNode*, TIntermTyped*, TIntermTyped*, TIntermNode*, TSourceLoc);
- TIntermBranch* addBranch(TOperator, TSourceLoc);
- TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc);
- TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc);
+ bool parseConstTree(const TSourceLoc&, TIntermNode*, ConstantUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false);
+ TIntermNode* addLoop(TLoopType, TIntermNode*, TIntermTyped*, TIntermTyped*, TIntermNode*, const TSourceLoc&);
+ TIntermBranch* addBranch(TOperator, const TSourceLoc&);
+ TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
+ TIntermTyped* addSwizzle(TVectorFields&, const TSourceLoc&);
bool postProcess(TIntermNode*);
- void remove(TIntermNode*);
+ void remove(TIntermNode*);
void outputTree(TIntermNode*);
-
-protected:
- TInfoSink& infoSink;
private:
void operator=(TIntermediate&); // prevent assignments
+
+ TInfoSink& infoSink;
};
#endif // _LOCAL_INTERMEDIATE_INCLUDED_
diff --git a/src/3rdparty/angle/src/compiler/parseConst.cpp b/src/3rdparty/angle/src/compiler/parseConst.cpp
index 421d31f586..1cc5db8d77 100644
--- a/src/3rdparty/angle/src/compiler/parseConst.cpp
+++ b/src/3rdparty/angle/src/compiler/parseConst.cpp
@@ -38,16 +38,16 @@ protected:
bool visitLoop(Visit visit, TIntermLoop*);
bool visitBranch(Visit visit, TIntermBranch*);
- int index;
+ size_t index;
ConstantUnion *unionArray;
TType type;
TOperator constructorType;
bool singleConstantParam;
TInfoSink& infoSink;
TSymbolTable& symbolTable;
- int size; // size of the constructor ( 4 for vec4)
+ size_t size; // size of the constructor ( 4 for vec4)
bool isMatrix;
- int matrixSize; // dimension of the matrix (nominal size and not the instance size)
+ size_t matrixSize; // dimension of the matrix (nominal size and not the instance size)
};
//
@@ -61,7 +61,7 @@ protected:
void TConstTraverser::visitSymbol(TIntermSymbol* node)
{
- infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine());
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Symbol Node found in constant constructor");
return;
}
@@ -74,12 +74,12 @@ bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
TString buf;
buf.append("'constructor' : assigning non-constant to ");
buf.append(type.getCompleteString());
- infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
+ infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
error = true;
return false;
}
- infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine());
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Binary Node found in constant constructor");
return false;
}
@@ -89,7 +89,7 @@ bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
TString buf;
buf.append("'constructor' : assigning non-constant to ");
buf.append(type.getCompleteString());
- infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
+ infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
error = true;
return false;
}
@@ -100,7 +100,7 @@ bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
TString buf;
buf.append("'constructor' : assigning non-constant to ");
buf.append(type.getCompleteString());
- infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
+ infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
error = true;
return false;
}
@@ -144,7 +144,7 @@ bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node)
{
- infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine());
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Selection Node found in constant constructor");
error = true;
return false;
}
@@ -159,16 +159,16 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
}
ConstantUnion* leftUnionArray = unionArray;
- int instanceSize = type.getObjectSize();
+ size_t instanceSize = type.getObjectSize();
if (index >= instanceSize)
return;
if (!singleConstantParam) {
- int size = node->getType().getObjectSize();
+ size_t size = node->getType().getObjectSize();
ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
- for (int i=0; i < size; i++) {
+ for (size_t i = 0; i < size; i++) {
if (index >= instanceSize)
return;
leftUnionArray[index] = rightUnionArray[i];
@@ -176,11 +176,11 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
(index)++;
}
} else {
- int totalSize = index + size;
+ size_t totalSize = index + size;
ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
if (!isMatrix) {
- int count = 0;
- for (int i = index; i < totalSize; i++) {
+ size_t count = 0;
+ for (size_t i = index; i < totalSize; i++) {
if (i >= instanceSize)
return;
@@ -192,9 +192,9 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
count++;
}
} else { // for matrix constructors
- int count = 0;
- int element = index;
- for (int i = index; i < totalSize; i++) {
+ size_t count = 0;
+ size_t element = index;
+ for (size_t i = index; i < totalSize; i++) {
if (i >= instanceSize)
return;
if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 )
@@ -213,14 +213,14 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node)
{
- infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Loop Node found in constant constructor");
error = true;
return false;
}
bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
{
- infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Branch Node found in constant constructor");
error = true;
return false;
}
@@ -230,7 +230,7 @@ bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
// Individual functions can be initialized to 0 to skip processing of that
// type of node. It's children will still be processed.
//
-bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam)
+bool TIntermediate::parseConstTree(const TSourceLoc& line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam)
{
if (root == 0)
return false;
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp
index 5ffc6420bc..b615c85dce 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp
@@ -81,6 +81,11 @@ void Preprocessor::predefineMacro(const char* name, int value)
mImpl->macroSet[name] = macro;
}
+void Preprocessor::setMaxTokenLength(size_t maxLength)
+{
+ mImpl->tokenizer.setMaxTokenLength(maxLength);
+}
+
void Preprocessor::lex(Token* token)
{
bool validToken = false;
@@ -95,34 +100,6 @@ void Preprocessor::lex(Token* token)
case Token::PP_HASH:
assert(false);
break;
- case Token::CONST_INT:
- {
- int val = 0;
- if (!token->iValue(&val))
- {
- // Do not mark the token as invalid.
- // Just emit the diagnostic and reset value to 0.
- mImpl->diagnostics->report(Diagnostics::INTEGER_OVERFLOW,
- token->location, token->text);
- token->text.assign("0");
- }
- validToken = true;
- break;
- }
- case Token::CONST_FLOAT:
- {
- float val = 0;
- if (!token->fValue(&val))
- {
- // Do not mark the token as invalid.
- // Just emit the diagnostic and reset value to 0.0.
- mImpl->diagnostics->report(Diagnostics::FLOAT_OVERFLOW,
- token->location, token->text);
- token->text.assign("0.0");
- }
- validToken = true;
- break;
- }
case Token::PP_NUMBER:
mImpl->diagnostics->report(Diagnostics::INVALID_NUMBER,
token->location, token->text);
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h
index 7b70180fc8..9a90d79a1a 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h
@@ -37,6 +37,12 @@ class Preprocessor
bool init(size_t count, const char* const string[], const int length[]);
// Adds a pre-defined macro.
void predefineMacro(const char* name, int value);
+ // Sets maximum allowed token length.
+ // If token length exceeds this limit,
+ // the token text will be truncated to the given maximum length, and
+ // TOKEN_TOO_LONG diagnostic will be generated.
+ // The maximum length defaults to 256.
+ void setMaxTokenLength(size_t maxLength);
void lex(Token* token);
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h
index 7a6fa87b04..9d131f865a 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h
@@ -32,13 +32,13 @@ class Tokenizer : public Lexer
bool leadingSpace;
bool lineStart;
};
- static const std::size_t kMaxTokenLength;
Tokenizer(Diagnostics* diagnostics);
~Tokenizer();
bool init(size_t count, const char* const string[], const int length[]);
+ void setMaxTokenLength(size_t maxLength) { mMaxTokenLength = maxLength; }
void setFileNumber(int file);
void setLineNumber(int line);
@@ -51,6 +51,7 @@ class Tokenizer : public Lexer
void* mHandle; // Scanner handle.
Context mContext; // Scanner extra.
+ size_t mMaxTokenLength;
};
} // namespace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l
index fc81d84f37..01f0177b6c 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l
@@ -267,11 +267,9 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
namespace pp {
-// TODO(alokp): Maximum token length should ideally be specified by
-// the preprocessor client, i.e., the compiler.
-const size_t Tokenizer::kMaxTokenLength = 256;
-
-Tokenizer::Tokenizer(Diagnostics* diagnostics) : mHandle(0)
+Tokenizer::Tokenizer(Diagnostics* diagnostics)
+ : mHandle(0),
+ mMaxTokenLength(256)
{
mContext.diagnostics = diagnostics;
}
@@ -304,11 +302,11 @@ void Tokenizer::setLineNumber(int line)
void Tokenizer::lex(Token* token)
{
token->type = yylex(&token->text, &token->location, mHandle);
- if (token->text.size() > kMaxTokenLength)
+ if (token->text.size() > mMaxTokenLength)
{
mContext.diagnostics->report(Diagnostics::TOKEN_TOO_LONG,
token->location, token->text);
- token->text.erase(kMaxTokenLength);
+ token->text.erase(mMaxTokenLength);
}
token->flags = 0;
diff --git a/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp b/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp
index 524c6cf53a..355eb62d65 100644
--- a/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp
+++ b/src/3rdparty/angle/src/compiler/timing/RestrictVertexShaderTiming.cpp
@@ -10,8 +10,8 @@ void RestrictVertexShaderTiming::visitSymbol(TIntermSymbol* node)
{
if (IsSampler(node->getBasicType())) {
++mNumErrors;
- mSink.prefix(EPrefixError);
- mSink.location(node->getLine());
- mSink << "Samplers are not permitted in vertex shaders.\n";
+ mSink.message(EPrefixError,
+ node->getLine(),
+ "Samplers are not permitted in vertex shaders");
}
}
diff --git a/src/3rdparty/angle/src/compiler/util.cpp b/src/3rdparty/angle/src/compiler/util.cpp
index b46e4d0e34..d6e5eeed91 100644
--- a/src/3rdparty/angle/src/compiler/util.cpp
+++ b/src/3rdparty/angle/src/compiler/util.cpp
@@ -4,30 +4,25 @@
// found in the LICENSE file.
//
-#include <math.h>
-#include <stdlib.h>
+#include "compiler/util.h"
-#include "util.h"
+#include <limits>
-#ifdef _MSC_VER
- #include <locale.h>
-#else
- #include <sstream>
-#endif
+#include "compiler/preprocessor/numeric_lex.h"
-double atof_dot(const char *str)
+bool atof_clamp(const char *str, float *value)
{
-#ifdef _MSC_VER
- _locale_t l = _create_locale(LC_NUMERIC, "C");
- double result = _atof_l(str, l);
- _free_locale(l);
- return result;
-#else
- double result;
- std::istringstream s(str);
- std::locale l("C");
- s.imbue(l);
- s >> result;
- return result;
-#endif
+ bool success = pp::numeric_lex_float(str, value);
+ if (!success)
+ *value = std::numeric_limits<float>::max();
+ return success;
}
+
+bool atoi_clamp(const char *str, int *value)
+{
+ bool success = pp::numeric_lex_int(str, value);
+ if (!success)
+ *value = std::numeric_limits<int>::max();
+ return success;
+}
+
diff --git a/src/3rdparty/angle/src/compiler/util.h b/src/3rdparty/angle/src/compiler/util.h
index 35288b7396..dc69f39060 100644
--- a/src/3rdparty/angle/src/compiler/util.h
+++ b/src/3rdparty/angle/src/compiler/util.h
@@ -7,15 +7,14 @@
#ifndef COMPILER_UTIL_H
#define COMPILER_UTIL_H
-#ifdef __cplusplus
-extern "C" {
-#endif
+// atof_clamp is like atof but
+// 1. it forces C locale, i.e. forcing '.' as decimal point.
+// 2. it clamps the value to -FLT_MAX or FLT_MAX if overflow happens.
+// Return false if overflow happens.
+extern bool atof_clamp(const char *str, float *value);
-// atof_dot is like atof but forcing C locale, i.e. forcing '.' as decimal point.
-double atof_dot(const char *str);
-
-#ifdef __cplusplus
-} // end extern "C"
-#endif
+// If overflow happens, clamp the value to INT_MIN or INT_MAX.
+// Return false if overflow happens.
+extern bool atoi_clamp(const char *str, int *value);
#endif // COMPILER_UTIL_H
diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp
index d5d0f0f831..a382c3b1eb 100644
--- a/src/3rdparty/angle/src/libEGL/Display.cpp
+++ b/src/3rdparty/angle/src/libEGL/Display.cpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -38,31 +38,16 @@ egl::Display *Display::getDisplay(EGLNativeDisplayType displayId)
return displays[displayId];
}
- egl::Display *display = NULL;
+ // FIXME: Check if displayId is a valid display device context
- if (displayId == EGL_DEFAULT_DISPLAY)
- {
- display = new egl::Display(displayId, (HDC)NULL, false);
- }
- else if (displayId == EGL_SOFTWARE_DISPLAY_ANGLE)
- {
- display = new egl::Display(displayId, (HDC)NULL, true);
- }
- else
- {
- // FIXME: Check if displayId is a valid display device context
-
- display = new egl::Display(displayId, (HDC)displayId, false);
- }
+ egl::Display *display = new egl::Display(displayId, (HDC)displayId);
displays[displayId] = display;
return display;
}
-Display::Display(EGLNativeDisplayType displayId, HDC deviceContext, bool software) : mDc(deviceContext)
+Display::Display(EGLNativeDisplayType displayId, HDC deviceContext) : mDc(deviceContext)
{
-
- mSoftwareDevice = software;
mDisplayId = displayId;
mRenderer = NULL;
}
@@ -86,7 +71,7 @@ bool Display::initialize()
return true;
}
- mRenderer = glCreateRenderer(this, mDc, mSoftwareDevice);
+ mRenderer = glCreateRenderer(this, mDc, mDisplayId);
if (!mRenderer)
{
@@ -128,6 +113,7 @@ bool Display::initialize()
}
initExtensionString();
+ initVendorString();
return true;
}
@@ -528,5 +514,24 @@ const char *Display::getExtensionString() const
return mExtensionString.c_str();
}
+void Display::initVendorString()
+{
+ mVendorString = "Google Inc.";
+
+ LUID adapterLuid = {0};
+
+ if (mRenderer && mRenderer->getLUID(&adapterLuid))
+ {
+ char adapterLuidString[64];
+ sprintf_s(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart);
+
+ mVendorString += adapterLuidString;
+ }
+}
+
+const char *Display::getVendorString() const
+{
+ return mVendorString.c_str();
+}
}
diff --git a/src/3rdparty/angle/src/libEGL/Display.h b/src/3rdparty/angle/src/libEGL/Display.h
index 8c71e51b7a..58c3940331 100644
--- a/src/3rdparty/angle/src/libEGL/Display.h
+++ b/src/3rdparty/angle/src/libEGL/Display.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -60,11 +60,12 @@ class Display
virtual void recreateSwapChains();
const char *getExtensionString() const;
+ const char *getVendorString() const;
private:
DISALLOW_COPY_AND_ASSIGN(Display);
- Display(EGLNativeDisplayType displayId, HDC deviceContext, bool software);
+ Display(EGLNativeDisplayType displayId, HDC deviceContext);
bool restoreLostDevice();
@@ -84,7 +85,9 @@ class Display
rx::Renderer *mRenderer;
void initExtensionString();
+ void initVendorString();
std::string mExtensionString;
+ std::string mVendorString;
};
}
diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp
index a430a3530f..b47a7bcc20 100644
--- a/src/3rdparty/angle/src/libEGL/Surface.cpp
+++ b/src/3rdparty/angle/src/libEGL/Surface.cpp
@@ -20,8 +20,6 @@
#include "libEGL/main.h"
#include "libEGL/Display.h"
-#include <dwmapi.h>
-
namespace egl
{
@@ -71,44 +69,9 @@ Surface::~Surface()
bool Surface::initialize()
{
- typedef HRESULT (STDAPICALLTYPE *PtrDwmIsCompositionEnabled)(BOOL*);
- typedef HRESULT (STDAPICALLTYPE *PtrDwmSetPresentParameters)(HWND, DWM_PRESENT_PARAMETERS *);
-
if (!resetSwapChain())
return false;
- // Modify present parameters for this window, if we are composited,
- // to minimize the amount of queuing done by DWM between our calls to
- // present and the actual screen.
- if (mWindow && (getComparableOSVersion() >= versionWindowsVista)) {
- // Resolve dwmapi.dll functions dynamically as the Library is
- // not present on Windows XP. Alternatively, /DELAYLOAD could be used.
- static PtrDwmIsCompositionEnabled dwmIsCompositionEnabled = 0;
- static PtrDwmSetPresentParameters dwmSetPresentParameters = 0;
- if (!dwmIsCompositionEnabled) {
- if (const HMODULE dwmLibrary = LoadLibraryW(L"dwmapi.dll")) {
- dwmIsCompositionEnabled =
- (PtrDwmIsCompositionEnabled)GetProcAddress(dwmLibrary, "DwmIsCompositionEnabled");
- dwmSetPresentParameters =
- (PtrDwmSetPresentParameters)GetProcAddress(dwmLibrary, "DwmSetPresentParameters");
- }
- }
- if (dwmIsCompositionEnabled && dwmSetPresentParameters) {
- BOOL isComposited;
- HRESULT result = dwmIsCompositionEnabled(&isComposited);
- if (SUCCEEDED(result) && isComposited) {
- DWM_PRESENT_PARAMETERS presentParams;
- memset(&presentParams, 0, sizeof(presentParams));
- presentParams.cbSize = sizeof(DWM_PRESENT_PARAMETERS);
- presentParams.cBuffer = 2;
-
- result = dwmSetPresentParameters(mWindow, &presentParams);
- if (FAILED(result))
- ERR("Unable to set present parameters: 0x%08X", result);
- }
- }
- }
-
return true;
}
diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp
index 7fca456cf5..6e10c3926d 100644
--- a/src/3rdparty/angle/src/libEGL/libEGL.cpp
+++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp
@@ -180,9 +180,9 @@ const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name)
case EGL_CLIENT_APIS:
return egl::success("OpenGL_ES");
case EGL_EXTENSIONS:
- return display->getExtensionString();
+ return egl::success(display->getExtensionString());
case EGL_VENDOR:
- return egl::success("Google Inc.");
+ return egl::success(display->getVendorString());
case EGL_VERSION:
return egl::success("1.4 (ANGLE " VERSION_STRING ")");
}
@@ -888,15 +888,18 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface
return EGL_FALSE;
}
- rx::Renderer *renderer = display->getRenderer();
- if (renderer->testDeviceLost(true))
+ if (dpy != EGL_NO_DISPLAY)
{
- return EGL_FALSE;
- }
+ rx::Renderer *renderer = display->getRenderer();
+ if (renderer->testDeviceLost(true))
+ {
+ return EGL_FALSE;
+ }
- if (renderer->isDeviceLost())
- {
- return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
+ if (renderer->isDeviceLost())
+ {
+ return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
+ }
}
if ((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(draw))) ||
diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp
index 7ba77f08d1..7dea5fc74b 100644
--- a/src/3rdparty/angle/src/libEGL/main.cpp
+++ b/src/3rdparty/angle/src/libEGL/main.cpp
@@ -88,72 +88,89 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
return TRUE;
}
-static inline egl::Current *current()
-{
- return (egl::Current*)TlsGetValue(currentTLS);
-}
-
-#else // !QT_OPENGL_ES_2_ANGLE_STATIC
+#endif // !QT_OPENGL_ES_2_ANGLE_STATIC
-static egl::Current *current()
+namespace egl
+{
+Current *getCurrent()
{
+#ifndef QT_OPENGL_ES_2_ANGLE_STATIC
+ return (Current*)TlsGetValue(currentTLS);
+#else
// No precautions for thread safety taken as ANGLE is used single-threaded in Qt.
- static egl::Current curr = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE };
+ static Current curr = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE };
return &curr;
+#endif
}
-#endif // QT_OPENGL_ES_2_ANGLE_STATIC
-
-namespace egl
-{
void setCurrentError(EGLint error)
{
- current()->error = error;
+ Current *current = getCurrent();
+
+ current->error = error;
}
EGLint getCurrentError()
{
- return current()->error;
+ Current *current = getCurrent();
+
+ return current->error;
}
void setCurrentAPI(EGLenum API)
{
- current()->API = API;
+ Current *current = getCurrent();
+
+ current->API = API;
}
EGLenum getCurrentAPI()
{
- return current()->API;
+ Current *current = getCurrent();
+
+ return current->API;
}
void setCurrentDisplay(EGLDisplay dpy)
{
- current()->display = dpy;
+ Current *current = getCurrent();
+
+ current->display = dpy;
}
EGLDisplay getCurrentDisplay()
{
- return current()->display;
+ Current *current = getCurrent();
+
+ return current->display;
}
void setCurrentDrawSurface(EGLSurface surface)
{
- current()->drawSurface = surface;
+ Current *current = getCurrent();
+
+ current->drawSurface = surface;
}
EGLSurface getCurrentDrawSurface()
{
- return current()->drawSurface;
+ Current *current = getCurrent();
+
+ return current->drawSurface;
}
void setCurrentReadSurface(EGLSurface surface)
{
- current()->readSurface = surface;
+ Current *current = getCurrent();
+
+ current->readSurface = surface;
}
EGLSurface getCurrentReadSurface()
{
- return current()->readSurface;
+ Current *current = getCurrent();
+
+ return current->readSurface;
}
void error(EGLint errorCode)
diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp b/src/3rdparty/angle/src/libGLESv2/Buffer.cpp
index 8d5b4ef2a1..c007d5d9e9 100644
--- a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Buffer.cpp
@@ -40,6 +40,7 @@ Buffer::~Buffer()
void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
{
mBufferStorage->clear();
+ mIndexRangeCache.clear();
mBufferStorage->setData(data, size, 0);
mUsage = usage;
@@ -56,6 +57,7 @@ void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset)
{
mBufferStorage->setData(data, size, offset);
+ mIndexRangeCache.invalidateRange(offset, size);
if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0))
{
@@ -70,7 +72,7 @@ rx::BufferStorage *Buffer::getStorage() const
return mBufferStorage;
}
-unsigned int Buffer::size()
+unsigned int Buffer::size() const
{
return mBufferStorage->getSize();
}
@@ -116,4 +118,9 @@ void Buffer::promoteStaticUsage(int dataSize)
}
}
+rx::IndexRangeCache *Buffer::getIndexRangeCache()
+{
+ return &mIndexRangeCache;
+}
+
}
diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.h b/src/3rdparty/angle/src/libGLESv2/Buffer.h
index 4376ada5c0..4048f4b906 100644
--- a/src/3rdparty/angle/src/libGLESv2/Buffer.h
+++ b/src/3rdparty/angle/src/libGLESv2/Buffer.h
@@ -13,6 +13,7 @@
#include "common/angleutils.h"
#include "common/RefCountObject.h"
+#include "libGLESv2/renderer/IndexRangeCache.h"
namespace rx
{
@@ -38,13 +39,15 @@ class Buffer : public RefCountObject
GLenum usage() const;
rx::BufferStorage *getStorage() const;
- unsigned int size();
+ unsigned int size() const;
rx::StaticVertexBufferInterface *getStaticVertexBuffer();
rx::StaticIndexBufferInterface *getStaticIndexBuffer();
void invalidateStaticData();
void promoteStaticUsage(int dataSize);
+ rx::IndexRangeCache *getIndexRangeCache();
+
private:
DISALLOW_COPY_AND_ASSIGN(Buffer);
@@ -53,6 +56,8 @@ class Buffer : public RefCountObject
rx::BufferStorage *mBufferStorage;
+ rx::IndexRangeCache mIndexRangeCache;
+
rx::StaticVertexBufferInterface *mStaticVertexBuffer;
rx::StaticIndexBufferInterface *mStaticIndexBuffer;
unsigned int mUnmodifiedDataUse;
diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp
index 90ba2539d8..e829d508a6 100644
--- a/src/3rdparty/angle/src/libGLESv2/Context.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp
@@ -60,6 +60,7 @@ Context::Context(const gl::Context *shareContext, rx::Renderer *renderer, bool n
mState.rasterizer.polygonOffsetFactor = 0.0f;
mState.rasterizer.polygonOffsetUnits = 0.0f;
mState.rasterizer.pointDrawMode = false;
+ mState.rasterizer.multiSample = false;
mState.scissorTest = false;
mState.scissor.x = 0;
mState.scissor.y = 0;
@@ -1075,6 +1076,7 @@ void Context::setRenderbufferStorage(GLsizei width, GLsizei height, GLenum inter
case GL_RGB565:
case GL_RGB8_OES:
case GL_RGBA8_OES:
+ case GL_BGRA8_EXT:
renderbuffer = new gl::Colorbuffer(mRenderer,width, height, internalformat, samples);
break;
case GL_STENCIL_INDEX8:
@@ -1741,7 +1743,11 @@ bool Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport)
// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
void Context::applyState(GLenum drawMode)
{
+ Framebuffer *framebufferObject = getDrawFramebuffer();
+ int samples = framebufferObject->getSamples();
+
mState.rasterizer.pointDrawMode = (drawMode == GL_POINTS);
+ mState.rasterizer.multiSample = (samples != 0);
mRenderer->setRasterizerState(mState.rasterizer);
unsigned int mask = 0;
@@ -1749,10 +1755,10 @@ void Context::applyState(GLenum drawMode)
{
if (mState.sampleCoverageValue != 0)
{
- Framebuffer *framebufferObject = getDrawFramebuffer();
+
float threshold = 0.5f;
- for (int i = 0; i < framebufferObject->getSamples(); ++i)
+ for (int i = 0; i < samples; ++i)
{
mask <<= 1;
@@ -2582,6 +2588,7 @@ void Context::initExtensionString()
}
extensionString += "GL_EXT_texture_storage ";
+ extensionString += "GL_EXT_frag_depth ";
// ANGLE-specific extensions
if (supportsDepthTextures())
diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp
index 42fee3bbad..b0abba0ac4 100644
--- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp
@@ -303,6 +303,19 @@ bool Framebuffer::hasStencil() const
return false;
}
+bool Framebuffer::usingExtendedDrawBuffers() const
+{
+ for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
+ {
+ if (isEnabledColorAttachment(colorAttachment))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
GLenum Framebuffer::completeness() const
{
int width = 0;
diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h
index 66acdc4c37..b54e008dd8 100644
--- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h
+++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h
@@ -68,6 +68,7 @@ class Framebuffer
bool hasEnabledColorAttachment() const;
bool hasStencil() const;
int getSamples() const;
+ bool usingExtendedDrawBuffers() const;
virtual GLenum completeness() const;
diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp
index 14e6c94ca4..bcd04b7157 100644
--- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp
@@ -1165,7 +1165,7 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying
bool usesMRT = fragmentShader->mUsesMultipleRenderTargets;
bool usesFragColor = fragmentShader->mUsesFragColor;
bool usesFragData = fragmentShader->mUsesFragData;
- if (usesMRT && usesFragColor && usesFragData)
+ if (usesFragColor && usesFragData)
{
infoLog.append("Cannot use both gl_FragColor and gl_FragData in the same fragment shader.");
return false;
@@ -1177,6 +1177,10 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying
const int registersNeeded = registers + (fragmentShader->mUsesFragCoord ? 1 : 0) + (fragmentShader->mUsesPointCoord ? 1 : 0);
+ // The output color is broadcast to all enabled draw buffers when writing to gl_FragColor
+ const bool broadcast = fragmentShader->mUsesFragColor;
+ const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getMaxRenderTargets() : 1);
+
if (registersNeeded > maxVaryingVectors)
{
infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord");
@@ -1221,8 +1225,7 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying
std::string varyingSemantic = (mUsesPointSize && shaderModel == 3) ? "COLOR" : "TEXCOORD";
std::string targetSemantic = (shaderModel >= 4) ? "SV_Target" : "COLOR";
std::string positionSemantic = (shaderModel >= 4) ? "SV_Position" : "POSITION";
-
- const unsigned int renderTargetCount = usesMRT ? mRenderer->getMaxRenderTargets() : 1;
+ std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
// special varyings that use reserved registers
int reservedRegisterIndex = registers;
@@ -1472,9 +1475,14 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying
"struct PS_OUTPUT\n"
"{\n";
- for (unsigned int i = 0; i < renderTargetCount; i++)
+ for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
+ {
+ pixelHLSL += " float4 gl_Color" + str(renderTargetIndex) + " : " + targetSemantic + str(renderTargetIndex) + ";\n";
+ }
+
+ if (fragmentShader->mUsesFragDepth)
{
- pixelHLSL += " float4 gl_Color" + str(i) + " : " + targetSemantic + str(i) + ";\n";
+ pixelHLSL += " float gl_Depth : " + depthSemantic + ";\n";
}
pixelHLSL += "};\n"
@@ -1583,11 +1591,16 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying
"\n"
" PS_OUTPUT output;\n";
- for (unsigned int i = 0; i < renderTargetCount; i++)
+ for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
{
- unsigned int sourceColor = fragmentShader->mUsesFragData ? i : 0;
+ unsigned int sourceColorIndex = broadcast ? 0 : renderTargetIndex;
+
+ pixelHLSL += " output.gl_Color" + str(renderTargetIndex) + " = gl_Color[" + str(sourceColorIndex) + "];\n";
+ }
- pixelHLSL += " output.gl_Color" + str(i) + " = gl_Color[" + str(sourceColor) + "];\n";
+ if (fragmentShader->mUsesFragDepth)
+ {
+ pixelHLSL += " output.gl_Depth = gl_Depth;\n";
}
pixelHLSL += "\n"
@@ -1617,6 +1630,14 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
return false;
}
+ int compileFlags = 0;
+ stream.read(&compileFlags);
+ if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
+ {
+ infoLog.append("Mismatched compilation flags.");
+ return false;
+ }
+
for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
{
stream.read(&mLinkedAttribute[i].type);
@@ -1626,6 +1647,8 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
stream.read(&mSemanticIndex[i]);
}
+ initAttributesByLayout();
+
for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
{
stream.read(&mSamplersPS[i].active);
@@ -1769,6 +1792,7 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length)
stream.write(GL_PROGRAM_BINARY_ANGLE);
stream.write(VERSION_DWORD);
+ stream.write(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
{
@@ -1917,36 +1941,48 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
}
bool success = true;
- mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX);
- mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL);
- if (usesGeometryShader())
+ if (!linkAttributes(infoLog, attributeBindings, fragmentShader, vertexShader))
{
- std::string geometryHLSL = generateGeometryShaderHLSL(registers, packing, fragmentShader, vertexShader);
- mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY);
+ success = false;
}
- if (!mVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable))
+ if (!linkUniforms(infoLog, vertexShader->getUniforms(), fragmentShader->getUniforms()))
{
- infoLog.append("Failed to create D3D shaders.");
success = false;
-
- delete mVertexExecutable;
- mVertexExecutable = NULL;
- delete mPixelExecutable;
- mPixelExecutable = NULL;
- delete mGeometryExecutable;
- mGeometryExecutable = NULL;
}
- if (!linkAttributes(infoLog, attributeBindings, fragmentShader, vertexShader))
+ // special case for gl_DepthRange, the only built-in uniform (also a struct)
+ if (vertexShader->mUsesDepthRange || fragmentShader->mUsesDepthRange)
{
- success = false;
+ mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0));
+ mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0));
+ mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0));
}
- if (!linkUniforms(infoLog, vertexShader->getUniforms(), fragmentShader->getUniforms()))
+ if (success)
{
- success = false;
+ mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX);
+ mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL);
+
+ if (usesGeometryShader())
+ {
+ std::string geometryHLSL = generateGeometryShaderHLSL(registers, packing, fragmentShader, vertexShader);
+ mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY);
+ }
+
+ if (!mVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable))
+ {
+ infoLog.append("Failed to create D3D shaders.");
+ success = false;
+
+ delete mVertexExecutable;
+ mVertexExecutable = NULL;
+ delete mPixelExecutable;
+ mPixelExecutable = NULL;
+ delete mGeometryExecutable;
+ mGeometryExecutable = NULL;
+ }
}
return success;
@@ -2019,6 +2055,8 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at
}
}
+ initAttributesByLayout();
+
return true;
}
@@ -2545,12 +2583,6 @@ struct AttributeSorter
AttributeSorter(const int (&semanticIndices)[MAX_VERTEX_ATTRIBS])
: originalIndices(semanticIndices)
{
- for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
- {
- indices[i] = i;
- }
-
- std::sort(&indices[0], &indices[MAX_VERTEX_ATTRIBS], *this);
}
bool operator()(int a, int b)
@@ -2558,27 +2590,32 @@ struct AttributeSorter
return originalIndices[a] == -1 ? false : originalIndices[a] < originalIndices[b];
}
- int indices[MAX_VERTEX_ATTRIBS];
const int (&originalIndices)[MAX_VERTEX_ATTRIBS];
};
-void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const
+void ProgramBinary::initAttributesByLayout()
{
- AttributeSorter sorter(mSemanticIndex);
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ mAttributesByLayout[i] = i;
+ }
+
+ std::sort(&mAttributesByLayout[0], &mAttributesByLayout[MAX_VERTEX_ATTRIBS], AttributeSorter(mSemanticIndex));
+}
- int oldIndices[MAX_VERTEX_ATTRIBS];
+void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const
+{
rx::TranslatedAttribute oldTranslatedAttributes[MAX_VERTEX_ATTRIBS];
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
- oldIndices[i] = mSemanticIndex[i];
oldTranslatedAttributes[i] = attributes[i];
}
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
- int oldIndex = sorter.indices[i];
- sortedSemanticIndices[i] = oldIndices[oldIndex];
+ int oldIndex = mAttributesByLayout[i];
+ sortedSemanticIndices[i] = mSemanticIndex[oldIndex];
attributes[i] = oldTranslatedAttributes[oldIndex];
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h
index 2386c0bd6f..d6320863f2 100644
--- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h
+++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h
@@ -114,6 +114,7 @@ class ProgramBinary : public RefCountObject
unsigned int getSerial() const;
+ void initAttributesByLayout();
void sortAttributesByLayout(rx::TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const;
static std::string decorateAttribute(const std::string &name); // Prepend an underscore
@@ -142,6 +143,7 @@ class ProgramBinary : public RefCountObject
Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS];
int mSemanticIndex[MAX_VERTEX_ATTRIBS];
+ int mAttributesByLayout[MAX_VERTEX_ATTRIBS];
struct Sampler
{
diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.cpp b/src/3rdparty/angle/src/libGLESv2/Shader.cpp
index abddab427b..7dfdd0ba3a 100644
--- a/src/3rdparty/angle/src/libGLESv2/Shader.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Shader.cpp
@@ -247,6 +247,7 @@ void Shader::initializeCompiler()
resources.EXT_draw_buffers = mRenderer->getMaxRenderTargets() > 1;
// resources.OES_EGL_image_external = mRenderer->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported.
resources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp
+ resources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output
mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
@@ -304,6 +305,8 @@ void Shader::parseVaryings()
mUsesFrontFacing = strstr(mHlsl, "GL_USES_FRONT_FACING") != NULL;
mUsesPointSize = strstr(mHlsl, "GL_USES_POINT_SIZE") != NULL;
mUsesPointCoord = strstr(mHlsl, "GL_USES_POINT_COORD") != NULL;
+ mUsesDepthRange = strstr(mHlsl, "GL_USES_DEPTH_RANGE") != NULL;
+ mUsesFragDepth = strstr(mHlsl, "GL_USES_FRAG_DEPTH") != NULL;
}
}
@@ -335,6 +338,8 @@ void Shader::uncompile()
mUsesFrontFacing = false;
mUsesPointSize = false;
mUsesPointCoord = false;
+ mUsesDepthRange = false;
+ mUsesFragDepth = false;
mActiveUniforms.clear();
}
diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.h b/src/3rdparty/angle/src/libGLESv2/Shader.h
index f471968550..2afe2976c3 100644
--- a/src/3rdparty/angle/src/libGLESv2/Shader.h
+++ b/src/3rdparty/angle/src/libGLESv2/Shader.h
@@ -105,6 +105,8 @@ class Shader
bool mUsesFrontFacing;
bool mUsesPointSize;
bool mUsesPointCoord;
+ bool mUsesDepthRange;
+ bool mUsesFragDepth;
static void *mFragmentCompiler;
static void *mVertexCompiler;
diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.cpp b/src/3rdparty/angle/src/libGLESv2/Texture.cpp
index 461357a1ce..72c0a8ab79 100644
--- a/src/3rdparty/angle/src/libGLESv2/Texture.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Texture.cpp
@@ -14,10 +14,10 @@
#include "libGLESv2/main.h"
#include "libGLESv2/mathutil.h"
#include "libGLESv2/utilities.h"
-#if defined(ANGLE_ENABLE_D3D11)
-# define D3DFMT_UNKNOWN DXGI_FORMAT_UNKNOWN
+#ifndef ANGLE_ENABLE_D3D11
+# include "libGLESv2/renderer/Blit.h"
#else
-# include "libGLESv2/renderer/Blit.h"
+# define D3DFMT_UNKNOWN DXGI_FORMAT_UNKNOWN
#endif
#include "libGLESv2/Renderbuffer.h"
#include "libGLESv2/renderer/Image.h"
diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.h b/src/3rdparty/angle/src/libGLESv2/angletypes.h
index 37f67f41ac..b2f0cad265 100644
--- a/src/3rdparty/angle/src/libGLESv2/angletypes.h
+++ b/src/3rdparty/angle/src/libGLESv2/angletypes.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -54,6 +54,7 @@ struct RasterizerState
GLfloat polygonOffsetUnits;
bool pointDrawMode;
+ bool multiSample;
};
struct BlendState
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp
index 64f67d7d6d..320bbccc27 100644
--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp
@@ -4893,6 +4893,7 @@ void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samp
case GL_RGB565:
case GL_RGB8_OES:
case GL_RGBA8_OES:
+ case GL_BGRA8_EXT:
case GL_STENCIL_INDEX8:
case GL_DEPTH24_STENCIL8_OES:
context->setRenderbufferStorage(width, height, internalformat, samples);
@@ -6977,17 +6978,14 @@ void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs)
if (context->getDrawFramebufferHandle() == 0)
{
- if (n > 1)
+ if (n != 1)
{
return gl::error(GL_INVALID_OPERATION);
}
- if (n == 1)
+ if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
{
- if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ return gl::error(GL_INVALID_OPERATION);
}
}
else
@@ -7008,6 +7006,11 @@ void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs)
{
framebuffer->setDrawBufferState(colorAttachment, bufs[colorAttachment]);
}
+
+ for (int colorAttachment = n; colorAttachment < (int)context->getMaximumRenderTargets(); colorAttachment++)
+ {
+ framebuffer->setDrawBufferState(colorAttachment, GL_NONE);
+ }
}
}
catch (std::bad_alloc&)
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def
index 71398b3142..b8320c8f25 100644
--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def
+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def
@@ -182,4 +182,7 @@ EXPORTS
glGetProcAddress @148 NONAME
glBindTexImage @158 NONAME
glCreateRenderer @177 NONAME
- glDestroyRenderer @178 NONAME \ No newline at end of file
+ glDestroyRenderer @178 NONAME
+
+ ; Setting up TRACE macro callbacks
+ SetTraceFunctionPointers @180
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def
index 0f6caf17a3..ef44917d71 100644
--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def
+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def
@@ -172,6 +172,7 @@ EXPORTS
glDrawElementsInstancedANGLE@20 @174
glProgramBinaryOES@16 @175
glGetProgramBinaryOES@20 @176
+ glDrawBuffersEXT@8 @179
; EGL dependencies
glCreateContext @144 NONAME
@@ -181,4 +182,7 @@ EXPORTS
glGetProcAddress@4 @148 NONAME
glBindTexImage@4 @158 NONAME
glCreateRenderer @177 NONAME
- glDestroyRenderer @178 NONAME \ No newline at end of file
+ glDestroyRenderer @178 NONAME
+
+ ; Setting up TRACE macro callbacks
+ SetTraceFunctionPointers@8 @180
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def
index 2b3b34009e..3dd5683b5f 100644
--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def
+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def
@@ -172,6 +172,7 @@ EXPORTS
glDrawElementsInstancedANGLE @174
glProgramBinaryOES @175
glGetProgramBinaryOES @176
+ glDrawBuffersEXT @179
; EGL dependencies
glCreateContext @144 NONAME
@@ -182,3 +183,6 @@ EXPORTS
glBindTexImage @158 NONAME
glCreateRenderer @177 NONAME
glDestroyRenderer @178 NONAME
+
+ ; Setting up TRACE macro callbacks
+ SetTraceFunctionPointers @180
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def
index dd92a2a12b..6c8d3ed630 100644
--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def
+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def
@@ -172,6 +172,7 @@ EXPORTS
glDrawElementsInstancedANGLE@20 @174
glProgramBinaryOES@16 @175
glGetProgramBinaryOES@20 @176
+ glDrawBuffersEXT@8 @179
; EGL dependencies
glCreateContext @144 NONAME
@@ -181,4 +182,7 @@ EXPORTS
glGetProcAddress@4 @148 NONAME
glBindTexImage@4 @158 NONAME
glCreateRenderer @177 NONAME
- glDestroyRenderer @178 NONAME \ No newline at end of file
+ glDestroyRenderer @178 NONAME
+
+ ; Setting up TRACE macro callbacks
+ SetTraceFunctionPointers@8 @180
diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp
index 5d23e8e70f..730a6ac022 100644
--- a/src/3rdparty/angle/src/libGLESv2/main.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/main.cpp
@@ -71,30 +71,27 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
return TRUE;
}
-static gl::Current *current()
-{
- return (gl::Current*)TlsGetValue(currentTLS);
-}
-
-#else // !QT_OPENGL_ES_2_ANGLE_STATIC
+#endif // !QT_OPENGL_ES_2_ANGLE_STATIC
-static inline gl::Current *current()
+namespace gl
+{
+Current *getCurrent()
{
+#ifndef QT_OPENGL_ES_2_ANGLE_STATIC
+ return (Current*)TlsGetValue(currentTLS);
+#else
// No precautions for thread safety taken as ANGLE is used single-threaded in Qt.
static gl::Current curr = { 0, 0 };
return &curr;
+#endif
}
-#endif // QT_OPENGL_ES_2_ANGLE_STATIC
-
-namespace gl
-{
void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface)
{
- Current *curr = current();
+ Current *current = getCurrent();
- curr->context = context;
- curr->display = display;
+ current->context = context;
+ current->display = display;
if (context && display && surface)
{
@@ -104,7 +101,9 @@ void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface)
Context *getContext()
{
- return current()->context;
+ Current *current = getCurrent();
+
+ return current->context;
}
Context *getNonLostContext()
@@ -128,7 +127,9 @@ Context *getNonLostContext()
egl::Display *getDisplay()
{
- return current()->display;
+ Current *current = getCurrent();
+
+ return current->display;
}
// Records an error code
diff --git a/src/3rdparty/angle/src/libGLESv2/main.h b/src/3rdparty/angle/src/libGLESv2/main.h
index 9168a2212e..196afaeab6 100644
--- a/src/3rdparty/angle/src/libGLESv2/main.h
+++ b/src/3rdparty/angle/src/libGLESv2/main.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -58,7 +58,7 @@ gl::Context *glCreateContext(const gl::Context *shareContext, rx::Renderer *rend
void glDestroyContext(gl::Context *context);
void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface);
gl::Context *glGetCurrentContext();
-rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, bool softwareDevice);
+rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayType displayId);
void glDestroyRenderer(rx::Renderer *renderer);
__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname);
diff --git a/src/3rdparty/angle/src/libGLESv2/mathutil.h b/src/3rdparty/angle/src/libGLESv2/mathutil.h
index bb48b94eaf..083548669a 100644
--- a/src/3rdparty/angle/src/libGLESv2/mathutil.h
+++ b/src/3rdparty/angle/src/libGLESv2/mathutil.h
@@ -93,6 +93,7 @@ inline bool supportsSSE2()
return supports;
}
+#if defined(_M_IX86) || defined(_M_AMD64) // ARM doesn't provide __cpuid()
int info[4];
__cpuid(info, 0);
@@ -102,6 +103,7 @@ inline bool supportsSSE2()
supports = (info[3] >> 26) & 1;
}
+#endif
checked = true;
diff --git a/src/3rdparty/angle/src/libGLESv2/precompiled.h b/src/3rdparty/angle/src/libGLESv2/precompiled.h
index b8b043c964..50dec6b084 100644
--- a/src/3rdparty/angle/src/libGLESv2/precompiled.h
+++ b/src/3rdparty/angle/src/libGLESv2/precompiled.h
@@ -32,11 +32,11 @@
#include <unordered_map>
#include <vector>
-#if defined(ANGLE_ENABLE_D3D11)
-# include <D3D11.h>
-# include <dxgi.h>
+#ifndef ANGLE_ENABLE_D3D11
+#include <d3d9.h>
#else
-# include <d3d9.h>
+#include <D3D11.h>
+#include <dxgi.h>
#endif
#include <D3Dcompiler.h>
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp
index 7fe9e6b762..3647d8a898 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp
@@ -160,12 +160,20 @@ void BufferStorage11::setData(const void* data, unsigned int size, unsigned int
bufferDesc.MiscFlags = 0;
bufferDesc.StructureByteStride = 0;
- D3D11_SUBRESOURCE_DATA initialData;
- initialData.pSysMem = data;
- initialData.SysMemPitch = size;
- initialData.SysMemSlicePitch = 0;
+ if (data)
+ {
+ D3D11_SUBRESOURCE_DATA initialData;
+ initialData.pSysMem = data;
+ initialData.SysMemPitch = size;
+ initialData.SysMemSlicePitch = 0;
+
+ result = device->CreateBuffer(&bufferDesc, &initialData, &mStagingBuffer);
+ }
+ else
+ {
+ result = device->CreateBuffer(&bufferDesc, NULL, &mStagingBuffer);
+ }
- result = device->CreateBuffer(&bufferDesc, &initialData, &mStagingBuffer);
if (FAILED(result))
{
return gl::error(GL_OUT_OF_MEMORY);
@@ -173,7 +181,7 @@ void BufferStorage11::setData(const void* data, unsigned int size, unsigned int
mStagingBufferSize = size;
}
- else
+ else if (data)
{
D3D11_MAPPED_SUBRESOURCE mappedResource;
result = context->Map(mStagingBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource);
@@ -182,8 +190,7 @@ void BufferStorage11::setData(const void* data, unsigned int size, unsigned int
return gl::error(GL_OUT_OF_MEMORY);
}
- if (data)
- memcpy(mappedResource.pData, data, size);
+ memcpy(mappedResource.pData, data, size);
context->Unmap(mStagingBuffer, 0);
}
@@ -212,7 +219,6 @@ void BufferStorage11::setData(const void* data, unsigned int size, unsigned int
mBufferSize = 0;
}
-
if (data)
{
D3D11_SUBRESOURCE_DATA initialData;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp
index 4468461871..e69e7a8921 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp
@@ -55,7 +55,9 @@ void BufferStorage9::setData(const void* data, unsigned int size, unsigned int o
mSize = std::max(mSize, offset + size);
if (data)
+ {
memcpy(reinterpret_cast<char*>(mMemory) + offset, data, size);
+ }
}
void BufferStorage9::clear()
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp
index 8c78c7d750..09c8922d07 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp
@@ -50,8 +50,8 @@ void Image11::generateMipmap(Image11 *dest, Image11 *src)
ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight());
D3D11_MAPPED_SUBRESOURCE destMapped, srcMapped;
- dest->map(&destMapped);
- src->map(&srcMapped);
+ dest->map(D3D11_MAP_WRITE, &destMapped);
+ src->map(D3D11_MAP_READ, &srcMapped);
const unsigned char *sourceData = reinterpret_cast<const unsigned char*>(srcMapped.pData);
unsigned char *destData = reinterpret_cast<unsigned char*>(destMapped.pData);
@@ -171,7 +171,7 @@ void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei heig
GLint unpackAlignment, const void *input)
{
D3D11_MAPPED_SUBRESOURCE mappedImage;
- HRESULT result = map(&mappedImage);
+ HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
if (FAILED(result))
{
ERR("Could not map image for loading.");
@@ -194,7 +194,7 @@ void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei heig
loadAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
break;
case GL_LUMINANCE32F_EXT:
- loadLuminanceFloatDataToRGB(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ loadLuminanceFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
break;
case GL_ALPHA16F_EXT:
loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
@@ -230,7 +230,7 @@ void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei heig
loadBGRADataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
break;
case GL_RGB32F_EXT:
- loadRGBFloatDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ loadRGBFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
break;
case GL_RGB16F_EXT:
loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
@@ -254,7 +254,7 @@ void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GL
ASSERT(yoffset % 4 == 0);
D3D11_MAPPED_SUBRESOURCE mappedImage;
- HRESULT result = map(&mappedImage);
+ HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
if (FAILED(result))
{
ERR("Could not map image for loading.");
@@ -344,8 +344,8 @@ void Image11::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width
{
// This format requires conversion, so we must copy the texture to staging and manually convert via readPixels
D3D11_MAPPED_SUBRESOURCE mappedImage;
- HRESULT result = map(&mappedImage);
-
+ HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
+
// determine the offset coordinate into the destination buffer
GLsizei rowOffset = gl::ComputePixelSize(mActualFormat) * xoffset;
void *dataOffset = static_cast<unsigned char*>(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset;
@@ -402,7 +402,7 @@ void Image11::createStagingTexture()
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_STAGING;
desc.BindFlags = 0;
- desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
HRESULT result = device->CreateTexture2D(&desc, NULL, &newTexture);
@@ -420,7 +420,7 @@ void Image11::createStagingTexture()
mDirty = false;
}
-HRESULT Image11::map(D3D11_MAPPED_SUBRESOURCE *map)
+HRESULT Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map)
{
createStagingTexture();
@@ -429,7 +429,7 @@ HRESULT Image11::map(D3D11_MAPPED_SUBRESOURCE *map)
if (mStagingTexture)
{
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
- result = deviceContext->Map(mStagingTexture, mStagingSubresource, D3D11_MAP_WRITE, 0, map);
+ result = deviceContext->Map(mStagingTexture, mStagingSubresource, mapType, 0, map);
// this can fail if the device is removed (from TDR)
if (d3d11::isDeviceLostError(result))
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image11.h b/src/3rdparty/angle/src/libGLESv2/renderer/Image11.h
index 4d5f1c1780..11a6492dc8 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/Image11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Image11.h
@@ -54,7 +54,7 @@ class Image11 : public Image
virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
protected:
- HRESULT map(D3D11_MAPPED_SUBRESOURCE *map);
+ HRESULT map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map);
void unmap();
private:
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.cpp
index 16fd782315..37dbd3e195 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.cpp
@@ -67,18 +67,30 @@ unsigned int IndexBufferInterface::getSerial() const
return mIndexBuffer->getSerial();
}
-int IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory)
+bool IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset)
{
+ // Protect against integer overflow
+ if (mWritePosition + size < mWritePosition)
+ {
+ return false;
+ }
+
if (!mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory))
{
- *outMappedMemory = NULL;
- return -1;
+ if (outMappedMemory)
+ {
+ *outMappedMemory = NULL;
+ }
+ return false;
}
- int oldWritePos = static_cast<int>(mWritePosition);
- mWritePosition += size;
+ if (streamOffset)
+ {
+ *streamOffset = mWritePosition;
+ }
- return oldWritePos;
+ mWritePosition += size;
+ return true;
}
bool IndexBufferInterface::unmapBuffer()
@@ -130,12 +142,13 @@ bool StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum
{
bool result = true;
unsigned int curBufferSize = getBufferSize();
+ unsigned int writePos = getWritePosition();
if (size > curBufferSize)
{
result = setBufferSize(std::max(size, 2 * curBufferSize), indexType);
setWritePosition(0);
}
- else if (getWritePosition() + size > curBufferSize)
+ else if (writePos + size > curBufferSize || writePos + size < writePos)
{
if (!discard())
{
@@ -175,27 +188,9 @@ bool StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum in
}
}
-unsigned int StaticIndexBufferInterface::lookupRange(intptr_t offset, GLsizei count, unsigned int *minIndex, unsigned int *maxIndex)
-{
- IndexRange range = {offset, count};
-
- std::map<IndexRange, IndexResult>::iterator res = mCache.find(range);
-
- if (res == mCache.end())
- {
- return -1;
- }
-
- *minIndex = res->second.minIndex;
- *maxIndex = res->second.maxIndex;
- return res->second.streamOffset;
-}
-
-void StaticIndexBufferInterface::addRange(intptr_t offset, GLsizei count, unsigned int minIndex, unsigned int maxIndex, unsigned int streamOffset)
+IndexRangeCache *StaticIndexBufferInterface::getIndexRangeCache()
{
- IndexRange indexRange = {offset, count};
- IndexResult indexResult = {minIndex, maxIndex, streamOffset};
- mCache[indexRange] = indexResult;
+ return &mIndexRangeCache;
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.h
index 1afbd626fa..6fb885a1cd 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.h
@@ -11,6 +11,7 @@
#define LIBGLESV2_RENDERER_INDEXBUFFER_H_
#include "common/angleutils.h"
+#include "libGLESv2/renderer/IndexRangeCache.h"
namespace rx
{
@@ -58,7 +59,7 @@ class IndexBufferInterface
unsigned int getSerial() const;
- int mapBuffer(unsigned int size, void** outMappedMemory);
+ bool mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset);
bool unmapBuffer();
IndexBuffer *getIndexBuffer() const;
@@ -99,37 +100,10 @@ class StaticIndexBufferInterface : public IndexBufferInterface
virtual bool reserveBufferSpace(unsigned int size, GLenum indexType);
- unsigned int lookupRange(intptr_t offset, GLsizei count, unsigned int *minIndex, unsigned int *maxIndex); // Returns the offset into the index buffer, or -1 if not found
- void addRange(intptr_t offset, GLsizei count, unsigned int minIndex, unsigned int maxIndex, unsigned int streamOffset);
+ IndexRangeCache *getIndexRangeCache();
private:
- struct IndexRange
- {
- intptr_t offset;
- GLsizei count;
-
- bool operator<(const IndexRange& rhs) const
- {
- if (offset != rhs.offset)
- {
- return offset < rhs.offset;
- }
- if (count != rhs.count)
- {
- return count < rhs.count;
- }
- return false;
- }
- };
-
- struct IndexResult
- {
- unsigned int minIndex;
- unsigned int maxIndex;
- unsigned int streamOffset;
- };
-
- std::map<IndexRange, IndexResult> mCache;
+ IndexRangeCache mIndexRangeCache;
};
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp
index 2a442ecd1a..66604c4558 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp
@@ -75,7 +75,8 @@ bool IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** out
{
if (mBuffer)
{
- if (offset + size > mBufferSize)
+ // Check for integer overflows and out-out-bounds map requests
+ if (offset + size < offset || offset + size > mBufferSize)
{
ERR("Index buffer map range is not inside the buffer.");
return false;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.cpp
index 84b79b4109..49bace8193 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.cpp
@@ -13,6 +13,7 @@
#include "libGLESv2/Buffer.h"
#include "libGLESv2/main.h"
+#include "libGLESv2/utilities.h"
#include "libGLESv2/renderer/IndexBuffer.h"
namespace rx
@@ -53,17 +54,6 @@ IndexDataManager::~IndexDataManager()
delete mCountingBuffer;
}
-static unsigned int indexTypeSize(GLenum type)
-{
- switch (type)
- {
- case GL_UNSIGNED_INT: return sizeof(GLuint);
- case GL_UNSIGNED_SHORT: return sizeof(GLushort);
- case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
- default: UNREACHABLE(); return sizeof(GLushort);
- }
-}
-
static void convertIndices(GLenum type, const void *input, GLsizei count, void *output)
{
if (type == GL_UNSIGNED_BYTE)
@@ -125,13 +115,19 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
}
GLenum destinationIndexType = (type == GL_UNSIGNED_INT) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
- intptr_t offset = reinterpret_cast<intptr_t>(indices);
+ unsigned int offset = 0;
bool alignedOffset = false;
BufferStorage *storage = NULL;
if (buffer != NULL)
{
+ if (reinterpret_cast<uintptr_t>(indices) > std::numeric_limits<unsigned int>::max())
+ {
+ return GL_OUT_OF_MEMORY;
+ }
+ offset = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(indices));
+
storage = buffer->getStorage();
switch (type)
@@ -142,7 +138,16 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
default: UNREACHABLE(); alignedOffset = false;
}
- if (indexTypeSize(type) * count + offset > storage->getSize())
+ unsigned int typeSize = gl::ComputeTypeSize(type);
+
+ // check for integer overflows
+ if (static_cast<unsigned int>(count) > (std::numeric_limits<unsigned int>::max() / typeSize) ||
+ typeSize * static_cast<unsigned int>(count) + offset < offset)
+ {
+ return GL_OUT_OF_MEMORY;
+ }
+
+ if (typeSize * static_cast<unsigned int>(count) + offset > storage->getSize())
{
return GL_INVALID_OPERATION;
}
@@ -156,37 +161,44 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
IndexBufferInterface *indexBuffer = streamingBuffer;
bool directStorage = alignedOffset && storage && storage->supportsDirectBinding() &&
destinationIndexType == type;
- UINT streamOffset = 0;
+ unsigned int streamOffset = 0;
if (directStorage)
{
indexBuffer = streamingBuffer;
streamOffset = offset;
storage->markBufferUsage();
- computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
+
+ if (!buffer->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex,
+ &translated->maxIndex, NULL))
+ {
+ computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
+ buffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex,
+ translated->maxIndex, offset);
+ }
}
else if (staticBuffer && staticBuffer->getBufferSize() != 0 && staticBuffer->getIndexType() == type && alignedOffset)
{
indexBuffer = staticBuffer;
- streamOffset = staticBuffer->lookupRange(offset, count, &translated->minIndex, &translated->maxIndex);
-
- if (streamOffset == -1)
+ if (!staticBuffer->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex,
+ &translated->maxIndex, &streamOffset))
{
- streamOffset = (offset / indexTypeSize(type)) * indexTypeSize(destinationIndexType);
+ streamOffset = (offset / gl::ComputeTypeSize(type)) * gl::ComputeTypeSize(destinationIndexType);
computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
- staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
+ staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex,
+ translated->maxIndex, streamOffset);
}
}
else
{
- int convertCount = count;
+ unsigned int convertCount = count;
if (staticBuffer)
{
if (staticBuffer->getBufferSize() == 0 && alignedOffset)
{
indexBuffer = staticBuffer;
- convertCount = storage->getSize() / indexTypeSize(type);
+ convertCount = storage->getSize() / gl::ComputeTypeSize(type);
}
else
{
@@ -201,12 +213,22 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
return GL_INVALID_OPERATION;
}
- unsigned int bufferSizeRequired = convertCount * indexTypeSize(destinationIndexType);
- indexBuffer->reserveBufferSpace(bufferSizeRequired, type);
+ unsigned int indexTypeSize = gl::ComputeTypeSize(destinationIndexType);
+ if (convertCount > std::numeric_limits<unsigned int>::max() / indexTypeSize)
+ {
+ ERR("Reserving %u indicies of %u bytes each exceeds the maximum buffer size.", convertCount, indexTypeSize);
+ return GL_OUT_OF_MEMORY;
+ }
+
+ unsigned int bufferSizeRequired = convertCount * indexTypeSize;
+ if (!indexBuffer->reserveBufferSpace(bufferSizeRequired, type))
+ {
+ ERR("Failed to reserve %u bytes in an index buffer.", bufferSizeRequired);
+ return GL_OUT_OF_MEMORY;
+ }
void* output = NULL;
- streamOffset = indexBuffer->mapBuffer(bufferSizeRequired, &output);
- if (streamOffset == -1 || output == NULL)
+ if (!indexBuffer->mapBuffer(bufferSizeRequired, &output, &streamOffset))
{
ERR("Failed to map index buffer.");
return GL_OUT_OF_MEMORY;
@@ -224,20 +246,21 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
if (staticBuffer)
{
- streamOffset = (offset / indexTypeSize(type)) * indexTypeSize(destinationIndexType);
- staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
+ streamOffset = (offset / gl::ComputeTypeSize(type)) * gl::ComputeTypeSize(destinationIndexType);
+ staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex,
+ translated->maxIndex, streamOffset);
}
}
translated->storage = directStorage ? storage : NULL;
translated->indexBuffer = indexBuffer->getIndexBuffer();
translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial();
- translated->startIndex = streamOffset / indexTypeSize(destinationIndexType);
+ translated->startIndex = streamOffset / gl::ComputeTypeSize(destinationIndexType);
translated->startOffset = streamOffset;
if (buffer)
{
- buffer->promoteStaticUsage(count * indexTypeSize(type));
+ buffer->promoteStaticUsage(count * gl::ComputeTypeSize(type));
}
return GL_NO_ERROR;
@@ -256,7 +279,7 @@ StaticIndexBufferInterface *IndexDataManager::getCountingIndices(GLsizei count)
mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT);
void* mappedMemory = NULL;
- if (mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory) == -1 || mappedMemory == NULL)
+ if (!mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory, NULL))
{
ERR("Failed to map counting buffer.");
return NULL;
@@ -286,7 +309,7 @@ StaticIndexBufferInterface *IndexDataManager::getCountingIndices(GLsizei count)
mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT);
void* mappedMemory = NULL;
- if (mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory) == -1 || mappedMemory == NULL)
+ if (!mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory, NULL))
{
ERR("Failed to map counting buffer.");
return NULL;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp
new file mode 100644
index 0000000000..610a5efb9c
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp
@@ -0,0 +1,97 @@
+#include "precompiled.h"
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// IndexRangeCache.cpp: Defines the rx::IndexRangeCache class which stores information about
+// ranges of indices.
+
+#include "libGLESv2/renderer/IndexRangeCache.h"
+#include "common/debug.h"
+#include "libGLESv2/utilities.h"
+#include <tuple>
+
+namespace rx
+{
+
+void IndexRangeCache::addRange(GLenum type, unsigned int offset, GLsizei count, unsigned int minIdx, unsigned int maxIdx,
+ unsigned int streamOffset)
+{
+ mIndexRangeCache[IndexRange(type, offset, count)] = IndexBounds(minIdx, maxIdx, streamOffset);
+}
+
+void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size)
+{
+ unsigned int invalidateStart = offset;
+ unsigned int invalidateEnd = offset + size;
+
+ IndexRangeMap::iterator i = mIndexRangeCache.begin();
+ while (i != mIndexRangeCache.end())
+ {
+ unsigned int rangeStart = i->second.streamOffset;
+ unsigned int rangeEnd = i->second.streamOffset + (gl::ComputeTypeSize(i->first.type) * i->first.count);
+
+ if (invalidateEnd < rangeStart || invalidateStart > rangeEnd)
+ {
+ ++i;
+ }
+ else
+ {
+ i = mIndexRangeCache.erase(i);
+ }
+ }
+}
+
+bool IndexRangeCache::findRange(GLenum type, unsigned int offset, GLsizei count, unsigned int *outMinIndex,
+ unsigned int *outMaxIndex, unsigned int *outStreamOffset) const
+{
+ IndexRangeMap::const_iterator i = mIndexRangeCache.find(IndexRange(type, offset, count));
+ if (i != mIndexRangeCache.end())
+ {
+ if (outMinIndex) *outMinIndex = i->second.minIndex;
+ if (outMaxIndex) *outMaxIndex = i->second.maxIndex;
+ if (outStreamOffset) *outStreamOffset = i->second.streamOffset;
+ return true;
+ }
+ else
+ {
+ if (outMinIndex) *outMinIndex = 0;
+ if (outMaxIndex) *outMaxIndex = 0;
+ if (outStreamOffset) *outStreamOffset = 0;
+ return false;
+ }
+}
+
+void IndexRangeCache::clear()
+{
+ mIndexRangeCache.clear();
+}
+
+IndexRangeCache::IndexRange::IndexRange()
+ : type(GL_NONE), offset(0), count(0)
+{
+}
+
+IndexRangeCache::IndexRange::IndexRange(GLenum typ, intptr_t off, GLsizei c)
+ : type(typ), offset(off), count(c)
+{
+}
+
+bool IndexRangeCache::IndexRange::operator<(const IndexRange& rhs) const
+{
+ return std::make_tuple(type, offset, count) < std::make_tuple(rhs.type, rhs.offset, rhs.count);
+}
+
+IndexRangeCache::IndexBounds::IndexBounds()
+ : minIndex(0), maxIndex(0), streamOffset(0)
+{
+}
+
+IndexRangeCache::IndexBounds::IndexBounds(unsigned int minIdx, unsigned int maxIdx, unsigned int offset)
+ : minIndex(minIdx), maxIndex(maxIdx), streamOffset(offset)
+{
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h
new file mode 100644
index 0000000000..56834306f2
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// IndexRangeCache.h: Defines the rx::IndexRangeCache class which stores information about
+// ranges of indices.
+
+#ifndef LIBGLESV2_RENDERER_INDEXRANGECACHE_H_
+#define LIBGLESV2_RENDERER_INDEXRANGECACHE_H_
+
+#include "common/angleutils.h"
+
+namespace rx
+{
+
+class IndexRangeCache
+{
+ public:
+ void addRange(GLenum type, unsigned int offset, GLsizei count, unsigned int minIdx, unsigned int maxIdx,
+ unsigned int streamOffset);
+ bool findRange(GLenum type, unsigned int offset, GLsizei count, unsigned int *outMinIndex,
+ unsigned int *outMaxIndex, unsigned int *outStreamOffset) const;
+
+ void invalidateRange(unsigned int offset, unsigned int size);
+ void clear();
+
+ private:
+ struct IndexRange
+ {
+ GLenum type;
+ unsigned int offset;
+ GLsizei count;
+
+ IndexRange();
+ IndexRange(GLenum type, intptr_t offset, GLsizei count);
+
+ bool operator<(const IndexRange& rhs) const;
+ };
+
+ struct IndexBounds
+ {
+ unsigned int minIndex;
+ unsigned int maxIndex;
+ unsigned int streamOffset;
+
+ IndexBounds();
+ IndexBounds(unsigned int minIdx, unsigned int maxIdx, unsigned int offset);
+ };
+
+ typedef std::map<IndexRange, IndexBounds> IndexRangeMap;
+ IndexRangeMap mIndexRangeCache;
+};
+
+}
+
+#endif LIBGLESV2_RENDERER_INDEXRANGECACHE_H
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.cpp
index 0402bb35ac..1552f3a326 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.cpp
@@ -28,6 +28,13 @@ InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInp
mCounter = 0;
mDevice = NULL;
mDeviceContext = NULL;
+ mCurrentIL = NULL;
+ for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ mCurrentBuffers[i] = -1;
+ mCurrentVertexStrides[i] = -1;
+ mCurrentVertexOffsets[i] = -1;
+ }
}
InputLayoutCache::~InputLayoutCache()
@@ -49,6 +56,18 @@ void InputLayoutCache::clear()
i->second.inputLayout->Release();
}
mInputLayoutMap.clear();
+ markDirty();
+}
+
+void InputLayoutCache::markDirty()
+{
+ mCurrentIL = NULL;
+ for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ mCurrentBuffers[i] = -1;
+ mCurrentVertexStrides[i] = -1;
+ mCurrentVertexOffsets[i] = -1;
+ }
}
GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
@@ -66,6 +85,7 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M
InputLayoutKey ilKey = { 0 };
ID3D11Buffer *vertexBuffers[gl::MAX_VERTEX_ATTRIBS] = { NULL };
+ unsigned int vertexBufferSerials[gl::MAX_VERTEX_ATTRIBS] = { 0 };
UINT vertexStrides[gl::MAX_VERTEX_ATTRIBS] = { 0 };
UINT vertexOffsets[gl::MAX_VERTEX_ATTRIBS] = { 0 };
@@ -83,18 +103,19 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M
// Record the type of the associated vertex shader vector in our key
// This will prevent mismatched vertex shaders from using the same input layout
GLint attributeSize;
- programBinary->getActiveAttribute(ilKey.elementCount, 0, NULL, &attributeSize, &ilKey.glslElementType[ilKey.elementCount], NULL);
-
- ilKey.elements[ilKey.elementCount].SemanticName = semanticName;
- ilKey.elements[ilKey.elementCount].SemanticIndex = sortedSemanticIndices[i];
- ilKey.elements[ilKey.elementCount].Format = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDXGIFormat(*attributes[i].attribute) : DXGI_FORMAT_R32G32B32A32_FLOAT;
- ilKey.elements[ilKey.elementCount].InputSlot = i;
- ilKey.elements[ilKey.elementCount].AlignedByteOffset = 0;
- ilKey.elements[ilKey.elementCount].InputSlotClass = inputClass;
- ilKey.elements[ilKey.elementCount].InstanceDataStepRate = attributes[i].divisor;
+ programBinary->getActiveAttribute(ilKey.elementCount, 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL);
+
+ ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName;
+ ilKey.elements[ilKey.elementCount].desc.SemanticIndex = sortedSemanticIndices[i];
+ ilKey.elements[ilKey.elementCount].desc.Format = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDXGIFormat(*attributes[i].attribute) : DXGI_FORMAT_R32G32B32A32_FLOAT;
+ ilKey.elements[ilKey.elementCount].desc.InputSlot = i;
+ ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0;
+ ilKey.elements[ilKey.elementCount].desc.InputSlotClass = inputClass;
+ ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = attributes[i].divisor;
ilKey.elementCount++;
vertexBuffers[i] = bufferStorage ? bufferStorage->getBuffer() : vertexBuffer->getBuffer();
+ vertexBufferSerials[i] = bufferStorage ? bufferStorage->getSerial() : vertexBuffer->getSerial();
vertexStrides[i] = attributes[i].stride;
vertexOffsets[i] = attributes[i].offset;
}
@@ -112,7 +133,13 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M
{
ShaderExecutable11 *shader = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable());
- HRESULT result = mDevice->CreateInputLayout(ilKey.elements, ilKey.elementCount, shader->getFunction(), shader->getLength(), &inputLayout);
+ D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS];
+ for (unsigned int j = 0; j < ilKey.elementCount; ++j)
+ {
+ descs[j] = ilKey.elements[j].desc;
+ }
+
+ HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader->getFunction(), shader->getLength(), &inputLayout);
if (FAILED(result))
{
ERR("Failed to crate input layout, result: 0x%08x", result);
@@ -143,8 +170,23 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M
mInputLayoutMap.insert(std::make_pair(ilKey, inputCounterPair));
}
- mDeviceContext->IASetInputLayout(inputLayout);
- mDeviceContext->IASetVertexBuffers(0, gl::MAX_VERTEX_ATTRIBS, vertexBuffers, vertexStrides, vertexOffsets);
+ if (inputLayout != mCurrentIL)
+ {
+ mDeviceContext->IASetInputLayout(inputLayout);
+ mCurrentIL = inputLayout;
+ }
+
+ for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (vertexBufferSerials[i] != mCurrentBuffers[i] || vertexStrides[i] != mCurrentVertexStrides[i] ||
+ vertexOffsets[i] != mCurrentVertexOffsets[i])
+ {
+ mDeviceContext->IASetVertexBuffers(i, 1, &vertexBuffers[i], &vertexStrides[i], &vertexOffsets[i]);
+ mCurrentBuffers[i] = vertexBufferSerials[i];
+ mCurrentVertexStrides[i] = vertexStrides[i];
+ mCurrentVertexOffsets[i] = vertexOffsets[i];
+ }
+ }
return GL_NO_ERROR;
}
@@ -154,13 +196,18 @@ std::size_t InputLayoutCache::hashInputLayout(const InputLayoutKey &inputLayout)
static const unsigned int seed = 0xDEADBEEF;
std::size_t hash = 0;
- MurmurHash3_x86_32(&inputLayout, sizeof(InputLayoutKey), seed, &hash);
+ MurmurHash3_x86_32(inputLayout.begin(), inputLayout.end() - inputLayout.begin(), seed, &hash);
return hash;
}
bool InputLayoutCache::compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b)
{
- return memcmp(&a, &b, sizeof(InputLayoutKey)) == 0;
+ if (a.elementCount != b.elementCount)
+ {
+ return false;
+ }
+
+ return std::equal(a.begin(), a.end(), b.begin());
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.h
index d95f39fae4..bb1a8eebcf 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.h
@@ -30,6 +30,7 @@ class InputLayoutCache
void initialize(ID3D11Device *device, ID3D11DeviceContext *context);
void clear();
+ void markDirty();
GLenum applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
gl::ProgramBinary *programBinary);
@@ -37,11 +38,26 @@ class InputLayoutCache
private:
DISALLOW_COPY_AND_ASSIGN(InputLayoutCache);
+ struct InputLayoutElement
+ {
+ D3D11_INPUT_ELEMENT_DESC desc;
+ GLenum glslElementType;
+ };
+
struct InputLayoutKey
{
unsigned int elementCount;
- D3D11_INPUT_ELEMENT_DESC elements[gl::MAX_VERTEX_ATTRIBS];
- GLenum glslElementType[gl::MAX_VERTEX_ATTRIBS];
+ InputLayoutElement elements[gl::MAX_VERTEX_ATTRIBS];
+
+ const char *begin() const
+ {
+ return reinterpret_cast<const char*>(&elementCount);
+ }
+
+ const char *end() const
+ {
+ return reinterpret_cast<const char*>(&elements[elementCount]);
+ }
};
struct InputLayoutCounterPair
@@ -50,6 +66,11 @@ class InputLayoutCache
unsigned long long lastUsedTime;
};
+ ID3D11InputLayout *mCurrentIL;
+ unsigned int mCurrentBuffers[gl::MAX_VERTEX_ATTRIBS];
+ UINT mCurrentVertexStrides[gl::MAX_VERTEX_ATTRIBS];
+ UINT mCurrentVertexOffsets[gl::MAX_VERTEX_ATTRIBS];
+
static std::size_t hashInputLayout(const InputLayoutKey &inputLayout);
static bool compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b);
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp
index f60a88f97a..b3111af72b 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp
@@ -231,7 +231,7 @@ ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::Rasterizer
rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor;
rasterDesc.DepthClipEnable = TRUE;
rasterDesc.ScissorEnable = scissorEnabled ? TRUE : FALSE;
- rasterDesc.MultisampleEnable = TRUE;
+ rasterDesc.MultisampleEnable = rasterState.multiSample;
rasterDesc.AntialiasedLineEnable = FALSE;
ID3D11RasterizerState *dx11RasterizerState = NULL;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.cpp
index cf226de17b..2667cc6fa7 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.cpp
@@ -329,44 +329,21 @@ RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTarget *target)
ID3D11Texture2D *RenderTarget11::getTexture() const
{
- if (mTexture)
- {
- mTexture->AddRef();
- }
-
return mTexture;
}
-// Adds reference, caller must call Release
ID3D11RenderTargetView *RenderTarget11::getRenderTargetView() const
{
- if (mRenderTarget)
- {
- mRenderTarget->AddRef();
- }
-
return mRenderTarget;
}
-// Adds reference, caller must call Release
ID3D11DepthStencilView *RenderTarget11::getDepthStencilView() const
{
- if (mDepthStencil)
- {
- mDepthStencil->AddRef();
- }
-
return mDepthStencil;
}
-// Adds reference, caller must call Release
ID3D11ShaderResourceView *RenderTarget11::getShaderResourceView() const
{
- if (mShaderResource)
- {
- mShaderResource->AddRef();
- }
-
return mShaderResource;
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.h b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.h
index dc697cf0e3..97827f2639 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.h
@@ -27,16 +27,9 @@ class RenderTarget11 : public RenderTarget
static RenderTarget11 *makeRenderTarget11(RenderTarget *renderTarget);
- // Adds reference, caller must call Release
ID3D11Texture2D *getTexture() const;
-
- // Adds reference, caller must call Release
ID3D11RenderTargetView *getRenderTargetView() const;
-
- // Adds reference, caller must call Release
ID3D11DepthStencilView *getDepthStencilView() const;
-
- // Adds reference, caller must call Release
ID3D11ShaderResourceView *getShaderResourceView() const;
unsigned int getSubresourceIndex() const;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp
index 218356c59b..21ad223467 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp
@@ -7,19 +7,25 @@
// Renderer.cpp: Implements EGL dependencies for creating and destroying Renderer instances.
+#include <EGL/eglext.h>
#include "libGLESv2/main.h"
#include "libGLESv2/Program.h"
#include "libGLESv2/renderer/Renderer.h"
-#if defined(ANGLE_ENABLE_D3D11)
-# include "libGLESv2/renderer/Renderer11.h"
-# define D3DERR_OUTOFVIDEOMEMORY MAKE_HRESULT( 1, 0x876, 380 )
+#ifndef ANGLE_ENABLE_D3D11
+#include "libGLESv2/renderer/Renderer9.h"
#else
-# include "libGLESv2/renderer/Renderer9.h"
+#include "libGLESv2/renderer/Renderer11.h"
#endif
#include "libGLESv2/utilities.h"
+#include "third_party/trace_event/trace_event.h"
-#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
-#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3
+#if !defined(ANGLE_ENABLE_D3D11)
+// Enables use of the Direct3D 11 API for a default display, when available
+#define ANGLE_ENABLE_D3D11 0
+#endif
+
+#ifndef D3DERR_OUTOFVIDEOMEMORY
+#define D3DERR_OUTOFVIDEOMEMORY MAKE_HRESULT(1, 0x876, 380)
#endif
#ifdef __MINGW32__
@@ -61,6 +67,7 @@ Renderer::~Renderer()
bool Renderer::initializeCompiler()
{
+ TRACE_EVENT0("gpu", "initializeCompiler");
#if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES)
// Find a D3DCompiler module that had already been loaded based on a predefined list of versions.
static TCHAR* d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES;
@@ -188,14 +195,15 @@ ShaderBlob *Renderer::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, co
extern "C"
{
-rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, bool softwareDevice)
+rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayType displayId)
{
rx::Renderer *renderer = NULL;
EGLint status = EGL_BAD_ALLOC;
-#if defined(ANGLE_ENABLE_D3D11)
+#if ANGLE_ENABLE_D3D11
renderer = new rx::Renderer11(display, hDc);
#else
+ bool softwareDevice = (displayId == EGL_SOFTWARE_DISPLAY_ANGLE);
renderer = new rx::Renderer9(display, hDc, softwareDevice);
#endif
@@ -217,4 +225,4 @@ void glDestroyRenderer(rx::Renderer *renderer)
delete renderer;
}
-}
+} \ No newline at end of file
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h
index 656cb0f1bf..04e877ba9e 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h
@@ -13,6 +13,10 @@
#include "libGLESv2/Uniform.h"
#include "libGLESv2/angletypes.h"
+#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
+#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3
+#endif
+
const int versionWindowsVista = MAKEWORD(0x00, 0x06);
const int versionWindows7 = MAKEWORD(0x01, 0x06);
@@ -221,6 +225,8 @@ class Renderer
virtual QueryImpl *createQuery(GLenum type) = 0;
virtual FenceImpl *createFence() = 0;
+ virtual bool getLUID(LUID *adapterLuid) const = 0;
+
protected:
bool initializeCompiler();
ShaderBlob *compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, UINT optimizationFlags, bool alternateFlags);
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp
index cf083963e1..a43101807a 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp
@@ -35,7 +35,8 @@
#include "libGLESv2/renderer/shaders/compiled/passthroughlumalpha11ps.h"
#include "libGLESv2/renderer/shaders/compiled/clear11vs.h"
-#include "libGLESv2/renderer/shaders/compiled/clear11ps.h"
+#include "libGLESv2/renderer/shaders/compiled/clearsingle11ps.h"
+#include "libGLESv2/renderer/shaders/compiled/clearmultiple11ps.h"
#include "libEGL/Display.h"
@@ -87,7 +88,8 @@ Renderer11::Renderer11(egl::Display *display, HDC hDc) : Renderer(display), mDc(
mClearVB = NULL;
mClearIL = NULL;
mClearVS = NULL;
- mClearPS = NULL;
+ mClearSinglePS = NULL;
+ mClearMultiplePS = NULL;
mClearScissorRS = NULL;
mClearNoScissorRS = NULL;
@@ -161,25 +163,44 @@ EGLint Renderer11::initialize()
D3D_FEATURE_LEVEL_10_0,
};
- HRESULT result = D3D11CreateDevice(NULL,
- D3D_DRIVER_TYPE_HARDWARE,
- NULL,
- #if defined(_DEBUG)
- D3D11_CREATE_DEVICE_DEBUG,
- #else
- 0,
- #endif
- featureLevels,
- ArraySize(featureLevels),
- D3D11_SDK_VERSION,
- &mDevice,
- &mFeatureLevel,
- &mDeviceContext);
+ HRESULT result = S_OK;
+
+#ifdef _DEBUG
+ result = D3D11CreateDevice(NULL,
+ D3D_DRIVER_TYPE_HARDWARE,
+ NULL,
+ D3D11_CREATE_DEVICE_DEBUG,
+ featureLevels,
+ ArraySize(featureLevels),
+ D3D11_SDK_VERSION,
+ &mDevice,
+ &mFeatureLevel,
+ &mDeviceContext);
if (!mDevice || FAILED(result))
{
- ERR("Could not create D3D11 device - aborting!\n");
- return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer
+ ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n");
+ }
+
+ if (!mDevice || FAILED(result))
+#endif
+ {
+ result = D3D11CreateDevice(NULL,
+ D3D_DRIVER_TYPE_HARDWARE,
+ NULL,
+ 0,
+ featureLevels,
+ ArraySize(featureLevels),
+ D3D11_SDK_VERSION,
+ &mDevice,
+ &mFeatureLevel,
+ &mDeviceContext);
+
+ if (!mDevice || FAILED(result))
+ {
+ ERR("Could not create D3D11 device - aborting!\n");
+ return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer
+ }
}
IDXGIDevice *dxgiDevice = NULL;
@@ -301,7 +322,6 @@ EGLint Renderer11::initialize()
{
DXGI_FORMAT_R32_FLOAT,
DXGI_FORMAT_R32G32_FLOAT,
- DXGI_FORMAT_R32G32B32_FLOAT,
DXGI_FORMAT_R32G32B32A32_FLOAT,
};
@@ -655,7 +675,23 @@ void Renderer11::setBlendState(const gl::BlendState &blendState, const gl::Color
"blend state.");
}
- const float blendColors[] = { blendColor.red, blendColor.green, blendColor.blue, blendColor.alpha };
+ float blendColors[4] = {0.0f};
+ if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
+ blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
+ {
+ blendColors[0] = blendColor.red;
+ blendColors[1] = blendColor.green;
+ blendColors[2] = blendColor.blue;
+ blendColors[3] = blendColor.alpha;
+ }
+ else
+ {
+ blendColors[0] = blendColor.alpha;
+ blendColors[1] = blendColor.alpha;
+ blendColors[2] = blendColor.alpha;
+ blendColors[3] = blendColor.alpha;
+ }
+
mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask);
mCurBlendState = blendState;
@@ -798,23 +834,29 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count)
{
D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
+ GLsizei minCount = 0;
+
switch (mode)
{
- case GL_POINTS: primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; break;
- case GL_LINES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; break;
- case GL_LINE_LOOP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; break;
- case GL_LINE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; break;
- case GL_TRIANGLES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; break;
- case GL_TRIANGLE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; break;
+ case GL_POINTS: primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; minCount = 1; break;
+ case GL_LINES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; minCount = 2; break;
+ case GL_LINE_LOOP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break;
+ case GL_LINE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break;
+ case GL_TRIANGLES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break;
+ case GL_TRIANGLE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; minCount = 3; break;
// emulate fans via rewriting index buffer
- case GL_TRIANGLE_FAN: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; break;
+ case GL_TRIANGLE_FAN: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break;
default:
return gl::error(GL_INVALID_ENUM, false);
}
- mDeviceContext->IASetPrimitiveTopology(primitiveTopology);
+ if (primitiveTopology != mCurrentPrimitiveTopology)
+ {
+ mDeviceContext->IASetPrimitiveTopology(primitiveTopology);
+ mCurrentPrimitiveTopology = primitiveTopology;
+ }
- return count > 0;
+ return count >= minCount;
}
bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
@@ -976,9 +1018,6 @@ bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
mDepthStencilInitialized = true;
}
- SafeRelease(framebufferRTVs);
- SafeRelease(framebufferDSV);
-
return true;
}
@@ -1093,7 +1132,16 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
}
}
- const int spaceNeeded = (count + 1) * sizeof(unsigned int);
+ // Checked by Renderer11::applyPrimitiveType
+ ASSERT(count >= 0);
+
+ if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
+ {
+ ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int);
if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
{
ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
@@ -1101,15 +1149,15 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
}
void* mappedMemory = NULL;
- int offset = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory);
- if (offset == -1 || mappedMemory == NULL)
+ unsigned int offset;
+ if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
{
ERR("Could not map index buffer for GL_LINE_LOOP.");
return gl::error(GL_OUT_OF_MEMORY);
}
unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
- unsigned int indexBufferOffset = static_cast<unsigned int>(offset);
+ unsigned int indexBufferOffset = offset;
switch (type)
{
@@ -1187,8 +1235,18 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic
}
}
- const int numTris = count - 2;
- const int spaceNeeded = (numTris * 3) * sizeof(unsigned int);
+ // Checked by Renderer11::applyPrimitiveType
+ ASSERT(count >= 3);
+
+ const unsigned int numTris = count - 2;
+
+ if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3)))
+ {
+ ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int);
if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
{
ERR("Could not reserve enough space in scratch index buffer for GL_TRIANGLE_FAN.");
@@ -1196,20 +1254,20 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic
}
void* mappedMemory = NULL;
- int offset = mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory);
- if (offset == -1 || mappedMemory == NULL)
+ unsigned int offset;
+ if (!mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
{
ERR("Could not map scratch index buffer for GL_TRIANGLE_FAN.");
return gl::error(GL_OUT_OF_MEMORY);
}
unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
- unsigned int indexBufferOffset = static_cast<unsigned int>(offset);
+ unsigned int indexBufferOffset = offset;
switch (type)
{
case GL_NONE: // Non-indexed draw
- for (int i = 0; i < numTris; i++)
+ for (unsigned int i = 0; i < numTris; i++)
{
data[i*3 + 0] = 0;
data[i*3 + 1] = i + 1;
@@ -1217,7 +1275,7 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic
}
break;
case GL_UNSIGNED_BYTE:
- for (int i = 0; i < numTris; i++)
+ for (unsigned int i = 0; i < numTris; i++)
{
data[i*3 + 0] = static_cast<const GLubyte*>(indices)[0];
data[i*3 + 1] = static_cast<const GLubyte*>(indices)[i + 1];
@@ -1225,7 +1283,7 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic
}
break;
case GL_UNSIGNED_SHORT:
- for (int i = 0; i < numTris; i++)
+ for (unsigned int i = 0; i < numTris; i++)
{
data[i*3 + 0] = static_cast<const GLushort*>(indices)[0];
data[i*3 + 1] = static_cast<const GLushort*>(indices)[i + 1];
@@ -1233,7 +1291,7 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic
}
break;
case GL_UNSIGNED_INT:
- for (int i = 0; i < numTris; i++)
+ for (unsigned int i = 0; i < numTris; i++)
{
data[i*3 + 0] = static_cast<const GLuint*>(indices)[0];
data[i*3 + 1] = static_cast<const GLuint*>(indices)[i + 1];
@@ -1347,21 +1405,21 @@ void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArra
float (*mapVS)[4] = NULL;
float (*mapPS)[4] = NULL;
- if (totalRegisterCountVS > 0 && vertexUniformsDirty)
- {
- D3D11_MAPPED_SUBRESOURCE map = {0};
- HRESULT result = mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
- ASSERT(SUCCEEDED(result));
- mapVS = (float(*)[4])map.pData;
- }
-
- if (totalRegisterCountPS > 0 && pixelUniformsDirty)
- {
- D3D11_MAPPED_SUBRESOURCE map = {0};
- HRESULT result = mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
- ASSERT(SUCCEEDED(result));
- mapPS = (float(*)[4])map.pData;
- }
+ if (totalRegisterCountVS > 0 && vertexUniformsDirty)
+ {
+ D3D11_MAPPED_SUBRESOURCE map = {0};
+ HRESULT result = mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
+ ASSERT(SUCCEEDED(result));
+ mapVS = (float(*)[4])map.pData;
+ }
+
+ if (totalRegisterCountPS > 0 && pixelUniformsDirty)
+ {
+ D3D11_MAPPED_SUBRESOURCE map = {0};
+ HRESULT result = mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
+ ASSERT(SUCCEEDED(result));
+ mapPS = (float(*)[4])map.pData;
+ }
for (gl::UniformArray::iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++)
{
@@ -1392,9 +1450,18 @@ void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArra
{
mDeviceContext->Unmap(pixelConstantBuffer, 0);
}
-
- mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer);
- mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer);
+
+ if (mCurrentVertexConstantBuffer != vertexConstantBuffer)
+ {
+ mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer);
+ mCurrentVertexConstantBuffer = vertexConstantBuffer;
+ }
+
+ if (mCurrentPixelConstantBuffer != pixelConstantBuffer)
+ {
+ mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer);
+ mCurrentPixelConstantBuffer = pixelConstantBuffer;
+ }
// Driver uniforms
if (!mDriverConstantBufferVS)
@@ -1442,7 +1509,11 @@ void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArra
}
// needed for the point sprite geometry shader
- mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS);
+ if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS)
+ {
+ mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS);
+ mCurrentGeometryConstantBuffer = mDriverConstantBufferPS;
+ }
}
void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
@@ -1467,7 +1538,7 @@ void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *
if (needMaskedColorClear || needMaskedStencilClear || needScissoredClear)
{
- maskedClear(clearParams);
+ maskedClear(clearParams, frameBuffer->usingExtendedDrawBuffers());
}
else
{
@@ -1499,8 +1570,6 @@ void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *
clearParams.colorClearValue.blue,
clearParams.colorClearValue.alpha };
mDeviceContext->ClearRenderTargetView(framebufferRTV, clearValues);
-
- framebufferRTV->Release();
}
}
}
@@ -1538,20 +1607,18 @@ void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *
UINT8 stencilClear = clearParams.stencilClearValue & 0x000000FF;
mDeviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear);
-
- framebufferDSV->Release();
}
}
}
}
-void Renderer11::maskedClear(const gl::ClearParameters &clearParams)
+void Renderer11::maskedClear(const gl::ClearParameters &clearParams, bool usingExtendedDrawBuffers)
{
HRESULT result;
if (!mClearResourcesInitialized)
{
- ASSERT(!mClearVB && !mClearVS && !mClearPS && !mClearScissorRS && !mClearNoScissorRS);
+ ASSERT(!mClearVB && !mClearVS && !mClearSinglePS && !mClearMultiplePS && !mClearScissorRS && !mClearNoScissorRS);
D3D11_BUFFER_DESC vbDesc;
vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex) * 4;
@@ -1579,9 +1646,13 @@ void Renderer11::maskedClear(const gl::ClearParameters &clearParams)
ASSERT(SUCCEEDED(result));
d3d11::SetDebugName(mClearVS, "Renderer11 masked clear vertex shader");
- result = mDevice->CreatePixelShader(g_PS_Clear, sizeof(g_PS_Clear), NULL, &mClearPS);
+ result = mDevice->CreatePixelShader(g_PS_ClearSingle, sizeof(g_PS_ClearSingle), NULL, &mClearSinglePS);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mClearSinglePS, "Renderer11 masked clear pixel shader (1 RT)");
+
+ result = mDevice->CreatePixelShader(g_PS_ClearMultiple, sizeof(g_PS_ClearMultiple), NULL, &mClearMultiplePS);
ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mClearPS, "Renderer11 masked clear pixel shader");
+ d3d11::SetDebugName(mClearMultiplePS, "Renderer11 masked clear pixel shader (MRT)");
D3D11_RASTERIZER_DESC rsScissorDesc;
rsScissorDesc.FillMode = D3D11_FILL_SOLID;
@@ -1688,9 +1759,11 @@ void Renderer11::maskedClear(const gl::ClearParameters &clearParams)
mDeviceContext->RSSetState(mScissorEnabled ? mClearScissorRS : mClearNoScissorRS);
// Apply shaders
+ ID3D11PixelShader *pixelShader = usingExtendedDrawBuffers ? mClearMultiplePS : mClearSinglePS;
+
mDeviceContext->IASetInputLayout(mClearIL);
mDeviceContext->VSSetShader(mClearVS, NULL, 0);
- mDeviceContext->PSSetShader(mClearPS, NULL, 0);
+ mDeviceContext->PSSetShader(pixelShader, NULL, 0);
mDeviceContext->GSSetShader(NULL, NULL, 0);
// Apply vertex buffer
@@ -1741,6 +1814,14 @@ void Renderer11::markAllStateDirty()
mAppliedProgramBinarySerial = 0;
memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants));
memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants));
+
+ mInputLayoutCache.markDirty();
+
+ mCurrentVertexConstantBuffer = NULL;
+ mCurrentPixelConstantBuffer = NULL;
+ mCurrentGeometryConstantBuffer = NULL;
+
+ mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
}
void Renderer11::releaseDeviceResources()
@@ -1760,111 +1841,31 @@ void Renderer11::releaseDeviceResources()
delete mTriangleFanIB;
mTriangleFanIB = NULL;
- if (mCopyVB)
- {
- mCopyVB->Release();
- mCopyVB = NULL;
- }
-
- if (mCopySampler)
- {
- mCopySampler->Release();
- mCopySampler = NULL;
- }
-
- if (mCopyIL)
- {
- mCopyIL->Release();
- mCopyIL = NULL;
- }
-
- if (mCopyVS)
- {
- mCopyVS->Release();
- mCopyVS = NULL;
- }
-
- if (mCopyRGBAPS)
- {
- mCopyRGBAPS->Release();
- mCopyRGBAPS = NULL;
- }
-
- if (mCopyRGBPS)
- {
- mCopyRGBPS->Release();
- mCopyRGBPS = NULL;
- }
-
- if (mCopyLumPS)
- {
- mCopyLumPS->Release();
- mCopyLumPS = NULL;
- }
-
- if (mCopyLumAlphaPS)
- {
- mCopyLumAlphaPS->Release();
- mCopyLumAlphaPS = NULL;
- }
+ SafeRelease(mCopyVB);
+ SafeRelease(mCopySampler);
+ SafeRelease(mCopyIL);
+ SafeRelease(mCopyIL);
+ SafeRelease(mCopyVS);
+ SafeRelease(mCopyRGBAPS);
+ SafeRelease(mCopyRGBPS);
+ SafeRelease(mCopyLumPS);
+ SafeRelease(mCopyLumAlphaPS);
mCopyResourcesInitialized = false;
- if (mClearVB)
- {
- mClearVB->Release();
- mClearVB = NULL;
- }
-
- if (mClearIL)
- {
- mClearIL->Release();
- mClearIL = NULL;
- }
-
- if (mClearVS)
- {
- mClearVS->Release();
- mClearVS = NULL;
- }
-
- if (mClearPS)
- {
- mClearPS->Release();
- mClearPS = NULL;
- }
-
- if (mClearScissorRS)
- {
- mClearScissorRS->Release();
- mClearScissorRS = NULL;
- }
-
- if (mClearNoScissorRS)
- {
- mClearNoScissorRS->Release();
- mClearNoScissorRS = NULL;
- }
+ SafeRelease(mClearVB);
+ SafeRelease(mClearIL);
+ SafeRelease(mClearVS);
+ SafeRelease(mClearSinglePS);
+ SafeRelease(mClearMultiplePS);
+ SafeRelease(mClearScissorRS);
+ SafeRelease(mClearNoScissorRS);
mClearResourcesInitialized = false;
- if (mDriverConstantBufferVS)
- {
- mDriverConstantBufferVS->Release();
- mDriverConstantBufferVS = NULL;
- }
-
- if (mDriverConstantBufferPS)
- {
- mDriverConstantBufferPS->Release();
- mDriverConstantBufferPS = NULL;
- }
-
- if (mSyncQuery)
- {
- mSyncQuery->Release();
- mSyncQuery = NULL;
- }
+ SafeRelease(mDriverConstantBufferVS);
+ SafeRelease(mDriverConstantBufferPS);
+ SafeRelease(mSyncQuery);
}
void Renderer11::notifyDeviceLost()
@@ -2153,12 +2154,12 @@ unsigned int Renderer11::getMaxCombinedTextureImageUnits() const
unsigned int Renderer11::getReservedVertexUniformVectors() const
{
- return 0; // Driver uniforms are stored in a separate constant buffer
+ return 0; // Driver uniforms are stored in a separate constant buffer
}
unsigned int Renderer11::getReservedFragmentUniformVectors() const
{
- return 0; // Driver uniforms are stored in a separate constant buffer
+ return 0; // Driver uniforms are stored in a separate constant buffer
}
unsigned int Renderer11::getMaxVertexUniformVectors() const
@@ -2448,7 +2449,6 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so
TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance());
if (!storage11)
{
- source->Release();
ERR("Failed to retrieve the texture storage from the destination.");
return gl::error(GL_OUT_OF_MEMORY, false);
}
@@ -2456,7 +2456,6 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so
RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(level));
if (!destRenderTarget)
{
- source->Release();
ERR("Failed to retrieve the render target from the destination storage.");
return gl::error(GL_OUT_OF_MEMORY, false);
}
@@ -2464,7 +2463,6 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so
ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
if (!dest)
{
- source->Release();
ERR("Failed to retrieve the render target view from the destination render target.");
return gl::error(GL_OUT_OF_MEMORY, false);
}
@@ -2478,9 +2476,6 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so
bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(),
dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat);
- source->Release();
- dest->Release();
-
return ret;
}
@@ -2511,7 +2506,6 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so
TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance());
if (!storage11)
{
- source->Release();
ERR("Failed to retrieve the texture storage from the destination.");
return gl::error(GL_OUT_OF_MEMORY, false);
}
@@ -2519,7 +2513,6 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so
RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(target, level));
if (!destRenderTarget)
{
- source->Release();
ERR("Failed to retrieve the render target from the destination storage.");
return gl::error(GL_OUT_OF_MEMORY, false);
}
@@ -2527,7 +2520,6 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so
ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
if (!dest)
{
- source->Release();
ERR("Failed to retrieve the render target view from the destination render target.");
return gl::error(GL_OUT_OF_MEMORY, false);
}
@@ -2541,9 +2533,6 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so
bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(),
dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat);
- source->Release();
- dest->Release();
-
return ret;
}
@@ -2893,7 +2882,6 @@ bool Renderer11::getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned
{
ID3D11Resource *textureResource = NULL;
colorBufferRTV->GetResource(&textureResource);
- colorBufferRTV->Release();
if (textureResource)
{
@@ -3428,6 +3416,16 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R
{
ASSERT(readRect.width == drawRect.width && readRect.height == drawRect.height);
+ RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget);
+ if (!drawRenderTarget)
+ {
+ ERR("Failed to retrieve the draw render target from the draw framebuffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ ID3D11Texture2D *drawTexture = drawRenderTarget11->getTexture();
+ unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex();
+
RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget);
if (!readRenderTarget)
{
@@ -3439,16 +3437,13 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R
unsigned int readSubresource = 0;
if (readRenderTarget->getSamples() > 0)
{
- ID3D11Texture2D *unresolvedTexture = readRenderTarget11->getTexture();
-
- readTexture = resolveMultisampledTexture(unresolvedTexture, readRenderTarget11->getSubresourceIndex());
+ readTexture = resolveMultisampledTexture(readRenderTarget11->getTexture(), readRenderTarget11->getSubresourceIndex());
readSubresource = 0;
-
- unresolvedTexture->Release();
}
else
{
readTexture = readRenderTarget11->getTexture();
+ readTexture->AddRef();
readSubresource = readRenderTarget11->getSubresourceIndex();
}
@@ -3458,17 +3453,6 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R
return gl::error(GL_OUT_OF_MEMORY, false);
}
- RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget);
- if (!drawRenderTarget)
- {
- readTexture->Release();
- ERR("Failed to retrieve the draw render target from the draw framebuffer.");
- return gl::error(GL_OUT_OF_MEMORY, false);
- }
-
- ID3D11Texture2D *drawTexture = drawRenderTarget11->getTexture();
- unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex();
-
D3D11_BOX readBox;
readBox.left = readRect.x;
readBox.right = readRect.x + readRect.width;
@@ -3484,8 +3468,7 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R
mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, drawRect.x, drawRect.y, 0,
readTexture, readSubresource, pSrcBox);
- readTexture->Release();
- drawTexture->Release();
+ SafeRelease(readTexture);
return true;
}
@@ -3528,4 +3511,24 @@ ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source,
}
}
+bool Renderer11::getLUID(LUID *adapterLuid) const
+{
+ adapterLuid->HighPart = 0;
+ adapterLuid->LowPart = 0;
+
+ if (!mDxgiAdapter)
+ {
+ return false;
+ }
+
+ DXGI_ADAPTER_DESC adapterDesc;
+ if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc)))
+ {
+ return false;
+ }
+
+ *adapterLuid = adapterDesc.AdapterLuid;
+ return true;
+}
+
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h
index a3e42e9048..f024855f97 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h
@@ -182,6 +182,8 @@ class Renderer11 : public Renderer
void unapplyRenderTargets();
void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView);
+ virtual bool getLUID(LUID *adapterLuid) const;
+
private:
DISALLOW_COPY_AND_ASSIGN(Renderer11);
@@ -192,7 +194,7 @@ class Renderer11 : public Renderer
GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder,
GLint packAlignment, void *pixels);
- void maskedClear(const gl::ClearParameters &clearParams);
+ void maskedClear(const gl::ClearParameters &clearParams, bool usingExtendedDrawBuffers);
rx::Range getViewportBounds() const;
bool blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
@@ -286,6 +288,9 @@ class Renderer11 : public Renderer
float mCurNear;
float mCurFar;
+ // Currently applied primitive topology
+ D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology;
+
unsigned int mAppliedIBSerial;
unsigned int mAppliedStorageIBSerial;
unsigned int mAppliedIBOffset;
@@ -296,10 +301,14 @@ class Renderer11 : public Renderer
dx_VertexConstants mVertexConstants;
dx_VertexConstants mAppliedVertexConstants;
ID3D11Buffer *mDriverConstantBufferVS;
+ ID3D11Buffer *mCurrentVertexConstantBuffer;
dx_PixelConstants mPixelConstants;
dx_PixelConstants mAppliedPixelConstants;
ID3D11Buffer *mDriverConstantBufferPS;
+ ID3D11Buffer *mCurrentPixelConstantBuffer;
+
+ ID3D11Buffer *mCurrentGeometryConstantBuffer;
// Vertex, index and input layouts
VertexDataManager *mVertexDataManager;
@@ -325,7 +334,8 @@ class Renderer11 : public Renderer
ID3D11Buffer *mClearVB;
ID3D11InputLayout *mClearIL;
ID3D11VertexShader *mClearVS;
- ID3D11PixelShader *mClearPS;
+ ID3D11PixelShader *mClearSinglePS;
+ ID3D11PixelShader *mClearMultiplePS;
ID3D11RasterizerState *mClearScissorRS;
ID3D11RasterizerState *mClearNoScissorRS;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.cpp
index 8acbce4be7..d3f3814ae5 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.cpp
@@ -30,6 +30,8 @@
#include "libEGL/Display.h"
+#include "third_party/trace_event/trace_event.h"
+
// Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros
#define REF_RAST 0
@@ -41,10 +43,6 @@
#define ANGLE_ENABLE_D3D9EX 1
#endif // !defined(ANGLE_ENABLE_D3D9EX)
-#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
-#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3
-#endif
-
namespace rx
{
static const D3DFORMAT RenderTargetFormats[] =
@@ -188,10 +186,12 @@ EGLint Renderer9::initialize()
if (mSoftwareDevice)
{
+ TRACE_EVENT0("gpu", "GetModuleHandle_swiftshader");
mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll"));
}
else
{
+ TRACE_EVENT0("gpu", "GetModuleHandle_d3d9");
mD3d9Module = GetModuleHandle(TEXT("d3d9.dll"));
}
@@ -209,12 +209,14 @@ EGLint Renderer9::initialize()
// desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
{
+ TRACE_EVENT0("gpu", "D3d9Ex_QueryInterface");
ASSERT(mD3d9Ex);
mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
ASSERT(mD3d9);
}
else
{
+ TRACE_EVENT0("gpu", "Direct3DCreate9");
mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
}
@@ -232,21 +234,24 @@ EGLint Renderer9::initialize()
HRESULT result;
// Give up on getting device caps after about one second.
- for (int i = 0; i < 10; ++i)
{
- result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
- if (SUCCEEDED(result))
- {
- break;
- }
- else if (result == D3DERR_NOTAVAILABLE)
- {
- Sleep(100); // Give the driver some time to initialize/recover
- }
- else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from
+ TRACE_EVENT0("gpu", "GetDeviceCaps");
+ for (int i = 0; i < 10; ++i)
{
- ERR("failed to get device caps (0x%x)\n", result);
- return EGL_NOT_INITIALIZED;
+ result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
+ if (SUCCEEDED(result))
+ {
+ break;
+ }
+ else if (result == D3DERR_NOTAVAILABLE)
+ {
+ Sleep(100); // Give the driver some time to initialize/recover
+ }
+ else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from
+ {
+ ERR("failed to get device caps (0x%x)\n", result);
+ return EGL_NOT_INITIALIZED;
+ }
}
}
@@ -264,7 +269,10 @@ EGLint Renderer9::initialize()
return EGL_NOT_INITIALIZED;
}
- mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
+ {
+ TRACE_EVENT0("gpu", "GetAdapterIdentifier");
+ mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
+ }
// ATI cards on XP have problems with non-power-of-two textures.
mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
@@ -305,35 +313,41 @@ EGLint Renderer9::initialize()
}
int max = 0;
- for (unsigned int i = 0; i < ArraySize(RenderTargetFormats); ++i)
{
- bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
- getMultiSampleSupport(RenderTargetFormats[i], multisampleArray);
- mMultiSampleSupport[RenderTargetFormats[i]] = multisampleArray;
-
- for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
+ TRACE_EVENT0("gpu", "getMultiSampleSupport");
+ for (unsigned int i = 0; i < ArraySize(RenderTargetFormats); ++i)
{
- if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
+ bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
+ getMultiSampleSupport(RenderTargetFormats[i], multisampleArray);
+ mMultiSampleSupport[RenderTargetFormats[i]] = multisampleArray;
+
+ for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
{
- max = j;
+ if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
+ {
+ max = j;
+ }
}
}
}
- for (unsigned int i = 0; i < ArraySize(DepthStencilFormats); ++i)
{
- if (DepthStencilFormats[i] == D3DFMT_UNKNOWN)
- continue;
+ TRACE_EVENT0("gpu", "getMultiSampleSupport2");
+ for (unsigned int i = 0; i < ArraySize(DepthStencilFormats); ++i)
+ {
+ if (DepthStencilFormats[i] == D3DFMT_UNKNOWN)
+ continue;
- bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
- getMultiSampleSupport(DepthStencilFormats[i], multisampleArray);
- mMultiSampleSupport[DepthStencilFormats[i]] = multisampleArray;
+ bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
+ getMultiSampleSupport(DepthStencilFormats[i], multisampleArray);
+ mMultiSampleSupport[DepthStencilFormats[i]] = multisampleArray;
- for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
- {
- if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
+ for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
{
- max = j;
+ if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
+ {
+ max = j;
+ }
}
}
}
@@ -343,12 +357,18 @@ EGLint Renderer9::initialize()
static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
static const TCHAR className[] = TEXT("STATIC");
- mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
+ {
+ TRACE_EVENT0("gpu", "CreateWindowEx");
+ mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
+ }
D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
- result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
+ {
+ TRACE_EVENT0("gpu", "D3d9_CreateDevice");
+ result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
+ }
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST)
{
return EGL_BAD_ALLOC;
@@ -356,6 +376,7 @@ EGLint Renderer9::initialize()
if (FAILED(result))
{
+ TRACE_EVENT0("gpu", "D3d9_CreateDevice2");
result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
if (FAILED(result))
@@ -367,35 +388,45 @@ EGLint Renderer9::initialize()
if (mD3d9Ex)
{
+ TRACE_EVENT0("gpu", "mDevice_QueryInterface");
result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx);
ASSERT(SUCCEEDED(result));
}
- mVertexShaderCache.initialize(mDevice);
- mPixelShaderCache.initialize(mDevice);
+ {
+ TRACE_EVENT0("gpu", "ShaderCache initialize");
+ mVertexShaderCache.initialize(mDevice);
+ mPixelShaderCache.initialize(mDevice);
+ }
// Check occlusion query support
IDirect3DQuery9 *occlusionQuery = NULL;
- if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery)
{
- occlusionQuery->Release();
- mOcclusionQuerySupport = true;
- }
- else
- {
- mOcclusionQuerySupport = false;
+ TRACE_EVENT0("gpu", "device_CreateQuery");
+ if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery)
+ {
+ occlusionQuery->Release();
+ mOcclusionQuerySupport = true;
+ }
+ else
+ {
+ mOcclusionQuerySupport = false;
+ }
}
// Check event query support
IDirect3DQuery9 *eventQuery = NULL;
- if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery)
- {
- eventQuery->Release();
- mEventQuerySupport = true;
- }
- else
{
- mEventQuerySupport = false;
+ TRACE_EVENT0("gpu", "device_CreateQuery2");
+ if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery)
+ {
+ eventQuery->Release();
+ mEventQuerySupport = true;
+ }
+ else
+ {
+ mEventQuerySupport = false;
+ }
}
D3DDISPLAYMODE currentDisplayMode;
@@ -1080,8 +1111,10 @@ bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zF
return false; // Nothing to render
}
+ float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f);
+
bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 ||
- actualZNear != mCurNear || actualZFar != mCurFar;
+ actualZNear != mCurNear || actualZFar != mCurFar || mCurDepthFront != depthFront;
if (viewportChanged)
{
mDevice->SetViewport(&dxViewport);
@@ -1089,6 +1122,7 @@ bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zF
mCurViewport = actualViewport;
mCurNear = actualZNear;
mCurFar = actualZFar;
+ mCurDepthFront = depthFront;
dx_VertexConstants vc = {0};
dx_PixelConstants pc = {0};
@@ -1105,7 +1139,7 @@ bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zF
pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
- pc.depthFront[2] = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f);;
+ pc.depthFront[2] = depthFront;
vc.depthRange[0] = actualZNear;
vc.depthRange[1] = actualZFar;
@@ -1458,7 +1492,7 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
indices = static_cast<const GLubyte*>(storage->getData()) + offset;
}
- UINT startIndex = 0;
+ unsigned int startIndex = 0;
if (get32BitIndexSupport())
{
@@ -1475,7 +1509,16 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
}
}
- const int spaceNeeded = (count + 1) * sizeof(unsigned int);
+ if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
+ {
+ ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ // Checked by Renderer9::applyPrimitiveType
+ ASSERT(count >= 0);
+
+ const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int);
if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
{
ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
@@ -1483,14 +1526,14 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
}
void* mappedMemory = NULL;
- int offset = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory);
- if (offset == -1 || mappedMemory == NULL)
+ unsigned int offset = 0;
+ if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
{
ERR("Could not map index buffer for GL_LINE_LOOP.");
return gl::error(GL_OUT_OF_MEMORY);
}
- startIndex = static_cast<UINT>(offset) / 4;
+ startIndex = static_cast<unsigned int>(offset) / 4;
unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
switch (type)
@@ -1547,7 +1590,16 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
}
}
- const int spaceNeeded = (count + 1) * sizeof(unsigned short);
+ // Checked by Renderer9::applyPrimitiveType
+ ASSERT(count >= 0);
+
+ if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned short>::max() / sizeof(unsigned short)))
+ {
+ ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned short);
if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT))
{
ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
@@ -1555,14 +1607,14 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
}
void* mappedMemory = NULL;
- int offset = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory);
- if (offset == -1 || mappedMemory == NULL)
+ unsigned int offset;
+ if (mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
{
ERR("Could not map index buffer for GL_LINE_LOOP.");
return gl::error(GL_OUT_OF_MEMORY);
}
- startIndex = static_cast<UINT>(offset) / 2;
+ startIndex = static_cast<unsigned int>(offset) / 2;
unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory);
switch (type)
@@ -2042,23 +2094,6 @@ bool Renderer9::testDeviceLost(bool notify)
if (mDeviceEx)
{
status = mDeviceEx->CheckDeviceState(NULL);
-
- if (status == S_PRESENT_MODE_CHANGED)
- {
- // Reset the device so that D3D stops reporting S_PRESENT_MODE_CHANGED. Otherwise it will report
- // it continuously, potentially masking a lost device. D3D resources are not lost on a mode change with WDDM.
- D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
- mDeviceEx->Reset(&presentParameters);
-
- // Existing swap chains sometimes crash on the next present after a reset.
- mDisplay->recreateSwapChains();
-
- // Reset will not always cause the device loss to be reported so issue a dummy present.
- mDeviceEx->Present(NULL, NULL, NULL, NULL);
-
- // Retest the device status to see if the mode change really indicated a lost device.
- status = mDeviceEx->CheckDeviceState(NULL);
- }
}
else if (mDevice)
{
@@ -3208,4 +3243,18 @@ TextureStorage *Renderer9::createTextureStorageCube(int levels, GLenum internalf
return new TextureStorage9_Cube(this, levels, internalformat, usage, forceRenderable, size);
}
-} \ No newline at end of file
+bool Renderer9::getLUID(LUID *adapterLuid) const
+{
+ adapterLuid->HighPart = 0;
+ adapterLuid->LowPart = 0;
+
+ if (mD3d9Ex)
+ {
+ mD3d9Ex->GetAdapterLUID(mAdapter, adapterLuid);
+ return true;
+ }
+
+ return false;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.h
index 527a5010ae..f8932c4fd4 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.h
@@ -193,6 +193,8 @@ class Renderer9 : public Renderer
D3DPOOL getTexturePool(DWORD usage) const;
+ virtual bool getLUID(LUID *adapterLuid) const;
+
private:
DISALLOW_COPY_AND_ASSIGN(Renderer9);
@@ -296,6 +298,7 @@ class Renderer9 : public Renderer
gl::Rectangle mCurViewport;
float mCurNear;
float mCurFar;
+ float mCurDepthFront;
bool mForceSetBlendState;
gl::BlendState mCurBlendState;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h
index 128d123fbe..293e340845 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h
@@ -26,7 +26,7 @@ class ShaderExecutable
virtual ~ShaderExecutable()
{
- delete mFunction;
+ delete[] mFunction;
}
void *getFunction() const
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp
index 98f887587c..0da58cbe2e 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp
@@ -275,6 +275,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
else
{
result = offscreenTextureResource->GetSharedHandle(&mShareHandle);
+ offscreenTextureResource->Release();
if (FAILED(result))
{
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp
index 667dbff175..408b48ebab 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp
@@ -69,7 +69,6 @@ bool TextureStorage11::IsTextureFormatRenderable(DXGI_FORMAT format)
case DXGI_FORMAT_R8G8B8A8_UNORM:
case DXGI_FORMAT_A8_UNORM:
case DXGI_FORMAT_R32G32B32A32_FLOAT:
- case DXGI_FORMAT_R32G32B32_FLOAT:
case DXGI_FORMAT_R16G16B16A16_FLOAT:
case DXGI_FORMAT_B8G8R8A8_UNORM:
case DXGI_FORMAT_R8_UNORM:
@@ -80,6 +79,7 @@ bool TextureStorage11::IsTextureFormatRenderable(DXGI_FORMAT format)
case DXGI_FORMAT_BC1_UNORM:
case DXGI_FORMAT_BC2_UNORM:
case DXGI_FORMAT_BC3_UNORM:
+ case DXGI_FORMAT_R32G32B32_FLOAT: // not renderable on all devices
return false;
default:
UNREACHABLE();
@@ -187,15 +187,6 @@ void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget1
destRTV, destArea, dest->getWidth(), dest->getHeight(),
GL_RGBA);
}
-
- if (sourceSRV)
- {
- sourceSRV->Release();
- }
- if (destRTV)
- {
- destRTV->Release();
- }
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.cpp
index 16e1486511..a073d95033 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.cpp
@@ -87,52 +87,97 @@ bool VertexBufferInterface::discard()
return mVertexBuffer->discard();
}
-int VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances)
+bool VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances,
+ unsigned int *outStreamOffset)
{
+ unsigned int spaceRequired;
+ if (!mVertexBuffer->getSpaceRequired(attrib, count, instances, &spaceRequired))
+ {
+ return false;
+ }
+
+ if (mWritePosition + spaceRequired < mWritePosition)
+ {
+ return false;
+ }
+
if (!reserveSpace(mReservedSpace))
{
- return -1;
+ return false;
}
mReservedSpace = 0;
if (!mVertexBuffer->storeVertexAttributes(attrib, start, count, instances, mWritePosition))
{
- return -1;
+ return false;
}
- int oldWritePos = static_cast<int>(mWritePosition);
- mWritePosition += mVertexBuffer->getSpaceRequired(attrib, count, instances);
+ if (outStreamOffset)
+ {
+ *outStreamOffset = mWritePosition;
+ }
+
+ mWritePosition += spaceRequired;
- return oldWritePos;
+ return true;
}
-int VertexBufferInterface::storeRawData(const void* data, unsigned int size)
+bool VertexBufferInterface::storeRawData(const void* data, unsigned int size, unsigned int *outStreamOffset)
{
+ if (mWritePosition + size < mWritePosition)
+ {
+ return false;
+ }
+
if (!reserveSpace(mReservedSpace))
{
- return -1;
+ return false;
}
mReservedSpace = 0;
if (!mVertexBuffer->storeRawData(data, size, mWritePosition))
{
- return -1;
+ return false;
+ }
+
+ if (outStreamOffset)
+ {
+ *outStreamOffset = mWritePosition;
}
- int oldWritePos = static_cast<int>(mWritePosition);
mWritePosition += size;
- return oldWritePos;
+ return true;
}
-void VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances)
+bool VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances)
{
- mReservedSpace += mVertexBuffer->getSpaceRequired(attribute, count, instances);
+ unsigned int requiredSpace;
+ if (!mVertexBuffer->getSpaceRequired(attribute, count, instances, &requiredSpace))
+ {
+ return false;
+ }
+
+ // Protect against integer overflow
+ if (mReservedSpace + requiredSpace < mReservedSpace)
+ {
+ return false;
+ }
+
+ mReservedSpace += requiredSpace;
+ return true;
}
-void VertexBufferInterface::reserveRawDataSpace(unsigned int size)
+bool VertexBufferInterface::reserveRawDataSpace(unsigned int size)
{
+ // Protect against integer overflow
+ if (mReservedSpace + size < mReservedSpace)
+ {
+ return false;
+ }
+
mReservedSpace += size;
+ return true;
}
VertexBuffer* VertexBufferInterface::getVertexBuffer() const
@@ -179,7 +224,7 @@ StaticVertexBufferInterface::~StaticVertexBufferInterface()
{
}
-int StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attribute)
+bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attribute, unsigned int *outStreamOffset)
{
for (unsigned int element = 0; element < mCache.size(); element++)
{
@@ -190,12 +235,16 @@ int StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attr
{
if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride())
{
- return mCache[element].streamOffset;
+ if (outStreamOffset)
+ {
+ *outStreamOffset = mCache[element].streamOffset;
+ }
+ return true;
}
}
}
- return -1;
+ return false;
}
bool StaticVertexBufferInterface::reserveSpace(unsigned int size)
@@ -217,13 +266,27 @@ bool StaticVertexBufferInterface::reserveSpace(unsigned int size)
}
}
-int StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances)
+bool StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances,
+ unsigned int *outStreamOffset)
{
- int attributeOffset = attrib.mOffset % attrib.stride();
- VertexElement element = { attrib.mType, attrib.mSize, attrib.stride(), attrib.mNormalized, attributeOffset, getWritePosition() };
- mCache.push_back(element);
+ unsigned int streamOffset;
+ if (VertexBufferInterface::storeVertexAttributes(attrib, start, count, instances, &streamOffset))
+ {
+ int attributeOffset = attrib.mOffset % attrib.stride();
+ VertexElement element = { attrib.mType, attrib.mSize, attrib.stride(), attrib.mNormalized, attributeOffset, streamOffset };
+ mCache.push_back(element);
- return VertexBufferInterface::storeVertexAttributes(attrib, start, count, instances);
+ if (outStreamOffset)
+ {
+ *outStreamOffset = streamOffset;
+ }
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.h
index 6ecffd0c0b..cbafdd20f6 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.h
@@ -33,8 +33,8 @@ class VertexBuffer
GLsizei instances, unsigned int offset) = 0;
virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset) = 0;
- virtual unsigned int getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count,
- GLsizei instances) const = 0;
+ virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances,
+ unsigned int *outSpaceRequired) const = 0;
virtual bool requiresConversion(const gl::VertexAttribute &attrib) const = 0;
@@ -60,15 +60,16 @@ class VertexBufferInterface
VertexBufferInterface(rx::Renderer *renderer, bool dynamic);
virtual ~VertexBufferInterface();
- void reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances);
- void reserveRawDataSpace(unsigned int size);
+ bool reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances);
+ bool reserveRawDataSpace(unsigned int size);
unsigned int getBufferSize() const;
unsigned int getSerial() const;
- virtual int storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances);
- virtual int storeRawData(const void* data, unsigned int size);
+ virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances,
+ unsigned int *outStreamOffset);
+ virtual bool storeRawData(const void* data, unsigned int size, unsigned int *outStreamOffset);
VertexBuffer* getVertexBuffer() const;
@@ -110,10 +111,10 @@ class StaticVertexBufferInterface : public VertexBufferInterface
explicit StaticVertexBufferInterface(rx::Renderer *renderer);
~StaticVertexBufferInterface();
- int storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances);
+ bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances,
+ unsigned int *outStreamOffset);
- // Returns the offset into the vertex buffer, or -1 if not found
- int lookupAttribute(const gl::VertexAttribute &attribute);
+ bool lookupAttribute(const gl::VertexAttribute &attribute, unsigned int* outStreamOffset);
protected:
bool reserveSpace(unsigned int size);
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.cpp
index 92c8755e22..521da80c3d 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.cpp
@@ -152,18 +152,40 @@ bool VertexBuffer11::storeRawData(const void* data, unsigned int size, unsigned
}
}
-unsigned int VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count,
- GLsizei instances) const
+bool VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count,
+ GLsizei instances, unsigned int *outSpaceRequired) const
{
unsigned int elementSize = getVertexConversion(attrib).outputElementSize;
+ unsigned int elementCount = 0;
if (instances == 0 || attrib.mDivisor == 0)
{
- return elementSize * count;
+ elementCount = count;
}
else
{
- return elementSize * ((instances + attrib.mDivisor - 1) / attrib.mDivisor);
+ if (static_cast<unsigned int>(instances) < std::numeric_limits<unsigned int>::max() - (attrib.mDivisor - 1))
+ {
+ // Round up
+ elementCount = (static_cast<unsigned int>(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor;
+ }
+ else
+ {
+ elementCount = instances / attrib.mDivisor;
+ }
+ }
+
+ if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
+ {
+ if (outSpaceRequired)
+ {
+ *outSpaceRequired = elementSize * elementCount;
+ }
+ return true;
+ }
+ else
+ {
+ return false;
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.h
index 75e025075e..eceb426e82 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.h
@@ -26,10 +26,11 @@ class VertexBuffer11 : public VertexBuffer
static VertexBuffer11 *makeVertexBuffer11(VertexBuffer *vetexBuffer);
virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances,
- unsigned int offset);
+ unsigned int offset);
virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset);
- virtual unsigned int getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances) const;
+ virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances,
+ unsigned int *outSpaceRequired) const;
virtual bool requiresConversion(const gl::VertexAttribute &attrib) const;
@@ -70,4 +71,4 @@ class VertexBuffer11 : public VertexBuffer
}
-#endif // LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ \ No newline at end of file
+#endif // LIBGLESV2_RENDERER_VERTEXBUFFER11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.cpp
index 76dc73e391..b017b3af33 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.cpp
@@ -95,7 +95,14 @@ bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, GLi
DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
void *mapPtr = NULL;
- HRESULT result = mVertexBuffer->Lock(offset, spaceRequired(attrib, count, instances), &mapPtr, lockFlags);
+
+ unsigned int mapSize;
+ if (!spaceRequired(attrib, count, instances, &mapSize))
+ {
+ return false;
+ }
+
+ HRESULT result = mVertexBuffer->Lock(offset, mapSize, &mapPtr, lockFlags);
if (FAILED(result))
{
@@ -167,9 +174,10 @@ bool VertexBuffer9::storeRawData(const void* data, unsigned int size, unsigned i
}
}
-unsigned int VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances) const
+bool VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances,
+ unsigned int *outSpaceRequired) const
{
- return spaceRequired(attrib, count, instances);
+ return spaceRequired(attrib, count, instances, outSpaceRequired);
}
bool VertexBuffer9::requiresConversion(const gl::VertexAttribute &attrib) const
@@ -179,7 +187,8 @@ bool VertexBuffer9::requiresConversion(const gl::VertexAttribute &attrib) const
unsigned int VertexBuffer9::getVertexSize(const gl::VertexAttribute &attrib) const
{
- return spaceRequired(attrib, 1, 0);
+ unsigned int spaceRequired;
+ return getSpaceRequired(attrib, 1, 0, &spaceRequired) ? spaceRequired : 0;
}
D3DDECLTYPE VertexBuffer9::getDeclType(const gl::VertexAttribute &attrib) const
@@ -469,17 +478,52 @@ const VertexBuffer9::FormatConverter &VertexBuffer9::formatConverter(const gl::V
return mFormatConverters[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1];
}
-unsigned int VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances)
+bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances,
+ unsigned int *outSpaceRequired)
{
unsigned int elementSize = formatConverter(attrib).outputElementSize;
- if (instances == 0 || attrib.mDivisor == 0)
+ if (attrib.mArrayEnabled)
{
- return elementSize * count;
+ unsigned int elementCount = 0;
+ if (instances == 0 || attrib.mDivisor == 0)
+ {
+ elementCount = count;
+ }
+ else
+ {
+ if (static_cast<unsigned int>(instances) < std::numeric_limits<unsigned int>::max() - (attrib.mDivisor - 1))
+ {
+ // Round up
+ elementCount = (static_cast<unsigned int>(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor;
+ }
+ else
+ {
+ elementCount = static_cast<unsigned int>(instances) / attrib.mDivisor;
+ }
+ }
+
+ if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
+ {
+ if (outSpaceRequired)
+ {
+ *outSpaceRequired = elementSize * elementCount;
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
}
else
{
- return elementSize * ((instances + attrib.mDivisor - 1) / attrib.mDivisor);
+ const unsigned int elementSize = 4;
+ if (outSpaceRequired)
+ {
+ *outSpaceRequired = elementSize * 4;
+ }
+ return true;
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.h
index f771635bda..2f88117bda 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.h
@@ -29,7 +29,7 @@ class VertexBuffer9 : public VertexBuffer
unsigned int offset);
virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset);
- virtual unsigned int getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances) const;
+ virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, unsigned int *outSpaceRequired) const;
virtual bool requiresConversion(const gl::VertexAttribute &attrib) const;
@@ -82,7 +82,8 @@ class VertexBuffer9 : public VertexBuffer
static unsigned int typeIndex(GLenum type);
static const FormatConverter &formatConverter(const gl::VertexAttribute &attribute);
- static unsigned int spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances);
+ static bool spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances,
+ unsigned int *outSpaceRequired);
};
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp
index ec85857264..7ff5171fca 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp
@@ -26,12 +26,32 @@ namespace
namespace rx
{
-static int elementsInBuffer(const gl::VertexAttribute &attribute, int size)
+static int elementsInBuffer(const gl::VertexAttribute &attribute, unsigned int size)
{
- int stride = attribute.stride();
+ // Size cannot be larger than a GLsizei
+ if (size > static_cast<unsigned int>(std::numeric_limits<int>::max()))
+ {
+ size = static_cast<unsigned int>(std::numeric_limits<int>::max());
+ }
+
+ GLsizei stride = attribute.stride();
return (size - attribute.mOffset % stride + (stride - attribute.typeSize())) / stride;
}
+static int StreamingBufferElementCount(const gl::VertexAttribute &attribute, int vertexDrawCount, int instanceDrawCount)
+{
+ // For instanced rendering, we draw "instanceDrawCount" sets of "vertexDrawCount" vertices.
+ //
+ // A vertex attribute with a positive divisor loads one instanced vertex for every set of
+ // non-instanced vertices, and the instanced vertex index advances once every "mDivisor" instances.
+ if (instanceDrawCount > 0 && attribute.mDivisor > 0)
+ {
+ return instanceDrawCount / attribute.mDivisor;
+ }
+
+ return vertexDrawCount;
+}
+
VertexDataManager::VertexDataManager(Renderer *renderer) : mRenderer(renderer)
{
for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
@@ -92,7 +112,7 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[],
gl::Buffer *buffer = attribs[i].mBoundBuffer.get();
StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
- if (staticBuffer && staticBuffer->getBufferSize() > 0 && staticBuffer->lookupAttribute(attribs[i]) == -1 &&
+ if (staticBuffer && staticBuffer->getBufferSize() > 0 && !staticBuffer->lookupAttribute(attribs[i], NULL) &&
!directStoragePossible(staticBuffer, attribs[i]))
{
buffer->invalidateStaticData();
@@ -116,12 +136,27 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[],
if (staticBuffer->getBufferSize() == 0)
{
int totalCount = elementsInBuffer(attribs[i], buffer->size());
- staticBuffer->reserveVertexSpace(attribs[i], totalCount, 0);
+ if (!staticBuffer->reserveVertexSpace(attribs[i], totalCount, 0))
+ {
+ return GL_OUT_OF_MEMORY;
+ }
}
}
else
{
- mStreamingBuffer->reserveVertexSpace(attribs[i], count, instances);
+ int totalCount = StreamingBufferElementCount(attribs[i], count, instances);
+
+ // Undefined behaviour:
+ // We can return INVALID_OPERATION if our vertex attribute does not have enough backing data.
+ if (buffer && elementsInBuffer(attribs[i], buffer->size()) < totalCount)
+ {
+ return GL_INVALID_OPERATION;
+ }
+
+ if (!mStreamingBuffer->reserveVertexSpace(attribs[i], totalCount, instances))
+ {
+ return GL_OUT_OF_MEMORY;
+ }
}
}
}
@@ -149,7 +184,7 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[],
BufferStorage *storage = buffer ? buffer->getStorage() : NULL;
bool directStorage = directStoragePossible(vertexBuffer, attribs[i]);
- std::size_t streamOffset = -1;
+ unsigned int streamOffset = 0;
unsigned int outputElementSize = 0;
if (directStorage)
@@ -160,37 +195,40 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[],
}
else if (staticBuffer)
{
- streamOffset = staticBuffer->lookupAttribute(attribs[i]);
- outputElementSize = staticBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0);
+ if (!staticBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0, &outputElementSize))
+ {
+ return GL_OUT_OF_MEMORY;
+ }
- if (streamOffset == -1)
+ if (!staticBuffer->lookupAttribute(attribs[i], &streamOffset))
{
// Convert the entire buffer
int totalCount = elementsInBuffer(attribs[i], storage->getSize());
int startIndex = attribs[i].mOffset / attribs[i].stride();
- streamOffset = staticBuffer->storeVertexAttributes(attribs[i], -startIndex, totalCount, 0);
+ if (!staticBuffer->storeVertexAttributes(attribs[i], -startIndex, totalCount, 0, &streamOffset))
+ {
+ return GL_OUT_OF_MEMORY;
+ }
}
- if (streamOffset != -1)
+ unsigned int firstElementOffset = (attribs[i].mOffset / attribs[i].stride()) * outputElementSize;
+ unsigned int startOffset = (instances == 0 || attribs[i].mDivisor == 0) ? start * outputElementSize : 0;
+ if (streamOffset + firstElementOffset + startOffset < streamOffset)
{
- streamOffset += (attribs[i].mOffset / attribs[i].stride()) * outputElementSize;
-
- if (instances == 0 || attribs[i].mDivisor == 0)
- {
- streamOffset += start * outputElementSize;
- }
+ return GL_OUT_OF_MEMORY;
}
+
+ streamOffset += firstElementOffset + startOffset;
}
else
{
- outputElementSize = mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0);
- streamOffset = mStreamingBuffer->storeVertexAttributes(attribs[i], start, count, instances);
- }
-
- if (streamOffset == -1)
- {
- return GL_OUT_OF_MEMORY;
+ int totalCount = StreamingBufferElementCount(attribs[i], count, instances);
+ if (!mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0, &outputElementSize) ||
+ !mStreamingBuffer->storeVertexAttributes(attribs[i], start, totalCount, instances, &streamOffset))
+ {
+ return GL_OUT_OF_MEMORY;
+ }
}
translated[i].storage = directStorage ? storage : NULL;
@@ -217,9 +255,13 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[],
mCurrentValue[i][3] != attribs[i].mCurrentValue[3])
{
unsigned int requiredSpace = sizeof(float) * 4;
- buffer->reserveRawDataSpace(requiredSpace);
- int streamOffset = buffer->storeRawData(attribs[i].mCurrentValue, requiredSpace);
- if (streamOffset == -1)
+ if (!buffer->reserveRawDataSpace(requiredSpace))
+ {
+ return GL_OUT_OF_MEMORY;
+ }
+
+ unsigned int streamOffset;
+ if (!buffer->storeRawData(attribs[i].mCurrentValue, requiredSpace, &streamOffset))
{
return GL_OUT_OF_MEMORY;
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h
index 28387e6baf..1a8786552a 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h
@@ -31,8 +31,8 @@ struct TranslatedAttribute
bool active;
const gl::VertexAttribute *attribute;
- UINT offset;
- UINT stride; // 0 means not to advance the read pointer at all
+ unsigned int offset;
+ unsigned int stride; // 0 means not to advance the read pointer at all
VertexBuffer *vertexBuffer;
BufferStorage *storage;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp
index 5f01dc12ed..13800da258 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp
@@ -356,7 +356,7 @@ DXGI_FORMAT ConvertTextureFormat(GLenum internalformat)
return DXGI_FORMAT_R32G32B32A32_FLOAT;
case GL_RGB32F_EXT:
case GL_LUMINANCE32F_EXT:
- return DXGI_FORMAT_R32G32B32_FLOAT;
+ return DXGI_FORMAT_R32G32B32A32_FLOAT;
case GL_RGBA16F_EXT:
case GL_ALPHA16F_EXT:
case GL_LUMINANCE_ALPHA16F_EXT:
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl
index d2752601e9..042ac699b6 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl
@@ -6,7 +6,7 @@ void VS_Clear( in float3 inPosition : POSITION, in float4 inColor : COLOR,
}
// Assume we are in SM4+, which has 8 color outputs
-struct PS_Output
+struct PS_OutputMultiple
{
float4 color0 : SV_TARGET0;
float4 color1 : SV_TARGET1;
@@ -18,9 +18,9 @@ struct PS_Output
float4 color7 : SV_TARGET7;
};
-PS_Output PS_Clear(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR)
+PS_OutputMultiple PS_ClearMultiple(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR)
{
- PS_Output outColor;
+ PS_OutputMultiple outColor;
outColor.color0 = inColor;
outColor.color1 = inColor;
outColor.color2 = inColor;
@@ -31,3 +31,8 @@ PS_Output PS_Clear(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR
outColor.color7 = inColor;
return outColor;
}
+
+float4 PS_ClearSingle(in float4 inPosition : SV_Position, in float4 inColor : COLOR) : SV_Target0
+{
+ return inColor;
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/utilities.cpp b/src/3rdparty/angle/src/libGLESv2/utilities.cpp
index 9809b9d8e8..32df49e672 100644
--- a/src/3rdparty/angle/src/libGLESv2/utilities.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/utilities.cpp
@@ -218,6 +218,29 @@ GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum internalform
}
}
+GLsizei ComputeTypeSize(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE: return 1;
+ case GL_UNSIGNED_BYTE: return 1;
+ case GL_SHORT: return 2;
+ case GL_UNSIGNED_SHORT: return 2;
+ case GL_INT: return 4;
+ case GL_UNSIGNED_INT: return 4;
+ case GL_FLOAT: return 4;
+ case GL_HALF_FLOAT_OES: return 2;
+ case GL_UNSIGNED_SHORT_5_6_5: return 2;
+ case GL_UNSIGNED_SHORT_4_4_4_4: return 2;
+ case GL_UNSIGNED_SHORT_5_5_5_1: return 2;
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: return 2;
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: return 2;
+ case GL_UNSIGNED_INT_2_10_10_10_REV_EXT: return 4;
+ case GL_UNSIGNED_INT_24_8_OES: return 4;
+ default: UNREACHABLE(); return 0;
+ }
+}
+
bool IsCompressed(GLenum format)
{
if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
diff --git a/src/3rdparty/angle/src/libGLESv2/utilities.h b/src/3rdparty/angle/src/libGLESv2/utilities.h
index 7a10767086..ed663ebca2 100644
--- a/src/3rdparty/angle/src/libGLESv2/utilities.h
+++ b/src/3rdparty/angle/src/libGLESv2/utilities.h
@@ -34,6 +34,7 @@ int ComputePixelSize(GLint internalformat);
GLsizei ComputePitch(GLsizei width, GLint internalformat, GLint alignment);
GLsizei ComputeCompressedPitch(GLsizei width, GLenum format);
GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format);
+GLsizei ComputeTypeSize(GLenum type);
bool IsCompressed(GLenum format);
bool IsDepthTexture(GLenum format);
bool IsStencilTexture(GLenum format);
diff --git a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h
new file mode 100644
index 0000000000..113b126a77
--- /dev/null
+++ b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h
@@ -0,0 +1,828 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Trace events are for tracking application performance and resource usage.
+// Macros are provided to track:
+// Begin and end of function calls
+// Counters
+//
+// Events are issued against categories. Whereas LOG's
+// categories are statically defined, TRACE categories are created
+// implicitly with a string. For example:
+// TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent")
+//
+// Events can be INSTANT, or can be pairs of BEGIN and END in the same scope:
+// TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly")
+// doSomethingCostly()
+// TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly")
+// Note: our tools can't always determine the correct BEGIN/END pairs unless
+// these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you need them
+// to be in separate scopes.
+//
+// A common use case is to trace entire function scopes. This
+// issues a trace BEGIN and END automatically:
+// void doSomethingCostly() {
+// TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly");
+// ...
+// }
+//
+// Additional parameters can be associated with an event:
+// void doSomethingCostly2(int howMuch) {
+// TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly",
+// "howMuch", howMuch);
+// ...
+// }
+//
+// The trace system will automatically add to this information the
+// current process id, thread id, and a timestamp in microseconds.
+//
+// To trace an asynchronous procedure such as an IPC send/receive, use ASYNC_BEGIN and
+// ASYNC_END:
+// [single threaded sender code]
+// static int send_count = 0;
+// ++send_count;
+// TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count);
+// Send(new MyMessage(send_count));
+// [receive code]
+// void OnMyMessage(send_count) {
+// TRACE_EVENT_ASYNC_END0("ipc", "message", send_count);
+// }
+// The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs.
+// ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process. Pointers can
+// be used for the ID parameter, and they will be mangled internally so that
+// the same pointer on two different processes will not match. For example:
+// class MyTracedClass {
+// public:
+// MyTracedClass() {
+// TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this);
+// }
+// ~MyTracedClass() {
+// TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this);
+// }
+// }
+//
+// Trace event also supports counters, which is a way to track a quantity
+// as it varies over time. Counters are created with the following macro:
+// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue);
+//
+// Counters are process-specific. The macro itself can be issued from any
+// thread, however.
+//
+// Sometimes, you want to track two counters at once. You can do this with two
+// counter macros:
+// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]);
+// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]);
+// Or you can do it with a combined macro:
+// TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter",
+// "bytesPinned", g_myCounterValue[0],
+// "bytesAllocated", g_myCounterValue[1]);
+// This indicates to the tracing UI that these counters should be displayed
+// in a single graph, as a summed area chart.
+//
+// Since counters are in a global namespace, you may want to disembiguate with a
+// unique ID, by using the TRACE_COUNTER_ID* variations.
+//
+// By default, trace collection is compiled in, but turned off at runtime.
+// Collecting trace data is the responsibility of the embedding
+// application. In Chrome's case, navigating to about:tracing will turn on
+// tracing and display data collected across all active processes.
+//
+//
+// Memory scoping note:
+// Tracing copies the pointers, not the string content, of the strings passed
+// in for category, name, and arg_names. Thus, the following code will
+// cause problems:
+// char* str = strdup("impprtantName");
+// TRACE_EVENT_INSTANT0("SUBSYSTEM", str); // BAD!
+// free(str); // Trace system now has dangling pointer
+//
+// To avoid this issue with the |name| and |arg_name| parameters, use the
+// TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime overhead.
+// Notes: The category must always be in a long-lived char* (i.e. static const).
+// The |arg_values|, when used, are always deep copied with the _COPY
+// macros.
+//
+// When are string argument values copied:
+// const char* arg_values are only referenced by default:
+// TRACE_EVENT1("category", "name",
+// "arg1", "literal string is only referenced");
+// Use TRACE_STR_COPY to force copying of a const char*:
+// TRACE_EVENT1("category", "name",
+// "arg1", TRACE_STR_COPY("string will be copied"));
+// std::string arg_values are always copied:
+// TRACE_EVENT1("category", "name",
+// "arg1", std::string("string will be copied"));
+//
+//
+// Thread Safety:
+// A thread safe singleton and mutex are used for thread safety. Category
+// enabled flags are used to limit the performance impact when the system
+// is not enabled.
+//
+// TRACE_EVENT macros first cache a pointer to a category. The categories are
+// statically allocated and safe at all times, even after exit. Fetching a
+// category is protected by the TraceLog::lock_. Multiple threads initializing
+// the static variable is safe, as they will be serialized by the lock and
+// multiple calls will return the same pointer to the category.
+//
+// Then the category_enabled flag is checked. This is a unsigned char, and
+// not intended to be multithread safe. It optimizes access to addTraceEvent
+// which is threadsafe internally via TraceLog::lock_. The enabled flag may
+// cause some threads to incorrectly call or skip calling addTraceEvent near
+// the time of the system being enabled or disabled. This is acceptable as
+// we tolerate some data loss while the system is being enabled/disabled and
+// because addTraceEvent is threadsafe internally and checks the enabled state
+// again under lock.
+//
+// Without the use of these static category pointers and enabled flags all
+// trace points would carry a significant performance cost of aquiring a lock
+// and resolving the category.
+
+#ifndef COMMON_TRACE_EVENT_H_
+#define COMMON_TRACE_EVENT_H_
+
+#include <string>
+
+#include "common/event_tracer.h"
+
+// By default, const char* argument values are assumed to have long-lived scope
+// and will not be copied. Use this macro to force a const char* to be copied.
+#define TRACE_STR_COPY(str) \
+ WebCore::TraceEvent::TraceStringWithCopy(str)
+
+// Records a pair of begin and end events called "name" for the current
+// scope, with 0, 1 or 2 associated arguments. If the category is not
+// enabled, then this does nothing.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+#define TRACE_EVENT0(category, name) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name)
+#define TRACE_EVENT1(category, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, arg1_name, arg1_val)
+#define TRACE_EVENT2(category, name, arg1_name, arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+
+// Records a single event called "name" immediately, with 0, 1 or 2
+// associated arguments. If the category is not enabled, then this
+// does nothing.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+#define TRACE_EVENT_INSTANT0(category, name) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+ category, name, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_INSTANT1(category, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+ category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+ category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_INSTANT0(category, name) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+ category, name, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_INSTANT1(category, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+ category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_INSTANT2(category, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+ category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+
+// Records a single BEGIN event called "name" immediately, with 0, 1 or 2
+// associated arguments. If the category is not enabled, then this
+// does nothing.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+#define TRACE_EVENT_BEGIN0(category, name) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+ category, name, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_BEGIN1(category, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+ category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_BEGIN2(category, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+ category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_BEGIN0(category, name) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+ category, name, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_BEGIN1(category, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+ category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_BEGIN2(category, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+ category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+
+// Records a single END event for "name" immediately. If the category
+// is not enabled, then this does nothing.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+#define TRACE_EVENT_END0(category, name) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+ category, name, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_END1(category, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+ category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_END2(category, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+ category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_END0(category, name) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+ category, name, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_END1(category, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+ category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_END2(category, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+ category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+
+// Records the value of a counter called "name" immediately. Value
+// must be representable as a 32 bit integer.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+#define TRACE_COUNTER1(category, name, value) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
+ category, name, TRACE_EVENT_FLAG_NONE, \
+ "value", static_cast<int>(value))
+#define TRACE_COPY_COUNTER1(category, name, value) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
+ category, name, TRACE_EVENT_FLAG_COPY, \
+ "value", static_cast<int>(value))
+
+// Records the values of a multi-parted counter called "name" immediately.
+// The UI will treat value1 and value2 as parts of a whole, displaying their
+// values as a stacked-bar chart.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+#define TRACE_COUNTER2(category, name, value1_name, value1_val, \
+ value2_name, value2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
+ category, name, TRACE_EVENT_FLAG_NONE, \
+ value1_name, static_cast<int>(value1_val), \
+ value2_name, static_cast<int>(value2_val))
+#define TRACE_COPY_COUNTER2(category, name, value1_name, value1_val, \
+ value2_name, value2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
+ category, name, TRACE_EVENT_FLAG_COPY, \
+ value1_name, static_cast<int>(value1_val), \
+ value2_name, static_cast<int>(value2_val))
+
+// Records the value of a counter called "name" immediately. Value
+// must be representable as a 32 bit integer.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+// - |id| is used to disambiguate counters with the same name. It must either
+// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits
+// will be xored with a hash of the process ID so that the same pointer on
+// two different processes will not collide.
+#define TRACE_COUNTER_ID1(category, name, id, value) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
+ category, name, id, TRACE_EVENT_FLAG_NONE, \
+ "value", static_cast<int>(value))
+#define TRACE_COPY_COUNTER_ID1(category, name, id, value) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
+ category, name, id, TRACE_EVENT_FLAG_COPY, \
+ "value", static_cast<int>(value))
+
+// Records the values of a multi-parted counter called "name" immediately.
+// The UI will treat value1 and value2 as parts of a whole, displaying their
+// values as a stacked-bar chart.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+// - |id| is used to disambiguate counters with the same name. It must either
+// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits
+// will be xored with a hash of the process ID so that the same pointer on
+// two different processes will not collide.
+#define TRACE_COUNTER_ID2(category, name, id, value1_name, value1_val, \
+ value2_name, value2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
+ category, name, id, TRACE_EVENT_FLAG_NONE, \
+ value1_name, static_cast<int>(value1_val), \
+ value2_name, static_cast<int>(value2_val))
+#define TRACE_COPY_COUNTER_ID2(category, name, id, value1_name, value1_val, \
+ value2_name, value2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
+ category, name, id, TRACE_EVENT_FLAG_COPY, \
+ value1_name, static_cast<int>(value1_val), \
+ value2_name, static_cast<int>(value2_val))
+
+// Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2
+// associated arguments. If the category is not enabled, then this
+// does nothing.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+// - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event. ASYNC
+// events are considered to match if their category, name and id values all
+// match. |id| must either be a pointer or an integer value up to 64 bits. If
+// it's a pointer, the bits will be xored with a hash of the process ID so
+// that the same pointer on two different processes will not collide.
+// An asynchronous operation can consist of multiple phases. The first phase is
+// defined by the ASYNC_BEGIN calls. Additional phases can be defined using the
+// ASYNC_STEP_BEGIN macros. When the operation completes, call ASYNC_END.
+// An async operation can span threads and processes, but all events in that
+// operation must use the same |name| and |id|. Each event can have its own
+// args.
+#define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category, name, id, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category, name, id, TRACE_EVENT_FLAG_NONE, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_ASYNC_BEGIN0(category, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category, name, id, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category, name, id, TRACE_EVENT_FLAG_COPY, \
+ arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category, name, id, TRACE_EVENT_FLAG_COPY, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
+
+// Records a single ASYNC_STEP event for |step| immediately. If the category
+// is not enabled, then this does nothing. The |name| and |id| must match the
+// ASYNC_BEGIN event above. The |step| param identifies this step within the
+// async event. This should be called at the beginning of the next phase of an
+// asynchronous operation.
+#define TRACE_EVENT_ASYNC_STEP0(category, name, id, step) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
+ category, name, id, TRACE_EVENT_FLAG_NONE, "step", step)
+#define TRACE_EVENT_ASYNC_STEP1(category, name, id, step, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
+ category, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \
+ arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_ASYNC_STEP0(category, name, id, step) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
+ category, name, id, TRACE_EVENT_FLAG_COPY, "step", step)
+#define TRACE_EVENT_COPY_ASYNC_STEP1(category, name, id, step, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
+ category, name, id, TRACE_EVENT_FLAG_COPY, "step", step, \
+ arg1_name, arg1_val)
+
+// Records a single ASYNC_END event for "name" immediately. If the category
+// is not enabled, then this does nothing.
+#define TRACE_EVENT_ASYNC_END0(category, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category, name, id, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category, name, id, TRACE_EVENT_FLAG_NONE, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_ASYNC_END0(category, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category, name, id, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_ASYNC_END1(category, name, id, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category, name, id, TRACE_EVENT_FLAG_COPY, \
+ arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_ASYNC_END2(category, name, id, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category, name, id, TRACE_EVENT_FLAG_COPY, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
+
+// Creates a scope of a sampling state with the given category and name (both must
+// be constant strings). These states are intended for a sampling profiler.
+// Implementation note: we store category and name together because we don't
+// want the inconsistency/expense of storing two pointers.
+// |thread_bucket| is [0..2] and is used to statically isolate samples in one
+// thread from others.
+//
+// { // The sampling state is set within this scope.
+// TRACE_EVENT_SAMPLING_STATE_SCOPE_FOR_BUCKET(0, "category", "name");
+// ...;
+// }
+#define TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \
+ TraceEvent::SamplingStateScope<bucket_number> traceEventSamplingScope(category "\0" name);
+
+// Returns a current sampling state of the given bucket.
+// The format of the returned string is "category\0name".
+#define TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(bucket_number) \
+ TraceEvent::SamplingStateScope<bucket_number>::current()
+
+// Sets a current sampling state of the given bucket.
+// |category| and |name| have to be constant strings.
+#define TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \
+ TraceEvent::SamplingStateScope<bucket_number>::set(category "\0" name)
+
+// Sets a current sampling state of the given bucket.
+// |categoryAndName| doesn't need to be a constant string.
+// The format of the string is "category\0name".
+#define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(bucket_number, categoryAndName) \
+ TraceEvent::SamplingStateScope<bucket_number>::set(categoryAndName)
+
+// Syntactic sugars for the sampling tracing in the main thread.
+#define TRACE_EVENT_SCOPED_SAMPLING_STATE(category, name) \
+ TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(0, category, name)
+#define TRACE_EVENT_GET_SAMPLING_STATE() \
+ TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(0)
+#define TRACE_EVENT_SET_SAMPLING_STATE(category, name) \
+ TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(0, category, name)
+#define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(categoryAndName) \
+ TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(0, categoryAndName)
+
+////////////////////////////////////////////////////////////////////////////////
+// Implementation specific tracing API definitions.
+
+// Get a pointer to the enabled state of the given trace category. Only
+// long-lived literal strings should be given as the category name. The returned
+// pointer can be held permanently in a local static for example. If the
+// unsigned char is non-zero, tracing is enabled. If tracing is enabled,
+// TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled
+// between the load of the tracing state and the call to
+// TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out
+// for best performance when tracing is disabled.
+// const unsigned char*
+// TRACE_EVENT_API_GET_CATEGORY_ENABLED(const char* category_name)
+#define TRACE_EVENT_API_GET_CATEGORY_ENABLED \
+ gl::TraceGetTraceCategoryEnabledFlag
+
+// Add a trace event to the platform tracing system.
+// void TRACE_EVENT_API_ADD_TRACE_EVENT(
+// char phase,
+// const unsigned char* category_enabled,
+// const char* name,
+// unsigned long long id,
+// int num_args,
+// const char** arg_names,
+// const unsigned char* arg_types,
+// const unsigned long long* arg_values,
+// unsigned char flags)
+#define TRACE_EVENT_API_ADD_TRACE_EVENT \
+ gl::TraceAddTraceEvent
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Implementation detail: trace event macros create temporary variables
+// to keep instrumentation overhead low. These macros give each temporary
+// variable a unique name based on the line number to prevent name collissions.
+#define INTERNAL_TRACE_EVENT_UID3(a, b) \
+ trace_event_unique_##a##b
+#define INTERNAL_TRACE_EVENT_UID2(a, b) \
+ INTERNAL_TRACE_EVENT_UID3(a, b)
+#define INTERNALTRACEEVENTUID(name_prefix) \
+ INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__)
+
+// Implementation detail: internal macro to create static category.
+#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category) \
+ static const unsigned char* INTERNALTRACEEVENTUID(catstatic) = 0; \
+ if (!INTERNALTRACEEVENTUID(catstatic)) \
+ INTERNALTRACEEVENTUID(catstatic) = \
+ TRACE_EVENT_API_GET_CATEGORY_ENABLED(category);
+
+// Implementation detail: internal macro to create static category and add
+// event if the category is enabled.
+#define INTERNAL_TRACE_EVENT_ADD(phase, category, name, flags, ...) \
+ do { \
+ INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
+ if (*INTERNALTRACEEVENTUID(catstatic)) { \
+ gl::TraceEvent::addTraceEvent( \
+ phase, INTERNALTRACEEVENTUID(catstatic), name, \
+ gl::TraceEvent::noEventId, flags, ##__VA_ARGS__); \
+ } \
+ } while (0)
+
+// Implementation detail: internal macro to create static category and add begin
+// event if the category is enabled. Also adds the end event when the scope
+// ends.
+#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, ...) \
+ INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
+ gl::TraceEvent::TraceEndOnScopeClose \
+ INTERNALTRACEEVENTUID(profileScope); \
+ if (*INTERNALTRACEEVENTUID(catstatic)) { \
+ gl::TraceEvent::addTraceEvent( \
+ TRACE_EVENT_PHASE_BEGIN, \
+ INTERNALTRACEEVENTUID(catstatic), \
+ name, gl::TraceEvent::noEventId, \
+ TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \
+ INTERNALTRACEEVENTUID(profileScope).initialize( \
+ INTERNALTRACEEVENTUID(catstatic), name); \
+ }
+
+// Implementation detail: internal macro to create static category and add
+// event if the category is enabled.
+#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category, name, id, flags, \
+ ...) \
+ do { \
+ INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
+ if (*INTERNALTRACEEVENTUID(catstatic)) { \
+ unsigned char traceEventFlags = flags | TRACE_EVENT_FLAG_HAS_ID; \
+ gl::TraceEvent::TraceID traceEventTraceID( \
+ id, &traceEventFlags); \
+ gl::TraceEvent::addTraceEvent( \
+ phase, INTERNALTRACEEVENTUID(catstatic), \
+ name, traceEventTraceID.data(), traceEventFlags, \
+ ##__VA_ARGS__); \
+ } \
+ } while (0)
+
+// Notes regarding the following definitions:
+// New values can be added and propagated to third party libraries, but existing
+// definitions must never be changed, because third party libraries may use old
+// definitions.
+
+// Phase indicates the nature of an event entry. E.g. part of a begin/end pair.
+#define TRACE_EVENT_PHASE_BEGIN ('B')
+#define TRACE_EVENT_PHASE_END ('E')
+#define TRACE_EVENT_PHASE_INSTANT ('I')
+#define TRACE_EVENT_PHASE_ASYNC_BEGIN ('S')
+#define TRACE_EVENT_PHASE_ASYNC_STEP ('T')
+#define TRACE_EVENT_PHASE_ASYNC_END ('F')
+#define TRACE_EVENT_PHASE_METADATA ('M')
+#define TRACE_EVENT_PHASE_COUNTER ('C')
+#define TRACE_EVENT_PHASE_SAMPLE ('P')
+
+// Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT.
+#define TRACE_EVENT_FLAG_NONE (static_cast<unsigned char>(0))
+#define TRACE_EVENT_FLAG_COPY (static_cast<unsigned char>(1 << 0))
+#define TRACE_EVENT_FLAG_HAS_ID (static_cast<unsigned char>(1 << 1))
+#define TRACE_EVENT_FLAG_MANGLE_ID (static_cast<unsigned char>(1 << 2))
+
+// Type values for identifying types in the TraceValue union.
+#define TRACE_VALUE_TYPE_BOOL (static_cast<unsigned char>(1))
+#define TRACE_VALUE_TYPE_UINT (static_cast<unsigned char>(2))
+#define TRACE_VALUE_TYPE_INT (static_cast<unsigned char>(3))
+#define TRACE_VALUE_TYPE_DOUBLE (static_cast<unsigned char>(4))
+#define TRACE_VALUE_TYPE_POINTER (static_cast<unsigned char>(5))
+#define TRACE_VALUE_TYPE_STRING (static_cast<unsigned char>(6))
+#define TRACE_VALUE_TYPE_COPY_STRING (static_cast<unsigned char>(7))
+
+
+namespace gl {
+
+extern long **traceSamplingState;
+
+namespace TraceEvent {
+
+// Specify these values when the corresponding argument of addTraceEvent is not
+// used.
+const int zeroNumArgs = 0;
+const unsigned long long noEventId = 0;
+
+// TraceID encapsulates an ID that can either be an integer or pointer. Pointers
+// are mangled with the Process ID so that they are unlikely to collide when the
+// same pointer is used on different processes.
+class TraceID {
+public:
+ explicit TraceID(const void* id, unsigned char* flags) :
+ m_data(static_cast<unsigned long long>(reinterpret_cast<unsigned long>(id)))
+ {
+ *flags |= TRACE_EVENT_FLAG_MANGLE_ID;
+ }
+ explicit TraceID(unsigned long long id, unsigned char* flags) : m_data(id) { (void)flags; }
+ explicit TraceID(unsigned long id, unsigned char* flags) : m_data(id) { (void)flags; }
+ explicit TraceID(unsigned int id, unsigned char* flags) : m_data(id) { (void)flags; }
+ explicit TraceID(unsigned short id, unsigned char* flags) : m_data(id) { (void)flags; }
+ explicit TraceID(unsigned char id, unsigned char* flags) : m_data(id) { (void)flags; }
+ explicit TraceID(long long id, unsigned char* flags) :
+ m_data(static_cast<unsigned long long>(id)) { (void)flags; }
+ explicit TraceID(long id, unsigned char* flags) :
+ m_data(static_cast<unsigned long long>(id)) { (void)flags; }
+ explicit TraceID(int id, unsigned char* flags) :
+ m_data(static_cast<unsigned long long>(id)) { (void)flags; }
+ explicit TraceID(short id, unsigned char* flags) :
+ m_data(static_cast<unsigned long long>(id)) { (void)flags; }
+ explicit TraceID(signed char id, unsigned char* flags) :
+ m_data(static_cast<unsigned long long>(id)) { (void)flags; }
+
+ unsigned long long data() const { return m_data; }
+
+private:
+ unsigned long long m_data;
+};
+
+// Simple union to store various types as unsigned long long.
+union TraceValueUnion {
+ bool m_bool;
+ unsigned long long m_uint;
+ long long m_int;
+ double m_double;
+ const void* m_pointer;
+ const char* m_string;
+};
+
+// Simple container for const char* that should be copied instead of retained.
+class TraceStringWithCopy {
+public:
+ explicit TraceStringWithCopy(const char* str) : m_str(str) { }
+ operator const char* () const { return m_str; }
+private:
+ const char* m_str;
+};
+
+// Define setTraceValue for each allowed type. It stores the type and
+// value in the return arguments. This allows this API to avoid declaring any
+// structures so that it is portable to third_party libraries.
+#define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, \
+ union_member, \
+ value_type_id) \
+ static inline void setTraceValue(actual_type arg, \
+ unsigned char* type, \
+ unsigned long long* value) { \
+ TraceValueUnion typeValue; \
+ typeValue.union_member = arg; \
+ *type = value_type_id; \
+ *value = typeValue.m_uint; \
+ }
+// Simpler form for int types that can be safely casted.
+#define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, \
+ value_type_id) \
+ static inline void setTraceValue(actual_type arg, \
+ unsigned char* type, \
+ unsigned long long* value) { \
+ *type = value_type_id; \
+ *value = static_cast<unsigned long long>(arg); \
+ }
+
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE(bool, m_bool, TRACE_VALUE_TYPE_BOOL)
+INTERNAL_DECLARE_SET_TRACE_VALUE(double, m_double, TRACE_VALUE_TYPE_DOUBLE)
+INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, m_pointer,
+ TRACE_VALUE_TYPE_POINTER)
+INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, m_string,
+ TRACE_VALUE_TYPE_STRING)
+INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, m_string,
+ TRACE_VALUE_TYPE_COPY_STRING)
+
+#undef INTERNAL_DECLARE_SET_TRACE_VALUE
+#undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT
+
+static inline void setTraceValue(const std::string& arg,
+ unsigned char* type,
+ unsigned long long* value) {
+ TraceValueUnion typeValue;
+ typeValue.m_string = arg.data();
+ *type = TRACE_VALUE_TYPE_COPY_STRING;
+ *value = typeValue.m_uint;
+}
+
+// These addTraceEvent template functions are defined here instead of in the
+// macro, because the arg values could be temporary string objects. In order to
+// store pointers to the internal c_str and pass through to the tracing API, the
+// arg values must live throughout these procedures.
+
+static inline void addTraceEvent(char phase,
+ const unsigned char* categoryEnabled,
+ const char* name,
+ unsigned long long id,
+ unsigned char flags) {
+ TRACE_EVENT_API_ADD_TRACE_EVENT(
+ phase, categoryEnabled, name, id,
+ zeroNumArgs, 0, 0, 0,
+ flags);
+}
+
+template<class ARG1_TYPE>
+static inline void addTraceEvent(char phase,
+ const unsigned char* categoryEnabled,
+ const char* name,
+ unsigned long long id,
+ unsigned char flags,
+ const char* arg1Name,
+ const ARG1_TYPE& arg1Val) {
+ const int numArgs = 1;
+ unsigned char argTypes[1];
+ unsigned long long argValues[1];
+ setTraceValue(arg1Val, &argTypes[0], &argValues[0]);
+ TRACE_EVENT_API_ADD_TRACE_EVENT(
+ phase, categoryEnabled, name, id,
+ numArgs, &arg1Name, argTypes, argValues,
+ flags);
+}
+
+template<class ARG1_TYPE, class ARG2_TYPE>
+static inline void addTraceEvent(char phase,
+ const unsigned char* categoryEnabled,
+ const char* name,
+ unsigned long long id,
+ unsigned char flags,
+ const char* arg1Name,
+ const ARG1_TYPE& arg1Val,
+ const char* arg2Name,
+ const ARG2_TYPE& arg2Val) {
+ const int numArgs = 2;
+ const char* argNames[2] = { arg1Name, arg2Name };
+ unsigned char argTypes[2];
+ unsigned long long argValues[2];
+ setTraceValue(arg1Val, &argTypes[0], &argValues[0]);
+ setTraceValue(arg2Val, &argTypes[1], &argValues[1]);
+ return TRACE_EVENT_API_ADD_TRACE_EVENT(
+ phase, categoryEnabled, name, id,
+ numArgs, argNames, argTypes, argValues,
+ flags);
+}
+
+// Used by TRACE_EVENTx macro. Do not use directly.
+class TraceEndOnScopeClose {
+public:
+ // Note: members of m_data intentionally left uninitialized. See initialize.
+ TraceEndOnScopeClose() : m_pdata(0) { }
+ ~TraceEndOnScopeClose()
+ {
+ if (m_pdata)
+ addEventIfEnabled();
+ }
+
+ void initialize(const unsigned char* categoryEnabled,
+ const char* name)
+ {
+ m_data.categoryEnabled = categoryEnabled;
+ m_data.name = name;
+ m_pdata = &m_data;
+ }
+
+private:
+ // Add the end event if the category is still enabled.
+ void addEventIfEnabled()
+ {
+ // Only called when m_pdata is non-null.
+ if (*m_pdata->categoryEnabled) {
+ TRACE_EVENT_API_ADD_TRACE_EVENT(
+ TRACE_EVENT_PHASE_END,
+ m_pdata->categoryEnabled,
+ m_pdata->name, noEventId,
+ zeroNumArgs, 0, 0, 0,
+ TRACE_EVENT_FLAG_NONE);
+ }
+ }
+
+ // This Data struct workaround is to avoid initializing all the members
+ // in Data during construction of this object, since this object is always
+ // constructed, even when tracing is disabled. If the members of Data were
+ // members of this class instead, compiler warnings occur about potential
+ // uninitialized accesses.
+ struct Data {
+ const unsigned char* categoryEnabled;
+ const char* name;
+ };
+ Data* m_pdata;
+ Data m_data;
+};
+
+// TraceEventSamplingStateScope records the current sampling state
+// and sets a new sampling state. When the scope exists, it restores
+// the sampling state having recorded.
+template<size_t BucketNumber>
+class SamplingStateScope {
+public:
+ SamplingStateScope(const char* categoryAndName)
+ {
+ m_previousState = SamplingStateScope<BucketNumber>::current();
+ SamplingStateScope<BucketNumber>::set(categoryAndName);
+ }
+
+ ~SamplingStateScope()
+ {
+ SamplingStateScope<BucketNumber>::set(m_previousState);
+ }
+
+ // FIXME: Make load/store to traceSamplingState[] thread-safe and atomic.
+ static inline const char* current()
+ {
+ return reinterpret_cast<const char*>(*gl::traceSamplingState[BucketNumber]);
+ }
+ static inline void set(const char* categoryAndName)
+ {
+ *gl::traceSamplingState[BucketNumber] = reinterpret_cast<long>(const_cast<char*>(categoryAndName));
+ }
+
+private:
+ const char* m_previousState;
+};
+
+} // namespace TraceEvent
+
+} // namespace gl
+
+#endif