Upgrade ANGLE to 2.1~99f075dade7c

This aligns with Chromium branch 2356.

This version brings more complete OpenGL ES 3 support as well as various
bug fixes and performance improvements.

The following changes were made to earlier patches:

-0000-General-fixes-for-ANGLE-2.1
  Removed. All changes are now handled elsewhere.
+0001-ANGLE-Improve-Windows-Phone-support
  Consolidated remaining parts from 0009/0010.
+0002-ANGLE-Fix-compilation-with-MinGW
  Remaining issues from patch 0016.
+0003-ANGLE-Fix-compilation-with-MSVC2010
  Remaining issues from patch 0015.
+0004-ANGLE-Dynamically-load-D3D-compiler-from-list
  Renamed from patch 0008.
+0005-ANGLE-Add-support-for-querying-platform-device
  Renamed from patch 0013.
-0004-Make-it-possible-to-link-ANGLE-statically-for-single
  Removed. Fixed by adding defines to project files.
-0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-or-t
  Renamed to patch 0005.
-0009-ANGLE-Support-WinRT
  Removed. Mostly fixed upstream; remaining parts in patch 0001.
-0010-ANGLE-Enable-D3D11-for-feature-level-9-cards
  Removed. Mostly fixed upstream; remaining parts in patch 0001.
-0012-ANGLE-fix-semantic-index-lookup
  Removed. Fixed upstream.
-0013-ANGLE-Add-support-for-querying-platform-device
  Renamed to patch 0005.
-0014-Let-ANGLE-use-multithreaded-devices-if-necessary
  Removed. No longer needed.
-0015-ANGLE-Fix-angle-d3d11-on-MSVC2010
  Moved remaining parts to patch 0003.
-0016-ANGLE-Fix-compilation-with-MinGW-D3D11
  Moved remaining parts to patch 0002.
-0017-ANGLE-Fix-compilation-with-D3D9
  Removed. Fixed upstream.
-0018-ANGLE-Fix-releasing-textures-after-we-kill-D3D11
  Removed. Fixed upstream.
-0019-ANGLE-Fix-handling-of-shader-source-with-fixed-lengt
  Removed. Fixed upstream.
-0020-ANGLE-Do-not-use-std-strlen
  Removed. Fixed upstream.
-0020-ANGLE-Fix-compilation-with-MSVC2013-Update4
  Removed. Fixed upstream.

[ChangeLog][Third-party libraries] ANGLE was updated to Chromium branch
2356 (2.1~99f075dade7c).

Change-Id: I32ccbfe95e10986bd94be7191dfd53445ea09158
Task-number: QTBUG-44815
Task-number: QTBUG-37660
Task-number: QTBUG-44694
Task-number: QTBUG-42443
Reviewed-by: Andrew Knight <qt@panimo.net>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@theqtcompany.com>
This commit is contained in:
Andrew Knight 2015-04-08 17:04:36 +03:00 committed by Andrew Knight
parent 331ddacfca
commit a218a252c4
511 changed files with 40623 additions and 31334 deletions

View File

@ -21,7 +21,7 @@ wince* {
QMAKE_LIBDIR += $$QMAKE_LIBDIR_OPENGL_ES2_RELEASE
}
DEFINES += QT_OPENGL_ES_2 QT_OPENGL_ES_2_ANGLE
contains(QT_CONFIG, static): DEFINES += QT_OPENGL_ES_2_ANGLE_STATIC
contains(QT_CONFIG, static): DEFINES += QT_OPENGL_ES_2_ANGLE_STATIC GL_APICALL= EGLAPI=
QT_CONFIG -= opengl
} else {
!contains(QT_CONFIG, dynamicgl) {

View File

@ -6,19 +6,28 @@ build
extensions
samples
tests
third_party
src/ipch
util
.svn
# Files from ANGLE we don't want/need
DEPS
*.chromium
*.isolate
*.md
*.gn
*.gyp
*.gypi
*.sh
*.bat
*.patch
*.py
*.rc
*_unittest.cpp
codereview.settings
src/commit.h
src/libANGLE/renderer/gl
src/third_party/khronos/GL
# Generated by flex/bison
src/compiler/preprocessor/Tokenizer.cpp
@ -28,5 +37,5 @@ src/compiler/translator/glslang_tab.cpp
src/compiler/translator/glslang_tab.h
# Generated by FXC
src/libGLESv2/renderer/d3d/d3d9/shaders/compiled/*.h
src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/*.h
src/libANGLE/renderer/d3d/d3d9/shaders/compiled/*.h
src/libANGLE/renderer/d3d/d3d11/shaders/compiled/*.h

View File

@ -16,17 +16,22 @@ Autodesk, Inc.
BlackBerry Limited
Cable Television Laboratories, Inc.
Cloud Party, Inc.
Imagination Technologies Ltd.
Intel Corporation
Mozilla Corporation
Turbulenz
Klarälvdalens Datakonsult AB
Microsoft Corporation
Microsoft Open Technologies, Inc.
NVIDIA Corporation
Opera Software ASA
The Qt Company Ltd.
Jacek Caban
Mark Callow
Ginn Chen
Tibor den Ouden
Régis Fénéon
James Hauxwell
Sam Hocevar
Pierre Leveille
@ -35,3 +40,4 @@ Boying Lu
Aitor Moreno
Yuri O'Donnell
Josh Soref
Maks Naumov

View File

@ -1,4 +1,4 @@
# This is the official list of people who can contribute
# This is the official list of people who can contribute
# (and who have contributed) code to the ANGLE project
# repository.
# The AUTHORS file lists the copyright holders; this file
@ -40,6 +40,7 @@ Google Inc.
thestig@chromium.org
Justin Schuh
Scott Graham
Corentin Wallez
Adobe Systems Inc.
Alexandru Chiculita
@ -55,6 +56,9 @@ Cloud Party, Inc.
The Qt Company Ltd.
Andrew Knight
Imagination Technologies Ltd.
Gregoire Payen de La Garanderie
Intel Corporation
Jin Yang
Andy Chen
@ -80,10 +84,21 @@ Mark Banner (standard8mbp)
David Kilzer
Jacek Caban
Tibor den Ouden
Régis Fénéon
Microsoft Corporation
Cooper Partin
Austin Kinross
Minmin Gong
Microsoft Open Technologies, Inc.
Cooper Partin
Austin Kinross
Cooper Partin
Austin Kinross
NVIDIA Corporation
Olli Etuaho
Arun Patole
Qingqing Deng
Opera Software ASA
Daniel Bratell

View File

@ -33,12 +33,12 @@ extern "C" {
** used to make the header, and the header can be found at
** http://www.opengl.org/registry/
**
** Khronos $Revision: 27018 $ on $Date: 2014-06-10 08:06:12 -0700 (Tue, 10 Jun 2014) $
** Khronos $Revision: 29318 $ on $Date: 2015-01-02 03:16:10 -0800 (Fri, 02 Jan 2015) $
*/
#include <EGL/eglplatform.h>
/* Generated on date 20140610 */
/* Generated on date 20150102 */
/* Generated C header for:
* API: egl
@ -240,6 +240,7 @@ EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void);
typedef void *EGLSync;
typedef intptr_t EGLAttrib;
typedef khronos_utime_nanoseconds_t EGLTime;
typedef void *EGLImage;
#define EGL_CONTEXT_MAJOR_VERSION 0x3098
#define EGL_CONTEXT_MINOR_VERSION 0x30FB
#define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD
@ -281,10 +282,14 @@ typedef khronos_utime_nanoseconds_t EGLTime;
#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6
#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7
#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8
#define EGL_IMAGE_PRESERVED 0x30D2
#define EGL_NO_IMAGE ((EGLImage)0)
EGLAPI EGLSync EGLAPIENTRY eglCreateSync (EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list);
EGLAPI EGLBoolean EGLAPIENTRY eglDestroySync (EGLDisplay dpy, EGLSync sync);
EGLAPI EGLint EGLAPIENTRY eglClientWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttrib (EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value);
EGLAPI EGLImage EGLAPIENTRY eglCreateImage (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list);
EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImage (EGLDisplay dpy, EGLImage image);
EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplay (EGLenum platform, void *native_display, const EGLAttrib *attrib_list);
EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list);
EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list);

View File

@ -440,24 +440,28 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu
#ifndef EGL_ANGLE_platform_angle
#define EGL_ANGLE_platform_angle 1
#define EGL_PLATFORM_ANGLE_ANGLE 0x3201
#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202
#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3203
#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3204
#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3205
#define EGL_PLATFORM_ANGLE_ANGLE 0x3202
#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203
#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3204
#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3205
#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3206
#endif /* EGL_ANGLE_platform_angle */
#ifndef EGL_ANGLE_platform_angle_d3d
#define EGL_ANGLE_platform_angle_d3d 1
#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3206
#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3207
#define EGL_PLATFORM_ANGLE_USE_WARP_ANGLE 0x3208
#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3207
#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208
#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE 0x3209
#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE 0x320A
#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE 0x320B
#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE 0x320C
#define EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE 0x320F
#endif /* EGL_ANGLE_platform_angle_d3d */
#ifndef EGL_ANGLE_platform_angle_opengl
#define EGL_ANGLE_platform_angle_opengl 1
#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x3209
#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320A
#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320D
#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320E
#endif /* EGL_ANGLE_platform_angle_opengl */
#ifndef EGL_ARM_pixmap_multisample_discard

View File

@ -73,15 +73,14 @@
#endif
#include <windows.h>
typedef HDC EGLNativeDisplayType;
typedef HBITMAP EGLNativePixmapType;
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) /* Windows Store */
#include <inspectable.h>
typedef IInspectable* EGLNativeDisplayType;
typedef IInspectable* EGLNativeWindowType;
#else
typedef HDC EGLNativeDisplayType;
#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP) /* Windows Desktop */
typedef HWND EGLNativeWindowType;
#else /* Windows Store */
#include <inspectable.h>
typedef IInspectable* EGLNativeWindowType;
#endif
#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
@ -110,6 +109,14 @@ typedef Display *EGLNativeDisplayType;
typedef Pixmap EGLNativePixmapType;
typedef Window EGLNativeWindowType;
#elif defined(__GNUC__) && ( defined(__APPLE_CPP__) || defined(__APPLE_CC__) || defined(__MACOS_CLASSIC__) )
// TODO(jmadill): native implementation for OSX
typedef void *EGLNativeDisplayType;
typedef void *EGLNativePixmapType;
typedef void *EGLNativeWindowType;
#else
#error "Platform not recognized"
#endif

View File

@ -3,8 +3,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#ifndef _COMPILER_INTERFACE_INCLUDED_
#define _COMPILER_INTERFACE_INCLUDED_
#ifndef GLSLANG_SHADERLANG_H_
#define GLSLANG_SHADERLANG_H_
#if defined(COMPONENT_BUILD) && !defined(ANGLE_TRANSLATOR_STATIC)
#if defined(_WIN32) || defined(_WIN64)
@ -48,7 +48,7 @@ typedef unsigned int GLenum;
// Version number for shader translation API.
// It is incremented every time the API changes.
#define ANGLE_SH_VERSION 132
#define ANGLE_SH_VERSION 134
typedef enum {
SH_GLES2_SPEC = 0x8B40,
@ -81,11 +81,16 @@ typedef enum {
} ShShaderSpec;
typedef enum {
SH_ESSL_OUTPUT = 0x8B45,
SH_GLSL_OUTPUT = 0x8B46,
SH_HLSL_OUTPUT = 0x8B47,
SH_HLSL9_OUTPUT = 0x8B47,
SH_HLSL11_OUTPUT = 0x8B48
SH_ESSL_OUTPUT = 0x8B45,
// SH_GLSL_OUTPUT is deprecated. This is to not break the build.
SH_GLSL_OUTPUT = 0x8B46,
SH_GLSL_COMPATIBILITY_OUTPUT = 0x8B46,
SH_GLSL_CORE_OUTPUT = 0x8B47,
// HLSL output only supported in some configurations.
SH_HLSL_OUTPUT = 0x8B48,
SH_HLSL9_OUTPUT = 0x8B48,
SH_HLSL11_OUTPUT = 0x8B49
} ShShaderOutput;
// Compile options.
@ -223,6 +228,10 @@ typedef struct
int EXT_draw_buffers;
int EXT_frag_depth;
int EXT_shader_texture_lod;
int WEBGL_debug_shader_precision;
int EXT_shader_framebuffer_fetch;
int NV_shader_framebuffer_fetch;
int ARM_shader_framebuffer_fetch;
// Set to 1 to enable replacing GL_EXT_draw_buffers #extension directives
// with GL_NV_draw_buffers in ESSL output. This flag can be used to emulate
@ -290,7 +299,8 @@ COMPILER_EXPORT const std::string &ShGetBuiltInResourcesString(const ShHandle ha
// spec: Specifies the language spec the compiler must conform to -
// SH_GLES2_SPEC or SH_WEBGL_SPEC.
// output: Specifies the output code type - SH_ESSL_OUTPUT, SH_GLSL_OUTPUT,
// SH_HLSL9_OUTPUT or SH_HLSL11_OUTPUT.
// SH_HLSL9_OUTPUT or SH_HLSL11_OUTPUT. Note: HLSL output is only
// supported in some configurations.
// resources: Specifies the built-in resources.
COMPILER_EXPORT ShHandle ShConstructCompiler(
sh::GLenum type,
@ -408,4 +418,4 @@ COMPILER_EXPORT bool ShGetUniformRegister(const ShHandle handle,
const std::string &uniformName,
unsigned int *indexOut);
#endif // _COMPILER_INTERFACE_INCLUDED_
#endif // GLSLANG_SHADERLANG_H_

View File

@ -7,8 +7,8 @@
// Types to represent GL variables (varyings, uniforms, etc)
//
#ifndef _COMPILER_INTERFACE_VARIABLES_
#define _COMPILER_INTERFACE_VARIABLES_
#ifndef GLSLANG_SHADERVARS_H_
#define GLSLANG_SHADERVARS_H_
#include <string>
#include <vector>
@ -28,6 +28,9 @@ enum InterpolationType
INTERPOLATION_FLAT
};
// Validate link & SSO consistency of interpolation qualifiers
COMPILER_EXPORT bool InterpolationTypesMatch(InterpolationType a, InterpolationType b);
// Uniform block layout qualifier, see section 4.3.8.3 of the ESSL 3.00.4 spec
enum BlockLayoutType
{
@ -182,4 +185,4 @@ struct COMPILER_EXPORT InterfaceBlock
}
#endif // _COMPILER_INTERFACE_VARIABLES_
#endif // GLSLANG_SHADERVARS_H_

2
src/3rdparty/angle/include/KHR/khrplatform.h vendored Normal file → Executable file
View File

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

View File

@ -7,8 +7,8 @@
// Includes all necessary GL headers and definitions for ANGLE.
//
#ifndef ANGLE_GL_H_
#define ANGLE_GL_H_
#ifndef ANGLEGL_H_
#define ANGLEGL_H_
#include "GLES2/gl2.h"
#include "GLES2/gl2ext.h"
@ -20,4 +20,4 @@
#define GL_SAMPLER_2D_RECT_ARB 0x8B63
#endif
#endif // ANGLE_GL_H_
#endif // ANGLEGL_H_

28
src/3rdparty/angle/include/export.h vendored Normal file
View File

@ -0,0 +1,28 @@
//
// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// export.h : Defines ANGLE_EXPORT, a macro for exporting functions from the DLL
#ifndef LIBGLESV2_EXPORT_H_
#define LIBGLESV2_EXPORT_H_
#if defined(_WIN32)
# if defined(LIBGLESV2_IMPLEMENTATION) || defined(LIBANGLE_IMPLEMENTATION)
# define ANGLE_EXPORT __declspec(dllexport)
# else
# define ANGLE_EXPORT __declspec(dllimport)
# endif
#elif defined(__GNUC__)
# if defined(LIBGLESV2_IMPLEMENTATION) || defined(LIBANGLE_IMPLEMENTATION)
# define ANGLE_EXPORT __attribute__((visibility ("default")))
# else
# define ANGLE_EXPORT
# endif
#else
# define ANGLE_EXPORT
#endif
#endif // LIBGLESV2_EXPORT_H_

View File

@ -0,0 +1,112 @@
//
// Copyright (c) 2015 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.
// Platform.h: The public interface ANGLE exposes to the API layer, for
// doing platform-specific tasks like gathering data, or for tracing.
#ifndef ANGLE_PLATFORM_H
#define ANGLE_PLATFORM_H
#include <stdint.h>
#include "../export.h"
namespace angle
{
class Platform
{
public:
// Tracing --------
typedef uint64_t TraceEventHandle;
// Add a trace event to the platform tracing system. Depending on the actual
// enabled state, this event may be recorded or dropped.
// - phase specifies the type of event:
// - BEGIN ('B'): Marks the beginning of a scoped event.
// - END ('E'): Marks the end of a scoped event.
// - COMPLETE ('X'): Marks the beginning of a scoped event, but doesn't
// need a matching END event. Instead, at the end of the scope,
// updateTraceEventDuration() must be called with the TraceEventHandle
// returned from addTraceEvent().
// - INSTANT ('I'): Standalone, instantaneous event.
// - START ('S'): Marks the beginning of an asynchronous event (the end
// event can occur in a different scope or thread). The id parameter is
// used to match START/FINISH pairs.
// - FINISH ('F'): Marks the end of an asynchronous event.
// - COUNTER ('C'): Used to trace integer quantities that change over
// time. The argument values are expected to be of type int.
// - METADATA ('M'): Reserved for internal use.
// - categoryEnabled is the pointer returned by getTraceCategoryEnabledFlag.
// - name is the name of the event. Also used to match BEGIN/END and
// START/FINISH pairs.
// - id optionally allows events of the same name to be distinguished from
// each other. For example, to trace the consutruction and destruction of
// objects, specify the pointer as the id parameter.
// - numArgs specifies the number of elements in argNames, argTypes, and
// argValues.
// - argNames is the array of argument names. Use long-lived literal strings
// or specify the COPY flag.
// - argTypes is the array of argument types:
// - BOOL (1): bool
// - UINT (2): unsigned long long
// - INT (3): long long
// - DOUBLE (4): double
// - POINTER (5): void*
// - STRING (6): char* (long-lived null-terminated char* string)
// - COPY_STRING (7): char* (temporary null-terminated char* string)
// - CONVERTABLE (8): WebConvertableToTraceFormat
// - argValues is the array of argument values. Each value is the unsigned
// long long member of a union of all supported types.
// - flags can be 0 or one or more of the following, ORed together:
// - COPY (0x1): treat all strings (name, argNames and argValues of type
// string) as temporary so that they will be copied by addTraceEvent.
// - HAS_ID (0x2): use the id argument to uniquely identify the event for
// matching with other events of the same name.
// - MANGLE_ID (0x4): specify this flag if the id parameter is the value
// of a pointer.
virtual TraceEventHandle addTraceEvent(char phase,
const unsigned char *categoryEnabledFlag,
const char *name,
unsigned long long id,
double timestamp,
int numArgs,
const char **argNames,
const unsigned char *argTypes,
const unsigned long long *argValues,
unsigned char flags)
{
return 0;
}
// Set the duration field of a COMPLETE trace event.
virtual void updateTraceEventDuration(const unsigned char* categoryEnabledFlag, const char* name, TraceEventHandle) { }
// Callbacks for reporting histogram data.
// CustomCounts histogram has exponential bucket sizes, so that min=1, max=1000000, bucketCount=50 would do.
virtual void histogramCustomCounts(const char* name, int sample, int min, int max, int bucketCount) { }
// Enumeration histogram buckets are linear, boundaryValue should be larger than any possible sample value.
virtual void histogramEnumeration(const char* name, int sample, int boundaryValue) { }
// Unlike enumeration histograms, sparse histograms only allocate memory for non-empty buckets.
virtual void histogramSparse(const char* name, int sample) { }
protected:
virtual ~Platform() { }
};
}
typedef void(*ANGLEPlatformInitializeFunc)(angle::Platform*);
ANGLE_EXPORT void ANGLEPlatformInitialize(angle::Platform*);
typedef void (*ANGLEPlatformShutdownFunc)();
ANGLE_EXPORT void ANGLEPlatformShutdown();
typedef angle::Platform *(*ANGLEPlatformCurrentFunc)();
ANGLE_EXPORT angle::Platform *ANGLEPlatformCurrent();
#endif // ANGLE_PLATFORM_H

View File

@ -1,12 +0,0 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// commit.h:
// This is a default commit hash header, when git is not available.
//
#define ANGLE_COMMIT_HASH "30d6c255d238"
#define ANGLE_COMMIT_HASH_SIZE 12
#define ANGLE_COMMIT_DATE "2014-11-13 17:37:03 +0000"

View File

@ -4,12 +4,13 @@
// found in the LICENSE file.
//
#include "libGLESv2/renderer/d3d/MemoryBuffer.h"
#include "common/debug.h"
#include "common/MemoryBuffer.h"
#include <algorithm>
#include <cstdlib>
#include "common/debug.h"
namespace rx
{
@ -32,26 +33,31 @@ bool MemoryBuffer::resize(size_t size)
free(mData);
mData = NULL;
mSize = 0;
return true;
}
else
if (size == mSize)
{
uint8_t *newMemory = reinterpret_cast<uint8_t*>(malloc(sizeof(uint8_t) * size));
if (newMemory == NULL)
{
return false;
}
if (mData)
{
// Copy the intersection of the old data and the new data
std::copy(mData, mData + std::min(mSize, size), newMemory);
free(mData);
}
mData = newMemory;
mSize = size;
return true;
}
// Only reallocate if the size has changed.
uint8_t *newMemory = reinterpret_cast<uint8_t*>(malloc(sizeof(uint8_t) * size));
if (newMemory == NULL)
{
return false;
}
if (mData)
{
// Copy the intersection of the old data and the new data
std::copy(mData, mData + std::min(mSize, size), newMemory);
free(mData);
}
mData = newMemory;
mSize = size;
return true;
}

View File

@ -4,16 +4,18 @@
// found in the LICENSE file.
//
#ifndef LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H_
#define LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H_
#ifndef COMMON_MEMORYBUFFER_H_
#define COMMON_MEMORYBUFFER_H_
#include "common/angleutils.h"
#include <cstddef>
#include <cstdint>
#include <stdint.h>
namespace rx
{
class MemoryBuffer
class MemoryBuffer : angle::NonCopyable
{
public:
MemoryBuffer();
@ -33,4 +35,4 @@ class MemoryBuffer
}
#endif // LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H
#endif // COMMON_MEMORYBUFFER_H_

View File

@ -0,0 +1,61 @@
//
// Copyright (c) 2015 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.
//
// Optional.h:
// Represents a type that may be invalid, similar to std::optional.
//
#ifndef COMMON_OPTIONAL_H_
#define COMMON_OPTIONAL_H_
template <class T>
struct Optional
{
Optional()
: mValid(false),
mValue(T())
{}
explicit Optional(const T &valueIn)
: mValid(true),
mValue(valueIn)
{}
Optional(const Optional &other)
: mValid(other.mValid),
mValue(other.mValue)
{}
Optional &operator=(const Optional &other)
{
this->mValid = other.mValid;
this->mValue = other.mValue;
return *this;
}
static Optional None()
{
return Optional();
}
bool valid() const { return mValid; }
const T &value() const { return mValue; }
bool operator==(const Optional &other) const
{
return ((mValid == other.mValid) && (!mValid || (mValue == other.mValue)));
}
bool operator!=(const Optional &other) const
{
return !(*this == other);
}
private:
bool mValid;
T mValue;
};
#endif // COMMON_OPTIONAL_H_

View File

@ -1,95 +0,0 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// RefCountObject.h: Defines the gl::RefCountObject base class that provides
// lifecycle support for GL objects using the traditional BindObject scheme, but
// that need to be reference counted for correct cross-context deletion.
// (Concretely, textures, buffers and renderbuffers.)
#ifndef COMMON_REFCOUNTOBJECT_H_
#define COMMON_REFCOUNTOBJECT_H_
#include "common/debug.h"
#include "angle_gl.h"
#include <cstddef>
class RefCountObject
{
public:
explicit RefCountObject(GLuint id);
virtual ~RefCountObject();
virtual void addRef() const;
virtual void release() const;
GLuint id() const { return mId; }
private:
GLuint mId;
mutable std::size_t mRefCount;
};
class RefCountObjectBindingPointer
{
protected:
RefCountObjectBindingPointer() : mObject(NULL) { }
~RefCountObjectBindingPointer() { ASSERT(mObject == NULL); } // Objects have to be released before the resource manager is destroyed, so they must be explicitly cleaned up.
void set(RefCountObject *newObject);
RefCountObject *get() const { return mObject; }
public:
GLuint id() const { return (mObject != NULL) ? mObject->id() : 0; }
bool operator!() const { return (get() == NULL); }
private:
RefCountObject *mObject;
};
template <class ObjectType>
class BindingPointer : public RefCountObjectBindingPointer
{
public:
void set(ObjectType *newObject) { RefCountObjectBindingPointer::set(newObject); }
ObjectType *get() const { return static_cast<ObjectType*>(RefCountObjectBindingPointer::get()); }
ObjectType *operator->() const { return get(); }
};
template <class ObjectType>
class OffsetBindingPointer : public RefCountObjectBindingPointer
{
public:
OffsetBindingPointer() : mOffset(0), mSize(0) { }
void set(ObjectType *newObject)
{
RefCountObjectBindingPointer::set(newObject);
mOffset = 0;
mSize = 0;
}
void set(ObjectType *newObject, GLintptr offset, GLsizeiptr size)
{
RefCountObjectBindingPointer::set(newObject);
mOffset = offset;
mSize = size;
}
GLintptr getOffset() const { return mOffset; }
GLsizeiptr getSize() const { return mSize; }
ObjectType *get() const { return static_cast<ObjectType*>(RefCountObjectBindingPointer::get()); }
ObjectType *operator->() const { return get(); }
private:
GLintptr mOffset;
GLsizeiptr mSize;
};
#endif // COMMON_REFCOUNTOBJECT_H_

View File

@ -5,7 +5,8 @@
//
#include "common/angleutils.h"
#include "debug.h"
#include "common/debug.h"
#include <stdio.h>
#include <vector>

View File

@ -11,19 +11,31 @@
#include "common/platform.h"
#include <stddef.h>
#include <limits.h>
#include <climits>
#include <cstdarg>
#include <cstddef>
#include <string>
#include <set>
#include <sstream>
#include <cstdarg>
#include <vector>
// 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) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
// A helper class to disallow copy and assignment operators
namespace angle
{
class NonCopyable
{
#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
public:
NonCopyable() = default;
~NonCopyable() = default;
protected:
NonCopyable(const NonCopyable&) = delete;
void operator=(const NonCopyable&) = delete;
#endif
};
}
template <typename T, size_t N>
inline size_t ArraySize(T(&)[N])
@ -150,13 +162,12 @@ std::string FormatString(const char *fmt, ...);
#define snprintf _snprintf
#endif
#define VENDOR_ID_AMD 0x1002
#define VENDOR_ID_INTEL 0x8086
#define VENDOR_ID_NVIDIA 0x10DE
#define GL_BGRA4_ANGLEX 0x6ABC
#define GL_BGR5_A1_ANGLEX 0x6ABD
#define GL_INT_64_ANGLEX 0x6ABE
#define GL_STRUCT_ANGLEX 0x6ABF
// Hidden enum for the NULL D3D device type.
#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE 0x6AC0
#endif // COMMON_ANGLEUTILS_H_

View File

@ -17,172 +17,9 @@
namespace gl
{
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
// Wraps the D3D9/D3D11 debug annotation functions.
class DebugAnnotationWrapper
namespace
{
public:
DebugAnnotationWrapper() { };
virtual ~DebugAnnotationWrapper() { };
virtual void beginEvent(const std::wstring &eventName) = 0;
virtual void endEvent() = 0;
virtual void setMarker(const std::wstring &markerName) = 0;
virtual bool getStatus() = 0;
};
#if defined(ANGLE_ENABLE_D3D9)
class D3D9DebugAnnotationWrapper : public DebugAnnotationWrapper
{
public:
void beginEvent(const std::wstring &eventName)
{
D3DPERF_BeginEvent(0, eventName.c_str());
}
void endEvent()
{
D3DPERF_EndEvent();
}
void setMarker(const std::wstring &markerName)
{
D3DPERF_SetMarker(0, markerName.c_str());
}
bool getStatus()
{
return !!D3DPERF_GetStatus();
}
};
#endif // ANGLE_ENABLE_D3D9
#if defined(ANGLE_ENABLE_D3D11)
class D3D11DebugAnnotationWrapper : public DebugAnnotationWrapper
{
public:
D3D11DebugAnnotationWrapper()
: mInitialized(false),
mD3d11Module(NULL),
mUserDefinedAnnotation(NULL)
{
// D3D11 devices can't be created during DllMain.
// We defer device creation until the object is actually used.
}
~D3D11DebugAnnotationWrapper()
{
if (mInitialized)
{
SafeRelease(mUserDefinedAnnotation);
FreeLibrary(mD3d11Module);
}
}
virtual void beginEvent(const std::wstring &eventName)
{
initializeDevice();
mUserDefinedAnnotation->BeginEvent(eventName.c_str());
}
virtual void endEvent()
{
initializeDevice();
mUserDefinedAnnotation->EndEvent();
}
virtual void setMarker(const std::wstring &markerName)
{
initializeDevice();
mUserDefinedAnnotation->SetMarker(markerName.c_str());
}
virtual bool getStatus()
{
// ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in Visual Studio 2013.
#if defined(_DEBUG) && defined(ANGLE_ENABLE_WINDOWS_STORE)
// In the Windows Store, we can use IDXGraphicsAnalysis. The call to GetDebugInterface1 only succeeds if the app is under capture.
// This should only be called in DEBUG mode.
// If an app links against DXGIGetDebugInterface1 in release mode then it will fail Windows Store ingestion checks.
IDXGraphicsAnalysis* graphicsAnalysis;
DXGIGetDebugInterface1(0, IID_PPV_ARGS(&graphicsAnalysis));
bool underCapture = (graphicsAnalysis != NULL);
SafeRelease(graphicsAnalysis);
return underCapture;
#endif
// Otherwise, we have to return true here.
return true;
}
protected:
void initializeDevice()
{
if (!mInitialized)
{
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
ASSERT(mD3d11Module);
PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
ASSERT(D3D11CreateDevice != NULL);
#endif // !ANGLE_ENABLE_WINDOWS_STORE
ID3D11Device* device = NULL;
ID3D11DeviceContext* context = NULL;
HRESULT hr = E_FAIL;
// Create a D3D_DRIVER_TYPE_NULL device, which is much cheaper than other types of device.
hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &device, NULL, &context);
ASSERT(SUCCEEDED(hr));
hr = context->QueryInterface(__uuidof(mUserDefinedAnnotation), reinterpret_cast<void**>(&mUserDefinedAnnotation));
ASSERT(SUCCEEDED(hr) && mUserDefinedAnnotation != NULL);
SafeRelease(device);
SafeRelease(context);
mInitialized = true;
}
}
bool mInitialized;
HMODULE mD3d11Module;
ID3DUserDefinedAnnotation* mUserDefinedAnnotation;
};
#endif // ANGLE_ENABLE_D3D11
static DebugAnnotationWrapper* g_DebugAnnotationWrapper = NULL;
void InitializeDebugAnnotations()
{
#if defined(ANGLE_ENABLE_D3D9)
g_DebugAnnotationWrapper = new D3D9DebugAnnotationWrapper();
#elif defined(ANGLE_ENABLE_D3D11)
// If the project uses D3D9 then we can use the D3D9 debug annotations, even with the D3D11 renderer.
// However, if D3D9 is unavailable (e.g. in Windows Store), then we use D3D11 debug annotations.
// The D3D11 debug annotations are methods on ID3DUserDefinedAnnotation, which is implemented by the DeviceContext.
// This doesn't have to be the same DeviceContext that the renderer uses, though.
g_DebugAnnotationWrapper = new D3D11DebugAnnotationWrapper();
#endif
}
void UninitializeDebugAnnotations()
{
if (g_DebugAnnotationWrapper != NULL)
{
SafeDelete(g_DebugAnnotationWrapper);
}
}
#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
enum DebugTraceOutputType
{
DebugTraceOutputTypeNone,
@ -190,29 +27,44 @@ enum DebugTraceOutputType
DebugTraceOutputTypeBeginEvent
};
static void output(bool traceInDebugOnly, DebugTraceOutputType outputType, const char *format, va_list vararg)
{
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
static std::vector<char> buffer(512);
DebugAnnotator *g_debugAnnotator = nullptr;
if (perfActive())
void output(bool traceInDebugOnly, MessageType messageType, DebugTraceOutputType outputType,
const char *format, va_list vararg)
{
if (DebugAnnotationsActive())
{
static std::vector<char> buffer(512);
size_t len = FormatStringIntoVector(format, vararg, buffer);
std::wstring formattedWideMessage(buffer.begin(), buffer.begin() + len);
ASSERT(g_debugAnnotator != nullptr);
switch (outputType)
{
case DebugTraceOutputTypeNone:
break;
case DebugTraceOutputTypeBeginEvent:
g_DebugAnnotationWrapper->beginEvent(formattedWideMessage);
break;
case DebugTraceOutputTypeSetMarker:
g_DebugAnnotationWrapper->setMarker(formattedWideMessage);
break;
case DebugTraceOutputTypeNone:
break;
case DebugTraceOutputTypeBeginEvent:
g_debugAnnotator->beginEvent(formattedWideMessage);
break;
case DebugTraceOutputTypeSetMarker:
g_debugAnnotator->setMarker(formattedWideMessage);
break;
}
}
#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
std::string formattedMessage;
UNUSED_TRACE_VARIABLE(formattedMessage);
#if !defined(NDEBUG) && defined(_MSC_VER)
if (messageType == MESSAGE_ERR)
{
if (formattedMessage.empty())
{
formattedMessage = FormatString(format, vararg);
}
OutputDebugStringA(formattedMessage.c_str());
}
#endif
#if defined(ANGLE_ENABLE_DEBUG_TRACE)
#if defined(NDEBUG)
@ -221,7 +73,10 @@ static void output(bool traceInDebugOnly, DebugTraceOutputType outputType, const
return;
}
#endif // NDEBUG
std::string formattedMessage = FormatString(format, vararg);
if (formattedMessage.empty())
{
formattedMessage = FormatString(format, vararg);
}
static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app);
if (file)
@ -237,53 +92,57 @@ static void output(bool traceInDebugOnly, DebugTraceOutputType outputType, const
#endif // ANGLE_ENABLE_DEBUG_TRACE
}
void trace(bool traceInDebugOnly, const char *format, ...)
{
va_list vararg;
va_start(vararg, format);
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
output(traceInDebugOnly, DebugTraceOutputTypeSetMarker, format, vararg);
#else
output(traceInDebugOnly, DebugTraceOutputTypeNone, format, vararg);
#endif
va_end(vararg);
}
} // namespace
bool perfActive()
bool DebugAnnotationsActive()
{
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
static bool active = g_DebugAnnotationWrapper->getStatus();
return active;
return g_debugAnnotator != nullptr && g_debugAnnotator->getStatus();
#else
return false;
#endif
}
void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator)
{
UninitializeDebugAnnotations();
g_debugAnnotator = debugAnnotator;
}
void UninitializeDebugAnnotations()
{
// Pointer is not managed.
g_debugAnnotator = nullptr;
}
void trace(bool traceInDebugOnly, MessageType messageType, const char *format, ...)
{
va_list vararg;
va_start(vararg, format);
output(traceInDebugOnly, messageType, DebugTraceOutputTypeSetMarker, format, vararg);
va_end(vararg);
}
ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...)
{
#if !defined(ANGLE_ENABLE_DEBUG_TRACE)
if (!perfActive())
if (!DebugAnnotationsActive())
{
return;
}
#endif // !ANGLE_ENABLE_DEBUG_TRACE
va_list vararg;
va_start(vararg, format);
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
output(true, DebugTraceOutputTypeBeginEvent, format, vararg);
#else
output(true, DebugTraceOutputTypeNone, format, vararg);
#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
output(true, MESSAGE_EVENT, DebugTraceOutputTypeBeginEvent, format, vararg);
va_end(vararg);
}
ScopedPerfEventHelper::~ScopedPerfEventHelper()
{
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
if (perfActive())
if (DebugAnnotationsActive())
{
g_DebugAnnotationWrapper->endEvent();
g_debugAnnotator->endEvent();
}
#endif
}
}

View File

@ -9,8 +9,9 @@
#ifndef COMMON_DEBUG_H_
#define COMMON_DEBUG_H_
#include <stdio.h>
#include <assert.h>
#include <stdio.h>
#include <string>
#include "common/angleutils.h"
@ -20,50 +21,71 @@
namespace gl
{
// Outputs text to the debugging log, or the debugging window
void trace(bool traceInDebugOnly, const char *format, ...);
// Returns whether D3DPERF is active.
bool perfActive();
enum MessageType
{
MESSAGE_TRACE,
MESSAGE_FIXME,
MESSAGE_ERR,
MESSAGE_EVENT,
};
// Pairs a D3D begin event with an end event.
class ScopedPerfEventHelper
{
public:
ScopedPerfEventHelper(const char* format, ...);
~ScopedPerfEventHelper();
// Outputs text to the debugging log, or the debugging window
void trace(bool traceInDebugOnly, MessageType messageType, const char *format, ...);
private:
DISALLOW_COPY_AND_ASSIGN(ScopedPerfEventHelper);
};
// Pairs a D3D begin event with an end event.
class ScopedPerfEventHelper : angle::NonCopyable
{
public:
ScopedPerfEventHelper(const char* format, ...);
~ScopedPerfEventHelper();
};
// Wraps the D3D9/D3D11 debug annotation functions.
class DebugAnnotator : angle::NonCopyable
{
public:
DebugAnnotator() { };
virtual ~DebugAnnotator() { };
virtual void beginEvent(const std::wstring &eventName) = 0;
virtual void endEvent() = 0;
virtual void setMarker(const std::wstring &markerName) = 0;
virtual bool getStatus() = 0;
};
void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator);
void UninitializeDebugAnnotations();
bool DebugAnnotationsActive();
void InitializeDebugAnnotations();
void UninitializeDebugAnnotations();
}
// A macro to output a trace of a function call and its arguments to the debugging log
#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
#define TRACE(message, ...) gl::trace(true, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define ANGLE_TRACE_ENABLED
#endif
// A macro to output a trace of a function call and its arguments to the debugging log
#if defined(ANGLE_TRACE_ENABLED)
#define TRACE(message, ...) gl::trace(true, gl::MESSAGE_TRACE, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define TRACE(message, ...) (void(0))
#endif
// A macro to output a function call and its arguments to the debugging log, to denote an item in need of fixing.
#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
#define FIXME(message, ...) gl::trace(false, "fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#if defined(ANGLE_TRACE_ENABLED)
#define FIXME(message, ...) gl::trace(false, gl::MESSAGE_FIXME, "fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define FIXME(message, ...) (void(0))
#endif
// A macro to output a function call and its arguments to the debugging log, in case of error.
#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
#define ERR(message, ...) gl::trace(false, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#if defined(ANGLE_TRACE_ENABLED)
#define ERR(message, ...) gl::trace(false, gl::MESSAGE_ERR, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define ERR(message, ...) (void(0))
#endif
// A macro to log a performance event around a scope.
#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
#if defined(ANGLE_TRACE_ENABLED)
#if defined(_MSC_VER)
#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__("%s" message "\n", __FUNCTION__, __VA_ARGS__);
#else
@ -73,6 +95,10 @@ namespace gl
#define EVENT(message, ...) (void(0))
#endif
#if defined(ANGLE_TRACE_ENABLED)
#undef ANGLE_TRACE_ENABLED
#endif
// A macro asserting a condition and outputting failures to the debug log
#if !defined(NDEBUG)
#define ASSERT(expression) do { \
@ -130,14 +156,4 @@ namespace gl
#define HAS_DYNAMIC_TYPE(type, obj) true
#endif
// A macro functioning as a compile-time assert to validate constant conditions
#if (defined(_MSC_VER) && _MSC_VER >= 1600) || (defined(__GNUC__) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3))
#define META_ASSERT_MSG(condition, msg) static_assert(condition, msg)
#else
#define META_ASSERT_CONCAT(a, b) a ## b
#define META_ASSERT_CONCAT2(a, b) META_ASSERT_CONCAT(a, b)
#define META_ASSERT_MSG(condition, msg) typedef int META_ASSERT_CONCAT2(COMPILE_TIME_ASSERT_, __LINE__)[static_cast<bool>(condition)?1:-1]
#endif
#define META_ASSERT(condition) META_ASSERT_MSG(condition, "compile time assertion failed.")
#endif // COMMON_DEBUG_H_

View File

@ -0,0 +1,38 @@
// 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
namespace gl
{
const unsigned char* TraceGetTraceCategoryEnabledFlag(const char* name)
{
if (g_getCategoryEnabledFlag)
{
return g_getCategoryEnabledFlag(name);
}
static unsigned char disabled = 0;
return &disabled;
}
void TraceAddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id,
int numArgs, const char** argNames, const unsigned char* argTypes,
const unsigned long long* argValues, unsigned char flags)
{
if (g_addTraceEvent)
{
g_addTraceEvent(phase, categoryGroupEnabled, name, id, numArgs, argNames, argTypes, argValues, flags);
}
}
} // namespace gl

View File

@ -0,0 +1,34 @@
// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMMON_EVENT_TRACER_H_
#define COMMON_EVENT_TRACER_H_
#include "common/platform.h"
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);
}
namespace gl
{
extern GetCategoryEnabledFlagFunc g_getCategoryEnabledFlag;
extern AddTraceEventFunc g_addTraceEvent;
const unsigned char* TraceGetTraceCategoryEnabledFlag(const char* name);
void TraceAddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id,
int numArgs, const char** argNames, const unsigned char* argTypes,
const unsigned long long* argValues, unsigned char flags);
}
#endif // COMMON_EVENT_TRACER_H_

View File

@ -6,8 +6,8 @@
// mathutil.h: Math and bit manipulation functions.
#ifndef LIBGLESV2_MATHUTIL_H_
#define LIBGLESV2_MATHUTIL_H_
#ifndef COMMON_MATHUTIL_H_
#define COMMON_MATHUTIL_H_
#include "common/debug.h"
#include "common/platform.h"
@ -15,6 +15,7 @@
#include <limits>
#include <algorithm>
#include <string.h>
#include <stdlib.h>
namespace gl
{
@ -118,6 +119,9 @@ inline bool supportsSSE2()
return supports;
}
#if defined(__GNUC__)
supports = __builtin_cpu_supports("sse2");
#else
int info[4];
__cpuid(info, 0);
@ -127,6 +131,7 @@ inline bool supportsSSE2()
supports = (info[3] >> 26) & 1;
}
#endif
checked = true;
@ -353,7 +358,7 @@ inline float float11ToFloat32(unsigned short fp11)
}
else // The value is zero
{
exponent = -112;
exponent = static_cast<unsigned short>(-112);
}
return bitCast<float>(((exponent + 112) << 23) | (mantissa << 17));
@ -392,7 +397,7 @@ inline float float10ToFloat32(unsigned short fp11)
}
else // The value is zero
{
exponent = -112;
exponent = static_cast<unsigned short>(-112);
}
return bitCast<float>(((exponent + 112) << 23) | (mantissa << 18));
@ -402,7 +407,7 @@ inline float float10ToFloat32(unsigned short fp11)
template <typename T>
inline float normalizedToFloat(T input)
{
META_ASSERT(std::numeric_limits<T>::is_integer);
static_assert(std::numeric_limits<T>::is_integer, "T must be an integer.");
const float inverseMax = 1.0f / std::numeric_limits<T>::max();
return input * inverseMax;
@ -411,8 +416,8 @@ inline float normalizedToFloat(T input)
template <unsigned int inputBitCount, typename T>
inline float normalizedToFloat(T input)
{
META_ASSERT(std::numeric_limits<T>::is_integer);
META_ASSERT(inputBitCount < (sizeof(T) * 8));
static_assert(std::numeric_limits<T>::is_integer, "T must be an integer.");
static_assert(inputBitCount < (sizeof(T) * 8), "T must have more bits than inputBitCount.");
const float inverseMax = 1.0f / ((1 << inputBitCount) - 1);
return input * inverseMax;
@ -427,14 +432,15 @@ inline T floatToNormalized(float input)
template <unsigned int outputBitCount, typename T>
inline T floatToNormalized(float input)
{
META_ASSERT(outputBitCount < (sizeof(T) * 8));
static_assert(outputBitCount < (sizeof(T) * 8), "T must have more bits than outputBitCount.");
return ((1 << outputBitCount) - 1) * input + 0.5f;
}
template <unsigned int inputBitCount, unsigned int inputBitStart, typename T>
inline T getShiftedData(T input)
{
META_ASSERT(inputBitCount + inputBitStart <= (sizeof(T) * 8));
static_assert(inputBitCount + inputBitStart <= (sizeof(T) * 8),
"T must have at least as many bits as inputBitCount + inputBitStart.");
const T mask = (1 << inputBitCount) - 1;
return (input >> inputBitStart) & mask;
}
@ -442,7 +448,8 @@ inline T getShiftedData(T input)
template <unsigned int inputBitCount, unsigned int inputBitStart, typename T>
inline T shiftData(T input)
{
META_ASSERT(inputBitCount + inputBitStart <= (sizeof(T) * 8));
static_assert(inputBitCount + inputBitStart <= (sizeof(T) * 8),
"T must have at least as many bits as inputBitCount + inputBitStart.");
const T mask = (1 << inputBitCount) - 1;
return (input & mask) << inputBitStart;
}
@ -503,6 +510,7 @@ inline unsigned int averageFloat10(unsigned int a, unsigned int b)
namespace rx
{
// Represents intervals of the type [a, b)
template <typename T>
struct Range
{
@ -513,6 +521,18 @@ struct Range
T end;
T length() const { return end - start; }
bool intersects(Range<T> other)
{
if (start <= other.start)
{
return other.start < end;
}
else
{
return start < other.end;
}
}
};
typedef Range<int> RangeI;
@ -533,14 +553,14 @@ inline unsigned int UnsignedCeilDivide(unsigned int value, unsigned int divisor)
template <class T>
inline bool IsUnsignedAdditionSafe(T lhs, T rhs)
{
META_ASSERT(!std::numeric_limits<T>::is_signed);
static_assert(!std::numeric_limits<T>::is_signed, "T must be unsigned.");
return (rhs <= std::numeric_limits<T>::max() - lhs);
}
template <class T>
inline bool IsUnsignedMultiplicationSafe(T lhs, T rhs)
{
META_ASSERT(!std::numeric_limits<T>::is_signed);
static_assert(!std::numeric_limits<T>::is_signed, "T must be unsigned.");
return (lhs == T(0) || rhs == T(0) || (rhs <= std::numeric_limits<T>::max() / lhs));
}
@ -550,6 +570,21 @@ inline bool IsIntegerCastSafe(BigIntT bigValue)
return (static_cast<BigIntT>(static_cast<SmallIntT>(bigValue)) == bigValue);
}
#if defined(_MSC_VER)
#define ANGLE_ROTL(x,y) _rotl(x,y)
#else
inline uint32_t RotL(uint32_t x, int8_t r)
{
return (x << r) | (x >> (32 - r));
}
#endif // LIBGLESV2_MATHUTIL_H_
#define ANGLE_ROTL(x,y) RotL(x,y)
#endif // namespace rx
}
#endif // COMMON_MATHUTIL_H_

View File

@ -14,12 +14,12 @@
#elif defined(__APPLE__)
# define ANGLE_PLATFORM_APPLE 1
# define ANGLE_PLATFORM_POSIX 1
#elif defined(__linux__)
# define ANGLE_PLATFORM_LINUX 1
# define ANGLE_PLATFORM_POSIX 1
#elif defined(ANDROID)
# define ANGLE_PLATFORM_ANDROID 1
# define ANGLE_PLATFORM_POSIX 1
#elif defined(__linux__) || defined(EMSCRIPTEN)
# define ANGLE_PLATFORM_LINUX 1
# define ANGLE_PLATFORM_POSIX 1
#elif defined(__FreeBSD__) || \
defined(__OpenBSD__) || \
defined(__NetBSD__) || \
@ -34,9 +34,6 @@
#endif
#ifdef ANGLE_PLATFORM_WINDOWS
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
# define ANGLE_ENABLE_WINDOWS_STORE 1
# endif
# ifndef STRICT
# define STRICT 1
# endif
@ -50,24 +47,32 @@
# include <windows.h>
# include <intrin.h>
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
# define ANGLE_ENABLE_WINDOWS_STORE 1
# endif
# if defined(ANGLE_ENABLE_D3D9)
# include <d3d9.h>
# include <dxgi.h>
# if !defined(COMPILER_IMPLEMENTATION)
# if !defined(ANGLE_TRANSLATOR_IMPLEMENTATION)
# include <d3dcompiler.h>
# endif
# endif
# if defined(ANGLE_ENABLE_D3D11)
# include <d3d10_1.h>
# include <d3d10.h>
# include <d3d11.h>
# include <dxgi.h>
# if defined(_MSC_VER) && (_MSC_VER >= 1700)
# if defined(__MINGW32__) && !defined(__d3d11sdklayers_h__)
# define ANGLE_MINGW32_COMPAT
# endif
# if defined(_MSC_VER) && _MSC_VER >= 1800
# define ANGLE_ENABLE_D3D11_1
# endif
# if defined(ANGLE_ENABLE_D3D11_1)
# include <d3d11_1.h>
# include <dxgi1_2.h>
# endif
# if !defined(COMPILER_IMPLEMENTATION)
# if !defined(ANGLE_TRANSLATOR_IMPLEMENTATION)
# include <d3dcompiler.h>
# endif
# endif
@ -75,88 +80,24 @@
# if defined(ANGLE_ENABLE_WINDOWS_STORE)
# include <dxgi1_3.h>
# if defined(_DEBUG)
# if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
# if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
# include <DXProgrammableCapture.h>
# endif
# include <dxgidebug.h>
# endif
# endif
# if defined(__MINGW32__) // Missing defines on MinGW
typedef enum D3D11_MAP_FLAG
{
D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000L
} D3D11_MAP_FLAG;
typedef struct D3D11_QUERY_DATA_SO_STATISTICS
{
UINT64 NumPrimitivesWritten;
UINT64 PrimitivesStorageNeeded;
} D3D11_QUERY_DATA_SO_STATISTICS;
typedef HRESULT (WINAPI *PFN_D3D11_CREATE_DEVICE)(
IDXGIAdapter *, D3D_DRIVER_TYPE, HMODULE, UINT, CONST D3D_FEATURE_LEVEL *,
UINT FeatureLevels, UINT, ID3D11Device **, D3D_FEATURE_LEVEL *, ID3D11DeviceContext **);
#define D3D11_MESSAGE_CATEGORY UINT
#define D3D11_MESSAGE_SEVERITY UINT
#define D3D11_MESSAGE_ID UINT
struct D3D11_MESSAGE;
typedef struct D3D11_INFO_QUEUE_FILTER_DESC
{
UINT NumCategories;
D3D11_MESSAGE_CATEGORY *pCategoryList;
UINT NumSeverities;
D3D11_MESSAGE_SEVERITY *pSeverityList;
UINT NumIDs;
D3D11_MESSAGE_ID *pIDList;
} D3D11_INFO_QUEUE_FILTER_DESC;
typedef struct D3D11_INFO_QUEUE_FILTER
{
D3D11_INFO_QUEUE_FILTER_DESC AllowList;
D3D11_INFO_QUEUE_FILTER_DESC DenyList;
} D3D11_INFO_QUEUE_FILTER;
static const IID IID_ID3D11InfoQueue = { 0x6543dbb6, 0x1b48, 0x42f5, 0xab, 0x82, 0xe9, 0x7e, 0xc7, 0x43, 0x26, 0xf6 };
MIDL_INTERFACE("6543dbb6-1b48-42f5-ab82-e97ec74326f6") ID3D11InfoQueue : public IUnknown
{
public:
virtual HRESULT __stdcall SetMessageCountLimit(UINT64) = 0;
virtual void __stdcall ClearStoredMessages() = 0;
virtual HRESULT __stdcall GetMessage(UINT64, D3D11_MESSAGE *, SIZE_T *) = 0;
virtual UINT64 __stdcall GetNumMessagesAllowedByStorageFilter() = 0;
virtual UINT64 __stdcall GetNumMessagesDeniedByStorageFilter() = 0;
virtual UINT64 __stdcall GetNumStoredMessages() = 0;
virtual UINT64 __stdcall GetNumStoredMessagesAllowedByRetrievalFilter() = 0;
virtual UINT64 __stdcall GetNumMessagesDiscardedByMessageCountLimit() = 0;
virtual UINT64 __stdcall GetMessageCountLimit() = 0;
virtual HRESULT __stdcall AddStorageFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0;
virtual HRESULT __stdcall GetStorageFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0;
virtual void __stdcall ClearStorageFilter() = 0;
virtual HRESULT __stdcall PushEmptyStorageFilter() = 0;
virtual HRESULT __stdcall PushCopyOfStorageFilter() = 0;
virtual HRESULT __stdcall PushStorageFilter(D3D11_INFO_QUEUE_FILTER *) = 0;
virtual void __stdcall PopStorageFilter() = 0;
virtual UINT __stdcall GetStorageFilterStackSize() = 0;
virtual HRESULT __stdcall AddRetrievalFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0;
virtual HRESULT __stdcall GetRetrievalFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0;
virtual void __stdcall ClearRetrievalFilter() = 0;
virtual HRESULT __stdcall PushEmptyRetrievalFilter() = 0;
virtual HRESULT __stdcall PushCopyOfRetrievalFilter() = 0;
virtual HRESULT __stdcall PushRetrievalFilter(D3D11_INFO_QUEUE_FILTER *) = 0;
virtual void __stdcall PopRetrievalFilter() = 0;
virtual UINT __stdcall GetRetrievalFilterStackSize() = 0;
virtual HRESULT __stdcall AddMessage(D3D11_MESSAGE_CATEGORY, D3D11_MESSAGE_SEVERITY, D3D11_MESSAGE_ID, LPCSTR) = 0;
virtual HRESULT __stdcall AddApplicationMessage(D3D11_MESSAGE_SEVERITY, LPCSTR) = 0;
virtual HRESULT __stdcall SetBreakOnCategory(D3D11_MESSAGE_CATEGORY, BOOL) = 0;
virtual HRESULT __stdcall SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY, BOOL) = 0;
virtual HRESULT __stdcall SetBreakOnID(D3D11_MESSAGE_ID, BOOL) = 0;
virtual BOOL __stdcall GetBreakOnCategory(D3D11_MESSAGE_CATEGORY) = 0;
virtual BOOL __stdcall GetBreakOnSeverity(D3D11_MESSAGE_SEVERITY) = 0;
virtual BOOL __stdcall GetBreakOnID(D3D11_MESSAGE_ID) = 0;
virtual void __stdcall SetMuteDebugOutput(BOOL) = 0;
virtual BOOL __stdcall GetMuteDebugOutput() = 0;
};
#endif // __MINGW32__
# if defined(_MSC_VER) && (_MSC_VER <= 1600)
# define final
# define override
# endif
# undef near
# undef far
#endif
#if !defined(_M_ARM) && !defined(ANGLE_PLATFORM_ANDROID)
# define ANGLE_USE_SSE
#endif
#endif // COMMON_PLATFORM_H_

View File

@ -15,7 +15,9 @@
// TLS does not exist for Windows Store and needs to be emulated
# ifdef ANGLE_ENABLE_WINDOWS_STORE
# define TLS_OUT_OF_INDEXES -1
# ifndef TLS_OUT_OF_INDEXES
# define TLS_OUT_OF_INDEXES static_cast<DWORD>(0xFFFFFFFF)
# endif
# ifndef CREATE_SUSPENDED
# define CREATE_SUSPENDED 0x00000004
# endif

View File

@ -254,7 +254,7 @@ int VariableColumnCount(GLenum type)
return 0;
}
bool IsSampler(GLenum type)
bool IsSamplerType(GLenum type)
{
switch (type)
{
@ -343,9 +343,27 @@ int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsig
return -1;
}
bool IsCubemapTextureTarget(GLenum target)
static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1, "Unexpected GL cube map enum value.");
static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2, "Unexpected GL cube map enum value.");
static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3, "Unexpected GL cube map enum value.");
static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4, "Unexpected GL cube map enum value.");
static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5, "Unexpected GL cube map enum value.");
bool IsCubeMapTextureTarget(GLenum target)
{
return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
return (target >= FirstCubeMapTextureTarget && target <= LastCubeMapTextureTarget);
}
size_t CubeMapTextureTargetToLayerIndex(GLenum target)
{
ASSERT(IsCubeMapTextureTarget(target));
return target - static_cast<size_t>(FirstCubeMapTextureTarget);
}
GLenum LayerIndexToCubeMapTextureTarget(size_t index)
{
ASSERT(index <= (LastCubeMapTextureTarget - FirstCubeMapTextureTarget));
return FirstCubeMapTextureTarget + static_cast<GLenum>(index);
}
bool IsTriangleMode(GLenum drawMode)
@ -486,10 +504,15 @@ void writeFile(const char* path, const void* content, size_t size)
}
#endif // !ANGLE_ENABLE_WINDOWS_STORE
#if defined(ANGLE_ENABLE_WINDOWS_STORE) && _MSC_FULL_VER < 180031101
#if defined (ANGLE_PLATFORM_WINDOWS)
void Sleep(unsigned long dwMilliseconds)
// Causes the thread to relinquish the remainder of its time slice to any
// other thread that is ready to run.If there are no other threads ready
// to run, the function returns immediately, and the thread continues execution.
void ScheduleYield()
{
#if defined(ANGLE_ENABLE_WINDOWS_STORE)
// This implementation of Sleep exists because it is not available prior to Update 4.
static HANDLE singletonEvent = nullptr;
HANDLE sleepEvent = singletonEvent;
if (!sleepEvent)
@ -510,7 +533,10 @@ void Sleep(unsigned long dwMilliseconds)
}
// Emulate sleep by waiting with timeout on an event that is never signalled.
WaitForSingleObjectEx(sleepEvent, dwMilliseconds, false);
WaitForSingleObjectEx(sleepEvent, 0, false);
#else
Sleep(0);
#endif
}
#endif // ANGLE_ENABLE_WINDOWS_STORE
#endif

View File

@ -6,8 +6,8 @@
// utilities.h: Conversion functions and other utility routines.
#ifndef LIBGLESV2_UTILITIES_H
#define LIBGLESV2_UTILITIES_H
#ifndef COMMON_UTILITIES_H_
#define COMMON_UTILITIES_H_
#include "angle_gl.h"
#include <string>
@ -24,7 +24,7 @@ size_t VariableExternalSize(GLenum type);
GLenum VariableBoolVectorType(GLenum type);
int VariableRowCount(GLenum type);
int VariableColumnCount(GLenum type);
bool IsSampler(GLenum type);
bool IsSamplerType(GLenum type);
bool IsMatrixType(GLenum type);
GLenum TransposeMatrixType(GLenum type);
int VariableRegisterCount(GLenum type);
@ -34,7 +34,11 @@ int VariableSortOrder(GLenum type);
int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize);
bool IsCubemapTextureTarget(GLenum target);
static const GLenum FirstCubeMapTextureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
static const GLenum LastCubeMapTextureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
bool IsCubeMapTextureTarget(GLenum target);
size_t CubeMapTextureTargetToLayerIndex(GLenum target);
GLenum LayerIndexToCubeMapTextureTarget(size_t index);
bool IsTriangleMode(GLenum drawMode);
@ -51,8 +55,8 @@ std::string getTempPath();
void writeFile(const char* path, const void* data, size_t size);
#endif
#if defined(ANGLE_ENABLE_WINDOWS_STORE) && _MSC_FULL_VER < 180031101
void Sleep(_In_ unsigned long dwMilliseconds);
#if defined (ANGLE_PLATFORM_WINDOWS)
void ScheduleYield();
#endif
#endif // LIBGLESV2_UTILITIES_H
#endif // COMMON_UTILITIES_H_

View File

@ -1,4 +1,13 @@
#include "../commit.h"
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#ifndef COMMON_VERSION_H_
#define COMMON_VERSION_H_
#include "id/commit.h"
#define ANGLE_MAJOR_VERSION 2
#define ANGLE_MINOR_VERSION 1
@ -10,3 +19,5 @@
ANGLE_MACRO_STRINGIFY(ANGLE_MAJOR_VERSION) "." \
ANGLE_MACRO_STRINGIFY(ANGLE_MINOR_VERSION) "." \
ANGLE_COMMIT_HASH
#endif // COMMON_VERSION_H_

View File

@ -1,39 +0,0 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CoreWindowNativeWindow.h: NativeWindow for managing ICoreWindow native window types.
#ifndef COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_
#define COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_
#include "common/winrt/InspectableNativeWindow.h"
#include <memory>
#include <windows.graphics.display.h>
namespace rx
{
class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<CoreWindowNativeWindow>
{
public:
~CoreWindowNativeWindow();
bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet);
bool registerForSizeChangeEvents();
void unregisterForSizeChangeEvents();
HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain);
private:
HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *);
ComPtr<ABI::Windows::UI::Core::ICoreWindow> mCoreWindow;
ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation> mDisplayInformation;
ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap;
};
}
#endif // COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILER_PREPROCESSOR_DIAGNOSTICS_H_
#define COMPILER_PREPROCESSOR_DIAGNOSTICS_H_
#ifndef COMPILER_PREPROCESSOR_DIAGNOSTICSBASE_H_
#define COMPILER_PREPROCESSOR_DIAGNOSTICSBASE_H_
#include <string>
@ -84,4 +84,5 @@ class Diagnostics
};
} // namespace pp
#endif // COMPILER_PREPROCESSOR_DIAGNOSTICS_H_
#endif // COMPILER_PREPROCESSOR_DIAGNOSTICSBASE_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_
#define COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_
#ifndef COMPILER_PREPROCESSOR_DIRECTIVEHANDLERBASE_H_
#define COMPILER_PREPROCESSOR_DIRECTIVEHANDLERBASE_H_
#include <string>
@ -41,4 +41,5 @@ class DirectiveHandler
};
} // namespace pp
#endif // COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_
#endif // COMPILER_PREPROCESSOR_DIRECTIVEHANDLERBASE_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_
#define COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_
#ifndef COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_
#define COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_
#include "Lexer.h"
#include "Macro.h"
@ -78,5 +78,5 @@ class DirectiveParser : public Lexer
};
} // namespace pp
#endif // COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_
#endif // COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_
#define COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_
#ifndef COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_
#define COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_
#include "pp_utils.h"
@ -31,4 +31,5 @@ class ExpressionParser
};
} // namespace pp
#endif // COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_
#endif // COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_

View File

@ -28,7 +28,7 @@ WHICH GENERATES THE GLSL ES preprocessor expression parser.
#pragma GCC diagnostic ignored "-Wuninitialized"
#endif
#elif defined(_MSC_VER)
#pragma warning(disable: 4065 4701)
#pragma warning(disable: 4065 4701 4702)
#endif
#include "ExpressionParser.h"
@ -69,7 +69,7 @@ struct Context
%}
%pure-parser
%name-prefix="pp"
%name-prefix "pp"
%parse-param {Context *context}
%lex-param {Context *context}

View File

@ -58,5 +58,5 @@ class Input
};
} // namespace pp
#endif // COMPILER_PREPROCESSOR_INPUT_H_
#endif // COMPILER_PREPROCESSOR_INPUT_H_

View File

@ -21,5 +21,5 @@ class Lexer
};
} // namespace pp
#endif // COMPILER_PREPROCESSOR_LEXER_H_
#endif // COMPILER_PREPROCESSOR_LEXER_H_

View File

@ -46,4 +46,5 @@ struct Macro
typedef std::map<std::string, Macro> MacroSet;
} // namespace pp
#endif // COMPILER_PREPROCESSOR_MACRO_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_
#define COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_
#ifndef COMPILER_PREPROCESSOR_MACROEXPANDER_H_
#define COMPILER_PREPROCESSOR_MACROEXPANDER_H_
#include <cassert>
#include <memory>
@ -85,5 +85,5 @@ class MacroExpander : public Lexer
};
} // namespace pp
#endif // COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_
#endif // COMPILER_PREPROCESSOR_MACROEXPANDER_H_

View File

@ -50,5 +50,5 @@ class Preprocessor
};
} // namespace pp
#endif // COMPILER_PREPROCESSOR_PREPROCESSOR_H_
#endif // COMPILER_PREPROCESSOR_PREPROCESSOR_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_
#define COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_
#ifndef COMPILER_PREPROCESSOR_SOURCELOCATION_H_
#define COMPILER_PREPROCESSOR_SOURCELOCATION_H_
namespace pp
{
@ -43,4 +43,5 @@ inline bool operator!=(const SourceLocation &lhs, const SourceLocation &rhs)
}
} // namespace pp
#endif // COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_
#endif // COMPILER_PREPROCESSOR_SOURCELOCATION_H_

View File

@ -116,4 +116,5 @@ inline bool operator!=(const Token &lhs, const Token &rhs)
extern std::ostream &operator<<(std::ostream &out, const Token &token);
} // namepsace pp
#endif // COMPILER_PREPROCESSOR_TOKEN_H_

View File

@ -55,5 +55,5 @@ class Tokenizer : public Lexer
};
} // namespace pp
#endif // COMPILER_PREPROCESSOR_TOKENIZER_H_
#endif // COMPILER_PREPROCESSOR_TOKENIZER_H_

View File

@ -267,7 +267,9 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
namespace pp {
Tokenizer::Tokenizer(Diagnostics *diagnostics) : mHandle(0)
Tokenizer::Tokenizer(Diagnostics *diagnostics)
: mHandle(0),
mMaxTokenSize(256)
{
mContext.diagnostics = diagnostics;
}

View File

@ -6,8 +6,8 @@
// numeric_lex.h: Functions to extract numeric values from string.
#ifndef COMPILER_PREPROCESSOR_NUMERIC_LEX_H_
#define COMPILER_PREPROCESSOR_NUMERIC_LEX_H_
#ifndef COMPILER_PREPROCESSOR_NUMERICLEX_H_
#define COMPILER_PREPROCESSOR_NUMERICLEX_H_
#include <sstream>
@ -58,4 +58,5 @@ bool numeric_lex_float(const std::string &str, FloatType *value)
}
} // namespace pp.
#endif // COMPILER_PREPROCESSOR_NUMERIC_LEX_H_
#endif // COMPILER_PREPROCESSOR_NUMERICLEX_H_

View File

@ -4,10 +4,10 @@
// found in the LICENSE file.
//
#ifndef _BASICTYPES_INCLUDED_
#define _BASICTYPES_INCLUDED_
#ifndef COMPILER_TRANSLATOR_BASETYPES_H_
#define COMPILER_TRANSLATOR_BASETYPES_H_
#include <assert.h>
#include "compiler/translator/compilerdebug.h"
//
// Precision qualifiers
@ -42,7 +42,15 @@ enum TBasicType
EbtInt,
EbtUInt,
EbtBool,
EbtGVec4, // non type: represents vec4, ivec4 and uvec4
EbtGVec4, // non type: represents vec4, ivec4, and uvec4
EbtGenType, // non type: represents float, vec2, vec3, and vec4
EbtGenIType, // non type: represents int, ivec2, ivec3, and ivec4
EbtGenUType, // non type: represents uint, uvec2, uvec3, and uvec4
EbtGenBType, // non type: represents bool, bvec2, bvec3, and bvec4
EbtVec, // non type: represents vec2, vec3, and vec4
EbtIVec, // non type: represents ivec2, ivec3, and ivec4
EbtUVec, // non type: represents uvec2, uvec3, and uvec4
EbtBVec, // non type: represents bvec2, bvec3, and bvec4
EbtGuardSamplerBegin, // non type: see implementation of IsSampler()
EbtSampler2D,
EbtSampler3D,
@ -62,10 +70,10 @@ enum TBasicType
EbtSamplerCubeShadow,
EbtSampler2DArrayShadow,
EbtGuardSamplerEnd, // non type: see implementation of IsSampler()
EbtGSampler2D, // non type: represents sampler2D, isampler2D and usampler2D
EbtGSampler3D, // non type: represents sampler3D, isampler3D and usampler3D
EbtGSamplerCube, // non type: represents samplerCube, isamplerCube and usamplerCube
EbtGSampler2DArray, // non type: represents sampler2DArray, isampler2DArray and usampler2DArray
EbtGSampler2D, // non type: represents sampler2D, isampler2D, and usampler2D
EbtGSampler3D, // non type: represents sampler3D, isampler3D, and usampler3D
EbtGSamplerCube, // non type: represents samplerCube, isamplerCube, and usamplerCube
EbtGSampler2DArray, // non type: represents sampler2DArray, isampler2DArray, and usampler2DArray
EbtStruct,
EbtInterfaceBlock,
EbtAddress, // should be deprecated??
@ -258,6 +266,11 @@ inline bool IsShadowSampler(TBasicType type)
return false;
}
inline bool IsInteger(TBasicType type)
{
return type == EbtInt || type == EbtUInt;
}
inline bool SupportsPrecision(TBasicType type)
{
return type == EbtFloat || type == EbtInt || type == EbtUInt || IsSampler(type);
@ -293,6 +306,9 @@ enum TQualifier
EvqInOut,
EvqConstReadOnly,
// built-ins read by vertex shader
EvqInstanceID,
// built-ins written by vertex shader
EvqPosition,
EvqPointSize,
@ -307,6 +323,10 @@ enum TQualifier
EvqFragData,
EvqFragDepth,
// built-ins written by the shader_framebuffer_fetch extension(s)
EvqLastFragColor,
EvqLastFragData,
// GLSL ES 3.0 vertex output and fragment input
EvqSmooth, // Incomplete qualifier, smooth is the default
EvqFlat, // Incomplete qualifier
@ -383,6 +403,7 @@ inline const char* getQualifierString(TQualifier q)
case EvqIn: return "in"; break;
case EvqOut: return "out"; break;
case EvqInOut: return "inout"; break;
case EvqInstanceID: return "InstanceID"; break;
case EvqPosition: return "Position"; break;
case EvqPointSize: return "PointSize"; break;
case EvqFragCoord: return "FragCoord"; break;
@ -396,7 +417,9 @@ inline const char* getQualifierString(TQualifier q)
case EvqSmoothIn: return "smooth in"; break;
case EvqCentroidIn: return "centroid in"; break;
case EvqFlatIn: return "flat in"; break;
default: return "unknown qualifier";
case EvqLastFragColor: return "LastFragColor"; break;
case EvqLastFragData: return "LastFragData"; break;
default: UNREACHABLE(); return "unknown qualifier";
}
}
@ -407,7 +430,7 @@ inline const char* getMatrixPackingString(TLayoutMatrixPacking mpq)
case EmpUnspecified: return "mp_unspecified";
case EmpRowMajor: return "row_major";
case EmpColumnMajor: return "column_major";
default: return "unknown matrix packing";
default: UNREACHABLE(); return "unknown matrix packing";
}
}
@ -419,7 +442,7 @@ inline const char* getBlockStorageString(TLayoutBlockStorage bsq)
case EbsShared: return "shared";
case EbsPacked: return "packed";
case EbsStd140: return "std140";
default: return "unknown block storage";
default: UNREACHABLE(); return "unknown block storage";
}
}
@ -433,8 +456,8 @@ inline const char* getInterpolationString(TQualifier q)
case EvqSmoothIn: return "smooth"; break;
case EvqCentroidIn: return "centroid"; break;
case EvqFlatIn: return "flat"; break;
default: return "unknown interpolation";
default: UNREACHABLE(); return "unknown interpolation";
}
}
#endif // _BASICTYPES_INCLUDED_
#endif // COMPILER_TRANSLATOR_BASETYPES_H_

View File

@ -8,193 +8,9 @@
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/SymbolTable.h"
namespace {
// we use macros here instead of function definitions to work around more GLSL
// compiler bugs, in particular on NVIDIA hardware on Mac OSX. Macros are
// problematic because if the argument has side-effects they will be repeatedly
// evaluated. This is unlikely to show up in real shaders, but is something to
// consider.
const char* kFunctionEmulationVertexSource[] = {
"#error no emulation for cos(float)",
"#error no emulation for cos(vec2)",
"#error no emulation for cos(vec3)",
"#error no emulation for cos(vec4)",
"#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))",
"#error no emulation for distance(vec2, vec2)",
"#error no emulation for distance(vec3, vec3)",
"#error no emulation for distance(vec4, vec4)",
"#define webgl_dot_emu(x, y) ((x) * (y))",
"#error no emulation for dot(vec2, vec2)",
"#error no emulation for dot(vec3, vec3)",
"#error no emulation for dot(vec4, vec4)",
"#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))",
"#error no emulation for length(vec2)",
"#error no emulation for length(vec3)",
"#error no emulation for length(vec4)",
"#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))",
"#error no emulation for normalize(vec2)",
"#error no emulation for normalize(vec3)",
"#error no emulation for normalize(vec4)",
"#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))",
"#error no emulation for reflect(vec2, vec2)",
"#error no emulation for reflect(vec3, vec3)",
"#error no emulation for reflect(vec4, vec4)"
};
const char* kFunctionEmulationFragmentSource[] = {
"webgl_emu_precision float webgl_cos_emu(webgl_emu_precision float a) { return cos(a); }",
"webgl_emu_precision vec2 webgl_cos_emu(webgl_emu_precision vec2 a) { return cos(a); }",
"webgl_emu_precision vec3 webgl_cos_emu(webgl_emu_precision vec3 a) { return cos(a); }",
"webgl_emu_precision vec4 webgl_cos_emu(webgl_emu_precision vec4 a) { return cos(a); }",
"#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))",
"#error no emulation for distance(vec2, vec2)",
"#error no emulation for distance(vec3, vec3)",
"#error no emulation for distance(vec4, vec4)",
"#define webgl_dot_emu(x, y) ((x) * (y))",
"#error no emulation for dot(vec2, vec2)",
"#error no emulation for dot(vec3, vec3)",
"#error no emulation for dot(vec4, vec4)",
"#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))",
"#error no emulation for length(vec2)",
"#error no emulation for length(vec3)",
"#error no emulation for length(vec4)",
"#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))",
"#error no emulation for normalize(vec2)",
"#error no emulation for normalize(vec3)",
"#error no emulation for normalize(vec4)",
"#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))",
"#error no emulation for reflect(vec2, vec2)",
"#error no emulation for reflect(vec3, vec3)",
"#error no emulation for reflect(vec4, vec4)"
};
const bool kFunctionEmulationVertexMask[] = {
#if defined(__APPLE__)
// Work around ATI driver bugs in Mac.
false, // TFunctionCos1
false, // TFunctionCos2
false, // TFunctionCos3
false, // TFunctionCos4
true, // TFunctionDistance1_1
false, // TFunctionDistance2_2
false, // TFunctionDistance3_3
false, // TFunctionDistance4_4
true, // TFunctionDot1_1
false, // TFunctionDot2_2
false, // TFunctionDot3_3
false, // TFunctionDot4_4
true, // TFunctionLength1
false, // TFunctionLength2
false, // TFunctionLength3
false, // TFunctionLength4
true, // TFunctionNormalize1
false, // TFunctionNormalize2
false, // TFunctionNormalize3
false, // TFunctionNormalize4
true, // TFunctionReflect1_1
false, // TFunctionReflect2_2
false, // TFunctionReflect3_3
false, // TFunctionReflect4_4
#else
// Work around D3D driver bug in Win.
false, // TFunctionCos1
false, // TFunctionCos2
false, // TFunctionCos3
false, // TFunctionCos4
false, // TFunctionDistance1_1
false, // TFunctionDistance2_2
false, // TFunctionDistance3_3
false, // TFunctionDistance4_4
false, // TFunctionDot1_1
false, // TFunctionDot2_2
false, // TFunctionDot3_3
false, // TFunctionDot4_4
false, // TFunctionLength1
false, // TFunctionLength2
false, // TFunctionLength3
false, // TFunctionLength4
false, // TFunctionNormalize1
false, // TFunctionNormalize2
false, // TFunctionNormalize3
false, // TFunctionNormalize4
false, // TFunctionReflect1_1
false, // TFunctionReflect2_2
false, // TFunctionReflect3_3
false, // TFunctionReflect4_4
#endif
false // TFunctionUnknown
};
const bool kFunctionEmulationFragmentMask[] = {
#if defined(__APPLE__)
// Work around ATI driver bugs in Mac.
true, // TFunctionCos1
true, // TFunctionCos2
true, // TFunctionCos3
true, // TFunctionCos4
true, // TFunctionDistance1_1
false, // TFunctionDistance2_2
false, // TFunctionDistance3_3
false, // TFunctionDistance4_4
true, // TFunctionDot1_1
false, // TFunctionDot2_2
false, // TFunctionDot3_3
false, // TFunctionDot4_4
true, // TFunctionLength1
false, // TFunctionLength2
false, // TFunctionLength3
false, // TFunctionLength4
true, // TFunctionNormalize1
false, // TFunctionNormalize2
false, // TFunctionNormalize3
false, // TFunctionNormalize4
true, // TFunctionReflect1_1
false, // TFunctionReflect2_2
false, // TFunctionReflect3_3
false, // TFunctionReflect4_4
#else
// Work around D3D driver bug in Win.
false, // TFunctionCos1
false, // TFunctionCos2
false, // TFunctionCos3
false, // TFunctionCos4
false, // TFunctionDistance1_1
false, // TFunctionDistance2_2
false, // TFunctionDistance3_3
false, // TFunctionDistance4_4
false, // TFunctionDot1_1
false, // TFunctionDot2_2
false, // TFunctionDot3_3
false, // TFunctionDot4_4
false, // TFunctionLength1
false, // TFunctionLength2
false, // TFunctionLength3
false, // TFunctionLength4
false, // TFunctionNormalize1
false, // TFunctionNormalize2
false, // TFunctionNormalize3
false, // TFunctionNormalize4
false, // TFunctionReflect1_1
false, // TFunctionReflect2_2
false, // TFunctionReflect3_3
false, // TFunctionReflect4_4
#endif
false // TFunctionUnknown
};
class BuiltInFunctionEmulationMarker : public TIntermTraverser {
public:
class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTraverser
{
public:
BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator& emulator)
: mEmulator(emulator)
{
@ -238,148 +54,119 @@ public:
case EOpFaceForward:
case EOpReflect:
case EOpRefract:
case EOpOuterProduct:
case EOpMul:
break;
default:
return true;
};
const TIntermSequence& sequence = *(node->getSequence());
// Right now we only handle built-in functions with two parameters.
if (sequence.size() != 2)
bool needToEmulate = false;
// Right now we only handle built-in functions with two or three parameters.
if (sequence.size() == 2)
{
TIntermTyped* param1 = sequence[0]->getAsTyped();
TIntermTyped* param2 = sequence[1]->getAsTyped();
if (!param1 || !param2)
return true;
needToEmulate = mEmulator.SetFunctionCalled(
node->getOp(), param1->getType(), param2->getType());
}
else if (sequence.size() == 3)
{
TIntermTyped* param1 = sequence[0]->getAsTyped();
TIntermTyped* param2 = sequence[1]->getAsTyped();
TIntermTyped* param3 = sequence[2]->getAsTyped();
if (!param1 || !param2 || !param3)
return true;
needToEmulate = mEmulator.SetFunctionCalled(
node->getOp(), param1->getType(), param2->getType(), param3->getType());
}
else
{
return true;
TIntermTyped* param1 = sequence[0]->getAsTyped();
TIntermTyped* param2 = sequence[1]->getAsTyped();
if (!param1 || !param2)
return true;
bool needToEmulate = mEmulator.SetFunctionCalled(
node->getOp(), param1->getType(), param2->getType());
}
if (needToEmulate)
node->setUseEmulatedFunction();
}
return true;
}
private:
private:
BuiltInFunctionEmulator& mEmulator;
};
} // anonymous namepsace
BuiltInFunctionEmulator::BuiltInFunctionEmulator()
{}
BuiltInFunctionEmulator::BuiltInFunctionEmulator(sh::GLenum shaderType)
void BuiltInFunctionEmulator::addEmulatedFunction(
TOperator op, const TType& param,
const char* emulatedFunctionDefinition)
{
if (shaderType == GL_FRAGMENT_SHADER) {
mFunctionMask = kFunctionEmulationFragmentMask;
mFunctionSource = kFunctionEmulationFragmentSource;
} else {
mFunctionMask = kFunctionEmulationVertexMask;
mFunctionSource = kFunctionEmulationVertexSource;
mEmulatedFunctions[FunctionId(op, param)] =
std::string(emulatedFunctionDefinition);
}
void BuiltInFunctionEmulator::addEmulatedFunction(
TOperator op, const TType& param1, const TType& param2,
const char* emulatedFunctionDefinition)
{
mEmulatedFunctions[FunctionId(op, param1, param2)] =
std::string(emulatedFunctionDefinition);
}
void BuiltInFunctionEmulator::addEmulatedFunction(
TOperator op, const TType& param1, const TType& param2, const TType& param3,
const char* emulatedFunctionDefinition)
{
mEmulatedFunctions[FunctionId(op, param1, param2, param3)] =
std::string(emulatedFunctionDefinition);
}
bool BuiltInFunctionEmulator::IsOutputEmpty() const
{
return (mFunctions.size() == 0);
}
void BuiltInFunctionEmulator::OutputEmulatedFunctions(
TInfoSinkBase& out) const
{
for (size_t i = 0; i < mFunctions.size(); ++i) {
out << mEmulatedFunctions.find(mFunctions[i])->second << "\n\n";
}
}
bool BuiltInFunctionEmulator::SetFunctionCalled(
TOperator op, const TType& param)
{
TBuiltInFunction function = IdentifyFunction(op, param);
return SetFunctionCalled(function);
return SetFunctionCalled(FunctionId(op, param));
}
bool BuiltInFunctionEmulator::SetFunctionCalled(
TOperator op, const TType& param1, const TType& param2)
{
TBuiltInFunction function = IdentifyFunction(op, param1, param2);
return SetFunctionCalled(function);
return SetFunctionCalled(FunctionId(op, param1, param2));
}
bool BuiltInFunctionEmulator::SetFunctionCalled(
BuiltInFunctionEmulator::TBuiltInFunction function) {
if (function == TFunctionUnknown || mFunctionMask[function] == false)
return false;
for (size_t i = 0; i < mFunctions.size(); ++i) {
if (mFunctions[i] == function)
return true;
}
mFunctions.push_back(function);
return true;
TOperator op, const TType& param1, const TType& param2, const TType& param3)
{
return SetFunctionCalled(FunctionId(op, param1, param2, param3));
}
void BuiltInFunctionEmulator::OutputEmulatedFunctionDefinition(
TInfoSinkBase& out, bool withPrecision) const
{
if (mFunctions.size() == 0)
return;
out << "// BEGIN: Generated code for built-in function emulation\n\n";
if (withPrecision) {
out << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n"
<< "#define webgl_emu_precision highp\n"
<< "#else\n"
<< "#define webgl_emu_precision mediump\n"
<< "#endif\n\n";
} else {
out << "#define webgl_emu_precision\n\n";
bool BuiltInFunctionEmulator::SetFunctionCalled(
const FunctionId& functionId) {
if (mEmulatedFunctions.find(functionId) != mEmulatedFunctions.end())
{
for (size_t i = 0; i < mFunctions.size(); ++i) {
if (mFunctions[i] == functionId)
return true;
}
mFunctions.push_back(functionId);
return true;
}
for (size_t i = 0; i < mFunctions.size(); ++i) {
out << mFunctionSource[mFunctions[i]] << "\n\n";
}
out << "// END: Generated code for built-in function emulation\n\n";
}
BuiltInFunctionEmulator::TBuiltInFunction
BuiltInFunctionEmulator::IdentifyFunction(
TOperator op, const TType& param)
{
if (param.getNominalSize() > 4 || param.getSecondarySize() > 4)
return TFunctionUnknown;
unsigned int function = TFunctionUnknown;
switch (op) {
case EOpCos:
function = TFunctionCos1;
break;
case EOpLength:
function = TFunctionLength1;
break;
case EOpNormalize:
function = TFunctionNormalize1;
break;
default:
break;
}
if (function == TFunctionUnknown)
return TFunctionUnknown;
if (param.isVector())
function += param.getNominalSize() - 1;
return static_cast<TBuiltInFunction>(function);
}
BuiltInFunctionEmulator::TBuiltInFunction
BuiltInFunctionEmulator::IdentifyFunction(
TOperator op, const TType& param1, const TType& param2)
{
// Right now for all the emulated functions with two parameters, the two
// parameters have the same type.
if (param1.getNominalSize() != param2.getNominalSize() ||
param1.getSecondarySize() != param2.getSecondarySize() ||
param1.getNominalSize() > 4 || param1.getSecondarySize() > 4)
return TFunctionUnknown;
unsigned int function = TFunctionUnknown;
switch (op) {
case EOpDistance:
function = TFunctionDistance1_1;
break;
case EOpDot:
function = TFunctionDot1_1;
break;
case EOpReflect:
function = TFunctionReflect1_1;
break;
default:
break;
}
if (function == TFunctionUnknown)
return TFunctionUnknown;
if (param1.isVector())
function += param1.getNominalSize() - 1;
return static_cast<TBuiltInFunction>(function);
return false;
}
void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation(
@ -387,6 +174,9 @@ void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation(
{
ASSERT(root);
if (mEmulatedFunctions.empty())
return;
BuiltInFunctionEmulationMarker marker(*this);
root->traverse(&marker);
}
@ -404,3 +194,52 @@ TString BuiltInFunctionEmulator::GetEmulatedFunctionName(
return "webgl_" + name.substr(0, name.length() - 1) + "_emu(";
}
BuiltInFunctionEmulator::FunctionId::FunctionId
(TOperator op, const TType& param)
: mOp(op),
mParam1(param),
mParam2(EbtVoid),
mParam3(EbtVoid)
{
}
BuiltInFunctionEmulator::FunctionId::FunctionId
(TOperator op, const TType& param1, const TType& param2)
: mOp(op),
mParam1(param1),
mParam2(param2),
mParam3(EbtVoid)
{
}
BuiltInFunctionEmulator::FunctionId::FunctionId
(TOperator op, const TType& param1, const TType& param2, const TType& param3)
: mOp(op),
mParam1(param1),
mParam2(param2),
mParam3(param3)
{
}
bool BuiltInFunctionEmulator::FunctionId::operator==
(const BuiltInFunctionEmulator::FunctionId& other) const
{
return (mOp == other.mOp &&
mParam1 == other.mParam1 &&
mParam2 == other.mParam2 &&
mParam3 == other.mParam3);
}
bool BuiltInFunctionEmulator::FunctionId::operator<
(const BuiltInFunctionEmulator::FunctionId& other) const
{
if (mOp != other.mOp)
return mOp < other.mOp;
if (mParam1 != other.mParam1)
return mParam1 < other.mParam1;
if (mParam2 != other.mParam2)
return mParam2 < other.mParam2;
if (mParam3 != other.mParam3)
return mParam3 < other.mParam3;
return false; // all fields are equal
}

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_
#define COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_
#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h"
@ -13,23 +13,13 @@
//
// This class decides which built-in functions need to be replaced with the
// emulated ones.
// It's only a workaround for OpenGL driver bugs, and isn't needed in general.
// It can be used to work around driver bugs or implement functions that are
// not natively implemented on a specific platform.
//
class BuiltInFunctionEmulator {
public:
BuiltInFunctionEmulator(sh::GLenum shaderType);
// Records that a function is called by the shader and might needs to be
// emulated. If the function's group is not in mFunctionGroupFilter, this
// becomes an no-op.
// Returns true if the function call needs to be replaced with an emulated
// one.
bool SetFunctionCalled(TOperator op, const TType& param);
bool SetFunctionCalled(
TOperator op, const TType& param1, const TType& param2);
// Output function emulation definition. This should be before any other
// shader source.
void OutputEmulatedFunctionDefinition(TInfoSinkBase& out, bool withPrecision) const;
class BuiltInFunctionEmulator
{
public:
BuiltInFunctionEmulator();
void MarkBuiltInFunctionsForEmulation(TIntermNode* root);
@ -38,54 +28,52 @@ public:
// "name(" becomes "webgl_name_emu(".
static TString GetEmulatedFunctionName(const TString& name);
private:
//
// Built-in functions.
//
enum TBuiltInFunction {
TFunctionCos1 = 0, // float cos(float);
TFunctionCos2, // vec2 cos(vec2);
TFunctionCos3, // vec3 cos(vec3);
TFunctionCos4, // vec4 cos(vec4);
bool IsOutputEmpty() const;
TFunctionDistance1_1, // float distance(float, float);
TFunctionDistance2_2, // vec2 distance(vec2, vec2);
TFunctionDistance3_3, // vec3 distance(vec3, vec3);
TFunctionDistance4_4, // vec4 distance(vec4, vec4);
// Output function emulation definition. This should be before any other
// shader source.
void OutputEmulatedFunctions(TInfoSinkBase& out) const;
TFunctionDot1_1, // float dot(float, float);
TFunctionDot2_2, // vec2 dot(vec2, vec2);
TFunctionDot3_3, // vec3 dot(vec3, vec3);
TFunctionDot4_4, // vec4 dot(vec4, vec4);
// Add functions that need to be emulated.
void addEmulatedFunction(TOperator op, const TType& param, const char* emulatedFunctionDefinition);
void addEmulatedFunction(TOperator op, const TType& param1, const TType& param2, const char* emulatedFunctionDefinition);
void addEmulatedFunction(TOperator op, const TType& param1, const TType& param2, const TType& param3, const char* emulatedFunctionDefinition);
TFunctionLength1, // float length(float);
TFunctionLength2, // float length(vec2);
TFunctionLength3, // float length(vec3);
TFunctionLength4, // float length(vec4);
private:
class BuiltInFunctionEmulationMarker;
TFunctionNormalize1, // float normalize(float);
TFunctionNormalize2, // vec2 normalize(vec2);
TFunctionNormalize3, // vec3 normalize(vec3);
TFunctionNormalize4, // vec4 normalize(vec4);
// Records that a function is called by the shader and might need to be
// emulated. If the function is not in mEmulatedFunctions, this becomes a
// no-op. Returns true if the function call needs to be replaced with an
// emulated one.
bool SetFunctionCalled(TOperator op, const TType& param);
bool SetFunctionCalled(
TOperator op, const TType& param1, const TType& param2);
bool SetFunctionCalled(
TOperator op, const TType& param1, const TType& param2, const TType& param3);
TFunctionReflect1_1, // float reflect(float, float);
TFunctionReflect2_2, // vec2 reflect(vec2, vec2);
TFunctionReflect3_3, // vec3 reflect(vec3, vec3);
TFunctionReflect4_4, // vec4 reflect(vec4, vec4);
class FunctionId {
public:
FunctionId(TOperator op, const TType& param);
FunctionId(TOperator op, const TType& param1, const TType& param2);
FunctionId(TOperator op, const TType& param1, const TType& param2, const TType& param3);
TFunctionUnknown
bool operator==(const FunctionId& other) const;
bool operator<(const FunctionId& other) const;
private:
TOperator mOp;
TType mParam1;
TType mParam2;
TType mParam3;
};
TBuiltInFunction IdentifyFunction(TOperator op, const TType& param);
TBuiltInFunction IdentifyFunction(
TOperator op, const TType& param1, const TType& param2);
bool SetFunctionCalled(const FunctionId& functionId);
bool SetFunctionCalled(TBuiltInFunction function);
// Map from function id to emulated function definition
std::map<FunctionId, std::string> mEmulatedFunctions;
std::vector<TBuiltInFunction> mFunctions;
const bool* mFunctionMask; // a boolean flag for each function.
const char** mFunctionSource;
// Called function ids
std::vector<FunctionId> mFunctions;
};
#endif // COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_
#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_

View File

@ -0,0 +1,37 @@
//
// 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 "angle_gl.h"
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
#include "compiler/translator/SymbolTable.h"
void InitBuiltInFunctionEmulatorForGLSL(BuiltInFunctionEmulator *emu, sh::GLenum shaderType)
{
// we use macros here instead of function definitions to work around more GLSL
// compiler bugs, in particular on NVIDIA hardware on Mac OSX. Macros are
// problematic because if the argument has side-effects they will be repeatedly
// evaluated. This is unlikely to show up in real shaders, but is something to
// consider.
TType float1(EbtFloat);
TType float2(EbtFloat, 2);
TType float3(EbtFloat, 3);
TType float4(EbtFloat, 4);
if (shaderType == GL_FRAGMENT_SHADER)
{
emu->addEmulatedFunction(EOpCos, float1, "webgl_emu_precision float webgl_cos_emu(webgl_emu_precision float a) { return cos(a); }");
emu->addEmulatedFunction(EOpCos, float2, "webgl_emu_precision vec2 webgl_cos_emu(webgl_emu_precision vec2 a) { return cos(a); }");
emu->addEmulatedFunction(EOpCos, float3, "webgl_emu_precision vec3 webgl_cos_emu(webgl_emu_precision vec3 a) { return cos(a); }");
emu->addEmulatedFunction(EOpCos, float4, "webgl_emu_precision vec4 webgl_cos_emu(webgl_emu_precision vec4 a) { return cos(a); }");
}
emu->addEmulatedFunction(EOpDistance, float1, float1, "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))");
emu->addEmulatedFunction(EOpDot, float1, float1, "#define webgl_dot_emu(x, y) ((x) * (y))");
emu->addEmulatedFunction(EOpLength, float1, "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))");
emu->addEmulatedFunction(EOpNormalize, float1, "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))");
emu->addEmulatedFunction(EOpReflect, float1, float1, "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))");
}

View File

@ -0,0 +1,19 @@
//
// Copyright (c) 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_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_
#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_
#include "GLSLANG/ShaderLang.h"
class BuiltInFunctionEmulator;
//
// This is only a workaround for OpenGL driver bugs, and isn't needed in general.
//
void InitBuiltInFunctionEmulatorForGLSL(BuiltInFunctionEmulator *emu, sh::GLenum shaderType);
#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_

View File

@ -0,0 +1,410 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "angle_gl.h"
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
#include "compiler/translator/SymbolTable.h"
void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
{
TType float1(EbtFloat);
TType float2(EbtFloat, 2);
TType float3(EbtFloat, 3);
TType float4(EbtFloat, 4);
emu->addEmulatedFunction(EOpMod, float1, float1,
"float webgl_mod_emu(float x, float y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpMod, float2, float2,
"float2 webgl_mod_emu(float2 x, float2 y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpMod, float2, float1,
"float2 webgl_mod_emu(float2 x, float y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpMod, float3, float3,
"float3 webgl_mod_emu(float3 x, float3 y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpMod, float3, float1,
"float3 webgl_mod_emu(float3 x, float y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpMod, float4, float4,
"float4 webgl_mod_emu(float4 x, float4 y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpMod, float4, float1,
"float4 webgl_mod_emu(float4 x, float y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpFaceForward, float1, float1, float1,
"float webgl_faceforward_emu(float N, float I, float Nref)\n"
"{\n"
" if(dot(Nref, I) >= 0)\n"
" {\n"
" return -N;\n"
" }\n"
" else\n"
" {\n"
" return N;\n"
" }\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpFaceForward, float2, float2, float2,
"float2 webgl_faceforward_emu(float2 N, float2 I, float2 Nref)\n"
"{\n"
" if(dot(Nref, I) >= 0)\n"
" {\n"
" return -N;\n"
" }\n"
" else\n"
" {\n"
" return N;\n"
" }\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpFaceForward, float3, float3, float3,
"float3 webgl_faceforward_emu(float3 N, float3 I, float3 Nref)\n"
"{\n"
" if(dot(Nref, I) >= 0)\n"
" {\n"
" return -N;\n"
" }\n"
" else\n"
" {\n"
" return N;\n"
" }\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpFaceForward, float4, float4, float4,
"float4 webgl_faceforward_emu(float4 N, float4 I, float4 Nref)\n"
"{\n"
" if(dot(Nref, I) >= 0)\n"
" {\n"
" return -N;\n"
" }\n"
" else\n"
" {\n"
" return N;\n"
" }\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpAtan, float1, float1,
"float webgl_atan_emu(float y, float x)\n"
"{\n"
" if(x == 0 && y == 0) x = 1;\n" // Avoid producing a NaN
" return atan2(y, x);\n"
"}\n");
emu->addEmulatedFunction(EOpAtan, float2, float2,
"float2 webgl_atan_emu(float2 y, float2 x)\n"
"{\n"
" if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
" if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
" return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n"
"}\n");
emu->addEmulatedFunction(EOpAtan, float3, float3,
"float3 webgl_atan_emu(float3 y, float3 x)\n"
"{\n"
" if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
" if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
" if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
" return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n"
"}\n");
emu->addEmulatedFunction(EOpAtan, float4, float4,
"float4 webgl_atan_emu(float4 y, float4 x)\n"
"{\n"
" if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
" if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
" if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
" if(x[3] == 0 && y[3] == 0) x[3] = 1;\n"
" return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]), atan2(y[3], x[3]));\n"
"}\n");
emu->addEmulatedFunction(EOpAsinh, float1,
"float webgl_asinh_emu(in float x) {\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n");
emu->addEmulatedFunction(EOpAsinh, float2,
"float2 webgl_asinh_emu(in float2 x) {\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n");
emu->addEmulatedFunction(EOpAsinh, float3,
"float3 webgl_asinh_emu(in float3 x) {\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n");
emu->addEmulatedFunction(EOpAsinh, float4,
"float4 webgl_asinh_emu(in float4 x) {\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n");
emu->addEmulatedFunction(EOpAcosh, float1,
"float webgl_acosh_emu(in float x) {\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n");
emu->addEmulatedFunction(EOpAcosh, float2,
"float2 webgl_acosh_emu(in float2 x) {\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n");
emu->addEmulatedFunction(EOpAcosh, float3,
"float3 webgl_acosh_emu(in float3 x) {\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n");
emu->addEmulatedFunction(EOpAcosh, float4,
"float4 webgl_acosh_emu(in float4 x) {\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n");
emu->addEmulatedFunction(EOpAtanh, float1,
"float webgl_atanh_emu(in float x) {\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n");
emu->addEmulatedFunction(EOpAtanh, float2,
"float2 webgl_atanh_emu(in float2 x) {\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n");
emu->addEmulatedFunction(EOpAtanh, float3,
"float3 webgl_atanh_emu(in float3 x) {\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n");
emu->addEmulatedFunction(EOpAtanh, float4,
"float4 webgl_atanh_emu(in float4 x) {\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n");
emu->addEmulatedFunction(EOpRoundEven, float1,
"float webgl_roundEven_emu(in float x) {\n"
" return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);\n"
"}\n");
emu->addEmulatedFunction(EOpRoundEven, float2,
"float2 webgl_roundEven_emu(in float2 x) {\n"
" float2 v;\n"
" v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
" v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
" return v;\n"
"}\n");
emu->addEmulatedFunction(EOpRoundEven, float3,
"float3 webgl_roundEven_emu(in float3 x) {\n"
" float3 v;\n"
" v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
" v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
" v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n"
" return v;\n"
"}\n");
emu->addEmulatedFunction(EOpRoundEven, float4,
"float4 webgl_roundEven_emu(in float4 x) {\n"
" float4 v;\n"
" v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
" v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
" v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n"
" v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);\n"
" return v;\n"
"}\n");
emu->addEmulatedFunction(EOpPackSnorm2x16, float2,
"int webgl_toSnorm(in float x) {\n"
" return int(round(clamp(x, -1.0, 1.0) * 32767.0));\n"
"}\n"
"\n"
"uint webgl_packSnorm2x16_emu(in float2 v) {\n"
" int x = webgl_toSnorm(v.x);\n"
" int y = webgl_toSnorm(v.y);\n"
" return (asuint(y) << 16) | (asuint(x) & 0xffffu);\n"
"}\n");
emu->addEmulatedFunction(EOpPackUnorm2x16, float2,
"uint webgl_toUnorm(in float x) {\n"
" return uint(round(clamp(x, 0.0, 1.0) * 65535.0));\n"
"}\n"
"\n"
"uint webgl_packUnorm2x16_emu(in float2 v) {\n"
" uint x = webgl_toUnorm(v.x);\n"
" uint y = webgl_toUnorm(v.y);\n"
" return (y << 16) | x;\n"
"}\n");
emu->addEmulatedFunction(EOpPackHalf2x16, float2,
"uint webgl_packHalf2x16_emu(in float2 v) {\n"
" uint x = f32tof16(v.x);\n"
" uint y = f32tof16(v.y);\n"
" return (y << 16) | x;\n"
"}\n");
TType uint1(EbtUInt);
emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1,
"float webgl_fromSnorm(in uint x) {\n"
" int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);\n"
" return clamp(float(xi) / 32767.0, -1.0, 1.0);\n"
"}\n"
"\n"
"float2 webgl_unpackSnorm2x16_emu(in uint u) {\n"
" uint y = (u >> 16);\n"
" uint x = u;\n"
" return float2(webgl_fromSnorm(x), webgl_fromSnorm(y));\n"
"}\n");
emu->addEmulatedFunction(EOpUnpackUnorm2x16, uint1,
"float webgl_fromUnorm(in uint x) {\n"
" return float(x) / 65535.0;\n"
"}\n"
"\n"
"float2 webgl_unpackUnorm2x16_emu(in uint u) {\n"
" uint y = (u >> 16);\n"
" uint x = u & 0xffffu;\n"
" return float2(webgl_fromUnorm(x), webgl_fromUnorm(y));\n"
"}\n");
emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1,
"float2 webgl_unpackHalf2x16_emu(in uint u) {\n"
" uint y = (u >> 16);\n"
" uint x = u & 0xffffu;\n"
" return float2(f16tof32(x), f16tof32(y));\n"
"}\n");
// The matrix resulting from outer product needs to be transposed
// (matrices are stored as transposed to simplify element access in HLSL).
// So the function should return transpose(c * r) where c is a column vector
// and r is a row vector. This can be simplified by using the following
// formula:
// transpose(c * r) = transpose(r) * transpose(c)
// transpose(r) and transpose(c) are in a sense free, since to get the
// transpose of r, we simply can build a column matrix out of the original
// vector instead of a row matrix.
emu->addEmulatedFunction(EOpOuterProduct, float2, float2,
"float2x2 webgl_outerProduct_emu(in float2 c, in float2 r) {\n"
" return mul(float2x1(r), float1x2(c));\n"
"}\n");
emu->addEmulatedFunction(EOpOuterProduct, float3, float3,
"float3x3 webgl_outerProduct_emu(in float3 c, in float3 r) {\n"
" return mul(float3x1(r), float1x3(c));\n"
"}\n");
emu->addEmulatedFunction(EOpOuterProduct, float4, float4,
"float4x4 webgl_outerProduct_emu(in float4 c, in float4 r) {\n"
" return mul(float4x1(r), float1x4(c));\n"
"}\n");
emu->addEmulatedFunction(EOpOuterProduct, float3, float2,
"float2x3 webgl_outerProduct_emu(in float3 c, in float2 r) {\n"
" return mul(float2x1(r), float1x3(c));\n"
"}\n");
emu->addEmulatedFunction(EOpOuterProduct, float2, float3,
"float3x2 webgl_outerProduct_emu(in float2 c, in float3 r) {\n"
" return mul(float3x1(r), float1x2(c));\n"
"}\n");
emu->addEmulatedFunction(EOpOuterProduct, float4, float2,
"float2x4 webgl_outerProduct_emu(in float4 c, in float2 r) {\n"
" return mul(float2x1(r), float1x4(c));\n"
"}\n");
emu->addEmulatedFunction(EOpOuterProduct, float2, float4,
"float4x2 webgl_outerProduct_emu(in float2 c, in float4 r) {\n"
" return mul(float4x1(r), float1x2(c));\n"
"}\n");
emu->addEmulatedFunction(EOpOuterProduct, float4, float3,
"float3x4 webgl_outerProduct_emu(in float4 c, in float3 r) {\n"
" return mul(float3x1(r), float1x4(c));\n"
"}\n");
emu->addEmulatedFunction(EOpOuterProduct, float3, float4,
"float4x3 webgl_outerProduct_emu(in float3 c, in float4 r) {\n"
" return mul(float4x1(r), float1x3(c));\n"
"}\n");
TType mat2(EbtFloat, 2, 2);
TType mat3(EbtFloat, 3, 3);
TType mat4(EbtFloat, 4, 4);
// Remember here that the parameter matrix is actually the transpose
// of the matrix that we're trying to invert, and the resulting matrix
// should also be the transpose of the inverse.
// When accessing the parameter matrix with m[a][b] it can be thought of so
// that a is the column and b is the row of the matrix that we're inverting.
// We calculate the inverse as the adjugate matrix divided by the
// determinant of the matrix being inverted. However, as the result needs
// to be transposed, we actually use of the transpose of the adjugate matrix
// which happens to be the cofactor matrix. That's stored in "cof".
// We don't need to care about divide-by-zero since results are undefined
// for singular or poorly-conditioned matrices.
emu->addEmulatedFunction(EOpInverse, mat2,
"float2x2 webgl_inverse_emu(in float2x2 m) {\n"
" float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };\n"
" return cof / determinant(transpose(m));\n"
"}\n");
// cofAB is the cofactor for column A and row B.
emu->addEmulatedFunction(EOpInverse, mat3,
"float3x3 webgl_inverse_emu(in float3x3 m) {\n"
" float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];\n"
" float cof01 = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]);\n"
" float cof02 = m[1][0] * m[2][1] - m[2][0] * m[1][1];\n"
" float cof10 = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]);\n"
" float cof11 = m[0][0] * m[2][2] - m[2][0] * m[0][2];\n"
" float cof12 = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]);\n"
" float cof20 = m[0][1] * m[1][2] - m[1][1] * m[0][2];\n"
" float cof21 = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]);\n"
" float cof22 = m[0][0] * m[1][1] - m[1][0] * m[0][1];\n"
" float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };\n"
" return cof / determinant(transpose(m));\n"
"}\n");
emu->addEmulatedFunction(EOpInverse, mat4,
"float4x4 webgl_inverse_emu(in float4x4 m) {\n"
" float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * m[1][2] * m[2][3]"
" - m[1][1] * m[3][2] * m[2][3] - m[2][1] * m[1][2] * m[3][3] - m[3][1] * m[2][2] * m[1][3];\n"
" float cof01 = -(m[1][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[1][3] + m[3][0] * m[1][2] * m[2][3]"
" - m[1][0] * m[3][2] * m[2][3] - m[2][0] * m[1][2] * m[3][3] - m[3][0] * m[2][2] * m[1][3]);\n"
" float cof02 = m[1][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[1][3] + m[3][0] * m[1][1] * m[2][3]"
" - m[1][0] * m[3][1] * m[2][3] - m[2][0] * m[1][1] * m[3][3] - m[3][0] * m[2][1] * m[1][3];\n"
" float cof03 = -(m[1][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[1][2] + m[3][0] * m[1][1] * m[2][2]"
" - m[1][0] * m[3][1] * m[2][2] - m[2][0] * m[1][1] * m[3][2] - m[3][0] * m[2][1] * m[1][2]);\n"
" float cof10 = -(m[0][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[0][3] + m[3][1] * m[0][2] * m[2][3]"
" - m[0][1] * m[3][2] * m[2][3] - m[2][1] * m[0][2] * m[3][3] - m[3][1] * m[2][2] * m[0][3]);\n"
" float cof11 = m[0][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[0][3] + m[3][0] * m[0][2] * m[2][3]"
" - m[0][0] * m[3][2] * m[2][3] - m[2][0] * m[0][2] * m[3][3] - m[3][0] * m[2][2] * m[0][3];\n"
" float cof12 = -(m[0][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[0][3] + m[3][0] * m[0][1] * m[2][3]"
" - m[0][0] * m[3][1] * m[2][3] - m[2][0] * m[0][1] * m[3][3] - m[3][0] * m[2][1] * m[0][3]);\n"
" float cof13 = m[0][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[0][2] + m[3][0] * m[0][1] * m[2][2]"
" - m[0][0] * m[3][1] * m[2][2] - m[2][0] * m[0][1] * m[3][2] - m[3][0] * m[2][1] * m[0][2];\n"
" float cof20 = m[0][1] * m[1][2] * m[3][3] + m[1][1] * m[3][2] * m[0][3] + m[3][1] * m[0][2] * m[1][3]"
" - m[0][1] * m[3][2] * m[1][3] - m[1][1] * m[0][2] * m[3][3] - m[3][1] * m[1][2] * m[0][3];\n"
" float cof21 = -(m[0][0] * m[1][2] * m[3][3] + m[1][0] * m[3][2] * m[0][3] + m[3][0] * m[0][2] * m[1][3]"
" - m[0][0] * m[3][2] * m[1][3] - m[1][0] * m[0][2] * m[3][3] - m[3][0] * m[1][2] * m[0][3]);\n"
" float cof22 = m[0][0] * m[1][1] * m[3][3] + m[1][0] * m[3][1] * m[0][3] + m[3][0] * m[0][1] * m[1][3]"
" - m[0][0] * m[3][1] * m[1][3] - m[1][0] * m[0][1] * m[3][3] - m[3][0] * m[1][1] * m[0][3];\n"
" float cof23 = -(m[0][0] * m[1][1] * m[3][2] + m[1][0] * m[3][1] * m[0][2] + m[3][0] * m[0][1] * m[1][2]"
" - m[0][0] * m[3][1] * m[1][2] - m[1][0] * m[0][1] * m[3][2] - m[3][0] * m[1][1] * m[0][2]);\n"
" float cof30 = -(m[0][1] * m[1][2] * m[2][3] + m[1][1] * m[2][2] * m[0][3] + m[2][1] * m[0][2] * m[1][3]"
" - m[0][1] * m[2][2] * m[1][3] - m[1][1] * m[0][2] * m[2][3] - m[2][1] * m[1][2] * m[0][3]);\n"
" float cof31 = m[0][0] * m[1][2] * m[2][3] + m[1][0] * m[2][2] * m[0][3] + m[2][0] * m[0][2] * m[1][3]"
" - m[0][0] * m[2][2] * m[1][3] - m[1][0] * m[0][2] * m[2][3] - m[2][0] * m[1][2] * m[0][3];\n"
" float cof32 = -(m[0][0] * m[1][1] * m[2][3] + m[1][0] * m[2][1] * m[0][3] + m[2][0] * m[0][1] * m[1][3]"
" - m[0][0] * m[2][1] * m[1][3] - m[1][0] * m[0][1] * m[2][3] - m[2][0] * m[1][1] * m[0][3]);\n"
" float cof33 = m[0][0] * m[1][1] * m[2][2] + m[1][0] * m[2][1] * m[0][2] + m[2][0] * m[0][1] * m[1][2]"
" - m[0][0] * m[2][1] * m[1][2] - m[1][0] * m[0][1] * m[2][2] - m[2][0] * m[1][1] * m[0][2];\n"
" float4x4 cof = { cof00, cof10, cof20, cof30, cof01, cof11, cof21, cof31,"
" cof02, cof12, cof22, cof32, cof03, cof13, cof23, cof33 };\n"
" return cof / determinant(transpose(m));\n"
"}\n");
}

View File

@ -0,0 +1,16 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_
#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_
#include "GLSLANG/ShaderLang.h"
class BuiltInFunctionEmulator;
void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu);
#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_

View File

@ -6,7 +6,9 @@
#include "compiler/translator/TranslatorESSL.h"
#include "compiler/translator/TranslatorGLSL.h"
#ifdef ANGLE_ENABLE_HLSL
#include "compiler/translator/TranslatorHLSL.h"
#endif // ANGLE_ENABLE_HLSL
//
// This function must be provided to create the actual
@ -17,14 +19,22 @@ TCompiler* ConstructCompiler(
sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
{
switch (output) {
case SH_ESSL_OUTPUT:
case SH_ESSL_OUTPUT:
return new TranslatorESSL(type, spec);
case SH_GLSL_OUTPUT:
return new TranslatorGLSL(type, spec);
case SH_HLSL9_OUTPUT:
case SH_HLSL11_OUTPUT:
case SH_GLSL_CORE_OUTPUT:
case SH_GLSL_COMPATIBILITY_OUTPUT:
return new TranslatorGLSL(type, spec, output);
case SH_HLSL9_OUTPUT:
case SH_HLSL11_OUTPUT:
#ifdef ANGLE_ENABLE_HLSL
return new TranslatorHLSL(type, spec, output);
default:
#else
// This compiler is not supported in this
// configuration. Return NULL per the ShConstructCompiler API.
return NULL;
#endif // ANGLE_ENABLE_HLSL
default:
// Unknown format. Return NULL per the ShConstructCompiler API.
return NULL;
}
}

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef _COMMON_INCLUDED_
#define _COMMON_INCLUDED_
#ifndef COMPILER_TRANSLATOR_COMMON_H_
#define COMPILER_TRANSLATOR_COMMON_H_
#include <map>
#include <sstream>
@ -89,4 +89,4 @@ inline TString str(T i)
return buffer;
}
#endif // _COMMON_INCLUDED_
#endif // COMPILER_TRANSLATOR_COMMON_H_

View File

@ -4,7 +4,6 @@
// found in the LICENSE file.
//
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/Compiler.h"
#include "compiler/translator/DetectCallDepth.h"
#include "compiler/translator/ForLoopUnroll.h"
@ -126,7 +125,8 @@ TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
maxCallStackDepth(0),
fragmentPrecisionHigh(false),
clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
builtInFunctionEmulator(type)
builtInFunctionEmulator(),
mSourcePath(NULL)
{
}
@ -159,33 +159,41 @@ bool TCompiler::Init(const ShBuiltInResources& resources)
return true;
}
bool TCompiler::compile(const char* const shaderStrings[],
size_t numStrings,
int compileOptions)
TIntermNode *TCompiler::compileTreeForTesting(const char* const shaderStrings[],
size_t numStrings, int compileOptions)
{
return compileTreeImpl(shaderStrings, numStrings, compileOptions);
}
TIntermNode *TCompiler::compileTreeImpl(const char* const shaderStrings[],
size_t numStrings, int compileOptions)
{
TScopedPoolAllocator scopedAlloc(&allocator);
clearResults();
if (numStrings == 0)
return true;
ASSERT(numStrings > 0);
ASSERT(GetGlobalPoolAllocator());
// Reset the extension behavior for each compilation unit.
ResetExtensionBehavior(extensionBehavior);
// If compiling for WebGL, validate loop and indexing as well.
if (IsWebGLBasedSpec(shaderSpec))
compileOptions |= SH_VALIDATE_LOOP_INDEXING;
// First string is path of source file if flag is set. The actual source follows.
const char* sourcePath = NULL;
size_t firstSource = 0;
if (compileOptions & SH_SOURCE_PATH)
{
sourcePath = shaderStrings[0];
mSourcePath = shaderStrings[0];
++firstSource;
}
bool debugShaderPrecision = getResources().WEBGL_debug_shader_precision == 1;
TIntermediate intermediate(infoSink);
TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
shaderType, shaderSpec, compileOptions, true,
sourcePath, infoSink);
infoSink, debugShaderPrecision);
parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh;
SetGlobalParseContext(&parseContext);
@ -206,6 +214,8 @@ bool TCompiler::compile(const char* const shaderStrings[],
success = false;
}
TIntermNode *root = NULL;
if (success)
{
mPragma = parseContext.pragma();
@ -214,7 +224,7 @@ bool TCompiler::compile(const char* const shaderStrings[],
symbolTable.setGlobalInvariant();
}
TIntermNode* root = parseContext.treeRoot;
root = parseContext.treeRoot;
success = intermediate.postProcess(root);
// Disallow expressions deemed too complex.
@ -255,8 +265,11 @@ bool TCompiler::compile(const char* const shaderStrings[],
}
// Built-in function emulation needs to happen after validateLimitations pass.
if (success && (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS))
if (success)
{
initBuiltInFunctionEmulator(&builtInFunctionEmulator, compileOptions);
builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root);
}
// Clamping uniform array bounds needs to happen after validateLimitations pass.
if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
@ -301,18 +314,37 @@ bool TCompiler::compile(const char* const shaderStrings[],
RegenerateStructNames gen(symbolTable, shaderVersion);
root->traverse(&gen);
}
if (success && (compileOptions & SH_INTERMEDIATE_TREE))
intermediate.outputTree(root);
if (success && (compileOptions & SH_OBJECT_CODE))
translate(root);
}
// Cleanup memory.
intermediate.remove(parseContext.treeRoot);
SetGlobalParseContext(NULL);
return success;
if (success)
return root;
return NULL;
}
bool TCompiler::compile(const char* const shaderStrings[],
size_t numStrings, int compileOptions)
{
if (numStrings == 0)
return true;
TScopedPoolAllocator scopedAlloc(&allocator);
TIntermNode *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);
if (root)
{
if (compileOptions & SH_INTERMEDIATE_TREE)
TIntermediate::outputTree(root, infoSink.info);
if (compileOptions & SH_OBJECT_CODE)
translate(root, compileOptions);
// The IntermNode tree doesn't need to be deleted here, since the
// memory will be freed in a big chunk by the PoolAllocator.
return true;
}
return false;
}
bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
@ -390,11 +422,15 @@ void TCompiler::setResourceString()
<< ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth
<< ":EXT_frag_depth:" << compileResources.EXT_frag_depth
<< ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod
<< ":EXT_shader_framebuffer_fetch:" << compileResources.EXT_shader_framebuffer_fetch
<< ":NV_shader_framebuffer_fetch:" << compileResources.NV_shader_framebuffer_fetch
<< ":ARM_shader_framebuffer_fetch:" << compileResources.ARM_shader_framebuffer_fetch
<< ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors
<< ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors
<< ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset
<< ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset
<< ":NV_draw_buffers:" << compileResources.NV_draw_buffers;
<< ":NV_draw_buffers:" << compileResources.NV_draw_buffers
<< ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision;
builtInResourcesString = strstream.str();
}
@ -416,27 +452,29 @@ void TCompiler::clearResults()
builtInFunctionEmulator.Cleanup();
nameMap.clear();
mSourcePath = NULL;
}
bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth)
bool TCompiler::detectCallDepth(TIntermNode* inputRoot, TInfoSink& inputInfoSink, bool limitCallStackDepth)
{
DetectCallDepth detect(infoSink, limitCallStackDepth, maxCallStackDepth);
root->traverse(&detect);
DetectCallDepth detect(inputInfoSink, limitCallStackDepth, maxCallStackDepth);
inputRoot->traverse(&detect);
switch (detect.detectCallDepth())
{
case DetectCallDepth::kErrorNone:
return true;
case DetectCallDepth::kErrorMissingMain:
infoSink.info.prefix(EPrefixError);
infoSink.info << "Missing main()";
inputInfoSink.info.prefix(EPrefixError);
inputInfoSink.info << "Missing main()";
return false;
case DetectCallDepth::kErrorRecursion:
infoSink.info.prefix(EPrefixError);
infoSink.info << "Function recursion detected";
inputInfoSink.info.prefix(EPrefixError);
inputInfoSink.info << "Function recursion detected";
return false;
case DetectCallDepth::kErrorMaxDepthExceeded:
infoSink.info.prefix(EPrefixError);
infoSink.info << "Function call stack too deep";
inputInfoSink.info.prefix(EPrefixError);
inputInfoSink.info << "Function call stack too deep";
return false;
default:
UNREACHABLE();
@ -594,6 +632,11 @@ const TExtensionBehavior& TCompiler::getExtensionBehavior() const
return extensionBehavior;
}
const char *TCompiler::getSourcePath() const
{
return mSourcePath;
}
const ShBuiltInResources& TCompiler::getResources() const
{
return compileResources;

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef _SHHANDLE_INCLUDED_
#define _SHHANDLE_INCLUDED_
#ifndef COMPILER_TRANSLATOR_COMPILER_H_
#define COMPILER_TRANSLATOR_COMPILER_H_
//
// Machine independent part of the compiler private objects
@ -25,7 +25,9 @@
class TCompiler;
class TDependencyGraph;
#ifdef ANGLE_ENABLE_HLSL
class TranslatorHLSL;
#endif // ANGLE_ENABLE_HLSL
//
// Helper function to identify specs that are based on the WebGL spec,
@ -41,7 +43,9 @@ public:
TShHandleBase();
virtual ~TShHandleBase();
virtual TCompiler* getAsCompiler() { return 0; }
#ifdef ANGLE_ENABLE_HLSL
virtual TranslatorHLSL* getAsTranslatorHLSL() { return 0; }
#endif // ANGLE_ENABLE_HLSL
protected:
// Memory allocator. Allocates and tracks memory required by the compiler.
@ -61,9 +65,15 @@ class TCompiler : public TShHandleBase
virtual TCompiler* getAsCompiler() { return this; }
bool Init(const ShBuiltInResources& resources);
// compileTreeForTesting should be used only when tests require access to
// the AST. Users of this function need to manually manage the global pool
// allocator. Returns NULL whenever there are compilation errors.
TIntermNode *compileTreeForTesting(const char* const shaderStrings[],
size_t numStrings, int compileOptions);
bool compile(const char* const shaderStrings[],
size_t numStrings,
int compileOptions);
size_t numStrings, int compileOptions);
// Get results of the last compilation.
int getShaderVersion() const { return shaderVersion; }
@ -104,8 +114,10 @@ class TCompiler : public TShHandleBase
bool validateLimitations(TIntermNode* root);
// Collect info for all attribs, uniforms, varyings.
void collectVariables(TIntermNode* root);
// Add emulated functions to the built-in function emulator.
virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) {};
// Translate to object code.
virtual void translate(TIntermNode* root) = 0;
virtual void translate(TIntermNode *root, int compileOptions) = 0;
// Returns true if, after applying the packing rules in the GLSL 1.017 spec
// Appendix A, section 7, the shader does not use too many uniforms.
bool enforcePackingRestrictions();
@ -130,6 +142,7 @@ class TCompiler : public TShHandleBase
bool limitExpressionComplexity(TIntermNode* root);
// Get built-in extensions with default behavior.
const TExtensionBehavior& getExtensionBehavior() const;
const char *getSourcePath() const;
const TPragma& getPragma() const { return mPragma; }
void writePragma();
@ -145,6 +158,9 @@ class TCompiler : public TShHandleBase
std::vector<sh::InterfaceBlock> interfaceBlocks;
private:
TIntermNode *compileTreeImpl(const char* const shaderStrings[],
size_t numStrings, int compileOptions);
sh::GLenum shaderType;
ShShaderSpec shaderSpec;
ShShaderOutput outputType;
@ -170,6 +186,7 @@ class TCompiler : public TShHandleBase
// Results of compilation.
int shaderVersion;
TInfoSink infoSink; // Output sink.
const char *mSourcePath; // Path of source file or NULL
// name hashing.
ShHashFunction64 hashFunction;
@ -191,4 +208,4 @@ TCompiler* ConstructCompiler(
sh::GLenum type, ShShaderSpec spec, ShShaderOutput output);
void DeleteCompiler(TCompiler*);
#endif // _SHHANDLE_INCLUDED_
#endif // COMPILER_TRANSLATOR_COMPILER_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef _CONSTANT_UNION_INCLUDED_
#define _CONSTANT_UNION_INCLUDED_
#ifndef COMPILER_TRANSLATOR_CONSTANTUNION_H_
#define COMPILER_TRANSLATOR_CONSTANTUNION_H_
#include <assert.h>
@ -254,7 +254,10 @@ public:
ConstantUnion operator<<(const ConstantUnion& constant) const
{
ConstantUnion returnValue;
assert(type == constant.type);
// The signedness of the second parameter might be different, but we
// don't care, since the result is undefined if the second parameter is
// negative, and aliasing should not be a problem with unions.
assert(constant.type == EbtInt || constant.type == EbtUInt);
switch (type) {
case EbtInt: returnValue.setIConst(iConst << constant.iConst); break;
case EbtUInt: returnValue.setUConst(uConst << constant.uConst); break;
@ -267,7 +270,7 @@ public:
ConstantUnion operator&(const ConstantUnion& constant) const
{
ConstantUnion returnValue;
assert(type == constant.type);
assert(constant.type == EbtInt || constant.type == EbtUInt);
switch (type) {
case EbtInt: returnValue.setIConst(iConst & constant.iConst); break;
case EbtUInt: returnValue.setUConst(uConst & constant.uConst); break;
@ -340,4 +343,4 @@ private:
TBasicType type;
};
#endif // _CONSTANT_UNION_INCLUDED_
#endif // COMPILER_TRANSLATOR_CONSTANTUNION_H_

View File

@ -33,7 +33,7 @@ int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDe
ASSERT(visit == PreVisit);
ASSERT(detectCallDepth);
int maxDepth = depth;
int retMaxDepth = depth;
visit = InVisit;
for (size_t i = 0; i < callees.size(); ++i) {
switch (callees[i]->visit) {
@ -52,7 +52,7 @@ int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDe
detectCallDepth->getInfoSink().info << "<-" << callees[i]->getName();
return callDepth;
}
maxDepth = std::max(callDepth, maxDepth);
retMaxDepth = std::max(callDepth, retMaxDepth);
break;
}
default:
@ -61,7 +61,7 @@ int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDe
}
}
visit = PostVisit;
return maxDepth;
return retMaxDepth;
}
void DetectCallDepth::FunctionNode::reset()

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILER_DETECT_RECURSION_H_
#define COMPILER_DETECT_RECURSION_H_
#ifndef COMPILER_TRANSLATOR_DETECTCALLDEPTH_H_
#define COMPILER_TRANSLATOR_DETECTCALLDEPTH_H_
#include <limits.h>
#include "compiler/translator/IntermNode.h"
@ -75,4 +75,4 @@ private:
void operator=(const DetectCallDepth&);
};
#endif // COMPILER_DETECT_RECURSION_H_
#endif // COMPILER_TRANSLATOR_DETECTCALLDEPTH_H_

View File

@ -8,8 +8,8 @@
// gradients of functions with discontinuities.
//
#ifndef COMPILER_DETECTDISCONTINUITY_H_
#define COMPILER_DETECTDISCONTINUITY_H_
#ifndef COMPILER_TRANSLATOR_DETECTDISCONTINUITY_H_
#define COMPILER_TRANSLATOR_DETECTDISCONTINUITY_H_
#include "compiler/translator/IntermNode.h"
@ -68,4 +68,4 @@ bool containsGradientOperation(TIntermNode *node);
}
#endif // COMPILER_DETECTDISCONTINUITY_H_
#endif // COMPILER_TRANSLATOR_DETECTDISCONTINUITY_H_

View File

@ -4,14 +4,15 @@
// found in the LICENSE file.
//
#ifndef COMPILER_DIAGNOSTICS_H_
#define COMPILER_DIAGNOSTICS_H_
#ifndef COMPILER_TRANSLATOR_DIAGNOSTICS_H_
#define COMPILER_TRANSLATOR_DIAGNOSTICS_H_
#include "common/angleutils.h"
#include "compiler/preprocessor/DiagnosticsBase.h"
class TInfoSink;
class TDiagnostics : public pp::Diagnostics
class TDiagnostics : public pp::Diagnostics, angle::NonCopyable
{
public:
TDiagnostics(TInfoSink& infoSink);
@ -41,4 +42,4 @@ class TDiagnostics : public pp::Diagnostics
int mNumWarnings;
};
#endif // COMPILER_DIAGNOSTICS_H_
#endif // COMPILER_TRANSLATOR_DIAGNOSTICS_H_

View File

@ -27,10 +27,12 @@ static TBehavior getBehavior(const std::string& str)
TDirectiveHandler::TDirectiveHandler(TExtensionBehavior& extBehavior,
TDiagnostics& diagnostics,
int& shaderVersion)
int& shaderVersion,
bool debugShaderPrecisionSupported)
: mExtensionBehavior(extBehavior),
mDiagnostics(diagnostics),
mShaderVersion(shaderVersion)
mShaderVersion(shaderVersion),
mDebugShaderPrecisionSupported(debugShaderPrecisionSupported)
{
}
@ -65,6 +67,7 @@ void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc,
{
const char kOptimize[] = "optimize";
const char kDebug[] = "debug";
const char kDebugShaderPrecision[] = "webgl_debug_shader_precision";
const char kOn[] = "on";
const char kOff[] = "off";
@ -81,6 +84,12 @@ void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc,
else if (value == kOff) mPragma.debug = false;
else invalidValue = true;
}
else if (name == kDebugShaderPrecision && mDebugShaderPrecisionSupported)
{
if (value == kOn) mPragma.debugShaderPrecision = true;
else if (value == kOff) mPragma.debugShaderPrecision = false;
else invalidValue = true;
}
else
{
mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name);

View File

@ -4,21 +4,23 @@
// found in the LICENSE file.
//
#ifndef COMPILER_DIRECTIVE_HANDLER_H_
#define COMPILER_DIRECTIVE_HANDLER_H_
#ifndef COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_
#define COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_
#include "common/angleutils.h"
#include "compiler/translator/ExtensionBehavior.h"
#include "compiler/translator/Pragma.h"
#include "compiler/preprocessor/DirectiveHandlerBase.h"
class TDiagnostics;
class TDirectiveHandler : public pp::DirectiveHandler
class TDirectiveHandler : public pp::DirectiveHandler, angle::NonCopyable
{
public:
TDirectiveHandler(TExtensionBehavior& extBehavior,
TDiagnostics& diagnostics,
int& shaderVersion);
int& shaderVersion,
bool debugShaderPrecisionSupported);
virtual ~TDirectiveHandler();
const TPragma& pragma() const { return mPragma; }
@ -44,6 +46,7 @@ class TDirectiveHandler : public pp::DirectiveHandler
TExtensionBehavior& mExtensionBehavior;
TDiagnostics& mDiagnostics;
int& mShaderVersion;
bool mDebugShaderPrecisionSupported;
};
#endif // COMPILER_DIRECTIVE_HANDLER_H_
#endif // COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_

View File

@ -0,0 +1,528 @@
//
// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "compiler/translator/EmulatePrecision.h"
namespace
{
static void writeVectorPrecisionEmulationHelpers(
TInfoSinkBase& sink, ShShaderOutput outputLanguage, unsigned int size)
{
std::stringstream vecTypeStrStr;
if (outputLanguage == SH_ESSL_OUTPUT)
vecTypeStrStr << "highp ";
vecTypeStrStr << "vec" << size;
std::string vecType = vecTypeStrStr.str();
sink <<
vecType << " angle_frm(in " << vecType << " v) {\n"
" v = clamp(v, -65504.0, 65504.0);\n"
" " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n"
" bvec" << size << " isNonZero = greaterThanEqual(exponent, vec" << size << "(-25.0));\n"
" v = v * exp2(-exponent);\n"
" v = sign(v) * floor(abs(v));\n"
" return v * exp2(exponent) * vec" << size << "(isNonZero);\n"
"}\n";
sink <<
vecType << " angle_frl(in " << vecType << " v) {\n"
" v = clamp(v, -2.0, 2.0);\n"
" v = v * 256.0;\n"
" v = sign(v) * floor(abs(v));\n"
" return v * 0.00390625;\n"
"}\n";
}
static void writeMatrixPrecisionEmulationHelper(
TInfoSinkBase& sink, ShShaderOutput outputLanguage, unsigned int size, const char *functionName)
{
std::stringstream matTypeStrStr;
if (outputLanguage == SH_ESSL_OUTPUT)
matTypeStrStr << "highp ";
matTypeStrStr << "mat" << size;
std::string matType = matTypeStrStr.str();
sink << matType << " " << functionName << "(in " << matType << " m) {\n"
" " << matType << " rounded;\n";
for (unsigned int i = 0; i < size; ++i)
{
sink << " rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n";
}
sink << " return rounded;\n"
"}\n";
}
static void writeCommonPrecisionEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage)
{
// Write the angle_frm functions that round floating point numbers to
// half precision, and angle_frl functions that round them to minimum lowp
// precision.
// Unoptimized version of angle_frm for single floats:
//
// int webgl_maxNormalExponent(in int exponentBits) {
// int possibleExponents = int(exp2(float(exponentBits)));
// int exponentBias = possibleExponents / 2 - 1;
// int allExponentBitsOne = possibleExponents - 1;
// return (allExponentBitsOne - 1) - exponentBias;
// }
//
// float angle_frm(in float x) {
// int mantissaBits = 10;
// int exponentBits = 5;
// float possibleMantissas = exp2(float(mantissaBits));
// float mantissaMax = 2.0 - 1.0 / possibleMantissas;
// int maxNE = webgl_maxNormalExponent(exponentBits);
// float max = exp2(float(maxNE)) * mantissaMax;
// if (x > max) {
// return max;
// }
// if (x < -max) {
// return -max;
// }
// float exponent = floor(log2(abs(x)));
// if (abs(x) == 0.0 || exponent < -float(maxNE)) {
// return 0.0 * sign(x)
// }
// x = x * exp2(-(exponent - float(mantissaBits)));
// x = sign(x) * floor(abs(x));
// return x * exp2(exponent - float(mantissaBits));
// }
// All numbers with a magnitude less than 2^-15 are subnormal, and are
// flushed to zero.
// Note the constant numbers below:
// a) 65504 is the maximum possible mantissa (1.1111111111 in binary) times
// 2^15, the maximum normal exponent.
// b) 10.0 is the number of mantissa bits.
// c) -25.0 is the minimum normal half-float exponent -15.0 minus the number
// of mantissa bits.
// d) + 1e-30 is to make sure the argument of log2() won't be zero. It can
// only affect the result of log2 on x where abs(x) < 1e-22. Since these
// numbers will be flushed to zero either way (2^-15 is the smallest
// normal positive number), this does not introduce any error.
std::string floatType = "float";
if (outputLanguage == SH_ESSL_OUTPUT)
floatType = "highp float";
sink <<
floatType << " angle_frm(in " << floatType << " x) {\n"
" x = clamp(x, -65504.0, 65504.0);\n"
" " << floatType << " exponent = floor(log2(abs(x) + 1e-30)) - 10.0;\n"
" bool isNonZero = (exponent >= -25.0);\n"
" x = x * exp2(-exponent);\n"
" x = sign(x) * floor(abs(x));\n"
" return x * exp2(exponent) * float(isNonZero);\n"
"}\n";
sink <<
floatType << " angle_frl(in " << floatType << " x) {\n"
" x = clamp(x, -2.0, 2.0);\n"
" x = x * 256.0;\n"
" x = sign(x) * floor(abs(x));\n"
" return x * 0.00390625;\n"
"}\n";
writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 2);
writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 3);
writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 4);
for (unsigned int size = 2; size <= 4; ++size)
{
writeMatrixPrecisionEmulationHelper(sink, outputLanguage, size, "angle_frm");
writeMatrixPrecisionEmulationHelper(sink, outputLanguage, size, "angle_frl");
}
}
static void writeCompoundAssignmentPrecisionEmulation(
TInfoSinkBase& sink, ShShaderOutput outputLanguage,
const char *lType, const char *rType, const char *opStr, const char *opNameStr)
{
std::string lTypeStr = lType;
std::string rTypeStr = rType;
if (outputLanguage == SH_ESSL_OUTPUT)
{
std::stringstream lTypeStrStr;
lTypeStrStr << "highp " << lType;
lTypeStr = lTypeStrStr.str();
std::stringstream rTypeStrStr;
rTypeStrStr << "highp " << rType;
rTypeStr = rTypeStrStr.str();
}
// Note that y should be passed through angle_frm at the function call site,
// but x can't be passed through angle_frm there since it is an inout parameter.
// So only pass x and the result through angle_frm here.
sink <<
lTypeStr << " angle_compound_" << opNameStr << "_frm(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n"
" x = angle_frm(angle_frm(x) " << opStr << " y);\n"
" return x;\n"
"}\n";
sink <<
lTypeStr << " angle_compound_" << opNameStr << "_frl(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n"
" x = angle_frl(angle_frm(x) " << opStr << " y);\n"
" return x;\n"
"}\n";
}
const char *getFloatTypeStr(const TType& type)
{
switch (type.getNominalSize())
{
case 1:
return "float";
case 2:
return type.getSecondarySize() > 1 ? "mat2" : "vec2";
case 3:
return type.getSecondarySize() > 1 ? "mat3" : "vec3";
case 4:
return type.getSecondarySize() > 1 ? "mat4" : "vec4";
default:
UNREACHABLE();
return NULL;
}
}
bool canRoundFloat(const TType &type)
{
return type.getBasicType() == EbtFloat && !type.isNonSquareMatrix() && !type.isArray() &&
(type.getPrecision() == EbpLow || type.getPrecision() == EbpMedium);
}
TIntermAggregate *createInternalFunctionCallNode(TString name, TIntermNode *child)
{
TIntermAggregate *callNode = new TIntermAggregate();
callNode->setOp(EOpInternalFunctionCall);
callNode->setName(name);
callNode->getSequence()->push_back(child);
return callNode;
}
TIntermAggregate *createRoundingFunctionCallNode(TIntermTyped *roundedChild)
{
TString roundFunctionName;
if (roundedChild->getPrecision() == EbpMedium)
roundFunctionName = "angle_frm";
else
roundFunctionName = "angle_frl";
return createInternalFunctionCallNode(roundFunctionName, roundedChild);
}
TIntermAggregate *createCompoundAssignmentFunctionCallNode(TIntermTyped *left, TIntermTyped *right, const char *opNameStr)
{
std::stringstream strstr;
if (left->getPrecision() == EbpMedium)
strstr << "angle_compound_" << opNameStr << "_frm";
else
strstr << "angle_compound_" << opNameStr << "_frl";
TString functionName = strstr.str().c_str();
TIntermAggregate *callNode = createInternalFunctionCallNode(functionName, left);
callNode->getSequence()->push_back(right);
return callNode;
}
bool parentUsesResult(TIntermNode* parent, TIntermNode* node)
{
if (!parent)
{
return false;
}
TIntermAggregate *aggParent = parent->getAsAggregate();
// If the parent's op is EOpSequence, the result is not assigned anywhere,
// so rounding it is not needed. In particular, this can avoid a lot of
// unnecessary rounding of unused return values of assignment.
if (aggParent && aggParent->getOp() == EOpSequence)
{
return false;
}
if (aggParent && aggParent->getOp() == EOpComma && (aggParent->getSequence()->back() != node))
{
return false;
}
return true;
}
} // namespace anonymous
EmulatePrecision::EmulatePrecision()
: TIntermTraverser(true, true, true),
mDeclaringVariables(false),
mInLValue(false),
mInFunctionCallOutParameter(false)
{}
void EmulatePrecision::visitSymbol(TIntermSymbol *node)
{
if (canRoundFloat(node->getType()) &&
!mDeclaringVariables && !mInLValue && !mInFunctionCallOutParameter)
{
TIntermNode *parent = getParentNode();
TIntermNode *replacement = createRoundingFunctionCallNode(node);
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
}
}
bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node)
{
bool visitChildren = true;
if (node->isAssignment())
{
if (visit == PreVisit)
mInLValue = true;
else if (visit == InVisit)
mInLValue = false;
}
TOperator op = node->getOp();
// RHS of initialize is not being declared.
if (op == EOpInitialize && visit == InVisit)
mDeclaringVariables = false;
if ((op == EOpIndexDirectStruct || op == EOpVectorSwizzle) && visit == InVisit)
visitChildren = false;
if (visit != PreVisit)
return visitChildren;
const TType& type = node->getType();
bool roundFloat = canRoundFloat(type);
if (roundFloat) {
switch (op) {
// Math operators that can result in a float may need to apply rounding to the return
// value. Note that in the case of assignment, the rounding is applied to its return
// value here, not the value being assigned.
case EOpAssign:
case EOpAdd:
case EOpSub:
case EOpMul:
case EOpDiv:
case EOpVectorTimesScalar:
case EOpVectorTimesMatrix:
case EOpMatrixTimesVector:
case EOpMatrixTimesScalar:
case EOpMatrixTimesMatrix:
{
TIntermNode *parent = getParentNode();
if (!parentUsesResult(parent, node))
{
break;
}
TIntermNode *replacement = createRoundingFunctionCallNode(node);
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
break;
}
// Compound assignment cases need to replace the operator with a function call.
case EOpAddAssign:
{
mEmulateCompoundAdd.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType())));
TIntermNode *parent = getParentNode();
TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "add");
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
break;
}
case EOpSubAssign:
{
mEmulateCompoundSub.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType())));
TIntermNode *parent = getParentNode();
TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "sub");
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
break;
}
case EOpMulAssign:
case EOpVectorTimesMatrixAssign:
case EOpVectorTimesScalarAssign:
case EOpMatrixTimesScalarAssign:
case EOpMatrixTimesMatrixAssign:
{
mEmulateCompoundMul.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType())));
TIntermNode *parent = getParentNode();
TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "mul");
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
break;
}
case EOpDivAssign:
{
mEmulateCompoundDiv.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType())));
TIntermNode *parent = getParentNode();
TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "div");
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
break;
}
default:
// The rest of the binary operations should not need precision emulation.
break;
}
}
return visitChildren;
}
bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node)
{
bool visitChildren = true;
switch (node->getOp())
{
case EOpSequence:
case EOpConstructStruct:
// No special handling
break;
case EOpFunction:
if (visit == PreVisit)
{
const TIntermSequence &sequence = *(node->getSequence());
TIntermSequence::const_iterator seqIter = sequence.begin();
TIntermAggregate *params = (*seqIter)->getAsAggregate();
ASSERT(params != NULL);
ASSERT(params->getOp() == EOpParameters);
mFunctionMap[node->getName()] = params->getSequence();
}
break;
case EOpPrototype:
if (visit == PreVisit)
mFunctionMap[node->getName()] = node->getSequence();
visitChildren = false;
break;
case EOpParameters:
visitChildren = false;
break;
case EOpInvariantDeclaration:
visitChildren = false;
break;
case EOpDeclaration:
// Variable declaration.
if (visit == PreVisit)
{
mDeclaringVariables = true;
}
else if (visit == InVisit)
{
mDeclaringVariables = true;
}
else
{
mDeclaringVariables = false;
}
break;
case EOpFunctionCall:
{
// Function call.
bool inFunctionMap = (mFunctionMap.find(node->getName()) != mFunctionMap.end());
if (visit == PreVisit)
{
// User-defined function return values are not rounded, this relies on that
// calculations producing the value were rounded.
TIntermNode *parent = getParentNode();
if (canRoundFloat(node->getType()) && !inFunctionMap && parentUsesResult(parent, node))
{
TIntermNode *replacement = createRoundingFunctionCallNode(node);
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
}
if (inFunctionMap)
{
mSeqIterStack.push_back(mFunctionMap[node->getName()]->begin());
if (mSeqIterStack.back() != mFunctionMap[node->getName()]->end())
{
TQualifier qualifier = (*mSeqIterStack.back())->getAsTyped()->getQualifier();
mInFunctionCallOutParameter = (qualifier == EvqOut || qualifier == EvqInOut);
}
}
else
{
// The function is not user-defined - it is likely built-in texture function.
// Assume that those do not have out parameters.
mInFunctionCallOutParameter = false;
}
}
else if (visit == InVisit)
{
if (inFunctionMap)
{
++mSeqIterStack.back();
TQualifier qualifier = (*mSeqIterStack.back())->getAsTyped()->getQualifier();
mInFunctionCallOutParameter = (qualifier == EvqOut || qualifier == EvqInOut);
}
}
else
{
if (inFunctionMap)
{
mSeqIterStack.pop_back();
mInFunctionCallOutParameter = false;
}
}
break;
}
default:
TIntermNode *parent = getParentNode();
if (canRoundFloat(node->getType()) && visit == PreVisit && parentUsesResult(parent, node))
{
TIntermNode *replacement = createRoundingFunctionCallNode(node);
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
}
break;
}
return visitChildren;
}
bool EmulatePrecision::visitUnary(Visit visit, TIntermUnary *node)
{
switch (node->getOp())
{
case EOpNegative:
case EOpVectorLogicalNot:
case EOpLogicalNot:
break;
case EOpPostIncrement:
case EOpPostDecrement:
case EOpPreIncrement:
case EOpPreDecrement:
if (visit == PreVisit)
mInLValue = true;
else if (visit == PostVisit)
mInLValue = false;
break;
default:
if (canRoundFloat(node->getType()) && visit == PreVisit)
{
TIntermNode *parent = getParentNode();
TIntermNode *replacement = createRoundingFunctionCallNode(node);
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
}
break;
}
return true;
}
void EmulatePrecision::writeEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage)
{
// Other languages not yet supported
ASSERT(outputLanguage == SH_GLSL_COMPATIBILITY_OUTPUT ||
outputLanguage == SH_GLSL_CORE_OUTPUT ||
outputLanguage == SH_ESSL_OUTPUT);
writeCommonPrecisionEmulationHelpers(sink, outputLanguage);
EmulationSet::const_iterator it;
for (it = mEmulateCompoundAdd.begin(); it != mEmulateCompoundAdd.end(); it++)
writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "+", "add");
for (it = mEmulateCompoundSub.begin(); it != mEmulateCompoundSub.end(); it++)
writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "-", "sub");
for (it = mEmulateCompoundDiv.begin(); it != mEmulateCompoundDiv.end(); it++)
writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "/", "div");
for (it = mEmulateCompoundMul.begin(); it != mEmulateCompoundMul.end(); it++)
writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "*", "mul");
}

View File

@ -0,0 +1,74 @@
//
// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#ifndef COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
#define COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
#include "common/angleutils.h"
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h"
#include "GLSLANG/ShaderLang.h"
// This class gathers all compound assignments from the AST and can then write
// the functions required for their precision emulation. This way there is no
// need to write a huge number of variations of the emulated compound assignment
// to every translated shader with emulation enabled.
class EmulatePrecision : public TIntermTraverser
{
public:
EmulatePrecision();
virtual void visitSymbol(TIntermSymbol *node);
virtual bool visitBinary(Visit visit, TIntermBinary *node);
virtual bool visitUnary(Visit visit, TIntermUnary *node);
virtual bool visitAggregate(Visit visit, TIntermAggregate *node);
void writeEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage);
private:
struct TypePair
{
TypePair(const char *l, const char *r)
: lType(l), rType(r) { }
const char *lType;
const char *rType;
};
struct TypePairComparator
{
bool operator() (const TypePair& l, const TypePair& r) const
{
if (l.lType == r.lType)
return l.rType < r.rType;
return l.lType < r.lType;
}
};
typedef std::set<TypePair, TypePairComparator> EmulationSet;
EmulationSet mEmulateCompoundAdd;
EmulationSet mEmulateCompoundSub;
EmulationSet mEmulateCompoundMul;
EmulationSet mEmulateCompoundDiv;
// Stack of function call parameter iterators
std::vector<TIntermSequence::const_iterator> mSeqIterStack;
bool mDeclaringVariables;
bool mInLValue;
bool mInFunctionCallOutParameter;
struct TStringComparator
{
bool operator() (const TString& a, const TString& b) const { return a.compare(b) < 0; }
};
// Map from function names to their parameter sequences
std::map<TString, TIntermSequence*, TStringComparator> mFunctionMap;
};
#endif // COMPILER_TRANSLATOR_EMULATE_PRECISION_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef _EXTENSION_BEHAVIOR_INCLUDED_
#define _EXTENSION_BEHAVIOR_INCLUDED_
#ifndef COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_
#define COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_
#include <map>
#include <string>
@ -34,4 +34,4 @@ inline const char* getBehaviorString(TBehavior b)
// Mapping between extension name and behavior.
typedef std::map<std::string, TBehavior> TExtensionBehavior;
#endif // _EXTENSION_TABLE_INCLUDED_
#endif // COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILER_FLAGSTD140STRUCTS_H_
#define COMPILER_FLAGSTD140STRUCTS_H_
#ifndef COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_
#define COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_
#include "compiler/translator/IntermNode.h"
@ -34,4 +34,4 @@ std::vector<TIntermTyped *> FlagStd140ValueStructs(TIntermNode *node);
}
#endif // COMPILER_FLAGSTD140STRUCTS_H_
#endif // COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILER_FORLOOPUNROLL_H_
#define COMPILER_FORLOOPUNROLL_H_
#ifndef COMPILER_TRANSLATOR_FORLOOPUNROLL_H_
#define COMPILER_TRANSLATOR_FORLOOPUNROLL_H_
#include "compiler/translator/LoopInfo.h"
@ -47,4 +47,4 @@ class ForLoopUnrollMarker : public TIntermTraverser
bool mVisitSamplerArrayIndexNodeInsideLoop;
};
#endif
#endif // COMPILER_TRANSLATOR_FORLOOPUNROLL_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILER_HASH_NAMES_H_
#define COMPILER_HASH_NAMES_H_
#ifndef COMPILER_TRANSLATOR_HASHNAMES_H_
#define COMPILER_TRANSLATOR_HASHNAMES_H_
#include <map>
@ -15,4 +15,4 @@
typedef std::map<TPersistString, TPersistString> NameMap;
#endif // COMPILER_HASH_NAMES_H_
#endif // COMPILER_TRANSLATOR_HASHNAMES_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef _INFOSINK_INCLUDED_
#define _INFOSINK_INCLUDED_
#ifndef COMPILER_TRANSLATOR_INFOSINK_H_
#define COMPILER_TRANSLATOR_INFOSINK_H_
#include <math.h>
#include <stdlib.h>
@ -113,4 +113,4 @@ public:
TInfoSinkBase obj;
};
#endif // _INFOSINK_INCLUDED_
#endif // COMPILER_TRANSLATOR_INFOSINK_H_

View File

@ -21,307 +21,208 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
TType *float2 = new TType(EbtFloat, 2);
TType *float3 = new TType(EbtFloat, 3);
TType *float4 = new TType(EbtFloat, 4);
TType *int1 = new TType(EbtInt);
TType *int2 = new TType(EbtInt, 2);
TType *int3 = new TType(EbtInt, 3);
TType *int4 = new TType(EbtInt, 4);
TType *uint1 = new TType(EbtUInt);
TType *bool1 = new TType(EbtBool);
TType *genType = new TType(EbtGenType);
TType *genIType = new TType(EbtGenIType);
TType *genUType = new TType(EbtGenUType);
TType *genBType = new TType(EbtGenBType);
//
// Angle and Trigonometric Functions.
//
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "radians", float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "radians", float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "radians", float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "radians", float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "degrees", float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "degrees", float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "degrees", float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "degrees", float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "sin", float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "sin", float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "sin", float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "sin", float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "cos", float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "cos", float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "cos", float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "cos", float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "tan", float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "tan", float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "tan", float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "tan", float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "asin", float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "asin", float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "asin", float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "asin", float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "acos", float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "acos", float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "acos", float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "acos", float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "atan", float1, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "atan", float2, float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "atan", float3, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "atan", float4, float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "atan", float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "atan", float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "atan", float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "atan", float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpRadians, genType, "radians", genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpDegrees, genType, "degrees", genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSin, genType, "sin", genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpCos, genType, "cos", genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpTan, genType, "tan", genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAsin, genType, "asin", genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAcos, genType, "acos", genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAtan, genType, "atan", genType, genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAtan, genType, "atan", genType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpSinh, genType, "sinh", genType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpCosh, genType, "cosh", genType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTanh, genType, "tanh", genType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAsinh, genType, "asinh", genType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAcosh, genType, "acosh", genType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAtanh, genType, "atanh", genType);
//
// Exponential Functions.
//
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "pow", float1, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "pow", float2, float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "pow", float3, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "pow", float4, float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "exp", float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "exp", float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "exp", float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "exp", float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "log", float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "log", float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "log", float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "log", float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "exp2", float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "exp2", float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "exp2", float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "exp2", float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "log2", float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "log2", float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "log2", float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "log2", float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "sqrt", float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "sqrt", float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "sqrt", float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "sqrt", float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "inversesqrt", float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "inversesqrt", float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "inversesqrt", float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "inversesqrt", float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpPow, genType, "pow", genType, genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpExp, genType, "exp", genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLog, genType, "log", genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpExp2, genType, "exp2", genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLog2, genType, "log2", genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSqrt, genType, "sqrt", genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpInverseSqrt, genType, "inversesqrt", genType);
//
// Common Functions.
//
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "abs", float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "abs", float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "abs", float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "abs", float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAbs, genType, "abs", genType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAbs, genIType, "abs", genIType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSign, genType, "sign", genType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpSign, genIType, "sign", genIType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFloor, genType, "floor", genType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTrunc, genType, "trunc", genType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpRound, genType, "round", genType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpRoundEven, genType, "roundEven", genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpCeil, genType, "ceil", genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFract, genType, "fract", genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMod, genType, "mod", genType, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMod, genType, "mod", genType, genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMin, genType, "min", genType, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMin, genType, "min", genType, genType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genIType, "min", genIType, genIType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genIType, "min", genIType, int1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genUType, "min", genUType, genUType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genUType, "min", genUType, uint1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMax, genType, "max", genType, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMax, genType, "max", genType, genType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genIType, "max", genIType, genIType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genIType, "max", genIType, int1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genUType, "max", genUType, genUType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genUType, "max", genUType, uint1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpClamp, genType, "clamp", genType, float1, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpClamp, genType, "clamp", genType, genType, genType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genIType, "clamp", genIType, int1, int1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genIType, "clamp", genIType, genIType, genIType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genUType, "clamp", genUType, uint1, uint1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genUType, "clamp", genUType, genUType, genUType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMix, genType, "mix", genType, genType, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMix, genType, "mix", genType, genType, genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpStep, genType, "step", genType, genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpStep, genType, "step", float1, genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSmoothStep, genType, "smoothstep", genType, genType, genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSmoothStep, genType, "smoothstep", float1, float1, genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "sign", float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "sign", float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "sign", float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "sign", float4);
TType *outFloat1 = new TType(EbtFloat);
TType *outFloat2 = new TType(EbtFloat, 2);
TType *outFloat3 = new TType(EbtFloat, 3);
TType *outFloat4 = new TType(EbtFloat, 4);
outFloat1->setQualifier(EvqOut);
outFloat2->setQualifier(EvqOut);
outFloat3->setQualifier(EvqOut);
outFloat4->setQualifier(EvqOut);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "floor", float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "floor", float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "floor", float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "floor", float4);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float1, "modf", float1, outFloat1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float2, "modf", float2, outFloat2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float3, "modf", float3, outFloat3);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float4, "modf", float4, outFloat4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "ceil", float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "ceil", float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "ceil", float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "ceil", float4);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpIsNan, genBType, "isnan", genType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpIsInf, genBType, "isinf", genType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpFloatBitsToInt, genIType, "floatBitsToInt", genType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpFloatBitsToUint, genUType, "floatBitsToUint", genType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpIntBitsToFloat, genType, "intBitsToFloat", genIType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUintBitsToFloat, genType, "uintBitsToFloat", genUType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "fract", float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "fract", float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "fract", float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "fract", float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "mod", float1, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "mod", float2, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "mod", float3, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "mod", float4, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "mod", float2, float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "mod", float3, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "mod", float4, float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "min", float1, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "min", float2, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "min", float3, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "min", float4, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "min", float2, float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "min", float3, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "min", float4, float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "max", float1, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "max", float2, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "max", float3, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "max", float4, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "max", float2, float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "max", float3, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "max", float4, float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "clamp", float1, float1, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "clamp", float2, float1, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "clamp", float3, float1, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "clamp", float4, float1, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "clamp", float2, float2, float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "clamp", float3, float3, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "clamp", float4, float4, float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "mix", float1, float1, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "mix", float2, float2, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "mix", float3, float3, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "mix", float4, float4, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "mix", float2, float2, float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "mix", float3, float3, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "mix", float4, float4, float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "step", float1, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "step", float2, float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "step", float3, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "step", float4, float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "step", float1, float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "step", float1, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "step", float1, float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "smoothstep", float1, float1, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "smoothstep", float2, float2, float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "smoothstep", float3, float3, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "smoothstep", float4, float4, float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "smoothstep", float1, float1, float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "smoothstep", float1, float1, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "smoothstep", float1, float1, float4);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpPackSnorm2x16, uint1, "packSnorm2x16", float2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpPackUnorm2x16, uint1, "packUnorm2x16", float2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpPackHalf2x16, uint1, "packHalf2x16", float2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUnpackSnorm2x16, float2, "unpackSnorm2x16", uint1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUnpackUnorm2x16, float2, "unpackUnorm2x16", uint1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUnpackHalf2x16, float2, "unpackHalf2x16", uint1);
//
// Geometric Functions.
//
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "length", float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "length", float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "length", float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "length", float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "distance", float1, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "distance", float2, float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "distance", float3, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "distance", float4, float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "dot", float1, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "dot", float2, float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "dot", float3, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "dot", float4, float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "cross", float3, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "normalize", float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "normalize", float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "normalize", float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "normalize", float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "faceforward", float1, float1, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "faceforward", float2, float2, float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "faceforward", float3, float3, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "faceforward", float4, float4, float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "reflect", float1, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "reflect", float2, float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "reflect", float3, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "reflect", float4, float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "refract", float1, float1, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "refract", float2, float2, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "refract", float3, float3, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "refract", float4, float4, float1);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLength, float1, "length", genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpDistance, float1, "distance", genType, genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpDot, float1, "dot", genType, genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpCross, float3, "cross", float3, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpNormalize, genType, "normalize", genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFaceForward, genType, "faceforward", genType, genType, genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpReflect, genType, "reflect", genType, genType);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpRefract, genType, "refract", genType, genType, float1);
TType *mat2 = new TType(EbtFloat, 2, 2);
TType *mat3 = new TType(EbtFloat, 3, 3);
TType *mat4 = new TType(EbtFloat, 4, 4);
TType *mat2x3 = new TType(EbtFloat, 2, 3);
TType *mat3x2 = new TType(EbtFloat, 3, 2);
TType *mat2x4 = new TType(EbtFloat, 2, 4);
TType *mat4x2 = new TType(EbtFloat, 4, 2);
TType *mat3x4 = new TType(EbtFloat, 3, 4);
TType *mat4x3 = new TType(EbtFloat, 4, 3);
//
// Matrix Functions.
//
symbolTable.insertBuiltIn(COMMON_BUILTINS, mat2, "matrixCompMult", mat2, mat2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, mat3, "matrixCompMult", mat3, mat3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, mat4, "matrixCompMult", mat4, mat4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMul, mat2, "matrixCompMult", mat2, mat2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMul, mat3, "matrixCompMult", mat3, mat3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMul, mat4, "matrixCompMult", mat4, mat4);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat2x3, "matrixCompMult", mat2x3, mat2x3);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat3x2, "matrixCompMult", mat3x2, mat3x2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat2x4, "matrixCompMult", mat2x4, mat2x4);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat4x2, "matrixCompMult", mat4x2, mat4x2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat3x4, "matrixCompMult", mat3x4, mat3x4);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat4x3, "matrixCompMult", mat4x3, mat4x3);
TType *bool1 = new TType(EbtBool);
TType *bool2 = new TType(EbtBool, 2);
TType *bool3 = new TType(EbtBool, 3);
TType *bool4 = new TType(EbtBool, 4);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat2, "outerProduct", float2, float2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat3, "outerProduct", float3, float3);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat4, "outerProduct", float4, float4);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat2x3, "outerProduct", float3, float2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat3x2, "outerProduct", float2, float3);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat2x4, "outerProduct", float4, float2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat4x2, "outerProduct", float2, float4);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat3x4, "outerProduct", float4, float3);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat4x3, "outerProduct", float3, float4);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat2, "transpose", mat2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat3, "transpose", mat3);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat4, "transpose", mat4);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat2x3, "transpose", mat3x2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat3x2, "transpose", mat2x3);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat2x4, "transpose", mat4x2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat4x2, "transpose", mat2x4);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat3x4, "transpose", mat4x3);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat4x3, "transpose", mat3x4);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDeterminant, float1, "determinant", mat2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDeterminant, float1, "determinant", mat3);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDeterminant, float1, "determinant", mat4);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat2, "inverse", mat2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat3, "inverse", mat3);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat4, "inverse", mat4);
TType *vec = new TType(EbtVec);
TType *ivec = new TType(EbtIVec);
TType *uvec = new TType(EbtUVec);
TType *bvec = new TType(EbtBVec);
//
// Vector relational functions.
//
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "lessThan", float2, float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "lessThan", float3, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "lessThan", float4, float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "lessThan", int2, int2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "lessThan", int3, int3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "lessThan", int4, int4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "lessThanEqual", float2, float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "lessThanEqual", float3, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "lessThanEqual", float4, float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "lessThanEqual", int2, int2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "lessThanEqual", int3, int3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "lessThanEqual", int4, int4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "greaterThan", float2, float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "greaterThan", float3, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "greaterThan", float4, float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "greaterThan", int2, int2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "greaterThan", int3, int3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "greaterThan", int4, int4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "greaterThanEqual", float2, float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "greaterThanEqual", float3, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "greaterThanEqual", float4, float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "greaterThanEqual", int2, int2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "greaterThanEqual", int3, int3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "greaterThanEqual", int4, int4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "equal", float2, float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "equal", float3, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "equal", float4, float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "equal", int2, int2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "equal", int3, int3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "equal", int4, int4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "equal", bool2, bool2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "equal", bool3, bool3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "equal", bool4, bool4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "notEqual", float2, float2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "notEqual", float3, float3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "notEqual", float4, float4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "notEqual", int2, int2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "notEqual", int3, int3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "notEqual", int4, int4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "notEqual", bool2, bool2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "notEqual", bool3, bool3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "notEqual", bool4, bool4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "any", bool2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "any", bool3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "any", bool4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "all", bool2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "all", bool3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "all", bool4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "not", bool2);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "not", bool3);
symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "not", bool4);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThan, bvec, "lessThan", vec, vec);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThan, bvec, "lessThan", ivec, ivec);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpLessThan, bvec, "lessThan", uvec, uvec);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThanEqual, bvec, "lessThanEqual", vec, vec);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThanEqual, bvec, "lessThanEqual", ivec, ivec);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpLessThanEqual, bvec, "lessThanEqual", uvec, uvec);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThan, bvec, "greaterThan", vec, vec);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThan, bvec, "greaterThan", ivec, ivec);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpGreaterThan, bvec, "greaterThan", uvec, uvec);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThanEqual, bvec, "greaterThanEqual", vec, vec);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThanEqual, bvec, "greaterThanEqual", ivec, ivec);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpGreaterThanEqual, bvec, "greaterThanEqual", uvec, uvec);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorEqual, bvec, "equal", vec, vec);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorEqual, bvec, "equal", ivec, ivec);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpVectorEqual, bvec, "equal", uvec, uvec);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorEqual, bvec, "equal", bvec, bvec);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", vec, vec);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", ivec, ivec);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", uvec, uvec);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", bvec, bvec);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAny, bool1, "any", bvec);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAll, bool1, "all", bvec);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorLogicalNot, bvec, "not", bvec);
TType *sampler2D = new TType(EbtSampler2D);
TType *samplerCube = new TType(EbtSamplerCube);
@ -357,10 +258,10 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
/* The *Grad* variants are new to both vertex and fragment shaders; the fragment
* shader specific pieces are added separately below.
*/
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DGradEXT", sampler2D, float2, float2, float2);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjGradEXT", sampler2D, float3, float2, float2);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjGradEXT", sampler2D, float4, float2, float2);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCubeGradEXT", samplerCube, float3, float3, float3);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DGradEXT", sampler2D, float2, float2, float2);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DProjGradEXT", sampler2D, float3, float2, float2);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DProjGradEXT", sampler2D, float4, float2, float2);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "textureCubeGradEXT", samplerCube, float3, float3, float3);
}
if (type == GL_FRAGMENT_SHADER)
@ -372,32 +273,21 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
if (resources.OES_standard_derivatives)
{
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float1, "dFdx", float1);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float2, "dFdx", float2);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float3, "dFdx", float3);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "dFdx", float4);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float1, "dFdy", float1);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float2, "dFdy", float2);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float3, "dFdy", float3);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "dFdy", float4);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float1, "fwidth", float1);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float2, "fwidth", float2);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float3, "fwidth", float3);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "fwidth", float4);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, EOpDFdx, "GL_OES_standard_derivatives", genType, "dFdx", genType);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, EOpDFdy, "GL_OES_standard_derivatives", genType, "dFdy", genType);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, EOpFwidth, "GL_OES_standard_derivatives", genType, "fwidth", genType);
}
if (resources.EXT_shader_texture_lod)
{
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DLodEXT", sampler2D, float2, float1);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLodEXT", sampler2D, float3, float1);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLodEXT", sampler2D, float4, float1);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCubeLodEXT", samplerCube, float3, float1);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DLodEXT", sampler2D, float2, float1);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DProjLodEXT", sampler2D, float3, float1);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DProjLodEXT", sampler2D, float4, float1);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "textureCubeLodEXT", samplerCube, float3, float1);
}
}
if(type == GL_VERTEX_SHADER)
if (type == GL_VERTEX_SHADER)
{
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DLod", sampler2D, float2, float1);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLod", sampler2D, float3, float1);
@ -463,22 +353,11 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", samplerCubeShadow, int1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", sampler2DArrayShadow, int1);
if(type == GL_FRAGMENT_SHADER)
if (type == GL_FRAGMENT_SHADER)
{
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "dFdx", float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float2, "dFdx", float2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float3, "dFdx", float3);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "dFdx", float4);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "dFdy", float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float2, "dFdy", float2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float3, "dFdy", float3);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "dFdy", float4);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "fwidth", float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float2, "fwidth", float2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float3, "fwidth", float3);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "fwidth", float4);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDFdx, genType, "dFdx", genType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDFdy, genType, "dFdy", genType);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpFwidth, genType, "fwidth", genType);
}
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2D, float2, int2);
@ -486,7 +365,7 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureOffset", sampler2DShadow, float3, int2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2DArray, float3, int2);
if(type == GL_FRAGMENT_SHADER)
if (type == GL_FRAGMENT_SHADER)
{
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2D, float2, int2, float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler3D, float3, int3, float1);
@ -499,7 +378,7 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler3D, float4, int3);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjOffset", sampler2DShadow, float4, int2);
if(type == GL_FRAGMENT_SHADER)
if (type == GL_FRAGMENT_SHADER)
{
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float3, int2, float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float4, int2, float1);
@ -600,146 +479,84 @@ void IdentifyBuiltIns(sh::GLenum type, ShShaderSpec spec,
TSymbolTable &symbolTable)
{
//
// First, insert some special built-in variables that are not in
// Insert some special built-in variables that are not in
// the built-in header files.
//
switch(type) {
case GL_FRAGMENT_SHADER:
symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EbpMedium, EvqFragCoord, 4)));
symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EbpUndefined, EvqFrontFacing, 1)));
symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EbpMedium, EvqPointCoord, 2)));
switch (type)
{
case GL_FRAGMENT_SHADER:
symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FragCoord"),
TType(EbtFloat, EbpMedium, EvqFragCoord, 4)));
symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FrontFacing"),
TType(EbtBool, EbpUndefined, EvqFrontFacing, 1)));
symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointCoord"),
TType(EbtFloat, EbpMedium, EvqPointCoord, 2)));
//
// In CSS Shaders, gl_FragColor, gl_FragData, and gl_MaxDrawBuffers are not available.
// Instead, css_MixColor and css_ColorMatrix are available.
//
if (spec != SH_CSS_SHADERS_SPEC) {
symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4)));
symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4)));
if (resources.EXT_frag_depth) {
symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragDepthEXT"), TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1)));
symbolTable.relateToExtension(ESSL1_BUILTINS, "gl_FragDepthEXT", "GL_EXT_frag_depth");
}
} else {
symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_MixColor"), TType(EbtFloat, EbpMedium, EvqGlobal, 4)));
symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_ColorMatrix"), TType(EbtFloat, EbpMedium, EvqGlobal, 4, 4)));
}
break;
case GL_VERTEX_SHADER:
symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EbpHigh, EvqPosition, 4)));
symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EbpMedium, EvqPointSize, 1)));
break;
default: assert(false && "Language not supported");
}
//
// Next, identify which built-ins from the already loaded headers have
// a mapping to an operator. Those that are not identified as such are
// expected to be resolved through a library of functions, versus as
// operations.
//
symbolTable.relateToOperator(COMMON_BUILTINS, "matrixCompMult", EOpMul);
symbolTable.relateToOperator(COMMON_BUILTINS, "equal", EOpVectorEqual);
symbolTable.relateToOperator(COMMON_BUILTINS, "notEqual", EOpVectorNotEqual);
symbolTable.relateToOperator(COMMON_BUILTINS, "lessThan", EOpLessThan);
symbolTable.relateToOperator(COMMON_BUILTINS, "greaterThan", EOpGreaterThan);
symbolTable.relateToOperator(COMMON_BUILTINS, "lessThanEqual", EOpLessThanEqual);
symbolTable.relateToOperator(COMMON_BUILTINS, "greaterThanEqual", EOpGreaterThanEqual);
symbolTable.relateToOperator(COMMON_BUILTINS, "radians", EOpRadians);
symbolTable.relateToOperator(COMMON_BUILTINS, "degrees", EOpDegrees);
symbolTable.relateToOperator(COMMON_BUILTINS, "sin", EOpSin);
symbolTable.relateToOperator(COMMON_BUILTINS, "cos", EOpCos);
symbolTable.relateToOperator(COMMON_BUILTINS, "tan", EOpTan);
symbolTable.relateToOperator(COMMON_BUILTINS, "asin", EOpAsin);
symbolTable.relateToOperator(COMMON_BUILTINS, "acos", EOpAcos);
symbolTable.relateToOperator(COMMON_BUILTINS, "atan", EOpAtan);
symbolTable.relateToOperator(COMMON_BUILTINS, "pow", EOpPow);
symbolTable.relateToOperator(COMMON_BUILTINS, "exp2", EOpExp2);
symbolTable.relateToOperator(COMMON_BUILTINS, "log", EOpLog);
symbolTable.relateToOperator(COMMON_BUILTINS, "exp", EOpExp);
symbolTable.relateToOperator(COMMON_BUILTINS, "log2", EOpLog2);
symbolTable.relateToOperator(COMMON_BUILTINS, "sqrt", EOpSqrt);
symbolTable.relateToOperator(COMMON_BUILTINS, "inversesqrt", EOpInverseSqrt);
symbolTable.relateToOperator(COMMON_BUILTINS, "abs", EOpAbs);
symbolTable.relateToOperator(COMMON_BUILTINS, "sign", EOpSign);
symbolTable.relateToOperator(COMMON_BUILTINS, "floor", EOpFloor);
symbolTable.relateToOperator(COMMON_BUILTINS, "ceil", EOpCeil);
symbolTable.relateToOperator(COMMON_BUILTINS, "fract", EOpFract);
symbolTable.relateToOperator(COMMON_BUILTINS, "mod", EOpMod);
symbolTable.relateToOperator(COMMON_BUILTINS, "min", EOpMin);
symbolTable.relateToOperator(COMMON_BUILTINS, "max", EOpMax);
symbolTable.relateToOperator(COMMON_BUILTINS, "clamp", EOpClamp);
symbolTable.relateToOperator(COMMON_BUILTINS, "mix", EOpMix);
symbolTable.relateToOperator(COMMON_BUILTINS, "step", EOpStep);
symbolTable.relateToOperator(COMMON_BUILTINS, "smoothstep", EOpSmoothStep);
symbolTable.relateToOperator(COMMON_BUILTINS, "length", EOpLength);
symbolTable.relateToOperator(COMMON_BUILTINS, "distance", EOpDistance);
symbolTable.relateToOperator(COMMON_BUILTINS, "dot", EOpDot);
symbolTable.relateToOperator(COMMON_BUILTINS, "cross", EOpCross);
symbolTable.relateToOperator(COMMON_BUILTINS, "normalize", EOpNormalize);
symbolTable.relateToOperator(COMMON_BUILTINS, "faceforward", EOpFaceForward);
symbolTable.relateToOperator(COMMON_BUILTINS, "reflect", EOpReflect);
symbolTable.relateToOperator(COMMON_BUILTINS, "refract", EOpRefract);
symbolTable.relateToOperator(COMMON_BUILTINS, "any", EOpAny);
symbolTable.relateToOperator(COMMON_BUILTINS, "all", EOpAll);
symbolTable.relateToOperator(COMMON_BUILTINS, "not", EOpVectorLogicalNot);
// Map language-specific operators.
switch(type) {
case GL_VERTEX_SHADER:
break;
case GL_FRAGMENT_SHADER:
if (resources.OES_standard_derivatives)
if (spec != SH_CSS_SHADERS_SPEC)
{
symbolTable.relateToOperator(ESSL1_BUILTINS, "dFdx", EOpDFdx);
symbolTable.relateToOperator(ESSL1_BUILTINS, "dFdy", EOpDFdy);
symbolTable.relateToOperator(ESSL1_BUILTINS, "fwidth", EOpFwidth);
symbolTable.relateToExtension(ESSL1_BUILTINS, "dFdx", "GL_OES_standard_derivatives");
symbolTable.relateToExtension(ESSL1_BUILTINS, "dFdy", "GL_OES_standard_derivatives");
symbolTable.relateToExtension(ESSL1_BUILTINS, "fwidth", "GL_OES_standard_derivatives");
}
if (resources.EXT_shader_texture_lod)
{
symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DLodEXT", "GL_EXT_shader_texture_lod");
symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DProjLodEXT", "GL_EXT_shader_texture_lod");
symbolTable.relateToExtension(ESSL1_BUILTINS, "textureCubeLodEXT", "GL_EXT_shader_texture_lod");
}
break;
default: break;
}
symbolTable.relateToOperator(ESSL3_BUILTINS, "dFdx", EOpDFdx);
symbolTable.relateToOperator(ESSL3_BUILTINS, "dFdy", EOpDFdy);
symbolTable.relateToOperator(ESSL3_BUILTINS, "fwidth", EOpFwidth);
if (resources.EXT_shader_texture_lod)
{
symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DGradEXT", "GL_EXT_shader_texture_lod");
symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DProjGradEXT", "GL_EXT_shader_texture_lod");
symbolTable.relateToExtension(ESSL1_BUILTINS, "textureCubeGradEXT", "GL_EXT_shader_texture_lod");
}
// Finally add resource-specific variables.
switch(type) {
case GL_FRAGMENT_SHADER:
if (spec != SH_CSS_SHADERS_SPEC) {
// Set up gl_FragData. The array size.
symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragColor"),
TType(EbtFloat, EbpMedium, EvqFragColor, 4)));
TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, 1, true);
fragData.setArraySize(resources.MaxDrawBuffers);
symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragData"), fragData));
if (resources.EXT_frag_depth)
{
symbolTable.insert(ESSL1_BUILTINS, "GL_EXT_frag_depth", new TVariable(NewPoolTString("gl_FragDepthEXT"),
TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1)));
}
if (resources.EXT_shader_framebuffer_fetch || resources.NV_shader_framebuffer_fetch)
{
TType lastFragData(EbtFloat, EbpMedium, EvqLastFragData, 4, 1, true);
lastFragData.setArraySize(resources.MaxDrawBuffers);
if (resources.EXT_shader_framebuffer_fetch)
{
symbolTable.insert(ESSL1_BUILTINS, "GL_EXT_shader_framebuffer_fetch",
new TVariable(NewPoolTString("gl_LastFragData"), lastFragData));
}
else if (resources.NV_shader_framebuffer_fetch)
{
symbolTable.insert(ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch",
new TVariable(NewPoolTString("gl_LastFragColor"),
TType(EbtFloat, EbpMedium, EvqLastFragColor, 4)));
symbolTable.insert(ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch",
new TVariable(NewPoolTString("gl_LastFragData"), lastFragData));
}
}
else if (resources.ARM_shader_framebuffer_fetch)
{
symbolTable.insert(ESSL1_BUILTINS, "GL_ARM_shader_framebuffer_fetch",
new TVariable(NewPoolTString("gl_LastFragColorARM"),
TType(EbtFloat, EbpMedium, EvqLastFragColor, 4)));
}
}
else
{
symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_MixColor"),
TType(EbtFloat, EbpMedium, EvqGlobal, 4)));
symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_ColorMatrix"),
TType(EbtFloat, EbpMedium, EvqGlobal, 4, 4)));
}
break;
default: break;
case GL_VERTEX_SHADER:
symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_Position"),
TType(EbtFloat, EbpHigh, EvqPosition, 4)));
symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointSize"),
TType(EbtFloat, EbpMedium, EvqPointSize, 1)));
symbolTable.insert(ESSL3_BUILTINS, new TVariable(NewPoolTString("gl_InstanceID"),
TType(EbtInt, EbpHigh, EvqInstanceID, 1)));
break;
default:
assert(false && "Language not supported");
}
}
@ -758,4 +575,20 @@ void InitExtensionBehavior(const ShBuiltInResources& resources,
extBehavior["GL_EXT_frag_depth"] = EBhUndefined;
if (resources.EXT_shader_texture_lod)
extBehavior["GL_EXT_shader_texture_lod"] = EBhUndefined;
if (resources.EXT_shader_framebuffer_fetch)
extBehavior["GL_EXT_shader_framebuffer_fetch"] = EBhUndefined;
if (resources.NV_shader_framebuffer_fetch)
extBehavior["GL_NV_shader_framebuffer_fetch"] = EBhUndefined;
if (resources.ARM_shader_framebuffer_fetch)
extBehavior["GL_ARM_shader_framebuffer_fetch"] = EBhUndefined;
}
void ResetExtensionBehavior(TExtensionBehavior &extBehavior)
{
for (auto ext_iter = extBehavior.begin();
ext_iter != extBehavior.end();
++ext_iter)
{
ext_iter->second = EBhUndefined;
}
}

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef _INITIALIZE_INCLUDED_
#define _INITIALIZE_INCLUDED_
#ifndef COMPILER_TRANSLATOR_INITIALIZE_H_
#define COMPILER_TRANSLATOR_INITIALIZE_H_
#include "compiler/translator/Common.h"
#include "compiler/translator/Compiler.h"
@ -20,4 +20,10 @@ void IdentifyBuiltIns(sh::GLenum type, ShShaderSpec spec,
void InitExtensionBehavior(const ShBuiltInResources& resources,
TExtensionBehavior& extensionBehavior);
#endif // _INITIALIZE_INCLUDED_
// Resets the behavior of the extensions listed in |extensionBehavior| to the
// undefined state. These extensions will only be those initially supported in
// the ShBuiltInResources object for this compiler instance. All other
// extensions will remain unsupported.
void ResetExtensionBehavior(TExtensionBehavior &extensionBehavior);
#endif // COMPILER_TRANSLATOR_INITIALIZE_H_

View File

@ -3,11 +3,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#ifndef __INITIALIZEDLL_H
#define __INITIALIZEDLL_H
#ifndef COMPILER_TRANSLATOR_INITIALIZEDLL_H_
#define COMPILER_TRANSLATOR_INITIALIZEDLL_H_
bool InitProcess();
void DetachProcess();
#endif // __INITIALIZEDLL_H
#endif // COMPILER_TRANSLATOR_INITIALIZEDLL_H_

View File

@ -4,10 +4,10 @@
// found in the LICENSE file.
//
#ifndef __INITIALIZE_GLOBALS_INCLUDED_
#define __INITIALIZE_GLOBALS_INCLUDED_
#ifndef COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_
#define COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_
bool InitializePoolIndex();
void FreePoolIndex();
#endif // __INITIALIZE_GLOBALS_INCLUDED_
#endif // COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef __INITIALIZE_PARSE_CONTEXT_INCLUDED_
#define __INITIALIZE_PARSE_CONTEXT_INCLUDED_
#ifndef COMPILER_TRANSLATOR_INITIALIZEPARSECONTEXT_H_
#define COMPILER_TRANSLATOR_INITIALIZEPARSECONTEXT_H_
bool InitializeParseContextIndex();
void FreeParseContextIndex();
@ -14,4 +14,4 @@ struct TParseContext;
extern void SetGlobalParseContext(TParseContext* context);
extern TParseContext* GetGlobalParseContext();
#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_
#endif // COMPILER_TRANSLATOR_INITIALIZEPARSECONTEXT_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILER_INITIALIZE_VARIABLES_H_
#define COMPILER_INITIALIZE_VARIABLES_H_
#ifndef COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_
#define COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_
#include "compiler/translator/IntermNode.h"
@ -47,4 +47,4 @@ class InitializeVariables : public TIntermTraverser
bool mCodeInserted;
};
#endif // COMPILER_INITIALIZE_VARIABLES_H_
#endif // COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_

View File

@ -157,26 +157,6 @@ bool TIntermLoop::replaceChildNode(
return false;
}
void TIntermLoop::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
{
if (mInit)
{
nodeQueue->push(mInit);
}
if (mCond)
{
nodeQueue->push(mCond);
}
if (mExpr)
{
nodeQueue->push(mExpr);
}
if (mBody)
{
nodeQueue->push(mBody);
}
}
bool TIntermBranch::replaceChildNode(
TIntermNode *original, TIntermNode *replacement)
{
@ -184,14 +164,6 @@ bool TIntermBranch::replaceChildNode(
return false;
}
void TIntermBranch::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
{
if (mExpression)
{
nodeQueue->push(mExpression);
}
}
bool TIntermBinary::replaceChildNode(
TIntermNode *original, TIntermNode *replacement)
{
@ -200,18 +172,6 @@ bool TIntermBinary::replaceChildNode(
return false;
}
void TIntermBinary::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
{
if (mLeft)
{
nodeQueue->push(mLeft);
}
if (mRight)
{
nodeQueue->push(mRight);
}
}
bool TIntermUnary::replaceChildNode(
TIntermNode *original, TIntermNode *replacement)
{
@ -219,14 +179,6 @@ bool TIntermUnary::replaceChildNode(
return false;
}
void TIntermUnary::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
{
if (mOperand)
{
nodeQueue->push(mOperand);
}
}
bool TIntermAggregate::replaceChildNode(
TIntermNode *original, TIntermNode *replacement)
{
@ -237,14 +189,6 @@ bool TIntermAggregate::replaceChildNode(
return false;
}
void TIntermAggregate::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
{
for (size_t childIndex = 0; childIndex < mSequence.size(); childIndex++)
{
nodeQueue->push(mSequence[childIndex]);
}
}
void TIntermAggregate::setPrecisionFromChildren()
{
if (getBasicType() == EbtBool)
@ -300,20 +244,19 @@ bool TIntermSelection::replaceChildNode(
return false;
}
void TIntermSelection::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
bool TIntermSwitch::replaceChildNode(
TIntermNode *original, TIntermNode *replacement)
{
if (mCondition)
{
nodeQueue->push(mCondition);
}
if (mTrueBlock)
{
nodeQueue->push(mTrueBlock);
}
if (mFalseBlock)
{
nodeQueue->push(mFalseBlock);
}
REPLACE_IF_IS(mInit, TIntermTyped, original, replacement);
REPLACE_IF_IS(mStatementList, TIntermAggregate, original, replacement);
return false;
}
bool TIntermCase::replaceChildNode(
TIntermNode *original, TIntermNode *replacement)
{
REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
return false;
}
//
@ -336,6 +279,12 @@ bool TIntermOperator::isAssignment() const
case EOpMatrixTimesScalarAssign:
case EOpMatrixTimesMatrixAssign:
case EOpDivAssign:
case EOpIModAssign:
case EOpBitShiftLeftAssign:
case EOpBitShiftRightAssign:
case EOpBitwiseAndAssign:
case EOpBitwiseXorAssign:
case EOpBitwiseOrAssign:
return true;
default:
return false;
@ -379,65 +328,55 @@ bool TIntermOperator::isConstructor() const
// Make sure the type of a unary operator is appropriate for its
// combination of operation and operand type.
//
// Returns false in nothing makes sense.
//
bool TIntermUnary::promote(TInfoSink &)
void TIntermUnary::promote(const TType *funcReturnType)
{
switch (mOp)
{
case EOpLogicalNot:
if (mOperand->getBasicType() != EbtBool)
return false;
case EOpFloatBitsToInt:
case EOpFloatBitsToUint:
case EOpIntBitsToFloat:
case EOpUintBitsToFloat:
case EOpPackSnorm2x16:
case EOpPackUnorm2x16:
case EOpPackHalf2x16:
case EOpUnpackSnorm2x16:
case EOpUnpackUnorm2x16:
mType.setPrecision(EbpHigh);
break;
case EOpNegative:
case EOpPositive:
case EOpPostIncrement:
case EOpPostDecrement:
case EOpPreIncrement:
case EOpPreDecrement:
if (mOperand->getBasicType() == EbtBool)
return false;
case EOpUnpackHalf2x16:
mType.setPrecision(EbpMedium);
break;
// operators for built-ins are already type checked against their prototype
case EOpAny:
case EOpAll:
case EOpVectorLogicalNot:
return true;
default:
if (mOperand->getBasicType() != EbtFloat)
return false;
setType(mOperand->getType());
}
setType(mOperand->getType());
mType.setQualifier(EvqTemporary);
if (funcReturnType != nullptr)
{
if (funcReturnType->getBasicType() == EbtBool)
{
// Bool types should not have precision.
setType(*funcReturnType);
}
else
{
// Precision of the node has been set based on the operand.
setTypePreservePrecision(*funcReturnType);
}
}
return true;
mType.setQualifier(EvqTemporary);
}
//
// Establishes the type of the resultant operation, as well as
// makes the operator the correct one for the operands.
//
// Returns false if operator can't work on operands.
// For lots of operations it should already be established that the operand
// combination is valid, but returns false if operator can't work on operands.
//
bool TIntermBinary::promote(TInfoSink &infoSink)
{
// This function only handles scalars, vectors, and matrices.
if (mLeft->isArray() || mRight->isArray())
{
infoSink.info.message(EPrefixInternalError, getLine(),
"Invalid operation for arrays");
return false;
}
// GLSL ES 2.0 does not support implicit type casting.
// So the basic type should always match.
if (mLeft->getBasicType() != mRight->getBasicType())
{
return false;
}
ASSERT(mLeft->isArray() == mRight->isArray());
//
// Base assumption: just make the type the same as the left
@ -483,12 +422,9 @@ bool TIntermBinary::promote(TInfoSink &infoSink)
// And and Or operate on conditionals
//
case EOpLogicalAnd:
case EOpLogicalXor:
case EOpLogicalOr:
// Both operands must be of type bool.
if (mLeft->getBasicType() != EbtBool || mRight->getBasicType() != EbtBool)
{
return false;
}
ASSERT(mLeft->getBasicType() == EbtBool && mRight->getBasicType() == EbtBool);
setType(TType(EbtBool, EbpUndefined));
break;
@ -625,12 +561,28 @@ bool TIntermBinary::promote(TInfoSink &infoSink)
case EOpAssign:
case EOpInitialize:
// No more additional checks are needed.
ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
(mLeft->getSecondarySize() == mRight->getSecondarySize()));
break;
case EOpAdd:
case EOpSub:
case EOpDiv:
case EOpIMod:
case EOpBitShiftLeft:
case EOpBitShiftRight:
case EOpBitwiseAnd:
case EOpBitwiseXor:
case EOpBitwiseOr:
case EOpAddAssign:
case EOpSubAssign:
case EOpDivAssign:
case EOpIModAssign:
case EOpBitShiftLeftAssign:
case EOpBitShiftRightAssign:
case EOpBitwiseAndAssign:
case EOpBitwiseXorAssign:
case EOpBitwiseOrAssign:
if ((mLeft->isMatrix() && mRight->isVector()) ||
(mLeft->isVector() && mRight->isMatrix()))
{
@ -641,13 +593,19 @@ bool TIntermBinary::promote(TInfoSink &infoSink)
if (mLeft->getNominalSize() != mRight->getNominalSize() ||
mLeft->getSecondarySize() != mRight->getSecondarySize())
{
// If the nominal size of operands do not match:
// One of them must be scalar.
// If the nominal sizes of operands do not match:
// One of them must be a scalar.
if (!mLeft->isScalar() && !mRight->isScalar())
return false;
// Operator cannot be of type pure assignment.
if (mOp == EOpAssign || mOp == EOpInitialize)
// In the case of compound assignment other than multiply-assign,
// the right side needs to be a scalar. Otherwise a vector/matrix
// would be assigned to a scalar. A scalar can't be shifted by a
// vector either.
if (!mRight->isScalar() &&
(isAssignment() ||
mOp == EOpBitShiftLeft ||
mOp == EOpBitShiftRight))
return false;
}
@ -656,6 +614,11 @@ bool TIntermBinary::promote(TInfoSink &infoSink)
mLeft->getSecondarySize(), mRight->getSecondarySize());
setType(TType(basicType, higherPrecision, EvqTemporary,
nominalSize, secondarySize));
if (mLeft->isArray())
{
ASSERT(mLeft->getArraySize() == mRight->getArraySize());
mType.setArraySize(mLeft->getArraySize());
}
}
break;
@ -665,11 +628,8 @@ bool TIntermBinary::promote(TInfoSink &infoSink)
case EOpGreaterThan:
case EOpLessThanEqual:
case EOpGreaterThanEqual:
if ((mLeft->getNominalSize() != mRight->getNominalSize()) ||
(mLeft->getSecondarySize() != mRight->getSecondarySize()))
{
return false;
}
ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
(mLeft->getSecondarySize() == mRight->getSecondarySize()));
setType(TType(EbtBool, EbpUndefined));
break;
@ -793,6 +753,7 @@ TIntermTyped *TIntermConstantUnion::fold(
break;
case EOpDiv:
case EOpIMod:
{
tempConstArray = new ConstantUnion[objectSize];
for (size_t i = 0; i < objectSize; i++)
@ -810,6 +771,7 @@ TIntermTyped *TIntermConstantUnion::fold(
}
else
{
ASSERT(op == EOpDiv);
tempConstArray[i].setFConst(
unionArray[i].getFConst() /
rightUnionArray[i].getFConst());
@ -826,9 +788,19 @@ TIntermTyped *TIntermConstantUnion::fold(
}
else
{
tempConstArray[i].setIConst(
unionArray[i].getIConst() /
rightUnionArray[i].getIConst());
if (op == EOpDiv)
{
tempConstArray[i].setIConst(
unionArray[i].getIConst() /
rightUnionArray[i].getIConst());
}
else
{
ASSERT(op == EOpIMod);
tempConstArray[i].setIConst(
unionArray[i].getIConst() %
rightUnionArray[i].getIConst());
}
}
break;
@ -842,9 +814,19 @@ TIntermTyped *TIntermConstantUnion::fold(
}
else
{
tempConstArray[i].setUConst(
unionArray[i].getUConst() /
rightUnionArray[i].getUConst());
if (op == EOpDiv)
{
tempConstArray[i].setUConst(
unionArray[i].getUConst() /
rightUnionArray[i].getUConst());
}
else
{
ASSERT(op == EOpIMod);
tempConstArray[i].setUConst(
unionArray[i].getUConst() %
rightUnionArray[i].getUConst());
}
}
break;
@ -968,6 +950,32 @@ TIntermTyped *TIntermConstantUnion::fold(
}
break;
case EOpBitwiseAnd:
tempConstArray = new ConstantUnion[objectSize];
for (size_t i = 0; i < objectSize; i++)
tempConstArray[i] = unionArray[i] & rightUnionArray[i];
break;
case EOpBitwiseXor:
tempConstArray = new ConstantUnion[objectSize];
for (size_t i = 0; i < objectSize; i++)
tempConstArray[i] = unionArray[i] ^ rightUnionArray[i];
break;
case EOpBitwiseOr:
tempConstArray = new ConstantUnion[objectSize];
for (size_t i = 0; i < objectSize; i++)
tempConstArray[i] = unionArray[i] | rightUnionArray[i];
break;
case EOpBitShiftLeft:
tempConstArray = new ConstantUnion[objectSize];
for (size_t i = 0; i < objectSize; i++)
tempConstArray[i] = unionArray[i] << rightUnionArray[i];
break;
case EOpBitShiftRight:
tempConstArray = new ConstantUnion[objectSize];
for (size_t i = 0; i < objectSize; i++)
tempConstArray[i] = unionArray[i] >> rightUnionArray[i];
break;
case EOpLessThan:
ASSERT(objectSize == 1);
tempConstArray = new ConstantUnion[1];
@ -1160,6 +1168,23 @@ TIntermTyped *TIntermConstantUnion::fold(
}
break;
case EOpBitwiseNot:
switch (getType().getBasicType())
{
case EbtInt:
tempConstArray[i].setIConst(~unionArray[i].getIConst());
break;
case EbtUInt:
tempConstArray[i].setUConst(~unionArray[i].getUConst());
break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return NULL;
}
break;
default:
return NULL;
}
@ -1181,3 +1206,29 @@ TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunctio
TString hashedName = stream.str();
return hashedName;
}
void TIntermTraverser::updateTree()
{
for (size_t ii = 0; ii < mReplacements.size(); ++ii)
{
const NodeUpdateEntry& entry = mReplacements[ii];
ASSERT(entry.parent);
bool replaced = entry.parent->replaceChildNode(
entry.original, entry.replacement);
ASSERT(replaced);
if (!entry.originalBecomesChildOfReplacement)
{
// In AST traversing, a parent is visited before its children.
// After we replace a node, if an immediate child is to
// be replaced, we need to make sure we don't update the replaced
// node; instead, we update the replacement node.
for (size_t jj = ii + 1; jj < mReplacements.size(); ++jj)
{
NodeUpdateEntry& entry2 = mReplacements[jj];
if (entry2.parent == entry.original)
entry2.parent = entry.replacement;
}
}
}
}

View File

@ -13,182 +13,19 @@
// each node can have it's own type of list of children.
//
#ifndef COMPILER_TRANSLATOR_INTERMEDIATE_H_
#define COMPILER_TRANSLATOR_INTERMEDIATE_H_
#ifndef COMPILER_TRANSLATOR_INTERMNODE_H_
#define COMPILER_TRANSLATOR_INTERMNODE_H_
#include "GLSLANG/ShaderLang.h"
#include <algorithm>
#include <queue>
#include "common/angleutils.h"
#include "compiler/translator/Common.h"
#include "compiler/translator/Types.h"
#include "compiler/translator/ConstantUnion.h"
//
// Operators used by the high-level (parse tree) representation.
//
enum TOperator
{
EOpNull, // if in a node, should only mean a node is still being built
EOpSequence, // denotes a list of statements, or parameters, etc.
EOpFunctionCall,
EOpFunction, // For function definition
EOpParameters, // an aggregate listing the parameters to a function
EOpDeclaration,
EOpInvariantDeclaration, // Specialized declarations for attributing invariance
EOpPrototype,
//
// Unary operators
//
EOpNegative,
EOpPositive,
EOpLogicalNot,
EOpVectorLogicalNot,
EOpPostIncrement,
EOpPostDecrement,
EOpPreIncrement,
EOpPreDecrement,
//
// binary operations
//
EOpAdd,
EOpSub,
EOpMul,
EOpDiv,
EOpEqual,
EOpNotEqual,
EOpVectorEqual,
EOpVectorNotEqual,
EOpLessThan,
EOpGreaterThan,
EOpLessThanEqual,
EOpGreaterThanEqual,
EOpComma,
EOpVectorTimesScalar,
EOpVectorTimesMatrix,
EOpMatrixTimesVector,
EOpMatrixTimesScalar,
EOpLogicalOr,
EOpLogicalXor,
EOpLogicalAnd,
EOpIndexDirect,
EOpIndexIndirect,
EOpIndexDirectStruct,
EOpIndexDirectInterfaceBlock,
EOpVectorSwizzle,
//
// Built-in functions potentially mapped to operators
//
EOpRadians,
EOpDegrees,
EOpSin,
EOpCos,
EOpTan,
EOpAsin,
EOpAcos,
EOpAtan,
EOpPow,
EOpExp,
EOpLog,
EOpExp2,
EOpLog2,
EOpSqrt,
EOpInverseSqrt,
EOpAbs,
EOpSign,
EOpFloor,
EOpCeil,
EOpFract,
EOpMod,
EOpMin,
EOpMax,
EOpClamp,
EOpMix,
EOpStep,
EOpSmoothStep,
EOpLength,
EOpDistance,
EOpDot,
EOpCross,
EOpNormalize,
EOpFaceForward,
EOpReflect,
EOpRefract,
EOpDFdx, // Fragment only, OES_standard_derivatives extension
EOpDFdy, // Fragment only, OES_standard_derivatives extension
EOpFwidth, // Fragment only, OES_standard_derivatives extension
EOpMatrixTimesMatrix,
EOpAny,
EOpAll,
//
// Branch
//
EOpKill, // Fragment only
EOpReturn,
EOpBreak,
EOpContinue,
//
// Constructors
//
EOpConstructInt,
EOpConstructUInt,
EOpConstructBool,
EOpConstructFloat,
EOpConstructVec2,
EOpConstructVec3,
EOpConstructVec4,
EOpConstructBVec2,
EOpConstructBVec3,
EOpConstructBVec4,
EOpConstructIVec2,
EOpConstructIVec3,
EOpConstructIVec4,
EOpConstructUVec2,
EOpConstructUVec3,
EOpConstructUVec4,
EOpConstructMat2,
EOpConstructMat3,
EOpConstructMat4,
EOpConstructStruct,
//
// moves
//
EOpAssign,
EOpInitialize,
EOpAddAssign,
EOpSubAssign,
EOpMulAssign,
EOpVectorTimesMatrixAssign,
EOpVectorTimesScalarAssign,
EOpMatrixTimesScalarAssign,
EOpMatrixTimesMatrixAssign,
EOpDivAssign
};
#include "compiler/translator/Operator.h"
class TIntermTraverser;
class TIntermAggregate;
@ -196,10 +33,13 @@ class TIntermBinary;
class TIntermUnary;
class TIntermConstantUnion;
class TIntermSelection;
class TIntermSwitch;
class TIntermCase;
class TIntermTyped;
class TIntermSymbol;
class TIntermLoop;
class TInfoSink;
class TInfoSinkBase;
class TIntermRaw;
//
@ -228,6 +68,8 @@ class TIntermNode
virtual TIntermBinary *getAsBinaryNode() { return 0; }
virtual TIntermUnary *getAsUnaryNode() { return 0; }
virtual TIntermSelection *getAsSelectionNode() { return 0; }
virtual TIntermSwitch *getAsSwitchNode() { return 0; }
virtual TIntermCase *getAsCaseNode() { return 0; }
virtual TIntermSymbol *getAsSymbolNode() { return 0; }
virtual TIntermLoop *getAsLoopNode() { return 0; }
virtual TIntermRaw *getAsRawNode() { return 0; }
@ -237,10 +79,6 @@ class TIntermNode
virtual bool replaceChildNode(
TIntermNode *original, TIntermNode *replacement) = 0;
// For traversing a tree in no particular order, but using
// heap memory.
virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const = 0;
protected:
TSourceLoc mLine;
};
@ -331,8 +169,6 @@ class TIntermLoop : public TIntermNode
void setUnrollFlag(bool flag) { mUnrollFlag = flag; }
bool getUnrollFlag() const { return mUnrollFlag; }
virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
protected:
TLoopType mType;
TIntermNode *mInit; // for-loop initialization
@ -360,8 +196,6 @@ class TIntermBranch : public TIntermNode
TOperator getFlowOp() { return mFlowOp; }
TIntermTyped* getExpression() { return mExpression; }
virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
protected:
TOperator mFlowOp;
TIntermTyped *mExpression; // non-zero except for "return exp;" statements
@ -394,8 +228,6 @@ class TIntermSymbol : public TIntermTyped
virtual TIntermSymbol *getAsSymbolNode() { return this; }
virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {}
protected:
int mId;
TString mSymbol;
@ -419,7 +251,6 @@ class TIntermRaw : public TIntermTyped
virtual TIntermRaw *getAsRawNode() { return this; }
virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {}
protected:
TString mRawText;
@ -459,8 +290,6 @@ class TIntermConstantUnion : public TIntermTyped
TIntermTyped *fold(TOperator, TIntermTyped *, TInfoSink &);
virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {}
protected:
ConstantUnion *mUnionArrayPointer;
};
@ -519,8 +348,6 @@ class TIntermBinary : public TIntermOperator
void setAddIndexClamp() { mAddIndexClamp = true; }
bool getAddIndexClamp() { return mAddIndexClamp; }
virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
protected:
TIntermTyped* mLeft;
TIntermTyped* mRight;
@ -556,13 +383,11 @@ class TIntermUnary : public TIntermOperator
void setOperand(TIntermTyped *operand) { mOperand = operand; }
TIntermTyped *getOperand() { return mOperand; }
bool promote(TInfoSink &);
void promote(const TType *funcReturnType);
void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
protected:
TIntermTyped *mOperand;
@ -613,8 +438,6 @@ class TIntermAggregate : public TIntermOperator
void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
void setPrecisionFromChildren();
void setBuiltInFunctionPrecision();
@ -634,7 +457,7 @@ class TIntermAggregate : public TIntermOperator
};
//
// For if tests. Simplified since there is no switch statement.
// For if tests.
//
class TIntermSelection : public TIntermTyped
{
@ -664,14 +487,64 @@ class TIntermSelection : public TIntermTyped
TIntermNode *getFalseBlock() const { return mFalseBlock; }
TIntermSelection *getAsSelectionNode() { return this; }
virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
protected:
TIntermTyped *mCondition;
TIntermNode *mTrueBlock;
TIntermNode *mFalseBlock;
};
//
// Switch statement.
//
class TIntermSwitch : public TIntermNode
{
public:
TIntermSwitch(TIntermTyped *init, TIntermAggregate *statementList)
: TIntermNode(),
mInit(init),
mStatementList(statementList)
{
}
void traverse(TIntermTraverser *it) override;
bool replaceChildNode(
TIntermNode *original, TIntermNode *replacement) override;
TIntermSwitch *getAsSwitchNode() override { return this; }
TIntermAggregate *getStatementList() { return mStatementList; }
void setStatementList(TIntermAggregate *statementList) { mStatementList = statementList; }
protected:
TIntermTyped *mInit;
TIntermAggregate *mStatementList;
};
//
// Case label.
//
class TIntermCase : public TIntermNode
{
public:
TIntermCase(TIntermTyped *condition)
: TIntermNode(),
mCondition(condition)
{
}
void traverse(TIntermTraverser *it) override;
bool replaceChildNode(
TIntermNode *original, TIntermNode *replacement) override;
TIntermCase *getAsCaseNode() override { return this; }
bool hasCondition() const { return mCondition != nullptr; }
TIntermTyped *getCondition() const { return mCondition; }
protected:
TIntermTyped *mCondition;
};
enum Visit
{
PreVisit,
@ -687,7 +560,7 @@ enum Visit
// When using this, just fill in the methods for nodes you want visited.
// Return false from a pre-visit to skip visiting that node's subtree.
//
class TIntermTraverser
class TIntermTraverser : angle::NonCopyable
{
public:
POOL_ALLOCATOR_NEW_DELETE();
@ -708,6 +581,8 @@ class TIntermTraverser
virtual bool visitBinary(Visit, TIntermBinary *) { return true; }
virtual bool visitUnary(Visit, TIntermUnary *) { return true; }
virtual bool visitSelection(Visit, TIntermSelection *) { return true; }
virtual bool visitSwitch(Visit, TIntermSwitch *) { return true; }
virtual bool visitCase(Visit, TIntermCase *) { return true; }
virtual bool visitAggregate(Visit, TIntermAggregate *) { return true; }
virtual bool visitLoop(Visit, TIntermLoop *) { return true; }
virtual bool visitBranch(Visit, TIntermBranch *) { return true; }
@ -741,12 +616,38 @@ class TIntermTraverser
const bool postVisit;
const bool rightToLeft;
// If traversers need to replace nodes, they can add the replacements in
// mReplacements during traversal and the user of the traverser should call
// this function after traversal to perform them.
void updateTree();
protected:
int mDepth;
int mMaxDepth;
// All the nodes from root to the current node's parent during traversing.
TVector<TIntermNode *> mPath;
struct NodeUpdateEntry
{
NodeUpdateEntry(TIntermNode *_parent,
TIntermNode *_original,
TIntermNode *_replacement,
bool _originalBecomesChildOfReplacement)
: parent(_parent),
original(_original),
replacement(_replacement),
originalBecomesChildOfReplacement(_originalBecomesChildOfReplacement) {}
TIntermNode *parent;
TIntermNode *original;
TIntermNode *replacement;
bool originalBecomesChildOfReplacement;
};
// During traversing, save all the changes that need to happen into
// mReplacements, then do them by calling updateTree().
std::vector<NodeUpdateEntry> mReplacements;
};
//
@ -768,10 +669,10 @@ class TMaxDepthTraverser : public TIntermTraverser
virtual bool visitLoop(Visit, TIntermLoop *) { return depthCheck(); }
virtual bool visitBranch(Visit, TIntermBranch *) { return depthCheck(); }
protected:
protected:
bool depthCheck() const { return mMaxDepth < mDepthLimit; }
int mDepthLimit;
};
#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_
#endif // COMPILER_TRANSLATOR_INTERMNODE_H_

View File

@ -193,6 +193,60 @@ void TIntermSelection::traverse(TIntermTraverser *it)
it->visitSelection(PostVisit, this);
}
//
// Traverse a switch node. Same comments in binary node apply here.
//
void TIntermSwitch::traverse(TIntermTraverser *it)
{
bool visit = true;
if (it->preVisit)
visit = it->visitSwitch(PreVisit, this);
if (visit)
{
it->incrementDepth(this);
if (it->rightToLeft)
{
if (mStatementList)
mStatementList->traverse(it);
if (it->inVisit)
visit = it->visitSwitch(InVisit, this);
if (visit)
mInit->traverse(it);
}
else
{
mInit->traverse(it);
if (it->inVisit)
visit = it->visitSwitch(InVisit, this);
if (visit && mStatementList)
mStatementList->traverse(it);
}
it->decrementDepth();
}
if (visit && it->postVisit)
it->visitSwitch(PostVisit, this);
}
//
// Traverse a switch node. Same comments in binary node apply here.
//
void TIntermCase::traverse(TIntermTraverser *it)
{
bool visit = true;
if (it->preVisit)
visit = it->visitCase(PreVisit, this);
if (visit && mCondition)
mCondition->traverse(it);
if (visit && it->postVisit)
it->visitCase(PostVisit, this);
}
//
// Traverse a loop node. Same comments in binary node apply here.
//

View File

@ -13,7 +13,6 @@
#include <algorithm>
#include "compiler/translator/Intermediate.h"
#include "compiler/translator/RemoveTree.h"
#include "compiler/translator/SymbolTable.h"
////////////////////////////////////////////////////////////////////////////
@ -46,47 +45,6 @@ TIntermSymbol *TIntermediate::addSymbol(
TIntermTyped *TIntermediate::addBinaryMath(
TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
{
switch (op)
{
case EOpEqual:
case EOpNotEqual:
if (left->isArray())
return NULL;
break;
case EOpLessThan:
case EOpGreaterThan:
case EOpLessThanEqual:
case EOpGreaterThanEqual:
if (left->isMatrix() || left->isArray() || left->isVector() ||
left->getBasicType() == EbtStruct)
{
return NULL;
}
break;
case EOpLogicalOr:
case EOpLogicalXor:
case EOpLogicalAnd:
if (left->getBasicType() != EbtBool ||
left->isMatrix() || left->isArray() || left->isVector())
{
return NULL;
}
break;
case EOpAdd:
case EOpSub:
case EOpDiv:
case EOpMul:
if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
return NULL;
default:
break;
}
if (left->getBasicType() != right->getBasicType())
{
return NULL;
}
//
// Need a new node holding things together then. Make
// one and promote it to the right type.
@ -169,45 +127,8 @@ TIntermTyped *TIntermediate::addIndex(
// Returns the added node.
//
TIntermTyped *TIntermediate::addUnaryMath(
TOperator op, TIntermNode *childNode, const TSourceLoc &line)
TOperator op, TIntermTyped *child, const TSourceLoc &line, const TType *funcReturnType)
{
TIntermUnary *node;
TIntermTyped *child = childNode->getAsTyped();
if (child == NULL)
{
mInfoSink.info.message(EPrefixInternalError, line,
"Bad type in AddUnaryMath");
return NULL;
}
switch (op)
{
case EOpLogicalNot:
if (child->getType().getBasicType() != EbtBool ||
child->getType().isMatrix() ||
child->getType().isArray() ||
child->getType().isVector())
{
return NULL;
}
break;
case EOpPostIncrement:
case EOpPreIncrement:
case EOpPostDecrement:
case EOpPreDecrement:
case EOpNegative:
case EOpPositive:
if (child->getType().getBasicType() == EbtStruct ||
child->getType().isArray())
{
return NULL;
}
default:
break;
}
TIntermConstantUnion *childTempConstant = 0;
if (child->getAsConstantUnion())
childTempConstant = child->getAsConstantUnion();
@ -215,12 +136,10 @@ TIntermTyped *TIntermediate::addUnaryMath(
//
// Make a new node for the operator.
//
node = new TIntermUnary(op);
TIntermUnary *node = new TIntermUnary(op);
node->setLine(line);
node->setOperand(child);
if (!node->promote(mInfoSink))
return 0;
node->promote(funcReturnType);
if (childTempConstant)
{
@ -423,6 +342,24 @@ TIntermTyped *TIntermediate::addSelection(
return node;
}
TIntermSwitch *TIntermediate::addSwitch(
TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
{
TIntermSwitch *node = new TIntermSwitch(init, statementList);
node->setLine(line);
return node;
}
TIntermCase *TIntermediate::addCase(
TIntermTyped *condition, const TSourceLoc &line)
{
TIntermCase *node = new TIntermCase(condition);
node->setLine(line);
return node;
}
//
// Constant terminal nodes. Has a union that contains bool, float or int constants
//
@ -510,12 +447,3 @@ bool TIntermediate::postProcess(TIntermNode *root)
return true;
}
//
// This deletes the tree.
//
void TIntermediate::remove(TIntermNode *root)
{
if (root)
RemoveAllTreeNodes(root);
}

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_
#define COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_
#ifndef COMPILER_TRANSLATOR_INTERMEDIATE_H_
#define COMPILER_TRANSLATOR_INTERMEDIATE_H_
#include "compiler/translator/IntermNode.h"
@ -35,7 +35,7 @@ class TIntermediate
TIntermTyped *addIndex(
TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &);
TIntermTyped *addUnaryMath(
TOperator op, TIntermNode *child, const TSourceLoc &);
TOperator op, TIntermTyped *child, const TSourceLoc &line, const TType *funcReturnType);
TIntermAggregate *growAggregate(
TIntermNode *left, TIntermNode *right, const TSourceLoc &);
TIntermAggregate *makeAggregate(TIntermNode *node, const TSourceLoc &);
@ -43,6 +43,10 @@ class TIntermediate
TIntermNode *addSelection(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &);
TIntermTyped *addSelection(
TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &);
TIntermSwitch *addSwitch(
TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line);
TIntermCase *addCase(
TIntermTyped *condition, const TSourceLoc &line);
TIntermTyped *addComma(
TIntermTyped *left, TIntermTyped *right, const TSourceLoc &);
TIntermConstantUnion *addConstantUnion(ConstantUnion *, const TType &, const TSourceLoc &);
@ -55,8 +59,8 @@ class TIntermediate
TIntermBranch *addBranch(TOperator, TIntermTyped *, const TSourceLoc &);
TIntermTyped *addSwizzle(TVectorFields &, const TSourceLoc &);
bool postProcess(TIntermNode *);
void remove(TIntermNode *);
void outputTree(TIntermNode *);
static void outputTree(TIntermNode *, TInfoSinkBase &);
private:
void operator=(TIntermediate &); // prevent assignments
@ -64,4 +68,4 @@ class TIntermediate
TInfoSink & mInfoSink;
};
#endif // COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_
#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILER_TRANSLATOR_LOOP_INFO_H_
#define COMPILER_TRANSLATOR_LOOP_INFO_H_
#ifndef COMPILER_TRANSLATOR_LOOPINFO_H_
#define COMPILER_TRANSLATOR_LOOPINFO_H_
#include "compiler/translator/IntermNode.h"
@ -76,5 +76,5 @@ class TLoopStack : public TVector<TLoopInfo>
void pop();
};
#endif // COMPILER_TRANSLATOR_LOOP_INDEX_H_
#endif // COMPILER_TRANSLATOR_LOOPINFO_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef _MMAP_INCLUDED_
#define _MMAP_INCLUDED_
#ifndef COMPILER_TRANSLATOR_MMAP_H_
#define COMPILER_TRANSLATOR_MMAP_H_
//
// Encapsulate memory mapped files
@ -53,4 +53,4 @@ private:
char* fBuff; // the actual data;
};
#endif // _MMAP_INCLUDED_
#endif // COMPILER_TRANSLATOR_MMAP_H_

View File

@ -6,8 +6,8 @@
// NodeSearch.h: Utilities for searching translator node graphs
//
#ifndef TRANSLATOR_NODESEARCH_H_
#define TRANSLATOR_NODESEARCH_H_
#ifndef COMPILER_TRANSLATOR_NODESEARCH_H_
#define COMPILER_TRANSLATOR_NODESEARCH_H_
#include "compiler/translator/IntermNode.h"
@ -77,4 +77,4 @@ class FindSideEffectRewriting : public NodeSearchTraverser<FindSideEffectRewriti
}
#endif // TRANSLATOR_NODESEARCH_H_
#endif // COMPILER_TRANSLATOR_NODESEARCH_H_

View File

@ -0,0 +1,195 @@
//
// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "compiler/translator/Operator.h"
const char *GetOperatorString(TOperator op)
{
switch (op)
{
// Note: ops from EOpNull to EOpPrototype can't be handled here.
case EOpNegative: return "-";
case EOpPositive: return "+";
case EOpLogicalNot: return "!";
case EOpVectorLogicalNot: return "not";
case EOpBitwiseNot: return "~";
case EOpPostIncrement: return "++";
case EOpPostDecrement: return "--";
case EOpPreIncrement: return "++";
case EOpPreDecrement: return "--";
case EOpAdd: return "+";
case EOpSub: return "-";
case EOpMul: return "*";
case EOpDiv: return "/";
case EOpIMod: return "%";
case EOpEqual: return "==";
case EOpNotEqual: return "!=";
case EOpVectorEqual: return "equal";
case EOpVectorNotEqual: return "notEqual";
case EOpLessThan: return "<";
case EOpGreaterThan: return ">";
case EOpLessThanEqual: return "<=";
case EOpGreaterThanEqual: return ">=";
case EOpComma: return ",";
// Fall-through.
case EOpVectorTimesScalar:
case EOpVectorTimesMatrix:
case EOpMatrixTimesVector:
case EOpMatrixTimesScalar: return "*";
case EOpLogicalOr: return "||";
case EOpLogicalXor: return "^^";
case EOpLogicalAnd: return "&&";
case EOpBitShiftLeft: return "<<";
case EOpBitShiftRight: return ">>";
case EOpBitwiseAnd: return "&";
case EOpBitwiseXor: return "^";
case EOpBitwiseOr: return "|";
// Fall-through.
case EOpIndexDirect:
case EOpIndexIndirect: return "[]";
case EOpIndexDirectStruct:
case EOpIndexDirectInterfaceBlock: return ".";
case EOpVectorSwizzle: return ".";
case EOpRadians: return "radians";
case EOpDegrees: return "degrees";
case EOpSin: return "sin";
case EOpCos: return "cos";
case EOpTan: return "tan";
case EOpAsin: return "asin";
case EOpAcos: return "acos";
case EOpAtan: return "atan";
case EOpSinh: return "sinh";
case EOpCosh: return "cosh";
case EOpTanh: return "tanh";
case EOpAsinh: return "asinh";
case EOpAcosh: return "acosh";
case EOpAtanh: return "atanh";
case EOpPow: return "pow";
case EOpExp: return "exp";
case EOpLog: return "log";
case EOpExp2: return "exp2";
case EOpLog2: return "log2";
case EOpSqrt: return "sqrt";
case EOpInverseSqrt: return "inversesqrt";
case EOpAbs: return "abs";
case EOpSign: return "sign";
case EOpFloor: return "floor";
case EOpTrunc: return "trunc";
case EOpRound: return "round";
case EOpRoundEven: return "roundEven";
case EOpCeil: return "ceil";
case EOpFract: return "fract";
case EOpMod: return "mod";
case EOpModf: return "modf";
case EOpMin: return "min";
case EOpMax: return "max";
case EOpClamp: return "clamp";
case EOpMix: return "mix";
case EOpStep: return "step";
case EOpSmoothStep: return "smoothstep";
case EOpIsNan: return "isnan";
case EOpIsInf: return "isinf";
case EOpFloatBitsToInt: return "floatBitsToInt";
case EOpFloatBitsToUint: return "floatBitsToUint";
case EOpIntBitsToFloat: return "intBitsToFloat";
case EOpUintBitsToFloat: return "uintBitsToFloat";
case EOpPackSnorm2x16: return "packSnorm2x16";
case EOpPackUnorm2x16: return "packUnorm2x16";
case EOpPackHalf2x16: return "packHalf2x16";
case EOpUnpackSnorm2x16: return "unpackSnorm2x16";
case EOpUnpackUnorm2x16: return "unpackUnorm2x16";
case EOpUnpackHalf2x16: return "unpackHalf2x16";
case EOpLength: return "length";
case EOpDistance: return "distance";
case EOpDot: return "dot";
case EOpCross: return "cross";
case EOpNormalize: return "normalize";
case EOpFaceForward: return "faceforward";
case EOpReflect: return "reflect";
case EOpRefract: return "refract";
case EOpDFdx: return "dFdx";
case EOpDFdy: return "dFdy";
case EOpFwidth: return "fwidth";
case EOpMatrixTimesMatrix: return "*";
case EOpOuterProduct: return "outerProduct";
case EOpTranspose: return "transpose";
case EOpDeterminant: return "determinant";
case EOpInverse: return "inverse";
case EOpAny: return "any";
case EOpAll: return "all";
case EOpKill: return "kill";
case EOpReturn: return "return";
case EOpBreak: return "break";
case EOpContinue: return "continue";
case EOpConstructInt: return "int";
case EOpConstructUInt: return "uint";
case EOpConstructBool: return "bool";
case EOpConstructFloat: return "float";
case EOpConstructVec2: return "vec2";
case EOpConstructVec3: return "vec3";
case EOpConstructVec4: return "vec4";
case EOpConstructBVec2: return "bvec2";
case EOpConstructBVec3: return "bvec3";
case EOpConstructBVec4: return "bvec4";
case EOpConstructIVec2: return "ivec2";
case EOpConstructIVec3: return "ivec3";
case EOpConstructIVec4: return "ivec4";
case EOpConstructUVec2: return "uvec2";
case EOpConstructUVec3: return "uvec3";
case EOpConstructUVec4: return "uvec4";
case EOpConstructMat2: return "mat2";
case EOpConstructMat3: return "mat3";
case EOpConstructMat4: return "mat4";
// Note: EOpConstructStruct can't be handled here
case EOpAssign: return "=";
case EOpInitialize: return "=";
case EOpAddAssign: return "+=";
case EOpSubAssign: return "-=";
// Fall-through.
case EOpMulAssign:
case EOpVectorTimesMatrixAssign:
case EOpVectorTimesScalarAssign:
case EOpMatrixTimesScalarAssign:
case EOpMatrixTimesMatrixAssign: return "*=";
case EOpDivAssign: return "/=";
case EOpIModAssign: return "%=";
case EOpBitShiftLeftAssign: return "<<=";
case EOpBitShiftRightAssign: return ">>=";
case EOpBitwiseAndAssign: return "&=";
case EOpBitwiseXorAssign: return "^=";
case EOpBitwiseOrAssign: return "|=";
default: break;
}
return "";
}

View File

@ -0,0 +1,226 @@
//
// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#ifndef COMPILER_TRANSLATOR_OPERATOR_H_
#define COMPILER_TRANSLATOR_OPERATOR_H_
//
// Operators used by the high-level (parse tree) representation.
//
enum TOperator
{
EOpNull, // if in a node, should only mean a node is still being built
EOpSequence, // denotes a list of statements, or parameters, etc.
EOpFunctionCall,
EOpInternalFunctionCall, // Call to an internal helper function
EOpFunction, // For function definition
EOpParameters, // an aggregate listing the parameters to a function
EOpDeclaration,
EOpInvariantDeclaration, // Specialized declarations for attributing invariance
EOpPrototype,
//
// Unary operators
//
EOpNegative,
EOpPositive,
EOpLogicalNot,
EOpVectorLogicalNot,
EOpBitwiseNot,
EOpPostIncrement,
EOpPostDecrement,
EOpPreIncrement,
EOpPreDecrement,
//
// binary operations
//
EOpAdd,
EOpSub,
EOpMul,
EOpDiv,
EOpIMod,
EOpEqual,
EOpNotEqual,
EOpVectorEqual,
EOpVectorNotEqual,
EOpLessThan,
EOpGreaterThan,
EOpLessThanEqual,
EOpGreaterThanEqual,
EOpComma,
EOpVectorTimesScalar,
EOpVectorTimesMatrix,
EOpMatrixTimesVector,
EOpMatrixTimesScalar,
EOpLogicalOr,
EOpLogicalXor,
EOpLogicalAnd,
EOpBitShiftLeft,
EOpBitShiftRight,
EOpBitwiseAnd,
EOpBitwiseXor,
EOpBitwiseOr,
EOpIndexDirect,
EOpIndexIndirect,
EOpIndexDirectStruct,
EOpIndexDirectInterfaceBlock,
EOpVectorSwizzle,
//
// Built-in functions potentially mapped to operators
//
EOpRadians,
EOpDegrees,
EOpSin,
EOpCos,
EOpTan,
EOpAsin,
EOpAcos,
EOpAtan,
EOpSinh,
EOpCosh,
EOpTanh,
EOpAsinh,
EOpAcosh,
EOpAtanh,
EOpPow,
EOpExp,
EOpLog,
EOpExp2,
EOpLog2,
EOpSqrt,
EOpInverseSqrt,
EOpAbs,
EOpSign,
EOpFloor,
EOpTrunc,
EOpRound,
EOpRoundEven,
EOpCeil,
EOpFract,
EOpMod,
EOpModf,
EOpMin,
EOpMax,
EOpClamp,
EOpMix,
EOpStep,
EOpSmoothStep,
EOpIsNan,
EOpIsInf,
EOpFloatBitsToInt,
EOpFloatBitsToUint,
EOpIntBitsToFloat,
EOpUintBitsToFloat,
EOpPackSnorm2x16,
EOpPackUnorm2x16,
EOpPackHalf2x16,
EOpUnpackSnorm2x16,
EOpUnpackUnorm2x16,
EOpUnpackHalf2x16,
EOpLength,
EOpDistance,
EOpDot,
EOpCross,
EOpNormalize,
EOpFaceForward,
EOpReflect,
EOpRefract,
EOpDFdx, // Fragment only, OES_standard_derivatives extension
EOpDFdy, // Fragment only, OES_standard_derivatives extension
EOpFwidth, // Fragment only, OES_standard_derivatives extension
EOpMatrixTimesMatrix,
EOpOuterProduct,
EOpTranspose,
EOpDeterminant,
EOpInverse,
EOpAny,
EOpAll,
//
// Branch
//
EOpKill, // Fragment only
EOpReturn,
EOpBreak,
EOpContinue,
//
// Constructors
//
EOpConstructInt,
EOpConstructUInt,
EOpConstructBool,
EOpConstructFloat,
EOpConstructVec2,
EOpConstructVec3,
EOpConstructVec4,
EOpConstructBVec2,
EOpConstructBVec3,
EOpConstructBVec4,
EOpConstructIVec2,
EOpConstructIVec3,
EOpConstructIVec4,
EOpConstructUVec2,
EOpConstructUVec3,
EOpConstructUVec4,
EOpConstructMat2,
EOpConstructMat3,
EOpConstructMat4,
EOpConstructStruct,
//
// moves
//
EOpAssign,
EOpInitialize,
EOpAddAssign,
EOpSubAssign,
EOpMulAssign,
EOpVectorTimesMatrixAssign,
EOpVectorTimesScalarAssign,
EOpMatrixTimesScalarAssign,
EOpMatrixTimesMatrixAssign,
EOpDivAssign,
EOpIModAssign,
EOpBitShiftLeftAssign,
EOpBitShiftRightAssign,
EOpBitwiseAndAssign,
EOpBitwiseXorAssign,
EOpBitwiseOrAssign
};
// Returns the string corresponding to the operator in GLSL
const char* GetOperatorString(TOperator op);
#endif // COMPILER_TRANSLATOR_OPERATOR_H_

View File

@ -6,13 +6,21 @@
#include "compiler/translator/OutputESSL.h"
TOutputESSL::TOutputESSL(TInfoSinkBase& objSink,
TOutputESSL::TOutputESSL(TInfoSinkBase &objSink,
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction,
NameMap& nameMap,
TSymbolTable& symbolTable,
int shaderVersion)
: TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable, shaderVersion)
NameMap &nameMap,
TSymbolTable &symbolTable,
int shaderVersion,
bool forceHighp)
: TOutputGLSLBase(objSink,
clampingStrategy,
hashFunction,
nameMap,
symbolTable,
shaderVersion,
SH_ESSL_OUTPUT),
mForceHighp(forceHighp)
{
}
@ -22,6 +30,9 @@ bool TOutputESSL::writeVariablePrecision(TPrecision precision)
return false;
TInfoSinkBase& out = objSink();
out << getPrecisionString(precision);
if (mForceHighp)
out << getPrecisionString(EbpHigh);
else
out << getPrecisionString(precision);
return true;
}

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef CROSSCOMPILERGLSL_OUTPUTESSL_H_
#define CROSSCOMPILERGLSL_OUTPUTESSL_H_
#ifndef COMPILER_TRANSLATOR_OUTPUTESSL_H_
#define COMPILER_TRANSLATOR_OUTPUTESSL_H_
#include "compiler/translator/OutputGLSLBase.h"
@ -17,10 +17,13 @@ public:
ShHashFunction64 hashFunction,
NameMap& nameMap,
TSymbolTable& symbolTable,
int shaderVersion);
int shaderVersion,
bool forceHighp);
protected:
virtual bool writeVariablePrecision(TPrecision precision);
private:
bool mForceHighp;
};
#endif // CROSSCOMPILERGLSL_OUTPUTESSL_H_
#endif // COMPILER_TRANSLATOR_OUTPUTESSL_H_

View File

@ -11,8 +11,15 @@ TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink,
ShHashFunction64 hashFunction,
NameMap& nameMap,
TSymbolTable& symbolTable,
int shaderVersion)
: TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable, shaderVersion)
int shaderVersion,
ShShaderOutput output)
: TOutputGLSLBase(objSink,
clampingStrategy,
hashFunction,
nameMap,
symbolTable,
shaderVersion,
output)
{
}
@ -21,21 +28,30 @@ bool TOutputGLSL::writeVariablePrecision(TPrecision)
return false;
}
void TOutputGLSL::visitSymbol(TIntermSymbol* node)
void TOutputGLSL::visitSymbol(TIntermSymbol *node)
{
TInfoSinkBase& out = objSink();
if (node->getSymbol() == "gl_FragDepthEXT")
const TString &symbol = node->getSymbol();
if (symbol == "gl_FragDepthEXT")
{
out << "gl_FragDepth";
}
else if (symbol == "gl_FragColor" && getShaderOutput() == SH_GLSL_CORE_OUTPUT)
{
out << "webgl_FragColor";
}
else if (symbol == "gl_FragData" && getShaderOutput() == SH_GLSL_CORE_OUTPUT)
{
out << "webgl_FragData";
}
else
{
TOutputGLSLBase::visitSymbol(node);
}
}
TString TOutputGLSL::translateTextureFunction(TString& name)
TString TOutputGLSL::translateTextureFunction(TString &name)
{
static const char *simpleRename[] = {
"texture2DLodEXT", "texture2DLod",
@ -46,10 +62,30 @@ TString TOutputGLSL::translateTextureFunction(TString& name)
"textureCubeGradEXT", "textureCubeGradARB",
NULL, NULL
};
static const char *legacyToCoreRename[] = {
"texture2D", "texture",
"texture2DProj", "textureProj",
"texture2DLod", "textureLod",
"texture2DProjLod", "textureProjLod",
"textureCube", "texture",
"textureCubeLod", "textureLod",
// Extensions
"texture2DLodEXT", "textureLod",
"texture2DProjLodEXT", "textureProjLod",
"textureCubeLodEXT", "textureLod",
"texture2DGradEXT", "textureGrad",
"texture2DProjGradEXT", "textureProjGrad",
"textureCubeGradEXT", "textureGrad",
NULL, NULL
};
const char **mapping = (getShaderOutput() == SH_GLSL_CORE_OUTPUT) ?
legacyToCoreRename : simpleRename;
for (int i = 0; simpleRename[i] != NULL; i += 2) {
if (name == simpleRename[i]) {
return simpleRename[i+1];
for (int i = 0; mapping[i] != NULL; i += 2)
{
if (name == mapping[i])
{
return mapping[i+1];
}
}

View File

@ -4,25 +4,26 @@
// found in the LICENSE file.
//
#ifndef CROSSCOMPILERGLSL_OUTPUTGLSL_H_
#define CROSSCOMPILERGLSL_OUTPUTGLSL_H_
#ifndef COMPILER_TRANSLATOR_OUTPUTGLSL_H_
#define COMPILER_TRANSLATOR_OUTPUTGLSL_H_
#include "compiler/translator/OutputGLSLBase.h"
class TOutputGLSL : public TOutputGLSLBase
{
public:
public:
TOutputGLSL(TInfoSinkBase& objSink,
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction,
NameMap& nameMap,
TSymbolTable& symbolTable,
int shaderVersion);
int shaderVersion,
ShShaderOutput output);
protected:
protected:
virtual bool writeVariablePrecision(TPrecision);
virtual void visitSymbol(TIntermSymbol* node);
virtual TString translateTextureFunction(TString& name);
};
#endif // CROSSCOMPILERGLSL_OUTPUTGLSL_H_
#endif // COMPILER_TRANSLATOR_OUTPUTGLSL_H_

View File

@ -36,8 +36,17 @@ bool isSingleStatement(TIntermNode *node)
{
return false;
}
else if (node->getAsSwitchNode())
{
return false;
}
else if (node->getAsCaseNode())
{
return false;
}
return true;
}
} // namespace
TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink,
@ -45,7 +54,8 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink,
ShHashFunction64 hashFunction,
NameMap &nameMap,
TSymbolTable &symbolTable,
int shaderVersion)
int shaderVersion,
ShShaderOutput output)
: TIntermTraverser(true, true, true),
mObjSink(objSink),
mDeclaringVariables(false),
@ -53,7 +63,8 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink,
mHashFunction(hashFunction),
mNameMap(nameMap),
mSymbolTable(symbolTable),
mShaderVersion(shaderVersion)
mShaderVersion(shaderVersion),
mOutput(output)
{
}
@ -83,7 +94,34 @@ void TOutputGLSLBase::writeVariableType(const TType &type)
TQualifier qualifier = type.getQualifier();
if (qualifier != EvqTemporary && qualifier != EvqGlobal)
{
out << type.getQualifierString() << " ";
if (mOutput == SH_GLSL_CORE_OUTPUT)
{
switch (qualifier)
{
case EvqAttribute:
out << "in" << " ";
break;
case EvqVaryingIn:
out << "in" << " ";
break;
case EvqVaryingOut:
out << "out" << " ";
break;
case EvqInvariantVaryingIn:
out << "invariant in" << " ";
break;
case EvqInvariantVaryingOut:
out << "invariant out" << " ";
break;
default:
out << type.getQualifierString() << " ";
break;
}
}
else
{
out << type.getQualifierString() << " ";
}
}
// Declare the struct if we have not done so already.
if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct()))
@ -166,6 +204,9 @@ const ConstantUnion *TOutputGLSLBase::writeConstantUnion(
case EbtInt:
out << pConstUnion->getIConst();
break;
case EbtUInt:
out << pConstUnion->getUConst() << "u";
break;
case EbtBool:
out << pConstUnion->getBConst();
break;
@ -223,6 +264,9 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
case EOpDivAssign:
writeTriplet(visit, "(", " /= ", ")");
break;
case EOpIModAssign:
writeTriplet(visit, "(", " %= ", ")");
break;
// Notice the fall-through.
case EOpMulAssign:
case EOpVectorTimesMatrixAssign:
@ -231,6 +275,21 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
case EOpMatrixTimesMatrixAssign:
writeTriplet(visit, "(", " *= ", ")");
break;
case EOpBitShiftLeftAssign:
writeTriplet(visit, "(", " <<= ", ")");
break;
case EOpBitShiftRightAssign:
writeTriplet(visit, "(", " >>= ", ")");
break;
case EOpBitwiseAndAssign:
writeTriplet(visit, "(", " &= ", ")");
break;
case EOpBitwiseXorAssign:
writeTriplet(visit, "(", " ^= ", ")");
break;
case EOpBitwiseOrAssign:
writeTriplet(visit, "(", " |= ", ")");
break;
case EOpIndexDirect:
writeTriplet(visit, NULL, "[", "]");
@ -340,9 +399,25 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
case EOpDiv:
writeTriplet(visit, "(", " / ", ")");
break;
case EOpMod:
UNIMPLEMENTED();
case EOpIMod:
writeTriplet(visit, "(", " % ", ")");
break;
case EOpBitShiftLeft:
writeTriplet(visit, "(", " << ", ")");
break;
case EOpBitShiftRight:
writeTriplet(visit, "(", " >> ", ")");
break;
case EOpBitwiseAnd:
writeTriplet(visit, "(", " & ", ")");
break;
case EOpBitwiseXor:
writeTriplet(visit, "(", " ^ ", ")");
break;
case EOpBitwiseOr:
writeTriplet(visit, "(", " | ", ")");
break;
case EOpEqual:
writeTriplet(visit, "(", " == ", ")");
break;
@ -398,6 +473,7 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node)
case EOpPositive: preString = "(+"; break;
case EOpVectorLogicalNot: preString = "not("; break;
case EOpLogicalNot: preString = "(!"; break;
case EOpBitwiseNot: preString = "(~"; break;
case EOpPostIncrement: preString = "("; postString = "++)"; break;
case EOpPostDecrement: preString = "("; postString = "--)"; break;
@ -429,6 +505,25 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node)
preString = "atan(";
break;
case EOpSinh:
preString = "sinh(";
break;
case EOpCosh:
preString = "cosh(";
break;
case EOpTanh:
preString = "tanh(";
break;
case EOpAsinh:
preString = "asinh(";
break;
case EOpAcosh:
preString = "acosh(";
break;
case EOpAtanh:
preString = "atanh(";
break;
case EOpExp:
preString = "exp(";
break;
@ -457,12 +552,59 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node)
case EOpFloor:
preString = "floor(";
break;
case EOpTrunc:
preString = "trunc(";
break;
case EOpRound:
preString = "round(";
break;
case EOpRoundEven:
preString = "roundEven(";
break;
case EOpCeil:
preString = "ceil(";
break;
case EOpFract:
preString = "fract(";
break;
case EOpIsNan:
preString = "isnan(";
break;
case EOpIsInf:
preString = "isinf(";
break;
case EOpFloatBitsToInt:
preString = "floatBitsToInt(";
break;
case EOpFloatBitsToUint:
preString = "floatBitsToUint(";
break;
case EOpIntBitsToFloat:
preString = "intBitsToFloat(";
break;
case EOpUintBitsToFloat:
preString = "uintBitsToFloat(";
break;
case EOpPackSnorm2x16:
preString = "packSnorm2x16(";
break;
case EOpPackUnorm2x16:
preString = "packUnorm2x16(";
break;
case EOpPackHalf2x16:
preString = "packHalf2x16(";
break;
case EOpUnpackSnorm2x16:
preString = "unpackSnorm2x16(";
break;
case EOpUnpackUnorm2x16:
preString = "unpackUnorm2x16(";
break;
case EOpUnpackHalf2x16:
preString = "unpackHalf2x16(";
break;
case EOpLength:
preString = "length(";
@ -481,6 +623,16 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node)
preString = "fwidth(";
break;
case EOpTranspose:
preString = "transpose(";
break;
case EOpDeterminant:
preString = "determinant(";
break;
case EOpInverse:
preString = "inverse(";
break;
case EOpAny:
preString = "any(";
break;
@ -536,6 +688,36 @@ bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection *node)
return false;
}
bool TOutputGLSLBase::visitSwitch(Visit visit, TIntermSwitch *node)
{
if (node->getStatementList())
{
writeTriplet(visit, "switch (", ") ", nullptr);
// The curly braces get written when visiting the statementList aggregate
}
else
{
// No statementList, so it won't output curly braces
writeTriplet(visit, "switch (", ") {", "}\n");
}
return true;
}
bool TOutputGLSLBase::visitCase(Visit visit, TIntermCase *node)
{
if (node->hasCondition())
{
writeTriplet(visit, "case (", nullptr, "):\n");
return true;
}
else
{
TInfoSinkBase &out = objSink();
out << "default:\n";
return false;
}
}
bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
{
bool visitChildren = true;
@ -555,11 +737,11 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
for (TIntermSequence::const_iterator iter = node->getSequence()->begin();
iter != node->getSequence()->end(); ++iter)
{
TIntermNode *node = *iter;
ASSERT(node != NULL);
node->traverse(this);
TIntermNode *curNode = *iter;
ASSERT(curNode != NULL);
curNode->traverse(this);
if (isSingleStatement(node))
if (isSingleStatement(curNode))
out << ";\n";
}
decrementDepth();
@ -622,6 +804,15 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
else
out << ")";
break;
case EOpInternalFunctionCall:
// Function call to an internal helper function.
if (visit == PreVisit)
out << node->getName() << "(";
else if (visit == InVisit)
out << ", ";
else
out << ")";
break;
case EOpParameters:
// Function parameters.
ASSERT(visit == PreVisit);
@ -724,6 +915,10 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
}
break;
case EOpOuterProduct:
writeBuiltInFunctionTriplet(visit, "outerProduct(", useEmulatedFunction);
break;
case EOpLessThan:
writeBuiltInFunctionTriplet(visit, "lessThan(", useEmulatedFunction);
break;
@ -749,6 +944,9 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpMod:
writeBuiltInFunctionTriplet(visit, "mod(", useEmulatedFunction);
break;
case EOpModf:
writeBuiltInFunctionTriplet(visit, "modf(", useEmulatedFunction);
break;
case EOpPow:
writeBuiltInFunctionTriplet(visit, "pow(", useEmulatedFunction);
break;

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_
#define CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_
#ifndef COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_
#define COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_
#include <set>
@ -21,7 +21,13 @@ class TOutputGLSLBase : public TIntermTraverser
ShHashFunction64 hashFunction,
NameMap &nameMap,
TSymbolTable& symbolTable,
int shaderVersion);
int shaderVersion,
ShShaderOutput output);
ShShaderOutput getShaderOutput() const
{
return mOutput;
}
protected:
TInfoSinkBase &objSink() { return mObjSink; }
@ -37,6 +43,8 @@ class TOutputGLSLBase : public TIntermTraverser
virtual bool visitBinary(Visit visit, TIntermBinary *node);
virtual bool visitUnary(Visit visit, TIntermUnary *node);
virtual bool visitSelection(Visit visit, TIntermSelection *node);
virtual bool visitSwitch(Visit visit, TIntermSwitch *node);
virtual bool visitCase(Visit visit, TIntermCase *node);
virtual bool visitAggregate(Visit visit, TIntermAggregate *node);
virtual bool visitLoop(Visit visit, TIntermLoop *node);
virtual bool visitBranch(Visit visit, TIntermBranch *node);
@ -78,6 +86,8 @@ class TOutputGLSLBase : public TIntermTraverser
TSymbolTable &mSymbolTable;
const int mShaderVersion;
ShShaderOutput mOutput;
};
#endif // CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_
#endif // COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_

File diff suppressed because it is too large Load Diff

View File

@ -4,18 +4,20 @@
// found in the LICENSE file.
//
#ifndef COMPILER_OUTPUTHLSL_H_
#define COMPILER_OUTPUTHLSL_H_
#ifndef COMPILER_TRANSLATOR_OUTPUTHLSL_H_
#define COMPILER_TRANSLATOR_OUTPUTHLSL_H_
#include <list>
#include <set>
#include <map>
#include <stack>
#include "angle_gl.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/ParseContext.h"
class BuiltInFunctionEmulator;
namespace sh
{
class UnfoldShortCircuit;
@ -27,20 +29,25 @@ typedef std::map<TString, TIntermSymbol*> ReferencedSymbols;
class OutputHLSL : public TIntermTraverser
{
public:
OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator);
OutputHLSL(sh::GLenum shaderType, int shaderVersion,
const TExtensionBehavior &extensionBehavior,
const char *sourcePath, ShShaderOutput outputType,
int numRenderTargets, const std::vector<Uniform> &uniforms,
int compileOptions);
~OutputHLSL();
void output();
TInfoSinkBase &getBodyStream();
void output(TIntermNode *treeRoot, TInfoSinkBase &objSink);
const std::map<std::string, unsigned int> &getInterfaceBlockRegisterMap() const;
const std::map<std::string, unsigned int> &getUniformRegisterMap() const;
static TString initializer(const TType &type);
TInfoSinkBase &getInfoSink() { ASSERT(!mInfoSinkStack.empty()); return *mInfoSinkStack.top(); }
protected:
void header();
void header(const BuiltInFunctionEmulator *builtInFunctionEmulator);
// Visit AST nodes and output their code to the body stream
void visitSymbol(TIntermSymbol*);
@ -49,6 +56,8 @@ class OutputHLSL : public TIntermTraverser
bool visitBinary(Visit visit, TIntermBinary*);
bool visitUnary(Visit visit, TIntermUnary*);
bool visitSelection(Visit visit, TIntermSelection*);
bool visitSwitch(Visit visit, TIntermSwitch *);
bool visitCase(Visit visit, TIntermCase *);
bool visitAggregate(Visit visit, TIntermAggregate*);
bool visitLoop(Visit visit, TIntermLoop*);
bool visitBranch(Visit visit, TIntermBranch*);
@ -56,16 +65,39 @@ class OutputHLSL : public TIntermTraverser
void traverseStatements(TIntermNode *node);
bool isSingleStatement(TIntermNode *node);
bool handleExcessiveLoop(TIntermLoop *node);
void outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString);
// Emit one of three strings depending on traverse phase. Called with literal strings so using const char* instead of TString.
void outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString, TInfoSinkBase &out);
void outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString);
void outputLineDirective(int line);
TString argumentString(const TIntermSymbol *symbol);
int vectorSize(const TType &type) const;
void outputConstructor(Visit visit, const TType &type, const TString &name, const TIntermSequence *parameters);
// Emit constructor. Called with literal names so using const char* instead of TString.
void outputConstructor(Visit visit, const TType &type, const char *name, const TIntermSequence *parameters);
const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *constUnion);
TParseContext &mContext;
void outputEqual(Visit visit, const TType &type, TOperator op, TInfoSinkBase &out);
void writeEmulatedFunctionTriplet(Visit visit, const char *preStr);
void makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flaggedStructs);
// Returns true if it found a 'same symbol' initializer (initializer that references the variable it's initting)
bool writeSameSymbolInitializer(TInfoSinkBase &out, TIntermSymbol *symbolNode, TIntermTyped *expression);
void writeDeferredGlobalInitializers(TInfoSinkBase &out);
// Returns the function name
TString addStructEqualityFunction(const TStructure &structure);
TString addArrayEqualityFunction(const TType &type);
TString addArrayAssignmentFunction(const TType &type);
sh::GLenum mShaderType;
int mShaderVersion;
const TExtensionBehavior &mExtensionBehavior;
const char *mSourcePath;
const ShShaderOutput mOutputType;
int mCompileOptions;
UnfoldShortCircuit *mUnfoldShortCircuit;
bool mInsideFunction;
@ -74,6 +106,11 @@ class OutputHLSL : public TIntermTraverser
TInfoSinkBase mBody;
TInfoSinkBase mFooter;
// A stack is useful when we want to traverse in the header, or in helper functions, but not always
// write to the body. Instead use an InfoSink stack to keep our current state intact.
// TODO (jmadill): Just passing an InfoSink in function parameters would be simpler.
std::stack<TInfoSinkBase *> mInfoSinkStack;
ReferencedSymbols mReferencedUniforms;
ReferencedSymbols mReferencedInterfaceBlocks;
ReferencedSymbols mReferencedAttributes;
@ -119,25 +156,13 @@ class OutputHLSL : public TIntermTraverser
bool mUsesPointCoord;
bool mUsesFrontFacing;
bool mUsesPointSize;
bool mUsesInstanceID;
bool mUsesFragDepth;
bool mUsesXor;
bool mUsesMod1;
bool mUsesMod2v;
bool mUsesMod2f;
bool mUsesMod3v;
bool mUsesMod3f;
bool mUsesMod4v;
bool mUsesMod4f;
bool mUsesFaceforward1;
bool mUsesFaceforward2;
bool mUsesFaceforward3;
bool mUsesFaceforward4;
bool mUsesAtan2_1;
bool mUsesAtan2_2;
bool mUsesAtan2_3;
bool mUsesAtan2_4;
bool mUsesDiscardRewriting;
bool mUsesNestedBreak;
bool mRequiresIEEEStrictCompiling;
int mNumRenderTargets;
@ -156,9 +181,41 @@ class OutputHLSL : public TIntermTraverser
std::map<TIntermTyped*, TString> mFlaggedStructMappedNames;
std::map<TIntermTyped*, TString> mFlaggedStructOriginalNames;
void makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flaggedStructs);
// Some initializers use varyings, uniforms or attributes, thus we can't evaluate some variables
// at global static scope in HLSL. These variables depend on values which we retrieve from the
// shader input structure, which we set in the D3D main function. Instead, we can initialize
// these static globals after we initialize our other globals.
std::vector<std::pair<TIntermSymbol*, TIntermTyped*>> mDeferredGlobalInitializers;
struct HelperFunction
{
TString functionName;
TString functionDefinition;
virtual ~HelperFunction() {}
};
// A list of all equality comparison functions. It's important to preserve the order at
// which we add the functions, since nested structures call each other recursively, and
// structure equality functions may need to call array equality functions and vice versa.
// The ownership of the pointers is maintained by the type-specific arrays.
std::vector<HelperFunction*> mEqualityFunctions;
struct StructEqualityFunction : public HelperFunction
{
const TStructure *structure;
};
std::vector<StructEqualityFunction*> mStructEqualityFunctions;
struct ArrayHelperFunction : public HelperFunction
{
TType type;
};
std::vector<ArrayHelperFunction*> mArrayEqualityFunctions;
std::vector<ArrayHelperFunction> mArrayAssignmentFunctions;
};
}
#endif // COMPILER_OUTPUTHLSL_H_
#endif // COMPILER_TRANSLATOR_OUTPUTHLSL_H_

View File

@ -9,8 +9,9 @@
#include <stdarg.h>
#include <stdio.h>
#include "compiler/translator/glslang.h"
#include "compiler/preprocessor/SourceLocation.h"
#include "compiler/translator/glslang.h"
#include "compiler/translator/ValidateSwitch.h"
///////////////////////////////////////////////////////////////////////
//
@ -796,8 +797,23 @@ bool TParseContext::arrayErrorCheck(const TSourceLoc& line, const TString& ident
bool sameScope = false;
TSymbol* symbol = symbolTable.find(identifier, 0, &builtIn, &sameScope);
if (symbol == 0 || !sameScope) {
if (reservedErrorCheck(line, identifier))
return true;
bool needsReservedErrorCheck = true;
// gl_LastFragData may be redeclared with a new precision qualifier
if (identifier.compare(0, 15, "gl_LastFragData") == 0) {
if (type.arraySize == static_cast<const TVariable*>(symbolTable.findBuiltIn("gl_MaxDrawBuffers", shaderVersion))->getConstPointer()->getIConst()) {
if (TSymbol* builtInSymbol = symbolTable.findBuiltIn(identifier, shaderVersion)) {
needsReservedErrorCheck = extensionErrorCheck(line, builtInSymbol->getExtension());
}
} else {
error(line, "redeclaration of array with size != gl_MaxDrawBuffers", identifier.c_str());
return true;
}
}
if (needsReservedErrorCheck)
if (reservedErrorCheck(line, identifier))
return true;
variable = new TVariable(&identifier, TType(type));
@ -976,6 +992,26 @@ bool TParseContext::layoutLocationErrorCheck(const TSourceLoc& location, const T
return false;
}
bool TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *aggregate)
{
for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
{
TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
if (qual == EvqOut || qual == EvqInOut)
{
TIntermTyped *node = (*(aggregate->getSequence()))[i]->getAsTyped();
if (lValueErrorCheck(node->getLine(), "assign", node))
{
error(node->getLine(),
"Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
recover();
return true;
}
}
}
return false;
}
bool TParseContext::supportsExtension(const char* extension)
{
const TExtensionBehavior& extbehavior = extensionBehavior();
@ -1062,14 +1098,14 @@ const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
//
// Return the function symbol if found, otherwise 0.
//
const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, int shaderVersion, bool *builtIn)
const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, int inputShaderVersion, 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(), shaderVersion, builtIn);
const TSymbol* symbol = symbolTable.find(call->getName(), inputShaderVersion, builtIn);
if (symbol == 0 || symbol->isFunction()) {
symbol = symbolTable.find(call->getMangledName(), shaderVersion, builtIn);
symbol = symbolTable.find(call->getMangledName(), inputShaderVersion, builtIn);
}
if (symbol == 0) {
@ -1162,7 +1198,7 @@ bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& id
if (qualifier != EvqConst) {
TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line);
intermNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
if (intermNode == 0) {
assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
return true;
@ -1375,7 +1411,7 @@ TIntermAggregate* TParseContext::parseInvariantDeclaration(const TSourceLoc &inv
recover();
return NULL;
}
symbolTable.addInvariantVarying(*identifier);
symbolTable.addInvariantVarying(std::string(identifier->c_str()));
const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
ASSERT(variable);
const TType &type = variable->getType();
@ -1605,7 +1641,7 @@ TFunction *TParseContext::addConstructorFunc(TPublicType publicType)
//
// Returns 0 for an error or the constructed node (aggregate or typed) for no error.
//
TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, const TType *type, TOperator op, TFunction *fnCall, const TSourceLoc &line)
TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, TType *type, TOperator op, TFunction *fnCall, const TSourceLoc &line)
{
TIntermAggregate *aggregateArguments = arguments->getAsAggregate();
@ -1633,13 +1669,21 @@ TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, const TType
}
// Turn the argument list itself into a constructor
TIntermTyped *constructor = intermediate.setAggregateOperator(aggregateArguments, op, line);
TIntermTyped *constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type);
TIntermAggregate *constructor = intermediate.setAggregateOperator(aggregateArguments, op, line);
TIntermTyped *constConstructor = foldConstConstructor(constructor, *type);
if (constConstructor)
{
return constConstructor;
}
// Structs should not be precision qualified, the individual members may be.
// Built-in types on the other hand should be precision qualified.
if (op != EOpConstructStruct)
{
constructor->setPrecisionFromChildren();
type->setPrecision(constructor->getPrecision());
}
return constructor;
}
@ -2028,9 +2072,11 @@ TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, co
recover();
}
if (indexExpression->getQualifier() == EvqConst)
TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
if (indexExpression->getQualifier() == EvqConst && indexConstantUnion)
{
int index = indexExpression->getAsConstantUnion()->getIConst(0);
int index = indexConstantUnion->getIConst(0);
if (index < 0)
{
std::stringstream infoStream;
@ -2091,7 +2137,7 @@ TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, co
index = baseExpression->getType().getNominalSize() - 1;
}
indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index);
indexConstantUnion->getUnionArrayPointer()->setIConst(index);
indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
}
}
@ -2520,7 +2566,10 @@ TPublicType TParseContext::addStructure(const TSourceLoc& structLine, const TSou
TStructure* structure = new TStructure(structName, fieldList);
TType* structureType = new TType(structure);
// Store a bool in the struct if we're at global scope, to allow us to
// skip the local struct scoping workaround in HLSL.
structure->setUniqueId(TSymbolTable::nextUniqueId());
structure->setAtGlobalScope(symbolTable.atGlobalLevel());
if (!structName->empty())
{
@ -2560,6 +2609,553 @@ TPublicType TParseContext::addStructure(const TSourceLoc& structLine, const TSou
return publicType;
}
TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc)
{
TBasicType switchType = init->getBasicType();
if ((switchType != EbtInt && switchType != EbtUInt) ||
init->isMatrix() ||
init->isArray() ||
init->isVector())
{
error(init->getLine(), "init-expression in a switch statement must be a scalar integer", "switch");
recover();
return nullptr;
}
if (statementList)
{
if (!ValidateSwitch::validate(switchType, this, statementList, loc))
{
recover();
return nullptr;
}
}
TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
if (node == nullptr)
{
error(loc, "erroneous switch statement", "switch");
recover();
return nullptr;
}
return node;
}
TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
{
if (mSwitchNestingLevel == 0)
{
error(loc, "case labels need to be inside switch statements", "case");
recover();
return nullptr;
}
if (condition == nullptr)
{
error(loc, "case label must have a condition", "case");
recover();
return nullptr;
}
if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
condition->isMatrix() ||
condition->isArray() ||
condition->isVector())
{
error(condition->getLine(), "case label must be a scalar integer", "case");
recover();
}
TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
if (conditionConst == nullptr)
{
error(condition->getLine(), "case label must be constant", "case");
recover();
}
TIntermCase *node = intermediate.addCase(condition, loc);
if (node == nullptr)
{
error(loc, "erroneous case statement", "case");
recover();
return nullptr;
}
return node;
}
TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
{
if (mSwitchNestingLevel == 0)
{
error(loc, "default labels need to be inside switch statements", "default");
recover();
return nullptr;
}
TIntermCase *node = intermediate.addCase(nullptr, loc);
if (node == nullptr)
{
error(loc, "erroneous default statement", "default");
recover();
return nullptr;
}
return node;
}
TIntermTyped *TParseContext::createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc,
const TType *funcReturnType)
{
if (child == nullptr)
{
return nullptr;
}
switch (op)
{
case EOpLogicalNot:
if (child->getBasicType() != EbtBool ||
child->isMatrix() ||
child->isArray() ||
child->isVector())
{
return nullptr;
}
break;
case EOpBitwiseNot:
if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
child->isMatrix() ||
child->isArray())
{
return nullptr;
}
break;
case EOpPostIncrement:
case EOpPreIncrement:
case EOpPostDecrement:
case EOpPreDecrement:
case EOpNegative:
case EOpPositive:
if (child->getBasicType() == EbtStruct ||
child->getBasicType() == EbtBool ||
child->isArray())
{
return nullptr;
}
// Operators for built-ins are already type checked against their prototype.
default:
break;
}
return intermediate.addUnaryMath(op, child, loc, funcReturnType);
}
TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
{
TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
if (node == nullptr)
{
unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
recover();
return child;
}
return node;
}
TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
{
if (lValueErrorCheck(loc, GetOperatorString(op), child))
recover();
return addUnaryMath(op, child, loc);
}
bool TParseContext::binaryOpCommonCheck(TOperator op, TIntermTyped *left, TIntermTyped *right,
const TSourceLoc &loc)
{
if (left->isArray() || right->isArray())
{
if (shaderVersion < 300)
{
error(loc, "Invalid operation for arrays", GetOperatorString(op));
return false;
}
if (left->isArray() != right->isArray())
{
error(loc, "array / non-array mismatch", GetOperatorString(op));
return false;
}
switch (op)
{
case EOpEqual:
case EOpNotEqual:
case EOpAssign:
case EOpInitialize:
break;
default:
error(loc, "Invalid operation for arrays", GetOperatorString(op));
return false;
}
if (left->getArraySize() != right->getArraySize())
{
error(loc, "array size mismatch", GetOperatorString(op));
return false;
}
}
// Check ops which require integer / ivec parameters
bool isBitShift = false;
switch (op)
{
case EOpBitShiftLeft:
case EOpBitShiftRight:
case EOpBitShiftLeftAssign:
case EOpBitShiftRightAssign:
// Unsigned can be bit-shifted by signed and vice versa, but we need to
// check that the basic type is an integer type.
isBitShift = true;
if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
{
return false;
}
break;
case EOpBitwiseAnd:
case EOpBitwiseXor:
case EOpBitwiseOr:
case EOpBitwiseAndAssign:
case EOpBitwiseXorAssign:
case EOpBitwiseOrAssign:
// It is enough to check the type of only one operand, since later it
// is checked that the operand types match.
if (!IsInteger(left->getBasicType()))
{
return false;
}
break;
default:
break;
}
// GLSL ES 1.00 and 3.00 do not support implicit type casting.
// So the basic type should usually match.
if (!isBitShift && left->getBasicType() != right->getBasicType())
{
return false;
}
// Check that type sizes match exactly on ops that require that.
// Also check restrictions for structs that contain arrays or samplers.
switch(op)
{
case EOpAssign:
case EOpInitialize:
case EOpEqual:
case EOpNotEqual:
// ESSL 1.00 sections 5.7, 5.8, 5.9
if (shaderVersion < 300 && left->getType().isStructureContainingArrays())
{
error(loc, "undefined operation for structs containing arrays", GetOperatorString(op));
return false;
}
// Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
// we interpret the spec so that this extends to structs containing samplers,
// similarly to ESSL 1.00 spec.
if ((shaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
left->getType().isStructureContainingSamplers())
{
error(loc, "undefined operation for structs containing samplers", GetOperatorString(op));
return false;
}
case EOpLessThan:
case EOpGreaterThan:
case EOpLessThanEqual:
case EOpGreaterThanEqual:
if ((left->getNominalSize() != right->getNominalSize()) ||
(left->getSecondarySize() != right->getSecondarySize()))
{
return false;
}
default:
break;
}
return true;
}
TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op, TIntermTyped *left, TIntermTyped *right,
const TSourceLoc &loc)
{
if (!binaryOpCommonCheck(op, left, right, loc))
return nullptr;
switch (op)
{
case EOpEqual:
case EOpNotEqual:
break;
case EOpLessThan:
case EOpGreaterThan:
case EOpLessThanEqual:
case EOpGreaterThanEqual:
ASSERT(!left->isArray() && !right->isArray());
if (left->isMatrix() || left->isVector() ||
left->getBasicType() == EbtStruct)
{
return nullptr;
}
break;
case EOpLogicalOr:
case EOpLogicalXor:
case EOpLogicalAnd:
ASSERT(!left->isArray() && !right->isArray());
if (left->getBasicType() != EbtBool ||
left->isMatrix() || left->isVector())
{
return nullptr;
}
break;
case EOpAdd:
case EOpSub:
case EOpDiv:
case EOpMul:
ASSERT(!left->isArray() && !right->isArray());
if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
{
return nullptr;
}
break;
case EOpIMod:
ASSERT(!left->isArray() && !right->isArray());
// Note that this is only for the % operator, not for mod()
if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
{
return nullptr;
}
break;
// Note that for bitwise ops, type checking is done in promote() to
// share code between ops and compound assignment
default:
break;
}
return intermediate.addBinaryMath(op, left, right, loc);
}
TIntermTyped *TParseContext::addBinaryMath(TOperator op, TIntermTyped *left, TIntermTyped *right,
const TSourceLoc &loc)
{
TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
if (node == 0)
{
binaryOpError(loc, GetOperatorString(op), left->getCompleteString(), right->getCompleteString());
recover();
return left;
}
return node;
}
TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op, TIntermTyped *left, TIntermTyped *right,
const TSourceLoc &loc)
{
TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
if (node == 0)
{
binaryOpError(loc, GetOperatorString(op), left->getCompleteString(), right->getCompleteString());
recover();
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setBConst(false);
return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), loc);
}
return node;
}
TIntermTyped *TParseContext::createAssign(TOperator op, TIntermTyped *left, TIntermTyped *right,
const TSourceLoc &loc)
{
if (binaryOpCommonCheck(op, left, right, loc))
{
return intermediate.addAssign(op, left, right, loc);
}
return nullptr;
}
TIntermTyped *TParseContext::addAssign(TOperator op, TIntermTyped *left, TIntermTyped *right,
const TSourceLoc &loc)
{
TIntermTyped *node = createAssign(op, left, right, loc);
if (node == nullptr)
{
assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
recover();
return left;
}
return node;
}
TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
{
switch (op)
{
case EOpContinue:
if (mLoopNestingLevel <= 0)
{
error(loc, "continue statement only allowed in loops", "");
recover();
}
break;
case EOpBreak:
if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
{
error(loc, "break statement only allowed in loops and switch statements", "");
recover();
}
break;
case EOpReturn:
if (currentFunctionType->getBasicType() != EbtVoid)
{
error(loc, "non-void function must return a value", "return");
recover();
}
break;
default:
// No checks for discard
break;
}
return intermediate.addBranch(op, loc);
}
TIntermBranch *TParseContext::addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc)
{
ASSERT(op == EOpReturn);
mFunctionReturnsValue = true;
if (currentFunctionType->getBasicType() == EbtVoid)
{
error(loc, "void function cannot return a value", "return");
recover();
}
else if (*currentFunctionType != returnValue->getType())
{
error(loc, "function return is not matching type:", "return");
recover();
}
return intermediate.addBranch(op, returnValue, loc);
}
TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *node,
const TSourceLoc &loc, bool *fatalError)
{
*fatalError = false;
TOperator op = fnCall->getBuiltInOp();
TIntermTyped *callNode = nullptr;
if (op != EOpNull)
{
//
// Then this should be a constructor.
// Don't go through the symbol table for constructors.
// Their parameters will be verified algorithmically.
//
TType type(EbtVoid, EbpUndefined); // use this to get the type back
if (!constructorErrorCheck(loc, node, *fnCall, op, &type))
{
//
// It's a constructor, of type 'type'.
//
callNode = addConstructor(node, &type, op, fnCall, loc);
}
if (callNode == nullptr)
{
recover();
callNode = intermediate.setAggregateOperator(nullptr, op, loc);
}
callNode->setType(type);
}
else
{
//
// Not a constructor. Find it in the symbol table.
//
const TFunction* fnCandidate;
bool builtIn;
fnCandidate = findFunction(loc, fnCall, shaderVersion, &builtIn);
if (fnCandidate)
{
//
// A declared function.
//
if (builtIn && !fnCandidate->getExtension().empty() &&
extensionErrorCheck(loc, fnCandidate->getExtension()))
{
recover();
}
op = fnCandidate->getBuiltInOp();
if (builtIn && op != EOpNull)
{
//
// A function call mapped to a built-in operation.
//
if (fnCandidate->getParamCount() == 1)
{
//
// Treat it like a built-in unary operator.
//
callNode = createUnaryMath(op, node->getAsTyped(), loc, &fnCandidate->getReturnType());
if (callNode == nullptr)
{
std::stringstream extraInfoStream;
extraInfoStream << "built in unary operator function. Type: "
<< static_cast<TIntermTyped*>(node)->getCompleteString();
std::string extraInfo = extraInfoStream.str();
error(node->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str());
*fatalError = true;
return nullptr;
}
}
else
{
TIntermAggregate *aggregate = intermediate.setAggregateOperator(node, op, loc);
aggregate->setType(fnCandidate->getReturnType());
aggregate->setPrecisionFromChildren();
callNode = aggregate;
// Some built-in functions have out parameters too.
functionCallLValueErrorCheck(fnCandidate, aggregate);
}
}
else
{
// This is a real function call
TIntermAggregate *aggregate = intermediate.setAggregateOperator(node, EOpFunctionCall, loc);
aggregate->setType(fnCandidate->getReturnType());
// this is how we know whether the given function is a builtIn function or a user defined function
// if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
// if builtIn == true, it's definitely a builtIn function with EOpNull
if (!builtIn)
aggregate->setUserDefined();
aggregate->setName(fnCandidate->getMangledName());
// This needs to happen after the name is set
if (builtIn)
aggregate->setBuiltInFunctionPrecision();
callNode = aggregate;
functionCallLValueErrorCheck(fnCandidate, aggregate);
}
}
else
{
// error message was put out by findFunction()
// Put on a dummy node for error recovery
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setFConst(0.0f);
callNode = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), loc);
recover();
}
}
delete fnCall;
return callNode;
}
//
// Parse an array of strings using yyparse.
//

View File

@ -3,8 +3,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#ifndef _PARSER_HELPER_INCLUDED_
#define _PARSER_HELPER_INCLUDED_
#ifndef COMPILER_TRANSLATOR_PARSECONTEXT_H_
#define COMPILER_TRANSLATOR_PARSECONTEXT_H_
#include "compiler/translator/Compiler.h"
#include "compiler/translator/Diagnostics.h"
@ -25,24 +25,25 @@ struct TMatrixFields {
// they can be passed to the parser without needing a global.
//
struct TParseContext {
TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, sh::GLenum type, ShShaderSpec spec, int options, bool checksPrecErrors, const char* sourcePath, TInfoSink& is) :
TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, sh::GLenum type, ShShaderSpec spec, int options, bool checksPrecErrors, TInfoSink& is, bool debugShaderPrecisionSupported) :
intermediate(interm),
symbolTable(symt),
shaderType(type),
shaderSpec(spec),
compileOptions(options),
sourcePath(sourcePath),
treeRoot(0),
loopNestingLevel(0),
mLoopNestingLevel(0),
structNestingLevel(0),
mSwitchNestingLevel(0),
currentFunctionType(NULL),
functionReturnsValue(false),
mFunctionReturnsValue(false),
checksPrecisionErrors(checksPrecErrors),
fragmentPrecisionHigh(false),
defaultMatrixPacking(EmpColumnMajor),
defaultBlockStorage(EbsShared),
diagnostics(is),
shaderVersion(100),
directiveHandler(ext, diagnostics, shaderVersion),
directiveHandler(ext, diagnostics, shaderVersion, debugShaderPrecisionSupported),
preprocessor(&diagnostics, &directiveHandler),
scanner(NULL) { }
TIntermediate& intermediate; // to hold and build a parse tree
@ -51,12 +52,12 @@ struct TParseContext {
ShShaderSpec shaderSpec; // The language specification compiler conforms to - GLES2 or WebGL.
int shaderVersion;
int compileOptions;
const char* sourcePath; // Path of source file or NULL.
TIntermNode* treeRoot; // root of parse tree being created
int loopNestingLevel; // 0 if outside all loops
int mLoopNestingLevel; // 0 if outside all loops
int structNestingLevel; // incremented while parsing a struct declaration
int mSwitchNestingLevel; // 0 if outside all switch statements
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 mFunctionReturnsValue; // 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.
TLayoutMatrixPacking defaultMatrixPacking;
@ -110,6 +111,7 @@ struct TParseContext {
bool extensionErrorCheck(const TSourceLoc& line, const TString&);
bool singleDeclarationErrorCheck(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier);
bool layoutLocationErrorCheck(const TSourceLoc& location, const TLayoutQualifier &layoutQualifier);
bool functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *);
const TPragma& pragma() const { return directiveHandler.pragma(); }
const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); }
@ -120,7 +122,7 @@ struct TParseContext {
bool containsSampler(TType& type);
bool areAllChildConst(TIntermAggregate* aggrNode);
const TFunction* findFunction(const TSourceLoc& line, TFunction* pfnCall, int shaderVersion, bool *builtIn = 0);
const TFunction* findFunction(const TSourceLoc& line, TFunction* pfnCall, int inputShaderVersion, bool *builtIn = 0);
bool executeInitializer(const TSourceLoc& line, const TString& identifier, TPublicType& pType,
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
@ -136,7 +138,7 @@ struct TParseContext {
TIntermAggregate* parseInitDeclarator(TPublicType &publicType, TIntermAggregate *declaratorList, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& initLocation, TIntermTyped *initializer);
void parseGlobalLayoutQualifier(const TPublicType &typeQualifier);
TFunction *addConstructorFunc(TPublicType publicType);
TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, const TSourceLoc&);
TIntermTyped* addConstructor(TIntermNode*, TType*, TOperator, TFunction*, const TSourceLoc&);
TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type);
TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, const TSourceLoc&);
TIntermTyped* addConstMatrixNode(int , TIntermTyped*, const TSourceLoc&);
@ -164,9 +166,42 @@ struct TParseContext {
void exitStructDeclaration();
bool structNestingErrorCheck(const TSourceLoc& line, const TField& field);
TIntermSwitch *addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc);
TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &loc);
TIntermCase *addDefault(const TSourceLoc &loc);
TIntermTyped *addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &);
TIntermTyped *addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &);
TIntermTyped *addBinaryMath(TOperator op, TIntermTyped *left, TIntermTyped *right,
const TSourceLoc &);
TIntermTyped *addBinaryMathBooleanResult(TOperator op, TIntermTyped *left, TIntermTyped *right,
const TSourceLoc &);
TIntermTyped *addAssign(TOperator op, TIntermTyped *left, TIntermTyped *right,
const TSourceLoc &loc);
TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc);
TIntermBranch *addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc);
TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *node,
const TSourceLoc &loc, bool *fatalError);
private:
TIntermTyped *addBinaryMathInternal(TOperator op, TIntermTyped *left, TIntermTyped *right,
const TSourceLoc &loc);
TIntermTyped *createAssign(TOperator op, TIntermTyped *left, TIntermTyped *right,
const TSourceLoc &loc);
// The funcReturnType parameter is expected to be non-null when the operation is a built-in function.
// It is expected to be null for other unary operators.
TIntermTyped *createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc,
const TType *funcReturnType);
// Return true if the checks pass
bool binaryOpCommonCheck(TOperator op, TIntermTyped *left, TIntermTyped *right,
const TSourceLoc &loc);
};
int PaParseStrings(size_t count, const char* const string[], const int length[],
TParseContext* context);
#endif // _PARSER_HELPER_INCLUDED_
#endif // COMPILER_TRANSLATOR_PARSECONTEXT_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef _POOLALLOC_INCLUDED_
#define _POOLALLOC_INCLUDED_
#ifndef COMPILER_TRANSLATOR_POOLALLOC_H_
#define COMPILER_TRANSLATOR_POOLALLOC_H_
#ifdef _DEBUG
#define GUARD_BLOCKS // define to enable guard block sanity checking
@ -297,4 +297,4 @@ protected:
TPoolAllocator* allocator;
};
#endif // _POOLALLOC_INCLUDED_
#endif // COMPILER_TRANSLATOR_POOLALLOC_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILER_PRAGMA_H_
#define COMPILER_PRAGMA_H_
#ifndef COMPILER_TRANSLATOR_PRAGMA_H_
#define COMPILER_TRANSLATOR_PRAGMA_H_
struct TPragma
{
@ -18,12 +18,15 @@ struct TPragma
// By default optimization is turned on and debug is turned off.
TPragma() : optimize(true), debug(false) { }
TPragma(bool o, bool d) : optimize(o), debug(d) { }
// Precision emulation is turned on by default, but has no effect unless
// the extension is enabled.
TPragma() : optimize(true), debug(false), debugShaderPrecision(true) { }
TPragma(bool o, bool d) : optimize(o), debug(d), debugShaderPrecision(true) { }
bool optimize;
bool debug;
bool debugShaderPrecision;
STDGL stdgl;
};
#endif // COMPILER_PRAGMA_H_
#endif // COMPILER_TRANSLATOR_PRAGMA_H_

View File

@ -49,7 +49,7 @@ void TAliveTraverser::visitSymbol(TIntermSymbol* node)
found = true;
}
bool TAliveTraverser::visitSelection(Visit preVisit, TIntermSelection* node)
bool TAliveTraverser::visitSelection(Visit, TIntermSelection*)
{
if (wasFound())
return false;

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