Update ANGLE to chromium/2651
Change-Id: I1cd32b780b1a0b913fab870e155ae1f4f9ac40d7 Reviewed-by: Maurice Kalinowski <maurice.kalinowski@qt.io>
This commit is contained in:
parent
d3dcc6f610
commit
e12ba07322
1
src/3rdparty/angle/AUTHORS
vendored
1
src/3rdparty/angle/AUTHORS
vendored
@ -41,3 +41,4 @@ Aitor Moreno
|
||||
Yuri O'Donnell
|
||||
Josh Soref
|
||||
Maks Naumov
|
||||
Jinyoung Hur
|
||||
|
3
src/3rdparty/angle/CONTRIBUTORS
vendored
3
src/3rdparty/angle/CONTRIBUTORS
vendored
@ -90,6 +90,7 @@ Microsoft Corporation
|
||||
Cooper Partin
|
||||
Austin Kinross
|
||||
Minmin Gong
|
||||
Shawn Hargreaves
|
||||
|
||||
Microsoft Open Technologies, Inc.
|
||||
Cooper Partin
|
||||
@ -99,6 +100,8 @@ NVIDIA Corporation
|
||||
Olli Etuaho
|
||||
Arun Patole
|
||||
Qingqing Deng
|
||||
Kimmo Kinnunen
|
||||
|
||||
Opera Software ASA
|
||||
Daniel Bratell
|
||||
Tomasz Moniuszko
|
||||
|
2
src/3rdparty/angle/LICENSE
vendored
2
src/3rdparty/angle/LICENSE
vendored
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2002-2013 The ANGLE Project Authors.
|
||||
// Copyright (C) 2002-2013 The ANGLE Project Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
|
6
src/3rdparty/angle/include/EGL/egl.h
vendored
6
src/3rdparty/angle/include/EGL/egl.h
vendored
@ -6,7 +6,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Copyright (c) 2013-2014 The Khronos Group Inc.
|
||||
** Copyright (c) 2013-2015 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
@ -33,12 +33,12 @@ extern "C" {
|
||||
** used to make the header, and the header can be found at
|
||||
** http://www.opengl.org/registry/
|
||||
**
|
||||
** Khronos $Revision: 29318 $ on $Date: 2015-01-02 03:16:10 -0800 (Fri, 02 Jan 2015) $
|
||||
** Khronos $Revision: 31566 $ on $Date: 2015-06-23 08:48:48 -0700 (Tue, 23 Jun 2015) $
|
||||
*/
|
||||
|
||||
#include <EGL/eglplatform.h>
|
||||
|
||||
/* Generated on date 20150102 */
|
||||
/* Generated on date 20150623 */
|
||||
|
||||
/* Generated C header for:
|
||||
* API: egl
|
||||
|
236
src/3rdparty/angle/include/EGL/eglext.h
vendored
236
src/3rdparty/angle/include/EGL/eglext.h
vendored
@ -6,7 +6,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Copyright (c) 2013-2014 The Khronos Group Inc.
|
||||
** Copyright (c) 2013-2015 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
@ -33,12 +33,12 @@ extern "C" {
|
||||
** used to make the header, and the header can be found at
|
||||
** http://www.opengl.org/registry/
|
||||
**
|
||||
** Khronos $Revision: 27018 $ on $Date: 2014-06-10 08:06:12 -0700 (Tue, 10 Jun 2014) $
|
||||
** Khronos $Revision: 31566 $ on $Date: 2015-06-23 08:48:48 -0700 (Tue, 23 Jun 2015) $
|
||||
*/
|
||||
|
||||
#include <EGL/eglplatform.h>
|
||||
|
||||
#define EGL_EGLEXT_VERSION 20140610
|
||||
#define EGL_EGLEXT_VERSION 20150623
|
||||
|
||||
/* Generated C header for:
|
||||
* API: egl
|
||||
@ -94,12 +94,28 @@ EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type,
|
||||
#define EGL_OPENGL_ES3_BIT_KHR 0x00000040
|
||||
#endif /* EGL_KHR_create_context */
|
||||
|
||||
#ifndef EGL_KHR_create_context_no_error
|
||||
#define EGL_KHR_create_context_no_error 1
|
||||
#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31B3
|
||||
#endif /* EGL_KHR_create_context_no_error */
|
||||
|
||||
#ifndef EGL_KHR_fence_sync
|
||||
#define EGL_KHR_fence_sync 1
|
||||
typedef khronos_utime_nanoseconds_t EGLTimeKHR;
|
||||
#ifdef KHRONOS_SUPPORT_INT64
|
||||
#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0
|
||||
#define EGL_SYNC_CONDITION_KHR 0x30F8
|
||||
#define EGL_SYNC_FENCE_KHR 0x30F9
|
||||
typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync);
|
||||
typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR (EGLDisplay dpy, EGLSyncKHR sync);
|
||||
EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
|
||||
#endif
|
||||
#endif /* KHRONOS_SUPPORT_INT64 */
|
||||
#endif /* EGL_KHR_fence_sync */
|
||||
|
||||
@ -207,6 +223,15 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface64KHR (EGLDisplay dpy, EGLSurface s
|
||||
#endif
|
||||
#endif /* EGL_KHR_lock_surface3 */
|
||||
|
||||
#ifndef EGL_KHR_partial_update
|
||||
#define EGL_KHR_partial_update 1
|
||||
#define EGL_BUFFER_AGE_KHR 0x313D
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETDAMAGEREGIONKHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglSetDamageRegionKHR (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
|
||||
#endif
|
||||
#endif /* EGL_KHR_partial_update */
|
||||
|
||||
#ifndef EGL_KHR_platform_android
|
||||
#define EGL_KHR_platform_android 1
|
||||
#define EGL_PLATFORM_ANDROID_KHR 0x3141
|
||||
@ -230,7 +255,6 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface64KHR (EGLDisplay dpy, EGLSurface s
|
||||
|
||||
#ifndef EGL_KHR_reusable_sync
|
||||
#define EGL_KHR_reusable_sync 1
|
||||
typedef khronos_utime_nanoseconds_t EGLTimeKHR;
|
||||
#ifdef KHRONOS_SUPPORT_INT64
|
||||
#define EGL_SYNC_STATUS_KHR 0x30F1
|
||||
#define EGL_SIGNALED_KHR 0x30F2
|
||||
@ -242,17 +266,9 @@ typedef khronos_utime_nanoseconds_t EGLTimeKHR;
|
||||
#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR 0x0001
|
||||
#define EGL_FOREVER_KHR 0xFFFFFFFFFFFFFFFFull
|
||||
#define EGL_NO_SYNC_KHR ((EGLSyncKHR)0)
|
||||
typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync);
|
||||
typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR (EGLDisplay dpy, EGLSyncKHR sync);
|
||||
EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
|
||||
#endif
|
||||
#endif /* KHRONOS_SUPPORT_INT64 */
|
||||
#endif /* EGL_KHR_reusable_sync */
|
||||
@ -354,6 +370,14 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreateStreamProducerSurfaceKHR (EGLDisplay dpy,
|
||||
#define EGL_KHR_surfaceless_context 1
|
||||
#endif /* EGL_KHR_surfaceless_context */
|
||||
|
||||
#ifndef EGL_KHR_swap_buffers_with_damage
|
||||
#define EGL_KHR_swap_buffers_with_damage 1
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEKHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageKHR (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
|
||||
#endif
|
||||
#endif /* EGL_KHR_swap_buffers_with_damage */
|
||||
|
||||
#ifndef EGL_KHR_vg_parent_image
|
||||
#define EGL_KHR_vg_parent_image 1
|
||||
#define EGL_VG_PARENT_IMAGE_KHR 0x30BA
|
||||
@ -410,10 +434,16 @@ EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID (EGLDisplay dpy, EGLSyncKHR
|
||||
#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
|
||||
#endif /* EGL_ANGLE_d3d_share_handle_client_buffer */
|
||||
|
||||
#ifndef EGL_ANGLE_window_fixed_size
|
||||
#define EGL_ANGLE_window_fixed_size 1
|
||||
#define EGL_FIXED_SIZE_ANGLE 0x3201
|
||||
#endif /* EGL_ANGLE_window_fixed_size */
|
||||
#ifndef EGL_ANGLE_device_d3d
|
||||
#define EGL_ANGLE_device_d3d 1
|
||||
#define EGL_D3D9_DEVICE_ANGLE 0x33A0
|
||||
#define EGL_D3D11_DEVICE_ANGLE 0x33A1
|
||||
#endif /* EGL_ANGLE_device_d3d */
|
||||
|
||||
#ifndef EGL_ANGLE_keyed_mutex
|
||||
#define EGL_ANGLE_keyed_mutex 1
|
||||
#define EGL_DXGI_KEYED_MUTEX_ANGLE 0x33A2
|
||||
#endif /* EGL_ANGLE_keyed_mutex */
|
||||
|
||||
#ifndef EGL_ANGLE_query_surface_pointer
|
||||
#define EGL_ANGLE_query_surface_pointer 1
|
||||
@ -438,6 +468,11 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu
|
||||
#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
|
||||
#endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */
|
||||
|
||||
#ifndef EGL_ANGLE_direct_composition
|
||||
#define EGL_ANGLE_direct_composition 1
|
||||
#define EGL_DIRECT_COMPOSITION_ANGLE 0x33A5
|
||||
#endif /* EGL_ANGLE_direct_composition */
|
||||
|
||||
#ifndef EGL_ANGLE_platform_angle
|
||||
#define EGL_ANGLE_platform_angle 1
|
||||
#define EGL_PLATFORM_ANGLE_ANGLE 0x3202
|
||||
@ -464,6 +499,36 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu
|
||||
#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320E
|
||||
#endif /* EGL_ANGLE_platform_angle_opengl */
|
||||
|
||||
#ifndef EGL_ANGLE_window_fixed_size
|
||||
#define EGL_ANGLE_window_fixed_size 1
|
||||
#define EGL_FIXED_SIZE_ANGLE 0x3201
|
||||
#endif /* EGL_ANGLE_window_fixed_size */
|
||||
|
||||
#ifndef EGL_ANGLE_x11_visual
|
||||
#define EGL_ANGLE_x11_visual
|
||||
#define EGL_X11_VISUAL_ID_ANGLE 0x33A3
|
||||
#endif /* EGL_ANGLE_x11_visual */
|
||||
|
||||
#ifndef EGL_ANGLE_flexible_surface_compatibility
|
||||
#define EGL_ANGLE_flexible_surface_compatibility 1
|
||||
#define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6
|
||||
#endif /* EGL_ANGLE_flexible_surface_compatibility */
|
||||
|
||||
#ifndef EGL_ANGLE_surface_orientation
|
||||
#define EGL_ANGLE_surface_orientation
|
||||
#define EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE 0x33A7
|
||||
#define EGL_SURFACE_ORIENTATION_ANGLE 0x33A8
|
||||
#define EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE 0x0001
|
||||
#define EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE 0x0002
|
||||
#endif /* EGL_ANGLE_surface_orientation */
|
||||
|
||||
#ifndef EGL_ANGLE_experimental_present_path
|
||||
#define EGL_ANGLE_experimental_present_path
|
||||
#define EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE 0x33A4
|
||||
#define EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE 0x33A9
|
||||
#define EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE 0x33AA
|
||||
#endif /* EGL_ANGLE_experimental_present_path */
|
||||
|
||||
#ifndef EGL_ARM_pixmap_multisample_discard
|
||||
#define EGL_ARM_pixmap_multisample_discard 1
|
||||
#define EGL_DISCARD_SAMPLES_ARM 0x3286
|
||||
@ -504,6 +569,34 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT (EGLDisplay dpy, EGLint a
|
||||
#endif
|
||||
#endif /* EGL_EXT_device_base */
|
||||
|
||||
#ifndef EGL_ANGLE_device_creation
|
||||
#define EGL_ANGLE_device_creation 1
|
||||
typedef EGLDeviceEXT (EGLAPIENTRYP PFNEGLCREATEDEVICEANGLEPROC) (EGLint device_type, void *native_device, const EGLAttrib *attrib_list);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLRELEASEDEVICEANGLEPROC) (EGLDeviceEXT device);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLDeviceEXT EGLAPIENTRY eglCreateDeviceANGLE (EGLint device_type, void *native_device, const EGLAttrib *attrib_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglReleaseDeviceANGLE (EGLDeviceEXT device);
|
||||
#endif
|
||||
#endif /* EGL_ANGLE_device_creation */
|
||||
|
||||
#ifndef EGL_EXT_device_drm
|
||||
#define EGL_EXT_device_drm 1
|
||||
#define EGL_DRM_DEVICE_FILE_EXT 0x3233
|
||||
#endif /* EGL_EXT_device_drm */
|
||||
|
||||
#ifndef EGL_EXT_device_enumeration
|
||||
#define EGL_EXT_device_enumeration 1
|
||||
#endif /* EGL_EXT_device_enumeration */
|
||||
|
||||
#ifndef EGL_EXT_device_openwf
|
||||
#define EGL_EXT_device_openwf 1
|
||||
#define EGL_OPENWF_DEVICE_ID_EXT 0x3237
|
||||
#endif /* EGL_EXT_device_openwf */
|
||||
|
||||
#ifndef EGL_EXT_device_query
|
||||
#define EGL_EXT_device_query 1
|
||||
#endif /* EGL_EXT_device_query */
|
||||
|
||||
#ifndef EGL_EXT_image_dma_buf_import
|
||||
#define EGL_EXT_image_dma_buf_import 1
|
||||
#define EGL_LINUX_DMA_BUF_EXT 0x3270
|
||||
@ -535,6 +628,48 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT (EGLDisplay dpy, EGLint a
|
||||
#define EGL_MULTIVIEW_VIEW_COUNT_EXT 0x3134
|
||||
#endif /* EGL_EXT_multiview_window */
|
||||
|
||||
#ifndef EGL_EXT_output_base
|
||||
#define EGL_EXT_output_base 1
|
||||
typedef void *EGLOutputLayerEXT;
|
||||
typedef void *EGLOutputPortEXT;
|
||||
#define EGL_NO_OUTPUT_LAYER_EXT ((EGLOutputLayerEXT)0)
|
||||
#define EGL_NO_OUTPUT_PORT_EXT ((EGLOutputPortEXT)0)
|
||||
#define EGL_BAD_OUTPUT_LAYER_EXT 0x322D
|
||||
#define EGL_BAD_OUTPUT_PORT_EXT 0x322E
|
||||
#define EGL_SWAP_INTERVAL_EXT 0x322F
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETOUTPUTLAYERSEXTPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputLayerEXT *layers, EGLint max_layers, EGLint *num_layers);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETOUTPUTPORTSEXTPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputPortEXT *ports, EGLint max_ports, EGLint *num_ports);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLOUTPUTLAYERATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib value);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYOUTPUTLAYERATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib *value);
|
||||
typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTLAYERSTRINGEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint name);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLOUTPUTPORTATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib value);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib *value);
|
||||
typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTSTRINGEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint name);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglGetOutputLayersEXT (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputLayerEXT *layers, EGLint max_layers, EGLint *num_layers);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglGetOutputPortsEXT (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputPortEXT *ports, EGLint max_ports, EGLint *num_ports);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglOutputLayerAttribEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib value);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglQueryOutputLayerAttribEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib *value);
|
||||
EGLAPI const char *EGLAPIENTRY eglQueryOutputLayerStringEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint name);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglOutputPortAttribEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib value);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglQueryOutputPortAttribEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib *value);
|
||||
EGLAPI const char *EGLAPIENTRY eglQueryOutputPortStringEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint name);
|
||||
#endif
|
||||
#endif /* EGL_EXT_output_base */
|
||||
|
||||
#ifndef EGL_EXT_output_drm
|
||||
#define EGL_EXT_output_drm 1
|
||||
#define EGL_DRM_CRTC_EXT 0x3234
|
||||
#define EGL_DRM_PLANE_EXT 0x3235
|
||||
#define EGL_DRM_CONNECTOR_EXT 0x3236
|
||||
#endif /* EGL_EXT_output_drm */
|
||||
|
||||
#ifndef EGL_EXT_output_openwf
|
||||
#define EGL_EXT_output_openwf 1
|
||||
#define EGL_OPENWF_PIPELINE_ID_EXT 0x3238
|
||||
#define EGL_OPENWF_PORT_ID_EXT 0x3239
|
||||
#endif /* EGL_EXT_output_openwf */
|
||||
|
||||
#ifndef EGL_EXT_platform_base
|
||||
#define EGL_EXT_platform_base 1
|
||||
typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list);
|
||||
@ -568,6 +703,14 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurfaceEXT (EGLDisplay dpy,
|
||||
#define EGL_PROTECTED_CONTENT_EXT 0x32C0
|
||||
#endif /* EGL_EXT_protected_surface */
|
||||
|
||||
#ifndef EGL_EXT_stream_consumer_egloutput
|
||||
#define EGL_EXT_stream_consumer_egloutput 1
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMEROUTPUTEXTPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLOutputLayerEXT layer);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerOutputEXT (EGLDisplay dpy, EGLStreamKHR stream, EGLOutputLayerEXT layer);
|
||||
#endif
|
||||
#endif /* EGL_EXT_stream_consumer_egloutput */
|
||||
|
||||
#ifndef EGL_EXT_swap_buffers_with_damage
|
||||
#define EGL_EXT_swap_buffers_with_damage 1
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
|
||||
@ -576,6 +719,35 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageEXT (EGLDisplay dpy, EGLSu
|
||||
#endif
|
||||
#endif /* EGL_EXT_swap_buffers_with_damage */
|
||||
|
||||
#ifndef EGL_EXT_yuv_surface
|
||||
#define EGL_EXT_yuv_surface 1
|
||||
#define EGL_YUV_ORDER_EXT 0x3301
|
||||
#define EGL_YUV_NUMBER_OF_PLANES_EXT 0x3311
|
||||
#define EGL_YUV_SUBSAMPLE_EXT 0x3312
|
||||
#define EGL_YUV_DEPTH_RANGE_EXT 0x3317
|
||||
#define EGL_YUV_CSC_STANDARD_EXT 0x330A
|
||||
#define EGL_YUV_PLANE_BPP_EXT 0x331A
|
||||
#define EGL_YUV_BUFFER_EXT 0x3300
|
||||
#define EGL_YUV_ORDER_YUV_EXT 0x3302
|
||||
#define EGL_YUV_ORDER_YVU_EXT 0x3303
|
||||
#define EGL_YUV_ORDER_YUYV_EXT 0x3304
|
||||
#define EGL_YUV_ORDER_UYVY_EXT 0x3305
|
||||
#define EGL_YUV_ORDER_YVYU_EXT 0x3306
|
||||
#define EGL_YUV_ORDER_VYUY_EXT 0x3307
|
||||
#define EGL_YUV_ORDER_AYUV_EXT 0x3308
|
||||
#define EGL_YUV_SUBSAMPLE_4_2_0_EXT 0x3313
|
||||
#define EGL_YUV_SUBSAMPLE_4_2_2_EXT 0x3314
|
||||
#define EGL_YUV_SUBSAMPLE_4_4_4_EXT 0x3315
|
||||
#define EGL_YUV_DEPTH_RANGE_LIMITED_EXT 0x3318
|
||||
#define EGL_YUV_DEPTH_RANGE_FULL_EXT 0x3319
|
||||
#define EGL_YUV_CSC_STANDARD_601_EXT 0x330B
|
||||
#define EGL_YUV_CSC_STANDARD_709_EXT 0x330C
|
||||
#define EGL_YUV_CSC_STANDARD_2020_EXT 0x330D
|
||||
#define EGL_YUV_PLANE_BPP_0_EXT 0x331B
|
||||
#define EGL_YUV_PLANE_BPP_8_EXT 0x331C
|
||||
#define EGL_YUV_PLANE_BPP_10_EXT 0x331D
|
||||
#endif /* EGL_EXT_yuv_surface */
|
||||
|
||||
#ifndef EGL_HI_clientpixmap
|
||||
#define EGL_HI_clientpixmap 1
|
||||
struct EGLClientPixmapHI {
|
||||
@ -624,6 +796,16 @@ EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA (EGLDisplay dpy, EGLImageKHR
|
||||
#endif
|
||||
#endif /* EGL_MESA_drm_image */
|
||||
|
||||
#ifndef EGL_MESA_image_dma_buf_export
|
||||
#define EGL_MESA_image_dma_buf_export 1
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC) (EGLDisplay dpy, EGLImageKHR image, int *fourcc, int *num_planes, EGLuint64KHR *modifiers);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDMABUFIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, int *fds, EGLint *strides, EGLint *offsets);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglExportDMABUFImageQueryMESA (EGLDisplay dpy, EGLImageKHR image, int *fourcc, int *num_planes, EGLuint64KHR *modifiers);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglExportDMABUFImageMESA (EGLDisplay dpy, EGLImageKHR image, int *fds, EGLint *strides, EGLint *offsets);
|
||||
#endif
|
||||
#endif /* EGL_MESA_image_dma_buf_export */
|
||||
|
||||
#ifndef EGL_MESA_platform_gbm
|
||||
#define EGL_MESA_platform_gbm 1
|
||||
#define EGL_PLATFORM_GBM_MESA 0x31D7
|
||||
@ -668,6 +850,13 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegion2NOK (EGLDisplay dpy, EGLSurfa
|
||||
#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV 0x3133
|
||||
#endif /* EGL_NV_coverage_sample_resolve */
|
||||
|
||||
#ifndef EGL_NV_cuda_event
|
||||
#define EGL_NV_cuda_event 1
|
||||
#define EGL_CUDA_EVENT_HANDLE_NV 0x323B
|
||||
#define EGL_SYNC_CUDA_EVENT_NV 0x323C
|
||||
#define EGL_SYNC_CUDA_EVENT_COMPLETE_NV 0x323D
|
||||
#endif /* EGL_NV_cuda_event */
|
||||
|
||||
#ifndef EGL_NV_depth_nonlinear
|
||||
#define EGL_NV_depth_nonlinear 1
|
||||
#define EGL_DEPTH_ENCODING_NV 0x30E2
|
||||
@ -675,6 +864,11 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegion2NOK (EGLDisplay dpy, EGLSurfa
|
||||
#define EGL_DEPTH_ENCODING_NONLINEAR_NV 0x30E3
|
||||
#endif /* EGL_NV_depth_nonlinear */
|
||||
|
||||
#ifndef EGL_NV_device_cuda
|
||||
#define EGL_NV_device_cuda 1
|
||||
#define EGL_CUDA_DEVICE_NV 0x323A
|
||||
#endif /* EGL_NV_device_cuda */
|
||||
|
||||
#ifndef EGL_NV_native_query
|
||||
#define EGL_NV_native_query 1
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEDISPLAYNVPROC) (EGLDisplay dpy, EGLNativeDisplayType *display_id);
|
||||
@ -757,6 +951,16 @@ EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV (void);
|
||||
#endif /* KHRONOS_SUPPORT_INT64 */
|
||||
#endif /* EGL_NV_system_time */
|
||||
|
||||
#ifndef EGL_TIZEN_image_native_buffer
|
||||
#define EGL_TIZEN_image_native_buffer 1
|
||||
#define EGL_NATIVE_BUFFER_TIZEN 0x32A0
|
||||
#endif /* EGL_TIZEN_image_native_buffer */
|
||||
|
||||
#ifndef EGL_TIZEN_image_native_surface
|
||||
#define EGL_TIZEN_image_native_surface 1
|
||||
#define EGL_NATIVE_SURFACE_TIZEN 0x32A1
|
||||
#endif /* EGL_TIZEN_image_native_surface */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
16
src/3rdparty/angle/include/EGL/eglplatform.h
vendored
16
src/3rdparty/angle/include/EGL/eglplatform.h
vendored
@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
/* Platform-specific types and definitions for egl.h
|
||||
* $Revision: 23432 $ on $Date: 2013-10-09 00:57:24 -0700 (Wed, 09 Oct 2013) $
|
||||
* $Revision: 30994 $ on $Date: 2015-04-30 13:36:48 -0700 (Thu, 30 Apr 2015) $
|
||||
*
|
||||
* Adopters may modify khrplatform.h and this file to suit their platform.
|
||||
* You are encouraged to submit all modifications to the Khronos group so that
|
||||
@ -99,6 +99,12 @@ typedef struct ANativeWindow* EGLNativeWindowType;
|
||||
typedef struct egl_native_pixmap_t* EGLNativePixmapType;
|
||||
typedef void* EGLNativeDisplayType;
|
||||
|
||||
#elif defined(USE_OZONE)
|
||||
|
||||
typedef intptr_t EGLNativeDisplayType;
|
||||
typedef intptr_t EGLNativeWindowType;
|
||||
typedef intptr_t EGLNativePixmapType;
|
||||
|
||||
#elif defined(__unix__)
|
||||
|
||||
/* X11 (tentative) */
|
||||
@ -111,11 +117,15 @@ typedef Window EGLNativeWindowType;
|
||||
|
||||
#elif defined(__GNUC__) && ( defined(__APPLE_CPP__) || defined(__APPLE_CC__) || defined(__MACOS_CLASSIC__) )
|
||||
|
||||
// TODO(jmadill): native implementation for OSX
|
||||
#if defined(__OBJC__)
|
||||
@class CALayer;
|
||||
#else
|
||||
class CALayer;
|
||||
#endif
|
||||
|
||||
typedef void *EGLNativeDisplayType;
|
||||
typedef void *EGLNativePixmapType;
|
||||
typedef void *EGLNativeWindowType;
|
||||
typedef CALayer *EGLNativeWindowType;
|
||||
|
||||
#else
|
||||
#error "Platform not recognized"
|
||||
|
731
src/3rdparty/angle/include/GLES2/gl2.h
vendored
731
src/3rdparty/angle/include/GLES2/gl2.h
vendored
@ -1,56 +1,87 @@
|
||||
#ifndef __gl2_h_
|
||||
#define __gl2_h_
|
||||
|
||||
/* $Revision: 20555 $ on $Date:: 2013-02-12 14:32:47 -0800 #$ */
|
||||
|
||||
#include <GLES2/gl2platform.h>
|
||||
#define __gl2_h_ 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This document is licensed under the SGI Free Software B License Version
|
||||
* 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
|
||||
** Copyright (c) 2013-2015 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
/*
|
||||
** This header is generated from the Khronos OpenGL / OpenGL ES XML
|
||||
** API Registry. The current version of the Registry, generator scripts
|
||||
** used to make the header, and the header can be found at
|
||||
** http://www.opengl.org/registry/
|
||||
**
|
||||
** Khronos $Revision: 31811 $ on $Date: 2015-08-10 00:01:11 -0700 (Mon, 10 Aug 2015) $
|
||||
*/
|
||||
|
||||
#include <GLES2/gl2platform.h>
|
||||
|
||||
#ifndef GL_APIENTRYP
|
||||
#define GL_APIENTRYP GL_APIENTRY*
|
||||
#endif
|
||||
|
||||
/* Generated on date 20150809 */
|
||||
|
||||
/* Generated C header for:
|
||||
* API: gles2
|
||||
* Profile: common
|
||||
* Versions considered: 2\.[0-9]
|
||||
* Versions emitted: .*
|
||||
* Default extensions included: None
|
||||
* Additional extensions included: _nomatch_^
|
||||
* Extensions removed: _nomatch_^
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Data type definitions
|
||||
*-----------------------------------------------------------------------*/
|
||||
|
||||
typedef void GLvoid;
|
||||
typedef char GLchar;
|
||||
typedef unsigned int GLenum;
|
||||
typedef unsigned char GLboolean;
|
||||
typedef unsigned int GLbitfield;
|
||||
typedef khronos_int8_t GLbyte;
|
||||
typedef short GLshort;
|
||||
typedef int GLint;
|
||||
typedef int GLsizei;
|
||||
typedef khronos_uint8_t GLubyte;
|
||||
typedef unsigned short GLushort;
|
||||
typedef unsigned int GLuint;
|
||||
typedef khronos_float_t GLfloat;
|
||||
typedef khronos_float_t GLclampf;
|
||||
typedef khronos_int32_t GLfixed;
|
||||
|
||||
/* GL types for handling large vertex buffer objects */
|
||||
#ifndef GL_ES_VERSION_2_0
|
||||
#define GL_ES_VERSION_2_0 1
|
||||
#include <KHR/khrplatform.h>
|
||||
typedef khronos_int8_t GLbyte;
|
||||
typedef khronos_float_t GLclampf;
|
||||
typedef khronos_int32_t GLfixed;
|
||||
typedef short GLshort;
|
||||
typedef unsigned short GLushort;
|
||||
typedef void GLvoid;
|
||||
typedef struct __GLsync *GLsync;
|
||||
typedef khronos_int64_t GLint64;
|
||||
typedef khronos_uint64_t GLuint64;
|
||||
typedef unsigned int GLenum;
|
||||
typedef unsigned int GLuint;
|
||||
typedef char GLchar;
|
||||
typedef khronos_float_t GLfloat;
|
||||
typedef khronos_ssize_t GLsizeiptr;
|
||||
typedef khronos_intptr_t GLintptr;
|
||||
typedef khronos_ssize_t GLsizeiptr;
|
||||
|
||||
/* OpenGL ES core versions */
|
||||
#define GL_ES_VERSION_2_0 1
|
||||
|
||||
/* ClearBufferMask */
|
||||
typedef unsigned int GLbitfield;
|
||||
typedef int GLint;
|
||||
typedef unsigned char GLboolean;
|
||||
typedef int GLsizei;
|
||||
typedef khronos_uint8_t GLubyte;
|
||||
#define GL_DEPTH_BUFFER_BIT 0x00000100
|
||||
#define GL_STENCIL_BUFFER_BIT 0x00000400
|
||||
#define GL_COLOR_BUFFER_BIT 0x00004000
|
||||
|
||||
/* Boolean */
|
||||
#define GL_FALSE 0
|
||||
#define GL_TRUE 1
|
||||
|
||||
/* BeginMode */
|
||||
#define GL_POINTS 0x0000
|
||||
#define GL_LINES 0x0001
|
||||
#define GL_LINE_LOOP 0x0002
|
||||
@ -58,18 +89,6 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_TRIANGLES 0x0004
|
||||
#define GL_TRIANGLE_STRIP 0x0005
|
||||
#define GL_TRIANGLE_FAN 0x0006
|
||||
|
||||
/* AlphaFunction (not supported in ES20) */
|
||||
/* GL_NEVER */
|
||||
/* GL_LESS */
|
||||
/* GL_EQUAL */
|
||||
/* GL_LEQUAL */
|
||||
/* GL_GREATER */
|
||||
/* GL_NOTEQUAL */
|
||||
/* GL_GEQUAL */
|
||||
/* GL_ALWAYS */
|
||||
|
||||
/* BlendingFactorDest */
|
||||
#define GL_ZERO 0
|
||||
#define GL_ONE 1
|
||||
#define GL_SRC_COLOR 0x0300
|
||||
@ -78,29 +97,15 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_ONE_MINUS_SRC_ALPHA 0x0303
|
||||
#define GL_DST_ALPHA 0x0304
|
||||
#define GL_ONE_MINUS_DST_ALPHA 0x0305
|
||||
|
||||
/* BlendingFactorSrc */
|
||||
/* GL_ZERO */
|
||||
/* GL_ONE */
|
||||
#define GL_DST_COLOR 0x0306
|
||||
#define GL_ONE_MINUS_DST_COLOR 0x0307
|
||||
#define GL_SRC_ALPHA_SATURATE 0x0308
|
||||
/* GL_SRC_ALPHA */
|
||||
/* GL_ONE_MINUS_SRC_ALPHA */
|
||||
/* GL_DST_ALPHA */
|
||||
/* GL_ONE_MINUS_DST_ALPHA */
|
||||
|
||||
/* BlendEquationSeparate */
|
||||
#define GL_FUNC_ADD 0x8006
|
||||
#define GL_BLEND_EQUATION 0x8009
|
||||
#define GL_BLEND_EQUATION_RGB 0x8009 /* same as BLEND_EQUATION */
|
||||
#define GL_BLEND_EQUATION_RGB 0x8009
|
||||
#define GL_BLEND_EQUATION_ALPHA 0x883D
|
||||
|
||||
/* BlendSubtract */
|
||||
#define GL_FUNC_SUBTRACT 0x800A
|
||||
#define GL_FUNC_REVERSE_SUBTRACT 0x800B
|
||||
|
||||
/* Separate Blend Functions */
|
||||
#define GL_BLEND_DST_RGB 0x80C8
|
||||
#define GL_BLEND_SRC_RGB 0x80C9
|
||||
#define GL_BLEND_DST_ALPHA 0x80CA
|
||||
@ -110,38 +115,19 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_CONSTANT_ALPHA 0x8003
|
||||
#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
|
||||
#define GL_BLEND_COLOR 0x8005
|
||||
|
||||
/* Buffer Objects */
|
||||
#define GL_ARRAY_BUFFER 0x8892
|
||||
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
|
||||
#define GL_ARRAY_BUFFER_BINDING 0x8894
|
||||
#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
|
||||
|
||||
#define GL_STREAM_DRAW 0x88E0
|
||||
#define GL_STATIC_DRAW 0x88E4
|
||||
#define GL_DYNAMIC_DRAW 0x88E8
|
||||
|
||||
#define GL_BUFFER_SIZE 0x8764
|
||||
#define GL_BUFFER_USAGE 0x8765
|
||||
|
||||
#define GL_CURRENT_VERTEX_ATTRIB 0x8626
|
||||
|
||||
/* CullFaceMode */
|
||||
#define GL_FRONT 0x0404
|
||||
#define GL_BACK 0x0405
|
||||
#define GL_FRONT_AND_BACK 0x0408
|
||||
|
||||
/* DepthFunction */
|
||||
/* GL_NEVER */
|
||||
/* GL_LESS */
|
||||
/* GL_EQUAL */
|
||||
/* GL_LEQUAL */
|
||||
/* GL_GREATER */
|
||||
/* GL_NOTEQUAL */
|
||||
/* GL_GEQUAL */
|
||||
/* GL_ALWAYS */
|
||||
|
||||
/* EnableCap */
|
||||
#define GL_TEXTURE_2D 0x0DE1
|
||||
#define GL_CULL_FACE 0x0B44
|
||||
#define GL_BLEND 0x0BE2
|
||||
@ -152,19 +138,13 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_POLYGON_OFFSET_FILL 0x8037
|
||||
#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
|
||||
#define GL_SAMPLE_COVERAGE 0x80A0
|
||||
|
||||
/* ErrorCode */
|
||||
#define GL_NO_ERROR 0
|
||||
#define GL_INVALID_ENUM 0x0500
|
||||
#define GL_INVALID_VALUE 0x0501
|
||||
#define GL_INVALID_OPERATION 0x0502
|
||||
#define GL_OUT_OF_MEMORY 0x0505
|
||||
|
||||
/* FrontFaceDirection */
|
||||
#define GL_CW 0x0900
|
||||
#define GL_CCW 0x0901
|
||||
|
||||
/* GetPName */
|
||||
#define GL_LINE_WIDTH 0x0B21
|
||||
#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
|
||||
#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
|
||||
@ -191,7 +171,6 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
|
||||
#define GL_VIEWPORT 0x0BA2
|
||||
#define GL_SCISSOR_BOX 0x0C10
|
||||
/* GL_SCISSOR_TEST */
|
||||
#define GL_COLOR_CLEAR_VALUE 0x0C22
|
||||
#define GL_COLOR_WRITEMASK 0x0C23
|
||||
#define GL_UNPACK_ALIGNMENT 0x0CF5
|
||||
@ -206,32 +185,18 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_DEPTH_BITS 0x0D56
|
||||
#define GL_STENCIL_BITS 0x0D57
|
||||
#define GL_POLYGON_OFFSET_UNITS 0x2A00
|
||||
/* GL_POLYGON_OFFSET_FILL */
|
||||
#define GL_POLYGON_OFFSET_FACTOR 0x8038
|
||||
#define GL_TEXTURE_BINDING_2D 0x8069
|
||||
#define GL_SAMPLE_BUFFERS 0x80A8
|
||||
#define GL_SAMPLES 0x80A9
|
||||
#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
|
||||
#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
|
||||
|
||||
/* GetTextureParameter */
|
||||
/* GL_TEXTURE_MAG_FILTER */
|
||||
/* GL_TEXTURE_MIN_FILTER */
|
||||
/* GL_TEXTURE_WRAP_S */
|
||||
/* GL_TEXTURE_WRAP_T */
|
||||
|
||||
#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
|
||||
#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
|
||||
|
||||
/* HintMode */
|
||||
#define GL_DONT_CARE 0x1100
|
||||
#define GL_FASTEST 0x1101
|
||||
#define GL_NICEST 0x1102
|
||||
|
||||
/* HintTarget */
|
||||
#define GL_GENERATE_MIPMAP_HINT 0x8192
|
||||
|
||||
/* DataType */
|
||||
#define GL_GENERATE_MIPMAP_HINT 0x8192
|
||||
#define GL_BYTE 0x1400
|
||||
#define GL_UNSIGNED_BYTE 0x1401
|
||||
#define GL_SHORT 0x1402
|
||||
@ -240,44 +205,35 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_UNSIGNED_INT 0x1405
|
||||
#define GL_FLOAT 0x1406
|
||||
#define GL_FIXED 0x140C
|
||||
|
||||
/* PixelFormat */
|
||||
#define GL_DEPTH_COMPONENT 0x1902
|
||||
#define GL_ALPHA 0x1906
|
||||
#define GL_RGB 0x1907
|
||||
#define GL_RGBA 0x1908
|
||||
#define GL_LUMINANCE 0x1909
|
||||
#define GL_LUMINANCE_ALPHA 0x190A
|
||||
|
||||
/* PixelType */
|
||||
/* GL_UNSIGNED_BYTE */
|
||||
#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
|
||||
#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
|
||||
#define GL_UNSIGNED_SHORT_5_6_5 0x8363
|
||||
|
||||
/* Shaders */
|
||||
#define GL_FRAGMENT_SHADER 0x8B30
|
||||
#define GL_VERTEX_SHADER 0x8B31
|
||||
#define GL_MAX_VERTEX_ATTRIBS 0x8869
|
||||
#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
|
||||
#define GL_MAX_VARYING_VECTORS 0x8DFC
|
||||
#define GL_FRAGMENT_SHADER 0x8B30
|
||||
#define GL_VERTEX_SHADER 0x8B31
|
||||
#define GL_MAX_VERTEX_ATTRIBS 0x8869
|
||||
#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
|
||||
#define GL_MAX_VARYING_VECTORS 0x8DFC
|
||||
#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
|
||||
#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
|
||||
#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
|
||||
#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
|
||||
#define GL_SHADER_TYPE 0x8B4F
|
||||
#define GL_DELETE_STATUS 0x8B80
|
||||
#define GL_LINK_STATUS 0x8B82
|
||||
#define GL_VALIDATE_STATUS 0x8B83
|
||||
#define GL_ATTACHED_SHADERS 0x8B85
|
||||
#define GL_ACTIVE_UNIFORMS 0x8B86
|
||||
#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
|
||||
#define GL_ACTIVE_ATTRIBUTES 0x8B89
|
||||
#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
|
||||
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
|
||||
#define GL_CURRENT_PROGRAM 0x8B8D
|
||||
|
||||
/* StencilFunction */
|
||||
#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
|
||||
#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
|
||||
#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
|
||||
#define GL_SHADER_TYPE 0x8B4F
|
||||
#define GL_DELETE_STATUS 0x8B80
|
||||
#define GL_LINK_STATUS 0x8B82
|
||||
#define GL_VALIDATE_STATUS 0x8B83
|
||||
#define GL_ATTACHED_SHADERS 0x8B85
|
||||
#define GL_ACTIVE_UNIFORMS 0x8B86
|
||||
#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
|
||||
#define GL_ACTIVE_ATTRIBUTES 0x8B89
|
||||
#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
|
||||
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
|
||||
#define GL_CURRENT_PROGRAM 0x8B8D
|
||||
#define GL_NEVER 0x0200
|
||||
#define GL_LESS 0x0201
|
||||
#define GL_EQUAL 0x0202
|
||||
@ -286,9 +242,6 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_NOTEQUAL 0x0205
|
||||
#define GL_GEQUAL 0x0206
|
||||
#define GL_ALWAYS 0x0207
|
||||
|
||||
/* StencilOp */
|
||||
/* GL_ZERO */
|
||||
#define GL_KEEP 0x1E00
|
||||
#define GL_REPLACE 0x1E01
|
||||
#define GL_INCR 0x1E02
|
||||
@ -296,35 +249,21 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_INVERT 0x150A
|
||||
#define GL_INCR_WRAP 0x8507
|
||||
#define GL_DECR_WRAP 0x8508
|
||||
|
||||
/* StringName */
|
||||
#define GL_VENDOR 0x1F00
|
||||
#define GL_RENDERER 0x1F01
|
||||
#define GL_VERSION 0x1F02
|
||||
#define GL_EXTENSIONS 0x1F03
|
||||
|
||||
/* TextureMagFilter */
|
||||
#define GL_NEAREST 0x2600
|
||||
#define GL_LINEAR 0x2601
|
||||
|
||||
/* TextureMinFilter */
|
||||
/* GL_NEAREST */
|
||||
/* GL_LINEAR */
|
||||
#define GL_NEAREST_MIPMAP_NEAREST 0x2700
|
||||
#define GL_LINEAR_MIPMAP_NEAREST 0x2701
|
||||
#define GL_NEAREST_MIPMAP_LINEAR 0x2702
|
||||
#define GL_LINEAR_MIPMAP_LINEAR 0x2703
|
||||
|
||||
/* TextureParameterName */
|
||||
#define GL_TEXTURE_MAG_FILTER 0x2800
|
||||
#define GL_TEXTURE_MIN_FILTER 0x2801
|
||||
#define GL_TEXTURE_WRAP_S 0x2802
|
||||
#define GL_TEXTURE_WRAP_T 0x2803
|
||||
|
||||
/* TextureTarget */
|
||||
/* GL_TEXTURE_2D */
|
||||
#define GL_TEXTURE 0x1702
|
||||
|
||||
#define GL_TEXTURE_CUBE_MAP 0x8513
|
||||
#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
|
||||
#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
|
||||
@ -334,8 +273,6 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
|
||||
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
|
||||
#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
|
||||
|
||||
/* TextureUnit */
|
||||
#define GL_TEXTURE0 0x84C0
|
||||
#define GL_TEXTURE1 0x84C1
|
||||
#define GL_TEXTURE2 0x84C2
|
||||
@ -369,13 +306,9 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_TEXTURE30 0x84DE
|
||||
#define GL_TEXTURE31 0x84DF
|
||||
#define GL_ACTIVE_TEXTURE 0x84E0
|
||||
|
||||
/* TextureWrapMode */
|
||||
#define GL_REPEAT 0x2901
|
||||
#define GL_CLAMP_TO_EDGE 0x812F
|
||||
#define GL_MIRRORED_REPEAT 0x8370
|
||||
|
||||
/* Uniform Types */
|
||||
#define GL_FLOAT_VEC2 0x8B50
|
||||
#define GL_FLOAT_VEC3 0x8B51
|
||||
#define GL_FLOAT_VEC4 0x8B52
|
||||
@ -391,48 +324,34 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_FLOAT_MAT4 0x8B5C
|
||||
#define GL_SAMPLER_2D 0x8B5E
|
||||
#define GL_SAMPLER_CUBE 0x8B60
|
||||
|
||||
/* Vertex Arrays */
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
|
||||
|
||||
/* Read Format */
|
||||
#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
|
||||
#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
|
||||
#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
|
||||
|
||||
/* Shader Source */
|
||||
#define GL_COMPILE_STATUS 0x8B81
|
||||
#define GL_INFO_LOG_LENGTH 0x8B84
|
||||
#define GL_SHADER_SOURCE_LENGTH 0x8B88
|
||||
#define GL_SHADER_COMPILER 0x8DFA
|
||||
|
||||
/* Shader Binary */
|
||||
#define GL_SHADER_BINARY_FORMATS 0x8DF8
|
||||
#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
|
||||
|
||||
/* Shader Precision-Specified Types */
|
||||
#define GL_LOW_FLOAT 0x8DF0
|
||||
#define GL_MEDIUM_FLOAT 0x8DF1
|
||||
#define GL_HIGH_FLOAT 0x8DF2
|
||||
#define GL_LOW_INT 0x8DF3
|
||||
#define GL_MEDIUM_INT 0x8DF4
|
||||
#define GL_HIGH_INT 0x8DF5
|
||||
|
||||
/* Framebuffer Object. */
|
||||
#define GL_FRAMEBUFFER 0x8D40
|
||||
#define GL_RENDERBUFFER 0x8D41
|
||||
|
||||
#define GL_RGBA4 0x8056
|
||||
#define GL_RGB5_A1 0x8057
|
||||
#define GL_RGB565 0x8D62
|
||||
#define GL_DEPTH_COMPONENT16 0x81A5
|
||||
#define GL_STENCIL_INDEX8 0x8D48
|
||||
|
||||
#define GL_RENDERBUFFER_WIDTH 0x8D42
|
||||
#define GL_RENDERBUFFER_HEIGHT 0x8D43
|
||||
#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
|
||||
@ -442,179 +361,313 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
|
||||
#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
|
||||
#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
|
||||
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
|
||||
|
||||
#define GL_COLOR_ATTACHMENT0 0x8CE0
|
||||
#define GL_DEPTH_ATTACHMENT 0x8D00
|
||||
#define GL_STENCIL_ATTACHMENT 0x8D20
|
||||
|
||||
#define GL_NONE 0
|
||||
|
||||
#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
|
||||
#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
|
||||
#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
|
||||
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
|
||||
#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
|
||||
#define GL_FRAMEBUFFER_BINDING 0x8CA6
|
||||
#define GL_RENDERBUFFER_BINDING 0x8CA7
|
||||
#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
|
||||
|
||||
#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* GL core functions.
|
||||
*-----------------------------------------------------------------------*/
|
||||
|
||||
GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
|
||||
GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar* name);
|
||||
GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
|
||||
GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
|
||||
GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
|
||||
GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
|
||||
GL_APICALL void GL_APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
|
||||
GL_APICALL void GL_APIENTRY glBlendEquation ( GLenum mode );
|
||||
GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
|
||||
GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
|
||||
GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
|
||||
GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
|
||||
GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
|
||||
GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target);
|
||||
GL_APICALL void GL_APIENTRY glClear (GLbitfield mask);
|
||||
GL_APICALL void GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
|
||||
GL_APICALL void GL_APIENTRY glClearDepthf (GLclampf depth);
|
||||
GL_APICALL void GL_APIENTRY glClearStencil (GLint s);
|
||||
GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
|
||||
GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
|
||||
GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
|
||||
GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
|
||||
GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
|
||||
GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type);
|
||||
GL_APICALL void GL_APIENTRY glCullFace (GLenum mode);
|
||||
GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers);
|
||||
GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers);
|
||||
GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers);
|
||||
GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures);
|
||||
GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func);
|
||||
GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag);
|
||||
GL_APICALL void GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar);
|
||||
GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glDisable (GLenum cap);
|
||||
GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index);
|
||||
GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
|
||||
GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
|
||||
GL_APICALL void GL_APIENTRY glEnable (GLenum cap);
|
||||
GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
|
||||
GL_APICALL void GL_APIENTRY glFinish (void);
|
||||
GL_APICALL void GL_APIENTRY glFlush (void);
|
||||
GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
|
||||
GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
|
||||
GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode);
|
||||
GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers);
|
||||
GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target);
|
||||
GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers);
|
||||
GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers);
|
||||
GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures);
|
||||
GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
|
||||
GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
|
||||
GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
|
||||
GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name);
|
||||
GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params);
|
||||
GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params);
|
||||
GL_APICALL GLenum GL_APIENTRY glGetError (void);
|
||||
GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params);
|
||||
GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
|
||||
GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
|
||||
GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name);
|
||||
GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params);
|
||||
GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params);
|
||||
GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params);
|
||||
GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar* name);
|
||||
GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params);
|
||||
GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer);
|
||||
GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture);
|
||||
GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width);
|
||||
GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
|
||||
GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
|
||||
GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
|
||||
GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void);
|
||||
GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
|
||||
GL_APICALL void GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert);
|
||||
GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
|
||||
GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length);
|
||||
GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
|
||||
GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
|
||||
GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
|
||||
GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
|
||||
GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params);
|
||||
GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
|
||||
GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
|
||||
GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat x);
|
||||
GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v);
|
||||
GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint x);
|
||||
GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v);
|
||||
GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y);
|
||||
GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v);
|
||||
GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y);
|
||||
GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v);
|
||||
GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z);
|
||||
GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v);
|
||||
GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z);
|
||||
GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v);
|
||||
GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
|
||||
GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v);
|
||||
GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w);
|
||||
GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||
GL_APICALL void GL_APIENTRY glUseProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
|
||||
GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
typedef void (GL_APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
|
||||
typedef void (GL_APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
|
||||
typedef void (GL_APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);
|
||||
typedef void (GL_APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
|
||||
typedef void (GL_APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
|
||||
typedef void (GL_APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
|
||||
typedef void (GL_APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
|
||||
typedef void (GL_APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||
typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
|
||||
typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
|
||||
typedef void (GL_APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor);
|
||||
typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
|
||||
typedef void (GL_APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
|
||||
typedef void (GL_APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
|
||||
typedef GLenum (GL_APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
|
||||
typedef void (GL_APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
|
||||
typedef void (GL_APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||
typedef void (GL_APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d);
|
||||
typedef void (GL_APIENTRYP PFNGLCLEARSTENCILPROC) (GLint s);
|
||||
typedef void (GL_APIENTRYP PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
|
||||
typedef void (GL_APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
|
||||
typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
|
||||
typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
|
||||
typedef void (GL_APIENTRYP PFNGLCOPYTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
|
||||
typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
typedef GLuint (GL_APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
|
||||
typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
|
||||
typedef void (GL_APIENTRYP PFNGLCULLFACEPROC) (GLenum mode);
|
||||
typedef void (GL_APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
|
||||
typedef void (GL_APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers);
|
||||
typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
|
||||
typedef void (GL_APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers);
|
||||
typedef void (GL_APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
|
||||
typedef void (GL_APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
|
||||
typedef void (GL_APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func);
|
||||
typedef void (GL_APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag);
|
||||
typedef void (GL_APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f);
|
||||
typedef void (GL_APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
|
||||
typedef void (GL_APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
|
||||
typedef void (GL_APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
|
||||
typedef void (GL_APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count);
|
||||
typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices);
|
||||
typedef void (GL_APIENTRYP PFNGLENABLEPROC) (GLenum cap);
|
||||
typedef void (GL_APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
|
||||
typedef void (GL_APIENTRYP PFNGLFINISHPROC) (void);
|
||||
typedef void (GL_APIENTRYP PFNGLFLUSHPROC) (void);
|
||||
typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
|
||||
typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
|
||||
typedef void (GL_APIENTRYP PFNGLFRONTFACEPROC) (GLenum mode);
|
||||
typedef void (GL_APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
|
||||
typedef void (GL_APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target);
|
||||
typedef void (GL_APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);
|
||||
typedef void (GL_APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);
|
||||
typedef void (GL_APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
|
||||
typedef void (GL_APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
|
||||
typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
|
||||
typedef void (GL_APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
|
||||
typedef GLint (GL_APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
|
||||
typedef void (GL_APIENTRYP PFNGLGETBOOLEANVPROC) (GLenum pname, GLboolean *data);
|
||||
typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
|
||||
typedef GLenum (GL_APIENTRYP PFNGLGETERRORPROC) (void);
|
||||
typedef void (GL_APIENTRYP PFNGLGETFLOATVPROC) (GLenum pname, GLfloat *data);
|
||||
typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
|
||||
typedef void (GL_APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data);
|
||||
typedef void (GL_APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
|
||||
typedef void (GL_APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
|
||||
typedef void (GL_APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
|
||||
typedef void (GL_APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
typedef void (GL_APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
|
||||
typedef void (GL_APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
|
||||
typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
|
||||
typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
|
||||
typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
|
||||
typedef void (GL_APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);
|
||||
typedef void (GL_APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);
|
||||
typedef GLint (GL_APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
|
||||
typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);
|
||||
typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
|
||||
typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
|
||||
typedef void (GL_APIENTRYP PFNGLHINTPROC) (GLenum target, GLenum mode);
|
||||
typedef GLboolean (GL_APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);
|
||||
typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDPROC) (GLenum cap);
|
||||
typedef GLboolean (GL_APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
|
||||
typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
|
||||
typedef GLboolean (GL_APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
|
||||
typedef GLboolean (GL_APIENTRYP PFNGLISSHADERPROC) (GLuint shader);
|
||||
typedef GLboolean (GL_APIENTRYP PFNGLISTEXTUREPROC) (GLuint texture);
|
||||
typedef void (GL_APIENTRYP PFNGLLINEWIDTHPROC) (GLfloat width);
|
||||
typedef void (GL_APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
|
||||
typedef void (GL_APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
|
||||
typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat units);
|
||||
typedef void (GL_APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
|
||||
typedef void (GL_APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void);
|
||||
typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
|
||||
typedef void (GL_APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert);
|
||||
typedef void (GL_APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
typedef void (GL_APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
|
||||
typedef void (GL_APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
|
||||
typedef void (GL_APIENTRYP PFNGLSTENCILFUNCPROC) (GLenum func, GLint ref, GLuint mask);
|
||||
typedef void (GL_APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask);
|
||||
typedef void (GL_APIENTRYP PFNGLSTENCILMASKPROC) (GLuint mask);
|
||||
typedef void (GL_APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
|
||||
typedef void (GL_APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum zpass);
|
||||
typedef void (GL_APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
|
||||
typedef void (GL_APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
|
||||
typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat param);
|
||||
typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
|
||||
typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
|
||||
typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
|
||||
typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
|
||||
typedef void (GL_APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
|
||||
typedef void (GL_APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);
|
||||
typedef void (GL_APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
|
||||
typedef void (GL_APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
|
||||
typedef void (GL_APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
|
||||
typedef void (GL_APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);
|
||||
typedef void (GL_APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
|
||||
typedef void (GL_APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);
|
||||
typedef void (GL_APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
|
||||
typedef void (GL_APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
|
||||
typedef void (GL_APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
|
||||
typedef void (GL_APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);
|
||||
typedef void (GL_APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
|
||||
typedef void (GL_APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
|
||||
typedef void (GL_APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
|
||||
typedef void (GL_APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);
|
||||
typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
typedef void (GL_APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
|
||||
typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
|
||||
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
|
||||
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);
|
||||
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
|
||||
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);
|
||||
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
|
||||
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);
|
||||
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
|
||||
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
|
||||
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
|
||||
typedef void (GL_APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
|
||||
GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
|
||||
GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
|
||||
GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
|
||||
GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
|
||||
GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
|
||||
GL_APICALL void GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||
GL_APICALL void GL_APIENTRY glBlendEquation (GLenum mode);
|
||||
GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
|
||||
GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
|
||||
GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
|
||||
GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
|
||||
GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
|
||||
GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target);
|
||||
GL_APICALL void GL_APIENTRY glClear (GLbitfield mask);
|
||||
GL_APICALL void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||
GL_APICALL void GL_APIENTRY glClearDepthf (GLfloat d);
|
||||
GL_APICALL void GL_APIENTRY glClearStencil (GLint s);
|
||||
GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
|
||||
GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
|
||||
GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
|
||||
GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
|
||||
GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
|
||||
GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type);
|
||||
GL_APICALL void GL_APIENTRY glCullFace (GLenum mode);
|
||||
GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
|
||||
GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers);
|
||||
GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers);
|
||||
GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
|
||||
GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func);
|
||||
GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag);
|
||||
GL_APICALL void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f);
|
||||
GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glDisable (GLenum cap);
|
||||
GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index);
|
||||
GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
|
||||
GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);
|
||||
GL_APICALL void GL_APIENTRY glEnable (GLenum cap);
|
||||
GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
|
||||
GL_APICALL void GL_APIENTRY glFinish (void);
|
||||
GL_APICALL void GL_APIENTRY glFlush (void);
|
||||
GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
|
||||
GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
|
||||
GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode);
|
||||
GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
|
||||
GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target);
|
||||
GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers);
|
||||
GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers);
|
||||
GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures);
|
||||
GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
|
||||
GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
|
||||
GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
|
||||
GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
|
||||
GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean *data);
|
||||
GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params);
|
||||
GL_APICALL GLenum GL_APIENTRY glGetError (void);
|
||||
GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data);
|
||||
GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data);
|
||||
GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
|
||||
GL_APICALL const GLubyte *GL_APIENTRY glGetString (GLenum name);
|
||||
GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params);
|
||||
GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params);
|
||||
GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params);
|
||||
GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
|
||||
GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params);
|
||||
GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer);
|
||||
GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture);
|
||||
GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width);
|
||||
GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
|
||||
GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
|
||||
GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
|
||||
GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void);
|
||||
GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
|
||||
GL_APICALL void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert);
|
||||
GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
|
||||
GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
|
||||
GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
|
||||
GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
|
||||
GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
|
||||
GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
|
||||
GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params);
|
||||
GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
|
||||
GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
|
||||
GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat v0);
|
||||
GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint v0);
|
||||
GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1);
|
||||
GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint v0, GLint v1);
|
||||
GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
|
||||
GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2);
|
||||
GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
|
||||
GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
|
||||
GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUseProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint index, GLfloat x);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
|
||||
GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
#endif
|
||||
#endif /* GL_ES_VERSION_2_0 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __gl2_h_ */
|
||||
#endif
|
||||
|
4005
src/3rdparty/angle/include/GLES2/gl2ext.h
vendored
4005
src/3rdparty/angle/include/GLES2/gl2ext.h
vendored
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
#ifndef __gl2platform_h_
|
||||
#define __gl2platform_h_
|
||||
|
||||
/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */
|
||||
/* $Revision: 23328 $ on $Date:: 2013-10-02 02:28:28 -0700 #$ */
|
||||
|
||||
/*
|
||||
* This document is licensed under the SGI Free Software B License Version
|
||||
|
2188
src/3rdparty/angle/include/GLES3/gl3.h
vendored
2188
src/3rdparty/angle/include/GLES3/gl3.h
vendored
File diff suppressed because it is too large
Load Diff
1524
src/3rdparty/angle/include/GLES3/gl31.h
vendored
Normal file
1524
src/3rdparty/angle/include/GLES3/gl31.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1825
src/3rdparty/angle/include/GLES3/gl32.h
vendored
Normal file
1825
src/3rdparty/angle/include/GLES3/gl32.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
#ifndef __gl3platform_h_
|
||||
#define __gl3platform_h_
|
||||
|
||||
/* $Revision: 18437 $ on $Date:: 2012-07-08 23:31:39 -0700 #$ */
|
||||
/* $Revision: 23328 $ on $Date:: 2013-10-02 02:28:28 -0700 #$ */
|
||||
|
||||
/*
|
||||
* This document is licensed under the SGI Free Software B License Version
|
||||
|
78
src/3rdparty/angle/include/GLSLANG/ShaderLang.h
vendored
78
src/3rdparty/angle/include/GLSLANG/ShaderLang.h
vendored
@ -48,7 +48,7 @@ typedef unsigned int GLenum;
|
||||
|
||||
// Version number for shader translation API.
|
||||
// It is incremented every time the API changes.
|
||||
#define ANGLE_SH_VERSION 134
|
||||
#define ANGLE_SH_VERSION 143
|
||||
|
||||
typedef enum {
|
||||
SH_GLES2_SPEC = 0x8B40,
|
||||
@ -80,17 +80,35 @@ typedef enum {
|
||||
SH_CSS_SHADERS_SPEC = 0x8B42
|
||||
} ShShaderSpec;
|
||||
|
||||
typedef enum {
|
||||
SH_ESSL_OUTPUT = 0x8B45,
|
||||
// SH_GLSL_OUTPUT is deprecated. This is to not break the build.
|
||||
SH_GLSL_OUTPUT = 0x8B46,
|
||||
SH_GLSL_COMPATIBILITY_OUTPUT = 0x8B46,
|
||||
SH_GLSL_CORE_OUTPUT = 0x8B47,
|
||||
typedef enum
|
||||
{
|
||||
// ESSL output only supported in some configurations.
|
||||
SH_ESSL_OUTPUT = 0x8B45,
|
||||
|
||||
// HLSL output only supported in some configurations.
|
||||
SH_HLSL_OUTPUT = 0x8B48,
|
||||
SH_HLSL9_OUTPUT = 0x8B48,
|
||||
SH_HLSL11_OUTPUT = 0x8B49
|
||||
// GLSL output only supported in some configurations.
|
||||
SH_GLSL_COMPATIBILITY_OUTPUT = 0x8B46,
|
||||
// Note: GL introduced core profiles in 1.5.
|
||||
SH_GLSL_130_OUTPUT = 0x8B47,
|
||||
SH_GLSL_140_OUTPUT = 0x8B80,
|
||||
SH_GLSL_150_CORE_OUTPUT = 0x8B81,
|
||||
SH_GLSL_330_CORE_OUTPUT = 0x8B82,
|
||||
SH_GLSL_400_CORE_OUTPUT = 0x8B83,
|
||||
SH_GLSL_410_CORE_OUTPUT = 0x8B84,
|
||||
SH_GLSL_420_CORE_OUTPUT = 0x8B85,
|
||||
SH_GLSL_430_CORE_OUTPUT = 0x8B86,
|
||||
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.
|
||||
@ -112,7 +130,7 @@ typedef enum {
|
||||
// This is needed only as a workaround for certain OpenGL driver bugs.
|
||||
SH_EMULATE_BUILT_IN_FUNCTIONS = 0x0100,
|
||||
|
||||
// This is an experimental flag to enforce restrictions that aim to prevent
|
||||
// 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.
|
||||
@ -177,6 +195,19 @@ typedef enum {
|
||||
// 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.
|
||||
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.
|
||||
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.
|
||||
SH_REWRITE_DO_WHILE_LOOPS = 0x400000,
|
||||
} ShCompileOptions;
|
||||
|
||||
// Defines alternate strategies for implementing array index clamping.
|
||||
@ -225,6 +256,7 @@ typedef struct
|
||||
int OES_standard_derivatives;
|
||||
int OES_EGL_image_external;
|
||||
int ARB_texture_rectangle;
|
||||
int EXT_blend_func_extended;
|
||||
int EXT_draw_buffers;
|
||||
int EXT_frag_depth;
|
||||
int EXT_shader_texture_lod;
|
||||
@ -239,7 +271,9 @@ typedef struct
|
||||
// function. This applies to Tegra K1 devices.
|
||||
int NV_draw_buffers;
|
||||
|
||||
// Set to 1 if highp precision is supported in the fragment language.
|
||||
// Set to 1 if highp precision is supported in the ESSL 1.00 version of the
|
||||
// fragment language. Does not affect versions of the language where highp
|
||||
// support is mandatory.
|
||||
// Default is 0.
|
||||
int FragmentPrecisionHigh;
|
||||
|
||||
@ -249,6 +283,13 @@ typedef struct
|
||||
int MinProgramTexelOffset;
|
||||
int MaxProgramTexelOffset;
|
||||
|
||||
// Extension constants.
|
||||
|
||||
// Value of GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT for OpenGL ES output context.
|
||||
// Value of GL_MAX_DUAL_SOURCE_DRAW_BUFFERS for OpenGL output context.
|
||||
// GLES SL version 100 gl_MaxDualSourceDrawBuffersEXT value for EXT_blend_func_extended.
|
||||
int MaxDualSourceDrawBuffers;
|
||||
|
||||
// Name Hashing.
|
||||
// Set a 64 bit hash function to enable user-defined name hashing.
|
||||
// Default is NULL.
|
||||
@ -298,9 +339,9 @@ COMPILER_EXPORT const std::string &ShGetBuiltInResourcesString(const ShHandle ha
|
||||
// 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 - SH_ESSL_OUTPUT, SH_GLSL_OUTPUT,
|
||||
// SH_HLSL9_OUTPUT or SH_HLSL11_OUTPUT. Note: HLSL output is only
|
||||
// supported in some configurations.
|
||||
// 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.
|
||||
COMPILER_EXPORT ShHandle ShConstructCompiler(
|
||||
sh::GLenum type,
|
||||
@ -339,6 +380,9 @@ COMPILER_EXPORT bool ShCompile(
|
||||
size_t numStrings,
|
||||
int compileOptions);
|
||||
|
||||
// Clears the results from the previous compilation.
|
||||
COMPILER_EXPORT void ShClearResults(const ShHandle handle);
|
||||
|
||||
// Return the version of the shader language.
|
||||
COMPILER_EXPORT int ShGetShaderVersion(const ShHandle handle);
|
||||
|
||||
@ -373,7 +417,7 @@ COMPILER_EXPORT const std::map<std::string, std::string> *ShGetNameHashingMap(
|
||||
COMPILER_EXPORT const std::vector<sh::Uniform> *ShGetUniforms(const ShHandle handle);
|
||||
COMPILER_EXPORT const std::vector<sh::Varying> *ShGetVaryings(const ShHandle handle);
|
||||
COMPILER_EXPORT const std::vector<sh::Attribute> *ShGetAttributes(const ShHandle handle);
|
||||
COMPILER_EXPORT const std::vector<sh::Attribute> *ShGetOutputVariables(const ShHandle handle);
|
||||
COMPILER_EXPORT const std::vector<sh::OutputVariable> *ShGetOutputVariables(const ShHandle handle);
|
||||
COMPILER_EXPORT const std::vector<sh::InterfaceBlock> *ShGetInterfaceBlocks(const ShHandle handle);
|
||||
|
||||
typedef struct
|
||||
|
46
src/3rdparty/angle/include/GLSLANG/ShaderVars.h
vendored
46
src/3rdparty/angle/include/GLSLANG/ShaderVars.h
vendored
@ -70,6 +70,8 @@ struct COMPILER_EXPORT ShaderVariable
|
||||
const ShaderVariable **leafVar,
|
||||
std::string* originalFullName) const;
|
||||
|
||||
bool isBuiltIn() const { return name.compare(0, 3, "gl_") == 0; }
|
||||
|
||||
GLenum type;
|
||||
GLenum precision;
|
||||
std::string name;
|
||||
@ -108,19 +110,39 @@ struct COMPILER_EXPORT Uniform : public ShaderVariable
|
||||
bool isSameUniformAtLinkTime(const Uniform &other) const;
|
||||
};
|
||||
|
||||
struct COMPILER_EXPORT Attribute : 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 COMPILER_EXPORT InterfaceVariable : public ShaderVariable
|
||||
{
|
||||
InterfaceVariable();
|
||||
~InterfaceVariable();
|
||||
InterfaceVariable(const InterfaceVariable &other);
|
||||
InterfaceVariable &operator=(const InterfaceVariable &other);
|
||||
bool operator==(const InterfaceVariable &other) const;
|
||||
bool operator!=(const InterfaceVariable &other) const { return !operator==(other); }
|
||||
|
||||
int location;
|
||||
};
|
||||
|
||||
struct COMPILER_EXPORT Attribute : public InterfaceVariable
|
||||
{
|
||||
Attribute();
|
||||
~Attribute();
|
||||
Attribute(const Attribute &other);
|
||||
Attribute &operator=(const Attribute &other);
|
||||
bool operator==(const Attribute &other) const;
|
||||
bool operator!=(const Attribute &other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
bool operator!=(const Attribute &other) const { return !operator==(other); }
|
||||
};
|
||||
|
||||
int location;
|
||||
struct COMPILER_EXPORT OutputVariable : public InterfaceVariable
|
||||
{
|
||||
OutputVariable();
|
||||
~OutputVariable();
|
||||
OutputVariable(const OutputVariable &other);
|
||||
OutputVariable &operator=(const OutputVariable &other);
|
||||
bool operator==(const OutputVariable &other) const;
|
||||
bool operator!=(const OutputVariable &other) const { return !operator==(other); }
|
||||
};
|
||||
|
||||
struct COMPILER_EXPORT InterfaceBlockField : public ShaderVariable
|
||||
@ -159,7 +181,12 @@ struct COMPILER_EXPORT Varying : public ShaderVariable
|
||||
|
||||
// Decide whether two varyings are the same at shader link time,
|
||||
// assuming one from vertex shader and the other from fragment shader.
|
||||
// See GLSL ES Spec 3.00.3, sec 4.3.9.
|
||||
// Invariance needs to match only in ESSL1. Relevant spec sections:
|
||||
// GLSL ES 3.00.4, sections 4.6.1 and 4.3.9.
|
||||
// GLSL ES 1.00.17, section 4.6.4.
|
||||
bool isSameVaryingAtLinkTime(const Varying &other, int shaderVersion) const;
|
||||
|
||||
// Deprecated version of isSameVaryingAtLinkTime, which assumes ESSL1.
|
||||
bool isSameVaryingAtLinkTime(const Varying &other) const;
|
||||
|
||||
InterpolationType interpolation;
|
||||
@ -173,6 +200,9 @@ struct COMPILER_EXPORT InterfaceBlock
|
||||
InterfaceBlock(const InterfaceBlock &other);
|
||||
InterfaceBlock &operator=(const InterfaceBlock &other);
|
||||
|
||||
// Fields from blocks with non-empty instance names are prefixed with the block name.
|
||||
std::string fieldPrefix() const;
|
||||
|
||||
std::string name;
|
||||
std::string mappedName;
|
||||
std::string instanceName;
|
||||
@ -183,6 +213,6 @@ struct COMPILER_EXPORT InterfaceBlock
|
||||
std::vector<InterfaceBlockField> fields;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace sh
|
||||
|
||||
#endif // GLSLANG_SHADERVARS_H_
|
||||
|
3
src/3rdparty/angle/include/angle_gl.h
vendored
3
src/3rdparty/angle/include/angle_gl.h
vendored
@ -13,7 +13,8 @@
|
||||
#include "GLES2/gl2.h"
|
||||
#include "GLES2/gl2ext.h"
|
||||
#include "GLES3/gl3.h"
|
||||
#include "GLES3/gl3ext.h"
|
||||
#include "GLES3/gl31.h"
|
||||
#include "GLES3/gl32.h"
|
||||
|
||||
// The following enum is used in ANGLE, but is from desktop GL
|
||||
#ifndef GL_SAMPLER_2D_RECT_ARB
|
||||
|
14
src/3rdparty/angle/include/angle_windowsstore.h
vendored
14
src/3rdparty/angle/include/angle_windowsstore.h
vendored
@ -28,10 +28,24 @@ const wchar_t EGLNativeWindowTypeProperty[] = L"EGLNativeWindowTypeProperty";
|
||||
// Description: Set this property to specify a preferred size in pixels of the render surface.
|
||||
// The render surface size width and height must be greater than 0.
|
||||
// If this property is set, then the render surface size is fixed.
|
||||
// The render surface will then be scaled to the window dimensions.
|
||||
// If this property is missing, a default behavior will be provided.
|
||||
// The default behavior uses the window size if a CoreWindow is specified or
|
||||
// the size of the SwapChainPanel control if one is specified.
|
||||
//
|
||||
const wchar_t EGLRenderSurfaceSizeProperty[] = L"EGLRenderSurfaceSizeProperty";
|
||||
|
||||
//
|
||||
// Property: EGLRenderResolutionScaleProperty
|
||||
// Type: Single
|
||||
// Description: Use this to specify a preferred scale for the render surface compared to the window.
|
||||
// For example, if the window is 800x480, and:
|
||||
// - scale is set to 0.5f then the surface will be 400x240
|
||||
// - scale is set to 1.2f then the surface will be 960x576
|
||||
// If the window resizes or rotates then the surface will resize accordingly.
|
||||
// EGLRenderResolutionScaleProperty and EGLRenderSurfaceSizeProperty cannot both be set.
|
||||
// The scale factor should be > 0.0f.
|
||||
//
|
||||
const wchar_t EGLRenderResolutionScaleProperty[] = L"EGLRenderResolutionScaleProperty";
|
||||
|
||||
#endif // ANGLE_WINDOWSSTORE_H_
|
||||
|
78
src/3rdparty/angle/include/platform/Platform.h
vendored
78
src/3rdparty/angle/include/platform/Platform.h
vendored
@ -11,7 +11,24 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../export.h"
|
||||
#if defined(_WIN32)
|
||||
# if !defined(LIBANGLE_IMPLEMENTATION)
|
||||
# define ANGLE_PLATFORM_EXPORT __declspec(dllimport)
|
||||
# endif
|
||||
#elif defined(__GNUC__)
|
||||
# if defined(LIBANGLE_IMPLEMENTATION)
|
||||
# define ANGLE_PLATFORM_EXPORT __attribute__((visibility ("default")))
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(ANGLE_PLATFORM_EXPORT)
|
||||
# define ANGLE_PLATFORM_EXPORT
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
# define ANGLE_APIENTRY __stdcall
|
||||
#else
|
||||
# define ANGLE_APIENTRY
|
||||
#endif
|
||||
|
||||
namespace angle
|
||||
{
|
||||
@ -20,8 +37,39 @@ class Platform
|
||||
{
|
||||
public:
|
||||
|
||||
// System --------------------------------------------------------------
|
||||
|
||||
// Wall clock time in seconds since the epoch.
|
||||
// TODO(jmadill): investigate using an ANGLE internal time library
|
||||
virtual double currentTime() { return 0; }
|
||||
|
||||
// Monotonically increasing time in seconds from an arbitrary fixed point in the past.
|
||||
// This function is expected to return at least millisecond-precision values. For this reason,
|
||||
// it is recommended that the fixed point be no further in the past than the epoch.
|
||||
virtual double monotonicallyIncreasingTime() { return 0; }
|
||||
|
||||
// Logging ------------------------------------------------------------
|
||||
|
||||
// Log an error message within the platform implementation.
|
||||
virtual void logError(const char *errorMessage) {}
|
||||
|
||||
// Log a warning message within the platform implementation.
|
||||
virtual void logWarning(const char *warningMessage) {}
|
||||
|
||||
// Log an info message within the platform implementation.
|
||||
virtual void logInfo(const char *infoMessage) {}
|
||||
|
||||
// Tracing --------
|
||||
|
||||
// Get a pointer to the enabled state of the given trace category. The
|
||||
// embedder can dynamically change the enabled state as trace event
|
||||
// recording is started and stopped by the application. Only long-lived
|
||||
// literal strings should be given as the category name. The implementation
|
||||
// expects the returned pointer to be held permanently in a local static. If
|
||||
// the unsigned char is non-zero, tracing is enabled. If tracing is enabled,
|
||||
// addTraceEvent is expected to be called by the trace event macros.
|
||||
virtual const unsigned char *getTraceCategoryEnabledFlag(const char *categoryName) { return 0; }
|
||||
|
||||
typedef uint64_t TraceEventHandle;
|
||||
|
||||
// Add a trace event to the platform tracing system. Depending on the actual
|
||||
@ -47,6 +95,7 @@ class Platform
|
||||
// - id optionally allows events of the same name to be distinguished from
|
||||
// each other. For example, to trace the consutruction and destruction of
|
||||
// objects, specify the pointer as the id parameter.
|
||||
// - timestamp should be a time value returned from monotonicallyIncreasingTime.
|
||||
// - numArgs specifies the number of elements in argNames, argTypes, and
|
||||
// argValues.
|
||||
// - argNames is the array of argument names. Use long-lived literal strings
|
||||
@ -84,15 +133,17 @@ class Platform
|
||||
}
|
||||
|
||||
// Set the duration field of a COMPLETE trace event.
|
||||
virtual void updateTraceEventDuration(const unsigned char* categoryEnabledFlag, const char* name, TraceEventHandle) { }
|
||||
virtual void updateTraceEventDuration(const unsigned char *categoryEnabledFlag, const char *name, TraceEventHandle eventHandle) { }
|
||||
|
||||
// Callbacks for reporting histogram data.
|
||||
// CustomCounts histogram has exponential bucket sizes, so that min=1, max=1000000, bucketCount=50 would do.
|
||||
virtual void histogramCustomCounts(const char* name, int sample, int min, int max, int bucketCount) { }
|
||||
virtual void histogramCustomCounts(const char *name, int sample, int min, int max, int bucketCount) { }
|
||||
// Enumeration histogram buckets are linear, boundaryValue should be larger than any possible sample value.
|
||||
virtual void histogramEnumeration(const char* name, int sample, int boundaryValue) { }
|
||||
virtual void histogramEnumeration(const char *name, int sample, int boundaryValue) { }
|
||||
// Unlike enumeration histograms, sparse histograms only allocate memory for non-empty buckets.
|
||||
virtual void histogramSparse(const char* name, int sample) { }
|
||||
virtual void histogramSparse(const char *name, int sample) { }
|
||||
// Boolean histograms track two-state variables.
|
||||
virtual void histogramBoolean(const char *name, bool sample) { }
|
||||
|
||||
protected:
|
||||
virtual ~Platform() { }
|
||||
@ -100,13 +151,18 @@ class Platform
|
||||
|
||||
}
|
||||
|
||||
typedef void(*ANGLEPlatformInitializeFunc)(angle::Platform*);
|
||||
ANGLE_EXPORT void ANGLEPlatformInitialize(angle::Platform*);
|
||||
extern "C"
|
||||
{
|
||||
|
||||
typedef void (*ANGLEPlatformShutdownFunc)();
|
||||
ANGLE_EXPORT void ANGLEPlatformShutdown();
|
||||
typedef void (ANGLE_APIENTRY *ANGLEPlatformInitializeFunc)(angle::Platform*);
|
||||
ANGLE_PLATFORM_EXPORT void ANGLE_APIENTRY ANGLEPlatformInitialize(angle::Platform*);
|
||||
|
||||
typedef angle::Platform *(*ANGLEPlatformCurrentFunc)();
|
||||
ANGLE_EXPORT angle::Platform *ANGLEPlatformCurrent();
|
||||
typedef void (ANGLE_APIENTRY *ANGLEPlatformShutdownFunc)();
|
||||
ANGLE_PLATFORM_EXPORT void ANGLE_APIENTRY ANGLEPlatformShutdown();
|
||||
|
||||
typedef angle::Platform *(ANGLE_APIENTRY *ANGLEPlatformCurrentFunc)();
|
||||
ANGLE_PLATFORM_EXPORT angle::Platform *ANGLE_APIENTRY ANGLEPlatformCurrent();
|
||||
|
||||
}
|
||||
|
||||
#endif // ANGLE_PLATFORM_H
|
||||
|
156
src/3rdparty/angle/src/common/BitSetIterator.h
vendored
Normal file
156
src/3rdparty/angle/src/common/BitSetIterator.h
vendored
Normal file
@ -0,0 +1,156 @@
|
||||
//
|
||||
// Copyright 2015 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// BitSetIterator:
|
||||
// A helper class to quickly bitscan bitsets for set bits.
|
||||
//
|
||||
|
||||
#ifndef COMMON_BITSETITERATOR_H_
|
||||
#define COMMON_BITSETITERATOR_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <bitset>
|
||||
|
||||
#include "common/angleutils.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/mathutil.h"
|
||||
#include "common/platform.h"
|
||||
|
||||
namespace angle
|
||||
{
|
||||
template <size_t N>
|
||||
class BitSetIterator final
|
||||
{
|
||||
public:
|
||||
BitSetIterator(const std::bitset<N> &bitset);
|
||||
BitSetIterator(const BitSetIterator &other);
|
||||
BitSetIterator &operator=(const BitSetIterator &other);
|
||||
|
||||
class Iterator final
|
||||
{
|
||||
public:
|
||||
Iterator(const std::bitset<N> &bits);
|
||||
Iterator &operator++();
|
||||
|
||||
bool operator==(const Iterator &other) const;
|
||||
bool operator!=(const Iterator &other) const;
|
||||
unsigned long operator*() const { return mCurrentBit; }
|
||||
|
||||
private:
|
||||
unsigned long getNextBit();
|
||||
|
||||
static const size_t BitsPerWord = sizeof(unsigned long) * 8;
|
||||
std::bitset<N> mBits;
|
||||
unsigned long mCurrentBit;
|
||||
unsigned long mOffset;
|
||||
};
|
||||
|
||||
Iterator begin() const { return Iterator(mBits); }
|
||||
Iterator end() const { return Iterator(std::bitset<N>(0)); }
|
||||
|
||||
private:
|
||||
const std::bitset<N> mBits;
|
||||
};
|
||||
|
||||
template <size_t N>
|
||||
BitSetIterator<N>::BitSetIterator(const std::bitset<N> &bitset)
|
||||
: mBits(bitset)
|
||||
{
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
BitSetIterator<N>::BitSetIterator(const BitSetIterator &other)
|
||||
: mBits(other.mBits)
|
||||
{
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
BitSetIterator<N> &BitSetIterator<N>::operator=(const BitSetIterator &other)
|
||||
{
|
||||
mBits = other.mBits;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
BitSetIterator<N>::Iterator::Iterator(const std::bitset<N> &bits)
|
||||
: mBits(bits), mCurrentBit(0), mOffset(0)
|
||||
{
|
||||
if (bits.any())
|
||||
{
|
||||
mCurrentBit = getNextBit();
|
||||
}
|
||||
else
|
||||
{
|
||||
mOffset = static_cast<unsigned long>(rx::roundUp(N, BitsPerWord));
|
||||
}
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
typename BitSetIterator<N>::Iterator &BitSetIterator<N>::Iterator::operator++()
|
||||
{
|
||||
ASSERT(mBits.any());
|
||||
mBits.set(mCurrentBit - mOffset, 0);
|
||||
mCurrentBit = getNextBit();
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline unsigned long ScanForward(unsigned long bits)
|
||||
{
|
||||
ASSERT(bits != 0);
|
||||
#if defined(ANGLE_PLATFORM_WINDOWS)
|
||||
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));
|
||||
#else
|
||||
#error Please implement bit-scan-forward for your platform!
|
||||
#endif
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
bool BitSetIterator<N>::Iterator::operator==(const Iterator &other) const
|
||||
{
|
||||
return mOffset == other.mOffset && mBits == other.mBits;
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
bool BitSetIterator<N>::Iterator::operator!=(const Iterator &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
unsigned long BitSetIterator<N>::Iterator::getNextBit()
|
||||
{
|
||||
static std::bitset<N> wordMask(std::numeric_limits<unsigned long>::max());
|
||||
|
||||
while (mOffset < N)
|
||||
{
|
||||
unsigned long wordBits = (mBits & wordMask).to_ulong();
|
||||
if (wordBits != 0ul)
|
||||
{
|
||||
return ScanForward(wordBits) + mOffset;
|
||||
}
|
||||
|
||||
mBits >>= BitsPerWord;
|
||||
mOffset += BitsPerWord;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Helper to avoid needing to specify the template parameter size
|
||||
template <size_t N>
|
||||
BitSetIterator<N> IterateBitSet(const std::bitset<N> &bitset)
|
||||
{
|
||||
return BitSetIterator<N>(bitset);
|
||||
}
|
||||
|
||||
} // angle
|
||||
|
||||
#endif // COMMON_BITSETITERATOR_H_
|
@ -6,6 +6,8 @@
|
||||
|
||||
// This file is automatically generated.
|
||||
|
||||
#include "common/mathutil.h"
|
||||
|
||||
namespace gl
|
||||
{
|
||||
|
||||
@ -2197,7 +2199,7 @@ const static unsigned g_offset[64] = {
|
||||
float float16ToFloat32(unsigned short h)
|
||||
{
|
||||
unsigned i32 = g_mantissa[g_offset[h >> 10] + (h & 0x3ff)] + g_exponent[h >> 10];
|
||||
return *(float*) &i32;
|
||||
return bitCast<float>(i32);
|
||||
}
|
||||
}
|
||||
|
20
src/3rdparty/angle/src/common/Optional.h
vendored
20
src/3rdparty/angle/src/common/Optional.h
vendored
@ -35,11 +35,27 @@ struct Optional
|
||||
return *this;
|
||||
}
|
||||
|
||||
static Optional None()
|
||||
Optional &operator=(const T &value)
|
||||
{
|
||||
return Optional();
|
||||
mValue = value;
|
||||
mValid = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Optional &operator=(T &&value)
|
||||
{
|
||||
mValue = std::move(value);
|
||||
mValid = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
mValid = false;
|
||||
}
|
||||
|
||||
static Optional Invalid() { return Optional(); }
|
||||
|
||||
bool valid() const { return mValid; }
|
||||
const T &value() const { return mValue; }
|
||||
|
||||
|
7
src/3rdparty/angle/src/common/angleutils.cpp
vendored
7
src/3rdparty/angle/src/common/angleutils.cpp
vendored
@ -8,8 +8,15 @@
|
||||
#include "common/debug.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
namespace angle
|
||||
{
|
||||
const uintptr_t DirtyPointer = std::numeric_limits<uintptr_t>::max();
|
||||
}
|
||||
|
||||
size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char>& outBuffer)
|
||||
{
|
||||
// Attempt to just print to the current buffer
|
||||
|
7
src/3rdparty/angle/src/common/angleutils.h
vendored
7
src/3rdparty/angle/src/common/angleutils.h
vendored
@ -25,16 +25,15 @@ namespace angle
|
||||
|
||||
class NonCopyable
|
||||
{
|
||||
#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
|
||||
public:
|
||||
NonCopyable() = default;
|
||||
~NonCopyable() = default;
|
||||
protected:
|
||||
NonCopyable(const NonCopyable&) = delete;
|
||||
void operator=(const NonCopyable&) = delete;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern const uintptr_t DirtyPointer;
|
||||
}
|
||||
|
||||
template <typename T, size_t N>
|
||||
@ -72,9 +71,9 @@ void SafeDelete(T*& resource)
|
||||
template <typename T>
|
||||
void SafeDeleteContainer(T& resource)
|
||||
{
|
||||
for (typename T::iterator i = resource.begin(); i != resource.end(); i++)
|
||||
for (auto &element : resource)
|
||||
{
|
||||
SafeDelete(*i);
|
||||
SafeDelete(element);
|
||||
}
|
||||
resource.clear();
|
||||
}
|
||||
|
6
src/3rdparty/angle/src/common/debug.cpp
vendored
6
src/3rdparty/angle/src/common/debug.cpp
vendored
@ -44,16 +44,16 @@ void output(bool traceInDebugOnly, MessageType messageType, DebugTraceOutputType
|
||||
case DebugTraceOutputTypeNone:
|
||||
break;
|
||||
case DebugTraceOutputTypeBeginEvent:
|
||||
g_debugAnnotator->beginEvent(formattedWideMessage);
|
||||
g_debugAnnotator->beginEvent(formattedWideMessage.c_str());
|
||||
break;
|
||||
case DebugTraceOutputTypeSetMarker:
|
||||
g_debugAnnotator->setMarker(formattedWideMessage);
|
||||
g_debugAnnotator->setMarker(formattedWideMessage.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::string formattedMessage;
|
||||
UNUSED_TRACE_VARIABLE(formattedMessage);
|
||||
UNUSED_VARIABLE(formattedMessage);
|
||||
|
||||
#if !defined(NDEBUG) && defined(_MSC_VER)
|
||||
if (messageType == MESSAGE_ERR)
|
||||
|
37
src/3rdparty/angle/src/common/debug.h
vendored
37
src/3rdparty/angle/src/common/debug.h
vendored
@ -16,7 +16,7 @@
|
||||
#include "common/angleutils.h"
|
||||
|
||||
#if !defined(TRACE_OUTPUT_FILE)
|
||||
#define TRACE_OUTPUT_FILE "debug.txt"
|
||||
#define TRACE_OUTPUT_FILE "angle_debug.txt"
|
||||
#endif
|
||||
|
||||
namespace gl
|
||||
@ -47,9 +47,9 @@ class DebugAnnotator : angle::NonCopyable
|
||||
public:
|
||||
DebugAnnotator() { };
|
||||
virtual ~DebugAnnotator() { };
|
||||
virtual void beginEvent(const std::wstring &eventName) = 0;
|
||||
virtual void beginEvent(const wchar_t *eventName) = 0;
|
||||
virtual void endEvent() = 0;
|
||||
virtual void setMarker(const std::wstring &markerName) = 0;
|
||||
virtual void setMarker(const wchar_t *markerName) = 0;
|
||||
virtual bool getStatus() = 0;
|
||||
};
|
||||
|
||||
@ -63,6 +63,8 @@ bool DebugAnnotationsActive();
|
||||
#define ANGLE_TRACE_ENABLED
|
||||
#endif
|
||||
|
||||
#define ANGLE_EMPTY_STATEMENT for (;;) break
|
||||
|
||||
// A macro to output a trace of a function call and its arguments to the debugging log
|
||||
#if defined(ANGLE_TRACE_ENABLED)
|
||||
#define TRACE(message, ...) gl::trace(true, gl::MESSAGE_TRACE, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
@ -89,7 +91,7 @@ bool DebugAnnotationsActive();
|
||||
#if defined(_MSC_VER)
|
||||
#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__("%s" message "\n", __FUNCTION__, __VA_ARGS__);
|
||||
#else
|
||||
#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper(message "\n", ##__VA_ARGS__);
|
||||
#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper("%s" message "\n", __FUNCTION__, ##__VA_ARGS__);
|
||||
#endif // _MSC_VER
|
||||
#else
|
||||
#define EVENT(message, ...) (void(0))
|
||||
@ -101,22 +103,18 @@ bool DebugAnnotationsActive();
|
||||
|
||||
// A macro asserting a condition and outputting failures to the debug log
|
||||
#if !defined(NDEBUG)
|
||||
#define ASSERT(expression) do { \
|
||||
#define ASSERT(expression) { \
|
||||
if(!(expression)) \
|
||||
ERR("\t! Assert failed in %s(%d): "#expression"\n", __FUNCTION__, __LINE__); \
|
||||
ERR("\t! Assert failed in %s(%d): %s\n", __FUNCTION__, __LINE__, #expression); \
|
||||
assert(expression); \
|
||||
} while(0)
|
||||
} ANGLE_EMPTY_STATEMENT
|
||||
#define UNUSED_ASSERTION_VARIABLE(variable)
|
||||
#else
|
||||
#define ASSERT(expression) (void(0))
|
||||
#define UNUSED_ASSERTION_VARIABLE(variable) ((void)variable)
|
||||
#endif
|
||||
|
||||
#ifndef ANGLE_ENABLE_DEBUG_TRACE
|
||||
#define UNUSED_TRACE_VARIABLE(variable) ((void)variable)
|
||||
#else
|
||||
#define UNUSED_TRACE_VARIABLE(variable)
|
||||
#endif
|
||||
#define UNUSED_VARIABLE(variable) ((void)variable)
|
||||
|
||||
// A macro to indicate unimplemented functionality
|
||||
|
||||
@ -131,29 +129,22 @@ bool DebugAnnotationsActive();
|
||||
#endif
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
#define UNIMPLEMENTED() do { \
|
||||
#define UNIMPLEMENTED() { \
|
||||
FIXME("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__); \
|
||||
assert(NOASSERT_UNIMPLEMENTED); \
|
||||
} while(0)
|
||||
} 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
|
||||
#if !defined(NDEBUG)
|
||||
#define UNREACHABLE() do { \
|
||||
#define UNREACHABLE() { \
|
||||
ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__); \
|
||||
assert(false); \
|
||||
} while(0)
|
||||
} ANGLE_EMPTY_STATEMENT
|
||||
#else
|
||||
#define UNREACHABLE() ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__)
|
||||
#endif
|
||||
|
||||
// A macro that determines whether an object has a given runtime type.
|
||||
#if !defined(NDEBUG) && (!defined(_MSC_VER) || defined(_CPPRTTI)) && (!defined(__GNUC__) || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || defined(__GXX_RTTI))
|
||||
#define HAS_DYNAMIC_TYPE(type, obj) (dynamic_cast<type >(obj) != NULL)
|
||||
#else
|
||||
#define HAS_DYNAMIC_TYPE(type, obj) true
|
||||
#endif
|
||||
|
||||
#endif // COMMON_DEBUG_H_
|
||||
|
52
src/3rdparty/angle/src/common/event_tracer.cpp
vendored
52
src/3rdparty/angle/src/common/event_tracer.cpp
vendored
@ -4,35 +4,53 @@
|
||||
|
||||
#include "common/event_tracer.h"
|
||||
|
||||
namespace gl
|
||||
#include "common/debug.h"
|
||||
|
||||
namespace angle
|
||||
{
|
||||
|
||||
GetCategoryEnabledFlagFunc g_getCategoryEnabledFlag;
|
||||
AddTraceEventFunc g_addTraceEvent;
|
||||
|
||||
} // namespace gl
|
||||
|
||||
namespace gl
|
||||
const unsigned char *GetTraceCategoryEnabledFlag(const char *name)
|
||||
{
|
||||
angle::Platform *platform = ANGLEPlatformCurrent();
|
||||
ASSERT(platform);
|
||||
|
||||
const unsigned char* TraceGetTraceCategoryEnabledFlag(const char* name)
|
||||
{
|
||||
if (g_getCategoryEnabledFlag)
|
||||
const unsigned char *categoryEnabledFlag = platform->getTraceCategoryEnabledFlag(name);
|
||||
if (categoryEnabledFlag != nullptr)
|
||||
{
|
||||
return g_getCategoryEnabledFlag(name);
|
||||
return categoryEnabledFlag;
|
||||
}
|
||||
|
||||
static unsigned char disabled = 0;
|
||||
return &disabled;
|
||||
}
|
||||
|
||||
void TraceAddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id,
|
||||
int numArgs, const char** argNames, const unsigned char* argTypes,
|
||||
const unsigned long long* argValues, unsigned char flags)
|
||||
Platform::TraceEventHandle AddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id,
|
||||
int numArgs, const char** argNames, const unsigned char* argTypes,
|
||||
const unsigned long long* argValues, unsigned char flags)
|
||||
{
|
||||
if (g_addTraceEvent)
|
||||
angle::Platform *platform = ANGLEPlatformCurrent();
|
||||
ASSERT(platform);
|
||||
|
||||
double timestamp = platform->monotonicallyIncreasingTime();
|
||||
|
||||
if (timestamp != 0)
|
||||
{
|
||||
g_addTraceEvent(phase, categoryGroupEnabled, name, id, numArgs, argNames, argTypes, argValues, flags);
|
||||
angle::Platform::TraceEventHandle handle =
|
||||
platform->addTraceEvent(phase,
|
||||
categoryGroupEnabled,
|
||||
name,
|
||||
id,
|
||||
timestamp,
|
||||
numArgs,
|
||||
argNames,
|
||||
argTypes,
|
||||
argValues,
|
||||
flags);
|
||||
ASSERT(handle != 0);
|
||||
return handle;
|
||||
}
|
||||
|
||||
return static_cast<Platform::TraceEventHandle>(0);
|
||||
}
|
||||
|
||||
} // namespace gl
|
||||
} // namespace angle
|
||||
|
26
src/3rdparty/angle/src/common/event_tracer.h
vendored
26
src/3rdparty/angle/src/common/event_tracer.h
vendored
@ -6,28 +6,16 @@
|
||||
#define COMMON_EVENT_TRACER_H_
|
||||
|
||||
#include "common/platform.h"
|
||||
#include "platform/Platform.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
typedef const unsigned char* (*GetCategoryEnabledFlagFunc)(const char* name);
|
||||
typedef void (*AddTraceEventFunc)(char phase, const unsigned char* categoryGroupEnabled, const char* name,
|
||||
unsigned long long id, int numArgs, const char** argNames,
|
||||
const unsigned char* argTypes, const unsigned long long* argValues,
|
||||
unsigned char flags);
|
||||
|
||||
}
|
||||
|
||||
namespace gl
|
||||
namespace angle
|
||||
{
|
||||
|
||||
extern GetCategoryEnabledFlagFunc g_getCategoryEnabledFlag;
|
||||
extern AddTraceEventFunc g_addTraceEvent;
|
||||
|
||||
const unsigned char* TraceGetTraceCategoryEnabledFlag(const char* name);
|
||||
|
||||
void TraceAddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id,
|
||||
int numArgs, const char** argNames, const unsigned char* argTypes,
|
||||
const unsigned long long* argValues, unsigned char flags);
|
||||
const unsigned char *GetTraceCategoryEnabledFlag(const char* name);
|
||||
Platform::TraceEventHandle AddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name,
|
||||
unsigned long long id, int numArgs, const char** argNames,
|
||||
const unsigned char* argTypes, const unsigned long long* argValues,
|
||||
unsigned char flags);
|
||||
|
||||
}
|
||||
|
||||
|
12
src/3rdparty/angle/src/common/mathutil.cpp
vendored
12
src/3rdparty/angle/src/common/mathutil.cpp
vendored
@ -43,16 +43,16 @@ unsigned int convertRGBFloatsTo999E5(float red, float green, float blue)
|
||||
|
||||
const float max_c = std::max<float>(std::max<float>(red_c, green_c), blue_c);
|
||||
const float exp_p = std::max<float>(-g_sharedexp_bias - 1, floor(log(max_c))) + 1 + g_sharedexp_bias;
|
||||
const int max_s = floor((max_c / (pow(2.0f, exp_p - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f);
|
||||
const int exp_s = (max_s < pow(2.0f, g_sharedexp_mantissabits)) ? exp_p : exp_p + 1;
|
||||
const int max_s = static_cast<int>(floor((max_c / (pow(2.0f, exp_p - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
|
||||
const int exp_s = static_cast<int>((max_s < pow(2.0f, g_sharedexp_mantissabits)) ? exp_p : exp_p + 1);
|
||||
|
||||
RGB9E5Data output;
|
||||
output.R = floor((red_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f);
|
||||
output.G = floor((green_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f);
|
||||
output.B = floor((blue_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f);
|
||||
output.R = static_cast<unsigned int>(floor((red_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
|
||||
output.G = static_cast<unsigned int>(floor((green_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
|
||||
output.B = static_cast<unsigned int>(floor((blue_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
|
||||
output.E = exp_s;
|
||||
|
||||
return *reinterpret_cast<unsigned int*>(&output);
|
||||
return bitCast<unsigned int>(output);
|
||||
}
|
||||
|
||||
void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float *blue)
|
||||
|
204
src/3rdparty/angle/src/common/mathutil.h
vendored
204
src/3rdparty/angle/src/common/mathutil.h
vendored
@ -14,7 +14,9 @@
|
||||
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace gl
|
||||
@ -67,14 +69,29 @@ inline int clampToInt(unsigned int x)
|
||||
template <typename DestT, typename SrcT>
|
||||
inline DestT clampCast(SrcT value)
|
||||
{
|
||||
// This assumes SrcT can properly represent DestT::min/max
|
||||
// Unfortunately we can't use META_ASSERT without C++11 constexpr support
|
||||
ASSERT(static_cast<DestT>(static_cast<SrcT>(std::numeric_limits<DestT>::min())) == std::numeric_limits<DestT>::min());
|
||||
ASSERT(static_cast<DestT>(static_cast<SrcT>(std::numeric_limits<DestT>::max())) == std::numeric_limits<DestT>::max());
|
||||
static const DestT destLo = std::numeric_limits<DestT>::min();
|
||||
static const DestT destHi = std::numeric_limits<DestT>::max();
|
||||
static const SrcT srcLo = static_cast<SrcT>(destLo);
|
||||
static const SrcT srcHi = static_cast<SrcT>(destHi);
|
||||
|
||||
SrcT lo = static_cast<SrcT>(std::numeric_limits<DestT>::min());
|
||||
SrcT hi = static_cast<SrcT>(std::numeric_limits<DestT>::max());
|
||||
return static_cast<DestT>(value > lo ? (value > hi ? hi : value) : lo);
|
||||
// When value is outside of or equal to the limits for DestT we use the DestT limit directly.
|
||||
// This avoids undefined behaviors due to loss of precision when converting from floats to
|
||||
// integers:
|
||||
// destHi for ints is 2147483647 but the closest float number is around 2147483648, so when
|
||||
// doing a conversion from float to int we run into an UB because the float is outside of the
|
||||
// range representable by the int.
|
||||
if (value <= srcLo)
|
||||
{
|
||||
return destLo;
|
||||
}
|
||||
else if (value >= srcHi)
|
||||
{
|
||||
return destHi;
|
||||
}
|
||||
else
|
||||
{
|
||||
return static_cast<DestT>(value);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename MIN, typename MAX>
|
||||
@ -119,9 +136,6 @@ inline bool supportsSSE2()
|
||||
return supports;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__)
|
||||
supports = __builtin_cpu_supports("sse2");
|
||||
#else
|
||||
int info[4];
|
||||
__cpuid(info, 0);
|
||||
|
||||
@ -131,7 +145,6 @@ inline bool supportsSSE2()
|
||||
|
||||
supports = (info[3] >> 26) & 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
checked = true;
|
||||
|
||||
@ -153,13 +166,13 @@ destType bitCast(const sourceType &source)
|
||||
|
||||
inline unsigned short float32ToFloat16(float fp32)
|
||||
{
|
||||
unsigned int fp32i = (unsigned int&)fp32;
|
||||
unsigned int fp32i = bitCast<unsigned int>(fp32);
|
||||
unsigned int sign = (fp32i & 0x80000000) >> 16;
|
||||
unsigned int abs = fp32i & 0x7FFFFFFF;
|
||||
|
||||
if(abs > 0x47FFEFFF) // Infinity
|
||||
{
|
||||
return sign | 0x7FFF;
|
||||
return static_cast<unsigned short>(sign | 0x7FFF);
|
||||
}
|
||||
else if(abs < 0x38800000) // Denormal
|
||||
{
|
||||
@ -175,11 +188,11 @@ inline unsigned short float32ToFloat16(float fp32)
|
||||
abs = 0;
|
||||
}
|
||||
|
||||
return sign | (abs + 0x00000FFF + ((abs >> 13) & 1)) >> 13;
|
||||
return static_cast<unsigned short>(sign | (abs + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
|
||||
}
|
||||
else
|
||||
{
|
||||
return sign | (abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13;
|
||||
return static_cast<unsigned short>(sign | (abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
|
||||
}
|
||||
}
|
||||
|
||||
@ -426,14 +439,14 @@ inline float normalizedToFloat(T input)
|
||||
template <typename T>
|
||||
inline T floatToNormalized(float input)
|
||||
{
|
||||
return std::numeric_limits<T>::max() * input + 0.5f;
|
||||
return static_cast<T>(std::numeric_limits<T>::max() * input + 0.5f);
|
||||
}
|
||||
|
||||
template <unsigned int outputBitCount, typename T>
|
||||
inline T floatToNormalized(float input)
|
||||
{
|
||||
static_assert(outputBitCount < (sizeof(T) * 8), "T must have more bits than outputBitCount.");
|
||||
return ((1 << outputBitCount) - 1) * input + 0.5f;
|
||||
return static_cast<T>(((1 << outputBitCount) - 1) * input + 0.5f);
|
||||
}
|
||||
|
||||
template <unsigned int inputBitCount, unsigned int inputBitStart, typename T>
|
||||
@ -480,9 +493,10 @@ inline unsigned int average(unsigned int a, unsigned int b)
|
||||
return ((a ^ b) >> 1) + (a & b);
|
||||
}
|
||||
|
||||
inline signed int average(signed int a, signed int b)
|
||||
inline int average(int a, int b)
|
||||
{
|
||||
return ((long long)a + (long long)b) / 2;
|
||||
long long average = (static_cast<long long>(a) + static_cast<long long>(b)) / 2ll;
|
||||
return static_cast<int>(average);
|
||||
}
|
||||
|
||||
inline float average(float a, float b)
|
||||
@ -497,20 +511,14 @@ inline unsigned short averageHalfFloat(unsigned short a, unsigned short b)
|
||||
|
||||
inline unsigned int averageFloat11(unsigned int a, unsigned int b)
|
||||
{
|
||||
return float32ToFloat11((float11ToFloat32(a) + float11ToFloat32(b)) * 0.5f);
|
||||
return float32ToFloat11((float11ToFloat32(static_cast<unsigned short>(a)) + float11ToFloat32(static_cast<unsigned short>(b))) * 0.5f);
|
||||
}
|
||||
|
||||
inline unsigned int averageFloat10(unsigned int a, unsigned int b)
|
||||
{
|
||||
return float32ToFloat10((float10ToFloat32(a) + float10ToFloat32(b)) * 0.5f);
|
||||
return float32ToFloat10((float10ToFloat32(static_cast<unsigned short>(a)) + float10ToFloat32(static_cast<unsigned short>(b))) * 0.5f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
||||
// Represents intervals of the type [a, b)
|
||||
template <typename T>
|
||||
struct Range
|
||||
{
|
||||
@ -533,11 +541,146 @@ struct Range
|
||||
return start < other.end;
|
||||
}
|
||||
}
|
||||
|
||||
void extend(T value)
|
||||
{
|
||||
start = value > start ? value : start;
|
||||
end = value < end ? value : end;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return end <= start;
|
||||
}
|
||||
};
|
||||
|
||||
typedef Range<int> RangeI;
|
||||
typedef Range<unsigned int> RangeUI;
|
||||
|
||||
struct IndexRange
|
||||
{
|
||||
IndexRange() : IndexRange(0, 0, 0) {}
|
||||
IndexRange(size_t start_, size_t end_, size_t vertexIndexCount_)
|
||||
: start(start_), end(end_), vertexIndexCount(vertexIndexCount_)
|
||||
{
|
||||
ASSERT(start <= end);
|
||||
}
|
||||
|
||||
// Number of vertices in the range.
|
||||
size_t vertexCount() const { return (end - start) + 1; }
|
||||
|
||||
// Inclusive range of indices that are not primitive restart
|
||||
size_t start;
|
||||
size_t end;
|
||||
|
||||
// Number of non-primitive restart indices
|
||||
size_t vertexIndexCount;
|
||||
};
|
||||
|
||||
// First, both normalized floating-point values are converted into 16-bit integer values.
|
||||
// Then, the results are packed into the returned 32-bit unsigned integer.
|
||||
// The first float value will be written to the least significant bits of the output;
|
||||
// the last float value will be written to the most significant bits.
|
||||
// The conversion of each value to fixed point is done as follows :
|
||||
// packSnorm2x16 : round(clamp(c, -1, +1) * 32767.0)
|
||||
inline uint32_t packSnorm2x16(float f1, float f2)
|
||||
{
|
||||
int16_t leastSignificantBits = static_cast<int16_t>(roundf(clamp(f1, -1.0f, 1.0f) * 32767.0f));
|
||||
int16_t mostSignificantBits = static_cast<int16_t>(roundf(clamp(f2, -1.0f, 1.0f) * 32767.0f));
|
||||
return static_cast<uint32_t>(mostSignificantBits) << 16 |
|
||||
(static_cast<uint32_t>(leastSignificantBits) & 0xFFFF);
|
||||
}
|
||||
|
||||
// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then, each
|
||||
// component is converted to a normalized floating-point value to generate the returned two float values.
|
||||
// The first float value will be extracted from the least significant bits of the input;
|
||||
// the last float value will be extracted from the most-significant bits.
|
||||
// The conversion for unpacked fixed-point value to floating point is done as follows:
|
||||
// unpackSnorm2x16 : clamp(f / 32767.0, -1, +1)
|
||||
inline void unpackSnorm2x16(uint32_t u, float *f1, float *f2)
|
||||
{
|
||||
int16_t leastSignificantBits = static_cast<int16_t>(u & 0xFFFF);
|
||||
int16_t mostSignificantBits = static_cast<int16_t>(u >> 16);
|
||||
*f1 = clamp(static_cast<float>(leastSignificantBits) / 32767.0f, -1.0f, 1.0f);
|
||||
*f2 = clamp(static_cast<float>(mostSignificantBits) / 32767.0f, -1.0f, 1.0f);
|
||||
}
|
||||
|
||||
// First, both normalized floating-point values are converted into 16-bit integer values.
|
||||
// Then, the results are packed into the returned 32-bit unsigned integer.
|
||||
// The first float value will be written to the least significant bits of the output;
|
||||
// the last float value will be written to the most significant bits.
|
||||
// The conversion of each value to fixed point is done as follows:
|
||||
// packUnorm2x16 : round(clamp(c, 0, +1) * 65535.0)
|
||||
inline uint32_t packUnorm2x16(float f1, float f2)
|
||||
{
|
||||
uint16_t leastSignificantBits = static_cast<uint16_t>(roundf(clamp(f1, 0.0f, 1.0f) * 65535.0f));
|
||||
uint16_t mostSignificantBits = static_cast<uint16_t>(roundf(clamp(f2, 0.0f, 1.0f) * 65535.0f));
|
||||
return static_cast<uint32_t>(mostSignificantBits) << 16 | static_cast<uint32_t>(leastSignificantBits);
|
||||
}
|
||||
|
||||
// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then, each
|
||||
// component is converted to a normalized floating-point value to generate the returned two float values.
|
||||
// The first float value will be extracted from the least significant bits of the input;
|
||||
// the last float value will be extracted from the most-significant bits.
|
||||
// The conversion for unpacked fixed-point value to floating point is done as follows:
|
||||
// unpackUnorm2x16 : f / 65535.0
|
||||
inline void unpackUnorm2x16(uint32_t u, float *f1, float *f2)
|
||||
{
|
||||
uint16_t leastSignificantBits = static_cast<uint16_t>(u & 0xFFFF);
|
||||
uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16);
|
||||
*f1 = static_cast<float>(leastSignificantBits) / 65535.0f;
|
||||
*f2 = static_cast<float>(mostSignificantBits) / 65535.0f;
|
||||
}
|
||||
|
||||
// Returns an unsigned integer obtained by converting the two floating-point values to the 16-bit
|
||||
// floating-point representation found in the OpenGL ES Specification, and then packing these
|
||||
// two 16-bit integers into a 32-bit unsigned integer.
|
||||
// f1: The 16 least-significant bits of the result;
|
||||
// f2: The 16 most-significant bits.
|
||||
inline uint32_t packHalf2x16(float f1, float f2)
|
||||
{
|
||||
uint16_t leastSignificantBits = static_cast<uint16_t>(float32ToFloat16(f1));
|
||||
uint16_t mostSignificantBits = static_cast<uint16_t>(float32ToFloat16(f2));
|
||||
return static_cast<uint32_t>(mostSignificantBits) << 16 | static_cast<uint32_t>(leastSignificantBits);
|
||||
}
|
||||
|
||||
// Returns two floating-point values obtained by unpacking a 32-bit unsigned integer into a pair of 16-bit values,
|
||||
// interpreting those values as 16-bit floating-point numbers according to the OpenGL ES Specification,
|
||||
// and converting them to 32-bit floating-point values.
|
||||
// The first float value is obtained from the 16 least-significant bits of u;
|
||||
// the second component is obtained from the 16 most-significant bits of u.
|
||||
inline void unpackHalf2x16(uint32_t u, float *f1, float *f2)
|
||||
{
|
||||
uint16_t leastSignificantBits = static_cast<uint16_t>(u & 0xFFFF);
|
||||
uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16);
|
||||
|
||||
*f1 = float16ToFloat32(leastSignificantBits);
|
||||
*f2 = float16ToFloat32(mostSignificantBits);
|
||||
}
|
||||
|
||||
// Returns whether the argument is Not a Number.
|
||||
// IEEE 754 single precision NaN representation: Exponent(8 bits) - 255, Mantissa(23 bits) - non-zero.
|
||||
inline bool isNaN(float f)
|
||||
{
|
||||
// Exponent mask: ((1u << 8) - 1u) << 23 = 0x7f800000u
|
||||
// Mantissa mask: ((1u << 23) - 1u) = 0x7fffffu
|
||||
return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) && (bitCast<uint32_t>(f) & 0x7fffffu);
|
||||
}
|
||||
|
||||
// Returns whether the argument is infinity.
|
||||
// IEEE 754 single precision infinity representation: Exponent(8 bits) - 255, Mantissa(23 bits) - zero.
|
||||
inline bool isInf(float f)
|
||||
{
|
||||
// Exponent mask: ((1u << 8) - 1u) << 23 = 0x7f800000u
|
||||
// Mantissa mask: ((1u << 23) - 1u) = 0x7fffffu
|
||||
return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) && !(bitCast<uint32_t>(f) & 0x7fffffu);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
T roundUp(const T value, const T alignment)
|
||||
{
|
||||
@ -573,6 +716,7 @@ inline bool IsIntegerCastSafe(BigIntT bigValue)
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
#define ANGLE_ROTL(x,y) _rotl(x,y)
|
||||
#define ANGLE_ROTR16(x,y) _rotr16(x,y)
|
||||
|
||||
#else
|
||||
|
||||
@ -581,7 +725,13 @@ inline uint32_t RotL(uint32_t x, int8_t r)
|
||||
return (x << r) | (x >> (32 - r));
|
||||
}
|
||||
|
||||
inline uint16_t RotR16(uint16_t x, int8_t r)
|
||||
{
|
||||
return (x >> r) | (x << (16 - r));
|
||||
}
|
||||
|
||||
#define ANGLE_ROTL(x,y) RotL(x,y)
|
||||
#define ANGLE_ROTR16(x,y) RotR16(x,y)
|
||||
|
||||
#endif // namespace rx
|
||||
|
||||
|
349
src/3rdparty/angle/src/common/matrix_utils.h
vendored
Normal file
349
src/3rdparty/angle/src/common/matrix_utils.h
vendored
Normal file
@ -0,0 +1,349 @@
|
||||
//
|
||||
// Copyright 2015 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// Matrix:
|
||||
// Utility class implementing various matrix operations.
|
||||
// Supports matrices with minimum 2 and maximum 4 number of rows/columns.
|
||||
//
|
||||
// TODO: Check if we can merge Matrix.h in sample_util with this and replace it with this implementation.
|
||||
// TODO: Rename this file to Matrix.h once we remove Matrix.h in sample_util.
|
||||
|
||||
#ifndef COMMON_MATRIX_UTILS_H_
|
||||
#define COMMON_MATRIX_UTILS_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "common/debug.h"
|
||||
|
||||
namespace angle
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
class Matrix
|
||||
{
|
||||
public:
|
||||
Matrix(const std::vector<T> &elements, const unsigned int &numRows, const unsigned int &numCols)
|
||||
: mElements(elements),
|
||||
mRows(numRows),
|
||||
mCols(numCols)
|
||||
{
|
||||
ASSERT(rows() >= 1 && rows() <= 4);
|
||||
ASSERT(columns() >= 1 && columns() <= 4);
|
||||
}
|
||||
|
||||
Matrix(const std::vector<T> &elements, const unsigned int &size)
|
||||
: mElements(elements),
|
||||
mRows(size),
|
||||
mCols(size)
|
||||
{
|
||||
ASSERT(rows() >= 1 && rows() <= 4);
|
||||
ASSERT(columns() >= 1 && columns() <= 4);
|
||||
}
|
||||
|
||||
Matrix(const T *elements, const unsigned int &size)
|
||||
: mRows(size),
|
||||
mCols(size)
|
||||
{
|
||||
ASSERT(rows() >= 1 && rows() <= 4);
|
||||
ASSERT(columns() >= 1 && columns() <= 4);
|
||||
for (size_t i = 0; i < size * size; i++)
|
||||
mElements.push_back(elements[i]);
|
||||
}
|
||||
|
||||
const T &operator()(const unsigned int &rowIndex, const unsigned int &columnIndex) const
|
||||
{
|
||||
return mElements[rowIndex * columns() + columnIndex];
|
||||
}
|
||||
|
||||
T &operator()(const unsigned int &rowIndex, const unsigned int &columnIndex)
|
||||
{
|
||||
return mElements[rowIndex * columns() + columnIndex];
|
||||
}
|
||||
|
||||
const T &at(const unsigned int &rowIndex, const unsigned int &columnIndex) const
|
||||
{
|
||||
return operator()(rowIndex, columnIndex);
|
||||
}
|
||||
|
||||
Matrix<T> operator*(const Matrix<T> &m)
|
||||
{
|
||||
ASSERT(columns() == m.rows());
|
||||
|
||||
unsigned int resultRows = rows();
|
||||
unsigned int resultCols = m.columns();
|
||||
Matrix<T> result(std::vector<T>(resultRows * resultCols), resultRows, resultCols);
|
||||
for (unsigned int i = 0; i < resultRows; i++)
|
||||
{
|
||||
for (unsigned int j = 0; j < resultCols; j++)
|
||||
{
|
||||
T tmp = 0.0f;
|
||||
for (unsigned int k = 0; k < columns(); k++)
|
||||
tmp += at(i, k) * m(k, j);
|
||||
result(i, j) = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned int size() const
|
||||
{
|
||||
ASSERT(rows() == columns());
|
||||
return rows();
|
||||
}
|
||||
|
||||
unsigned int rows() const { return mRows; }
|
||||
|
||||
unsigned int columns() const { return mCols; }
|
||||
|
||||
std::vector<T> elements() const { return mElements; }
|
||||
|
||||
Matrix<T> compMult(const Matrix<T> &mat1) const
|
||||
{
|
||||
Matrix result(std::vector<T>(mElements.size()), size());
|
||||
for (unsigned int i = 0; i < columns(); i++)
|
||||
for (unsigned int j = 0; j < rows(); j++)
|
||||
result(i, j) = at(i, j) * mat1(i, j);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Matrix<T> outerProduct(const Matrix<T> &mat1) const
|
||||
{
|
||||
unsigned int cols = mat1.columns();
|
||||
Matrix result(std::vector<T>(rows() * cols), rows(), cols);
|
||||
for (unsigned int i = 0; i < rows(); i++)
|
||||
for (unsigned int j = 0; j < cols; j++)
|
||||
result(i, j) = at(i, 0) * mat1(0, j);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Matrix<T> transpose() const
|
||||
{
|
||||
Matrix result(std::vector<T>(mElements.size()), columns(), rows());
|
||||
for (unsigned int i = 0; i < columns(); i++)
|
||||
for (unsigned int j = 0; j < rows(); j++)
|
||||
result(i, j) = at(j, i);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
T determinant() const
|
||||
{
|
||||
ASSERT(rows() == columns());
|
||||
|
||||
switch (size())
|
||||
{
|
||||
case 2:
|
||||
return at(0, 0) * at(1, 1) - at(0, 1) * at(1, 0);
|
||||
|
||||
case 3:
|
||||
return at(0, 0) * at(1, 1) * at(2, 2) +
|
||||
at(0, 1) * at(1, 2) * at(2, 0) +
|
||||
at(0, 2) * at(1, 0) * at(2, 1) -
|
||||
at(0, 2) * at(1, 1) * at(2, 0) -
|
||||
at(0, 1) * at(1, 0) * at(2, 2) -
|
||||
at(0, 0) * at(1, 2) * at(2, 1);
|
||||
|
||||
case 4:
|
||||
{
|
||||
const float minorMatrices[4][3 * 3] =
|
||||
{
|
||||
{
|
||||
at(1, 1), at(2, 1), at(3, 1),
|
||||
at(1, 2), at(2, 2), at(3, 2),
|
||||
at(1, 3), at(2, 3), at(3, 3),
|
||||
},
|
||||
{
|
||||
at(1, 0), at(2, 0), at(3, 0),
|
||||
at(1, 2), at(2, 2), at(3, 2),
|
||||
at(1, 3), at(2, 3), at(3, 3),
|
||||
},
|
||||
{
|
||||
at(1, 0), at(2, 0), at(3, 0),
|
||||
at(1, 1), at(2, 1), at(3, 1),
|
||||
at(1, 3), at(2, 3), at(3, 3),
|
||||
},
|
||||
{
|
||||
at(1, 0), at(2, 0), at(3, 0),
|
||||
at(1, 1), at(2, 1), at(3, 1),
|
||||
at(1, 2), at(2, 2), at(3, 2),
|
||||
}
|
||||
};
|
||||
return at(0, 0) * Matrix<T>(minorMatrices[0], 3).determinant() -
|
||||
at(0, 1) * Matrix<T>(minorMatrices[1], 3).determinant() +
|
||||
at(0, 2) * Matrix<T>(minorMatrices[2], 3).determinant() -
|
||||
at(0, 3) * Matrix<T>(minorMatrices[3], 3).determinant();
|
||||
}
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
return T();
|
||||
}
|
||||
|
||||
Matrix<T> inverse() const
|
||||
{
|
||||
ASSERT(rows() == columns());
|
||||
|
||||
Matrix<T> cof(std::vector<T>(mElements.size()), rows(), columns());
|
||||
switch (size())
|
||||
{
|
||||
case 2:
|
||||
cof(0, 0) = at(1, 1);
|
||||
cof(0, 1) = -at(1, 0);
|
||||
cof(1, 0) = -at(0, 1);
|
||||
cof(1, 1) = at(0, 0);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
cof(0, 0) = at(1, 1) * at(2, 2) -
|
||||
at(2, 1) * at(1, 2);
|
||||
cof(0, 1) = -(at(1, 0) * at(2, 2) -
|
||||
at(2, 0) * at(1, 2));
|
||||
cof(0, 2) = at(1, 0) * at(2, 1) -
|
||||
at(2, 0) * at(1, 1);
|
||||
cof(1, 0) = -(at(0, 1) * at(2, 2) -
|
||||
at(2, 1) * at(0, 2));
|
||||
cof(1, 1) = at(0, 0) * at(2, 2) -
|
||||
at(2, 0) * at(0, 2);
|
||||
cof(1, 2) = -(at(0, 0) * at(2, 1) -
|
||||
at(2, 0) * at(0, 1));
|
||||
cof(2, 0) = at(0, 1) * at(1, 2) -
|
||||
at(1, 1) * at(0, 2);
|
||||
cof(2, 1) = -(at(0, 0) * at(1, 2) -
|
||||
at(1, 0) * at(0, 2));
|
||||
cof(2, 2) = at(0, 0) * at(1, 1) -
|
||||
at(1, 0) * at(0, 1);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
cof(0, 0) = at(1, 1) * at(2, 2) * at(3, 3) +
|
||||
at(2, 1) * at(3, 2) * at(1, 3) +
|
||||
at(3, 1) * at(1, 2) * at(2, 3) -
|
||||
at(1, 1) * at(3, 2) * at(2, 3) -
|
||||
at(2, 1) * at(1, 2) * at(3, 3) -
|
||||
at(3, 1) * at(2, 2) * at(1, 3);
|
||||
cof(0, 1) = -(at(1, 0) * at(2, 2) * at(3, 3) +
|
||||
at(2, 0) * at(3, 2) * at(1, 3) +
|
||||
at(3, 0) * at(1, 2) * at(2, 3) -
|
||||
at(1, 0) * at(3, 2) * at(2, 3) -
|
||||
at(2, 0) * at(1, 2) * at(3, 3) -
|
||||
at(3, 0) * at(2, 2) * at(1, 3));
|
||||
cof(0, 2) = at(1, 0) * at(2, 1) * at(3, 3) +
|
||||
at(2, 0) * at(3, 1) * at(1, 3) +
|
||||
at(3, 0) * at(1, 1) * at(2, 3) -
|
||||
at(1, 0) * at(3, 1) * at(2, 3) -
|
||||
at(2, 0) * at(1, 1) * at(3, 3) -
|
||||
at(3, 0) * at(2, 1) * at(1, 3);
|
||||
cof(0, 3) = -(at(1, 0) * at(2, 1) * at(3, 2) +
|
||||
at(2, 0) * at(3, 1) * at(1, 2) +
|
||||
at(3, 0) * at(1, 1) * at(2, 2) -
|
||||
at(1, 0) * at(3, 1) * at(2, 2) -
|
||||
at(2, 0) * at(1, 1) * at(3, 2) -
|
||||
at(3, 0) * at(2, 1) * at(1, 2));
|
||||
cof(1, 0) = -(at(0, 1) * at(2, 2) * at(3, 3) +
|
||||
at(2, 1) * at(3, 2) * at(0, 3) +
|
||||
at(3, 1) * at(0, 2) * at(2, 3) -
|
||||
at(0, 1) * at(3, 2) * at(2, 3) -
|
||||
at(2, 1) * at(0, 2) * at(3, 3) -
|
||||
at(3, 1) * at(2, 2) * at(0, 3));
|
||||
cof(1, 1) = at(0, 0) * at(2, 2) * at(3, 3) +
|
||||
at(2, 0) * at(3, 2) * at(0, 3) +
|
||||
at(3, 0) * at(0, 2) * at(2, 3) -
|
||||
at(0, 0) * at(3, 2) * at(2, 3) -
|
||||
at(2, 0) * at(0, 2) * at(3, 3) -
|
||||
at(3, 0) * at(2, 2) * at(0, 3);
|
||||
cof(1, 2) = -(at(0, 0) * at(2, 1) * at(3, 3) +
|
||||
at(2, 0) * at(3, 1) * at(0, 3) +
|
||||
at(3, 0) * at(0, 1) * at(2, 3) -
|
||||
at(0, 0) * at(3, 1) * at(2, 3) -
|
||||
at(2, 0) * at(0, 1) * at(3, 3) -
|
||||
at(3, 0) * at(2, 1) * at(0, 3));
|
||||
cof(1, 3) = at(0, 0) * at(2, 1) * at(3, 2) +
|
||||
at(2, 0) * at(3, 1) * at(0, 2) +
|
||||
at(3, 0) * at(0, 1) * at(2, 2) -
|
||||
at(0, 0) * at(3, 1) * at(2, 2) -
|
||||
at(2, 0) * at(0, 1) * at(3, 2) -
|
||||
at(3, 0) * at(2, 1) * at(0, 2);
|
||||
cof(2, 0) = at(0, 1) * at(1, 2) * at(3, 3) +
|
||||
at(1, 1) * at(3, 2) * at(0, 3) +
|
||||
at(3, 1) * at(0, 2) * at(1, 3) -
|
||||
at(0, 1) * at(3, 2) * at(1, 3) -
|
||||
at(1, 1) * at(0, 2) * at(3, 3) -
|
||||
at(3, 1) * at(1, 2) * at(0, 3);
|
||||
cof(2, 1) = -(at(0, 0) * at(1, 2) * at(3, 3) +
|
||||
at(1, 0) * at(3, 2) * at(0, 3) +
|
||||
at(3, 0) * at(0, 2) * at(1, 3) -
|
||||
at(0, 0) * at(3, 2) * at(1, 3) -
|
||||
at(1, 0) * at(0, 2) * at(3, 3) -
|
||||
at(3, 0) * at(1, 2) * at(0, 3));
|
||||
cof(2, 2) = at(0, 0) * at(1, 1) * at(3, 3) +
|
||||
at(1, 0) * at(3, 1) * at(0, 3) +
|
||||
at(3, 0) * at(0, 1) * at(1, 3) -
|
||||
at(0, 0) * at(3, 1) * at(1, 3) -
|
||||
at(1, 0) * at(0, 1) * at(3, 3) -
|
||||
at(3, 0) * at(1, 1) * at(0, 3);
|
||||
cof(2, 3) = -(at(0, 0) * at(1, 1) * at(3, 2) +
|
||||
at(1, 0) * at(3, 1) * at(0, 2) +
|
||||
at(3, 0) * at(0, 1) * at(1, 2) -
|
||||
at(0, 0) * at(3, 1) * at(1, 2) -
|
||||
at(1, 0) * at(0, 1) * at(3, 2) -
|
||||
at(3, 0) * at(1, 1) * at(0, 2));
|
||||
cof(3, 0) = -(at(0, 1) * at(1, 2) * at(2, 3) +
|
||||
at(1, 1) * at(2, 2) * at(0, 3) +
|
||||
at(2, 1) * at(0, 2) * at(1, 3) -
|
||||
at(0, 1) * at(2, 2) * at(1, 3) -
|
||||
at(1, 1) * at(0, 2) * at(2, 3) -
|
||||
at(2, 1) * at(1, 2) * at(0, 3));
|
||||
cof(3, 1) = at(0, 0) * at(1, 2) * at(2, 3) +
|
||||
at(1, 0) * at(2, 2) * at(0, 3) +
|
||||
at(2, 0) * at(0, 2) * at(1, 3) -
|
||||
at(0, 0) * at(2, 2) * at(1, 3) -
|
||||
at(1, 0) * at(0, 2) * at(2, 3) -
|
||||
at(2, 0) * at(1, 2) * at(0, 3);
|
||||
cof(3, 2) = -(at(0, 0) * at(1, 1) * at(2, 3) +
|
||||
at(1, 0) * at(2, 1) * at(0, 3) +
|
||||
at(2, 0) * at(0, 1) * at(1, 3) -
|
||||
at(0, 0) * at(2, 1) * at(1, 3) -
|
||||
at(1, 0) * at(0, 1) * at(2, 3) -
|
||||
at(2, 0) * at(1, 1) * at(0, 3));
|
||||
cof(3, 3) = at(0, 0) * at(1, 1) * at(2, 2) +
|
||||
at(1, 0) * at(2, 1) * at(0, 2) +
|
||||
at(2, 0) * at(0, 1) * at(1, 2) -
|
||||
at(0, 0) * at(2, 1) * at(1, 2) -
|
||||
at(1, 0) * at(0, 1) * at(2, 2) -
|
||||
at(2, 0) * at(1, 1) * at(0, 2);
|
||||
break;
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
// The inverse of A is the transpose of the cofactor matrix times the reciprocal of the determinant of A.
|
||||
Matrix<T> adjugateMatrix(cof.transpose());
|
||||
T det = determinant();
|
||||
Matrix<T> result(std::vector<T>(mElements.size()), rows(), columns());
|
||||
for (unsigned int i = 0; i < rows(); i++)
|
||||
for (unsigned int j = 0; j < columns(); j++)
|
||||
result(i, j) = det ? adjugateMatrix(i, j) / det : T();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<T> mElements;
|
||||
unsigned int mRows;
|
||||
unsigned int mCols;
|
||||
};
|
||||
|
||||
} // namespace angle
|
||||
|
||||
#endif // COMMON_MATRIX_UTILS_H_
|
||||
|
9
src/3rdparty/angle/src/common/platform.h
vendored
9
src/3rdparty/angle/src/common/platform.h
vendored
@ -53,9 +53,7 @@
|
||||
|
||||
# if defined(ANGLE_ENABLE_D3D9)
|
||||
# include <d3d9.h>
|
||||
# if !defined(ANGLE_TRANSLATOR_IMPLEMENTATION)
|
||||
# include <d3dcompiler.h>
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if defined(ANGLE_ENABLE_D3D11)
|
||||
@ -72,9 +70,7 @@
|
||||
# include <d3d11_1.h>
|
||||
# include <dxgi1_2.h>
|
||||
# endif
|
||||
# if !defined(ANGLE_TRANSLATOR_IMPLEMENTATION)
|
||||
# include <d3dcompiler.h>
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if defined(ANGLE_ENABLE_WINDOWS_STORE)
|
||||
@ -87,11 +83,6 @@
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if defined(_MSC_VER) && (_MSC_VER <= 1600)
|
||||
# define final
|
||||
# define override
|
||||
# endif
|
||||
|
||||
# undef near
|
||||
# undef far
|
||||
#endif
|
||||
|
136
src/3rdparty/angle/src/common/string_utils.cpp
vendored
Normal file
136
src/3rdparty/angle/src/common/string_utils.cpp
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
//
|
||||
// Copyright 2015 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// string_utils:
|
||||
// String helper functions.
|
||||
//
|
||||
|
||||
#include "string_utils.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
namespace angle
|
||||
{
|
||||
|
||||
const char kWhitespaceASCII[] = " \f\n\r\t\v";
|
||||
|
||||
std::vector<std::string> SplitString(const std::string &input,
|
||||
const std::string &delimiters,
|
||||
WhitespaceHandling whitespace,
|
||||
SplitResult resultType)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
if (input.empty())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string::size_type start = 0;
|
||||
while (start != std::string::npos)
|
||||
{
|
||||
auto end = input.find_first_of(delimiters, start);
|
||||
|
||||
std::string piece;
|
||||
if (end == std::string::npos)
|
||||
{
|
||||
piece = input.substr(start);
|
||||
start = std::string::npos;
|
||||
}
|
||||
else
|
||||
{
|
||||
piece = input.substr(start, end - start);
|
||||
start = end + 1;
|
||||
}
|
||||
|
||||
if (whitespace == TRIM_WHITESPACE)
|
||||
{
|
||||
piece = TrimString(piece, kWhitespaceASCII);
|
||||
}
|
||||
|
||||
if (resultType == SPLIT_WANT_ALL || !piece.empty())
|
||||
{
|
||||
result.push_back(piece);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void SplitStringAlongWhitespace(const std::string &input,
|
||||
std::vector<std::string> *tokensOut)
|
||||
{
|
||||
|
||||
std::istringstream stream(input);
|
||||
std::string line;
|
||||
|
||||
while (std::getline(stream, line))
|
||||
{
|
||||
size_t prev = 0, pos;
|
||||
while ((pos = line.find_first_of(kWhitespaceASCII, prev)) != std::string::npos)
|
||||
{
|
||||
if (pos > prev)
|
||||
tokensOut->push_back(line.substr(prev, pos - prev));
|
||||
prev = pos + 1;
|
||||
}
|
||||
if (prev < line.length())
|
||||
tokensOut->push_back(line.substr(prev, std::string::npos));
|
||||
}
|
||||
}
|
||||
|
||||
std::string TrimString(const std::string &input, const std::string &trimChars)
|
||||
{
|
||||
auto begin = input.find_first_not_of(trimChars);
|
||||
if (begin == std::string::npos)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string::size_type end = input.find_last_not_of(trimChars);
|
||||
if (end == std::string::npos)
|
||||
{
|
||||
return input.substr(begin);
|
||||
}
|
||||
|
||||
return input.substr(begin, end - begin + 1);
|
||||
}
|
||||
|
||||
bool HexStringToUInt(const std::string &input, unsigned int *uintOut)
|
||||
{
|
||||
unsigned int offset = 0;
|
||||
|
||||
if (input.size() >= 2 && input[0] == '0' && input[1] == 'x')
|
||||
{
|
||||
offset = 2u;
|
||||
}
|
||||
|
||||
// Simple validity check
|
||||
if (input.find_first_not_of("0123456789ABCDEFabcdef", offset) != std::string::npos)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::stringstream inStream(input);
|
||||
inStream >> std::hex >> *uintOut;
|
||||
return !inStream.fail();
|
||||
}
|
||||
|
||||
bool ReadFileToString(const std::string &path, std::string *stringOut)
|
||||
{
|
||||
std::ifstream inFile(path.c_str());
|
||||
if (inFile.fail())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
inFile.seekg(0, std::ios::end);
|
||||
stringOut->reserve(static_cast<std::string::size_type>(inFile.tellg()));
|
||||
inFile.seekg(0, std::ios::beg);
|
||||
|
||||
stringOut->assign(std::istreambuf_iterator<char>(inFile), std::istreambuf_iterator<char>());
|
||||
return !inFile.fail();
|
||||
}
|
||||
|
||||
}
|
49
src/3rdparty/angle/src/common/string_utils.h
vendored
Normal file
49
src/3rdparty/angle/src/common/string_utils.h
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
//
|
||||
// Copyright 2015 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// string_utils:
|
||||
// String helper functions.
|
||||
//
|
||||
|
||||
#ifndef LIBANGLE_STRING_UTILS_H_
|
||||
#define LIBANGLE_STRING_UTILS_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace angle
|
||||
{
|
||||
|
||||
extern const char kWhitespaceASCII[];
|
||||
|
||||
enum WhitespaceHandling
|
||||
{
|
||||
KEEP_WHITESPACE,
|
||||
TRIM_WHITESPACE,
|
||||
};
|
||||
|
||||
enum SplitResult
|
||||
{
|
||||
SPLIT_WANT_ALL,
|
||||
SPLIT_WANT_NONEMPTY,
|
||||
};
|
||||
|
||||
std::vector<std::string> SplitString(const std::string &input,
|
||||
const std::string &delimiters,
|
||||
WhitespaceHandling whitespace,
|
||||
SplitResult resultType);
|
||||
|
||||
void SplitStringAlongWhitespace(const std::string &input,
|
||||
std::vector<std::string> *tokensOut);
|
||||
|
||||
std::string TrimString(const std::string &input, const std::string &trimChars);
|
||||
|
||||
bool HexStringToUInt(const std::string &input, unsigned int *uintOut);
|
||||
|
||||
bool ReadFileToString(const std::string &path, std::string *stringOut);
|
||||
|
||||
}
|
||||
|
||||
#endif // LIBANGLE_STRING_UTILS_H_
|
311
src/3rdparty/angle/src/common/utilities.cpp
vendored
311
src/3rdparty/angle/src/common/utilities.cpp
vendored
@ -19,6 +19,78 @@
|
||||
# include <windows.graphics.display.h>
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template <class IndexType>
|
||||
gl::IndexRange ComputeTypedIndexRange(const IndexType *indices,
|
||||
size_t count,
|
||||
bool primitiveRestartEnabled,
|
||||
GLuint primitiveRestartIndex)
|
||||
{
|
||||
ASSERT(count > 0);
|
||||
|
||||
IndexType minIndex = 0;
|
||||
IndexType maxIndex = 0;
|
||||
size_t nonPrimitiveRestartIndices = 0;
|
||||
|
||||
if (primitiveRestartEnabled)
|
||||
{
|
||||
// Find the first non-primitive restart index to initialize the min and max values
|
||||
size_t i = 0;
|
||||
for (; i < count; i++)
|
||||
{
|
||||
if (indices[i] != primitiveRestartIndex)
|
||||
{
|
||||
minIndex = indices[i];
|
||||
maxIndex = indices[i];
|
||||
nonPrimitiveRestartIndices++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Loop over the rest of the indices
|
||||
for (; i < count; i++)
|
||||
{
|
||||
if (indices[i] != primitiveRestartIndex)
|
||||
{
|
||||
if (minIndex > indices[i])
|
||||
{
|
||||
minIndex = indices[i];
|
||||
}
|
||||
if (maxIndex < indices[i])
|
||||
{
|
||||
maxIndex = indices[i];
|
||||
}
|
||||
nonPrimitiveRestartIndices++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
minIndex = indices[0];
|
||||
maxIndex = indices[0];
|
||||
nonPrimitiveRestartIndices = count;
|
||||
|
||||
for (size_t i = 1; i < count; i++)
|
||||
{
|
||||
if (minIndex > indices[i])
|
||||
{
|
||||
minIndex = indices[i];
|
||||
}
|
||||
if (maxIndex < indices[i])
|
||||
{
|
||||
maxIndex = indices[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return gl::IndexRange(static_cast<size_t>(minIndex), static_cast<size_t>(maxIndex),
|
||||
nonPrimitiveRestartIndices);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace gl
|
||||
{
|
||||
|
||||
@ -279,6 +351,39 @@ bool IsSamplerType(GLenum type)
|
||||
return false;
|
||||
}
|
||||
|
||||
GLenum SamplerTypeToTextureType(GLenum samplerType)
|
||||
{
|
||||
switch (samplerType)
|
||||
{
|
||||
case GL_SAMPLER_2D:
|
||||
case GL_INT_SAMPLER_2D:
|
||||
case GL_UNSIGNED_INT_SAMPLER_2D:
|
||||
case GL_SAMPLER_2D_SHADOW:
|
||||
return GL_TEXTURE_2D;
|
||||
|
||||
case GL_SAMPLER_CUBE:
|
||||
case GL_INT_SAMPLER_CUBE:
|
||||
case GL_UNSIGNED_INT_SAMPLER_CUBE:
|
||||
case GL_SAMPLER_CUBE_SHADOW:
|
||||
return GL_TEXTURE_CUBE_MAP;
|
||||
|
||||
case GL_SAMPLER_2D_ARRAY:
|
||||
case GL_INT_SAMPLER_2D_ARRAY:
|
||||
case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
|
||||
case GL_SAMPLER_2D_ARRAY_SHADOW:
|
||||
return GL_TEXTURE_2D_ARRAY;
|
||||
|
||||
case GL_SAMPLER_3D:
|
||||
case GL_INT_SAMPLER_3D:
|
||||
case GL_UNSIGNED_INT_SAMPLER_3D:
|
||||
return GL_TEXTURE_3D;
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsMatrixType(GLenum type)
|
||||
{
|
||||
return VariableRowCount(type) > 1;
|
||||
@ -366,6 +471,47 @@ GLenum LayerIndexToCubeMapTextureTarget(size_t index)
|
||||
return FirstCubeMapTextureTarget + static_cast<GLenum>(index);
|
||||
}
|
||||
|
||||
IndexRange ComputeIndexRange(GLenum indexType,
|
||||
const GLvoid *indices,
|
||||
size_t count,
|
||||
bool primitiveRestartEnabled)
|
||||
{
|
||||
switch (indexType)
|
||||
{
|
||||
case GL_UNSIGNED_BYTE:
|
||||
return ComputeTypedIndexRange(static_cast<const GLubyte *>(indices), count,
|
||||
primitiveRestartEnabled,
|
||||
GetPrimitiveRestartIndex(indexType));
|
||||
case GL_UNSIGNED_SHORT:
|
||||
return ComputeTypedIndexRange(static_cast<const GLushort *>(indices), count,
|
||||
primitiveRestartEnabled,
|
||||
GetPrimitiveRestartIndex(indexType));
|
||||
case GL_UNSIGNED_INT:
|
||||
return ComputeTypedIndexRange(static_cast<const GLuint *>(indices), count,
|
||||
primitiveRestartEnabled,
|
||||
GetPrimitiveRestartIndex(indexType));
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return IndexRange();
|
||||
}
|
||||
}
|
||||
|
||||
GLuint GetPrimitiveRestartIndex(GLenum indexType)
|
||||
{
|
||||
switch (indexType)
|
||||
{
|
||||
case GL_UNSIGNED_BYTE:
|
||||
return 0xFF;
|
||||
case GL_UNSIGNED_SHORT:
|
||||
return 0xFFFF;
|
||||
case GL_UNSIGNED_INT:
|
||||
return 0xFFFFFFFF;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsTriangleMode(GLenum drawMode)
|
||||
{
|
||||
switch (drawMode)
|
||||
@ -462,6 +608,146 @@ int VariableSortOrder(GLenum type)
|
||||
}
|
||||
}
|
||||
|
||||
std::string ParseUniformName(const std::string &name, size_t *outSubscript)
|
||||
{
|
||||
// Strip any trailing array operator and retrieve the subscript
|
||||
size_t open = name.find_last_of('[');
|
||||
size_t close = name.find_last_of(']');
|
||||
bool hasIndex = (open != std::string::npos) && (close == name.length() - 1);
|
||||
if (!hasIndex)
|
||||
{
|
||||
if (outSubscript)
|
||||
{
|
||||
*outSubscript = GL_INVALID_INDEX;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
if (outSubscript)
|
||||
{
|
||||
int index = atoi(name.substr(open + 1).c_str());
|
||||
if (index >= 0)
|
||||
{
|
||||
*outSubscript = index;
|
||||
}
|
||||
else
|
||||
{
|
||||
*outSubscript = GL_INVALID_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
return name.substr(0, open);
|
||||
}
|
||||
|
||||
unsigned int ParseAndStripArrayIndex(std::string *name)
|
||||
{
|
||||
unsigned int subscript = GL_INVALID_INDEX;
|
||||
|
||||
// Strip any trailing array operator and retrieve the subscript
|
||||
size_t open = name->find_last_of('[');
|
||||
size_t close = name->find_last_of(']');
|
||||
if (open != std::string::npos && close == name->length() - 1)
|
||||
{
|
||||
subscript = atoi(name->c_str() + open + 1);
|
||||
name->erase(open);
|
||||
}
|
||||
|
||||
return subscript;
|
||||
}
|
||||
|
||||
} // namespace gl
|
||||
|
||||
namespace egl
|
||||
{
|
||||
static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 1,
|
||||
"Unexpected EGL cube map enum value.");
|
||||
static_assert(EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 2,
|
||||
"Unexpected EGL cube map enum value.");
|
||||
static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 3,
|
||||
"Unexpected EGL cube map enum value.");
|
||||
static_assert(EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 4,
|
||||
"Unexpected EGL cube map enum value.");
|
||||
static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 5,
|
||||
"Unexpected EGL cube map enum value.");
|
||||
|
||||
bool IsCubeMapTextureTarget(EGLenum target)
|
||||
{
|
||||
return (target >= FirstCubeMapTextureTarget && target <= LastCubeMapTextureTarget);
|
||||
}
|
||||
|
||||
size_t CubeMapTextureTargetToLayerIndex(EGLenum target)
|
||||
{
|
||||
ASSERT(IsCubeMapTextureTarget(target));
|
||||
return target - static_cast<size_t>(FirstCubeMapTextureTarget);
|
||||
}
|
||||
|
||||
EGLenum LayerIndexToCubeMapTextureTarget(size_t index)
|
||||
{
|
||||
ASSERT(index <= (LastCubeMapTextureTarget - FirstCubeMapTextureTarget));
|
||||
return FirstCubeMapTextureTarget + static_cast<GLenum>(index);
|
||||
}
|
||||
|
||||
bool IsTextureTarget(EGLenum target)
|
||||
{
|
||||
switch (target)
|
||||
{
|
||||
case EGL_GL_TEXTURE_2D_KHR:
|
||||
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
|
||||
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
|
||||
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
|
||||
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
|
||||
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
|
||||
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
|
||||
case EGL_GL_TEXTURE_3D_KHR:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsRenderbufferTarget(EGLenum target)
|
||||
{
|
||||
return target == EGL_GL_RENDERBUFFER_KHR;
|
||||
}
|
||||
}
|
||||
|
||||
namespace egl_gl
|
||||
{
|
||||
GLenum EGLCubeMapTargetToGLCubeMapTarget(EGLenum eglTarget)
|
||||
{
|
||||
ASSERT(egl::IsCubeMapTextureTarget(eglTarget));
|
||||
return gl::LayerIndexToCubeMapTextureTarget(egl::CubeMapTextureTargetToLayerIndex(eglTarget));
|
||||
}
|
||||
|
||||
GLenum EGLImageTargetToGLTextureTarget(EGLenum eglTarget)
|
||||
{
|
||||
switch (eglTarget)
|
||||
{
|
||||
case EGL_GL_TEXTURE_2D_KHR:
|
||||
return GL_TEXTURE_2D;
|
||||
|
||||
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
|
||||
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
|
||||
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
|
||||
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
|
||||
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
|
||||
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
|
||||
return EGLCubeMapTargetToGLCubeMapTarget(eglTarget);
|
||||
|
||||
case EGL_GL_TEXTURE_3D_KHR:
|
||||
return GL_TEXTURE_3D;
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return GL_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
GLuint EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer)
|
||||
{
|
||||
return static_cast<GLuint>(reinterpret_cast<uintptr_t>(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
|
||||
@ -511,32 +797,7 @@ void writeFile(const char* path, const void* content, size_t size)
|
||||
// to run, the function returns immediately, and the thread continues execution.
|
||||
void ScheduleYield()
|
||||
{
|
||||
#if defined(ANGLE_ENABLE_WINDOWS_STORE)
|
||||
// This implementation of Sleep exists because it is not available prior to Update 4.
|
||||
static HANDLE singletonEvent = nullptr;
|
||||
HANDLE sleepEvent = singletonEvent;
|
||||
if (!sleepEvent)
|
||||
{
|
||||
sleepEvent = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
|
||||
|
||||
if (!sleepEvent)
|
||||
return;
|
||||
|
||||
HANDLE previousEvent = InterlockedCompareExchangePointerRelease(&singletonEvent, sleepEvent, nullptr);
|
||||
|
||||
if (previousEvent)
|
||||
{
|
||||
// Back out if multiple threads try to demand create at the same time.
|
||||
CloseHandle(sleepEvent);
|
||||
sleepEvent = previousEvent;
|
||||
}
|
||||
}
|
||||
|
||||
// Emulate sleep by waiting with timeout on an event that is never signalled.
|
||||
WaitForSingleObjectEx(sleepEvent, 0, false);
|
||||
#else
|
||||
Sleep(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
40
src/3rdparty/angle/src/common/utilities.h
vendored
40
src/3rdparty/angle/src/common/utilities.h
vendored
@ -9,10 +9,15 @@
|
||||
#ifndef COMMON_UTILITIES_H_
|
||||
#define COMMON_UTILITIES_H_
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
|
||||
#include "angle_gl.h"
|
||||
#include <string>
|
||||
#include <math.h>
|
||||
|
||||
#include "common/mathutil.h"
|
||||
|
||||
namespace gl
|
||||
{
|
||||
|
||||
@ -25,6 +30,7 @@ GLenum VariableBoolVectorType(GLenum type);
|
||||
int VariableRowCount(GLenum type);
|
||||
int VariableColumnCount(GLenum type);
|
||||
bool IsSamplerType(GLenum type);
|
||||
GLenum SamplerTypeToTextureType(GLenum samplerType);
|
||||
bool IsMatrixType(GLenum type);
|
||||
GLenum TransposeMatrixType(GLenum type);
|
||||
int VariableRegisterCount(GLenum type);
|
||||
@ -40,6 +46,20 @@ bool IsCubeMapTextureTarget(GLenum target);
|
||||
size_t CubeMapTextureTargetToLayerIndex(GLenum target);
|
||||
GLenum LayerIndexToCubeMapTextureTarget(size_t index);
|
||||
|
||||
// Parse the base uniform name and array index. Returns the base name of the uniform. outSubscript is
|
||||
// set to GL_INVALID_INDEX if the provided name is not an array or the array index is invalid.
|
||||
std::string ParseUniformName(const std::string &name, size_t *outSubscript);
|
||||
|
||||
// Find the range of index values in the provided indices pointer. Primitive restart indices are
|
||||
// only counted in the range if primitive restart is disabled.
|
||||
IndexRange ComputeIndexRange(GLenum indexType,
|
||||
const GLvoid *indices,
|
||||
size_t count,
|
||||
bool primitiveRestartEnabled);
|
||||
|
||||
// Get the primitive restart index value for the given index type.
|
||||
GLuint GetPrimitiveRestartIndex(GLenum indexType);
|
||||
|
||||
bool IsTriangleMode(GLenum drawMode);
|
||||
|
||||
// [OpenGL ES 3.0.2] Section 2.3.1 page 14
|
||||
@ -48,6 +68,26 @@ 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); }
|
||||
|
||||
unsigned int ParseAndStripArrayIndex(std::string *name);
|
||||
|
||||
} // namespace gl
|
||||
|
||||
namespace egl
|
||||
{
|
||||
static const EGLenum FirstCubeMapTextureTarget = EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
|
||||
static const EGLenum LastCubeMapTextureTarget = EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR;
|
||||
bool IsCubeMapTextureTarget(EGLenum target);
|
||||
size_t CubeMapTextureTargetToLayerIndex(EGLenum target);
|
||||
EGLenum LayerIndexToCubeMapTextureTarget(size_t index);
|
||||
bool IsTextureTarget(EGLenum target);
|
||||
bool IsRenderbufferTarget(EGLenum target);
|
||||
}
|
||||
|
||||
namespace egl_gl
|
||||
{
|
||||
GLenum EGLCubeMapTargetToGLCubeMapTarget(EGLenum eglTarget);
|
||||
GLenum EGLImageTargetToGLTextureTarget(EGLenum eglTarget);
|
||||
GLuint EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer);
|
||||
}
|
||||
|
||||
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
|
||||
|
5
src/3rdparty/angle/src/common/version.h
vendored
5
src/3rdparty/angle/src/common/version.h
vendored
@ -12,12 +12,17 @@
|
||||
#define ANGLE_MAJOR_VERSION 2
|
||||
#define ANGLE_MINOR_VERSION 1
|
||||
|
||||
#ifndef ANGLE_REVISION
|
||||
#define ANGLE_REVISION 0
|
||||
#endif
|
||||
|
||||
#define ANGLE_STRINGIFY(x) #x
|
||||
#define ANGLE_MACRO_STRINGIFY(x) ANGLE_STRINGIFY(x)
|
||||
|
||||
#define ANGLE_VERSION_STRING \
|
||||
ANGLE_MACRO_STRINGIFY(ANGLE_MAJOR_VERSION) "." \
|
||||
ANGLE_MACRO_STRINGIFY(ANGLE_MINOR_VERSION) "." \
|
||||
ANGLE_MACRO_STRINGIFY(ANGLE_REVISION) "." \
|
||||
ANGLE_COMMIT_HASH
|
||||
|
||||
#endif // COMMON_VERSION_H_
|
||||
|
@ -78,6 +78,8 @@ std::string Diagnostics::message(ID id)
|
||||
return "Not enough arguments for macro";
|
||||
case PP_MACRO_TOO_MANY_ARGS:
|
||||
return "Too many arguments for macro";
|
||||
case PP_MACRO_DUPLICATE_PARAMETER_NAMES:
|
||||
return "duplicate macro parameter name";
|
||||
case PP_CONDITIONAL_ENDIF_WITHOUT_IF:
|
||||
return "unexpected #endif found without a matching #if";
|
||||
case PP_CONDITIONAL_ELSE_WITHOUT_IF:
|
||||
@ -103,12 +105,16 @@ std::string Diagnostics::message(ID id)
|
||||
case PP_VERSION_NOT_FIRST_STATEMENT:
|
||||
return "#version directive must occur before anything else, "
|
||||
"except for comments and white space";
|
||||
case PP_VERSION_NOT_FIRST_LINE_ESSL3:
|
||||
return "#version directive must occur on the first line of the shader";
|
||||
case PP_INVALID_LINE_NUMBER:
|
||||
return "invalid line number";
|
||||
case PP_INVALID_FILE_NUMBER:
|
||||
return "invalid file number";
|
||||
case PP_INVALID_LINE_DIRECTIVE:
|
||||
return "invalid line directive";
|
||||
case PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL3:
|
||||
return "extension directive must occur before any non-preprocessor tokens in ESSL3";
|
||||
// Errors end.
|
||||
// Warnings begin.
|
||||
case PP_EOF_IN_DIRECTIVE:
|
||||
@ -117,6 +123,10 @@ std::string Diagnostics::message(ID id)
|
||||
return "unexpected token after conditional expression";
|
||||
case PP_UNRECOGNIZED_PRAGMA:
|
||||
return "unrecognized pragma";
|
||||
case PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL1:
|
||||
return "extension directive should occur before any non-preprocessor tokens";
|
||||
case PP_WARNING_MACRO_NAME_RESERVED:
|
||||
return "macro name with a double underscore is reserved - unintented behavior is possible";
|
||||
// Warnings end.
|
||||
default:
|
||||
assert(false);
|
||||
|
@ -46,27 +46,32 @@ class Diagnostics
|
||||
PP_MACRO_UNTERMINATED_INVOCATION,
|
||||
PP_MACRO_TOO_FEW_ARGS,
|
||||
PP_MACRO_TOO_MANY_ARGS,
|
||||
PP_MACRO_DUPLICATE_PARAMETER_NAMES,
|
||||
PP_CONDITIONAL_ENDIF_WITHOUT_IF,
|
||||
PP_CONDITIONAL_ELSE_WITHOUT_IF,
|
||||
PP_CONDITIONAL_ELSE_AFTER_ELSE,
|
||||
PP_CONDITIONAL_ELIF_WITHOUT_IF,
|
||||
PP_CONDITIONAL_ELIF_AFTER_ELSE,
|
||||
PP_CONDITIONAL_UNTERMINATED,
|
||||
PP_CONDITIONAL_UNEXPECTED_TOKEN,
|
||||
PP_INVALID_EXTENSION_NAME,
|
||||
PP_INVALID_EXTENSION_BEHAVIOR,
|
||||
PP_INVALID_EXTENSION_DIRECTIVE,
|
||||
PP_INVALID_VERSION_NUMBER,
|
||||
PP_INVALID_VERSION_DIRECTIVE,
|
||||
PP_VERSION_NOT_FIRST_STATEMENT,
|
||||
PP_VERSION_NOT_FIRST_LINE_ESSL3,
|
||||
PP_INVALID_LINE_NUMBER,
|
||||
PP_INVALID_FILE_NUMBER,
|
||||
PP_INVALID_LINE_DIRECTIVE,
|
||||
PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL3,
|
||||
PP_ERROR_END,
|
||||
|
||||
PP_WARNING_BEGIN,
|
||||
PP_EOF_IN_DIRECTIVE,
|
||||
PP_CONDITIONAL_UNEXPECTED_TOKEN,
|
||||
PP_UNRECOGNIZED_PRAGMA,
|
||||
PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL1,
|
||||
PP_WARNING_MACRO_NAME_RESERVED,
|
||||
PP_WARNING_END
|
||||
};
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "DirectiveParser.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
@ -118,14 +119,12 @@ void skipUntilEOD(pp::Lexer *lexer, pp::Token *token)
|
||||
bool isMacroNameReserved(const std::string &name)
|
||||
{
|
||||
// Names prefixed with "GL_" are reserved.
|
||||
if (name.substr(0, 3) == "GL_")
|
||||
return true;
|
||||
return (name.substr(0, 3) == "GL_");
|
||||
}
|
||||
|
||||
// Names containing two consecutive underscores are reserved.
|
||||
if (name.find("__") != std::string::npos)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
bool hasDoubleUnderscores(const std::string &name)
|
||||
{
|
||||
return (name.find("__") != std::string::npos);
|
||||
}
|
||||
|
||||
bool isMacroPredefined(const std::string &name,
|
||||
@ -140,80 +139,17 @@ bool isMacroPredefined(const std::string &name,
|
||||
namespace pp
|
||||
{
|
||||
|
||||
class DefinedParser : public Lexer
|
||||
{
|
||||
public:
|
||||
DefinedParser(Lexer *lexer,
|
||||
const MacroSet *macroSet,
|
||||
Diagnostics *diagnostics)
|
||||
: mLexer(lexer),
|
||||
mMacroSet(macroSet),
|
||||
mDiagnostics(diagnostics)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void lex(Token *token)
|
||||
{
|
||||
const char kDefined[] = "defined";
|
||||
|
||||
mLexer->lex(token);
|
||||
if (token->type != Token::IDENTIFIER)
|
||||
return;
|
||||
if (token->text != kDefined)
|
||||
return;
|
||||
|
||||
bool paren = false;
|
||||
mLexer->lex(token);
|
||||
if (token->type == '(')
|
||||
{
|
||||
paren = true;
|
||||
mLexer->lex(token);
|
||||
}
|
||||
|
||||
if (token->type != Token::IDENTIFIER)
|
||||
{
|
||||
mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
|
||||
token->location, token->text);
|
||||
skipUntilEOD(mLexer, token);
|
||||
return;
|
||||
}
|
||||
MacroSet::const_iterator iter = mMacroSet->find(token->text);
|
||||
std::string expression = iter != mMacroSet->end() ? "1" : "0";
|
||||
|
||||
if (paren)
|
||||
{
|
||||
mLexer->lex(token);
|
||||
if (token->type != ')')
|
||||
{
|
||||
mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
|
||||
token->location, token->text);
|
||||
skipUntilEOD(mLexer, token);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// We have a valid defined operator.
|
||||
// Convert the current token into a CONST_INT token.
|
||||
token->type = Token::CONST_INT;
|
||||
token->text = expression;
|
||||
}
|
||||
|
||||
private:
|
||||
Lexer *mLexer;
|
||||
const MacroSet *mMacroSet;
|
||||
Diagnostics *mDiagnostics;
|
||||
};
|
||||
|
||||
DirectiveParser::DirectiveParser(Tokenizer *tokenizer,
|
||||
MacroSet *macroSet,
|
||||
Diagnostics *diagnostics,
|
||||
DirectiveHandler *directiveHandler)
|
||||
: mPastFirstStatement(false),
|
||||
mSeenNonPreprocessorToken(false),
|
||||
mTokenizer(tokenizer),
|
||||
mMacroSet(macroSet),
|
||||
mDiagnostics(diagnostics),
|
||||
mDirectiveHandler(directiveHandler)
|
||||
mDirectiveHandler(directiveHandler),
|
||||
mShaderVersion(100)
|
||||
{
|
||||
}
|
||||
|
||||
@ -228,6 +164,10 @@ void DirectiveParser::lex(Token *token)
|
||||
parseDirective(token);
|
||||
mPastFirstStatement = true;
|
||||
}
|
||||
else if (!isEOD(token))
|
||||
{
|
||||
mSeenNonPreprocessorToken = true;
|
||||
}
|
||||
|
||||
if (token->type == Token::LAST)
|
||||
{
|
||||
@ -349,6 +289,16 @@ void DirectiveParser::parseDefine(Token *token)
|
||||
token->location, token->text);
|
||||
return;
|
||||
}
|
||||
// Using double underscores is allowed, but may result in unintended
|
||||
// behavior, so a warning is issued. At the time of writing this was
|
||||
// specified in ESSL 3.10, but the intent judging from Khronos
|
||||
// discussions and dEQP tests was that double underscores should be
|
||||
// allowed in earlier ESSL versions too.
|
||||
if (hasDoubleUnderscores(token->text))
|
||||
{
|
||||
mDiagnostics->report(Diagnostics::PP_WARNING_MACRO_NAME_RESERVED, token->location,
|
||||
token->text);
|
||||
}
|
||||
|
||||
Macro macro;
|
||||
macro.type = Macro::kTypeObj;
|
||||
@ -364,6 +314,14 @@ void DirectiveParser::parseDefine(Token *token)
|
||||
mTokenizer->lex(token);
|
||||
if (token->type != Token::IDENTIFIER)
|
||||
break;
|
||||
|
||||
if (std::find(macro.parameters.begin(), macro.parameters.end(), token->text) != macro.parameters.end())
|
||||
{
|
||||
mDiagnostics->report(Diagnostics::PP_MACRO_DUPLICATE_PARAMETER_NAMES,
|
||||
token->location, token->text);
|
||||
return;
|
||||
}
|
||||
|
||||
macro.parameters.push_back(token->text);
|
||||
|
||||
mTokenizer->lex(token); // Get ','.
|
||||
@ -435,6 +393,12 @@ void DirectiveParser::parseUndef(Token *token)
|
||||
}
|
||||
|
||||
mTokenizer->lex(token);
|
||||
if (!isEOD(token))
|
||||
{
|
||||
mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
|
||||
token->location, token->text);
|
||||
skipUntilEOD(mTokenizer, token);
|
||||
}
|
||||
}
|
||||
|
||||
void DirectiveParser::parseIf(Token *token)
|
||||
@ -486,7 +450,7 @@ void DirectiveParser::parseElse(Token *token)
|
||||
block.skipGroup = block.foundValidGroup;
|
||||
block.foundValidGroup = true;
|
||||
|
||||
// Warn if there are extra tokens after #else.
|
||||
// Check if there are extra tokens after #else.
|
||||
mTokenizer->lex(token);
|
||||
if (!isEOD(token))
|
||||
{
|
||||
@ -550,7 +514,7 @@ void DirectiveParser::parseEndif(Token *token)
|
||||
|
||||
mConditionalStack.pop_back();
|
||||
|
||||
// Warn if there are tokens after #endif.
|
||||
// Check if there are tokens after #endif.
|
||||
mTokenizer->lex(token);
|
||||
if (!isEOD(token))
|
||||
{
|
||||
@ -699,6 +663,20 @@ void DirectiveParser::parseExtension(Token *token)
|
||||
token->location, token->text);
|
||||
valid = false;
|
||||
}
|
||||
if (valid && mSeenNonPreprocessorToken)
|
||||
{
|
||||
if (mShaderVersion >= 300)
|
||||
{
|
||||
mDiagnostics->report(Diagnostics::PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL3,
|
||||
token->location, token->text);
|
||||
valid = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
mDiagnostics->report(Diagnostics::PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL1,
|
||||
token->location, token->text);
|
||||
}
|
||||
}
|
||||
if (valid)
|
||||
mDirectiveHandler->handleExtension(token->location, name, behavior);
|
||||
}
|
||||
@ -775,9 +753,18 @@ void DirectiveParser::parseVersion(Token *token)
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (valid && version >= 300 && token->location.line > 1)
|
||||
{
|
||||
mDiagnostics->report(Diagnostics::PP_VERSION_NOT_FIRST_LINE_ESSL3,
|
||||
token->location, token->text);
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (valid)
|
||||
{
|
||||
mDirectiveHandler->handleVersion(token->location, version);
|
||||
mShaderVersion = version;
|
||||
PredefineMacro(mMacroSet, "__VERSION__", version);
|
||||
}
|
||||
}
|
||||
|
||||
@ -785,72 +772,60 @@ void DirectiveParser::parseLine(Token *token)
|
||||
{
|
||||
assert(getDirective(token) == DIRECTIVE_LINE);
|
||||
|
||||
enum State
|
||||
{
|
||||
LINE_NUMBER,
|
||||
FILE_NUMBER
|
||||
};
|
||||
|
||||
bool valid = true;
|
||||
bool parsedFileNumber = false;
|
||||
int line = 0, file = 0;
|
||||
int state = LINE_NUMBER;
|
||||
|
||||
MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics);
|
||||
MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, false);
|
||||
|
||||
// Lex the first token after "#line" so we can check it for EOD.
|
||||
macroExpander.lex(token);
|
||||
while ((token->type != '\n') && (token->type != Token::LAST))
|
||||
|
||||
if (isEOD(token))
|
||||
{
|
||||
switch (state++)
|
||||
mDiagnostics->report(Diagnostics::PP_INVALID_LINE_DIRECTIVE, token->location, token->text);
|
||||
valid = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ExpressionParser expressionParser(¯oExpander, mDiagnostics);
|
||||
ExpressionParser::ErrorSettings errorSettings;
|
||||
|
||||
// See GLES3 section 12.42
|
||||
errorSettings.integerLiteralsMustFit32BitSignedRange = true;
|
||||
|
||||
errorSettings.unexpectedIdentifier = Diagnostics::PP_INVALID_LINE_NUMBER;
|
||||
// The first token was lexed earlier to check if it was EOD. Include
|
||||
// the token in parsing for a second time by setting the
|
||||
// parsePresetToken flag to true.
|
||||
expressionParser.parse(token, &line, true, errorSettings, &valid);
|
||||
if (!isEOD(token) && valid)
|
||||
{
|
||||
errorSettings.unexpectedIdentifier = Diagnostics::PP_INVALID_FILE_NUMBER;
|
||||
// After parsing the line expression expressionParser has also
|
||||
// advanced to the first token of the file expression - this is the
|
||||
// token that makes the parser reduce the "input" rule for the line
|
||||
// expression and stop. So we're using parsePresetToken = true here
|
||||
// as well.
|
||||
expressionParser.parse(token, &file, true, errorSettings, &valid);
|
||||
parsedFileNumber = true;
|
||||
}
|
||||
if (!isEOD(token))
|
||||
{
|
||||
case LINE_NUMBER:
|
||||
if (valid && (token->type != Token::CONST_INT))
|
||||
{
|
||||
mDiagnostics->report(Diagnostics::PP_INVALID_LINE_NUMBER,
|
||||
token->location, token->text);
|
||||
valid = false;
|
||||
}
|
||||
if (valid && !token->iValue(&line))
|
||||
{
|
||||
mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW,
|
||||
token->location, token->text);
|
||||
valid = false;
|
||||
}
|
||||
break;
|
||||
case FILE_NUMBER:
|
||||
if (valid && (token->type != Token::CONST_INT))
|
||||
{
|
||||
mDiagnostics->report(Diagnostics::PP_INVALID_FILE_NUMBER,
|
||||
token->location, token->text);
|
||||
valid = false;
|
||||
}
|
||||
if (valid && !token->iValue(&file))
|
||||
{
|
||||
mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW,
|
||||
token->location, token->text);
|
||||
valid = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (valid)
|
||||
{
|
||||
mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
|
||||
token->location, token->text);
|
||||
valid = false;
|
||||
}
|
||||
break;
|
||||
skipUntilEOD(mTokenizer, token);
|
||||
}
|
||||
macroExpander.lex(token);
|
||||
}
|
||||
|
||||
if (valid && (state != FILE_NUMBER) && (state != FILE_NUMBER + 1))
|
||||
{
|
||||
mDiagnostics->report(Diagnostics::PP_INVALID_LINE_DIRECTIVE,
|
||||
token->location, token->text);
|
||||
valid = false;
|
||||
}
|
||||
if (valid)
|
||||
{
|
||||
mTokenizer->setLineNumber(line);
|
||||
if (state == FILE_NUMBER + 1)
|
||||
if (parsedFileNumber)
|
||||
mTokenizer->setFileNumber(file);
|
||||
}
|
||||
}
|
||||
@ -910,15 +885,18 @@ int DirectiveParser::parseExpressionIf(Token *token)
|
||||
assert((getDirective(token) == DIRECTIVE_IF) ||
|
||||
(getDirective(token) == DIRECTIVE_ELIF));
|
||||
|
||||
DefinedParser definedParser(mTokenizer, mMacroSet, mDiagnostics);
|
||||
MacroExpander macroExpander(&definedParser, mMacroSet, mDiagnostics);
|
||||
MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, true);
|
||||
ExpressionParser expressionParser(¯oExpander, mDiagnostics);
|
||||
|
||||
int expression = 0;
|
||||
macroExpander.lex(token);
|
||||
expressionParser.parse(token, &expression);
|
||||
ExpressionParser::ErrorSettings errorSettings;
|
||||
errorSettings.integerLiteralsMustFit32BitSignedRange = false;
|
||||
errorSettings.unexpectedIdentifier = Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN;
|
||||
|
||||
// Warn if there are tokens after #if expression.
|
||||
bool valid = true;
|
||||
expressionParser.parse(token, &expression, false, errorSettings, &valid);
|
||||
|
||||
// Check if there are tokens after #if expression.
|
||||
if (!isEOD(token))
|
||||
{
|
||||
mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
|
||||
@ -946,7 +924,7 @@ int DirectiveParser::parseExpressionIfdef(Token *token)
|
||||
MacroSet::const_iterator iter = mMacroSet->find(token->text);
|
||||
int expression = iter != mMacroSet->end() ? 1 : 0;
|
||||
|
||||
// Warn if there are tokens after #ifdef expression.
|
||||
// Check if there are tokens after #ifdef expression.
|
||||
mTokenizer->lex(token);
|
||||
if (!isEOD(token))
|
||||
{
|
||||
|
@ -27,7 +27,7 @@ class DirectiveParser : public Lexer
|
||||
Diagnostics *diagnostics,
|
||||
DirectiveHandler *directiveHandler);
|
||||
|
||||
virtual void lex(Token *token);
|
||||
void lex(Token *token) override;
|
||||
|
||||
private:
|
||||
PP_DISALLOW_COPY_AND_ASSIGN(DirectiveParser);
|
||||
@ -70,11 +70,14 @@ class DirectiveParser : public Lexer
|
||||
}
|
||||
};
|
||||
bool mPastFirstStatement;
|
||||
bool mSeenNonPreprocessorToken; // Tracks if a non-preprocessor token has been seen yet. Some macros, such as
|
||||
// #extension must be declared before all shader code.
|
||||
std::vector<ConditionalBlock> mConditionalStack;
|
||||
Tokenizer *mTokenizer;
|
||||
MacroSet *mMacroSet;
|
||||
Diagnostics *mDiagnostics;
|
||||
DirectiveHandler *mDirectiveHandler;
|
||||
int mShaderVersion;
|
||||
};
|
||||
|
||||
} // namespace pp
|
||||
|
@ -7,21 +7,31 @@
|
||||
#ifndef COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_
|
||||
#define COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_
|
||||
|
||||
#include "DiagnosticsBase.h"
|
||||
#include "pp_utils.h"
|
||||
|
||||
namespace pp
|
||||
{
|
||||
|
||||
class Diagnostics;
|
||||
class Lexer;
|
||||
struct Token;
|
||||
|
||||
class ExpressionParser
|
||||
{
|
||||
public:
|
||||
struct ErrorSettings
|
||||
{
|
||||
Diagnostics::ID unexpectedIdentifier;
|
||||
bool integerLiteralsMustFit32BitSignedRange;
|
||||
};
|
||||
|
||||
ExpressionParser(Lexer *lexer, Diagnostics *diagnostics);
|
||||
|
||||
bool parse(Token *token, int *result);
|
||||
bool parse(Token *token,
|
||||
int *result,
|
||||
bool parsePresetToken,
|
||||
const ErrorSettings &errorSettings,
|
||||
bool *valid);
|
||||
|
||||
private:
|
||||
PP_DISALLOW_COPY_AND_ASSIGN(ExpressionParser);
|
||||
|
@ -28,7 +28,7 @@ WHICH GENERATES THE GLSL ES preprocessor expression parser.
|
||||
#pragma GCC diagnostic ignored "-Wuninitialized"
|
||||
#endif
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma warning(disable: 4065 4701 4702)
|
||||
#pragma warning(disable: 4065 4244 4701 4702)
|
||||
#endif
|
||||
|
||||
#include "ExpressionParser.h"
|
||||
@ -52,6 +52,7 @@ typedef __int64 YYSTYPE;
|
||||
#include <stdint.h>
|
||||
typedef intmax_t YYSTYPE;
|
||||
#endif // _MSC_VER
|
||||
|
||||
#define YYENABLE_NLS 0
|
||||
#define YYLTYPE_IS_TRIVIAL 1
|
||||
#define YYSTYPE_IS_TRIVIAL 1
|
||||
@ -64,6 +65,17 @@ struct Context
|
||||
pp::Lexer* lexer;
|
||||
pp::Token* token;
|
||||
int* result;
|
||||
bool parsePresetToken;
|
||||
|
||||
pp::ExpressionParser::ErrorSettings errorSettings;
|
||||
bool *valid;
|
||||
|
||||
void startIgnoreErrors() { ++ignoreErrors; }
|
||||
void endIgnoreErrors() { --ignoreErrors; }
|
||||
|
||||
bool isIgnoringErrors() { return ignoreErrors > 0; }
|
||||
|
||||
int ignoreErrors;
|
||||
};
|
||||
} // namespace
|
||||
%}
|
||||
@ -79,6 +91,7 @@ static void yyerror(Context* context, const char* reason);
|
||||
%}
|
||||
|
||||
%token TOK_CONST_INT
|
||||
%token TOK_IDENTIFIER
|
||||
%left TOK_OP_OR
|
||||
%left TOK_OP_AND
|
||||
%left '|'
|
||||
@ -102,11 +115,58 @@ input
|
||||
|
||||
expression
|
||||
: TOK_CONST_INT
|
||||
| expression TOK_OP_OR expression {
|
||||
$$ = $1 || $3;
|
||||
| TOK_IDENTIFIER {
|
||||
if (!context->isIgnoringErrors())
|
||||
{
|
||||
// This rule should be applied right after the token is lexed, so we can
|
||||
// refer to context->token in the error message.
|
||||
context->diagnostics->report(context->errorSettings.unexpectedIdentifier,
|
||||
context->token->location, context->token->text);
|
||||
*(context->valid) = false;
|
||||
}
|
||||
$$ = $1;
|
||||
}
|
||||
| expression TOK_OP_AND expression {
|
||||
$$ = $1 && $3;
|
||||
| expression TOK_OP_OR {
|
||||
if ($1 != 0)
|
||||
{
|
||||
// Ignore errors in the short-circuited part of the expression.
|
||||
// ESSL3.00 section 3.4:
|
||||
// If an operand is not evaluated, the presence of undefined identifiers
|
||||
// in the operand will not cause an error.
|
||||
// Unevaluated division by zero should not cause an error either.
|
||||
context->startIgnoreErrors();
|
||||
}
|
||||
} expression {
|
||||
if ($1 != 0)
|
||||
{
|
||||
context->endIgnoreErrors();
|
||||
$$ = static_cast<YYSTYPE>(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
$$ = $1 || $4;
|
||||
}
|
||||
}
|
||||
| expression TOK_OP_AND {
|
||||
if ($1 == 0)
|
||||
{
|
||||
// Ignore errors in the short-circuited part of the expression.
|
||||
// ESSL3.00 section 3.4:
|
||||
// If an operand is not evaluated, the presence of undefined identifiers
|
||||
// in the operand will not cause an error.
|
||||
// Unevaluated division by zero should not cause an error either.
|
||||
context->startIgnoreErrors();
|
||||
}
|
||||
} expression {
|
||||
if ($1 == 0)
|
||||
{
|
||||
context->endIgnoreErrors();
|
||||
$$ = static_cast<YYSTYPE>(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
$$ = $1 && $4;
|
||||
}
|
||||
}
|
||||
| expression '|' expression {
|
||||
$$ = $1 | $3;
|
||||
@ -148,28 +208,42 @@ expression
|
||||
$$ = $1 + $3;
|
||||
}
|
||||
| expression '%' expression {
|
||||
if ($3 == 0) {
|
||||
std::ostringstream stream;
|
||||
stream << $1 << " % " << $3;
|
||||
std::string text = stream.str();
|
||||
context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
|
||||
context->token->location,
|
||||
text.c_str());
|
||||
YYABORT;
|
||||
} else {
|
||||
if ($3 == 0)
|
||||
{
|
||||
if (!context->isIgnoringErrors())
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << $1 << " % " << $3;
|
||||
std::string text = stream.str();
|
||||
context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
|
||||
context->token->location,
|
||||
text.c_str());
|
||||
*(context->valid) = false;
|
||||
}
|
||||
$$ = static_cast<YYSTYPE>(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
$$ = $1 % $3;
|
||||
}
|
||||
}
|
||||
| expression '/' expression {
|
||||
if ($3 == 0) {
|
||||
std::ostringstream stream;
|
||||
stream << $1 << " / " << $3;
|
||||
std::string text = stream.str();
|
||||
context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
|
||||
context->token->location,
|
||||
text.c_str());
|
||||
YYABORT;
|
||||
} else {
|
||||
if ($3 == 0)
|
||||
{
|
||||
if (!context->isIgnoringErrors())
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << $1 << " / " << $3;
|
||||
std::string text = stream.str();
|
||||
context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
|
||||
context->token->location,
|
||||
text.c_str());
|
||||
*(context->valid) = false;
|
||||
}
|
||||
$$ = static_cast<YYSTYPE>(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
$$ = $1 / $3;
|
||||
}
|
||||
}
|
||||
@ -197,22 +271,35 @@ expression
|
||||
|
||||
int yylex(YYSTYPE *lvalp, Context *context)
|
||||
{
|
||||
pp::Token *token = context->token;
|
||||
if (!context->parsePresetToken)
|
||||
{
|
||||
context->lexer->lex(token);
|
||||
}
|
||||
context->parsePresetToken = false;
|
||||
|
||||
int type = 0;
|
||||
|
||||
pp::Token *token = context->token;
|
||||
switch (token->type)
|
||||
{
|
||||
case pp::Token::CONST_INT: {
|
||||
unsigned int val = 0;
|
||||
if (!token->uValue(&val))
|
||||
int testVal = 0;
|
||||
if (!token->uValue(&val) || (!token->iValue(&testVal) &&
|
||||
context->errorSettings.integerLiteralsMustFit32BitSignedRange))
|
||||
{
|
||||
context->diagnostics->report(pp::Diagnostics::PP_INTEGER_OVERFLOW,
|
||||
token->location, token->text);
|
||||
*(context->valid) = false;
|
||||
}
|
||||
*lvalp = static_cast<YYSTYPE>(val);
|
||||
type = TOK_CONST_INT;
|
||||
break;
|
||||
}
|
||||
case pp::Token::IDENTIFIER:
|
||||
*lvalp = static_cast<YYSTYPE>(-1);
|
||||
type = TOK_IDENTIFIER;
|
||||
break;
|
||||
case pp::Token::OP_OR:
|
||||
type = TOK_OP_OR;
|
||||
break;
|
||||
@ -258,10 +345,6 @@ int yylex(YYSTYPE *lvalp, Context *context)
|
||||
break;
|
||||
}
|
||||
|
||||
// Advance to the next token if the current one is valid.
|
||||
if (type != 0)
|
||||
context->lexer->lex(token);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
@ -280,13 +363,21 @@ ExpressionParser::ExpressionParser(Lexer *lexer, Diagnostics *diagnostics)
|
||||
{
|
||||
}
|
||||
|
||||
bool ExpressionParser::parse(Token *token, int *result)
|
||||
bool ExpressionParser::parse(Token *token,
|
||||
int *result,
|
||||
bool parsePresetToken,
|
||||
const ErrorSettings &errorSettings,
|
||||
bool *valid)
|
||||
{
|
||||
Context context;
|
||||
context.diagnostics = mDiagnostics;
|
||||
context.lexer = mLexer;
|
||||
context.token = token;
|
||||
context.result = result;
|
||||
context.ignoreErrors = 0;
|
||||
context.parsePresetToken = parsePresetToken;
|
||||
context.errorSettings = errorSettings;
|
||||
context.valid = valid;
|
||||
int ret = yyparse(&context);
|
||||
switch (ret)
|
||||
{
|
||||
|
@ -29,13 +29,75 @@ Input::Input(size_t count, const char *const string[], const int length[]) :
|
||||
}
|
||||
}
|
||||
|
||||
size_t Input::read(char *buf, size_t maxSize)
|
||||
const char *Input::skipChar()
|
||||
{
|
||||
// This function should only be called when there is a character to skip.
|
||||
assert(mReadLoc.cIndex < mLength[mReadLoc.sIndex]);
|
||||
++mReadLoc.cIndex;
|
||||
if (mReadLoc.cIndex == mLength[mReadLoc.sIndex])
|
||||
{
|
||||
++mReadLoc.sIndex;
|
||||
mReadLoc.cIndex = 0;
|
||||
}
|
||||
if (mReadLoc.sIndex >= mCount)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return mString[mReadLoc.sIndex] + mReadLoc.cIndex;
|
||||
}
|
||||
|
||||
size_t Input::read(char *buf, size_t maxSize, int *lineNo)
|
||||
{
|
||||
size_t nRead = 0;
|
||||
while ((nRead < maxSize) && (mReadLoc.sIndex < mCount))
|
||||
// The previous call to read might have stopped copying the string when encountering a line
|
||||
// continuation. Check for this possibility first.
|
||||
if (mReadLoc.sIndex < mCount && maxSize > 0)
|
||||
{
|
||||
const char *c = mString[mReadLoc.sIndex] + mReadLoc.cIndex;
|
||||
if ((*c) == '\\')
|
||||
{
|
||||
c = skipChar();
|
||||
if (c != nullptr && (*c) == '\n')
|
||||
{
|
||||
// Line continuation of backslash + newline.
|
||||
skipChar();
|
||||
++(*lineNo);
|
||||
}
|
||||
else if (c != nullptr && (*c) == '\r')
|
||||
{
|
||||
// Line continuation. Could be backslash + '\r\n' or just backslash + '\r'.
|
||||
c = skipChar();
|
||||
if (c != nullptr && (*c) == '\n')
|
||||
{
|
||||
skipChar();
|
||||
}
|
||||
++(*lineNo);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not line continuation, so write the skipped backslash to buf.
|
||||
*buf = '\\';
|
||||
++nRead;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t maxRead = maxSize;
|
||||
while ((nRead < maxRead) && (mReadLoc.sIndex < mCount))
|
||||
{
|
||||
size_t size = mLength[mReadLoc.sIndex] - mReadLoc.cIndex;
|
||||
size = std::min(size, maxSize);
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
// Stop if a possible line continuation is encountered.
|
||||
// It will be processed on the next call on input, which skips it
|
||||
// and increments line number if necessary.
|
||||
if (*(mString[mReadLoc.sIndex] + mReadLoc.cIndex + i) == '\\')
|
||||
{
|
||||
size = i;
|
||||
maxRead = nRead + size; // Stop reading right before the backslash.
|
||||
}
|
||||
}
|
||||
std::memcpy(buf + nRead, mString[mReadLoc.sIndex] + mReadLoc.cIndex, size);
|
||||
nRead += size;
|
||||
mReadLoc.cIndex += size;
|
||||
|
@ -33,7 +33,7 @@ class Input
|
||||
return mLength[index];
|
||||
}
|
||||
|
||||
size_t read(char *buf, size_t maxSize);
|
||||
size_t read(char *buf, size_t maxSize, int *lineNo);
|
||||
|
||||
struct Location
|
||||
{
|
||||
@ -49,6 +49,10 @@ class Input
|
||||
const Location &readLoc() const { return mReadLoc; }
|
||||
|
||||
private:
|
||||
// Skip a character and return the next character after the one that was skipped.
|
||||
// Return nullptr if data runs out.
|
||||
const char *skipChar();
|
||||
|
||||
// Input.
|
||||
size_t mCount;
|
||||
const char * const *mString;
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
#include "Macro.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "Token.h"
|
||||
|
||||
namespace pp
|
||||
@ -19,5 +21,23 @@ bool Macro::equals(const Macro &other) const
|
||||
(replacements == other.replacements);
|
||||
}
|
||||
|
||||
void PredefineMacro(MacroSet *macroSet, const char *name, int value)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << value;
|
||||
|
||||
Token token;
|
||||
token.type = Token::CONST_INT;
|
||||
token.text = stream.str();
|
||||
|
||||
Macro macro;
|
||||
macro.predefined = true;
|
||||
macro.type = Macro::kTypeObj;
|
||||
macro.name = name;
|
||||
macro.replacements.push_back(token);
|
||||
|
||||
(*macroSet)[name] = macro;
|
||||
}
|
||||
|
||||
} // namespace pp
|
||||
|
||||
|
@ -45,6 +45,8 @@ struct Macro
|
||||
|
||||
typedef std::map<std::string, Macro> MacroSet;
|
||||
|
||||
void PredefineMacro(MacroSet *macroSet, const char *name, int value);
|
||||
|
||||
} // namespace pp
|
||||
|
||||
#endif // COMPILER_PREPROCESSOR_MACRO_H_
|
||||
|
@ -26,7 +26,7 @@ class TokenLexer : public Lexer
|
||||
mIter = mTokens.begin();
|
||||
}
|
||||
|
||||
virtual void lex(Token *token)
|
||||
void lex(Token *token) override
|
||||
{
|
||||
if (mIter == mTokens.end())
|
||||
{
|
||||
@ -48,10 +48,9 @@ class TokenLexer : public Lexer
|
||||
|
||||
MacroExpander::MacroExpander(Lexer *lexer,
|
||||
MacroSet *macroSet,
|
||||
Diagnostics *diagnostics)
|
||||
: mLexer(lexer),
|
||||
mMacroSet(macroSet),
|
||||
mDiagnostics(diagnostics)
|
||||
Diagnostics *diagnostics,
|
||||
bool parseDefined)
|
||||
: mLexer(lexer), mMacroSet(macroSet), mDiagnostics(diagnostics), mParseDefined(parseDefined)
|
||||
{
|
||||
}
|
||||
|
||||
@ -67,11 +66,54 @@ void MacroExpander::lex(Token *token)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
const char kDefined[] = "defined";
|
||||
|
||||
getToken(token);
|
||||
|
||||
if (token->type != Token::IDENTIFIER)
|
||||
break;
|
||||
|
||||
// Defined operator is parsed here since it may be generated by macro expansion.
|
||||
// Defined operator produced by macro expansion has undefined behavior according to C++
|
||||
// spec, which the GLSL spec references (see C++14 draft spec section 16.1.4), but this
|
||||
// behavior is needed for passing dEQP tests, which enforce stricter compatibility between
|
||||
// implementations.
|
||||
if (mParseDefined && token->text == kDefined)
|
||||
{
|
||||
bool paren = false;
|
||||
getToken(token);
|
||||
if (token->type == '(')
|
||||
{
|
||||
paren = true;
|
||||
getToken(token);
|
||||
}
|
||||
if (token->type != Token::IDENTIFIER)
|
||||
{
|
||||
mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
|
||||
token->text);
|
||||
break;
|
||||
}
|
||||
auto iter = mMacroSet->find(token->text);
|
||||
std::string expression = iter != mMacroSet->end() ? "1" : "0";
|
||||
|
||||
if (paren)
|
||||
{
|
||||
getToken(token);
|
||||
if (token->type != ')')
|
||||
{
|
||||
mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
|
||||
token->text);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We have a valid defined operator.
|
||||
// Convert the current token into a CONST_INT token.
|
||||
token->type = Token::CONST_INT;
|
||||
token->text = expression;
|
||||
break;
|
||||
}
|
||||
|
||||
if (token->expansionDisabled())
|
||||
break;
|
||||
|
||||
@ -187,6 +229,12 @@ bool MacroExpander::expandMacro(const Macro ¯o,
|
||||
std::vector<Token> *replacements)
|
||||
{
|
||||
replacements->clear();
|
||||
|
||||
// In the case of an object-like macro, the replacement list gets its location
|
||||
// from the identifier, but in the case of a function-like macro, the replacement
|
||||
// list gets its location from the closing parenthesis of the macro invocation.
|
||||
// This is tested by dEQP-GLES3.functional.shaders.preprocessor.predefined_macros.*
|
||||
SourceLocation replacementLocation = identifier.location;
|
||||
if (macro.type == Macro::kTypeObj)
|
||||
{
|
||||
replacements->assign(macro.replacements.begin(),
|
||||
@ -218,7 +266,7 @@ bool MacroExpander::expandMacro(const Macro ¯o,
|
||||
assert(macro.type == Macro::kTypeFunc);
|
||||
std::vector<MacroArg> args;
|
||||
args.reserve(macro.parameters.size());
|
||||
if (!collectMacroArgs(macro, identifier, &args))
|
||||
if (!collectMacroArgs(macro, identifier, &args, &replacementLocation))
|
||||
return false;
|
||||
|
||||
replaceMacroParams(macro, args, replacements);
|
||||
@ -234,14 +282,15 @@ bool MacroExpander::expandMacro(const Macro ¯o,
|
||||
repl.setAtStartOfLine(identifier.atStartOfLine());
|
||||
repl.setHasLeadingSpace(identifier.hasLeadingSpace());
|
||||
}
|
||||
repl.location = identifier.location;
|
||||
repl.location = replacementLocation;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroExpander::collectMacroArgs(const Macro ¯o,
|
||||
const Token &identifier,
|
||||
std::vector<MacroArg> *args)
|
||||
std::vector<MacroArg> *args,
|
||||
SourceLocation *closingParenthesisLocation)
|
||||
{
|
||||
Token token;
|
||||
getToken(&token);
|
||||
@ -271,6 +320,7 @@ bool MacroExpander::collectMacroArgs(const Macro ¯o,
|
||||
case ')':
|
||||
--openParens;
|
||||
isArg = openParens != 0;
|
||||
*closingParenthesisLocation = token.location;
|
||||
break;
|
||||
case ',':
|
||||
// The individual arguments are separated by comma tokens, but
|
||||
@ -317,7 +367,7 @@ bool MacroExpander::collectMacroArgs(const Macro ¯o,
|
||||
{
|
||||
MacroArg &arg = args->at(i);
|
||||
TokenLexer lexer(&arg);
|
||||
MacroExpander expander(&lexer, mMacroSet, mDiagnostics);
|
||||
MacroExpander expander(&lexer, mMacroSet, mDiagnostics, mParseDefined);
|
||||
|
||||
arg.clear();
|
||||
expander.lex(&token);
|
||||
|
@ -19,14 +19,15 @@ namespace pp
|
||||
{
|
||||
|
||||
class Diagnostics;
|
||||
struct SourceLocation;
|
||||
|
||||
class MacroExpander : public Lexer
|
||||
{
|
||||
public:
|
||||
MacroExpander(Lexer *lexer, MacroSet *macroSet, Diagnostics *diagnostics);
|
||||
virtual ~MacroExpander();
|
||||
MacroExpander(Lexer *lexer, MacroSet *macroSet, Diagnostics *diagnostics, bool parseDefined);
|
||||
~MacroExpander() override;
|
||||
|
||||
virtual void lex(Token *token);
|
||||
void lex(Token *token) override;
|
||||
|
||||
private:
|
||||
PP_DISALLOW_COPY_AND_ASSIGN(MacroExpander);
|
||||
@ -45,7 +46,8 @@ class MacroExpander : public Lexer
|
||||
typedef std::vector<Token> MacroArg;
|
||||
bool collectMacroArgs(const Macro ¯o,
|
||||
const Token &identifier,
|
||||
std::vector<MacroArg> *args);
|
||||
std::vector<MacroArg> *args,
|
||||
SourceLocation *closingParenthesisLocation);
|
||||
void replaceMacroParams(const Macro ¯o,
|
||||
const std::vector<MacroArg> &args,
|
||||
std::vector<Token> *replacements);
|
||||
@ -79,6 +81,7 @@ class MacroExpander : public Lexer
|
||||
Lexer *mLexer;
|
||||
MacroSet *mMacroSet;
|
||||
Diagnostics *mDiagnostics;
|
||||
bool mParseDefined;
|
||||
|
||||
std::auto_ptr<Token> mReserveToken;
|
||||
std::vector<MacroContext *> mContextStack;
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include "Preprocessor.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
|
||||
#include "DiagnosticsBase.h"
|
||||
#include "DirectiveParser.h"
|
||||
@ -27,12 +26,11 @@ struct PreprocessorImpl
|
||||
DirectiveParser directiveParser;
|
||||
MacroExpander macroExpander;
|
||||
|
||||
PreprocessorImpl(Diagnostics *diag,
|
||||
DirectiveHandler *directiveHandler)
|
||||
PreprocessorImpl(Diagnostics *diag, DirectiveHandler *directiveHandler)
|
||||
: diagnostics(diag),
|
||||
tokenizer(diag),
|
||||
directiveParser(&tokenizer, ¯oSet, diag, directiveHandler),
|
||||
macroExpander(&directiveParser, ¯oSet, diag)
|
||||
macroExpander(&directiveParser, ¯oSet, diag, false)
|
||||
{
|
||||
}
|
||||
};
|
||||
@ -52,12 +50,12 @@ bool Preprocessor::init(size_t count,
|
||||
const char * const string[],
|
||||
const int length[])
|
||||
{
|
||||
static const int kGLSLVersion = 100;
|
||||
static const int kDefaultGLSLVersion = 100;
|
||||
|
||||
// Add standard pre-defined macros.
|
||||
predefineMacro("__LINE__", 0);
|
||||
predefineMacro("__FILE__", 0);
|
||||
predefineMacro("__VERSION__", kGLSLVersion);
|
||||
predefineMacro("__VERSION__", kDefaultGLSLVersion);
|
||||
predefineMacro("GL_ES", 1);
|
||||
|
||||
return mImpl->tokenizer.init(count, string, length);
|
||||
@ -65,20 +63,7 @@ bool Preprocessor::init(size_t count,
|
||||
|
||||
void Preprocessor::predefineMacro(const char *name, int value)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << value;
|
||||
|
||||
Token token;
|
||||
token.type = Token::CONST_INT;
|
||||
token.text = stream.str();
|
||||
|
||||
Macro macro;
|
||||
macro.predefined = true;
|
||||
macro.type = Macro::kTypeObj;
|
||||
macro.name = name;
|
||||
macro.replacements.push_back(token);
|
||||
|
||||
mImpl->macroSet[name] = macro;
|
||||
PredefineMacro(&mImpl->macroSet, name, value);
|
||||
}
|
||||
|
||||
void Preprocessor::lex(Token *token)
|
||||
|
@ -42,7 +42,7 @@ class Tokenizer : public Lexer
|
||||
void setLineNumber(int line);
|
||||
void setMaxTokenSize(size_t maxTokenSize);
|
||||
|
||||
virtual void lex(Token *token);
|
||||
void lex(Token *token) override;
|
||||
|
||||
private:
|
||||
PP_DISALLOW_COPY_AND_ASSIGN(Tokenizer);
|
||||
|
@ -23,6 +23,10 @@ IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh.
|
||||
}
|
||||
|
||||
%{
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable: 4005)
|
||||
#endif
|
||||
|
||||
#include "Tokenizer.h"
|
||||
|
||||
#include "DiagnosticsBase.h"
|
||||
@ -31,6 +35,15 @@ IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh.
|
||||
#if defined(__GNUC__)
|
||||
// Triggered by the auto-generated yy_fatal_error function.
|
||||
#pragma GCC diagnostic ignored "-Wmissing-noreturn"
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma warning(disable: 4244)
|
||||
#endif
|
||||
|
||||
// Workaround for flex using the register keyword, deprecated in C++11.
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus > 199711L
|
||||
#define register
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef std::string YYSTYPE;
|
||||
@ -64,7 +77,7 @@ typedef pp::SourceLocation YYLTYPE;
|
||||
} while(0);
|
||||
|
||||
#define YY_INPUT(buf, result, maxSize) \
|
||||
result = yyextra->input.read(buf, maxSize);
|
||||
result = yyextra->input.read(buf, maxSize, &yylineno);
|
||||
|
||||
%}
|
||||
|
||||
@ -93,7 +106,7 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
|
||||
|
||||
/* Block comment */
|
||||
/* Line breaks are just counted - not returned. */
|
||||
/* The comment is replaced by a single space. */
|
||||
/* The comment is replaced by a single space. */
|
||||
"/*" { BEGIN(COMMENT); }
|
||||
<COMMENT>[^*\r\n]+
|
||||
<COMMENT>"*"
|
||||
|
@ -48,6 +48,15 @@ bool numeric_lex_int(const std::string &str, IntType *value)
|
||||
template<typename FloatType>
|
||||
bool numeric_lex_float(const std::string &str, FloatType *value)
|
||||
{
|
||||
// On 64-bit Intel Android, istringstream is broken. Until this is fixed in
|
||||
// a newer NDK, don't use it. Android doesn't have locale support, so this
|
||||
// doesn't have to force the C locale.
|
||||
// TODO(thakis): Remove this once this bug has been fixed in the NDK and
|
||||
// that NDK has been rolled into chromium.
|
||||
#if defined(ANGLE_PLATFORM_ANDROID) && __x86_64__
|
||||
*value = strtod(str.c_str(), nullptr);
|
||||
return errno != ERANGE;
|
||||
#else
|
||||
std::istringstream stream(str);
|
||||
// Force "C" locale so that decimal character is always '.', and
|
||||
// not dependent on the current locale.
|
||||
@ -55,6 +64,7 @@ bool numeric_lex_float(const std::string &str, FloatType *value)
|
||||
|
||||
stream >> (*value);
|
||||
return !stream.fail();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace pp.
|
||||
|
451
src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.cpp
vendored
Normal file
451
src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.cpp
vendored
Normal file
@ -0,0 +1,451 @@
|
||||
//
|
||||
// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
||||
// Analysis of the AST needed for HLSL generation
|
||||
|
||||
#include "compiler/translator/ASTMetadataHLSL.h"
|
||||
|
||||
#include "compiler/translator/CallDAG.h"
|
||||
#include "compiler/translator/SymbolTable.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Class used to traverse the AST of a function definition, checking if the
|
||||
// function uses a gradient, and writing the set of control flow using gradients.
|
||||
// It assumes that the analysis has already been made for the function's
|
||||
// callees.
|
||||
class PullGradient : public TIntermTraverser
|
||||
{
|
||||
public:
|
||||
PullGradient(MetadataList *metadataList, size_t index, const CallDAG &dag)
|
||||
: TIntermTraverser(true, false, true),
|
||||
mMetadataList(metadataList),
|
||||
mMetadata(&(*metadataList)[index]),
|
||||
mIndex(index),
|
||||
mDag(dag)
|
||||
{
|
||||
ASSERT(index < metadataList->size());
|
||||
}
|
||||
|
||||
void traverse(TIntermAggregate *node)
|
||||
{
|
||||
node->traverse(this);
|
||||
ASSERT(mParents.empty());
|
||||
}
|
||||
|
||||
// Called when a gradient operation or a call to a function using a gradient is found.
|
||||
void onGradient()
|
||||
{
|
||||
mMetadata->mUsesGradient = true;
|
||||
// Mark the latest control flow as using a gradient.
|
||||
if (!mParents.empty())
|
||||
{
|
||||
mMetadata->mControlFlowsContainingGradient.insert(mParents.back());
|
||||
}
|
||||
}
|
||||
|
||||
void visitControlFlow(Visit visit, TIntermNode *node)
|
||||
{
|
||||
if (visit == PreVisit)
|
||||
{
|
||||
mParents.push_back(node);
|
||||
}
|
||||
else if (visit == PostVisit)
|
||||
{
|
||||
ASSERT(mParents.back() == node);
|
||||
mParents.pop_back();
|
||||
// A control flow's using a gradient means its parents are too.
|
||||
if (mMetadata->mControlFlowsContainingGradient.count(node)> 0 && !mParents.empty())
|
||||
{
|
||||
mMetadata->mControlFlowsContainingGradient.insert(mParents.back());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool visitLoop(Visit visit, TIntermLoop *loop) override
|
||||
{
|
||||
visitControlFlow(visit, loop);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visitSelection(Visit visit, TIntermSelection *selection) override
|
||||
{
|
||||
visitControlFlow(visit, selection);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visitUnary(Visit visit, TIntermUnary *node) override
|
||||
{
|
||||
if (visit == PreVisit)
|
||||
{
|
||||
switch (node->getOp())
|
||||
{
|
||||
case EOpDFdx:
|
||||
case EOpDFdy:
|
||||
onGradient();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visitAggregate(Visit visit, TIntermAggregate *node) override
|
||||
{
|
||||
if (visit == PreVisit)
|
||||
{
|
||||
if (node->getOp() == EOpFunctionCall)
|
||||
{
|
||||
if (node->isUserDefined())
|
||||
{
|
||||
size_t calleeIndex = mDag.findIndex(node);
|
||||
ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);
|
||||
UNUSED_ASSERTION_VARIABLE(mIndex);
|
||||
|
||||
if ((*mMetadataList)[calleeIndex].mUsesGradient) {
|
||||
onGradient();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TString name = TFunction::unmangleName(node->getName());
|
||||
|
||||
if (name == "texture2D" ||
|
||||
name == "texture2DProj" ||
|
||||
name == "textureCube")
|
||||
{
|
||||
onGradient();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
MetadataList *mMetadataList;
|
||||
ASTMetadataHLSL *mMetadata;
|
||||
size_t mIndex;
|
||||
const CallDAG &mDag;
|
||||
|
||||
// Contains a stack of the control flow nodes that are parents of the node being
|
||||
// currently visited. It is used to mark control flows using a gradient.
|
||||
std::vector<TIntermNode*> mParents;
|
||||
};
|
||||
|
||||
// Traverses the AST of a function definition to compute the the discontinuous loops
|
||||
// and the if statements containing gradient loops. It assumes that the gradient loops
|
||||
// (loops that contain a gradient) have already been computed and that it has already
|
||||
// traversed the current function's callees.
|
||||
class PullComputeDiscontinuousAndGradientLoops : public TIntermTraverser
|
||||
{
|
||||
public:
|
||||
PullComputeDiscontinuousAndGradientLoops(MetadataList *metadataList,
|
||||
size_t index,
|
||||
const CallDAG &dag)
|
||||
: TIntermTraverser(true, false, true),
|
||||
mMetadataList(metadataList),
|
||||
mMetadata(&(*metadataList)[index]),
|
||||
mIndex(index),
|
||||
mDag(dag)
|
||||
{
|
||||
}
|
||||
|
||||
void traverse(TIntermAggregate *node)
|
||||
{
|
||||
node->traverse(this);
|
||||
ASSERT(mLoopsAndSwitches.empty());
|
||||
ASSERT(mIfs.empty());
|
||||
}
|
||||
|
||||
// Called when traversing a gradient loop or a call to a function with a
|
||||
// gradient loop in its call graph.
|
||||
void onGradientLoop()
|
||||
{
|
||||
mMetadata->mHasGradientLoopInCallGraph = true;
|
||||
// Mark the latest if as using a discontinuous loop.
|
||||
if (!mIfs.empty())
|
||||
{
|
||||
mMetadata->mIfsContainingGradientLoop.insert(mIfs.back());
|
||||
}
|
||||
}
|
||||
|
||||
bool visitLoop(Visit visit, TIntermLoop *loop) override
|
||||
{
|
||||
if (visit == PreVisit)
|
||||
{
|
||||
mLoopsAndSwitches.push_back(loop);
|
||||
|
||||
if (mMetadata->hasGradientInCallGraph(loop))
|
||||
{
|
||||
onGradientLoop();
|
||||
}
|
||||
}
|
||||
else if (visit == PostVisit)
|
||||
{
|
||||
ASSERT(mLoopsAndSwitches.back() == loop);
|
||||
mLoopsAndSwitches.pop_back();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visitSelection(Visit visit, TIntermSelection *node) override
|
||||
{
|
||||
if (visit == PreVisit)
|
||||
{
|
||||
mIfs.push_back(node);
|
||||
}
|
||||
else if (visit == PostVisit)
|
||||
{
|
||||
ASSERT(mIfs.back() == node);
|
||||
mIfs.pop_back();
|
||||
// An if using a discontinuous loop means its parents ifs are also discontinuous.
|
||||
if (mMetadata->mIfsContainingGradientLoop.count(node) > 0 && !mIfs.empty())
|
||||
{
|
||||
mMetadata->mIfsContainingGradientLoop.insert(mIfs.back());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visitBranch(Visit visit, TIntermBranch *node) override
|
||||
{
|
||||
if (visit == PreVisit)
|
||||
{
|
||||
switch (node->getFlowOp())
|
||||
{
|
||||
case EOpBreak:
|
||||
{
|
||||
ASSERT(!mLoopsAndSwitches.empty());
|
||||
TIntermLoop *loop = mLoopsAndSwitches.back()->getAsLoopNode();
|
||||
if (loop != nullptr)
|
||||
{
|
||||
mMetadata->mDiscontinuousLoops.insert(loop);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EOpContinue:
|
||||
{
|
||||
ASSERT(!mLoopsAndSwitches.empty());
|
||||
TIntermLoop *loop = nullptr;
|
||||
size_t i = mLoopsAndSwitches.size();
|
||||
while (loop == nullptr && i > 0)
|
||||
{
|
||||
--i;
|
||||
loop = mLoopsAndSwitches.at(i)->getAsLoopNode();
|
||||
}
|
||||
ASSERT(loop != nullptr);
|
||||
mMetadata->mDiscontinuousLoops.insert(loop);
|
||||
}
|
||||
break;
|
||||
case EOpKill:
|
||||
case EOpReturn:
|
||||
// A return or discard jumps out of all the enclosing loops
|
||||
if (!mLoopsAndSwitches.empty())
|
||||
{
|
||||
for (TIntermNode *intermNode : mLoopsAndSwitches)
|
||||
{
|
||||
TIntermLoop *loop = intermNode->getAsLoopNode();
|
||||
if (loop)
|
||||
{
|
||||
mMetadata->mDiscontinuousLoops.insert(loop);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visitAggregate(Visit visit, TIntermAggregate *node) override
|
||||
{
|
||||
if (visit == PreVisit && node->getOp() == EOpFunctionCall)
|
||||
{
|
||||
if (node->isUserDefined())
|
||||
{
|
||||
size_t calleeIndex = mDag.findIndex(node);
|
||||
ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);
|
||||
UNUSED_ASSERTION_VARIABLE(mIndex);
|
||||
|
||||
if ((*mMetadataList)[calleeIndex].mHasGradientLoopInCallGraph)
|
||||
{
|
||||
onGradientLoop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visitSwitch(Visit visit, TIntermSwitch *node) override
|
||||
{
|
||||
if (visit == PreVisit)
|
||||
{
|
||||
mLoopsAndSwitches.push_back(node);
|
||||
}
|
||||
else if (visit == PostVisit)
|
||||
{
|
||||
ASSERT(mLoopsAndSwitches.back() == node);
|
||||
mLoopsAndSwitches.pop_back();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
MetadataList *mMetadataList;
|
||||
ASTMetadataHLSL *mMetadata;
|
||||
size_t mIndex;
|
||||
const CallDAG &mDag;
|
||||
|
||||
std::vector<TIntermNode*> mLoopsAndSwitches;
|
||||
std::vector<TIntermSelection*> mIfs;
|
||||
};
|
||||
|
||||
// Tags all the functions called in a discontinuous loop
|
||||
class PushDiscontinuousLoops : public TIntermTraverser
|
||||
{
|
||||
public:
|
||||
PushDiscontinuousLoops(MetadataList *metadataList, size_t index, const CallDAG &dag)
|
||||
: TIntermTraverser(true, true, true),
|
||||
mMetadataList(metadataList),
|
||||
mMetadata(&(*metadataList)[index]),
|
||||
mIndex(index),
|
||||
mDag(dag),
|
||||
mNestedDiscont(mMetadata->mCalledInDiscontinuousLoop ? 1 : 0)
|
||||
{
|
||||
}
|
||||
|
||||
void traverse(TIntermAggregate *node)
|
||||
{
|
||||
node->traverse(this);
|
||||
ASSERT(mNestedDiscont == (mMetadata->mCalledInDiscontinuousLoop ? 1 : 0));
|
||||
}
|
||||
|
||||
bool visitLoop(Visit visit, TIntermLoop *loop) override
|
||||
{
|
||||
bool isDiscontinuous = mMetadata->mDiscontinuousLoops.count(loop) > 0;
|
||||
|
||||
if (visit == PreVisit && isDiscontinuous)
|
||||
{
|
||||
mNestedDiscont++;
|
||||
}
|
||||
else if (visit == PostVisit && isDiscontinuous)
|
||||
{
|
||||
mNestedDiscont--;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visitAggregate(Visit visit, TIntermAggregate *node) override
|
||||
{
|
||||
switch (node->getOp())
|
||||
{
|
||||
case EOpFunctionCall:
|
||||
if (visit == PreVisit && node->isUserDefined() && mNestedDiscont > 0)
|
||||
{
|
||||
size_t calleeIndex = mDag.findIndex(node);
|
||||
ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);
|
||||
UNUSED_ASSERTION_VARIABLE(mIndex);
|
||||
|
||||
(*mMetadataList)[calleeIndex].mCalledInDiscontinuousLoop = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
MetadataList *mMetadataList;
|
||||
ASTMetadataHLSL *mMetadata;
|
||||
size_t mIndex;
|
||||
const CallDAG &mDag;
|
||||
|
||||
int mNestedDiscont;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bool ASTMetadataHLSL::hasGradientInCallGraph(TIntermLoop *node)
|
||||
{
|
||||
return mControlFlowsContainingGradient.count(node) > 0;
|
||||
}
|
||||
|
||||
bool ASTMetadataHLSL::hasGradientLoop(TIntermSelection *node)
|
||||
{
|
||||
return mIfsContainingGradientLoop.count(node) > 0;
|
||||
}
|
||||
|
||||
MetadataList CreateASTMetadataHLSL(TIntermNode *root, const CallDAG &callDag)
|
||||
{
|
||||
MetadataList metadataList(callDag.size());
|
||||
|
||||
// Compute all the information related to when gradient operations are used.
|
||||
// We want to know for each function and control flow operation if they have
|
||||
// a gradient operation in their call graph (shortened to "using a gradient"
|
||||
// in the rest of the file).
|
||||
//
|
||||
// This computation is logically split in three steps:
|
||||
// 1 - For each function compute if it uses a gradient in its body, ignoring
|
||||
// calls to other user-defined functions.
|
||||
// 2 - For each function determine if it uses a gradient in its call graph,
|
||||
// using the result of step 1 and the CallDAG to know its callees.
|
||||
// 3 - For each control flow statement of each function, check if it uses a
|
||||
// gradient in the function's body, or if it calls a user-defined function that
|
||||
// uses a gradient.
|
||||
//
|
||||
// We take advantage of the call graph being a DAG and instead compute 1, 2 and 3
|
||||
// for leaves first, then going down the tree. This is correct because 1 doesn't
|
||||
// depend on other functions, and 2 and 3 depend only on callees.
|
||||
for (size_t i = 0; i < callDag.size(); i++)
|
||||
{
|
||||
PullGradient pull(&metadataList, i, callDag);
|
||||
pull.traverse(callDag.getRecordFromIndex(i).node);
|
||||
}
|
||||
|
||||
// Compute which loops are discontinuous and which function are called in
|
||||
// these loops. The same way computing gradient usage is a "pull" process,
|
||||
// computing "bing used in a discont. loop" is a push process. However we also
|
||||
// need to know what ifs have a discontinuous loop inside so we do the same type
|
||||
// of callgraph analysis as for the gradient.
|
||||
|
||||
// First compute which loops are discontinuous (no specific order) and pull
|
||||
// the ifs and functions using a gradient loop.
|
||||
for (size_t i = 0; i < callDag.size(); i++)
|
||||
{
|
||||
PullComputeDiscontinuousAndGradientLoops pull(&metadataList, i, callDag);
|
||||
pull.traverse(callDag.getRecordFromIndex(i).node);
|
||||
}
|
||||
|
||||
// Then push the information to callees, either from the a local discontinuous
|
||||
// loop or from the caller being called in a discontinuous loop already
|
||||
for (size_t i = callDag.size(); i-- > 0;)
|
||||
{
|
||||
PushDiscontinuousLoops push(&metadataList, i, callDag);
|
||||
push.traverse(callDag.getRecordFromIndex(i).node);
|
||||
}
|
||||
|
||||
// We create "Lod0" version of functions with the gradient operations replaced
|
||||
// by non-gradient operations so that the D3D compiler is happier with discont
|
||||
// loops.
|
||||
for (auto &metadata : metadataList)
|
||||
{
|
||||
metadata.mNeedsLod0 = metadata.mCalledInDiscontinuousLoop && metadata.mUsesGradient;
|
||||
}
|
||||
|
||||
return metadataList;
|
||||
}
|
58
src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.h
vendored
Normal file
58
src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.h
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
//
|
||||
// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
||||
// Defines analyses of the AST needed for HLSL generation
|
||||
|
||||
#ifndef COMPILER_TRANSLATOR_ASTMETADATAHLSL_H_
|
||||
#define COMPILER_TRANSLATOR_ASTMETADATAHLSL_H_
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
class CallDAG;
|
||||
class TIntermNode;
|
||||
class TIntermSelection;
|
||||
class TIntermLoop;
|
||||
|
||||
struct ASTMetadataHLSL
|
||||
{
|
||||
ASTMetadataHLSL()
|
||||
: mUsesGradient(false),
|
||||
mCalledInDiscontinuousLoop(false),
|
||||
mHasGradientLoopInCallGraph(false),
|
||||
mNeedsLod0(false)
|
||||
{
|
||||
}
|
||||
|
||||
// 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(TIntermSelection *node);
|
||||
|
||||
// Does the function use a gradient.
|
||||
bool mUsesGradient;
|
||||
|
||||
// Even if usesGradient is true, some control flow might not use a gradient
|
||||
// so we store the set of all gradient-using control flows.
|
||||
std::set<TIntermNode*> mControlFlowsContainingGradient;
|
||||
|
||||
// Remember information about the discontinuous loops and which functions
|
||||
// are called in such loops.
|
||||
bool mCalledInDiscontinuousLoop;
|
||||
bool mHasGradientLoopInCallGraph;
|
||||
std::set<TIntermLoop*> mDiscontinuousLoops;
|
||||
std::set<TIntermSelection *> mIfsContainingGradientLoop;
|
||||
|
||||
// Will we need to generate a Lod0 version of the function.
|
||||
bool mNeedsLod0;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
#endif // COMPILER_TRANSLATOR_ASTMETADATAHLSL_H_
|
206
src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
vendored
Normal file
206
src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
vendored
Normal file
@ -0,0 +1,206 @@
|
||||
//
|
||||
// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// The ArrayReturnValueToOutParameter function changes return values of an array type to out parameters in
|
||||
// function definitions, prototypes, and call sites.
|
||||
|
||||
#include "compiler/translator/ArrayReturnValueToOutParameter.h"
|
||||
|
||||
#include "compiler/translator/IntermNode.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void CopyAggregateChildren(TIntermAggregate *from, TIntermAggregate *to)
|
||||
{
|
||||
const TIntermSequence *fromSequence = from->getSequence();
|
||||
for (size_t ii = 0; ii < fromSequence->size(); ++ii)
|
||||
{
|
||||
to->getSequence()->push_back(fromSequence->at(ii));
|
||||
}
|
||||
}
|
||||
|
||||
TIntermSymbol *CreateReturnValueSymbol(const TType &type)
|
||||
{
|
||||
TIntermSymbol *node = new TIntermSymbol(0, "angle_return", type);
|
||||
node->setInternal(true);
|
||||
return node;
|
||||
}
|
||||
|
||||
TIntermSymbol *CreateReturnValueOutSymbol(const TType &type)
|
||||
{
|
||||
TType outType(type);
|
||||
outType.setQualifier(EvqOut);
|
||||
return CreateReturnValueSymbol(outType);
|
||||
}
|
||||
|
||||
TIntermAggregate *CreateReplacementCall(TIntermAggregate *originalCall, TIntermTyped *returnValueTarget)
|
||||
{
|
||||
TIntermAggregate *replacementCall = new TIntermAggregate(EOpFunctionCall);
|
||||
replacementCall->setType(TType(EbtVoid));
|
||||
replacementCall->setUserDefined();
|
||||
replacementCall->setNameObj(originalCall->getNameObj());
|
||||
replacementCall->setFunctionId(originalCall->getFunctionId());
|
||||
replacementCall->setLine(originalCall->getLine());
|
||||
TIntermSequence *replacementParameters = replacementCall->getSequence();
|
||||
TIntermSequence *originalParameters = originalCall->getSequence();
|
||||
for (auto ¶m : *originalParameters)
|
||||
{
|
||||
replacementParameters->push_back(param);
|
||||
}
|
||||
replacementParameters->push_back(returnValueTarget);
|
||||
return replacementCall;
|
||||
}
|
||||
|
||||
class ArrayReturnValueToOutParameterTraverser : private TIntermTraverser
|
||||
{
|
||||
public:
|
||||
static void apply(TIntermNode *root, unsigned int *temporaryIndex);
|
||||
private:
|
||||
ArrayReturnValueToOutParameterTraverser();
|
||||
|
||||
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
|
||||
bool visitBranch(Visit visit, TIntermBranch *node) override;
|
||||
bool visitBinary(Visit visit, TIntermBinary *node) override;
|
||||
|
||||
bool mInFunctionWithArrayReturnValue;
|
||||
};
|
||||
|
||||
void ArrayReturnValueToOutParameterTraverser::apply(TIntermNode *root, unsigned int *temporaryIndex)
|
||||
{
|
||||
ArrayReturnValueToOutParameterTraverser arrayReturnValueToOutParam;
|
||||
arrayReturnValueToOutParam.useTemporaryIndex(temporaryIndex);
|
||||
root->traverse(&arrayReturnValueToOutParam);
|
||||
arrayReturnValueToOutParam.updateTree();
|
||||
}
|
||||
|
||||
ArrayReturnValueToOutParameterTraverser::ArrayReturnValueToOutParameterTraverser()
|
||||
: TIntermTraverser(true, false, true),
|
||||
mInFunctionWithArrayReturnValue(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool ArrayReturnValueToOutParameterTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
|
||||
{
|
||||
if (visit == PreVisit)
|
||||
{
|
||||
if (node->isArray())
|
||||
{
|
||||
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());
|
||||
|
||||
mReplacements.push_back(NodeUpdateEntry(node, params, replacementParams, false));
|
||||
|
||||
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;
|
||||
replacement->setOp(EOpPrototype);
|
||||
CopyAggregateChildren(node, replacement);
|
||||
replacement->getSequence()->push_back(CreateReturnValueOutSymbol(node->getType()));
|
||||
replacement->setUserDefined();
|
||||
replacement->setNameObj(node->getNameObj());
|
||||
replacement->setFunctionId(node->getFunctionId());
|
||||
replacement->setLine(node->getLine());
|
||||
replacement->setType(TType(EbtVoid));
|
||||
|
||||
mReplacements.push_back(NodeUpdateEntry(getParentNode(), node, replacement, false));
|
||||
}
|
||||
else if (node->getOp() == EOpFunctionCall)
|
||||
{
|
||||
// Handle call sites where the returned array is not assigned.
|
||||
// Examples where f() is a function returning an array:
|
||||
// 1. f();
|
||||
// 2. another_array == f();
|
||||
// 3. another_function(f());
|
||||
// 4. return f();
|
||||
// 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.
|
||||
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(parentAgg, node, replacements));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (visit == PostVisit)
|
||||
{
|
||||
if (node->getOp() == EOpFunction)
|
||||
{
|
||||
mInFunctionWithArrayReturnValue = false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArrayReturnValueToOutParameterTraverser::visitBranch(Visit visit, TIntermBranch *node)
|
||||
{
|
||||
if (mInFunctionWithArrayReturnValue && node->getFlowOp() == EOpReturn)
|
||||
{
|
||||
// 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);
|
||||
replacementAssignment->setLeft(CreateReturnValueSymbol(expression->getType()));
|
||||
replacementAssignment->setRight(node->getExpression());
|
||||
replacementAssignment->setType(expression->getType());
|
||||
replacementAssignment->setLine(expression->getLine());
|
||||
replacements.push_back(replacementAssignment);
|
||||
|
||||
TIntermBranch *replacementBranch = new TIntermBranch(EOpReturn, nullptr);
|
||||
replacementBranch->setLine(node->getLine());
|
||||
replacements.push_back(replacementBranch);
|
||||
|
||||
mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(getParentNode()->getAsAggregate(), node, replacements));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ArrayReturnValueToOutParameterTraverser::visitBinary(Visit visit, TIntermBinary *node)
|
||||
{
|
||||
if (node->getOp() == EOpAssign && node->getLeft()->isArray())
|
||||
{
|
||||
TIntermAggregate *rightAgg = node->getRight()->getAsAggregate();
|
||||
if (rightAgg != nullptr && rightAgg->getOp() == EOpFunctionCall && rightAgg->isUserDefined())
|
||||
{
|
||||
TIntermAggregate *replacementCall = CreateReplacementCall(rightAgg, node->getLeft());
|
||||
mReplacements.push_back(NodeUpdateEntry(getParentNode(), node, replacementCall, false));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void ArrayReturnValueToOutParameter(TIntermNode *root, unsigned int *temporaryIndex)
|
||||
{
|
||||
ArrayReturnValueToOutParameterTraverser::apply(root, temporaryIndex);
|
||||
}
|
16
src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h
vendored
Normal file
16
src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
//
|
||||
// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// The ArrayReturnValueToOutParameter function changes return values of an array type to out parameters in
|
||||
// function definitions, prototypes and call sites.
|
||||
|
||||
#ifndef COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
|
||||
#define COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
|
||||
|
||||
class TIntermNode;
|
||||
|
||||
void ArrayReturnValueToOutParameter(TIntermNode *root, unsigned int *temporaryIndex);
|
||||
|
||||
#endif // COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
|
@ -7,7 +7,7 @@
|
||||
#ifndef COMPILER_TRANSLATOR_BASETYPES_H_
|
||||
#define COMPILER_TRANSLATOR_BASETYPES_H_
|
||||
|
||||
#include "compiler/translator/compilerdebug.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
//
|
||||
// Precision qualifiers
|
||||
@ -18,7 +18,10 @@ enum TPrecision
|
||||
EbpUndefined,
|
||||
EbpLow,
|
||||
EbpMedium,
|
||||
EbpHigh
|
||||
EbpHigh,
|
||||
|
||||
// end of list
|
||||
EbpLast
|
||||
};
|
||||
|
||||
inline const char* getPrecisionString(TPrecision p)
|
||||
@ -77,6 +80,9 @@ enum TBasicType
|
||||
EbtStruct,
|
||||
EbtInterfaceBlock,
|
||||
EbtAddress, // should be deprecated??
|
||||
|
||||
// end of list
|
||||
EbtLast
|
||||
};
|
||||
|
||||
const char* getBasicString(TBasicType t);
|
||||
@ -284,21 +290,18 @@ inline bool SupportsPrecision(TBasicType type)
|
||||
//
|
||||
enum TQualifier
|
||||
{
|
||||
EvqTemporary, // For temporaries (within a function), read/write
|
||||
EvqGlobal, // For globals read/write
|
||||
EvqInternal, // For internal use, not visible to the user
|
||||
EvqConst, // User defined constants and non-output parameters in functions
|
||||
EvqAttribute, // Readonly
|
||||
EvqVaryingIn, // readonly, fragment shaders only
|
||||
EvqVaryingOut, // vertex shaders only read/write
|
||||
EvqInvariantVaryingIn, // readonly, fragment shaders only
|
||||
EvqInvariantVaryingOut, // vertex shaders only read/write
|
||||
EvqUniform, // Readonly, vertex and fragment
|
||||
EvqTemporary, // For temporaries (within a function), read/write
|
||||
EvqGlobal, // For globals read/write
|
||||
EvqConst, // User defined constants and non-output parameters in functions
|
||||
EvqAttribute, // Readonly
|
||||
EvqVaryingIn, // readonly, fragment shaders only
|
||||
EvqVaryingOut, // vertex shaders only read/write
|
||||
EvqUniform, // Readonly, vertex and fragment
|
||||
|
||||
EvqVertexIn, // Vertex shader input
|
||||
EvqFragmentOut, // Fragment shader output
|
||||
EvqVertexOut, // Vertex shader output
|
||||
EvqFragmentIn, // Fragment shader input
|
||||
EvqVertexIn, // Vertex shader input
|
||||
EvqFragmentOut, // Fragment shader output
|
||||
EvqVertexOut, // Vertex shader output
|
||||
EvqFragmentIn, // Fragment shader input
|
||||
|
||||
// parameters
|
||||
EvqIn,
|
||||
@ -321,21 +324,26 @@ enum TQualifier
|
||||
// built-ins written by fragment shader
|
||||
EvqFragColor,
|
||||
EvqFragData,
|
||||
EvqFragDepth,
|
||||
|
||||
EvqFragDepth, // gl_FragDepth for ESSL300.
|
||||
EvqFragDepthEXT, // gl_FragDepthEXT for ESSL100, EXT_frag_depth.
|
||||
|
||||
EvqSecondaryFragColorEXT, // EXT_blend_func_extended
|
||||
EvqSecondaryFragDataEXT, // EXT_blend_func_extended
|
||||
|
||||
// built-ins written by the shader_framebuffer_fetch extension(s)
|
||||
EvqLastFragColor,
|
||||
EvqLastFragData,
|
||||
|
||||
// GLSL ES 3.0 vertex output and fragment input
|
||||
EvqSmooth, // Incomplete qualifier, smooth is the default
|
||||
EvqFlat, // Incomplete qualifier
|
||||
EvqSmooth, // Incomplete qualifier, smooth is the default
|
||||
EvqFlat, // Incomplete qualifier
|
||||
EvqSmoothOut = EvqSmooth,
|
||||
EvqFlatOut = EvqFlat,
|
||||
EvqCentroidOut, // Implies smooth
|
||||
EvqFlatOut = EvqFlat,
|
||||
EvqCentroidOut, // Implies smooth
|
||||
EvqSmoothIn,
|
||||
EvqFlatIn,
|
||||
EvqCentroidIn, // Implies smooth
|
||||
EvqCentroidIn, // Implies smooth
|
||||
|
||||
// end of list
|
||||
EvqLast
|
||||
@ -384,43 +392,47 @@ struct TLayoutQualifier
|
||||
//
|
||||
inline const char* getQualifierString(TQualifier q)
|
||||
{
|
||||
// clang-format off
|
||||
switch(q)
|
||||
{
|
||||
case EvqTemporary: return "Temporary"; break;
|
||||
case EvqGlobal: return "Global"; break;
|
||||
case EvqConst: return "const"; break;
|
||||
case EvqConstReadOnly: return "const"; break;
|
||||
case EvqAttribute: return "attribute"; break;
|
||||
case EvqVaryingIn: return "varying"; break;
|
||||
case EvqVaryingOut: return "varying"; break;
|
||||
case EvqInvariantVaryingIn: return "invariant varying"; break;
|
||||
case EvqInvariantVaryingOut:return "invariant varying"; break;
|
||||
case EvqUniform: return "uniform"; break;
|
||||
case EvqVertexIn: return "in"; break;
|
||||
case EvqFragmentOut: return "out"; break;
|
||||
case EvqVertexOut: return "out"; break;
|
||||
case EvqFragmentIn: return "in"; break;
|
||||
case EvqIn: return "in"; break;
|
||||
case EvqOut: return "out"; break;
|
||||
case EvqInOut: return "inout"; break;
|
||||
case EvqInstanceID: return "InstanceID"; break;
|
||||
case EvqPosition: return "Position"; break;
|
||||
case EvqPointSize: return "PointSize"; break;
|
||||
case EvqFragCoord: return "FragCoord"; break;
|
||||
case EvqFrontFacing: return "FrontFacing"; break;
|
||||
case EvqFragColor: return "FragColor"; break;
|
||||
case EvqFragData: return "FragData"; break;
|
||||
case EvqFragDepth: return "FragDepth"; break;
|
||||
case EvqSmoothOut: return "smooth out"; break;
|
||||
case EvqCentroidOut: return "centroid out"; break;
|
||||
case EvqFlatOut: return "flat out"; break;
|
||||
case EvqSmoothIn: return "smooth in"; break;
|
||||
case EvqCentroidIn: return "centroid in"; break;
|
||||
case EvqFlatIn: return "flat in"; break;
|
||||
case EvqLastFragColor: return "LastFragColor"; break;
|
||||
case EvqLastFragData: return "LastFragData"; break;
|
||||
default: UNREACHABLE(); return "unknown qualifier";
|
||||
case EvqTemporary: return "Temporary";
|
||||
case EvqGlobal: return "Global";
|
||||
case EvqConst: return "const";
|
||||
case EvqAttribute: return "attribute";
|
||||
case EvqVaryingIn: return "varying";
|
||||
case EvqVaryingOut: return "varying";
|
||||
case EvqUniform: return "uniform";
|
||||
case EvqVertexIn: return "in";
|
||||
case EvqFragmentOut: return "out";
|
||||
case EvqVertexOut: return "out";
|
||||
case EvqFragmentIn: return "in";
|
||||
case EvqIn: return "in";
|
||||
case EvqOut: return "out";
|
||||
case EvqInOut: return "inout";
|
||||
case EvqConstReadOnly: return "const";
|
||||
case EvqInstanceID: return "InstanceID";
|
||||
case EvqPosition: return "Position";
|
||||
case EvqPointSize: return "PointSize";
|
||||
case EvqFragCoord: return "FragCoord";
|
||||
case EvqFrontFacing: return "FrontFacing";
|
||||
case EvqPointCoord: return "PointCoord";
|
||||
case EvqFragColor: return "FragColor";
|
||||
case EvqFragData: return "FragData";
|
||||
case EvqFragDepthEXT: return "FragDepth";
|
||||
case EvqFragDepth: return "FragDepth";
|
||||
case EvqSecondaryFragColorEXT: return "SecondaryFragColorEXT";
|
||||
case EvqSecondaryFragDataEXT: return "SecondaryFragDataEXT";
|
||||
case EvqLastFragColor: return "LastFragColor";
|
||||
case EvqLastFragData: return "LastFragData";
|
||||
case EvqSmoothOut: return "smooth out";
|
||||
case EvqCentroidOut: return "centroid out";
|
||||
case EvqFlatOut: return "flat out";
|
||||
case EvqSmoothIn: return "smooth in";
|
||||
case EvqFlatIn: return "flat in";
|
||||
case EvqCentroidIn: return "centroid in";
|
||||
default: UNREACHABLE(); return "unknown qualifier";
|
||||
}
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
inline const char* getMatrixPackingString(TLayoutMatrixPacking mpq)
|
||||
|
@ -11,28 +11,31 @@
|
||||
class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTraverser
|
||||
{
|
||||
public:
|
||||
BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator& emulator)
|
||||
: mEmulator(emulator)
|
||||
BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator &emulator)
|
||||
: TIntermTraverser(true, false, false),
|
||||
mEmulator(emulator)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool visitUnary(Visit visit, TIntermUnary* node)
|
||||
bool visitUnary(Visit visit, TIntermUnary *node) override
|
||||
{
|
||||
if (visit == PreVisit) {
|
||||
bool needToEmulate = mEmulator.SetFunctionCalled(
|
||||
node->getOp(), node->getOperand()->getType());
|
||||
if (visit == PreVisit)
|
||||
{
|
||||
bool needToEmulate = mEmulator.SetFunctionCalled(node->getOp(), node->getOperand()->getType());
|
||||
if (needToEmulate)
|
||||
node->setUseEmulatedFunction();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool visitAggregate(Visit visit, TIntermAggregate* node)
|
||||
bool visitAggregate(Visit visit, TIntermAggregate *node) override
|
||||
{
|
||||
if (visit == PreVisit) {
|
||||
if (visit == PreVisit)
|
||||
{
|
||||
// Here we handle all the built-in functions instead of the ones we
|
||||
// currently identified as problematic.
|
||||
switch (node->getOp()) {
|
||||
switch (node->getOp())
|
||||
{
|
||||
case EOpLessThan:
|
||||
case EOpGreaterThan:
|
||||
case EOpLessThanEqual:
|
||||
@ -59,14 +62,14 @@ class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTr
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
};
|
||||
const TIntermSequence& sequence = *(node->getSequence());
|
||||
}
|
||||
const TIntermSequence &sequence = *(node->getSequence());
|
||||
bool needToEmulate = false;
|
||||
// Right now we only handle built-in functions with two or three parameters.
|
||||
if (sequence.size() == 2)
|
||||
{
|
||||
TIntermTyped* param1 = sequence[0]->getAsTyped();
|
||||
TIntermTyped* param2 = sequence[1]->getAsTyped();
|
||||
TIntermTyped *param1 = sequence[0]->getAsTyped();
|
||||
TIntermTyped *param2 = sequence[1]->getAsTyped();
|
||||
if (!param1 || !param2)
|
||||
return true;
|
||||
needToEmulate = mEmulator.SetFunctionCalled(
|
||||
@ -74,9 +77,9 @@ class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTr
|
||||
}
|
||||
else if (sequence.size() == 3)
|
||||
{
|
||||
TIntermTyped* param1 = sequence[0]->getAsTyped();
|
||||
TIntermTyped* param2 = sequence[1]->getAsTyped();
|
||||
TIntermTyped* param3 = sequence[2]->getAsTyped();
|
||||
TIntermTyped *param1 = sequence[0]->getAsTyped();
|
||||
TIntermTyped *param2 = sequence[1]->getAsTyped();
|
||||
TIntermTyped *param3 = sequence[2]->getAsTyped();
|
||||
if (!param1 || !param2 || !param3)
|
||||
return true;
|
||||
needToEmulate = mEmulator.SetFunctionCalled(
|
||||
@ -94,34 +97,28 @@ class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTr
|
||||
}
|
||||
|
||||
private:
|
||||
BuiltInFunctionEmulator& mEmulator;
|
||||
BuiltInFunctionEmulator &mEmulator;
|
||||
};
|
||||
|
||||
BuiltInFunctionEmulator::BuiltInFunctionEmulator()
|
||||
{}
|
||||
|
||||
void BuiltInFunctionEmulator::addEmulatedFunction(
|
||||
TOperator op, const TType& param,
|
||||
const char* emulatedFunctionDefinition)
|
||||
void BuiltInFunctionEmulator::addEmulatedFunction(TOperator op, const TType *param,
|
||||
const char *emulatedFunctionDefinition)
|
||||
{
|
||||
mEmulatedFunctions[FunctionId(op, param)] =
|
||||
std::string(emulatedFunctionDefinition);
|
||||
mEmulatedFunctions[FunctionId(op, param)] = std::string(emulatedFunctionDefinition);
|
||||
}
|
||||
|
||||
void BuiltInFunctionEmulator::addEmulatedFunction(
|
||||
TOperator op, const TType& param1, const TType& param2,
|
||||
const char* emulatedFunctionDefinition)
|
||||
void BuiltInFunctionEmulator::addEmulatedFunction(TOperator op, const TType *param1, const TType *param2,
|
||||
const char *emulatedFunctionDefinition)
|
||||
{
|
||||
mEmulatedFunctions[FunctionId(op, param1, param2)] =
|
||||
std::string(emulatedFunctionDefinition);
|
||||
mEmulatedFunctions[FunctionId(op, param1, param2)] = std::string(emulatedFunctionDefinition);
|
||||
}
|
||||
|
||||
void BuiltInFunctionEmulator::addEmulatedFunction(
|
||||
TOperator op, const TType& param1, const TType& param2, const TType& param3,
|
||||
const char* emulatedFunctionDefinition)
|
||||
void BuiltInFunctionEmulator::addEmulatedFunction(TOperator op, const TType *param1, const TType *param2,
|
||||
const TType *param3, const char *emulatedFunctionDefinition)
|
||||
{
|
||||
mEmulatedFunctions[FunctionId(op, param1, param2, param3)] =
|
||||
std::string(emulatedFunctionDefinition);
|
||||
mEmulatedFunctions[FunctionId(op, param1, param2, param3)] = std::string(emulatedFunctionDefinition);
|
||||
}
|
||||
|
||||
bool BuiltInFunctionEmulator::IsOutputEmpty() const
|
||||
@ -129,48 +126,48 @@ bool BuiltInFunctionEmulator::IsOutputEmpty() const
|
||||
return (mFunctions.size() == 0);
|
||||
}
|
||||
|
||||
void BuiltInFunctionEmulator::OutputEmulatedFunctions(
|
||||
TInfoSinkBase& out) const
|
||||
void BuiltInFunctionEmulator::OutputEmulatedFunctions(TInfoSinkBase &out) const
|
||||
{
|
||||
for (size_t i = 0; i < mFunctions.size(); ++i) {
|
||||
for (size_t i = 0; i < mFunctions.size(); ++i)
|
||||
{
|
||||
out << mEmulatedFunctions.find(mFunctions[i])->second << "\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
bool BuiltInFunctionEmulator::SetFunctionCalled(
|
||||
TOperator op, const TType& param)
|
||||
bool BuiltInFunctionEmulator::SetFunctionCalled(TOperator op, const TType ¶m)
|
||||
{
|
||||
return SetFunctionCalled(FunctionId(op, param));
|
||||
return SetFunctionCalled(FunctionId(op, ¶m));
|
||||
}
|
||||
|
||||
bool BuiltInFunctionEmulator::SetFunctionCalled(
|
||||
TOperator op, const TType& param1, const TType& param2)
|
||||
bool BuiltInFunctionEmulator::SetFunctionCalled(TOperator op, const TType ¶m1, const TType ¶m2)
|
||||
{
|
||||
return SetFunctionCalled(FunctionId(op, param1, param2));
|
||||
return SetFunctionCalled(FunctionId(op, ¶m1, ¶m2));
|
||||
}
|
||||
|
||||
bool BuiltInFunctionEmulator::SetFunctionCalled(
|
||||
TOperator op, const TType& param1, const TType& param2, const TType& param3)
|
||||
bool BuiltInFunctionEmulator::SetFunctionCalled(TOperator op,
|
||||
const TType ¶m1, const TType ¶m2, const TType ¶m3)
|
||||
{
|
||||
return SetFunctionCalled(FunctionId(op, param1, param2, param3));
|
||||
return SetFunctionCalled(FunctionId(op, ¶m1, ¶m2, ¶m3));
|
||||
}
|
||||
|
||||
bool BuiltInFunctionEmulator::SetFunctionCalled(
|
||||
const FunctionId& functionId) {
|
||||
bool BuiltInFunctionEmulator::SetFunctionCalled(const FunctionId &functionId)
|
||||
{
|
||||
if (mEmulatedFunctions.find(functionId) != mEmulatedFunctions.end())
|
||||
{
|
||||
for (size_t i = 0; i < mFunctions.size(); ++i) {
|
||||
for (size_t i = 0; i < mFunctions.size(); ++i)
|
||||
{
|
||||
if (mFunctions[i] == functionId)
|
||||
return true;
|
||||
}
|
||||
mFunctions.push_back(functionId);
|
||||
// Copy the functionId if it needs to be stored, to make sure that the TType pointers inside
|
||||
// remain valid and constant.
|
||||
mFunctions.push_back(functionId.getCopy());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation(
|
||||
TIntermNode* root)
|
||||
void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation(TIntermNode *root)
|
||||
{
|
||||
ASSERT(root);
|
||||
|
||||
@ -188,32 +185,30 @@ void BuiltInFunctionEmulator::Cleanup()
|
||||
|
||||
//static
|
||||
TString BuiltInFunctionEmulator::GetEmulatedFunctionName(
|
||||
const TString& name)
|
||||
const TString &name)
|
||||
{
|
||||
ASSERT(name[name.length() - 1] == '(');
|
||||
return "webgl_" + name.substr(0, name.length() - 1) + "_emu(";
|
||||
}
|
||||
|
||||
BuiltInFunctionEmulator::FunctionId::FunctionId
|
||||
(TOperator op, const TType& param)
|
||||
BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op, const TType *param)
|
||||
: mOp(op),
|
||||
mParam1(param),
|
||||
mParam2(EbtVoid),
|
||||
mParam3(EbtVoid)
|
||||
mParam2(new TType(EbtVoid)),
|
||||
mParam3(new TType(EbtVoid))
|
||||
{
|
||||
}
|
||||
|
||||
BuiltInFunctionEmulator::FunctionId::FunctionId
|
||||
(TOperator op, const TType& param1, const TType& param2)
|
||||
BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2)
|
||||
: mOp(op),
|
||||
mParam1(param1),
|
||||
mParam2(param2),
|
||||
mParam3(EbtVoid)
|
||||
mParam3(new TType(EbtVoid))
|
||||
{
|
||||
}
|
||||
|
||||
BuiltInFunctionEmulator::FunctionId::FunctionId
|
||||
(TOperator op, const TType& param1, const TType& param2, const TType& param3)
|
||||
BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op,
|
||||
const TType *param1, const TType *param2, const TType *param3)
|
||||
: mOp(op),
|
||||
mParam1(param1),
|
||||
mParam2(param2),
|
||||
@ -221,25 +216,28 @@ BuiltInFunctionEmulator::FunctionId::FunctionId
|
||||
{
|
||||
}
|
||||
|
||||
bool BuiltInFunctionEmulator::FunctionId::operator==
|
||||
(const BuiltInFunctionEmulator::FunctionId& other) const
|
||||
bool BuiltInFunctionEmulator::FunctionId::operator==(const BuiltInFunctionEmulator::FunctionId &other) const
|
||||
{
|
||||
return (mOp == other.mOp &&
|
||||
mParam1 == other.mParam1 &&
|
||||
mParam2 == other.mParam2 &&
|
||||
mParam3 == other.mParam3);
|
||||
*mParam1 == *other.mParam1 &&
|
||||
*mParam2 == *other.mParam2 &&
|
||||
*mParam3 == *other.mParam3);
|
||||
}
|
||||
|
||||
bool BuiltInFunctionEmulator::FunctionId::operator<
|
||||
(const BuiltInFunctionEmulator::FunctionId& other) const
|
||||
bool BuiltInFunctionEmulator::FunctionId::operator<(const BuiltInFunctionEmulator::FunctionId &other) const
|
||||
{
|
||||
if (mOp != other.mOp)
|
||||
return mOp < other.mOp;
|
||||
if (mParam1 != other.mParam1)
|
||||
return mParam1 < other.mParam1;
|
||||
if (mParam2 != other.mParam2)
|
||||
return mParam2 < other.mParam2;
|
||||
if (mParam3 != other.mParam3)
|
||||
return mParam3 < other.mParam3;
|
||||
if (*mParam1 != *other.mParam1)
|
||||
return *mParam1 < *other.mParam1;
|
||||
if (*mParam2 != *other.mParam2)
|
||||
return *mParam2 < *other.mParam2;
|
||||
if (*mParam3 != *other.mParam3)
|
||||
return *mParam3 < *other.mParam3;
|
||||
return false; // all fields are equal
|
||||
}
|
||||
|
||||
BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::FunctionId::getCopy() const
|
||||
{
|
||||
return FunctionId(mOp, new TType(*mParam1), new TType(*mParam2), new TType(*mParam3));
|
||||
}
|
||||
|
@ -21,23 +21,25 @@ class BuiltInFunctionEmulator
|
||||
public:
|
||||
BuiltInFunctionEmulator();
|
||||
|
||||
void MarkBuiltInFunctionsForEmulation(TIntermNode* root);
|
||||
void MarkBuiltInFunctionsForEmulation(TIntermNode *root);
|
||||
|
||||
void Cleanup();
|
||||
|
||||
// "name(" becomes "webgl_name_emu(".
|
||||
static TString GetEmulatedFunctionName(const TString& name);
|
||||
static TString GetEmulatedFunctionName(const TString &name);
|
||||
|
||||
bool IsOutputEmpty() const;
|
||||
|
||||
// Output function emulation definition. This should be before any other
|
||||
// shader source.
|
||||
void OutputEmulatedFunctions(TInfoSinkBase& out) const;
|
||||
void OutputEmulatedFunctions(TInfoSinkBase &out) const;
|
||||
|
||||
// Add functions that need to be emulated.
|
||||
void addEmulatedFunction(TOperator op, const TType& param, const char* emulatedFunctionDefinition);
|
||||
void addEmulatedFunction(TOperator op, const TType& param1, const TType& param2, const char* emulatedFunctionDefinition);
|
||||
void addEmulatedFunction(TOperator op, const TType& param1, const TType& param2, const TType& param3, const char* emulatedFunctionDefinition);
|
||||
void addEmulatedFunction(TOperator op, const TType *param, const char *emulatedFunctionDefinition);
|
||||
void addEmulatedFunction(TOperator op, const TType *param1, const TType *param2,
|
||||
const char *emulatedFunctionDefinition);
|
||||
void addEmulatedFunction(TOperator op, const TType *param1, const TType *param2, const TType *param3,
|
||||
const char *emulatedFunctionDefinition);
|
||||
|
||||
private:
|
||||
class BuiltInFunctionEmulationMarker;
|
||||
@ -46,28 +48,32 @@ class BuiltInFunctionEmulator
|
||||
// emulated. If the function is not in mEmulatedFunctions, this becomes a
|
||||
// no-op. Returns true if the function call needs to be replaced with an
|
||||
// emulated one.
|
||||
bool SetFunctionCalled(TOperator op, const TType& param);
|
||||
bool SetFunctionCalled(
|
||||
TOperator op, const TType& param1, const TType& param2);
|
||||
bool SetFunctionCalled(
|
||||
TOperator op, const TType& param1, const TType& param2, const TType& param3);
|
||||
bool SetFunctionCalled(TOperator op, const TType ¶m);
|
||||
bool SetFunctionCalled(TOperator op, const TType ¶m1, const TType ¶m2);
|
||||
bool SetFunctionCalled(TOperator op, const TType ¶m1, const TType ¶m2, const TType ¶m3);
|
||||
|
||||
class FunctionId {
|
||||
public:
|
||||
FunctionId(TOperator op, const TType& param);
|
||||
FunctionId(TOperator op, const TType& param1, const TType& param2);
|
||||
FunctionId(TOperator op, const TType& param1, const TType& param2, const TType& param3);
|
||||
FunctionId(TOperator op, const TType *param);
|
||||
FunctionId(TOperator op, const TType *param1, const TType *param2);
|
||||
FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3);
|
||||
|
||||
bool operator==(const FunctionId& other) const;
|
||||
bool operator<(const FunctionId& other) const;
|
||||
bool operator==(const FunctionId &other) const;
|
||||
bool operator<(const FunctionId &other) const;
|
||||
|
||||
FunctionId getCopy() const;
|
||||
private:
|
||||
TOperator mOp;
|
||||
TType mParam1;
|
||||
TType mParam2;
|
||||
TType mParam3;
|
||||
|
||||
// The memory that these TType objects use is freed by PoolAllocator. The BuiltInFunctionEmulator's lifetime
|
||||
// can extend until after the memory pool is freed, but that's not an issue since this class never destructs
|
||||
// these objects.
|
||||
const TType *mParam1;
|
||||
const TType *mParam2;
|
||||
const TType *mParam3;
|
||||
};
|
||||
|
||||
bool SetFunctionCalled(const FunctionId& functionId);
|
||||
bool SetFunctionCalled(const FunctionId &functionId);
|
||||
|
||||
// Map from function id to emulated function definition
|
||||
std::map<FunctionId, std::string> mEmulatedFunctions;
|
||||
|
@ -7,9 +7,11 @@
|
||||
#include "angle_gl.h"
|
||||
#include "compiler/translator/BuiltInFunctionEmulator.h"
|
||||
#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
|
||||
#include "compiler/translator/Cache.h"
|
||||
#include "compiler/translator/SymbolTable.h"
|
||||
#include "compiler/translator/VersionGLSL.h"
|
||||
|
||||
void InitBuiltInFunctionEmulatorForGLSL(BuiltInFunctionEmulator *emu, sh::GLenum shaderType)
|
||||
void InitBuiltInFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, sh::GLenum shaderType)
|
||||
{
|
||||
// we use macros here instead of function definitions to work around more GLSL
|
||||
// compiler bugs, in particular on NVIDIA hardware on Mac OSX. Macros are
|
||||
@ -17,10 +19,10 @@ void InitBuiltInFunctionEmulatorForGLSL(BuiltInFunctionEmulator *emu, sh::GLenum
|
||||
// evaluated. This is unlikely to show up in real shaders, but is something to
|
||||
// consider.
|
||||
|
||||
TType float1(EbtFloat);
|
||||
TType float2(EbtFloat, 2);
|
||||
TType float3(EbtFloat, 3);
|
||||
TType float4(EbtFloat, 4);
|
||||
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);
|
||||
|
||||
if (shaderType == GL_FRAGMENT_SHADER)
|
||||
{
|
||||
@ -35,3 +37,153 @@ void InitBuiltInFunctionEmulatorForGLSL(BuiltInFunctionEmulator *emu, sh::GLenum
|
||||
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))");
|
||||
}
|
||||
|
||||
// Emulate built-in functions missing from GLSL 1.30 and higher
|
||||
void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator *emu, sh::GLenum shaderType,
|
||||
int targetGLSLVersion)
|
||||
{
|
||||
// Emulate packSnorm2x16, packHalf2x16, unpackSnorm2x16, and unpackHalf2x16 (GLSL 4.20)
|
||||
// by using floatBitsToInt, floatBitsToUint, intBitsToFloat, and uintBitsToFloat (GLSL 3.30).
|
||||
if (targetGLSLVersion >= GLSL_VERSION_330 && targetGLSLVersion < GLSL_VERSION_420)
|
||||
{
|
||||
const TType *float2 = TCache::getType(EbtFloat, 2);
|
||||
const TType *uint1 = TCache::getType(EbtUInt);
|
||||
|
||||
// clang-format off
|
||||
emu->addEmulatedFunction(EOpPackSnorm2x16, float2,
|
||||
"uint webgl_packSnorm2x16_emu(vec2 v)\n"
|
||||
"{\n"
|
||||
" #if defined(GL_ARB_shading_language_packing)\n"
|
||||
" return packSnorm2x16(v);\n"
|
||||
" #else\n"
|
||||
" int x = int(round(clamp(v.x, -1.0, 1.0) * 32767.0));\n"
|
||||
" int y = int(round(clamp(v.y, -1.0, 1.0) * 32767.0));\n"
|
||||
" return uint((y << 16) | (x & 0xFFFF));\n"
|
||||
" #endif\n"
|
||||
"}\n");
|
||||
emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1,
|
||||
"#if !defined(GL_ARB_shading_language_packing)\n"
|
||||
" float webgl_fromSnorm(uint x)\n"
|
||||
" {\n"
|
||||
" int xi = (int(x) & 0x7FFF) - (int(x) & 0x8000);\n"
|
||||
" return clamp(float(xi) / 32767.0, -1.0, 1.0);\n"
|
||||
" }\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"vec2 webgl_unpackSnorm2x16_emu(uint u)\n"
|
||||
"{\n"
|
||||
" #if defined(GL_ARB_shading_language_packing)\n"
|
||||
" return unpackSnorm2x16(u);\n"
|
||||
" #else\n"
|
||||
" uint y = (u >> 16);\n"
|
||||
" uint x = u;\n"
|
||||
" return vec2(webgl_fromSnorm(x), webgl_fromSnorm(y));\n"
|
||||
" #endif\n"
|
||||
"}\n");
|
||||
// Functions uint webgl_f32tof16(float val) and float webgl_f16tof32(uint val) are
|
||||
// based on the OpenGL redbook Appendix Session "Floating-Point Formats Used in OpenGL".
|
||||
emu->addEmulatedFunction(EOpPackHalf2x16, float2,
|
||||
"#if !defined(GL_ARB_shading_language_packing)\n"
|
||||
" uint webgl_f32tof16(float val)\n"
|
||||
" {\n"
|
||||
" uint f32 = floatBitsToUint(val);\n"
|
||||
" uint f16 = 0u;\n"
|
||||
" uint sign = (f32 >> 16) & 0x8000u;\n"
|
||||
" int exponent = int((f32 >> 23) & 0xFFu) - 127;\n"
|
||||
" uint mantissa = f32 & 0x007FFFFFu;\n"
|
||||
" if (exponent == 128)\n"
|
||||
" {\n"
|
||||
" // Infinity or NaN\n"
|
||||
" // NaN bits that are masked out by 0x3FF get discarded.\n"
|
||||
" // This can turn some NaNs to infinity, but this is allowed by the spec.\n"
|
||||
" f16 = sign | (0x1Fu << 10);\n"
|
||||
" f16 |= (mantissa & 0x3FFu);\n"
|
||||
" }\n"
|
||||
" else if (exponent > 15)\n"
|
||||
" {\n"
|
||||
" // Overflow - flush to Infinity\n"
|
||||
" f16 = sign | (0x1Fu << 10);\n"
|
||||
" }\n"
|
||||
" else if (exponent > -15)\n"
|
||||
" {\n"
|
||||
" // Representable value\n"
|
||||
" exponent += 15;\n"
|
||||
" mantissa >>= 13;\n"
|
||||
" f16 = sign | uint(exponent << 10) | mantissa;\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" f16 = sign;\n"
|
||||
" }\n"
|
||||
" return f16;\n"
|
||||
" }\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"uint webgl_packHalf2x16_emu(vec2 v)\n"
|
||||
"{\n"
|
||||
" #if defined(GL_ARB_shading_language_packing)\n"
|
||||
" return packHalf2x16(v);\n"
|
||||
" #else\n"
|
||||
" uint x = webgl_f32tof16(v.x);\n"
|
||||
" uint y = webgl_f32tof16(v.y);\n"
|
||||
" return (y << 16) | x;\n"
|
||||
" #endif\n"
|
||||
"}\n");
|
||||
emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1,
|
||||
"#if !defined(GL_ARB_shading_language_packing)\n"
|
||||
" float webgl_f16tof32(uint val)\n"
|
||||
" {\n"
|
||||
" uint sign = (val & 0x8000u) << 16;\n"
|
||||
" int exponent = int((val & 0x7C00u) >> 10);\n"
|
||||
" uint mantissa = val & 0x03FFu;\n"
|
||||
" float f32 = 0.0;\n"
|
||||
" if(exponent == 0)\n"
|
||||
" {\n"
|
||||
" if (mantissa != 0u)\n"
|
||||
" {\n"
|
||||
" const float scale = 1.0 / (1 << 24);\n"
|
||||
" f32 = scale * mantissa;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" else if (exponent == 31)\n"
|
||||
" {\n"
|
||||
" return uintBitsToFloat(sign | 0x7F800000u | mantissa);\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" exponent -= 15;\n"
|
||||
" float scale;\n"
|
||||
" if(exponent < 0)\n"
|
||||
" {\n"
|
||||
" scale = 1.0 / (1 << -exponent);\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" scale = 1 << exponent;\n"
|
||||
" }\n"
|
||||
" float decimal = 1.0 + float(mantissa) / float(1 << 10);\n"
|
||||
" f32 = scale * decimal;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" if (sign != 0u)\n"
|
||||
" {\n"
|
||||
" f32 = -f32;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" return f32;\n"
|
||||
" }\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"vec2 webgl_unpackHalf2x16_emu(uint u)\n"
|
||||
"{\n"
|
||||
" #if defined(GL_ARB_shading_language_packing)\n"
|
||||
" return unpackHalf2x16(u);\n"
|
||||
" #else\n"
|
||||
" uint y = (u >> 16);\n"
|
||||
" uint x = u & 0xFFFFu;\n"
|
||||
" return vec2(webgl_f16tof32(x), webgl_f16tof32(y));\n"
|
||||
" #endif\n"
|
||||
"}\n");
|
||||
// clang-format on
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,12 @@ class BuiltInFunctionEmulator;
|
||||
//
|
||||
// This is only a workaround for OpenGL driver bugs, and isn't needed in general.
|
||||
//
|
||||
void InitBuiltInFunctionEmulatorForGLSL(BuiltInFunctionEmulator *emu, sh::GLenum shaderType);
|
||||
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);
|
||||
|
||||
#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_
|
||||
|
@ -11,10 +11,10 @@
|
||||
|
||||
void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
|
||||
{
|
||||
TType float1(EbtFloat);
|
||||
TType float2(EbtFloat, 2);
|
||||
TType float3(EbtFloat, 3);
|
||||
TType float4(EbtFloat, 4);
|
||||
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(EOpMod, float1, float1,
|
||||
"float webgl_mod_emu(float x, float y)\n"
|
||||
@ -250,7 +250,7 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
|
||||
" return (y << 16) | x;\n"
|
||||
"}\n");
|
||||
|
||||
TType uint1(EbtUInt);
|
||||
TType *uint1 = new TType(EbtUInt);
|
||||
|
||||
emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1,
|
||||
"float webgl_fromSnorm(in uint x) {\n"
|
||||
@ -327,9 +327,9 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
|
||||
" return mul(float4x1(r), float1x3(c));\n"
|
||||
"}\n");
|
||||
|
||||
TType mat2(EbtFloat, 2, 2);
|
||||
TType mat3(EbtFloat, 3, 3);
|
||||
TType mat4(EbtFloat, 4, 4);
|
||||
TType *mat2 = new TType(EbtFloat, 2, 2);
|
||||
TType *mat3 = new TType(EbtFloat, 3, 3);
|
||||
TType *mat4 = new TType(EbtFloat, 4, 4);
|
||||
|
||||
// Remember here that the parameter matrix is actually the transpose
|
||||
// of the matrix that we're trying to invert, and the resulting matrix
|
||||
@ -407,4 +407,35 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
|
||||
" cof02, cof12, cof22, cof32, cof03, cof13, cof23, cof33 };\n"
|
||||
" return cof / determinant(transpose(m));\n"
|
||||
"}\n");
|
||||
|
||||
TType *bool1 = new TType(EbtBool);
|
||||
TType *bool2 = new TType(EbtBool, 2);
|
||||
TType *bool3 = new TType(EbtBool, 3);
|
||||
TType *bool4 = new TType(EbtBool, 4);
|
||||
|
||||
// Emulate ESSL3 variant of mix that takes last argument as boolean vector.
|
||||
// genType mix (genType x, genType y, genBType a): Selects which vector each returned component comes from.
|
||||
// For a component of 'a' that is false, the corresponding component of 'x' is returned.For a component of 'a' that is true,
|
||||
// the corresponding component of 'y' is returned.
|
||||
emu->addEmulatedFunction(EOpMix, float1, float1, bool1,
|
||||
"float webgl_mix_emu(float x, float y, bool a)\n"
|
||||
"{\n"
|
||||
" return a ? y : x;\n"
|
||||
"}\n");
|
||||
emu->addEmulatedFunction(EOpMix, float2, float2, bool2,
|
||||
"float2 webgl_mix_emu(float2 x, float2 y, bool2 a)\n"
|
||||
"{\n"
|
||||
" return a ? y : x;\n"
|
||||
"}\n");
|
||||
emu->addEmulatedFunction(EOpMix, float3, float3, bool3,
|
||||
"float3 webgl_mix_emu(float3 x, float3 y, bool3 a)\n"
|
||||
"{\n"
|
||||
" return a ? y : x;\n"
|
||||
"}\n");
|
||||
emu->addEmulatedFunction(EOpMix, float4, float4, bool4,
|
||||
"float4 webgl_mix_emu(float4 x, float4 y, bool4 a)\n"
|
||||
"{\n"
|
||||
" return a ? y : x;\n"
|
||||
"}\n");
|
||||
|
||||
}
|
||||
|
100
src/3rdparty/angle/src/compiler/translator/Cache.cpp
vendored
Normal file
100
src/3rdparty/angle/src/compiler/translator/Cache.cpp
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
//
|
||||
// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
||||
// Cache.cpp: Implements a cache for various commonly created objects.
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "common/angleutils.h"
|
||||
#include "common/debug.h"
|
||||
#include "compiler/translator/Cache.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class TScopedAllocator : angle::NonCopyable
|
||||
{
|
||||
public:
|
||||
TScopedAllocator(TPoolAllocator *allocator)
|
||||
: mPreviousAllocator(GetGlobalPoolAllocator())
|
||||
{
|
||||
SetGlobalPoolAllocator(allocator);
|
||||
}
|
||||
~TScopedAllocator()
|
||||
{
|
||||
SetGlobalPoolAllocator(mPreviousAllocator);
|
||||
}
|
||||
|
||||
private:
|
||||
TPoolAllocator *mPreviousAllocator;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TCache::TypeKey::TypeKey(TBasicType basicType,
|
||||
TPrecision precision,
|
||||
TQualifier qualifier,
|
||||
unsigned char primarySize,
|
||||
unsigned char secondarySize)
|
||||
{
|
||||
static_assert(sizeof(components) <= sizeof(value),
|
||||
"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 &&
|
||||
MaxEnumValue >= EbpLast &&
|
||||
MaxEnumValue >= EvqLast &&
|
||||
"TypeKey::EnumComponentType is too small");
|
||||
|
||||
value = 0;
|
||||
components.basicType = static_cast<EnumComponentType>(basicType);
|
||||
components.precision = static_cast<EnumComponentType>(precision);
|
||||
components.qualifier = static_cast<EnumComponentType>(qualifier);
|
||||
components.primarySize = primarySize;
|
||||
components.secondarySize = secondarySize;
|
||||
}
|
||||
|
||||
TCache *TCache::sCache = nullptr;
|
||||
|
||||
void TCache::initialize()
|
||||
{
|
||||
if (sCache == nullptr)
|
||||
{
|
||||
sCache = new TCache();
|
||||
}
|
||||
}
|
||||
|
||||
void TCache::destroy()
|
||||
{
|
||||
SafeDelete(sCache);
|
||||
}
|
||||
|
||||
const TType *TCache::getType(TBasicType basicType,
|
||||
TPrecision precision,
|
||||
TQualifier qualifier,
|
||||
unsigned char primarySize,
|
||||
unsigned char secondarySize)
|
||||
{
|
||||
TypeKey key(basicType, precision, qualifier,
|
||||
primarySize, secondarySize);
|
||||
auto it = sCache->mTypes.find(key);
|
||||
if (it != sCache->mTypes.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
TScopedAllocator scopedAllocator(&sCache->mAllocator);
|
||||
|
||||
TType *type = new TType(basicType, precision, qualifier,
|
||||
primarySize, secondarySize);
|
||||
type->realize();
|
||||
sCache->mTypes.insert(std::make_pair(key, type));
|
||||
|
||||
return type;
|
||||
}
|
90
src/3rdparty/angle/src/compiler/translator/Cache.h
vendored
Normal file
90
src/3rdparty/angle/src/compiler/translator/Cache.h
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
//
|
||||
// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
||||
// Cache.h: Implements a cache for various commonly created objects.
|
||||
|
||||
#ifndef COMPILER_TRANSLATOR_CACHE_H_
|
||||
#define COMPILER_TRANSLATOR_CACHE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <map>
|
||||
|
||||
#include "compiler/translator/Types.h"
|
||||
#include "compiler/translator/PoolAlloc.h"
|
||||
|
||||
class TCache
|
||||
{
|
||||
public:
|
||||
|
||||
static void initialize();
|
||||
static void destroy();
|
||||
|
||||
static const TType *getType(TBasicType basicType,
|
||||
TPrecision precision)
|
||||
{
|
||||
return getType(basicType, precision, EvqTemporary,
|
||||
1, 1);
|
||||
}
|
||||
static const TType *getType(TBasicType basicType,
|
||||
unsigned char primarySize = 1,
|
||||
unsigned char secondarySize = 1)
|
||||
{
|
||||
return getType(basicType, EbpUndefined, EvqGlobal,
|
||||
primarySize, secondarySize);
|
||||
}
|
||||
static const TType *getType(TBasicType basicType,
|
||||
TQualifier qualifier,
|
||||
unsigned char primarySize = 1,
|
||||
unsigned char secondarySize = 1)
|
||||
{
|
||||
return getType(basicType, EbpUndefined, qualifier,
|
||||
primarySize, secondarySize);
|
||||
}
|
||||
static const TType *getType(TBasicType basicType,
|
||||
TPrecision precision,
|
||||
TQualifier qualifier,
|
||||
unsigned char primarySize,
|
||||
unsigned char secondarySize);
|
||||
|
||||
private:
|
||||
TCache()
|
||||
{
|
||||
}
|
||||
|
||||
union TypeKey
|
||||
{
|
||||
TypeKey(TBasicType basicType,
|
||||
TPrecision precision,
|
||||
TQualifier qualifier,
|
||||
unsigned char primarySize,
|
||||
unsigned char secondarySize);
|
||||
|
||||
typedef uint8_t EnumComponentType;
|
||||
struct
|
||||
{
|
||||
EnumComponentType basicType;
|
||||
EnumComponentType precision;
|
||||
EnumComponentType qualifier;
|
||||
unsigned char primarySize;
|
||||
unsigned char secondarySize;
|
||||
} components;
|
||||
uint64_t value;
|
||||
|
||||
bool operator < (const TypeKey &other) const
|
||||
{
|
||||
return value < other.value;
|
||||
}
|
||||
};
|
||||
typedef std::map<TypeKey, const TType*> TypeMap;
|
||||
|
||||
TypeMap mTypes;
|
||||
TPoolAllocator mAllocator;
|
||||
|
||||
static TCache *sCache;
|
||||
};
|
||||
|
||||
#endif // COMPILER_TRANSLATOR_CACHE_H_
|
293
src/3rdparty/angle/src/compiler/translator/CallDAG.cpp
vendored
Normal file
293
src/3rdparty/angle/src/compiler/translator/CallDAG.cpp
vendored
Normal file
@ -0,0 +1,293 @@
|
||||
//
|
||||
// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
||||
// CallDAG.h: Implements a call graph DAG of functions to be re-used accross
|
||||
// analyses, allows to efficiently traverse the functions in topological
|
||||
// order.
|
||||
|
||||
#include "compiler/translator/CallDAG.h"
|
||||
#include "compiler/translator/InfoSink.h"
|
||||
|
||||
// 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
|
||||
{
|
||||
public:
|
||||
CallDAGCreator(TInfoSinkBase *info)
|
||||
: TIntermTraverser(true, false, true),
|
||||
mCreationInfo(info),
|
||||
mCurrentFunction(nullptr),
|
||||
mCurrentIndex(0)
|
||||
{
|
||||
}
|
||||
|
||||
InitResult assignIndices()
|
||||
{
|
||||
int skipped = 0;
|
||||
for (auto &it : mFunctions)
|
||||
{
|
||||
// Skip unimplemented functions
|
||||
if (it.second.node)
|
||||
{
|
||||
InitResult result = assignIndicesInternal(&it.second);
|
||||
if (result != INITDAG_SUCCESS)
|
||||
{
|
||||
*mCreationInfo << "\n";
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
skipped++;
|
||||
}
|
||||
}
|
||||
ASSERT(mFunctions.size() == mCurrentIndex + skipped);
|
||||
return INITDAG_SUCCESS;
|
||||
}
|
||||
|
||||
void fillDataStructures(std::vector<Record> *records, std::map<int, int> *idToIndex)
|
||||
{
|
||||
ASSERT(records->empty());
|
||||
ASSERT(idToIndex->empty());
|
||||
|
||||
records->resize(mCurrentIndex);
|
||||
|
||||
for (auto &it : mFunctions)
|
||||
{
|
||||
CreatorFunctionData &data = it.second;
|
||||
// Skip unimplemented functions
|
||||
if (!data.node)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ASSERT(data.index < records->size());
|
||||
Record &record = (*records)[data.index];
|
||||
|
||||
record.name = data.name.data();
|
||||
record.node = data.node;
|
||||
|
||||
record.callees.reserve(data.callees.size());
|
||||
for (auto &callee : data.callees)
|
||||
{
|
||||
record.callees.push_back(static_cast<int>(callee->index));
|
||||
}
|
||||
|
||||
(*idToIndex)[data.node->getFunctionId()] = static_cast<int>(data.index);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
struct CreatorFunctionData
|
||||
{
|
||||
CreatorFunctionData()
|
||||
: node(nullptr),
|
||||
index(0),
|
||||
indexAssigned(false),
|
||||
visiting(false)
|
||||
{
|
||||
}
|
||||
|
||||
std::set<CreatorFunctionData*> callees;
|
||||
TIntermAggregate *node;
|
||||
TString name;
|
||||
size_t index;
|
||||
bool indexAssigned;
|
||||
bool visiting;
|
||||
};
|
||||
|
||||
// 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
|
||||
{
|
||||
switch (node->getOp())
|
||||
{
|
||||
case EOpPrototype:
|
||||
if (visit == PreVisit)
|
||||
{
|
||||
// Function declaration, create an empty record.
|
||||
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
|
||||
if (visit == PreVisit)
|
||||
{
|
||||
// Do not handle calls to builtin functions
|
||||
if (node->isUserDefined())
|
||||
{
|
||||
auto it = mFunctions.find(node->getName());
|
||||
ASSERT(it != mFunctions.end());
|
||||
|
||||
// We might be in a top-level function call to set a global variable
|
||||
if (mCurrentFunction)
|
||||
{
|
||||
mCurrentFunction->callees.insert(&it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Recursively assigns indices to a sub DAG
|
||||
InitResult assignIndicesInternal(CreatorFunctionData *function)
|
||||
{
|
||||
ASSERT(function);
|
||||
|
||||
if (!function->node)
|
||||
{
|
||||
*mCreationInfo << "Undefined function '" << function->name
|
||||
<< ")' used in the following call chain:";
|
||||
return INITDAG_UNDEFINED;
|
||||
}
|
||||
|
||||
if (function->indexAssigned)
|
||||
{
|
||||
return INITDAG_SUCCESS;
|
||||
}
|
||||
|
||||
if (function->visiting)
|
||||
{
|
||||
if (mCreationInfo)
|
||||
{
|
||||
*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)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
*mCreationInfo << " <- " << function->name << ")";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
function->index = mCurrentIndex++;
|
||||
function->indexAssigned = true;
|
||||
|
||||
function->visiting = false;
|
||||
return INITDAG_SUCCESS;
|
||||
}
|
||||
|
||||
TInfoSinkBase *mCreationInfo;
|
||||
|
||||
std::map<TString, CreatorFunctionData> mFunctions;
|
||||
CreatorFunctionData *mCurrentFunction;
|
||||
size_t mCurrentIndex;
|
||||
};
|
||||
|
||||
// CallDAG
|
||||
|
||||
CallDAG::CallDAG()
|
||||
{
|
||||
}
|
||||
|
||||
CallDAG::~CallDAG()
|
||||
{
|
||||
}
|
||||
|
||||
const size_t CallDAG::InvalidIndex = std::numeric_limits<size_t>::max();
|
||||
|
||||
size_t CallDAG::findIndex(const TIntermAggregate *function) const
|
||||
{
|
||||
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())
|
||||
{
|
||||
return InvalidIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
const CallDAG::Record &CallDAG::getRecordFromIndex(size_t index) const
|
||||
{
|
||||
ASSERT(index != InvalidIndex && index < mRecords.size());
|
||||
return mRecords[index];
|
||||
}
|
||||
|
||||
const CallDAG::Record &CallDAG::getRecord(const TIntermAggregate *function) const
|
||||
{
|
||||
size_t index = findIndex(function);
|
||||
ASSERT(index != InvalidIndex && index < mRecords.size());
|
||||
return mRecords[index];
|
||||
}
|
||||
|
||||
size_t CallDAG::size() const
|
||||
{
|
||||
return mRecords.size();
|
||||
}
|
||||
|
||||
void CallDAG::clear()
|
||||
{
|
||||
mRecords.clear();
|
||||
mFunctionIdToIndex.clear();
|
||||
}
|
||||
|
||||
CallDAG::InitResult CallDAG::init(TIntermNode *root, TInfoSinkBase *info)
|
||||
{
|
||||
CallDAGCreator creator(info);
|
||||
|
||||
// Creates the mapping of functions to callees
|
||||
root->traverse(&creator);
|
||||
|
||||
// Does the topological sort and detects recursions
|
||||
InitResult result = creator.assignIndices();
|
||||
if (result != INITDAG_SUCCESS)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
creator.fillDataStructures(&mRecords, &mFunctionIdToIndex);
|
||||
return INITDAG_SUCCESS;
|
||||
}
|
75
src/3rdparty/angle/src/compiler/translator/CallDAG.h
vendored
Normal file
75
src/3rdparty/angle/src/compiler/translator/CallDAG.h
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
//
|
||||
// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
||||
// CallDAG.h: Defines a call graph DAG of functions to be re-used accross
|
||||
// analyses, allows to efficiently traverse the functions in topological
|
||||
// order.
|
||||
|
||||
#ifndef COMPILER_TRANSLATOR_CALLDAG_H_
|
||||
#define COMPILER_TRANSLATOR_CALLDAG_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "compiler/translator/IntermNode.h"
|
||||
#include "compiler/translator/VariableInfo.h"
|
||||
|
||||
|
||||
// The translator needs to analyze the the graph of the function calls
|
||||
// to run checks and analyses; since in GLSL recursion is not allowed
|
||||
// that graph is a DAG.
|
||||
// This class is used to precompute that function call DAG so that it
|
||||
// can be reused by multiple analyses.
|
||||
//
|
||||
// It stores a vector of function records, with one record per function.
|
||||
// Records are accessed by index but a mangled function name can be converted
|
||||
// to the index of the corresponding record. The records mostly contain the
|
||||
// AST node of the function and the indices of the function's callees.
|
||||
//
|
||||
// In addition, records are in reverse topological order: a function F being
|
||||
// called by a function G will have index index(F) < index(G), that way
|
||||
// depth-first analysis becomes analysis in the order of indices.
|
||||
|
||||
class CallDAG : angle::NonCopyable
|
||||
{
|
||||
public:
|
||||
CallDAG();
|
||||
~CallDAG();
|
||||
|
||||
struct Record
|
||||
{
|
||||
std::string name;
|
||||
TIntermAggregate *node;
|
||||
std::vector<int> callees;
|
||||
};
|
||||
|
||||
enum InitResult
|
||||
{
|
||||
INITDAG_SUCCESS,
|
||||
INITDAG_RECURSION,
|
||||
INITDAG_UNDEFINED,
|
||||
};
|
||||
|
||||
// Returns INITDAG_SUCCESS if it was able to create the DAG, otherwise prints
|
||||
// the initialization error in info, if present.
|
||||
InitResult init(TIntermNode *root, TInfoSinkBase *info);
|
||||
|
||||
// Returns InvalidIndex if the function wasn't found
|
||||
size_t findIndex(const TIntermAggregate *function) const;
|
||||
|
||||
const Record &getRecordFromIndex(size_t index) const;
|
||||
const Record &getRecord(const TIntermAggregate *function) const;
|
||||
size_t size() const;
|
||||
void clear();
|
||||
|
||||
const static size_t InvalidIndex;
|
||||
private:
|
||||
std::vector<Record> mRecords;
|
||||
std::map<int, int> mFunctionIdToIndex;
|
||||
|
||||
class CallDAGCreator;
|
||||
};
|
||||
|
||||
#endif // COMPILER_TRANSLATOR_CALLDAG_H_
|
@ -4,8 +4,14 @@
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
||||
#ifdef ANGLE_ENABLE_ESSL
|
||||
#include "compiler/translator/TranslatorESSL.h"
|
||||
#endif
|
||||
|
||||
#ifdef ANGLE_ENABLE_GLSL
|
||||
#include "compiler/translator/TranslatorGLSL.h"
|
||||
#endif
|
||||
|
||||
#ifdef ANGLE_ENABLE_HLSL
|
||||
#include "compiler/translator/TranslatorHLSL.h"
|
||||
#endif // ANGLE_ENABLE_HLSL
|
||||
@ -20,22 +26,44 @@ TCompiler* ConstructCompiler(
|
||||
{
|
||||
switch (output) {
|
||||
case SH_ESSL_OUTPUT:
|
||||
#ifdef ANGLE_ENABLE_ESSL
|
||||
return new TranslatorESSL(type, spec);
|
||||
case SH_GLSL_CORE_OUTPUT:
|
||||
#else
|
||||
// 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);
|
||||
case SH_HLSL9_OUTPUT:
|
||||
case SH_HLSL11_OUTPUT:
|
||||
#else
|
||||
// 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);
|
||||
#else
|
||||
// This compiler is not supported in this
|
||||
// configuration. Return NULL per the ShConstructCompiler API.
|
||||
return NULL;
|
||||
return nullptr;
|
||||
#endif // ANGLE_ENABLE_HLSL
|
||||
default:
|
||||
// Unknown format. Return NULL per the ShConstructCompiler API.
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,9 +14,9 @@
|
||||
#include <limits>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "compiler/translator/PoolAlloc.h"
|
||||
#include "compiler/translator/compilerdebug.h"
|
||||
#include "common/angleutils.h"
|
||||
#include "common/debug.h"
|
||||
#include "compiler/translator/PoolAlloc.h"
|
||||
|
||||
struct TSourceLoc {
|
||||
int first_file;
|
||||
@ -60,18 +60,21 @@ inline TString* NewPoolTString(const char* s)
|
||||
//
|
||||
// Pool allocator versions of vectors, lists, and maps
|
||||
//
|
||||
template <class T> class TVector : public std::vector<T, pool_allocator<T> > {
|
||||
public:
|
||||
typedef typename std::vector<T, pool_allocator<T> >::size_type size_type;
|
||||
TVector() : std::vector<T, pool_allocator<T> >() {}
|
||||
TVector(const pool_allocator<T>& a) : std::vector<T, pool_allocator<T> >(a) {}
|
||||
TVector(size_type i): std::vector<T, pool_allocator<T> >(i) {}
|
||||
template <class T>
|
||||
class TVector : public std::vector<T, pool_allocator<T>>
|
||||
{
|
||||
public:
|
||||
typedef typename std::vector<T, pool_allocator<T>>::size_type size_type;
|
||||
TVector() : std::vector<T, pool_allocator<T>>() {}
|
||||
TVector(const pool_allocator<T> &a) : std::vector<T, pool_allocator<T>>(a) {}
|
||||
TVector(size_type i) : std::vector<T, pool_allocator<T>>(i) {}
|
||||
};
|
||||
|
||||
template <class K, class D, class CMP = std::less<K> >
|
||||
class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<const K, D> > > {
|
||||
public:
|
||||
typedef pool_allocator<std::pair<const K, D> > tAllocator;
|
||||
template <class K, class D, class CMP = std::less<K>>
|
||||
class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<const K, D>>>
|
||||
{
|
||||
public:
|
||||
typedef pool_allocator<std::pair<const K, D>> tAllocator;
|
||||
|
||||
TMap() : std::map<K, D, CMP, tAllocator>() {}
|
||||
// use correct two-stage name lookup supported in gcc 3.4 and above
|
||||
|
@ -4,15 +4,19 @@
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
||||
#include "compiler/translator/Cache.h"
|
||||
#include "compiler/translator/Compiler.h"
|
||||
#include "compiler/translator/DetectCallDepth.h"
|
||||
#include "compiler/translator/CallDAG.h"
|
||||
#include "compiler/translator/ForLoopUnroll.h"
|
||||
#include "compiler/translator/Initialize.h"
|
||||
#include "compiler/translator/InitializeParseContext.h"
|
||||
#include "compiler/translator/InitializeVariables.h"
|
||||
#include "compiler/translator/ParseContext.h"
|
||||
#include "compiler/translator/PruneEmptyDeclarations.h"
|
||||
#include "compiler/translator/RegenerateStructNames.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/ValidateLimitations.h"
|
||||
@ -33,6 +37,20 @@ bool IsWebGLBasedSpec(ShShaderSpec spec)
|
||||
spec == SH_WEBGL2_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);
|
||||
}
|
||||
|
||||
size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
|
||||
{
|
||||
// WebGL defines a max token legnth of 256, while ES2 leaves max token
|
||||
@ -126,7 +144,8 @@ TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
|
||||
fragmentPrecisionHigh(false),
|
||||
clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
|
||||
builtInFunctionEmulator(),
|
||||
mSourcePath(NULL)
|
||||
mSourcePath(NULL),
|
||||
mTemporaryIndex(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -134,6 +153,15 @@ TCompiler::~TCompiler()
|
||||
{
|
||||
}
|
||||
|
||||
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
|
||||
// of ESSL 1.00 as in Appendix A of the spec).
|
||||
return (IsWebGLBasedSpec(shaderSpec) && shaderVersion == 100) ||
|
||||
(compileOptions & SH_VALIDATE_LOOP_INDEXING);
|
||||
}
|
||||
|
||||
bool TCompiler::Init(const ShBuiltInResources& resources)
|
||||
{
|
||||
shaderVersion = 100;
|
||||
@ -165,8 +193,9 @@ TIntermNode *TCompiler::compileTreeForTesting(const char* const shaderStrings[],
|
||||
return compileTreeImpl(shaderStrings, numStrings, compileOptions);
|
||||
}
|
||||
|
||||
TIntermNode *TCompiler::compileTreeImpl(const char* const shaderStrings[],
|
||||
size_t numStrings, int compileOptions)
|
||||
TIntermNode *TCompiler::compileTreeImpl(const char *const shaderStrings[],
|
||||
size_t numStrings,
|
||||
const int compileOptions)
|
||||
{
|
||||
clearResults();
|
||||
|
||||
@ -176,10 +205,6 @@ TIntermNode *TCompiler::compileTreeImpl(const char* const shaderStrings[],
|
||||
// Reset the extension behavior for each compilation unit.
|
||||
ResetExtensionBehavior(extensionBehavior);
|
||||
|
||||
// If compiling for WebGL, validate loop and indexing as well.
|
||||
if (IsWebGLBasedSpec(shaderSpec))
|
||||
compileOptions |= SH_VALIDATE_LOOP_INDEXING;
|
||||
|
||||
// First string is path of source file if flag is set. The actual source follows.
|
||||
size_t firstSource = 0;
|
||||
if (compileOptions & SH_SOURCE_PATH)
|
||||
@ -188,13 +213,11 @@ TIntermNode *TCompiler::compileTreeImpl(const char* const shaderStrings[],
|
||||
++firstSource;
|
||||
}
|
||||
|
||||
bool debugShaderPrecision = getResources().WEBGL_debug_shader_precision == 1;
|
||||
TIntermediate intermediate(infoSink);
|
||||
TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
|
||||
shaderType, shaderSpec, compileOptions, true,
|
||||
infoSink, debugShaderPrecision);
|
||||
TParseContext parseContext(symbolTable, extensionBehavior, intermediate, shaderType, shaderSpec,
|
||||
compileOptions, true, infoSink, getResources());
|
||||
|
||||
parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh;
|
||||
parseContext.setFragmentPrecisionHighOnESSL1(fragmentPrecisionHigh);
|
||||
SetGlobalParseContext(&parseContext);
|
||||
|
||||
// We preserve symbols at the built-in level from compile-to-compile.
|
||||
@ -203,8 +226,8 @@ TIntermNode *TCompiler::compileTreeImpl(const char* const shaderStrings[],
|
||||
|
||||
// Parse shader.
|
||||
bool success =
|
||||
(PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], NULL, &parseContext) == 0) &&
|
||||
(parseContext.treeRoot != NULL);
|
||||
(PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr, &parseContext) == 0) &&
|
||||
(parseContext.getTreeRoot() != nullptr);
|
||||
|
||||
shaderVersion = parseContext.getShaderVersion();
|
||||
if (success && MapSpecToShaderVersion(shaderSpec) < shaderVersion)
|
||||
@ -214,7 +237,7 @@ TIntermNode *TCompiler::compileTreeImpl(const char* const shaderStrings[],
|
||||
success = false;
|
||||
}
|
||||
|
||||
TIntermNode *root = NULL;
|
||||
TIntermNode *root = nullptr;
|
||||
|
||||
if (success)
|
||||
{
|
||||
@ -224,20 +247,42 @@ TIntermNode *TCompiler::compileTreeImpl(const char* const shaderStrings[],
|
||||
symbolTable.setGlobalInvariant();
|
||||
}
|
||||
|
||||
root = parseContext.treeRoot;
|
||||
success = intermediate.postProcess(root);
|
||||
root = parseContext.getTreeRoot();
|
||||
root = intermediate.postProcess(root);
|
||||
|
||||
// Highp might have been auto-enabled based on shader version
|
||||
fragmentPrecisionHigh = parseContext.getFragmentPrecisionHigh();
|
||||
|
||||
// Disallow expressions deemed too complex.
|
||||
if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY))
|
||||
success = limitExpressionComplexity(root);
|
||||
|
||||
// Create the function DAG and check there is no recursion
|
||||
if (success)
|
||||
success = detectCallDepth(root, infoSink, (compileOptions & SH_LIMIT_CALL_STACK_DEPTH) != 0);
|
||||
success = initCallDag(root);
|
||||
|
||||
if (success && (compileOptions & SH_LIMIT_CALL_STACK_DEPTH))
|
||||
success = checkCallDepth();
|
||||
|
||||
// Checks which functions are used and if "main" exists
|
||||
if (success)
|
||||
{
|
||||
functionMetadata.clear();
|
||||
functionMetadata.resize(mCallDag.size());
|
||||
success = tagUsedFunctions();
|
||||
}
|
||||
|
||||
if (success && !(compileOptions & SH_DONT_PRUNE_UNUSED_FUNCTIONS))
|
||||
success = pruneUnusedFunctions(root);
|
||||
|
||||
// Prune empty declarations to work around driver bugs and to keep declaration output simple.
|
||||
if (success)
|
||||
PruneEmptyDeclarations(root);
|
||||
|
||||
if (success && shaderVersion == 300 && shaderType == GL_FRAGMENT_SHADER)
|
||||
success = validateOutputs(root);
|
||||
|
||||
if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
|
||||
if (success && shouldRunLoopAndIndexingValidation(compileOptions))
|
||||
success = validateLimitations(root);
|
||||
|
||||
if (success && (compileOptions & SH_TIMING_RESTRICTIONS))
|
||||
@ -249,12 +294,14 @@ TIntermNode *TCompiler::compileTreeImpl(const char* const shaderStrings[],
|
||||
// Unroll for-loop markup needs to happen after validateLimitations pass.
|
||||
if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX))
|
||||
{
|
||||
ForLoopUnrollMarker marker(ForLoopUnrollMarker::kIntegerIndex);
|
||||
ForLoopUnrollMarker marker(ForLoopUnrollMarker::kIntegerIndex,
|
||||
shouldRunLoopAndIndexingValidation(compileOptions));
|
||||
root->traverse(&marker);
|
||||
}
|
||||
if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX))
|
||||
{
|
||||
ForLoopUnrollMarker marker(ForLoopUnrollMarker::kSamplerArrayIndex);
|
||||
ForLoopUnrollMarker marker(ForLoopUnrollMarker::kSamplerArrayIndex,
|
||||
shouldRunLoopAndIndexingValidation(compileOptions));
|
||||
root->traverse(&marker);
|
||||
if (marker.samplerArrayIndexIsFloatLoopIndex())
|
||||
{
|
||||
@ -275,9 +322,16 @@ TIntermNode *TCompiler::compileTreeImpl(const char* const shaderStrings[],
|
||||
if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
|
||||
arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
|
||||
|
||||
if (success && shaderType == GL_VERTEX_SHADER && (compileOptions & SH_INIT_GL_POSITION))
|
||||
// gl_Position is always written in compatibility output mode
|
||||
if (success && shaderType == GL_VERTEX_SHADER &&
|
||||
((compileOptions & SH_INIT_GL_POSITION) ||
|
||||
(outputType == SH_GLSL_COMPATIBILITY_OUTPUT)))
|
||||
initializeGLPosition(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_UNFOLD_SHORT_CIRCUIT))
|
||||
{
|
||||
UnfoldShortCircuitAST unfoldShortCircuit;
|
||||
@ -285,7 +339,12 @@ TIntermNode *TCompiler::compileTreeImpl(const char* const shaderStrings[],
|
||||
unfoldShortCircuit.updateTree();
|
||||
}
|
||||
|
||||
if (success && (compileOptions & SH_VARIABLES))
|
||||
if (success && (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT))
|
||||
{
|
||||
RemovePow(root);
|
||||
}
|
||||
|
||||
if (success && shouldCollectVariables(compileOptions))
|
||||
{
|
||||
collectVariables(root);
|
||||
if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS)
|
||||
@ -369,11 +428,6 @@ bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
|
||||
floatingPoint.secondarySize = 1;
|
||||
floatingPoint.array = false;
|
||||
|
||||
TPublicType sampler;
|
||||
sampler.primarySize = 1;
|
||||
sampler.secondarySize = 1;
|
||||
sampler.array = false;
|
||||
|
||||
switch(shaderType)
|
||||
{
|
||||
case GL_FRAGMENT_SHADER:
|
||||
@ -386,14 +440,15 @@ bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
|
||||
default:
|
||||
assert(false && "Language not supported");
|
||||
}
|
||||
// We set defaults for all the sampler types, even those that are
|
||||
// Set defaults for sampler types that have default precision, even those that are
|
||||
// only available if an extension exists.
|
||||
for (int samplerType = EbtGuardSamplerBegin + 1;
|
||||
samplerType < EbtGuardSamplerEnd; ++samplerType)
|
||||
{
|
||||
sampler.type = static_cast<TBasicType>(samplerType);
|
||||
symbolTable.setDefaultPrecision(sampler, EbpLow);
|
||||
}
|
||||
// New sampler types in ESSL3 don't have default precision. ESSL1 types do.
|
||||
initSamplerDefaultPrecision(EbtSampler2D);
|
||||
initSamplerDefaultPrecision(EbtSamplerCube);
|
||||
// SamplerExternalOES is specified in the extension to have default precision.
|
||||
initSamplerDefaultPrecision(EbtSamplerExternalOES);
|
||||
// It isn't specified whether Sampler2DRect has default precision.
|
||||
initSamplerDefaultPrecision(EbtSampler2DRect);
|
||||
|
||||
InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable);
|
||||
|
||||
@ -402,6 +457,17 @@ bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
|
||||
return true;
|
||||
}
|
||||
|
||||
void TCompiler::initSamplerDefaultPrecision(TBasicType samplerType)
|
||||
{
|
||||
ASSERT(samplerType > EbtGuardSamplerBegin && samplerType < EbtGuardSamplerEnd);
|
||||
TPublicType sampler;
|
||||
sampler.primarySize = 1;
|
||||
sampler.secondarySize = 1;
|
||||
sampler.array = false;
|
||||
sampler.type = samplerType;
|
||||
symbolTable.setDefaultPrecision(sampler, EbpLow);
|
||||
}
|
||||
|
||||
void TCompiler::setResourceString()
|
||||
{
|
||||
std::ostringstream strstream;
|
||||
@ -420,6 +486,7 @@ void TCompiler::setResourceString()
|
||||
<< ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh
|
||||
<< ":MaxExpressionComplexity:" << compileResources.MaxExpressionComplexity
|
||||
<< ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth
|
||||
<< ":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
|
||||
@ -429,6 +496,7 @@ void TCompiler::setResourceString()
|
||||
<< ":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;
|
||||
|
||||
@ -454,39 +522,175 @@ void TCompiler::clearResults()
|
||||
nameMap.clear();
|
||||
|
||||
mSourcePath = NULL;
|
||||
mTemporaryIndex = 0;
|
||||
}
|
||||
|
||||
bool TCompiler::detectCallDepth(TIntermNode* inputRoot, TInfoSink& inputInfoSink, bool limitCallStackDepth)
|
||||
bool TCompiler::initCallDag(TIntermNode *root)
|
||||
{
|
||||
DetectCallDepth detect(inputInfoSink, limitCallStackDepth, maxCallStackDepth);
|
||||
inputRoot->traverse(&detect);
|
||||
switch (detect.detectCallDepth())
|
||||
mCallDag.clear();
|
||||
|
||||
switch (mCallDag.init(root, &infoSink.info))
|
||||
{
|
||||
case DetectCallDepth::kErrorNone:
|
||||
case CallDAG::INITDAG_SUCCESS:
|
||||
return true;
|
||||
case DetectCallDepth::kErrorMissingMain:
|
||||
inputInfoSink.info.prefix(EPrefixError);
|
||||
inputInfoSink.info << "Missing main()";
|
||||
case CallDAG::INITDAG_RECURSION:
|
||||
infoSink.info.prefix(EPrefixError);
|
||||
infoSink.info << "Function recursion detected";
|
||||
return false;
|
||||
case DetectCallDepth::kErrorRecursion:
|
||||
inputInfoSink.info.prefix(EPrefixError);
|
||||
inputInfoSink.info << "Function recursion detected";
|
||||
return false;
|
||||
case DetectCallDepth::kErrorMaxDepthExceeded:
|
||||
inputInfoSink.info.prefix(EPrefixError);
|
||||
inputInfoSink.info << "Function call stack too deep";
|
||||
return false;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
case CallDAG::INITDAG_UNDEFINED:
|
||||
infoSink.info.prefix(EPrefixError);
|
||||
infoSink.info << "Unimplemented function detected";
|
||||
return false;
|
||||
}
|
||||
|
||||
UNREACHABLE();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TCompiler::checkCallDepth()
|
||||
{
|
||||
std::vector<int> depths(mCallDag.size());
|
||||
|
||||
for (size_t i = 0; i < mCallDag.size(); i++)
|
||||
{
|
||||
int depth = 0;
|
||||
auto &record = mCallDag.getRecordFromIndex(i);
|
||||
|
||||
for (auto &calleeIndex : record.callees)
|
||||
{
|
||||
depth = std::max(depth, depths[calleeIndex] + 1);
|
||||
}
|
||||
|
||||
depths[i] = depth;
|
||||
|
||||
if (depth >= maxCallStackDepth)
|
||||
{
|
||||
// Trace back the function chain to have a meaningful info log.
|
||||
infoSink.info.prefix(EPrefixError);
|
||||
infoSink.info << "Call stack too deep (larger than " << maxCallStackDepth
|
||||
<< ") with the following call chain: " << record.name;
|
||||
|
||||
int currentFunction = static_cast<int>(i);
|
||||
int currentDepth = depth;
|
||||
|
||||
while (currentFunction != -1)
|
||||
{
|
||||
infoSink.info << " -> " << mCallDag.getRecordFromIndex(currentFunction).name;
|
||||
|
||||
int nextFunction = -1;
|
||||
for (auto& calleeIndex : mCallDag.getRecordFromIndex(currentFunction).callees)
|
||||
{
|
||||
if (depths[calleeIndex] == currentDepth - 1)
|
||||
{
|
||||
currentDepth--;
|
||||
nextFunction = calleeIndex;
|
||||
}
|
||||
}
|
||||
|
||||
currentFunction = nextFunction;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TCompiler::tagUsedFunctions()
|
||||
{
|
||||
// Search from main, starting from the end of the DAG as it usually is the root.
|
||||
for (size_t i = mCallDag.size(); i-- > 0;)
|
||||
{
|
||||
if (mCallDag.getRecordFromIndex(i).name == "main(")
|
||||
{
|
||||
internalTagUsedFunction(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
infoSink.info.prefix(EPrefixError);
|
||||
infoSink.info << "Missing main()\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
void TCompiler::internalTagUsedFunction(size_t index)
|
||||
{
|
||||
if (functionMetadata[index].used)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
functionMetadata[index].used = true;
|
||||
|
||||
for (int calleeIndex : mCallDag.getRecordFromIndex(index).callees)
|
||||
{
|
||||
internalTagUsedFunction(calleeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// A predicate for the stl that returns if a top-level node is unused
|
||||
class TCompiler::UnusedPredicate
|
||||
{
|
||||
public:
|
||||
UnusedPredicate(const CallDAG *callDag, const std::vector<FunctionMetadata> *metadatas)
|
||||
: mCallDag(callDag),
|
||||
mMetadatas(metadatas)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator ()(TIntermNode *node)
|
||||
{
|
||||
const TIntermAggregate *asAggregate = node->getAsAggregate();
|
||||
|
||||
if (asAggregate == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
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->getOp() == EOpPrototype);
|
||||
return true;
|
||||
}
|
||||
|
||||
ASSERT(callDagIndex < mMetadatas->size());
|
||||
return !(*mMetadatas)[callDagIndex].used;
|
||||
}
|
||||
|
||||
private:
|
||||
const CallDAG *mCallDag;
|
||||
const std::vector<FunctionMetadata> *mMetadatas;
|
||||
};
|
||||
|
||||
bool TCompiler::pruneUnusedFunctions(TIntermNode *root)
|
||||
{
|
||||
TIntermAggregate *rootNode = root->getAsAggregate();
|
||||
ASSERT(rootNode != nullptr);
|
||||
|
||||
UnusedPredicate isUnused(&mCallDag, &functionMetadata);
|
||||
TIntermSequence *sequence = rootNode->getSequence();
|
||||
|
||||
if (!sequence->empty())
|
||||
{
|
||||
sequence->erase(std::remove_if(sequence->begin(), sequence->end(), isUnused), sequence->end());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TCompiler::validateOutputs(TIntermNode* root)
|
||||
{
|
||||
ValidateOutputs validateOutputs(infoSink.info, compileResources.MaxDrawBuffers);
|
||||
ValidateOutputs validateOutputs(getExtensionBehavior(), compileResources.MaxDrawBuffers);
|
||||
root->traverse(&validateOutputs);
|
||||
return (validateOutputs.numErrors() == 0);
|
||||
return (validateOutputs.validateAndCountErrors(infoSink.info) == 0);
|
||||
}
|
||||
|
||||
void TCompiler::rewriteCSSShader(TIntermNode* root)
|
||||
@ -497,7 +701,7 @@ void TCompiler::rewriteCSSShader(TIntermNode* root)
|
||||
|
||||
bool TCompiler::validateLimitations(TIntermNode* root)
|
||||
{
|
||||
ValidateLimitations validate(shaderType, infoSink.info);
|
||||
ValidateLimitations validate(shaderType, &infoSink.info);
|
||||
root->traverse(&validate);
|
||||
return validate.numErrors() == 0;
|
||||
}
|
||||
@ -543,17 +747,6 @@ bool TCompiler::limitExpressionComplexity(TIntermNode* root)
|
||||
return false;
|
||||
}
|
||||
|
||||
TDependencyGraph graph(root);
|
||||
|
||||
for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls();
|
||||
iter != graph.endUserDefinedFunctionCalls();
|
||||
++iter)
|
||||
{
|
||||
TGraphFunctionCall* samplerSymbol = *iter;
|
||||
TDependencyGraphTraverser graphTraverser;
|
||||
samplerSymbol->traverse(&graphTraverser);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
//
|
||||
|
||||
#include "compiler/translator/BuiltInFunctionEmulator.h"
|
||||
#include "compiler/translator/CallDAG.h"
|
||||
#include "compiler/translator/ExtensionBehavior.h"
|
||||
#include "compiler/translator/HashNames.h"
|
||||
#include "compiler/translator/InfoSink.h"
|
||||
@ -35,6 +36,11 @@ class TranslatorHLSL;
|
||||
//
|
||||
bool IsWebGLBasedSpec(ShShaderSpec spec);
|
||||
|
||||
//
|
||||
// Helper function to check if the shader type is GLSL.
|
||||
//
|
||||
bool IsGLSL130OrNewer(ShShaderOutput output);
|
||||
|
||||
//
|
||||
// The base class used to back handles returned to the driver.
|
||||
//
|
||||
@ -61,8 +67,8 @@ class TCompiler : public TShHandleBase
|
||||
{
|
||||
public:
|
||||
TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output);
|
||||
virtual ~TCompiler();
|
||||
virtual TCompiler* getAsCompiler() { return this; }
|
||||
~TCompiler() override;
|
||||
TCompiler *getAsCompiler() override { return this; }
|
||||
|
||||
bool Init(const ShBuiltInResources& resources);
|
||||
|
||||
@ -79,8 +85,11 @@ class TCompiler : public TShHandleBase
|
||||
int getShaderVersion() const { return shaderVersion; }
|
||||
TInfoSink& getInfoSink() { return infoSink; }
|
||||
|
||||
// Clears the results from the previous compilation.
|
||||
void clearResults();
|
||||
|
||||
const std::vector<sh::Attribute> &getAttributes() const { return attributes; }
|
||||
const std::vector<sh::Attribute> &getOutputVariables() const { return outputVariables; }
|
||||
const std::vector<sh::OutputVariable> &getOutputVariables() const { return outputVariables; }
|
||||
const std::vector<sh::Uniform> &getUniforms() const { return uniforms; }
|
||||
const std::vector<sh::Varying> &getVaryings() const { return varyings; }
|
||||
const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return interfaceBlocks; }
|
||||
@ -92,6 +101,8 @@ class TCompiler : public TShHandleBase
|
||||
ShShaderOutput getOutputType() const { return outputType; }
|
||||
const std::string &getBuiltInResourcesString() const { return builtInResourcesString; }
|
||||
|
||||
bool shouldRunLoopAndIndexingValidation(int compileOptions) const;
|
||||
|
||||
// Get the resources set by InitBuiltInSymbolTable
|
||||
const ShBuiltInResources& getResources() const;
|
||||
|
||||
@ -101,10 +112,8 @@ class TCompiler : public TShHandleBase
|
||||
bool InitBuiltInSymbolTable(const ShBuiltInResources& resources);
|
||||
// Compute the string representation of the built-in resources
|
||||
void setResourceString();
|
||||
// Clears the results from the previous compilation.
|
||||
void clearResults();
|
||||
// Return true if function recursion is detected or call depth exceeded.
|
||||
bool detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth);
|
||||
// Return false if the call depth is exceeded.
|
||||
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.
|
||||
@ -145,26 +154,57 @@ class TCompiler : public TShHandleBase
|
||||
const char *getSourcePath() const;
|
||||
const TPragma& getPragma() const { return mPragma; }
|
||||
void writePragma();
|
||||
unsigned int *getTemporaryIndex() { return &mTemporaryIndex; }
|
||||
|
||||
const ArrayBoundsClamper& getArrayBoundsClamper() const;
|
||||
ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const;
|
||||
const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const;
|
||||
|
||||
std::vector<sh::Attribute> attributes;
|
||||
std::vector<sh::Attribute> outputVariables;
|
||||
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;
|
||||
|
||||
virtual bool shouldCollectVariables(int compileOptions)
|
||||
{
|
||||
return (compileOptions & SH_VARIABLES) != 0;
|
||||
}
|
||||
|
||||
private:
|
||||
TIntermNode *compileTreeImpl(const char* const shaderStrings[],
|
||||
size_t numStrings, int compileOptions);
|
||||
// Creates the function call DAG for further analysis, returning false if there is a recursion
|
||||
bool initCallDag(TIntermNode *root);
|
||||
// Return false if "main" doesn't exist
|
||||
bool tagUsedFunctions();
|
||||
void internalTagUsedFunction(size_t index);
|
||||
|
||||
void initSamplerDefaultPrecision(TBasicType samplerType);
|
||||
|
||||
// Removes unused function declarations and prototypes from the AST
|
||||
class UnusedPredicate;
|
||||
bool pruneUnusedFunctions(TIntermNode *root);
|
||||
|
||||
TIntermNode *compileTreeImpl(const char *const shaderStrings[],
|
||||
size_t numStrings,
|
||||
const int compileOptions);
|
||||
|
||||
sh::GLenum shaderType;
|
||||
ShShaderSpec shaderSpec;
|
||||
ShShaderOutput outputType;
|
||||
|
||||
struct FunctionMetadata
|
||||
{
|
||||
FunctionMetadata()
|
||||
: used(false)
|
||||
{
|
||||
}
|
||||
bool used;
|
||||
};
|
||||
|
||||
CallDAG mCallDag;
|
||||
std::vector<FunctionMetadata> functionMetadata;
|
||||
|
||||
int maxUniformVectors;
|
||||
int maxExpressionComplexity;
|
||||
int maxCallStackDepth;
|
||||
@ -193,6 +233,8 @@ class TCompiler : public TShHandleBase
|
||||
NameMap nameMap;
|
||||
|
||||
TPragma mPragma;
|
||||
|
||||
unsigned int mTemporaryIndex;
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -9,16 +9,18 @@
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
class ConstantUnion {
|
||||
#include "compiler/translator/BaseTypes.h"
|
||||
|
||||
class TConstantUnion {
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE();
|
||||
ConstantUnion()
|
||||
TConstantUnion()
|
||||
{
|
||||
iConst = 0;
|
||||
type = EbtVoid;
|
||||
}
|
||||
|
||||
bool cast(TBasicType newType, const ConstantUnion &constant)
|
||||
bool cast(TBasicType newType, const TConstantUnion &constant)
|
||||
{
|
||||
switch (newType)
|
||||
{
|
||||
@ -109,7 +111,7 @@ public:
|
||||
return b == bConst;
|
||||
}
|
||||
|
||||
bool operator==(const ConstantUnion& constant) const
|
||||
bool operator==(const TConstantUnion& constant) const
|
||||
{
|
||||
if (constant.type != type)
|
||||
return false;
|
||||
@ -148,12 +150,12 @@ public:
|
||||
return !operator==(b);
|
||||
}
|
||||
|
||||
bool operator!=(const ConstantUnion& constant) const
|
||||
bool operator!=(const TConstantUnion& constant) const
|
||||
{
|
||||
return !operator==(constant);
|
||||
}
|
||||
|
||||
bool operator>(const ConstantUnion& constant) const
|
||||
bool operator>(const TConstantUnion& constant) const
|
||||
{
|
||||
assert(type == constant.type);
|
||||
switch (type) {
|
||||
@ -168,7 +170,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool operator<(const ConstantUnion& constant) const
|
||||
bool operator<(const TConstantUnion& constant) const
|
||||
{
|
||||
assert(type == constant.type);
|
||||
switch (type) {
|
||||
@ -183,9 +185,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
ConstantUnion operator+(const ConstantUnion& constant) const
|
||||
TConstantUnion operator+(const TConstantUnion& constant) const
|
||||
{
|
||||
ConstantUnion returnValue;
|
||||
TConstantUnion returnValue;
|
||||
assert(type == constant.type);
|
||||
switch (type) {
|
||||
case EbtInt: returnValue.setIConst(iConst + constant.iConst); break;
|
||||
@ -197,9 +199,9 @@ public:
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
ConstantUnion operator-(const ConstantUnion& constant) const
|
||||
TConstantUnion operator-(const TConstantUnion& constant) const
|
||||
{
|
||||
ConstantUnion returnValue;
|
||||
TConstantUnion returnValue;
|
||||
assert(type == constant.type);
|
||||
switch (type) {
|
||||
case EbtInt: returnValue.setIConst(iConst - constant.iConst); break;
|
||||
@ -211,9 +213,9 @@ public:
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
ConstantUnion operator*(const ConstantUnion& constant) const
|
||||
TConstantUnion operator*(const TConstantUnion& constant) const
|
||||
{
|
||||
ConstantUnion returnValue;
|
||||
TConstantUnion returnValue;
|
||||
assert(type == constant.type);
|
||||
switch (type) {
|
||||
case EbtInt: returnValue.setIConst(iConst * constant.iConst); break;
|
||||
@ -225,9 +227,9 @@ public:
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
ConstantUnion operator%(const ConstantUnion& constant) const
|
||||
TConstantUnion operator%(const TConstantUnion& constant) const
|
||||
{
|
||||
ConstantUnion returnValue;
|
||||
TConstantUnion returnValue;
|
||||
assert(type == constant.type);
|
||||
switch (type) {
|
||||
case EbtInt: returnValue.setIConst(iConst % constant.iConst); break;
|
||||
@ -238,9 +240,9 @@ public:
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
ConstantUnion operator>>(const ConstantUnion& constant) const
|
||||
TConstantUnion operator>>(const TConstantUnion& constant) const
|
||||
{
|
||||
ConstantUnion returnValue;
|
||||
TConstantUnion returnValue;
|
||||
assert(type == constant.type);
|
||||
switch (type) {
|
||||
case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break;
|
||||
@ -251,9 +253,9 @@ public:
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
ConstantUnion operator<<(const ConstantUnion& constant) const
|
||||
TConstantUnion operator<<(const TConstantUnion& constant) const
|
||||
{
|
||||
ConstantUnion returnValue;
|
||||
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.
|
||||
@ -267,9 +269,9 @@ public:
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
ConstantUnion operator&(const ConstantUnion& constant) const
|
||||
TConstantUnion operator&(const TConstantUnion& constant) const
|
||||
{
|
||||
ConstantUnion returnValue;
|
||||
TConstantUnion returnValue;
|
||||
assert(constant.type == EbtInt || constant.type == EbtUInt);
|
||||
switch (type) {
|
||||
case EbtInt: returnValue.setIConst(iConst & constant.iConst); break;
|
||||
@ -280,9 +282,9 @@ public:
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
ConstantUnion operator|(const ConstantUnion& constant) const
|
||||
TConstantUnion operator|(const TConstantUnion& constant) const
|
||||
{
|
||||
ConstantUnion returnValue;
|
||||
TConstantUnion returnValue;
|
||||
assert(type == constant.type);
|
||||
switch (type) {
|
||||
case EbtInt: returnValue.setIConst(iConst | constant.iConst); break;
|
||||
@ -293,9 +295,9 @@ public:
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
ConstantUnion operator^(const ConstantUnion& constant) const
|
||||
TConstantUnion operator^(const TConstantUnion& constant) const
|
||||
{
|
||||
ConstantUnion returnValue;
|
||||
TConstantUnion returnValue;
|
||||
assert(type == constant.type);
|
||||
switch (type) {
|
||||
case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break;
|
||||
@ -306,9 +308,9 @@ public:
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
ConstantUnion operator&&(const ConstantUnion& constant) const
|
||||
TConstantUnion operator&&(const TConstantUnion& constant) const
|
||||
{
|
||||
ConstantUnion returnValue;
|
||||
TConstantUnion returnValue;
|
||||
assert(type == constant.type);
|
||||
switch (type) {
|
||||
case EbtBool: returnValue.setBConst(bConst && constant.bConst); break;
|
||||
@ -318,9 +320,9 @@ public:
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
ConstantUnion operator||(const ConstantUnion& constant) const
|
||||
TConstantUnion operator||(const TConstantUnion& constant) const
|
||||
{
|
||||
ConstantUnion returnValue;
|
||||
TConstantUnion returnValue;
|
||||
assert(type == constant.type);
|
||||
switch (type) {
|
||||
case EbtBool: returnValue.setBConst(bConst || constant.bConst); break;
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#include "compiler/translator/Diagnostics.h"
|
||||
|
||||
#include "compiler/translator/compilerdebug.h"
|
||||
#include "common/debug.h"
|
||||
#include "compiler/translator/InfoSink.h"
|
||||
#include "compiler/preprocessor/SourceLocation.h"
|
||||
|
||||
@ -50,11 +50,6 @@ void TDiagnostics::writeInfo(Severity severity,
|
||||
sink << "'" << token << "' : " << reason << " " << extra << "\n";
|
||||
}
|
||||
|
||||
void TDiagnostics::writeDebug(const std::string& str)
|
||||
{
|
||||
mInfoSink.debug << str;
|
||||
}
|
||||
|
||||
void TDiagnostics::print(ID id,
|
||||
const pp::SourceLocation& loc,
|
||||
const std::string& text)
|
||||
|
@ -16,7 +16,7 @@ class TDiagnostics : public pp::Diagnostics, angle::NonCopyable
|
||||
{
|
||||
public:
|
||||
TDiagnostics(TInfoSink& infoSink);
|
||||
virtual ~TDiagnostics();
|
||||
~TDiagnostics() override;
|
||||
|
||||
TInfoSink& infoSink() { return mInfoSink; }
|
||||
|
||||
@ -29,12 +29,8 @@ class TDiagnostics : public pp::Diagnostics, angle::NonCopyable
|
||||
const std::string& token,
|
||||
const std::string& extra);
|
||||
|
||||
void writeDebug(const std::string& str);
|
||||
|
||||
protected:
|
||||
virtual void print(ID id,
|
||||
const pp::SourceLocation& loc,
|
||||
const std::string& text);
|
||||
void print(ID id, const pp::SourceLocation &loc, const std::string &text) override;
|
||||
|
||||
private:
|
||||
TInfoSink& mInfoSink;
|
||||
|
@ -8,7 +8,8 @@
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "compiler/translator/compilerdebug.h"
|
||||
#include "angle_gl.h"
|
||||
#include "common/debug.h"
|
||||
#include "compiler/translator/Diagnostics.h"
|
||||
|
||||
static TBehavior getBehavior(const std::string& str)
|
||||
@ -25,13 +26,15 @@ static TBehavior getBehavior(const std::string& str)
|
||||
return EBhUndefined;
|
||||
}
|
||||
|
||||
TDirectiveHandler::TDirectiveHandler(TExtensionBehavior& extBehavior,
|
||||
TDiagnostics& diagnostics,
|
||||
int& shaderVersion,
|
||||
TDirectiveHandler::TDirectiveHandler(TExtensionBehavior &extBehavior,
|
||||
TDiagnostics &diagnostics,
|
||||
int &shaderVersion,
|
||||
sh::GLenum shaderType,
|
||||
bool debugShaderPrecisionSupported)
|
||||
: mExtensionBehavior(extBehavior),
|
||||
mDiagnostics(diagnostics),
|
||||
mShaderVersion(shaderVersion),
|
||||
mShaderType(shaderType),
|
||||
mDebugShaderPrecisionSupported(debugShaderPrecisionSupported)
|
||||
{
|
||||
}
|
||||
@ -57,7 +60,16 @@ void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc,
|
||||
const char kAll[] = "all";
|
||||
|
||||
if (name == kInvariant && value == kAll)
|
||||
{
|
||||
if (mShaderVersion == 300 && mShaderType == GL_FRAGMENT_SHADER)
|
||||
{
|
||||
// ESSL 3.00.4 section 4.6.1
|
||||
mDiagnostics.writeInfo(
|
||||
pp::Diagnostics::PP_ERROR, loc,
|
||||
"#pragma STDGL invariant(all) can not be used in fragment shader", name, value);
|
||||
}
|
||||
mPragma.stdgl.invariantAll = true;
|
||||
}
|
||||
// The STDGL pragma is used to reserve pragmas for use by future
|
||||
// revisions of GLSL. Do not generate an error on unexpected
|
||||
// name and value.
|
||||
|
@ -11,41 +11,42 @@
|
||||
#include "compiler/translator/ExtensionBehavior.h"
|
||||
#include "compiler/translator/Pragma.h"
|
||||
#include "compiler/preprocessor/DirectiveHandlerBase.h"
|
||||
#include "GLSLANG/ShaderLang.h"
|
||||
|
||||
class TDiagnostics;
|
||||
|
||||
class TDirectiveHandler : public pp::DirectiveHandler, angle::NonCopyable
|
||||
{
|
||||
public:
|
||||
TDirectiveHandler(TExtensionBehavior& extBehavior,
|
||||
TDiagnostics& diagnostics,
|
||||
int& shaderVersion,
|
||||
TDirectiveHandler(TExtensionBehavior &extBehavior,
|
||||
TDiagnostics &diagnostics,
|
||||
int &shaderVersion,
|
||||
sh::GLenum shaderType,
|
||||
bool debugShaderPrecisionSupported);
|
||||
virtual ~TDirectiveHandler();
|
||||
~TDirectiveHandler() override;
|
||||
|
||||
const TPragma& pragma() const { return mPragma; }
|
||||
const TExtensionBehavior& extensionBehavior() const { return mExtensionBehavior; }
|
||||
|
||||
virtual void handleError(const pp::SourceLocation& loc,
|
||||
const std::string& msg);
|
||||
void handleError(const pp::SourceLocation &loc, const std::string &msg) override;
|
||||
|
||||
virtual void handlePragma(const pp::SourceLocation& loc,
|
||||
const std::string& name,
|
||||
const std::string& value,
|
||||
bool stdgl);
|
||||
void handlePragma(const pp::SourceLocation &loc,
|
||||
const std::string &name,
|
||||
const std::string &value,
|
||||
bool stdgl) override;
|
||||
|
||||
virtual void handleExtension(const pp::SourceLocation& loc,
|
||||
const std::string& name,
|
||||
const std::string& behavior);
|
||||
void handleExtension(const pp::SourceLocation &loc,
|
||||
const std::string &name,
|
||||
const std::string &behavior) override;
|
||||
|
||||
virtual void handleVersion(const pp::SourceLocation& loc,
|
||||
int version);
|
||||
void handleVersion(const pp::SourceLocation &loc, int version) override;
|
||||
|
||||
private:
|
||||
TPragma mPragma;
|
||||
TExtensionBehavior& mExtensionBehavior;
|
||||
TDiagnostics& mDiagnostics;
|
||||
int& mShaderVersion;
|
||||
sh::GLenum mShaderType;
|
||||
bool mDebugShaderPrecisionSupported;
|
||||
};
|
||||
|
||||
|
@ -179,11 +179,50 @@ const char *getFloatTypeStr(const TType& type)
|
||||
case 1:
|
||||
return "float";
|
||||
case 2:
|
||||
return type.getSecondarySize() > 1 ? "mat2" : "vec2";
|
||||
switch(type.getSecondarySize())
|
||||
{
|
||||
case 1:
|
||||
return "vec2";
|
||||
case 2:
|
||||
return "mat2";
|
||||
case 3:
|
||||
return "mat2x3";
|
||||
case 4:
|
||||
return "mat2x4";
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return NULL;
|
||||
}
|
||||
case 3:
|
||||
return type.getSecondarySize() > 1 ? "mat3" : "vec3";
|
||||
switch(type.getSecondarySize())
|
||||
{
|
||||
case 1:
|
||||
return "vec3";
|
||||
case 2:
|
||||
return "mat3x2";
|
||||
case 3:
|
||||
return "mat3";
|
||||
case 4:
|
||||
return "mat3x4";
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return NULL;
|
||||
}
|
||||
case 4:
|
||||
return type.getSecondarySize() > 1 ? "mat4" : "vec4";
|
||||
switch(type.getSecondarySize())
|
||||
{
|
||||
case 1:
|
||||
return "vec4";
|
||||
case 2:
|
||||
return "mat4x2";
|
||||
case 3:
|
||||
return "mat4x3";
|
||||
case 4:
|
||||
return "mat4";
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return NULL;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return NULL;
|
||||
@ -199,8 +238,10 @@ bool canRoundFloat(const TType &type)
|
||||
TIntermAggregate *createInternalFunctionCallNode(TString name, TIntermNode *child)
|
||||
{
|
||||
TIntermAggregate *callNode = new TIntermAggregate();
|
||||
callNode->setOp(EOpInternalFunctionCall);
|
||||
callNode->setName(name);
|
||||
callNode->setOp(EOpFunctionCall);
|
||||
TName nameObj(TFunction::mangleName(name));
|
||||
nameObj.setInternal(true);
|
||||
callNode->setNameObj(nameObj);
|
||||
callNode->getSequence()->push_back(child);
|
||||
return callNode;
|
||||
}
|
||||
@ -252,17 +293,14 @@ bool parentUsesResult(TIntermNode* parent, TIntermNode* node)
|
||||
|
||||
} // namespace anonymous
|
||||
|
||||
EmulatePrecision::EmulatePrecision()
|
||||
: TIntermTraverser(true, true, true),
|
||||
mDeclaringVariables(false),
|
||||
mInLValue(false),
|
||||
mInFunctionCallOutParameter(false)
|
||||
EmulatePrecision::EmulatePrecision(const TSymbolTable &symbolTable, int shaderVersion)
|
||||
: TLValueTrackingTraverser(true, true, true, symbolTable, shaderVersion),
|
||||
mDeclaringVariables(false)
|
||||
{}
|
||||
|
||||
void EmulatePrecision::visitSymbol(TIntermSymbol *node)
|
||||
{
|
||||
if (canRoundFloat(node->getType()) &&
|
||||
!mDeclaringVariables && !mInLValue && !mInFunctionCallOutParameter)
|
||||
if (canRoundFloat(node->getType()) && !mDeclaringVariables && !isLValueRequiredHere())
|
||||
{
|
||||
TIntermNode *parent = getParentNode();
|
||||
TIntermNode *replacement = createRoundingFunctionCallNode(node);
|
||||
@ -275,14 +313,6 @@ bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node)
|
||||
{
|
||||
bool visitChildren = true;
|
||||
|
||||
if (node->isAssignment())
|
||||
{
|
||||
if (visit == PreVisit)
|
||||
mInLValue = true;
|
||||
else if (visit == InVisit)
|
||||
mInLValue = false;
|
||||
}
|
||||
|
||||
TOperator op = node->getOp();
|
||||
|
||||
// RHS of initialize is not being declared.
|
||||
@ -376,22 +406,9 @@ bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node)
|
||||
{
|
||||
case EOpSequence:
|
||||
case EOpConstructStruct:
|
||||
// No special handling
|
||||
break;
|
||||
case EOpFunction:
|
||||
if (visit == PreVisit)
|
||||
{
|
||||
const TIntermSequence &sequence = *(node->getSequence());
|
||||
TIntermSequence::const_iterator seqIter = sequence.begin();
|
||||
TIntermAggregate *params = (*seqIter)->getAsAggregate();
|
||||
ASSERT(params != NULL);
|
||||
ASSERT(params->getOp() == EOpParameters);
|
||||
mFunctionMap[node->getName()] = params->getSequence();
|
||||
}
|
||||
break;
|
||||
case EOpPrototype:
|
||||
if (visit == PreVisit)
|
||||
mFunctionMap[node->getName()] = node->getSequence();
|
||||
visitChildren = false;
|
||||
break;
|
||||
case EOpParameters:
|
||||
@ -418,50 +435,17 @@ bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node)
|
||||
case EOpFunctionCall:
|
||||
{
|
||||
// Function call.
|
||||
bool inFunctionMap = (mFunctionMap.find(node->getName()) != mFunctionMap.end());
|
||||
if (visit == PreVisit)
|
||||
{
|
||||
// User-defined function return values are not rounded, this relies on that
|
||||
// calculations producing the value were rounded.
|
||||
TIntermNode *parent = getParentNode();
|
||||
if (canRoundFloat(node->getType()) && !inFunctionMap && parentUsesResult(parent, node))
|
||||
if (canRoundFloat(node->getType()) && !isInFunctionMap(node) &&
|
||||
parentUsesResult(parent, node))
|
||||
{
|
||||
TIntermNode *replacement = createRoundingFunctionCallNode(node);
|
||||
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
|
||||
}
|
||||
|
||||
if (inFunctionMap)
|
||||
{
|
||||
mSeqIterStack.push_back(mFunctionMap[node->getName()]->begin());
|
||||
if (mSeqIterStack.back() != mFunctionMap[node->getName()]->end())
|
||||
{
|
||||
TQualifier qualifier = (*mSeqIterStack.back())->getAsTyped()->getQualifier();
|
||||
mInFunctionCallOutParameter = (qualifier == EvqOut || qualifier == EvqInOut);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The function is not user-defined - it is likely built-in texture function.
|
||||
// Assume that those do not have out parameters.
|
||||
mInFunctionCallOutParameter = false;
|
||||
}
|
||||
}
|
||||
else if (visit == InVisit)
|
||||
{
|
||||
if (inFunctionMap)
|
||||
{
|
||||
++mSeqIterStack.back();
|
||||
TQualifier qualifier = (*mSeqIterStack.back())->getAsTyped()->getQualifier();
|
||||
mInFunctionCallOutParameter = (qualifier == EvqOut || qualifier == EvqInOut);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inFunctionMap)
|
||||
{
|
||||
mSeqIterStack.pop_back();
|
||||
mInFunctionCallOutParameter = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -484,15 +468,10 @@ bool EmulatePrecision::visitUnary(Visit visit, TIntermUnary *node)
|
||||
case EOpNegative:
|
||||
case EOpVectorLogicalNot:
|
||||
case EOpLogicalNot:
|
||||
break;
|
||||
case EOpPostIncrement:
|
||||
case EOpPostDecrement:
|
||||
case EOpPreIncrement:
|
||||
case EOpPreDecrement:
|
||||
if (visit == PreVisit)
|
||||
mInLValue = true;
|
||||
else if (visit == PostVisit)
|
||||
mInLValue = false;
|
||||
break;
|
||||
default:
|
||||
if (canRoundFloat(node->getType()) && visit == PreVisit)
|
||||
@ -511,7 +490,7 @@ void EmulatePrecision::writeEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput
|
||||
{
|
||||
// Other languages not yet supported
|
||||
ASSERT(outputLanguage == SH_GLSL_COMPATIBILITY_OUTPUT ||
|
||||
outputLanguage == SH_GLSL_CORE_OUTPUT ||
|
||||
IsGLSL130OrNewer(outputLanguage) ||
|
||||
outputLanguage == SH_ESSL_OUTPUT);
|
||||
writeCommonPrecisionEmulationHelpers(sink, outputLanguage);
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
|
||||
|
||||
#include "common/angleutils.h"
|
||||
#include "compiler/translator/Compiler.h"
|
||||
#include "compiler/translator/InfoSink.h"
|
||||
#include "compiler/translator/IntermNode.h"
|
||||
#include "GLSLANG/ShaderLang.h"
|
||||
@ -17,15 +18,15 @@
|
||||
// need to write a huge number of variations of the emulated compound assignment
|
||||
// to every translated shader with emulation enabled.
|
||||
|
||||
class EmulatePrecision : public TIntermTraverser
|
||||
class EmulatePrecision : public TLValueTrackingTraverser
|
||||
{
|
||||
public:
|
||||
EmulatePrecision();
|
||||
EmulatePrecision(const TSymbolTable &symbolTable, int shaderVersion);
|
||||
|
||||
virtual void visitSymbol(TIntermSymbol *node);
|
||||
virtual bool visitBinary(Visit visit, TIntermBinary *node);
|
||||
virtual bool visitUnary(Visit visit, TIntermUnary *node);
|
||||
virtual bool visitAggregate(Visit visit, TIntermAggregate *node);
|
||||
void visitSymbol(TIntermSymbol *node) override;
|
||||
bool visitBinary(Visit visit, TIntermBinary *node) override;
|
||||
bool visitUnary(Visit visit, TIntermUnary *node) override;
|
||||
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
|
||||
|
||||
void writeEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage);
|
||||
|
||||
@ -55,20 +56,7 @@ class EmulatePrecision : public TIntermTraverser
|
||||
EmulationSet mEmulateCompoundMul;
|
||||
EmulationSet mEmulateCompoundDiv;
|
||||
|
||||
// Stack of function call parameter iterators
|
||||
std::vector<TIntermSequence::const_iterator> mSeqIterStack;
|
||||
|
||||
bool mDeclaringVariables;
|
||||
bool mInLValue;
|
||||
bool mInFunctionCallOutParameter;
|
||||
|
||||
struct TStringComparator
|
||||
{
|
||||
bool operator() (const TString& a, const TString& b) const { return a.compare(b) < 0; }
|
||||
};
|
||||
|
||||
// Map from function names to their parameter sequences
|
||||
std::map<TString, TIntermSequence*, TStringComparator> mFunctionMap;
|
||||
};
|
||||
|
||||
#endif // COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
|
||||
|
@ -34,4 +34,10 @@ inline const char* getBehaviorString(TBehavior b)
|
||||
// Mapping between extension name and behavior.
|
||||
typedef std::map<std::string, TBehavior> TExtensionBehavior;
|
||||
|
||||
inline bool IsExtensionEnabled(const TExtensionBehavior &extBehavior, const char *extension)
|
||||
{
|
||||
auto iter = extBehavior.find(extension);
|
||||
return iter != extBehavior.end() && (iter->second == EBhEnable || iter->second == EBhRequire);
|
||||
}
|
||||
|
||||
#endif // COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_
|
||||
|
100
src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.cpp
vendored
Normal file
100
src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.cpp
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
//
|
||||
// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// ExtensionGLSL.cpp: Implements the TExtensionGLSL class that tracks GLSL extension requirements
|
||||
// of shaders.
|
||||
|
||||
#include "compiler/translator/ExtensionGLSL.h"
|
||||
|
||||
#include "compiler/translator/VersionGLSL.h"
|
||||
|
||||
TExtensionGLSL::TExtensionGLSL(ShShaderOutput output)
|
||||
: TIntermTraverser(true, false, false), mTargetVersion(ShaderOutputTypeToGLSLVersion(output))
|
||||
{
|
||||
}
|
||||
|
||||
const std::set<std::string> &TExtensionGLSL::getEnabledExtensions() const
|
||||
{
|
||||
return mEnabledExtensions;
|
||||
}
|
||||
|
||||
const std::set<std::string> &TExtensionGLSL::getRequiredExtensions() const
|
||||
{
|
||||
return mRequiredExtensions;
|
||||
}
|
||||
|
||||
bool TExtensionGLSL::visitUnary(Visit, TIntermUnary *node)
|
||||
{
|
||||
checkOperator(node);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TExtensionGLSL::visitAggregate(Visit, TIntermAggregate *node)
|
||||
{
|
||||
checkOperator(node);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TExtensionGLSL::checkOperator(TIntermOperator *node)
|
||||
{
|
||||
if (mTargetVersion < GLSL_VERSION_130)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (node->getOp())
|
||||
{
|
||||
case EOpAbs:
|
||||
break;
|
||||
|
||||
case EOpSign:
|
||||
break;
|
||||
|
||||
case EOpMix:
|
||||
break;
|
||||
|
||||
case EOpFloatBitsToInt:
|
||||
case EOpFloatBitsToUint:
|
||||
case EOpIntBitsToFloat:
|
||||
case EOpUintBitsToFloat:
|
||||
if (mTargetVersion < GLSL_VERSION_330)
|
||||
{
|
||||
// Bit conversion functions cannot be emulated.
|
||||
mRequiredExtensions.insert("GL_ARB_shader_bit_encoding");
|
||||
}
|
||||
break;
|
||||
|
||||
case EOpPackSnorm2x16:
|
||||
case EOpPackHalf2x16:
|
||||
case EOpUnpackSnorm2x16:
|
||||
case EOpUnpackHalf2x16:
|
||||
if (mTargetVersion < GLSL_VERSION_420)
|
||||
{
|
||||
mEnabledExtensions.insert("GL_ARB_shading_language_packing");
|
||||
|
||||
if (mTargetVersion < GLSL_VERSION_330)
|
||||
{
|
||||
// floatBitsToUint and uintBitsToFloat are needed to emulate
|
||||
// packHalf2x16 and unpackHalf2x16 respectively and cannot be
|
||||
// emulated themselves.
|
||||
mRequiredExtensions.insert("GL_ARB_shader_bit_encoding");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EOpPackUnorm2x16:
|
||||
case EOpUnpackUnorm2x16:
|
||||
if (mTargetVersion < GLSL_VERSION_410)
|
||||
{
|
||||
mEnabledExtensions.insert("GL_ARB_shading_language_packing");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
39
src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.h
vendored
Normal file
39
src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.h
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
//
|
||||
// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// ExtensionGLSL.h: Defines the TExtensionGLSL class that tracks GLSL extension requirements of
|
||||
// shaders.
|
||||
|
||||
#ifndef COMPILER_TRANSLATOR_EXTENSIONGLSL_H_
|
||||
#define COMPILER_TRANSLATOR_EXTENSIONGLSL_H_
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "compiler/translator/IntermNode.h"
|
||||
|
||||
// Traverses the intermediate tree to determine which GLSL extensions are required
|
||||
// to support the shader.
|
||||
class TExtensionGLSL : public TIntermTraverser
|
||||
{
|
||||
public:
|
||||
TExtensionGLSL(ShShaderOutput output);
|
||||
|
||||
const std::set<std::string> &getEnabledExtensions() const;
|
||||
const std::set<std::string> &getRequiredExtensions() const;
|
||||
|
||||
bool visitUnary(Visit visit, TIntermUnary *node) override;
|
||||
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
|
||||
|
||||
private:
|
||||
void checkOperator(TIntermOperator *node);
|
||||
|
||||
int mTargetVersion;
|
||||
|
||||
std::set<std::string> mEnabledExtensions;
|
||||
std::set<std::string> mRequiredExtensions;
|
||||
};
|
||||
|
||||
#endif // COMPILER_TRANSLATOR_EXTENSIONGLSL_H_
|
@ -18,11 +18,17 @@ namespace sh
|
||||
class FlagStd140Structs : public TIntermTraverser
|
||||
{
|
||||
public:
|
||||
|
||||
FlagStd140Structs()
|
||||
: TIntermTraverser(true, false, false)
|
||||
{
|
||||
}
|
||||
|
||||
const std::vector<TIntermTyped *> getFlaggedNodes() const { return mFlaggedNodes; }
|
||||
|
||||
protected:
|
||||
virtual bool visitBinary(Visit visit, TIntermBinary *binaryNode);
|
||||
virtual void visitSymbol(TIntermSymbol *symbol);
|
||||
bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
|
||||
void visitSymbol(TIntermSymbol *symbol) override;
|
||||
|
||||
private:
|
||||
bool isInStd140InterfaceBlock(TIntermTyped *node) const;
|
||||
|
@ -6,6 +6,9 @@
|
||||
|
||||
#include "compiler/translator/ForLoopUnroll.h"
|
||||
|
||||
#include "compiler/translator/ValidateLimitations.h"
|
||||
#include "angle_gl.h"
|
||||
|
||||
bool ForLoopUnrollMarker::visitBinary(Visit, TIntermBinary *node)
|
||||
{
|
||||
if (mUnrollCondition != kSamplerArrayIndex)
|
||||
@ -38,11 +41,16 @@ bool ForLoopUnrollMarker::visitBinary(Visit, TIntermBinary *node)
|
||||
|
||||
bool ForLoopUnrollMarker::visitLoop(Visit, TIntermLoop *node)
|
||||
{
|
||||
if (mUnrollCondition == kIntegerIndex)
|
||||
bool canBeUnrolled = mHasRunLoopValidation;
|
||||
if (!mHasRunLoopValidation)
|
||||
{
|
||||
canBeUnrolled = ValidateLimitations::IsLimitedForLoop(node);
|
||||
}
|
||||
if (mUnrollCondition == kIntegerIndex && canBeUnrolled)
|
||||
{
|
||||
// Check if loop index type is integer.
|
||||
// This is called after ValidateLimitations pass, so all the calls
|
||||
// should be valid. See ValidateLimitations::validateForLoopInit().
|
||||
// This is called after ValidateLimitations pass, so the loop has the limited form specified
|
||||
// in ESSL 1.00 appendix A.
|
||||
TIntermSequence *declSeq = node->getInit()->getAsAggregate()->getSequence();
|
||||
TIntermSymbol *symbol = (*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode();
|
||||
if (symbol->getBasicType() == EbtInt)
|
||||
@ -50,11 +58,18 @@ bool ForLoopUnrollMarker::visitLoop(Visit, TIntermLoop *node)
|
||||
}
|
||||
|
||||
TIntermNode *body = node->getBody();
|
||||
if (body != NULL)
|
||||
if (body != nullptr)
|
||||
{
|
||||
mLoopStack.push(node);
|
||||
body->traverse(this);
|
||||
mLoopStack.pop();
|
||||
if (canBeUnrolled)
|
||||
{
|
||||
mLoopStack.push(node);
|
||||
body->traverse(this);
|
||||
mLoopStack.pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
body->traverse(this);
|
||||
}
|
||||
}
|
||||
// The loop is fully processed - no need to visit children.
|
||||
return false;
|
||||
|
@ -24,16 +24,18 @@ class ForLoopUnrollMarker : public TIntermTraverser
|
||||
kSamplerArrayIndex
|
||||
};
|
||||
|
||||
ForLoopUnrollMarker(UnrollCondition condition)
|
||||
: mUnrollCondition(condition),
|
||||
ForLoopUnrollMarker(UnrollCondition condition, bool hasRunLoopValidation)
|
||||
: TIntermTraverser(true, false, false),
|
||||
mUnrollCondition(condition),
|
||||
mSamplerArrayIndexIsFloatLoopIndex(false),
|
||||
mVisitSamplerArrayIndexNodeInsideLoop(false)
|
||||
mVisitSamplerArrayIndexNodeInsideLoop(false),
|
||||
mHasRunLoopValidation(hasRunLoopValidation)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool visitBinary(Visit, TIntermBinary *node);
|
||||
virtual bool visitLoop(Visit, TIntermLoop *node);
|
||||
virtual void visitSymbol(TIntermSymbol *node);
|
||||
bool visitBinary(Visit, TIntermBinary *node) override;
|
||||
bool visitLoop(Visit, TIntermLoop *node) override;
|
||||
void visitSymbol(TIntermSymbol *node) override;
|
||||
|
||||
bool samplerArrayIndexIsFloatLoopIndex() const
|
||||
{
|
||||
@ -45,6 +47,7 @@ class ForLoopUnrollMarker : public TIntermTraverser
|
||||
TLoopStack mLoopStack;
|
||||
bool mSamplerArrayIndexIsFloatLoopIndex;
|
||||
bool mVisitSamplerArrayIndexNodeInsideLoop;
|
||||
bool mHasRunLoopValidation;
|
||||
};
|
||||
|
||||
#endif // COMPILER_TRANSLATOR_FORLOOPUNROLL_H_
|
||||
|
@ -11,25 +11,26 @@
|
||||
//
|
||||
|
||||
#include "compiler/translator/Initialize.h"
|
||||
#include "compiler/translator/Cache.h"
|
||||
|
||||
#include "compiler/translator/IntermNode.h"
|
||||
#include "angle_gl.h"
|
||||
|
||||
void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable)
|
||||
{
|
||||
TType *float1 = new TType(EbtFloat);
|
||||
TType *float2 = new TType(EbtFloat, 2);
|
||||
TType *float3 = new TType(EbtFloat, 3);
|
||||
TType *float4 = new TType(EbtFloat, 4);
|
||||
TType *int1 = new TType(EbtInt);
|
||||
TType *int2 = new TType(EbtInt, 2);
|
||||
TType *int3 = new TType(EbtInt, 3);
|
||||
TType *uint1 = new TType(EbtUInt);
|
||||
TType *bool1 = new TType(EbtBool);
|
||||
TType *genType = new TType(EbtGenType);
|
||||
TType *genIType = new TType(EbtGenIType);
|
||||
TType *genUType = new TType(EbtGenUType);
|
||||
TType *genBType = new TType(EbtGenBType);
|
||||
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);
|
||||
const TType *int1 = TCache::getType(EbtInt);
|
||||
const TType *int2 = TCache::getType(EbtInt, 2);
|
||||
const TType *int3 = TCache::getType(EbtInt, 3);
|
||||
const TType *uint1 = TCache::getType(EbtUInt);
|
||||
const TType *bool1 = TCache::getType(EbtBool);
|
||||
const TType *genType = TCache::getType(EbtGenType);
|
||||
const TType *genIType = TCache::getType(EbtGenIType);
|
||||
const TType *genUType = TCache::getType(EbtGenUType);
|
||||
const TType *genBType = TCache::getType(EbtGenBType);
|
||||
|
||||
//
|
||||
// Angle and Trigonometric Functions.
|
||||
@ -96,19 +97,16 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
|
||||
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genUType, "clamp", genUType, genUType, genUType);
|
||||
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMix, genType, "mix", genType, genType, float1);
|
||||
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMix, genType, "mix", genType, genType, genType);
|
||||
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMix, genType, "mix", genType, genType, genBType);
|
||||
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpStep, genType, "step", genType, genType);
|
||||
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpStep, genType, "step", float1, genType);
|
||||
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSmoothStep, genType, "smoothstep", genType, genType, genType);
|
||||
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSmoothStep, genType, "smoothstep", float1, float1, genType);
|
||||
|
||||
TType *outFloat1 = new TType(EbtFloat);
|
||||
TType *outFloat2 = new TType(EbtFloat, 2);
|
||||
TType *outFloat3 = new TType(EbtFloat, 3);
|
||||
TType *outFloat4 = new TType(EbtFloat, 4);
|
||||
outFloat1->setQualifier(EvqOut);
|
||||
outFloat2->setQualifier(EvqOut);
|
||||
outFloat3->setQualifier(EvqOut);
|
||||
outFloat4->setQualifier(EvqOut);
|
||||
const TType *outFloat1 = TCache::getType(EbtFloat, EvqOut);
|
||||
const TType *outFloat2 = TCache::getType(EbtFloat, EvqOut, 2);
|
||||
const TType *outFloat3 = TCache::getType(EbtFloat, EvqOut, 3);
|
||||
const TType *outFloat4 = TCache::getType(EbtFloat, EvqOut, 4);
|
||||
|
||||
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float1, "modf", float1, outFloat1);
|
||||
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float2, "modf", float2, outFloat2);
|
||||
@ -141,15 +139,15 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
|
||||
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpReflect, genType, "reflect", genType, genType);
|
||||
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpRefract, genType, "refract", genType, genType, float1);
|
||||
|
||||
TType *mat2 = new TType(EbtFloat, 2, 2);
|
||||
TType *mat3 = new TType(EbtFloat, 3, 3);
|
||||
TType *mat4 = new TType(EbtFloat, 4, 4);
|
||||
TType *mat2x3 = new TType(EbtFloat, 2, 3);
|
||||
TType *mat3x2 = new TType(EbtFloat, 3, 2);
|
||||
TType *mat2x4 = new TType(EbtFloat, 2, 4);
|
||||
TType *mat4x2 = new TType(EbtFloat, 4, 2);
|
||||
TType *mat3x4 = new TType(EbtFloat, 3, 4);
|
||||
TType *mat4x3 = new TType(EbtFloat, 4, 3);
|
||||
const TType *mat2 = TCache::getType(EbtFloat, 2, 2);
|
||||
const TType *mat3 = TCache::getType(EbtFloat, 3, 3);
|
||||
const TType *mat4 = TCache::getType(EbtFloat, 4, 4);
|
||||
const TType *mat2x3 = TCache::getType(EbtFloat, 2, 3);
|
||||
const TType *mat3x2 = TCache::getType(EbtFloat, 3, 2);
|
||||
const TType *mat2x4 = TCache::getType(EbtFloat, 2, 4);
|
||||
const TType *mat4x2 = TCache::getType(EbtFloat, 4, 2);
|
||||
const TType *mat3x4 = TCache::getType(EbtFloat, 3, 4);
|
||||
const TType *mat4x3 = TCache::getType(EbtFloat, 4, 3);
|
||||
|
||||
//
|
||||
// Matrix Functions.
|
||||
@ -192,10 +190,10 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
|
||||
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat3, "inverse", mat3);
|
||||
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat4, "inverse", mat4);
|
||||
|
||||
TType *vec = new TType(EbtVec);
|
||||
TType *ivec = new TType(EbtIVec);
|
||||
TType *uvec = new TType(EbtUVec);
|
||||
TType *bvec = new TType(EbtBVec);
|
||||
const TType *vec = TCache::getType(EbtVec);
|
||||
const TType *ivec = TCache::getType(EbtIVec);
|
||||
const TType *uvec = TCache::getType(EbtUVec);
|
||||
const TType *bvec = TCache::getType(EbtBVec);
|
||||
|
||||
//
|
||||
// Vector relational functions.
|
||||
@ -224,8 +222,8 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
|
||||
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAll, bool1, "all", bvec);
|
||||
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorLogicalNot, bvec, "not", bvec);
|
||||
|
||||
TType *sampler2D = new TType(EbtSampler2D);
|
||||
TType *samplerCube = new TType(EbtSamplerCube);
|
||||
const TType *sampler2D = TCache::getType(EbtSampler2D);
|
||||
const TType *samplerCube = TCache::getType(EbtSamplerCube);
|
||||
|
||||
//
|
||||
// Texture Functions for GLSL ES 1.0
|
||||
@ -237,7 +235,7 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
|
||||
|
||||
if (resources.OES_EGL_image_external)
|
||||
{
|
||||
TType *samplerExternalOES = new TType(EbtSamplerExternalOES);
|
||||
const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES);
|
||||
|
||||
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", samplerExternalOES, float2);
|
||||
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", samplerExternalOES, float3);
|
||||
@ -246,7 +244,7 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
|
||||
|
||||
if (resources.ARB_texture_rectangle)
|
||||
{
|
||||
TType *sampler2DRect = new TType(EbtSampler2DRect);
|
||||
const TType *sampler2DRect = TCache::getType(EbtSampler2DRect);
|
||||
|
||||
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRect", sampler2DRect, float2);
|
||||
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRectProj", sampler2DRect, float3);
|
||||
@ -295,12 +293,12 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
|
||||
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCubeLod", samplerCube, float3, float1);
|
||||
}
|
||||
|
||||
TType *gvec4 = new TType(EbtGVec4);
|
||||
const TType *gvec4 = TCache::getType(EbtGVec4);
|
||||
|
||||
TType *gsampler2D = new TType(EbtGSampler2D);
|
||||
TType *gsamplerCube = new TType(EbtGSamplerCube);
|
||||
TType *gsampler3D = new TType(EbtGSampler3D);
|
||||
TType *gsampler2DArray = new TType(EbtGSampler2DArray);
|
||||
const TType *gsampler2D = TCache::getType(EbtGSampler2D);
|
||||
const TType *gsamplerCube = TCache::getType(EbtGSamplerCube);
|
||||
const TType *gsampler3D = TCache::getType(EbtGSampler3D);
|
||||
const TType *gsampler2DArray = TCache::getType(EbtGSampler2DArray);
|
||||
|
||||
//
|
||||
// Texture Functions for GLSL ES 3.0
|
||||
@ -328,9 +326,9 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
|
||||
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler3D, float4, float1);
|
||||
}
|
||||
|
||||
TType *sampler2DShadow = new TType(EbtSampler2DShadow);
|
||||
TType *samplerCubeShadow = new TType(EbtSamplerCubeShadow);
|
||||
TType *sampler2DArrayShadow = new TType(EbtSampler2DArrayShadow);
|
||||
const TType *sampler2DShadow = TCache::getType(EbtSampler2DShadow);
|
||||
const TType *samplerCubeShadow = TCache::getType(EbtSamplerCubeShadow);
|
||||
const TType *sampler2DArrayShadow = TCache::getType(EbtSampler2DArrayShadow);
|
||||
|
||||
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", sampler2DShadow, float3);
|
||||
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", samplerCubeShadow, float4);
|
||||
@ -466,6 +464,12 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
|
||||
if (spec != SH_CSS_SHADERS_SPEC)
|
||||
{
|
||||
symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxDrawBuffers", resources.MaxDrawBuffers);
|
||||
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", resources.MaxVertexOutputVectors);
|
||||
@ -504,12 +508,33 @@ void IdentifyBuiltIns(sh::GLenum type, ShShaderSpec spec,
|
||||
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_frag_depth)
|
||||
{
|
||||
symbolTable.insert(ESSL1_BUILTINS, "GL_EXT_frag_depth", new TVariable(NewPoolTString("gl_FragDepthEXT"),
|
||||
TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1)));
|
||||
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)));
|
||||
|
||||
if (resources.EXT_shader_framebuffer_fetch || resources.NV_shader_framebuffer_fetch)
|
||||
{
|
||||
TType lastFragData(EbtFloat, EbpMedium, EvqLastFragData, 4, 1, true);
|
||||
@ -569,6 +594,8 @@ void InitExtensionBehavior(const ShBuiltInResources& resources,
|
||||
extBehavior["GL_OES_EGL_image_external"] = EBhUndefined;
|
||||
if (resources.ARB_texture_rectangle)
|
||||
extBehavior["GL_ARB_texture_rectangle"] = EBhUndefined;
|
||||
if (resources.EXT_blend_func_extended)
|
||||
extBehavior["GL_EXT_blend_func_extended"] = EBhUndefined;
|
||||
if (resources.EXT_draw_buffers)
|
||||
extBehavior["GL_EXT_draw_buffers"] = EBhUndefined;
|
||||
if (resources.EXT_frag_depth)
|
||||
|
@ -4,6 +4,7 @@
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
||||
#include "compiler/translator/Cache.h"
|
||||
#include "compiler/translator/InitializeDll.h"
|
||||
#include "compiler/translator/InitializeGlobals.h"
|
||||
#include "compiler/translator/InitializeParseContext.h"
|
||||
@ -24,6 +25,8 @@ bool InitProcess()
|
||||
return false;
|
||||
}
|
||||
|
||||
TCache::initialize();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -31,4 +34,5 @@ void DetachProcess()
|
||||
{
|
||||
FreeParseContextIndex();
|
||||
FreePoolIndex();
|
||||
TCache::destroy();
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
bool InitializeParseContextIndex();
|
||||
void FreeParseContextIndex();
|
||||
|
||||
struct TParseContext;
|
||||
class TParseContext;
|
||||
extern void SetGlobalParseContext(TParseContext* context);
|
||||
extern TParseContext* GetGlobalParseContext();
|
||||
|
||||
|
@ -5,7 +5,8 @@
|
||||
//
|
||||
|
||||
#include "compiler/translator/InitializeVariables.h"
|
||||
#include "compiler/translator/compilerdebug.h"
|
||||
|
||||
#include "common/debug.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -13,10 +14,10 @@ namespace
|
||||
TIntermConstantUnion *constructFloatConstUnionNode(const TType &type)
|
||||
{
|
||||
TType myType = type;
|
||||
unsigned char size = myType.getNominalSize();
|
||||
unsigned char size = static_cast<unsigned char>(myType.getNominalSize());
|
||||
if (myType.isMatrix())
|
||||
size *= size;
|
||||
ConstantUnion *u = new ConstantUnion[size];
|
||||
TConstantUnion *u = new TConstantUnion[size];
|
||||
for (int ii = 0; ii < size; ++ii)
|
||||
u[ii].setFConst(0.0f);
|
||||
|
||||
@ -28,7 +29,7 @@ TIntermConstantUnion *constructFloatConstUnionNode(const TType &type)
|
||||
|
||||
TIntermConstantUnion *constructIndexNode(int index)
|
||||
{
|
||||
ConstantUnion *u = new ConstantUnion[1];
|
||||
TConstantUnion *u = new TConstantUnion[1];
|
||||
u[0].setIConst(index);
|
||||
|
||||
TType type(EbtInt, EbpUndefined, EvqConst, 1);
|
||||
|
@ -26,19 +26,20 @@ class InitializeVariables : public TIntermTraverser
|
||||
typedef TVector<InitVariableInfo> InitVariableInfoList;
|
||||
|
||||
InitializeVariables(const InitVariableInfoList &vars)
|
||||
: mCodeInserted(false),
|
||||
mVariables(vars)
|
||||
: TIntermTraverser(true, false, false),
|
||||
mVariables(vars),
|
||||
mCodeInserted(false)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool visitBinary(Visit, TIntermBinary *node) { return false; }
|
||||
virtual bool visitUnary(Visit, TIntermUnary *node) { return false; }
|
||||
virtual bool visitSelection(Visit, TIntermSelection *node) { return false; }
|
||||
virtual bool visitLoop(Visit, TIntermLoop *node) { return false; }
|
||||
virtual bool visitBranch(Visit, TIntermBranch *node) { return false; }
|
||||
bool visitBinary(Visit, TIntermBinary *node) override { return false; }
|
||||
bool visitUnary(Visit, TIntermUnary *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; }
|
||||
|
||||
virtual bool visitAggregate(Visit visit, TIntermAggregate* node);
|
||||
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
|
||||
|
||||
private:
|
||||
void insertInitCode(TIntermSequence *sequence);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -23,9 +23,9 @@
|
||||
|
||||
#include "common/angleutils.h"
|
||||
#include "compiler/translator/Common.h"
|
||||
#include "compiler/translator/Types.h"
|
||||
#include "compiler/translator/ConstantUnion.h"
|
||||
#include "compiler/translator/Operator.h"
|
||||
#include "compiler/translator/Types.h"
|
||||
|
||||
class TIntermTraverser;
|
||||
class TIntermAggregate;
|
||||
@ -42,10 +42,33 @@ class TInfoSink;
|
||||
class TInfoSinkBase;
|
||||
class TIntermRaw;
|
||||
|
||||
class TSymbolTable;
|
||||
|
||||
// Encapsulate an identifier string and track whether it is coming from the original shader code
|
||||
// (not internal) or from ANGLE (internal). Usually internal names shouldn't be decorated or hashed.
|
||||
class TName
|
||||
{
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE();
|
||||
explicit TName(const TString &name) : mName(name), mIsInternal(false) {}
|
||||
TName() : mName(), mIsInternal(false) {}
|
||||
TName(const TName &) = default;
|
||||
TName &operator=(const TName &) = default;
|
||||
|
||||
const TString &getString() const { return mName; }
|
||||
void setString(const TString &string) { mName = string; }
|
||||
bool isInternal() const { return mIsInternal; }
|
||||
void setInternal(bool isInternal) { mIsInternal = isInternal; }
|
||||
|
||||
private:
|
||||
TString mName;
|
||||
bool mIsInternal;
|
||||
};
|
||||
|
||||
//
|
||||
// Base class for the tree nodes
|
||||
//
|
||||
class TIntermNode
|
||||
class TIntermNode : angle::NonCopyable
|
||||
{
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE();
|
||||
@ -99,7 +122,10 @@ class TIntermTyped : public TIntermNode
|
||||
{
|
||||
public:
|
||||
TIntermTyped(const TType &t) : mType(t) { }
|
||||
virtual TIntermTyped *getAsTyped() { return this; }
|
||||
|
||||
virtual TIntermTyped *deepCopy() const = 0;
|
||||
|
||||
TIntermTyped *getAsTyped() override { return this; }
|
||||
|
||||
virtual bool hasSideEffects() const = 0;
|
||||
|
||||
@ -123,13 +149,14 @@ class TIntermTyped : public TIntermNode
|
||||
bool isScalar() const { return mType.isScalar(); }
|
||||
bool isScalarInt() const { return mType.isScalarInt(); }
|
||||
const char *getBasicString() const { return mType.getBasicString(); }
|
||||
const char *getQualifierString() const { return mType.getQualifierString(); }
|
||||
TString getCompleteString() const { return mType.getCompleteString(); }
|
||||
|
||||
int getArraySize() const { return mType.getArraySize(); }
|
||||
|
||||
protected:
|
||||
TType mType;
|
||||
|
||||
TIntermTyped(const TIntermTyped &node);
|
||||
};
|
||||
|
||||
//
|
||||
@ -146,25 +173,23 @@ class TIntermLoop : public TIntermNode
|
||||
{
|
||||
public:
|
||||
TIntermLoop(TLoopType type,
|
||||
TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
|
||||
TIntermNode *body)
|
||||
: mType(type),
|
||||
mInit(init),
|
||||
mCond(cond),
|
||||
mExpr(expr),
|
||||
mBody(body),
|
||||
mUnrollFlag(false) { }
|
||||
TIntermNode *init,
|
||||
TIntermTyped *cond,
|
||||
TIntermTyped *expr,
|
||||
TIntermAggregate *body)
|
||||
: mType(type), mInit(init), mCond(cond), mExpr(expr), mBody(body), mUnrollFlag(false)
|
||||
{
|
||||
}
|
||||
|
||||
virtual TIntermLoop *getAsLoopNode() { return this; }
|
||||
virtual void traverse(TIntermTraverser *);
|
||||
virtual bool replaceChildNode(
|
||||
TIntermNode *original, TIntermNode *replacement);
|
||||
TIntermLoop *getAsLoopNode() override { return this; }
|
||||
void traverse(TIntermTraverser *it) override;
|
||||
bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
|
||||
|
||||
TLoopType getType() const { return mType; }
|
||||
TIntermNode *getInit() { return mInit; }
|
||||
TIntermTyped *getCondition() { return mCond; }
|
||||
TIntermTyped *getExpression() { return mExpr; }
|
||||
TIntermNode *getBody() { return mBody; }
|
||||
TIntermAggregate *getBody() { return mBody; }
|
||||
|
||||
void setUnrollFlag(bool flag) { mUnrollFlag = flag; }
|
||||
bool getUnrollFlag() const { return mUnrollFlag; }
|
||||
@ -174,7 +199,7 @@ class TIntermLoop : public TIntermNode
|
||||
TIntermNode *mInit; // for-loop initialization
|
||||
TIntermTyped *mCond; // loop exit condition
|
||||
TIntermTyped *mExpr; // for-loop expression
|
||||
TIntermNode *mBody; // loop body
|
||||
TIntermAggregate *mBody; // loop body
|
||||
|
||||
bool mUnrollFlag; // Whether the loop should be unrolled or not.
|
||||
};
|
||||
@ -189,9 +214,8 @@ class TIntermBranch : public TIntermNode
|
||||
: mFlowOp(op),
|
||||
mExpression(e) { }
|
||||
|
||||
virtual void traverse(TIntermTraverser *);
|
||||
virtual bool replaceChildNode(
|
||||
TIntermNode *original, TIntermNode *replacement);
|
||||
void traverse(TIntermTraverser *it) override;
|
||||
bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
|
||||
|
||||
TOperator getFlowOp() { return mFlowOp; }
|
||||
TIntermTyped* getExpression() { return mExpression; }
|
||||
@ -211,26 +235,32 @@ class TIntermSymbol : public TIntermTyped
|
||||
// If sym comes from per process globalpoolallocator, then it causes increased memory usage
|
||||
// per compile it is essential to use "symbol = sym" to assign to symbol
|
||||
TIntermSymbol(int id, const TString &symbol, const TType &type)
|
||||
: TIntermTyped(type),
|
||||
mId(id)
|
||||
: TIntermTyped(type), mId(id), mSymbol(symbol)
|
||||
{
|
||||
mSymbol = symbol;
|
||||
}
|
||||
|
||||
virtual bool hasSideEffects() const { return false; }
|
||||
TIntermTyped *deepCopy() const override { return new TIntermSymbol(*this); }
|
||||
|
||||
bool hasSideEffects() const override { return false; }
|
||||
|
||||
int getId() const { return mId; }
|
||||
const TString &getSymbol() const { return mSymbol; }
|
||||
const TString &getSymbol() const { return mSymbol.getString(); }
|
||||
const TName &getName() const { return mSymbol; }
|
||||
|
||||
void setId(int newId) { mId = newId; }
|
||||
|
||||
virtual void traverse(TIntermTraverser *);
|
||||
virtual TIntermSymbol *getAsSymbolNode() { return this; }
|
||||
virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
|
||||
void setInternal(bool internal) { mSymbol.setInternal(internal); }
|
||||
|
||||
void traverse(TIntermTraverser *it) override;
|
||||
TIntermSymbol *getAsSymbolNode() override { return this; }
|
||||
bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; }
|
||||
|
||||
protected:
|
||||
int mId;
|
||||
TString mSymbol;
|
||||
TName mSymbol;
|
||||
|
||||
private:
|
||||
TIntermSymbol(const TIntermSymbol &) = default; // Note: not deleted, just private!
|
||||
};
|
||||
|
||||
// A Raw node stores raw code, that the translator will insert verbatim
|
||||
@ -242,30 +272,46 @@ class TIntermRaw : public TIntermTyped
|
||||
TIntermRaw(const TType &type, const TString &rawText)
|
||||
: TIntermTyped(type),
|
||||
mRawText(rawText) { }
|
||||
TIntermRaw(const TIntermRaw &) = delete;
|
||||
|
||||
virtual bool hasSideEffects() const { return false; }
|
||||
TIntermTyped *deepCopy() const override
|
||||
{
|
||||
UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool hasSideEffects() const override { return false; }
|
||||
|
||||
TString getRawText() const { return mRawText; }
|
||||
|
||||
virtual void traverse(TIntermTraverser *);
|
||||
void traverse(TIntermTraverser *it) override;
|
||||
|
||||
virtual TIntermRaw *getAsRawNode() { return this; }
|
||||
virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
|
||||
TIntermRaw *getAsRawNode() override { return this; }
|
||||
bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; }
|
||||
|
||||
protected:
|
||||
TString mRawText;
|
||||
};
|
||||
|
||||
// Constant folded node.
|
||||
// Note that nodes may be constant folded and not be constant expressions with the EvqConst
|
||||
// qualifier. This happens for example when the following expression is processed:
|
||||
// "true ? 1.0 : non_constant"
|
||||
// Other nodes than TIntermConstantUnion may also be constant expressions.
|
||||
//
|
||||
class TIntermConstantUnion : public TIntermTyped
|
||||
{
|
||||
public:
|
||||
TIntermConstantUnion(ConstantUnion *unionPointer, const TType &type)
|
||||
: TIntermTyped(type),
|
||||
mUnionArrayPointer(unionPointer) { }
|
||||
TIntermConstantUnion(const TConstantUnion *unionPointer, const TType &type)
|
||||
: TIntermTyped(type), mUnionArrayPointer(unionPointer)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool hasSideEffects() const { return false; }
|
||||
TIntermTyped *deepCopy() const override { return new TIntermConstantUnion(*this); }
|
||||
|
||||
ConstantUnion *getUnionArrayPointer() const { return mUnionArrayPointer; }
|
||||
bool hasSideEffects() const override { return false; }
|
||||
|
||||
const TConstantUnion *getUnionArrayPointer() const { return mUnionArrayPointer; }
|
||||
|
||||
int getIConst(size_t index) const
|
||||
{
|
||||
@ -284,14 +330,33 @@ class TIntermConstantUnion : public TIntermTyped
|
||||
return mUnionArrayPointer ? mUnionArrayPointer[index].getBConst() : false;
|
||||
}
|
||||
|
||||
virtual TIntermConstantUnion *getAsConstantUnion() { return this; }
|
||||
virtual void traverse(TIntermTraverser *);
|
||||
virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
|
||||
void replaceConstantUnion(const TConstantUnion *safeConstantUnion)
|
||||
{
|
||||
// Previous union pointer freed on pool deallocation.
|
||||
mUnionArrayPointer = safeConstantUnion;
|
||||
}
|
||||
|
||||
TIntermTyped *fold(TOperator, TIntermTyped *, TInfoSink &);
|
||||
TIntermConstantUnion *getAsConstantUnion() override { return this; }
|
||||
void traverse(TIntermTraverser *it) override;
|
||||
bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; }
|
||||
|
||||
TConstantUnion *foldBinary(TOperator op, TIntermConstantUnion *rightNode, TInfoSink &infoSink);
|
||||
TConstantUnion *foldUnaryWithDifferentReturnType(TOperator op, TInfoSink &infoSink);
|
||||
TConstantUnion *foldUnaryWithSameReturnType(TOperator op, TInfoSink &infoSink);
|
||||
|
||||
static TConstantUnion *FoldAggregateConstructor(TIntermAggregate *aggregate,
|
||||
TInfoSink &infoSink);
|
||||
static TConstantUnion *FoldAggregateBuiltIn(TIntermAggregate *aggregate, TInfoSink &infoSink);
|
||||
|
||||
protected:
|
||||
ConstantUnion *mUnionArrayPointer;
|
||||
// Same data may be shared between multiple constant unions, so it can't be modified.
|
||||
const TConstantUnion *mUnionArrayPointer;
|
||||
|
||||
private:
|
||||
typedef float(*FloatTypeUnaryFunc) (float);
|
||||
bool foldFloatTypeUnary(const TConstantUnion ¶meter, FloatTypeUnaryFunc builtinFunc, TInfoSink &infoSink, TConstantUnion *result) const;
|
||||
|
||||
TIntermConstantUnion(const TIntermConstantUnion &node); // Note: not deleted, just private!
|
||||
};
|
||||
|
||||
//
|
||||
@ -304,9 +369,10 @@ class TIntermOperator : public TIntermTyped
|
||||
void setOp(TOperator op) { mOp = op; }
|
||||
|
||||
bool isAssignment() const;
|
||||
bool isMultiplication() const;
|
||||
bool isConstructor() const;
|
||||
|
||||
virtual bool hasSideEffects() const { return isAssignment(); }
|
||||
bool hasSideEffects() const override { return isAssignment(); }
|
||||
|
||||
protected:
|
||||
TIntermOperator(TOperator op)
|
||||
@ -316,6 +382,8 @@ class TIntermOperator : public TIntermTyped
|
||||
: TIntermTyped(type),
|
||||
mOp(op) {}
|
||||
|
||||
TIntermOperator(const TIntermOperator &) = default;
|
||||
|
||||
TOperator mOp;
|
||||
};
|
||||
|
||||
@ -329,12 +397,13 @@ class TIntermBinary : public TIntermOperator
|
||||
: TIntermOperator(op),
|
||||
mAddIndexClamp(false) {}
|
||||
|
||||
virtual TIntermBinary *getAsBinaryNode() { return this; }
|
||||
virtual void traverse(TIntermTraverser *);
|
||||
virtual bool replaceChildNode(
|
||||
TIntermNode *original, TIntermNode *replacement);
|
||||
TIntermTyped *deepCopy() const override { return new TIntermBinary(*this); }
|
||||
|
||||
virtual bool hasSideEffects() const
|
||||
TIntermBinary *getAsBinaryNode() override { return this; };
|
||||
void traverse(TIntermTraverser *it) override;
|
||||
bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
|
||||
|
||||
bool hasSideEffects() const override
|
||||
{
|
||||
return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects();
|
||||
}
|
||||
@ -344,6 +413,7 @@ class TIntermBinary : public TIntermOperator
|
||||
TIntermTyped *getLeft() const { return mLeft; }
|
||||
TIntermTyped *getRight() const { return mRight; }
|
||||
bool promote(TInfoSink &);
|
||||
TIntermTyped *fold(TInfoSink &infoSink);
|
||||
|
||||
void setAddIndexClamp() { mAddIndexClamp = true; }
|
||||
bool getAddIndexClamp() { return mAddIndexClamp; }
|
||||
@ -354,6 +424,9 @@ class TIntermBinary : public TIntermOperator
|
||||
|
||||
// If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
|
||||
bool mAddIndexClamp;
|
||||
|
||||
private:
|
||||
TIntermBinary(const TIntermBinary &node); // Note: not deleted, just private!
|
||||
};
|
||||
|
||||
//
|
||||
@ -371,19 +444,18 @@ class TIntermUnary : public TIntermOperator
|
||||
mOperand(NULL),
|
||||
mUseEmulatedFunction(false) {}
|
||||
|
||||
virtual void traverse(TIntermTraverser *);
|
||||
virtual TIntermUnary *getAsUnaryNode() { return this; }
|
||||
virtual bool replaceChildNode(
|
||||
TIntermNode *original, TIntermNode *replacement);
|
||||
TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); }
|
||||
|
||||
virtual bool hasSideEffects() const
|
||||
{
|
||||
return isAssignment() || mOperand->hasSideEffects();
|
||||
}
|
||||
void traverse(TIntermTraverser *it) override;
|
||||
TIntermUnary *getAsUnaryNode() override { return this; }
|
||||
bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
|
||||
|
||||
bool hasSideEffects() const override { return isAssignment() || mOperand->hasSideEffects(); }
|
||||
|
||||
void setOperand(TIntermTyped *operand) { mOperand = operand; }
|
||||
TIntermTyped *getOperand() { return mOperand; }
|
||||
void promote(const TType *funcReturnType);
|
||||
TIntermTyped *fold(TInfoSink &infoSink);
|
||||
|
||||
void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
|
||||
bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
|
||||
@ -394,6 +466,9 @@ class TIntermUnary : public TIntermOperator
|
||||
// If set to true, replace the built-in function call with an emulated one
|
||||
// to work around driver bugs.
|
||||
bool mUseEmulatedFunction;
|
||||
|
||||
private:
|
||||
TIntermUnary(const TIntermUnary &node); // note: not deleted, just private!
|
||||
};
|
||||
|
||||
typedef TVector<TIntermNode *> TIntermSequence;
|
||||
@ -408,52 +483,68 @@ class TIntermAggregate : public TIntermOperator
|
||||
TIntermAggregate()
|
||||
: TIntermOperator(EOpNull),
|
||||
mUserDefined(false),
|
||||
mUseEmulatedFunction(false) { }
|
||||
mUseEmulatedFunction(false),
|
||||
mGotPrecisionFromChildren(false)
|
||||
{
|
||||
}
|
||||
TIntermAggregate(TOperator op)
|
||||
: TIntermOperator(op),
|
||||
mUseEmulatedFunction(false) { }
|
||||
mUseEmulatedFunction(false),
|
||||
mGotPrecisionFromChildren(false)
|
||||
{
|
||||
}
|
||||
~TIntermAggregate() { }
|
||||
|
||||
virtual TIntermAggregate *getAsAggregate() { return this; }
|
||||
virtual void traverse(TIntermTraverser *);
|
||||
virtual bool replaceChildNode(
|
||||
TIntermNode *original, TIntermNode *replacement);
|
||||
// Note: only supported for nodes that can be a part of an expression.
|
||||
TIntermTyped *deepCopy() const override { return new TIntermAggregate(*this); }
|
||||
|
||||
TIntermAggregate *getAsAggregate() override { return this; }
|
||||
void traverse(TIntermTraverser *it) override;
|
||||
bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
|
||||
bool replaceChildNodeWithMultiple(TIntermNode *original, TIntermSequence replacements);
|
||||
bool insertChildNodes(TIntermSequence::size_type position, TIntermSequence insertions);
|
||||
// Conservatively assume function calls and other aggregate operators have side-effects
|
||||
virtual bool hasSideEffects() const { return true; }
|
||||
bool hasSideEffects() const override { return true; }
|
||||
TIntermTyped *fold(TInfoSink &infoSink);
|
||||
|
||||
TIntermSequence *getSequence() { return &mSequence; }
|
||||
|
||||
void setName(const TString &name) { mName = name; }
|
||||
const TString &getName() const { return mName; }
|
||||
void setNameObj(const TName &name) { mName = name; }
|
||||
const TName &getNameObj() const { return mName; }
|
||||
|
||||
void setName(const TString &name) { mName.setString(name); }
|
||||
const TString &getName() const { return mName.getString(); }
|
||||
|
||||
void setUserDefined() { mUserDefined = true; }
|
||||
bool isUserDefined() const { return mUserDefined; }
|
||||
|
||||
void setOptimize(bool optimize) { mOptimize = optimize; }
|
||||
bool getOptimize() const { return mOptimize; }
|
||||
void setDebug(bool debug) { mDebug = debug; }
|
||||
bool getDebug() const { return mDebug; }
|
||||
void setFunctionId(int functionId) { mFunctionId = functionId; }
|
||||
int getFunctionId() const { return mFunctionId; }
|
||||
|
||||
void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
|
||||
bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
|
||||
|
||||
bool areChildrenConstQualified();
|
||||
void setPrecisionFromChildren();
|
||||
void setBuiltInFunctionPrecision();
|
||||
|
||||
protected:
|
||||
TIntermAggregate(const TIntermAggregate &); // disallow copy constructor
|
||||
TIntermAggregate &operator=(const TIntermAggregate &); // disallow assignment operator
|
||||
TIntermSequence mSequence;
|
||||
TString mName;
|
||||
bool mUserDefined; // used for user defined function names
|
||||
// Returns true if changing parameter precision may affect the return value.
|
||||
bool gotPrecisionFromChildren() const { return mGotPrecisionFromChildren; }
|
||||
|
||||
bool mOptimize;
|
||||
bool mDebug;
|
||||
protected:
|
||||
TIntermSequence mSequence;
|
||||
TName mName;
|
||||
bool mUserDefined; // used for user defined function names
|
||||
int mFunctionId;
|
||||
|
||||
// If set to true, replace the built-in function call with an emulated one
|
||||
// to work around driver bugs.
|
||||
bool mUseEmulatedFunction;
|
||||
|
||||
bool mGotPrecisionFromChildren;
|
||||
|
||||
private:
|
||||
TIntermAggregate(const TIntermAggregate &node); // note: not deleted, just private!
|
||||
};
|
||||
|
||||
//
|
||||
@ -474,23 +565,28 @@ class TIntermSelection : public TIntermTyped
|
||||
mTrueBlock(trueB),
|
||||
mFalseBlock(falseB) {}
|
||||
|
||||
virtual void traverse(TIntermTraverser *);
|
||||
virtual bool replaceChildNode(
|
||||
TIntermNode *original, TIntermNode *replacement);
|
||||
// Note: only supported for ternary operator nodes.
|
||||
TIntermTyped *deepCopy() const override { return new TIntermSelection(*this); }
|
||||
|
||||
void traverse(TIntermTraverser *it) override;
|
||||
bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
|
||||
|
||||
// Conservatively assume selections have side-effects
|
||||
virtual bool hasSideEffects() const { return true; }
|
||||
bool hasSideEffects() const override { return true; }
|
||||
|
||||
bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
|
||||
TIntermNode *getCondition() const { return mCondition; }
|
||||
TIntermNode *getTrueBlock() const { return mTrueBlock; }
|
||||
TIntermNode *getFalseBlock() const { return mFalseBlock; }
|
||||
TIntermSelection *getAsSelectionNode() { return this; }
|
||||
TIntermSelection *getAsSelectionNode() override { return this; }
|
||||
|
||||
protected:
|
||||
protected:
|
||||
TIntermTyped *mCondition;
|
||||
TIntermNode *mTrueBlock;
|
||||
TIntermNode *mFalseBlock;
|
||||
|
||||
private:
|
||||
TIntermSelection(const TIntermSelection &node); // Note: not deleted, just private!
|
||||
};
|
||||
|
||||
//
|
||||
@ -512,6 +608,7 @@ class TIntermSwitch : public TIntermNode
|
||||
|
||||
TIntermSwitch *getAsSwitchNode() override { return this; }
|
||||
|
||||
TIntermTyped *getInit() { return mInit; }
|
||||
TIntermAggregate *getStatementList() { return mStatementList; }
|
||||
void setStatementList(TIntermAggregate *statementList) { mStatementList = statementList; }
|
||||
|
||||
@ -553,9 +650,12 @@ enum Visit
|
||||
};
|
||||
|
||||
//
|
||||
// For traversing the tree. User should derive from this,
|
||||
// put their traversal specific data in it, and then pass
|
||||
// it to a Traverse method.
|
||||
// For traversing the tree. User should derive from this class overriding the visit functions,
|
||||
// and then pass an object of the subclass to a traverse method of a node.
|
||||
//
|
||||
// The traverse*() functions may also be overridden do other bookkeeping on the tree to provide
|
||||
// contextual information to the visit functions, such as whether the node is the target of an
|
||||
// assignment.
|
||||
//
|
||||
// When using this, just fill in the methods for nodes you want visited.
|
||||
// Return false from a pre-visit to skip visiting that node's subtree.
|
||||
@ -564,31 +664,59 @@ class TIntermTraverser : angle::NonCopyable
|
||||
{
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE();
|
||||
// TODO(zmo): remove default values.
|
||||
TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false,
|
||||
bool rightToLeft = false)
|
||||
TIntermTraverser(bool preVisit, bool inVisit, bool postVisit)
|
||||
: preVisit(preVisit),
|
||||
inVisit(inVisit),
|
||||
postVisit(postVisit),
|
||||
rightToLeft(rightToLeft),
|
||||
mDepth(0),
|
||||
mMaxDepth(0) {}
|
||||
mMaxDepth(0),
|
||||
mTemporaryIndex(nullptr)
|
||||
{
|
||||
}
|
||||
virtual ~TIntermTraverser() {}
|
||||
|
||||
virtual void visitSymbol(TIntermSymbol *) {}
|
||||
virtual void visitRaw(TIntermRaw *) {}
|
||||
virtual void visitConstantUnion(TIntermConstantUnion *) {}
|
||||
virtual bool visitBinary(Visit, TIntermBinary *) { return true; }
|
||||
virtual bool visitUnary(Visit, TIntermUnary *) { return true; }
|
||||
virtual bool visitSelection(Visit, TIntermSelection *) { return true; }
|
||||
virtual bool visitSwitch(Visit, TIntermSwitch *) { return true; }
|
||||
virtual bool visitCase(Visit, TIntermCase *) { return true; }
|
||||
virtual bool visitAggregate(Visit, TIntermAggregate *) { return true; }
|
||||
virtual bool visitLoop(Visit, TIntermLoop *) { return true; }
|
||||
virtual bool visitBranch(Visit, TIntermBranch *) { return true; }
|
||||
virtual void visitSymbol(TIntermSymbol *node) {}
|
||||
virtual void visitRaw(TIntermRaw *node) {}
|
||||
virtual void visitConstantUnion(TIntermConstantUnion *node) {}
|
||||
virtual bool visitBinary(Visit visit, TIntermBinary *node) { return true; }
|
||||
virtual bool visitUnary(Visit visit, TIntermUnary *node) { return true; }
|
||||
virtual bool visitSelection(Visit visit, TIntermSelection *node) { return true; }
|
||||
virtual bool visitSwitch(Visit visit, TIntermSwitch *node) { return true; }
|
||||
virtual bool visitCase(Visit visit, TIntermCase *node) { return true; }
|
||||
virtual bool visitAggregate(Visit visit, TIntermAggregate *node) { return true; }
|
||||
virtual bool visitLoop(Visit visit, TIntermLoop *node) { return true; }
|
||||
virtual bool visitBranch(Visit visit, TIntermBranch *node) { return true; }
|
||||
|
||||
// The traverse functions contain logic for iterating over the children of the node
|
||||
// and calling the visit functions in the appropriate places. They also track some
|
||||
// context that may be used by the visit functions.
|
||||
virtual void traverseSymbol(TIntermSymbol *node);
|
||||
virtual void traverseRaw(TIntermRaw *node);
|
||||
virtual void traverseConstantUnion(TIntermConstantUnion *node);
|
||||
virtual void traverseBinary(TIntermBinary *node);
|
||||
virtual void traverseUnary(TIntermUnary *node);
|
||||
virtual void traverseSelection(TIntermSelection *node);
|
||||
virtual void traverseSwitch(TIntermSwitch *node);
|
||||
virtual void traverseCase(TIntermCase *node);
|
||||
virtual void traverseAggregate(TIntermAggregate *node);
|
||||
virtual void traverseLoop(TIntermLoop *node);
|
||||
virtual void traverseBranch(TIntermBranch *node);
|
||||
|
||||
int getMaxDepth() const { return mMaxDepth; }
|
||||
|
||||
// Return the original name if hash function pointer is NULL;
|
||||
// otherwise return the hashed name.
|
||||
static TString hash(const TString &name, ShHashFunction64 hashFunction);
|
||||
|
||||
// If traversers need to replace nodes, they can add the replacements in
|
||||
// mReplacements/mMultiReplacements during traversal and the user of the traverser should call
|
||||
// this function after traversal to perform them.
|
||||
void updateTree();
|
||||
|
||||
// Start creating temporary symbols from the given temporary symbol index + 1.
|
||||
void useTemporaryIndex(unsigned int *temporaryIndex);
|
||||
|
||||
protected:
|
||||
void incrementDepth(TIntermNode *current)
|
||||
{
|
||||
mDepth++;
|
||||
@ -607,27 +735,26 @@ class TIntermTraverser : angle::NonCopyable
|
||||
return mPath.size() == 0 ? NULL : mPath.back();
|
||||
}
|
||||
|
||||
// Return the original name if hash function pointer is NULL;
|
||||
// otherwise return the hashed name.
|
||||
static TString hash(const TString& name, ShHashFunction64 hashFunction);
|
||||
void pushParentBlock(TIntermAggregate *node);
|
||||
void incrementParentBlockPos();
|
||||
void popParentBlock();
|
||||
|
||||
bool parentNodeIsBlock()
|
||||
{
|
||||
return !mParentBlockStack.empty() && getParentNode() == mParentBlockStack.back().node;
|
||||
}
|
||||
|
||||
const bool preVisit;
|
||||
const bool inVisit;
|
||||
const bool postVisit;
|
||||
const bool rightToLeft;
|
||||
|
||||
// If traversers need to replace nodes, they can add the replacements in
|
||||
// mReplacements during traversal and the user of the traverser should call
|
||||
// this function after traversal to perform them.
|
||||
void updateTree();
|
||||
|
||||
protected:
|
||||
int mDepth;
|
||||
int mMaxDepth;
|
||||
|
||||
// All the nodes from root to the current node's parent during traversing.
|
||||
TVector<TIntermNode *> mPath;
|
||||
|
||||
// To replace a single node with another on the parent node
|
||||
struct NodeUpdateEntry
|
||||
{
|
||||
NodeUpdateEntry(TIntermNode *_parent,
|
||||
@ -645,9 +772,166 @@ class TIntermTraverser : angle::NonCopyable
|
||||
bool originalBecomesChildOfReplacement;
|
||||
};
|
||||
|
||||
// To replace a single node with multiple nodes on the parent aggregate node
|
||||
struct NodeReplaceWithMultipleEntry
|
||||
{
|
||||
NodeReplaceWithMultipleEntry(TIntermAggregate *_parent, TIntermNode *_original, TIntermSequence _replacements)
|
||||
: parent(_parent),
|
||||
original(_original),
|
||||
replacements(_replacements)
|
||||
{
|
||||
}
|
||||
|
||||
TIntermAggregate *parent;
|
||||
TIntermNode *original;
|
||||
TIntermSequence replacements;
|
||||
};
|
||||
|
||||
// To insert multiple nodes on the parent aggregate node
|
||||
struct NodeInsertMultipleEntry
|
||||
{
|
||||
NodeInsertMultipleEntry(TIntermAggregate *_parent,
|
||||
TIntermSequence::size_type _position,
|
||||
TIntermSequence _insertionsBefore,
|
||||
TIntermSequence _insertionsAfter)
|
||||
: parent(_parent),
|
||||
position(_position),
|
||||
insertionsBefore(_insertionsBefore),
|
||||
insertionsAfter(_insertionsAfter)
|
||||
{
|
||||
}
|
||||
|
||||
TIntermAggregate *parent;
|
||||
TIntermSequence::size_type position;
|
||||
TIntermSequence insertionsBefore;
|
||||
TIntermSequence insertionsAfter;
|
||||
};
|
||||
|
||||
// During traversing, save all the changes that need to happen into
|
||||
// mReplacements, then do them by calling updateTree().
|
||||
// mReplacements/mMultiReplacements, then do them by calling updateTree().
|
||||
// Multi replacements are processed after single replacements.
|
||||
std::vector<NodeUpdateEntry> mReplacements;
|
||||
std::vector<NodeReplaceWithMultipleEntry> mMultiReplacements;
|
||||
std::vector<NodeInsertMultipleEntry> mInsertions;
|
||||
|
||||
// Helper to insert statements in the parent block (sequence) of the node currently being traversed.
|
||||
// The statements will be inserted before the node being traversed once updateTree is called.
|
||||
// Should only be called during PreVisit or PostVisit from sequence nodes.
|
||||
// Note that inserting more than one set of nodes to the same parent node on a single updateTree call is not
|
||||
// supported.
|
||||
void insertStatementsInParentBlock(const TIntermSequence &insertions);
|
||||
|
||||
// Same as above, but supports simultaneous insertion of statements before and after the node
|
||||
// currently being traversed.
|
||||
void insertStatementsInParentBlock(const TIntermSequence &insertionsBefore,
|
||||
const TIntermSequence &insertionsAfter);
|
||||
|
||||
// Helper to create a temporary symbol node with the given qualifier.
|
||||
TIntermSymbol *createTempSymbol(const TType &type, TQualifier qualifier);
|
||||
// Helper to create a temporary symbol node.
|
||||
TIntermSymbol *createTempSymbol(const TType &type);
|
||||
// Create a node that declares but doesn't initialize a temporary symbol.
|
||||
TIntermAggregate *createTempDeclaration(const TType &type);
|
||||
// Create a node that initializes the current temporary symbol with initializer having the given qualifier.
|
||||
TIntermAggregate *createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier);
|
||||
// Create a node that initializes the current temporary symbol with initializer.
|
||||
TIntermAggregate *createTempInitDeclaration(TIntermTyped *initializer);
|
||||
// Create a node that assigns rightNode to the current temporary symbol.
|
||||
TIntermBinary *createTempAssignment(TIntermTyped *rightNode);
|
||||
// Increment temporary symbol index.
|
||||
void nextTemporaryIndex();
|
||||
|
||||
private:
|
||||
struct ParentBlock
|
||||
{
|
||||
ParentBlock(TIntermAggregate *nodeIn, TIntermSequence::size_type posIn)
|
||||
: node(nodeIn),
|
||||
pos(posIn)
|
||||
{
|
||||
}
|
||||
|
||||
TIntermAggregate *node;
|
||||
TIntermSequence::size_type pos;
|
||||
};
|
||||
// All the code blocks from the root to the current node's parent during traversal.
|
||||
std::vector<ParentBlock> mParentBlockStack;
|
||||
|
||||
unsigned int *mTemporaryIndex;
|
||||
};
|
||||
|
||||
// Traverser parent class that tracks where a node is a destination of a write operation and so is
|
||||
// required to be an l-value.
|
||||
class TLValueTrackingTraverser : public TIntermTraverser
|
||||
{
|
||||
public:
|
||||
TLValueTrackingTraverser(bool preVisit,
|
||||
bool inVisit,
|
||||
bool postVisit,
|
||||
const TSymbolTable &symbolTable,
|
||||
int shaderVersion)
|
||||
: TIntermTraverser(preVisit, inVisit, postVisit),
|
||||
mOperatorRequiresLValue(false),
|
||||
mInFunctionCallOutParameter(false),
|
||||
mSymbolTable(symbolTable),
|
||||
mShaderVersion(shaderVersion)
|
||||
{
|
||||
}
|
||||
virtual ~TLValueTrackingTraverser() {}
|
||||
|
||||
void traverseBinary(TIntermBinary *node) override;
|
||||
void traverseUnary(TIntermUnary *node) override;
|
||||
void traverseAggregate(TIntermAggregate *node) override;
|
||||
|
||||
protected:
|
||||
bool isLValueRequiredHere() const
|
||||
{
|
||||
return mOperatorRequiresLValue || mInFunctionCallOutParameter;
|
||||
}
|
||||
|
||||
// Return true if the prototype or definition of the function being called has been encountered
|
||||
// during traversal.
|
||||
bool isInFunctionMap(const TIntermAggregate *callNode) const;
|
||||
|
||||
private:
|
||||
// Track whether an l-value is required in the node that is currently being traversed by the
|
||||
// surrounding operator.
|
||||
// Use isLValueRequiredHere to check all conditions which require an l-value.
|
||||
void setOperatorRequiresLValue(bool lValueRequired)
|
||||
{
|
||||
mOperatorRequiresLValue = lValueRequired;
|
||||
}
|
||||
bool operatorRequiresLValue() const { return mOperatorRequiresLValue; }
|
||||
|
||||
// Add a function encountered during traversal to the function map.
|
||||
void addToFunctionMap(const TName &name, TIntermSequence *paramSequence);
|
||||
|
||||
// Return the parameters sequence from the function definition or prototype.
|
||||
TIntermSequence *getFunctionParameters(const TIntermAggregate *callNode);
|
||||
|
||||
// Track whether an l-value is required inside a function call.
|
||||
void setInFunctionCallOutParameter(bool inOutParameter);
|
||||
bool isInFunctionCallOutParameter() const;
|
||||
|
||||
bool mOperatorRequiresLValue;
|
||||
bool mInFunctionCallOutParameter;
|
||||
|
||||
struct TNameComparator
|
||||
{
|
||||
bool operator()(const TName &a, const TName &b) const
|
||||
{
|
||||
int compareResult = a.getString().compare(b.getString());
|
||||
if (compareResult != 0)
|
||||
return compareResult < 0;
|
||||
// Internal functions may have same names as non-internal functions.
|
||||
return !a.isInternal() && b.isInternal();
|
||||
}
|
||||
};
|
||||
|
||||
// Map from mangled function names to their parameter sequences
|
||||
TMap<TName, TIntermSequence *, TNameComparator> mFunctionMap;
|
||||
|
||||
const TSymbolTable &mSymbolTable;
|
||||
const int mShaderVersion;
|
||||
};
|
||||
|
||||
//
|
||||
@ -659,15 +943,15 @@ class TMaxDepthTraverser : public TIntermTraverser
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE();
|
||||
TMaxDepthTraverser(int depthLimit)
|
||||
: TIntermTraverser(true, true, false, false),
|
||||
: TIntermTraverser(true, true, false),
|
||||
mDepthLimit(depthLimit) { }
|
||||
|
||||
virtual bool visitBinary(Visit, TIntermBinary *) { return depthCheck(); }
|
||||
virtual bool visitUnary(Visit, TIntermUnary *) { return depthCheck(); }
|
||||
virtual bool visitSelection(Visit, TIntermSelection *) { return depthCheck(); }
|
||||
virtual bool visitAggregate(Visit, TIntermAggregate *) { return depthCheck(); }
|
||||
virtual bool visitLoop(Visit, TIntermLoop *) { return depthCheck(); }
|
||||
virtual bool visitBranch(Visit, TIntermBranch *) { return depthCheck(); }
|
||||
bool visitBinary(Visit, TIntermBinary *) override { return depthCheck(); }
|
||||
bool visitUnary(Visit, TIntermUnary *) override { return depthCheck(); }
|
||||
bool visitSelection(Visit, TIntermSelection *) override { return depthCheck(); }
|
||||
bool visitAggregate(Visit, TIntermAggregate *) override { return depthCheck(); }
|
||||
bool visitLoop(Visit, TIntermLoop *) override { return depthCheck(); }
|
||||
bool visitBranch(Visit, TIntermBranch *) override { return depthCheck(); }
|
||||
|
||||
protected:
|
||||
bool depthCheck() const { return mMaxDepth < mDepthLimit; }
|
||||
|
@ -5,6 +5,187 @@
|
||||
//
|
||||
|
||||
#include "compiler/translator/IntermNode.h"
|
||||
#include "compiler/translator/InfoSink.h"
|
||||
#include "compiler/translator/SymbolTable.h"
|
||||
|
||||
void TIntermSymbol::traverse(TIntermTraverser *it)
|
||||
{
|
||||
it->traverseSymbol(this);
|
||||
}
|
||||
|
||||
void TIntermRaw::traverse(TIntermTraverser *it)
|
||||
{
|
||||
it->traverseRaw(this);
|
||||
}
|
||||
|
||||
void TIntermConstantUnion::traverse(TIntermTraverser *it)
|
||||
{
|
||||
it->traverseConstantUnion(this);
|
||||
}
|
||||
|
||||
void TIntermBinary::traverse(TIntermTraverser *it)
|
||||
{
|
||||
it->traverseBinary(this);
|
||||
}
|
||||
|
||||
void TIntermUnary::traverse(TIntermTraverser *it)
|
||||
{
|
||||
it->traverseUnary(this);
|
||||
}
|
||||
|
||||
void TIntermSelection::traverse(TIntermTraverser *it)
|
||||
{
|
||||
it->traverseSelection(this);
|
||||
}
|
||||
|
||||
void TIntermSwitch::traverse(TIntermTraverser *it)
|
||||
{
|
||||
it->traverseSwitch(this);
|
||||
}
|
||||
|
||||
void TIntermCase::traverse(TIntermTraverser *it)
|
||||
{
|
||||
it->traverseCase(this);
|
||||
}
|
||||
|
||||
void TIntermAggregate::traverse(TIntermTraverser *it)
|
||||
{
|
||||
it->traverseAggregate(this);
|
||||
}
|
||||
|
||||
void TIntermLoop::traverse(TIntermTraverser *it)
|
||||
{
|
||||
it->traverseLoop(this);
|
||||
}
|
||||
|
||||
void TIntermBranch::traverse(TIntermTraverser *it)
|
||||
{
|
||||
it->traverseBranch(this);
|
||||
}
|
||||
|
||||
void TIntermTraverser::pushParentBlock(TIntermAggregate *node)
|
||||
{
|
||||
mParentBlockStack.push_back(ParentBlock(node, 0));
|
||||
}
|
||||
|
||||
void TIntermTraverser::incrementParentBlockPos()
|
||||
{
|
||||
++mParentBlockStack.back().pos;
|
||||
}
|
||||
|
||||
void TIntermTraverser::popParentBlock()
|
||||
{
|
||||
ASSERT(!mParentBlockStack.empty());
|
||||
mParentBlockStack.pop_back();
|
||||
}
|
||||
|
||||
void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertions)
|
||||
{
|
||||
TIntermSequence emptyInsertionsAfter;
|
||||
insertStatementsInParentBlock(insertions, emptyInsertionsAfter);
|
||||
}
|
||||
|
||||
void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &insertionsBefore,
|
||||
const TIntermSequence &insertionsAfter)
|
||||
{
|
||||
ASSERT(!mParentBlockStack.empty());
|
||||
NodeInsertMultipleEntry insert(mParentBlockStack.back().node, mParentBlockStack.back().pos,
|
||||
insertionsBefore, insertionsAfter);
|
||||
mInsertions.push_back(insert);
|
||||
}
|
||||
|
||||
TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type, TQualifier qualifier)
|
||||
{
|
||||
// Each traversal uses at most one temporary variable, so the index stays the same within a single traversal.
|
||||
TInfoSinkBase symbolNameOut;
|
||||
ASSERT(mTemporaryIndex != nullptr);
|
||||
symbolNameOut << "s" << (*mTemporaryIndex);
|
||||
TString symbolName = symbolNameOut.c_str();
|
||||
|
||||
TIntermSymbol *node = new TIntermSymbol(0, symbolName, type);
|
||||
node->setInternal(true);
|
||||
node->getTypePointer()->setQualifier(qualifier);
|
||||
return node;
|
||||
}
|
||||
|
||||
TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
|
||||
{
|
||||
return createTempSymbol(type, EvqTemporary);
|
||||
}
|
||||
|
||||
TIntermAggregate *TIntermTraverser::createTempDeclaration(const TType &type)
|
||||
{
|
||||
TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
|
||||
tempDeclaration->getSequence()->push_back(createTempSymbol(type));
|
||||
return tempDeclaration;
|
||||
}
|
||||
|
||||
TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier)
|
||||
{
|
||||
ASSERT(initializer != nullptr);
|
||||
TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType(), qualifier);
|
||||
TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
|
||||
TIntermBinary *tempInit = new TIntermBinary(EOpInitialize);
|
||||
tempInit->setLeft(tempSymbol);
|
||||
tempInit->setRight(initializer);
|
||||
tempInit->setType(tempSymbol->getType());
|
||||
tempDeclaration->getSequence()->push_back(tempInit);
|
||||
return tempDeclaration;
|
||||
}
|
||||
|
||||
TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
|
||||
{
|
||||
return createTempInitDeclaration(initializer, EvqTemporary);
|
||||
}
|
||||
|
||||
TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode)
|
||||
{
|
||||
ASSERT(rightNode != nullptr);
|
||||
TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType());
|
||||
TIntermBinary *assignment = new TIntermBinary(EOpAssign);
|
||||
assignment->setLeft(tempSymbol);
|
||||
assignment->setRight(rightNode);
|
||||
assignment->setType(tempSymbol->getType());
|
||||
return assignment;
|
||||
}
|
||||
|
||||
void TIntermTraverser::useTemporaryIndex(unsigned int *temporaryIndex)
|
||||
{
|
||||
mTemporaryIndex = temporaryIndex;
|
||||
}
|
||||
|
||||
void TIntermTraverser::nextTemporaryIndex()
|
||||
{
|
||||
ASSERT(mTemporaryIndex != nullptr);
|
||||
++(*mTemporaryIndex);
|
||||
}
|
||||
|
||||
void TLValueTrackingTraverser::addToFunctionMap(const TName &name, TIntermSequence *paramSequence)
|
||||
{
|
||||
mFunctionMap[name] = paramSequence;
|
||||
}
|
||||
|
||||
bool TLValueTrackingTraverser::isInFunctionMap(const TIntermAggregate *callNode) const
|
||||
{
|
||||
ASSERT(callNode->getOp() == EOpFunctionCall);
|
||||
return (mFunctionMap.find(callNode->getNameObj()) != mFunctionMap.end());
|
||||
}
|
||||
|
||||
TIntermSequence *TLValueTrackingTraverser::getFunctionParameters(const TIntermAggregate *callNode)
|
||||
{
|
||||
ASSERT(isInFunctionMap(callNode));
|
||||
return mFunctionMap[callNode->getNameObj()];
|
||||
}
|
||||
|
||||
void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter)
|
||||
{
|
||||
mInFunctionCallOutParameter = inOutParameter;
|
||||
}
|
||||
|
||||
bool TLValueTrackingTraverser::isInFunctionCallOutParameter() const
|
||||
{
|
||||
return mInFunctionCallOutParameter;
|
||||
}
|
||||
|
||||
//
|
||||
// Traverse the intermediate representation tree, and
|
||||
@ -16,308 +197,473 @@
|
||||
// if preVisit is turned on and the type specific function
|
||||
// returns false.
|
||||
//
|
||||
// preVisit, postVisit, and rightToLeft control what order
|
||||
// nodes are visited in.
|
||||
//
|
||||
|
||||
//
|
||||
// Traversal functions for terminals are straighforward....
|
||||
//
|
||||
void TIntermSymbol::traverse(TIntermTraverser *it)
|
||||
void TIntermTraverser::traverseSymbol(TIntermSymbol *node)
|
||||
{
|
||||
it->visitSymbol(this);
|
||||
visitSymbol(node);
|
||||
}
|
||||
|
||||
void TIntermConstantUnion::traverse(TIntermTraverser *it)
|
||||
void TIntermTraverser::traverseConstantUnion(TIntermConstantUnion *node)
|
||||
{
|
||||
it->visitConstantUnion(this);
|
||||
visitConstantUnion(node);
|
||||
}
|
||||
|
||||
//
|
||||
// Traverse a binary node.
|
||||
//
|
||||
void TIntermBinary::traverse(TIntermTraverser *it)
|
||||
void TIntermTraverser::traverseBinary(TIntermBinary *node)
|
||||
{
|
||||
bool visit = true;
|
||||
|
||||
//
|
||||
// visit the node before children if pre-visiting.
|
||||
//
|
||||
if (it->preVisit)
|
||||
visit = it->visitBinary(PreVisit, this);
|
||||
if (preVisit)
|
||||
visit = visitBinary(PreVisit, node);
|
||||
|
||||
//
|
||||
// Visit the children, in the right order.
|
||||
//
|
||||
if (visit)
|
||||
{
|
||||
it->incrementDepth(this);
|
||||
incrementDepth(node);
|
||||
|
||||
if (it->rightToLeft)
|
||||
{
|
||||
if (mRight)
|
||||
mRight->traverse(it);
|
||||
if (node->getLeft())
|
||||
node->getLeft()->traverse(this);
|
||||
|
||||
if (it->inVisit)
|
||||
visit = it->visitBinary(InVisit, this);
|
||||
if (inVisit)
|
||||
visit = visitBinary(InVisit, node);
|
||||
|
||||
if (visit && mLeft)
|
||||
mLeft->traverse(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mLeft)
|
||||
mLeft->traverse(it);
|
||||
if (visit && node->getRight())
|
||||
node->getRight()->traverse(this);
|
||||
|
||||
if (it->inVisit)
|
||||
visit = it->visitBinary(InVisit, this);
|
||||
|
||||
if (visit && mRight)
|
||||
mRight->traverse(it);
|
||||
}
|
||||
|
||||
it->decrementDepth();
|
||||
decrementDepth();
|
||||
}
|
||||
|
||||
//
|
||||
// Visit the node after the children, if requested and the traversal
|
||||
// hasn't been cancelled yet.
|
||||
//
|
||||
if (visit && it->postVisit)
|
||||
it->visitBinary(PostVisit, this);
|
||||
if (visit && postVisit)
|
||||
visitBinary(PostVisit, node);
|
||||
}
|
||||
|
||||
void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
|
||||
{
|
||||
bool visit = true;
|
||||
|
||||
//
|
||||
// visit the node before children if pre-visiting.
|
||||
//
|
||||
if (preVisit)
|
||||
visit = visitBinary(PreVisit, node);
|
||||
|
||||
//
|
||||
// Visit the children, in the right order.
|
||||
//
|
||||
if (visit)
|
||||
{
|
||||
incrementDepth(node);
|
||||
|
||||
// Some binary operations like indexing can be inside an expression which must be an
|
||||
// l-value.
|
||||
bool parentOperatorRequiresLValue = operatorRequiresLValue();
|
||||
bool parentInFunctionCallOutParameter = isInFunctionCallOutParameter();
|
||||
if (node->isAssignment())
|
||||
{
|
||||
ASSERT(!isLValueRequiredHere());
|
||||
setOperatorRequiresLValue(true);
|
||||
}
|
||||
|
||||
if (node->getLeft())
|
||||
node->getLeft()->traverse(this);
|
||||
|
||||
if (inVisit)
|
||||
visit = visitBinary(InVisit, node);
|
||||
|
||||
if (node->isAssignment())
|
||||
setOperatorRequiresLValue(false);
|
||||
|
||||
// Index is not required to be an l-value even when the surrounding expression is required
|
||||
// to be an l-value.
|
||||
TOperator op = node->getOp();
|
||||
if (op == EOpIndexDirect || op == EOpIndexDirectInterfaceBlock ||
|
||||
op == EOpIndexDirectStruct || op == EOpIndexIndirect)
|
||||
{
|
||||
setOperatorRequiresLValue(false);
|
||||
setInFunctionCallOutParameter(false);
|
||||
}
|
||||
|
||||
if (visit && node->getRight())
|
||||
node->getRight()->traverse(this);
|
||||
|
||||
setOperatorRequiresLValue(parentOperatorRequiresLValue);
|
||||
setInFunctionCallOutParameter(parentInFunctionCallOutParameter);
|
||||
|
||||
decrementDepth();
|
||||
}
|
||||
|
||||
//
|
||||
// Visit the node after the children, if requested and the traversal
|
||||
// hasn't been cancelled yet.
|
||||
//
|
||||
if (visit && postVisit)
|
||||
visitBinary(PostVisit, node);
|
||||
}
|
||||
|
||||
//
|
||||
// Traverse a unary node. Same comments in binary node apply here.
|
||||
//
|
||||
void TIntermUnary::traverse(TIntermTraverser *it)
|
||||
void TIntermTraverser::traverseUnary(TIntermUnary *node)
|
||||
{
|
||||
bool visit = true;
|
||||
|
||||
if (it->preVisit)
|
||||
visit = it->visitUnary(PreVisit, this);
|
||||
if (preVisit)
|
||||
visit = visitUnary(PreVisit, node);
|
||||
|
||||
if (visit) {
|
||||
it->incrementDepth(this);
|
||||
mOperand->traverse(it);
|
||||
it->decrementDepth();
|
||||
if (visit)
|
||||
{
|
||||
incrementDepth(node);
|
||||
|
||||
node->getOperand()->traverse(this);
|
||||
|
||||
decrementDepth();
|
||||
}
|
||||
|
||||
if (visit && it->postVisit)
|
||||
it->visitUnary(PostVisit, this);
|
||||
if (visit && postVisit)
|
||||
visitUnary(PostVisit, node);
|
||||
}
|
||||
|
||||
void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node)
|
||||
{
|
||||
bool visit = true;
|
||||
|
||||
if (preVisit)
|
||||
visit = visitUnary(PreVisit, node);
|
||||
|
||||
if (visit)
|
||||
{
|
||||
incrementDepth(node);
|
||||
|
||||
ASSERT(!operatorRequiresLValue());
|
||||
switch (node->getOp())
|
||||
{
|
||||
case EOpPostIncrement:
|
||||
case EOpPostDecrement:
|
||||
case EOpPreIncrement:
|
||||
case EOpPreDecrement:
|
||||
setOperatorRequiresLValue(true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
node->getOperand()->traverse(this);
|
||||
|
||||
setOperatorRequiresLValue(false);
|
||||
|
||||
decrementDepth();
|
||||
}
|
||||
|
||||
if (visit && postVisit)
|
||||
visitUnary(PostVisit, node);
|
||||
}
|
||||
|
||||
//
|
||||
// Traverse an aggregate node. Same comments in binary node apply here.
|
||||
//
|
||||
void TIntermAggregate::traverse(TIntermTraverser *it)
|
||||
void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
|
||||
{
|
||||
bool visit = true;
|
||||
|
||||
if (it->preVisit)
|
||||
visit = it->visitAggregate(PreVisit, this);
|
||||
TIntermSequence *sequence = node->getSequence();
|
||||
|
||||
if (preVisit)
|
||||
visit = visitAggregate(PreVisit, node);
|
||||
|
||||
if (visit)
|
||||
{
|
||||
it->incrementDepth(this);
|
||||
incrementDepth(node);
|
||||
|
||||
if (it->rightToLeft)
|
||||
if (node->getOp() == EOpSequence)
|
||||
pushParentBlock(node);
|
||||
|
||||
for (auto *child : *sequence)
|
||||
{
|
||||
for (TIntermSequence::reverse_iterator sit = mSequence.rbegin();
|
||||
sit != mSequence.rend(); sit++)
|
||||
child->traverse(this);
|
||||
if (visit && inVisit)
|
||||
{
|
||||
(*sit)->traverse(it);
|
||||
|
||||
if (visit && it->inVisit)
|
||||
{
|
||||
if (*sit != mSequence.front())
|
||||
visit = it->visitAggregate(InVisit, this);
|
||||
}
|
||||
if (child != sequence->back())
|
||||
visit = visitAggregate(InVisit, node);
|
||||
}
|
||||
|
||||
if (node->getOp() == EOpSequence)
|
||||
incrementParentBlockPos();
|
||||
}
|
||||
|
||||
if (node->getOp() == EOpSequence)
|
||||
popParentBlock();
|
||||
|
||||
decrementDepth();
|
||||
}
|
||||
|
||||
if (visit && postVisit)
|
||||
visitAggregate(PostVisit, node);
|
||||
}
|
||||
|
||||
void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
|
||||
{
|
||||
bool visit = true;
|
||||
|
||||
TIntermSequence *sequence = node->getSequence();
|
||||
switch (node->getOp())
|
||||
{
|
||||
case EOpFunction:
|
||||
{
|
||||
TIntermAggregate *params = sequence->front()->getAsAggregate();
|
||||
ASSERT(params != nullptr);
|
||||
ASSERT(params->getOp() == EOpParameters);
|
||||
addToFunctionMap(node->getNameObj(), params->getSequence());
|
||||
break;
|
||||
}
|
||||
case EOpPrototype:
|
||||
addToFunctionMap(node->getNameObj(), sequence);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (preVisit)
|
||||
visit = visitAggregate(PreVisit, node);
|
||||
|
||||
if (visit)
|
||||
{
|
||||
bool inFunctionMap = false;
|
||||
if (node->getOp() == EOpFunctionCall)
|
||||
{
|
||||
inFunctionMap = isInFunctionMap(node);
|
||||
if (!inFunctionMap)
|
||||
{
|
||||
// The function is not user-defined - it is likely built-in texture function.
|
||||
// Assume that those do not have out parameters.
|
||||
setInFunctionCallOutParameter(false);
|
||||
}
|
||||
}
|
||||
|
||||
incrementDepth(node);
|
||||
|
||||
if (inFunctionMap)
|
||||
{
|
||||
TIntermSequence *params = getFunctionParameters(node);
|
||||
TIntermSequence::iterator paramIter = params->begin();
|
||||
for (auto *child : *sequence)
|
||||
{
|
||||
ASSERT(paramIter != params->end());
|
||||
TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier();
|
||||
setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
|
||||
|
||||
child->traverse(this);
|
||||
if (visit && inVisit)
|
||||
{
|
||||
if (child != sequence->back())
|
||||
visit = visitAggregate(InVisit, node);
|
||||
}
|
||||
|
||||
++paramIter;
|
||||
}
|
||||
|
||||
setInFunctionCallOutParameter(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (TIntermSequence::iterator sit = mSequence.begin();
|
||||
sit != mSequence.end(); sit++)
|
||||
{
|
||||
(*sit)->traverse(it);
|
||||
if (node->getOp() == EOpSequence)
|
||||
pushParentBlock(node);
|
||||
|
||||
if (visit && it->inVisit)
|
||||
// Find the built-in function corresponding to this op so that we can determine the
|
||||
// in/out qualifiers of its parameters.
|
||||
TFunction *builtInFunc = nullptr;
|
||||
TString opString = GetOperatorString(node->getOp());
|
||||
if (!node->isConstructor() && !opString.empty())
|
||||
{
|
||||
// The return type doesn't affect the mangled name of the function, which is used
|
||||
// to look it up from the symbol table.
|
||||
TType dummyReturnType;
|
||||
TFunction call(&opString, &dummyReturnType, node->getOp());
|
||||
for (auto *child : *sequence)
|
||||
{
|
||||
if (*sit != mSequence.back())
|
||||
visit = it->visitAggregate(InVisit, this);
|
||||
TType *paramType = child->getAsTyped()->getTypePointer();
|
||||
TConstParameter p(paramType);
|
||||
call.addParameter(p);
|
||||
}
|
||||
|
||||
TSymbol *sym = mSymbolTable.findBuiltIn(call.getMangledName(), mShaderVersion);
|
||||
if (sym != nullptr && sym->isFunction())
|
||||
{
|
||||
builtInFunc = static_cast<TFunction *>(sym);
|
||||
ASSERT(builtInFunc->getParamCount() == sequence->size());
|
||||
}
|
||||
}
|
||||
|
||||
size_t paramIndex = 0;
|
||||
|
||||
for (auto *child : *sequence)
|
||||
{
|
||||
TQualifier qualifier = EvqIn;
|
||||
if (builtInFunc != nullptr)
|
||||
qualifier = builtInFunc->getParam(paramIndex).type->getQualifier();
|
||||
setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
|
||||
child->traverse(this);
|
||||
|
||||
if (visit && inVisit)
|
||||
{
|
||||
if (child != sequence->back())
|
||||
visit = visitAggregate(InVisit, node);
|
||||
}
|
||||
|
||||
if (node->getOp() == EOpSequence)
|
||||
incrementParentBlockPos();
|
||||
|
||||
++paramIndex;
|
||||
}
|
||||
|
||||
setInFunctionCallOutParameter(false);
|
||||
|
||||
if (node->getOp() == EOpSequence)
|
||||
popParentBlock();
|
||||
}
|
||||
|
||||
it->decrementDepth();
|
||||
decrementDepth();
|
||||
}
|
||||
|
||||
if (visit && it->postVisit)
|
||||
it->visitAggregate(PostVisit, this);
|
||||
if (visit && postVisit)
|
||||
visitAggregate(PostVisit, node);
|
||||
}
|
||||
|
||||
//
|
||||
// Traverse a selection node. Same comments in binary node apply here.
|
||||
//
|
||||
void TIntermSelection::traverse(TIntermTraverser *it)
|
||||
void TIntermTraverser::traverseSelection(TIntermSelection *node)
|
||||
{
|
||||
bool visit = true;
|
||||
|
||||
if (it->preVisit)
|
||||
visit = it->visitSelection(PreVisit, this);
|
||||
if (preVisit)
|
||||
visit = visitSelection(PreVisit, node);
|
||||
|
||||
if (visit)
|
||||
{
|
||||
it->incrementDepth(this);
|
||||
if (it->rightToLeft)
|
||||
{
|
||||
if (mFalseBlock)
|
||||
mFalseBlock->traverse(it);
|
||||
if (mTrueBlock)
|
||||
mTrueBlock->traverse(it);
|
||||
mCondition->traverse(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
mCondition->traverse(it);
|
||||
if (mTrueBlock)
|
||||
mTrueBlock->traverse(it);
|
||||
if (mFalseBlock)
|
||||
mFalseBlock->traverse(it);
|
||||
}
|
||||
it->decrementDepth();
|
||||
incrementDepth(node);
|
||||
node->getCondition()->traverse(this);
|
||||
if (node->getTrueBlock())
|
||||
node->getTrueBlock()->traverse(this);
|
||||
if (node->getFalseBlock())
|
||||
node->getFalseBlock()->traverse(this);
|
||||
decrementDepth();
|
||||
}
|
||||
|
||||
if (visit && it->postVisit)
|
||||
it->visitSelection(PostVisit, this);
|
||||
if (visit && postVisit)
|
||||
visitSelection(PostVisit, node);
|
||||
}
|
||||
|
||||
//
|
||||
// Traverse a switch node. Same comments in binary node apply here.
|
||||
//
|
||||
void TIntermSwitch::traverse(TIntermTraverser *it)
|
||||
void TIntermTraverser::traverseSwitch(TIntermSwitch *node)
|
||||
{
|
||||
bool visit = true;
|
||||
|
||||
if (it->preVisit)
|
||||
visit = it->visitSwitch(PreVisit, this);
|
||||
if (preVisit)
|
||||
visit = visitSwitch(PreVisit, node);
|
||||
|
||||
if (visit)
|
||||
{
|
||||
it->incrementDepth(this);
|
||||
if (it->rightToLeft)
|
||||
{
|
||||
if (mStatementList)
|
||||
mStatementList->traverse(it);
|
||||
if (it->inVisit)
|
||||
visit = it->visitSwitch(InVisit, this);
|
||||
if (visit)
|
||||
mInit->traverse(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
mInit->traverse(it);
|
||||
if (it->inVisit)
|
||||
visit = it->visitSwitch(InVisit, this);
|
||||
if (visit && mStatementList)
|
||||
mStatementList->traverse(it);
|
||||
}
|
||||
it->decrementDepth();
|
||||
incrementDepth(node);
|
||||
node->getInit()->traverse(this);
|
||||
if (inVisit)
|
||||
visit = visitSwitch(InVisit, node);
|
||||
if (visit && node->getStatementList())
|
||||
node->getStatementList()->traverse(this);
|
||||
decrementDepth();
|
||||
}
|
||||
|
||||
if (visit && it->postVisit)
|
||||
it->visitSwitch(PostVisit, this);
|
||||
if (visit && postVisit)
|
||||
visitSwitch(PostVisit, node);
|
||||
}
|
||||
|
||||
//
|
||||
// Traverse a switch node. Same comments in binary node apply here.
|
||||
// Traverse a case node. Same comments in binary node apply here.
|
||||
//
|
||||
void TIntermCase::traverse(TIntermTraverser *it)
|
||||
void TIntermTraverser::traverseCase(TIntermCase *node)
|
||||
{
|
||||
bool visit = true;
|
||||
|
||||
if (it->preVisit)
|
||||
visit = it->visitCase(PreVisit, this);
|
||||
if (preVisit)
|
||||
visit = visitCase(PreVisit, node);
|
||||
|
||||
if (visit && mCondition)
|
||||
mCondition->traverse(it);
|
||||
if (visit && node->getCondition())
|
||||
node->getCondition()->traverse(this);
|
||||
|
||||
if (visit && it->postVisit)
|
||||
it->visitCase(PostVisit, this);
|
||||
if (visit && postVisit)
|
||||
visitCase(PostVisit, node);
|
||||
}
|
||||
|
||||
//
|
||||
// Traverse a loop node. Same comments in binary node apply here.
|
||||
//
|
||||
void TIntermLoop::traverse(TIntermTraverser *it)
|
||||
void TIntermTraverser::traverseLoop(TIntermLoop *node)
|
||||
{
|
||||
bool visit = true;
|
||||
|
||||
if (it->preVisit)
|
||||
visit = it->visitLoop(PreVisit, this);
|
||||
if (preVisit)
|
||||
visit = visitLoop(PreVisit, node);
|
||||
|
||||
if (visit)
|
||||
{
|
||||
it->incrementDepth(this);
|
||||
incrementDepth(node);
|
||||
|
||||
if (it->rightToLeft)
|
||||
{
|
||||
if (mExpr)
|
||||
mExpr->traverse(it);
|
||||
if (node->getInit())
|
||||
node->getInit()->traverse(this);
|
||||
|
||||
if (mBody)
|
||||
mBody->traverse(it);
|
||||
if (node->getCondition())
|
||||
node->getCondition()->traverse(this);
|
||||
|
||||
if (mCond)
|
||||
mCond->traverse(it);
|
||||
if (node->getBody())
|
||||
node->getBody()->traverse(this);
|
||||
|
||||
if (mInit)
|
||||
mInit->traverse(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mInit)
|
||||
mInit->traverse(it);
|
||||
if (node->getExpression())
|
||||
node->getExpression()->traverse(this);
|
||||
|
||||
if (mCond)
|
||||
mCond->traverse(it);
|
||||
|
||||
if (mBody)
|
||||
mBody->traverse(it);
|
||||
|
||||
if (mExpr)
|
||||
mExpr->traverse(it);
|
||||
}
|
||||
|
||||
it->decrementDepth();
|
||||
decrementDepth();
|
||||
}
|
||||
|
||||
if (visit && it->postVisit)
|
||||
it->visitLoop(PostVisit, this);
|
||||
if (visit && postVisit)
|
||||
visitLoop(PostVisit, node);
|
||||
}
|
||||
|
||||
//
|
||||
// Traverse a branch node. Same comments in binary node apply here.
|
||||
//
|
||||
void TIntermBranch::traverse(TIntermTraverser *it)
|
||||
void TIntermTraverser::traverseBranch(TIntermBranch *node)
|
||||
{
|
||||
bool visit = true;
|
||||
|
||||
if (it->preVisit)
|
||||
visit = it->visitBranch(PreVisit, this);
|
||||
if (preVisit)
|
||||
visit = visitBranch(PreVisit, node);
|
||||
|
||||
if (visit && mExpression) {
|
||||
it->incrementDepth(this);
|
||||
mExpression->traverse(it);
|
||||
it->decrementDepth();
|
||||
if (visit && node->getExpression())
|
||||
{
|
||||
incrementDepth(node);
|
||||
node->getExpression()->traverse(this);
|
||||
decrementDepth();
|
||||
}
|
||||
|
||||
if (visit && it->postVisit)
|
||||
it->visitBranch(PostVisit, this);
|
||||
if (visit && postVisit)
|
||||
visitBranch(PostVisit, node);
|
||||
}
|
||||
|
||||
void TIntermRaw::traverse(TIntermTraverser *it)
|
||||
void TIntermTraverser::traverseRaw(TIntermRaw *node)
|
||||
{
|
||||
it->visitRaw(this);
|
||||
visitRaw(node);
|
||||
}
|
||||
|
@ -57,19 +57,10 @@ TIntermTyped *TIntermediate::addBinaryMath(
|
||||
if (!node->promote(mInfoSink))
|
||||
return NULL;
|
||||
|
||||
//
|
||||
// See if we can fold constants.
|
||||
//
|
||||
TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
|
||||
TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
|
||||
if (leftTempConstant && rightTempConstant)
|
||||
{
|
||||
TIntermTyped *typedReturnNode =
|
||||
leftTempConstant->fold(node->getOp(), rightTempConstant, mInfoSink);
|
||||
|
||||
if (typedReturnNode)
|
||||
return typedReturnNode;
|
||||
}
|
||||
TIntermTyped *foldedNode = node->fold(mInfoSink);
|
||||
if (foldedNode)
|
||||
return foldedNode;
|
||||
|
||||
return node;
|
||||
}
|
||||
@ -129,10 +120,6 @@ TIntermTyped *TIntermediate::addIndex(
|
||||
TIntermTyped *TIntermediate::addUnaryMath(
|
||||
TOperator op, TIntermTyped *child, const TSourceLoc &line, const TType *funcReturnType)
|
||||
{
|
||||
TIntermConstantUnion *childTempConstant = 0;
|
||||
if (child->getAsConstantUnion())
|
||||
childTempConstant = child->getAsConstantUnion();
|
||||
|
||||
//
|
||||
// Make a new node for the operator.
|
||||
//
|
||||
@ -141,13 +128,9 @@ TIntermTyped *TIntermediate::addUnaryMath(
|
||||
node->setOperand(child);
|
||||
node->promote(funcReturnType);
|
||||
|
||||
if (childTempConstant)
|
||||
{
|
||||
TIntermTyped *newChild = childTempConstant->fold(op, 0, mInfoSink);
|
||||
|
||||
if (newChild)
|
||||
return newChild;
|
||||
}
|
||||
TIntermTyped *foldedNode = node->fold(mInfoSink);
|
||||
if (foldedNode)
|
||||
return foldedNode;
|
||||
|
||||
return node;
|
||||
}
|
||||
@ -246,6 +229,22 @@ TIntermAggregate *TIntermediate::makeAggregate(
|
||||
return aggNode;
|
||||
}
|
||||
|
||||
// If the input node is nullptr, return nullptr.
|
||||
// If the input node is a sequence (block) node, return it.
|
||||
// If the input node is not a sequence node, put it inside a sequence node and return that.
|
||||
TIntermAggregate *TIntermediate::ensureSequence(TIntermNode *node)
|
||||
{
|
||||
if (node == nullptr)
|
||||
return nullptr;
|
||||
TIntermAggregate *aggNode = node->getAsAggregate();
|
||||
if (aggNode != nullptr && aggNode->getOp() == EOpSequence)
|
||||
return aggNode;
|
||||
|
||||
aggNode = makeAggregate(node, node->getLine());
|
||||
aggNode->setOp(EOpSequence);
|
||||
return aggNode;
|
||||
}
|
||||
|
||||
//
|
||||
// For "if" test nodes. There are three children; a condition,
|
||||
// a true path, and a false path. The two paths are in the
|
||||
@ -261,7 +260,7 @@ TIntermNode *TIntermediate::addSelection(
|
||||
// test now.
|
||||
//
|
||||
|
||||
if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion())
|
||||
if (cond->getAsConstantUnion())
|
||||
{
|
||||
if (cond->getAsConstantUnion()->getBConst(0) == true)
|
||||
{
|
||||
@ -276,28 +275,38 @@ TIntermNode *TIntermediate::addSelection(
|
||||
}
|
||||
|
||||
TIntermSelection *node = new TIntermSelection(
|
||||
cond, nodePair.node1, nodePair.node2);
|
||||
cond, ensureSequence(nodePair.node1), ensureSequence(nodePair.node2));
|
||||
node->setLine(line);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
TIntermTyped *TIntermediate::addComma(
|
||||
TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
|
||||
TIntermTyped *TIntermediate::addComma(TIntermTyped *left,
|
||||
TIntermTyped *right,
|
||||
const TSourceLoc &line,
|
||||
int shaderVersion)
|
||||
{
|
||||
if (left->getType().getQualifier() == EvqConst &&
|
||||
right->getType().getQualifier() == EvqConst)
|
||||
TQualifier resultQualifier = EvqConst;
|
||||
// ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression.
|
||||
if (shaderVersion >= 300 || left->getQualifier() != EvqConst ||
|
||||
right->getQualifier() != EvqConst)
|
||||
{
|
||||
return right;
|
||||
resultQualifier = EvqTemporary;
|
||||
}
|
||||
|
||||
TIntermTyped *commaNode = nullptr;
|
||||
if (!left->hasSideEffects())
|
||||
{
|
||||
commaNode = right;
|
||||
}
|
||||
else
|
||||
{
|
||||
TIntermTyped *commaAggregate = growAggregate(left, right, line);
|
||||
commaAggregate->getAsAggregate()->setOp(EOpComma);
|
||||
commaAggregate->setType(right->getType());
|
||||
commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
|
||||
return commaAggregate;
|
||||
commaNode = growAggregate(left, right, line);
|
||||
commaNode->getAsAggregate()->setOp(EOpComma);
|
||||
commaNode->setType(right->getType());
|
||||
}
|
||||
commaNode->getTypePointer()->setQualifier(resultQualifier);
|
||||
return commaNode;
|
||||
}
|
||||
|
||||
//
|
||||
@ -305,38 +314,38 @@ TIntermTyped *TIntermediate::addComma(
|
||||
// a true path, and a false path. The two paths are specified
|
||||
// as separate parameters.
|
||||
//
|
||||
// Returns the selection node created, or 0 if one could not be.
|
||||
// Returns the selection node created, or one of trueBlock and falseBlock if the expression could be folded.
|
||||
//
|
||||
TIntermTyped *TIntermediate::addSelection(
|
||||
TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock,
|
||||
const TSourceLoc &line)
|
||||
TIntermTyped *TIntermediate::addSelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock,
|
||||
const TSourceLoc &line)
|
||||
{
|
||||
if (!cond || !trueBlock || !falseBlock ||
|
||||
trueBlock->getType() != falseBlock->getType())
|
||||
TQualifier resultQualifier = EvqTemporary;
|
||||
if (cond->getQualifier() == EvqConst && trueBlock->getQualifier() == EvqConst &&
|
||||
falseBlock->getQualifier() == EvqConst)
|
||||
{
|
||||
return NULL;
|
||||
resultQualifier = EvqConst;
|
||||
}
|
||||
|
||||
//
|
||||
// See if all the operands are constant, then fold it otherwise not.
|
||||
//
|
||||
|
||||
if (cond->getAsConstantUnion() &&
|
||||
trueBlock->getAsConstantUnion() &&
|
||||
falseBlock->getAsConstantUnion())
|
||||
// Note that the node resulting from here can be a constant union without being qualified as
|
||||
// constant.
|
||||
if (cond->getAsConstantUnion())
|
||||
{
|
||||
if (cond->getAsConstantUnion()->getBConst(0))
|
||||
{
|
||||
trueBlock->getTypePointer()->setQualifier(resultQualifier);
|
||||
return trueBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
falseBlock->getTypePointer()->setQualifier(resultQualifier);
|
||||
return falseBlock;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Make a selection node.
|
||||
//
|
||||
TIntermSelection *node = new TIntermSelection(
|
||||
cond, trueBlock, falseBlock, trueBlock->getType());
|
||||
node->getTypePointer()->setQualifier(EvqTemporary);
|
||||
TIntermSelection *node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
|
||||
node->getTypePointer()->setQualifier(resultQualifier);
|
||||
node->setLine(line);
|
||||
|
||||
return node;
|
||||
@ -366,10 +375,11 @@ TIntermCase *TIntermediate::addCase(
|
||||
// Returns the constant union node created.
|
||||
//
|
||||
|
||||
TIntermConstantUnion *TIntermediate::addConstantUnion(
|
||||
ConstantUnion *unionArrayPointer, const TType &t, const TSourceLoc &line)
|
||||
TIntermConstantUnion *TIntermediate::addConstantUnion(const TConstantUnion *constantUnion,
|
||||
const TType &type,
|
||||
const TSourceLoc &line)
|
||||
{
|
||||
TIntermConstantUnion *node = new TIntermConstantUnion(unionArrayPointer, t);
|
||||
TIntermConstantUnion *node = new TIntermConstantUnion(constantUnion, type);
|
||||
node->setLine(line);
|
||||
|
||||
return node;
|
||||
@ -384,11 +394,11 @@ TIntermTyped *TIntermediate::addSwizzle(
|
||||
node->setLine(line);
|
||||
TIntermConstantUnion *constIntNode;
|
||||
TIntermSequence *sequenceVector = node->getSequence();
|
||||
ConstantUnion *unionArray;
|
||||
TConstantUnion *unionArray;
|
||||
|
||||
for (int i = 0; i < fields.num; i++)
|
||||
{
|
||||
unionArray = new ConstantUnion[1];
|
||||
unionArray = new TConstantUnion[1];
|
||||
unionArray->setIConst(fields.offsets[i]);
|
||||
constIntNode = addConstantUnion(
|
||||
unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
|
||||
@ -405,7 +415,7 @@ TIntermNode *TIntermediate::addLoop(
|
||||
TLoopType type, TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
|
||||
TIntermNode *body, const TSourceLoc &line)
|
||||
{
|
||||
TIntermNode *node = new TIntermLoop(type, init, cond, expr, body);
|
||||
TIntermNode *node = new TIntermLoop(type, init, cond, expr, ensureSequence(body));
|
||||
node->setLine(line);
|
||||
|
||||
return node;
|
||||
@ -433,17 +443,66 @@ TIntermBranch* TIntermediate::addBranch(
|
||||
// This is to be executed once the final root is put on top by the parsing
|
||||
// process.
|
||||
//
|
||||
bool TIntermediate::postProcess(TIntermNode *root)
|
||||
TIntermAggregate *TIntermediate::postProcess(TIntermNode *root)
|
||||
{
|
||||
if (root == NULL)
|
||||
return true;
|
||||
if (root == nullptr)
|
||||
return nullptr;
|
||||
|
||||
//
|
||||
// First, finish off the top level sequence, if any
|
||||
// Finish off the top level sequence, if any
|
||||
//
|
||||
TIntermAggregate *aggRoot = root->getAsAggregate();
|
||||
if (aggRoot && aggRoot->getOp() == EOpNull)
|
||||
if (aggRoot != nullptr && aggRoot->getOp() == EOpNull)
|
||||
{
|
||||
aggRoot->setOp(EOpSequence);
|
||||
}
|
||||
else if (aggRoot == nullptr || aggRoot->getOp() != EOpSequence)
|
||||
{
|
||||
aggRoot = new TIntermAggregate(EOpSequence);
|
||||
aggRoot->setLine(root->getLine());
|
||||
aggRoot->getSequence()->push_back(root);
|
||||
}
|
||||
|
||||
return true;
|
||||
return aggRoot;
|
||||
}
|
||||
|
||||
TIntermTyped *TIntermediate::foldAggregateBuiltIn(TIntermAggregate *aggregate)
|
||||
{
|
||||
switch (aggregate->getOp())
|
||||
{
|
||||
case EOpAtan:
|
||||
case EOpPow:
|
||||
case EOpMod:
|
||||
case EOpMin:
|
||||
case EOpMax:
|
||||
case EOpClamp:
|
||||
case EOpMix:
|
||||
case EOpStep:
|
||||
case EOpSmoothStep:
|
||||
case EOpMul:
|
||||
case EOpOuterProduct:
|
||||
case EOpLessThan:
|
||||
case EOpLessThanEqual:
|
||||
case EOpGreaterThan:
|
||||
case EOpGreaterThanEqual:
|
||||
case EOpVectorEqual:
|
||||
case EOpVectorNotEqual:
|
||||
case EOpDistance:
|
||||
case EOpDot:
|
||||
case EOpCross:
|
||||
case EOpFaceForward:
|
||||
case EOpReflect:
|
||||
case EOpRefract:
|
||||
return aggregate->fold(mInfoSink);
|
||||
default:
|
||||
// TODO: Add support for folding array constructors
|
||||
if (aggregate->isConstructor() && !aggregate->isArray())
|
||||
{
|
||||
return aggregate->fold(mInfoSink);
|
||||
}
|
||||
// Constant folding not supported for the built-in.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -39,29 +39,33 @@ class TIntermediate
|
||||
TIntermAggregate *growAggregate(
|
||||
TIntermNode *left, TIntermNode *right, const TSourceLoc &);
|
||||
TIntermAggregate *makeAggregate(TIntermNode *node, const TSourceLoc &);
|
||||
TIntermAggregate *ensureSequence(TIntermNode *node);
|
||||
TIntermAggregate *setAggregateOperator(TIntermNode *, TOperator, const TSourceLoc &);
|
||||
TIntermNode *addSelection(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &);
|
||||
TIntermTyped *addSelection(
|
||||
TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &);
|
||||
TIntermTyped *addSelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock,
|
||||
const TSourceLoc &line);
|
||||
TIntermSwitch *addSwitch(
|
||||
TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line);
|
||||
TIntermCase *addCase(
|
||||
TIntermTyped *condition, const TSourceLoc &line);
|
||||
TIntermTyped *addComma(
|
||||
TIntermTyped *left, TIntermTyped *right, const TSourceLoc &);
|
||||
TIntermConstantUnion *addConstantUnion(ConstantUnion *, const TType &, const TSourceLoc &);
|
||||
// TODO(zmo): Get rid of default value.
|
||||
bool parseConstTree(const TSourceLoc &, TIntermNode *, ConstantUnion *,
|
||||
TOperator, TType, bool singleConstantParam = false);
|
||||
TIntermTyped *addComma(TIntermTyped *left,
|
||||
TIntermTyped *right,
|
||||
const TSourceLoc &line,
|
||||
int shaderVersion);
|
||||
TIntermConstantUnion *addConstantUnion(const TConstantUnion *constantUnion,
|
||||
const TType &type,
|
||||
const TSourceLoc &line);
|
||||
TIntermNode *addLoop(TLoopType, TIntermNode *, TIntermTyped *, TIntermTyped *,
|
||||
TIntermNode *, const TSourceLoc &);
|
||||
TIntermBranch *addBranch(TOperator, const TSourceLoc &);
|
||||
TIntermBranch *addBranch(TOperator, TIntermTyped *, const TSourceLoc &);
|
||||
TIntermTyped *addSwizzle(TVectorFields &, const TSourceLoc &);
|
||||
bool postProcess(TIntermNode *);
|
||||
TIntermAggregate *postProcess(TIntermNode *root);
|
||||
|
||||
static void outputTree(TIntermNode *, TInfoSinkBase &);
|
||||
|
||||
TIntermTyped *foldAggregateBuiltIn(TIntermAggregate *aggregate);
|
||||
|
||||
private:
|
||||
void operator=(TIntermediate &); // prevent assignments
|
||||
|
||||
|
@ -19,7 +19,8 @@ class NodeSearchTraverser : public TIntermTraverser
|
||||
{
|
||||
public:
|
||||
NodeSearchTraverser()
|
||||
: mFound(false)
|
||||
: TIntermTraverser(true, false, false),
|
||||
mFound(false)
|
||||
{}
|
||||
|
||||
bool found() const { return mFound; }
|
||||
@ -53,28 +54,6 @@ class FindDiscard : public NodeSearchTraverser<FindDiscard>
|
||||
}
|
||||
};
|
||||
|
||||
class FindSideEffectRewriting : public NodeSearchTraverser<FindSideEffectRewriting>
|
||||
{
|
||||
public:
|
||||
virtual bool visitBinary(Visit visit, TIntermBinary *node)
|
||||
{
|
||||
switch (node->getOp())
|
||||
{
|
||||
case EOpLogicalOr:
|
||||
case EOpLogicalAnd:
|
||||
if (node->getRight()->hasSideEffects())
|
||||
{
|
||||
mFound = true;
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
return !mFound;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // COMPILER_TRANSLATOR_NODESEARCH_H_
|
||||
|
@ -164,7 +164,13 @@ const char *GetOperatorString(TOperator op)
|
||||
case EOpConstructUVec3: return "uvec3";
|
||||
case EOpConstructUVec4: return "uvec4";
|
||||
case EOpConstructMat2: return "mat2";
|
||||
case EOpConstructMat2x3: return "mat2x3";
|
||||
case EOpConstructMat2x4: return "mat2x4";
|
||||
case EOpConstructMat3x2: return "mat3x2";
|
||||
case EOpConstructMat3: return "mat3";
|
||||
case EOpConstructMat3x4: return "mat3x4";
|
||||
case EOpConstructMat4x2: return "mat4x2";
|
||||
case EOpConstructMat4x3: return "mat4x3";
|
||||
case EOpConstructMat4: return "mat4";
|
||||
// Note: EOpConstructStruct can't be handled here
|
||||
|
||||
|
@ -15,7 +15,6 @@ enum TOperator
|
||||
EOpNull, // if in a node, should only mean a node is still being built
|
||||
EOpSequence, // denotes a list of statements, or parameters, etc.
|
||||
EOpFunctionCall,
|
||||
EOpInternalFunctionCall, // Call to an internal helper function
|
||||
EOpFunction, // For function definition
|
||||
EOpParameters, // an aggregate listing the parameters to a function
|
||||
|
||||
@ -192,7 +191,13 @@ enum TOperator
|
||||
EOpConstructUVec3,
|
||||
EOpConstructUVec4,
|
||||
EOpConstructMat2,
|
||||
EOpConstructMat2x3,
|
||||
EOpConstructMat2x4,
|
||||
EOpConstructMat3x2,
|
||||
EOpConstructMat3,
|
||||
EOpConstructMat3x4,
|
||||
EOpConstructMat4x2,
|
||||
EOpConstructMat4x3,
|
||||
EOpConstructMat4,
|
||||
EOpConstructStruct,
|
||||
|
||||
|
@ -21,7 +21,8 @@ public:
|
||||
bool forceHighp);
|
||||
|
||||
protected:
|
||||
virtual bool writeVariablePrecision(TPrecision precision);
|
||||
bool writeVariablePrecision(TPrecision precision) override;
|
||||
|
||||
private:
|
||||
bool mForceHighp;
|
||||
};
|
||||
|
@ -37,14 +37,22 @@ void TOutputGLSL::visitSymbol(TIntermSymbol *node)
|
||||
{
|
||||
out << "gl_FragDepth";
|
||||
}
|
||||
else if (symbol == "gl_FragColor" && getShaderOutput() == SH_GLSL_CORE_OUTPUT)
|
||||
else if (symbol == "gl_FragColor" && IsGLSL130OrNewer(getShaderOutput()))
|
||||
{
|
||||
out << "webgl_FragColor";
|
||||
}
|
||||
else if (symbol == "gl_FragData" && getShaderOutput() == SH_GLSL_CORE_OUTPUT)
|
||||
else if (symbol == "gl_FragData" && IsGLSL130OrNewer(getShaderOutput()))
|
||||
{
|
||||
out << "webgl_FragData";
|
||||
}
|
||||
else if (symbol == "gl_SecondaryFragColorEXT")
|
||||
{
|
||||
out << "angle_SecondaryFragColor";
|
||||
}
|
||||
else if (symbol == "gl_SecondaryFragDataEXT")
|
||||
{
|
||||
out << "angle_SecondaryFragData";
|
||||
}
|
||||
else
|
||||
{
|
||||
TOutputGLSLBase::visitSymbol(node);
|
||||
@ -67,6 +75,7 @@ TString TOutputGLSL::translateTextureFunction(TString &name)
|
||||
"texture2DProj", "textureProj",
|
||||
"texture2DLod", "textureLod",
|
||||
"texture2DProjLod", "textureProjLod",
|
||||
"texture2DRect", "texture",
|
||||
"textureCube", "texture",
|
||||
"textureCubeLod", "textureLod",
|
||||
// Extensions
|
||||
@ -78,7 +87,7 @@ TString TOutputGLSL::translateTextureFunction(TString &name)
|
||||
"textureCubeGradEXT", "textureGrad",
|
||||
NULL, NULL
|
||||
};
|
||||
const char **mapping = (getShaderOutput() == SH_GLSL_CORE_OUTPUT) ?
|
||||
const char **mapping = (IsGLSL130OrNewer(getShaderOutput())) ?
|
||||
legacyToCoreRename : simpleRename;
|
||||
|
||||
for (int i = 0; mapping[i] != NULL; i += 2)
|
||||
|
@ -21,9 +21,9 @@ class TOutputGLSL : public TOutputGLSLBase
|
||||
ShShaderOutput output);
|
||||
|
||||
protected:
|
||||
virtual bool writeVariablePrecision(TPrecision);
|
||||
virtual void visitSymbol(TIntermSymbol* node);
|
||||
virtual TString translateTextureFunction(TString& name);
|
||||
bool writeVariablePrecision(TPrecision) override;
|
||||
void visitSymbol(TIntermSymbol *node) override;
|
||||
TString translateTextureFunction(TString &name) override;
|
||||
};
|
||||
|
||||
#endif // COMPILER_TRANSLATOR_OUTPUTGLSL_H_
|
||||
|
@ -5,7 +5,8 @@
|
||||
//
|
||||
|
||||
#include "compiler/translator/OutputGLSLBase.h"
|
||||
#include "compiler/translator/compilerdebug.h"
|
||||
|
||||
#include "common/debug.h"
|
||||
|
||||
#include <cfloat>
|
||||
|
||||
@ -88,30 +89,46 @@ void TOutputGLSLBase::writeBuiltInFunctionTriplet(
|
||||
writeTriplet(visit, preString.c_str(), ", ", ")");
|
||||
}
|
||||
|
||||
void TOutputGLSLBase::writeLayoutQualifier(const TType &type)
|
||||
{
|
||||
if (type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqVertexIn)
|
||||
{
|
||||
const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier();
|
||||
if (layoutQualifier.location >= 0)
|
||||
{
|
||||
TInfoSinkBase &out = objSink();
|
||||
out << "layout(location = " << layoutQualifier.location << ") ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TOutputGLSLBase::writeVariableType(const TType &type)
|
||||
{
|
||||
TInfoSinkBase &out = objSink();
|
||||
if (type.isInvariant())
|
||||
{
|
||||
out << "invariant ";
|
||||
}
|
||||
if (type.getBasicType() == EbtInterfaceBlock)
|
||||
{
|
||||
TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
|
||||
declareInterfaceBlockLayout(interfaceBlock);
|
||||
}
|
||||
TQualifier qualifier = type.getQualifier();
|
||||
if (qualifier != EvqTemporary && qualifier != EvqGlobal)
|
||||
{
|
||||
if (mOutput == SH_GLSL_CORE_OUTPUT)
|
||||
if (IsGLSL130OrNewer(mOutput))
|
||||
{
|
||||
switch (qualifier)
|
||||
{
|
||||
case EvqAttribute:
|
||||
out << "in" << " ";
|
||||
out << "in ";
|
||||
break;
|
||||
case EvqVaryingIn:
|
||||
out << "in" << " ";
|
||||
out << "in ";
|
||||
break;
|
||||
case EvqVaryingOut:
|
||||
out << "out" << " ";
|
||||
break;
|
||||
case EvqInvariantVaryingIn:
|
||||
out << "invariant in" << " ";
|
||||
break;
|
||||
case EvqInvariantVaryingOut:
|
||||
out << "invariant out" << " ";
|
||||
out << "out ";
|
||||
break;
|
||||
default:
|
||||
out << type.getQualifierString() << " ";
|
||||
@ -135,6 +152,11 @@ void TOutputGLSLBase::writeVariableType(const TType &type)
|
||||
mDeclaredStructs.insert(structure->uniqueId());
|
||||
}
|
||||
}
|
||||
else if (type.getBasicType() == EbtInterfaceBlock)
|
||||
{
|
||||
TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
|
||||
declareInterfaceBlock(interfaceBlock);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (writeVariablePrecision(type.getPrecision()))
|
||||
@ -167,8 +189,8 @@ void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence &args)
|
||||
}
|
||||
}
|
||||
|
||||
const ConstantUnion *TOutputGLSLBase::writeConstantUnion(
|
||||
const TType &type, const ConstantUnion *pConstUnion)
|
||||
const TConstantUnion *TOutputGLSLBase::writeConstantUnion(
|
||||
const TType &type, const TConstantUnion *pConstUnion)
|
||||
{
|
||||
TInfoSinkBase &out = objSink();
|
||||
|
||||
@ -221,6 +243,28 @@ const ConstantUnion *TOutputGLSLBase::writeConstantUnion(
|
||||
return pConstUnion;
|
||||
}
|
||||
|
||||
void TOutputGLSLBase::writeConstructorTriplet(Visit visit, const TType &type, const char *constructorBaseType)
|
||||
{
|
||||
TInfoSinkBase &out = objSink();
|
||||
if (visit == PreVisit)
|
||||
{
|
||||
if (type.isArray())
|
||||
{
|
||||
out << constructorBaseType;
|
||||
out << arrayBrackets(type);
|
||||
out << "(";
|
||||
}
|
||||
else
|
||||
{
|
||||
out << constructorBaseType << "(";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
writeTriplet(visit, nullptr, ", ", ")");
|
||||
}
|
||||
}
|
||||
|
||||
void TOutputGLSLBase::visitSymbol(TIntermSymbol *node)
|
||||
{
|
||||
TInfoSinkBase &out = objSink();
|
||||
@ -352,6 +396,22 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
|
||||
visitChildren = false;
|
||||
}
|
||||
break;
|
||||
case EOpIndexDirectInterfaceBlock:
|
||||
if (visit == InVisit)
|
||||
{
|
||||
out << ".";
|
||||
const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock();
|
||||
const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
|
||||
const TField *field = interfaceBlock->fields()[index->getIConst(0)];
|
||||
|
||||
TString fieldName = field->name();
|
||||
ASSERT(!mSymbolTable.findBuiltIn(interfaceBlock->name(), mShaderVersion));
|
||||
fieldName = hashName(fieldName);
|
||||
|
||||
out << fieldName;
|
||||
visitChildren = false;
|
||||
}
|
||||
break;
|
||||
case EOpVectorSwizzle:
|
||||
if (visit == InVisit)
|
||||
{
|
||||
@ -363,7 +423,7 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
|
||||
TIntermConstantUnion *element = (*sit)->getAsConstantUnion();
|
||||
ASSERT(element->getBasicType() == EbtInt);
|
||||
ASSERT(element->getNominalSize() == 1);
|
||||
const ConstantUnion& data = element->getUnionArrayPointer()[0];
|
||||
const TConstantUnion& data = element->getUnionArrayPointer()[0];
|
||||
ASSERT(data.getType() == EbtInt);
|
||||
switch (data.getIConst())
|
||||
{
|
||||
@ -722,7 +782,6 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
|
||||
{
|
||||
bool visitChildren = true;
|
||||
TInfoSinkBase &out = objSink();
|
||||
TString preString;
|
||||
bool useEmulatedFunction = (visit == PreVisit && node->getUseEmulatedFunction());
|
||||
switch (node->getOp())
|
||||
{
|
||||
@ -756,8 +815,14 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
|
||||
case EOpPrototype:
|
||||
// Function declaration.
|
||||
ASSERT(visit == PreVisit);
|
||||
writeVariableType(node->getType());
|
||||
out << " " << hashFunctionName(node->getName());
|
||||
{
|
||||
const TType &type = node->getType();
|
||||
writeVariableType(type);
|
||||
if (type.isArray())
|
||||
out << arrayBrackets(type);
|
||||
}
|
||||
|
||||
out << " " << hashFunctionNameIfNeeded(node->getNameObj());
|
||||
|
||||
out << "(";
|
||||
writeFunctionParameters(*(node->getSequence()));
|
||||
@ -768,8 +833,14 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
|
||||
case EOpFunction: {
|
||||
// Function definition.
|
||||
ASSERT(visit == PreVisit);
|
||||
writeVariableType(node->getType());
|
||||
out << " " << hashFunctionName(node->getName());
|
||||
{
|
||||
const TType &type = node->getType();
|
||||
writeVariableType(type);
|
||||
if (type.isArray())
|
||||
out << arrayBrackets(type);
|
||||
}
|
||||
|
||||
out << " " << hashFunctionNameIfNeeded(node->getNameObj());
|
||||
|
||||
incrementDepth(node);
|
||||
// Function definition node contains one or two children nodes
|
||||
@ -798,16 +869,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
|
||||
case EOpFunctionCall:
|
||||
// Function call.
|
||||
if (visit == PreVisit)
|
||||
out << hashFunctionName(node->getName()) << "(";
|
||||
else if (visit == InVisit)
|
||||
out << ", ";
|
||||
else
|
||||
out << ")";
|
||||
break;
|
||||
case EOpInternalFunctionCall:
|
||||
// Function call to an internal helper function.
|
||||
if (visit == PreVisit)
|
||||
out << node->getName() << "(";
|
||||
out << hashFunctionNameIfNeeded(node->getNameObj()) << "(";
|
||||
else if (visit == InVisit)
|
||||
out << ", ";
|
||||
else
|
||||
@ -827,6 +889,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
|
||||
{
|
||||
const TIntermSequence &sequence = *(node->getSequence());
|
||||
const TIntermTyped *variable = sequence.front()->getAsTyped();
|
||||
writeLayoutQualifier(variable->getType());
|
||||
writeVariableType(variable->getType());
|
||||
out << " ";
|
||||
mDeclaringVariables = true;
|
||||
@ -854,66 +917,88 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
|
||||
visitChildren = false;
|
||||
break;
|
||||
case EOpConstructFloat:
|
||||
writeTriplet(visit, "float(", NULL, ")");
|
||||
writeConstructorTriplet(visit, node->getType(), "float");
|
||||
break;
|
||||
case EOpConstructVec2:
|
||||
writeBuiltInFunctionTriplet(visit, "vec2(", false);
|
||||
writeConstructorTriplet(visit, node->getType(), "vec2");
|
||||
break;
|
||||
case EOpConstructVec3:
|
||||
writeBuiltInFunctionTriplet(visit, "vec3(", false);
|
||||
writeConstructorTriplet(visit, node->getType(), "vec3");
|
||||
break;
|
||||
case EOpConstructVec4:
|
||||
writeBuiltInFunctionTriplet(visit, "vec4(", false);
|
||||
writeConstructorTriplet(visit, node->getType(), "vec4");
|
||||
break;
|
||||
case EOpConstructBool:
|
||||
writeTriplet(visit, "bool(", NULL, ")");
|
||||
writeConstructorTriplet(visit, node->getType(), "bool");
|
||||
break;
|
||||
case EOpConstructBVec2:
|
||||
writeBuiltInFunctionTriplet(visit, "bvec2(", false);
|
||||
writeConstructorTriplet(visit, node->getType(), "bvec2");
|
||||
break;
|
||||
case EOpConstructBVec3:
|
||||
writeBuiltInFunctionTriplet(visit, "bvec3(", false);
|
||||
writeConstructorTriplet(visit, node->getType(), "bvec3");
|
||||
break;
|
||||
case EOpConstructBVec4:
|
||||
writeBuiltInFunctionTriplet(visit, "bvec4(", false);
|
||||
writeConstructorTriplet(visit, node->getType(), "bvec4");
|
||||
break;
|
||||
case EOpConstructInt:
|
||||
writeTriplet(visit, "int(", NULL, ")");
|
||||
writeConstructorTriplet(visit, node->getType(), "int");
|
||||
break;
|
||||
case EOpConstructIVec2:
|
||||
writeBuiltInFunctionTriplet(visit, "ivec2(", false);
|
||||
writeConstructorTriplet(visit, node->getType(), "ivec2");
|
||||
break;
|
||||
case EOpConstructIVec3:
|
||||
writeBuiltInFunctionTriplet(visit, "ivec3(", false);
|
||||
writeConstructorTriplet(visit, node->getType(), "ivec3");
|
||||
break;
|
||||
case EOpConstructIVec4:
|
||||
writeBuiltInFunctionTriplet(visit, "ivec4(", false);
|
||||
writeConstructorTriplet(visit, node->getType(), "ivec4");
|
||||
break;
|
||||
case EOpConstructUInt:
|
||||
writeConstructorTriplet(visit, node->getType(), "uint");
|
||||
break;
|
||||
case EOpConstructUVec2:
|
||||
writeConstructorTriplet(visit, node->getType(), "uvec2");
|
||||
break;
|
||||
case EOpConstructUVec3:
|
||||
writeConstructorTriplet(visit, node->getType(), "uvec3");
|
||||
break;
|
||||
case EOpConstructUVec4:
|
||||
writeConstructorTriplet(visit, node->getType(), "uvec4");
|
||||
break;
|
||||
case EOpConstructMat2:
|
||||
writeBuiltInFunctionTriplet(visit, "mat2(", false);
|
||||
writeConstructorTriplet(visit, node->getType(), "mat2");
|
||||
break;
|
||||
case EOpConstructMat2x3:
|
||||
writeConstructorTriplet(visit, node->getType(), "mat2x3");
|
||||
break;
|
||||
case EOpConstructMat2x4:
|
||||
writeConstructorTriplet(visit, node->getType(), "mat2x4");
|
||||
break;
|
||||
case EOpConstructMat3x2:
|
||||
writeConstructorTriplet(visit, node->getType(), "mat3x2");
|
||||
break;
|
||||
case EOpConstructMat3:
|
||||
writeBuiltInFunctionTriplet(visit, "mat3(", false);
|
||||
writeConstructorTriplet(visit, node->getType(), "mat3");
|
||||
break;
|
||||
case EOpConstructMat3x4:
|
||||
writeConstructorTriplet(visit, node->getType(), "mat3x4");
|
||||
break;
|
||||
case EOpConstructMat4x2:
|
||||
writeConstructorTriplet(visit, node->getType(), "mat4x2");
|
||||
break;
|
||||
case EOpConstructMat4x3:
|
||||
writeConstructorTriplet(visit, node->getType(), "mat4x3");
|
||||
break;
|
||||
case EOpConstructMat4:
|
||||
writeBuiltInFunctionTriplet(visit, "mat4(", false);
|
||||
writeConstructorTriplet(visit, node->getType(), "mat4");
|
||||
break;
|
||||
case EOpConstructStruct:
|
||||
if (visit == PreVisit)
|
||||
{
|
||||
const TType &type = node->getType();
|
||||
ASSERT(type.getBasicType() == EbtStruct);
|
||||
out << hashName(type.getStruct()->name()) << "(";
|
||||
TString constructorName = hashName(type.getStruct()->name());
|
||||
writeConstructorTriplet(visit, node->getType(), constructorName.c_str());
|
||||
break;
|
||||
}
|
||||
else if (visit == InVisit)
|
||||
{
|
||||
out << ", ";
|
||||
}
|
||||
else
|
||||
{
|
||||
out << ")";
|
||||
}
|
||||
break;
|
||||
|
||||
case EOpOuterProduct:
|
||||
writeBuiltInFunctionTriplet(visit, "outerProduct(", useEmulatedFunction);
|
||||
@ -1004,8 +1089,12 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node)
|
||||
TInfoSinkBase &out = objSink();
|
||||
|
||||
incrementDepth(node);
|
||||
// Loop header.
|
||||
|
||||
TLoopType loopType = node->getType();
|
||||
|
||||
// Only for loops can be unrolled
|
||||
ASSERT(!node->getUnrollFlag() || loopType == ELoopFor);
|
||||
|
||||
if (loopType == ELoopFor) // for loop
|
||||
{
|
||||
if (!node->getUnrollFlag())
|
||||
@ -1022,6 +1111,8 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node)
|
||||
if (node->getExpression())
|
||||
node->getExpression()->traverse(this);
|
||||
out << ")\n";
|
||||
|
||||
visitCodeBlock(node->getBody());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1034,6 +1125,16 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node)
|
||||
out << "for (int " << name << " = 0; "
|
||||
<< name << " < 1; "
|
||||
<< "++" << name << ")\n";
|
||||
|
||||
out << "{\n";
|
||||
mLoopUnrollStack.push(node);
|
||||
while (mLoopUnrollStack.satisfiesLoopCondition())
|
||||
{
|
||||
visitCodeBlock(node->getBody());
|
||||
mLoopUnrollStack.step();
|
||||
}
|
||||
mLoopUnrollStack.pop();
|
||||
out << "}\n";
|
||||
}
|
||||
}
|
||||
else if (loopType == ELoopWhile) // while loop
|
||||
@ -1042,39 +1143,22 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node)
|
||||
ASSERT(node->getCondition() != NULL);
|
||||
node->getCondition()->traverse(this);
|
||||
out << ")\n";
|
||||
|
||||
visitCodeBlock(node->getBody());
|
||||
}
|
||||
else // do-while loop
|
||||
{
|
||||
ASSERT(loopType == ELoopDoWhile);
|
||||
out << "do\n";
|
||||
}
|
||||
|
||||
// Loop body.
|
||||
if (node->getUnrollFlag())
|
||||
{
|
||||
out << "{\n";
|
||||
mLoopUnrollStack.push(node);
|
||||
while (mLoopUnrollStack.satisfiesLoopCondition())
|
||||
{
|
||||
visitCodeBlock(node->getBody());
|
||||
mLoopUnrollStack.step();
|
||||
}
|
||||
mLoopUnrollStack.pop();
|
||||
out << "}\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
visitCodeBlock(node->getBody());
|
||||
}
|
||||
|
||||
// Loop footer.
|
||||
if (loopType == ELoopDoWhile) // do-while loop
|
||||
{
|
||||
out << "while (";
|
||||
ASSERT(node->getCondition() != NULL);
|
||||
node->getCondition()->traverse(this);
|
||||
out << ");\n";
|
||||
}
|
||||
|
||||
decrementDepth();
|
||||
|
||||
// No need to visit children. They have been already processed in
|
||||
@ -1129,6 +1213,10 @@ TString TOutputGLSLBase::getTypeName(const TType &type)
|
||||
{
|
||||
out << "mat";
|
||||
out << type.getNominalSize();
|
||||
if (type.getSecondarySize() != type.getNominalSize())
|
||||
{
|
||||
out << "x" << type.getSecondarySize();
|
||||
}
|
||||
}
|
||||
else if (type.isVector())
|
||||
{
|
||||
@ -1143,6 +1231,9 @@ TString TOutputGLSLBase::getTypeName(const TType &type)
|
||||
case EbtBool:
|
||||
out << "bvec";
|
||||
break;
|
||||
case EbtUInt:
|
||||
out << "uvec";
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
@ -1177,12 +1268,16 @@ TString TOutputGLSLBase::hashVariableName(const TString &name)
|
||||
return hashName(name);
|
||||
}
|
||||
|
||||
TString TOutputGLSLBase::hashFunctionName(const TString &mangled_name)
|
||||
TString TOutputGLSLBase::hashFunctionNameIfNeeded(const TName &mangledName)
|
||||
{
|
||||
TString name = TFunction::unmangleName(mangled_name);
|
||||
if (mSymbolTable.findBuiltIn(mangled_name, mShaderVersion) != NULL || name == "main")
|
||||
TString mangledStr = mangledName.getString();
|
||||
TString name = TFunction::unmangleName(mangledStr);
|
||||
if (mSymbolTable.findBuiltIn(mangledStr, mShaderVersion) != nullptr || name == "main")
|
||||
return translateTextureFunction(name);
|
||||
return hashName(name);
|
||||
if (mangledName.isInternal())
|
||||
return name;
|
||||
else
|
||||
return hashName(name);
|
||||
}
|
||||
|
||||
bool TOutputGLSLBase::structDeclared(const TStructure *structure) const
|
||||
@ -1215,3 +1310,70 @@ void TOutputGLSLBase::declareStruct(const TStructure *structure)
|
||||
out << "}";
|
||||
}
|
||||
|
||||
void TOutputGLSLBase::declareInterfaceBlockLayout(const TInterfaceBlock *interfaceBlock)
|
||||
{
|
||||
TInfoSinkBase &out = objSink();
|
||||
|
||||
out << "layout(";
|
||||
|
||||
switch (interfaceBlock->blockStorage())
|
||||
{
|
||||
case EbsUnspecified:
|
||||
case EbsShared:
|
||||
// Default block storage is shared.
|
||||
out << "shared";
|
||||
break;
|
||||
|
||||
case EbsPacked:
|
||||
out << "packed";
|
||||
break;
|
||||
|
||||
case EbsStd140:
|
||||
out << "std140";
|
||||
break;
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
out << ", ";
|
||||
|
||||
switch (interfaceBlock->matrixPacking())
|
||||
{
|
||||
case EmpUnspecified:
|
||||
case EmpColumnMajor:
|
||||
// Default matrix packing is column major.
|
||||
out << "column_major";
|
||||
break;
|
||||
|
||||
case EmpRowMajor:
|
||||
out << "row_major";
|
||||
break;
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
out << ") ";
|
||||
}
|
||||
|
||||
void TOutputGLSLBase::declareInterfaceBlock(const TInterfaceBlock *interfaceBlock)
|
||||
{
|
||||
TInfoSinkBase &out = objSink();
|
||||
|
||||
out << hashName(interfaceBlock->name()) << "{\n";
|
||||
const TFieldList &fields = interfaceBlock->fields();
|
||||
for (size_t i = 0; i < fields.size(); ++i)
|
||||
{
|
||||
const TField *field = fields[i];
|
||||
if (writeVariablePrecision(field->type()->getPrecision()))
|
||||
out << " ";
|
||||
out << getTypeName(*field->type()) << " " << hashName(field->name());
|
||||
if (field->type()->isArray())
|
||||
out << arrayBrackets(*field->type());
|
||||
out << ";\n";
|
||||
}
|
||||
out << "}";
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user