Roll back to ANGLE/2845

This commit is contained in:
wolfbeast 2018-07-11 18:11:13 +02:00 committed by Roy Tam
commit 581db453db
582 changed files with 22757 additions and 56816 deletions

View file

@ -6,8 +6,7 @@
import("//build/config/dcheck_always_on.gni")
import("//build/config/linux/pkg_config.gni")
import("//build/config/ui.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
import("//third_party/angle/gni/angle.gni")
import("//third_party/angle/build/angle_common.gni")
import("//ui/ozone/ozone.gni")
if (ozone_platform_gbm) {
@ -55,7 +54,6 @@ config("extra_warnings") {
cflags = [
"/we4244", # Conversion: possible loss of data.
"/we4456", # Variable shadowing.
"/we4458", # declaration hides class member.
]
}
}
@ -73,6 +71,22 @@ if (is_win) {
angle_undefine_configs = [ "//build/config/compiler:default_include_dirs" ]
component("translator") {
sources = [
"src/compiler/translator/ShaderLang.cpp",
"src/compiler/translator/ShaderVars.cpp",
]
defines = [ "ANGLE_TRANSLATOR_IMPLEMENTATION" ]
configs -= angle_undefine_configs
configs += [ ":internal_config" ]
public_deps = [
":translator_lib",
]
}
# Holds the shared includes so we only need to list them once.
source_set("includes") {
sources = [
@ -96,14 +110,10 @@ static_library("preprocessor") {
configs -= angle_undefine_configs
configs += [ ":internal_config" ]
public_deps = [
":angle_common",
]
}
config("translator_disable_pool_alloc") {
defines = [ "ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC" ]
config("translator_static_config") {
defines = [ "ANGLE_TRANSLATOR_STATIC" ]
}
config("debug_annotations_config") {
@ -162,33 +172,33 @@ static_library("angle_image_util") {
]
}
static_library("translator") {
sources = rebase_path(compiler_gypi.angle_translator_sources, ".", "src")
static_library("translator_lib") {
sources = rebase_path(compiler_gypi.angle_translator_lib_sources, ".", "src")
defines = []
if (angle_enable_essl || use_libfuzzer) {
if (angle_enable_essl) {
sources +=
rebase_path(compiler_gypi.angle_translator_essl_sources, ".", "src")
rebase_path(compiler_gypi.angle_translator_lib_essl_sources, ".", "src")
defines += [ "ANGLE_ENABLE_ESSL" ]
}
if (angle_enable_glsl || use_libfuzzer) {
if (angle_enable_glsl) {
sources +=
rebase_path(compiler_gypi.angle_translator_glsl_sources, ".", "src")
rebase_path(compiler_gypi.angle_translator_lib_glsl_sources, ".", "src")
defines += [ "ANGLE_ENABLE_GLSL" ]
}
if (angle_enable_hlsl || use_libfuzzer) {
if (angle_enable_hlsl) {
sources +=
rebase_path(compiler_gypi.angle_translator_hlsl_sources, ".", "src")
rebase_path(compiler_gypi.angle_translator_lib_hlsl_sources, ".", "src")
defines += [ "ANGLE_ENABLE_HLSL" ]
}
configs -= angle_undefine_configs
configs += [ ":internal_config" ]
configs += [
":internal_config",
":translator_static_config",
]
public_configs = [ ":external_config" ]
if (use_libfuzzer) {
all_dependent_configs = [ ":translator_disable_pool_alloc" ]
}
deps = [
":includes",
@ -206,18 +216,22 @@ static_library("translator") {
}
}
source_set("translator_fuzzer") {
static_library("translator_static") {
sources = [
"src/compiler/fuzz/translator_fuzzer.cpp",
"src/compiler/translator/ShaderLang.cpp",
"src/compiler/translator/ShaderVars.cpp",
]
include_dirs = [
"include",
"src",
]
if (angle_enable_hlsl) {
defines = [ "ANGLE_ENABLE_HLSL" ]
}
deps = [
":translator",
configs -= angle_undefine_configs
configs += [ ":internal_config" ]
public_configs = [ ":translator_static_config" ]
public_deps = [
":translator_lib",
]
}
@ -271,13 +285,9 @@ config("libANGLE_config") {
if (angle_enable_vulkan) {
defines += [ "ANGLE_ENABLE_VULKAN" ]
}
if (angle_enable_null) {
defines += [ "ANGLE_ENABLE_NULL" ]
}
defines += [
"GL_GLEXT_PROTOTYPES",
"EGL_EGLEXT_PROTOTYPES",
"LIBANGLE_IMPLEMENTATION",
]
if (is_win) {
@ -301,7 +311,7 @@ static_library("libANGLE") {
include_dirs = []
libs = []
defines = []
defines = [ "LIBANGLE_IMPLEMENTATION" ]
public_deps = [
":angle_common",
]
@ -309,7 +319,7 @@ static_library("libANGLE") {
":angle_image_util",
":commit_id",
":includes",
":translator",
":translator_static",
]
# Shared D3D sources.
@ -379,10 +389,6 @@ static_library("libANGLE") {
sources += rebase_path(gles_gypi.libangle_vulkan_sources, ".", "src")
}
if (angle_enable_null) {
sources += rebase_path(gles_gypi.libangle_null_sources, ".", "src")
}
if (is_debug) {
defines += [ "ANGLE_GENERATE_SHADER_DEBUG_INFO" ]
}
@ -491,7 +497,7 @@ config("angle_util_config") {
}
}
shared_library("angle_util") {
static_library("angle_util") {
sources = rebase_path(util_gypi.util_sources, ".", "util")
if (is_win) {
@ -508,10 +514,6 @@ shared_library("angle_util") {
if (is_mac) {
sources += rebase_path(util_gypi.util_osx_sources, ".", "util")
libs = [
"AppKit.framework",
"QuartzCore.framework",
]
}
if (use_x11) {
@ -536,7 +538,6 @@ shared_library("angle_util") {
defines = [
"GL_GLEXT_PROTOTYPES",
"EGL_EGLEXT_PROTOTYPES",
"LIBANGLE_UTIL_IMPLEMENTATION",
]
configs += [
@ -548,13 +549,6 @@ shared_library("angle_util") {
":angle_util_config",
":internal_config",
]
if (is_mac && !is_component_build) {
ldflags = [
"-install_name",
"@rpath/lib${target_name}.dylib",
]
public_configs += [ ":shared_library_public_config" ]
}
deps = [
":angle_common",

View file

@ -64,18 +64,12 @@ Intel Corporation
Andy Chen
Josh Triplett
Sudarsana Nagineni
Jiajia Qin
Jiawei Shao
Jie Chen
Qiankun Miao
Bryan Bernhart
Klarälvdalens Datakonsult AB
Milian Wolff
Mozilla Corp.
Ehsan Akhgari
Edwin Flores
Jeff Gilbert
Mike Hommey
Benoit Jacob

View file

@ -3,30 +3,32 @@ vars = {
}
deps = {
'third_party/gyp':
Var('chromium_git') + '/external/gyp' + '@' + '81c2e5ff92af29bab61c982808076ddce3d200a2',
"third_party/gyp":
Var('chromium_git') + "/external/gyp@81c2e5ff92af29bab61c982808076ddce3d200a2",
'testing/gtest':
Var('chromium_git') + '/external/github.com/google/googletest.git' + '@' + '6f8a66431cb592dad629028a50b3dd418a408c87',
# TODO(kbr): figure out how to better stay in sync with Chromium's
# versions of googletest and googlemock.
"src/tests/third_party/googletest":
Var('chromium_git') + "/external/googletest.git@9855a87157778d39b95eccfb201a9dc90f6d61c6",
'testing/gmock':
Var('chromium_git') + '/external/googlemock.git' + '@' + '0421b6f358139f02e102c9c332ce19a33faf75be', # from svn revision 566
"src/tests/third_party/googlemock":
Var('chromium_git') + "/external/googlemock.git@b2cb211e49d872101d991201362d7b97d7d69910",
# Cherry is a dEQP management GUI written in Go. We use it for viewing test results.
'third_party/cherry':
'https://android.googlesource.com/platform/external/cherry' + '@' + 'd2e26b4d864ec2a6757e7f1174e464949ca5bf73',
"third_party/cherry":
"https://android.googlesource.com/platform/external/cherry@d2e26b4d864ec2a6757e7f1174e464949ca5bf73",
'third_party/deqp/src':
'https://android.googlesource.com/platform/external/deqp' + '@' + 'f4f3d8079e7a37d7675ab93583e6438d0bca0e58',
"third_party/deqp/src":
"https://android.googlesource.com/platform/external/deqp@f4f3d8079e7a37d7675ab93583e6438d0bca0e58",
'third_party/libpng':
'https://android.googlesource.com/platform/external/libpng' + '@' + '094e181e79a3d6c23fd005679025058b7df1ad6c',
"third_party/libpng":
"https://android.googlesource.com/platform/external/libpng@094e181e79a3d6c23fd005679025058b7df1ad6c",
'third_party/zlib':
Var('chromium_git') + '/chromium/src/third_party/zlib' + '@' + 'afd8c4593c010c045902f6c0501718f1823064a3',
"third_party/zlib":
Var('chromium_git') + "/chromium/src/third_party/zlib@afd8c4593c010c045902f6c0501718f1823064a3",
'buildtools':
Var('chromium_git') + '/chromium/buildtools.git' + '@' + '39b1db2ab4aa4b2ccaa263c29bdf63e7c1ee28aa',
"buildtools":
Var('chromium_git') + '/chromium/buildtools.git@06e80a0e17319868d4a9b13f9bb6a248dc8d8b20',
}
hooks = [
@ -100,12 +102,7 @@ hooks = [
},
{
# A change to a .gyp, .gypi, or to GYP itself should run the generator.
'pattern': '.',
'action': ['python', 'gyp/gyp_angle'],
"pattern": ".",
"action": ["python", "build/gyp_angle"],
},
]
recursedeps = [
# buildtools provides clang_format.
'buildtools',
]

View file

@ -472,11 +472,6 @@ EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID (EGLDisplay dpy, EGLSyncKHR
#define EGL_DXGI_KEYED_MUTEX_ANGLE 0x33A2
#endif /* EGL_ANGLE_keyed_mutex */
#ifndef EGL_ANGLE_d3d_texture_client_buffer
#define EGL_ANGLE_d3d_texture_client_buffer 1
#define EGL_D3D_TEXTURE_ANGLE 0x33A3
#endif /* EGL_ANGLE_d3d_texture_client_buffer */
#ifndef EGL_ANGLE_query_surface_pointer
#define EGL_ANGLE_query_surface_pointer 1
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
@ -531,11 +526,6 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu
#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320E
#endif /* EGL_ANGLE_platform_angle_opengl */
#ifndef EGL_ANGLE_platform_angle_null
#define EGL_ANGLE_platform_angle_null 1
#define EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE 0x33AE
#endif /* EGL_ANGLE_platform_angle_null */
#ifndef EGL_ANGLE_window_fixed_size
#define EGL_ANGLE_window_fixed_size 1
#define EGL_FIXED_SIZE_ANGLE 0x3201
@ -568,7 +558,7 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu
#ifndef EGL_ANGLE_stream_producer_d3d_texture_nv12
#define EGL_ANGLE_stream_producer_d3d_texture_nv12
#define EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE 0x33AB
#define EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE 0x3AAB
typedef EGLBoolean(EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERD3DTEXTURENV12ANGLEPROC)(EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
typedef EGLBoolean(EGLAPIENTRYP PFNEGLSTREAMPOSTD3DTEXTURENV12ANGLEPROC)(EGLDisplay dpy, EGLStreamKHR stream, void *texture, const EGLAttrib *attrib_list);
#ifdef EGL_EGLEXT_PROTOTYPES
@ -577,16 +567,6 @@ EGLAPI EGLBoolean EGLAPIENTRY eglStreamPostD3DTextureNV12ANGLE(EGLDisplay dpy, E
#endif
#endif /* EGL_ANGLE_stream_producer_d3d_texture_nv12 */
#ifndef EGL_ANGLE_create_context_webgl_compatibility
#define EGL_ANGLE_create_context_webgl_compatibility 1
#define EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE 0x3AAC
#endif /* EGL_ANGLE_create_context_webgl_compatibility */
#ifndef EGL_CHROMIUM_create_context_bind_generates_resource
#define EGL_CHROMIUM_create_context_bind_generates_resource 1
#define EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM 0x3AAD
#endif /* EGL_CHROMIUM_create_context_bind_generates_resource */
#ifndef EGL_ARM_pixmap_multisample_discard
#define EGL_ARM_pixmap_multisample_discard 1
#define EGL_DISCARD_SAMPLES_ARM 0x3286

View file

@ -821,14 +821,6 @@ GL_APICALL void GL_APIENTRY glBlitFramebufferANGLE (GLint srcX0, GLint srcY0, GL
#endif
#endif /* GL_ANGLE_framebuffer_blit */
#ifndef GL_ANGLE_webgl_compatibility
#define GL_ANGLE_webgl_compatibility 1
typedef GLboolean(GL_APIENTRYP PFNGLENABLEEXTENSIONANGLEPROC) (const GLchar *name);
#ifdef GL_GLEXT_PROTOTYPES
GL_APICALL GLboolean GL_APIENTRY glEnableExtensionANGLE (const GLchar *name);
#endif
#endif /* GL_ANGLE_webgl_compatibility */
#ifndef GL_CHROMIUM_framebuffer_mixed_samples
#define GL_CHROMIUM_frambuffer_mixed_samples 1
#define GL_COVERAGE_MODULATION_CHROMIUM 0x9332
@ -838,11 +830,6 @@ GL_APICALL void GL_APIENTRY glCoverageModulationCHROMIUM(GLenum components);
#endif
#endif /* GL_CHROMIUM_framebuffer_mixed_samples */
#ifndef GL_CHROMIUM_bind_generates_resource
#define GL_CHROMIUM_bind_generates_resource 1
#define GL_BIND_GENERATES_RESOURCE_CHROMIUM 0x9244
#endif /* GL_CHROMIUM_bind_generates_resource */
// needed by NV_path_rendering (and thus CHROMIUM_path_rendering)
// but CHROMIUM_path_rendering only needs MatrixLoadfEXT, MatrixLoadIdentityEXT
#ifndef GL_EXT_direct_state_access
@ -1316,14 +1303,6 @@ GL_APICALL void GL_APIENTRY glCopySubTextureCHROMIUM(GLuint sourceId,
#endif
#endif /* GL_CHROMIUM_copy_texture */
#ifndef GL_CHROMIUM_compressed_copy_texture
#define GL_CHROMIUM_compressed_copy_texture 1
typedef void(GL_APIENTRYP PFNGLCOMPRESSEDCOPYTEXTURECHROMIUMPROC)(GLuint sourceId, GLuint destId);
#ifdef GL_GLEXT_PROTOTYPES
GL_APICALL void GL_APIENTRY glCompressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId);
#endif
#endif /* GL_CHROMIUM_compressed_copy_texture */
#ifndef GL_CHROMIUM_sync_query
#define GL_CHROMIUM_sync_query 1
#define GL_COMMANDS_COMPLETED_CHROMIUM 0x84F7
@ -3255,132 +3234,6 @@ GL_APICALL void GL_APIENTRY glEndTilingQCOM (GLbitfield preserveMask);
#define GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE 0x969A
#endif /* GL_ANGLE_lossy_etc_decode */
#ifndef GL_ANGLE_robust_client_memory
#define GL_ANGLE_robust_client_memory 1
typedef void (GL_APIENTRYP PFNGLGETBOOLEANVROBUSTANGLE) (GLenum pname, GLsizei bufSize, GLsizei *length, GLboolean *data);
typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
typedef void (GL_APIENTRYP PFNGLGETFLOATVROBUSTANGLE) (GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *data);
typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVROBUSTANGLE) (GLenum target, GLenum attachment, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
typedef void (GL_APIENTRYP PFNGLGETINTEGERVROBUSTANGLE) (GLenum pname, GLsizei bufSize, GLsizei *length, GLint *data);
typedef void (GL_APIENTRYP PFNGLGETPROGRAMIVROBUSTANGLE) (GLuint program, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
typedef void (GL_APIENTRYP PFNGLGETSHADERIVROBUSTANGLE) (GLuint shader, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERFVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
typedef void (GL_APIENTRYP PFNGLGETUNIFORMFVROBUSTANGLE) (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLfloat *params);
typedef void (GL_APIENTRYP PFNGLGETUNIFORMIVROBUSTANGLE) (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLint *params);
typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBFVROBUSTANGLE) (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIVROBUSTANGLE) (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVROBUSTANGLE) (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, void **pointer);
typedef void (GL_APIENTRYP PFNGLREADPIXELSROBUSTANGLE) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLsizei *length, void *pixels);
typedef void (GL_APIENTRYP PFNGLTEXIMAGE2DROBUSTANGLE) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, const GLfloat *params);
typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, const GLint *params);
typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE2DROBUSTANGLE) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DROBUSTANGLE) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DROBUSTANGLE) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
typedef void (GL_APIENTRYP PFNGLGETQUERYIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVROBUSTANGLE) (GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, void **params);
typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VROBUSTANGLE) (GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, GLint *data);
typedef void (GL_APIENTRYP PFNGETINTERNALFORMATIVROBUSTANGLE) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIIVROBUSTANGLE) (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIUIVROBUSTANGLE) (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
typedef void (GL_APIENTRYP PFNGLGETUNIFORMUIVROBUSTANGLE) (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLuint *params);
typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVROBUSTANGLE) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
typedef void (GL_APIENTRYP PFNGLGETINTEGER64VROBUSTANGLE) (GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *data);
typedef void (GL_APIENTRYP PFNGLGETINTEGER64I_VROBUSTANGLE) (GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, GLint64 *data);
typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERI64VROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *params);
typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, const GLint *param);
typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, const GLfloat *param);
typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERFVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
typedef void (GL_APIENTRYP PFNGLGETPROGRAMINTERFACEIVROBUSTANGLE) (GLuint program, GLenum programInterface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
typedef void (GL_APIENTRYP PFNGLGETBOOLEANI_VROBUSTANGLE) (GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, GLboolean *data);
typedef void (GL_APIENTRYP PFNGLGETMULTISAMPLEFVROBUSTANGLE) (GLenum pname, GLuint index, GLsizei bufSize, GLsizei *length, GLfloat *val);
typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERIVROBUSTANGLE) (GLenum target, GLint level, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERFVROBUSTANGLE) (GLenum target, GLint level, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
typedef void (GL_APIENTRYP PFNGLGETPOINTERVROBUSTANGLEROBUSTANGLE) (GLenum pname, GLsizei bufSize, GLsizei *length, void **params);
typedef void (GL_APIENTRYP PFNGLREADNPIXELSROBUSTANGLE) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLsizei *length, void *data);
typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVROBUSTANGLE) (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLfloat *params);
typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVROBUSTANGLE) (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLint *params);
typedef void (GL_APIENTRYP PFNGLGETNUNIFORMUIVROBUSTANGLE) (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLuint *params);
typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, const GLint *params);
typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIUIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, const GLuint *params);
typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIUIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIIVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, const GLint *param);
typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIUIVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, const GLuint *param);
typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIIVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTIVROBUSTANGLE)(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTI64VROBUSTANGLE)(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *params);
typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUI64VROBUSTANGLE)(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint64 *params);
#ifdef GL_GLEXT_PROTOTYPES
GL_APICALL void GL_APIENTRY glGetBooleanvRobustANGLE (GLenum pname, GLsizei bufSize, GLsizei *length, GLboolean *data);
GL_APICALL void GL_APIENTRY glGetBufferParameterivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
GL_APICALL void GL_APIENTRY glGetFloatvRobustANGLE (GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *data);
GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameterivRobustANGLE (GLenum target, GLenum attachment, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
GL_APICALL void GL_APIENTRY glGetIntegervRobustANGLE (GLenum pname, GLsizei bufSize, GLsizei *length, GLint *data);
GL_APICALL void GL_APIENTRY glGetProgramivRobustANGLE (GLuint program, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
GL_APICALL void GL_APIENTRY glGetRenderbufferParameterivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
GL_APICALL void GL_APIENTRY glGetShaderivRobustANGLE (GLuint shader, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
GL_APICALL void GL_APIENTRY glGetTexParameterfvRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
GL_APICALL void GL_APIENTRY glGetTexParameterivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
GL_APICALL void GL_APIENTRY glGetUniformfvRobustANGLE (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLfloat *params);
GL_APICALL void GL_APIENTRY glGetUniformivRobustANGLE (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLint *params);
GL_APICALL void GL_APIENTRY glGetVertexAttribfvRobustANGLE (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
GL_APICALL void GL_APIENTRY glGetVertexAttribivRobustANGLE (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
GL_APICALL void GL_APIENTRY glGetVertexAttribPointervRobustANGLE (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, void **pointer);
GL_APICALL void GL_APIENTRY glReadPixelsRobustANGLE (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLsizei *length, void *pixels);
GL_APICALL void GL_APIENTRY glTexImage2DRobustANGLE (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
GL_APICALL void GL_APIENTRY glTexParameterfvRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, const GLfloat *params);
GL_APICALL void GL_APIENTRY glTexParameterivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, const GLint *params);
GL_APICALL void GL_APIENTRY glTexSubImage2DRobustANGLE (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
GL_APICALL void GL_APIENTRY glTexImage3DRobustANGLE (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
GL_APICALL void GL_APIENTRY glTexSubImage3DRobustANGLE (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
GL_APICALL void GL_APIENTRY glGetQueryivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
GL_APICALL void GL_APIENTRY glGetQueryObjectuivRobustANGLE (GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
GL_APICALL void GL_APIENTRY glGetBufferPointervRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, void **params);
GL_APICALL void GL_APIENTRY glGetIntegeri_vRobustANGLE (GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, GLint *data);
GL_APICALL void GL_APIENTRY glGetInternalformativRobustANGLE (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
GL_APICALL void GL_APIENTRY glGetVertexAttribIivRobustANGLE (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
GL_APICALL void GL_APIENTRY glGetVertexAttribIuivRobustANGLE (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
GL_APICALL void GL_APIENTRY glGetUniformuivRobustANGLE (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLuint *params);
GL_APICALL void GL_APIENTRY glGetActiveUniformBlockivRobustANGLE (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
GL_APICALL void GL_APIENTRY glGetInteger64vRobustANGLE (GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *data);
GL_APICALL void GL_APIENTRY glGetInteger64i_vRobustANGLE (GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, GLint64 *data);
GL_APICALL void GL_APIENTRY glGetBufferParameteri64vRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *params);
GL_APICALL void GL_APIENTRY glSamplerParameterivRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, const GLint *param);
GL_APICALL void GL_APIENTRY glSamplerParameterfvRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, const GLfloat *param);
GL_APICALL void GL_APIENTRY glGetSamplerParameterivRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
GL_APICALL void GL_APIENTRY glGetSamplerParameterfvRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
GL_APICALL void GL_APIENTRY glGetFramebufferParameterivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
GL_APICALL void GL_APIENTRY glGetProgramInterfaceivRobustANGLE (GLuint program, GLenum programInterface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
GL_APICALL void GL_APIENTRY glGetBooleani_vRobustANGLE (GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, GLboolean *data);
GL_APICALL void GL_APIENTRY glGetMultisamplefvRobustANGLE (GLenum pname, GLuint index, GLsizei bufSize, GLsizei *length, GLfloat *val);
GL_APICALL void GL_APIENTRY glGetTexLevelParameterivRobustANGLE (GLenum target, GLint level, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
GL_APICALL void GL_APIENTRY glGetTexLevelParameterfvRobustANGLE (GLenum target, GLint level, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
GL_APICALL void GL_APIENTRY glGetPointervRobustANGLERobustANGLE (GLenum pname, GLsizei bufSize, GLsizei *length, void **params);
GL_APICALL void GL_APIENTRY glReadnPixelsRobustANGLE (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLsizei *length, void *data);
GL_APICALL void GL_APIENTRY glGetnUniformfvRobustANGLE (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLfloat *params);
GL_APICALL void GL_APIENTRY glGetnUniformivRobustANGLE (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLint *params);
GL_APICALL void GL_APIENTRY glGetnUniformuivRobustANGLE (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLuint *params);
GL_APICALL void GL_APIENTRY glTexParameterIivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, const GLint *params);
GL_APICALL void GL_APIENTRY glTexParameterIuivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, const GLuint *params);
GL_APICALL void GL_APIENTRY glGetTexParameterIivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
GL_APICALL void GL_APIENTRY glGetTexParameterIuivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
GL_APICALL void GL_APIENTRY glSamplerParameterIivRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, const GLint *param);
GL_APICALL void GL_APIENTRY glSamplerParameterIuivRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, const GLuint *param);
GL_APICALL void GL_APIENTRY glGetSamplerParameterIivRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
GL_APICALL void GL_APIENTRY glGetSamplerParameterIuivRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
GL_APICALL void GL_APIENTRY glGetQueryObjectivRobustANGLE(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
GL_APICALL void GL_APIENTRY glGetQueryObjecti64vRobustANGLE(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *params);
GL_APICALL void GL_APIENTRY glGetQueryObjectui64vRobustANGLE(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint64 *params);
#endif
#endif /* GL_ANGLE_robust_client_memory */
#ifdef __cplusplus
}
#endif

View file

@ -6,6 +6,23 @@
#ifndef GLSLANG_SHADERLANG_H_
#define GLSLANG_SHADERLANG_H_
#if defined(COMPONENT_BUILD) && !defined(ANGLE_TRANSLATOR_STATIC)
#if defined(_WIN32) || defined(_WIN64)
#if defined(ANGLE_TRANSLATOR_IMPLEMENTATION)
#define COMPILER_EXPORT __declspec(dllexport)
#else
#define COMPILER_EXPORT __declspec(dllimport)
#endif // defined(ANGLE_TRANSLATOR_IMPLEMENTATION)
#else // defined(_WIN32) || defined(_WIN64)
#define COMPILER_EXPORT __attribute__((visibility("default")))
#endif
#else // defined(COMPONENT_BUILD) && !defined(ANGLE_TRANSLATOR_STATIC)
#define COMPILER_EXPORT
#endif
#include <stddef.h>
#include "KHR/khrplatform.h"
@ -32,10 +49,9 @@ typedef unsigned int GLenum;
// Version number for shader translation API.
// It is incremented every time the API changes.
#define ANGLE_SH_VERSION 167
#define ANGLE_SH_VERSION 155
enum ShShaderSpec
{
typedef enum {
SH_GLES2_SPEC,
SH_WEBGL_SPEC,
@ -44,9 +60,31 @@ enum ShShaderSpec
SH_GLES3_1_SPEC,
SH_WEBGL3_SPEC,
};
enum ShShaderOutput
// The CSS Shaders spec is a subset of the WebGL spec.
//
// In both CSS vertex and fragment shaders, ANGLE:
// (1) Reserves the "css_" prefix.
// (2) Renames the main function to css_main.
// (3) Disables the gl_MaxDrawBuffers built-in.
//
// In CSS fragment shaders, ANGLE:
// (1) Disables the gl_FragColor built-in.
// (2) Disables the gl_FragData built-in.
// (3) Enables the css_MixColor built-in.
// (4) Enables the css_ColorMatrix built-in.
//
// After passing a CSS shader through ANGLE, the browser is expected to append
// a new main function to it.
// This new main function will call the css_main function.
// It may also perform additional operations like varying assignment, texture
// access, and gl_FragColor assignment in order to implement the CSS Shaders
// blend modes.
//
SH_CSS_SHADERS_SPEC
} ShShaderSpec;
typedef enum
{
// ESSL output only supported in some configurations.
SH_ESSL_OUTPUT = 0x8B45,
@ -65,171 +103,166 @@ enum ShShaderOutput
SH_GLSL_440_CORE_OUTPUT = 0x8B87,
SH_GLSL_450_CORE_OUTPUT = 0x8B88,
// HLSL output only supported in some configurations.
// Deprecated:
SH_HLSL_OUTPUT = 0x8B48,
SH_HLSL9_OUTPUT = 0x8B48,
SH_HLSL11_OUTPUT = 0x8B49,
// Prefer using these to specify HLSL output type:
SH_HLSL_3_0_OUTPUT = 0x8B48, // D3D 9
SH_HLSL_4_1_OUTPUT = 0x8B49, // D3D 11
SH_HLSL_4_0_FL9_3_OUTPUT = 0x8B4A // D3D 11 feature level 9_3
};
} ShShaderOutput;
// Compile options.
typedef enum {
SH_VALIDATE = 0,
SH_VALIDATE_LOOP_INDEXING = 0x0001,
SH_INTERMEDIATE_TREE = 0x0002,
SH_OBJECT_CODE = 0x0004,
SH_VARIABLES = 0x0008,
SH_LINE_DIRECTIVES = 0x0010,
SH_SOURCE_PATH = 0x0020,
SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX = 0x0040,
// If a sampler array index happens to be a loop index,
// 1) if its type is integer, unroll the loop.
// 2) if its type is float, fail the shader compile.
// This is to work around a mac driver bug.
SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX = 0x0080,
using ShCompileOptions = uint64_t;
// This is needed only as a workaround for certain OpenGL driver bugs.
SH_EMULATE_BUILT_IN_FUNCTIONS = 0x0100,
const ShCompileOptions SH_VALIDATE = 0;
const ShCompileOptions SH_VALIDATE_LOOP_INDEXING = UINT64_C(1) << 0;
const ShCompileOptions SH_INTERMEDIATE_TREE = UINT64_C(1) << 1;
const ShCompileOptions SH_OBJECT_CODE = UINT64_C(1) << 2;
const ShCompileOptions SH_VARIABLES = UINT64_C(1) << 3;
const ShCompileOptions SH_LINE_DIRECTIVES = UINT64_C(1) << 4;
const ShCompileOptions SH_SOURCE_PATH = UINT64_C(1) << 5;
const ShCompileOptions SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX = UINT64_C(1) << 6;
// If a sampler array index happens to be a loop index,
// 1) if its type is integer, unroll the loop.
// 2) if its type is float, fail the shader compile.
// This is to work around a mac driver bug.
const ShCompileOptions SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX = UINT64_C(1) << 7;
// This is an experimental flag to enforce restrictions that aim to prevent
// timing attacks.
// It generates compilation errors for shaders that could expose sensitive
// texture information via the timing channel.
// To use this flag, you must compile the shader under the WebGL spec
// (using the SH_WEBGL_SPEC flag).
SH_TIMING_RESTRICTIONS = 0x0200,
// This flag works around bug in Intel Mac drivers related to abs(i) where
// i is an integer.
const ShCompileOptions SH_EMULATE_ABS_INT_FUNCTION = UINT64_C(1) << 8;
// This flag prints the dependency graph that is used to enforce timing
// restrictions on fragment shaders.
// This flag only has an effect if all of the following are true:
// - The shader spec is SH_WEBGL_SPEC.
// - The compile options contain the SH_TIMING_RESTRICTIONS flag.
// - The shader type is GL_FRAGMENT_SHADER.
SH_DEPENDENCY_GRAPH = 0x0400,
// Enforce the GLSL 1.017 Appendix A section 7 packing restrictions.
// This flag only enforces (and can only enforce) the packing
// restrictions for uniform variables in both vertex and fragment
// shaders. ShCheckVariablesWithinPackingLimits() lets embedders
// enforce the packing restrictions for varying variables during
// program link time.
const ShCompileOptions SH_ENFORCE_PACKING_RESTRICTIONS = UINT64_C(1) << 9;
// Enforce the GLSL 1.017 Appendix A section 7 packing restrictions.
// This flag only enforces (and can only enforce) the packing
// restrictions for uniform variables in both vertex and fragment
// shaders. ShCheckVariablesWithinPackingLimits() lets embedders
// enforce the packing restrictions for varying variables during
// program link time.
SH_ENFORCE_PACKING_RESTRICTIONS = 0x0800,
// This flag ensures all indirect (expression-based) array indexing
// is clamped to the bounds of the array. This ensures, for example,
// that you cannot read off the end of a uniform, whether an array
// vec234, or mat234 type. The ShArrayIndexClampingStrategy enum,
// specified in the ShBuiltInResources when constructing the
// compiler, selects the strategy for the clamping implementation.
const ShCompileOptions SH_CLAMP_INDIRECT_ARRAY_BOUNDS = UINT64_C(1) << 10;
// This flag ensures all indirect (expression-based) array indexing
// is clamped to the bounds of the array. This ensures, for example,
// that you cannot read off the end of a uniform, whether an array
// vec234, or mat234 type. The ShArrayIndexClampingStrategy enum,
// specified in the ShBuiltInResources when constructing the
// compiler, selects the strategy for the clamping implementation.
SH_CLAMP_INDIRECT_ARRAY_BOUNDS = 0x1000,
// This flag limits the complexity of an expression.
const ShCompileOptions SH_LIMIT_EXPRESSION_COMPLEXITY = UINT64_C(1) << 11;
// This flag limits the complexity of an expression.
SH_LIMIT_EXPRESSION_COMPLEXITY = 0x2000,
// This flag limits the depth of the call stack.
const ShCompileOptions SH_LIMIT_CALL_STACK_DEPTH = UINT64_C(1) << 12;
// This flag limits the depth of the call stack.
SH_LIMIT_CALL_STACK_DEPTH = 0x4000,
// This flag initializes gl_Position to vec4(0,0,0,0) at the
// beginning of the vertex shader's main(), and has no effect in the
// fragment shader. It is intended as a workaround for drivers which
// incorrectly fail to link programs if gl_Position is not written.
const ShCompileOptions SH_INIT_GL_POSITION = UINT64_C(1) << 13;
// This flag initializes gl_Position to vec4(0,0,0,0) at the
// beginning of the vertex shader's main(), and has no effect in the
// fragment shader. It is intended as a workaround for drivers which
// incorrectly fail to link programs if gl_Position is not written.
SH_INIT_GL_POSITION = 0x8000,
// This flag replaces
// "a && b" with "a ? b : false",
// "a || b" with "a ? true : b".
// This is to work around a MacOSX driver bug that |b| is executed
// independent of |a|'s value.
const ShCompileOptions SH_UNFOLD_SHORT_CIRCUIT = UINT64_C(1) << 14;
// This flag replaces
// "a && b" with "a ? b : false",
// "a || b" with "a ? true : b".
// This is to work around a MacOSX driver bug that |b| is executed
// independent of |a|'s value.
SH_UNFOLD_SHORT_CIRCUIT = 0x10000,
// This flag initializes output variables to 0 at the beginning of main().
// It is to avoid undefined behaviors.
const ShCompileOptions SH_INIT_OUTPUT_VARIABLES = UINT64_C(1) << 15;
// This flag initializes output variables to 0 at the beginning of main().
// It is to avoid undefined behaviors.
SH_INIT_OUTPUT_VARIABLES = 0x20000,
// TODO(zmo): obsolete, remove after ANGLE roll into Chromium.
SH_INIT_VARYINGS_WITHOUT_STATIC_USE = 0x20000,
// This flag scalarizes vec/ivec/bvec/mat constructor args.
// It is intended as a workaround for Linux/Mac driver bugs.
const ShCompileOptions SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS = UINT64_C(1) << 16;
// This flag scalarizes vec/ivec/bvec/mat constructor args.
// It is intended as a workaround for Linux/Mac driver bugs.
SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS = 0x40000,
// This flag overwrites a struct name with a unique prefix.
// It is intended as a workaround for drivers that do not handle
// struct scopes correctly, including all Mac drivers and Linux AMD.
const ShCompileOptions SH_REGENERATE_STRUCT_NAMES = UINT64_C(1) << 17;
// This flag overwrites a struct name with a unique prefix.
// It is intended as a workaround for drivers that do not handle
// struct scopes correctly, including all Mac drivers and Linux AMD.
SH_REGENERATE_STRUCT_NAMES = 0x80000,
// This flag makes the compiler not prune unused function early in the
// compilation process. Pruning coupled with SH_LIMIT_CALL_STACK_DEPTH
// helps avoid bad shaders causing stack overflows.
const ShCompileOptions SH_DONT_PRUNE_UNUSED_FUNCTIONS = UINT64_C(1) << 18;
// This flag makes the compiler not prune unused function early in the
// compilation process. Pruning coupled with SH_LIMIT_CALL_STACK_DEPTH
// helps avoid bad shaders causing stack overflows.
SH_DONT_PRUNE_UNUSED_FUNCTIONS = 0x100000,
// This flag works around a bug in NVIDIA 331 series drivers related
// to pow(x, y) where y is a constant vector.
const ShCompileOptions SH_REMOVE_POW_WITH_CONSTANT_EXPONENT = UINT64_C(1) << 19;
// This flag works around a bug in NVIDIA 331 series drivers related
// to pow(x, y) where y is a constant vector.
SH_REMOVE_POW_WITH_CONSTANT_EXPONENT = 0x200000,
// This flag works around bugs in Mac drivers related to do-while by
// transforming them into an other construct.
const ShCompileOptions SH_REWRITE_DO_WHILE_LOOPS = UINT64_C(1) << 20;
// This flag works around bugs in Mac drivers related to do-while by
// transforming them into an other construct.
SH_REWRITE_DO_WHILE_LOOPS = 0x400000,
// This flag works around a bug in the HLSL compiler optimizer that folds certain
// constant pow expressions incorrectly. Only applies to the HLSL back-end. It works
// by expanding the integer pow expressions into a series of multiplies.
const ShCompileOptions SH_EXPAND_SELECT_HLSL_INTEGER_POW_EXPRESSIONS = UINT64_C(1) << 21;
// This flag works around a bug in the HLSL compiler optimizer that folds certain
// constant pow expressions incorrectly. Only applies to the HLSL back-end. It works
// by expanding the integer pow expressions into a series of multiplies.
SH_EXPAND_SELECT_HLSL_INTEGER_POW_EXPRESSIONS = 0x800000,
// Flatten "#pragma STDGL invariant(all)" into the declarations of
// varying variables and built-in GLSL variables. This compiler
// option is enabled automatically when needed.
const ShCompileOptions SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL = UINT64_C(1) << 22;
// Flatten "#pragma STDGL invariant(all)" into the declarations of
// varying variables and built-in GLSL variables. This compiler
// option is enabled automatically when needed.
SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL = 0x1000000,
// Some drivers do not take into account the base level of the texture in the results of the
// HLSL GetDimensions builtin. This flag instructs the compiler to manually add the base level
// offsetting.
const ShCompileOptions SH_HLSL_GET_DIMENSIONS_IGNORES_BASE_LEVEL = UINT64_C(1) << 23;
// Some drivers do not take into account the base level of the texture in the results of the
// HLSL GetDimensions builtin. This flag instructs the compiler to manually add the base level
// offsetting.
SH_HLSL_GET_DIMENSIONS_IGNORES_BASE_LEVEL = 0x2000000,
// This flag works around an issue in translating GLSL function texelFetchOffset on
// INTEL drivers. It works by translating texelFetchOffset into texelFetch.
const ShCompileOptions SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH = UINT64_C(1) << 24;
// This flag works around condition bug of for and while loops in Intel Mac OSX drivers.
// Condition calculation is not correct. Rewrite it from "CONDITION" to "CONDITION && true".
const ShCompileOptions SH_ADD_AND_TRUE_TO_LOOP_CONDITION = UINT64_C(1) << 25;
// This flag works around a bug in evaluating unary minus operator on integer on some INTEL
// drivers. It works by translating -(int) into ~(int) + 1.
const ShCompileOptions SH_REWRITE_INTEGER_UNARY_MINUS_OPERATOR = UINT64_C(1) << 26;
// This flag works around a bug in evaluating isnan() on some INTEL D3D and Mac OSX drivers.
// It works by using an expression to emulate this function.
const ShCompileOptions SH_EMULATE_ISNAN_FLOAT_FUNCTION = UINT64_C(1) << 27;
// This flag will use all uniforms of unused std140 and shared uniform blocks at the
// beginning of the vertex/fragment shader's main(). It is intended as a workaround for Mac
// drivers with shader version 4.10. In those drivers, they will treat unused
// std140 and shared uniform blocks' members as inactive. However, WebGL2.0 based on
// OpenGL ES3.0.4 requires all members of a named uniform block declared with a shared or std140
// layout qualifier to be considered active. The uniform block itself is also considered active.
const ShCompileOptions SH_USE_UNUSED_STANDARD_SHARED_BLOCKS = UINT64_C(1) << 28;
// This flag will keep invariant declaration for input in fragment shader for GLSL >=4.20 on AMD.
// From GLSL >= 4.20, it's optional to add invariant for fragment input, but GPU vendors have
// different implementations about this. Some drivers forbid invariant in fragment for GLSL>= 4.20,
// e.g. Linux Mesa, some drivers treat that as optional, e.g. NVIDIA, some drivers require invariant
// must match between vertex and fragment shader, e.g. AMD. The behavior on AMD is obviously wrong.
// Remove invariant for input in fragment shader to workaround the restriction on Intel Mesa.
// But don't remove on AMD Linux to avoid triggering the bug on AMD.
const ShCompileOptions SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT = UINT64_C(1) << 29;
// Due to spec difference between GLSL 4.1 or lower and ESSL3, some platforms (for example, Mac OSX
// core profile) require a variable's "invariant"/"centroid" qualifiers to match between vertex and
// fragment shader. A simple solution to allow such shaders to link is to omit the two qualifiers.
// Note that the two flags only take effect on ESSL3 input shaders translated to GLSL 4.1 or lower.
// TODO(zmo): This is not a good long-term solution. Simply dropping these qualifiers may break some
// developers' content. A more complex workaround of dynamically generating, compiling, and
// re-linking shaders that use these qualifiers should be implemented.
const ShCompileOptions SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3 = UINT64_C(1) << 30;
// This flag works around an issue in translating GLSL function texelFetchOffset on
// INTEL drivers. It works by translating texelFetchOffset into texelFetch.
SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH = 0x4000000,
} ShCompileOptions;
// Defines alternate strategies for implementing array index clamping.
enum ShArrayIndexClampingStrategy
{
// Use the clamp intrinsic for array index clamping.
SH_CLAMP_WITH_CLAMP_INTRINSIC = 1,
typedef enum {
// Use the clamp intrinsic for array index clamping.
SH_CLAMP_WITH_CLAMP_INTRINSIC = 1,
// Use a user-defined function for array index clamping.
SH_CLAMP_WITH_USER_DEFINED_INT_CLAMP_FUNCTION
};
// Use a user-defined function for array index clamping.
SH_CLAMP_WITH_USER_DEFINED_INT_CLAMP_FUNCTION
} ShArrayIndexClampingStrategy;
//
// Driver must call this first, once, before doing any other
// compiler operations.
// If the function succeeds, the return value is true, else false.
//
COMPILER_EXPORT bool ShInitialize();
//
// Driver should call this at shutdown.
// If the function succeeds, the return value is true, else false.
//
COMPILER_EXPORT bool ShFinalize();
// The 64 bits hash function. The first parameter is the input string; the
// second parameter is the string length.
using ShHashFunction64 = khronos_uint64_t (*)(const char *, size_t);
typedef khronos_uint64_t (*ShHashFunction64)(const char*, size_t);
//
// Implementation dependent built-in resources (constants and extensions).
// The names for these resources has been obtained by stripping gl_/GL_.
//
struct ShBuiltInResources
typedef struct
{
// Constants.
int MaxVertexAttribs;
@ -361,7 +394,15 @@ struct ShBuiltInResources
// maximum number of buffer object storage in machine units
int MaxAtomicCounterBufferSize;
};
} ShBuiltInResources;
//
// Initialize built-in resources with minimum expected values.
// Parameters:
// resources: The object to initialize. Will be comparable with memcmp.
//
COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources *resources);
//
// ShHandle held by but opaque to the driver. It is allocated,
@ -370,26 +411,7 @@ struct ShBuiltInResources
//
// If handle creation fails, 0 will be returned.
//
using ShHandle = void *;
//
// Driver must call this first, once, before doing any other
// compiler operations.
// If the function succeeds, the return value is true, else false.
//
bool ShInitialize();
//
// Driver should call this at shutdown.
// If the function succeeds, the return value is true, else false.
//
bool ShFinalize();
//
// Initialize built-in resources with minimum expected values.
// Parameters:
// resources: The object to initialize. Will be comparable with memcmp.
//
void ShInitBuiltInResources(ShBuiltInResources *resources);
typedef void *ShHandle;
//
// Returns the a concatenated list of the items in ShBuiltInResources as a
@ -397,7 +419,7 @@ void ShInitBuiltInResources(ShBuiltInResources *resources);
// This function must be updated whenever ShBuiltInResources is changed.
// Parameters:
// handle: Specifies the handle of the compiler to be used.
const std::string &ShGetBuiltInResourcesString(const ShHandle handle);
COMPILER_EXPORT const std::string &ShGetBuiltInResourcesString(const ShHandle handle);
//
// Driver calls these to create and destroy compiler objects.
@ -412,11 +434,12 @@ const std::string &ShGetBuiltInResourcesString(const ShHandle handle);
// SH_HLSL_3_0_OUTPUT or SH_HLSL_4_1_OUTPUT. Note: Each output type may only
// be supported in some configurations.
// resources: Specifies the built-in resources.
ShHandle ShConstructCompiler(sh::GLenum type,
ShShaderSpec spec,
ShShaderOutput output,
const ShBuiltInResources *resources);
void ShDestruct(ShHandle handle);
COMPILER_EXPORT ShHandle ShConstructCompiler(
sh::GLenum type,
ShShaderSpec spec,
ShShaderOutput output,
const ShBuiltInResources *resources);
COMPILER_EXPORT void ShDestruct(ShHandle handle);
//
// Compiles the given shader source.
@ -436,42 +459,45 @@ void ShDestruct(ShHandle handle);
// There is no need to specify this parameter when
// compiling for WebGL - it is implied.
// SH_INTERMEDIATE_TREE: Writes intermediate tree to info log.
// Can be queried by calling sh::GetInfoLog().
// Can be queried by calling ShGetInfoLog().
// SH_OBJECT_CODE: Translates intermediate tree to glsl or hlsl shader.
// Can be queried by calling sh::GetObjectCode().
// Can be queried by calling ShGetObjectCode().
// SH_VARIABLES: Extracts attributes, uniforms, and varyings.
// Can be queried by calling ShGetVariableInfo().
//
bool ShCompile(const ShHandle handle,
const char *const shaderStrings[],
size_t numStrings,
ShCompileOptions compileOptions);
COMPILER_EXPORT bool ShCompile(
const ShHandle handle,
const char * const shaderStrings[],
size_t numStrings,
int compileOptions);
// Clears the results from the previous compilation.
void ShClearResults(const ShHandle handle);
COMPILER_EXPORT void ShClearResults(const ShHandle handle);
// Return the version of the shader language.
int ShGetShaderVersion(const ShHandle handle);
COMPILER_EXPORT int ShGetShaderVersion(const ShHandle handle);
// Return the currently set language output type.
ShShaderOutput ShGetShaderOutputType(const ShHandle handle);
COMPILER_EXPORT ShShaderOutput ShGetShaderOutputType(
const ShHandle handle);
// Returns null-terminated information log for a compiled shader.
// Parameters:
// handle: Specifies the compiler
const std::string &ShGetInfoLog(const ShHandle handle);
COMPILER_EXPORT const std::string &ShGetInfoLog(const ShHandle handle);
// Returns null-terminated object code for a compiled shader.
// Parameters:
// handle: Specifies the compiler
const std::string &ShGetObjectCode(const ShHandle handle);
COMPILER_EXPORT const std::string &ShGetObjectCode(const ShHandle handle);
// Returns a (original_name, hash) map containing all the user defined
// names in the shader, including variable names, function names, struct
// names, and struct field names.
// Parameters:
// handle: Specifies the compiler
const std::map<std::string, std::string> *ShGetNameHashingMap(const ShHandle handle);
COMPILER_EXPORT const std::map<std::string, std::string> *ShGetNameHashingMap(
const ShHandle handle);
// Shader variable inspection.
// Returns a pointer to a list of variables of the designated type.
@ -479,12 +505,18 @@ const std::map<std::string, std::string> *ShGetNameHashingMap(const ShHandle han
// Returns NULL on failure.
// Parameters:
// handle: Specifies the compiler
const std::vector<sh::Uniform> *ShGetUniforms(const ShHandle handle);
const std::vector<sh::Varying> *ShGetVaryings(const ShHandle handle);
const std::vector<sh::Attribute> *ShGetAttributes(const ShHandle handle);
const std::vector<sh::OutputVariable> *ShGetOutputVariables(const ShHandle handle);
const std::vector<sh::InterfaceBlock> *ShGetInterfaceBlocks(const ShHandle handle);
sh::WorkGroupSize ShGetComputeShaderLocalGroupSize(const ShHandle handle);
COMPILER_EXPORT const std::vector<sh::Uniform> *ShGetUniforms(const ShHandle handle);
COMPILER_EXPORT const std::vector<sh::Varying> *ShGetVaryings(const ShHandle handle);
COMPILER_EXPORT const std::vector<sh::Attribute> *ShGetAttributes(const ShHandle handle);
COMPILER_EXPORT const std::vector<sh::OutputVariable> *ShGetOutputVariables(const ShHandle handle);
COMPILER_EXPORT const std::vector<sh::InterfaceBlock> *ShGetInterfaceBlocks(const ShHandle handle);
COMPILER_EXPORT sh::WorkGroupSize ShGetComputeShaderLocalGroupSize(const ShHandle handle);
typedef struct
{
sh::GLenum type;
int size;
} ShVariableInfo;
// Returns true if the passed in variables pack in maxVectors following
// the packing rules from the GLSL 1.017 spec, Appendix A, section 7.
@ -493,8 +525,9 @@ sh::WorkGroupSize ShGetComputeShaderLocalGroupSize(const ShHandle handle);
// Parameters:
// maxVectors: the available rows of registers.
// variables: an array of variables.
bool ShCheckVariablesWithinPackingLimits(int maxVectors,
const std::vector<sh::ShaderVariable> &variables);
COMPILER_EXPORT bool ShCheckVariablesWithinPackingLimits(
int maxVectors,
const std::vector<sh::ShaderVariable> &variables);
// Gives the compiler-assigned register for an interface block.
// The method writes the value to the output variable "indexOut".
@ -503,155 +536,14 @@ bool ShCheckVariablesWithinPackingLimits(int maxVectors,
// handle: Specifies the compiler
// interfaceBlockName: Specifies the interface block
// indexOut: output variable that stores the assigned register
bool ShGetInterfaceBlockRegister(const ShHandle handle,
const std::string &interfaceBlockName,
unsigned int *indexOut);
COMPILER_EXPORT bool ShGetInterfaceBlockRegister(const ShHandle handle,
const std::string &interfaceBlockName,
unsigned int *indexOut);
// Gives a map from uniform names to compiler-assigned registers in the default
// interface block. Note that the map contains also registers of samplers that
// have been extracted from structs.
const std::map<std::string, unsigned int> *ShGetUniformRegisterMap(const ShHandle handle);
// Temporary duplicate of the scoped APIs, to be removed when we roll ANGLE and fix Chromium.
// TODO(jmadill): Consolidate with these APIs once we roll ANGLE.
namespace sh
{
//
// Driver must call this first, once, before doing any other compiler operations.
// If the function succeeds, the return value is true, else false.
//
bool Initialize();
//
// Driver should call this at shutdown.
// If the function succeeds, the return value is true, else false.
//
bool Finalize();
//
// Initialize built-in resources with minimum expected values.
// Parameters:
// resources: The object to initialize. Will be comparable with memcmp.
//
void InitBuiltInResources(ShBuiltInResources *resources);
//
// Returns the a concatenated list of the items in ShBuiltInResources as a null-terminated string.
// This function must be updated whenever ShBuiltInResources is changed.
// Parameters:
// handle: Specifies the handle of the compiler to be used.
const std::string &GetBuiltInResourcesString(const ShHandle handle);
//
// Driver calls these to create and destroy compiler objects.
//
// Returns the handle of constructed compiler, null if the requested compiler is not supported.
// Parameters:
// type: Specifies the type of shader - GL_FRAGMENT_SHADER or GL_VERTEX_SHADER.
// spec: Specifies the language spec the compiler must conform to - SH_GLES2_SPEC or SH_WEBGL_SPEC.
// output: Specifies the output code type - for example SH_ESSL_OUTPUT, SH_GLSL_OUTPUT,
// SH_HLSL_3_0_OUTPUT or SH_HLSL_4_1_OUTPUT. Note: Each output type may only
// be supported in some configurations.
// resources: Specifies the built-in resources.
ShHandle ConstructCompiler(sh::GLenum type,
ShShaderSpec spec,
ShShaderOutput output,
const ShBuiltInResources *resources);
void Destruct(ShHandle handle);
//
// Compiles the given shader source.
// If the function succeeds, the return value is true, else false.
// Parameters:
// handle: Specifies the handle of compiler to be used.
// shaderStrings: Specifies an array of pointers to null-terminated strings containing the shader
// source code.
// numStrings: Specifies the number of elements in shaderStrings array.
// compileOptions: A mask containing the following parameters:
// SH_VALIDATE: Validates shader to ensure that it conforms to the spec
// specified during compiler construction.
// SH_VALIDATE_LOOP_INDEXING: Validates loop and indexing in the shader to
// ensure that they do not exceed the minimum
// functionality mandated in GLSL 1.0 spec,
// Appendix A, Section 4 and 5.
// There is no need to specify this parameter when
// compiling for WebGL - it is implied.
// SH_INTERMEDIATE_TREE: Writes intermediate tree to info log.
// Can be queried by calling sh::GetInfoLog().
// SH_OBJECT_CODE: Translates intermediate tree to glsl or hlsl shader.
// Can be queried by calling sh::GetObjectCode().
// SH_VARIABLES: Extracts attributes, uniforms, and varyings.
// Can be queried by calling ShGetVariableInfo().
//
bool Compile(const ShHandle handle,
const char *const shaderStrings[],
size_t numStrings,
ShCompileOptions compileOptions);
// Clears the results from the previous compilation.
void ClearResults(const ShHandle handle);
// Return the version of the shader language.
int GetShaderVersion(const ShHandle handle);
// Return the currently set language output type.
ShShaderOutput GetShaderOutputType(const ShHandle handle);
// Returns null-terminated information log for a compiled shader.
// Parameters:
// handle: Specifies the compiler
const std::string &GetInfoLog(const ShHandle handle);
// Returns null-terminated object code for a compiled shader.
// Parameters:
// handle: Specifies the compiler
const std::string &GetObjectCode(const ShHandle handle);
// Returns a (original_name, hash) map containing all the user defined names in the shader,
// including variable names, function names, struct names, and struct field names.
// Parameters:
// handle: Specifies the compiler
const std::map<std::string, std::string> *GetNameHashingMap(const ShHandle handle);
// Shader variable inspection.
// Returns a pointer to a list of variables of the designated type.
// (See ShaderVars.h for type definitions, included above)
// Returns NULL on failure.
// Parameters:
// handle: Specifies the compiler
const std::vector<sh::Uniform> *GetUniforms(const ShHandle handle);
const std::vector<sh::Varying> *GetVaryings(const ShHandle handle);
const std::vector<sh::Attribute> *GetAttributes(const ShHandle handle);
const std::vector<sh::OutputVariable> *GetOutputVariables(const ShHandle handle);
const std::vector<sh::InterfaceBlock> *GetInterfaceBlocks(const ShHandle handle);
sh::WorkGroupSize GetComputeShaderLocalGroupSize(const ShHandle handle);
// Returns true if the passed in variables pack in maxVectors followingthe packing rules from the
// GLSL 1.017 spec, Appendix A, section 7.
// Returns false otherwise. Also look at the SH_ENFORCE_PACKING_RESTRICTIONS
// flag above.
// Parameters:
// maxVectors: the available rows of registers.
// variables: an array of variables.
bool CheckVariablesWithinPackingLimits(int maxVectors,
const std::vector<sh::ShaderVariable> &variables);
// Gives the compiler-assigned register for an interface block.
// The method writes the value to the output variable "indexOut".
// Returns true if it found a valid interface block, false otherwise.
// Parameters:
// handle: Specifies the compiler
// interfaceBlockName: Specifies the interface block
// indexOut: output variable that stores the assigned register
bool GetInterfaceBlockRegister(const ShHandle handle,
const std::string &interfaceBlockName,
unsigned int *indexOut);
// Gives a map from uniform names to compiler-assigned registers in the default interface block.
// Note that the map contains also registers of samplers that have been extracted from structs.
const std::map<std::string, unsigned int> *GetUniformRegisterMap(const ShHandle handle);
} // namespace sh
COMPILER_EXPORT const std::map<std::string, unsigned int> *ShGetUniformRegisterMap(
const ShHandle handle);
#endif // GLSLANG_SHADERLANG_H_

View file

@ -29,7 +29,7 @@ enum InterpolationType
};
// Validate link & SSO consistency of interpolation qualifiers
bool InterpolationTypesMatch(InterpolationType a, InterpolationType b);
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
@ -43,7 +43,7 @@ enum BlockLayoutType
// Note: we must override the copy constructor and assignment operator so we can
// work around excessive GCC binary bloating:
// See https://code.google.com/p/angleproject/issues/detail?id=697
struct ShaderVariable
struct COMPILER_EXPORT ShaderVariable
{
ShaderVariable();
ShaderVariable(GLenum typeIn, unsigned int arraySizeIn);
@ -92,7 +92,7 @@ struct ShaderVariable
}
};
struct Uniform : public ShaderVariable
struct COMPILER_EXPORT Uniform : public ShaderVariable
{
Uniform();
~Uniform();
@ -113,7 +113,7 @@ struct Uniform : public ShaderVariable
// An interface variable is a variable which passes data between the GL data structures and the
// shader execution: either vertex shader inputs or fragment shader outputs. These variables can
// have integer locations to pass back to the GL API.
struct InterfaceVariable : public ShaderVariable
struct COMPILER_EXPORT InterfaceVariable : public ShaderVariable
{
InterfaceVariable();
~InterfaceVariable();
@ -125,7 +125,7 @@ struct InterfaceVariable : public ShaderVariable
int location;
};
struct Attribute : public InterfaceVariable
struct COMPILER_EXPORT Attribute : public InterfaceVariable
{
Attribute();
~Attribute();
@ -135,7 +135,7 @@ struct Attribute : public InterfaceVariable
bool operator!=(const Attribute &other) const { return !operator==(other); }
};
struct OutputVariable : public InterfaceVariable
struct COMPILER_EXPORT OutputVariable : public InterfaceVariable
{
OutputVariable();
~OutputVariable();
@ -145,7 +145,7 @@ struct OutputVariable : public InterfaceVariable
bool operator!=(const OutputVariable &other) const { return !operator==(other); }
};
struct InterfaceBlockField : public ShaderVariable
struct COMPILER_EXPORT InterfaceBlockField : public ShaderVariable
{
InterfaceBlockField();
~InterfaceBlockField();
@ -167,7 +167,7 @@ struct InterfaceBlockField : public ShaderVariable
bool isRowMajorLayout;
};
struct Varying : public ShaderVariable
struct COMPILER_EXPORT Varying : public ShaderVariable
{
Varying();
~Varying();
@ -193,7 +193,7 @@ struct Varying : public ShaderVariable
bool isInvariant;
};
struct InterfaceBlock
struct COMPILER_EXPORT InterfaceBlock
{
InterfaceBlock();
~InterfaceBlock();
@ -216,7 +216,7 @@ struct InterfaceBlock
std::vector<InterfaceBlockField> fields;
};
struct WorkGroupSize
struct COMPILER_EXPORT WorkGroupSize
{
void fill(int fillValue);
void setLocalSize(int localSizeX, int localSizeY, int localSizeZ);

View file

@ -10,15 +10,13 @@
#define LIBGLESV2_EXPORT_H_
#if defined(_WIN32)
#if defined(LIBGLESV2_IMPLEMENTATION) || defined(LIBANGLE_IMPLEMENTATION) || \
defined(LIBANGLE_UTIL_IMPLEMENTATION)
# 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) || \
defined(LIBANGLE_UTIL_IMPLEMENTATION)
# if defined(LIBGLESV2_IMPLEMENTATION) || defined(LIBANGLE_IMPLEMENTATION)
# define ANGLE_EXPORT __attribute__((visibility ("default")))
# else
# define ANGLE_EXPORT

View file

@ -28,13 +28,11 @@ UNIFIED_SOURCES += [
'src/compiler/preprocessor/Preprocessor.cpp',
'src/compiler/preprocessor/Token.cpp',
'src/compiler/preprocessor/Tokenizer.cpp',
'src/compiler/translator/AddAndTrueToLoopCondition.cpp',
'src/compiler/translator/AddDefaultReturnStatements.cpp',
'src/compiler/translator/ArrayReturnValueToOutParameter.cpp',
'src/compiler/translator/ASTMetadataHLSL.cpp',
'src/compiler/translator/blocklayout.cpp',
'src/compiler/translator/blocklayoutHLSL.cpp',
'src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp',
'src/compiler/translator/BuiltInFunctionEmulator.cpp',
'src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp',
'src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp',
@ -42,8 +40,11 @@ UNIFIED_SOURCES += [
'src/compiler/translator/CallDAG.cpp',
'src/compiler/translator/CodeGen.cpp',
'src/compiler/translator/Compiler.cpp',
'src/compiler/translator/ConstantUnion.cpp',
'src/compiler/translator/DeferGlobalInitializers.cpp',
'src/compiler/translator/depgraph/DependencyGraph.cpp',
'src/compiler/translator/depgraph/DependencyGraphBuilder.cpp',
'src/compiler/translator/depgraph/DependencyGraphOutput.cpp',
'src/compiler/translator/depgraph/DependencyGraphTraverse.cpp',
'src/compiler/translator/Diagnostics.cpp',
'src/compiler/translator/DirectiveHandler.cpp',
'src/compiler/translator/EmulatePrecision.cpp',
@ -70,27 +71,28 @@ UNIFIED_SOURCES += [
'src/compiler/translator/ParseContext.cpp',
'src/compiler/translator/PoolAlloc.cpp',
'src/compiler/translator/PruneEmptyDeclarations.cpp',
'src/compiler/translator/QualifierTypes.cpp',
'src/compiler/translator/RecordConstantPrecision.cpp',
'src/compiler/translator/RegenerateStructNames.cpp',
'src/compiler/translator/RemoveDynamicIndexing.cpp',
'src/compiler/translator/RemoveInvariantDeclaration.cpp',
'src/compiler/translator/RemovePow.cpp',
'src/compiler/translator/RemoveSwitchFallThrough.cpp',
'src/compiler/translator/RewriteDoWhile.cpp',
'src/compiler/translator/RewriteElseBlocks.cpp',
'src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp',
'src/compiler/translator/RewriteTexelFetchOffset.cpp',
'src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp',
'src/compiler/translator/SearchSymbol.cpp',
'src/compiler/translator/SeparateArrayInitialization.cpp',
'src/compiler/translator/SeparateDeclarations.cpp',
'src/compiler/translator/SeparateExpressionsReturningArrays.cpp',
'src/compiler/translator/ShaderLang.cpp',
'src/compiler/translator/ShaderVars.cpp',
'src/compiler/translator/SimplifyLoopConditions.cpp',
'src/compiler/translator/SplitSequenceOperator.cpp',
'src/compiler/translator/StructureHLSL.cpp',
'src/compiler/translator/SymbolTable.cpp',
'src/compiler/translator/TextureFunctionHLSL.cpp',
'src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp',
'src/compiler/translator/timing/RestrictVertexShaderTiming.cpp',
'src/compiler/translator/TranslatorESSL.cpp',
'src/compiler/translator/TranslatorGLSL.cpp',
'src/compiler/translator/TranslatorHLSL.cpp',
@ -98,7 +100,6 @@ UNIFIED_SOURCES += [
'src/compiler/translator/UnfoldShortCircuitAST.cpp',
'src/compiler/translator/UnfoldShortCircuitToIf.cpp',
'src/compiler/translator/UniformHLSL.cpp',
'src/compiler/translator/UseInterfaceBlockFields.cpp',
'src/compiler/translator/util.cpp',
'src/compiler/translator/UtilsHLSL.cpp',
'src/compiler/translator/ValidateGlobalInitializer.cpp',
@ -115,8 +116,6 @@ SOURCES += [
'src/compiler/translator/EmulateGLFragColorBroadcast.cpp',
'src/compiler/translator/glslang_lex.cpp',
'src/compiler/translator/glslang_tab.cpp',
'src/compiler/translator/RewriteTexelFetchOffset.cpp',
'src/compiler/translator/ShaderLang.cpp',
]

View file

@ -45,7 +45,6 @@
'angle_enable_gl%': 1,
}],
],
'angle_enable_null%': 1, # Available on all platforms
},
'includes':
[
@ -59,7 +58,7 @@
{
'target_name': 'angle_common',
'type': 'static_library',
'includes': [ '../gyp/common_defines.gypi', ],
'includes': [ '../build/common_defines.gypi', ],
'sources':
[
'<@(libangle_common_sources)',
@ -146,7 +145,7 @@
{
'target_name': 'angle_image_util',
'type': 'static_library',
'includes': [ '../gyp/common_defines.gypi', ],
'includes': [ '../build/common_defines.gypi', ],
'sources':
[
'<@(libangle_image_util_sources)',
@ -173,7 +172,7 @@
{
'target_name': 'copy_scripts',
'type': 'none',
'includes': [ '../gyp/common_defines.gypi', ],
'includes': [ '../build/common_defines.gypi', ],
'hard_dependency': 1,
'copies':
[
@ -200,7 +199,7 @@
{
'target_name': 'commit_id',
'type': 'none',
'includes': [ '../gyp/common_defines.gypi', ],
'includes': [ '../build/common_defines.gypi', ],
'dependencies': [ 'copy_scripts', ],
'hard_dependency': 1,
'actions':
@ -242,7 +241,7 @@
'target_name': 'commit_id',
'type': 'none',
'hard_dependency': 1,
'includes': [ '../gyp/common_defines.gypi', ],
'includes': [ '../build/common_defines.gypi', ],
'copies':
[
{
@ -275,7 +274,7 @@
'target_name': 'copy_compiler_dll',
'type': 'none',
'dependencies': [ 'copy_scripts', ],
'includes': [ '../gyp/common_defines.gypi', ],
'includes': [ '../build/common_defines.gypi', ],
'conditions':
[
['angle_build_winrt==0',

View file

@ -1,3 +1,3 @@
#define ANGLE_COMMIT_HASH "2a250c8a0e15"
#define ANGLE_COMMIT_HASH_SIZE 12
#define ANGLE_COMMIT_DATE "2016-11-23 17:58:16 +0800"
#define ANGLE_COMMIT_HASH ""
#define ANGLE_COMMIT_HASH_SIZE 12
#define ANGLE_COMMIT_DATE ""

View file

@ -104,6 +104,7 @@ inline unsigned long ScanForward(unsigned long bits)
unsigned long firstBitIndex = 0ul;
unsigned char ret = _BitScanForward(&firstBitIndex, bits);
ASSERT(ret != 0);
UNUSED_ASSERTION_VARIABLE(ret);
return firstBitIndex;
#elif defined(ANGLE_PLATFORM_POSIX)
return static_cast<unsigned long>(__builtin_ctzl(bits));

View file

@ -156,14 +156,6 @@ size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char>
std::string FormatString(const char *fmt, va_list vararg);
std::string FormatString(const char *fmt, ...);
template <typename T>
std::string ToString(const T &value)
{
std::ostringstream o;
o << value;
return o.str();
}
// snprintf is not defined with MSVC prior to to msvc14
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf

View file

@ -171,9 +171,4 @@ ScopedPerfEventHelper::~ScopedPerfEventHelper()
}
}
std::ostream &DummyStream()
{
return std::cout;
}
} // namespace gl

View file

@ -57,20 +57,7 @@ void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator);
void UninitializeDebugAnnotations();
bool DebugAnnotationsActive();
// This class is used to explicitly ignore values in the conditional logging macros. This avoids
// compiler warnings like "value computed is not used" and "statement has no effect".
class LogMessageVoidify
{
public:
LogMessageVoidify() {}
// This has to be an operator with a precedence lower than << but higher than ?:
void operator&(std::ostream &) {}
};
// This can be any ostream, it is unused, but needs to be a valid reference.
std::ostream &DummyStream();
} // namespace gl
}
#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
#define ANGLE_TRACE_ENABLED
@ -117,58 +104,61 @@ std::ostream &DummyStream();
#undef ANGLE_TRACE_ENABLED
#endif
#if defined(COMPILER_GCC) || defined(__clang__)
#define ANGLE_CRASH() __builtin_trap()
#else
#define ANGLE_CRASH() ((void)(*(volatile char *)0 = 0))
#endif
#if !defined(NDEBUG)
#define ANGLE_ASSERT_IMPL(expression) assert(expression)
#else
// TODO(jmadill): Detect if debugger is attached and break.
#define ANGLE_ASSERT_IMPL(expression) ANGLE_CRASH()
#define ANGLE_ASSERT_IMPL(expression) abort()
#endif // !defined(NDEBUG)
// Helper macro which avoids evaluating the arguments to a stream if the condition doesn't hold.
// Condition is evaluated once and only once.
#define ANGLE_LAZY_STREAM(stream, condition) \
!(condition) ? static_cast<void>(0) : ::gl::LogMessageVoidify() & (stream)
#if defined(NDEBUG) && !defined(ANGLE_ENABLE_ASSERTS)
#define ANGLE_ASSERTS_ON 0
#else
#define ANGLE_ASSERTS_ON 1
#endif
// A macro asserting a condition and outputting failures to the debug log
#if ANGLE_ASSERTS_ON
#define ASSERT(expression) \
(expression ? static_cast<void>(0) \
: (ERR("\t! Assert failed in %s(%d): %s\n", __FUNCTION__, __LINE__, #expression), \
ANGLE_ASSERT_IMPL(expression)))
#if defined(ANGLE_ENABLE_ASSERTS)
#define ASSERT(expression) \
{ \
if (!(expression)) \
{ \
ERR("\t! Assert failed in %s(%d): %s\n", __FUNCTION__, __LINE__, #expression); \
ANGLE_ASSERT_IMPL(expression); \
} \
} \
ANGLE_EMPTY_STATEMENT
#define UNUSED_ASSERTION_VARIABLE(variable)
#else
#define ASSERT(condition) \
ANGLE_LAZY_STREAM(::gl::DummyStream(), ANGLE_ASSERTS_ON ? !(condition) : false) \
<< "Check failed: " #condition ". "
#endif // ANGLE_ASSERTS_ON
#define ASSERT(expression) (void(0))
#define UNUSED_ASSERTION_VARIABLE(variable) ((void)variable)
#endif
#define UNUSED_VARIABLE(variable) ((void)variable)
// A macro to indicate unimplemented functionality
#ifndef NOASSERT_UNIMPLEMENTED
#if defined (ANGLE_TEST_CONFIG)
#define NOASSERT_UNIMPLEMENTED 1
#endif
#define UNIMPLEMENTED() \
{ \
ERR("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__); \
ASSERT(NOASSERT_UNIMPLEMENTED); \
} \
ANGLE_EMPTY_STATEMENT
// Define NOASSERT_UNIMPLEMENTED to non zero to skip the assert fail in the unimplemented checks
// This will allow us to test with some automated test suites (eg dEQP) without crashing
#ifndef NOASSERT_UNIMPLEMENTED
#define NOASSERT_UNIMPLEMENTED 0
#endif
#if !defined(NDEBUG)
#define UNIMPLEMENTED() { \
FIXME("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__); \
assert(NOASSERT_UNIMPLEMENTED); \
} ANGLE_EMPTY_STATEMENT
#else
#define UNIMPLEMENTED() FIXME("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__)
#endif
// A macro for code which is not expected to be reached under valid assumptions
#define UNREACHABLE() \
(ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__), ASSERT(false))
#if !defined(NDEBUG)
#define UNREACHABLE() { \
ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__); \
assert(false); \
} ANGLE_EMPTY_STATEMENT
#else
#define UNREACHABLE() ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__)
#endif
#endif // COMMON_DEBUG_H_

View file

@ -14,9 +14,6 @@
namespace gl
{
namespace
{
struct RGB9E5Data
{
unsigned int R : 9;
@ -26,20 +23,17 @@ struct RGB9E5Data
};
// B is the exponent bias (15)
constexpr int g_sharedexp_bias = 15;
static const int g_sharedexp_bias = 15;
// N is the number of mantissa bits per component (9)
constexpr int g_sharedexp_mantissabits = 9;
static const int g_sharedexp_mantissabits = 9;
// Emax is the maximum allowed biased exponent value (31)
constexpr int g_sharedexp_maxexponent = 31;
static const int g_sharedexp_maxexponent = 31;
constexpr float g_sharedexp_max =
((static_cast<float>(1 << g_sharedexp_mantissabits) - 1) /
static_cast<float>(1 << g_sharedexp_mantissabits)) *
static_cast<float>(1 << (g_sharedexp_maxexponent - g_sharedexp_bias));
} // anonymous namespace
static const float g_sharedexp_max = ((pow(2.0f, g_sharedexp_mantissabits) - 1) /
pow(2.0f, g_sharedexp_mantissabits)) *
pow(2.0f, g_sharedexp_maxexponent - g_sharedexp_bias);
unsigned int convertRGBFloatsTo999E5(float red, float green, float blue)
{

View file

@ -44,15 +44,6 @@ struct Vector4
float w;
};
struct Vector2
{
Vector2() {}
Vector2(float x, float y) : x(x), y(y) {}
float x;
float y;
};
inline bool isPow2(int x)
{
return (x & (x - 1)) == 0 && (x != 0);
@ -765,40 +756,6 @@ constexpr unsigned int iSquareRoot()
return priv::iSquareRoot<N, 1>::value;
}
// Sum, difference and multiplication operations for signed ints that wrap on 32-bit overflow.
//
// Unsigned types are defined to do arithmetic modulo 2^n in C++. For signed types, overflow
// behavior is undefined.
template <typename T>
inline T WrappingSum(T lhs, T rhs)
{
uint32_t lhsUnsigned = static_cast<uint32_t>(lhs);
uint32_t rhsUnsigned = static_cast<uint32_t>(rhs);
return static_cast<T>(lhsUnsigned + rhsUnsigned);
}
template <typename T>
inline T WrappingDiff(T lhs, T rhs)
{
uint32_t lhsUnsigned = static_cast<uint32_t>(lhs);
uint32_t rhsUnsigned = static_cast<uint32_t>(rhs);
return static_cast<T>(lhsUnsigned - rhsUnsigned);
}
inline int32_t WrappingMul(int32_t lhs, int32_t rhs)
{
int64_t lhsWide = static_cast<int64_t>(lhs);
int64_t rhsWide = static_cast<int64_t>(rhs);
// The multiplication is guaranteed not to overflow.
int64_t resultWide = lhsWide * rhsWide;
// Implement the desired wrapping behavior by masking out the high-order 32 bits.
resultWide = resultWide & 0xffffffffll;
// Casting to a narrower signed type is fine since the casted value is representable in the
// narrower type.
return static_cast<int32_t>(resultWide);
}
} // namespace gl
namespace rx

View file

@ -16,7 +16,7 @@
// Unfortunately ANGLE relies on ASSERT being an empty statement, which these libs don't respect.
#ifndef NOTREACHED
#define NOTREACHED() UNREACHABLE()
#define NOTREACHED() 0
#endif
#endif // BASE_LOGGING_H_
#endif // BASE_LOGGING_H_

View file

@ -92,7 +92,7 @@ struct StaticDstRangeRelationToSrcRange<Dst,
static const NumericRangeRepresentation value = NUMERIC_RANGE_NOT_CONTAINED;
};
enum RangeConstraint : unsigned char
enum RangeConstraint
{
RANGE_VALID = 0x0, // Value can be represented by the destination type.
RANGE_UNDERFLOW = 0x1, // Value would overflow.

View file

@ -247,19 +247,7 @@ int VariableRowCount(GLenum type)
case GL_SAMPLER_2D_SHADOW:
case GL_SAMPLER_CUBE_SHADOW:
case GL_SAMPLER_2D_ARRAY_SHADOW:
case GL_IMAGE_2D:
case GL_INT_IMAGE_2D:
case GL_UNSIGNED_INT_IMAGE_2D:
case GL_IMAGE_2D_ARRAY:
case GL_INT_IMAGE_2D_ARRAY:
case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
case GL_IMAGE_3D:
case GL_INT_IMAGE_3D:
case GL_UNSIGNED_INT_IMAGE_3D:
case GL_IMAGE_CUBE:
case GL_INT_IMAGE_CUBE:
case GL_UNSIGNED_INT_IMAGE_CUBE:
return 1;
return 1;
case GL_FLOAT_MAT2:
case GL_FLOAT_MAT3x2:
case GL_FLOAT_MAT4x2:
@ -656,29 +644,6 @@ std::string ParseUniformName(const std::string &name, size_t *outSubscript)
return name.substr(0, open);
}
template <>
GLuint ConvertToGLuint(GLfloat param)
{
return uiround<GLuint>(param);
}
template <>
GLint ConvertToGLint(GLfloat param)
{
return iround<GLint>(param);
}
template <>
GLint ConvertFromGLfloat(GLfloat param)
{
return iround<GLint>(param);
}
template <>
GLuint ConvertFromGLfloat(GLfloat param)
{
return uiround<GLuint>(param);
}
unsigned int ParseAndStripArrayIndex(std::string *name)
{
unsigned int subscript = GL_INVALID_INDEX;

View file

@ -68,76 +68,6 @@ bool IsTriangleMode(GLenum drawMode);
template <typename outT> outT iround(GLfloat value) { return static_cast<outT>(value > 0.0f ? floor(value + 0.5f) : ceil(value - 0.5f)); }
template <typename outT> outT uiround(GLfloat value) { return static_cast<outT>(value + 0.5f); }
// Helper for converting arbitrary GL types to other GL types used in queries and state setting
template <typename ParamType>
GLuint ConvertToGLuint(ParamType param)
{
return static_cast<GLuint>(param);
}
template <>
GLuint ConvertToGLuint(GLfloat param);
template <typename ParamType>
GLint ConvertToGLint(ParamType param)
{
return static_cast<GLint>(param);
}
template <>
GLint ConvertToGLint(GLfloat param);
// Same conversion as uint
template <typename ParamType>
GLenum ConvertToGLenum(ParamType param)
{
return static_cast<GLenum>(ConvertToGLuint(param));
}
template <typename ParamType>
GLfloat ConvertToGLfloat(ParamType param)
{
return static_cast<GLfloat>(param);
}
template <typename ParamType>
ParamType ConvertFromGLfloat(GLfloat param)
{
return static_cast<ParamType>(param);
}
template <>
GLint ConvertFromGLfloat(GLfloat param);
template <>
GLuint ConvertFromGLfloat(GLfloat param);
template <typename ParamType>
ParamType ConvertFromGLenum(GLenum param)
{
return static_cast<ParamType>(param);
}
template <typename ParamType>
ParamType ConvertFromGLuint(GLuint param)
{
return static_cast<ParamType>(param);
}
template <typename ParamType>
ParamType ConvertFromGLint(GLint param)
{
return static_cast<ParamType>(param);
}
template <typename ParamType>
ParamType ConvertFromGLboolean(GLboolean param)
{
return static_cast<ParamType>(param ? GL_TRUE : GL_FALSE);
}
template <typename ParamType>
ParamType ConvertFromGLint64(GLint64 param)
{
return clampCast<ParamType>(param);
}
unsigned int ParseAndStripArrayIndex(std::string *name);
} // namespace gl

View file

@ -6,7 +6,7 @@
'variables':
{
# These file lists are shared with the GN build.
'angle_translator_sources':
'angle_translator_lib_sources':
[
'../include/EGL/egl.h',
'../include/EGL/eglext.h',
@ -22,13 +22,9 @@
'../include/GLSLANG/ShaderVars.h',
'../include/KHR/khrplatform.h',
'../include/angle_gl.h',
'compiler/translator/AddAndTrueToLoopCondition.cpp',
'compiler/translator/AddAndTrueToLoopCondition.h',
'compiler/translator/BaseTypes.h',
'compiler/translator/BuiltInFunctionEmulator.cpp',
'compiler/translator/BuiltInFunctionEmulator.h',
'compiler/translator/BreakVariableAliasingInInnerLoops.cpp',
'compiler/translator/BreakVariableAliasingInInnerLoops.h',
'compiler/translator/Cache.cpp',
'compiler/translator/Cache.h',
'compiler/translator/CallDAG.cpp',
@ -37,7 +33,6 @@
'compiler/translator/Common.h',
'compiler/translator/Compiler.cpp',
'compiler/translator/Compiler.h',
'compiler/translator/ConstantUnion.cpp',
'compiler/translator/ConstantUnion.h',
'compiler/translator/DeferGlobalInitializers.cpp',
'compiler/translator/DeferGlobalInitializers.h',
@ -86,36 +81,27 @@
'compiler/translator/Pragma.h',
'compiler/translator/PruneEmptyDeclarations.cpp',
'compiler/translator/PruneEmptyDeclarations.h',
'compiler/translator/QualifierTypes.h',
'compiler/translator/QualifierTypes.cpp',
'compiler/translator/RecordConstantPrecision.cpp',
'compiler/translator/RecordConstantPrecision.h',
'compiler/translator/RegenerateStructNames.cpp',
'compiler/translator/RegenerateStructNames.h',
'compiler/translator/RemoveInvariantDeclaration.cpp',
'compiler/translator/RemoveInvariantDeclaration.h',
'compiler/translator/RemovePow.cpp',
'compiler/translator/RemovePow.h',
'compiler/translator/RewriteDoWhile.cpp',
'compiler/translator/RewriteDoWhile.h',
'compiler/translator/RewriteTexelFetchOffset.cpp',
'compiler/translator/RewriteTexelFetchOffset.h',
'compiler/translator/RewriteUnaryMinusOperatorInt.cpp',
'compiler/translator/RewriteUnaryMinusOperatorInt.h',
'compiler/translator/RenameFunction.h',
'compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp',
'compiler/translator/ScalarizeVecAndMatConstructorArgs.h',
'compiler/translator/SearchSymbol.cpp',
'compiler/translator/SearchSymbol.h',
'compiler/translator/ShaderLang.cpp',
'compiler/translator/ShaderVars.cpp',
'compiler/translator/SymbolTable.cpp',
'compiler/translator/SymbolTable.h',
'compiler/translator/Types.cpp',
'compiler/translator/Types.h',
'compiler/translator/UnfoldShortCircuitAST.cpp',
'compiler/translator/UnfoldShortCircuitAST.h',
'compiler/translator/UseInterfaceBlockFields.cpp',
'compiler/translator/UseInterfaceBlockFields.h',
'compiler/translator/ValidateGlobalInitializer.cpp',
'compiler/translator/ValidateGlobalInitializer.h',
'compiler/translator/ValidateLimitations.cpp',
@ -132,6 +118,13 @@
'compiler/translator/VariablePacker.h',
'compiler/translator/blocklayout.cpp',
'compiler/translator/blocklayout.h',
'compiler/translator/depgraph/DependencyGraph.cpp',
'compiler/translator/depgraph/DependencyGraph.h',
'compiler/translator/depgraph/DependencyGraphBuilder.cpp',
'compiler/translator/depgraph/DependencyGraphBuilder.h',
'compiler/translator/depgraph/DependencyGraphOutput.cpp',
'compiler/translator/depgraph/DependencyGraphOutput.h',
'compiler/translator/depgraph/DependencyGraphTraverse.cpp',
'compiler/translator/glslang.h',
'compiler/translator/glslang.l',
'compiler/translator/glslang.y',
@ -140,19 +133,23 @@
'compiler/translator/glslang_tab.h',
'compiler/translator/intermOut.cpp',
'compiler/translator/length_limits.h',
'compiler/translator/timing/RestrictFragmentShaderTiming.cpp',
'compiler/translator/timing/RestrictFragmentShaderTiming.h',
'compiler/translator/timing/RestrictVertexShaderTiming.cpp',
'compiler/translator/timing/RestrictVertexShaderTiming.h',
'compiler/translator/util.cpp',
'compiler/translator/util.h',
'third_party/compiler/ArrayBoundsClamper.cpp',
'third_party/compiler/ArrayBoundsClamper.h',
],
'angle_translator_essl_sources':
'angle_translator_lib_essl_sources':
[
'compiler/translator/OutputESSL.cpp',
'compiler/translator/OutputESSL.h',
'compiler/translator/TranslatorESSL.cpp',
'compiler/translator/TranslatorESSL.h',
],
'angle_translator_glsl_sources':
'angle_translator_lib_glsl_sources':
[
'compiler/translator/BuiltInFunctionEmulatorGLSL.cpp',
'compiler/translator/BuiltInFunctionEmulatorGLSL.h',
@ -167,7 +164,7 @@
'compiler/translator/VersionGLSL.cpp',
'compiler/translator/VersionGLSL.h',
],
'angle_translator_hlsl_sources':
'angle_translator_lib_hlsl_sources':
[
'compiler/translator/AddDefaultReturnStatements.cpp',
'compiler/translator/AddDefaultReturnStatements.h',
@ -240,6 +237,7 @@
'compiler/preprocessor/Tokenizer.h',
'compiler/preprocessor/Tokenizer.l',
'compiler/preprocessor/numeric_lex.h',
'compiler/preprocessor/pp_utils.h',
],
},
# Everything below this is duplicated in the GN build. If you change
@ -249,23 +247,28 @@
{
'target_name': 'preprocessor',
'type': 'static_library',
'dependencies': [ 'angle_common' ],
'includes': [ '../gyp/common_defines.gypi', ],
'includes': [ '../build/common_defines.gypi', ],
'sources': [ '<@(angle_preprocessor_sources)', ],
},
{
'target_name': 'translator',
'target_name': 'translator_lib',
'type': 'static_library',
'dependencies': [ 'preprocessor', 'angle_common' ],
'includes': [ '../gyp/common_defines.gypi', ],
'includes': [ '../build/common_defines.gypi', ],
'include_dirs':
[
'.',
'../include',
],
'defines':
[
# define the static translator to indicate exported
# classes are (in fact) locally defined
'ANGLE_TRANSLATOR_STATIC',
],
'sources':
[
'<@(angle_translator_sources)',
'<@(angle_translator_lib_sources)',
],
'msvs_settings':
{
@ -291,7 +294,7 @@
},
'sources':
[
'<@(angle_translator_essl_sources)',
'<@(angle_translator_lib_essl_sources)',
],
}],
['angle_enable_glsl==1',
@ -309,7 +312,7 @@
},
'sources':
[
'<@(angle_translator_glsl_sources)',
'<@(angle_translator_lib_glsl_sources)',
],
}],
['angle_enable_hlsl==1',
@ -327,10 +330,59 @@
},
'sources':
[
'<@(angle_translator_hlsl_sources)',
'<@(angle_translator_lib_hlsl_sources)',
],
}],
],
},
{
'target_name': 'translator',
'type': '<(component)',
'dependencies': [ 'translator_lib', 'angle_common' ],
'includes': [ '../build/common_defines.gypi', ],
'include_dirs':
[
'.',
'../include',
],
'defines':
[
'ANGLE_TRANSLATOR_IMPLEMENTATION',
],
'sources':
[
'compiler/translator/ShaderLang.cpp',
'compiler/translator/ShaderVars.cpp'
],
},
{
'target_name': 'translator_static',
'type': 'static_library',
'dependencies': [ 'translator_lib' ],
'includes': [ '../build/common_defines.gypi', ],
'include_dirs':
[
'.',
'../include',
],
'defines':
[
'ANGLE_TRANSLATOR_STATIC',
],
'direct_dependent_settings':
{
'defines':
[
'ANGLE_TRANSLATOR_STATIC',
],
},
'sources':
[
'compiler/translator/ShaderLang.cpp',
'compiler/translator/ShaderVars.cpp'
],
},
],
}

View file

@ -1,161 +0,0 @@
//
// Copyright (c) 2016 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.
//
// translator_fuzzer.cpp: A libfuzzer fuzzer for the shader translator.
#include <stddef.h>
#include <stdint.h>
#include <unordered_map>
#include <iostream>
#include "compiler/translator/Compiler.h"
#include "angle_gl.h"
using namespace sh;
struct TranslatorCacheKey
{
bool operator==(const TranslatorCacheKey &other) const
{
return type == other.type && spec == other.spec && output == other.output;
}
uint32_t type = 0;
uint32_t spec = 0;
uint32_t output = 0;
};
namespace std
{
template <>
struct hash<TranslatorCacheKey>
{
std::size_t operator()(const TranslatorCacheKey &k) const
{
return (hash<uint32_t>()(k.type) << 1) ^ (hash<uint32_t>()(k.spec) >> 1) ^
hash<uint32_t>()(k.output);
}
};
} // namespace std
static std::unordered_map<TranslatorCacheKey, TCompiler *> translators;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
// Reserve some size for future compile options
const size_t kHeaderSize = 128;
if (size <= kHeaderSize)
{
return 0;
}
// Make sure the rest of data will be a valid C string so that we don't have to copy it.
if (data[size - 1] != 0)
{
return 0;
}
uint32_t type = *reinterpret_cast<const uint32_t *>(data);
uint32_t spec = *reinterpret_cast<const uint32_t *>(data + 4);
uint32_t output = *reinterpret_cast<const uint32_t *>(data + 8);
uint64_t options = *reinterpret_cast<const uint64_t *>(data + 12);
if (type != GL_FRAGMENT_SHADER && type != GL_VERTEX_SHADER)
{
return 0;
}
if (spec != SH_GLES2_SPEC && type != SH_WEBGL_SPEC && spec != SH_GLES3_SPEC &&
spec != SH_WEBGL2_SPEC)
{
return 0;
}
std::vector<uint32_t> validOutputs;
validOutputs.push_back(SH_ESSL_OUTPUT);
validOutputs.push_back(SH_GLSL_COMPATIBILITY_OUTPUT);
validOutputs.push_back(SH_GLSL_130_OUTPUT);
validOutputs.push_back(SH_GLSL_140_OUTPUT);
validOutputs.push_back(SH_GLSL_150_CORE_OUTPUT);
validOutputs.push_back(SH_GLSL_330_CORE_OUTPUT);
validOutputs.push_back(SH_GLSL_400_CORE_OUTPUT);
validOutputs.push_back(SH_GLSL_410_CORE_OUTPUT);
validOutputs.push_back(SH_GLSL_420_CORE_OUTPUT);
validOutputs.push_back(SH_GLSL_430_CORE_OUTPUT);
validOutputs.push_back(SH_GLSL_440_CORE_OUTPUT);
validOutputs.push_back(SH_GLSL_450_CORE_OUTPUT);
validOutputs.push_back(SH_HLSL_3_0_OUTPUT);
validOutputs.push_back(SH_HLSL_4_1_OUTPUT);
validOutputs.push_back(SH_HLSL_4_0_FL9_3_OUTPUT);
bool found = false;
for (auto valid : validOutputs)
{
found = found || (valid == output);
}
if (!found)
{
return 0;
}
size -= kHeaderSize;
data += kHeaderSize;
if (!ShInitialize())
{
return 0;
}
TranslatorCacheKey key;
key.type = type;
key.spec = spec;
key.output = output;
if (translators.find(key) == translators.end())
{
TCompiler *translator = ConstructCompiler(type, static_cast<ShShaderSpec>(spec),
static_cast<ShShaderOutput>(output));
if (!translator)
{
return 0;
}
ShBuiltInResources resources;
ShInitBuiltInResources(&resources);
// Enable all the extensions to have more coverage
resources.OES_standard_derivatives = 1;
resources.OES_EGL_image_external = 1;
resources.OES_EGL_image_external_essl3 = 1;
resources.NV_EGL_stream_consumer_external = 1;
resources.ARB_texture_rectangle = 1;
resources.EXT_blend_func_extended = 1;
resources.EXT_draw_buffers = 1;
resources.EXT_frag_depth = 1;
resources.EXT_shader_texture_lod = 1;
resources.WEBGL_debug_shader_precision = 1;
resources.EXT_shader_framebuffer_fetch = 1;
resources.NV_shader_framebuffer_fetch = 1;
resources.ARM_shader_framebuffer_fetch = 1;
if (!translator->Init(resources))
{
DeleteCompiler(translator);
return 0;
}
translators[key] = translator;
}
TCompiler *translator = translators[key];
const char *shaderStrings[] = {reinterpret_cast<const char *>(data)};
translator->compile(shaderStrings, 1, options);
return 0;
}

View file

@ -1,79 +1,31 @@
diff --git a/src/compiler/preprocessor/Tokenizer.cpp b/src/compiler/preprocessor/Tokenizer.cpp
index 0d7ad58..5ef0e5e 100644
--- a/src/compiler/preprocessor/Tokenizer.cpp
+++ b/src/compiler/preprocessor/Tokenizer.cpp
@@ -1703,7 +1703,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
{
int num_to_read =
- YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+ static_cast<int>(YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1);
while ( num_to_read <= 0 )
{ /* Not enough room in the buffer - grow it. */
@@ -1737,8 +1737,8 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
- num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
- number_to_move - 1;
+ num_to_read = static_cast<int>(YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1);
}
@@ -1746,8 +1746,10 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
num_to_read = YY_READ_BUF_SIZE;
/* Read in more data. */
+ yy_size_t ret = 0;
YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
- yyg->yy_n_chars, num_to_read );
+ ret, num_to_read );
+ yyg->yy_n_chars = static_cast<int>(ret);
YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
}
@@ -1773,13 +1775,13 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
if ((int) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
/* Extend the array by 50%, plus the number we really need. */
- int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+ yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) pprealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
}
- yyg->yy_n_chars += number_to_move;
+ yyg->yy_n_chars += static_cast<int>(number_to_move);
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
@@ -2171,7 +2173,7 @@ void pppop_buffer_state (yyscan_t yyscanner)
@@ -56,6 +56,7 @@ typedef int16_t flex_int16_t;
typedef uint16_t flex_uint16_t;
typedef int32_t flex_int32_t;
typedef uint32_t flex_uint32_t;
+typedef uint64_t flex_uint64_t;
#else
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
@@ -179,6 +180,11 @@ typedef void* yyscan_t;
typedef struct yy_buffer_state *YY_BUFFER_STATE;
#endif
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
#define EOB_ACT_CONTINUE_SCAN 0
#define EOB_ACT_END_OF_FILE 1
#define EOB_ACT_LAST_MATCH 2
@@ -353,7 +354,7 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
*/
static void ppensure_buffer_stack (yyscan_t yyscanner)
{
- int num_to_alloc;
+ yy_size_t num_to_alloc;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (!yyg->yy_buffer_stack) {
@@ -2238,7 +2240,7 @@ YY_BUFFER_STATE pp_scan_buffer (char * base, yy_size_t size , yyscan_t yyscann
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in pp_scan_buffer()" );
- b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_size = static_cast<int>(size - 2); /* "- 2" to take care of EOB's */
b->yy_buf_pos = b->yy_ch_buf = base;
b->yy_is_our_buffer = 0;
b->yy_input_file = NULL;
@@ -2293,7 +2295,7 @@ YY_BUFFER_STATE pp_scan_bytes (yyconst char * yybytes, int _yybytes_len , yysc
if ( ! buf )
YY_FATAL_ERROR( "out of dynamic memory in pp_scan_bytes()" );
- for ( i = 0; i < _yybytes_len; ++i )
+ for ( i = 0; i < static_cast<yy_size_t>(_yybytes_len); ++i )
buf[i] = yybytes[i];
buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
#define YY_DO_BEFORE_ACTION \
yyg->yytext_ptr = yy_bp; \
- yyleng = (size_t) (yy_cp - yy_bp); \
+ yyleng = (yy_size_t) (yy_cp - yy_bp); \
yyg->yy_hold_char = *yy_cp; \
*yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp;

View file

@ -4,9 +4,9 @@
// found in the LICENSE file.
//
#include "compiler/preprocessor/DiagnosticsBase.h"
#include "DiagnosticsBase.h"
#include "common/debug.h"
#include <cassert>
namespace pp
{
@ -31,7 +31,7 @@ Diagnostics::Severity Diagnostics::severity(ID id)
if ((id > PP_WARNING_BEGIN) && (id < PP_WARNING_END))
return PP_WARNING;
UNREACHABLE();
assert(false);
return PP_ERROR;
}
@ -74,8 +74,6 @@ std::string Diagnostics::message(ID id)
return "predefined macro undefined";
case PP_MACRO_UNTERMINATED_INVOCATION:
return "unterminated macro invocation";
case PP_MACRO_UNDEFINED_WHILE_INVOKED:
return "macro undefined while being invoked";
case PP_MACRO_TOO_FEW_ARGS:
return "Not enough arguments for macro";
case PP_MACRO_TOO_MANY_ARGS:
@ -133,8 +131,8 @@ std::string Diagnostics::message(ID id)
return "macro name with a double underscore is reserved - unintented behavior is possible";
// Warnings end.
default:
UNREACHABLE();
return "";
assert(false);
return "";
}
}

View file

@ -44,7 +44,6 @@ class Diagnostics
PP_MACRO_PREDEFINED_REDEFINED,
PP_MACRO_PREDEFINED_UNDEFINED,
PP_MACRO_UNTERMINATED_INVOCATION,
PP_MACRO_UNDEFINED_WHILE_INVOKED,
PP_MACRO_TOO_FEW_ARGS,
PP_MACRO_TOO_MANY_ARGS,
PP_MACRO_DUPLICATE_PARAMETER_NAMES,

View file

@ -4,7 +4,7 @@
// found in the LICENSE file.
//
#include "compiler/preprocessor/DirectiveHandlerBase.h"
#include "DirectiveHandlerBase.h"
namespace pp
{

View file

@ -4,19 +4,19 @@
// found in the LICENSE file.
//
#include "compiler/preprocessor/DirectiveParser.h"
#include "DirectiveParser.h"
#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <sstream>
#include "common/debug.h"
#include "compiler/preprocessor/DiagnosticsBase.h"
#include "compiler/preprocessor/DirectiveHandlerBase.h"
#include "compiler/preprocessor/ExpressionParser.h"
#include "compiler/preprocessor/MacroExpander.h"
#include "compiler/preprocessor/Token.h"
#include "compiler/preprocessor/Tokenizer.h"
#include "DiagnosticsBase.h"
#include "DirectiveHandlerBase.h"
#include "ExpressionParser.h"
#include "MacroExpander.h"
#include "Token.h"
#include "Tokenizer.h"
namespace {
enum DirectiveType
@ -248,7 +248,7 @@ void DirectiveParser::lex(Token *token)
void DirectiveParser::parseDirective(Token *token)
{
ASSERT(token->type == Token::PP_HASH);
assert(token->type == Token::PP_HASH);
mTokenizer->lex(token);
if (isEOD(token))
@ -314,8 +314,8 @@ void DirectiveParser::parseDirective(Token *token)
parseLine(token);
break;
default:
UNREACHABLE();
break;
assert(false);
break;
}
skipUntilEOD(mTokenizer, token);
@ -328,7 +328,7 @@ void DirectiveParser::parseDirective(Token *token)
void DirectiveParser::parseDefine(Token *token)
{
ASSERT(getDirective(token) == DIRECTIVE_DEFINE);
assert(getDirective(token) == DIRECTIVE_DEFINE);
mTokenizer->lex(token);
if (token->type != Token::IDENTIFIER)
@ -428,7 +428,7 @@ void DirectiveParser::parseDefine(Token *token)
void DirectiveParser::parseUndef(Token *token)
{
ASSERT(getDirective(token) == DIRECTIVE_UNDEF);
assert(getDirective(token) == DIRECTIVE_UNDEF);
mTokenizer->lex(token);
if (token->type != Token::IDENTIFIER)
@ -445,13 +445,6 @@ void DirectiveParser::parseUndef(Token *token)
{
mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_UNDEFINED,
token->location, token->text);
return;
}
else if (iter->second.expansionCount > 0)
{
mDiagnostics->report(Diagnostics::PP_MACRO_UNDEFINED_WHILE_INVOKED, token->location,
token->text);
return;
}
else
{
@ -470,25 +463,25 @@ void DirectiveParser::parseUndef(Token *token)
void DirectiveParser::parseIf(Token *token)
{
ASSERT(getDirective(token) == DIRECTIVE_IF);
assert(getDirective(token) == DIRECTIVE_IF);
parseConditionalIf(token);
}
void DirectiveParser::parseIfdef(Token *token)
{
ASSERT(getDirective(token) == DIRECTIVE_IFDEF);
assert(getDirective(token) == DIRECTIVE_IFDEF);
parseConditionalIf(token);
}
void DirectiveParser::parseIfndef(Token *token)
{
ASSERT(getDirective(token) == DIRECTIVE_IFNDEF);
assert(getDirective(token) == DIRECTIVE_IFNDEF);
parseConditionalIf(token);
}
void DirectiveParser::parseElse(Token *token)
{
ASSERT(getDirective(token) == DIRECTIVE_ELSE);
assert(getDirective(token) == DIRECTIVE_ELSE);
if (mConditionalStack.empty())
{
@ -529,7 +522,7 @@ void DirectiveParser::parseElse(Token *token)
void DirectiveParser::parseElif(Token *token)
{
ASSERT(getDirective(token) == DIRECTIVE_ELIF);
assert(getDirective(token) == DIRECTIVE_ELIF);
if (mConditionalStack.empty())
{
@ -569,7 +562,7 @@ void DirectiveParser::parseElif(Token *token)
void DirectiveParser::parseEndif(Token *token)
{
ASSERT(getDirective(token) == DIRECTIVE_ENDIF);
assert(getDirective(token) == DIRECTIVE_ENDIF);
if (mConditionalStack.empty())
{
@ -593,7 +586,7 @@ void DirectiveParser::parseEndif(Token *token)
void DirectiveParser::parseError(Token *token)
{
ASSERT(getDirective(token) == DIRECTIVE_ERROR);
assert(getDirective(token) == DIRECTIVE_ERROR);
std::ostringstream stream;
mTokenizer->lex(token);
@ -608,7 +601,7 @@ void DirectiveParser::parseError(Token *token)
// Parses pragma of form: #pragma name[(value)].
void DirectiveParser::parsePragma(Token *token)
{
ASSERT(getDirective(token) == DIRECTIVE_PRAGMA);
assert(getDirective(token) == DIRECTIVE_PRAGMA);
enum State
{
@ -669,7 +662,7 @@ void DirectiveParser::parsePragma(Token *token)
void DirectiveParser::parseExtension(Token *token)
{
ASSERT(getDirective(token) == DIRECTIVE_EXTENSION);
assert(getDirective(token) == DIRECTIVE_EXTENSION);
enum State
{
@ -750,7 +743,7 @@ void DirectiveParser::parseExtension(Token *token)
void DirectiveParser::parseVersion(Token *token)
{
ASSERT(getDirective(token) == DIRECTIVE_VERSION);
assert(getDirective(token) == DIRECTIVE_VERSION);
if (mPastFirstStatement)
{
@ -837,7 +830,7 @@ void DirectiveParser::parseVersion(Token *token)
void DirectiveParser::parseLine(Token *token)
{
ASSERT(getDirective(token) == DIRECTIVE_LINE);
assert(getDirective(token) == DIRECTIVE_LINE);
bool valid = true;
bool parsedFileNumber = false;
@ -938,8 +931,8 @@ void DirectiveParser::parseConditionalIf(Token *token)
expression = parseExpressionIfdef(token) == 0 ? 1 : 0;
break;
default:
UNREACHABLE();
break;
assert(false);
break;
}
block.skipGroup = expression == 0;
block.foundValidGroup = expression != 0;
@ -949,7 +942,8 @@ void DirectiveParser::parseConditionalIf(Token *token)
int DirectiveParser::parseExpressionIf(Token *token)
{
ASSERT((getDirective(token) == DIRECTIVE_IF) || (getDirective(token) == DIRECTIVE_ELIF));
assert((getDirective(token) == DIRECTIVE_IF) ||
(getDirective(token) == DIRECTIVE_ELIF));
DefinedParser definedParser(mTokenizer, mMacroSet, mDiagnostics);
MacroExpander macroExpander(&definedParser, mMacroSet, mDiagnostics);
@ -976,7 +970,8 @@ int DirectiveParser::parseExpressionIf(Token *token)
int DirectiveParser::parseExpressionIfdef(Token *token)
{
ASSERT((getDirective(token) == DIRECTIVE_IFDEF) || (getDirective(token) == DIRECTIVE_IFNDEF));
assert((getDirective(token) == DIRECTIVE_IFDEF) ||
(getDirective(token) == DIRECTIVE_IFNDEF));
mTokenizer->lex(token);
if (token->type != Token::IDENTIFIER)

View file

@ -7,9 +7,10 @@
#ifndef COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_
#define COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_
#include "compiler/preprocessor/Lexer.h"
#include "compiler/preprocessor/Macro.h"
#include "compiler/preprocessor/SourceLocation.h"
#include "Lexer.h"
#include "Macro.h"
#include "pp_utils.h"
#include "SourceLocation.h"
namespace pp
{
@ -29,6 +30,7 @@ class DirectiveParser : public Lexer
void lex(Token *token) override;
private:
PP_DISALLOW_COPY_AND_ASSIGN(DirectiveParser);
void parseDirective(Token *token);
void parseDefine(Token *token);

View file

@ -99,15 +99,17 @@
#include <cassert>
#include <sstream>
#include <stdint.h>
#include "DiagnosticsBase.h"
#include "Lexer.h"
#include "Token.h"
#include "common/mathutil.h"
typedef int32_t YYSTYPE;
typedef uint32_t UNSIGNED_TYPE;
#if defined(_MSC_VER)
typedef __int64 YYSTYPE;
#else
#include <stdint.h>
typedef intmax_t YYSTYPE;
#endif // _MSC_VER
#define YYENABLE_NLS 0
#define YYLTYPE_IS_TRIVIAL 1
@ -496,12 +498,9 @@ static const yytype_uint8 yytranslate[] =
#if YYDEBUG
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
0, 108, 108, 115, 116, 127, 127, 148, 148, 169,
172, 175, 178, 181, 184, 187, 190, 193, 196, 221,
246, 249, 252, 278, 305, 308, 311, 314, 326, 329
};
static const yytype_uint16 yyrline[] = {0, 110, 110, 117, 118, 129, 129, 150, 150, 171,
174, 177, 180, 183, 186, 189, 192, 195, 198, 218,
238, 241, 244, 264, 284, 287, 290, 293, 296, 299};
#endif
#if YYDEBUG || YYERROR_VERBOSE || 0
@ -1493,7 +1492,7 @@ yyreduce:
case 18:
{
if ((yyvsp[0]) < 0 || (yyvsp[0]) > 31)
if ((yyvsp[0]) < 0)
{
if (!context->isIgnoringErrors())
{
@ -1501,17 +1500,11 @@ yyreduce:
stream << (yyvsp[-2]) << " >> " << (yyvsp[0]);
std::string text = stream.str();
context->diagnostics->report(pp::Diagnostics::PP_UNDEFINED_SHIFT,
context->token->location,
text.c_str());
context->token->location, text.c_str());
*(context->valid) = false;
}
(yyval) = static_cast<YYSTYPE>(0);
}
else if ((yyvsp[-2]) < 0)
{
// Logical shift right.
(yyval) = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>((yyvsp[-2])) >> (yyvsp[0]));
}
else
{
(yyval) = (yyvsp[-2]) >> (yyvsp[0]);
@ -1523,7 +1516,7 @@ yyreduce:
case 19:
{
if ((yyvsp[0]) < 0 || (yyvsp[0]) > 31)
if ((yyvsp[0]) < 0)
{
if (!context->isIgnoringErrors())
{
@ -1531,17 +1524,11 @@ yyreduce:
stream << (yyvsp[-2]) << " << " << (yyvsp[0]);
std::string text = stream.str();
context->diagnostics->report(pp::Diagnostics::PP_UNDEFINED_SHIFT,
context->token->location,
text.c_str());
context->token->location, text.c_str());
*(context->valid) = false;
}
(yyval) = static_cast<YYSTYPE>(0);
}
else if ((yyvsp[-2]) < 0)
{
// Logical shift left.
(yyval) = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>((yyvsp[-2])) << (yyvsp[0]));
}
else
{
(yyval) = (yyvsp[-2]) << (yyvsp[0]);
@ -1553,7 +1540,7 @@ yyreduce:
case 20:
{
(yyval) = gl::WrappingDiff<YYSTYPE>((yyvsp[-2]), (yyvsp[0]));
(yyval) = (yyvsp[-2]) - (yyvsp[0]);
}
break;
@ -1561,7 +1548,7 @@ yyreduce:
case 21:
{
(yyval) = gl::WrappingSum<YYSTYPE>((yyvsp[-2]), (yyvsp[0]));
(yyval) = (yyvsp[-2]) + (yyvsp[0]);
}
break;
@ -1583,12 +1570,6 @@ yyreduce:
}
(yyval) = static_cast<YYSTYPE>(0);
}
else if (((yyvsp[-2]) == std::numeric_limits<YYSTYPE>::min()) && ((yyvsp[0]) == -1))
{
// Check for the special case where the minimum representable number is
// divided by -1. If left alone this has undefined results.
(yyval) = 0;
}
else
{
(yyval) = (yyvsp[-2]) % (yyvsp[0]);
@ -1614,13 +1595,6 @@ yyreduce:
}
(yyval) = static_cast<YYSTYPE>(0);
}
else if (((yyvsp[-2]) == std::numeric_limits<YYSTYPE>::min()) && ((yyvsp[0]) == -1))
{
// Check for the special case where the minimum representable number is
// divided by -1. If left alone this leads to integer overflow in C++, which
// has undefined results.
(yyval) = std::numeric_limits<YYSTYPE>::max();
}
else
{
(yyval) = (yyvsp[-2]) / (yyvsp[0]);
@ -1632,7 +1606,7 @@ yyreduce:
case 24:
{
(yyval) = gl::WrappingMul((yyvsp[-2]), (yyvsp[0]));
(yyval) = (yyvsp[-2]) * (yyvsp[0]);
}
break;
@ -1656,16 +1630,7 @@ yyreduce:
case 27:
{
// Check for negation of minimum representable integer to prevent undefined signed int
// overflow.
if ((yyvsp[0]) == std::numeric_limits<YYSTYPE>::min())
{
(yyval) = std::numeric_limits<YYSTYPE>::min();
}
else
{
(yyval) = -(yyvsp[0]);
}
(yyval) = - (yyvsp[0]);
}
break;

View file

@ -7,8 +7,8 @@
#ifndef COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_
#define COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_
#include "common/angleutils.h"
#include "compiler/preprocessor/DiagnosticsBase.h"
#include "DiagnosticsBase.h"
#include "pp_utils.h"
namespace pp
{
@ -16,7 +16,7 @@ namespace pp
class Lexer;
struct Token;
class ExpressionParser : angle::NonCopyable
class ExpressionParser
{
public:
struct ErrorSettings
@ -34,6 +34,8 @@ class ExpressionParser : angle::NonCopyable
bool *valid);
private:
PP_DISALLOW_COPY_AND_ASSIGN(ExpressionParser);
Lexer *mLexer;
Diagnostics *mDiagnostics;
};

View file

@ -41,15 +41,17 @@ WHICH GENERATES THE GLSL ES preprocessor expression parser.
#include <cassert>
#include <sstream>
#include <stdint.h>
#include "DiagnosticsBase.h"
#include "Lexer.h"
#include "Token.h"
#include "common/mathutil.h"
typedef int32_t YYSTYPE;
typedef uint32_t UNSIGNED_TYPE;
#if defined(_MSC_VER)
typedef __int64 YYSTYPE;
#else
#include <stdint.h>
typedef intmax_t YYSTYPE;
#endif // _MSC_VER
#define YYENABLE_NLS 0
#define YYLTYPE_IS_TRIVIAL 1
@ -194,7 +196,7 @@ expression
$$ = $1 < $3;
}
| expression TOK_OP_RIGHT expression {
if ($3 < 0 || $3 > 31)
if ($3 < 0)
{
if (!context->isIgnoringErrors())
{
@ -208,18 +210,13 @@ expression
}
$$ = static_cast<YYSTYPE>(0);
}
else if ($1 < 0)
{
// Logical shift right.
$$ = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>($1) >> $3);
}
else
{
$$ = $1 >> $3;
}
}
| expression TOK_OP_LEFT expression {
if ($3 < 0 || $3 > 31)
if ($3 < 0)
{
if (!context->isIgnoringErrors())
{
@ -233,21 +230,16 @@ expression
}
$$ = static_cast<YYSTYPE>(0);
}
else if ($1 < 0)
{
// Logical shift left.
$$ = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>($1) << $3);
}
else
{
$$ = $1 << $3;
}
}
| expression '-' expression {
$$ = gl::WrappingDiff<YYSTYPE>($1, $3);
$$ = $1 - $3;
}
| expression '+' expression {
$$ = gl::WrappingSum<YYSTYPE>($1, $3);
$$ = $1 + $3;
}
| expression '%' expression {
if ($3 == 0)
@ -264,12 +256,6 @@ expression
}
$$ = static_cast<YYSTYPE>(0);
}
else if (($1 == std::numeric_limits<YYSTYPE>::min()) && ($3 == -1))
{
// Check for the special case where the minimum representable number is
// divided by -1. If left alone this has undefined results.
$$ = 0;
}
else
{
$$ = $1 % $3;
@ -290,20 +276,13 @@ expression
}
$$ = static_cast<YYSTYPE>(0);
}
else if (($1 == std::numeric_limits<YYSTYPE>::min()) && ($3 == -1))
{
// Check for the special case where the minimum representable number is
// divided by -1. If left alone this leads to integer overflow in C++, which
// has undefined results.
$$ = std::numeric_limits<YYSTYPE>::max();
}
else
{
$$ = $1 / $3;
}
}
| expression '*' expression {
$$ = gl::WrappingMul($1, $3);
$$ = $1 * $3;
}
| '!' expression %prec TOK_UNARY {
$$ = ! $2;
@ -312,16 +291,7 @@ expression
$$ = ~ $2;
}
| '-' expression %prec TOK_UNARY {
// Check for negation of minimum representable integer to prevent undefined signed int
// overflow.
if ($2 == std::numeric_limits<YYSTYPE>::min())
{
$$ = std::numeric_limits<YYSTYPE>::min();
}
else
{
$$ = -$2;
}
$$ = - $2;
}
| '+' expression %prec TOK_UNARY {
$$ = + $2;

View file

@ -4,13 +4,12 @@
// found in the LICENSE file.
//
#include "compiler/preprocessor/Input.h"
#include "Input.h"
#include <algorithm>
#include <cassert>
#include <cstring>
#include "common/debug.h"
namespace pp
{
@ -33,7 +32,7 @@ Input::Input(size_t count, const char *const string[], const int length[]) :
const char *Input::skipChar()
{
// This function should only be called when there is a character to skip.
ASSERT(mReadLoc.cIndex < mLength[mReadLoc.sIndex]);
assert(mReadLoc.cIndex < mLength[mReadLoc.sIndex]);
++mReadLoc.cIndex;
if (mReadLoc.cIndex == mLength[mReadLoc.sIndex])
{

View file

@ -7,7 +7,7 @@
#ifndef COMPILER_PREPROCESSOR_INPUT_H_
#define COMPILER_PREPROCESSOR_INPUT_H_
#include <cstddef>
#include <stddef.h>
#include <vector>
namespace pp

View file

@ -4,7 +4,7 @@
// found in the LICENSE file.
//
#include "compiler/preprocessor/Lexer.h"
#include "Lexer.h"
namespace pp
{

View file

@ -7,14 +7,12 @@
#ifndef COMPILER_PREPROCESSOR_LEXER_H_
#define COMPILER_PREPROCESSOR_LEXER_H_
#include "common/angleutils.h"
namespace pp
{
struct Token;
class Lexer : angle::NonCopyable
class Lexer
{
public:
virtual ~Lexer();

View file

@ -4,10 +4,11 @@
// found in the LICENSE file.
//
#include "compiler/preprocessor/Macro.h"
#include "Macro.h"
#include "common/angleutils.h"
#include "compiler/preprocessor/Token.h"
#include <sstream>
#include "Token.h"
namespace pp
{
@ -22,9 +23,12 @@ bool Macro::equals(const Macro &other) const
void PredefineMacro(MacroSet *macroSet, const char *name, int value)
{
std::ostringstream stream;
stream << value;
Token token;
token.type = Token::CONST_INT;
token.text = ToString(value);
token.text = stream.str();
Macro macro;
macro.predefined = true;

View file

@ -26,12 +26,16 @@ struct Macro
typedef std::vector<std::string> Parameters;
typedef std::vector<Token> Replacements;
Macro() : predefined(false), disabled(false), expansionCount(0), type(kTypeObj) {}
Macro()
: predefined(false),
disabled(false),
type(kTypeObj)
{
}
bool equals(const Macro &other) const;
bool predefined;
mutable bool disabled;
mutable int expansionCount;
Type type;
std::string name;

View file

@ -4,22 +4,17 @@
// found in the LICENSE file.
//
#include "compiler/preprocessor/MacroExpander.h"
#include "MacroExpander.h"
#include <algorithm>
#include <sstream>
#include "common/debug.h"
#include "compiler/preprocessor/DiagnosticsBase.h"
#include "compiler/preprocessor/Token.h"
#include "DiagnosticsBase.h"
#include "Token.h"
namespace pp
{
namespace
{
const size_t kMaxContextTokens = 10000;
class TokenLexer : public Lexer
{
public:
@ -45,52 +40,22 @@ class TokenLexer : public Lexer
}
private:
PP_DISALLOW_COPY_AND_ASSIGN(TokenLexer);
TokenVector mTokens;
TokenVector::const_iterator mIter;
};
} // anonymous namespace
class MacroExpander::ScopedMacroReenabler final : angle::NonCopyable
{
public:
ScopedMacroReenabler(MacroExpander *expander);
~ScopedMacroReenabler();
private:
MacroExpander *mExpander;
};
MacroExpander::ScopedMacroReenabler::ScopedMacroReenabler(MacroExpander *expander)
: mExpander(expander)
{
mExpander->mDeferReenablingMacros = true;
}
MacroExpander::ScopedMacroReenabler::~ScopedMacroReenabler()
{
mExpander->mDeferReenablingMacros = false;
for (auto *macro : mExpander->mMacrosToReenable)
{
macro->disabled = false;
}
mExpander->mMacrosToReenable.clear();
}
MacroExpander::MacroExpander(Lexer *lexer, MacroSet *macroSet, Diagnostics *diagnostics)
: mLexer(lexer),
mMacroSet(macroSet),
mDiagnostics(diagnostics),
mTotalTokensInContexts(0),
mDeferReenablingMacros(false)
: mLexer(lexer), mMacroSet(macroSet), mDiagnostics(diagnostics)
{
}
MacroExpander::~MacroExpander()
{
for (MacroContext *context : mContextStack)
for (std::size_t i = 0; i < mContextStack.size(); ++i)
{
delete context;
delete mContextStack[i];
}
}
@ -117,15 +82,10 @@ void MacroExpander::lex(Token *token)
token->setExpansionDisabled(true);
break;
}
// Bump the expansion count before peeking if the next token is a '('
// otherwise there could be a #undef of the macro before the next token.
macro.expansionCount++;
if ((macro.type == Macro::kTypeFunc) && !isNextTokenLeftParen())
{
// If the token immediately after the macro name is not a '(',
// this macro should not be expanded.
macro.expansionCount--;
break;
}
@ -154,7 +114,6 @@ void MacroExpander::getToken(Token *token)
}
else
{
ASSERT(mTotalTokensInContexts == 0);
mLexer->lex(token);
}
}
@ -165,11 +124,11 @@ void MacroExpander::ungetToken(const Token &token)
{
MacroContext *context = mContextStack.back();
context->unget();
ASSERT(context->replacements[context->index] == token);
assert(context->replacements[context->index] == token);
}
else
{
ASSERT(!mReserveToken.get());
assert(!mReserveToken.get());
mReserveToken.reset(new Token(token));
}
}
@ -187,10 +146,10 @@ bool MacroExpander::isNextTokenLeftParen()
bool MacroExpander::pushMacro(const Macro &macro, const Token &identifier)
{
ASSERT(!macro.disabled);
ASSERT(!identifier.expansionDisabled());
ASSERT(identifier.type == Token::IDENTIFIER);
ASSERT(identifier.text == macro.name);
assert(!macro.disabled);
assert(!identifier.expansionDisabled());
assert(identifier.type == Token::IDENTIFIER);
assert(identifier.text == macro.name);
std::vector<Token> replacements;
if (!expandMacro(macro, identifier, &replacements))
@ -203,30 +162,19 @@ bool MacroExpander::pushMacro(const Macro &macro, const Token &identifier)
context->macro = &macro;
context->replacements.swap(replacements);
mContextStack.push_back(context);
mTotalTokensInContexts += context->replacements.size();
return true;
}
void MacroExpander::popMacro()
{
ASSERT(!mContextStack.empty());
assert(!mContextStack.empty());
MacroContext *context = mContextStack.back();
mContextStack.pop_back();
ASSERT(context->empty());
ASSERT(context->macro->disabled);
ASSERT(context->macro->expansionCount > 0);
if (mDeferReenablingMacros)
{
mMacrosToReenable.push_back(context->macro);
}
else
{
context->macro->disabled = false;
}
context->macro->expansionCount--;
mTotalTokensInContexts -= context->replacements.size();
assert(context->empty());
assert(context->macro->disabled);
context->macro->disabled = false;
delete context;
}
@ -251,21 +199,25 @@ bool MacroExpander::expandMacro(const Macro &macro,
const char kLine[] = "__LINE__";
const char kFile[] = "__FILE__";
ASSERT(replacements->size() == 1);
assert(replacements->size() == 1);
Token& repl = replacements->front();
if (macro.name == kLine)
{
repl.text = ToString(identifier.location.line);
std::ostringstream stream;
stream << identifier.location.line;
repl.text = stream.str();
}
else if (macro.name == kFile)
{
repl.text = ToString(identifier.location.file);
std::ostringstream stream;
stream << identifier.location.file;
repl.text = stream.str();
}
}
}
else
{
ASSERT(macro.type == Macro::kTypeFunc);
assert(macro.type == Macro::kTypeFunc);
std::vector<MacroArg> args;
args.reserve(macro.parameters.size());
if (!collectMacroArgs(macro, identifier, &args, &replacementLocation))
@ -296,17 +248,10 @@ bool MacroExpander::collectMacroArgs(const Macro &macro,
{
Token token;
getToken(&token);
ASSERT(token.type == '(');
assert(token.type == '(');
args->push_back(MacroArg());
// Defer reenabling macros until args collection is finished to avoid the possibility of
// infinite recursion. Otherwise infinite recursion might happen when expanding the args after
// macros have been popped from the context stack when parsing the args.
ScopedMacroReenabler deferReenablingMacros(this);
int openParens = 1;
while (openParens != 0)
for (int openParens = 1; openParens != 0; )
{
getToken(&token);
@ -372,9 +317,9 @@ bool MacroExpander::collectMacroArgs(const Macro &macro,
// Pre-expand each argument before substitution.
// This step expands each argument individually before they are
// inserted into the macro body.
size_t numTokens = 0;
for (auto &arg : *args)
for (std::size_t i = 0; i < args->size(); ++i)
{
MacroArg &arg = args->at(i);
TokenLexer lexer(&arg);
MacroExpander expander(&lexer, mMacroSet, mDiagnostics);
@ -384,12 +329,6 @@ bool MacroExpander::collectMacroArgs(const Macro &macro,
{
arg.push_back(token);
expander.lex(&token);
numTokens++;
if (numTokens + mTotalTokensInContexts > kMaxContextTokens)
{
mDiagnostics->report(Diagnostics::PP_OUT_OF_MEMORY, token.location, token.text);
return false;
}
}
}
return true;
@ -401,14 +340,6 @@ void MacroExpander::replaceMacroParams(const Macro &macro,
{
for (std::size_t i = 0; i < macro.replacements.size(); ++i)
{
if (!replacements->empty() &&
replacements->size() + mTotalTokensInContexts > kMaxContextTokens)
{
const Token &token = replacements->back();
mDiagnostics->report(Diagnostics::PP_OUT_OF_MEMORY, token.location, token.text);
return;
}
const Token &repl = macro.replacements[i];
if (repl.type != Token::IDENTIFIER)
{
@ -441,25 +372,5 @@ void MacroExpander::replaceMacroParams(const Macro &macro,
}
}
MacroExpander::MacroContext::MacroContext() : macro(0), index(0)
{
}
bool MacroExpander::MacroContext::empty() const
{
return index == replacements.size();
}
const Token &MacroExpander::MacroContext::get()
{
return replacements[index++];
}
void MacroExpander::MacroContext::unget()
{
ASSERT(index > 0);
--index;
}
} // namespace pp

View file

@ -7,11 +7,13 @@
#ifndef COMPILER_PREPROCESSOR_MACROEXPANDER_H_
#define COMPILER_PREPROCESSOR_MACROEXPANDER_H_
#include <cassert>
#include <memory>
#include <vector>
#include "compiler/preprocessor/Lexer.h"
#include "compiler/preprocessor/Macro.h"
#include "Lexer.h"
#include "Macro.h"
#include "pp_utils.h"
namespace pp
{
@ -28,6 +30,8 @@ class MacroExpander : public Lexer
void lex(Token *token) override;
private:
PP_DISALLOW_COPY_AND_ASSIGN(MacroExpander);
void getToken(Token *token);
void ungetToken(const Token &token);
bool isNextTokenLeftParen();
@ -50,14 +54,28 @@ class MacroExpander : public Lexer
struct MacroContext
{
MacroContext();
bool empty() const;
const Token &get();
void unget();
const Macro *macro;
std::size_t index;
std::vector<Token> replacements;
MacroContext()
: macro(0),
index(0)
{
}
bool empty() const
{
return index == replacements.size();
}
const Token &get()
{
return replacements[index++];
}
void unget()
{
assert(index > 0);
--index;
}
};
Lexer *mLexer;
@ -66,12 +84,6 @@ class MacroExpander : public Lexer
std::unique_ptr<Token> mReserveToken;
std::vector<MacroContext *> mContextStack;
size_t mTotalTokensInContexts;
bool mDeferReenablingMacros;
std::vector<const Macro *> mMacrosToReenable;
class ScopedMacroReenabler;
};
} // namespace pp

View file

@ -4,15 +4,16 @@
// found in the LICENSE file.
//
#include "compiler/preprocessor/Preprocessor.h"
#include "Preprocessor.h"
#include "common/debug.h"
#include "compiler/preprocessor/DiagnosticsBase.h"
#include "compiler/preprocessor/DirectiveParser.h"
#include "compiler/preprocessor/Macro.h"
#include "compiler/preprocessor/MacroExpander.h"
#include "compiler/preprocessor/Token.h"
#include "compiler/preprocessor/Tokenizer.h"
#include <cassert>
#include "DiagnosticsBase.h"
#include "DirectiveParser.h"
#include "Macro.h"
#include "MacroExpander.h"
#include "Token.h"
#include "Tokenizer.h"
namespace pp
{
@ -77,8 +78,8 @@ void Preprocessor::lex(Token *token)
// Convert preprocessing tokens to compiler tokens or report
// diagnostics.
case Token::PP_HASH:
UNREACHABLE();
break;
assert(false);
break;
case Token::PP_NUMBER:
mImpl->diagnostics->report(Diagnostics::PP_INVALID_NUMBER,
token->location, token->text);

View file

@ -7,9 +7,9 @@
#ifndef COMPILER_PREPROCESSOR_PREPROCESSOR_H_
#define COMPILER_PREPROCESSOR_PREPROCESSOR_H_
#include <cstddef>
#include <stddef.h>
#include "common/angleutils.h"
#include "pp_utils.h"
namespace pp
{
@ -19,7 +19,7 @@ class DirectiveHandler;
struct PreprocessorImpl;
struct Token;
class Preprocessor : angle::NonCopyable
class Preprocessor
{
public:
Preprocessor(Diagnostics *diagnostics, DirectiveHandler *directiveHandler);
@ -44,6 +44,8 @@ class Preprocessor : angle::NonCopyable
void setMaxTokenSize(size_t maxTokenSize);
private:
PP_DISALLOW_COPY_AND_ASSIGN(Preprocessor);
PreprocessorImpl *mImpl;
};

View file

@ -4,10 +4,11 @@
// found in the LICENSE file.
//
#include "compiler/preprocessor/Token.h"
#include "Token.h"
#include "common/debug.h"
#include "compiler/preprocessor/numeric_lex.h"
#include <cassert>
#include "numeric_lex.h"
namespace pp
{
@ -54,19 +55,19 @@ void Token::setExpansionDisabled(bool disable)
bool Token::iValue(int *value) const
{
ASSERT(type == CONST_INT);
assert(type == CONST_INT);
return numeric_lex_int(text, value);
}
bool Token::uValue(unsigned int *value) const
{
ASSERT(type == CONST_INT);
assert(type == CONST_INT);
return numeric_lex_int(text, value);
}
bool Token::fValue(float *value) const
{
ASSERT(type == CONST_FLOAT);
assert(type == CONST_FLOAT);
return numeric_lex_float(text, value);
}

View file

@ -10,7 +10,7 @@
#include <ostream>
#include <string>
#include "compiler/preprocessor/SourceLocation.h"
#include "SourceLocation.h"
namespace pp
{
@ -113,7 +113,7 @@ inline bool operator!=(const Token &lhs, const Token &rhs)
return !lhs.equals(rhs);
}
std::ostream &operator<<(std::ostream &out, const Token &token);
extern std::ostream &operator<<(std::ostream &out, const Token &token);
} // namepsace pp

File diff suppressed because it is too large Load diff

View file

@ -7,9 +7,9 @@
#ifndef COMPILER_PREPROCESSOR_TOKENIZER_H_
#define COMPILER_PREPROCESSOR_TOKENIZER_H_
#include "common/angleutils.h"
#include "compiler/preprocessor/Input.h"
#include "compiler/preprocessor/Lexer.h"
#include "Input.h"
#include "Lexer.h"
#include "pp_utils.h"
namespace pp
{
@ -45,6 +45,7 @@ class Tokenizer : public Lexer
void lex(Token *token) override;
private:
PP_DISALLOW_COPY_AND_ASSIGN(Tokenizer);
bool initScanner();
void destroyScanner();

View file

@ -27,10 +27,10 @@ IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh.
#pragma warning(disable: 4005)
#endif
#include "compiler/preprocessor/Tokenizer.h"
#include "Tokenizer.h"
#include "compiler/preprocessor/DiagnosticsBase.h"
#include "compiler/preprocessor/Token.h"
#include "DiagnosticsBase.h"
#include "Token.h"
#if defined(__GNUC__)
// Triggered by the auto-generated yy_fatal_error function.
@ -280,7 +280,9 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
namespace pp {
Tokenizer::Tokenizer(Diagnostics *diagnostics) : mHandle(nullptr), mMaxTokenSize(256)
Tokenizer::Tokenizer(Diagnostics *diagnostics)
: mHandle(0),
mMaxTokenSize(256)
{
mContext.diagnostics = diagnostics;
}
@ -337,7 +339,7 @@ void Tokenizer::lex(Token *token)
bool Tokenizer::initScanner()
{
if ((mHandle == nullptr) && yylex_init_extra(&mContext, &mHandle))
if ((mHandle == NULL) && yylex_init_extra(&mContext, &mHandle))
return false;
yyrestart(0, mHandle);
@ -346,11 +348,11 @@ bool Tokenizer::initScanner()
void Tokenizer::destroyScanner()
{
if (mHandle == nullptr)
if (mHandle == NULL)
return;
yylex_destroy(mHandle);
mHandle = nullptr;
mHandle = NULL;
}
} // namespace pp

View file

@ -9,7 +9,6 @@
#ifndef COMPILER_PREPROCESSOR_NUMERICLEX_H_
#define COMPILER_PREPROCESSOR_NUMERICLEX_H_
#include <cmath>
#include <sstream>
namespace pp {
@ -64,7 +63,7 @@ bool numeric_lex_float(const std::string &str, FloatType *value)
stream.imbue(std::locale::classic());
stream >> (*value);
return !stream.fail() && std::isfinite(*value);
return !stream.fail();
#endif
}

View file

@ -0,0 +1,18 @@
//
// 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.
//
// pp_utils.h: Common preprocessor utilities
#ifndef COMPILER_PREPROCESSOR_PPUTILS_H_
#define COMPILER_PREPROCESSOR_PPUTILS_H_
// A macro to disallow the copy constructor and operator= functions
// This must be used in the private: declarations for a class.
#define PP_DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName &); \
void operator=(const TypeName &)
#endif // COMPILER_PREPROCESSOR_PPUTILS_H_

View file

@ -1,13 +1,6 @@
diff --git a/src/compiler/translator/glslang_lex.cpp b/src/compiler/translator/glslang_lex.cpp
index 1ba63df..2a206ab 100644
--- a/src/compiler/translator/glslang_lex.cpp
+++ b/src/compiler/translator/glslang_lex.cpp
@@ -1,4 +1,3 @@
-#line 17 "./glslang.l"
//
// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
@@ -149,6 +148,7 @@ typedef int16_t flex_int16_t;
--- a/src/compiler/glslang_lex.cpp
+++ b/src/compiler/glslang_lex.cpp
@@ -68,6 +68,7 @@ typedef int16_t flex_int16_t;
typedef uint16_t flex_uint16_t;
typedef int32_t flex_int32_t;
typedef uint32_t flex_uint32_t;
@ -15,10 +8,10 @@ index 1ba63df..2a206ab 100644
#else
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
@@ -335,6 +335,11 @@ typedef size_t yy_size_t;
@@ -191,6 +192,11 @@ typedef void* yyscan_t;
typedef struct yy_buffer_state *YY_BUFFER_STATE;
#endif
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
@ -27,96 +20,21 @@ index 1ba63df..2a206ab 100644
#define EOB_ACT_CONTINUE_SCAN 0
#define EOB_ACT_END_OF_FILE 1
#define EOB_ACT_LAST_MATCH 2
@@ -351,8 +356,8 @@ typedef size_t yy_size_t;
@@ -204,7 +210,7 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE;
*/
#define YY_LESS_LINENO(n) \
do { \
- int yyl;\
- for ( yyl = n; yyl < yyleng; ++yyl )\
+ yy_size_t yyl;\
+ for ( yyl = n; yyl < static_cast<yy_site_t>(yyleng); ++yyl )\
for ( yyl = n; yyl < yyleng; ++yyl )\
if ( yytext[yyl] == '\n' )\
--yylineno;\
}while(0)
@@ -1692,7 +1697,7 @@ yy_find_action:
if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
{
yy_size_t yyl;
- for ( yyl = 0; yyl < yyleng; ++yyl )
+ for ( yyl = 0; yyl < static_cast<yy_size_t>(yyleng); ++yyl )
if ( yytext[yyl] == '\n' )
do{ yylineno++;
@@ -2655,7 +2660,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
{
int num_to_read =
- YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - static_cast<int>(number_to_move) - 1;
while ( num_to_read <= 0 )
{ /* Not enough room in the buffer - grow it. */
@@ -2690,7 +2695,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
- number_to_move - 1;
+ static_cast<int>(number_to_move) - 1;
}
@@ -2698,8 +2703,10 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
num_to_read = YY_READ_BUF_SIZE;
/* Read in more data. */
+ size_t result = 0;
YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
- yyg->yy_n_chars, num_to_read );
+ result, num_to_read );
+ yyg->yy_n_chars = static_cast<int>(result);
YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
}
@@ -2725,13 +2732,13 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
if ((int) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
/* Extend the array by 50%, plus the number we really need. */
- int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+ int new_size = yyg->yy_n_chars + static_cast<int>(number_to_move) + (yyg->yy_n_chars >> 1);
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
}
- yyg->yy_n_chars += number_to_move;
+ yyg->yy_n_chars += static_cast<int>(number_to_move);
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
@@ -3158,7 +3165,7 @@ static void yyensure_buffer_stack (yyscan_t yyscanner)
/* Increase the buffer to prepare for a possible push. */
yy_size_t grow_size = 8 /* arbitrary grow size */;
- num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
+ num_to_alloc = static_cast<int>(yyg->yy_buffer_stack_max + grow_size);
yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc
(yyg->yy_buffer_stack,
num_to_alloc * sizeof(struct yy_buffer_state*)
@@ -3196,7 +3203,7 @@ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscann
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
- b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_size = static_cast<int>(size) - 2; /* "- 2" to take care of EOB's */
b->yy_buf_pos = b->yy_ch_buf = base;
b->yy_is_our_buffer = 0;
b->yy_input_file = NULL;
@@ -3251,7 +3258,7 @@ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yysc
if ( ! buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
- for ( i = 0; i < _yybytes_len; ++i )
+ for ( i = 0; i < static_cast<yy_size_t>(_yybytes_len); ++i )
buf[i] = yybytes[i];
buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
@@ -378,7 +379,7 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
*/
#define YY_DO_BEFORE_ACTION \
yyg->yytext_ptr = yy_bp; \
- yyleng = (size_t) (yy_cp - yy_bp); \
+ yyleng = (yy_size_t) (yy_cp - yy_bp); \
yyg->yy_hold_char = *yy_cp; \
*yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp;

View file

@ -11,9 +11,6 @@
#include "compiler/translator/CallDAG.h"
#include "compiler/translator/SymbolTable.h"
namespace sh
{
namespace
{
@ -34,7 +31,7 @@ class PullGradient : public TIntermTraverser
ASSERT(index < metadataList->size());
}
void traverse(TIntermFunctionDefinition *node)
void traverse(TIntermAggregate *node)
{
node->traverse(this);
ASSERT(mParents.empty());
@ -75,9 +72,9 @@ class PullGradient : public TIntermTraverser
return true;
}
bool visitIfElse(Visit visit, TIntermIfElse *ifElse) override
bool visitSelection(Visit visit, TIntermSelection *selection) override
{
visitControlFlow(visit, ifElse);
visitControlFlow(visit, selection);
return true;
}
@ -106,8 +103,9 @@ class PullGradient : public TIntermTraverser
{
if (node->isUserDefined())
{
size_t calleeIndex = mDag.findIndex(node->getFunctionSymbolInfo());
size_t calleeIndex = mDag.findIndex(node);
ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);
UNUSED_ASSERTION_VARIABLE(mIndex);
if ((*mMetadataList)[calleeIndex].mUsesGradient) {
onGradient();
@ -115,8 +113,7 @@ class PullGradient : public TIntermTraverser
}
else
{
TString name =
TFunction::unmangleName(node->getFunctionSymbolInfo()->getName());
TString name = TFunction::unmangleName(node->getName());
if (name == "texture2D" ||
name == "texture2DProj" ||
@ -160,7 +157,7 @@ class PullComputeDiscontinuousAndGradientLoops : public TIntermTraverser
{
}
void traverse(TIntermFunctionDefinition *node)
void traverse(TIntermAggregate *node)
{
node->traverse(this);
ASSERT(mLoopsAndSwitches.empty());
@ -199,7 +196,7 @@ class PullComputeDiscontinuousAndGradientLoops : public TIntermTraverser
return true;
}
bool visitIfElse(Visit visit, TIntermIfElse *node) override
bool visitSelection(Visit visit, TIntermSelection *node) override
{
if (visit == PreVisit)
{
@ -278,8 +275,9 @@ class PullComputeDiscontinuousAndGradientLoops : public TIntermTraverser
{
if (node->isUserDefined())
{
size_t calleeIndex = mDag.findIndex(node->getFunctionSymbolInfo());
size_t calleeIndex = mDag.findIndex(node);
ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);
UNUSED_ASSERTION_VARIABLE(mIndex);
if ((*mMetadataList)[calleeIndex].mHasGradientLoopInCallGraph)
{
@ -312,7 +310,7 @@ class PullComputeDiscontinuousAndGradientLoops : public TIntermTraverser
const CallDAG &mDag;
std::vector<TIntermNode*> mLoopsAndSwitches;
std::vector<TIntermIfElse *> mIfs;
std::vector<TIntermSelection*> mIfs;
};
// Tags all the functions called in a discontinuous loop
@ -329,7 +327,7 @@ class PushDiscontinuousLoops : public TIntermTraverser
{
}
void traverse(TIntermFunctionDefinition *node)
void traverse(TIntermAggregate *node)
{
node->traverse(this);
ASSERT(mNestedDiscont == (mMetadata->mCalledInDiscontinuousLoop ? 1 : 0));
@ -358,8 +356,9 @@ class PushDiscontinuousLoops : public TIntermTraverser
case EOpFunctionCall:
if (visit == PreVisit && node->isUserDefined() && mNestedDiscont > 0)
{
size_t calleeIndex = mDag.findIndex(node->getFunctionSymbolInfo());
size_t calleeIndex = mDag.findIndex(node);
ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);
UNUSED_ASSERTION_VARIABLE(mIndex);
(*mMetadataList)[calleeIndex].mCalledInDiscontinuousLoop = true;
}
@ -386,7 +385,7 @@ bool ASTMetadataHLSL::hasGradientInCallGraph(TIntermLoop *node)
return mControlFlowsContainingGradient.count(node) > 0;
}
bool ASTMetadataHLSL::hasGradientLoop(TIntermIfElse *node)
bool ASTMetadataHLSL::hasGradientLoop(TIntermSelection *node)
{
return mIfsContainingGradientLoop.count(node) > 0;
}
@ -450,5 +449,3 @@ MetadataList CreateASTMetadataHLSL(TIntermNode *root, const CallDAG &callDag)
return metadataList;
}
} // namespace sh

View file

@ -12,12 +12,9 @@
#include <set>
#include <vector>
namespace sh
{
class CallDAG;
class TIntermNode;
class TIntermIfElse;
class TIntermSelection;
class TIntermLoop;
struct ASTMetadataHLSL
@ -33,7 +30,7 @@ struct ASTMetadataHLSL
// Here "something uses a gradient" means here that it either contains a
// gradient operation, or a call to a function that uses a gradient.
bool hasGradientInCallGraph(TIntermLoop *node);
bool hasGradientLoop(TIntermIfElse *node);
bool hasGradientLoop(TIntermSelection *node);
// Does the function use a gradient.
bool mUsesGradient;
@ -47,7 +44,7 @@ struct ASTMetadataHLSL
bool mCalledInDiscontinuousLoop;
bool mHasGradientLoopInCallGraph;
std::set<TIntermLoop*> mDiscontinuousLoops;
std::set<TIntermIfElse *> mIfsContainingGradientLoop;
std::set<TIntermSelection *> mIfsContainingGradientLoop;
// Will we need to generate a Lod0 version of the function.
bool mNeedsLod0;
@ -58,6 +55,4 @@ typedef std::vector<ASTMetadataHLSL> MetadataList;
// Return the AST analysis result, in the order defined by the call DAG
MetadataList CreateASTMetadataHLSL(TIntermNode *root, const CallDAG &callDag);
} // namespace sh
#endif // COMPILER_TRANSLATOR_ASTMETADATAHLSL_H_

View file

@ -1,59 +0,0 @@
//
// Copyright (c) 2016 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/AddAndTrueToLoopCondition.h"
#include "compiler/translator/IntermNode.h"
namespace sh
{
namespace
{
// An AST traverser that rewrites for and while loops by replacing "condition" with
// "condition && true" to work around condition bug on Intel Mac.
class AddAndTrueToLoopConditionTraverser : public TIntermTraverser
{
public:
AddAndTrueToLoopConditionTraverser() : TIntermTraverser(true, false, false) {}
bool visitLoop(Visit, TIntermLoop *loop) override
{
// do-while loop doesn't have this bug.
if (loop->getType() != ELoopFor && loop->getType() != ELoopWhile)
{
return true;
}
// For loop may not have a condition.
if (loop->getCondition() == nullptr)
{
return true;
}
// Constant true.
TConstantUnion *trueConstant = new TConstantUnion();
trueConstant->setBConst(true);
TIntermTyped *trueValue = new TIntermConstantUnion(trueConstant, TType(EbtBool));
// CONDITION && true.
TIntermBinary *andOp = new TIntermBinary(EOpLogicalAnd, loop->getCondition(), trueValue);
loop->setCondition(andOp);
return true;
}
};
} // anonymous namespace
void AddAndTrueToLoopCondition(TIntermNode *root)
{
AddAndTrueToLoopConditionTraverser traverser;
root->traverse(&traverser);
}
} // namespace sh

View file

@ -1,20 +0,0 @@
//
// Copyright (c) 2016 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.
//
// Rewrite condition in for and while loops to work around driver bug on Intel Mac.
#ifndef COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_
#define COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_
class TIntermNode;
namespace sh
{
void AddAndTrueToLoopCondition(TIntermNode *root);
} // namespace sh
#endif // COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_

View file

@ -31,16 +31,21 @@ class AddDefaultReturnStatementsTraverser : private TIntermTraverser
private:
AddDefaultReturnStatementsTraverser() : TIntermTraverser(true, false, false) {}
static bool IsFunctionWithoutReturnStatement(TIntermFunctionDefinition *node, TType *returnType)
static bool IsFunctionWithoutReturnStatement(TIntermAggregate *node, TType *returnType)
{
*returnType = node->getType();
if (node->getType().getBasicType() == EbtVoid)
if (node->getOp() != EOpFunction || node->getType().getBasicType() == EbtVoid)
{
return false;
}
TIntermBlock *bodyNode = node->getBody();
TIntermBranch *returnNode = bodyNode->getSequence()->back()->getAsBranchNode();
TIntermAggregate *lastNode = node->getSequence()->back()->getAsAggregate();
if (lastNode == nullptr)
{
return true;
}
TIntermBranch *returnNode = lastNode->getSequence()->front()->getAsBranchNode();
if (returnNode != nullptr && returnNode->getFlowOp() == EOpReturn)
{
return false;
@ -49,16 +54,51 @@ class AddDefaultReturnStatementsTraverser : private TIntermTraverser
return true;
}
bool visitFunctionDefinition(Visit, TIntermFunctionDefinition *node) override
static TIntermTyped *GenerateTypeConstructor(const TType &returnType)
{
// Base case, constructing a single element
if (!returnType.isArray())
{
size_t objectSize = returnType.getObjectSize();
TConstantUnion *constantUnion = new TConstantUnion[objectSize];
for (size_t constantIdx = 0; constantIdx < objectSize; constantIdx++)
{
constantUnion[constantIdx].setFConst(0.0f);
}
TIntermConstantUnion *intermConstantUnion =
new TIntermConstantUnion(constantUnion, returnType);
return intermConstantUnion;
}
// Recursive case, construct an array of single elements
TIntermAggregate *constructorAggrigate =
new TIntermAggregate(TypeToConstructorOperator(returnType));
constructorAggrigate->setType(returnType);
size_t arraySize = returnType.getArraySize();
for (size_t arrayIdx = 0; arrayIdx < arraySize; arrayIdx++)
{
TType arrayElementType(returnType);
arrayElementType.clearArrayness();
constructorAggrigate->getSequence()->push_back(
GenerateTypeConstructor(arrayElementType));
}
return constructorAggrigate;
}
bool visitAggregate(Visit, TIntermAggregate *node) override
{
TType returnType;
if (IsFunctionWithoutReturnStatement(node, &returnType))
{
TIntermBranch *branch =
new TIntermBranch(EOpReturn, TIntermTyped::CreateZero(returnType));
new TIntermBranch(EOpReturn, GenerateTypeConstructor(returnType));
TIntermBlock *bodyNode = node->getBody();
bodyNode->getSequence()->push_back(branch);
TIntermAggregate *lastNode = node->getSequence()->back()->getAsAggregate();
lastNode->getSequence()->push_back(branch);
return false;
}

View file

@ -10,9 +10,6 @@
#include "compiler/translator/IntermNode.h"
namespace sh
{
namespace
{
@ -44,7 +41,8 @@ TIntermAggregate *CreateReplacementCall(TIntermAggregate *originalCall, TIntermT
TIntermAggregate *replacementCall = new TIntermAggregate(EOpFunctionCall);
replacementCall->setType(TType(EbtVoid));
replacementCall->setUserDefined();
*replacementCall->getFunctionSymbolInfo() = *originalCall->getFunctionSymbolInfo();
replacementCall->setNameObj(originalCall->getNameObj());
replacementCall->setFunctionId(originalCall->getFunctionId());
replacementCall->setLine(originalCall->getLine());
TIntermSequence *replacementParameters = replacementCall->getSequence();
TIntermSequence *originalParameters = originalCall->getSequence();
@ -63,7 +61,6 @@ class ArrayReturnValueToOutParameterTraverser : private TIntermTraverser
private:
ArrayReturnValueToOutParameterTraverser();
bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
bool visitBranch(Visit visit, TIntermBranch *node) override;
bool visitBinary(Visit visit, TIntermBinary *node) override;
@ -85,47 +82,35 @@ ArrayReturnValueToOutParameterTraverser::ArrayReturnValueToOutParameterTraverser
{
}
bool ArrayReturnValueToOutParameterTraverser::visitFunctionDefinition(
Visit visit,
TIntermFunctionDefinition *node)
{
if (node->isArray() && visit == PreVisit)
{
// Replace the parameters child node of the function definition with another node
// that has the out parameter added.
// Also set the function to return void.
TIntermAggregate *params = node->getFunctionParameters();
ASSERT(params != nullptr && params->getOp() == EOpParameters);
TIntermAggregate *replacementParams = new TIntermAggregate;
replacementParams->setOp(EOpParameters);
CopyAggregateChildren(params, replacementParams);
replacementParams->getSequence()->push_back(CreateReturnValueOutSymbol(node->getType()));
replacementParams->setLine(params->getLine());
queueReplacementWithParent(node, params, replacementParams, OriginalNode::IS_DROPPED);
node->setType(TType(EbtVoid));
mInFunctionWithArrayReturnValue = true;
}
if (visit == PostVisit)
{
// This isn't conditional on node->isArray() since the type has already been changed on
// PreVisit.
mInFunctionWithArrayReturnValue = false;
}
return true;
}
bool ArrayReturnValueToOutParameterTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
{
if (visit == PreVisit)
{
if (node->isArray())
{
if (node->getOp() == EOpPrototype)
if (node->getOp() == EOpFunction)
{
// Replace the parameters child node of the function definition with another node
// that has the out parameter added.
// Also set the function to return void.
TIntermAggregate *params = node->getSequence()->front()->getAsAggregate();
ASSERT(params != nullptr && params->getOp() == EOpParameters);
TIntermAggregate *replacementParams = new TIntermAggregate;
replacementParams->setOp(EOpParameters);
CopyAggregateChildren(params, replacementParams);
replacementParams->getSequence()->push_back(CreateReturnValueOutSymbol(node->getType()));
replacementParams->setLine(params->getLine());
queueReplacementWithParent(node, params, replacementParams,
OriginalNode::IS_DROPPED);
node->setType(TType(EbtVoid));
mInFunctionWithArrayReturnValue = true;
}
else if (node->getOp() == EOpPrototype)
{
// Replace the whole prototype node with another node that has the out parameter added.
TIntermAggregate *replacement = new TIntermAggregate;
@ -133,7 +118,8 @@ bool ArrayReturnValueToOutParameterTraverser::visitAggregate(Visit visit, TInter
CopyAggregateChildren(node, replacement);
replacement->getSequence()->push_back(CreateReturnValueOutSymbol(node->getType()));
replacement->setUserDefined();
*replacement->getFunctionSymbolInfo() = *node->getFunctionSymbolInfo();
replacement->setNameObj(node->getNameObj());
replacement->setFunctionId(node->getFunctionId());
replacement->setLine(node->getLine());
replacement->setType(TType(EbtVoid));
@ -150,21 +136,27 @@ bool ArrayReturnValueToOutParameterTraverser::visitAggregate(Visit visit, TInter
// Cases 2 to 4 are already converted to simpler cases by SeparateExpressionsReturningArrays, so we
// only need to worry about the case where a function call returning an array forms an expression by
// itself.
TIntermBlock *parentBlock = getParentNode()->getAsBlock();
if (parentBlock)
TIntermAggregate *parentAgg = getParentNode()->getAsAggregate();
if (parentAgg != nullptr && parentAgg->getOp() == EOpSequence)
{
nextTemporaryIndex();
TIntermSequence replacements;
replacements.push_back(createTempDeclaration(node->getType()));
TIntermSymbol *returnSymbol = createTempSymbol(node->getType());
replacements.push_back(CreateReplacementCall(node, returnSymbol));
mMultiReplacements.push_back(
NodeReplaceWithMultipleEntry(parentBlock, node, replacements));
mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(parentAgg, node, replacements));
}
return false;
}
}
}
else if (visit == PostVisit)
{
if (node->getOp() == EOpFunction)
{
mInFunctionWithArrayReturnValue = false;
}
}
return true;
}
@ -175,11 +167,12 @@ bool ArrayReturnValueToOutParameterTraverser::visitBranch(Visit visit, TIntermBr
// Instead of returning a value, assign to the out parameter and then return.
TIntermSequence replacements;
TIntermBinary *replacementAssignment = new TIntermBinary(EOpAssign);
TIntermTyped *expression = node->getExpression();
ASSERT(expression != nullptr);
TIntermSymbol *returnValueSymbol = CreateReturnValueSymbol(expression->getType());
TIntermBinary *replacementAssignment =
new TIntermBinary(EOpAssign, returnValueSymbol, expression);
replacementAssignment->setLeft(CreateReturnValueSymbol(expression->getType()));
replacementAssignment->setRight(node->getExpression());
replacementAssignment->setType(expression->getType());
replacementAssignment->setLine(expression->getLine());
replacements.push_back(replacementAssignment);
@ -187,8 +180,7 @@ bool ArrayReturnValueToOutParameterTraverser::visitBranch(Visit visit, TIntermBr
replacementBranch->setLine(node->getLine());
replacements.push_back(replacementBranch);
mMultiReplacements.push_back(
NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), node, replacements));
mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(getParentNode()->getAsAggregate(), node, replacements));
}
return false;
}
@ -213,5 +205,3 @@ void ArrayReturnValueToOutParameter(TIntermNode *root, unsigned int *temporaryIn
{
ArrayReturnValueToOutParameterTraverser::apply(root, temporaryIndex);
}
} // namespace sh

View file

@ -9,11 +9,8 @@
#ifndef COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
#define COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
namespace sh
{
class TIntermNode;
void ArrayReturnValueToOutParameter(TIntermNode *root, unsigned int *temporaryIndex);
} // namespace sh
#endif // COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_

View file

@ -13,9 +13,6 @@
#include "common/debug.h"
#include "GLSLANG/ShaderLang.h"
namespace sh
{
//
// Precision qualifiers
//
@ -35,10 +32,10 @@ inline const char* getPrecisionString(TPrecision p)
{
switch(p)
{
case EbpHigh: return "highp";
case EbpMedium: return "mediump";
case EbpLow: return "lowp";
default: return "mediump"; // Safest fallback
case EbpHigh: return "highp"; break;
case EbpMedium: return "mediump"; break;
case EbpLow: return "lowp"; break;
default: return "mediump"; break; // Safest fallback
}
}
@ -79,98 +76,19 @@ enum TBasicType
EbtSampler2DShadow,
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
// images
EbtGuardImageBegin,
EbtImage2D,
EbtIImage2D,
EbtUImage2D,
EbtImage3D,
EbtIImage3D,
EbtUImage3D,
EbtImage2DArray,
EbtIImage2DArray,
EbtUImage2DArray,
EbtImageCube,
EbtIImageCube,
EbtUImageCube,
EbtGuardImageEnd,
EbtGuardGImageBegin,
EbtGImage2D, // non type: represents image2D, uimage2D, iimage2D
EbtGImage3D, // non type: represents image3D, uimage3D, iimage3D
EbtGImage2DArray, // non type: represents image2DArray, uimage2DArray, iimage2DArray
EbtGImageCube, // non type: represents imageCube, uimageCube, iimageCube
EbtGuardGImageEnd,
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
EbtStruct,
EbtInterfaceBlock,
EbtAddress, // should be deprecated??
EbtAddress, // should be deprecated??
// end of list
EbtLast
};
inline TBasicType convertGImageToFloatImage(TBasicType type)
{
switch (type)
{
case EbtGImage2D:
return EbtImage2D;
case EbtGImage3D:
return EbtImage3D;
case EbtGImage2DArray:
return EbtImage2DArray;
case EbtGImageCube:
return EbtImageCube;
default:
UNREACHABLE();
}
return EbtLast;
}
inline TBasicType convertGImageToIntImage(TBasicType type)
{
switch (type)
{
case EbtGImage2D:
return EbtIImage2D;
case EbtGImage3D:
return EbtIImage3D;
case EbtGImage2DArray:
return EbtIImage2DArray;
case EbtGImageCube:
return EbtIImageCube;
default:
UNREACHABLE();
}
return EbtLast;
}
inline TBasicType convertGImageToUnsignedImage(TBasicType type)
{
switch (type)
{
case EbtGImage2D:
return EbtUImage2D;
case EbtGImage3D:
return EbtUImage3D;
case EbtGImage2DArray:
return EbtUImage2DArray;
case EbtGImageCube:
return EbtUImageCube;
default:
UNREACHABLE();
}
return EbtLast;
}
const char* getBasicString(TBasicType t);
inline bool IsSampler(TBasicType type)
@ -178,22 +96,6 @@ inline bool IsSampler(TBasicType type)
return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd;
}
inline bool IsImage(TBasicType type)
{
return type > EbtGuardImageBegin && type < EbtGuardImageEnd;
}
inline bool IsGImage(TBasicType type)
{
return type > EbtGuardGImageBegin && type < EbtGuardGImageEnd;
}
inline bool IsOpaqueType(TBasicType type)
{
// TODO (mradev): add atomic types as opaque.
return IsSampler(type) || IsImage(type);
}
inline bool IsIntegerSampler(TBasicType type)
{
switch (type)
@ -224,56 +126,6 @@ inline bool IsIntegerSampler(TBasicType type)
return false;
}
inline bool IsFloatImage(TBasicType type)
{
switch (type)
{
case EbtImage2D:
case EbtImage3D:
case EbtImage2DArray:
case EbtImageCube:
return true;
default:
break;
}
return false;
}
inline bool IsIntegerImage(TBasicType type)
{
switch (type)
{
case EbtIImage2D:
case EbtIImage3D:
case EbtIImage2DArray:
case EbtIImageCube:
return true;
default:
break;
}
return false;
}
inline bool IsUnsignedImage(TBasicType type)
{
switch (type)
{
case EbtUImage2D:
case EbtUImage3D:
case EbtUImage2DArray:
case EbtUImageCube:
return true;
default:
break;
}
return false;
}
inline bool IsSampler2D(TBasicType type)
{
switch (type)
@ -431,7 +283,7 @@ inline bool IsInteger(TBasicType type)
inline bool SupportsPrecision(TBasicType type)
{
return type == EbtFloat || type == EbtInt || type == EbtUInt || IsOpaqueType(type);
return type == EbtFloat || type == EbtInt || type == EbtUInt || IsSampler(type);
}
//
@ -489,11 +341,10 @@ enum TQualifier
EvqLastFragData,
// GLSL ES 3.0 vertex output and fragment input
EvqSmooth, // Incomplete qualifier, smooth is the default
EvqFlat, // Incomplete qualifier
EvqCentroid, // Incomplete qualifier
EvqSmoothOut,
EvqFlatOut,
EvqSmooth, // Incomplete qualifier, smooth is the default
EvqFlat, // Incomplete qualifier
EvqSmoothOut = EvqSmooth,
EvqFlatOut = EvqFlat,
EvqCentroidOut, // Implies smooth
EvqSmoothIn,
EvqFlatIn,
@ -508,40 +359,10 @@ enum TQualifier
EvqGlobalInvocationID,
EvqLocalInvocationIndex,
// GLSL ES 3.1 memory qualifiers
EvqReadOnly,
EvqWriteOnly,
EvqCoherent,
EvqRestrict,
EvqVolatile,
// end of list
EvqLast
};
inline bool IsQualifierUnspecified(TQualifier qualifier)
{
return (qualifier == EvqTemporary || qualifier == EvqGlobal);
}
enum TLayoutImageInternalFormat
{
EiifUnspecified,
EiifRGBA32F,
EiifRGBA16F,
EiifR32F,
EiifRGBA32UI,
EiifRGBA16UI,
EiifRGBA8UI,
EiifR32UI,
EiifRGBA32I,
EiifRGBA16I,
EiifRGBA8I,
EiifR32I,
EiifRGBA8,
EiifRGBA8_SNORM
};
enum TLayoutMatrixPacking
{
EmpUnspecified,
@ -560,44 +381,36 @@ enum TLayoutBlockStorage
struct TLayoutQualifier
{
int location;
unsigned int locationsSpecified;
TLayoutMatrixPacking matrixPacking;
TLayoutBlockStorage blockStorage;
// Compute shader layout qualifiers.
sh::WorkGroupSize localSize;
// Image format layout qualifier
TLayoutImageInternalFormat imageInternalFormat;
static TLayoutQualifier create()
{
TLayoutQualifier layoutQualifier;
layoutQualifier.location = -1;
layoutQualifier.locationsSpecified = 0;
layoutQualifier.matrixPacking = EmpUnspecified;
layoutQualifier.blockStorage = EbsUnspecified;
layoutQualifier.localSize.fill(-1);
layoutQualifier.imageInternalFormat = EiifUnspecified;
return layoutQualifier;
}
bool isEmpty() const
{
return location == -1 && matrixPacking == EmpUnspecified &&
blockStorage == EbsUnspecified && !localSize.isAnyValueSet() &&
imageInternalFormat == EiifUnspecified;
blockStorage == EbsUnspecified && !localSize.isAnyValueSet();
}
bool isCombinationValid() const
{
bool workSizeSpecified = localSize.isAnyValueSet();
bool otherLayoutQualifiersSpecified =
(location != -1 || matrixPacking != EmpUnspecified || blockStorage != EbsUnspecified ||
imageInternalFormat != EiifUnspecified);
(location != -1 || matrixPacking != EmpUnspecified || blockStorage != EbsUnspecified);
// we can have either the work group size specified, or the other layout qualifiers
return !(workSizeSpecified && otherLayoutQualifiersSpecified);
@ -609,37 +422,6 @@ struct TLayoutQualifier
}
};
struct TMemoryQualifier
{
// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
// An image can be qualified as both readonly and writeonly. It still can be can be used with
// imageSize().
bool readonly;
bool writeonly;
bool coherent;
// restrict and volatile are reserved keywords in C/C++
bool restrictQualifier;
bool volatileQualifier;
static TMemoryQualifier create()
{
TMemoryQualifier memoryQualifier;
memoryQualifier.readonly = false;
memoryQualifier.writeonly = false;
memoryQualifier.coherent = false;
memoryQualifier.restrictQualifier = false;
memoryQualifier.volatileQualifier = false;
return memoryQualifier;
}
bool isEmpty()
{
return !readonly && !writeonly && !coherent && !restrictQualifier && !volatileQualifier;
}
};
inline const char *getWorkGroupSizeString(size_t dimension)
{
switch (dimension)
@ -700,9 +482,6 @@ inline const char* getQualifierString(TQualifier q)
case EvqSmoothIn: return "smooth in";
case EvqFlatIn: return "flat in";
case EvqCentroidIn: return "smooth centroid in";
case EvqCentroid: return "centroid";
case EvqFlat: return "flat";
case EvqSmooth: return "smooth";
case EvqComputeIn: return "in";
case EvqNumWorkGroups: return "NumWorkGroups";
case EvqWorkGroupSize: return "WorkGroupSize";
@ -710,8 +489,6 @@ inline const char* getQualifierString(TQualifier q)
case EvqLocalInvocationID: return "LocalInvocationID";
case EvqGlobalInvocationID: return "GlobalInvocationID";
case EvqLocalInvocationIndex: return "LocalInvocationIndex";
case EvqReadOnly: return "readonly";
case EvqWriteOnly: return "writeonly";
default: UNREACHABLE(); return "unknown qualifier";
}
// clang-format on
@ -740,42 +517,18 @@ inline const char* getBlockStorageString(TLayoutBlockStorage bsq)
}
}
inline const char *getImageInternalFormatString(TLayoutImageInternalFormat iifq)
inline const char* getInterpolationString(TQualifier q)
{
switch (iifq)
switch(q)
{
case EiifRGBA32F:
return "rgba32f";
case EiifRGBA16F:
return "rgba16f";
case EiifR32F:
return "r32f";
case EiifRGBA32UI:
return "rgba32ui";
case EiifRGBA16UI:
return "rgba16ui";
case EiifRGBA8UI:
return "rgba8ui";
case EiifR32UI:
return "r32ui";
case EiifRGBA32I:
return "rgba32i";
case EiifRGBA16I:
return "rgba16i";
case EiifRGBA8I:
return "rgba8i";
case EiifR32I:
return "r32i";
case EiifRGBA8:
return "rgba8";
case EiifRGBA8_SNORM:
return "rgba8_snorm";
default:
UNREACHABLE();
return "unknown internal image format";
case EvqSmoothOut: return "smooth"; break;
case EvqCentroidOut: return "smooth centroid"; break;
case EvqFlatOut: return "flat"; break;
case EvqSmoothIn: return "smooth"; break;
case EvqCentroidIn: return "smooth centroid"; break;
case EvqFlatIn: return "flat"; break;
default: UNREACHABLE(); return "unknown interpolation";
}
}
} // namespace sh
#endif // COMPILER_TRANSLATOR_BASETYPES_H_

View file

@ -1,106 +0,0 @@
//
// Copyright (c) 2016 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.
//
// BreakVariableAliasingInInnerLoops.h: To optimize simple assignments, the HLSL compiler frontend
// may record a variable as aliasing another. Sometimes the alias information gets garbled
// so we work around this issue by breaking the aliasing chain in inner loops.
#include "BreakVariableAliasingInInnerLoops.h"
#include "compiler/translator/IntermNode.h"
// A HLSL compiler developer gave us more details on the root cause and the workaround needed:
// The root problem is that if the HLSL compiler is applying aliasing information even on
// incomplete simulations (in this case, a single pass). The bug is triggered by an assignment
// that comes from a series of assignments, possibly with swizzled or ternary operators with
// known conditionals, where the source is before the loop.
// So, a workaround is to add a +0 term to variables the first time they are assigned to in
// an inner loop (if they are declared in an outside scope, otherwise there is no need).
// This will break the aliasing chain.
// For simplicity here we add a +0 to any assignment that is in at least two nested loops. Because
// the bug only shows up with swizzles, and ternary assignment, whole array or whole structure
// assignment don't need a workaround.
namespace sh
{
namespace
{
class AliasingBreaker : public TIntermTraverser
{
public:
AliasingBreaker() : TIntermTraverser(true, false, true) {}
protected:
bool visitBinary(Visit visit, TIntermBinary *binary)
{
if (visit != PreVisit)
{
return false;
}
if (mLoopLevel < 2 || !binary->isAssignment())
{
return true;
}
TIntermTyped *B = binary->getRight();
TType type = B->getType();
if (!type.isScalar() && !type.isVector() && !type.isMatrix())
{
return true;
}
if (type.isArray() || IsSampler(type.getBasicType()))
{
return true;
}
// We have a scalar / vector / matrix assignment with loop depth 2.
// Transform it from
// A = B
// to
// A = (B + typeof<B>(0));
TIntermBinary *bPlusZero = new TIntermBinary(EOpAdd, B, TIntermTyped::CreateZero(type));
bPlusZero->setLine(B->getLine());
binary->replaceChildNode(B, bPlusZero);
return true;
}
bool visitLoop(Visit visit, TIntermLoop *loop)
{
if (visit == PreVisit)
{
mLoopLevel++;
}
else
{
ASSERT(mLoopLevel > 0);
mLoopLevel--;
}
return true;
}
private:
int mLoopLevel = 0;
};
} // anonymous namespace
void BreakVariableAliasingInInnerLoops(TIntermNode *root)
{
AliasingBreaker breaker;
root->traverse(&breaker);
}
} // namespace sh

View file

@ -1,23 +0,0 @@
//
// Copyright (c) 2016 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.
//
// BreakVariableAliasingInInnerLoops.h: To optimize simple assignments, the HLSL compiler frontend
// may record a variable as aliasing another. Sometimes the alias information gets garbled
// so we work around this issue by breaking the aliasing chain in inner loops.
#ifndef COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_
#define COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_
class TIntermNode;
namespace sh
{
void BreakVariableAliasingInInnerLoops(TIntermNode *root);
} // namespace sh
#endif // COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_

View file

@ -9,9 +9,6 @@
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/Cache.h"
namespace sh
{
class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTraverser
{
public:
@ -245,5 +242,3 @@ BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::FunctionId::getCopy
{
return FunctionId(mOp, new TType(*mParam1), new TType(*mParam2), new TType(*mParam3));
}
} // namespace sh

View file

@ -10,9 +10,6 @@
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h"
namespace sh
{
//
// This class decides which built-in functions need to be replaced with the
// emulated ones.
@ -85,6 +82,4 @@ class BuiltInFunctionEmulator
std::vector<FunctionId> mFunctions;
};
} // namespace sh
#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_

View file

@ -11,68 +11,32 @@
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/VersionGLSL.h"
namespace sh
void InitBuiltInFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, sh::GLenum shaderType)
{
void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
sh::GLenum shaderType)
{
if (shaderType == GL_VERTEX_SHADER)
{
const TType *int1 = TCache::getType(EbtInt);
emu->addEmulatedFunction(EOpAbs, int1, "int webgl_abs_emu(int x) { return x * sign(x); }");
}
}
void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
int targetGLSLVersion)
{
// isnan() is supported since GLSL 1.3.
if (targetGLSLVersion < GLSL_VERSION_130)
return;
// 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 TType *float1 = TCache::getType(EbtFloat);
const TType *float2 = TCache::getType(EbtFloat, 2);
const TType *float3 = TCache::getType(EbtFloat, 3);
const TType *float4 = TCache::getType(EbtFloat, 4);
// !(x > 0.0 || x < 0.0 || x == 0.0) will be optimized and always equal to false.
emu->addEmulatedFunction(
EOpIsNan, float1,
"bool webgl_isnan_emu(float x) { return (x > 0.0 || x < 0.0) ? false : x != 0.0; }");
emu->addEmulatedFunction(
EOpIsNan, float2,
"bvec2 webgl_isnan_emu(vec2 x)\n"
"{\n"
" bvec2 isnan;\n"
" for (int i = 0; i < 2; i++)\n"
" {\n"
" isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
" }\n"
" return isnan;\n"
"}\n");
emu->addEmulatedFunction(
EOpIsNan, float3,
"bvec3 webgl_isnan_emu(vec3 x)\n"
"{\n"
" bvec3 isnan;\n"
" for (int i = 0; i < 3; i++)\n"
" {\n"
" isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
" }\n"
" return isnan;\n"
"}\n");
emu->addEmulatedFunction(
EOpIsNan, float4,
"bvec4 webgl_isnan_emu(vec4 x)\n"
"{\n"
" bvec4 isnan;\n"
" for (int i = 0; i < 4; i++)\n"
" {\n"
" isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
" }\n"
" return isnan;\n"
"}\n");
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))");
emu->addEmulatedFunction(EOpFaceForward, float1, float1, float1, "#define webgl_faceforward_emu(N, I, Nref) (((Nref) * (I) < 0.0) ? (N) : -(N))");
}
// Emulate built-in functions missing from GLSL 1.30 and higher
@ -217,9 +181,7 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
" float scale;\n"
" if(exponent < 0)\n"
" {\n"
" // The negative unary operator is buggy on OSX.\n"
" // Work around this by using abs instead.\n"
" scale = 1.0 / (1 << abs(exponent));\n"
" scale = 1.0 / (1 << -exponent);\n"
" }\n"
" else\n"
" {\n"
@ -251,5 +213,3 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
// clang-format on
}
}
} // namespace sh

View file

@ -9,27 +9,17 @@
#include "GLSLANG/ShaderLang.h"
namespace sh
{
class BuiltInFunctionEmulator;
//
// This works around bug in Intel Mac drivers.
// This is only a workaround for OpenGL driver bugs, and isn't needed in general.
//
void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
sh::GLenum shaderType);
//
// This works around isnan() bug in Intel Mac drivers
//
void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
int targetGLSLVersion);
void InitBuiltInFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, sh::GLenum shaderType);
//
// This function is emulating built-in functions missing from GLSL 1.30 and higher.
//
void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator *emu, sh::GLenum shaderType,
int targetGLSLVersion);
} // namespace sh
#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_

View file

@ -8,62 +8,6 @@
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/VersionGLSL.h"
namespace sh
{
void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu,
int targetGLSLVersion)
{
if (targetGLSLVersion < GLSL_VERSION_130)
return;
TType *float1 = new TType(EbtFloat);
TType *float2 = new TType(EbtFloat, 2);
TType *float3 = new TType(EbtFloat, 3);
TType *float4 = new TType(EbtFloat, 4);
emu->addEmulatedFunction(EOpIsNan, float1,
"bool webgl_isnan_emu(float x)\n"
"{\n"
" return (x > 0.0 || x < 0.0) ? false : x != 0.0;\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpIsNan, float2,
"bool2 webgl_isnan_emu(float2 x)\n"
"{\n"
" bool2 isnan;\n"
" for (int i = 0; i < 2; i++)\n"
" {\n"
" isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
" }\n"
" return isnan;\n"
"}\n");
emu->addEmulatedFunction(EOpIsNan, float3,
"bool3 webgl_isnan_emu(float3 x)\n"
"{\n"
" bool3 isnan;\n"
" for (int i = 0; i < 3; i++)\n"
" {\n"
" isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
" }\n"
" return isnan;\n"
"}\n");
emu->addEmulatedFunction(EOpIsNan, float4,
"bool4 webgl_isnan_emu(float4 x)\n"
"{\n"
" bool4 isnan;\n"
" for (int i = 0; i < 4; i++)\n"
" {\n"
" isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
" }\n"
" return isnan;\n"
"}\n");
}
void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
{
@ -495,5 +439,3 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
"}\n");
}
} // namespace sh

View file

@ -9,19 +9,8 @@
#include "GLSLANG/ShaderLang.h"
namespace sh
{
class BuiltInFunctionEmulator;
void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu);
//
// This works around isnan() bug on some Intel drivers.
//
void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu,
int targetGLSLVersion);
} // namespace sh
#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_

View file

@ -12,9 +12,6 @@
#include "common/debug.h"
#include "compiler/translator/Cache.h"
namespace sh
{
namespace
{
@ -47,6 +44,7 @@ TCache::TypeKey::TypeKey(TBasicType basicType,
"TypeKey::value is too small");
const size_t MaxEnumValue = std::numeric_limits<EnumComponentType>::max();
UNUSED_ASSERTION_VARIABLE(MaxEnumValue);
// TODO: change to static_assert() once we deprecate MSVC 2013 support
ASSERT(MaxEnumValue >= EbtLast &&
@ -100,5 +98,3 @@ const TType *TCache::getType(TBasicType basicType,
return type;
}
} // namespace sh

View file

@ -16,9 +16,6 @@
#include "compiler/translator/Types.h"
#include "compiler/translator/PoolAlloc.h"
namespace sh
{
class TCache
{
public:
@ -90,6 +87,4 @@ class TCache
static TCache *sCache;
};
} // namespace sh
#endif // COMPILER_TRANSLATOR_CACHE_H_

View file

@ -11,9 +11,6 @@
#include "compiler/translator/CallDAG.h"
#include "compiler/translator/InfoSink.h"
namespace sh
{
// The CallDAGCreator does all the processing required to create the CallDAG
// structure so that the latter contains only the necessary variables.
class CallDAG::CallDAGCreator : public TIntermTraverser
@ -47,7 +44,6 @@ class CallDAG::CallDAGCreator : public TIntermTraverser
skipped++;
}
}
ASSERT(mFunctions.size() == mCurrentIndex + skipped);
return INITDAG_SUCCESS;
}
@ -79,8 +75,7 @@ class CallDAG::CallDAGCreator : public TIntermTraverser
record.callees.push_back(static_cast<int>(callee->index));
}
(*idToIndex)[data.node->getFunctionSymbolInfo()->getId()] =
static_cast<int>(data.index);
(*idToIndex)[data.node->getFunctionId()] = static_cast<int>(data.index);
}
}
@ -97,39 +92,13 @@ class CallDAG::CallDAGCreator : public TIntermTraverser
}
std::set<CreatorFunctionData*> callees;
TIntermFunctionDefinition *node;
TIntermAggregate *node;
TString name;
size_t index;
bool indexAssigned;
bool visiting;
};
bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override
{
// Create the record if need be and remember the node.
if (visit == PreVisit)
{
auto it = mFunctions.find(node->getFunctionSymbolInfo()->getName());
if (it == mFunctions.end())
{
mCurrentFunction = &mFunctions[node->getFunctionSymbolInfo()->getName()];
}
else
{
mCurrentFunction = &it->second;
}
mCurrentFunction->node = node;
mCurrentFunction->name = node->getFunctionSymbolInfo()->getName();
}
else if (visit == PostVisit)
{
mCurrentFunction = nullptr;
}
return true;
}
// Aggregates the AST node for each function as well as the name of the functions called by it
bool visitAggregate(Visit visit, TIntermAggregate *node) override
{
@ -139,10 +108,36 @@ class CallDAG::CallDAGCreator : public TIntermTraverser
if (visit == PreVisit)
{
// Function declaration, create an empty record.
auto &record = mFunctions[node->getFunctionSymbolInfo()->getName()];
record.name = node->getFunctionSymbolInfo()->getName();
auto& record = mFunctions[node->getName()];
record.name = node->getName();
}
break;
case EOpFunction:
{
// Function definition, create the record if need be and remember the node.
if (visit == PreVisit)
{
auto it = mFunctions.find(node->getName());
if (it == mFunctions.end())
{
mCurrentFunction = &mFunctions[node->getName()];
}
else
{
mCurrentFunction = &it->second;
}
mCurrentFunction->node = node;
mCurrentFunction->name = node->getName();
}
else if (visit == PostVisit)
{
mCurrentFunction = nullptr;
}
break;
}
case EOpFunctionCall:
{
// Function call, add the callees
@ -151,7 +146,7 @@ class CallDAG::CallDAGCreator : public TIntermTraverser
// Do not handle calls to builtin functions
if (node->isUserDefined())
{
auto it = mFunctions.find(node->getFunctionSymbolInfo()->getName());
auto it = mFunctions.find(node->getName());
ASSERT(it != mFunctions.end());
// We might be in a top-level function call to set a global variable
@ -170,102 +165,52 @@ class CallDAG::CallDAGCreator : public TIntermTraverser
}
// Recursively assigns indices to a sub DAG
InitResult assignIndicesInternal(CreatorFunctionData *root)
InitResult assignIndicesInternal(CreatorFunctionData *function)
{
// Iterative implementation of the index assignment algorithm. A recursive version
// would be prettier but since the CallDAG creation runs before the limiting of the
// call depth, we might get stack overflows (computation of the call depth uses the
// CallDAG).
ASSERT(function);
ASSERT(root);
if (!function->node)
{
*mCreationInfo << "Undefined function '" << function->name
<< ")' used in the following call chain:";
return INITDAG_UNDEFINED;
}
if (root->indexAssigned)
if (function->indexAssigned)
{
return INITDAG_SUCCESS;
}
// If we didn't have to detect recursion, functionsToProcess could be a simple queue
// in which we add the function being processed's callees. However in order to detect
// recursion we need to know which functions we are currently visiting. For that reason
// functionsToProcess will look like a concatenation of segments of the form
// [F visiting = true, subset of F callees with visiting = false] and the following
// segment (if any) will be start with a callee of F.
// This way we can remember when we started visiting a function, to put visiting back
// to false.
TVector<CreatorFunctionData *> functionsToProcess;
functionsToProcess.push_back(root);
InitResult result = INITDAG_SUCCESS;
while (!functionsToProcess.empty())
if (function->visiting)
{
CreatorFunctionData *function = functionsToProcess.back();
if (function->visiting)
if (mCreationInfo)
{
function->visiting = false;
function->index = mCurrentIndex++;
function->indexAssigned = true;
functionsToProcess.pop_back();
continue;
}
if (!function->node)
{
*mCreationInfo << "Undefined function '" << function->name
<< ")' used in the following call chain:";
result = INITDAG_UNDEFINED;
break;
}
if (function->indexAssigned)
{
functionsToProcess.pop_back();
continue;
}
function->visiting = true;
for (auto callee : function->callees)
{
functionsToProcess.push_back(callee);
// Check if the callee is already being visited after pushing it so that it appears
// in the chain printed in the info log.
if (callee->visiting)
{
*mCreationInfo << "Recursive function call in the following call chain:";
result = INITDAG_RECURSION;
break;
}
*mCreationInfo << "Recursive function call in the following call chain:" << function->name;
}
return INITDAG_RECURSION;
}
function->visiting = true;
for (auto &callee : function->callees)
{
InitResult result = assignIndicesInternal(callee);
if (result != INITDAG_SUCCESS)
{
break;
}
}
// The call chain is made of the function we were visiting when the error was detected.
if (result != INITDAG_SUCCESS)
{
bool first = true;
for (auto function : functionsToProcess)
{
if (function->visiting)
// We know that there is an issue with the call chain in the AST,
// print the link of the chain we were processing.
if (mCreationInfo)
{
if (!first)
{
*mCreationInfo << " -> ";
}
*mCreationInfo << function->name << ")";
first = false;
*mCreationInfo << " <- " << function->name << ")";
}
return result;
}
}
return result;
function->index = mCurrentIndex++;
function->indexAssigned = true;
function->visiting = false;
return INITDAG_SUCCESS;
}
TInfoSinkBase *mCreationInfo;
@ -287,9 +232,13 @@ CallDAG::~CallDAG()
const size_t CallDAG::InvalidIndex = std::numeric_limits<size_t>::max();
size_t CallDAG::findIndex(const TFunctionSymbolInfo *functionInfo) const
size_t CallDAG::findIndex(const TIntermAggregate *function) const
{
auto it = mFunctionIdToIndex.find(functionInfo->getId());
TOperator op = function->getOp();
ASSERT(op == EOpPrototype || op == EOpFunction || op == EOpFunctionCall);
UNUSED_ASSERTION_VARIABLE(op);
auto it = mFunctionIdToIndex.find(function->getFunctionId());
if (it == mFunctionIdToIndex.end())
{
@ -309,7 +258,7 @@ const CallDAG::Record &CallDAG::getRecordFromIndex(size_t index) const
const CallDAG::Record &CallDAG::getRecord(const TIntermAggregate *function) const
{
size_t index = findIndex(function->getFunctionSymbolInfo());
size_t index = findIndex(function);
ASSERT(index != InvalidIndex && index < mRecords.size());
return mRecords[index];
}
@ -327,8 +276,6 @@ void CallDAG::clear()
CallDAG::InitResult CallDAG::init(TIntermNode *root, TInfoSinkBase *info)
{
ASSERT(info);
CallDAGCreator creator(info);
// Creates the mapping of functions to callees
@ -344,5 +291,3 @@ CallDAG::InitResult CallDAG::init(TIntermNode *root, TInfoSinkBase *info)
creator.fillDataStructures(&mRecords, &mFunctionIdToIndex);
return INITDAG_SUCCESS;
}
} // namespace sh

View file

@ -16,8 +16,6 @@
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/VariableInfo.h"
namespace sh
{
// The translator needs to analyze the the graph of the function calls
// to run checks and analyses; since in GLSL recursion is not allowed
@ -43,7 +41,7 @@ class CallDAG : angle::NonCopyable
struct Record
{
std::string name;
TIntermFunctionDefinition *node;
TIntermAggregate *node;
std::vector<int> callees;
};
@ -59,7 +57,7 @@ class CallDAG : angle::NonCopyable
InitResult init(TIntermNode *root, TInfoSinkBase *info);
// Returns InvalidIndex if the function wasn't found
size_t findIndex(const TFunctionSymbolInfo *functionInfo) const;
size_t findIndex(const TIntermAggregate *function) const;
const Record &getRecordFromIndex(size_t index) const;
const Record &getRecord(const TIntermAggregate *function) const;
@ -74,6 +72,4 @@ class CallDAG : angle::NonCopyable
class CallDAGCreator;
};
} // namespace sh
#endif // COMPILER_TRANSLATOR_CALLDAG_H_

View file

@ -6,79 +6,71 @@
#ifdef ANGLE_ENABLE_ESSL
#include "compiler/translator/TranslatorESSL.h"
#endif // ANGLE_ENABLE_ESSL
#endif
#ifdef ANGLE_ENABLE_GLSL
#include "compiler/translator/TranslatorGLSL.h"
#endif // ANGLE_ENABLE_GLSL
#endif
#ifdef ANGLE_ENABLE_HLSL
#include "compiler/translator/TranslatorHLSL.h"
#endif // ANGLE_ENABLE_HLSL
namespace sh
{
#endif // ANGLE_ENABLE_HLSL
//
// This function must be provided to create the actual
// compile object used by higher level code. It returns
// a subclass of TCompiler.
//
TCompiler *ConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
TCompiler* ConstructCompiler(
sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
{
switch (output)
{
case SH_ESSL_OUTPUT:
switch (output) {
case SH_ESSL_OUTPUT:
#ifdef ANGLE_ENABLE_ESSL
return new TranslatorESSL(type, spec);
return new TranslatorESSL(type, spec);
#else
// This compiler is not supported in this configuration. Return NULL per the
// sh::ConstructCompiler API.
return nullptr;
#endif // ANGLE_ENABLE_ESSL
case SH_GLSL_130_OUTPUT:
case SH_GLSL_140_OUTPUT:
case SH_GLSL_150_CORE_OUTPUT:
case SH_GLSL_330_CORE_OUTPUT:
case SH_GLSL_400_CORE_OUTPUT:
case SH_GLSL_410_CORE_OUTPUT:
case SH_GLSL_420_CORE_OUTPUT:
case SH_GLSL_430_CORE_OUTPUT:
case SH_GLSL_440_CORE_OUTPUT:
case SH_GLSL_450_CORE_OUTPUT:
case SH_GLSL_COMPATIBILITY_OUTPUT:
// This compiler is not supported in this
// configuration. Return NULL per the ShConstructCompiler API.
return nullptr;
#endif // ANGLE_ENABLE_ESSL
case SH_GLSL_130_OUTPUT:
case SH_GLSL_140_OUTPUT:
case SH_GLSL_150_CORE_OUTPUT:
case SH_GLSL_330_CORE_OUTPUT:
case SH_GLSL_400_CORE_OUTPUT:
case SH_GLSL_410_CORE_OUTPUT:
case SH_GLSL_420_CORE_OUTPUT:
case SH_GLSL_430_CORE_OUTPUT:
case SH_GLSL_440_CORE_OUTPUT:
case SH_GLSL_450_CORE_OUTPUT:
case SH_GLSL_COMPATIBILITY_OUTPUT:
#ifdef ANGLE_ENABLE_GLSL
return new TranslatorGLSL(type, spec, output);
return new TranslatorGLSL(type, spec, output);
#else
// This compiler is not supported in this configuration. Return NULL per the
// sh::ConstructCompiler API.
return nullptr;
#endif // ANGLE_ENABLE_GLSL
case SH_HLSL_3_0_OUTPUT:
case SH_HLSL_4_1_OUTPUT:
case SH_HLSL_4_0_FL9_3_OUTPUT:
// This compiler is not supported in this
// configuration. Return NULL per the ShConstructCompiler API.
return nullptr;
#endif // ANGLE_ENABLE_GLSL
case SH_HLSL_3_0_OUTPUT:
case SH_HLSL_4_1_OUTPUT:
case SH_HLSL_4_0_FL9_3_OUTPUT:
#ifdef ANGLE_ENABLE_HLSL
return new TranslatorHLSL(type, spec, output);
return new TranslatorHLSL(type, spec, output);
#else
// This compiler is not supported in this configuration. Return NULL per the
// sh::ConstructCompiler API.
return nullptr;
#endif // ANGLE_ENABLE_HLSL
default:
// Unknown format. Return NULL per the sh::ConstructCompiler API.
return nullptr;
// This compiler is not supported in this
// configuration. Return NULL per the ShConstructCompiler API.
return nullptr;
#endif // ANGLE_ENABLE_HLSL
default:
// Unknown format. Return NULL per the ShConstructCompiler API.
return nullptr;
}
}
//
// Delete the compiler made by ConstructCompiler
//
void DeleteCompiler(TCompiler *compiler)
void DeleteCompiler(TCompiler* compiler)
{
SafeDelete(compiler);
delete compiler;
}
} // namespace sh

View file

@ -18,9 +18,6 @@
#include "common/debug.h"
#include "compiler/translator/PoolAlloc.h"
namespace sh
{
struct TSourceLoc {
int first_file;
int first_line;
@ -95,6 +92,4 @@ inline TString str(T i)
return buffer;
}
} // namespace sh
#endif // COMPILER_TRANSLATOR_COMMON_H_

View file

@ -4,18 +4,11 @@
// found in the LICENSE file.
//
#include "compiler/translator/Compiler.h"
#include <sstream>
#include "angle_gl.h"
#include "common/utilities.h"
#include "compiler/translator/AddAndTrueToLoopCondition.h"
#include "compiler/translator/Cache.h"
#include "compiler/translator/Compiler.h"
#include "compiler/translator/CallDAG.h"
#include "compiler/translator/DeferGlobalInitializers.h"
#include "compiler/translator/EmulateGLFragColorBroadcast.h"
#include "compiler/translator/EmulatePrecision.h"
#include "compiler/translator/ForLoopUnroll.h"
#include "compiler/translator/Initialize.h"
#include "compiler/translator/InitializeParseContext.h"
@ -23,100 +16,41 @@
#include "compiler/translator/ParseContext.h"
#include "compiler/translator/PruneEmptyDeclarations.h"
#include "compiler/translator/RegenerateStructNames.h"
#include "compiler/translator/RemoveInvariantDeclaration.h"
#include "compiler/translator/RemovePow.h"
#include "compiler/translator/RenameFunction.h"
#include "compiler/translator/RewriteDoWhile.h"
#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h"
#include "compiler/translator/UnfoldShortCircuitAST.h"
#include "compiler/translator/UseInterfaceBlockFields.h"
#include "compiler/translator/ValidateLimitations.h"
#include "compiler/translator/ValidateMaxParameters.h"
#include "compiler/translator/ValidateOutputs.h"
#include "compiler/translator/VariablePacker.h"
#include "compiler/translator/depgraph/DependencyGraph.h"
#include "compiler/translator/depgraph/DependencyGraphOutput.h"
#include "compiler/translator/timing/RestrictFragmentShaderTiming.h"
#include "compiler/translator/timing/RestrictVertexShaderTiming.h"
#include "third_party/compiler/ArrayBoundsClamper.h"
namespace sh
{
namespace
{
#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
void DumpFuzzerCase(char const *const *shaderStrings,
size_t numStrings,
uint32_t type,
uint32_t spec,
uint32_t output,
uint64_t options)
{
static int fileIndex = 0;
std::ostringstream o;
o << "corpus/" << fileIndex++ << ".sample";
std::string s = o.str();
// Must match the input format of the fuzzer
FILE *f = fopen(s.c_str(), "w");
fwrite(&type, sizeof(type), 1, f);
fwrite(&spec, sizeof(spec), 1, f);
fwrite(&output, sizeof(output), 1, f);
fwrite(&options, sizeof(options), 1, f);
char zero[128 - 20] = {0};
fwrite(&zero, 128 - 20, 1, f);
for (size_t i = 0; i < numStrings; i++)
{
fwrite(shaderStrings[i], sizeof(char), strlen(shaderStrings[i]), f);
}
fwrite(&zero, 1, 1, f);
fclose(f);
}
#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
} // anonymous namespace
#include "angle_gl.h"
#include "common/utilities.h"
bool IsWebGLBasedSpec(ShShaderSpec spec)
{
return (spec == SH_WEBGL_SPEC || spec == SH_WEBGL2_SPEC || spec == SH_WEBGL3_SPEC);
return (spec == SH_WEBGL_SPEC || spec == SH_CSS_SHADERS_SPEC || spec == SH_WEBGL2_SPEC ||
spec == SH_WEBGL3_SPEC);
}
bool IsGLSL130OrNewer(ShShaderOutput output)
{
return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT ||
output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
}
bool IsGLSL420OrNewer(ShShaderOutput output)
{
return (output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
}
bool IsGLSL410OrOlder(ShShaderOutput output)
{
return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT);
}
bool RemoveInvariant(sh::GLenum shaderType,
int shaderVersion,
ShShaderOutput outputType,
ShCompileOptions compileOptions)
{
if ((compileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT) == 0 &&
shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType))
return true;
if ((compileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0 &&
shaderVersion >= 300 && shaderType == GL_VERTEX_SHADER && IsGLSL410OrOlder(outputType))
return true;
return false;
return (output == SH_GLSL_130_OUTPUT ||
output == SH_GLSL_140_OUTPUT ||
output == SH_GLSL_150_CORE_OUTPUT ||
output == SH_GLSL_330_CORE_OUTPUT ||
output == SH_GLSL_400_CORE_OUTPUT ||
output == SH_GLSL_410_CORE_OUTPUT ||
output == SH_GLSL_420_CORE_OUTPUT ||
output == SH_GLSL_430_CORE_OUTPUT ||
output == SH_GLSL_440_CORE_OUTPUT ||
output == SH_GLSL_450_CORE_OUTPUT);
}
size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
@ -125,10 +59,11 @@ size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
// size undefined. ES3 defines a max size of 1024 characters.
switch (spec)
{
case SH_WEBGL_SPEC:
return 256;
default:
return 1024;
case SH_WEBGL_SPEC:
case SH_CSS_SHADERS_SPEC:
return 256;
default:
return 1024;
}
}
@ -174,18 +109,19 @@ int MapSpecToShaderVersion(ShShaderSpec spec)
{
switch (spec)
{
case SH_GLES2_SPEC:
case SH_WEBGL_SPEC:
return 100;
case SH_GLES3_SPEC:
case SH_WEBGL2_SPEC:
return 300;
case SH_GLES3_1_SPEC:
case SH_WEBGL3_SPEC:
return 310;
default:
UNREACHABLE();
return 0;
case SH_GLES2_SPEC:
case SH_WEBGL_SPEC:
case SH_CSS_SHADERS_SPEC:
return 100;
case SH_GLES3_SPEC:
case SH_WEBGL2_SPEC:
return 300;
case SH_GLES3_1_SPEC:
case SH_WEBGL3_SPEC:
return 310;
default:
UNREACHABLE();
return 0;
}
}
@ -226,7 +162,7 @@ TCompiler::~TCompiler()
{
}
bool TCompiler::shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const
bool TCompiler::shouldRunLoopAndIndexingValidation(int compileOptions) const
{
// If compiling an ESSL 1.00 shader for WebGL, or if its been requested through the API,
// validate loop and indexing as well (to verify that the shader only uses minimal functionality
@ -261,16 +197,15 @@ bool TCompiler::Init(const ShBuiltInResources& resources)
return true;
}
TIntermBlock *TCompiler::compileTreeForTesting(const char *const shaderStrings[],
size_t numStrings,
ShCompileOptions compileOptions)
TIntermNode *TCompiler::compileTreeForTesting(const char* const shaderStrings[],
size_t numStrings, int compileOptions)
{
return compileTreeImpl(shaderStrings, numStrings, compileOptions);
}
TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
size_t numStrings,
const ShCompileOptions compileOptions)
TIntermNode *TCompiler::compileTreeImpl(const char *const shaderStrings[],
size_t numStrings,
const int compileOptions)
{
clearResults();
@ -288,7 +223,8 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
++firstSource;
}
TParseContext parseContext(symbolTable, extensionBehavior, shaderType, shaderSpec,
TIntermediate intermediate(infoSink);
TParseContext parseContext(symbolTable, extensionBehavior, intermediate, shaderType, shaderSpec,
compileOptions, true, infoSink, getResources());
parseContext.setFragmentPrecisionHighOnESSL1(fragmentPrecisionHigh);
@ -311,7 +247,7 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
success = false;
}
TIntermBlock *root = nullptr;
TIntermNode *root = nullptr;
if (success)
{
@ -322,6 +258,7 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
mComputeShaderLocalSize = parseContext.getComputeShaderLocalSize();
root = parseContext.getTreeRoot();
root = intermediate.postProcess(root);
// Highp might have been auto-enabled based on shader version
fragmentPrecisionHigh = parseContext.getFragmentPrecisionHigh();
@ -358,17 +295,11 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
if (success && shouldRunLoopAndIndexingValidation(compileOptions))
success = validateLimitations(root);
// Fail compilation if precision emulation not supported.
if (success && getResources().WEBGL_debug_shader_precision &&
getPragma().debugShaderPrecision)
{
if (!EmulatePrecision::SupportedInLanguage(outputType))
{
infoSink.info.prefix(EPrefixError);
infoSink.info << "Precision emulation not supported for this output type.";
success = false;
}
}
if (success && (compileOptions & SH_TIMING_RESTRICTIONS))
success = enforceTimingRestrictions(root, (compileOptions & SH_DEPENDENCY_GRAPH) != 0);
if (success && shaderSpec == SH_CSS_SHADERS_SPEC)
rewriteCSSShader(root);
// Unroll for-loop markup needs to happen after validateLimitations pass.
if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX))
@ -410,16 +341,10 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
(outputType == SH_GLSL_COMPATIBILITY_OUTPUT)))
initializeGLPosition(root);
if (success && RemoveInvariant(shaderType, shaderVersion, outputType, compileOptions))
sh::RemoveInvariantDeclaration(root);
// This pass might emit short circuits so keep it before the short circuit unfolding
if (success && (compileOptions & SH_REWRITE_DO_WHILE_LOOPS))
RewriteDoWhile(root, getTemporaryIndex());
if (success && (compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION))
sh::AddAndTrueToLoopCondition(root);
if (success && (compileOptions & SH_UNFOLD_SHORT_CIRCUIT))
{
UnfoldShortCircuitAST unfoldShortCircuit;
@ -435,10 +360,6 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
if (success && shouldCollectVariables(compileOptions))
{
collectVariables(root);
if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS)
{
useAllMembersInUnusedStandardAndSharedBlocks(root);
}
if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS)
{
success = enforcePackingRestrictions();
@ -456,8 +377,9 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
if (success && (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS))
{
ScalarizeVecAndMatConstructorArgs(root, shaderType, fragmentPrecisionHigh,
&mTemporaryIndex);
ScalarizeVecAndMatConstructorArgs scalarizer(
shaderType, fragmentPrecisionHigh);
root->traverse(&scalarizer);
}
if (success && (compileOptions & SH_REGENERATE_STRUCT_NAMES))
@ -486,18 +408,12 @@ TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
return NULL;
}
bool TCompiler::compile(const char *const shaderStrings[],
size_t numStrings,
ShCompileOptions compileOptionsIn)
bool TCompiler::compile(const char *const shaderStrings[], size_t numStrings, int compileOptionsIn)
{
#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
DumpFuzzerCase(shaderStrings, numStrings, shaderType, shaderSpec, outputType, compileOptionsIn);
#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
if (numStrings == 0)
return true;
ShCompileOptions compileOptions = compileOptionsIn;
int compileOptions = compileOptionsIn;
// Apply key workarounds.
if (shouldFlattenPragmaStdglInvariantAll())
@ -506,19 +422,8 @@ bool TCompiler::compile(const char *const shaderStrings[],
compileOptions |= SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL;
}
ShCompileOptions unrollFlags =
SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX | SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
if ((compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION) != 0 &&
(compileOptions & unrollFlags) != 0)
{
infoSink.info.prefix(EPrefixError);
infoSink.info
<< "Unsupported compile flag combination: unroll & ADD_TRUE_TO_LOOP_CONDITION";
return false;
}
TScopedPoolAllocator scopedAlloc(&allocator);
TIntermBlock *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);
TIntermNode *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);
if (root)
{
@ -547,26 +452,32 @@ bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
symbolTable.push(); // ESSL3_1_BUILTINS
TPublicType integer;
integer.initializeBasicType(EbtInt);
integer.type = EbtInt;
integer.primarySize = 1;
integer.secondarySize = 1;
integer.array = false;
TPublicType floatingPoint;
floatingPoint.initializeBasicType(EbtFloat);
floatingPoint.type = EbtFloat;
floatingPoint.primarySize = 1;
floatingPoint.secondarySize = 1;
floatingPoint.array = false;
switch (shaderType)
switch(shaderType)
{
case GL_FRAGMENT_SHADER:
symbolTable.setDefaultPrecision(integer, EbpMedium);
break;
case GL_VERTEX_SHADER:
symbolTable.setDefaultPrecision(integer, EbpHigh);
symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
break;
case GL_COMPUTE_SHADER:
symbolTable.setDefaultPrecision(integer, EbpHigh);
symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
break;
default:
assert(false && "Language not supported");
case GL_FRAGMENT_SHADER:
symbolTable.setDefaultPrecision(integer, EbpMedium);
break;
case GL_VERTEX_SHADER:
symbolTable.setDefaultPrecision(integer, EbpHigh);
symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
break;
case GL_COMPUTE_SHADER:
symbolTable.setDefaultPrecision(integer, EbpHigh);
symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
break;
default:
assert(false && "Language not supported");
}
// Set defaults for sampler types that have default precision, even those that are
// only available if an extension exists.
@ -589,7 +500,10 @@ void TCompiler::initSamplerDefaultPrecision(TBasicType samplerType)
{
ASSERT(samplerType > EbtGuardSamplerBegin && samplerType < EbtGuardSamplerEnd);
TPublicType sampler;
sampler.initializeBasicType(samplerType);
sampler.primarySize = 1;
sampler.secondarySize = 1;
sampler.array = false;
sampler.type = samplerType;
symbolTable.setDefaultPrecision(sampler, EbpLow);
}
@ -599,60 +513,60 @@ void TCompiler::setResourceString()
// clang-format off
strstream << ":MaxVertexAttribs:" << compileResources.MaxVertexAttribs
<< ":MaxVertexUniformVectors:" << compileResources.MaxVertexUniformVectors
<< ":MaxVaryingVectors:" << compileResources.MaxVaryingVectors
<< ":MaxVertexTextureImageUnits:" << compileResources.MaxVertexTextureImageUnits
<< ":MaxCombinedTextureImageUnits:" << compileResources.MaxCombinedTextureImageUnits
<< ":MaxTextureImageUnits:" << compileResources.MaxTextureImageUnits
<< ":MaxFragmentUniformVectors:" << compileResources.MaxFragmentUniformVectors
<< ":MaxDrawBuffers:" << compileResources.MaxDrawBuffers
<< ":OES_standard_derivatives:" << compileResources.OES_standard_derivatives
<< ":OES_EGL_image_external:" << compileResources.OES_EGL_image_external
<< ":OES_EGL_image_external_essl3:" << compileResources.OES_EGL_image_external_essl3
<< ":NV_EGL_stream_consumer_external:" << compileResources.NV_EGL_stream_consumer_external
<< ":ARB_texture_rectangle:" << compileResources.ARB_texture_rectangle
<< ":EXT_draw_buffers:" << compileResources.EXT_draw_buffers
<< ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh
<< ":MaxExpressionComplexity:" << compileResources.MaxExpressionComplexity
<< ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth
<< ":MaxFunctionParameters:" << compileResources.MaxFunctionParameters
<< ":EXT_blend_func_extended:" << compileResources.EXT_blend_func_extended
<< ":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
<< ":MaxDualSourceDrawBuffers:" << compileResources.MaxDualSourceDrawBuffers
<< ":NV_draw_buffers:" << compileResources.NV_draw_buffers
<< ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision
<< ":MaxImageUnits:" << compileResources.MaxImageUnits
<< ":MaxVertexImageUniforms:" << compileResources.MaxVertexImageUniforms
<< ":MaxFragmentImageUniforms:" << compileResources.MaxFragmentImageUniforms
<< ":MaxComputeImageUniforms:" << compileResources.MaxComputeImageUniforms
<< ":MaxCombinedImageUniforms:" << compileResources.MaxCombinedImageUniforms
<< ":MaxCombinedShaderOutputResources:" << compileResources.MaxCombinedShaderOutputResources
<< ":MaxComputeWorkGroupCountX:" << compileResources.MaxComputeWorkGroupCount[0]
<< ":MaxComputeWorkGroupCountY:" << compileResources.MaxComputeWorkGroupCount[1]
<< ":MaxComputeWorkGroupCountZ:" << compileResources.MaxComputeWorkGroupCount[2]
<< ":MaxComputeWorkGroupSizeX:" << compileResources.MaxComputeWorkGroupSize[0]
<< ":MaxComputeWorkGroupSizeY:" << compileResources.MaxComputeWorkGroupSize[1]
<< ":MaxComputeWorkGroupSizeZ:" << compileResources.MaxComputeWorkGroupSize[2]
<< ":MaxComputeUniformComponents:" << compileResources.MaxComputeUniformComponents
<< ":MaxComputeTextureImageUnits:" << compileResources.MaxComputeTextureImageUnits
<< ":MaxComputeAtomicCounters:" << compileResources.MaxComputeAtomicCounters
<< ":MaxComputeAtomicCounterBuffers:" << compileResources.MaxComputeAtomicCounterBuffers
<< ":MaxVertexAtomicCounters:" << compileResources.MaxVertexAtomicCounters
<< ":MaxFragmentAtomicCounters:" << compileResources.MaxFragmentAtomicCounters
<< ":MaxCombinedAtomicCounters:" << compileResources.MaxCombinedAtomicCounters
<< ":MaxAtomicCounterBindings:" << compileResources.MaxAtomicCounterBindings
<< ":MaxVertexAtomicCounterBuffers:" << compileResources.MaxVertexAtomicCounterBuffers
<< ":MaxFragmentAtomicCounterBuffers:" << compileResources.MaxFragmentAtomicCounterBuffers
<< ":MaxCombinedAtomicCounterBuffers:" << compileResources.MaxCombinedAtomicCounterBuffers
<< ":MaxAtomicCounterBufferSize:" << compileResources.MaxAtomicCounterBufferSize;
<< ":MaxVertexUniformVectors:" << compileResources.MaxVertexUniformVectors
<< ":MaxVaryingVectors:" << compileResources.MaxVaryingVectors
<< ":MaxVertexTextureImageUnits:" << compileResources.MaxVertexTextureImageUnits
<< ":MaxCombinedTextureImageUnits:" << compileResources.MaxCombinedTextureImageUnits
<< ":MaxTextureImageUnits:" << compileResources.MaxTextureImageUnits
<< ":MaxFragmentUniformVectors:" << compileResources.MaxFragmentUniformVectors
<< ":MaxDrawBuffers:" << compileResources.MaxDrawBuffers
<< ":OES_standard_derivatives:" << compileResources.OES_standard_derivatives
<< ":OES_EGL_image_external:" << compileResources.OES_EGL_image_external
<< ":OES_EGL_image_external_essl3:" << compileResources.OES_EGL_image_external_essl3
<< ":NV_EGL_stream_consumer_external:" << compileResources.NV_EGL_stream_consumer_external
<< ":ARB_texture_rectangle:" << compileResources.ARB_texture_rectangle
<< ":EXT_draw_buffers:" << compileResources.EXT_draw_buffers
<< ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh
<< ":MaxExpressionComplexity:" << compileResources.MaxExpressionComplexity
<< ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth
<< ":MaxFunctionParameters:" << compileResources.MaxFunctionParameters
<< ":EXT_blend_func_extended:" << compileResources.EXT_blend_func_extended
<< ":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
<< ":MaxDualSourceDrawBuffers:" << compileResources.MaxDualSourceDrawBuffers
<< ":NV_draw_buffers:" << compileResources.NV_draw_buffers
<< ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision
<< ":MaxImageUnits:" << compileResources.MaxImageUnits
<< ":MaxVertexImageUniforms:" << compileResources.MaxVertexImageUniforms
<< ":MaxFragmentImageUniforms:" << compileResources.MaxFragmentImageUniforms
<< ":MaxComputeImageUniforms:" << compileResources.MaxComputeImageUniforms
<< ":MaxCombinedImageUniforms:" << compileResources.MaxCombinedImageUniforms
<< ":MaxCombinedShaderOutputResources:" << compileResources.MaxCombinedShaderOutputResources
<< ":MaxComputeWorkGroupCountX:" << compileResources.MaxComputeWorkGroupCount[0]
<< ":MaxComputeWorkGroupCountY:" << compileResources.MaxComputeWorkGroupCount[1]
<< ":MaxComputeWorkGroupCountZ:" << compileResources.MaxComputeWorkGroupCount[2]
<< ":MaxComputeWorkGroupSizeX:" << compileResources.MaxComputeWorkGroupSize[0]
<< ":MaxComputeWorkGroupSizeY:" << compileResources.MaxComputeWorkGroupSize[1]
<< ":MaxComputeWorkGroupSizeZ:" << compileResources.MaxComputeWorkGroupSize[2]
<< ":MaxComputeUniformComponents:" << compileResources.MaxComputeUniformComponents
<< ":MaxComputeTextureImageUnits:" << compileResources.MaxComputeTextureImageUnits
<< ":MaxComputeAtomicCounters:" << compileResources.MaxComputeAtomicCounters
<< ":MaxComputeAtomicCounterBuffers:" << compileResources.MaxComputeAtomicCounterBuffers
<< ":MaxVertexAtomicCounters:" << compileResources.MaxVertexAtomicCounters
<< ":MaxFragmentAtomicCounters:" << compileResources.MaxFragmentAtomicCounters
<< ":MaxCombinedAtomicCounters:" << compileResources.MaxCombinedAtomicCounters
<< ":MaxAtomicCounterBindings:" << compileResources.MaxAtomicCounterBindings
<< ":MaxVertexAtomicCounterBuffers:" << compileResources.MaxVertexAtomicCounterBuffers
<< ":MaxFragmentAtomicCounterBuffers:" << compileResources.MaxFragmentAtomicCounterBuffers
<< ":MaxCombinedAtomicCounterBuffers:" << compileResources.MaxCombinedAtomicCounterBuffers
<< ":MaxAtomicCounterBufferSize:" << compileResources.MaxAtomicCounterBufferSize;
// clang-format on
builtInResourcesString = strstream.str();
@ -687,16 +601,16 @@ bool TCompiler::initCallDag(TIntermNode *root)
switch (mCallDag.init(root, &infoSink.info))
{
case CallDAG::INITDAG_SUCCESS:
return true;
case CallDAG::INITDAG_RECURSION:
infoSink.info.prefix(EPrefixError);
infoSink.info << "Function recursion detected";
return false;
case CallDAG::INITDAG_UNDEFINED:
infoSink.info.prefix(EPrefixError);
infoSink.info << "Unimplemented function detected";
return false;
case CallDAG::INITDAG_SUCCESS:
return true;
case CallDAG::INITDAG_RECURSION:
infoSink.info.prefix(EPrefixError);
infoSink.info << "Function recursion detected";
return false;
case CallDAG::INITDAG_UNDEFINED:
infoSink.info.prefix(EPrefixError);
infoSink.info << "Unimplemented function detected";
return false;
}
UNREACHABLE();
@ -790,38 +704,30 @@ class TCompiler::UnusedPredicate
{
public:
UnusedPredicate(const CallDAG *callDag, const std::vector<FunctionMetadata> *metadatas)
: mCallDag(callDag), mMetadatas(metadatas)
: mCallDag(callDag),
mMetadatas(metadatas)
{
}
bool operator ()(TIntermNode *node)
{
const TIntermAggregate *asAggregate = node->getAsAggregate();
const TIntermFunctionDefinition *asFunction = node->getAsFunctionDefinition();
const TFunctionSymbolInfo *functionInfo = nullptr;
if (asFunction)
{
functionInfo = asFunction->getFunctionSymbolInfo();
}
else if (asAggregate)
{
if (asAggregate->getOp() == EOpPrototype)
{
functionInfo = asAggregate->getFunctionSymbolInfo();
}
}
if (functionInfo == nullptr)
if (asAggregate == nullptr)
{
return false;
}
size_t callDagIndex = mCallDag->findIndex(functionInfo);
if (!(asAggregate->getOp() == EOpFunction || asAggregate->getOp() == EOpPrototype))
{
return false;
}
size_t callDagIndex = mCallDag->findIndex(asAggregate);
if (callDagIndex == CallDAG::InvalidIndex)
{
// This happens only for unimplemented prototypes which are thus unused
ASSERT(asAggregate && asAggregate->getOp() == EOpPrototype);
ASSERT(asAggregate->getOp() == EOpPrototype);
return true;
}
@ -834,10 +740,13 @@ class TCompiler::UnusedPredicate
const std::vector<FunctionMetadata> *mMetadatas;
};
bool TCompiler::pruneUnusedFunctions(TIntermBlock *root)
bool TCompiler::pruneUnusedFunctions(TIntermNode *root)
{
TIntermAggregate *rootNode = root->getAsAggregate();
ASSERT(rootNode != nullptr);
UnusedPredicate isUnused(&mCallDag, &functionMetadata);
TIntermSequence *sequence = root->getSequence();
TIntermSequence *sequence = rootNode->getSequence();
if (!sequence->empty())
{
@ -854,6 +763,12 @@ bool TCompiler::validateOutputs(TIntermNode* root)
return (validateOutputs.validateAndCountErrors(infoSink.info) == 0);
}
void TCompiler::rewriteCSSShader(TIntermNode* root)
{
RenameFunction renamer("main(", "css_main(");
root->traverse(&renamer);
}
bool TCompiler::validateLimitations(TIntermNode* root)
{
ValidateLimitations validate(shaderType, &infoSink.info);
@ -861,9 +776,39 @@ bool TCompiler::validateLimitations(TIntermNode* root)
return validate.numErrors() == 0;
}
bool TCompiler::enforceTimingRestrictions(TIntermNode* root, bool outputGraph)
{
if (shaderSpec != SH_WEBGL_SPEC)
{
infoSink.info << "Timing restrictions must be enforced under the WebGL spec.";
return false;
}
if (shaderType == GL_FRAGMENT_SHADER)
{
TDependencyGraph graph(root);
// Output any errors first.
bool success = enforceFragmentShaderTimingRestrictions(graph);
// Then, output the dependency graph.
if (outputGraph)
{
TDependencyGraphOutput output(infoSink.info);
output.outputAllSpanningTrees(graph);
}
return success;
}
else
{
return enforceVertexShaderTimingRestrictions(root);
}
}
bool TCompiler::limitExpressionComplexity(TIntermNode* root)
{
TMaxDepthTraverser traverser(maxExpressionComplexity + 1);
TMaxDepthTraverser traverser(maxExpressionComplexity+1);
root->traverse(&traverser);
if (traverser.getMaxDepth() > maxExpressionComplexity)
@ -881,13 +826,26 @@ bool TCompiler::limitExpressionComplexity(TIntermNode* root)
return true;
}
bool TCompiler::enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph)
{
RestrictFragmentShaderTiming restrictor(infoSink.info);
restrictor.enforceRestrictions(graph);
return restrictor.numErrors() == 0;
}
bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root)
{
RestrictVertexShaderTiming restrictor(infoSink.info);
restrictor.enforceRestrictions(root);
return restrictor.numErrors() == 0;
}
void TCompiler::collectVariables(TIntermNode* root)
{
if (!variablesCollected)
{
sh::CollectVariables collect(&attributes, &outputVariables, &uniforms, &varyings,
&interfaceBlocks, hashFunction, symbolTable,
extensionBehavior);
&interfaceBlocks, hashFunction, symbolTable, extensionBehavior);
root->traverse(&collect);
// This is for enforcePackingRestriction().
@ -896,16 +854,6 @@ void TCompiler::collectVariables(TIntermNode* root)
}
}
bool TCompiler::shouldCollectVariables(ShCompileOptions compileOptions)
{
return (compileOptions & SH_VARIABLES) != 0;
}
bool TCompiler::wereVariablesCollected() const
{
return variablesCollected;
}
bool TCompiler::enforcePackingRestrictions()
{
VariablePacker packer;
@ -918,23 +866,7 @@ void TCompiler::initializeGLPosition(TIntermNode* root)
sh::ShaderVariable var(GL_FLOAT_VEC4, 0);
var.name = "gl_Position";
list.push_back(var);
InitializeVariables(root, list, symbolTable);
}
void TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermNode *root)
{
sh::InterfaceBlockList list;
for (auto block : interfaceBlocks)
{
if (!block.staticUse &&
(block.layout == sh::BLOCKLAYOUT_STANDARD || block.layout == sh::BLOCKLAYOUT_SHARED))
{
list.push_back(block);
}
}
sh::UseInterfaceBlockFields(root, list, symbolTable);
InitializeVariables(root, list);
}
void TCompiler::initializeOutputVariables(TIntermNode *root)
@ -955,7 +887,7 @@ void TCompiler::initializeOutputVariables(TIntermNode *root)
list.push_back(var);
}
}
InitializeVariables(root, list, symbolTable);
InitializeVariables(root, list);
}
const TExtensionBehavior& TCompiler::getExtensionBehavior() const
@ -988,7 +920,7 @@ const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const
return builtInFunctionEmulator;
}
void TCompiler::writePragma(ShCompileOptions compileOptions)
void TCompiler::writePragma(int compileOptions)
{
if (!(compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL))
{
@ -1011,5 +943,3 @@ bool TCompiler::isVaryingDefined(const char *varyingName)
return false;
}
} // namespace sh

View file

@ -24,16 +24,15 @@
#include "compiler/translator/VariableInfo.h"
#include "third_party/compiler/ArrayBoundsClamper.h"
namespace sh
{
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.
// Helper function to identify specs that are based on the WebGL spec,
// like the CSS Shaders spec.
//
bool IsWebGLBasedSpec(ShShaderSpec spec);
@ -41,16 +40,6 @@ bool IsWebGLBasedSpec(ShShaderSpec spec);
// Helper function to check if the shader type is GLSL.
//
bool IsGLSL130OrNewer(ShShaderOutput output);
bool IsGLSL420OrNewer(ShShaderOutput output);
bool IsGLSL410OrOlder(ShShaderOutput output);
//
// Helper function to check if the invariant qualifier can be removed.
//
bool RemoveInvariant(sh::GLenum shaderType,
int shaderVersion,
ShShaderOutput outputType,
ShCompileOptions compileOptions);
//
// The base class used to back handles returned to the driver.
@ -85,14 +74,12 @@ class TCompiler : public TShHandleBase
// 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 nullptr whenever there are compilation errors.
TIntermBlock *compileTreeForTesting(const char *const shaderStrings[],
size_t numStrings,
ShCompileOptions compileOptions);
// 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,
ShCompileOptions compileOptions);
bool compile(const char* const shaderStrings[],
size_t numStrings, int compileOptions);
// Get results of the last compilation.
int getShaderVersion() const { return shaderVersion; }
@ -117,7 +104,7 @@ class TCompiler : public TShHandleBase
ShShaderOutput getOutputType() const { return outputType; }
const std::string &getBuiltInResourcesString() const { return builtInResourcesString; }
bool shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const;
bool shouldRunLoopAndIndexingValidation(int compileOptions) const;
// Get the resources set by InitBuiltInSymbolTable
const ShBuiltInResources& getResources() const;
@ -132,21 +119,20 @@ class TCompiler : public TShHandleBase
bool checkCallDepth();
// Returns true if a program has no conflicting or missing fragment outputs
bool validateOutputs(TIntermNode* root);
// Rewrites a shader's intermediate tree according to the CSS Shaders spec.
void rewriteCSSShader(TIntermNode* root);
// Returns true if the given shader does not exceed the minimum
// functionality mandated in GLSL 1.0 spec Appendix A.
bool validateLimitations(TIntermNode* root);
// Collect info for all attribs, uniforms, varyings.
void collectVariables(TIntermNode* root);
// Add emulated functions to the built-in function emulator.
virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu,
ShCompileOptions compileOptions){};
virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) {};
// Translate to object code.
virtual void translate(TIntermNode *root, ShCompileOptions compileOptions) = 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();
// Insert statements to reference all members in unused uniform blocks with standard and shared
// layout. This is to work around a Mac driver that treats unused standard/shared
// uniform blocks as inactive.
void useAllMembersInUnusedStandardAndSharedBlocks(TIntermNode *root);
// Insert statements to initialize output variables in the beginning of main().
// This is to avoid undefined behaviors.
void initializeOutputVariables(TIntermNode *root);
@ -155,13 +141,20 @@ class TCompiler : public TShHandleBase
// while spec says it is allowed.
// This function should only be applied to vertex shaders.
void initializeGLPosition(TIntermNode* root);
// Returns true if the shader passes the restrictions that aim to prevent timing attacks.
bool enforceTimingRestrictions(TIntermNode* root, bool outputGraph);
// Returns true if the shader does not use samplers.
bool enforceVertexShaderTimingRestrictions(TIntermNode* root);
// Returns true if the shader does not use sampler dependent values to affect control
// flow or in operations whose time can depend on the input values.
bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph);
// Return true if the maximum expression complexity is below the limit.
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(ShCompileOptions compileOptions);
void writePragma(int compileOptions);
unsigned int *getTemporaryIndex() { return &mTemporaryIndex; }
// Relies on collectVariables having been called.
bool isVaryingDefined(const char *varyingName);
@ -170,16 +163,20 @@ class TCompiler : public TShHandleBase
ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const;
const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const;
virtual bool shouldFlattenPragmaStdglInvariantAll() = 0;
virtual bool shouldCollectVariables(ShCompileOptions compileOptions);
virtual bool shouldCollectVariables(int compileOptions)
{
return (compileOptions & SH_VARIABLES) != 0;
}
virtual bool shouldFlattenPragmaStdglInvariantAll() = 0;
bool wereVariablesCollected() const;
std::vector<sh::Attribute> attributes;
std::vector<sh::OutputVariable> outputVariables;
std::vector<sh::Uniform> uniforms;
std::vector<sh::ShaderVariable> expandedUniforms;
std::vector<sh::Varying> varyings;
std::vector<sh::InterfaceBlock> interfaceBlocks;
bool variablesCollected;
private:
// Creates the function call DAG for further analysis, returning false if there is a recursion
@ -190,18 +187,13 @@ class TCompiler : public TShHandleBase
void initSamplerDefaultPrecision(TBasicType samplerType);
// Collect info for all attribs, uniforms, varyings.
void collectVariables(TIntermNode *root);
bool variablesCollected;
// Removes unused function declarations and prototypes from the AST
class UnusedPredicate;
bool pruneUnusedFunctions(TIntermBlock *root);
bool pruneUnusedFunctions(TIntermNode *root);
TIntermBlock *compileTreeImpl(const char *const shaderStrings[],
size_t numStrings,
const ShCompileOptions compileOptions);
TIntermNode *compileTreeImpl(const char *const shaderStrings[],
size_t numStrings,
const int compileOptions);
sh::GLenum shaderType;
ShShaderSpec shaderSpec;
@ -269,6 +261,4 @@ TCompiler* ConstructCompiler(
sh::GLenum type, ShShaderSpec spec, ShShaderOutput output);
void DeleteCompiler(TCompiler*);
} // namespace sh
#endif // COMPILER_TRANSLATOR_COMPILER_H_

View file

@ -1,642 +0,0 @@
//
// Copyright 2016 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.
//
// ConstantUnion: Constant folding helper class.
#include "compiler/translator/ConstantUnion.h"
#include "base/numerics/safe_math.h"
#include "common/mathutil.h"
#include "compiler/translator/Diagnostics.h"
namespace sh
{
namespace
{
template <typename T>
T CheckedSum(base::CheckedNumeric<T> lhs,
base::CheckedNumeric<T> rhs,
TDiagnostics *diag,
const TSourceLoc &line)
{
ASSERT(lhs.IsValid() && rhs.IsValid());
auto result = lhs + rhs;
if (!result.IsValid())
{
diag->error(line, "Addition out of range", "*", "");
return 0;
}
return result.ValueOrDefault(0);
}
template <typename T>
T CheckedDiff(base::CheckedNumeric<T> lhs,
base::CheckedNumeric<T> rhs,
TDiagnostics *diag,
const TSourceLoc &line)
{
ASSERT(lhs.IsValid() && rhs.IsValid());
auto result = lhs - rhs;
if (!result.IsValid())
{
diag->error(line, "Difference out of range", "*", "");
return 0;
}
return result.ValueOrDefault(0);
}
template <typename T>
T CheckedMul(base::CheckedNumeric<T> lhs,
base::CheckedNumeric<T> rhs,
TDiagnostics *diag,
const TSourceLoc &line)
{
ASSERT(lhs.IsValid() && rhs.IsValid());
auto result = lhs * rhs;
if (!result.IsValid())
{
diag->error(line, "Multiplication out of range", "*", "");
return 0;
}
return result.ValueOrDefault(0);
}
} // anonymous namespace
TConstantUnion::TConstantUnion()
{
iConst = 0;
type = EbtVoid;
}
bool TConstantUnion::cast(TBasicType newType, const TConstantUnion &constant)
{
switch (newType)
{
case EbtFloat:
switch (constant.type)
{
case EbtInt:
setFConst(static_cast<float>(constant.getIConst()));
break;
case EbtUInt:
setFConst(static_cast<float>(constant.getUConst()));
break;
case EbtBool:
setFConst(static_cast<float>(constant.getBConst()));
break;
case EbtFloat:
setFConst(static_cast<float>(constant.getFConst()));
break;
default:
return false;
}
break;
case EbtInt:
switch (constant.type)
{
case EbtInt:
setIConst(static_cast<int>(constant.getIConst()));
break;
case EbtUInt:
setIConst(static_cast<int>(constant.getUConst()));
break;
case EbtBool:
setIConst(static_cast<int>(constant.getBConst()));
break;
case EbtFloat:
setIConst(static_cast<int>(constant.getFConst()));
break;
default:
return false;
}
break;
case EbtUInt:
switch (constant.type)
{
case EbtInt:
setUConst(static_cast<unsigned int>(constant.getIConst()));
break;
case EbtUInt:
setUConst(static_cast<unsigned int>(constant.getUConst()));
break;
case EbtBool:
setUConst(static_cast<unsigned int>(constant.getBConst()));
break;
case EbtFloat:
setUConst(static_cast<unsigned int>(constant.getFConst()));
break;
default:
return false;
}
break;
case EbtBool:
switch (constant.type)
{
case EbtInt:
setBConst(constant.getIConst() != 0);
break;
case EbtUInt:
setBConst(constant.getUConst() != 0);
break;
case EbtBool:
setBConst(constant.getBConst());
break;
case EbtFloat:
setBConst(constant.getFConst() != 0.0f);
break;
default:
return false;
}
break;
case EbtStruct: // Struct fields don't get cast
switch (constant.type)
{
case EbtInt:
setIConst(constant.getIConst());
break;
case EbtUInt:
setUConst(constant.getUConst());
break;
case EbtBool:
setBConst(constant.getBConst());
break;
case EbtFloat:
setFConst(constant.getFConst());
break;
default:
return false;
}
break;
default:
return false;
}
return true;
}
bool TConstantUnion::operator==(const int i) const
{
return i == iConst;
}
bool TConstantUnion::operator==(const unsigned int u) const
{
return u == uConst;
}
bool TConstantUnion::operator==(const float f) const
{
return f == fConst;
}
bool TConstantUnion::operator==(const bool b) const
{
return b == bConst;
}
bool TConstantUnion::operator==(const TConstantUnion &constant) const
{
if (constant.type != type)
return false;
switch (type)
{
case EbtInt:
return constant.iConst == iConst;
case EbtUInt:
return constant.uConst == uConst;
case EbtFloat:
return constant.fConst == fConst;
case EbtBool:
return constant.bConst == bConst;
default:
return false;
}
}
bool TConstantUnion::operator!=(const int i) const
{
return !operator==(i);
}
bool TConstantUnion::operator!=(const unsigned int u) const
{
return !operator==(u);
}
bool TConstantUnion::operator!=(const float f) const
{
return !operator==(f);
}
bool TConstantUnion::operator!=(const bool b) const
{
return !operator==(b);
}
bool TConstantUnion::operator!=(const TConstantUnion &constant) const
{
return !operator==(constant);
}
bool TConstantUnion::operator>(const TConstantUnion &constant) const
{
ASSERT(type == constant.type);
switch (type)
{
case EbtInt:
return iConst > constant.iConst;
case EbtUInt:
return uConst > constant.uConst;
case EbtFloat:
return fConst > constant.fConst;
default:
return false; // Invalid operation, handled at semantic analysis
}
}
bool TConstantUnion::operator<(const TConstantUnion &constant) const
{
ASSERT(type == constant.type);
switch (type)
{
case EbtInt:
return iConst < constant.iConst;
case EbtUInt:
return uConst < constant.uConst;
case EbtFloat:
return fConst < constant.fConst;
default:
return false; // Invalid operation, handled at semantic analysis
}
}
// static
TConstantUnion TConstantUnion::add(const TConstantUnion &lhs,
const TConstantUnion &rhs,
TDiagnostics *diag,
const TSourceLoc &line)
{
TConstantUnion returnValue;
ASSERT(lhs.type == rhs.type);
switch (lhs.type)
{
case EbtInt:
returnValue.setIConst(gl::WrappingSum<int>(lhs.iConst, rhs.iConst));
break;
case EbtUInt:
returnValue.setUConst(gl::WrappingSum<unsigned int>(lhs.uConst, rhs.uConst));
break;
case EbtFloat:
returnValue.setFConst(CheckedSum<float>(lhs.fConst, rhs.fConst, diag, line));
break;
default:
UNREACHABLE();
}
return returnValue;
}
// static
TConstantUnion TConstantUnion::sub(const TConstantUnion &lhs,
const TConstantUnion &rhs,
TDiagnostics *diag,
const TSourceLoc &line)
{
TConstantUnion returnValue;
ASSERT(lhs.type == rhs.type);
switch (lhs.type)
{
case EbtInt:
returnValue.setIConst(gl::WrappingDiff<int>(lhs.iConst, rhs.iConst));
break;
case EbtUInt:
returnValue.setUConst(gl::WrappingDiff<unsigned int>(lhs.uConst, rhs.uConst));
break;
case EbtFloat:
returnValue.setFConst(CheckedDiff<float>(lhs.fConst, rhs.fConst, diag, line));
break;
default:
UNREACHABLE();
}
return returnValue;
}
// static
TConstantUnion TConstantUnion::mul(const TConstantUnion &lhs,
const TConstantUnion &rhs,
TDiagnostics *diag,
const TSourceLoc &line)
{
TConstantUnion returnValue;
ASSERT(lhs.type == rhs.type);
switch (lhs.type)
{
case EbtInt:
returnValue.setIConst(gl::WrappingMul(lhs.iConst, rhs.iConst));
break;
case EbtUInt:
// Unsigned integer math in C++ is defined to be done in modulo 2^n, so we rely on that
// to implement wrapping multiplication.
returnValue.setUConst(lhs.uConst * rhs.uConst);
break;
case EbtFloat:
returnValue.setFConst(CheckedMul<float>(lhs.fConst, rhs.fConst, diag, line));
break;
default:
UNREACHABLE();
}
return returnValue;
}
TConstantUnion TConstantUnion::operator%(const TConstantUnion &constant) const
{
TConstantUnion returnValue;
ASSERT(type == constant.type);
switch (type)
{
case EbtInt:
returnValue.setIConst(iConst % constant.iConst);
break;
case EbtUInt:
returnValue.setUConst(uConst % constant.uConst);
break;
default:
UNREACHABLE();
}
return returnValue;
}
// static
TConstantUnion TConstantUnion::rshift(const TConstantUnion &lhs,
const TConstantUnion &rhs,
TDiagnostics *diag,
const TSourceLoc &line)
{
TConstantUnion returnValue;
ASSERT(lhs.type == EbtInt || lhs.type == EbtUInt);
ASSERT(rhs.type == EbtInt || rhs.type == EbtUInt);
if ((rhs.type == EbtInt && (rhs.iConst < 0 || rhs.iConst > 31)) ||
(rhs.type == EbtUInt && rhs.uConst > 31u))
{
diag->error(line, "Undefined shift (operand out of range)", ">>", "");
switch (lhs.type)
{
case EbtInt:
returnValue.setIConst(0);
break;
case EbtUInt:
returnValue.setUConst(0u);
break;
default:
UNREACHABLE();
}
return returnValue;
}
switch (lhs.type)
{
case EbtInt:
{
unsigned int shiftOffset = 0;
switch (rhs.type)
{
case EbtInt:
shiftOffset = static_cast<unsigned int>(rhs.iConst);
break;
case EbtUInt:
shiftOffset = rhs.uConst;
break;
default:
UNREACHABLE();
}
if (shiftOffset > 0)
{
// ESSL 3.00.6 section 5.9: "If E1 is a signed integer, the right-shift will extend
// the sign bit." In C++ shifting negative integers is undefined, so we implement
// extending the sign bit manually.
int lhsSafe = lhs.iConst;
if (lhsSafe == std::numeric_limits<int>::min())
{
// The min integer needs special treatment because only bit it has set is the
// sign bit, which we clear later to implement safe right shift of negative
// numbers.
lhsSafe = -0x40000000;
--shiftOffset;
}
if (shiftOffset > 0)
{
bool extendSignBit = false;
if (lhsSafe < 0)
{
extendSignBit = true;
// Clear the sign bit so that bitshift right is defined in C++.
lhsSafe &= 0x7fffffff;
ASSERT(lhsSafe > 0);
}
returnValue.setIConst(lhsSafe >> shiftOffset);
// Manually fill in the extended sign bit if necessary.
if (extendSignBit)
{
int extendedSignBit = static_cast<int>(0xffffffffu << (31 - shiftOffset));
returnValue.setIConst(returnValue.getIConst() | extendedSignBit);
}
}
else
{
returnValue.setIConst(lhsSafe);
}
}
else
{
returnValue.setIConst(lhs.iConst);
}
break;
}
case EbtUInt:
switch (rhs.type)
{
case EbtInt:
returnValue.setUConst(lhs.uConst >> rhs.iConst);
break;
case EbtUInt:
returnValue.setUConst(lhs.uConst >> rhs.uConst);
break;
default:
UNREACHABLE();
}
break;
default:
UNREACHABLE();
}
return returnValue;
}
// static
TConstantUnion TConstantUnion::lshift(const TConstantUnion &lhs,
const TConstantUnion &rhs,
TDiagnostics *diag,
const TSourceLoc &line)
{
TConstantUnion returnValue;
ASSERT(lhs.type == EbtInt || lhs.type == EbtUInt);
ASSERT(rhs.type == EbtInt || rhs.type == EbtUInt);
if ((rhs.type == EbtInt && (rhs.iConst < 0 || rhs.iConst > 31)) ||
(rhs.type == EbtUInt && rhs.uConst > 31u))
{
diag->error(line, "Undefined shift (operand out of range)", "<<", "");
switch (lhs.type)
{
case EbtInt:
returnValue.setIConst(0);
break;
case EbtUInt:
returnValue.setUConst(0u);
break;
default:
UNREACHABLE();
}
return returnValue;
}
switch (lhs.type)
{
case EbtInt:
switch (rhs.type)
{
// Cast to unsigned integer before shifting, since ESSL 3.00.6 section 5.9 says that
// lhs is "interpreted as a bit pattern". This also avoids the possibility of signed
// integer overflow or undefined shift of a negative integer.
case EbtInt:
returnValue.setIConst(
static_cast<int>(static_cast<uint32_t>(lhs.iConst) << rhs.iConst));
break;
case EbtUInt:
returnValue.setIConst(
static_cast<int>(static_cast<uint32_t>(lhs.iConst) << rhs.uConst));
break;
default:
UNREACHABLE();
}
break;
case EbtUInt:
switch (rhs.type)
{
case EbtInt:
returnValue.setUConst(lhs.uConst << rhs.iConst);
break;
case EbtUInt:
returnValue.setUConst(lhs.uConst << rhs.uConst);
break;
default:
UNREACHABLE();
}
break;
default:
UNREACHABLE();
}
return returnValue;
}
TConstantUnion TConstantUnion::operator&(const TConstantUnion &constant) const
{
TConstantUnion returnValue;
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;
default:
UNREACHABLE();
}
return returnValue;
}
TConstantUnion TConstantUnion::operator|(const TConstantUnion &constant) const
{
TConstantUnion returnValue;
ASSERT(type == constant.type);
switch (type)
{
case EbtInt:
returnValue.setIConst(iConst | constant.iConst);
break;
case EbtUInt:
returnValue.setUConst(uConst | constant.uConst);
break;
default:
UNREACHABLE();
}
return returnValue;
}
TConstantUnion TConstantUnion::operator^(const TConstantUnion &constant) const
{
TConstantUnion returnValue;
ASSERT(type == constant.type);
switch (type)
{
case EbtInt:
returnValue.setIConst(iConst ^ constant.iConst);
break;
case EbtUInt:
returnValue.setUConst(uConst ^ constant.uConst);
break;
default:
UNREACHABLE();
}
return returnValue;
}
TConstantUnion TConstantUnion::operator&&(const TConstantUnion &constant) const
{
TConstantUnion returnValue;
ASSERT(type == constant.type);
switch (type)
{
case EbtBool:
returnValue.setBConst(bConst && constant.bConst);
break;
default:
UNREACHABLE();
}
return returnValue;
}
TConstantUnion TConstantUnion::operator||(const TConstantUnion &constant) const
{
TConstantUnion returnValue;
ASSERT(type == constant.type);
switch (type)
{
case EbtBool:
returnValue.setBConst(bConst || constant.bConst);
break;
default:
UNREACHABLE();
}
return returnValue;
}
} // namespace sh

View file

@ -9,21 +9,77 @@
#include <assert.h>
#include "compiler/translator/Common.h"
#include "compiler/translator/BaseTypes.h"
namespace sh
{
class TDiagnostics;
class TConstantUnion
{
public:
class TConstantUnion {
public:
POOL_ALLOCATOR_NEW_DELETE();
TConstantUnion();
TConstantUnion()
{
iConst = 0;
type = EbtVoid;
}
bool cast(TBasicType newType, const TConstantUnion &constant);
bool cast(TBasicType newType, const TConstantUnion &constant)
{
switch (newType)
{
case EbtFloat:
switch (constant.type)
{
case EbtInt: setFConst(static_cast<float>(constant.getIConst())); break;
case EbtUInt: setFConst(static_cast<float>(constant.getUConst())); break;
case EbtBool: setFConst(static_cast<float>(constant.getBConst())); break;
case EbtFloat: setFConst(static_cast<float>(constant.getFConst())); break;
default: return false;
}
break;
case EbtInt:
switch (constant.type)
{
case EbtInt: setIConst(static_cast<int>(constant.getIConst())); break;
case EbtUInt: setIConst(static_cast<int>(constant.getUConst())); break;
case EbtBool: setIConst(static_cast<int>(constant.getBConst())); break;
case EbtFloat: setIConst(static_cast<int>(constant.getFConst())); break;
default: return false;
}
break;
case EbtUInt:
switch (constant.type)
{
case EbtInt: setUConst(static_cast<unsigned int>(constant.getIConst())); break;
case EbtUInt: setUConst(static_cast<unsigned int>(constant.getUConst())); break;
case EbtBool: setUConst(static_cast<unsigned int>(constant.getBConst())); break;
case EbtFloat: setUConst(static_cast<unsigned int>(constant.getFConst())); break;
default: return false;
}
break;
case EbtBool:
switch (constant.type)
{
case EbtInt: setBConst(constant.getIConst() != 0); break;
case EbtUInt: setBConst(constant.getUConst() != 0); break;
case EbtBool: setBConst(constant.getBConst()); break;
case EbtFloat: setBConst(constant.getFConst() != 0.0f); break;
default: return false;
}
break;
case EbtStruct: // Struct fields don't get cast
switch (constant.type)
{
case EbtInt: setIConst(constant.getIConst()); break;
case EbtUInt: setUConst(constant.getUConst()); break;
case EbtBool: setBConst(constant.getBConst()); break;
case EbtFloat: setFConst(constant.getFConst()); break;
default: return false;
}
break;
default:
return false;
}
return true;
}
void setIConst(int i) {iConst = i; type = EbtInt; }
void setUConst(unsigned int u) { uConst = u; type = EbtUInt; }
@ -35,57 +91,258 @@ class TConstantUnion
float getFConst() const { return fConst; }
bool getBConst() const { return bConst; }
bool operator==(const int i) const;
bool operator==(const unsigned int u) const;
bool operator==(const float f) const;
bool operator==(const bool b) const;
bool operator==(const TConstantUnion &constant) const;
bool operator!=(const int i) const;
bool operator!=(const unsigned int u) const;
bool operator!=(const float f) const;
bool operator!=(const bool b) const;
bool operator!=(const TConstantUnion &constant) const;
bool operator>(const TConstantUnion &constant) const;
bool operator<(const TConstantUnion &constant) const;
static TConstantUnion add(const TConstantUnion &lhs,
const TConstantUnion &rhs,
TDiagnostics *diag,
const TSourceLoc &line);
static TConstantUnion sub(const TConstantUnion &lhs,
const TConstantUnion &rhs,
TDiagnostics *diag,
const TSourceLoc &line);
static TConstantUnion mul(const TConstantUnion &lhs,
const TConstantUnion &rhs,
TDiagnostics *diag,
const TSourceLoc &line);
TConstantUnion operator%(const TConstantUnion &constant) const;
static TConstantUnion rshift(const TConstantUnion &lhs,
const TConstantUnion &rhs,
TDiagnostics *diag,
const TSourceLoc &line);
static TConstantUnion lshift(const TConstantUnion &lhs,
const TConstantUnion &rhs,
TDiagnostics *diag,
const TSourceLoc &line);
TConstantUnion operator&(const TConstantUnion &constant) const;
TConstantUnion operator|(const TConstantUnion &constant) const;
TConstantUnion operator^(const TConstantUnion &constant) const;
TConstantUnion operator&&(const TConstantUnion &constant) const;
TConstantUnion operator||(const TConstantUnion &constant) const;
bool operator==(const int i) const
{
return i == iConst;
}
bool operator==(const unsigned int u) const
{
return u == uConst;
}
bool operator==(const float f) const
{
return f == fConst;
}
bool operator==(const bool b) const
{
return b == bConst;
}
bool operator==(const TConstantUnion& constant) const
{
if (constant.type != type)
return false;
switch (type) {
case EbtInt:
return constant.iConst == iConst;
case EbtUInt:
return constant.uConst == uConst;
case EbtFloat:
return constant.fConst == fConst;
case EbtBool:
return constant.bConst == bConst;
default:
return false;
}
}
bool operator!=(const int i) const
{
return !operator==(i);
}
bool operator!=(const unsigned int u) const
{
return !operator==(u);
}
bool operator!=(const float f) const
{
return !operator==(f);
}
bool operator!=(const bool b) const
{
return !operator==(b);
}
bool operator!=(const TConstantUnion& constant) const
{
return !operator==(constant);
}
bool operator>(const TConstantUnion& constant) const
{
assert(type == constant.type);
switch (type) {
case EbtInt:
return iConst > constant.iConst;
case EbtUInt:
return uConst > constant.uConst;
case EbtFloat:
return fConst > constant.fConst;
default:
return false; // Invalid operation, handled at semantic analysis
}
}
bool operator<(const TConstantUnion& constant) const
{
assert(type == constant.type);
switch (type) {
case EbtInt:
return iConst < constant.iConst;
case EbtUInt:
return uConst < constant.uConst;
case EbtFloat:
return fConst < constant.fConst;
default:
return false; // Invalid operation, handled at semantic analysis
}
}
TConstantUnion operator+(const TConstantUnion& constant) const
{
TConstantUnion returnValue;
assert(type == constant.type);
switch (type) {
case EbtInt: returnValue.setIConst(iConst + constant.iConst); break;
case EbtUInt: returnValue.setUConst(uConst + constant.uConst); break;
case EbtFloat: returnValue.setFConst(fConst + constant.fConst); break;
default: assert(false && "Default missing");
}
return returnValue;
}
TConstantUnion operator-(const TConstantUnion& constant) const
{
TConstantUnion returnValue;
assert(type == constant.type);
switch (type) {
case EbtInt: returnValue.setIConst(iConst - constant.iConst); break;
case EbtUInt: returnValue.setUConst(uConst - constant.uConst); break;
case EbtFloat: returnValue.setFConst(fConst - constant.fConst); break;
default: assert(false && "Default missing");
}
return returnValue;
}
TConstantUnion operator*(const TConstantUnion& constant) const
{
TConstantUnion returnValue;
assert(type == constant.type);
switch (type) {
case EbtInt: returnValue.setIConst(iConst * constant.iConst); break;
case EbtUInt: returnValue.setUConst(uConst * constant.uConst); break;
case EbtFloat: returnValue.setFConst(fConst * constant.fConst); break;
default: assert(false && "Default missing");
}
return returnValue;
}
TConstantUnion operator%(const TConstantUnion& constant) const
{
TConstantUnion returnValue;
assert(type == constant.type);
switch (type) {
case EbtInt: returnValue.setIConst(iConst % constant.iConst); break;
case EbtUInt: returnValue.setUConst(uConst % constant.uConst); break;
default: assert(false && "Default missing");
}
return returnValue;
}
TConstantUnion operator>>(const TConstantUnion& constant) const
{
TConstantUnion returnValue;
assert(type == constant.type);
switch (type) {
case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break;
case EbtUInt: returnValue.setUConst(uConst >> constant.uConst); break;
default: assert(false && "Default missing");
}
return returnValue;
}
TConstantUnion operator<<(const TConstantUnion& constant) const
{
TConstantUnion returnValue;
// 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;
default: assert(false && "Default missing");
}
return returnValue;
}
TConstantUnion operator&(const TConstantUnion& constant) const
{
TConstantUnion returnValue;
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;
default: assert(false && "Default missing");
}
return returnValue;
}
TConstantUnion operator|(const TConstantUnion& constant) const
{
TConstantUnion returnValue;
assert(type == constant.type);
switch (type) {
case EbtInt: returnValue.setIConst(iConst | constant.iConst); break;
case EbtUInt: returnValue.setUConst(uConst | constant.uConst); break;
default: assert(false && "Default missing");
}
return returnValue;
}
TConstantUnion operator^(const TConstantUnion& constant) const
{
TConstantUnion returnValue;
assert(type == constant.type);
switch (type) {
case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break;
case EbtUInt: returnValue.setUConst(uConst ^ constant.uConst); break;
default: assert(false && "Default missing");
}
return returnValue;
}
TConstantUnion operator&&(const TConstantUnion& constant) const
{
TConstantUnion returnValue;
assert(type == constant.type);
switch (type) {
case EbtBool: returnValue.setBConst(bConst && constant.bConst); break;
default: assert(false && "Default missing");
}
return returnValue;
}
TConstantUnion operator||(const TConstantUnion& constant) const
{
TConstantUnion returnValue;
assert(type == constant.type);
switch (type) {
case EbtBool: returnValue.setBConst(bConst || constant.bConst); break;
default: assert(false && "Default missing");
}
return returnValue;
}
TBasicType getType() const { return type; }
private:
union {
int iConst; // used for ivec, scalar ints
unsigned int uConst; // used for uvec, scalar uints
bool bConst; // used for bvec, scalar bools
float fConst; // used for vec, mat, scalar floats
};
private:
union {
int iConst; // used for ivec, scalar ints
unsigned int uConst; // used for uvec, scalar uints
bool bConst; // used for bvec, scalar bools
float fConst; // used for vec, mat, scalar floats
} ;
TBasicType type;
};
} // namespace sh
#endif // COMPILER_TRANSLATOR_CONSTANTUNION_H_

View file

@ -15,43 +15,42 @@
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/SymbolTable.h"
namespace sh
{
namespace
{
void SetInternalFunctionName(TFunctionSymbolInfo *functionInfo, const char *name)
void SetInternalFunctionName(TIntermAggregate *functionNode, const char *name)
{
TString nameStr(name);
nameStr = TFunction::mangleName(nameStr);
TName nameObj(nameStr);
nameObj.setInternal(true);
functionInfo->setNameObj(nameObj);
functionNode->setNameObj(nameObj);
}
TIntermAggregate *CreateFunctionPrototypeNode(const char *name, const int functionId)
{
TIntermAggregate *functionNode = new TIntermAggregate(EOpPrototype);
SetInternalFunctionName(functionNode->getFunctionSymbolInfo(), name);
SetInternalFunctionName(functionNode, name);
TType returnType(EbtVoid);
functionNode->setType(returnType);
functionNode->getFunctionSymbolInfo()->setId(functionId);
functionNode->setFunctionId(functionId);
return functionNode;
}
TIntermFunctionDefinition *CreateFunctionDefinitionNode(const char *name,
TIntermBlock *functionBody,
const int functionId)
TIntermAggregate *CreateFunctionDefinitionNode(const char *name,
TIntermAggregate *functionBody,
const int functionId)
{
TType returnType(EbtVoid);
TIntermAggregate *functionNode = new TIntermAggregate(EOpFunction);
TIntermAggregate *paramsNode = new TIntermAggregate(EOpParameters);
TIntermFunctionDefinition *functionNode =
new TIntermFunctionDefinition(returnType, paramsNode, functionBody);
functionNode->getSequence()->push_back(paramsNode);
functionNode->getSequence()->push_back(functionBody);
SetInternalFunctionName(functionNode->getFunctionSymbolInfo(), name);
functionNode->getFunctionSymbolInfo()->setId(functionId);
SetInternalFunctionName(functionNode, name);
TType returnType(EbtVoid);
functionNode->setType(returnType);
functionNode->setFunctionId(functionId);
return functionNode;
}
@ -60,10 +59,10 @@ TIntermAggregate *CreateFunctionCallNode(const char *name, const int functionId)
TIntermAggregate *functionNode = new TIntermAggregate(EOpFunctionCall);
functionNode->setUserDefined();
SetInternalFunctionName(functionNode->getFunctionSymbolInfo(), name);
SetInternalFunctionName(functionNode, name);
TType returnType(EbtVoid);
functionNode->setType(returnType);
functionNode->getFunctionSymbolInfo()->setId(functionId);
functionNode->setFunctionId(functionId);
return functionNode;
}
@ -74,7 +73,7 @@ class DeferGlobalInitializersTraverser : public TIntermTraverser
bool visitBinary(Visit visit, TIntermBinary *node) override;
void insertInitFunction(TIntermBlock *root);
void insertInitFunction(TIntermNode *root);
private:
TIntermSequence mDeferredInitializers;
@ -102,8 +101,10 @@ bool DeferGlobalInitializersTraverser::visitBinary(Visit visit, TIntermBinary *n
// Deferral is done also in any cases where the variable has not been constant folded,
// since otherwise there's a chance that HLSL output will generate extra statements
// from the initializer expression.
TIntermBinary *deferredInit =
new TIntermBinary(EOpAssign, symbolNode->deepCopy(), node->getRight());
TIntermBinary *deferredInit = new TIntermBinary(EOpAssign);
deferredInit->setLeft(symbolNode->deepCopy());
deferredInit->setRight(node->getRight());
deferredInit->setType(node->getType());
mDeferredInitializers.push_back(deferredInit);
// Change const global to a regular global if its initialization is deferred.
@ -114,7 +115,7 @@ bool DeferGlobalInitializersTraverser::visitBinary(Visit visit, TIntermBinary *n
if (symbolNode->getQualifier() == EvqConst)
{
// All of the siblings in the same declaration need to have consistent qualifiers.
auto *siblings = getParentNode()->getAsDeclarationNode()->getSequence();
auto *siblings = getParentNode()->getAsAggregate()->getSequence();
for (TIntermNode *siblingNode : *siblings)
{
TIntermBinary *siblingBinary = siblingNode->getAsBinaryNode();
@ -135,51 +136,56 @@ bool DeferGlobalInitializersTraverser::visitBinary(Visit visit, TIntermBinary *n
return false;
}
void DeferGlobalInitializersTraverser::insertInitFunction(TIntermBlock *root)
void DeferGlobalInitializersTraverser::insertInitFunction(TIntermNode *root)
{
if (mDeferredInitializers.empty())
{
return;
}
const int initFunctionId = TSymbolTable::nextUniqueId();
TIntermAggregate *rootAgg = root->getAsAggregate();
ASSERT(rootAgg != nullptr && rootAgg->getOp() == EOpSequence);
const char *functionName = "initializeDeferredGlobals";
// Add function prototype to the beginning of the shader
TIntermAggregate *functionPrototypeNode =
CreateFunctionPrototypeNode(functionName, initFunctionId);
root->getSequence()->insert(root->getSequence()->begin(), functionPrototypeNode);
rootAgg->getSequence()->insert(rootAgg->getSequence()->begin(), functionPrototypeNode);
// Add function definition to the end of the shader
TIntermBlock *functionBodyNode = new TIntermBlock();
TIntermAggregate *functionBodyNode = new TIntermAggregate(EOpSequence);
TIntermSequence *functionBody = functionBodyNode->getSequence();
for (const auto &deferredInit : mDeferredInitializers)
{
functionBody->push_back(deferredInit);
}
TIntermFunctionDefinition *functionDefinition =
TIntermAggregate *functionDefinition =
CreateFunctionDefinitionNode(functionName, functionBodyNode, initFunctionId);
root->getSequence()->push_back(functionDefinition);
rootAgg->getSequence()->push_back(functionDefinition);
// Insert call into main function
for (TIntermNode *node : *root->getSequence())
for (TIntermNode *node : *rootAgg->getSequence())
{
TIntermFunctionDefinition *nodeFunction = node->getAsFunctionDefinition();
if (nodeFunction != nullptr && nodeFunction->getFunctionSymbolInfo()->isMain())
TIntermAggregate *nodeAgg = node->getAsAggregate();
if (nodeAgg != nullptr && nodeAgg->getOp() == EOpFunction &&
TFunction::unmangleName(nodeAgg->getName()) == "main")
{
TIntermAggregate *functionCallNode =
CreateFunctionCallNode(functionName, initFunctionId);
TIntermBlock *mainBody = nodeFunction->getBody();
ASSERT(mainBody != nullptr);
mainBody->getSequence()->insert(mainBody->getSequence()->begin(), functionCallNode);
TIntermNode *mainBody = nodeAgg->getSequence()->back();
TIntermAggregate *mainBodyAgg = mainBody->getAsAggregate();
ASSERT(mainBodyAgg != nullptr && mainBodyAgg->getOp() == EOpSequence);
mainBodyAgg->getSequence()->insert(mainBodyAgg->getSequence()->begin(),
functionCallNode);
}
}
}
} // namespace
void DeferGlobalInitializers(TIntermBlock *root)
void DeferGlobalInitializers(TIntermNode *root)
{
DeferGlobalInitializersTraverser traverser;
root->traverse(&traverser);
@ -190,5 +196,3 @@ void DeferGlobalInitializers(TIntermBlock *root)
// Add the function with initialization and the call to that.
traverser.insertInitFunction(root);
}
} // namespace sh

View file

@ -13,11 +13,8 @@
#ifndef COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_
#define COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_
class TIntermBlock;
class TIntermNode;
namespace sh
{
void DeferGlobalInitializers(TIntermBlock *root);
} // namespace sh
void DeferGlobalInitializers(TIntermNode *root);
#endif // COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_

View file

@ -11,9 +11,6 @@
#include "compiler/translator/Common.h"
#include "compiler/translator/InfoSink.h"
namespace sh
{
TDiagnostics::TDiagnostics(TInfoSink& infoSink) :
mInfoSink(infoSink),
mNumErrors(0),
@ -82,5 +79,3 @@ void TDiagnostics::print(ID id,
{
writeInfo(severity(id), loc, message(id), text, "");
}
} // namespace sh

View file

@ -10,9 +10,6 @@
#include "common/angleutils.h"
#include "compiler/preprocessor/DiagnosticsBase.h"
namespace sh
{
class TInfoSink;
struct TSourceLoc;
@ -48,6 +45,4 @@ class TDiagnostics : public pp::Diagnostics, angle::NonCopyable
int mNumWarnings;
};
} // namespace sh
#endif // COMPILER_TRANSLATOR_DIAGNOSTICS_H_

View file

@ -12,9 +12,6 @@
#include "common/debug.h"
#include "compiler/translator/Diagnostics.h"
namespace sh
{
static TBehavior getBehavior(const std::string& str)
{
const char kRequire[] = "require";
@ -198,5 +195,3 @@ void TDirectiveHandler::handleVersion(const pp::SourceLocation& loc,
"version number", str, "not supported");
}
}
} // namespace sh

View file

@ -13,8 +13,6 @@
#include "compiler/preprocessor/DirectiveHandlerBase.h"
#include "GLSLANG/ShaderLang.h"
namespace sh
{
class TDiagnostics;
class TDirectiveHandler : public pp::DirectiveHandler, angle::NonCopyable
@ -52,6 +50,4 @@ class TDirectiveHandler : public pp::DirectiveHandler, angle::NonCopyable
bool mDebugShaderPrecisionSupported;
};
} // namespace sh
#endif // COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_

View file

@ -14,60 +14,59 @@
#include "compiler/translator/EmulateGLFragColorBroadcast.h"
#include "compiler/translator/IntermNode.h"
namespace sh
{
namespace
{
TIntermConstantUnion *constructIndexNode(int index)
{
TConstantUnion *u = new TConstantUnion[1];
u[0].setIConst(index);
TType type(EbtInt, EbpUndefined, EvqConst, 1);
TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
return node;
}
TIntermBinary *constructGLFragDataNode(int index)
{
TIntermBinary *indexDirect = new TIntermBinary(EOpIndexDirect);
TIntermSymbol *symbol = new TIntermSymbol(0, "gl_FragData", TType(EbtFloat, 4));
indexDirect->setLeft(symbol);
TIntermConstantUnion *indexNode = constructIndexNode(index);
indexDirect->setRight(indexNode);
return indexDirect;
}
TIntermBinary *constructGLFragDataAssignNode(int index)
{
TIntermBinary *assign = new TIntermBinary(EOpAssign);
assign->setLeft(constructGLFragDataNode(index));
assign->setRight(constructGLFragDataNode(0));
assign->setType(TType(EbtFloat, 4));
return assign;
}
class GLFragColorBroadcastTraverser : public TIntermTraverser
{
public:
GLFragColorBroadcastTraverser(int maxDrawBuffers)
: TIntermTraverser(true, false, false),
mMainSequence(nullptr),
mGLFragColorUsed(false),
mMaxDrawBuffers(maxDrawBuffers)
GLFragColorBroadcastTraverser()
: TIntermTraverser(true, false, false), mMainSequence(nullptr), mGLFragColorUsed(false)
{
}
void broadcastGLFragColor();
void broadcastGLFragColor(int maxDrawBuffers);
bool isGLFragColorUsed() const { return mGLFragColorUsed; }
protected:
void visitSymbol(TIntermSymbol *node) override;
bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
TIntermBinary *constructGLFragDataNode(int index) const;
TIntermBinary *constructGLFragDataAssignNode(int index) const;
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
private:
TIntermSequence *mMainSequence;
bool mGLFragColorUsed;
int mMaxDrawBuffers;
};
TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataNode(int index) const
{
TType gl_FragDataType = TType(EbtFloat, EbpMedium, EvqFragData, 4);
gl_FragDataType.setArraySize(mMaxDrawBuffers);
TIntermSymbol *symbol = new TIntermSymbol(0, "gl_FragData", gl_FragDataType);
TIntermTyped *indexNode = TIntermTyped::CreateIndexNode(index);
TIntermBinary *binary = new TIntermBinary(EOpIndexDirect, symbol, indexNode);
return binary;
}
TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataAssignNode(int index) const
{
TIntermTyped *fragDataIndex = constructGLFragDataNode(index);
TIntermTyped *fragDataZero = constructGLFragDataNode(0);
return new TIntermBinary(EOpAssign, fragDataIndex, fragDataZero);
}
void GLFragColorBroadcastTraverser::visitSymbol(TIntermSymbol *node)
{
if (node->getSymbol() == "gl_FragColor")
@ -77,22 +76,34 @@ void GLFragColorBroadcastTraverser::visitSymbol(TIntermSymbol *node)
}
}
bool GLFragColorBroadcastTraverser::visitFunctionDefinition(Visit visit,
TIntermFunctionDefinition *node)
bool GLFragColorBroadcastTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
{
ASSERT(visit == PreVisit);
if (node->getFunctionSymbolInfo()->isMain())
switch (node->getOp())
{
TIntermBlock *body = node->getBody();
ASSERT(body);
mMainSequence = body->getSequence();
case EOpFunction:
// Function definition.
ASSERT(visit == PreVisit);
if (node->getName() == "main(")
{
TIntermSequence *sequence = node->getSequence();
ASSERT((sequence->size() == 1) || (sequence->size() == 2));
if (sequence->size() == 2)
{
TIntermAggregate *body = (*sequence)[1]->getAsAggregate();
ASSERT(body);
mMainSequence = body->getSequence();
}
}
break;
default:
break;
}
return true;
}
void GLFragColorBroadcastTraverser::broadcastGLFragColor()
void GLFragColorBroadcastTraverser::broadcastGLFragColor(int maxDrawBuffers)
{
ASSERT(mMaxDrawBuffers > 1);
ASSERT(maxDrawBuffers > 1);
if (!mGLFragColorUsed)
{
return;
@ -102,7 +113,7 @@ void GLFragColorBroadcastTraverser::broadcastGLFragColor()
// gl_FragData[1] = gl_FragData[0];
// ...
// gl_FragData[maxDrawBuffers - 1] = gl_FragData[0];
for (int colorIndex = 1; colorIndex < mMaxDrawBuffers; ++colorIndex)
for (int colorIndex = 1; colorIndex < maxDrawBuffers; ++colorIndex)
{
mMainSequence->insert(mMainSequence->end(), constructGLFragDataAssignNode(colorIndex));
}
@ -115,12 +126,12 @@ void EmulateGLFragColorBroadcast(TIntermNode *root,
std::vector<sh::OutputVariable> *outputVariables)
{
ASSERT(maxDrawBuffers > 1);
GLFragColorBroadcastTraverser traverser(maxDrawBuffers);
GLFragColorBroadcastTraverser traverser;
root->traverse(&traverser);
if (traverser.isGLFragColorUsed())
{
traverser.updateTree();
traverser.broadcastGLFragColor();
traverser.broadcastGLFragColor(maxDrawBuffers);
for (auto &var : *outputVariables)
{
if (var.name == "gl_FragColor")
@ -133,5 +144,3 @@ void EmulateGLFragColorBroadcast(TIntermNode *root,
}
}
}
} // namespace sh

View file

@ -15,6 +15,8 @@
namespace sh
{
struct OutputVariable;
}
class TIntermNode;
// Replace all gl_FragColor with gl_FragData[0], and in the end of main() function,
@ -22,7 +24,6 @@ class TIntermNode;
// If gl_FragColor is in outputVariables, it is replaced by gl_FragData.
void EmulateGLFragColorBroadcast(TIntermNode *root,
int maxDrawBuffers,
std::vector<OutputVariable> *outputVariables);
}
std::vector<sh::OutputVariable> *outputVariables);
#endif // COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_

View file

@ -8,9 +8,6 @@
#include <memory>
namespace sh
{
namespace
{
@ -94,7 +91,6 @@ class RoundingHelperWriterHLSL : public RoundingHelperWriter
RoundingHelperWriter *RoundingHelperWriter::createHelperWriter(const ShShaderOutput outputLanguage)
{
ASSERT(EmulatePrecision::SupportedInLanguage(outputLanguage));
switch (outputLanguage)
{
case SH_HLSL_4_1_OUTPUT:
@ -102,6 +98,9 @@ RoundingHelperWriter *RoundingHelperWriter::createHelperWriter(const ShShaderOut
case SH_ESSL_OUTPUT:
return new RoundingHelperWriterESSL(outputLanguage);
default:
// Other languages not yet supported
ASSERT(outputLanguage == SH_GLSL_COMPATIBILITY_OUTPUT ||
IsGLSL130OrNewer(outputLanguage));
return new RoundingHelperWriterGLSL(outputLanguage);
}
}
@ -433,7 +432,7 @@ TIntermAggregate *createInternalFunctionCallNode(TString name, TIntermNode *chil
callNode->setOp(EOpFunctionCall);
TName nameObj(TFunction::mangleName(name));
nameObj.setInternal(true);
callNode->getFunctionSymbolInfo()->setNameObj(nameObj);
callNode->setNameObj(nameObj);
callNode->getSequence()->push_back(child);
return callNode;
}
@ -470,16 +469,15 @@ bool parentUsesResult(TIntermNode* parent, TIntermNode* node)
return false;
}
TIntermBlock *blockParent = parent->getAsBlock();
// If the parent is a block, the result is not assigned anywhere,
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 (blockParent)
if (aggParent && aggParent->getOp() == EOpSequence)
{
return false;
}
TIntermBinary *binaryParent = parent->getAsBinaryNode();
if (binaryParent && binaryParent->getOp() == EOpComma && (binaryParent->getRight() != node))
if (aggParent && aggParent->getOp() == EOpComma && (aggParent->getSequence()->back() != node))
{
return false;
}
@ -513,7 +511,7 @@ bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node)
if (op == EOpInitialize && visit == InVisit)
mDeclaringVariables = false;
if ((op == EOpIndexDirectStruct) && visit == InVisit)
if ((op == EOpIndexDirectStruct || op == EOpVectorSwizzle) && visit == InVisit)
visitChildren = false;
if (visit != PreVisit)
@ -601,30 +599,14 @@ bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node)
return visitChildren;
}
bool EmulatePrecision::visitDeclaration(Visit visit, TIntermDeclaration *node)
{
// Variable or interface block declaration.
if (visit == PreVisit)
{
mDeclaringVariables = true;
}
else if (visit == InVisit)
{
mDeclaringVariables = true;
}
else
{
mDeclaringVariables = false;
}
return true;
}
bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node)
{
bool visitChildren = true;
switch (node->getOp())
{
case EOpSequence:
case EOpConstructStruct:
case EOpFunction:
break;
case EOpPrototype:
visitChildren = false;
@ -635,6 +617,21 @@ bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node)
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.
@ -708,19 +705,3 @@ void EmulatePrecision::writeEmulationHelpers(TInfoSinkBase &sink,
roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "*", "mul");
}
// static
bool EmulatePrecision::SupportedInLanguage(const ShShaderOutput outputLanguage)
{
switch (outputLanguage)
{
case SH_HLSL_4_1_OUTPUT:
case SH_ESSL_OUTPUT:
return true;
default:
// Other languages not yet supported
return (outputLanguage == SH_GLSL_COMPATIBILITY_OUTPUT ||
sh::IsGLSL130OrNewer(outputLanguage));
}
}
} // namespace sh

View file

@ -18,9 +18,6 @@
// need to write a huge number of variations of the emulated compound assignment
// to every translated shader with emulation enabled.
namespace sh
{
class EmulatePrecision : public TLValueTrackingTraverser
{
public:
@ -30,14 +27,11 @@ class EmulatePrecision : public TLValueTrackingTraverser
bool visitBinary(Visit visit, TIntermBinary *node) override;
bool visitUnary(Visit visit, TIntermUnary *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
void writeEmulationHelpers(TInfoSinkBase &sink,
const int shaderVersion,
const ShShaderOutput outputLanguage);
static bool SupportedInLanguage(const ShShaderOutput outputLanguage);
private:
struct TypePair
{
@ -67,6 +61,4 @@ class EmulatePrecision : public TLValueTrackingTraverser
bool mDeclaringVariables;
};
} // namespace sh
#endif // COMPILER_TRANSLATOR_EMULATE_PRECISION_H_

View file

@ -116,7 +116,7 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
TIntermTyped *lhs = sequence->at(0)->getAsTyped();
ASSERT(lhs);
TIntermDeclaration *init = createTempInitDeclaration(lhs);
TIntermAggregate *init = createTempInitDeclaration(lhs);
TIntermTyped *current = createTempSymbol(lhs->getType());
insertStatementInParentBlock(init);
@ -124,7 +124,10 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
// Create a chain of n-1 multiples.
for (int i = 1; i < n; ++i)
{
TIntermBinary *mul = new TIntermBinary(EOpMul, current, createTempSymbol(lhs->getType()));
TIntermBinary *mul = new TIntermBinary(EOpMul);
mul->setLeft(current);
mul->setRight(createTempSymbol(lhs->getType()));
mul->setType(node->getType());
mul->setLine(node->getLine());
current = mul;
}
@ -135,7 +138,9 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
TConstantUnion *oneVal = new TConstantUnion();
oneVal->setFConst(1.0f);
TIntermConstantUnion *oneNode = new TIntermConstantUnion(oneVal, node->getType());
TIntermBinary *div = new TIntermBinary(EOpDiv, oneNode, current);
TIntermBinary *div = new TIntermBinary(EOpDiv);
div->setLeft(oneNode);
div->setRight(current);
current = div;
}

View file

@ -10,9 +10,6 @@
#include "compiler/translator/VersionGLSL.h"
namespace sh
{
TExtensionGLSL::TExtensionGLSL(ShShaderOutput output)
: TIntermTraverser(true, false, false), mTargetVersion(ShaderOutputTypeToGLSLVersion(output))
{
@ -101,5 +98,3 @@ void TExtensionGLSL::checkOperator(TIntermOperator *node)
break;
}
}
} // namespace sh

View file

@ -14,9 +14,6 @@
#include "compiler/translator/IntermNode.h"
namespace sh
{
// Traverses the intermediate tree to determine which GLSL extensions are required
// to support the shader.
class TExtensionGLSL : public TIntermTraverser
@ -39,6 +36,4 @@ class TExtensionGLSL : public TIntermTraverser
std::set<std::string> mRequiredExtensions;
};
} // namespace sh
#endif // COMPILER_TRANSLATOR_EXTENSIONGLSL_H_

View file

@ -9,9 +9,6 @@
#include "compiler/translator/ValidateLimitations.h"
#include "angle_gl.h"
namespace sh
{
bool ForLoopUnrollMarker::visitBinary(Visit, TIntermBinary *node)
{
if (mUnrollCondition != kSamplerArrayIndex)
@ -54,7 +51,7 @@ bool ForLoopUnrollMarker::visitLoop(Visit, TIntermLoop *node)
// Check if loop index type is integer.
// This is called after ValidateLimitations pass, so the loop has the limited form specified
// in ESSL 1.00 appendix A.
TIntermSequence *declSeq = node->getInit()->getAsDeclarationNode()->getSequence();
TIntermSequence *declSeq = node->getInit()->getAsAggregate()->getSequence();
TIntermSymbol *symbol = (*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode();
if (symbol->getBasicType() == EbtInt)
node->setUnrollFlag(true);
@ -98,5 +95,3 @@ void ForLoopUnrollMarker::visitSymbol(TIntermSymbol* symbol)
}
}
}
} // namespace sh

View file

@ -9,9 +9,6 @@
#include "compiler/translator/LoopInfo.h"
namespace sh
{
// This class detects for-loops that needs to be unrolled.
// Currently we support two unroll conditions:
// 1) kForLoopWithIntegerIndex: unroll if the index type is integer.
@ -53,6 +50,4 @@ class ForLoopUnrollMarker : public TIntermTraverser
bool mHasRunLoopValidation;
};
} // namespace sh
#endif // COMPILER_TRANSLATOR_FORLOOPUNROLL_H_

View file

@ -6,9 +6,6 @@
#include "compiler/translator/InfoSink.h"
namespace sh
{
void TInfoSinkBase::prefix(TPrefixType p) {
switch(p) {
case EPrefixNone:
@ -55,5 +52,3 @@ void TInfoSinkBase::message(TPrefixType p, const TSourceLoc& loc, const char* m)
sink.append(m);
sink.append("\n");
}
} // namespace sh

View file

@ -11,9 +11,6 @@
#include <stdlib.h>
#include "compiler/translator/Common.h"
namespace sh
{
// Returns the fractional part of the given floating-point number.
inline float fractionalPart(float f) {
float intPart = 0.0f;
@ -116,6 +113,4 @@ public:
TInfoSinkBase obj;
};
} // namespace sh
#endif // COMPILER_TRANSLATOR_INFOSINK_H_

View file

@ -16,12 +16,8 @@
#include "compiler/translator/IntermNode.h"
#include "angle_gl.h"
namespace sh
{
void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable)
{
const TType *voidType = TCache::getType(EbtVoid);
const TType *float1 = TCache::getType(EbtFloat);
const TType *float2 = TCache::getType(EbtFloat, 2);
const TType *float3 = TCache::getType(EbtFloat, 3);
@ -473,26 +469,6 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler3D, float4, float3, float3, int3);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjGradOffset", sampler2DShadow, float4, float2, float2, int2);
const TType *gimage2D = TCache::getType(EbtGImage2D);
const TType *gimage3D = TCache::getType(EbtGImage3D);
const TType *gimage2DArray = TCache::getType(EbtGImage2DArray);
const TType *gimageCube = TCache::getType(EbtGImageCube);
symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimage2D, int2, gvec4);
symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimage3D, int3, gvec4);
symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimage2DArray, int3, gvec4);
symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimageCube, int3, gvec4);
symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimage2D, int2);
symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimage3D, int3);
symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimage2DArray, int3);
symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimageCube, int3);
symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int2, "imageSize", gimage2D);
symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int3, "imageSize", gimage3D);
symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int3, "imageSize", gimage2DArray);
symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int3, "imageSize", gimageCube);
//
// Depth range in window coordinates
//
@ -535,13 +511,16 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
symbolTable.insertConstInt(ESSL1_BUILTINS, "gl_MaxVaryingVectors", resources.MaxVaryingVectors,
EbpMedium);
symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxDrawBuffers", resources.MaxDrawBuffers,
EbpMedium);
if (resources.EXT_blend_func_extended)
if (spec != SH_CSS_SHADERS_SPEC)
{
symbolTable.insertConstIntExt(COMMON_BUILTINS, "GL_EXT_blend_func_extended",
"gl_MaxDualSourceDrawBuffersEXT",
resources.MaxDualSourceDrawBuffers);
symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxDrawBuffers", resources.MaxDrawBuffers,
EbpMedium);
if (resources.EXT_blend_func_extended)
{
symbolTable.insertConstIntExt(COMMON_BUILTINS, "GL_EXT_blend_func_extended",
"gl_MaxDualSourceDrawBuffersEXT",
resources.MaxDualSourceDrawBuffers);
}
}
symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxVertexOutputVectors",
@ -611,73 +590,85 @@ void IdentifyBuiltIns(sh::GLenum type, ShShaderSpec spec,
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)));
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)));
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));
//
// 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)));
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_blend_func_extended)
{
symbolTable.insert(
ESSL1_BUILTINS, "GL_EXT_blend_func_extended",
new TVariable(NewPoolTString("gl_SecondaryFragColorEXT"),
TType(EbtFloat, EbpMedium, EvqSecondaryFragColorEXT, 4)));
TType secondaryFragData(EbtFloat, EbpMedium, EvqSecondaryFragDataEXT, 4, 1, true);
secondaryFragData.setArraySize(resources.MaxDualSourceDrawBuffers);
symbolTable.insert(
ESSL1_BUILTINS, "GL_EXT_blend_func_extended",
new TVariable(NewPoolTString("gl_SecondaryFragDataEXT"), secondaryFragData));
}
if (resources.EXT_blend_func_extended)
{
symbolTable.insert(
ESSL1_BUILTINS, "GL_EXT_blend_func_extended",
new TVariable(NewPoolTString("gl_SecondaryFragColorEXT"),
TType(EbtFloat, EbpMedium, EvqSecondaryFragColorEXT, 4)));
TType secondaryFragData(EbtFloat, EbpMedium, EvqSecondaryFragDataEXT, 4, 1, true);
secondaryFragData.setArraySize(resources.MaxDualSourceDrawBuffers);
symbolTable.insert(
ESSL1_BUILTINS, "GL_EXT_blend_func_extended",
new TVariable(NewPoolTString("gl_SecondaryFragDataEXT"), secondaryFragData));
}
if (resources.EXT_frag_depth)
{
symbolTable.insert(
ESSL1_BUILTINS, "GL_EXT_frag_depth",
new TVariable(
NewPoolTString("gl_FragDepthEXT"),
TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium,
EvqFragDepthEXT, 1)));
}
if (resources.EXT_frag_depth)
{
symbolTable.insert(
ESSL1_BUILTINS, "GL_EXT_frag_depth",
new TVariable(
NewPoolTString("gl_FragDepthEXT"),
TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium,
EvqFragDepthEXT, 1)));
}
symbolTable.insert(ESSL3_BUILTINS,
new TVariable(NewPoolTString("gl_FragDepth"),
TType(EbtFloat, EbpHigh, EvqFragDepth, 1)));
symbolTable.insert(ESSL3_BUILTINS,
new TVariable(NewPoolTString("gl_FragDepth"),
TType(EbtFloat, EbpHigh, 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 || 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)));
}
}
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;
@ -758,5 +749,3 @@ void ResetExtensionBehavior(TExtensionBehavior &extBehavior)
ext_iter->second = EBhUndefined;
}
}
} // namespace sh

View file

@ -11,9 +11,6 @@
#include "compiler/translator/Compiler.h"
#include "compiler/translator/SymbolTable.h"
namespace sh
{
void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &table);
void IdentifyBuiltIns(sh::GLenum type, ShShaderSpec spec,
@ -29,6 +26,4 @@ void InitExtensionBehavior(const ShBuiltInResources& resources,
// extensions will remain unsupported.
void ResetExtensionBehavior(TExtensionBehavior &extensionBehavior);
} // namespace sh
#endif // COMPILER_TRANSLATOR_INITIALIZE_H_

View file

@ -13,9 +13,6 @@
#include <assert.h>
namespace sh
{
bool InitProcess()
{
if (!InitializePoolIndex()) {
@ -39,5 +36,3 @@ void DetachProcess()
FreePoolIndex();
TCache::destroy();
}
} // namespace sh

View file

@ -6,11 +6,8 @@
#ifndef COMPILER_TRANSLATOR_INITIALIZEDLL_H_
#define COMPILER_TRANSLATOR_INITIALIZEDLL_H_
namespace sh
{
bool InitProcess();
void DetachProcess();
} // namespace sh
#endif // COMPILER_TRANSLATOR_INITIALIZEDLL_H_

View file

@ -10,9 +10,6 @@
#include <assert.h>
namespace sh
{
TLSIndex GlobalParseContextIndex = TLS_INVALID_INDEX;
bool InitializeParseContextIndex()
@ -43,4 +40,3 @@ TParseContext* GetGlobalParseContext()
return static_cast<TParseContext*>(GetTLSValue(GlobalParseContextIndex));
}
} // namespace sh

View file

@ -7,15 +7,11 @@
#ifndef COMPILER_TRANSLATOR_INITIALIZEPARSECONTEXT_H_
#define COMPILER_TRANSLATOR_INITIALIZEPARSECONTEXT_H_
namespace sh
{
bool InitializeParseContextIndex();
void FreeParseContextIndex();
class TParseContext;
extern void SetGlobalParseContext(TParseContext* context);
extern TParseContext* GetGlobalParseContext();
} // namespace sh
#endif // COMPILER_TRANSLATOR_INITIALIZEPARSECONTEXT_H_

View file

@ -9,122 +9,191 @@
#include "angle_gl.h"
#include "common/debug.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/util.h"
namespace sh
{
namespace
{
TIntermConstantUnion *constructConstUnionNode(const TType &type)
{
TType myType = type;
myType.clearArrayness();
myType.setQualifier(EvqConst);
size_t size = myType.getObjectSize();
TConstantUnion *u = new TConstantUnion[size];
for (size_t ii = 0; ii < size; ++ii)
{
switch (type.getBasicType())
{
case EbtFloat:
u[ii].setFConst(0.0f);
break;
case EbtInt:
u[ii].setIConst(0);
break;
case EbtUInt:
u[ii].setUConst(0u);
break;
default:
UNREACHABLE();
return nullptr;
}
}
TIntermConstantUnion *node = new TIntermConstantUnion(u, myType);
return node;
}
TIntermConstantUnion *constructIndexNode(int index)
{
TConstantUnion *u = new TConstantUnion[1];
u[0].setIConst(index);
TType type(EbtInt, EbpUndefined, EvqConst, 1);
TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
return node;
}
class VariableInitializer : public TIntermTraverser
{
public:
VariableInitializer(const InitVariableList &vars, const TSymbolTable &symbolTable)
: TIntermTraverser(true, false, false),
mVariables(vars),
mSymbolTable(symbolTable),
mCodeInserted(false)
VariableInitializer(const InitVariableList &vars)
: TIntermTraverser(true, false, false), mVariables(vars), mCodeInserted(false)
{
ASSERT(mSymbolTable.atGlobalLevel());
}
protected:
bool visitBinary(Visit, TIntermBinary *node) override { return false; }
bool visitUnary(Visit, TIntermUnary *node) override { return false; }
bool visitIfElse(Visit, TIntermIfElse *node) override { return false; }
bool visitSelection(Visit, TIntermSelection *node) override { return false; }
bool visitLoop(Visit, TIntermLoop *node) override { return false; }
bool visitBranch(Visit, TIntermBranch *node) override { return false; }
bool visitAggregate(Visit, TIntermAggregate *node) override { return false; }
bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
private:
void insertInitCode(TIntermSequence *sequence);
const InitVariableList &mVariables;
const TSymbolTable &mSymbolTable;
bool mCodeInserted;
};
// VariableInitializer implementation.
bool VariableInitializer::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
bool VariableInitializer::visitAggregate(Visit visit, TIntermAggregate *node)
{
// Function definition.
ASSERT(visit == PreVisit);
if (node->getFunctionSymbolInfo()->isMain())
bool visitChildren = !mCodeInserted;
switch (node->getOp())
{
TIntermBlock *body = node->getBody();
insertInitCode(body->getSequence());
mCodeInserted = true;
case EOpSequence:
break;
case EOpFunction:
{
// Function definition.
ASSERT(visit == PreVisit);
if (node->getName() == "main(")
{
TIntermSequence *sequence = node->getSequence();
ASSERT((sequence->size() == 1) || (sequence->size() == 2));
TIntermAggregate *body = NULL;
if (sequence->size() == 1)
{
body = new TIntermAggregate(EOpSequence);
sequence->push_back(body);
}
else
{
body = (*sequence)[1]->getAsAggregate();
}
ASSERT(body);
insertInitCode(body->getSequence());
mCodeInserted = true;
}
break;
}
default:
visitChildren = false;
break;
}
return false;
return visitChildren;
}
void VariableInitializer::insertInitCode(TIntermSequence *sequence)
{
for (const auto &var : mVariables)
for (size_t ii = 0; ii < mVariables.size(); ++ii)
{
const sh::ShaderVariable &var = mVariables[ii];
TString name = TString(var.name.c_str());
if (var.isArray())
{
// Assign the array elements one by one to keep the AST compatible with ESSL 1.00 which
// doesn't have array assignment.
TType type = sh::ConvertShaderVariableTypeToTType(var.type);
size_t pos = name.find_last_of('[');
if (pos != TString::npos)
{
name = name.substr(0, pos);
}
TType elementType = sh::GetShaderVariableBasicType(var);
TType arrayType = elementType;
arrayType.setArraySize(var.elementCount());
for (unsigned int i = 0; i < var.arraySize; ++i)
for (int index = static_cast<int>(var.arraySize) - 1; index >= 0; --index)
{
TIntermSymbol *arraySymbol = new TIntermSymbol(0, name, arrayType);
TIntermBinary *element = new TIntermBinary(EOpIndexDirect, arraySymbol,
TIntermTyped::CreateIndexNode(i));
TIntermBinary *assign = new TIntermBinary(EOpAssign);
sequence->insert(sequence->begin(), assign);
TIntermTyped *zero = TIntermTyped::CreateZero(elementType);
TIntermBinary *assignment = new TIntermBinary(EOpAssign, element, zero);
TIntermBinary *indexDirect = new TIntermBinary(EOpIndexDirect);
TIntermSymbol *symbol = new TIntermSymbol(0, name, type);
indexDirect->setLeft(symbol);
TIntermConstantUnion *indexNode = constructIndexNode(index);
indexDirect->setRight(indexNode);
sequence->insert(sequence->begin(), assignment);
assign->setLeft(indexDirect);
TIntermConstantUnion *zeroConst = constructConstUnionNode(type);
assign->setRight(zeroConst);
}
}
else if (var.isStruct())
{
TVariable *structInfo = reinterpret_cast<TVariable *>(mSymbolTable.findGlobal(name));
ASSERT(structInfo);
TFieldList *fields = new TFieldList;
TSourceLoc loc;
for (auto field : var.fields)
{
fields->push_back(new TField(nullptr, new TString(field.name.c_str()), loc));
}
TStructure *structure = new TStructure(new TString(var.structName.c_str()), fields);
TType type;
type.setStruct(structure);
for (int fieldIndex = 0; fieldIndex < static_cast<int>(var.fields.size()); ++fieldIndex)
{
TIntermBinary *assign = new TIntermBinary(EOpAssign);
sequence->insert(sequence->begin(), assign);
TIntermSymbol *symbol = new TIntermSymbol(0, name, structInfo->getType());
TIntermTyped *zero = TIntermTyped::CreateZero(structInfo->getType());
TIntermBinary *indexDirectStruct = new TIntermBinary(EOpIndexDirectStruct);
TIntermSymbol *symbol = new TIntermSymbol(0, name, type);
indexDirectStruct->setLeft(symbol);
TIntermConstantUnion *indexNode = constructIndexNode(fieldIndex);
indexDirectStruct->setRight(indexNode);
assign->setLeft(indexDirectStruct);
TIntermBinary *assign = new TIntermBinary(EOpAssign, symbol, zero);
sequence->insert(sequence->begin(), assign);
const sh::ShaderVariable &field = var.fields[fieldIndex];
TType fieldType = sh::ConvertShaderVariableTypeToTType(field.type);
TIntermConstantUnion *zeroConst = constructConstUnionNode(fieldType);
assign->setRight(zeroConst);
}
}
else
{
TType type = sh::GetShaderVariableBasicType(var);
TIntermSymbol *symbol = new TIntermSymbol(0, name, type);
TIntermTyped *zero = TIntermTyped::CreateZero(type);
TIntermBinary *assign = new TIntermBinary(EOpAssign, symbol, zero);
TType type = sh::ConvertShaderVariableTypeToTType(var.type);
TIntermBinary *assign = new TIntermBinary(EOpAssign);
sequence->insert(sequence->begin(), assign);
TIntermSymbol *symbol = new TIntermSymbol(0, name, type);
assign->setLeft(symbol);
TIntermConstantUnion *zeroConst = constructConstUnionNode(type);
assign->setRight(zeroConst);
}
}
}
} // namespace anonymous
void InitializeVariables(TIntermNode *root,
const InitVariableList &vars,
const TSymbolTable &symbolTable)
void InitializeVariables(TIntermNode *root, const InitVariableList &vars)
{
VariableInitializer initializer(vars, symbolTable);
VariableInitializer initializer(vars);
root->traverse(&initializer);
}
} // namespace sh

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