Update ANGLE to chromium/2651

Change-Id: I1cd32b780b1a0b913fab870e155ae1f4f9ac40d7
Reviewed-by: Maurice Kalinowski <maurice.kalinowski@qt.io>
This commit is contained in:
Oliver Wolff 2016-03-24 12:38:18 +01:00 committed by Oliver Wolff
parent d3dcc6f610
commit e12ba07322
493 changed files with 70061 additions and 23976 deletions

View File

@ -41,3 +41,4 @@ Aitor Moreno
Yuri O'Donnell
Josh Soref
Maks Naumov
Jinyoung Hur

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

File diff suppressed because it is too large Load Diff

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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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

View 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_

View File

@ -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);
}
}

View File

@ -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; }

View File

@ -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

View File

@ -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();
}

View File

@ -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)

View File

@ -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_

View File

@ -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

View File

@ -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);
}

View File

@ -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)

View File

@ -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

View 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_

View File

@ -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

View 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();
}
}

View 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_

View File

@ -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

View File

@ -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)

View File

@ -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_

View File

@ -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);

View File

@ -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
};

View File

@ -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(&macroExpander, 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(&macroExpander, 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))
{

View File

@ -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

View File

@ -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);

View File

@ -28,7 +28,7 @@ WHICH GENERATES THE GLSL ES preprocessor expression parser.
#pragma GCC diagnostic ignored "-Wuninitialized"
#endif
#elif defined(_MSC_VER)
#pragma warning(disable: 4065 4701 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)
{

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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_

View File

@ -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 &macro,
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 &macro,
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 &macro,
repl.setAtStartOfLine(identifier.atStartOfLine());
repl.setHasLeadingSpace(identifier.hasLeadingSpace());
}
repl.location = identifier.location;
repl.location = replacementLocation;
}
return true;
}
bool MacroExpander::collectMacroArgs(const Macro &macro,
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 &macro,
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 &macro,
{
MacroArg &arg = args->at(i);
TokenLexer lexer(&arg);
MacroExpander expander(&lexer, mMacroSet, mDiagnostics);
MacroExpander expander(&lexer, mMacroSet, mDiagnostics, mParseDefined);
arg.clear();
expander.lex(&token);

View File

@ -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 &macro,
const Token &identifier,
std::vector<MacroArg> *args);
std::vector<MacroArg> *args,
SourceLocation *closingParenthesisLocation);
void replaceMacroParams(const Macro &macro,
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;

View File

@ -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, &macroSet, diag, directiveHandler),
macroExpander(&directiveParser, &macroSet, diag)
macroExpander(&directiveParser, &macroSet, 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)

View File

@ -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);

View File

@ -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>"*"

View File

@ -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.

View 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;
}

View 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_

View 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 &param : *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);
}

View 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_

View File

@ -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)

View File

@ -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 &param)
{
return SetFunctionCalled(FunctionId(op, param));
return SetFunctionCalled(FunctionId(op, &param));
}
bool BuiltInFunctionEmulator::SetFunctionCalled(
TOperator op, const TType& param1, const TType& param2)
bool BuiltInFunctionEmulator::SetFunctionCalled(TOperator op, const TType &param1, const TType &param2)
{
return SetFunctionCalled(FunctionId(op, param1, param2));
return SetFunctionCalled(FunctionId(op, &param1, &param2));
}
bool BuiltInFunctionEmulator::SetFunctionCalled(
TOperator op, const TType& param1, const TType& param2, const TType& param3)
bool BuiltInFunctionEmulator::SetFunctionCalled(TOperator op,
const TType &param1, const TType &param2, const TType &param3)
{
return SetFunctionCalled(FunctionId(op, param1, param2, param3));
return SetFunctionCalled(FunctionId(op, &param1, &param2, &param3));
}
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));
}

View File

@ -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 &param);
bool SetFunctionCalled(TOperator op, const TType &param1, const TType &param2);
bool SetFunctionCalled(TOperator op, const TType &param1, const TType &param2, const TType &param3);
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;

View File

@ -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
}
}

View File

@ -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_

View File

@ -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");
}

View 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;
}

View 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_

View 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;
}

View 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_

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
};
//

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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.

View File

@ -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;
};

View File

@ -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);

View File

@ -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_

View File

@ -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_

View 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;
}
}

View 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_

View File

@ -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;

View File

@ -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;

View File

@ -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_

View File

@ -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)

View File

@ -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();
}

View File

@ -10,7 +10,7 @@
bool InitializeParseContextIndex();
void FreeParseContextIndex();
struct TParseContext;
class TParseContext;
extern void SetGlobalParseContext(TParseContext* context);
extern TParseContext* GetGlobalParseContext();

View File

@ -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);

View File

@ -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

View File

@ -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 &parameter, 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; }

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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,

View File

@ -21,7 +21,8 @@ public:
bool forceHighp);
protected:
virtual bool writeVariablePrecision(TPrecision precision);
bool writeVariablePrecision(TPrecision precision) override;
private:
bool mForceHighp;
};

View File

@ -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)

View File

@ -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_

View File

@ -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