Bug 1459785 - Update ANGLE to chromium/3396.

MozReview-Commit-ID: EA39lUfXuPI
This commit is contained in:
Jeff Gilbert 2018-05-07 17:38:32 -07:00
parent 10e715bdf1
commit 1895dfc6e6
351 changed files with 39061 additions and 13689 deletions

View File

@ -175,6 +175,11 @@ EGLAPI EGLint EGLAPIENTRY eglProgramCacheResizeANGLE(EGLDisplay dpy, EGLint limi
#define EGL_TEXTURE_INTERNAL_FORMAT_ANGLE 0x345D #define EGL_TEXTURE_INTERNAL_FORMAT_ANGLE 0x345D
#endif /* EGL_ANGLE_iosurface_client_buffer */ #endif /* EGL_ANGLE_iosurface_client_buffer */
#ifndef EGL_ANGLE_create_context_extensions_enabled
#define EGL_ANGLE_create_context_extensions_enabled 1
#define EGL_EXTENSIONS_ENABLED_ANGLE 0x345F
#endif /* EGL_ANGLE_create_context_extensions_enabled */
// clang-format on // clang-format on
#endif // INCLUDE_EGL_EGLEXT_ANGLE_ #endif // INCLUDE_EGL_EGLEXT_ANGLE_

View File

@ -25,7 +25,7 @@
// Version number for shader translation API. // Version number for shader translation API.
// It is incremented every time the API changes. // It is incremented every time the API changes.
#define ANGLE_SH_VERSION 196 #define ANGLE_SH_VERSION 197
enum ShShaderSpec enum ShShaderSpec
{ {

View File

@ -126,7 +126,12 @@ struct ShaderVariable
// and flattenedOffsetInParentArrays of a[2][1] would be 2*4 + 1 = 9. // and flattenedOffsetInParentArrays of a[2][1] would be 2*4 + 1 = 9.
unsigned int flattenedOffsetInParentArrays; unsigned int flattenedOffsetInParentArrays;
// Static use means that the variable is accessed somewhere in the shader source.
bool staticUse; bool staticUse;
// A variable is active unless the compiler determined that it is not accessed by the shader.
// All active variables are statically used, but not all statically used variables are
// necessarily active. GLES 3.0.5 section 2.12.6. GLES 3.1 section 7.3.1.
bool active;
std::vector<ShaderVariable> fields; std::vector<ShaderVariable> fields;
std::string structName; std::string structName;
@ -279,6 +284,7 @@ struct InterfaceBlock
int binding; int binding;
bool staticUse; bool staticUse;
bool active;
BlockType blockType; BlockType blockType;
std::vector<InterfaceBlockField> fields; std::vector<InterfaceBlockField> fields;
}; };

View File

@ -2,7 +2,7 @@
#define __khrplatform_h_ #define __khrplatform_h_
/* /*
** Copyright (c) 2008-2009 The Khronos Group Inc. ** Copyright (c) 2008-2018 The Khronos Group Inc.
** **
** Permission is hereby granted, free of charge, to any person obtaining a ** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the ** copy of this software and/or associated documentation files (the
@ -26,18 +26,16 @@
/* Khronos platform-specific types and definitions. /* Khronos platform-specific types and definitions.
* *
* $Revision: 32517 $ on $Date: 2016-03-11 02:41:19 -0800 (Fri, 11 Mar 2016) $ * The master copy of khrplatform.h is maintained in the Khronos EGL
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
* The last semantic modification to khrplatform.h was at commit ID:
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
* *
* Adopters may modify this file to suit their platform. Adopters are * Adopters may modify this file to suit their platform. Adopters are
* encouraged to submit platform specific modifications to the Khronos * encouraged to submit platform specific modifications to the Khronos
* group so that they can be included in future versions of this file. * group so that they can be included in future versions of this file.
* Please submit changes by sending them to the public Khronos Bugzilla * Please submit changes by filing pull requests or issues on
* (http://khronos.org/bugzilla) by filing a bug against product * the EGL Registry repository linked above.
* "Khronos (general)" component "Registry".
*
* A predefined template which fills in some of the bug fields can be
* reached using http://tinyurl.com/khrplatform-h-bugreport, but you
* must create a Bugzilla login first.
* *
* *
* See the Implementer's Guidelines for information about where this file * See the Implementer's Guidelines for information about where this file
@ -102,8 +100,7 @@
#elif defined (__SYMBIAN32__) #elif defined (__SYMBIAN32__)
# define KHRONOS_APICALL IMPORT_C # define KHRONOS_APICALL IMPORT_C
#elif defined(__ANDROID__) #elif defined(__ANDROID__)
# include <sys/cdefs.h> # define KHRONOS_APICALL __attribute__((visibility("default")))
# define KHRONOS_APICALL __attribute__((visibility("default"))) __NDK_FPABI__
#else #else
# define KHRONOS_APICALL # define KHRONOS_APICALL
#endif #endif
@ -282,4 +279,4 @@ typedef enum {
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
} khronos_boolean_enum_t; } khronos_boolean_enum_t;
#endif /* __khrplatform_h_ */ #endif /* __khrplatform_h_ */

View File

@ -1,3 +1,3 @@
#define ANGLE_COMMIT_HASH "fcbca0e873c3" #define ANGLE_COMMIT_HASH "2426b097472f"
#define ANGLE_COMMIT_HASH_SIZE 12 #define ANGLE_COMMIT_HASH_SIZE 12
#define ANGLE_COMMIT_DATE "2018-04-20 16:07:35 -0700" #define ANGLE_COMMIT_DATE "2018-05-22 15:14:46 -0700"

View File

@ -15,13 +15,16 @@ namespace angle
template <typename T> template <typename T>
struct Color struct Color
{ {
Color();
Color(T r, T g, T b, T a);
const T *data() const { return &red; }
T *ptr() { return &red; }
T red; T red;
T green; T green;
T blue; T blue;
T alpha; T alpha;
Color();
Color(T r, T g, T b, T a);
}; };
template <typename T> template <typename T>

View File

@ -0,0 +1,331 @@
//
// Copyright 2018 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.
//
// FixedVector.h:
// A vector class with a maximum size and fixed storage.
//
#ifndef COMMON_FIXEDVECTOR_H_
#define COMMON_FIXEDVECTOR_H_
#include "common/debug.h"
#include <algorithm>
#include <array>
#include <initializer_list>
namespace angle
{
template <class T, size_t N, class Storage = std::array<T, N>>
class FixedVector final
{
public:
using value_type = typename Storage::value_type;
using size_type = typename Storage::size_type;
using reference = typename Storage::reference;
using const_reference = typename Storage::const_reference;
using pointer = typename Storage::pointer;
using const_pointer = typename Storage::const_pointer;
using iterator = typename Storage::iterator;
using const_iterator = typename Storage::const_iterator;
using reverse_iterator = typename Storage::reverse_iterator;
using const_reverse_iterator = typename Storage::const_reverse_iterator;
FixedVector();
FixedVector(size_type count, const value_type &value);
FixedVector(size_type count);
FixedVector(const FixedVector<T, N, Storage> &other);
FixedVector(FixedVector<T, N, Storage> &&other);
FixedVector(std::initializer_list<value_type> init);
FixedVector<T, N, Storage> &operator=(const FixedVector<T, N, Storage> &other);
FixedVector<T, N, Storage> &operator=(FixedVector<T, N, Storage> &&other);
FixedVector<T, N, Storage> &operator=(std::initializer_list<value_type> init);
~FixedVector();
reference at(size_type pos);
const_reference at(size_type pos) const;
reference operator[](size_type pos);
const_reference operator[](size_type pos) const;
pointer data();
const_pointer data() const;
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
bool empty() const;
size_type size() const;
size_type max_size() const;
void clear();
void push_back(const value_type &value);
void push_back(value_type &&value);
void pop_back();
reference back();
const_reference back() const;
void swap(FixedVector<T, N, Storage> &other);
void resize(size_type count);
void resize(size_type count, const value_type &value);
bool full() const;
private:
void assign_from_initializer_list(std::initializer_list<value_type> init);
Storage mStorage;
size_type mSize = 0;
};
template <class T, size_t N, class Storage>
bool operator==(const FixedVector<T, N, Storage> &a, const FixedVector<T, N, Storage> &b)
{
return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin());
}
template <class T, size_t N, class Storage>
bool operator!=(const FixedVector<T, N, Storage> &a, const FixedVector<T, N, Storage> &b)
{
return !(a == b);
}
template <class T, size_t N, class Storage>
FixedVector<T, N, Storage>::FixedVector() = default;
template <class T, size_t N, class Storage>
FixedVector<T, N, Storage>::FixedVector(size_type count, const value_type &value) : mSize(count)
{
ASSERT(count <= N);
std::fill(mStorage.begin(), mStorage.begin() + count, value);
}
template <class T, size_t N, class Storage>
FixedVector<T, N, Storage>::FixedVector(size_type count) : mSize(count)
{
ASSERT(count <= N);
}
template <class T, size_t N, class Storage>
FixedVector<T, N, Storage>::FixedVector(const FixedVector<T, N, Storage> &other) = default;
template <class T, size_t N, class Storage>
FixedVector<T, N, Storage>::FixedVector(FixedVector<T, N, Storage> &&other) = default;
template <class T, size_t N, class Storage>
FixedVector<T, N, Storage>::FixedVector(std::initializer_list<value_type> init)
{
ASSERT(init.size() <= N);
assign_from_initializer_list(init);
}
template <class T, size_t N, class Storage>
FixedVector<T, N, Storage> &FixedVector<T, N, Storage>::operator=(
const FixedVector<T, N, Storage> &other) = default;
template <class T, size_t N, class Storage>
FixedVector<T, N, Storage> &FixedVector<T, N, Storage>::operator=(
FixedVector<T, N, Storage> &&other) = default;
template <class T, size_t N, class Storage>
FixedVector<T, N, Storage> &FixedVector<T, N, Storage>::operator=(
std::initializer_list<value_type> init)
{
clear();
ASSERT(init.size() <= N);
assign_from_initializer_list(init);
return this;
}
template <class T, size_t N, class Storage>
FixedVector<T, N, Storage>::~FixedVector()
{
clear();
}
template <class T, size_t N, class Storage>
typename FixedVector<T, N, Storage>::reference FixedVector<T, N, Storage>::at(size_type pos)
{
ASSERT(pos < N);
return mStorage.at(pos);
}
template <class T, size_t N, class Storage>
typename FixedVector<T, N, Storage>::const_reference FixedVector<T, N, Storage>::at(
size_type pos) const
{
ASSERT(pos < N);
return mStorage.at(pos);
}
template <class T, size_t N, class Storage>
typename FixedVector<T, N, Storage>::reference FixedVector<T, N, Storage>::operator[](size_type pos)
{
ASSERT(pos < N);
return mStorage[pos];
}
template <class T, size_t N, class Storage>
typename FixedVector<T, N, Storage>::const_reference FixedVector<T, N, Storage>::operator[](
size_type pos) const
{
ASSERT(pos < N);
return mStorage[pos];
}
template <class T, size_t N, class Storage>
typename FixedVector<T, N, Storage>::const_pointer angle::FixedVector<T, N, Storage>::data() const
{
return mStorage.data();
}
template <class T, size_t N, class Storage>
typename FixedVector<T, N, Storage>::pointer angle::FixedVector<T, N, Storage>::data()
{
return mStorage.data();
}
template <class T, size_t N, class Storage>
typename FixedVector<T, N, Storage>::iterator FixedVector<T, N, Storage>::begin()
{
return mStorage.begin();
}
template <class T, size_t N, class Storage>
typename FixedVector<T, N, Storage>::const_iterator FixedVector<T, N, Storage>::begin() const
{
return mStorage.begin();
}
template <class T, size_t N, class Storage>
typename FixedVector<T, N, Storage>::iterator FixedVector<T, N, Storage>::end()
{
return mStorage.begin() + mSize;
}
template <class T, size_t N, class Storage>
typename FixedVector<T, N, Storage>::const_iterator FixedVector<T, N, Storage>::end() const
{
return mStorage.begin() + mSize;
}
template <class T, size_t N, class Storage>
bool FixedVector<T, N, Storage>::empty() const
{
return mSize == 0;
}
template <class T, size_t N, class Storage>
typename FixedVector<T, N, Storage>::size_type FixedVector<T, N, Storage>::size() const
{
return mSize;
}
template <class T, size_t N, class Storage>
typename FixedVector<T, N, Storage>::size_type FixedVector<T, N, Storage>::max_size() const
{
return N;
}
template <class T, size_t N, class Storage>
void FixedVector<T, N, Storage>::clear()
{
resize(0);
}
template <class T, size_t N, class Storage>
void FixedVector<T, N, Storage>::push_back(const value_type &value)
{
ASSERT(mSize < N);
mStorage[mSize] = value;
mSize++;
}
template <class T, size_t N, class Storage>
void FixedVector<T, N, Storage>::push_back(value_type &&value)
{
ASSERT(mSize < N);
mStorage[mSize] = std::move(value);
mSize++;
}
template <class T, size_t N, class Storage>
void FixedVector<T, N, Storage>::pop_back()
{
ASSERT(mSize > 0);
mSize--;
}
template <class T, size_t N, class Storage>
typename FixedVector<T, N, Storage>::reference FixedVector<T, N, Storage>::back()
{
ASSERT(mSize > 0);
return mStorage[mSize - 1];
}
template <class T, size_t N, class Storage>
typename FixedVector<T, N, Storage>::const_reference FixedVector<T, N, Storage>::back() const
{
ASSERT(mSize > 0);
return mStorage[mSize - 1];
}
template <class T, size_t N, class Storage>
void FixedVector<T, N, Storage>::swap(FixedVector<T, N, Storage> &other)
{
std::swap(mSize, other.mSize);
std::swap(mStorage, other.mStorage);
}
template <class T, size_t N, class Storage>
void FixedVector<T, N, Storage>::resize(size_type count)
{
resize(count, value_type());
}
template <class T, size_t N, class Storage>
void FixedVector<T, N, Storage>::resize(size_type count, const value_type &value)
{
ASSERT(count <= N);
while (mSize > count)
{
mSize--;
mStorage[mSize] = T();
}
while (mSize < count)
{
mStorage[mSize] = value;
mSize++;
}
}
template <class T, size_t N, class Storage>
void FixedVector<T, N, Storage>::assign_from_initializer_list(
std::initializer_list<value_type> init)
{
for (auto element : init)
{
mStorage[mSize] = std::move(element);
mSize++;
}
}
template <class T, size_t N, class Storage>
bool FixedVector<T, N, Storage>::full() const
{
return (mSize == N);
}
} // namespace angle
#endif // COMMON_FIXEDVECTOR_H_

View File

@ -191,6 +191,7 @@ std::string ToString(const T &value)
#define snprintf _snprintf #define snprintf _snprintf
#endif #endif
#define GL_A1RGB5_ANGLEX 0x6AC5
#define GL_BGRX8_ANGLEX 0x6ABA #define GL_BGRX8_ANGLEX 0x6ABA
#define GL_BGR565_ANGLEX 0x6ABB #define GL_BGR565_ANGLEX 0x6ABB
#define GL_BGRA4_ANGLEX 0x6ABC #define GL_BGRA4_ANGLEX 0x6ABC

View File

@ -40,10 +40,10 @@ class BitSetT final
private: private:
friend class BitSetT; friend class BitSetT;
Reference(BitSetT *parent, std::size_t bit) : mParent(parent), mBit(bit) {} Reference(BitSetT *parent, ParamT bit) : mParent(parent), mBit(bit) {}
BitSetT *mParent; BitSetT *mParent;
std::size_t mBit; ParamT mBit;
}; };
class Iterator final class Iterator final
@ -64,8 +64,7 @@ class BitSetT final
}; };
BitSetT(); BitSetT();
BitSetT(BitsT value); constexpr explicit BitSetT(BitsT value);
~BitSetT();
BitSetT(const BitSetT &other); BitSetT(const BitSetT &other);
BitSetT &operator=(const BitSetT &other); BitSetT &operator=(const BitSetT &other);
@ -90,6 +89,10 @@ class BitSetT final
BitSetT &operator^=(const BitSetT &other); BitSetT &operator^=(const BitSetT &other);
BitSetT operator~() const; BitSetT operator~() const;
BitSetT &operator&=(BitsT value);
BitSetT &operator|=(BitsT value);
BitSetT &operator^=(BitsT value);
BitSetT operator<<(std::size_t pos) const; BitSetT operator<<(std::size_t pos) const;
BitSetT &operator<<=(std::size_t pos); BitSetT &operator<<=(std::size_t pos);
BitSetT operator>>(std::size_t pos) const; BitSetT operator>>(std::size_t pos) const;
@ -115,7 +118,11 @@ class BitSetT final
{ {
return (static_cast<BitsT>(1) << static_cast<size_t>(x)); return (static_cast<BitsT>(1) << static_cast<size_t>(x));
} }
constexpr static BitsT Mask(std::size_t x) { return ((Bit(x - 1) - 1) << 1) + 1; } // Produces a mask of ones up to the "x"th bit.
constexpr static BitsT Mask(std::size_t x)
{
return ((Bit(static_cast<ParamT>(x - 1)) - 1) << 1) + 1;
}
BitsT mBits; BitsT mBits;
}; };
@ -213,12 +220,7 @@ BitSetT<N, BitsT, ParamT>::BitSetT() : mBits(0)
} }
template <size_t N, typename BitsT, typename ParamT> template <size_t N, typename BitsT, typename ParamT>
BitSetT<N, BitsT, ParamT>::BitSetT(BitsT value) : mBits(value & Mask(N)) constexpr BitSetT<N, BitsT, ParamT>::BitSetT(BitsT value) : mBits(value & Mask(N))
{
}
template <size_t N, typename BitsT, typename ParamT>
BitSetT<N, BitsT, ParamT>::~BitSetT()
{ {
} }
@ -312,6 +314,27 @@ BitSetT<N, BitsT, ParamT> BitSetT<N, BitsT, ParamT>::operator~() const
return BitSetT<N, BitsT, ParamT>(~mBits & Mask(N)); return BitSetT<N, BitsT, ParamT>(~mBits & Mask(N));
} }
template <size_t N, typename BitsT, typename ParamT>
BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator&=(BitsT value)
{
mBits &= value;
return *this;
}
template <size_t N, typename BitsT, typename ParamT>
BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator|=(BitsT value)
{
mBits |= value;
return *this;
}
template <size_t N, typename BitsT, typename ParamT>
BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator^=(BitsT value)
{
mBits ^= value;
return *this;
}
template <size_t N, typename BitsT, typename ParamT> template <size_t N, typename BitsT, typename ParamT>
BitSetT<N, BitsT, ParamT> BitSetT<N, BitsT, ParamT>::operator<<(std::size_t pos) const BitSetT<N, BitsT, ParamT> BitSetT<N, BitsT, ParamT>::operator<<(std::size_t pos) const
{ {

View File

@ -9,12 +9,12 @@
#ifndef COMMON_MATHUTIL_H_ #ifndef COMMON_MATHUTIL_H_
#define COMMON_MATHUTIL_H_ #define COMMON_MATHUTIL_H_
#include <limits>
#include <algorithm>
#include <math.h> #include <math.h>
#include <string.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <limits>
#include <anglebase/numerics/safe_math.h> #include <anglebase/numerics/safe_math.h>
@ -30,10 +30,10 @@ using base::IsValueInRangeForNumericType;
namespace gl namespace gl
{ {
const unsigned int Float32One = 0x3F800000; const unsigned int Float32One = 0x3F800000;
const unsigned short Float16One = 0x3C00; const unsigned short Float16One = 0x3C00;
template<typename T> template <typename T>
inline bool isPow2(T x) inline bool isPow2(T x)
{ {
static_assert(std::is_integral<T>::value, "isPow2 must be called on an integer type."); static_assert(std::is_integral<T>::value, "isPow2 must be called on an integer type.");
@ -43,13 +43,15 @@ inline bool isPow2(T x)
inline int log2(int x) inline int log2(int x)
{ {
int r = 0; int r = 0;
while ((x >> r) > 1) r++; while ((x >> r) > 1)
r++;
return r; return r;
} }
inline unsigned int ceilPow2(unsigned int x) inline unsigned int ceilPow2(unsigned int x)
{ {
if (x != 0) x--; if (x != 0)
x--;
x |= x >> 1; x |= x >> 1;
x |= x >> 2; x |= x >> 2;
x |= x >> 4; x |= x >> 4;
@ -108,7 +110,7 @@ inline int clampCast(bool value)
return static_cast<int>(value); return static_cast<int>(value);
} }
template<typename T, typename MIN, typename MAX> template <typename T, typename MIN, typename MAX>
inline T clamp(T x, MIN min, MAX max) inline T clamp(T x, MIN min, MAX max)
{ {
// Since NaNs fail all comparison tests, a NaN value will default to min // Since NaNs fail all comparison tests, a NaN value will default to min
@ -120,7 +122,7 @@ inline float clamp01(float x)
return clamp(x, 0.0f, 1.0f); return clamp(x, 0.0f, 1.0f);
} }
template<const int n> template <const int n>
inline unsigned int unorm(float x) inline unsigned int unorm(float x)
{ {
const unsigned int max = 0xFFFFFFFF >> (32 - n); const unsigned int max = 0xFFFFFFFF >> (32 - n);
@ -142,7 +144,7 @@ inline unsigned int unorm(float x)
inline bool supportsSSE2() inline bool supportsSSE2()
{ {
#if defined(ANGLE_USE_SSE) #if defined(ANGLE_USE_SSE)
static bool checked = false; static bool checked = false;
static bool supports = false; static bool supports = false;
if (checked) if (checked)
@ -182,19 +184,19 @@ destType bitCast(const sourceType &source)
inline unsigned short float32ToFloat16(float fp32) inline unsigned short float32ToFloat16(float fp32)
{ {
unsigned int fp32i = bitCast<unsigned int>(fp32); unsigned int fp32i = bitCast<unsigned int>(fp32);
unsigned int sign = (fp32i & 0x80000000) >> 16; unsigned int sign = (fp32i & 0x80000000) >> 16;
unsigned int abs = fp32i & 0x7FFFFFFF; unsigned int abs = fp32i & 0x7FFFFFFF;
if(abs > 0x47FFEFFF) // Infinity if (abs > 0x47FFEFFF) // Infinity
{ {
return static_cast<unsigned short>(sign | 0x7FFF); return static_cast<unsigned short>(sign | 0x7FFF);
} }
else if(abs < 0x38800000) // Denormal else if (abs < 0x38800000) // Denormal
{ {
unsigned int mantissa = (abs & 0x007FFFFF) | 0x00800000; unsigned int mantissa = (abs & 0x007FFFFF) | 0x00800000;
int e = 113 - (abs >> 23); int e = 113 - (abs >> 23);
if(e < 24) if (e < 24)
{ {
abs = mantissa >> e; abs = mantissa >> e;
} }
@ -207,7 +209,8 @@ inline unsigned short float32ToFloat16(float fp32)
} }
else else
{ {
return static_cast<unsigned short>(sign | (abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13); return static_cast<unsigned short>(
sign | (abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
} }
} }
@ -218,24 +221,24 @@ void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float
inline unsigned short float32ToFloat11(float fp32) inline unsigned short float32ToFloat11(float fp32)
{ {
const unsigned int float32MantissaMask = 0x7FFFFF; const unsigned int float32MantissaMask = 0x7FFFFF;
const unsigned int float32ExponentMask = 0x7F800000; const unsigned int float32ExponentMask = 0x7F800000;
const unsigned int float32SignMask = 0x80000000; const unsigned int float32SignMask = 0x80000000;
const unsigned int float32ValueMask = ~float32SignMask; const unsigned int float32ValueMask = ~float32SignMask;
const unsigned int float32ExponentFirstBit = 23; const unsigned int float32ExponentFirstBit = 23;
const unsigned int float32ExponentBias = 127; const unsigned int float32ExponentBias = 127;
const unsigned short float11Max = 0x7BF; const unsigned short float11Max = 0x7BF;
const unsigned short float11MantissaMask = 0x3F; const unsigned short float11MantissaMask = 0x3F;
const unsigned short float11ExponentMask = 0x7C0; const unsigned short float11ExponentMask = 0x7C0;
const unsigned short float11BitMask = 0x7FF; const unsigned short float11BitMask = 0x7FF;
const unsigned int float11ExponentBias = 14; const unsigned int float11ExponentBias = 14;
const unsigned int float32Maxfloat11 = 0x477E0000; const unsigned int float32Maxfloat11 = 0x477E0000;
const unsigned int float32Minfloat11 = 0x38800000; const unsigned int float32Minfloat11 = 0x38800000;
const unsigned int float32Bits = bitCast<unsigned int>(fp32); const unsigned int float32Bits = bitCast<unsigned int>(fp32);
const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask; const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
unsigned int float32Val = float32Bits & float32ValueMask; unsigned int float32Val = float32Bits & float32ValueMask;
@ -244,7 +247,9 @@ inline unsigned short float32ToFloat11(float fp32)
// INF or NAN // INF or NAN
if ((float32Val & float32MantissaMask) != 0) if ((float32Val & float32MantissaMask) != 0)
{ {
return float11ExponentMask | (((float32Val >> 17) | (float32Val >> 11) | (float32Val >> 6) | (float32Val)) & float11MantissaMask); return float11ExponentMask |
(((float32Val >> 17) | (float32Val >> 11) | (float32Val >> 6) | (float32Val)) &
float11MantissaMask);
} }
else if (float32Sign) else if (float32Sign)
{ {
@ -272,8 +277,10 @@ inline unsigned short float32ToFloat11(float fp32)
{ {
// The number is too small to be represented as a normalized float11 // The number is too small to be represented as a normalized float11
// Convert it to a denormalized value. // Convert it to a denormalized value.
const unsigned int shift = (float32ExponentBias - float11ExponentBias) - (float32Val >> float32ExponentFirstBit); const unsigned int shift = (float32ExponentBias - float11ExponentBias) -
float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift; (float32Val >> float32ExponentFirstBit);
float32Val =
((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
} }
else else
{ {
@ -287,24 +294,24 @@ inline unsigned short float32ToFloat11(float fp32)
inline unsigned short float32ToFloat10(float fp32) inline unsigned short float32ToFloat10(float fp32)
{ {
const unsigned int float32MantissaMask = 0x7FFFFF; const unsigned int float32MantissaMask = 0x7FFFFF;
const unsigned int float32ExponentMask = 0x7F800000; const unsigned int float32ExponentMask = 0x7F800000;
const unsigned int float32SignMask = 0x80000000; const unsigned int float32SignMask = 0x80000000;
const unsigned int float32ValueMask = ~float32SignMask; const unsigned int float32ValueMask = ~float32SignMask;
const unsigned int float32ExponentFirstBit = 23; const unsigned int float32ExponentFirstBit = 23;
const unsigned int float32ExponentBias = 127; const unsigned int float32ExponentBias = 127;
const unsigned short float10Max = 0x3DF; const unsigned short float10Max = 0x3DF;
const unsigned short float10MantissaMask = 0x1F; const unsigned short float10MantissaMask = 0x1F;
const unsigned short float10ExponentMask = 0x3E0; const unsigned short float10ExponentMask = 0x3E0;
const unsigned short float10BitMask = 0x3FF; const unsigned short float10BitMask = 0x3FF;
const unsigned int float10ExponentBias = 14; const unsigned int float10ExponentBias = 14;
const unsigned int float32Maxfloat10 = 0x477C0000; const unsigned int float32Maxfloat10 = 0x477C0000;
const unsigned int float32Minfloat10 = 0x38800000; const unsigned int float32Minfloat10 = 0x38800000;
const unsigned int float32Bits = bitCast<unsigned int>(fp32); const unsigned int float32Bits = bitCast<unsigned int>(fp32);
const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask; const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
unsigned int float32Val = float32Bits & float32ValueMask; unsigned int float32Val = float32Bits & float32ValueMask;
@ -313,7 +320,9 @@ inline unsigned short float32ToFloat10(float fp32)
// INF or NAN // INF or NAN
if ((float32Val & float32MantissaMask) != 0) if ((float32Val & float32MantissaMask) != 0)
{ {
return float10ExponentMask | (((float32Val >> 18) | (float32Val >> 13) | (float32Val >> 3) | (float32Val)) & float10MantissaMask); return float10ExponentMask |
(((float32Val >> 18) | (float32Val >> 13) | (float32Val >> 3) | (float32Val)) &
float10MantissaMask);
} }
else if (float32Sign) else if (float32Sign)
{ {
@ -341,8 +350,10 @@ inline unsigned short float32ToFloat10(float fp32)
{ {
// The number is too small to be represented as a normalized float11 // The number is too small to be represented as a normalized float11
// Convert it to a denormalized value. // Convert it to a denormalized value.
const unsigned int shift = (float32ExponentBias - float10ExponentBias) - (float32Val >> float32ExponentFirstBit); const unsigned int shift = (float32ExponentBias - float10ExponentBias) -
float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift; (float32Val >> float32ExponentFirstBit);
float32Val =
((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
} }
else else
{ {
@ -379,12 +390,11 @@ inline float float11ToFloat32(unsigned short fp11)
{ {
exponent--; exponent--;
mantissa <<= 1; mantissa <<= 1;
} } while ((mantissa & 0x40) == 0);
while ((mantissa & 0x40) == 0);
mantissa = mantissa & 0x3F; mantissa = mantissa & 0x3F;
} }
else // The value is zero else // The value is zero
{ {
exponent = static_cast<unsigned short>(-112); exponent = static_cast<unsigned short>(-112);
} }
@ -418,12 +428,11 @@ inline float float10ToFloat32(unsigned short fp11)
{ {
exponent--; exponent--;
mantissa <<= 1; mantissa <<= 1;
} } while ((mantissa & 0x20) == 0);
while ((mantissa & 0x20) == 0);
mantissa = mantissa & 0x1F; mantissa = mantissa & 0x1F;
} }
else // The value is zero else // The value is zero
{ {
exponent = static_cast<unsigned short>(-112); exponent = static_cast<unsigned short>(-112);
} }
@ -432,6 +441,32 @@ inline float float10ToFloat32(unsigned short fp11)
} }
} }
// Convers to and from float and 16.16 fixed point format.
inline float FixedToFloat(uint32_t fixedInput)
{
return static_cast<float>(fixedInput) / 65536.0f;
}
inline uint32_t FloatToFixed(float floatInput)
{
static constexpr uint32_t kHighest = 32767 * 65536 + 65535;
static constexpr uint32_t kLowest = static_cast<uint32_t>(-32768 * 65536 + 65535);
if (floatInput > 32767.65535)
{
return kHighest;
}
else if (floatInput < -32768.65535)
{
return kLowest;
}
else
{
return static_cast<uint32_t>(floatInput * 65536);
}
}
template <typename T> template <typename T>
inline float normalizedToFloat(T input) inline float normalizedToFloat(T input)
{ {
@ -563,12 +598,16 @@ inline unsigned short averageHalfFloat(unsigned short a, unsigned short b)
inline unsigned int averageFloat11(unsigned int a, unsigned int b) inline unsigned int averageFloat11(unsigned int a, unsigned int b)
{ {
return float32ToFloat11((float11ToFloat32(static_cast<unsigned short>(a)) + float11ToFloat32(static_cast<unsigned short>(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) inline unsigned int averageFloat10(unsigned int a, unsigned int b)
{ {
return float32ToFloat10((float10ToFloat32(static_cast<unsigned short>(a)) + float10ToFloat32(static_cast<unsigned short>(b))) * 0.5f); return float32ToFloat10((float10ToFloat32(static_cast<unsigned short>(a)) +
float10ToFloat32(static_cast<unsigned short>(b))) *
0.5f);
} }
template <typename T> template <typename T>
@ -687,21 +726,21 @@ inline float Ldexp(float x, int exp)
inline uint32_t packSnorm2x16(float f1, float f2) 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 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)); int16_t mostSignificantBits = static_cast<int16_t>(roundf(clamp(f2, -1.0f, 1.0f) * 32767.0f));
return static_cast<uint32_t>(mostSignificantBits) << 16 | return static_cast<uint32_t>(mostSignificantBits) << 16 |
(static_cast<uint32_t>(leastSignificantBits) & 0xFFFF); (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 // First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then,
// component is converted to a normalized floating-point value to generate the returned two float values. // each component is converted to a normalized floating-point value to generate the returned two
// The first float value will be extracted from the least significant bits of the input; // float values. The first float value will be extracted from the least significant bits of the
// the last float value will be extracted from the most-significant bits. // input; the last float value will be extracted from the most-significant bits. The conversion for
// The conversion for unpacked fixed-point value to floating point is done as follows: // unpacked fixed-point value to floating point is done as follows: unpackSnorm2x16 : clamp(f /
// unpackSnorm2x16 : clamp(f / 32767.0, -1, +1) // 32767.0, -1, +1)
inline void unpackSnorm2x16(uint32_t u, float *f1, float *f2) inline void unpackSnorm2x16(uint32_t u, float *f1, float *f2)
{ {
int16_t leastSignificantBits = static_cast<int16_t>(u & 0xFFFF); int16_t leastSignificantBits = static_cast<int16_t>(u & 0xFFFF);
int16_t mostSignificantBits = static_cast<int16_t>(u >> 16); int16_t mostSignificantBits = static_cast<int16_t>(u >> 16);
*f1 = clamp(static_cast<float>(leastSignificantBits) / 32767.0f, -1.0f, 1.0f); *f1 = clamp(static_cast<float>(leastSignificantBits) / 32767.0f, -1.0f, 1.0f);
*f2 = clamp(static_cast<float>(mostSignificantBits) / 32767.0f, -1.0f, 1.0f); *f2 = clamp(static_cast<float>(mostSignificantBits) / 32767.0f, -1.0f, 1.0f);
} }
@ -715,22 +754,22 @@ inline void unpackSnorm2x16(uint32_t u, float *f1, float *f2)
inline uint32_t packUnorm2x16(float f1, float f2) 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 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)); 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); 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 // First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then,
// component is converted to a normalized floating-point value to generate the returned two float values. // each component is converted to a normalized floating-point value to generate the returned two
// The first float value will be extracted from the least significant bits of the input; // float values. The first float value will be extracted from the least significant bits of the
// the last float value will be extracted from the most-significant bits. // input; the last float value will be extracted from the most-significant bits. The conversion for
// The conversion for unpacked fixed-point value to floating point is done as follows: // unpacked fixed-point value to floating point is done as follows: unpackUnorm2x16 : f / 65535.0
// unpackUnorm2x16 : f / 65535.0
inline void unpackUnorm2x16(uint32_t u, float *f1, float *f2) inline void unpackUnorm2x16(uint32_t u, float *f1, float *f2)
{ {
uint16_t leastSignificantBits = static_cast<uint16_t>(u & 0xFFFF); uint16_t leastSignificantBits = static_cast<uint16_t>(u & 0xFFFF);
uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16); uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16);
*f1 = static_cast<float>(leastSignificantBits) / 65535.0f; *f1 = static_cast<float>(leastSignificantBits) / 65535.0f;
*f2 = static_cast<float>(mostSignificantBits) / 65535.0f; *f2 = static_cast<float>(mostSignificantBits) / 65535.0f;
} }
// Helper functions intended to be used only here. // Helper functions intended to be used only here.
@ -821,19 +860,20 @@ inline void UnpackSnorm4x8(uint32_t u, float *f)
inline uint32_t packHalf2x16(float f1, float f2) inline uint32_t packHalf2x16(float f1, float f2)
{ {
uint16_t leastSignificantBits = static_cast<uint16_t>(float32ToFloat16(f1)); uint16_t leastSignificantBits = static_cast<uint16_t>(float32ToFloat16(f1));
uint16_t mostSignificantBits = static_cast<uint16_t>(float32ToFloat16(f2)); uint16_t mostSignificantBits = static_cast<uint16_t>(float32ToFloat16(f2));
return static_cast<uint32_t>(mostSignificantBits) << 16 | static_cast<uint32_t>(leastSignificantBits); 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, // Returns two floating-point values obtained by unpacking a 32-bit unsigned integer into a pair of
// interpreting those values as 16-bit floating-point numbers according to the OpenGL ES Specification, // 16-bit values, interpreting those values as 16-bit floating-point numbers according to the OpenGL
// and converting them to 32-bit floating-point values. // ES Specification, and converting them to 32-bit floating-point values. The first float value is
// The first float value is obtained from the 16 least-significant bits of u; // obtained from the 16 least-significant bits of u; the second component is obtained from the 16
// the second component is obtained from the 16 most-significant bits of u. // most-significant bits of u.
inline void unpackHalf2x16(uint32_t u, float *f1, float *f2) inline void unpackHalf2x16(uint32_t u, float *f1, float *f2)
{ {
uint16_t leastSignificantBits = static_cast<uint16_t>(u & 0xFFFF); uint16_t leastSignificantBits = static_cast<uint16_t>(u & 0xFFFF);
uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16); uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16);
*f1 = float16ToFloat32(leastSignificantBits); *f1 = float16ToFloat32(leastSignificantBits);
*f2 = float16ToFloat32(mostSignificantBits); *f2 = float16ToFloat32(mostSignificantBits);
@ -1004,21 +1044,25 @@ int FindMSB(T bits)
} }
// Returns whether the argument is Not a Number. // Returns whether the argument is Not a Number.
// IEEE 754 single precision NaN representation: Exponent(8 bits) - 255, Mantissa(23 bits) - non-zero. // IEEE 754 single precision NaN representation: Exponent(8 bits) - 255, Mantissa(23 bits) -
// non-zero.
inline bool isNaN(float f) inline bool isNaN(float f)
{ {
// Exponent mask: ((1u << 8) - 1u) << 23 = 0x7f800000u // Exponent mask: ((1u << 8) - 1u) << 23 = 0x7f800000u
// Mantissa mask: ((1u << 23) - 1u) = 0x7fffffu // Mantissa mask: ((1u << 23) - 1u) = 0x7fffffu
return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) && (bitCast<uint32_t>(f) & 0x7fffffu); return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) &&
(bitCast<uint32_t>(f) & 0x7fffffu);
} }
// Returns whether the argument is infinity. // Returns whether the argument is infinity.
// IEEE 754 single precision infinity representation: Exponent(8 bits) - 255, Mantissa(23 bits) - zero. // IEEE 754 single precision infinity representation: Exponent(8 bits) - 255, Mantissa(23 bits) -
// zero.
inline bool isInf(float f) inline bool isInf(float f)
{ {
// Exponent mask: ((1u << 8) - 1u) << 23 = 0x7f800000u // Exponent mask: ((1u << 8) - 1u) << 23 = 0x7f800000u
// Mantissa mask: ((1u << 23) - 1u) = 0x7fffffu // Mantissa mask: ((1u << 23) - 1u) = 0x7fffffu
return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) && !(bitCast<uint32_t>(f) & 0x7fffffu); return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) &&
!(bitCast<uint32_t>(f) & 0x7fffffu);
} }
namespace priv namespace priv
@ -1117,8 +1161,8 @@ inline unsigned int UnsignedCeilDivide(unsigned int value, unsigned int divisor)
#if defined(_MSC_VER) #if defined(_MSC_VER)
#define ANGLE_ROTL(x,y) _rotl(x,y) #define ANGLE_ROTL(x, y) _rotl(x, y)
#define ANGLE_ROTR16(x,y) _rotr16(x,y) #define ANGLE_ROTR16(x, y) _rotr16(x, y)
#else #else
@ -1135,8 +1179,7 @@ inline uint16_t RotR16(uint16_t x, int8_t r)
#define ANGLE_ROTL(x, y) ::rx::RotL(x, y) #define ANGLE_ROTL(x, y) ::rx::RotL(x, y)
#define ANGLE_ROTR16(x, y) ::rx::RotR16(x, y) #define ANGLE_ROTR16(x, y) ::rx::RotR16(x, y)
#endif // namespace rx #endif // namespace rx
} }
#endif // COMMON_MATHUTIL_H_ #endif // COMMON_MATHUTIL_H_

View File

@ -94,6 +94,28 @@ class Matrix
memcpy(mElements.data(), res.data(), numElts * sizeof(float)); memcpy(mElements.data(), res.data(), numElts * sizeof(float));
} }
bool operator==(const Matrix<T> &m) const
{
ASSERT(columns() == m.columns());
ASSERT(rows() == m.rows());
return mElements == m.elements();
}
bool operator!=(const Matrix<T> &m) const { return !(mElements == m.elements()); }
bool nearlyEqual(T epsilon, const Matrix<T> &m) const
{
ASSERT(columns() == m.columns());
ASSERT(rows() == m.rows());
const auto &otherElts = m.elements();
for (size_t i = 0; i < otherElts.size(); i++)
{
if ((mElements[i] - otherElts[i] > epsilon) && (otherElts[i] - mElements[i] > epsilon))
return false;
}
return true;
}
unsigned int size() const unsigned int size() const
{ {
ASSERT(rows() == columns()); ASSERT(rows() == columns());

View File

@ -437,50 +437,6 @@ bool IsOpaqueType(GLenum type)
return IsImageType(type) || IsSamplerType(type) || IsAtomicCounterType(type); return IsImageType(type) || IsSamplerType(type) || IsAtomicCounterType(type);
} }
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_EXTERNAL_OES:
return GL_TEXTURE_EXTERNAL_OES;
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;
case GL_SAMPLER_2D_MULTISAMPLE:
case GL_INT_SAMPLER_2D_MULTISAMPLE:
case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
return GL_TEXTURE_2D_MULTISAMPLE;
case GL_SAMPLER_2D_RECT_ANGLE:
return GL_TEXTURE_RECTANGLE_ANGLE;
default:
UNREACHABLE();
return 0;
}
}
bool IsMatrixType(GLenum type) bool IsMatrixType(GLenum type)
{ {
return VariableRowCount(type) > 1; return VariableRowCount(type) > 1;
@ -545,29 +501,6 @@ int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsig
return -1; return -1;
} }
static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1, "Unexpected GL cube map enum value.");
static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2, "Unexpected GL cube map enum value.");
static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3, "Unexpected GL cube map enum value.");
static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4, "Unexpected GL cube map enum value.");
static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5, "Unexpected GL cube map enum value.");
bool IsCubeMapTextureTarget(GLenum target)
{
return (target >= FirstCubeMapTextureTarget && target <= LastCubeMapTextureTarget);
}
size_t CubeMapTextureTargetToLayerIndex(GLenum target)
{
ASSERT(IsCubeMapTextureTarget(target));
return target - static_cast<size_t>(FirstCubeMapTextureTarget);
}
GLenum LayerIndexToCubeMapTextureTarget(size_t index)
{
ASSERT(index <= (LastCubeMapTextureTarget - FirstCubeMapTextureTarget));
return FirstCubeMapTextureTarget + static_cast<GLenum>(index);
}
IndexRange ComputeIndexRange(GLenum indexType, IndexRange ComputeIndexRange(GLenum indexType,
const GLvoid *indices, const GLvoid *indices,
size_t count, size_t count,
@ -996,52 +929,6 @@ const char *GetGenericErrorMessage(EGLint error)
namespace egl_gl 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;
}
}
GLenum EGLTextureTargetToGLTextureTarget(EGLenum eglTarget)
{
switch (eglTarget)
{
case EGL_TEXTURE_2D:
return GL_TEXTURE_2D;
case EGL_TEXTURE_RECTANGLE_ANGLE:
return GL_TEXTURE_RECTANGLE_ANGLE;
default:
UNREACHABLE();
return GL_NONE;
}
}
GLuint EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer) GLuint EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer)
{ {
return static_cast<GLuint>(reinterpret_cast<uintptr_t>(buffer)); return static_cast<GLuint>(reinterpret_cast<uintptr_t>(buffer));

View File

@ -38,7 +38,6 @@ bool IsSamplerType(GLenum type);
bool IsImageType(GLenum type); bool IsImageType(GLenum type);
bool IsAtomicCounterType(GLenum type); bool IsAtomicCounterType(GLenum type);
bool IsOpaqueType(GLenum type); bool IsOpaqueType(GLenum type);
GLenum SamplerTypeToTextureType(GLenum samplerType);
bool IsMatrixType(GLenum type); bool IsMatrixType(GLenum type);
GLenum TransposeMatrixType(GLenum type); GLenum TransposeMatrixType(GLenum type);
int VariableRegisterCount(GLenum type); int VariableRegisterCount(GLenum type);
@ -49,12 +48,6 @@ GLenum VariableBoolVectorType(GLenum type);
int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize); int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize);
static const GLenum FirstCubeMapTextureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
static const GLenum LastCubeMapTextureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
bool IsCubeMapTextureTarget(GLenum target);
size_t CubeMapTextureTargetToLayerIndex(GLenum target);
GLenum LayerIndexToCubeMapTextureTarget(size_t index);
// Parse the base resource name and array indices. Returns the base name of the resource. // Parse the base resource name and array indices. Returns the base name of the resource.
// If the provided name doesn't index an array, the outSubscripts vector will be empty. // If the provided name doesn't index an array, the outSubscripts vector will be empty.
// If the provided name indexes an array, the outSubscripts vector will contain indices with // If the provided name indexes an array, the outSubscripts vector will contain indices with
@ -161,9 +154,6 @@ const char *GetGenericErrorMessage(EGLint error);
namespace egl_gl namespace egl_gl
{ {
GLenum EGLCubeMapTargetToGLCubeMapTarget(EGLenum eglTarget);
GLenum EGLImageTargetToGLTextureTarget(EGLenum eglTarget);
GLenum EGLTextureTargetToGLTextureTarget(EGLenum eglTarget);
GLuint EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer); GLuint EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer);
} }

View File

@ -937,6 +937,7 @@ typedef pp::SourceLocation YYLTYPE;
yyextra->lineStart = true; \ yyextra->lineStart = true; \
} while(0); } while(0);
#define YY_NO_INPUT
#define YY_USER_ACTION \ #define YY_USER_ACTION \
do \ do \
{ \ { \

View File

@ -64,6 +64,7 @@ typedef pp::SourceLocation YYLTYPE;
yyextra->lineStart = true; \ yyextra->lineStart = true; \
} while(0); } while(0);
#define YY_NO_INPUT
#define YY_USER_ACTION \ #define YY_USER_ACTION \
do \ do \
{ \ { \

View File

@ -48,23 +48,10 @@ bool numeric_lex_int(const std::string &str, IntType *value)
template <typename FloatType> template <typename FloatType>
bool numeric_lex_float(const std::string &str, FloatType *value) bool numeric_lex_float(const std::string &str, FloatType *value)
{ {
// On 64-bit Intel Android, istringstream is broken. Until this is fixed in // Some platforms have issues with the usage of std::locale and std::stringstream and cause
// a newer NDK, don't use it. Android doesn't have locale support, so this // crashes. Usage of strtod appears to be safe.
// doesn't have to force the C locale. *value = static_cast<FloatType>(strtod(str.c_str(), nullptr));
// TODO(thakis): Remove this once this bug has been fixed in the NDK and return errno != ERANGE && std::isfinite(*value);
// 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.
stream.imbue(std::locale::classic());
stream >> (*value);
return !stream.fail() && std::isfinite(*value);
#endif
} }
} // namespace pp. } // namespace pp.

View File

@ -9,8 +9,8 @@
#include "compiler/translator/ASTMetadataHLSL.h" #include "compiler/translator/ASTMetadataHLSL.h"
#include "compiler/translator/CallDAG.h" #include "compiler/translator/CallDAG.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/SymbolTable.h" #include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh namespace sh
{ {

View File

@ -57,18 +57,12 @@ enum TBasicType
EbtInt, EbtInt,
EbtUInt, EbtUInt,
EbtBool, EbtBool,
EbtGVec4, // non type: represents vec4, ivec4, and uvec4
EbtGenType, // non type: represents float, vec2, vec3, and vec4 EbtAtomicCounter,
EbtGenIType, // non type: represents int, ivec2, ivec3, and ivec4
EbtGenUType, // non type: represents uint, uvec2, uvec3, and uvec4
EbtGenBType, // non type: represents bool, bvec2, bvec3, and bvec4
EbtVec, // non type: represents vec2, vec3, and vec4
EbtIVec, // non type: represents ivec2, ivec3, and ivec4
EbtUVec, // non type: represents uvec2, uvec3, and uvec4
EbtBVec, // non type: represents bvec2, bvec3, and bvec4
EbtYuvCscStandardEXT, // Only valid if EXT_YUV_target exists. EbtYuvCscStandardEXT, // Only valid if EXT_YUV_target exists.
EbtGuardSamplerBegin, // non type: see implementation of IsSampler() EbtGuardSamplerBegin, // non type: see implementation of IsSampler()
EbtSampler2D, EbtSampler2D = EbtGuardSamplerBegin,
EbtSampler3D, EbtSampler3D,
EbtSamplerCube, EbtSamplerCube,
EbtSampler2DArray, EbtSampler2DArray,
@ -89,17 +83,11 @@ enum TBasicType
EbtSampler2DShadow, EbtSampler2DShadow,
EbtSamplerCubeShadow, EbtSamplerCubeShadow,
EbtSampler2DArrayShadow, EbtSampler2DArrayShadow,
EbtGuardSamplerEnd, // non type: see implementation of IsSampler() EbtGuardSamplerEnd = EbtSampler2DArrayShadow, // non type: see implementation of IsSampler()
EbtGSampler2D, // non type: represents sampler2D, isampler2D, and usampler2D
EbtGSampler3D, // non type: represents sampler3D, isampler3D, and usampler3D
EbtGSamplerCube, // non type: represents samplerCube, isamplerCube, and usamplerCube
EbtGSampler2DArray, // non type: represents sampler2DArray, isampler2DArray, and
// usampler2DArray
EbtGSampler2DMS, // non type: represents sampler2DMS, isampler2DMS, and usampler2DMS
// images // images
EbtGuardImageBegin, EbtGuardImageBegin,
EbtImage2D, EbtImage2D = EbtGuardImageBegin,
EbtIImage2D, EbtIImage2D,
EbtUImage2D, EbtUImage2D,
EbtImage3D, EbtImage3D,
@ -111,131 +99,41 @@ enum TBasicType
EbtImageCube, EbtImageCube,
EbtIImageCube, EbtIImageCube,
EbtUImageCube, EbtUImageCube,
EbtGuardImageEnd, EbtGuardImageEnd = EbtUImageCube,
EbtGuardGImageBegin, EbtLastSimpleType = EbtGuardImageEnd,
EbtGImage2D, // non type: represents image2D, uimage2D, iimage2D
EbtGImage3D, // non type: represents image3D, uimage3D, iimage3D
EbtGImage2DArray, // non type: represents image2DArray, uimage2DArray, iimage2DArray
EbtGImageCube, // non type: represents imageCube, uimageCube, iimageCube
EbtGuardGImageEnd,
EbtStruct, EbtStruct,
EbtInterfaceBlock, EbtInterfaceBlock,
EbtAddress, // should be deprecated??
EbtAtomicCounter,
// end of list // end of list
EbtLast EbtLast = EbtInterfaceBlock
}; };
constexpr const char *GetBasicMangledName(TBasicType t) constexpr char GetBasicMangledName(TBasicType t)
{ {
switch (t) if (t > EbtLastSimpleType)
{ {
case EbtFloat: return '{';
return "f";
case EbtInt:
return "i";
case EbtUInt:
return "u";
case EbtBool:
return "b";
case EbtYuvCscStandardEXT:
return "ycs";
case EbtSampler2D:
return "s2";
case EbtSampler3D:
return "s3";
case EbtSamplerCube:
return "sC";
case EbtSampler2DArray:
return "s2a";
case EbtSamplerExternalOES:
return "sext";
case EbtSamplerExternal2DY2YEXT:
return "sext2y2y";
case EbtSampler2DRect:
return "s2r";
case EbtSampler2DMS:
return "s2ms";
case EbtISampler2D:
return "is2";
case EbtISampler3D:
return "is3";
case EbtISamplerCube:
return "isC";
case EbtISampler2DArray:
return "is2a";
case EbtISampler2DMS:
return "is2ms";
case EbtUSampler2D:
return "us2";
case EbtUSampler3D:
return "us3";
case EbtUSamplerCube:
return "usC";
case EbtUSampler2DArray:
return "us2a";
case EbtUSampler2DMS:
return "us2ms";
case EbtSampler2DShadow:
return "s2s";
case EbtSamplerCubeShadow:
return "sCs";
case EbtSampler2DArrayShadow:
return "s2as";
case EbtImage2D:
return "im2";
case EbtIImage2D:
return "iim2";
case EbtUImage2D:
return "uim2";
case EbtImage3D:
return "im3";
case EbtIImage3D:
return "iim3";
case EbtUImage3D:
return "uim3";
case EbtImage2DArray:
return "im2a";
case EbtIImage2DArray:
return "iim2a";
case EbtUImage2DArray:
return "uim2a";
case EbtImageCube:
return "imc";
case EbtIImageCube:
return "iimc";
case EbtUImageCube:
return "uimc";
case EbtAtomicCounter:
return "ac";
case EbtStruct:
case EbtInterfaceBlock:
return nullptr;
default:
// EbtVoid, EbtAddress and non types
return "";
} }
static_assert(EbtLastSimpleType < 52, "We only use alphabetic characters for mangled names");
if (t < 26)
{
return static_cast<char>('A' + t);
}
return static_cast<char>('a' - 26 + t);
} }
const char *getBasicString(TBasicType t); const char *getBasicString(TBasicType t);
inline bool IsSampler(TBasicType type) inline bool IsSampler(TBasicType type)
{ {
return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd; return type >= EbtGuardSamplerBegin && type <= EbtGuardSamplerEnd;
} }
inline bool IsImage(TBasicType type) inline bool IsImage(TBasicType type)
{ {
return type > EbtGuardImageBegin && type < EbtGuardImageEnd; return type >= EbtGuardImageBegin && type <= EbtGuardImageEnd;
}
inline bool IsGImage(TBasicType type)
{
return type > EbtGuardGImageBegin && type < EbtGuardGImageEnd;
} }
inline bool IsAtomicCounter(TBasicType type) inline bool IsAtomicCounter(TBasicType type)

View File

@ -6,9 +6,9 @@
#include "compiler/translator/BuiltInFunctionEmulator.h" #include "compiler/translator/BuiltInFunctionEmulator.h"
#include "angle_gl.h" #include "angle_gl.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/StaticType.h" #include "compiler/translator/StaticType.h"
#include "compiler/translator/Symbol.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh namespace sh
{ {
@ -23,10 +23,9 @@ class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTr
bool visitUnary(Visit visit, TIntermUnary *node) override bool visitUnary(Visit visit, TIntermUnary *node) override
{ {
if (visit == PreVisit) if (node->getFunction())
{ {
bool needToEmulate = bool needToEmulate = mEmulator.setFunctionCalled(node->getFunction());
mEmulator.setFunctionCalled(node->getOp(), node->getOperand()->getType());
if (needToEmulate) if (needToEmulate)
node->setUseEmulatedFunction(); node->setUseEmulatedFunction();
} }
@ -35,56 +34,15 @@ class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTr
bool visitAggregate(Visit visit, TIntermAggregate *node) override bool visitAggregate(Visit visit, TIntermAggregate *node) override
{ {
if (visit == PreVisit) // Here we handle all the built-in functions mapped to ops, not just the ones that are
// currently identified as problematic.
if (node->isConstructor() || node->isFunctionCall())
{ {
// Here we handle all the built-in functions mapped to ops, not just the ones that are return true;
// currently identified as problematic.
if (node->isConstructor() || node->isFunctionCall())
{
return true;
}
const TIntermSequence &sequence = *(node->getSequence());
bool needToEmulate = false;
// Right now we only handle built-in functions with two to four parameters.
if (sequence.size() == 2)
{
TIntermTyped *param1 = sequence[0]->getAsTyped();
TIntermTyped *param2 = sequence[1]->getAsTyped();
if (!param1 || !param2)
return true;
needToEmulate = mEmulator.setFunctionCalled(node->getOp(), param1->getType(),
param2->getType());
}
else if (sequence.size() == 3)
{
TIntermTyped *param1 = sequence[0]->getAsTyped();
TIntermTyped *param2 = sequence[1]->getAsTyped();
TIntermTyped *param3 = sequence[2]->getAsTyped();
if (!param1 || !param2 || !param3)
return true;
needToEmulate = mEmulator.setFunctionCalled(node->getOp(), param1->getType(),
param2->getType(), param3->getType());
}
else if (sequence.size() == 4)
{
TIntermTyped *param1 = sequence[0]->getAsTyped();
TIntermTyped *param2 = sequence[1]->getAsTyped();
TIntermTyped *param3 = sequence[2]->getAsTyped();
TIntermTyped *param4 = sequence[3]->getAsTyped();
if (!param1 || !param2 || !param3 || !param4)
return true;
needToEmulate =
mEmulator.setFunctionCalled(node->getOp(), param1->getType(), param2->getType(),
param3->getType(), param4->getType());
}
else
{
return true;
}
if (needToEmulate)
node->setUseEmulatedFunction();
} }
bool needToEmulate = mEmulator.setFunctionCalled(node->getFunction());
if (needToEmulate)
node->setUseEmulatedFunction();
return true; return true;
} }
@ -96,74 +54,19 @@ BuiltInFunctionEmulator::BuiltInFunctionEmulator()
{ {
} }
FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op, void BuiltInFunctionEmulator::addEmulatedFunction(const TSymbolUniqueId &uniqueId,
const TType *param, const char *emulatedFunctionDefinition)
const char *emulatedFunctionDefinition)
{ {
FunctionId id(op, param); mEmulatedFunctions[uniqueId.get()] = std::string(emulatedFunctionDefinition);
mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
return id;
} }
FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op, void BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
const TType *param1, const TSymbolUniqueId &dependency,
const TType *param2, const TSymbolUniqueId &uniqueId,
const char *emulatedFunctionDefinition)
{
FunctionId id(op, param1, param2);
mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
return id;
}
FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
const FunctionId &dependency,
TOperator op,
const TType *param1,
const TType *param2,
const char *emulatedFunctionDefinition) const char *emulatedFunctionDefinition)
{ {
FunctionId id(op, param1, param2); mEmulatedFunctions[uniqueId.get()] = std::string(emulatedFunctionDefinition);
mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition); mFunctionDependencies[uniqueId.get()] = dependency.get();
mFunctionDependencies[id] = dependency;
return id;
}
FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
const TType *param1,
const TType *param2,
const TType *param3,
const char *emulatedFunctionDefinition)
{
FunctionId id(op, param1, param2, param3);
mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
return id;
}
FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
const TType *param1,
const TType *param2,
const TType *param3,
const TType *param4,
const char *emulatedFunctionDefinition)
{
FunctionId id(op, param1, param2, param3, param4);
mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
return id;
}
FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
const FunctionId &dependency,
TOperator op,
const TType *param1,
const TType *param2,
const TType *param3,
const TType *param4,
const char *emulatedFunctionDefinition)
{
FunctionId id(op, param1, param2, param3, param4);
mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
mFunctionDependencies[id] = dependency;
return id;
} }
bool BuiltInFunctionEmulator::isOutputEmpty() const bool BuiltInFunctionEmulator::isOutputEmpty() const
@ -182,47 +85,18 @@ void BuiltInFunctionEmulator::outputEmulatedFunctions(TInfoSinkBase &out) const
} }
} }
bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, const TType &param) const char *BuiltInFunctionEmulator::findEmulatedFunction(int uniqueId) const
{
return setFunctionCalled(FunctionId(op, &param));
}
bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
const TType &param1,
const TType &param2)
{
return setFunctionCalled(FunctionId(op, &param1, &param2));
}
bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
const TType &param1,
const TType &param2,
const TType &param3)
{
return setFunctionCalled(FunctionId(op, &param1, &param2, &param3));
}
bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
const TType &param1,
const TType &param2,
const TType &param3,
const TType &param4)
{
return setFunctionCalled(FunctionId(op, &param1, &param2, &param3, &param4));
}
const char *BuiltInFunctionEmulator::findEmulatedFunction(const FunctionId &functionId) const
{ {
for (const auto &queryFunction : mQueryFunctions) for (const auto &queryFunction : mQueryFunctions)
{ {
const char *result = queryFunction(functionId); const char *result = queryFunction(uniqueId);
if (result) if (result)
{ {
return result; return result;
} }
} }
const auto &result = mEmulatedFunctions.find(functionId); const auto &result = mEmulatedFunctions.find(uniqueId);
if (result != mEmulatedFunctions.end()) if (result != mEmulatedFunctions.end())
{ {
return result->second.c_str(); return result->second.c_str();
@ -231,27 +105,31 @@ const char *BuiltInFunctionEmulator::findEmulatedFunction(const FunctionId &func
return nullptr; return nullptr;
} }
bool BuiltInFunctionEmulator::setFunctionCalled(const FunctionId &functionId) bool BuiltInFunctionEmulator::setFunctionCalled(const TFunction *function)
{ {
if (!findEmulatedFunction(functionId)) ASSERT(function != nullptr);
return setFunctionCalled(function->uniqueId().get());
}
bool BuiltInFunctionEmulator::setFunctionCalled(int uniqueId)
{
if (!findEmulatedFunction(uniqueId))
{ {
return false; return false;
} }
for (size_t i = 0; i < mFunctions.size(); ++i) for (size_t i = 0; i < mFunctions.size(); ++i)
{ {
if (mFunctions[i] == functionId) if (mFunctions[i] == uniqueId)
return true; return true;
} }
// If the function depends on another, mark the dependency as called. // If the function depends on another, mark the dependency as called.
auto dependency = mFunctionDependencies.find(functionId); auto dependency = mFunctionDependencies.find(uniqueId);
if (dependency != mFunctionDependencies.end()) if (dependency != mFunctionDependencies.end())
{ {
setFunctionCalled((*dependency).second); setFunctionCalled((*dependency).second);
} }
// Copy the functionId if it needs to be stored, to make sure that the TType pointers inside mFunctions.push_back(uniqueId);
// remain valid and constant.
mFunctions.push_back(functionId.getCopy());
return true; return true;
} }
@ -284,76 +162,4 @@ void BuiltInFunctionEmulator::WriteEmulatedFunctionName(TInfoSinkBase &out, cons
out << name << "_emu"; out << name << "_emu";
} }
FunctionId::FunctionId()
: mOp(EOpNull),
mParam1(StaticType::GetBasic<EbtVoid>()),
mParam2(StaticType::GetBasic<EbtVoid>()),
mParam3(StaticType::GetBasic<EbtVoid>()),
mParam4(StaticType::GetBasic<EbtVoid>())
{
}
FunctionId::FunctionId(TOperator op, const TType *param)
: mOp(op),
mParam1(param),
mParam2(StaticType::GetBasic<EbtVoid>()),
mParam3(StaticType::GetBasic<EbtVoid>()),
mParam4(StaticType::GetBasic<EbtVoid>())
{
}
FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2)
: mOp(op),
mParam1(param1),
mParam2(param2),
mParam3(StaticType::GetBasic<EbtVoid>()),
mParam4(StaticType::GetBasic<EbtVoid>())
{
}
FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3)
: mOp(op),
mParam1(param1),
mParam2(param2),
mParam3(param3),
mParam4(StaticType::GetBasic<EbtVoid>())
{
}
FunctionId::FunctionId(TOperator op,
const TType *param1,
const TType *param2,
const TType *param3,
const TType *param4)
: mOp(op), mParam1(param1), mParam2(param2), mParam3(param3), mParam4(param4)
{
}
bool FunctionId::operator==(const FunctionId &other) const
{
return (mOp == other.mOp && *mParam1 == *other.mParam1 && *mParam2 == *other.mParam2 &&
*mParam3 == *other.mParam3 && *mParam4 == *other.mParam4);
}
bool FunctionId::operator<(const 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 (*mParam4 != *other.mParam4)
return *mParam4 < *other.mParam4;
return false; // all fields are equal
}
FunctionId FunctionId::getCopy() const
{
return FunctionId(mOp, new TType(*mParam1), new TType(*mParam2), new TType(*mParam3),
new TType(*mParam4));
}
} // namespace sh } // namespace sh

View File

@ -8,82 +8,15 @@
#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_ #define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
#include "compiler/translator/InfoSink.h" #include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/ParamType.h"
namespace sh namespace sh
{ {
struct MiniFunctionId class TIntermNode;
{ class TFunction;
constexpr MiniFunctionId(TOperator op = EOpNull, class TSymbolUniqueId;
ParamType paramType1 = ParamType::Void,
ParamType paramType2 = ParamType::Void,
ParamType paramType3 = ParamType::Void,
ParamType paramType4 = ParamType::Void)
: op(op),
paramType1(paramType1),
paramType2(paramType2),
paramType3(paramType3),
paramType4(paramType4)
{
}
TOperator op; using BuiltinQueryFunc = const char *(int);
ParamType paramType1;
ParamType paramType2;
ParamType paramType3;
ParamType paramType4;
};
class FunctionId final
{
public:
FunctionId();
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 *param1,
const TType *param2,
const TType *param3,
const TType *param4);
FunctionId(const FunctionId &) = default;
FunctionId &operator=(const FunctionId &) = default;
bool operator==(const FunctionId &other) const;
bool operator<(const FunctionId &other) const;
FunctionId getCopy() const;
private:
friend bool operator==(const MiniFunctionId &miniId, const FunctionId &functionId);
TOperator mOp;
// 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;
const TType *mParam4;
};
inline bool operator==(ParamType paramType, const TType *type)
{
return SameParamType(paramType, type->getBasicType(), type->getNominalSize(),
type->getSecondarySize());
}
inline bool operator==(const MiniFunctionId &miniId, const FunctionId &functionId)
{
return miniId.op == functionId.mOp && miniId.paramType1 == functionId.mParam1 &&
miniId.paramType2 == functionId.mParam2 && miniId.paramType3 == functionId.mParam3 &&
miniId.paramType4 == functionId.mParam4;
}
using BuiltinQueryFunc = const char *(const FunctionId &);
// //
// This class decides which built-in functions need to be replaced with the emulated ones. It can be // This class decides which built-in functions need to be replaced with the emulated ones. It can be
@ -108,37 +41,12 @@ class BuiltInFunctionEmulator
void outputEmulatedFunctions(TInfoSinkBase &out) const; void outputEmulatedFunctions(TInfoSinkBase &out) const;
// Add functions that need to be emulated. // Add functions that need to be emulated.
FunctionId addEmulatedFunction(TOperator op, void addEmulatedFunction(const TSymbolUniqueId &uniqueId,
const TType *param, const char *emulatedFunctionDefinition);
const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunction(TOperator op,
const TType *param1,
const TType *param2,
const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunction(TOperator op,
const TType *param1,
const TType *param2,
const TType *param3,
const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunction(TOperator op,
const TType *param1,
const TType *param2,
const TType *param3,
const TType *param4,
const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency, void addEmulatedFunctionWithDependency(const TSymbolUniqueId &dependency,
TOperator op, const TSymbolUniqueId &uniqueId,
const TType *param1, const char *emulatedFunctionDefinition);
const TType *param2,
const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency,
TOperator op,
const TType *param1,
const TType *param2,
const TType *param3,
const TType *param4,
const char *emulatedFunctionDefinition);
void addFunctionMap(BuiltinQueryFunc queryFunc); void addFunctionMap(BuiltinQueryFunc queryFunc);
@ -148,31 +56,20 @@ class BuiltInFunctionEmulator
// Records that a function is called by the shader and might need to be emulated. If the // Records that a function is called by the shader and might need to be emulated. If the
// function is not in mEmulatedFunctions, this becomes a no-op. Returns true if the function // function is not in mEmulatedFunctions, this becomes a no-op. Returns true if the function
// call needs to be replaced with an emulated one. // call needs to be replaced with an emulated one.
bool setFunctionCalled(TOperator op, const TType &param); bool setFunctionCalled(const TFunction *function);
bool setFunctionCalled(TOperator op, const TType &param1, const TType &param2); bool setFunctionCalled(int uniqueId);
bool setFunctionCalled(TOperator op,
const TType &param1,
const TType &param2,
const TType &param3);
bool setFunctionCalled(TOperator op,
const TType &param1,
const TType &param2,
const TType &param3,
const TType &param4);
bool setFunctionCalled(const FunctionId &functionId); const char *findEmulatedFunction(int uniqueId) const;
const char *findEmulatedFunction(const FunctionId &functionId) const; // Map from function unique id to emulated function definition
std::map<int, std::string> mEmulatedFunctions;
// Map from function id to emulated function definition
std::map<FunctionId, std::string> mEmulatedFunctions;
// Map from dependent functions to their dependencies. This structure allows each function to // Map from dependent functions to their dependencies. This structure allows each function to
// have at most one dependency. // have at most one dependency.
std::map<FunctionId, FunctionId> mFunctionDependencies; std::map<int, int> mFunctionDependencies;
// Called function ids // Called function ids
std::vector<FunctionId> mFunctions; std::vector<int> mFunctions;
// Constexpr function tables. // Constexpr function tables.
std::vector<BuiltinQueryFunc *> mQueryFunctions; std::vector<BuiltinQueryFunc *> mQueryFunctions;

View File

@ -7,9 +7,8 @@
#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h" #include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
#include "angle_gl.h" #include "angle_gl.h"
#include "compiler/translator/BuiltInFunctionEmulator.h" #include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/StaticType.h"
#include "compiler/translator/VersionGLSL.h" #include "compiler/translator/VersionGLSL.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
namespace sh namespace sh
{ {
@ -19,8 +18,7 @@ void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *e
{ {
if (shaderType == GL_VERTEX_SHADER) if (shaderType == GL_VERTEX_SHADER)
{ {
const TType *int1 = StaticType::GetBasic<EbtInt>(); emu->addEmulatedFunction(BuiltInId::abs_Int1, "int abs_emu(int x) { return x * sign(x); }");
emu->addEmulatedFunction(EOpAbs, int1, "int abs_emu(int x) { return x * sign(x); }");
} }
} }
@ -31,17 +29,12 @@ void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator
if (targetGLSLVersion < GLSL_VERSION_130) if (targetGLSLVersion < GLSL_VERSION_130)
return; return;
const TType *float1 = StaticType::GetBasic<EbtFloat>();
const TType *float2 = StaticType::GetBasic<EbtFloat, 2>();
const TType *float3 = StaticType::GetBasic<EbtFloat, 3>();
const TType *float4 = StaticType::GetBasic<EbtFloat, 4>();
// !(x > 0.0 || x < 0.0 || x == 0.0) will be optimized and always equal to false. // !(x > 0.0 || x < 0.0 || x == 0.0) will be optimized and always equal to false.
emu->addEmulatedFunction( emu->addEmulatedFunction(
EOpIsnan, float1, BuiltInId::isnan_Float1,
"bool isnan_emu(float x) { return (x > 0.0 || x < 0.0) ? false : x != 0.0; }"); "bool isnan_emu(float x) { return (x > 0.0 || x < 0.0) ? false : x != 0.0; }");
emu->addEmulatedFunction( emu->addEmulatedFunction(
EOpIsnan, float2, BuiltInId::isnan_Float2,
"bvec2 isnan_emu(vec2 x)\n" "bvec2 isnan_emu(vec2 x)\n"
"{\n" "{\n"
" bvec2 isnan;\n" " bvec2 isnan;\n"
@ -52,7 +45,7 @@ void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator
" return isnan;\n" " return isnan;\n"
"}\n"); "}\n");
emu->addEmulatedFunction( emu->addEmulatedFunction(
EOpIsnan, float3, BuiltInId::isnan_Float3,
"bvec3 isnan_emu(vec3 x)\n" "bvec3 isnan_emu(vec3 x)\n"
"{\n" "{\n"
" bvec3 isnan;\n" " bvec3 isnan;\n"
@ -63,7 +56,7 @@ void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator
" return isnan;\n" " return isnan;\n"
"}\n"); "}\n");
emu->addEmulatedFunction( emu->addEmulatedFunction(
EOpIsnan, float4, BuiltInId::isnan_Float4,
"bvec4 isnan_emu(vec4 x)\n" "bvec4 isnan_emu(vec4 x)\n"
"{\n" "{\n"
" bvec4 isnan;\n" " bvec4 isnan;\n"
@ -77,27 +70,21 @@ void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator
void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu) void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu)
{ {
const TType *float1 = StaticType::GetBasic<EbtFloat>(); emu->addEmulatedFunction(BuiltInId::atan_Float1_Float1,
auto floatFuncId = emu->addEmulatedFunction( "emu_precision float atan_emu(emu_precision float y, emu_precision "
EOpAtan, float1, float1, "float x)\n"
"emu_precision float atan_emu(emu_precision float y, emu_precision " "{\n"
"float x)\n" " if (x > 0.0) return atan(y / x);\n"
"{\n" " else if (x < 0.0 && y >= 0.0) return atan(y / x) + 3.14159265;\n"
" if (x > 0.0) return atan(y / x);\n" " else if (x < 0.0 && y < 0.0) return atan(y / x) - 3.14159265;\n"
" else if (x < 0.0 && y >= 0.0) return atan(y / x) + 3.14159265;\n" " else return 1.57079632 * sign(y);\n"
" else if (x < 0.0 && y < 0.0) return atan(y / x) - 3.14159265;\n" "}\n");
" else return 1.57079632 * sign(y);\n" static const std::array<TSymbolUniqueId, 4> ids = {
"}\n"); BuiltInId::atan_Float1_Float1, BuiltInId::atan_Float2_Float2, BuiltInId::atan_Float3_Float3,
static const std::array<const TType *, 5> floatVecs = { BuiltInId::atan_Float4_Float4,
nullptr,
nullptr,
StaticType::GetBasic<EbtFloat, 2>(),
StaticType::GetBasic<EbtFloat, 3>(),
StaticType::GetBasic<EbtFloat, 4>(),
}; };
for (int dim = 2; dim <= 4; ++dim) for (int dim = 2; dim <= 4; ++dim)
{ {
const TType *floatVec = floatVecs[dim];
std::stringstream ss; std::stringstream ss;
ss << "emu_precision vec" << dim << " atan_emu(emu_precision vec" << dim ss << "emu_precision vec" << dim << " atan_emu(emu_precision vec" << dim
<< " y, emu_precision vec" << dim << " x)\n" << " y, emu_precision vec" << dim << " x)\n"
@ -114,7 +101,7 @@ void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *
} }
ss << ");\n" ss << ");\n"
"}\n"; "}\n";
emu->addEmulatedFunctionWithDependency(floatFuncId, EOpAtan, floatVec, floatVec, emu->addEmulatedFunctionWithDependency(BuiltInId::atan_Float1_Float1, ids[dim - 1],
ss.str().c_str()); ss.str().c_str());
} }
} }
@ -127,11 +114,8 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
// Emulate packUnorm2x16 and unpackUnorm2x16 (GLSL 4.10) // Emulate packUnorm2x16 and unpackUnorm2x16 (GLSL 4.10)
if (targetGLSLVersion < GLSL_VERSION_410) if (targetGLSLVersion < GLSL_VERSION_410)
{ {
const TType *float2 = StaticType::GetBasic<EbtFloat, 2>();
const TType *uint1 = StaticType::GetBasic<EbtUInt>();
// clang-format off // clang-format off
emu->addEmulatedFunction(EOpPackUnorm2x16, float2, emu->addEmulatedFunction(BuiltInId::packUnorm2x16_Float2,
"uint packUnorm2x16_emu(vec2 v)\n" "uint packUnorm2x16_emu(vec2 v)\n"
"{\n" "{\n"
" int x = int(round(clamp(v.x, 0.0, 1.0) * 65535.0));\n" " int x = int(round(clamp(v.x, 0.0, 1.0) * 65535.0));\n"
@ -139,7 +123,7 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
" return uint((y << 16) | (x & 0xFFFF));\n" " return uint((y << 16) | (x & 0xFFFF));\n"
"}\n"); "}\n");
emu->addEmulatedFunction(EOpUnpackUnorm2x16, uint1, emu->addEmulatedFunction(BuiltInId::unpackUnorm2x16_UInt1,
"vec2 unpackUnorm2x16_emu(uint u)\n" "vec2 unpackUnorm2x16_emu(uint u)\n"
"{\n" "{\n"
" float x = float(u & 0xFFFFu) / 65535.0;\n" " float x = float(u & 0xFFFFu) / 65535.0;\n"
@ -153,11 +137,8 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
// by using floatBitsToInt, floatBitsToUint, intBitsToFloat, and uintBitsToFloat (GLSL 3.30). // by using floatBitsToInt, floatBitsToUint, intBitsToFloat, and uintBitsToFloat (GLSL 3.30).
if (targetGLSLVersion >= GLSL_VERSION_330 && targetGLSLVersion < GLSL_VERSION_420) if (targetGLSLVersion >= GLSL_VERSION_330 && targetGLSLVersion < GLSL_VERSION_420)
{ {
const TType *float2 = StaticType::GetBasic<EbtFloat, 2>();
const TType *uint1 = StaticType::GetBasic<EbtUInt>();
// clang-format off // clang-format off
emu->addEmulatedFunction(EOpPackSnorm2x16, float2, emu->addEmulatedFunction(BuiltInId::packSnorm2x16_Float2,
"uint packSnorm2x16_emu(vec2 v)\n" "uint packSnorm2x16_emu(vec2 v)\n"
"{\n" "{\n"
" #if defined(GL_ARB_shading_language_packing)\n" " #if defined(GL_ARB_shading_language_packing)\n"
@ -168,7 +149,7 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
" return uint((y << 16) | (x & 0xFFFF));\n" " return uint((y << 16) | (x & 0xFFFF));\n"
" #endif\n" " #endif\n"
"}\n"); "}\n");
emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1, emu->addEmulatedFunction(BuiltInId::unpackSnorm2x16_UInt1,
"#if !defined(GL_ARB_shading_language_packing)\n" "#if !defined(GL_ARB_shading_language_packing)\n"
" float fromSnorm(uint x)\n" " float fromSnorm(uint x)\n"
" {\n" " {\n"
@ -189,7 +170,7 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
"}\n"); "}\n");
// Functions uint f32tof16(float val) and float f16tof32(uint val) are // Functions uint f32tof16(float val) and float f16tof32(uint val) are
// based on the OpenGL redbook Appendix Session "Floating-Point Formats Used in OpenGL". // based on the OpenGL redbook Appendix Session "Floating-Point Formats Used in OpenGL".
emu->addEmulatedFunction(EOpPackHalf2x16, float2, emu->addEmulatedFunction(BuiltInId::packHalf2x16_Float2,
"#if !defined(GL_ARB_shading_language_packing)\n" "#if !defined(GL_ARB_shading_language_packing)\n"
" uint f32tof16(float val)\n" " uint f32tof16(float val)\n"
" {\n" " {\n"
@ -236,7 +217,7 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
" return (y << 16) | x;\n" " return (y << 16) | x;\n"
" #endif\n" " #endif\n"
"}\n"); "}\n");
emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1, emu->addEmulatedFunction(BuiltInId::unpackHalf2x16_UInt1,
"#if !defined(GL_ARB_shading_language_packing)\n" "#if !defined(GL_ARB_shading_language_packing)\n"
" float f16tof32(uint val)\n" " float f16tof32(uint val)\n"
" {\n" " {\n"

View File

@ -4,17 +4,17 @@
// found in the LICENSE file. // found in the LICENSE file.
// //
#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
#include "angle_gl.h" #include "angle_gl.h"
#include "compiler/translator/BuiltInFunctionEmulator.h" #include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/VersionGLSL.h" #include "compiler/translator/VersionGLSL.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
namespace sh namespace sh
{ {
// Defined in emulated_builtin_functions_hlsl_autogen.cpp. // Defined in emulated_builtin_functions_hlsl_autogen.cpp.
const char *FindHLSLFunction(const FunctionId &functionID); const char *FindHLSLFunction(int uniqueId);
void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu, void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu,
int targetGLSLVersion) int targetGLSLVersion)
@ -22,12 +22,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
if (targetGLSLVersion < GLSL_VERSION_130) if (targetGLSLVersion < GLSL_VERSION_130)
return; return;
TType *float1 = new TType(EbtFloat); emu->addEmulatedFunction(BuiltInId::isnan_Float1,
TType *float2 = new TType(EbtFloat, 2);
TType *float3 = new TType(EbtFloat, 3);
TType *float4 = new TType(EbtFloat, 4);
emu->addEmulatedFunction(EOpIsnan, float1,
"bool isnan_emu(float x)\n" "bool isnan_emu(float x)\n"
"{\n" "{\n"
" return (x > 0.0 || x < 0.0) ? false : x != 0.0;\n" " return (x > 0.0 || x < 0.0) ? false : x != 0.0;\n"
@ -35,7 +30,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
"\n"); "\n");
emu->addEmulatedFunction( emu->addEmulatedFunction(
EOpIsnan, float2, BuiltInId::isnan_Float2,
"bool2 isnan_emu(float2 x)\n" "bool2 isnan_emu(float2 x)\n"
"{\n" "{\n"
" bool2 isnan;\n" " bool2 isnan;\n"
@ -47,7 +42,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
"}\n"); "}\n");
emu->addEmulatedFunction( emu->addEmulatedFunction(
EOpIsnan, float3, BuiltInId::isnan_Float3,
"bool3 isnan_emu(float3 x)\n" "bool3 isnan_emu(float3 x)\n"
"{\n" "{\n"
" bool3 isnan;\n" " bool3 isnan;\n"
@ -59,7 +54,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
"}\n"); "}\n");
emu->addEmulatedFunction( emu->addEmulatedFunction(
EOpIsnan, float4, BuiltInId::isnan_Float4,
"bool4 isnan_emu(float4 x)\n" "bool4 isnan_emu(float4 x)\n"
"{\n" "{\n"
" bool4 isnan;\n" " bool4 isnan;\n"
@ -73,43 +68,35 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu) void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
{ {
TType *int1 = new TType(EbtInt);
TType *int2 = new TType(EbtInt, 2);
TType *int3 = new TType(EbtInt, 3);
TType *int4 = new TType(EbtInt, 4);
TType *uint1 = new TType(EbtUInt);
TType *uint2 = new TType(EbtUInt, 2);
TType *uint3 = new TType(EbtUInt, 3);
TType *uint4 = new TType(EbtUInt, 4);
emu->addFunctionMap(FindHLSLFunction); emu->addFunctionMap(FindHLSLFunction);
// (a + b2^16) * (c + d2^16) = ac + (ad + bc) * 2^16 + bd * 2^32 // (a + b2^16) * (c + d2^16) = ac + (ad + bc) * 2^16 + bd * 2^32
// Also note that below, a * d + ((a * c) >> 16) is guaranteed not to overflow, because: // Also note that below, a * d + ((a * c) >> 16) is guaranteed not to overflow, because:
// a <= 0xffff, d <= 0xffff, ((a * c) >> 16) <= 0xffff and 0xffff * 0xffff + 0xffff = 0xffff0000 // a <= 0xffff, d <= 0xffff, ((a * c) >> 16) <= 0xffff and 0xffff * 0xffff + 0xffff = 0xffff0000
FunctionId umulExtendedUint1 = emu->addEmulatedFunction( emu->addEmulatedFunction(BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
EOpUmulExtended, uint1, uint1, uint1, uint1, "void umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n"
"void umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n" "{\n"
"{\n" " lsb = x * y;\n"
" lsb = x * y;\n" " uint a = (x & 0xffffu);\n"
" uint a = (x & 0xffffu);\n" " uint b = (x >> 16);\n"
" uint b = (x >> 16);\n" " uint c = (y & 0xffffu);\n"
" uint c = (y & 0xffffu);\n" " uint d = (y >> 16);\n"
" uint d = (y >> 16);\n" " uint ad = a * d + ((a * c) >> 16);\n"
" uint ad = a * d + ((a * c) >> 16);\n" " uint bc = b * c;\n"
" uint bc = b * c;\n" " uint carry = uint(ad > (0xffffffffu - bc));\n"
" uint carry = uint(ad > (0xffffffffu - bc));\n" " msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n"
" msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n" "}\n");
"}\n");
emu->addEmulatedFunctionWithDependency( emu->addEmulatedFunctionWithDependency(
umulExtendedUint1, EOpUmulExtended, uint2, uint2, uint2, uint2, BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
BuiltInId::umulExtended_UInt2_UInt2_UInt2_UInt2,
"void umulExtended_emu(uint2 x, uint2 y, out uint2 msb, out uint2 lsb)\n" "void umulExtended_emu(uint2 x, uint2 y, out uint2 msb, out uint2 lsb)\n"
"{\n" "{\n"
" umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" " umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
" umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n" " umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
"}\n"); "}\n");
emu->addEmulatedFunctionWithDependency( emu->addEmulatedFunctionWithDependency(
umulExtendedUint1, EOpUmulExtended, uint3, uint3, uint3, uint3, BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
BuiltInId::umulExtended_UInt3_UInt3_UInt3_UInt3,
"void umulExtended_emu(uint3 x, uint3 y, out uint3 msb, out uint3 lsb)\n" "void umulExtended_emu(uint3 x, uint3 y, out uint3 msb, out uint3 lsb)\n"
"{\n" "{\n"
" umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" " umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
@ -117,7 +104,8 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
" umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n" " umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
"}\n"); "}\n");
emu->addEmulatedFunctionWithDependency( emu->addEmulatedFunctionWithDependency(
umulExtendedUint1, EOpUmulExtended, uint4, uint4, uint4, uint4, BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
BuiltInId::umulExtended_UInt4_UInt4_UInt4_UInt4,
"void umulExtended_emu(uint4 x, uint4 y, out uint4 msb, out uint4 lsb)\n" "void umulExtended_emu(uint4 x, uint4 y, out uint4 msb, out uint4 lsb)\n"
"{\n" "{\n"
" umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" " umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
@ -130,8 +118,9 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
// result needs to be negative. // result needs to be negative.
// TODO(oetuaho): Note that this code doesn't take one edge case into account, where x or y is // TODO(oetuaho): Note that this code doesn't take one edge case into account, where x or y is
// -2^31. abs(-2^31) is undefined. // -2^31. abs(-2^31) is undefined.
FunctionId imulExtendedInt1 = emu->addEmulatedFunctionWithDependency( emu->addEmulatedFunctionWithDependency(
umulExtendedUint1, EOpImulExtended, int1, int1, int1, int1, BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
BuiltInId::imulExtended_Int1_Int1_Int1_Int1,
"void imulExtended_emu(int x, int y, out int msb, out int lsb)\n" "void imulExtended_emu(int x, int y, out int msb, out int lsb)\n"
"{\n" "{\n"
" uint unsignedMsb;\n" " uint unsignedMsb;\n"
@ -156,14 +145,14 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
" }\n" " }\n"
"}\n"); "}\n");
emu->addEmulatedFunctionWithDependency( emu->addEmulatedFunctionWithDependency(
imulExtendedInt1, EOpImulExtended, int2, int2, int2, int2, BuiltInId::imulExtended_Int1_Int1_Int1_Int1, BuiltInId::imulExtended_Int2_Int2_Int2_Int2,
"void imulExtended_emu(int2 x, int2 y, out int2 msb, out int2 lsb)\n" "void imulExtended_emu(int2 x, int2 y, out int2 msb, out int2 lsb)\n"
"{\n" "{\n"
" imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" " imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
" imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n" " imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
"}\n"); "}\n");
emu->addEmulatedFunctionWithDependency( emu->addEmulatedFunctionWithDependency(
imulExtendedInt1, EOpImulExtended, int3, int3, int3, int3, BuiltInId::imulExtended_Int1_Int1_Int1_Int1, BuiltInId::imulExtended_Int3_Int3_Int3_Int3,
"void imulExtended_emu(int3 x, int3 y, out int3 msb, out int3 lsb)\n" "void imulExtended_emu(int3 x, int3 y, out int3 msb, out int3 lsb)\n"
"{\n" "{\n"
" imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" " imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
@ -171,7 +160,7 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
" imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n" " imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
"}\n"); "}\n");
emu->addEmulatedFunctionWithDependency( emu->addEmulatedFunctionWithDependency(
imulExtendedInt1, EOpImulExtended, int4, int4, int4, int4, BuiltInId::imulExtended_Int1_Int1_Int1_Int1, BuiltInId::imulExtended_Int4_Int4_Int4_Int4,
"void imulExtended_emu(int4 x, int4 y, out int4 msb, out int4 lsb)\n" "void imulExtended_emu(int4 x, int4 y, out int4 msb, out int4 lsb)\n"
"{\n" "{\n"
" imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" " imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"

View File

@ -11,8 +11,8 @@
#include "compiler/translator/CallDAG.h" #include "compiler/translator/CallDAG.h"
#include "compiler/translator/Diagnostics.h" #include "compiler/translator/Diagnostics.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/SymbolTable.h" #include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh namespace sh
{ {
@ -116,16 +116,13 @@ class CallDAG::CallDAGCreator : public TIntermTraverser
return false; return false;
} }
bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override void visitFunctionPrototype(TIntermFunctionPrototype *node) override
{ {
ASSERT(mCurrentFunction == nullptr); ASSERT(mCurrentFunction == nullptr);
// Function declaration, create an empty record. // Function declaration, create an empty record.
auto &record = mFunctions[node->getFunction()->uniqueId().get()]; auto &record = mFunctions[node->getFunction()->uniqueId().get()];
record.name = node->getFunction()->name(); record.name = node->getFunction()->name();
// No need to traverse the parameters.
return false;
} }
// Track functions called from another function. // Track functions called from another function.

View File

@ -10,8 +10,8 @@
#include "angle_gl.h" #include "angle_gl.h"
#include "common/utilities.h" #include "common/utilities.h"
#include "compiler/translator/HashNames.h" #include "compiler/translator/HashNames.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/SymbolTable.h" #include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
#include "compiler/translator/util.h" #include "compiler/translator/util.h"
namespace sh namespace sh
@ -68,21 +68,22 @@ VarT *FindVariable(const ImmutableString &name, std::vector<VarT> *infoList)
return nullptr; return nullptr;
} }
// Note that this shouldn't be called for interface blocks - static use information is collected for // Note that this shouldn't be called for interface blocks - active information is collected for
// individual fields in case of interface blocks. // individual fields in case of interface blocks.
void MarkStaticallyUsed(ShaderVariable *variable) void MarkActive(ShaderVariable *variable)
{ {
if (!variable->staticUse) if (!variable->active)
{ {
if (variable->isStruct()) if (variable->isStruct())
{ {
// Conservatively assume all fields are statically used as well. // Conservatively assume all fields are statically used as well.
for (auto &field : variable->fields) for (auto &field : variable->fields)
{ {
MarkStaticallyUsed(&field); MarkActive(&field);
} }
} }
variable->staticUse = true; ASSERT(variable->staticUse);
variable->active = true;
} }
} }
@ -96,6 +97,7 @@ ShaderVariable *FindVariableInInterfaceBlock(const ImmutableString &name,
// Set static use on the parent interface block here // Set static use on the parent interface block here
namedBlock->staticUse = true; namedBlock->staticUse = true;
namedBlock->active = true;
return FindVariable(name, &namedBlock->fields); return FindVariable(name, &namedBlock->fields);
} }
@ -114,10 +116,10 @@ class CollectVariablesTraverser : public TIntermTraverser
std::vector<InterfaceBlock> *inBlocks, std::vector<InterfaceBlock> *inBlocks,
ShHashFunction64 hashFunction, ShHashFunction64 hashFunction,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
int shaderVersion,
GLenum shaderType, GLenum shaderType,
const TExtensionBehavior &extensionBehavior); const TExtensionBehavior &extensionBehavior);
bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override;
void visitSymbol(TIntermSymbol *symbol) override; void visitSymbol(TIntermSymbol *symbol) override;
bool visitDeclaration(Visit, TIntermDeclaration *node) override; bool visitDeclaration(Visit, TIntermDeclaration *node) override;
bool visitBinary(Visit visit, TIntermBinary *binaryNode) override; bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
@ -125,9 +127,12 @@ class CollectVariablesTraverser : public TIntermTraverser
private: private:
std::string getMappedName(const TSymbol *symbol) const; std::string getMappedName(const TSymbol *symbol) const;
void setFieldOrVariableProperties(const TType &type, ShaderVariable *variableOut) const; void setFieldOrVariableProperties(const TType &type,
bool staticUse,
ShaderVariable *variableOut) const;
void setFieldProperties(const TType &type, void setFieldProperties(const TType &type,
const ImmutableString &name, const ImmutableString &name,
bool staticUse,
ShaderVariable *variableOut) const; ShaderVariable *variableOut) const;
void setCommonVariableProperties(const TType &type, void setCommonVariableProperties(const TType &type,
const TVariable &variable, const TVariable &variable,
@ -141,13 +146,13 @@ class CollectVariablesTraverser : public TIntermTraverser
InterfaceBlock *interfaceBlock) const; InterfaceBlock *interfaceBlock) const;
Uniform recordUniform(const TIntermSymbol &variable) const; Uniform recordUniform(const TIntermSymbol &variable) const;
void setBuiltInInfoFromSymbolTable(const ImmutableString &name, ShaderVariable *info); void setBuiltInInfoFromSymbol(const TVariable &variable, ShaderVariable *info);
void recordBuiltInVaryingUsed(const ImmutableString &name, void recordBuiltInVaryingUsed(const TVariable &variable,
bool *addedFlag, bool *addedFlag,
std::vector<Varying> *varyings); std::vector<Varying> *varyings);
void recordBuiltInFragmentOutputUsed(const ImmutableString &name, bool *addedFlag); void recordBuiltInFragmentOutputUsed(const TVariable &variable, bool *addedFlag);
void recordBuiltInAttributeUsed(const ImmutableString &name, bool *addedFlag); void recordBuiltInAttributeUsed(const TVariable &variable, bool *addedFlag);
InterfaceBlock *recordGLInUsed(const TType &glInType); InterfaceBlock *recordGLInUsed(const TType &glInType);
InterfaceBlock *findNamedInterfaceBlock(const ImmutableString &name) const; InterfaceBlock *findNamedInterfaceBlock(const ImmutableString &name) const;
@ -196,7 +201,6 @@ class CollectVariablesTraverser : public TIntermTraverser
ShHashFunction64 mHashFunction; ShHashFunction64 mHashFunction;
int mShaderVersion;
GLenum mShaderType; GLenum mShaderType;
const TExtensionBehavior &mExtensionBehavior; const TExtensionBehavior &mExtensionBehavior;
}; };
@ -212,7 +216,6 @@ CollectVariablesTraverser::CollectVariablesTraverser(
std::vector<sh::InterfaceBlock> *inBlocks, std::vector<sh::InterfaceBlock> *inBlocks,
ShHashFunction64 hashFunction, ShHashFunction64 hashFunction,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
int shaderVersion,
GLenum shaderType, GLenum shaderType,
const TExtensionBehavior &extensionBehavior) const TExtensionBehavior &extensionBehavior)
: TIntermTraverser(true, false, false, symbolTable), : TIntermTraverser(true, false, false, symbolTable),
@ -245,7 +248,6 @@ CollectVariablesTraverser::CollectVariablesTraverser(
mPrimitiveIDAdded(false), mPrimitiveIDAdded(false),
mLayerAdded(false), mLayerAdded(false),
mHashFunction(hashFunction), mHashFunction(hashFunction),
mShaderVersion(shaderVersion),
mShaderType(shaderType), mShaderType(shaderType),
mExtensionBehavior(extensionBehavior) mExtensionBehavior(extensionBehavior)
{ {
@ -256,16 +258,13 @@ std::string CollectVariablesTraverser::getMappedName(const TSymbol *symbol) cons
return HashName(symbol, mHashFunction, nullptr).data(); return HashName(symbol, mHashFunction, nullptr).data();
} }
void CollectVariablesTraverser::setBuiltInInfoFromSymbolTable(const ImmutableString &name, void CollectVariablesTraverser::setBuiltInInfoFromSymbol(const TVariable &variable,
ShaderVariable *info) ShaderVariable *info)
{ {
const TVariable *symbolTableVar = const TType &type = variable.getType();
reinterpret_cast<const TVariable *>(mSymbolTable->findBuiltIn(name, mShaderVersion));
ASSERT(symbolTableVar);
const TType &type = symbolTableVar->getType();
info->name = name.data(); info->name = variable.name().data();
info->mappedName = name.data(); info->mappedName = variable.name().data();
info->type = GLVariableType(type); info->type = GLVariableType(type);
info->precision = GLVariablePrecision(type); info->precision = GLVariablePrecision(type);
if (auto *arraySizes = type.getArraySizes()) if (auto *arraySizes = type.getArraySizes())
@ -274,7 +273,7 @@ void CollectVariablesTraverser::setBuiltInInfoFromSymbolTable(const ImmutableStr
} }
} }
void CollectVariablesTraverser::recordBuiltInVaryingUsed(const ImmutableString &name, void CollectVariablesTraverser::recordBuiltInVaryingUsed(const TVariable &variable,
bool *addedFlag, bool *addedFlag,
std::vector<Varying> *varyings) std::vector<Varying> *varyings)
{ {
@ -282,35 +281,38 @@ void CollectVariablesTraverser::recordBuiltInVaryingUsed(const ImmutableString &
if (!(*addedFlag)) if (!(*addedFlag))
{ {
Varying info; Varying info;
setBuiltInInfoFromSymbolTable(name, &info); setBuiltInInfoFromSymbol(variable, &info);
info.staticUse = true; info.staticUse = true;
info.isInvariant = mSymbolTable->isVaryingInvariant(name); info.active = true;
info.isInvariant = mSymbolTable->isVaryingInvariant(variable.name());
varyings->push_back(info); varyings->push_back(info);
(*addedFlag) = true; (*addedFlag) = true;
} }
} }
void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const ImmutableString &name, void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const TVariable &variable,
bool *addedFlag) bool *addedFlag)
{ {
if (!(*addedFlag)) if (!(*addedFlag))
{ {
OutputVariable info; OutputVariable info;
setBuiltInInfoFromSymbolTable(name, &info); setBuiltInInfoFromSymbol(variable, &info);
info.staticUse = true; info.staticUse = true;
info.active = true;
mOutputVariables->push_back(info); mOutputVariables->push_back(info);
(*addedFlag) = true; (*addedFlag) = true;
} }
} }
void CollectVariablesTraverser::recordBuiltInAttributeUsed(const ImmutableString &name, void CollectVariablesTraverser::recordBuiltInAttributeUsed(const TVariable &variable,
bool *addedFlag) bool *addedFlag)
{ {
if (!(*addedFlag)) if (!(*addedFlag))
{ {
Attribute info; Attribute info;
setBuiltInInfoFromSymbolTable(name, &info); setBuiltInInfoFromSymbol(variable, &info);
info.staticUse = true; info.staticUse = true;
info.active = true;
info.location = -1; info.location = -1;
mAttribs->push_back(info); mAttribs->push_back(info);
(*addedFlag) = true; (*addedFlag) = true;
@ -324,7 +326,6 @@ InterfaceBlock *CollectVariablesTraverser::recordGLInUsed(const TType &glInType)
ASSERT(glInType.getQualifier() == EvqPerVertexIn); ASSERT(glInType.getQualifier() == EvqPerVertexIn);
InterfaceBlock info; InterfaceBlock info;
recordInterfaceBlock("gl_in", glInType, &info); recordInterfaceBlock("gl_in", glInType, &info);
info.staticUse = true;
mPerVertexInAdded = true; mPerVertexInAdded = true;
mInBlocks->push_back(info); mInBlocks->push_back(info);
@ -336,11 +337,17 @@ InterfaceBlock *CollectVariablesTraverser::recordGLInUsed(const TType &glInType)
} }
} }
// We want to check whether a uniform/varying is statically used bool CollectVariablesTraverser::visitInvariantDeclaration(Visit visit,
// because we only count the used ones in packing computing. TIntermInvariantDeclaration *node)
// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count {
// toward varying counting if they are statically used in a fragment // We should not mark variables as active just based on an invariant declaration, so we don't
// shader. // traverse the symbols declared invariant.
return false;
}
// We want to check whether a uniform/varying is active because we need to skip updating inactive
// ones. We also only count the active ones in packing computing. Also, gl_FragCoord, gl_PointCoord,
// and gl_FrontFacing count toward varying counting if they are active in a fragment shader.
void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol) void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
{ {
ASSERT(symbol != nullptr); ASSERT(symbol != nullptr);
@ -385,6 +392,7 @@ void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
info.type = GL_NONE; info.type = GL_NONE;
info.precision = GL_NONE; info.precision = GL_NONE;
info.staticUse = true; info.staticUse = true;
info.active = true;
ShaderVariable nearInfo(GL_FLOAT); ShaderVariable nearInfo(GL_FLOAT);
const char kNearName[] = "near"; const char kNearName[] = "near";
@ -392,6 +400,7 @@ void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
nearInfo.mappedName = kNearName; nearInfo.mappedName = kNearName;
nearInfo.precision = GL_HIGH_FLOAT; nearInfo.precision = GL_HIGH_FLOAT;
nearInfo.staticUse = true; nearInfo.staticUse = true;
nearInfo.active = true;
ShaderVariable farInfo(GL_FLOAT); ShaderVariable farInfo(GL_FLOAT);
const char kFarName[] = "far"; const char kFarName[] = "far";
@ -399,6 +408,7 @@ void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
farInfo.mappedName = kFarName; farInfo.mappedName = kFarName;
farInfo.precision = GL_HIGH_FLOAT; farInfo.precision = GL_HIGH_FLOAT;
farInfo.staticUse = true; farInfo.staticUse = true;
farInfo.active = true;
ShaderVariable diffInfo(GL_FLOAT); ShaderVariable diffInfo(GL_FLOAT);
const char kDiffName[] = "diff"; const char kDiffName[] = "diff";
@ -406,6 +416,7 @@ void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
diffInfo.mappedName = kDiffName; diffInfo.mappedName = kDiffName;
diffInfo.precision = GL_HIGH_FLOAT; diffInfo.precision = GL_HIGH_FLOAT;
diffInfo.staticUse = true; diffInfo.staticUse = true;
diffInfo.active = true;
info.fields.push_back(nearInfo); info.fields.push_back(nearInfo);
info.fields.push_back(farInfo); info.fields.push_back(farInfo);
@ -450,116 +461,91 @@ void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
} }
break; break;
case EvqFragCoord: case EvqFragCoord:
recordBuiltInVaryingUsed(ImmutableString("gl_FragCoord"), &mFragCoordAdded, recordBuiltInVaryingUsed(symbol->variable(), &mFragCoordAdded, mInputVaryings);
mInputVaryings);
return; return;
case EvqFrontFacing: case EvqFrontFacing:
recordBuiltInVaryingUsed(ImmutableString("gl_FrontFacing"), &mFrontFacingAdded, recordBuiltInVaryingUsed(symbol->variable(), &mFrontFacingAdded, mInputVaryings);
mInputVaryings);
return; return;
case EvqPointCoord: case EvqPointCoord:
recordBuiltInVaryingUsed(ImmutableString("gl_PointCoord"), &mPointCoordAdded, recordBuiltInVaryingUsed(symbol->variable(), &mPointCoordAdded, mInputVaryings);
mInputVaryings);
return; return;
case EvqInstanceID: case EvqInstanceID:
// Whenever the SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW option is set, // Whenever the SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW option is set,
// gl_InstanceID is added inside expressions to initialize ViewID_OVR and // gl_InstanceID is added inside expressions to initialize ViewID_OVR and
// InstanceID. gl_InstanceID is not added to the symbol table for ESSL1 shaders // InstanceID. Note that gl_InstanceID is not added to the symbol table for ESSL1
// which makes it necessary to populate the type information explicitly instead of // shaders.
// extracting it from the symbol table. recordBuiltInAttributeUsed(symbol->variable(), &mInstanceIDAdded);
if (!mInstanceIDAdded)
{
Attribute info;
const char kName[] = "gl_InstanceID";
info.name = kName;
info.mappedName = kName;
info.type = GL_INT;
info.precision = GL_HIGH_INT; // Defined by spec.
info.staticUse = true;
info.location = -1;
mAttribs->push_back(info);
mInstanceIDAdded = true;
}
return; return;
case EvqVertexID: case EvqVertexID:
recordBuiltInAttributeUsed(ImmutableString("gl_VertexID"), &mVertexIDAdded); recordBuiltInAttributeUsed(symbol->variable(), &mVertexIDAdded);
return; return;
case EvqPosition: case EvqPosition:
recordBuiltInVaryingUsed(ImmutableString("gl_Position"), &mPositionAdded, recordBuiltInVaryingUsed(symbol->variable(), &mPositionAdded, mOutputVaryings);
mOutputVaryings);
return; return;
case EvqPointSize: case EvqPointSize:
recordBuiltInVaryingUsed(ImmutableString("gl_PointSize"), &mPointSizeAdded, recordBuiltInVaryingUsed(symbol->variable(), &mPointSizeAdded, mOutputVaryings);
mOutputVaryings);
return; return;
case EvqLastFragData: case EvqLastFragData:
recordBuiltInVaryingUsed(ImmutableString("gl_LastFragData"), &mLastFragDataAdded, recordBuiltInVaryingUsed(symbol->variable(), &mLastFragDataAdded, mInputVaryings);
mInputVaryings);
return; return;
case EvqFragColor: case EvqFragColor:
recordBuiltInFragmentOutputUsed(ImmutableString("gl_FragColor"), &mFragColorAdded); recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragColorAdded);
return; return;
case EvqFragData: case EvqFragData:
if (!mFragDataAdded) if (!mFragDataAdded)
{ {
OutputVariable info; OutputVariable info;
setBuiltInInfoFromSymbolTable(ImmutableString("gl_FragData"), &info); setBuiltInInfoFromSymbol(symbol->variable(), &info);
if (!IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers)) if (!IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers))
{ {
ASSERT(info.arraySizes.size() == 1u); ASSERT(info.arraySizes.size() == 1u);
info.arraySizes.back() = 1u; info.arraySizes.back() = 1u;
} }
info.staticUse = true; info.staticUse = true;
info.active = true;
mOutputVariables->push_back(info); mOutputVariables->push_back(info);
mFragDataAdded = true; mFragDataAdded = true;
} }
return; return;
case EvqFragDepthEXT: case EvqFragDepthEXT:
recordBuiltInFragmentOutputUsed(ImmutableString("gl_FragDepthEXT"), recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragDepthEXTAdded);
&mFragDepthEXTAdded);
return; return;
case EvqFragDepth: case EvqFragDepth:
recordBuiltInFragmentOutputUsed(ImmutableString("gl_FragDepth"), &mFragDepthAdded); recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragDepthAdded);
return; return;
case EvqSecondaryFragColorEXT: case EvqSecondaryFragColorEXT:
recordBuiltInFragmentOutputUsed(ImmutableString("gl_SecondaryFragColorEXT"), recordBuiltInFragmentOutputUsed(symbol->variable(), &mSecondaryFragColorEXTAdded);
&mSecondaryFragColorEXTAdded);
return; return;
case EvqSecondaryFragDataEXT: case EvqSecondaryFragDataEXT:
recordBuiltInFragmentOutputUsed(ImmutableString("gl_SecondaryFragDataEXT"), recordBuiltInFragmentOutputUsed(symbol->variable(), &mSecondaryFragDataEXTAdded);
&mSecondaryFragDataEXTAdded);
return; return;
case EvqInvocationID: case EvqInvocationID:
recordBuiltInVaryingUsed(ImmutableString("gl_InvocationID"), &mInvocationIDAdded, recordBuiltInVaryingUsed(symbol->variable(), &mInvocationIDAdded, mInputVaryings);
mInputVaryings);
break; break;
case EvqPrimitiveIDIn: case EvqPrimitiveIDIn:
recordBuiltInVaryingUsed(ImmutableString("gl_PrimitiveIDIn"), &mPrimitiveIDInAdded, recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDInAdded, mInputVaryings);
mInputVaryings);
break; break;
case EvqPrimitiveID: case EvqPrimitiveID:
if (mShaderType == GL_GEOMETRY_SHADER_EXT) if (mShaderType == GL_GEOMETRY_SHADER_EXT)
{ {
recordBuiltInVaryingUsed(ImmutableString("gl_PrimitiveID"), &mPrimitiveIDAdded, recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDAdded,
mOutputVaryings); mOutputVaryings);
} }
else else
{ {
ASSERT(mShaderType == GL_FRAGMENT_SHADER); ASSERT(mShaderType == GL_FRAGMENT_SHADER);
recordBuiltInVaryingUsed(ImmutableString("gl_PrimitiveID"), &mPrimitiveIDAdded, recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDAdded,
mInputVaryings); mInputVaryings);
} }
break; break;
case EvqLayer: case EvqLayer:
if (mShaderType == GL_GEOMETRY_SHADER_EXT) if (mShaderType == GL_GEOMETRY_SHADER_EXT)
{ {
recordBuiltInVaryingUsed(ImmutableString("gl_Layer"), &mLayerAdded, recordBuiltInVaryingUsed(symbol->variable(), &mLayerAdded, mOutputVaryings);
mOutputVaryings);
} }
else if (mShaderType == GL_FRAGMENT_SHADER) else if (mShaderType == GL_FRAGMENT_SHADER)
{ {
recordBuiltInVaryingUsed(ImmutableString("gl_Layer"), &mLayerAdded, recordBuiltInVaryingUsed(symbol->variable(), &mLayerAdded, mInputVaryings);
mInputVaryings);
} }
else else
{ {
@ -573,15 +559,18 @@ void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
} }
if (var) if (var)
{ {
MarkStaticallyUsed(var); MarkActive(var);
} }
} }
void CollectVariablesTraverser::setFieldOrVariableProperties(const TType &type, void CollectVariablesTraverser::setFieldOrVariableProperties(const TType &type,
bool staticUse,
ShaderVariable *variableOut) const ShaderVariable *variableOut) const
{ {
ASSERT(variableOut); ASSERT(variableOut);
variableOut->staticUse = staticUse;
const TStructure *structure = type.getStruct(); const TStructure *structure = type.getStruct();
if (!structure) if (!structure)
{ {
@ -604,7 +593,7 @@ void CollectVariablesTraverser::setFieldOrVariableProperties(const TType &type,
// Regardless of the variable type (uniform, in/out etc.) its fields are always plain // Regardless of the variable type (uniform, in/out etc.) its fields are always plain
// ShaderVariable objects. // ShaderVariable objects.
ShaderVariable fieldVariable; ShaderVariable fieldVariable;
setFieldProperties(*field->type(), field->name(), &fieldVariable); setFieldProperties(*field->type(), field->name(), staticUse, &fieldVariable);
variableOut->fields.push_back(fieldVariable); variableOut->fields.push_back(fieldVariable);
} }
} }
@ -616,10 +605,11 @@ void CollectVariablesTraverser::setFieldOrVariableProperties(const TType &type,
void CollectVariablesTraverser::setFieldProperties(const TType &type, void CollectVariablesTraverser::setFieldProperties(const TType &type,
const ImmutableString &name, const ImmutableString &name,
bool staticUse,
ShaderVariable *variableOut) const ShaderVariable *variableOut) const
{ {
ASSERT(variableOut); ASSERT(variableOut);
setFieldOrVariableProperties(type, variableOut); setFieldOrVariableProperties(type, staticUse, variableOut);
variableOut->name.assign(name.data(), name.length()); variableOut->name.assign(name.data(), name.length());
variableOut->mappedName = HashName(name, mHashFunction, nullptr).data(); variableOut->mappedName = HashName(name, mHashFunction, nullptr).data();
} }
@ -630,7 +620,8 @@ void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
{ {
ASSERT(variableOut); ASSERT(variableOut);
setFieldOrVariableProperties(type, variableOut); variableOut->staticUse = mSymbolTable->isStaticallyUsed(variable);
setFieldOrVariableProperties(type, variableOut->staticUse, variableOut);
ASSERT(variable.symbolType() != SymbolType::Empty); ASSERT(variable.symbolType() != SymbolType::Empty);
variableOut->name.assign(variable.name().data(), variable.name().length()); variableOut->name.assign(variable.name().data(), variable.name().length());
variableOut->mappedName = getMappedName(&variable); variableOut->mappedName = getMappedName(&variable);
@ -706,6 +697,18 @@ void CollectVariablesTraverser::recordInterfaceBlock(const char *instanceName,
if (instanceName != nullptr) if (instanceName != nullptr)
{ {
interfaceBlock->instanceName = instanceName; interfaceBlock->instanceName = instanceName;
const TSymbol *blockSymbol = nullptr;
if (strncmp(instanceName, "gl_in", 5u) == 0)
{
blockSymbol = mSymbolTable->getGlInVariableWithArraySize();
}
else
{
blockSymbol = mSymbolTable->findGlobal(ImmutableString(instanceName));
}
ASSERT(blockSymbol && blockSymbol->isVariable());
interfaceBlock->staticUse =
mSymbolTable->isStaticallyUsed(*static_cast<const TVariable *>(blockSymbol));
} }
ASSERT(!interfaceBlockType.isArrayOfArrays()); // Disallowed by GLSL ES 3.10 section 4.3.9 ASSERT(!interfaceBlockType.isArrayOfArrays()); // Disallowed by GLSL ES 3.10 section 4.3.9
interfaceBlock->arraySize = interfaceBlockType.isArray() ? interfaceBlockType.getOutermostArraySize() : 0; interfaceBlock->arraySize = interfaceBlockType.isArray() ? interfaceBlockType.getOutermostArraySize() : 0;
@ -721,16 +724,36 @@ void CollectVariablesTraverser::recordInterfaceBlock(const char *instanceName,
} }
// Gather field information // Gather field information
bool anyFieldStaticallyUsed = false;
for (const TField *field : blockType->fields()) for (const TField *field : blockType->fields())
{ {
const TType &fieldType = *field->type(); const TType &fieldType = *field->type();
bool staticUse = false;
if (instanceName == nullptr)
{
// Static use of individual fields has been recorded, since they are present in the
// symbol table as variables.
const TSymbol *fieldSymbol = mSymbolTable->findGlobal(field->name());
ASSERT(fieldSymbol && fieldSymbol->isVariable());
staticUse =
mSymbolTable->isStaticallyUsed(*static_cast<const TVariable *>(fieldSymbol));
if (staticUse)
{
anyFieldStaticallyUsed = true;
}
}
InterfaceBlockField fieldVariable; InterfaceBlockField fieldVariable;
setFieldProperties(fieldType, field->name(), &fieldVariable); setFieldProperties(fieldType, field->name(), staticUse, &fieldVariable);
fieldVariable.isRowMajorLayout = fieldVariable.isRowMajorLayout =
(fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor); (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
interfaceBlock->fields.push_back(fieldVariable); interfaceBlock->fields.push_back(fieldVariable);
} }
if (anyFieldStaticallyUsed)
{
interfaceBlock->staticUse = true;
}
} }
Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const
@ -848,7 +871,7 @@ bool CollectVariablesTraverser::visitBinary(Visit, TIntermBinary *binaryNode)
{ {
if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock) if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
{ {
// NOTE: we do not determine static use for individual blocks of an array // NOTE: we do not determine static use / activeness for individual blocks of an array.
TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped(); TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
ASSERT(blockNode); ASSERT(blockNode);
@ -882,10 +905,15 @@ bool CollectVariablesTraverser::visitBinary(Visit, TIntermBinary *binaryNode)
namedBlock = findNamedInterfaceBlock(interfaceBlock->name()); namedBlock = findNamedInterfaceBlock(interfaceBlock->name());
} }
ASSERT(namedBlock); ASSERT(namedBlock);
namedBlock->staticUse = true; ASSERT(namedBlock->staticUse);
namedBlock->active = true;
unsigned int fieldIndex = static_cast<unsigned int>(constantUnion->getIConst(0)); unsigned int fieldIndex = static_cast<unsigned int>(constantUnion->getIConst(0));
ASSERT(fieldIndex < namedBlock->fields.size()); ASSERT(fieldIndex < namedBlock->fields.size());
// TODO(oetuaho): Would be nicer to record static use of fields of named interface blocks
// more accurately at parse time - now we only mark the fields statically used if they are
// active. http://anglebug.com/2440
namedBlock->fields[fieldIndex].staticUse = true; namedBlock->fields[fieldIndex].staticUse = true;
namedBlock->fields[fieldIndex].active = true;
if (traverseIndexExpression) if (traverseIndexExpression)
{ {
@ -911,14 +939,12 @@ void CollectVariables(TIntermBlock *root,
std::vector<InterfaceBlock> *inBlocks, std::vector<InterfaceBlock> *inBlocks,
ShHashFunction64 hashFunction, ShHashFunction64 hashFunction,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
int shaderVersion,
GLenum shaderType, GLenum shaderType,
const TExtensionBehavior &extensionBehavior) const TExtensionBehavior &extensionBehavior)
{ {
CollectVariablesTraverser collect(attributes, outputVariables, uniforms, inputVaryings, CollectVariablesTraverser collect(attributes, outputVariables, uniforms, inputVaryings,
outputVaryings, uniformBlocks, shaderStorageBlocks, inBlocks, outputVaryings, uniformBlocks, shaderStorageBlocks, inBlocks,
hashFunction, symbolTable, shaderVersion, shaderType, hashFunction, symbolTable, shaderType, extensionBehavior);
extensionBehavior);
root->traverse(&collect); root->traverse(&collect);
} }

View File

@ -29,7 +29,6 @@ void CollectVariables(TIntermBlock *root,
std::vector<InterfaceBlock> *inBlocks, std::vector<InterfaceBlock> *inBlocks,
ShHashFunction64 hashFunction, ShHashFunction64 hashFunction,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
int shaderVersion,
GLenum shaderType, GLenum shaderType,
const TExtensionBehavior &extensionBehavior); const TExtensionBehavior &extensionBehavior);
} }

View File

@ -10,43 +10,43 @@
#include "angle_gl.h" #include "angle_gl.h"
#include "common/utilities.h" #include "common/utilities.h"
#include "compiler/translator/AddAndTrueToLoopCondition.h"
#include "compiler/translator/CallDAG.h" #include "compiler/translator/CallDAG.h"
#include "compiler/translator/ClampFragDepth.h"
#include "compiler/translator/ClampPointSize.h"
#include "compiler/translator/CollectVariables.h" #include "compiler/translator/CollectVariables.h"
#include "compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h"
#include "compiler/translator/DeferGlobalInitializers.h"
#include "compiler/translator/EmulateGLFragColorBroadcast.h"
#include "compiler/translator/EmulatePrecision.h"
#include "compiler/translator/FoldExpressions.h"
#include "compiler/translator/Initialize.h" #include "compiler/translator/Initialize.h"
#include "compiler/translator/InitializeVariables.h"
#include "compiler/translator/IntermNodePatternMatcher.h"
#include "compiler/translator/IsASTDepthBelowLimit.h" #include "compiler/translator/IsASTDepthBelowLimit.h"
#include "compiler/translator/OutputTree.h" #include "compiler/translator/OutputTree.h"
#include "compiler/translator/ParseContext.h" #include "compiler/translator/ParseContext.h"
#include "compiler/translator/PruneNoOps.h"
#include "compiler/translator/RegenerateStructNames.h"
#include "compiler/translator/RemoveArrayLengthMethod.h"
#include "compiler/translator/RemoveEmptySwitchStatements.h"
#include "compiler/translator/RemoveInvariantDeclaration.h"
#include "compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h"
#include "compiler/translator/RemovePow.h"
#include "compiler/translator/RemoveUnreferencedVariables.h"
#include "compiler/translator/RewriteDoWhile.h"
#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h"
#include "compiler/translator/SeparateDeclarations.h"
#include "compiler/translator/SimplifyLoopConditions.h"
#include "compiler/translator/SplitSequenceOperator.h"
#include "compiler/translator/UnfoldShortCircuitAST.h"
#include "compiler/translator/UseInterfaceBlockFields.h"
#include "compiler/translator/ValidateLimitations.h" #include "compiler/translator/ValidateLimitations.h"
#include "compiler/translator/ValidateMaxParameters.h" #include "compiler/translator/ValidateMaxParameters.h"
#include "compiler/translator/ValidateOutputs.h" #include "compiler/translator/ValidateOutputs.h"
#include "compiler/translator/ValidateVaryingLocations.h" #include "compiler/translator/ValidateVaryingLocations.h"
#include "compiler/translator/VariablePacker.h" #include "compiler/translator/VariablePacker.h"
#include "compiler/translator/VectorizeVectorScalarArithmetic.h" #include "compiler/translator/tree_ops/AddAndTrueToLoopCondition.h"
#include "compiler/translator/tree_ops/ClampFragDepth.h"
#include "compiler/translator/tree_ops/ClampPointSize.h"
#include "compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.h"
#include "compiler/translator/tree_ops/DeferGlobalInitializers.h"
#include "compiler/translator/tree_ops/EmulateGLFragColorBroadcast.h"
#include "compiler/translator/tree_ops/EmulatePrecision.h"
#include "compiler/translator/tree_ops/FoldExpressions.h"
#include "compiler/translator/tree_ops/InitializeVariables.h"
#include "compiler/translator/tree_ops/PruneEmptyCases.h"
#include "compiler/translator/tree_ops/PruneNoOps.h"
#include "compiler/translator/tree_ops/RegenerateStructNames.h"
#include "compiler/translator/tree_ops/RemoveArrayLengthMethod.h"
#include "compiler/translator/tree_ops/RemoveInvariantDeclaration.h"
#include "compiler/translator/tree_ops/RemovePow.h"
#include "compiler/translator/tree_ops/RemoveUnreferencedVariables.h"
#include "compiler/translator/tree_ops/RewriteDoWhile.h"
#include "compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.h"
#include "compiler/translator/tree_ops/SeparateDeclarations.h"
#include "compiler/translator/tree_ops/SimplifyLoopConditions.h"
#include "compiler/translator/tree_ops/SplitSequenceOperator.h"
#include "compiler/translator/tree_ops/UnfoldShortCircuitAST.h"
#include "compiler/translator/tree_ops/UseInterfaceBlockFields.h"
#include "compiler/translator/tree_ops/VectorizeVectorScalarArithmetic.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
#include "compiler/translator/tree_util/IntermNodePatternMatcher.h"
#include "compiler/translator/util.h" #include "compiler/translator/util.h"
#include "third_party/compiler/ArrayBoundsClamper.h" #include "third_party/compiler/ArrayBoundsClamper.h"
@ -193,12 +193,12 @@ class TScopedSymbolTableLevel
public: public:
TScopedSymbolTableLevel(TSymbolTable *table) : mTable(table) TScopedSymbolTableLevel(TSymbolTable *table) : mTable(table)
{ {
ASSERT(mTable->atBuiltInLevel()); ASSERT(mTable->isEmpty());
mTable->push(); mTable->push();
} }
~TScopedSymbolTableLevel() ~TScopedSymbolTableLevel()
{ {
while (!mTable->atBuiltInLevel()) while (!mTable->isEmpty())
mTable->pop(); mTable->pop();
} }
@ -225,6 +225,51 @@ int MapSpecToShaderVersion(ShShaderSpec spec)
} }
} }
bool ValidateFragColorAndFragData(GLenum shaderType,
int shaderVersion,
const TSymbolTable &symbolTable,
TDiagnostics *diagnostics)
{
if (shaderVersion > 100 || shaderType != GL_FRAGMENT_SHADER)
{
return true;
}
bool usesFragColor = false;
bool usesFragData = false;
// This validation is a bit stricter than the spec - it's only an error to write to
// both FragData and FragColor. But because it's better not to have reads from undefined
// variables, we always return an error if they are both referenced, rather than only if they
// are written.
if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_FragColor()) ||
symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()))
{
usesFragColor = true;
}
// Extension variables may not always be initialized (saves some time at symbol table init).
bool secondaryFragDataUsed =
symbolTable.gl_SecondaryFragDataEXT() != nullptr &&
symbolTable.isStaticallyUsed(*symbolTable.gl_SecondaryFragDataEXT());
if (symbolTable.isStaticallyUsed(*symbolTable.gl_FragData()) || secondaryFragDataUsed)
{
usesFragData = true;
}
if (usesFragColor && usesFragData)
{
const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()) ||
secondaryFragDataUsed)
{
errorMessage =
"cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
" and (gl_FragColor, gl_SecondaryFragColorEXT)";
}
diagnostics->globalError(errorMessage);
return false;
}
return true;
}
} // namespace } // namespace
TShHandleBase::TShHandleBase() TShHandleBase::TShHandleBase()
@ -451,6 +496,11 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
return false; return false;
} }
if (!ValidateFragColorAndFragData(shaderType, shaderVersion, symbolTable, &mDiagnostics))
{
return false;
}
// Fold expressions that could not be folded before validation that was done as a part of // Fold expressions that could not be folded before validation that was done as a part of
// parsing. // parsing.
FoldExpressions(root, &mDiagnostics); FoldExpressions(root, &mDiagnostics);
@ -466,16 +516,6 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
// After this empty declarations are not allowed in the AST. // After this empty declarations are not allowed in the AST.
PruneNoOps(root, &symbolTable); PruneNoOps(root, &symbolTable);
// In case the last case inside a switch statement is a certain type of no-op, GLSL
// compilers in drivers may not accept it. In this case we clean up the dead code from the
// end of switch statements. This is also required because PruneNoOps may have left switch
// statements that only contained an empty declaration inside the final case in an invalid
// state. Relies on that PruneNoOps has already been run.
RemoveNoOpCasesFromEndOfSwitchStatements(root, &symbolTable);
// Remove empty switch statements - this makes output simpler.
RemoveEmptySwitchStatements(root);
// Create the function DAG and check there is no recursion // Create the function DAG and check there is no recursion
if (!initCallDag(root)) if (!initCallDag(root))
{ {
@ -548,7 +588,7 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
if (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT) if (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT)
{ {
RemovePow(root); RemovePow(root, &symbolTable);
} }
if (compileOptions & SH_REGENERATE_STRUCT_NAMES) if (compileOptions & SH_REGENERATE_STRUCT_NAMES)
@ -588,6 +628,14 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
RemoveUnreferencedVariables(root, &symbolTable); RemoveUnreferencedVariables(root, &symbolTable);
// In case the last case inside a switch statement is a certain type of no-op, GLSL compilers in
// drivers may not accept it. In this case we clean up the dead code from the end of switch
// statements. This is also required because PruneNoOps or RemoveUnreferencedVariables may have
// left switch statements that only contained an empty declaration inside the final case in an
// invalid state. Relies on that PruneNoOps and RemoveUnreferencedVariables have already been
// run.
PruneEmptyCases(root);
// Built-in function emulation needs to happen after validateLimitations pass. // Built-in function emulation needs to happen after validateLimitations pass.
// TODO(jmadill): Remove global pool allocator. // TODO(jmadill): Remove global pool allocator.
GetGlobalPoolAllocator()->lock(); GetGlobalPoolAllocator()->lock();
@ -605,7 +653,7 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
ASSERT(!variablesCollected); ASSERT(!variablesCollected);
CollectVariables(root, &attributes, &outputVariables, &uniforms, &inputVaryings, CollectVariables(root, &attributes, &outputVariables, &uniforms, &inputVaryings,
&outputVaryings, &uniformBlocks, &shaderStorageBlocks, &inBlocks, &outputVaryings, &uniformBlocks, &shaderStorageBlocks, &inBlocks,
hashFunction, &symbolTable, shaderVersion, shaderType, extensionBehavior); hashFunction, &symbolTable, shaderType, extensionBehavior);
collectInterfaceBlocks(); collectInterfaceBlocks();
variablesCollected = true; variablesCollected = true;
if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS) if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS)

View File

@ -12,7 +12,7 @@
#include <set> #include <set>
#include <string> #include <string>
#include "compiler/translator/IntermTraverse.h" #include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh namespace sh
{ {

View File

@ -8,8 +8,8 @@
#include "compiler/translator/FlagStd140Structs.h" #include "compiler/translator/FlagStd140Structs.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/SymbolTable.h" #include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh namespace sh
{ {

View File

@ -35,17 +35,35 @@ template <>
const size_t ImmutableString::FowlerNollVoHash<8>::kFnvOffsetBasis = const size_t ImmutableString::FowlerNollVoHash<8>::kFnvOffsetBasis =
static_cast<size_t>(0xcbf29ce484222325ull); static_cast<size_t>(0xcbf29ce484222325ull);
uint32_t ImmutableString::hash32() const uint32_t ImmutableString::mangledNameHash() const
{ {
const char *data_ptr = data(); const char *dataPtr = data();
uint32_t hash = static_cast<uint32_t>(FowlerNollVoHash<4>::kFnvOffsetBasis); uint32_t hash = static_cast<uint32_t>(FowlerNollVoHash<4>::kFnvOffsetBasis);
while ((*data_ptr) != '\0') const uint32_t kMaxSixBitValue = (1u << 6) - 1u;
uint32_t parenLocation = kMaxSixBitValue;
uint32_t hasArrayOrBlockParamBit = 0u;
uint32_t index = 0;
while (dataPtr[index] != '\0')
{ {
hash = hash ^ (*data_ptr); hash = hash ^ dataPtr[index];
hash = hash * static_cast<uint32_t>(FowlerNollVoHash<4>::kFnvPrime); hash = hash * static_cast<uint32_t>(FowlerNollVoHash<4>::kFnvPrime);
++data_ptr; if (dataPtr[index] == '(')
{
// We should only reach here once, since this function should not be called with invalid
// mangled names.
ASSERT(parenLocation == kMaxSixBitValue);
parenLocation = index;
}
else if (dataPtr[index] == '{' || dataPtr[index] == '[')
{
hasArrayOrBlockParamBit = 1u;
}
++index;
} }
return hash; // Should not be called with strings longer than 63 characters.
ASSERT(index <= kMaxSixBitValue);
return ((hash >> 13) ^ (hash & 0x1fff)) | (index << 19) | (parenLocation << 25) |
(hasArrayOrBlockParamBit << 31);
} }
} // namespace sh } // namespace sh

View File

@ -128,7 +128,10 @@ class ImmutableString
} }
}; };
uint32_t hash32() const; // This hash encodes the opening parentheses location (if any), name length and whether the name
// contains { or [ characters in addition to a 19-bit hash. This way the hash is more useful for
// lookups. The string passed in should be at most 63 characters.
uint32_t mangledNameHash() const;
private: private:
const char *mData; const char *mData;

View File

@ -47,7 +47,7 @@ class ImmutableStringBuilder
while (index >= 0) while (index >= 0)
{ {
char digit = static_cast<char>((number >> (index * 4)) & 0xfu); char digit = static_cast<char>((number >> (index * 4)) & 0xfu);
char digitChar = digit < 10 ? digit + '0' : digit + 'a'; char digitChar = (digit < 10) ? (digit + '0') : (digit + ('a' - 10));
mData[mPos++] = digitChar; mData[mPos++] = digitChar;
--index; --index;
} }

View File

@ -264,7 +264,7 @@ bool TIntermBlock::replaceChildNode(TIntermNode *original, TIntermNode *replacem
bool TIntermFunctionPrototype::replaceChildNode(TIntermNode *original, TIntermNode *replacement) bool TIntermFunctionPrototype::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{ {
return replaceChildNodeInternal(original, replacement); return false;
} }
bool TIntermDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement) bool TIntermDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
@ -689,12 +689,6 @@ void TIntermBlock::appendStatement(TIntermNode *statement)
} }
} }
void TIntermFunctionPrototype::appendParameter(TIntermSymbol *parameter)
{
ASSERT(parameter != nullptr);
mParameters.push_back(parameter);
}
void TIntermDeclaration::appendDeclarator(TIntermTyped *declarator) void TIntermDeclaration::appendDeclarator(TIntermTyped *declarator)
{ {
ASSERT(declarator != nullptr); ASSERT(declarator != nullptr);
@ -801,6 +795,7 @@ TIntermSwizzle::TIntermSwizzle(const TIntermSwizzle &node) : TIntermExpression(n
ASSERT(operandCopy != nullptr); ASSERT(operandCopy != nullptr);
mOperand = operandCopy; mOperand = operandCopy;
mSwizzleOffsets = node.mSwizzleOffsets; mSwizzleOffsets = node.mSwizzleOffsets;
mHasFoldedDuplicateOffsets = node.mHasFoldedDuplicateOffsets;
} }
TIntermBinary::TIntermBinary(const TIntermBinary &node) TIntermBinary::TIntermBinary(const TIntermBinary &node)
@ -814,7 +809,9 @@ TIntermBinary::TIntermBinary(const TIntermBinary &node)
} }
TIntermUnary::TIntermUnary(const TIntermUnary &node) TIntermUnary::TIntermUnary(const TIntermUnary &node)
: TIntermOperator(node), mUseEmulatedFunction(node.mUseEmulatedFunction) : TIntermOperator(node),
mUseEmulatedFunction(node.mUseEmulatedFunction),
mFunction(node.mFunction)
{ {
TIntermTyped *operandCopy = node.mOperand->deepCopy(); TIntermTyped *operandCopy = node.mOperand->deepCopy();
ASSERT(operandCopy != nullptr); ASSERT(operandCopy != nullptr);
@ -1047,14 +1044,15 @@ void TIntermUnary::promote()
TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets) TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets)
: TIntermExpression(TType(EbtFloat, EbpUndefined)), : TIntermExpression(TType(EbtFloat, EbpUndefined)),
mOperand(operand), mOperand(operand),
mSwizzleOffsets(swizzleOffsets) mSwizzleOffsets(swizzleOffsets),
mHasFoldedDuplicateOffsets(false)
{ {
ASSERT(mSwizzleOffsets.size() <= 4); ASSERT(mSwizzleOffsets.size() <= 4);
promote(); promote();
} }
TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand) TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand, const TFunction *function)
: TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false) : TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false), mFunction(function)
{ {
promote(); promote();
} }
@ -1173,6 +1171,10 @@ void TIntermSwizzle::promote()
bool TIntermSwizzle::hasDuplicateOffsets() const bool TIntermSwizzle::hasDuplicateOffsets() const
{ {
if (mHasFoldedDuplicateOffsets)
{
return true;
}
int offsetCount[4] = {0u, 0u, 0u, 0u}; int offsetCount[4] = {0u, 0u, 0u, 0u};
for (const auto offset : mSwizzleOffsets) for (const auto offset : mSwizzleOffsets)
{ {
@ -1185,6 +1187,11 @@ bool TIntermSwizzle::hasDuplicateOffsets() const
return false; return false;
} }
void TIntermSwizzle::setHasFoldedDuplicateOffsets(bool hasFoldedDuplicateOffsets)
{
mHasFoldedDuplicateOffsets = hasFoldedDuplicateOffsets;
}
bool TIntermSwizzle::offsetsMatch(int offset) const bool TIntermSwizzle::offsetsMatch(int offset) const
{ {
return mSwizzleOffsets.size() == 1 && mSwizzleOffsets[0] == offset; return mSwizzleOffsets.size() == 1 && mSwizzleOffsets[0] == offset;
@ -1478,6 +1485,24 @@ const TConstantUnion *TIntermConstantUnion::FoldIndexing(const TType &type,
TIntermTyped *TIntermSwizzle::fold(TDiagnostics * /* diagnostics */) TIntermTyped *TIntermSwizzle::fold(TDiagnostics * /* diagnostics */)
{ {
TIntermSwizzle *operandSwizzle = mOperand->getAsSwizzleNode();
if (operandSwizzle)
{
// We need to fold the two swizzles into one, so that repeated swizzling can't cause stack
// overflow in ParseContext::checkCanBeLValue().
bool hadDuplicateOffsets = operandSwizzle->hasDuplicateOffsets();
TVector<int> foldedOffsets;
for (int offset : mSwizzleOffsets)
{
// Offset should already be validated.
ASSERT(static_cast<size_t>(offset) < operandSwizzle->mSwizzleOffsets.size());
foldedOffsets.push_back(operandSwizzle->mSwizzleOffsets[offset]);
}
operandSwizzle->mSwizzleOffsets = foldedOffsets;
operandSwizzle->setType(getType());
operandSwizzle->setHasFoldedDuplicateOffsets(hadDuplicateOffsets);
return operandSwizzle;
}
TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion(); TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
if (operandConstant == nullptr) if (operandConstant == nullptr)
{ {

View File

@ -431,6 +431,7 @@ class TIntermSwizzle : public TIntermExpression
void writeOffsetsAsXYZW(TInfoSinkBase *out) const; void writeOffsetsAsXYZW(TInfoSinkBase *out) const;
bool hasDuplicateOffsets() const; bool hasDuplicateOffsets() const;
void setHasFoldedDuplicateOffsets(bool hasFoldedDuplicateOffsets);
bool offsetsMatch(int offset) const; bool offsetsMatch(int offset) const;
TIntermTyped *fold(TDiagnostics *diagnostics) override; TIntermTyped *fold(TDiagnostics *diagnostics) override;
@ -438,6 +439,7 @@ class TIntermSwizzle : public TIntermExpression
protected: protected:
TIntermTyped *mOperand; TIntermTyped *mOperand;
TVector<int> mSwizzleOffsets; TVector<int> mSwizzleOffsets;
bool mHasFoldedDuplicateOffsets;
private: private:
void promote(); void promote();
@ -503,7 +505,7 @@ class TIntermBinary : public TIntermOperator
class TIntermUnary : public TIntermOperator class TIntermUnary : public TIntermOperator
{ {
public: public:
TIntermUnary(TOperator op, TIntermTyped *operand); TIntermUnary(TOperator op, TIntermTyped *operand, const TFunction *function);
TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); } TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); }
@ -516,6 +518,8 @@ class TIntermUnary : public TIntermOperator
TIntermTyped *getOperand() { return mOperand; } TIntermTyped *getOperand() { return mOperand; }
TIntermTyped *fold(TDiagnostics *diagnostics) override; TIntermTyped *fold(TDiagnostics *diagnostics) override;
const TFunction *getFunction() const { return mFunction; }
void setUseEmulatedFunction() { mUseEmulatedFunction = true; } void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
bool getUseEmulatedFunction() { return mUseEmulatedFunction; } bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
@ -526,6 +530,8 @@ class TIntermUnary : public TIntermOperator
// to work around driver bugs. // to work around driver bugs.
bool mUseEmulatedFunction; bool mUseEmulatedFunction;
const TFunction *const mFunction;
private: private:
void promote(); void promote();
@ -660,7 +666,7 @@ class TIntermBlock : public TIntermNode, public TIntermAggregateBase
// Function prototype. May be in the AST either as a function prototype declaration or as a part of // Function prototype. May be in the AST either as a function prototype declaration or as a part of
// a function definition. The type of the node is the function return type. // a function definition. The type of the node is the function return type.
class TIntermFunctionPrototype : public TIntermTyped, public TIntermAggregateBase class TIntermFunctionPrototype : public TIntermTyped
{ {
public: public:
TIntermFunctionPrototype(const TFunction *function); TIntermFunctionPrototype(const TFunction *function);
@ -683,17 +689,9 @@ class TIntermFunctionPrototype : public TIntermTyped, public TIntermAggregateBas
return true; return true;
} }
// Only intended for initially building the declaration.
void appendParameter(TIntermSymbol *parameter);
TIntermSequence *getSequence() override { return &mParameters; }
const TIntermSequence *getSequence() const override { return &mParameters; }
const TFunction *getFunction() const { return mFunction; } const TFunction *getFunction() const { return mFunction; }
protected: protected:
TIntermSequence mParameters;
const TFunction *const mFunction; const TFunction *const mFunction;
}; };

View File

@ -6,7 +6,7 @@
#include "compiler/translator/IsASTDepthBelowLimit.h" #include "compiler/translator/IsASTDepthBelowLimit.h"
#include "compiler/translator/IntermTraverse.h" #include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh namespace sh
{ {
@ -18,24 +18,10 @@ namespace
class MaxDepthTraverser : public TIntermTraverser class MaxDepthTraverser : public TIntermTraverser
{ {
public: public:
MaxDepthTraverser(int depthLimit) : TIntermTraverser(true, true, false), mDepthLimit(depthLimit) MaxDepthTraverser(int depthLimit) : TIntermTraverser(true, false, false, nullptr)
{ {
setMaxAllowedDepth(depthLimit);
} }
bool visitBinary(Visit, TIntermBinary *) override { return depthCheck(); }
bool visitUnary(Visit, TIntermUnary *) override { return depthCheck(); }
bool visitTernary(Visit, TIntermTernary *) override { return depthCheck(); }
bool visitSwizzle(Visit, TIntermSwizzle *) override { return depthCheck(); }
bool visitIfElse(Visit, TIntermIfElse *) override { return depthCheck(); }
bool visitAggregate(Visit, TIntermAggregate *) override { return depthCheck(); }
bool visitBlock(Visit, TIntermBlock *) override { return depthCheck(); }
bool visitLoop(Visit, TIntermLoop *) override { return depthCheck(); }
bool visitBranch(Visit, TIntermBranch *) override { return depthCheck(); }
protected:
bool depthCheck() const { return mMaxDepth < mDepthLimit; }
int mDepthLimit;
}; };
} // anonymous namespace } // anonymous namespace

View File

@ -94,8 +94,8 @@ ImmutableString TOutputGLSL::translateTextureFunction(const ImmutableString &nam
nullptr}; nullptr};
static const char *legacyToCoreRename[] = { static const char *legacyToCoreRename[] = {
"texture2D", "texture", "texture2DProj", "textureProj", "texture2DLod", "textureLod", "texture2D", "texture", "texture2DProj", "textureProj", "texture2DLod", "textureLod",
"texture2DProjLod", "textureProjLod", "texture2DRect", "texture", "textureCube", "texture", "texture2DProjLod", "textureProjLod", "texture2DRect", "texture", "texture2DRectProj",
"textureCubeLod", "textureLod", "textureProj", "textureCube", "texture", "textureCubeLod", "textureLod",
// Extensions // Extensions
"texture2DLodEXT", "textureLod", "texture2DProjLodEXT", "textureProjLod", "texture2DLodEXT", "textureLod", "texture2DProjLodEXT", "textureProjLod",
"textureCubeLodEXT", "textureLod", "texture2DGradEXT", "textureGrad", "textureCubeLodEXT", "textureLod", "texture2DGradEXT", "textureGrad",

View File

@ -328,24 +328,23 @@ void TOutputGLSLBase::writeVariableType(const TType &type)
} }
} }
void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence &args) void TOutputGLSLBase::writeFunctionParameters(const TFunction *func)
{ {
TInfoSinkBase &out = objSink(); TInfoSinkBase &out = objSink();
for (TIntermSequence::const_iterator iter = args.begin(); iter != args.end(); ++iter) size_t paramCount = func->getParamCount();
for (size_t i = 0; i < paramCount; ++i)
{ {
const TIntermSymbol *arg = (*iter)->getAsSymbolNode(); const TVariable *param = func->getParam(i);
ASSERT(arg != nullptr); const TType &type = param->getType();
const TType &type = arg->getType();
writeVariableType(type); writeVariableType(type);
if (arg->variable().symbolType() != SymbolType::Empty) if (param->symbolType() != SymbolType::Empty)
out << " " << hashName(&arg->variable()); out << " " << hashName(param);
if (type.isArray()) if (type.isArray())
out << ArrayString(type); out << ArrayString(type);
// Put a comma if this is not the last argument. // Put a comma if this is not the last argument.
if (iter != args.end() - 1) if (i != paramCount - 1)
out << ", "; out << ", ";
} }
} }
@ -847,7 +846,7 @@ bool TOutputGLSLBase::visitBlock(Visit visit, TIntermBlock *node)
{ {
TInfoSinkBase &out = objSink(); TInfoSinkBase &out = objSink();
// Scope the blocks except when at the global scope. // Scope the blocks except when at the global scope.
if (mDepth > 0) if (getCurrentTraversalDepth() > 0)
{ {
out << "{\n"; out << "{\n";
} }
@ -864,7 +863,7 @@ bool TOutputGLSLBase::visitBlock(Visit visit, TIntermBlock *node)
} }
// Scope the blocks except when at the global scope. // Scope the blocks except when at the global scope.
if (mDepth > 0) if (getCurrentTraversalDepth() > 0)
{ {
out << "}\n"; out << "}\n";
} }
@ -890,10 +889,9 @@ bool TOutputGLSLBase::visitInvariantDeclaration(Visit visit, TIntermInvariantDec
return false; return false;
} }
bool TOutputGLSLBase::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) void TOutputGLSLBase::visitFunctionPrototype(TIntermFunctionPrototype *node)
{ {
TInfoSinkBase &out = objSink(); TInfoSinkBase &out = objSink();
ASSERT(visit == PreVisit);
const TType &type = node->getType(); const TType &type = node->getType();
writeVariableType(type); writeVariableType(type);
@ -903,10 +901,8 @@ bool TOutputGLSLBase::visitFunctionPrototype(Visit visit, TIntermFunctionPrototy
out << " " << hashFunctionNameIfNeeded(node->getFunction()); out << " " << hashFunctionNameIfNeeded(node->getFunction());
out << "("; out << "(";
writeFunctionParameters(*(node->getSequence())); writeFunctionParameters(node->getFunction());
out << ")"; out << ")";
return false;
} }
bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)

View File

@ -11,7 +11,7 @@
#include "compiler/translator/HashNames.h" #include "compiler/translator/HashNames.h"
#include "compiler/translator/InfoSink.h" #include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermTraverse.h" #include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh namespace sh
{ {
@ -44,7 +44,7 @@ class TOutputGLSLBase : public TIntermTraverser
void writeInvariantQualifier(const TType &type); void writeInvariantQualifier(const TType &type);
void writeVariableType(const TType &type); void writeVariableType(const TType &type);
virtual bool writeVariablePrecision(TPrecision precision) = 0; virtual bool writeVariablePrecision(TPrecision precision) = 0;
void writeFunctionParameters(const TIntermSequence &args); void writeFunctionParameters(const TFunction *func);
const TConstantUnion *writeConstantUnion(const TType &type, const TConstantUnion *pConstUnion); const TConstantUnion *writeConstantUnion(const TType &type, const TConstantUnion *pConstUnion);
void writeConstructorTriplet(Visit visit, const TType &type); void writeConstructorTriplet(Visit visit, const TType &type);
ImmutableString getTypeName(const TType &type); ImmutableString getTypeName(const TType &type);
@ -58,7 +58,7 @@ class TOutputGLSLBase : public TIntermTraverser
bool visitIfElse(Visit visit, TIntermIfElse *node) override; bool visitIfElse(Visit visit, TIntermIfElse *node) override;
bool visitSwitch(Visit visit, TIntermSwitch *node) override; bool visitSwitch(Visit visit, TIntermSwitch *node) override;
bool visitCase(Visit visit, TIntermCase *node) override; bool visitCase(Visit visit, TIntermCase *node) override;
bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override; void visitFunctionPrototype(TIntermFunctionPrototype *node) override;
bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *node) override; bool visitAggregate(Visit visit, TIntermAggregate *node) override;
bool visitBlock(Visit visit, TIntermBlock *node) override; bool visitBlock(Visit visit, TIntermBlock *node) override;
@ -76,9 +76,10 @@ class TOutputGLSLBase : public TIntermTraverser
// Used to translate function names for differences between ESSL and GLSL // Used to translate function names for differences between ESSL and GLSL
virtual ImmutableString translateTextureFunction(const ImmutableString &name) { return name; } virtual ImmutableString translateTextureFunction(const ImmutableString &name) { return name; }
void declareStruct(const TStructure *structure);
private: private:
bool structDeclared(const TStructure *structure) const; bool structDeclared(const TStructure *structure) const;
void declareStruct(const TStructure *structure);
void declareInterfaceBlockLayout(const TInterfaceBlock *interfaceBlock); void declareInterfaceBlockLayout(const TInterfaceBlock *interfaceBlock);
void declareInterfaceBlock(const TInterfaceBlock *interfaceBlock); void declareInterfaceBlock(const TInterfaceBlock *interfaceBlock);

View File

@ -15,17 +15,17 @@
#include "common/utilities.h" #include "common/utilities.h"
#include "compiler/translator/BuiltInFunctionEmulator.h" #include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h" #include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
#include "compiler/translator/FindSymbolNode.h"
#include "compiler/translator/ImageFunctionHLSL.h" #include "compiler/translator/ImageFunctionHLSL.h"
#include "compiler/translator/InfoSink.h" #include "compiler/translator/InfoSink.h"
#include "compiler/translator/NodeSearch.h"
#include "compiler/translator/RemoveSwitchFallThrough.h"
#include "compiler/translator/StructureHLSL.h" #include "compiler/translator/StructureHLSL.h"
#include "compiler/translator/TextureFunctionHLSL.h" #include "compiler/translator/TextureFunctionHLSL.h"
#include "compiler/translator/TranslatorHLSL.h" #include "compiler/translator/TranslatorHLSL.h"
#include "compiler/translator/UniformHLSL.h" #include "compiler/translator/UniformHLSL.h"
#include "compiler/translator/UtilsHLSL.h" #include "compiler/translator/UtilsHLSL.h"
#include "compiler/translator/blocklayout.h" #include "compiler/translator/blocklayout.h"
#include "compiler/translator/tree_ops/RemoveSwitchFallThrough.h"
#include "compiler/translator/tree_util/FindSymbolNode.h"
#include "compiler/translator/tree_util/NodeSearch.h"
#include "compiler/translator/util.h" #include "compiler/translator/util.h"
namespace sh namespace sh
@ -1756,35 +1756,30 @@ bool OutputHLSL::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition
out << TypeString(node->getFunctionPrototype()->getType()) << " "; out << TypeString(node->getFunctionPrototype()->getType()) << " ";
TIntermSequence *parameters = node->getFunctionPrototype()->getSequence(); const TFunction *func = node->getFunction();
if (node->getFunction()->isMain()) if (func->isMain())
{ {
out << "gl_main("; out << "gl_main(";
} }
else else
{ {
out << DecorateFunctionIfNeeded(node->getFunction()) << DisambiguateFunctionName(parameters) out << DecorateFunctionIfNeeded(func) << DisambiguateFunctionName(func)
<< (mOutputLod0Function ? "Lod0(" : "("); << (mOutputLod0Function ? "Lod0(" : "(");
} }
for (unsigned int i = 0; i < parameters->size(); i++) size_t paramCount = func->getParamCount();
for (unsigned int i = 0; i < paramCount; i++)
{ {
TIntermSymbol *symbol = (*parameters)[i]->getAsSymbolNode(); const TVariable *param = func->getParam(i);
ensureStructDefined(param->getType());
if (symbol) writeParameter(param, out);
if (i < paramCount - 1)
{ {
ensureStructDefined(symbol->getType()); out << ", ";
writeParameter(symbol, out);
if (i < parameters->size() - 1)
{
out << ", ";
}
} }
else
UNREACHABLE();
} }
out << ")\n"; out << ")\n";
@ -1871,32 +1866,29 @@ bool OutputHLSL::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclarat
return false; return false;
} }
bool OutputHLSL::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) void OutputHLSL::visitFunctionPrototype(TIntermFunctionPrototype *node)
{ {
TInfoSinkBase &out = getInfoSink(); TInfoSinkBase &out = getInfoSink();
ASSERT(visit == PreVisit);
size_t index = mCallDag.findIndex(node->getFunction()->uniqueId()); size_t index = mCallDag.findIndex(node->getFunction()->uniqueId());
// Skip the prototype if it is not implemented (and thus not used) // Skip the prototype if it is not implemented (and thus not used)
if (index == CallDAG::InvalidIndex) if (index == CallDAG::InvalidIndex)
{ {
return false; return;
} }
TIntermSequence *arguments = node->getSequence(); const TFunction *func = node->getFunction();
TString name = DecorateFunctionIfNeeded(node->getFunction()); TString name = DecorateFunctionIfNeeded(func);
out << TypeString(node->getType()) << " " << name << DisambiguateFunctionName(arguments) out << TypeString(node->getType()) << " " << name << DisambiguateFunctionName(func)
<< (mOutputLod0Function ? "Lod0(" : "("); << (mOutputLod0Function ? "Lod0(" : "(");
for (unsigned int i = 0; i < arguments->size(); i++) size_t paramCount = func->getParamCount();
for (unsigned int i = 0; i < paramCount; i++)
{ {
TIntermSymbol *symbol = (*arguments)[i]->getAsSymbolNode(); writeParameter(func->getParam(i), out);
ASSERT(symbol != nullptr);
writeParameter(symbol, out); if (i < paramCount - 1)
if (i < arguments->size() - 1)
{ {
out << ", "; out << ", ";
} }
@ -1912,8 +1904,6 @@ bool OutputHLSL::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *n
node->traverse(this); node->traverse(this);
mOutputLod0Function = false; mOutputLod0Function = false;
} }
return false;
} }
bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
@ -2128,6 +2118,24 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
ASSERT(node->getUseEmulatedFunction()); ASSERT(node->getUseEmulatedFunction());
writeEmulatedFunctionTriplet(out, visit, node->getOp()); writeEmulatedFunctionTriplet(out, visit, node->getOp());
break; break;
case EOpBarrier:
// barrier() is translated to GroupMemoryBarrierWithGroupSync(), which is the
// cheapest *WithGroupSync() function, without any functionality loss, but
// with the potential for severe performance loss.
outputTriplet(out, visit, "GroupMemoryBarrierWithGroupSync(", "", ")");
break;
case EOpMemoryBarrierShared:
outputTriplet(out, visit, "GroupMemoryBarrier(", "", ")");
break;
case EOpMemoryBarrierAtomicCounter:
case EOpMemoryBarrierBuffer:
case EOpMemoryBarrierImage:
outputTriplet(out, visit, "DeviceMemoryBarrier(", "", ")");
break;
case EOpGroupMemoryBarrier:
case EOpMemoryBarrier:
outputTriplet(out, visit, "AllMemoryBarrier(", "", ")");
break;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
@ -2642,22 +2650,13 @@ void OutputHLSL::outputLineDirective(TInfoSinkBase &out, int line)
} }
} }
void OutputHLSL::writeParameter(const TIntermSymbol *symbol, TInfoSinkBase &out) void OutputHLSL::writeParameter(const TVariable *param, TInfoSinkBase &out)
{ {
TQualifier qualifier = symbol->getQualifier(); const TType &type = param->getType();
const TType &type = symbol->getType(); TQualifier qualifier = type.getQualifier();
const TVariable &variable = symbol->variable();
TString nameStr;
if (variable.symbolType() == TString nameStr = DecorateVariableIfNeeded(*param);
SymbolType::Empty) // HLSL demands named arguments, also for prototypes ASSERT(nameStr != ""); // HLSL demands named arguments, also for prototypes
{
nameStr = "x" + str(mUniqueIndex++);
}
else
{
nameStr = DecorateVariableIfNeeded(variable);
}
if (IsSampler(type.getBasicType())) if (IsSampler(type.getBasicType()))
{ {

View File

@ -16,7 +16,7 @@
#include "compiler/translator/Compiler.h" #include "compiler/translator/Compiler.h"
#include "compiler/translator/FlagStd140Structs.h" #include "compiler/translator/FlagStd140Structs.h"
#include "compiler/translator/ImmutableString.h" #include "compiler/translator/ImmutableString.h"
#include "compiler/translator/IntermTraverse.h" #include "compiler/translator/tree_util/IntermTraverse.h"
class BuiltInFunctionEmulator; class BuiltInFunctionEmulator;
@ -93,7 +93,7 @@ class OutputHLSL : public TIntermTraverser
bool visitIfElse(Visit visit, TIntermIfElse *) override; bool visitIfElse(Visit visit, TIntermIfElse *) override;
bool visitSwitch(Visit visit, TIntermSwitch *) override; bool visitSwitch(Visit visit, TIntermSwitch *) override;
bool visitCase(Visit visit, TIntermCase *) override; bool visitCase(Visit visit, TIntermCase *) override;
bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override; void visitFunctionPrototype(TIntermFunctionPrototype *node) override;
bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *) override; bool visitAggregate(Visit visit, TIntermAggregate *) override;
bool visitBlock(Visit visit, TIntermBlock *node) override; bool visitBlock(Visit visit, TIntermBlock *node) override;
@ -112,7 +112,7 @@ class OutputHLSL : public TIntermTraverser
const char *inString, const char *inString,
const char *postString); const char *postString);
void outputLineDirective(TInfoSinkBase &out, int line); void outputLineDirective(TInfoSinkBase &out, int line);
void writeParameter(const TIntermSymbol *symbol, TInfoSinkBase &out); void writeParameter(const TVariable *param, TInfoSinkBase &out);
void outputConstructor(TInfoSinkBase &out, Visit visit, TIntermAggregate *node); void outputConstructor(TInfoSinkBase &out, Visit visit, TIntermAggregate *node);
const TConstantUnion *writeConstantUnion(TInfoSinkBase &out, const TConstantUnion *writeConstantUnion(TInfoSinkBase &out,

View File

@ -4,8 +4,8 @@
// found in the LICENSE file. // found in the LICENSE file.
// //
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/SymbolTable.h" #include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh namespace sh
{ {
@ -31,7 +31,10 @@ void OutputFunction(TInfoSinkBase &out, const char *str, const TFunction *func)
class TOutputTraverser : public TIntermTraverser class TOutputTraverser : public TIntermTraverser
{ {
public: public:
TOutputTraverser(TInfoSinkBase &out) : TIntermTraverser(true, false, false), mOut(out) {} TOutputTraverser(TInfoSinkBase &out)
: TIntermTraverser(true, false, false), mOut(out), mIndentDepth(0)
{
}
protected: protected:
void visitSymbol(TIntermSymbol *) override; void visitSymbol(TIntermSymbol *) override;
@ -43,7 +46,7 @@ class TOutputTraverser : public TIntermTraverser
bool visitIfElse(Visit visit, TIntermIfElse *node) override; bool visitIfElse(Visit visit, TIntermIfElse *node) override;
bool visitSwitch(Visit visit, TIntermSwitch *node) override; bool visitSwitch(Visit visit, TIntermSwitch *node) override;
bool visitCase(Visit visit, TIntermCase *node) override; bool visitCase(Visit visit, TIntermCase *node) override;
bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override; void visitFunctionPrototype(TIntermFunctionPrototype *node) override;
bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *) override; bool visitAggregate(Visit visit, TIntermAggregate *) override;
bool visitBlock(Visit visit, TIntermBlock *) override; bool visitBlock(Visit visit, TIntermBlock *) override;
@ -52,7 +55,10 @@ class TOutputTraverser : public TIntermTraverser
bool visitLoop(Visit visit, TIntermLoop *) override; bool visitLoop(Visit visit, TIntermLoop *) override;
bool visitBranch(Visit visit, TIntermBranch *) override; bool visitBranch(Visit visit, TIntermBranch *) override;
int getCurrentIndentDepth() const { return mIndentDepth + getCurrentTraversalDepth(); }
TInfoSinkBase &mOut; TInfoSinkBase &mOut;
int mIndentDepth;
}; };
// //
@ -79,7 +85,7 @@ void OutputTreeText(TInfoSinkBase &out, TIntermNode *node, const int depth)
void TOutputTraverser::visitSymbol(TIntermSymbol *node) void TOutputTraverser::visitSymbol(TIntermSymbol *node)
{ {
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
if (node->variable().symbolType() == SymbolType::Empty) if (node->variable().symbolType() == SymbolType::Empty)
{ {
@ -96,7 +102,7 @@ void TOutputTraverser::visitSymbol(TIntermSymbol *node)
bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node) bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node)
{ {
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "vector swizzle ("; mOut << "vector swizzle (";
node->writeOffsetsAsXYZW(&mOut); node->writeOffsetsAsXYZW(&mOut);
mOut << ")"; mOut << ")";
@ -108,7 +114,7 @@ bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node)
bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node) bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
{ {
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
switch (node->getOp()) switch (node->getOp())
{ {
@ -270,7 +276,7 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
TIntermConstantUnion *intermConstantUnion = node->getRight()->getAsConstantUnion(); TIntermConstantUnion *intermConstantUnion = node->getRight()->getAsConstantUnion();
ASSERT(intermConstantUnion); ASSERT(intermConstantUnion);
OutputTreeText(mOut, intermConstantUnion, mDepth + 1); OutputTreeText(mOut, intermConstantUnion, getCurrentIndentDepth() + 1);
// The following code finds the field name from the constant union // The following code finds the field name from the constant union
const TConstantUnion *constantUnion = intermConstantUnion->getConstantValue(); const TConstantUnion *constantUnion = intermConstantUnion->getConstantValue();
@ -294,7 +300,7 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node) bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
{ {
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
switch (node->getOp()) switch (node->getOp())
{ {
@ -348,32 +354,37 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
bool TOutputTraverser::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) bool TOutputTraverser::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
{ {
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "Function Definition:\n"; mOut << "Function Definition:\n";
mOut << "\n";
return true; return true;
} }
bool TOutputTraverser::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) bool TOutputTraverser::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node)
{ {
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "Invariant Declaration:\n"; mOut << "Invariant Declaration:\n";
return true; return true;
} }
bool TOutputTraverser::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) void TOutputTraverser::visitFunctionPrototype(TIntermFunctionPrototype *node)
{ {
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
OutputFunction(mOut, "Function Prototype", node->getFunction()); OutputFunction(mOut, "Function Prototype", node->getFunction());
mOut << " (" << node->getCompleteString() << ")"; mOut << " (" << node->getCompleteString() << ")";
mOut << "\n"; mOut << "\n";
size_t paramCount = node->getFunction()->getParamCount();
return true; for (size_t i = 0; i < paramCount; ++i)
{
const TVariable *param = node->getFunction()->getParam(i);
OutputTreeText(mOut, node, getCurrentIndentDepth() + 1);
mOut << "parameter: " << param->name() << " (" << param->getType().getCompleteString()
<< ")";
}
} }
bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
{ {
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
if (node->getOp() == EOpNull) if (node->getOp() == EOpNull)
{ {
@ -445,7 +456,7 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
bool TOutputTraverser::visitBlock(Visit visit, TIntermBlock *node) bool TOutputTraverser::visitBlock(Visit visit, TIntermBlock *node)
{ {
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "Code block\n"; mOut << "Code block\n";
return true; return true;
@ -453,7 +464,7 @@ bool TOutputTraverser::visitBlock(Visit visit, TIntermBlock *node)
bool TOutputTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node) bool TOutputTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node)
{ {
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "Declaration\n"; mOut << "Declaration\n";
return true; return true;
@ -461,18 +472,18 @@ bool TOutputTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node)
bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node) bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node)
{ {
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "Ternary selection"; mOut << "Ternary selection";
mOut << " (" << node->getCompleteString() << ")\n"; mOut << " (" << node->getCompleteString() << ")\n";
++mDepth; ++mIndentDepth;
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "Condition\n"; mOut << "Condition\n";
node->getCondition()->traverse(this); node->getCondition()->traverse(this);
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
if (node->getTrueExpression()) if (node->getTrueExpression())
{ {
mOut << "true case\n"; mOut << "true case\n";
@ -480,29 +491,29 @@ bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node)
} }
if (node->getFalseExpression()) if (node->getFalseExpression())
{ {
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "false case\n"; mOut << "false case\n";
node->getFalseExpression()->traverse(this); node->getFalseExpression()->traverse(this);
} }
--mDepth; --mIndentDepth;
return false; return false;
} }
bool TOutputTraverser::visitIfElse(Visit visit, TIntermIfElse *node) bool TOutputTraverser::visitIfElse(Visit visit, TIntermIfElse *node)
{ {
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "If test\n"; mOut << "If test\n";
++mDepth; ++mIndentDepth;
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "Condition\n"; mOut << "Condition\n";
node->getCondition()->traverse(this); node->getCondition()->traverse(this);
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
if (node->getTrueBlock()) if (node->getTrueBlock())
{ {
mOut << "true case\n"; mOut << "true case\n";
@ -515,19 +526,19 @@ bool TOutputTraverser::visitIfElse(Visit visit, TIntermIfElse *node)
if (node->getFalseBlock()) if (node->getFalseBlock())
{ {
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "false case\n"; mOut << "false case\n";
node->getFalseBlock()->traverse(this); node->getFalseBlock()->traverse(this);
} }
--mDepth; --mIndentDepth;
return false; return false;
} }
bool TOutputTraverser::visitSwitch(Visit visit, TIntermSwitch *node) bool TOutputTraverser::visitSwitch(Visit visit, TIntermSwitch *node)
{ {
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "Switch\n"; mOut << "Switch\n";
@ -536,7 +547,7 @@ bool TOutputTraverser::visitSwitch(Visit visit, TIntermSwitch *node)
bool TOutputTraverser::visitCase(Visit visit, TIntermCase *node) bool TOutputTraverser::visitCase(Visit visit, TIntermCase *node)
{ {
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
if (node->getCondition() == nullptr) if (node->getCondition() == nullptr)
{ {
@ -556,7 +567,7 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion *node)
for (size_t i = 0; i < size; i++) for (size_t i = 0; i < size; i++)
{ {
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
switch (node->getConstantValue()[i].getType()) switch (node->getConstantValue()[i].getType())
{ {
case EbtBool: case EbtBool:
@ -597,16 +608,16 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion *node)
bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop *node) bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop *node)
{ {
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "Loop with condition "; mOut << "Loop with condition ";
if (node->getType() == ELoopDoWhile) if (node->getType() == ELoopDoWhile)
mOut << "not "; mOut << "not ";
mOut << "tested first\n"; mOut << "tested first\n";
++mDepth; ++mIndentDepth;
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
if (node->getCondition()) if (node->getCondition())
{ {
mOut << "Loop Condition\n"; mOut << "Loop Condition\n";
@ -617,7 +628,7 @@ bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop *node)
mOut << "No loop condition\n"; mOut << "No loop condition\n";
} }
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
if (node->getBody()) if (node->getBody())
{ {
mOut << "Loop Body\n"; mOut << "Loop Body\n";
@ -630,19 +641,19 @@ bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop *node)
if (node->getExpression()) if (node->getExpression())
{ {
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "Loop Terminal Expression\n"; mOut << "Loop Terminal Expression\n";
node->getExpression()->traverse(this); node->getExpression()->traverse(this);
} }
--mDepth; --mIndentDepth;
return false; return false;
} }
bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node) bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node)
{ {
OutputTreeText(mOut, node, mDepth); OutputTreeText(mOut, node, getCurrentIndentDepth());
switch (node->getFlowOp()) switch (node->getFlowOp())
{ {
@ -666,9 +677,9 @@ bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node)
if (node->getExpression()) if (node->getExpression())
{ {
mOut << " with expression\n"; mOut << " with expression\n";
++mDepth; ++mIndentDepth;
node->getExpression()->traverse(this); node->getExpression()->traverse(this);
--mDepth; --mIndentDepth;
} }
else else
{ {

View File

@ -1,102 +0,0 @@
//
// Copyright 2017 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.
//
// ParamType:
// Helper type for built-in function emulator tables. Defines types for parameters.
#ifndef COMPILER_TRANSLATOR_PARAMTYPE_H_
#define COMPILER_TRANSLATOR_PARAMTYPE_H_
#include "common/angleutils.h"
#include "compiler/translator/BaseTypes.h"
namespace sh
{
enum class ParamType : uint8_t
{
Void,
Bool1,
Bool2,
Bool3,
Bool4,
Float1,
Float2,
Float3,
Float4,
Int1,
Int2,
Int3,
Int4,
Mat2,
Mat3,
Mat4,
Uint1,
Uint2,
Uint3,
Uint4,
Last,
};
struct ParamTypeInfo
{
ParamType self;
TBasicType basicType;
int primarySize;
int secondarySize;
};
constexpr ParamTypeInfo g_ParamTypeInfo[] = {
{ParamType::Void, EbtVoid, 1, 1}, {ParamType::Bool1, EbtBool, 1, 1},
{ParamType::Bool2, EbtBool, 2, 1}, {ParamType::Bool3, EbtBool, 3, 1},
{ParamType::Bool4, EbtBool, 4, 1}, {ParamType::Float1, EbtFloat, 1, 1},
{ParamType::Float2, EbtFloat, 2, 1}, {ParamType::Float3, EbtFloat, 3, 1},
{ParamType::Float4, EbtFloat, 4, 1}, {ParamType::Int1, EbtInt, 1, 1},
{ParamType::Int2, EbtInt, 2, 1}, {ParamType::Int3, EbtInt, 3, 1},
{ParamType::Int4, EbtInt, 4, 1}, {ParamType::Mat2, EbtFloat, 2, 2},
{ParamType::Mat3, EbtFloat, 3, 3}, {ParamType::Mat4, EbtFloat, 4, 4},
{ParamType::Uint1, EbtUInt, 1, 1}, {ParamType::Uint2, EbtUInt, 2, 1},
{ParamType::Uint3, EbtUInt, 3, 1}, {ParamType::Uint4, EbtUInt, 4, 1},
};
constexpr size_t ParamTypeIndex(ParamType paramType)
{
return static_cast<size_t>(paramType);
}
constexpr size_t NumParamTypes()
{
return ParamTypeIndex(ParamType::Last);
}
static_assert(ArraySize(g_ParamTypeInfo) == NumParamTypes(), "Invalid array size");
constexpr TBasicType GetBasicType(ParamType paramType)
{
return g_ParamTypeInfo[ParamTypeIndex(paramType)].basicType;
}
constexpr int GetPrimarySize(ParamType paramType)
{
return g_ParamTypeInfo[ParamTypeIndex(paramType)].primarySize;
}
constexpr int GetSecondarySize(ParamType paramType)
{
return g_ParamTypeInfo[ParamTypeIndex(paramType)].secondarySize;
}
constexpr bool SameParamType(ParamType paramType,
TBasicType basicType,
int primarySize,
int secondarySize)
{
return GetBasicType(paramType) == basicType && primarySize == GetPrimarySize(paramType) &&
secondarySize == GetSecondarySize(paramType);
}
} // namespace sh
#endif // COMPILER_TRANSLATOR_PARAMTYPE_H_

View File

@ -12,11 +12,12 @@
#include "common/mathutil.h" #include "common/mathutil.h"
#include "compiler/preprocessor/SourceLocation.h" #include "compiler/preprocessor/SourceLocation.h"
#include "compiler/translator/Declarator.h" #include "compiler/translator/Declarator.h"
#include "compiler/translator/IntermNode_util.h" #include "compiler/translator/ParseContext_autogen.h"
#include "compiler/translator/StaticType.h" #include "compiler/translator/StaticType.h"
#include "compiler/translator/ValidateGlobalInitializer.h" #include "compiler/translator/ValidateGlobalInitializer.h"
#include "compiler/translator/ValidateSwitch.h" #include "compiler/translator/ValidateSwitch.h"
#include "compiler/translator/glslang.h" #include "compiler/translator/glslang.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/util.h" #include "compiler/translator/util.h"
namespace sh namespace sh
@ -33,33 +34,6 @@ namespace
const int kWebGLMaxStructNesting = 4; const int kWebGLMaxStructNesting = 4;
constexpr const ImmutableString kTexelFetchOffsetName("texelFetchOffsetName");
constexpr const ImmutableString kTextureLodOffsetName("textureLodOffset");
constexpr const ImmutableString kTextureProjLodOffsetName("textureProjLodOffset");
constexpr const ImmutableString kTextureGradOffsetName("textureGradOffset");
constexpr const ImmutableString kTextureProjGradOffsetName("textureProjGradOffset");
constexpr const ImmutableString kTextureOffsetName("textureOffset");
constexpr const ImmutableString kTextureProjOffsetName("textureProjOffset");
constexpr const ImmutableString kTextureGatherName("textureGather");
constexpr const ImmutableString kTextureGatherOffsetName("textureGatherOffset");
constexpr const std::array<ImmutableString, 8> kAtomicBuiltin = {
{ImmutableString("atomicAdd"), ImmutableString("atomicMin"), ImmutableString("atomicMax"),
ImmutableString("atomicAnd"), ImmutableString("atomicOr"), ImmutableString("atomicXor"),
ImmutableString("atomicExchange"), ImmutableString("atomicCompSwap")}};
bool IsAtomicBuiltin(const ImmutableString &name)
{
for (size_t i = 0; i < kAtomicBuiltin.size(); ++i)
{
if (name == kAtomicBuiltin[i])
{
return true;
}
}
return false;
}
bool ContainsSampler(const TStructure *structType); bool ContainsSampler(const TStructure *structType);
bool ContainsSampler(const TType &type) bool ContainsSampler(const TType &type)
@ -222,9 +196,6 @@ TParseContext::TParseContext(TSymbolTable &symt,
resources.WEBGL_debug_shader_precision == 1), resources.WEBGL_debug_shader_precision == 1),
mPreprocessor(mDiagnostics, &mDirectiveHandler, pp::PreprocessorSettings()), mPreprocessor(mDiagnostics, &mDirectiveHandler, pp::PreprocessorSettings()),
mScanner(nullptr), mScanner(nullptr),
mUsesFragData(false),
mUsesFragColor(false),
mUsesSecondaryOutputs(false),
mMinProgramTexelOffset(resources.MinProgramTexelOffset), mMinProgramTexelOffset(resources.MinProgramTexelOffset),
mMaxProgramTexelOffset(resources.MaxProgramTexelOffset), mMaxProgramTexelOffset(resources.MaxProgramTexelOffset),
mMinProgramTextureGatherOffset(resources.MinProgramTextureGatherOffset), mMinProgramTextureGatherOffset(resources.MinProgramTextureGatherOffset),
@ -245,8 +216,7 @@ TParseContext::TParseContext(TSymbolTable &symt,
mGeometryShaderInvocations(0), mGeometryShaderInvocations(0),
mGeometryShaderMaxVertices(-1), mGeometryShaderMaxVertices(-1),
mMaxGeometryShaderInvocations(resources.MaxGeometryShaderInvocations), mMaxGeometryShaderInvocations(resources.MaxGeometryShaderInvocations),
mMaxGeometryShaderMaxVertices(resources.MaxGeometryOutputVertices), mMaxGeometryShaderMaxVertices(resources.MaxGeometryOutputVertices)
mGlInVariableWithArraySize(nullptr)
{ {
} }
@ -469,14 +439,41 @@ void TParseContext::checkPrecisionSpecified(const TSourceLoc &line,
} }
} }
void TParseContext::markStaticReadIfSymbol(TIntermNode *node)
{
TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
if (swizzleNode)
{
markStaticReadIfSymbol(swizzleNode->getOperand());
return;
}
TIntermBinary *binaryNode = node->getAsBinaryNode();
if (binaryNode)
{
switch (binaryNode->getOp())
{
case EOpIndexDirect:
case EOpIndexIndirect:
case EOpIndexDirectStruct:
case EOpIndexDirectInterfaceBlock:
markStaticReadIfSymbol(binaryNode->getLeft());
return;
default:
return;
}
}
TIntermSymbol *symbolNode = node->getAsSymbolNode();
if (symbolNode)
{
symbolTable.markStaticRead(symbolNode->variable());
}
}
// Both test and if necessary, spit out an error, to see if the node is really // Both test and if necessary, spit out an error, to see if the node is really
// an l-value that can be operated on this way. // an l-value that can be operated on this way.
bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node) bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node)
{ {
TIntermSymbol *symNode = node->getAsSymbolNode();
TIntermBinary *binaryNode = node->getAsBinaryNode();
TIntermSwizzle *swizzleNode = node->getAsSwizzleNode(); TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
if (swizzleNode) if (swizzleNode)
{ {
bool ok = checkCanBeLValue(line, op, swizzleNode->getOperand()); bool ok = checkCanBeLValue(line, op, swizzleNode->getOperand());
@ -488,6 +485,7 @@ bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIn
return ok; return ok;
} }
TIntermBinary *binaryNode = node->getAsBinaryNode();
if (binaryNode) if (binaryNode)
{ {
switch (binaryNode->getOp()) switch (binaryNode->getOp())
@ -608,40 +606,32 @@ bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIn
} }
} }
if (message.empty() && binaryNode == 0 && symNode == 0) ASSERT(binaryNode == nullptr && swizzleNode == nullptr);
TIntermSymbol *symNode = node->getAsSymbolNode();
if (message.empty() && symNode != nullptr)
{ {
error(line, "l-value required", op); symbolTable.markStaticWrite(symNode->variable());
return false;
}
//
// Everything else is okay, no error.
//
if (message.empty())
return true; return true;
//
// If we get here, we have an error and a message.
//
if (symNode)
{
// Symbol inside an expression can't be nameless.
ASSERT(symNode->variable().symbolType() != SymbolType::Empty);
const ImmutableString &symbol = symNode->getName();
std::stringstream reasonStream;
reasonStream << "l-value required (" << message << " \"" << symbol << "\")";
std::string reason = reasonStream.str();
error(line, reason.c_str(), op);
} }
else
std::stringstream reasonStream;
reasonStream << "l-value required";
if (!message.empty())
{ {
std::stringstream reasonStream; if (symNode)
reasonStream << "l-value required (" << message << ")"; {
std::string reason = reasonStream.str(); // Symbol inside an expression can't be nameless.
error(line, reason.c_str(), op); ASSERT(symNode->variable().symbolType() != SymbolType::Empty);
const ImmutableString &symbol = symNode->getName();
reasonStream << " (" << message << " \"" << symbol << "\")";
}
else
{
reasonStream << " (" << message << ")";
}
} }
std::string reason = reasonStream.str();
error(line, reason.c_str(), op);
return false; return false;
} }
@ -726,6 +716,7 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
for (TIntermNode *arg : arguments) for (TIntermNode *arg : arguments)
{ {
markStaticReadIfSymbol(arg);
const TIntermTyped *argTyped = arg->getAsTyped(); const TIntermTyped *argTyped = arg->getAsTyped();
ASSERT(argTyped != nullptr); ASSERT(argTyped != nullptr);
if (type.getBasicType() != EbtStruct && IsOpaqueType(argTyped->getBasicType())) if (type.getBasicType() != EbtStruct && IsOpaqueType(argTyped->getBasicType()))
@ -1169,7 +1160,7 @@ bool TParseContext::declareVariable(const TSourceLoc &line,
if (needsReservedCheck && !checkIsNotReserved(line, identifier)) if (needsReservedCheck && !checkIsNotReserved(line, identifier))
return false; return false;
if (!symbolTable.declareVariable(*variable)) if (!symbolTable.declare(*variable))
{ {
error(line, "redefinition", identifier); error(line, "redefinition", identifier);
return false; return false;
@ -1700,17 +1691,22 @@ void TParseContext::functionCallRValueLValueErrorCheck(const TFunction *fnCandid
{ {
for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
{ {
TQualifier qual = fnCandidate->getParam(i).type->getQualifier(); TQualifier qual = fnCandidate->getParam(i)->getType().getQualifier();
TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped(); TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
if (!IsImage(argument->getBasicType()) && (IsQualifierUnspecified(qual) || qual == EvqIn || bool argumentIsRead = (IsQualifierUnspecified(qual) || qual == EvqIn || qual == EvqInOut ||
qual == EvqInOut || qual == EvqConstReadOnly)) qual == EvqConstReadOnly);
if (argumentIsRead)
{ {
if (argument->getMemoryQualifier().writeonly) markStaticReadIfSymbol(argument);
if (!IsImage(argument->getBasicType()))
{ {
error(argument->getLine(), if (argument->getMemoryQualifier().writeonly)
"Writeonly value cannot be passed for 'in' or 'inout' parameters.", {
fnCall->functionName()); error(argument->getLine(),
return; "Writeonly value cannot be passed for 'in' or 'inout' parameters.",
fnCall->functionName());
return;
}
} }
} }
if (qual == EvqOut || qual == EvqInOut) if (qual == EvqOut || qual == EvqInOut)
@ -1831,40 +1827,9 @@ const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
checkCanUseExtension(location, variable->extension()); checkCanUseExtension(location, variable->extension());
} }
// Reject shaders using both gl_FragData and gl_FragColor
TQualifier qualifier = variable->getType().getQualifier();
if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT)
{
mUsesFragData = true;
}
else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT)
{
mUsesFragColor = true;
}
if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT)
{
mUsesSecondaryOutputs = true;
}
// This validation is not quite correct - it's only an error to write to
// both FragData and FragColor. For simplicity, and because users shouldn't
// be rewarded for reading from undefined varaibles, return an error
// if they are both referenced, rather than assigned.
if (mUsesFragData && mUsesFragColor)
{
const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
if (mUsesSecondaryOutputs)
{
errorMessage =
"cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
" and (gl_FragColor, gl_SecondaryFragColorEXT)";
}
error(location, errorMessage, name);
}
// GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared && if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
qualifier == EvqWorkGroupSize) variable->getType().getQualifier() == EvqWorkGroupSize)
{ {
error(location, error(location,
"It is an error to use gl_WorkGroupSize before declaring the local group size", "It is an error to use gl_WorkGroupSize before declaring the local group size",
@ -1915,8 +1880,8 @@ TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
else if ((mGeometryShaderInputPrimitiveType != EptUndefined) && else if ((mGeometryShaderInputPrimitiveType != EptUndefined) &&
(variableType.getQualifier() == EvqPerVertexIn)) (variableType.getQualifier() == EvqPerVertexIn))
{ {
ASSERT(mGlInVariableWithArraySize != nullptr); ASSERT(symbolTable.getGlInVariableWithArraySize() != nullptr);
node = new TIntermSymbol(mGlInVariableWithArraySize); node = new TIntermSymbol(symbolTable.getGlInVariableWithArraySize());
} }
else else
{ {
@ -2031,6 +1996,7 @@ bool TParseContext::executeInitializer(const TSourceLoc &line,
} }
*initNode = new TIntermBinary(EOpInitialize, intermSymbol, initializer); *initNode = new TIntermBinary(EOpInitialize, intermSymbol, initializer);
markStaticReadIfSymbol(initializer);
(*initNode)->setLine(line); (*initNode)->setLine(line);
return true; return true;
} }
@ -2073,8 +2039,19 @@ TIntermNode *TParseContext::addLoop(TLoopType type,
TIntermTyped *typedCond = nullptr; TIntermTyped *typedCond = nullptr;
if (cond) if (cond)
{ {
markStaticReadIfSymbol(cond);
typedCond = cond->getAsTyped(); typedCond = cond->getAsTyped();
} }
if (expr)
{
markStaticReadIfSymbol(expr);
}
// In case the loop body was not parsed as a block and contains a statement that simply refers
// to a variable, we need to mark it as statically used.
if (body)
{
markStaticReadIfSymbol(body);
}
if (cond == nullptr || typedCond) if (cond == nullptr || typedCond)
{ {
if (type == ELoopDoWhile) if (type == ELoopDoWhile)
@ -2121,6 +2098,16 @@ TIntermNode *TParseContext::addIfElse(TIntermTyped *cond,
const TSourceLoc &loc) const TSourceLoc &loc)
{ {
bool isScalarBool = checkIsScalarBool(loc, cond); bool isScalarBool = checkIsScalarBool(loc, cond);
// In case the conditional statements were not parsed as blocks and contain a statement that
// simply refers to a variable, we need to mark them as statically used.
if (code.node1)
{
markStaticReadIfSymbol(code.node1);
}
if (code.node2)
{
markStaticReadIfSymbol(code.node2);
}
// For compile time constant conditions, prune the code now. // For compile time constant conditions, prune the code now.
if (isScalarBool && cond->getAsConstantUnion()) if (isScalarBool && cond->getAsConstantUnion())
@ -2136,6 +2123,7 @@ TIntermNode *TParseContext::addIfElse(TIntermTyped *cond,
} }
TIntermIfElse *node = new TIntermIfElse(cond, EnsureBlock(code.node1), EnsureBlock(code.node2)); TIntermIfElse *node = new TIntermIfElse(cond, EnsureBlock(code.node1), EnsureBlock(code.node2));
markStaticReadIfSymbol(cond);
node->setLine(loc); node->setLine(loc);
return node; return node;
@ -2383,9 +2371,9 @@ void TParseContext::checkGeometryShaderInputAndSetArraySize(const TSourceLoc &lo
// input primitive declaration. // input primitive declaration.
if (mGeometryShaderInputPrimitiveType != EptUndefined) if (mGeometryShaderInputPrimitiveType != EptUndefined)
{ {
ASSERT(mGlInVariableWithArraySize != nullptr); ASSERT(symbolTable.getGlInVariableWithArraySize() != nullptr);
type->sizeOutermostUnsizedArray( type->sizeOutermostUnsizedArray(
mGlInVariableWithArraySize->getType().getOutermostArraySize()); symbolTable.getGlInVariableWithArraySize()->getType().getOutermostArraySize());
} }
else else
{ {
@ -2855,17 +2843,7 @@ bool TParseContext::checkPrimitiveTypeMatchesTypeQualifier(const TTypeQualifier
void TParseContext::setGeometryShaderInputArraySize(unsigned int inputArraySize, void TParseContext::setGeometryShaderInputArraySize(unsigned int inputArraySize,
const TSourceLoc &line) const TSourceLoc &line)
{ {
if (mGlInVariableWithArraySize == nullptr) if (!symbolTable.setGlInArraySize(inputArraySize))
{
const TSymbol *glPerVertex = symbolTable.findBuiltIn(ImmutableString("gl_PerVertex"), 310);
const TInterfaceBlock *glPerVertexBlock = static_cast<const TInterfaceBlock *>(glPerVertex);
TType *glInType = new TType(glPerVertexBlock, EvqPerVertexIn, TLayoutQualifier::Create());
glInType->makeArray(inputArraySize);
mGlInVariableWithArraySize =
new TVariable(&symbolTable, ImmutableString("gl_in"), glInType, SymbolType::BuiltIn,
TExtension::EXT_geometry_shader);
}
else if (mGlInVariableWithArraySize->getType().getOutermostArraySize() != inputArraySize)
{ {
error(line, error(line,
"Array size or input primitive declaration doesn't match the size of earlier sized " "Array size or input primitive declaration doesn't match the size of earlier sized "
@ -3180,47 +3158,31 @@ TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
for (size_t i = 0; i < function.getParamCount(); i++) for (size_t i = 0; i < function.getParamCount(); i++)
{ {
const TConstParameter &param = function.getParam(i); const TVariable *param = function.getParam(i);
TIntermSymbol *symbol = nullptr;
// If the parameter has no name, it's not an error, just don't add it to symbol table (could // If the parameter has no name, it's not an error, just don't add it to symbol table (could
// be used for unused args). // be used for unused args).
if (param.name != nullptr) if (param->symbolType() != SymbolType::Empty)
{ {
TVariable *variable =
new TVariable(&symbolTable, param.name, param.type, SymbolType::UserDefined);
symbol = new TIntermSymbol(variable);
// Insert the parameter in the symbol table.
if (insertParametersToSymbolTable) if (insertParametersToSymbolTable)
{ {
if (!symbolTable.declareVariable(variable)) if (!symbolTable.declare(const_cast<TVariable *>(param)))
{ {
error(location, "redefinition", param.name); error(location, "redefinition", param->name());
} }
} }
// Unsized type of a named parameter should have already been checked and sanitized. // Unsized type of a named parameter should have already been checked and sanitized.
ASSERT(!param.type->isUnsizedArray()); ASSERT(!param->getType().isUnsizedArray());
} }
else else
{ {
if (param.type->isUnsizedArray()) if (param->getType().isUnsizedArray())
{ {
error(location, "function parameter array must be sized at compile time", "[]"); error(location, "function parameter array must be sized at compile time", "[]");
// We don't need to size the arrays since the parameter is unnamed and hence // We don't need to size the arrays since the parameter is unnamed and hence
// inaccessible. // inaccessible.
} }
} }
if (!symbol)
{
// The parameter had no name or declaring the symbol failed - either way, add a nameless
// symbol.
TVariable *emptyVariable =
new TVariable(&symbolTable, ImmutableString(""), param.type, SymbolType::Empty);
symbol = new TIntermSymbol(emptyVariable);
}
symbol->setLine(location);
prototype->appendParameter(symbol);
} }
return prototype; return prototype;
} }
@ -3313,8 +3275,8 @@ TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TF
for (size_t i = 0u; i < function->getParamCount(); ++i) for (size_t i = 0u; i < function->getParamCount(); ++i)
{ {
auto &param = function->getParam(i); const TVariable *param = function->getParam(i);
if (param.type->isStructSpecifier()) if (param->getType().isStructSpecifier())
{ {
// ESSL 3.00.6 section 12.10. // ESSL 3.00.6 section 12.10.
error(location, "Function parameter type cannot be a structure definition", error(location, "Function parameter type cannot be a structure definition",
@ -3360,12 +3322,12 @@ TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TF
} }
for (size_t i = 0; i < prevDec->getParamCount(); ++i) for (size_t i = 0; i < prevDec->getParamCount(); ++i)
{ {
if (prevDec->getParam(i).type->getQualifier() != if (prevDec->getParam(i)->getType().getQualifier() !=
function->getParam(i).type->getQualifier()) function->getParam(i)->getType().getQualifier())
{ {
error(location, error(location,
"function must have the same parameter qualifiers in all of its declarations", "function must have the same parameter qualifiers in all of its declarations",
function->getParam(i).type->getQualifierString()); function->getParam(i)->getType().getQualifierString());
} }
} }
} }
@ -3792,7 +3754,7 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
TInterfaceBlock *interfaceBlock = new TInterfaceBlock( TInterfaceBlock *interfaceBlock = new TInterfaceBlock(
&symbolTable, blockName, fieldList, blockLayoutQualifier, SymbolType::UserDefined); &symbolTable, blockName, fieldList, blockLayoutQualifier, SymbolType::UserDefined);
if (!symbolTable.declareInterfaceBlock(interfaceBlock)) if (!symbolTable.declare(interfaceBlock))
{ {
error(nameLine, "redefinition of an interface block name", blockName); error(nameLine, "redefinition of an interface block name", blockName);
} }
@ -3826,7 +3788,7 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
TVariable *fieldVariable = TVariable *fieldVariable =
new TVariable(&symbolTable, field->name(), fieldType, SymbolType::UserDefined); new TVariable(&symbolTable, field->name(), fieldType, SymbolType::UserDefined);
if (!symbolTable.declareVariable(fieldVariable)) if (!symbolTable.declare(fieldVariable))
{ {
error(field->line(), "redefinition of an interface block member name", error(field->line(), "redefinition of an interface block member name",
field->name()); field->name());
@ -3838,7 +3800,7 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
checkIsNotReserved(instanceLine, instanceName); checkIsNotReserved(instanceLine, instanceName);
// add a symbol for this interface block // add a symbol for this interface block
if (!symbolTable.declareVariable(instanceVariable)) if (!symbolTable.declare(instanceVariable))
{ {
error(instanceLine, "redefinition of an interface block instance name", instanceName); error(instanceLine, "redefinition of an interface block instance name", instanceName);
} }
@ -4063,6 +4025,7 @@ TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
} }
} }
markStaticReadIfSymbol(indexExpression);
TIntermBinary *node = new TIntermBinary(EOpIndexIndirect, baseExpression, indexExpression); TIntermBinary *node = new TIntermBinary(EOpIndexIndirect, baseExpression, indexExpression);
node->setLine(location); node->setLine(location);
// Indirect indexing can never be constant folded. // Indirect indexing can never be constant folded.
@ -4778,7 +4741,7 @@ TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
if (structSymbolType != SymbolType::Empty) if (structSymbolType != SymbolType::Empty)
{ {
checkIsNotReserved(nameLine, structName); checkIsNotReserved(nameLine, structName);
if (!symbolTable.declareStructType(structure)) if (!symbolTable.declare(structure))
{ {
error(nameLine, "redefinition of a struct", structName); error(nameLine, "redefinition of a struct", structName);
} }
@ -4840,12 +4803,13 @@ TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
} }
ASSERT(statementList); ASSERT(statementList);
if (!ValidateSwitchStatementList(switchType, mShaderVersion, mDiagnostics, statementList, loc)) if (!ValidateSwitchStatementList(switchType, mDiagnostics, statementList, loc))
{ {
ASSERT(mDiagnostics->numErrors() > 0); ASSERT(mDiagnostics->numErrors() > 0);
return nullptr; return nullptr;
} }
markStaticReadIfSymbol(init);
TIntermSwitch *node = new TIntermSwitch(init, statementList); TIntermSwitch *node = new TIntermSwitch(init, statementList);
node->setLine(loc); node->setLine(loc);
return node; return node;
@ -4895,7 +4859,8 @@ TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
TIntermTyped *TParseContext::createUnaryMath(TOperator op, TIntermTyped *TParseContext::createUnaryMath(TOperator op,
TIntermTyped *child, TIntermTyped *child,
const TSourceLoc &loc) const TSourceLoc &loc,
const TFunction *func)
{ {
ASSERT(child != nullptr); ASSERT(child != nullptr);
@ -4942,7 +4907,8 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op,
return nullptr; return nullptr;
} }
TIntermUnary *node = new TIntermUnary(op, child); markStaticReadIfSymbol(child);
TIntermUnary *node = new TIntermUnary(op, child, func);
node->setLine(loc); node->setLine(loc);
return node->fold(mDiagnostics); return node->fold(mDiagnostics);
@ -4951,7 +4917,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op,
TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc) TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
{ {
ASSERT(op != EOpNull); ASSERT(op != EOpNull);
TIntermTyped *node = createUnaryMath(op, child, loc); TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
if (node == nullptr) if (node == nullptr)
{ {
return child; return child;
@ -5345,6 +5311,9 @@ TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
} }
TIntermBinary *node = new TIntermBinary(op, left, right); TIntermBinary *node = new TIntermBinary(op, left, right);
ASSERT(op != EOpAssign);
markStaticReadIfSymbol(left);
markStaticReadIfSymbol(right);
node->setLine(loc); node->setLine(loc);
return expressionOrFoldedResult(node); return expressionOrFoldedResult(node);
} }
@ -5380,41 +5349,39 @@ TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
return node; return node;
} }
TIntermBinary *TParseContext::createAssign(TOperator op,
TIntermTyped *left,
TIntermTyped *right,
const TSourceLoc &loc)
{
if (binaryOpCommonCheck(op, left, right, loc))
{
if (op == EOpMulAssign)
{
op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
{
return nullptr;
}
}
TIntermBinary *node = new TIntermBinary(op, left, right);
node->setLine(loc);
return node;
}
return nullptr;
}
TIntermTyped *TParseContext::addAssign(TOperator op, TIntermTyped *TParseContext::addAssign(TOperator op,
TIntermTyped *left, TIntermTyped *left,
TIntermTyped *right, TIntermTyped *right,
const TSourceLoc &loc) const TSourceLoc &loc)
{ {
checkCanBeLValue(loc, "assign", left); checkCanBeLValue(loc, "assign", left);
TIntermTyped *node = createAssign(op, left, right, loc); TIntermBinary *node = nullptr;
if (binaryOpCommonCheck(op, left, right, loc))
{
if (op == EOpMulAssign)
{
op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
if (isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
{
node = new TIntermBinary(op, left, right);
}
}
else
{
node = new TIntermBinary(op, left, right);
}
}
if (node == nullptr) if (node == nullptr)
{ {
assignError(loc, "assign", left->getCompleteString(), right->getCompleteString()); assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
return left; return left;
} }
if (op != EOpAssign)
{
markStaticReadIfSymbol(left);
}
markStaticReadIfSymbol(right);
node->setLine(loc);
return node; return node;
} }
@ -5435,6 +5402,9 @@ TIntermTyped *TParseContext::addComma(TIntermTyped *left,
} }
TIntermBinary *commaNode = TIntermBinary::CreateComma(left, right, mShaderVersion); TIntermBinary *commaNode = TIntermBinary::CreateComma(left, right, mShaderVersion);
markStaticReadIfSymbol(left);
markStaticReadIfSymbol(right);
commaNode->setLine(loc);
return expressionOrFoldedResult(commaNode); return expressionOrFoldedResult(commaNode);
} }
@ -5480,6 +5450,7 @@ TIntermBranch *TParseContext::addBranch(TOperator op,
{ {
if (expression != nullptr) if (expression != nullptr)
{ {
markStaticReadIfSymbol(expression);
ASSERT(op == EOpReturn); ASSERT(op == EOpReturn);
mFunctionReturnsValue = true; mFunctionReturnsValue = true;
if (mCurrentFunctionType->getBasicType() == EbtVoid) if (mCurrentFunctionType->getBasicType() == EbtVoid)
@ -5496,14 +5467,22 @@ TIntermBranch *TParseContext::addBranch(TOperator op,
return node; return node;
} }
void TParseContext::appendStatement(TIntermBlock *block, TIntermNode *statement)
{
if (statement != nullptr)
{
markStaticReadIfSymbol(statement);
block->appendStatement(statement);
}
}
void TParseContext::checkTextureGather(TIntermAggregate *functionCall) void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
{ {
ASSERT(functionCall->getOp() == EOpCallBuiltInFunction); ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
const ImmutableString &name = functionCall->getFunction()->name(); const TFunction *func = functionCall->getFunction();
bool isTextureGather = name == kTextureGatherName; if (BuiltInGroup::isTextureGather(func))
bool isTextureGatherOffset = name == kTextureGatherOffsetName;
if (isTextureGather || isTextureGatherOffset)
{ {
bool isTextureGatherOffset = BuiltInGroup::isTextureGatherOffset(func);
TIntermNode *componentNode = nullptr; TIntermNode *componentNode = nullptr;
TIntermSequence *arguments = functionCall->getSequence(); TIntermSequence *arguments = functionCall->getSequence();
ASSERT(arguments->size() >= 2u && arguments->size() <= 4u); ASSERT(arguments->size() >= 2u && arguments->size() <= 4u);
@ -5517,7 +5496,7 @@ void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
case EbtSampler2DArray: case EbtSampler2DArray:
case EbtISampler2DArray: case EbtISampler2DArray:
case EbtUSampler2DArray: case EbtUSampler2DArray:
if ((isTextureGather && arguments->size() == 3u) || if ((!isTextureGatherOffset && arguments->size() == 3u) ||
(isTextureGatherOffset && arguments->size() == 4u)) (isTextureGatherOffset && arguments->size() == 4u))
{ {
componentNode = arguments->back(); componentNode = arguments->back();
@ -5547,14 +5526,15 @@ void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
if (componentNode->getAsTyped()->getQualifier() != EvqConst || !componentConstantUnion) if (componentNode->getAsTyped()->getQualifier() != EvqConst || !componentConstantUnion)
{ {
error(functionCall->getLine(), "Texture component must be a constant expression", error(functionCall->getLine(), "Texture component must be a constant expression",
name); func->name());
} }
else else
{ {
int component = componentConstantUnion->getIConst(0); int component = componentConstantUnion->getIConst(0);
if (component < 0 || component > 3) if (component < 0 || component > 3)
{ {
error(functionCall->getLine(), "Component must be in the range [0;3]", name); error(functionCall->getLine(), "Component must be in the range [0;3]",
func->name());
} }
} }
} }
@ -5564,23 +5544,21 @@ void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall) void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
{ {
ASSERT(functionCall->getOp() == EOpCallBuiltInFunction); ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
const ImmutableString &name = functionCall->getFunction()->name(); const TFunction *func = functionCall->getFunction();
TIntermNode *offset = nullptr; TIntermNode *offset = nullptr;
TIntermSequence *arguments = functionCall->getSequence(); TIntermSequence *arguments = functionCall->getSequence();
bool useTextureGatherOffsetConstraints = false; bool useTextureGatherOffsetConstraints = false;
if (name == kTexelFetchOffsetName || name == kTextureLodOffsetName || if (BuiltInGroup::isTextureOffsetNoBias(func))
name == kTextureProjLodOffsetName || name == kTextureGradOffsetName ||
name == kTextureProjGradOffsetName)
{ {
offset = arguments->back(); offset = arguments->back();
} }
else if (name == kTextureOffsetName || name == kTextureProjOffsetName) else if (BuiltInGroup::isTextureOffsetBias(func))
{ {
// A bias parameter might follow the offset parameter. // A bias parameter follows the offset parameter.
ASSERT(arguments->size() >= 3); ASSERT(arguments->size() >= 3);
offset = (*arguments)[2]; offset = (*arguments)[2];
} }
else if (name == kTextureGatherOffsetName) else if (BuiltInGroup::isTextureGatherOffset(func))
{ {
ASSERT(arguments->size() >= 3u); ASSERT(arguments->size() >= 3u);
const TIntermTyped *sampler = arguments->front()->getAsTyped(); const TIntermTyped *sampler = arguments->front()->getAsTyped();
@ -5610,7 +5588,8 @@ void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion(); TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion) if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
{ {
error(functionCall->getLine(), "Texture offset must be a constant expression", name); error(functionCall->getLine(), "Texture offset must be a constant expression",
func->name());
} }
else else
{ {
@ -5640,8 +5619,8 @@ void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
void TParseContext::checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall) void TParseContext::checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall)
{ {
ASSERT(functionCall->getOp() == EOpCallBuiltInFunction); ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
const ImmutableString &functionName = functionCall->getFunction()->name(); const TFunction *func = functionCall->getFunction();
if (IsAtomicBuiltin(functionName)) if (BuiltInGroup::isAtomicMemory(func))
{ {
TIntermSequence *arguments = functionCall->getSequence(); TIntermSequence *arguments = functionCall->getSequence();
TIntermTyped *memNode = (*arguments)[0]->getAsTyped(); TIntermTyped *memNode = (*arguments)[0]->getAsTyped();
@ -5663,7 +5642,7 @@ void TParseContext::checkAtomicMemoryBuiltinFunctions(TIntermAggregate *function
error(memNode->getLine(), error(memNode->getLine(),
"The value passed to the mem argument of an atomic memory function does not " "The value passed to the mem argument of an atomic memory function does not "
"correspond to a buffer or shared variable.", "correspond to a buffer or shared variable.",
functionName); func->name());
} }
} }
@ -5672,15 +5651,16 @@ void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *
{ {
ASSERT(functionCall->getOp() == EOpCallBuiltInFunction); ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
if (functionCall->getFunction()->isImageFunction()) const TFunction *func = functionCall->getFunction();
if (BuiltInGroup::isImage(func))
{ {
const ImmutableString &name = functionCall->getFunction()->name();
TIntermSequence *arguments = functionCall->getSequence(); TIntermSequence *arguments = functionCall->getSequence();
TIntermTyped *imageNode = (*arguments)[0]->getAsTyped(); TIntermTyped *imageNode = (*arguments)[0]->getAsTyped();
const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier(); const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier();
if (strcmp(name.data() + 5u, "Store") == 0) if (BuiltInGroup::isImageStore(func))
{ {
if (memoryQualifier.readonly) if (memoryQualifier.readonly)
{ {
@ -5689,7 +5669,7 @@ void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *
GetImageArgumentToken(imageNode)); GetImageArgumentToken(imageNode));
} }
} }
else if (strcmp(name.data() + 5u, "Load") == 0) else if (BuiltInGroup::isImageLoad(func))
{ {
if (memoryQualifier.writeonly) if (memoryQualifier.writeonly)
{ {
@ -5716,7 +5696,7 @@ void TParseContext::checkImageMemoryAccessForUserDefinedFunctions(
{ {
TIntermTyped *typedArgument = arguments[i]->getAsTyped(); TIntermTyped *typedArgument = arguments[i]->getAsTyped();
const TType &functionArgumentType = typedArgument->getType(); const TType &functionArgumentType = typedArgument->getType();
const TType &functionParameterType = *functionDefinition->getParam(i).type; const TType &functionParameterType = functionDefinition->getParam(i)->getType();
ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType()); ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType());
if (IsImage(functionArgumentType.getBasicType())) if (IsImage(functionArgumentType.getBasicType()))
@ -5800,7 +5780,7 @@ TIntermTyped *TParseContext::addMethod(TFunctionLookup *fnCall, const TSourceLoc
} }
else else
{ {
TIntermUnary *node = new TIntermUnary(EOpArrayLength, thisNode); TIntermUnary *node = new TIntermUnary(EOpArrayLength, thisNode, nullptr);
node->setLine(loc); node->setLine(loc);
return node->fold(mDiagnostics); return node->fold(mDiagnostics);
} }
@ -5858,7 +5838,8 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunctionLookup *fnCa
{ {
// Treat it like a built-in unary operator. // Treat it like a built-in unary operator.
TIntermNode *unaryParamNode = fnCall->arguments().front(); TIntermNode *unaryParamNode = fnCall->arguments().front();
TIntermTyped *callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc); TIntermTyped *callNode =
createUnaryMath(op, unaryParamNode->getAsTyped(), loc, fnCandidate);
ASSERT(callNode != nullptr); ASSERT(callNode != nullptr);
return callNode; return callNode;
} }
@ -5955,6 +5936,9 @@ TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
} }
TIntermTernary *node = new TIntermTernary(cond, trueExpression, falseExpression); TIntermTernary *node = new TIntermTernary(cond, trueExpression, falseExpression);
markStaticReadIfSymbol(cond);
markStaticReadIfSymbol(trueExpression);
markStaticReadIfSymbol(falseExpression);
node->setLine(loc); node->setLine(loc);
return expressionOrFoldedResult(node); return expressionOrFoldedResult(node);
} }

View File

@ -419,6 +419,8 @@ class TParseContext : angle::NonCopyable
TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc); TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc);
TIntermBranch *addBranch(TOperator op, TIntermTyped *expression, const TSourceLoc &loc); TIntermBranch *addBranch(TOperator op, TIntermTyped *expression, const TSourceLoc &loc);
void appendStatement(TIntermBlock *block, TIntermNode *statement);
void checkTextureGather(TIntermAggregate *functionCall); void checkTextureGather(TIntermAggregate *functionCall);
void checkTextureOffsetConst(TIntermAggregate *functionCall); void checkTextureOffsetConst(TIntermAggregate *functionCall);
void checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall); void checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall);
@ -464,6 +466,8 @@ class TParseContext : angle::NonCopyable
// Note that there may be tests in AtomicCounter_test that will need to be updated as well. // Note that there may be tests in AtomicCounter_test that will need to be updated as well.
constexpr static size_t kAtomicCounterArrayStride = 4; constexpr static size_t kAtomicCounterArrayStride = 4;
void markStaticReadIfSymbol(TIntermNode *node);
// Returns a clamped index. If it prints out an error message, the token is "[]". // Returns a clamped index. If it prints out an error message, the token is "[]".
int checkIndexLessThan(bool outOfRangeIndexIsError, int checkIndexLessThan(bool outOfRangeIndexIsError,
const TSourceLoc &location, const TSourceLoc &location,
@ -545,11 +549,10 @@ class TParseContext : angle::NonCopyable
TIntermTyped *left, TIntermTyped *left,
TIntermTyped *right, TIntermTyped *right,
const TSourceLoc &loc); const TSourceLoc &loc);
TIntermBinary *createAssign(TOperator op, TIntermTyped *createUnaryMath(TOperator op,
TIntermTyped *left, TIntermTyped *child,
TIntermTyped *right, const TSourceLoc &loc,
const TSourceLoc &loc); const TFunction *func);
TIntermTyped *createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
TIntermTyped *addMethod(TFunctionLookup *fnCall, const TSourceLoc &loc); TIntermTyped *addMethod(TFunctionLookup *fnCall, const TSourceLoc &loc);
TIntermTyped *addConstructor(TFunctionLookup *fnCall, const TSourceLoc &line); TIntermTyped *addConstructor(TFunctionLookup *fnCall, const TSourceLoc &line);
@ -606,10 +609,6 @@ class TParseContext : angle::NonCopyable
TDirectiveHandler mDirectiveHandler; TDirectiveHandler mDirectiveHandler;
pp::Preprocessor mPreprocessor; pp::Preprocessor mPreprocessor;
void *mScanner; void *mScanner;
bool mUsesFragData; // track if we are using both gl_FragData and gl_FragColor
bool mUsesFragColor;
bool mUsesSecondaryOutputs; // Track if we are using either gl_SecondaryFragData or
// gl_Secondary FragColor or both.
int mMinProgramTexelOffset; int mMinProgramTexelOffset;
int mMaxProgramTexelOffset; int mMaxProgramTexelOffset;
@ -642,10 +641,6 @@ class TParseContext : angle::NonCopyable
int mGeometryShaderMaxVertices; int mGeometryShaderMaxVertices;
int mMaxGeometryShaderInvocations; int mMaxGeometryShaderInvocations;
int mMaxGeometryShaderMaxVertices; int mMaxGeometryShaderMaxVertices;
// Store gl_in variable with its array size once the array size can be determined. The array
// size can also be checked against latter input primitive type declaration.
const TVariable *mGlInVariableWithArraySize;
}; };
int PaParseStrings(size_t count, int PaParseStrings(size_t count,

View File

@ -0,0 +1,66 @@
// GENERATED FILE - DO NOT EDIT.
// Generated by gen_builtin_symbols.py using data from builtin_variables.json and
// builtin_function_declarations.txt.
//
// Copyright 2018 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.
//
// ParseContext_autogen.h:
// Helpers for built-in related checks.
#ifndef COMPILER_TRANSLATOR_PARSECONTEXT_AUTOGEN_H_
#define COMPILER_TRANSLATOR_PARSECONTEXT_AUTOGEN_H_
namespace sh
{
namespace BuiltInGroup
{
bool isTextureOffsetNoBias(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 662 && id <= 731;
}
bool isTextureOffsetBias(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 732 && id <= 751;
}
bool isTextureGatherOffset(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 823 && id <= 836;
}
bool isTextureGather(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 799 && id <= 836;
}
bool isAtomicMemory(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 853 && id <= 870;
}
bool isImageLoad(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 895 && id <= 906;
}
bool isImageStore(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 907 && id <= 918;
}
bool isImage(const TFunction *func)
{
int id = func->uniqueId().get();
return id >= 871 && id <= 918;
}
} // namespace BuiltInGroup
} // namespace sh
#endif // COMPILER_TRANSLATOR_PARSECONTEXT_AUTOGEN_H_

View File

@ -1,56 +0,0 @@
//
// Copyright (c) 2017 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.
//
// RemoveEmptySwitchStatements.cpp: Remove switch statements that have an empty statement list.
#include "compiler/translator/RemoveEmptySwitchStatements.h"
#include "compiler/translator/IntermTraverse.h"
namespace sh
{
namespace
{
class RemoveEmptySwitchStatementsTraverser : public TIntermTraverser
{
public:
RemoveEmptySwitchStatementsTraverser() : TIntermTraverser(true, false, false) {}
bool visitSwitch(Visit visit, TIntermSwitch *node);
};
bool RemoveEmptySwitchStatementsTraverser::visitSwitch(Visit visit, TIntermSwitch *node)
{
if (node->getStatementList()->getSequence()->empty())
{
// Just output the init statement.
if (node->getInit()->hasSideEffects())
{
queueReplacement(node->getInit(), OriginalNode::IS_DROPPED);
}
else
{
TIntermSequence emptyReplacement;
ASSERT(getParentNode()->getAsBlock());
mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(),
node, emptyReplacement));
}
return false; // Nothing inside the child nodes to traverse.
}
return true;
}
} // anonymous namespace
void RemoveEmptySwitchStatements(TIntermBlock *root)
{
RemoveEmptySwitchStatementsTraverser traverser;
root->traverse(&traverser);
traverser.updateTree();
}
} // namespace sh

View File

@ -1,18 +0,0 @@
//
// Copyright (c) 2017 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.
//
// RemoveEmptySwitchStatements.h: Remove switch statements that have an empty statement list.
#ifndef COMPILER_TRANSLATOR_REMOVEEMPTYSWITCHSTATEMENTS_H_
#define COMPILER_TRANSLATOR_REMOVEEMPTYSWITCHSTATEMENTS_H_
namespace sh
{
class TIntermBlock;
void RemoveEmptySwitchStatements(TIntermBlock *root);
}
#endif // COMPILER_TRANSLATOR_REMOVEEMPTYSWITCHSTATEMENTS_H_

View File

@ -1,116 +0,0 @@
//
// Copyright (c) 2017 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.
//
// RemoveNoOpCasesFromEndOfSwitchStatements.cpp: Clean up cases from the end of a switch statement
// that only contain no-ops.
#include "compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/IntermNode_util.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/SymbolTable.h"
namespace sh
{
namespace
{
bool AreEmptyBlocks(TIntermSequence *statements, size_t i);
bool IsEmptyBlock(TIntermNode *node)
{
TIntermBlock *asBlock = node->getAsBlock();
if (asBlock)
{
if (asBlock->getSequence()->empty())
{
return true;
}
return AreEmptyBlocks(asBlock->getSequence(), 0u);
}
// Empty declarations should have already been pruned, otherwise they would need to be handled
// here. Note that declarations for struct types do contain a nameless child node.
ASSERT(node->getAsDeclarationNode() == nullptr ||
!node->getAsDeclarationNode()->getSequence()->empty());
// Pure literal statements should also already be pruned.
ASSERT(node->getAsConstantUnion() == nullptr);
return false;
}
// Return true if all statements in "statements" starting from index i consist only of empty blocks
// and no-op statements. Returns true also if there are no statements.
bool AreEmptyBlocks(TIntermSequence *statements, size_t i)
{
for (; i < statements->size(); ++i)
{
if (!IsEmptyBlock(statements->at(i)))
{
return false;
}
}
return true;
}
void RemoveNoOpCasesFromEndOfStatementList(TIntermBlock *statementList, TSymbolTable *symbolTable)
{
TIntermSequence *statements = statementList->getSequence();
bool foundDeadCase = false;
do
{
if (statements->empty())
{
return;
}
// Find the last case label.
size_t i = statements->size();
while (i > 0u && !(*statements)[i - 1]->getAsCaseNode())
{
--i;
}
// Now i is the index of the first statement following the last label inside the switch
// statement.
ASSERT(i > 0u);
foundDeadCase = AreEmptyBlocks(statements, i);
if (foundDeadCase)
{
statements->erase(statements->begin() + (i - 1u), statements->end());
}
} while (foundDeadCase);
}
class RemoveNoOpCasesFromEndOfSwitchTraverser : public TIntermTraverser
{
public:
RemoveNoOpCasesFromEndOfSwitchTraverser(TSymbolTable *symbolTable)
: TIntermTraverser(true, false, false, symbolTable)
{
}
bool visitSwitch(Visit visit, TIntermSwitch *node) override;
};
bool RemoveNoOpCasesFromEndOfSwitchTraverser::visitSwitch(Visit visit, TIntermSwitch *node)
{
// Here we may mutate the statement list, but it's safe since traversal has not yet reached
// there.
RemoveNoOpCasesFromEndOfStatementList(node->getStatementList(), mSymbolTable);
// Handle also nested switch statements.
return true;
}
} // anonymous namespace
void RemoveNoOpCasesFromEndOfSwitchStatements(TIntermBlock *root, TSymbolTable *symbolTable)
{
RemoveNoOpCasesFromEndOfSwitchTraverser traverser(symbolTable);
root->traverse(&traverser);
}
} // namespace sh

View File

@ -1,21 +0,0 @@
//
// Copyright (c) 2017 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.
//
// RemoveNoOpCasesFromEndOfSwitchStatements.h: Clean up cases from the end of a switch statement
// that only contain no-ops.
#ifndef COMPILER_TRANSLATOR_REMOVENOOPCASESFROMENDOFSWITCHSTATEMENTS_H_
#define COMPILER_TRANSLATOR_REMOVENOOPCASESFROMENDOFSWITCHSTATEMENTS_H_
namespace sh
{
class TIntermBlock;
class TSymbolTable;
void RemoveNoOpCasesFromEndOfSwitchStatements(TIntermBlock *root, TSymbolTable *symbolTable);
} // namespace sh
#endif // COMPILER_TRANSLATOR_REMOVENOOPCASESFROMENDOFSWITCHSTATEMENTS_H_

View File

@ -32,17 +32,17 @@ bool InterpolationTypesMatch(InterpolationType a, InterpolationType b)
} }
ShaderVariable::ShaderVariable() ShaderVariable::ShaderVariable()
: type(0), precision(0), flattenedOffsetInParentArrays(0), staticUse(false) : type(0), precision(0), flattenedOffsetInParentArrays(0), staticUse(false), active(false)
{ {
} }
ShaderVariable::ShaderVariable(GLenum typeIn) ShaderVariable::ShaderVariable(GLenum typeIn)
: type(typeIn), precision(0), flattenedOffsetInParentArrays(0), staticUse(false) : type(typeIn), precision(0), flattenedOffsetInParentArrays(0), staticUse(false), active(false)
{ {
} }
ShaderVariable::ShaderVariable(GLenum typeIn, unsigned int arraySizeIn) ShaderVariable::ShaderVariable(GLenum typeIn, unsigned int arraySizeIn)
: type(typeIn), precision(0), flattenedOffsetInParentArrays(0), staticUse(false) : type(typeIn), precision(0), flattenedOffsetInParentArrays(0), staticUse(false), active(false)
{ {
ASSERT(arraySizeIn != 0); ASSERT(arraySizeIn != 0);
arraySizes.push_back(arraySizeIn); arraySizes.push_back(arraySizeIn);
@ -60,6 +60,7 @@ ShaderVariable::ShaderVariable(const ShaderVariable &other)
arraySizes(other.arraySizes), arraySizes(other.arraySizes),
flattenedOffsetInParentArrays(other.flattenedOffsetInParentArrays), flattenedOffsetInParentArrays(other.flattenedOffsetInParentArrays),
staticUse(other.staticUse), staticUse(other.staticUse),
active(other.active),
fields(other.fields), fields(other.fields),
structName(other.structName) structName(other.structName)
{ {
@ -73,6 +74,7 @@ ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other)
mappedName = other.mappedName; mappedName = other.mappedName;
arraySizes = other.arraySizes; arraySizes = other.arraySizes;
staticUse = other.staticUse; staticUse = other.staticUse;
active = other.active;
flattenedOffsetInParentArrays = other.flattenedOffsetInParentArrays; flattenedOffsetInParentArrays = other.flattenedOffsetInParentArrays;
fields = other.fields; fields = other.fields;
structName = other.structName; structName = other.structName;
@ -83,8 +85,8 @@ bool ShaderVariable::operator==(const ShaderVariable &other) const
{ {
if (type != other.type || precision != other.precision || name != other.name || if (type != other.type || precision != other.precision || name != other.name ||
mappedName != other.mappedName || arraySizes != other.arraySizes || mappedName != other.mappedName || arraySizes != other.arraySizes ||
staticUse != other.staticUse || fields.size() != other.fields.size() || staticUse != other.staticUse || active != other.active ||
structName != other.structName) fields.size() != other.fields.size() || structName != other.structName)
{ {
return false; return false;
} }
@ -454,6 +456,7 @@ InterfaceBlock::InterfaceBlock()
isRowMajorLayout(false), isRowMajorLayout(false),
binding(-1), binding(-1),
staticUse(false), staticUse(false),
active(false),
blockType(BlockType::BLOCK_UNIFORM) blockType(BlockType::BLOCK_UNIFORM)
{ {
} }
@ -471,6 +474,7 @@ InterfaceBlock::InterfaceBlock(const InterfaceBlock &other)
isRowMajorLayout(other.isRowMajorLayout), isRowMajorLayout(other.isRowMajorLayout),
binding(other.binding), binding(other.binding),
staticUse(other.staticUse), staticUse(other.staticUse),
active(other.active),
blockType(other.blockType), blockType(other.blockType),
fields(other.fields) fields(other.fields)
{ {
@ -486,6 +490,7 @@ InterfaceBlock &InterfaceBlock::operator=(const InterfaceBlock &other)
isRowMajorLayout = other.isRowMajorLayout; isRowMajorLayout = other.isRowMajorLayout;
binding = other.binding; binding = other.binding;
staticUse = other.staticUse; staticUse = other.staticUse;
active = other.active;
blockType = other.blockType; blockType = other.blockType;
fields = other.fields; fields = other.fields;
return *this; return *this;

View File

@ -1,74 +0,0 @@
//
// Copyright (c) 2017 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.
//
// Compile-time instances of many common TType values. These are looked up
// (statically or dynamically) through the methods defined in the namespace.
//
#include "compiler/translator/StaticType.h"
namespace sh
{
namespace StaticType
{
const TType *GetForFloatImage(TBasicType basicType)
{
switch (basicType)
{
case EbtGImage2D:
return Get<EbtImage2D, EbpUndefined, EvqGlobal, 1, 1>();
case EbtGImage3D:
return Get<EbtImage3D, EbpUndefined, EvqGlobal, 1, 1>();
case EbtGImage2DArray:
return Get<EbtImage2DArray, EbpUndefined, EvqGlobal, 1, 1>();
case EbtGImageCube:
return Get<EbtImageCube, EbpUndefined, EvqGlobal, 1, 1>();
default:
UNREACHABLE();
return GetBasic<EbtVoid>();
}
}
const TType *GetForIntImage(TBasicType basicType)
{
switch (basicType)
{
case EbtGImage2D:
return Get<EbtIImage2D, EbpUndefined, EvqGlobal, 1, 1>();
case EbtGImage3D:
return Get<EbtIImage3D, EbpUndefined, EvqGlobal, 1, 1>();
case EbtGImage2DArray:
return Get<EbtIImage2DArray, EbpUndefined, EvqGlobal, 1, 1>();
case EbtGImageCube:
return Get<EbtIImageCube, EbpUndefined, EvqGlobal, 1, 1>();
default:
UNREACHABLE();
return GetBasic<EbtVoid>();
}
}
const TType *GetForUintImage(TBasicType basicType)
{
switch (basicType)
{
case EbtGImage2D:
return Get<EbtUImage2D, EbpUndefined, EvqGlobal, 1, 1>();
case EbtGImage3D:
return Get<EbtUImage3D, EbpUndefined, EvqGlobal, 1, 1>();
case EbtGImage2DArray:
return Get<EbtUImage2DArray, EbpUndefined, EvqGlobal, 1, 1>();
case EbtGImageCube:
return Get<EbtUImageCube, EbpUndefined, EvqGlobal, 1, 1>();
default:
UNREACHABLE();
return GetBasic<EbtVoid>();
}
}
} // namespace StaticType
} // namespace sh

View File

@ -25,16 +25,16 @@ namespace Helpers
// Generation and static allocation of type mangled name values. // Generation and static allocation of type mangled name values.
// //
// Size of the maximum possible constexpr-generated mangled name. // Size of the constexpr-generated mangled name.
// If this value is too small, the compiler will produce errors. // If this value is too small, the compiler will produce errors.
static constexpr size_t kStaticMangledNameMaxLength = 10; static constexpr size_t kStaticMangledNameLength = 2;
// Type which holds the mangled names for constexpr-generated TTypes. // Type which holds the mangled names for constexpr-generated TTypes.
// This simple struct is needed so that a char array can be returned by value. // This simple struct is needed so that a char array can be returned by value.
struct StaticMangledName struct StaticMangledName
{ {
// If this array is too small, the compiler will produce errors. // If this array is too small, the compiler will produce errors.
char name[kStaticMangledNameMaxLength + 1] = {}; char name[kStaticMangledNameLength + 1] = {};
}; };
// Generates a mangled name for a TType given its parameters. // Generates a mangled name for a TType given its parameters.
@ -45,40 +45,9 @@ constexpr StaticMangledName BuildStaticMangledName(TBasicType basicType,
unsigned char secondarySize) unsigned char secondarySize)
{ {
StaticMangledName name = {}; StaticMangledName name = {};
// When this function is executed constexpr (should be always), name.name[0] = TType::GetSizeMangledName(primarySize, secondarySize);
// name.name[at] is guaranteed by the compiler to never go out of bounds. name.name[1] = GetBasicMangledName(basicType);
size_t at = 0; name.name[2] = '\0';
bool isMatrix = primarySize > 1 && secondarySize > 1;
bool isVector = primarySize > 1 && secondarySize == 1;
if (isMatrix)
{
name.name[at++] = 'm';
}
else if (isVector)
{
name.name[at++] = 'v';
}
{
const char *basicMangledName = GetBasicMangledName(basicType);
for (size_t i = 0; basicMangledName[i] != '\0'; ++i)
{
name.name[at++] = basicMangledName[i];
}
}
name.name[at++] = '0' + primarySize;
if (isMatrix)
{
name.name[at++] = 'x';
name.name[at++] = '0' + secondarySize;
}
name.name[at++] = ';';
name.name[at] = '\0';
return name; return name;
} }
@ -222,12 +191,6 @@ constexpr const TType *GetForVec(TQualifier qualifier, unsigned char size)
} }
} }
const TType *GetForFloatImage(TBasicType basicType);
const TType *GetForIntImage(TBasicType basicType);
const TType *GetForUintImage(TBasicType basicType);
} // namespace StaticType } // namespace StaticType
} // namespace sh } // namespace sh

View File

@ -46,11 +46,13 @@ TSymbol::TSymbol(TSymbolTable *symbolTable,
ImmutableString TSymbol::name() const ImmutableString TSymbol::name() const
{ {
if (mName != "") if (!mName.empty())
{ {
return mName; return mName;
} }
ASSERT(mSymbolType == SymbolType::AngleInternal); // This can be called for nameless function parameters in HLSL.
ASSERT(mSymbolType == SymbolType::AngleInternal ||
(mSymbolType == SymbolType::Empty && isVariable()));
int uniqueId = mUniqueId.get(); int uniqueId = mUniqueId.get();
ImmutableStringBuilder symbolNameOut(sizeof(uniqueId) * 2u + 1u); ImmutableStringBuilder symbolNameOut(sizeof(uniqueId) * 2u + 1u);
symbolNameOut << 's'; symbolNameOut << 's';
@ -82,6 +84,14 @@ TStructure::TStructure(TSymbolTable *symbolTable,
{ {
} }
TStructure::TStructure(const TSymbolUniqueId &id,
const ImmutableString &name,
TExtension extension,
const TFieldList *fields)
: TSymbol(id, name, SymbolType::BuiltIn, extension), TFieldListCollection(fields)
{
}
void TStructure::createSamplerSymbols(const char *namePrefix, void TStructure::createSamplerSymbols(const char *namePrefix,
const TString &apiNamePrefix, const TString &apiNamePrefix,
TVector<const TVariable *> *outputSymbols, TVector<const TVariable *> *outputSymbols,
@ -124,6 +134,17 @@ TInterfaceBlock::TInterfaceBlock(TSymbolTable *symbolTable,
ASSERT(name != nullptr); ASSERT(name != nullptr);
} }
TInterfaceBlock::TInterfaceBlock(const TSymbolUniqueId &id,
const ImmutableString &name,
TExtension extension,
const TFieldList *fields)
: TSymbol(id, name, SymbolType::BuiltIn, extension),
TFieldListCollection(fields),
mBlockStorage(EbsUnspecified),
mBinding(0)
{
}
TFunction::TFunction(TSymbolTable *symbolTable, TFunction::TFunction(TSymbolTable *symbolTable,
const ImmutableString &name, const ImmutableString &name,
SymbolType symbolType, SymbolType symbolType,
@ -145,32 +166,7 @@ TFunction::TFunction(TSymbolTable *symbolTable,
ASSERT(name != nullptr || symbolType == SymbolType::AngleInternal); ASSERT(name != nullptr || symbolType == SymbolType::AngleInternal);
} }
TFunction::TFunction(TSymbolTable *symbolTable, void TFunction::addParameter(const TVariable *p)
const ImmutableString &name,
TExtension extension,
TConstParameter *parameters,
size_t paramCount,
const TType *retType,
TOperator op,
bool knownToNotHaveSideEffects)
: TSymbol(symbolTable, name, SymbolType::BuiltIn, extension),
mParametersVector(nullptr),
mParameters(parameters),
mParamCount(paramCount),
returnType(retType),
mMangledName(""),
mOp(op),
defined(false),
mHasPrototypeDeclaration(false),
mKnownToNotHaveSideEffects(knownToNotHaveSideEffects)
{
ASSERT(name != nullptr);
ASSERT(op != EOpNull);
ASSERT(paramCount == 0 || parameters != nullptr);
mMangledName = buildMangledName();
}
void TFunction::addParameter(const TConstParameter &p)
{ {
ASSERT(mParametersVector); ASSERT(mParametersVector);
mParametersVector->push_back(p); mParametersVector->push_back(p);
@ -195,7 +191,7 @@ ImmutableString TFunction::buildMangledName() const
for (size_t i = 0u; i < mParamCount; ++i) for (size_t i = 0u; i < mParamCount; ++i)
{ {
newName += mParameters[i].type->getMangledName(); newName += mParameters[i]->getType().getMangledName();
} }
return ImmutableString(newName); return ImmutableString(newName);
} }

View File

@ -42,8 +42,10 @@ class TSymbol : angle::NonCopyable
// either statically allocated or pool allocated. // either statically allocated or pool allocated.
~TSymbol() = default; ~TSymbol() = default;
// Don't call name() or getMangledName() for empty symbols (symbolType == SymbolType::Empty). // Calling name() for empty symbols (symbolType == SymbolType::Empty) generates a similar name
// as for internal variables.
ImmutableString name() const; ImmutableString name() const;
// Don't call getMangledName() for empty symbols (symbolType == SymbolType::Empty).
virtual ImmutableString getMangledName() const; virtual ImmutableString getMangledName() const;
virtual bool isFunction() const { return false; } virtual bool isFunction() const { return false; }
@ -89,7 +91,7 @@ class TVariable : public TSymbol
void shareConstPointer(const TConstantUnion *constArray) { unionArray = constArray; } void shareConstPointer(const TConstantUnion *constArray) { unionArray = constArray; }
private: // Note: only to be used for built-in variables with autogenerated ids!
constexpr TVariable(const TSymbolUniqueId &id, constexpr TVariable(const TSymbolUniqueId &id,
const ImmutableString &name, const ImmutableString &name,
SymbolType symbolType, SymbolType symbolType,
@ -99,6 +101,7 @@ class TVariable : public TSymbol
{ {
} }
private:
const TType *mType; const TType *mType;
const TConstantUnion *unionArray; const TConstantUnion *unionArray;
}; };
@ -125,6 +128,13 @@ class TStructure : public TSymbol, public TFieldListCollection
bool atGlobalScope() const { return mAtGlobalScope; } bool atGlobalScope() const { return mAtGlobalScope; }
private: private:
friend class TSymbolTable;
// For creating built-in structs.
TStructure(const TSymbolUniqueId &id,
const ImmutableString &name,
TExtension extension,
const TFieldList *fields);
// TODO(zmo): Find a way to get rid of the const_cast in function // TODO(zmo): Find a way to get rid of the const_cast in function
// setName(). At the moment keep this function private so only // setName(). At the moment keep this function private so only
// friend class RegenerateStructNames may call it. // friend class RegenerateStructNames may call it.
@ -150,44 +160,33 @@ class TInterfaceBlock : public TSymbol, public TFieldListCollection
int blockBinding() const { return mBinding; } int blockBinding() const { return mBinding; }
private: private:
friend class TSymbolTable;
// For creating built-in interface blocks.
TInterfaceBlock(const TSymbolUniqueId &id,
const ImmutableString &name,
TExtension extension,
const TFieldList *fields);
TLayoutBlockStorage mBlockStorage; TLayoutBlockStorage mBlockStorage;
int mBinding; int mBinding;
// Note that we only record matrix packing on a per-field granularity. // Note that we only record matrix packing on a per-field granularity.
}; };
// Immutable version of TParameter. // Parameter class used for parsing user-defined function parameters.
struct TConstParameter
{
POOL_ALLOCATOR_NEW_DELETE();
TConstParameter() : name(""), type(nullptr) {}
explicit TConstParameter(const ImmutableString &n) : name(n), type(nullptr) {}
constexpr explicit TConstParameter(const TType *t) : name(""), type(t) {}
TConstParameter(const ImmutableString &n, const TType *t) : name(n), type(t) {}
// Both constructor arguments must be const.
TConstParameter(ImmutableString *n, TType *t) = delete;
TConstParameter(const ImmutableString *n, TType *t) = delete;
TConstParameter(ImmutableString *n, const TType *t) = delete;
const ImmutableString name;
const TType *const type;
};
// The function sub-class of symbols and the parser will need to
// share this definition of a function parameter.
struct TParameter struct TParameter
{ {
// Destructively converts to TConstParameter. // Destructively converts to TVariable.
// This method resets name and type to nullptrs to make sure // This method resets name and type to nullptrs to make sure
// their content cannot be modified after the call. // their content cannot be modified after the call.
TConstParameter turnToConst() const TVariable *createVariable(TSymbolTable *symbolTable)
{ {
const ImmutableString constName(name); const ImmutableString constName(name);
const TType *constType = type; const TType *constType = type;
name = nullptr; name = nullptr;
type = nullptr; type = nullptr;
return TConstParameter(constName, constType); return new TVariable(symbolTable, constName, constType,
constName.empty() ? SymbolType::Empty : SymbolType::UserDefined);
} }
const char *name; // either pool allocated or static. const char *name; // either pool allocated or static.
@ -205,24 +204,15 @@ class TFunction : public TSymbol
const TType *retType, const TType *retType,
bool knownToNotHaveSideEffects); bool knownToNotHaveSideEffects);
// Built-in function
TFunction(TSymbolTable *symbolTable,
const ImmutableString &name,
TExtension extension,
TConstParameter *parameters,
size_t paramCount,
const TType *retType,
TOperator op,
bool knownToNotHaveSideEffects);
bool isFunction() const override { return true; } bool isFunction() const override { return true; }
void addParameter(const TConstParameter &p); void addParameter(const TVariable *p);
void shareParameters(const TFunction &parametersSource); void shareParameters(const TFunction &parametersSource);
ImmutableString getMangledName() const override ImmutableString getMangledName() const override
{ {
if (mMangledName == "") ASSERT(symbolType() != SymbolType::BuiltIn);
if (mMangledName.empty())
{ {
mMangledName = buildMangledName(); mMangledName = buildMangledName();
} }
@ -239,21 +229,20 @@ class TFunction : public TSymbol
bool hasPrototypeDeclaration() const { return mHasPrototypeDeclaration; } bool hasPrototypeDeclaration() const { return mHasPrototypeDeclaration; }
size_t getParamCount() const { return mParamCount; } size_t getParamCount() const { return mParamCount; }
const TConstParameter &getParam(size_t i) const { return mParameters[i]; } const TVariable *getParam(size_t i) const { return mParameters[i]; }
bool isKnownToNotHaveSideEffects() const { return mKnownToNotHaveSideEffects; } bool isKnownToNotHaveSideEffects() const { return mKnownToNotHaveSideEffects; }
bool isMain() const; bool isMain() const;
bool isImageFunction() const; bool isImageFunction() const;
private: // Note: Only to be used for static built-in functions!
constexpr TFunction(const TSymbolUniqueId &id, constexpr TFunction(const TSymbolUniqueId &id,
const ImmutableString &name, const ImmutableString &name,
TExtension extension, TExtension extension,
const TConstParameter *parameters, const TVariable *const *parameters,
size_t paramCount, size_t paramCount,
const TType *retType, const TType *retType,
const ImmutableString &mangledName,
TOperator op, TOperator op,
bool knownToNotHaveSideEffects) bool knownToNotHaveSideEffects)
: TSymbol(id, name, SymbolType::BuiltIn, extension), : TSymbol(id, name, SymbolType::BuiltIn, extension),
@ -261,7 +250,7 @@ class TFunction : public TSymbol
mParameters(parameters), mParameters(parameters),
mParamCount(paramCount), mParamCount(paramCount),
returnType(retType), returnType(retType),
mMangledName(mangledName), mMangledName(nullptr),
mOp(op), mOp(op),
defined(false), defined(false),
mHasPrototypeDeclaration(false), mHasPrototypeDeclaration(false),
@ -269,11 +258,12 @@ class TFunction : public TSymbol
{ {
} }
private:
ImmutableString buildMangledName() const; ImmutableString buildMangledName() const;
typedef TVector<TConstParameter> TParamVector; typedef TVector<const TVariable *> TParamVector;
TParamVector *mParametersVector; TParamVector *mParametersVector;
const TConstParameter *mParameters; const TVariable *const *mParameters;
size_t mParamCount; size_t mParamCount;
const TType *const returnType; const TType *const returnType;
mutable ImmutableString mMangledName; mutable ImmutableString mMangledName;

File diff suppressed because it is too large Load Diff

View File

@ -30,7 +30,6 @@
// are tracked in the intermediate representation, not the symbol table. // are tracked in the intermediate representation, not the symbol table.
// //
#include <array>
#include <memory> #include <memory>
#include "common/angleutils.h" #include "common/angleutils.h"
@ -39,13 +38,12 @@
#include "compiler/translator/InfoSink.h" #include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h" #include "compiler/translator/IntermNode.h"
#include "compiler/translator/Symbol.h" #include "compiler/translator/Symbol.h"
#include "compiler/translator/SymbolTable_autogen.h"
namespace sh namespace sh
{ {
// Define ESymbolLevel as int rather than an enum since level can go // Define ESymbolLevel as int rather than an enum so that we can do arithmetic on it.
// above GLOBAL_LEVEL and cause atBuiltInLevel() to fail if the
// compiler optimizes the >= of the last element to ==.
typedef int ESymbolLevel; typedef int ESymbolLevel;
const int COMMON_BUILTINS = 0; const int COMMON_BUILTINS = 0;
const int ESSL1_BUILTINS = 1; const int ESSL1_BUILTINS = 1;
@ -55,18 +53,15 @@ const int ESSL3_1_BUILTINS = 3;
// features in ANGLE's GLSL backend. They're not visible to the parser. // features in ANGLE's GLSL backend. They're not visible to the parser.
const int GLSL_BUILTINS = 4; const int GLSL_BUILTINS = 4;
const int LAST_BUILTIN_LEVEL = GLSL_BUILTINS; const int LAST_BUILTIN_LEVEL = GLSL_BUILTINS;
const int GLOBAL_LEVEL = 5;
struct UnmangledBuiltIn struct UnmangledBuiltIn
{ {
constexpr UnmangledBuiltIn() : extension(TExtension::UNDEFINED) {}
constexpr UnmangledBuiltIn(TExtension extension) : extension(extension) {} constexpr UnmangledBuiltIn(TExtension extension) : extension(extension) {}
TExtension extension; TExtension extension;
}; };
class TSymbolTable : angle::NonCopyable class TSymbolTable : angle::NonCopyable, TSymbolTableBase
{ {
public: public:
TSymbolTable(); TSymbolTable();
@ -76,22 +71,16 @@ class TSymbolTable : angle::NonCopyable
~TSymbolTable(); ~TSymbolTable();
// When the symbol table is initialized with the built-ins, there should bool isEmpty() const;
// 'push' calls, so that built-ins are at level 0 and the shader bool atGlobalLevel() const;
// globals are at level 1.
bool isEmpty() const { return mTable.empty(); }
bool atBuiltInLevel() const { return currentLevel() <= LAST_BUILTIN_LEVEL; }
bool atGlobalLevel() const { return currentLevel() == GLOBAL_LEVEL; }
void push(); void push();
void pop(); void pop();
// The declare* entry points are used when parsing and declare symbols at the current scope. // Declare a non-function symbol at the current scope. Return true in case the declaration was
// They return the created true in case the declaration was successful, and false if the // successful, and false if the declaration failed due to redefinition.
// declaration failed due to redefinition. bool declare(TSymbol *symbol);
bool declareVariable(TVariable *variable);
bool declareStructType(TStructure *str);
bool declareInterfaceBlock(TInterfaceBlock *interfaceBlock);
// Functions are always declared at global scope. // Functions are always declared at global scope.
void declareUserDefinedFunction(TFunction *function, bool insertUnmangledName); void declareUserDefinedFunction(TFunction *function, bool insertUnmangledName);
@ -101,6 +90,19 @@ class TSymbolTable : angle::NonCopyable
const TFunction *setFunctionParameterNamesFromDefinition(const TFunction *function, const TFunction *setFunctionParameterNamesFromDefinition(const TFunction *function,
bool *wasDefinedOut); bool *wasDefinedOut);
// Return false if the gl_in array size has already been initialized with a mismatching value.
bool setGlInArraySize(unsigned int inputArraySize);
TVariable *getGlInVariableWithArraySize() const;
const TVariable *gl_FragData() const;
const TVariable *gl_SecondaryFragDataEXT() const;
void markStaticRead(const TVariable &variable);
void markStaticWrite(const TVariable &variable);
// Note: Should not call this for constant variables.
bool isStaticallyUsed(const TVariable &variable) const;
// find() is guaranteed not to retain a reference to the ImmutableString, so an ImmutableString // find() is guaranteed not to retain a reference to the ImmutableString, so an ImmutableString
// with a reference to a short-lived char * is fine to pass here. // with a reference to a short-lived char * is fine to pass here.
const TSymbol *find(const ImmutableString &name, int shaderVersion) const; const TSymbol *find(const ImmutableString &name, int shaderVersion) const;
@ -109,10 +111,6 @@ class TSymbolTable : angle::NonCopyable
const TSymbol *findBuiltIn(const ImmutableString &name, int shaderVersion) const; const TSymbol *findBuiltIn(const ImmutableString &name, int shaderVersion) const;
const TSymbol *findBuiltIn(const ImmutableString &name,
int shaderVersion,
bool includeGLSLBuiltins) const;
void setDefaultPrecision(TBasicType type, TPrecision prec); void setDefaultPrecision(TBasicType type, TPrecision prec);
// Searches down the precisionStack for a precision qualifier // Searches down the precisionStack for a precision qualifier
@ -146,138 +144,16 @@ class TSymbolTable : angle::NonCopyable
friend class TSymbolUniqueId; friend class TSymbolUniqueId;
int nextUniqueIdValue(); int nextUniqueIdValue();
class TSymbolTableBuiltInLevel;
class TSymbolTableLevel; class TSymbolTableLevel;
void pushBuiltInLevel();
ESymbolLevel currentLevel() const
{
return static_cast<ESymbolLevel>(mTable.size() + LAST_BUILTIN_LEVEL);
}
// The insert* entry points are used when initializing the symbol table with built-ins.
// They return the created symbol / true in case the declaration was successful, and nullptr /
// false if the declaration failed due to redefinition.
TVariable *insertVariable(ESymbolLevel level, const ImmutableString &name, const TType *type);
void insertVariableExt(ESymbolLevel level,
TExtension ext,
const ImmutableString &name,
const TType *type);
bool insertVariable(ESymbolLevel level, TVariable *variable);
bool insertStructType(ESymbolLevel level, TStructure *str);
bool insertInterfaceBlock(ESymbolLevel level, TInterfaceBlock *interfaceBlock);
template <TPrecision precision>
bool insertConstInt(ESymbolLevel level, const ImmutableString &name, int value);
template <TPrecision precision>
bool insertConstIntExt(ESymbolLevel level,
TExtension ext,
const ImmutableString &name,
int value);
template <TPrecision precision>
bool insertConstIvec3(ESymbolLevel level,
const ImmutableString &name,
const std::array<int, 3> &values);
// Note that for inserted built-in functions the const char *name needs to remain valid for the
// lifetime of the SymbolTable. SymbolTable does not allocate a copy of it.
void insertBuiltIn(ESymbolLevel level,
TOperator op,
TExtension ext,
const TType *rvalue,
const char *name,
const TType *ptype1,
const TType *ptype2 = 0,
const TType *ptype3 = 0,
const TType *ptype4 = 0,
const TType *ptype5 = 0);
void insertBuiltIn(ESymbolLevel level,
const TType *rvalue,
const char *name,
const TType *ptype1,
const TType *ptype2 = 0,
const TType *ptype3 = 0,
const TType *ptype4 = 0,
const TType *ptype5 = 0)
{
insertUnmangledBuiltIn(name, TExtension::UNDEFINED, level);
insertBuiltIn(level, EOpCallBuiltInFunction, TExtension::UNDEFINED, rvalue, name, ptype1,
ptype2, ptype3, ptype4, ptype5);
}
void insertBuiltIn(ESymbolLevel level,
TExtension ext,
const TType *rvalue,
const char *name,
const TType *ptype1,
const TType *ptype2 = 0,
const TType *ptype3 = 0,
const TType *ptype4 = 0,
const TType *ptype5 = 0)
{
insertUnmangledBuiltIn(name, ext, level);
insertBuiltIn(level, EOpCallBuiltInFunction, ext, rvalue, name, ptype1, ptype2, ptype3,
ptype4, ptype5);
}
void insertBuiltInOp(ESymbolLevel level,
TOperator op,
const TType *rvalue,
const TType *ptype1,
const TType *ptype2 = 0,
const TType *ptype3 = 0,
const TType *ptype4 = 0,
const TType *ptype5 = 0);
void insertBuiltInOp(ESymbolLevel level,
TOperator op,
TExtension ext,
const TType *rvalue,
const TType *ptype1,
const TType *ptype2 = 0,
const TType *ptype3 = 0,
const TType *ptype4 = 0,
const TType *ptype5 = 0);
void insertBuiltInFunctionNoParameters(ESymbolLevel level,
TOperator op,
const TType *rvalue,
const char *name);
void insertBuiltInFunctionNoParametersExt(ESymbolLevel level,
TExtension ext,
TOperator op,
const TType *rvalue,
const char *name);
TVariable *insertVariable(ESymbolLevel level,
const ImmutableString &name,
const TType *type,
SymbolType symbolType);
bool insert(ESymbolLevel level, TSymbol *symbol);
TFunction *findUserDefinedFunction(const ImmutableString &name) const; TFunction *findUserDefinedFunction(const ImmutableString &name) const;
// Used to insert unmangled functions to check redeclaration of built-ins in ESSL 3.00 and
// above.
void insertUnmangledBuiltIn(const char *name, TExtension ext, ESymbolLevel level);
bool hasUnmangledBuiltInAtLevel(const char *name, ESymbolLevel level);
void initSamplerDefaultPrecision(TBasicType samplerType); void initSamplerDefaultPrecision(TBasicType samplerType);
void initializeBuiltInFunctions(sh::GLenum type); void initializeBuiltInVariables(sh::GLenum shaderType,
void initializeBuiltInVariables(sh::GLenum type,
ShShaderSpec spec, ShShaderSpec spec,
const ShBuiltInResources &resources); const ShBuiltInResources &resources);
void markBuiltInInitializationFinished();
std::vector<std::unique_ptr<TSymbolTableBuiltInLevel>> mBuiltInTable;
std::vector<std::unique_ptr<TSymbolTableLevel>> mTable; std::vector<std::unique_ptr<TSymbolTableLevel>> mTable;
// There's one precision stack level for predefined precisions and then one level for each scope // There's one precision stack level for predefined precisions and then one level for each scope
@ -287,10 +163,24 @@ class TSymbolTable : angle::NonCopyable
int mUniqueIdCounter; int mUniqueIdCounter;
// -1 before built-in init has finished, one past the last built-in id afterwards. static const int kLastBuiltInId;
// TODO(oetuaho): Make this a compile-time constant once the symbol table is initialized at
// compile time. http://anglebug.com/1432 sh::GLenum mShaderType;
int mUserDefinedUniqueIdsStart; ShBuiltInResources mResources;
struct VariableMetadata
{
VariableMetadata();
bool staticRead;
bool staticWrite;
};
// Indexed by unique id. Map instead of vector since the variables are fairly sparse.
std::map<int, VariableMetadata> mVariableMetadata;
// Store gl_in variable with its array size once the array size can be determined. The array
// size can also be checked against latter input primitive type declaration.
TVariable *mGlInVariableWithArraySize;
}; };
} // namespace sh } // namespace sh

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,78 @@
// GENERATED FILE - DO NOT EDIT.
// Generated by gen_builtin_symbols.py using data from builtin_variables.json and
// builtin_function_declarations.txt.
//
// Copyright 2018 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.
//
// SymbolTable_autogen.h:
// Autogenerated member variables of TSymbolTable.
#ifndef COMPILER_TRANSLATOR_SYMBOLTABLE_AUTOGEN_H_
#define COMPILER_TRANSLATOR_SYMBOLTABLE_AUTOGEN_H_
namespace sh
{
class TSymbolTableBase
{
protected:
TSymbolTableBase() = default;
TStructure *mVar_gl_DepthRangeParameters = nullptr;
TVariable *mVar_gl_DepthRange = nullptr;
TVariable *mVar_gl_MaxVertexAttribs = nullptr;
TVariable *mVar_gl_MaxVertexUniformVectors = nullptr;
TVariable *mVar_gl_MaxVertexTextureImageUnits = nullptr;
TVariable *mVar_gl_MaxCombinedTextureImageUnits = nullptr;
TVariable *mVar_gl_MaxTextureImageUnits = nullptr;
TVariable *mVar_gl_MaxFragmentUniformVectors = nullptr;
TVariable *mVar_gl_MaxVaryingVectors = nullptr;
TVariable *mVar_gl_MaxDrawBuffers = nullptr;
TVariable *mVar_gl_MaxDualSourceDrawBuffersEXT = nullptr;
TVariable *mVar_gl_MaxVertexOutputVectors = nullptr;
TVariable *mVar_gl_MaxFragmentInputVectors = nullptr;
TVariable *mVar_gl_MinProgramTexelOffset = nullptr;
TVariable *mVar_gl_MaxProgramTexelOffset = nullptr;
TVariable *mVar_gl_MaxImageUnits = nullptr;
TVariable *mVar_gl_MaxVertexImageUniforms = nullptr;
TVariable *mVar_gl_MaxFragmentImageUniforms = nullptr;
TVariable *mVar_gl_MaxComputeImageUniforms = nullptr;
TVariable *mVar_gl_MaxCombinedImageUniforms = nullptr;
TVariable *mVar_gl_MaxCombinedShaderOutputResources = nullptr;
TVariable *mVar_gl_MaxComputeWorkGroupCount = nullptr;
TVariable *mVar_gl_MaxComputeWorkGroupSize = nullptr;
TVariable *mVar_gl_MaxComputeUniformComponents = nullptr;
TVariable *mVar_gl_MaxComputeTextureImageUnits = nullptr;
TVariable *mVar_gl_MaxComputeAtomicCounters = nullptr;
TVariable *mVar_gl_MaxComputeAtomicCounterBuffers = nullptr;
TVariable *mVar_gl_MaxVertexAtomicCounters = nullptr;
TVariable *mVar_gl_MaxFragmentAtomicCounters = nullptr;
TVariable *mVar_gl_MaxCombinedAtomicCounters = nullptr;
TVariable *mVar_gl_MaxAtomicCounterBindings = nullptr;
TVariable *mVar_gl_MaxVertexAtomicCounterBuffers = nullptr;
TVariable *mVar_gl_MaxFragmentAtomicCounterBuffers = nullptr;
TVariable *mVar_gl_MaxCombinedAtomicCounterBuffers = nullptr;
TVariable *mVar_gl_MaxAtomicCounterBufferSize = nullptr;
TVariable *mVar_gl_MaxGeometryInputComponents = nullptr;
TVariable *mVar_gl_MaxGeometryOutputComponents = nullptr;
TVariable *mVar_gl_MaxGeometryImageUniforms = nullptr;
TVariable *mVar_gl_MaxGeometryTextureImageUnits = nullptr;
TVariable *mVar_gl_MaxGeometryOutputVertices = nullptr;
TVariable *mVar_gl_MaxGeometryTotalOutputComponents = nullptr;
TVariable *mVar_gl_MaxGeometryUniformComponents = nullptr;
TVariable *mVar_gl_MaxGeometryAtomicCounters = nullptr;
TVariable *mVar_gl_MaxGeometryAtomicCounterBuffers = nullptr;
TVariable *mVar_gl_FragData = nullptr;
TVariable *mVar_gl_SecondaryFragDataEXT = nullptr;
TVariable *mVar_gl_FragDepthEXT = nullptr;
TVariable *mVar_gl_LastFragData = nullptr;
TVariable *mVar_gl_LastFragDataNV = nullptr;
TInterfaceBlock *mVar_gl_PerVertex = nullptr;
TVariable *mVar_gl_in = nullptr;
TVariable *mVar_gl_PositionGS = nullptr;
};
} // namespace sh
#endif // COMPILER_TRANSLATOR_SYMBOLTABLE_AUTOGEN_H_

View File

@ -22,11 +22,6 @@ TSymbolUniqueId::TSymbolUniqueId(const TSymbol &symbol) : mId(symbol.uniqueId().
TSymbolUniqueId &TSymbolUniqueId::operator=(const TSymbolUniqueId &) = default; TSymbolUniqueId &TSymbolUniqueId::operator=(const TSymbolUniqueId &) = default;
int TSymbolUniqueId::get() const
{
return mId;
}
bool TSymbolUniqueId::operator==(const TSymbolUniqueId &other) const bool TSymbolUniqueId::operator==(const TSymbolUniqueId &other) const
{ {
return mId == other.mId; return mId == other.mId;

View File

@ -20,15 +20,18 @@ class TSymbolUniqueId
{ {
public: public:
POOL_ALLOCATOR_NEW_DELETE(); POOL_ALLOCATOR_NEW_DELETE();
explicit TSymbolUniqueId(TSymbolTable *symbolTable);
explicit TSymbolUniqueId(const TSymbol &symbol); explicit TSymbolUniqueId(const TSymbol &symbol);
constexpr TSymbolUniqueId(const TSymbolUniqueId &) = default; constexpr TSymbolUniqueId(const TSymbolUniqueId &) = default;
TSymbolUniqueId &operator=(const TSymbolUniqueId &); TSymbolUniqueId &operator=(const TSymbolUniqueId &);
bool operator==(const TSymbolUniqueId &) const; bool operator==(const TSymbolUniqueId &) const;
int get() const; constexpr int get() const { return mId; }
private: private:
friend class TSymbolTable;
explicit TSymbolUniqueId(TSymbolTable *symbolTable);
friend class BuiltInId;
constexpr TSymbolUniqueId(int staticId) : mId(staticId) {} constexpr TSymbolUniqueId(int staticId) : mId(staticId) {}
int mId; int mId;

View File

@ -6,11 +6,11 @@
#include "compiler/translator/TranslatorESSL.h" #include "compiler/translator/TranslatorESSL.h"
#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
#include "compiler/translator/EmulatePrecision.h"
#include "compiler/translator/RecordConstantPrecision.h"
#include "compiler/translator/OutputESSL.h"
#include "angle_gl.h" #include "angle_gl.h"
#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
#include "compiler/translator/OutputESSL.h"
#include "compiler/translator/tree_ops/EmulatePrecision.h"
#include "compiler/translator/tree_ops/RecordConstantPrecision.h"
namespace sh namespace sh
{ {

View File

@ -8,12 +8,12 @@
#include "angle_gl.h" #include "angle_gl.h"
#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h" #include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
#include "compiler/translator/EmulatePrecision.h"
#include "compiler/translator/ExtensionGLSL.h" #include "compiler/translator/ExtensionGLSL.h"
#include "compiler/translator/OutputGLSL.h" #include "compiler/translator/OutputGLSL.h"
#include "compiler/translator/RewriteTexelFetchOffset.h"
#include "compiler/translator/RewriteUnaryMinusOperatorFloat.h"
#include "compiler/translator/VersionGLSL.h" #include "compiler/translator/VersionGLSL.h"
#include "compiler/translator/tree_ops/EmulatePrecision.h"
#include "compiler/translator/tree_ops/RewriteTexelFetchOffset.h"
#include "compiler/translator/tree_ops/RewriteUnaryMinusOperatorFloat.h"
namespace sh namespace sh
{ {

View File

@ -6,26 +6,26 @@
#include "compiler/translator/TranslatorHLSL.h" #include "compiler/translator/TranslatorHLSL.h"
#include "compiler/translator/AddDefaultReturnStatements.h"
#include "compiler/translator/ArrayReturnValueToOutParameter.h"
#include "compiler/translator/BreakVariableAliasingInInnerLoops.h"
#include "compiler/translator/EmulatePrecision.h"
#include "compiler/translator/ExpandIntegerPowExpressions.h"
#include "compiler/translator/IntermNodePatternMatcher.h"
#include "compiler/translator/OutputHLSL.h" #include "compiler/translator/OutputHLSL.h"
#include "compiler/translator/RemoveDynamicIndexing.h" #include "compiler/translator/tree_ops/AddDefaultReturnStatements.h"
#include "compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h" #include "compiler/translator/tree_ops/ArrayReturnValueToOutParameter.h"
#include "compiler/translator/RewriteElseBlocks.h" #include "compiler/translator/tree_ops/BreakVariableAliasingInInnerLoops.h"
#include "compiler/translator/RewriteTexelFetchOffset.h" #include "compiler/translator/tree_ops/EmulatePrecision.h"
#include "compiler/translator/RewriteUnaryMinusOperatorInt.h" #include "compiler/translator/tree_ops/ExpandIntegerPowExpressions.h"
#include "compiler/translator/SeparateArrayConstructorStatements.h" #include "compiler/translator/tree_ops/PruneEmptyCases.h"
#include "compiler/translator/SeparateArrayInitialization.h" #include "compiler/translator/tree_ops/RemoveDynamicIndexing.h"
#include "compiler/translator/SeparateDeclarations.h" #include "compiler/translator/tree_ops/RewriteElseBlocks.h"
#include "compiler/translator/SeparateExpressionsReturningArrays.h" #include "compiler/translator/tree_ops/RewriteTexelFetchOffset.h"
#include "compiler/translator/SimplifyLoopConditions.h" #include "compiler/translator/tree_ops/RewriteUnaryMinusOperatorInt.h"
#include "compiler/translator/SplitSequenceOperator.h" #include "compiler/translator/tree_ops/SeparateArrayConstructorStatements.h"
#include "compiler/translator/UnfoldShortCircuitToIf.h" #include "compiler/translator/tree_ops/SeparateArrayInitialization.h"
#include "compiler/translator/WrapSwitchStatementsInBlocks.h" #include "compiler/translator/tree_ops/SeparateDeclarations.h"
#include "compiler/translator/tree_ops/SeparateExpressionsReturningArrays.h"
#include "compiler/translator/tree_ops/SimplifyLoopConditions.h"
#include "compiler/translator/tree_ops/SplitSequenceOperator.h"
#include "compiler/translator/tree_ops/UnfoldShortCircuitToIf.h"
#include "compiler/translator/tree_ops/WrapSwitchStatementsInBlocks.h"
#include "compiler/translator/tree_util/IntermNodePatternMatcher.h"
namespace sh namespace sh
{ {
@ -93,13 +93,10 @@ void TranslatorHLSL::translate(TIntermBlock *root,
sh::BreakVariableAliasingInInnerLoops(root); sh::BreakVariableAliasingInInnerLoops(root);
// WrapSwitchStatementsInBlocks should be called after any AST transformations that might // WrapSwitchStatementsInBlocks should be called after any AST transformations that might
// introduce variable declarations inside the main scope of any switch statement. // introduce variable declarations inside the main scope of any switch statement. It cannot
if (WrapSwitchStatementsInBlocks(root)) // result in no-op cases at the end of switch statements, because unreferenced variables
{ // have already been pruned.
// The WrapSwitchStatementsInBlocks step might introduce new no-op cases to the end of WrapSwitchStatementsInBlocks(root);
// switch statements, so make sure to clean up the AST.
RemoveNoOpCasesFromEndOfSwitchStatements(root, &getSymbolTable());
}
bool precisionEmulation = bool precisionEmulation =
getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision; getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;

View File

@ -479,14 +479,10 @@ bool TType::canReplaceWithConstantUnion() const
// //
const char *TType::buildMangledName() const const char *TType::buildMangledName() const
{ {
TString mangledName; TString mangledName(1, GetSizeMangledName(primarySize, secondarySize));
if (isMatrix())
mangledName += 'm';
else if (isVector())
mangledName += 'v';
const char *basicMangledName = GetBasicMangledName(type); char basicMangledName = GetBasicMangledName(type);
if (basicMangledName != nullptr) if (basicMangledName != '{')
{ {
mangledName += basicMangledName; mangledName += basicMangledName;
} }
@ -496,17 +492,19 @@ const char *TType::buildMangledName() const
switch (type) switch (type)
{ {
case EbtStruct: case EbtStruct:
mangledName += "struct-"; mangledName += "{s";
if (mStructure->symbolType() != SymbolType::Empty) if (mStructure->symbolType() != SymbolType::Empty)
{ {
mangledName += mStructure->name().data(); mangledName += mStructure->name().data();
} }
mangledName += mStructure->mangledFieldList(); mangledName += mStructure->mangledFieldList();
mangledName += '}';
break; break;
case EbtInterfaceBlock: case EbtInterfaceBlock:
mangledName += "iblock-"; mangledName += "{i";
mangledName += mInterfaceBlock->name().data(); mangledName += mInterfaceBlock->name().data();
mangledName += mInterfaceBlock->mangledFieldList(); mangledName += mInterfaceBlock->mangledFieldList();
mangledName += '}';
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
@ -514,17 +512,6 @@ const char *TType::buildMangledName() const
} }
} }
if (isMatrix())
{
mangledName += static_cast<char>('0' + getCols());
mangledName += static_cast<char>('x');
mangledName += static_cast<char>('0' + getRows());
}
else
{
mangledName += static_cast<char>('0' + getNominalSize());
}
if (mArraySizes) if (mArraySizes)
{ {
for (unsigned int arraySize : *mArraySizes) for (unsigned int arraySize : *mArraySizes)
@ -537,8 +524,6 @@ const char *TType::buildMangledName() const
} }
} }
mangledName += ';';
// Copy string contents into a pool-allocated buffer, so we never need to call delete. // Copy string contents into a pool-allocated buffer, so we never need to call delete.
return AllocatePoolCharArray(mangledName.c_str(), mangledName.size()); return AllocatePoolCharArray(mangledName.c_str(), mangledName.size());
} }
@ -779,11 +764,6 @@ void TType::realize()
getMangledName(); getMangledName();
} }
bool TType::isRealized() const
{
return mMangledName != nullptr;
}
void TType::invalidateMangledName() void TType::invalidateMangledName()
{ {
mMangledName = nullptr; mMangledName = nullptr;
@ -884,7 +864,6 @@ TString TFieldListCollection::buildMangledFieldList() const
TString mangledName; TString mangledName;
for (const auto *field : *mFields) for (const auto *field : *mFields)
{ {
mangledName += '-';
mangledName += field->type()->getMangledName(); mangledName += field->type()->getMangledName();
} }
return mangledName; return mangledName;

View File

@ -229,6 +229,15 @@ class TType
const TStructure *getStruct() const { return mStructure; } const TStructure *getStruct() const { return mStructure; }
static constexpr char GetSizeMangledName(unsigned char primarySize, unsigned char secondarySize)
{
unsigned int sizeKey = (secondarySize - 1u) * 4u + primarySize - 1u;
if (sizeKey < 10u)
{
return static_cast<char>('0' + sizeKey);
}
return static_cast<char>('A' + sizeKey - 10);
}
const char *getMangledName() const; const char *getMangledName() const;
bool sameNonArrayType(const TType &right) const; bool sameNonArrayType(const TType &right) const;
@ -319,8 +328,6 @@ class TType
// Initializes all lazily-initialized members. // Initializes all lazily-initialized members.
void realize(); void realize();
bool isRealized() const;
private: private:
void invalidateMangledName(); void invalidateMangledName();
const char *buildMangledName() const; const char *buildMangledName() const;

View File

@ -15,6 +15,33 @@
namespace sh namespace sh
{ {
namespace
{
void DisambiguateFunctionNameForParameterType(const TType &paramType,
TString *disambiguatingStringOut)
{
// Parameter types are only added to function names if they are ambiguous according to the
// native HLSL compiler. Other parameter types are not added to function names to avoid
// making function names longer.
if (paramType.getObjectSize() == 4 && paramType.getBasicType() == EbtFloat)
{
// Disambiguation is needed for float2x2 and float4 parameters. These are the only
// built-in types that HLSL thinks are identical. float2x3 and float3x2 are different
// types, for example.
*disambiguatingStringOut += "_" + TypeString(paramType);
}
else if (paramType.getBasicType() == EbtStruct)
{
// Disambiguation is needed for struct parameters, since HLSL thinks that structs with
// the same fields but a different name are identical.
ASSERT(paramType.getStruct()->symbolType() != SymbolType::Empty);
*disambiguatingStringOut += "_" + TypeString(paramType);
}
}
} // anonymous namespace
const char *SamplerString(const TBasicType type) const char *SamplerString(const TBasicType type)
{ {
if (IsShadowSampler(type)) if (IsShadowSampler(type))
@ -802,8 +829,10 @@ TString Decorate(const ImmutableString &string)
TString DecorateVariableIfNeeded(const TVariable &variable) TString DecorateVariableIfNeeded(const TVariable &variable)
{ {
if (variable.symbolType() == SymbolType::AngleInternal) if (variable.symbolType() == SymbolType::AngleInternal ||
variable.symbolType() == SymbolType::Empty)
{ {
// Besides handling internal variables, we generate names for nameless parameters here.
const ImmutableString &name = variable.name(); const ImmutableString &name = variable.name();
// The name should not have a prefix reserved for user-defined variables or functions. // The name should not have a prefix reserved for user-defined variables or functions.
ASSERT(!name.beginsWith("f_")); ASSERT(!name.beginsWith("f_"));
@ -1025,29 +1054,26 @@ const char *QualifierString(TQualifier qualifier)
return ""; return "";
} }
TString DisambiguateFunctionName(const TIntermSequence *parameters) TString DisambiguateFunctionName(const TFunction *func)
{ {
TString disambiguatingString; TString disambiguatingString;
for (auto parameter : *parameters) size_t paramCount = func->getParamCount();
for (size_t i = 0; i < paramCount; ++i)
{ {
const TType &paramType = parameter->getAsTyped()->getType(); DisambiguateFunctionNameForParameterType(func->getParam(i)->getType(),
// Parameter types are only added to function names if they are ambiguous according to the &disambiguatingString);
// native HLSL compiler. Other parameter types are not added to function names to avoid }
// making function names longer. return disambiguatingString;
if (paramType.getObjectSize() == 4 && paramType.getBasicType() == EbtFloat) }
{
// Disambiguation is needed for float2x2 and float4 parameters. These are the only TString DisambiguateFunctionName(const TIntermSequence *args)
// built-in types that HLSL thinks are identical. float2x3 and float3x2 are different {
// types, for example. TString disambiguatingString;
disambiguatingString += "_" + TypeString(paramType); for (TIntermNode *arg : *args)
} {
else if (paramType.getBasicType() == EbtStruct) ASSERT(arg->getAsTyped());
{ DisambiguateFunctionNameForParameterType(arg->getAsTyped()->getType(),
// Disambiguation is needed for struct parameters, since HLSL thinks that structs with &disambiguatingString);
// the same fields but a different name are identical.
ASSERT(paramType.getStruct()->symbolType() != SymbolType::Empty);
disambiguatingString += "_" + TypeString(paramType);
}
} }
return disambiguatingString; return disambiguatingString;
} }

View File

@ -19,6 +19,8 @@
namespace sh namespace sh
{ {
class TFunction;
// HLSL Texture type for GLSL sampler type and readonly image type. // HLSL Texture type for GLSL sampler type and readonly image type.
enum HLSLTextureGroup enum HLSLTextureGroup
{ {
@ -123,7 +125,8 @@ const char *InterpolationString(TQualifier qualifier);
const char *QualifierString(TQualifier qualifier); const char *QualifierString(TQualifier qualifier);
// Parameters may need to be included in function names to disambiguate between overloaded // Parameters may need to be included in function names to disambiguate between overloaded
// functions. // functions.
TString DisambiguateFunctionName(const TIntermSequence *parameters); TString DisambiguateFunctionName(const TFunction *func);
TString DisambiguateFunctionName(const TIntermSequence *args);
} }
#endif // COMPILER_TRANSLATOR_UTILSHLSL_H_ #endif // COMPILER_TRANSLATOR_UTILSHLSL_H_

View File

@ -6,7 +6,7 @@
#include "compiler/translator/ValidateGlobalInitializer.h" #include "compiler/translator/ValidateGlobalInitializer.h"
#include "compiler/translator/IntermTraverse.h" #include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh namespace sh
{ {
@ -14,6 +14,8 @@ namespace sh
namespace namespace
{ {
const int kMaxAllowedTraversalDepth = 256;
class ValidateGlobalInitializerTraverser : public TIntermTraverser class ValidateGlobalInitializerTraverser : public TIntermTraverser
{ {
public: public:
@ -25,7 +27,7 @@ class ValidateGlobalInitializerTraverser : public TIntermTraverser
bool visitBinary(Visit visit, TIntermBinary *node) override; bool visitBinary(Visit visit, TIntermBinary *node) override;
bool visitUnary(Visit visit, TIntermUnary *node) override; bool visitUnary(Visit visit, TIntermUnary *node) override;
bool isValid() const { return mIsValid; } bool isValid() const { return mIsValid && mMaxDepth < mMaxAllowedDepth; }
bool issueWarning() const { return mIssueWarning; } bool issueWarning() const { return mIssueWarning; }
private: private:
@ -117,11 +119,12 @@ bool ValidateGlobalInitializerTraverser::visitUnary(Visit visit, TIntermUnary *n
} }
ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(int shaderVersion) ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(int shaderVersion)
: TIntermTraverser(true, false, false), : TIntermTraverser(true, false, false, nullptr),
mShaderVersion(shaderVersion), mShaderVersion(shaderVersion),
mIsValid(true), mIsValid(true),
mIssueWarning(false) mIssueWarning(false)
{ {
setMaxAllowedDepth(kMaxAllowedTraversalDepth);
} }
} // namespace } // namespace

View File

@ -8,8 +8,8 @@
#include "angle_gl.h" #include "angle_gl.h"
#include "compiler/translator/Diagnostics.h" #include "compiler/translator/Diagnostics.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/ParseContext.h" #include "compiler/translator/ParseContext.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh namespace sh
{ {

View File

@ -8,6 +8,7 @@
#include "compiler/translator/ValidateMaxParameters.h" #include "compiler/translator/ValidateMaxParameters.h"
#include "compiler/translator/IntermNode.h" #include "compiler/translator/IntermNode.h"
#include "compiler/translator/Symbol.h"
namespace sh namespace sh
{ {
@ -18,7 +19,7 @@ bool ValidateMaxParameters(TIntermBlock *root, unsigned int maxParameters)
{ {
TIntermFunctionDefinition *definition = node->getAsFunctionDefinition(); TIntermFunctionDefinition *definition = node->getAsFunctionDefinition();
if (definition != nullptr && if (definition != nullptr &&
definition->getFunctionPrototype()->getSequence()->size() > maxParameters) definition->getFunctionPrototype()->getFunction()->getParamCount() > maxParameters)
{ {
return false; return false;
} }

View File

@ -12,8 +12,8 @@
#include <set> #include <set>
#include "compiler/translator/InfoSink.h" #include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/ParseContext.h" #include "compiler/translator/ParseContext.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh namespace sh
{ {

View File

@ -7,7 +7,7 @@
#include "compiler/translator/ValidateSwitch.h" #include "compiler/translator/ValidateSwitch.h"
#include "compiler/translator/Diagnostics.h" #include "compiler/translator/Diagnostics.h"
#include "compiler/translator/IntermTraverse.h" #include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh namespace sh
{ {
@ -15,11 +15,12 @@ namespace sh
namespace namespace
{ {
const int kMaxAllowedTraversalDepth = 256;
class ValidateSwitch : public TIntermTraverser class ValidateSwitch : public TIntermTraverser
{ {
public: public:
static bool validate(TBasicType switchType, static bool validate(TBasicType switchType,
int shaderVersion,
TDiagnostics *diagnostics, TDiagnostics *diagnostics,
TIntermBlock *statementList, TIntermBlock *statementList,
const TSourceLoc &loc); const TSourceLoc &loc);
@ -27,7 +28,7 @@ class ValidateSwitch : public TIntermTraverser
void visitSymbol(TIntermSymbol *) override; void visitSymbol(TIntermSymbol *) override;
void visitConstantUnion(TIntermConstantUnion *) override; void visitConstantUnion(TIntermConstantUnion *) override;
bool visitDeclaration(Visit, TIntermDeclaration *) override; bool visitDeclaration(Visit, TIntermDeclaration *) override;
bool visitBlock(Visit, TIntermBlock *) override; bool visitBlock(Visit visit, TIntermBlock *) override;
bool visitBinary(Visit, TIntermBinary *) override; bool visitBinary(Visit, TIntermBinary *) override;
bool visitUnary(Visit, TIntermUnary *) override; bool visitUnary(Visit, TIntermUnary *) override;
bool visitTernary(Visit, TIntermTernary *) override; bool visitTernary(Visit, TIntermTernary *) override;
@ -40,12 +41,11 @@ class ValidateSwitch : public TIntermTraverser
bool visitBranch(Visit, TIntermBranch *) override; bool visitBranch(Visit, TIntermBranch *) override;
private: private:
ValidateSwitch(TBasicType switchType, int shaderVersion, TDiagnostics *context); ValidateSwitch(TBasicType switchType, TDiagnostics *context);
bool validateInternal(const TSourceLoc &loc); bool validateInternal(const TSourceLoc &loc);
TBasicType mSwitchType; TBasicType mSwitchType;
int mShaderVersion;
TDiagnostics *mDiagnostics; TDiagnostics *mDiagnostics;
bool mCaseTypeMismatch; bool mCaseTypeMismatch;
bool mFirstCaseFound; bool mFirstCaseFound;
@ -60,21 +60,19 @@ class ValidateSwitch : public TIntermTraverser
}; };
bool ValidateSwitch::validate(TBasicType switchType, bool ValidateSwitch::validate(TBasicType switchType,
int shaderVersion,
TDiagnostics *diagnostics, TDiagnostics *diagnostics,
TIntermBlock *statementList, TIntermBlock *statementList,
const TSourceLoc &loc) const TSourceLoc &loc)
{ {
ValidateSwitch validate(switchType, shaderVersion, diagnostics); ValidateSwitch validate(switchType, diagnostics);
ASSERT(statementList); ASSERT(statementList);
statementList->traverse(&validate); statementList->traverse(&validate);
return validate.validateInternal(loc); return validate.validateInternal(loc);
} }
ValidateSwitch::ValidateSwitch(TBasicType switchType, int shaderVersion, TDiagnostics *diagnostics) ValidateSwitch::ValidateSwitch(TBasicType switchType, TDiagnostics *diagnostics)
: TIntermTraverser(true, false, true), : TIntermTraverser(true, false, true, nullptr),
mSwitchType(switchType), mSwitchType(switchType),
mShaderVersion(shaderVersion),
mDiagnostics(diagnostics), mDiagnostics(diagnostics),
mCaseTypeMismatch(false), mCaseTypeMismatch(false),
mFirstCaseFound(false), mFirstCaseFound(false),
@ -85,6 +83,7 @@ ValidateSwitch::ValidateSwitch(TBasicType switchType, int shaderVersion, TDiagno
mDefaultCount(0), mDefaultCount(0),
mDuplicateCases(false) mDuplicateCases(false)
{ {
setMaxAllowedDepth(kMaxAllowedTraversalDepth);
} }
void ValidateSwitch::visitSymbol(TIntermSymbol *) void ValidateSwitch::visitSymbol(TIntermSymbol *)
@ -111,13 +110,17 @@ bool ValidateSwitch::visitDeclaration(Visit, TIntermDeclaration *)
return true; return true;
} }
bool ValidateSwitch::visitBlock(Visit, TIntermBlock *) bool ValidateSwitch::visitBlock(Visit visit, TIntermBlock *)
{ {
if (getParentNode() != nullptr) if (getParentNode() != nullptr)
{ {
if (!mFirstCaseFound) if (!mFirstCaseFound)
mStatementBeforeCase = true; mStatementBeforeCase = true;
mLastStatementWasCase = false; mLastStatementWasCase = false;
if (visit == PreVisit)
++mControlFlowDepth;
if (visit == PostVisit)
--mControlFlowDepth;
} }
return true; return true;
} }
@ -281,39 +284,32 @@ bool ValidateSwitch::validateInternal(const TSourceLoc &loc)
{ {
mDiagnostics->error(loc, "statement before the first label", "switch"); mDiagnostics->error(loc, "statement before the first label", "switch");
} }
bool lastStatementWasCaseError = false;
if (mLastStatementWasCase) if (mLastStatementWasCase)
{ {
if (mShaderVersion == 300) // There have been some differences between versions of GLSL ES specs on whether this should
{ // be an error or not, but as of early 2018 the latest discussion is that this is an error
lastStatementWasCaseError = true; // also on GLSL ES versions newer than 3.00.
// This error has been proposed to be made optional in GLSL ES 3.00, but dEQP tests mDiagnostics->error(
// still require it. loc, "no statement between the last label and the end of the switch statement",
mDiagnostics->error( "switch");
loc, "no statement between the last label and the end of the switch statement",
"switch");
}
else
{
// The error has been removed from GLSL ES 3.10.
mDiagnostics->warning(
loc, "no statement between the last label and the end of the switch statement",
"switch");
}
} }
return !mStatementBeforeCase && !lastStatementWasCaseError && !mCaseInsideControlFlow && if (getMaxDepth() >= kMaxAllowedTraversalDepth)
!mCaseTypeMismatch && mDefaultCount <= 1 && !mDuplicateCases; {
mDiagnostics->error(loc, "too complex expressions inside a switch statement", "switch");
}
return !mStatementBeforeCase && !mLastStatementWasCase && !mCaseInsideControlFlow &&
!mCaseTypeMismatch && mDefaultCount <= 1 && !mDuplicateCases &&
getMaxDepth() < kMaxAllowedTraversalDepth;
} }
} // anonymous namespace } // anonymous namespace
bool ValidateSwitchStatementList(TBasicType switchType, bool ValidateSwitchStatementList(TBasicType switchType,
int shaderVersion,
TDiagnostics *diagnostics, TDiagnostics *diagnostics,
TIntermBlock *statementList, TIntermBlock *statementList,
const TSourceLoc &loc) const TSourceLoc &loc)
{ {
return ValidateSwitch::validate(switchType, shaderVersion, diagnostics, statementList, loc); return ValidateSwitch::validate(switchType, diagnostics, statementList, loc);
} }
} // namespace sh } // namespace sh

View File

@ -18,7 +18,6 @@ class TIntermBlock;
// Check for errors and output error messages on the context. // Check for errors and output error messages on the context.
// Returns true if there are no errors. // Returns true if there are no errors.
bool ValidateSwitchStatementList(TBasicType switchType, bool ValidateSwitchStatementList(TBasicType switchType,
int shaderVersion,
TDiagnostics *diagnostics, TDiagnostics *diagnostics,
TIntermBlock *statementList, TIntermBlock *statementList,
const TSourceLoc &loc); const TSourceLoc &loc);

View File

@ -10,8 +10,8 @@
#include "ValidateVaryingLocations.h" #include "ValidateVaryingLocations.h"
#include "compiler/translator/Diagnostics.h" #include "compiler/translator/Diagnostics.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/SymbolTable.h" #include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
#include "compiler/translator/util.h" #include "compiler/translator/util.h"
namespace sh namespace sh

View File

@ -105,15 +105,16 @@ bool TVersionGLSL::visitInvariantDeclaration(Visit, TIntermInvariantDeclaration
return true; return true;
} }
bool TVersionGLSL::visitFunctionPrototype(Visit, TIntermFunctionPrototype *node) void TVersionGLSL::visitFunctionPrototype(TIntermFunctionPrototype *node)
{ {
const TIntermSequence &params = *(node->getSequence()); size_t paramCount = node->getFunction()->getParamCount();
for (TIntermSequence::const_iterator iter = params.begin(); iter != params.end(); ++iter) for (size_t i = 0; i < paramCount; ++i)
{ {
const TIntermTyped *param = (*iter)->getAsTyped(); const TVariable *param = node->getFunction()->getParam(i);
if (param->isArray()) const TType &type = param->getType();
if (type.isArray())
{ {
TQualifier qualifier = param->getQualifier(); TQualifier qualifier = type.getQualifier();
if ((qualifier == EvqOut) || (qualifier == EvqInOut)) if ((qualifier == EvqOut) || (qualifier == EvqInOut))
{ {
ensureVersionIsAtLeast(GLSL_VERSION_120); ensureVersionIsAtLeast(GLSL_VERSION_120);
@ -121,8 +122,6 @@ bool TVersionGLSL::visitFunctionPrototype(Visit, TIntermFunctionPrototype *node)
} }
} }
} }
// Fully processed. No need to visit children.
return false;
} }
bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate *node) bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate *node)

View File

@ -7,7 +7,7 @@
#ifndef COMPILER_TRANSLATOR_VERSIONGLSL_H_ #ifndef COMPILER_TRANSLATOR_VERSIONGLSL_H_
#define COMPILER_TRANSLATOR_VERSIONGLSL_H_ #define COMPILER_TRANSLATOR_VERSIONGLSL_H_
#include "compiler/translator/IntermTraverse.h" #include "compiler/translator/tree_util/IntermTraverse.h"
#include "compiler/translator/Pragma.h" #include "compiler/translator/Pragma.h"
@ -62,7 +62,7 @@ class TVersionGLSL : public TIntermTraverser
void visitSymbol(TIntermSymbol *node) override; void visitSymbol(TIntermSymbol *node) override;
bool visitAggregate(Visit, TIntermAggregate *node) override; bool visitAggregate(Visit, TIntermAggregate *node) override;
bool visitInvariantDeclaration(Visit, TIntermInvariantDeclaration *node) override; bool visitInvariantDeclaration(Visit, TIntermInvariantDeclaration *node) override;
bool visitFunctionPrototype(Visit, TIntermFunctionPrototype *node) override; void visitFunctionPrototype(TIntermFunctionPrototype *node) override;
bool visitDeclaration(Visit, TIntermDeclaration *node) override; bool visitDeclaration(Visit, TIntermDeclaration *node) override;
private: private:

View File

@ -2,7 +2,7 @@
// Generated by gen_emulated_builtin_function_tables.py using data from // Generated by gen_emulated_builtin_function_tables.py using data from
// emulated_builtin_function_data_hlsl.json. // emulated_builtin_function_data_hlsl.json.
// //
// Copyright 2017 The ANGLE Project Authors. All rights reserved. // Copyright 2018 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
@ -10,6 +10,7 @@
// HLSL code for emulating GLSL builtin functions not present in HLSL. // HLSL code for emulating GLSL builtin functions not present in HLSL.
#include "compiler/translator/BuiltInFunctionEmulator.h" #include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
namespace sh namespace sh
{ {
@ -19,51 +20,52 @@ namespace
struct FunctionPair struct FunctionPair
{ {
constexpr FunctionPair(const MiniFunctionId &idIn, const char *bodyIn) : id(idIn), body(bodyIn) constexpr FunctionPair(const TSymbolUniqueId &idIn, const char *bodyIn)
: id(idIn.get()), body(bodyIn)
{ {
} }
MiniFunctionId id; int id;
const char *body; const char *body;
}; };
constexpr FunctionPair g_hlslFunctions[] = { constexpr FunctionPair g_hlslFunctions[] = {
{{EOpMod, ParamType::Float1, ParamType::Float1}, {BuiltInId::mod_Float1_Float1,
"float mod_emu(float x, float y)\n" "float mod_emu(float x, float y)\n"
"{\n" "{\n"
" return x - y * floor(x / y);\n" " return x - y * floor(x / y);\n"
"}\n"}, "}\n"},
{{EOpMod, ParamType::Float2, ParamType::Float2}, {BuiltInId::mod_Float2_Float2,
"float2 mod_emu(float2 x, float2 y)\n" "float2 mod_emu(float2 x, float2 y)\n"
"{\n" "{\n"
" return x - y * floor(x / y);\n" " return x - y * floor(x / y);\n"
"}\n"}, "}\n"},
{{EOpMod, ParamType::Float2, ParamType::Float1}, {BuiltInId::mod_Float2_Float1,
"float2 mod_emu(float2 x, float y)\n" "float2 mod_emu(float2 x, float y)\n"
"{\n" "{\n"
" return x - y * floor(x / y);\n" " return x - y * floor(x / y);\n"
"}\n"}, "}\n"},
{{EOpMod, ParamType::Float3, ParamType::Float3}, {BuiltInId::mod_Float3_Float3,
"float3 mod_emu(float3 x, float3 y)\n" "float3 mod_emu(float3 x, float3 y)\n"
"{\n" "{\n"
" return x - y * floor(x / y);\n" " return x - y * floor(x / y);\n"
"}\n"}, "}\n"},
{{EOpMod, ParamType::Float3, ParamType::Float1}, {BuiltInId::mod_Float3_Float1,
"float3 mod_emu(float3 x, float y)\n" "float3 mod_emu(float3 x, float y)\n"
"{\n" "{\n"
" return x - y * floor(x / y);\n" " return x - y * floor(x / y);\n"
"}\n"}, "}\n"},
{{EOpMod, ParamType::Float4, ParamType::Float4}, {BuiltInId::mod_Float4_Float4,
"float4 mod_emu(float4 x, float4 y)\n" "float4 mod_emu(float4 x, float4 y)\n"
"{\n" "{\n"
" return x - y * floor(x / y);\n" " return x - y * floor(x / y);\n"
"}\n"}, "}\n"},
{{EOpMod, ParamType::Float4, ParamType::Float1}, {BuiltInId::mod_Float4_Float1,
"float4 mod_emu(float4 x, float y)\n" "float4 mod_emu(float4 x, float y)\n"
"{\n" "{\n"
" return x - y * floor(x / y);\n" " return x - y * floor(x / y);\n"
"}\n"}, "}\n"},
{{EOpFrexp, ParamType::Float1, ParamType::Int1}, {BuiltInId::frexp_Float1_Int1,
"float frexp_emu(float x, out int exp)\n" "float frexp_emu(float x, out int exp)\n"
"{\n" "{\n"
" float fexp;\n" " float fexp;\n"
@ -71,7 +73,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" exp = int(fexp);\n" " exp = int(fexp);\n"
" return mantissa;\n" " return mantissa;\n"
"}\n"}, "}\n"},
{{EOpFrexp, ParamType::Float2, ParamType::Int2}, {BuiltInId::frexp_Float2_Int2,
"float2 frexp_emu(float2 x, out int2 exp)\n" "float2 frexp_emu(float2 x, out int2 exp)\n"
"{\n" "{\n"
" float2 fexp;\n" " float2 fexp;\n"
@ -79,7 +81,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" exp = int2(fexp);\n" " exp = int2(fexp);\n"
" return mantissa;\n" " return mantissa;\n"
"}\n"}, "}\n"},
{{EOpFrexp, ParamType::Float3, ParamType::Int3}, {BuiltInId::frexp_Float3_Int3,
"float3 frexp_emu(float3 x, out int3 exp)\n" "float3 frexp_emu(float3 x, out int3 exp)\n"
"{\n" "{\n"
" float3 fexp;\n" " float3 fexp;\n"
@ -87,7 +89,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" exp = int3(fexp);\n" " exp = int3(fexp);\n"
" return mantissa;\n" " return mantissa;\n"
"}\n"}, "}\n"},
{{EOpFrexp, ParamType::Float4, ParamType::Int4}, {BuiltInId::frexp_Float4_Int4,
"float4 frexp_emu(float4 x, out int4 exp)\n" "float4 frexp_emu(float4 x, out int4 exp)\n"
"{\n" "{\n"
" float4 fexp;\n" " float4 fexp;\n"
@ -95,27 +97,27 @@ constexpr FunctionPair g_hlslFunctions[] = {
" exp = int4(fexp);\n" " exp = int4(fexp);\n"
" return mantissa;\n" " return mantissa;\n"
"}\n"}, "}\n"},
{{EOpLdexp, ParamType::Float1, ParamType::Int1}, {BuiltInId::ldexp_Float1_Int1,
"float ldexp_emu(float x, int exp)\n" "float ldexp_emu(float x, int exp)\n"
"{\n" "{\n"
" return ldexp(x, float(exp));\n" " return ldexp(x, float(exp));\n"
"}\n"}, "}\n"},
{{EOpLdexp, ParamType::Float2, ParamType::Int2}, {BuiltInId::ldexp_Float2_Int2,
"float2 ldexp_emu(float2 x, int2 exp)\n" "float2 ldexp_emu(float2 x, int2 exp)\n"
"{\n" "{\n"
" return ldexp(x, float2(exp));\n" " return ldexp(x, float2(exp));\n"
"}\n"}, "}\n"},
{{EOpLdexp, ParamType::Float3, ParamType::Int3}, {BuiltInId::ldexp_Float3_Int3,
"float3 ldexp_emu(float3 x, int3 exp)\n" "float3 ldexp_emu(float3 x, int3 exp)\n"
"{\n" "{\n"
" return ldexp(x, float3(exp));\n" " return ldexp(x, float3(exp));\n"
"}\n"}, "}\n"},
{{EOpLdexp, ParamType::Float4, ParamType::Int4}, {BuiltInId::ldexp_Float4_Int4,
"float4 ldexp_emu(float4 x, int4 exp)\n" "float4 ldexp_emu(float4 x, int4 exp)\n"
"{\n" "{\n"
" return ldexp(x, float4(exp));\n" " return ldexp(x, float4(exp));\n"
"}\n"}, "}\n"},
{{EOpFaceforward, ParamType::Float1, ParamType::Float1, ParamType::Float1}, {BuiltInId::faceforward_Float1_Float1_Float1,
"float faceforward_emu(float N, float I, float Nref)\n" "float faceforward_emu(float N, float I, float Nref)\n"
"{\n" "{\n"
" if(dot(Nref, I) >= 0)\n" " if(dot(Nref, I) >= 0)\n"
@ -127,7 +129,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return N;\n" " return N;\n"
" }\n" " }\n"
"}\n"}, "}\n"},
{{EOpFaceforward, ParamType::Float2, ParamType::Float2, ParamType::Float2}, {BuiltInId::faceforward_Float2_Float2_Float2,
"float2 faceforward_emu(float2 N, float2 I, float2 Nref)\n" "float2 faceforward_emu(float2 N, float2 I, float2 Nref)\n"
"{\n" "{\n"
" if(dot(Nref, I) >= 0)\n" " if(dot(Nref, I) >= 0)\n"
@ -139,7 +141,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return N;\n" " return N;\n"
" }\n" " }\n"
"}\n"}, "}\n"},
{{EOpFaceforward, ParamType::Float3, ParamType::Float3, ParamType::Float3}, {BuiltInId::faceforward_Float3_Float3_Float3,
"float3 faceforward_emu(float3 N, float3 I, float3 Nref)\n" "float3 faceforward_emu(float3 N, float3 I, float3 Nref)\n"
"{\n" "{\n"
" if(dot(Nref, I) >= 0)\n" " if(dot(Nref, I) >= 0)\n"
@ -151,7 +153,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return N;\n" " return N;\n"
" }\n" " }\n"
"}\n"}, "}\n"},
{{EOpFaceforward, ParamType::Float4, ParamType::Float4, ParamType::Float4}, {BuiltInId::faceforward_Float4_Float4_Float4,
"float4 faceforward_emu(float4 N, float4 I, float4 Nref)\n" "float4 faceforward_emu(float4 N, float4 I, float4 Nref)\n"
"{\n" "{\n"
" if(dot(Nref, I) >= 0)\n" " if(dot(Nref, I) >= 0)\n"
@ -163,20 +165,20 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return N;\n" " return N;\n"
" }\n" " }\n"
"}\n"}, "}\n"},
{{EOpAtan, ParamType::Float1, ParamType::Float1}, {BuiltInId::atan_Float1_Float1,
"float atan_emu(float y, float x)\n" "float atan_emu(float y, float x)\n"
"{\n" "{\n"
" if(x == 0 && y == 0) x = 1;\n" " if(x == 0 && y == 0) x = 1;\n"
" return atan2(y, x);\n" " return atan2(y, x);\n"
"}\n"}, "}\n"},
{{EOpAtan, ParamType::Float2, ParamType::Float2}, {BuiltInId::atan_Float2_Float2,
"float2 atan_emu(float2 y, float2 x)\n" "float2 atan_emu(float2 y, float2 x)\n"
"{\n" "{\n"
" if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
" if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
" return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n" " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n"
"}\n"}, "}\n"},
{{EOpAtan, ParamType::Float3, ParamType::Float3}, {BuiltInId::atan_Float3_Float3,
"float3 atan_emu(float3 y, float3 x)\n" "float3 atan_emu(float3 y, float3 x)\n"
"{\n" "{\n"
" if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
@ -184,7 +186,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
" return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n" " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n"
"}\n"}, "}\n"},
{{EOpAtan, ParamType::Float4, ParamType::Float4}, {BuiltInId::atan_Float4_Float4,
"float4 atan_emu(float4 y, float4 x)\n" "float4 atan_emu(float4 y, float4 x)\n"
"{\n" "{\n"
" if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
@ -194,72 +196,72 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], \n" " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], \n"
" x[2]), atan2(y[3], x[3]));\n" " x[2]), atan2(y[3], x[3]));\n"
"}\n"}, "}\n"},
{{EOpAsinh, ParamType::Float1}, {BuiltInId::asinh_Float1,
"float asinh_emu(in float x)\n" "float asinh_emu(in float x)\n"
"{\n" "{\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n" " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n"}, "}\n"},
{{EOpAsinh, ParamType::Float2}, {BuiltInId::asinh_Float2,
"float2 asinh_emu(in float2 x)\n" "float2 asinh_emu(in float2 x)\n"
"{\n" "{\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n" " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n"}, "}\n"},
{{EOpAsinh, ParamType::Float3}, {BuiltInId::asinh_Float3,
"float3 asinh_emu(in float3 x)\n" "float3 asinh_emu(in float3 x)\n"
"{\n" "{\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n" " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n"}, "}\n"},
{{EOpAsinh, ParamType::Float4}, {BuiltInId::asinh_Float4,
"float4 asinh_emu(in float4 x)\n" "float4 asinh_emu(in float4 x)\n"
"{\n" "{\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n" " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n"}, "}\n"},
{{EOpAcosh, ParamType::Float1}, {BuiltInId::acosh_Float1,
"float acosh_emu(in float x)\n" "float acosh_emu(in float x)\n"
"{\n" "{\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n"}, "}\n"},
{{EOpAcosh, ParamType::Float2}, {BuiltInId::acosh_Float2,
"float2 acosh_emu(in float2 x)\n" "float2 acosh_emu(in float2 x)\n"
"{\n" "{\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n"}, "}\n"},
{{EOpAcosh, ParamType::Float3}, {BuiltInId::acosh_Float3,
"float3 acosh_emu(in float3 x)\n" "float3 acosh_emu(in float3 x)\n"
"{\n" "{\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n"}, "}\n"},
{{EOpAcosh, ParamType::Float4}, {BuiltInId::acosh_Float4,
"float4 acosh_emu(in float4 x)\n" "float4 acosh_emu(in float4 x)\n"
"{\n" "{\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n"}, "}\n"},
{{EOpAtanh, ParamType::Float1}, {BuiltInId::atanh_Float1,
"float atanh_emu(in float x)\n" "float atanh_emu(in float x)\n"
"{\n" "{\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n" " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n"}, "}\n"},
{{EOpAtanh, ParamType::Float2}, {BuiltInId::atanh_Float2,
"float2 atanh_emu(in float2 x)\n" "float2 atanh_emu(in float2 x)\n"
"{\n" "{\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n" " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n"}, "}\n"},
{{EOpAtanh, ParamType::Float3}, {BuiltInId::atanh_Float3,
"float3 atanh_emu(in float3 x)\n" "float3 atanh_emu(in float3 x)\n"
"{\n" "{\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n" " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n"}, "}\n"},
{{EOpAtanh, ParamType::Float4}, {BuiltInId::atanh_Float4,
"float4 atanh_emu(in float4 x)\n" "float4 atanh_emu(in float4 x)\n"
"{\n" "{\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n" " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n"}, "}\n"},
{{EOpRoundEven, ParamType::Float1}, {BuiltInId::roundEven_Float1,
"float roundEven_emu(in float x)\n" "float roundEven_emu(in float x)\n"
"{\n" "{\n"
" return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);\n" " return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);\n"
"}\n"}, "}\n"},
{{EOpRoundEven, ParamType::Float2}, {BuiltInId::roundEven_Float2,
"float2 roundEven_emu(in float2 x)\n" "float2 roundEven_emu(in float2 x)\n"
"{\n" "{\n"
" float2 v;\n" " float2 v;\n"
@ -267,7 +269,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n" " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
" return v;\n" " return v;\n"
"}\n"}, "}\n"},
{{EOpRoundEven, ParamType::Float3}, {BuiltInId::roundEven_Float3,
"float3 roundEven_emu(in float3 x)\n" "float3 roundEven_emu(in float3 x)\n"
"{\n" "{\n"
" float3 v;\n" " float3 v;\n"
@ -276,7 +278,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n" " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n"
" return v;\n" " return v;\n"
"}\n"}, "}\n"},
{{EOpRoundEven, ParamType::Float4}, {BuiltInId::roundEven_Float4,
"float4 roundEven_emu(in float4 x)\n" "float4 roundEven_emu(in float4 x)\n"
"{\n" "{\n"
" float4 v;\n" " float4 v;\n"
@ -286,7 +288,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);\n" " v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);\n"
" return v;\n" " return v;\n"
"}\n"}, "}\n"},
{{EOpPackSnorm2x16, ParamType::Float2}, {BuiltInId::packSnorm2x16_Float2,
"int webgl_toSnorm16(in float x) {\n" "int webgl_toSnorm16(in float x) {\n"
" return int(round(clamp(x, -1.0, 1.0) * 32767.0));\n" " return int(round(clamp(x, -1.0, 1.0) * 32767.0));\n"
"}\n" "}\n"
@ -296,7 +298,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" int y = webgl_toSnorm16(v.y);\n" " int y = webgl_toSnorm16(v.y);\n"
" return (asuint(y) << 16) | (asuint(x) & 0xffffu);\n" " return (asuint(y) << 16) | (asuint(x) & 0xffffu);\n"
"}\n"}, "}\n"},
{{EOpPackUnorm2x16, ParamType::Float2}, {BuiltInId::packUnorm2x16_Float2,
"uint webgl_toUnorm16(in float x) {\n" "uint webgl_toUnorm16(in float x) {\n"
" return uint(round(clamp(x, 0.0, 1.0) * 65535.0));\n" " return uint(round(clamp(x, 0.0, 1.0) * 65535.0));\n"
"}\n" "}\n"
@ -306,14 +308,14 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint y = webgl_toUnorm16(v.y);\n" " uint y = webgl_toUnorm16(v.y);\n"
" return (y << 16) | x;\n" " return (y << 16) | x;\n"
"}\n"}, "}\n"},
{{EOpPackHalf2x16, ParamType::Float2}, {BuiltInId::packHalf2x16_Float2,
"uint packHalf2x16_emu(in float2 v)\n" "uint packHalf2x16_emu(in float2 v)\n"
"{\n" "{\n"
" uint x = f32tof16(v.x);\n" " uint x = f32tof16(v.x);\n"
" uint y = f32tof16(v.y);\n" " uint y = f32tof16(v.y);\n"
" return (y << 16) | x;\n" " return (y << 16) | x;\n"
"}\n"}, "}\n"},
{{EOpUnpackSnorm2x16, ParamType::Uint1}, {BuiltInId::unpackSnorm2x16_UInt1,
"float webgl_fromSnorm16(in uint x) {\n" "float webgl_fromSnorm16(in uint x) {\n"
" int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);\n" " int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);\n"
" return clamp(float(xi) / 32767.0, -1.0, 1.0);\n" " return clamp(float(xi) / 32767.0, -1.0, 1.0);\n"
@ -324,7 +326,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint x = u;\n" " uint x = u;\n"
" return float2(webgl_fromSnorm16(x), webgl_fromSnorm16(y));\n" " return float2(webgl_fromSnorm16(x), webgl_fromSnorm16(y));\n"
"}\n"}, "}\n"},
{{EOpUnpackUnorm2x16, ParamType::Uint1}, {BuiltInId::unpackUnorm2x16_UInt1,
"float webgl_fromUnorm16(in uint x) {\n" "float webgl_fromUnorm16(in uint x) {\n"
" return float(x) / 65535.0;\n" " return float(x) / 65535.0;\n"
"}\n" "}\n"
@ -334,14 +336,14 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint x = u & 0xffffu;\n" " uint x = u & 0xffffu;\n"
" return float2(webgl_fromUnorm16(x), webgl_fromUnorm16(y));\n" " return float2(webgl_fromUnorm16(x), webgl_fromUnorm16(y));\n"
"}\n"}, "}\n"},
{{EOpUnpackHalf2x16, ParamType::Uint1}, {BuiltInId::unpackHalf2x16_UInt1,
"float2 unpackHalf2x16_emu(in uint u)\n" "float2 unpackHalf2x16_emu(in uint u)\n"
"{\n" "{\n"
" uint y = (u >> 16);\n" " uint y = (u >> 16);\n"
" uint x = u & 0xffffu;\n" " uint x = u & 0xffffu;\n"
" return float2(f16tof32(x), f16tof32(y));\n" " return float2(f16tof32(x), f16tof32(y));\n"
"}\n"}, "}\n"},
{{EOpPackSnorm4x8, ParamType::Float4}, {BuiltInId::packSnorm4x8_Float4,
"int webgl_toSnorm8(in float x) {\n" "int webgl_toSnorm8(in float x) {\n"
" return int(round(clamp(x, -1.0, 1.0) * 127.0));\n" " return int(round(clamp(x, -1.0, 1.0) * 127.0));\n"
"}\n" "}\n"
@ -354,7 +356,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return ((asuint(w) & 0xffu) << 24) | ((asuint(z) & 0xffu) << 16) \n" " return ((asuint(w) & 0xffu) << 24) | ((asuint(z) & 0xffu) << 16) \n"
" | ((asuint(y) & 0xffu) << 8) | (asuint(x) & 0xffu);\n" " | ((asuint(y) & 0xffu) << 8) | (asuint(x) & 0xffu);\n"
"}\n"}, "}\n"},
{{EOpPackUnorm4x8, ParamType::Float4}, {BuiltInId::packUnorm4x8_Float4,
"uint webgl_toUnorm8(in float x) {\n" "uint webgl_toUnorm8(in float x) {\n"
" return uint(round(clamp(x, 0.0, 1.0) * 255.0));\n" " return uint(round(clamp(x, 0.0, 1.0) * 255.0));\n"
"}\n" "}\n"
@ -366,7 +368,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint w = webgl_toUnorm8(v.w);\n" " uint w = webgl_toUnorm8(v.w);\n"
" return (w << 24) | (z << 16) | (y << 8) | x;\n" " return (w << 24) | (z << 16) | (y << 8) | x;\n"
"}\n"}, "}\n"},
{{EOpUnpackSnorm4x8, ParamType::Uint1}, {BuiltInId::unpackSnorm4x8_UInt1,
"float webgl_fromSnorm8(in uint x) {\n" "float webgl_fromSnorm8(in uint x) {\n"
" int xi = asint(x & 0x7fu) - asint(x & 0x80u);\n" " int xi = asint(x & 0x7fu) - asint(x & 0x80u);\n"
" return clamp(float(xi) / 127.0, -1.0, 1.0);\n" " return clamp(float(xi) / 127.0, -1.0, 1.0);\n"
@ -380,7 +382,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return float4(webgl_fromSnorm8(x), webgl_fromSnorm8(y), \n" " return float4(webgl_fromSnorm8(x), webgl_fromSnorm8(y), \n"
" webgl_fromSnorm8(z), webgl_fromSnorm8(w));\n" " webgl_fromSnorm8(z), webgl_fromSnorm8(w));\n"
"}\n"}, "}\n"},
{{EOpUnpackUnorm4x8, ParamType::Uint1}, {BuiltInId::unpackUnorm4x8_UInt1,
"float webgl_fromUnorm8(in uint x) {\n" "float webgl_fromUnorm8(in uint x) {\n"
" return float(x) / 255.0;\n" " return float(x) / 255.0;\n"
"}\n" "}\n"
@ -402,47 +404,47 @@ constexpr FunctionPair g_hlslFunctions[] = {
// transpose(r) and transpose(c) are in a sense free, since to get the // transpose(r) and transpose(c) are in a sense free, since to get the
// transpose of r, we simply can build a column matrix out of the original // transpose of r, we simply can build a column matrix out of the original
// vector instead of a row matrix. // vector instead of a row matrix.
{{EOpOuterProduct, ParamType::Float2, ParamType::Float2}, {BuiltInId::outerProduct_Float2_Float2,
"float2x2 outerProduct_emu(in float2 c, in float2 r)\n" "float2x2 outerProduct_emu(in float2 c, in float2 r)\n"
"{\n" "{\n"
" return mul(float2x1(r), float1x2(c));\n" " return mul(float2x1(r), float1x2(c));\n"
"}\n"}, "}\n"},
{{EOpOuterProduct, ParamType::Float3, ParamType::Float3}, {BuiltInId::outerProduct_Float3_Float3,
"float3x3 outerProduct_emu(in float3 c, in float3 r)\n" "float3x3 outerProduct_emu(in float3 c, in float3 r)\n"
"{\n" "{\n"
" return mul(float3x1(r), float1x3(c));\n" " return mul(float3x1(r), float1x3(c));\n"
"}\n"}, "}\n"},
{{EOpOuterProduct, ParamType::Float4, ParamType::Float4}, {BuiltInId::outerProduct_Float4_Float4,
"float4x4 outerProduct_emu(in float4 c, in float4 r)\n" "float4x4 outerProduct_emu(in float4 c, in float4 r)\n"
"{\n" "{\n"
" return mul(float4x1(r), float1x4(c));\n" " return mul(float4x1(r), float1x4(c));\n"
"}\n"}, "}\n"},
{{EOpOuterProduct, ParamType::Float3, ParamType::Float2}, {BuiltInId::outerProduct_Float3_Float2,
"float2x3 outerProduct_emu(in float3 c, in float2 r)\n" "float2x3 outerProduct_emu(in float3 c, in float2 r)\n"
"{\n" "{\n"
" return mul(float2x1(r), float1x3(c));\n" " return mul(float2x1(r), float1x3(c));\n"
"}\n"}, "}\n"},
{{EOpOuterProduct, ParamType::Float2, ParamType::Float3}, {BuiltInId::outerProduct_Float2_Float3,
"float3x2 outerProduct_emu(in float2 c, in float3 r)\n" "float3x2 outerProduct_emu(in float2 c, in float3 r)\n"
"{\n" "{\n"
" return mul(float3x1(r), float1x2(c));\n" " return mul(float3x1(r), float1x2(c));\n"
"}\n"}, "}\n"},
{{EOpOuterProduct, ParamType::Float4, ParamType::Float2}, {BuiltInId::outerProduct_Float4_Float2,
"float2x4 outerProduct_emu(in float4 c, in float2 r)\n" "float2x4 outerProduct_emu(in float4 c, in float2 r)\n"
"{\n" "{\n"
" return mul(float2x1(r), float1x4(c));\n" " return mul(float2x1(r), float1x4(c));\n"
"}\n"}, "}\n"},
{{EOpOuterProduct, ParamType::Float2, ParamType::Float4}, {BuiltInId::outerProduct_Float2_Float4,
"float4x2 outerProduct_emu(in float2 c, in float4 r)\n" "float4x2 outerProduct_emu(in float2 c, in float4 r)\n"
"{\n" "{\n"
" return mul(float4x1(r), float1x2(c));\n" " return mul(float4x1(r), float1x2(c));\n"
"}\n"}, "}\n"},
{{EOpOuterProduct, ParamType::Float4, ParamType::Float3}, {BuiltInId::outerProduct_Float4_Float3,
"float3x4 outerProduct_emu(in float4 c, in float3 r)\n" "float3x4 outerProduct_emu(in float4 c, in float3 r)\n"
"{\n" "{\n"
" return mul(float3x1(r), float1x4(c));\n" " return mul(float3x1(r), float1x4(c));\n"
"}\n"}, "}\n"},
{{EOpOuterProduct, ParamType::Float3, ParamType::Float4}, {BuiltInId::outerProduct_Float3_Float4,
"float4x3 outerProduct_emu(in float3 c, in float4 r)\n" "float4x3 outerProduct_emu(in float3 c, in float4 r)\n"
"{\n" "{\n"
" return mul(float4x1(r), float1x3(c));\n" " return mul(float4x1(r), float1x3(c));\n"
@ -458,14 +460,14 @@ constexpr FunctionPair g_hlslFunctions[] = {
// which happens to be the cofactor matrix. That's stored in 'cof'. // which happens to be the cofactor matrix. That's stored in 'cof'.
// We don't need to care about divide-by-zero since results are undefined // We don't need to care about divide-by-zero since results are undefined
// for singular or poorly-conditioned matrices. // for singular or poorly-conditioned matrices.
{{EOpInverse, ParamType::Mat2}, {BuiltInId::inverse_Float2x2,
"float2x2 inverse_emu(in float2x2 m)\n" "float2x2 inverse_emu(in float2x2 m)\n"
"{\n" "{\n"
" float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };\n" " float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };\n"
" return cof / determinant(transpose(m));\n" " return cof / determinant(transpose(m));\n"
"}\n"}, "}\n"},
// cofAB is the cofactor for column A and row B. // cofAB is the cofactor for column A and row B.
{{EOpInverse, ParamType::Mat3}, {BuiltInId::inverse_Float3x3,
"float3x3 inverse_emu(in float3x3 m)\n" "float3x3 inverse_emu(in float3x3 m)\n"
"{\n" "{\n"
" float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];\n" " float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];\n"
@ -480,7 +482,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };\n" " float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };\n"
" return cof / determinant(transpose(m));\n" " return cof / determinant(transpose(m));\n"
"}\n"}, "}\n"},
{{EOpInverse, ParamType::Mat4}, {BuiltInId::inverse_Float4x4,
"float4x4 inverse_emu(in float4x4 m)\n" "float4x4 inverse_emu(in float4x4 m)\n"
"{\n" "{\n"
" float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * \n" " float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * \n"
@ -556,27 +558,27 @@ constexpr FunctionPair g_hlslFunctions[] = {
// comes from. For a component of 'a' that is false, the corresponding component of 'x' is // 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. For a component of 'a' that is true, the corresponding component of 'y' is
// returned. // returned.
{{EOpMix, ParamType::Float1, ParamType::Float1, ParamType::Bool1}, {BuiltInId::mix_Float1_Float1_Bool1,
"float mix_emu(float x, float y, bool a)\n" "float mix_emu(float x, float y, bool a)\n"
"{\n" "{\n"
" return a ? y : x;\n" " return a ? y : x;\n"
"}\n"}, "}\n"},
{{EOpMix, ParamType::Float2, ParamType::Float2, ParamType::Bool2}, {BuiltInId::mix_Float2_Float2_Bool2,
"float2 mix_emu(float2 x, float2 y, bool2 a)\n" "float2 mix_emu(float2 x, float2 y, bool2 a)\n"
"{\n" "{\n"
" return a ? y : x;\n" " return a ? y : x;\n"
"}\n"}, "}\n"},
{{EOpMix, ParamType::Float3, ParamType::Float3, ParamType::Bool3}, {BuiltInId::mix_Float3_Float3_Bool3,
"float3 mix_emu(float3 x, float3 y, bool3 a)\n" "float3 mix_emu(float3 x, float3 y, bool3 a)\n"
"{\n" "{\n"
" return a ? y : x;\n" " return a ? y : x;\n"
"}\n"}, "}\n"},
{{EOpMix, ParamType::Float4, ParamType::Float4, ParamType::Bool4}, {BuiltInId::mix_Float4_Float4_Bool4,
"float4 mix_emu(float4 x, float4 y, bool4 a)\n" "float4 mix_emu(float4 x, float4 y, bool4 a)\n"
"{\n" "{\n"
" return a ? y : x;\n" " return a ? y : x;\n"
"}\n"}, "}\n"},
{{EOpBitfieldExtract, ParamType::Uint1, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldExtract_UInt1_Int1_Int1,
"uint bitfieldExtract_emu(uint value, int offset, int bits)\n" "uint bitfieldExtract_emu(uint value, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -587,7 +589,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" return (value & mask) >> offset;\n" " return (value & mask) >> offset;\n"
"}\n"}, "}\n"},
{{EOpBitfieldExtract, ParamType::Uint2, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldExtract_UInt2_Int1_Int1,
"uint2 bitfieldExtract_emu(uint2 value, int offset, int bits)\n" "uint2 bitfieldExtract_emu(uint2 value, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -598,7 +600,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" return (value & mask) >> offset;\n" " return (value & mask) >> offset;\n"
"}\n"}, "}\n"},
{{EOpBitfieldExtract, ParamType::Uint3, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldExtract_UInt3_Int1_Int1,
"uint3 bitfieldExtract_emu(uint3 value, int offset, int bits)\n" "uint3 bitfieldExtract_emu(uint3 value, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -609,7 +611,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" return (value & mask) >> offset;\n" " return (value & mask) >> offset;\n"
"}\n"}, "}\n"},
{{EOpBitfieldExtract, ParamType::Uint4, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldExtract_UInt4_Int1_Int1,
"uint4 bitfieldExtract_emu(uint4 value, int offset, int bits)\n" "uint4 bitfieldExtract_emu(uint4 value, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -620,7 +622,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" return (value & mask) >> offset;\n" " return (value & mask) >> offset;\n"
"}\n"}, "}\n"},
{{EOpBitfieldExtract, ParamType::Int1, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldExtract_Int1_Int1_Int1,
"int bitfieldExtract_emu(int value, int offset, int bits)\n" "int bitfieldExtract_emu(int value, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -637,7 +639,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" }\n" " }\n"
" return asint(resultUnsigned);\n" " return asint(resultUnsigned);\n"
"}\n"}, "}\n"},
{{EOpBitfieldExtract, ParamType::Int2, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldExtract_Int2_Int1_Int1,
"int2 bitfieldExtract_emu(int2 value, int offset, int bits)\n" "int2 bitfieldExtract_emu(int2 value, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -654,7 +656,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" }\n" " }\n"
" return asint(resultUnsigned);\n" " return asint(resultUnsigned);\n"
"}\n"}, "}\n"},
{{EOpBitfieldExtract, ParamType::Int3, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldExtract_Int3_Int1_Int1,
"int3 bitfieldExtract_emu(int3 value, int offset, int bits)\n" "int3 bitfieldExtract_emu(int3 value, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -671,7 +673,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" }\n" " }\n"
" return asint(resultUnsigned);\n" " return asint(resultUnsigned);\n"
"}\n"}, "}\n"},
{{EOpBitfieldExtract, ParamType::Int4, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldExtract_Int4_Int1_Int1,
"int4 bitfieldExtract_emu(int4 value, int offset, int bits)\n" "int4 bitfieldExtract_emu(int4 value, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -688,7 +690,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" }\n" " }\n"
" return asint(resultUnsigned);\n" " return asint(resultUnsigned);\n"
"}\n"}, "}\n"},
{{EOpBitfieldInsert, ParamType::Uint1, ParamType::Uint1, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldInsert_UInt1_UInt1_Int1_Int1,
"uint bitfieldInsert_emu(uint base, uint insert, int offset, int bits)\n" "uint bitfieldInsert_emu(uint base, uint insert, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -700,7 +702,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint baseMask = ~insertMask;\n" " uint baseMask = ~insertMask;\n"
" return (base & baseMask) | ((insert << offset) & insertMask);\n" " return (base & baseMask) | ((insert << offset) & insertMask);\n"
"}\n"}, "}\n"},
{{EOpBitfieldInsert, ParamType::Uint2, ParamType::Uint2, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldInsert_UInt2_UInt2_Int1_Int1,
"uint2 bitfieldInsert_emu(uint2 base, uint2 insert, int offset, int bits)\n" "uint2 bitfieldInsert_emu(uint2 base, uint2 insert, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -712,7 +714,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint baseMask = ~insertMask;\n" " uint baseMask = ~insertMask;\n"
" return (base & baseMask) | ((insert << offset) & insertMask);\n" " return (base & baseMask) | ((insert << offset) & insertMask);\n"
"}\n"}, "}\n"},
{{EOpBitfieldInsert, ParamType::Uint3, ParamType::Uint3, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldInsert_UInt3_UInt3_Int1_Int1,
"uint3 bitfieldInsert_emu(uint3 base, uint3 insert, int offset, int bits)\n" "uint3 bitfieldInsert_emu(uint3 base, uint3 insert, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -724,7 +726,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint baseMask = ~insertMask;\n" " uint baseMask = ~insertMask;\n"
" return (base & baseMask) | ((insert << offset) & insertMask);\n" " return (base & baseMask) | ((insert << offset) & insertMask);\n"
"}\n"}, "}\n"},
{{EOpBitfieldInsert, ParamType::Uint4, ParamType::Uint4, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldInsert_UInt4_UInt4_Int1_Int1,
"uint4 bitfieldInsert_emu(uint4 base, uint4 insert, int offset, int bits)\n" "uint4 bitfieldInsert_emu(uint4 base, uint4 insert, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -736,7 +738,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint baseMask = ~insertMask;\n" " uint baseMask = ~insertMask;\n"
" return (base & baseMask) | ((insert << offset) & insertMask);\n" " return (base & baseMask) | ((insert << offset) & insertMask);\n"
"}\n"}, "}\n"},
{{EOpBitfieldInsert, ParamType::Int1, ParamType::Int1, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldInsert_Int1_Int1_Int1_Int1,
"int bitfieldInsert_emu(int base, int insert, int offset, int bits)\n" "int bitfieldInsert_emu(int base, int insert, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -750,7 +752,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" insertMask);\n" " insertMask);\n"
" return asint(resultUnsigned);\n" " return asint(resultUnsigned);\n"
"}\n"}, "}\n"},
{{EOpBitfieldInsert, ParamType::Int2, ParamType::Int2, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldInsert_Int2_Int2_Int1_Int1,
"int2 bitfieldInsert_emu(int2 base, int2 insert, int offset, int bits)\n" "int2 bitfieldInsert_emu(int2 base, int2 insert, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -764,7 +766,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" insertMask);\n" " insertMask);\n"
" return asint(resultUnsigned);\n" " return asint(resultUnsigned);\n"
"}\n"}, "}\n"},
{{EOpBitfieldInsert, ParamType::Int3, ParamType::Int3, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldInsert_Int3_Int3_Int1_Int1,
"int3 bitfieldInsert_emu(int3 base, int3 insert, int offset, int bits)\n" "int3 bitfieldInsert_emu(int3 base, int3 insert, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -778,7 +780,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" insertMask);\n" " insertMask);\n"
" return asint(resultUnsigned);\n" " return asint(resultUnsigned);\n"
"}\n"}, "}\n"},
{{EOpBitfieldInsert, ParamType::Int4, ParamType::Int4, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldInsert_Int4_Int4_Int1_Int1,
"int4 bitfieldInsert_emu(int4 base, int4 insert, int offset, int bits)\n" "int4 bitfieldInsert_emu(int4 base, int4 insert, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -792,71 +794,71 @@ constexpr FunctionPair g_hlslFunctions[] = {
" insertMask);\n" " insertMask);\n"
" return asint(resultUnsigned);\n" " return asint(resultUnsigned);\n"
"}\n"}, "}\n"},
{{EOpUaddCarry, ParamType::Uint1, ParamType::Uint1, ParamType::Uint1}, {BuiltInId::uaddCarry_UInt1_UInt1_UInt1,
"uint uaddCarry_emu(uint x, uint y, out uint carry)\n" "uint uaddCarry_emu(uint x, uint y, out uint carry)\n"
"{\n" "{\n"
" carry = uint(x > (0xffffffffu - y));\n" " carry = uint(x > (0xffffffffu - y));\n"
" return x + y;\n" " return x + y;\n"
"}\n"}, "}\n"},
{{EOpUaddCarry, ParamType::Uint2, ParamType::Uint2, ParamType::Uint2}, {BuiltInId::uaddCarry_UInt2_UInt2_UInt2,
"uint2 uaddCarry_emu(uint2 x, uint2 y, out uint2 carry)\n" "uint2 uaddCarry_emu(uint2 x, uint2 y, out uint2 carry)\n"
"{\n" "{\n"
" carry = uint2(x > (0xffffffffu - y));\n" " carry = uint2(x > (0xffffffffu - y));\n"
" return x + y;\n" " return x + y;\n"
"}\n"}, "}\n"},
{{EOpUaddCarry, ParamType::Uint3, ParamType::Uint3, ParamType::Uint3}, {BuiltInId::uaddCarry_UInt3_UInt3_UInt3,
"uint3 uaddCarry_emu(uint3 x, uint3 y, out uint3 carry)\n" "uint3 uaddCarry_emu(uint3 x, uint3 y, out uint3 carry)\n"
"{\n" "{\n"
" carry = uint3(x > (0xffffffffu - y));\n" " carry = uint3(x > (0xffffffffu - y));\n"
" return x + y;\n" " return x + y;\n"
"}\n"}, "}\n"},
{{EOpUaddCarry, ParamType::Uint4, ParamType::Uint4, ParamType::Uint4}, {BuiltInId::uaddCarry_UInt4_UInt4_UInt4,
"uint4 uaddCarry_emu(uint4 x, uint4 y, out uint4 carry)\n" "uint4 uaddCarry_emu(uint4 x, uint4 y, out uint4 carry)\n"
"{\n" "{\n"
" carry = uint4(x > (0xffffffffu - y));\n" " carry = uint4(x > (0xffffffffu - y));\n"
" return x + y;\n" " return x + y;\n"
"}\n"}, "}\n"},
{{EOpUsubBorrow, ParamType::Uint1, ParamType::Uint1, ParamType::Uint1}, {BuiltInId::usubBorrow_UInt1_UInt1_UInt1,
"uint usubBorrow_emu(uint x, uint y, out uint borrow)\n" "uint usubBorrow_emu(uint x, uint y, out uint borrow)\n"
"{\n" "{\n"
" borrow = uint(x < y);\n" " borrow = uint(x < y);\n"
" return x - y;\n" " return x - y;\n"
"}\n"}, "}\n"},
{{EOpUsubBorrow, ParamType::Uint2, ParamType::Uint2, ParamType::Uint2}, {BuiltInId::usubBorrow_UInt2_UInt2_UInt2,
"uint2 usubBorrow_emu(uint2 x, uint2 y, out uint2 borrow)\n" "uint2 usubBorrow_emu(uint2 x, uint2 y, out uint2 borrow)\n"
"{\n" "{\n"
" borrow = uint2(x < y);\n" " borrow = uint2(x < y);\n"
" return x - y;\n" " return x - y;\n"
"}\n"}, "}\n"},
{{EOpUsubBorrow, ParamType::Uint3, ParamType::Uint3, ParamType::Uint3}, {BuiltInId::usubBorrow_UInt3_UInt3_UInt3,
"uint3 usubBorrow_emu(uint3 x, uint3 y, out uint3 borrow)\n" "uint3 usubBorrow_emu(uint3 x, uint3 y, out uint3 borrow)\n"
"{\n" "{\n"
" borrow = uint3(x < y);\n" " borrow = uint3(x < y);\n"
" return x - y;\n" " return x - y;\n"
"}\n"}, "}\n"},
{{EOpUsubBorrow, ParamType::Uint4, ParamType::Uint4, ParamType::Uint4}, {BuiltInId::usubBorrow_UInt4_UInt4_UInt4,
"uint4 usubBorrow_emu(uint4 x, uint4 y, out uint4 borrow)\n" "uint4 usubBorrow_emu(uint4 x, uint4 y, out uint4 borrow)\n"
"{\n" "{\n"
" borrow = uint4(x < y);\n" " borrow = uint4(x < y);\n"
" return x - y;\n" " return x - y;\n"
"}\n"}, "}\n"},
// We emulate tanh just to avoid overflow on large arguments. // We emulate tanh just to avoid overflow on large arguments.
{{EOpTanh, ParamType::Float1}, {BuiltInId::tanh_Float1,
"float tanh_emu(float x)\n" "float tanh_emu(float x)\n"
"{\n" "{\n"
" return (abs(x) > 15.0) ? sign(x) : tanh(x);\n" " return (abs(x) > 15.0) ? sign(x) : tanh(x);\n"
"}\n"}, "}\n"},
{{EOpTanh, ParamType::Float2}, {BuiltInId::tanh_Float2,
"float2 tanh_emu(float2 x)\n" "float2 tanh_emu(float2 x)\n"
"{\n" "{\n"
" return (abs(x) > 15.0) ? sign(x) : tanh(x);\n" " return (abs(x) > 15.0) ? sign(x) : tanh(x);\n"
"}\n"}, "}\n"},
{{EOpTanh, ParamType::Float3}, {BuiltInId::tanh_Float3,
"float3 tanh_emu(float3 x)\n" "float3 tanh_emu(float3 x)\n"
"{\n" "{\n"
" return (abs(x) > 15.0) ? sign(x) : tanh(x);\n" " return (abs(x) > 15.0) ? sign(x) : tanh(x);\n"
"}\n"}, "}\n"},
{{EOpTanh, ParamType::Float4}, {BuiltInId::tanh_Float4,
"float4 tanh_emu(float4 x)\n" "float4 tanh_emu(float4 x)\n"
"{\n" "{\n"
" return (abs(x) > 15.0) ? sign(x) : tanh(x);\n" " return (abs(x) > 15.0) ? sign(x) : tanh(x);\n"
@ -864,12 +866,12 @@ constexpr FunctionPair g_hlslFunctions[] = {
}; };
} // anonymous namespace } // anonymous namespace
const char *FindHLSLFunction(const FunctionId &functionID) const char *FindHLSLFunction(int uniqueId)
{ {
for (size_t index = 0; index < ArraySize(g_hlslFunctions); ++index) for (size_t index = 0; index < ArraySize(g_hlslFunctions); ++index)
{ {
const auto &function = g_hlslFunctions[index]; const auto &function = g_hlslFunctions[index];
if (function.id == functionID) if (function.id == uniqueId)
{ {
return function.body; return function.body;
} }

View File

@ -650,7 +650,7 @@ function_header_with_parameters
$$ = $1; $$ = $1;
if ($2.type->getBasicType() != EbtVoid) if ($2.type->getBasicType() != EbtVoid)
{ {
$1->addParameter($2.turnToConst()); $1->addParameter($2.createVariable(&context->symbolTable));
} }
} }
| function_header_with_parameters COMMA parameter_declaration { | function_header_with_parameters COMMA parameter_declaration {
@ -664,7 +664,7 @@ function_header_with_parameters
} }
else else
{ {
$1->addParameter($3.turnToConst()); $1->addParameter($3.createVariable(&context->symbolTable));
} }
} }
; ;
@ -1304,11 +1304,11 @@ compound_statement_no_new_scope
statement_list statement_list
: statement { : statement {
$$ = new TIntermBlock(); $$ = new TIntermBlock();
$$->appendStatement($1); context->appendStatement($$, $1);
} }
| statement_list statement { | statement_list statement {
$$ = $1; $$ = $1;
$$->appendStatement($2); context->appendStatement($$, $2);
} }
; ;

View File

@ -3268,7 +3268,7 @@ yyreduce:
(yyval.interm.function) = (yyvsp[-1].interm.function); (yyval.interm.function) = (yyvsp[-1].interm.function);
if ((yyvsp[0].interm.param).type->getBasicType() != EbtVoid) if ((yyvsp[0].interm.param).type->getBasicType() != EbtVoid)
{ {
(yyvsp[-1].interm.function)->addParameter((yyvsp[0].interm.param).turnToConst()); (yyvsp[-1].interm.function)->addParameter((yyvsp[0].interm.param).createVariable(&context->symbolTable));
} }
} }
@ -3287,7 +3287,7 @@ yyreduce:
} }
else else
{ {
(yyvsp[-2].interm.function)->addParameter((yyvsp[0].interm.param).turnToConst()); (yyvsp[-2].interm.function)->addParameter((yyvsp[0].interm.param).createVariable(&context->symbolTable));
} }
} }
@ -4630,7 +4630,7 @@ yyreduce:
{ {
(yyval.interm.intermBlock) = new TIntermBlock(); (yyval.interm.intermBlock) = new TIntermBlock();
(yyval.interm.intermBlock)->appendStatement((yyvsp[0].interm.intermNode)); context->appendStatement((yyval.interm.intermBlock), (yyvsp[0].interm.intermNode));
} }
break; break;
@ -4639,7 +4639,7 @@ yyreduce:
{ {
(yyval.interm.intermBlock) = (yyvsp[-1].interm.intermBlock); (yyval.interm.intermBlock) = (yyvsp[-1].interm.intermBlock);
(yyval.interm.intermBlock)->appendStatement((yyvsp[0].interm.intermNode)); context->appendStatement((yyval.interm.intermBlock), (yyvsp[0].interm.intermNode));
} }
break; break;

View File

@ -4,10 +4,10 @@
// found in the LICENSE file. // found in the LICENSE file.
// //
#include "compiler/translator/AddAndTrueToLoopCondition.h" #include "compiler/translator/tree_ops/AddAndTrueToLoopCondition.h"
#include "compiler/translator/IntermNode_util.h" #include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/IntermTraverse.h" #include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh namespace sh
{ {

View File

@ -6,8 +6,8 @@
// Rewrite condition in for and while loops to work around driver bug on Intel Mac. // Rewrite condition in for and while loops to work around driver bug on Intel Mac.
#ifndef COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_ #ifndef COMPILER_TRANSLATOR_TREEOPS_ADDANDTRUETOLOOPCONDITION_H_
#define COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_ #define COMPILER_TRANSLATOR_TREEOPS_ADDANDTRUETOLOOPCONDITION_H_
class TIntermNode; class TIntermNode;
namespace sh namespace sh
@ -17,4 +17,4 @@ void AddAndTrueToLoopCondition(TIntermNode *root);
} // namespace sh } // namespace sh
#endif // COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_ #endif // COMPILER_TRANSLATOR_TREEOPS_ADDANDTRUETOLOOPCONDITION_H_

View File

@ -7,10 +7,10 @@
// return. // return.
// //
#include "compiler/translator/AddDefaultReturnStatements.h" #include "compiler/translator/tree_ops/AddDefaultReturnStatements.h"
#include "compiler/translator/IntermNode.h" #include "compiler/translator/IntermNode.h"
#include "compiler/translator/IntermNode_util.h" #include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/util.h" #include "compiler/translator/util.h"
namespace sh namespace sh

View File

@ -7,8 +7,8 @@
// return. // return.
// //
#ifndef COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_ #ifndef COMPILER_TRANSLATOR_TREEOPS_ADDDEFAULTRETURNSTATEMENTS_H_
#define COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_ #define COMPILER_TRANSLATOR_TREEOPS_ADDDEFAULTRETURNSTATEMENTS_H_
class TIntermBlock; class TIntermBlock;
@ -19,4 +19,4 @@ void AddDefaultReturnStatements(TIntermBlock *root);
} // namespace sh } // namespace sh
#endif // COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_ #endif // COMPILER_TRANSLATOR_TREEOPS_ADDDEFAULTRETURNSTATEMENTS_H_

View File

@ -6,14 +6,14 @@
// The ArrayReturnValueToOutParameter function changes return values of an array type to out // The ArrayReturnValueToOutParameter function changes return values of an array type to out
// parameters in function definitions, prototypes, and call sites. // parameters in function definitions, prototypes, and call sites.
#include "compiler/translator/ArrayReturnValueToOutParameter.h" #include "compiler/translator/tree_ops/ArrayReturnValueToOutParameter.h"
#include <map> #include <map>
#include "compiler/translator/IntermNode_util.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/StaticType.h" #include "compiler/translator/StaticType.h"
#include "compiler/translator/SymbolTable.h" #include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh namespace sh
{ {
@ -23,15 +23,6 @@ namespace
constexpr const ImmutableString kReturnValueVariableName("angle_return"); constexpr const ImmutableString kReturnValueVariableName("angle_return");
void CopyAggregateChildren(TIntermAggregateBase *from, TIntermAggregateBase *to)
{
const TIntermSequence *fromSequence = from->getSequence();
for (size_t ii = 0; ii < fromSequence->size(); ++ii)
{
to->getSequence()->push_back(fromSequence->at(ii));
}
}
class ArrayReturnValueToOutParameterTraverser : private TIntermTraverser class ArrayReturnValueToOutParameterTraverser : private TIntermTraverser
{ {
public: public:
@ -40,7 +31,7 @@ class ArrayReturnValueToOutParameterTraverser : private TIntermTraverser
private: private:
ArrayReturnValueToOutParameterTraverser(TSymbolTable *symbolTable); ArrayReturnValueToOutParameterTraverser(TSymbolTable *symbolTable);
bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override; void visitFunctionPrototype(TIntermFunctionPrototype *node) override;
bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *node) override; bool visitAggregate(Visit visit, TIntermAggregate *node) override;
bool visitBranch(Visit visit, TIntermBranch *node) override; bool visitBranch(Visit visit, TIntermBranch *node) override;
@ -110,10 +101,9 @@ bool ArrayReturnValueToOutParameterTraverser::visitFunctionDefinition(
return true; return true;
} }
bool ArrayReturnValueToOutParameterTraverser::visitFunctionPrototype(Visit visit, void ArrayReturnValueToOutParameterTraverser::visitFunctionPrototype(TIntermFunctionPrototype *node)
TIntermFunctionPrototype *node)
{ {
if (visit == PreVisit && node->isArray()) if (node->isArray())
{ {
// Replace the whole prototype node with another node that has the out parameter // Replace the whole prototype node with another node that has the out parameter
// added. Also set the function to return void. // added. Also set the function to return void.
@ -133,21 +123,16 @@ bool ArrayReturnValueToOutParameterTraverser::visitFunctionPrototype(Visit visit
{ {
func->addParameter(node->getFunction()->getParam(i)); func->addParameter(node->getFunction()->getParam(i));
} }
func->addParameter(TConstParameter( func->addParameter(changedFunction.returnValueVariable);
kReturnValueVariableName, static_cast<const TType *>(returnValueVariableType)));
changedFunction.func = func; changedFunction.func = func;
mChangedFunctions[functionId.get()] = changedFunction; mChangedFunctions[functionId.get()] = changedFunction;
} }
TIntermFunctionPrototype *replacement = TIntermFunctionPrototype *replacement =
new TIntermFunctionPrototype(mChangedFunctions[functionId.get()].func); new TIntermFunctionPrototype(mChangedFunctions[functionId.get()].func);
CopyAggregateChildren(node, replacement);
replacement->getSequence()->push_back(
new TIntermSymbol(mChangedFunctions[functionId.get()].returnValueVariable));
replacement->setLine(node->getLine()); replacement->setLine(node->getLine());
queueReplacement(replacement, OriginalNode::IS_DROPPED); queueReplacement(replacement, OriginalNode::IS_DROPPED);
} }
return false;
} }
bool ArrayReturnValueToOutParameterTraverser::visitAggregate(Visit visit, TIntermAggregate *node) bool ArrayReturnValueToOutParameterTraverser::visitAggregate(Visit visit, TIntermAggregate *node)

View File

@ -6,8 +6,8 @@
// The ArrayReturnValueToOutParameter function changes return values of an array type to out // The ArrayReturnValueToOutParameter function changes return values of an array type to out
// parameters in function definitions, prototypes and call sites. // parameters in function definitions, prototypes and call sites.
#ifndef COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_ #ifndef COMPILER_TRANSLATOR_TREEOPS_ARRAYRETURNVALUETOOUTPARAMETER_H_
#define COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_ #define COMPILER_TRANSLATOR_TREEOPS_ARRAYRETURNVALUETOOUTPARAMETER_H_
namespace sh namespace sh
{ {
@ -19,4 +19,4 @@ void ArrayReturnValueToOutParameter(TIntermNode *root, TSymbolTable *symbolTable
} // namespace sh } // namespace sh
#endif // COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_ #endif // COMPILER_TRANSLATOR_TREEOPS_ARRAYRETURNVALUETOOUTPARAMETER_H_

View File

@ -10,8 +10,8 @@
#include "BreakVariableAliasingInInnerLoops.h" #include "BreakVariableAliasingInInnerLoops.h"
#include "compiler/translator/IntermNode_util.h" #include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/IntermTraverse.h" #include "compiler/translator/tree_util/IntermTraverse.h"
// A HLSL compiler developer gave us more details on the root cause and the workaround needed: // A HLSL compiler developer gave us more details on the root cause and the workaround needed:
// The root problem is that if the HLSL compiler is applying aliasing information even on // The root problem is that if the HLSL compiler is applying aliasing information even on

View File

@ -8,8 +8,8 @@
// may record a variable as aliasing another. Sometimes the alias information gets garbled // may record a variable as aliasing another. Sometimes the alias information gets garbled
// so we work around this issue by breaking the aliasing chain in inner loops. // so we work around this issue by breaking the aliasing chain in inner loops.
#ifndef COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_ #ifndef COMPILER_TRANSLATOR_TREEOPS_BREAKVARIABLEALIASINGININNERLOOPS_H_
#define COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_ #define COMPILER_TRANSLATOR_TREEOPS_BREAKVARIABLEALIASINGININNERLOOPS_H_
class TIntermNode; class TIntermNode;
@ -20,4 +20,4 @@ void BreakVariableAliasingInInnerLoops(TIntermNode *root);
} // namespace sh } // namespace sh
#endif // COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_ #endif // COMPILER_TRANSLATOR_TREEOPS_BREAKVARIABLEALIASINGININNERLOOPS_H_

View File

@ -8,13 +8,14 @@
// statically accesses gl_FragDepth. // statically accesses gl_FragDepth.
// //
#include "compiler/translator/ClampFragDepth.h" #include "compiler/translator/tree_ops/ClampFragDepth.h"
#include "compiler/translator/FindSymbolNode.h"
#include "compiler/translator/ImmutableString.h" #include "compiler/translator/ImmutableString.h"
#include "compiler/translator/IntermNode_util.h"
#include "compiler/translator/RunAtTheEndOfShader.h"
#include "compiler/translator/SymbolTable.h" #include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
#include "compiler/translator/tree_util/FindSymbolNode.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/RunAtTheEndOfShader.h"
namespace sh namespace sh
{ {
@ -27,8 +28,7 @@ void ClampFragDepth(TIntermBlock *root, TSymbolTable *symbolTable)
return; return;
} }
TIntermSymbol *fragDepthNode = TIntermSymbol *fragDepthNode = new TIntermSymbol(BuiltInVariable::gl_FragDepth());
ReferenceBuiltInVariable(ImmutableString("gl_FragDepth"), *symbolTable, 300);
TIntermTyped *minFragDepthNode = CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst)); TIntermTyped *minFragDepthNode = CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));

View File

@ -8,8 +8,8 @@
// statically accesses gl_FragDepth. // statically accesses gl_FragDepth.
// //
#ifndef COMPILER_TRANSLATOR_CLAMPFRAGDEPTH_H_ #ifndef COMPILER_TRANSLATOR_TREEOPS_CLAMPFRAGDEPTH_H_
#define COMPILER_TRANSLATOR_CLAMPFRAGDEPTH_H_ #define COMPILER_TRANSLATOR_TREEOPS_CLAMPFRAGDEPTH_H_
namespace sh namespace sh
{ {
@ -21,4 +21,4 @@ void ClampFragDepth(TIntermBlock *root, TSymbolTable *symbolTable);
} // namespace sh } // namespace sh
#endif // COMPILER_TRANSLATOR_CLAMPFRAGDEPTH_H_ #endif // COMPILER_TRANSLATOR_TREEOPS_CLAMPFRAGDEPTH_H_

View File

@ -6,12 +6,13 @@
// ClampPointSize.cpp: Limit the value that is written to gl_PointSize. // ClampPointSize.cpp: Limit the value that is written to gl_PointSize.
// //
#include "compiler/translator/ClampPointSize.h" #include "compiler/translator/tree_ops/ClampPointSize.h"
#include "compiler/translator/FindSymbolNode.h"
#include "compiler/translator/IntermNode_util.h"
#include "compiler/translator/RunAtTheEndOfShader.h"
#include "compiler/translator/SymbolTable.h" #include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
#include "compiler/translator/tree_util/FindSymbolNode.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/RunAtTheEndOfShader.h"
namespace sh namespace sh
{ {
@ -24,8 +25,7 @@ void ClampPointSize(TIntermBlock *root, float maxPointSize, TSymbolTable *symbol
return; return;
} }
TIntermSymbol *pointSizeNode = TIntermSymbol *pointSizeNode = new TIntermSymbol(BuiltInVariable::gl_PointSize());
ReferenceBuiltInVariable(ImmutableString("gl_PointSize"), *symbolTable, 100);
TConstantUnion *maxPointSizeConstant = new TConstantUnion(); TConstantUnion *maxPointSizeConstant = new TConstantUnion();
maxPointSizeConstant->setFConst(maxPointSize); maxPointSizeConstant->setFConst(maxPointSize);

View File

@ -6,8 +6,8 @@
// ClampPointSize.h: Limit the value that is written to gl_PointSize. // ClampPointSize.h: Limit the value that is written to gl_PointSize.
// //
#ifndef COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_ #ifndef COMPILER_TRANSLATOR_TREEOPS_CLAMPPOINTSIZE_H_
#define COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_ #define COMPILER_TRANSLATOR_TREEOPS_CLAMPPOINTSIZE_H_
namespace sh namespace sh
{ {
@ -19,4 +19,4 @@ void ClampPointSize(TIntermBlock *root, float maxPointSize, TSymbolTable *symbol
} // namespace sh } // namespace sh
#endif // COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_ #endif // COMPILER_TRANSLATOR_TREEOPS_CLAMPPOINTSIZE_H_

View File

@ -7,15 +7,16 @@
// Check the header file For more information. // Check the header file For more information.
// //
#include "compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h" #include "compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.h"
#include "compiler/translator/FindMain.h"
#include "compiler/translator/InitializeVariables.h"
#include "compiler/translator/IntermNode_util.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/ReplaceVariable.h"
#include "compiler/translator/StaticType.h" #include "compiler/translator/StaticType.h"
#include "compiler/translator/SymbolTable.h" #include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_ops/InitializeVariables.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
#include "compiler/translator/tree_util/FindMain.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
#include "compiler/translator/tree_util/ReplaceVariable.h"
#include "compiler/translator/util.h" #include "compiler/translator/util.h"
namespace sh namespace sh
@ -24,20 +25,11 @@ namespace sh
namespace namespace
{ {
constexpr const ImmutableString kGlLayerString("gl_Layer");
constexpr const ImmutableString kGlViewportIndexString("gl_ViewportIndex");
constexpr const ImmutableString kGlViewIdOVRString("gl_ViewID_OVR");
constexpr const ImmutableString kGlInstanceIdString("gl_InstanceID");
constexpr const ImmutableString kViewIDVariableName("ViewID_OVR"); constexpr const ImmutableString kViewIDVariableName("ViewID_OVR");
constexpr const ImmutableString kInstanceIDVariableName("InstanceID"); constexpr const ImmutableString kInstanceIDVariableName("InstanceID");
constexpr const ImmutableString kMultiviewBaseViewLayerIndexVariableName( constexpr const ImmutableString kMultiviewBaseViewLayerIndexVariableName(
"multiviewBaseViewLayerIndex"); "multiviewBaseViewLayerIndex");
TIntermSymbol *CreateGLInstanceIDSymbol(const TSymbolTable &symbolTable)
{
return ReferenceBuiltInVariable(kGlInstanceIdString, symbolTable, 300);
}
// Adds the InstanceID and ViewID_OVR initializers to the end of the initializers' sequence. // Adds the InstanceID and ViewID_OVR initializers to the end of the initializers' sequence.
void InitializeViewIDAndInstanceID(const TVariable *viewID, void InitializeViewIDAndInstanceID(const TVariable *viewID,
const TVariable *instanceID, const TVariable *instanceID,
@ -53,7 +45,7 @@ void InitializeViewIDAndInstanceID(const TVariable *viewID,
// Create a uint(gl_InstanceID) node. // Create a uint(gl_InstanceID) node.
TIntermSequence *glInstanceIDSymbolCastArguments = new TIntermSequence(); TIntermSequence *glInstanceIDSymbolCastArguments = new TIntermSequence();
glInstanceIDSymbolCastArguments->push_back(CreateGLInstanceIDSymbol(symbolTable)); glInstanceIDSymbolCastArguments->push_back(new TIntermSymbol(BuiltInVariable::gl_InstanceID()));
TIntermAggregate *glInstanceIDAsUint = TIntermAggregate::CreateConstructor( TIntermAggregate *glInstanceIDAsUint = TIntermAggregate::CreateConstructor(
TType(EbtUInt, EbpHigh, EvqTemporary), glInstanceIDSymbolCastArguments); TType(EbtUInt, EbpHigh, EvqTemporary), glInstanceIDSymbolCastArguments);
@ -105,8 +97,7 @@ void SelectViewIndexInVertexShader(const TVariable *viewID,
TType(EbtInt, EbpHigh, EvqTemporary), viewIDSymbolCastArguments); TType(EbtInt, EbpHigh, EvqTemporary), viewIDSymbolCastArguments);
// Create a gl_ViewportIndex node. // Create a gl_ViewportIndex node.
TIntermSymbol *viewportIndexSymbol = TIntermSymbol *viewportIndexSymbol = new TIntermSymbol(BuiltInVariable::gl_ViewportIndex());
ReferenceBuiltInVariable(kGlViewportIndexString, symbolTable, 0);
// Create a { gl_ViewportIndex = int(ViewID_OVR) } node. // Create a { gl_ViewportIndex = int(ViewID_OVR) } node.
TIntermBlock *viewportIndexInitializerInBlock = new TIntermBlock(); TIntermBlock *viewportIndexInitializerInBlock = new TIntermBlock();
@ -114,7 +105,7 @@ void SelectViewIndexInVertexShader(const TVariable *viewID,
new TIntermBinary(EOpAssign, viewportIndexSymbol, viewIDAsInt)); new TIntermBinary(EOpAssign, viewportIndexSymbol, viewIDAsInt));
// Create a gl_Layer node. // Create a gl_Layer node.
TIntermSymbol *layerSymbol = ReferenceBuiltInVariable(kGlLayerString, symbolTable, 0); TIntermSymbol *layerSymbol = new TIntermSymbol(BuiltInVariable::gl_LayerVS());
// Create an int(ViewID_OVR) + multiviewBaseViewLayerIndex node // Create an int(ViewID_OVR) + multiviewBaseViewLayerIndex node
TIntermBinary *sumOfViewIDAndBaseViewIndex = new TIntermBinary( TIntermBinary *sumOfViewIDAndBaseViewIndex = new TIntermBinary(
@ -149,29 +140,23 @@ void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root,
{ {
ASSERT(shaderType == GL_VERTEX_SHADER || shaderType == GL_FRAGMENT_SHADER); ASSERT(shaderType == GL_VERTEX_SHADER || shaderType == GL_FRAGMENT_SHADER);
TQualifier viewIDQualifier = (shaderType == GL_VERTEX_SHADER) ? EvqFlatOut : EvqFlatIn; TQualifier viewIDQualifier = (shaderType == GL_VERTEX_SHADER) ? EvqFlatOut : EvqFlatIn;
const TVariable *viewID = const TVariable *viewID =
new TVariable(symbolTable, kViewIDVariableName, new TVariable(symbolTable, kViewIDVariableName,
new TType(EbtUInt, EbpHigh, viewIDQualifier), SymbolType::AngleInternal); new TType(EbtUInt, EbpHigh, viewIDQualifier), SymbolType::AngleInternal);
DeclareGlobalVariable(root, viewID); DeclareGlobalVariable(root, viewID);
ReplaceVariable( ReplaceVariable(root, BuiltInVariable::gl_ViewID_OVR(), viewID);
root,
static_cast<const TVariable *>(symbolTable->findBuiltIn(kGlViewIdOVRString, 300, true)),
viewID);
if (shaderType == GL_VERTEX_SHADER) if (shaderType == GL_VERTEX_SHADER)
{ {
// Replacing gl_InstanceID with InstanceID should happen before adding the initializers of // Replacing gl_InstanceID with InstanceID should happen before adding the initializers of
// InstanceID and ViewID. // InstanceID and ViewID.
const TType *instanceIDVariableType = StaticType::Get<EbtInt, EbpHigh, EvqGlobal, 1, 1>(); const TType *instanceIDVariableType = StaticType::Get<EbtInt, EbpHigh, EvqGlobal, 1, 1>();
const TVariable *instanceID = const TVariable *instanceID =
new TVariable(symbolTable, kInstanceIDVariableName, instanceIDVariableType, new TVariable(symbolTable, kInstanceIDVariableName, instanceIDVariableType,
SymbolType::AngleInternal); SymbolType::AngleInternal);
DeclareGlobalVariable(root, instanceID); DeclareGlobalVariable(root, instanceID);
ReplaceVariable(root, ReplaceVariable(root, BuiltInVariable::gl_InstanceID(), instanceID);
static_cast<const TVariable *>(
symbolTable->findBuiltIn(kGlInstanceIdString, 300, true)),
instanceID);
TIntermSequence *initializers = new TIntermSequence(); TIntermSequence *initializers = new TIntermSequence();
InitializeViewIDAndInstanceID(viewID, instanceID, numberOfViews, *symbolTable, InitializeViewIDAndInstanceID(viewID, instanceID, numberOfViews, *symbolTable,
@ -207,4 +192,4 @@ void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root,
} }
} }
} // namespace sh } // namespace sh

View File

@ -24,8 +24,8 @@
// uniform. // uniform.
// //
#ifndef COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_ #ifndef COMPILER_TRANSLATOR_TREEOPS_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_
#define COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_ #define COMPILER_TRANSLATOR_TREEOPS_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_
#include "GLSLANG/ShaderLang.h" #include "GLSLANG/ShaderLang.h"
#include "angle_gl.h" #include "angle_gl.h"
@ -45,4 +45,4 @@ void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root,
} // namespace sh } // namespace sh
#endif // COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_ #endif // COMPILER_TRANSLATOR_TREEOPS_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_

View File

@ -13,17 +13,17 @@
// It can also initialize all uninitialized globals. // It can also initialize all uninitialized globals.
// //
#include "compiler/translator/DeferGlobalInitializers.h" #include "compiler/translator/tree_ops/DeferGlobalInitializers.h"
#include <vector> #include <vector>
#include "compiler/translator/FindMain.h"
#include "compiler/translator/InitializeVariables.h"
#include "compiler/translator/IntermNode.h" #include "compiler/translator/IntermNode.h"
#include "compiler/translator/IntermNode_util.h"
#include "compiler/translator/ReplaceVariable.h"
#include "compiler/translator/StaticType.h" #include "compiler/translator/StaticType.h"
#include "compiler/translator/SymbolTable.h" #include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_ops/InitializeVariables.h"
#include "compiler/translator/tree_util/FindMain.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/ReplaceVariable.h"
namespace sh namespace sh
{ {

View File

@ -13,8 +13,8 @@
// It can also initialize all uninitialized globals. // It can also initialize all uninitialized globals.
// //
#ifndef COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_ #ifndef COMPILER_TRANSLATOR_TREEOPS_DEFERGLOBALINITIALIZERS_H_
#define COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_ #define COMPILER_TRANSLATOR_TREEOPS_DEFERGLOBALINITIALIZERS_H_
namespace sh namespace sh
{ {
@ -30,4 +30,4 @@ void DeferGlobalInitializers(TIntermBlock *root,
} // namespace sh } // namespace sh
#endif // COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_ #endif // COMPILER_TRANSLATOR_TREEOPS_DEFERGLOBALINITIALIZERS_H_

View File

@ -11,12 +11,12 @@
// with gl_FragData[0]. // with gl_FragData[0].
// //
#include "compiler/translator/EmulateGLFragColorBroadcast.h" #include "compiler/translator/tree_ops/EmulateGLFragColorBroadcast.h"
#include "compiler/translator/IntermNode_util.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/RunAtTheEndOfShader.h"
#include "compiler/translator/Symbol.h" #include "compiler/translator/Symbol.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
#include "compiler/translator/tree_util/RunAtTheEndOfShader.h"
namespace sh namespace sh
{ {

View File

@ -7,8 +7,8 @@
// GL_EXT_draw_buffers is explicitly enabled in a fragment shader. // GL_EXT_draw_buffers is explicitly enabled in a fragment shader.
// //
#ifndef COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_ #ifndef COMPILER_TRANSLATOR_TREEOPS_EMULATEGLFRAGCOLORBROADCAST_H_
#define COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_ #define COMPILER_TRANSLATOR_TREEOPS_EMULATEGLFRAGCOLORBROADCAST_H_
#include <vector> #include <vector>
@ -28,4 +28,4 @@ void EmulateGLFragColorBroadcast(TIntermBlock *root,
int shaderVersion); int shaderVersion);
} }
#endif // COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_ #endif // COMPILER_TRANSLATOR_TREEOPS_EMULATEGLFRAGCOLORBROADCAST_H_

View File

@ -4,7 +4,7 @@
// found in the LICENSE file. // found in the LICENSE file.
// //
#include "compiler/translator/EmulatePrecision.h" #include "compiler/translator/tree_ops/EmulatePrecision.h"
#include "compiler/translator/FunctionLookup.h" #include "compiler/translator/FunctionLookup.h"
@ -42,13 +42,13 @@ class RoundingHelperWriter : angle::NonCopyable
const ShShaderOutput mOutputLanguage; const ShShaderOutput mOutputLanguage;
private: private:
virtual std::string getTypeString(const char *glslType) = 0; virtual std::string getTypeString(const char *glslType) = 0;
virtual void writeFloatRoundingHelpers(TInfoSinkBase &sink) = 0; virtual void writeFloatRoundingHelpers(TInfoSinkBase &sink) = 0;
virtual void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) = 0; virtual void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) = 0;
virtual void writeMatrixRoundingHelper(TInfoSinkBase &sink, virtual void writeMatrixRoundingHelper(TInfoSinkBase &sink,
const unsigned int columns, const unsigned int columns,
const unsigned int rows, const unsigned int rows,
const char *functionName) = 0; const char *functionName) = 0;
}; };
class RoundingHelperWriterGLSL : public RoundingHelperWriter class RoundingHelperWriterGLSL : public RoundingHelperWriter
@ -618,11 +618,6 @@ bool EmulatePrecision::visitInvariantDeclaration(Visit visit, TIntermInvariantDe
return false; return false;
} }
bool EmulatePrecision::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node)
{
return false;
}
bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node) bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node)
{ {
if (visit != PreVisit) if (visit != PreVisit)
@ -709,7 +704,7 @@ bool EmulatePrecision::SupportedInLanguage(const ShShaderOutput outputLanguage)
const TFunction *EmulatePrecision::getInternalFunction(const ImmutableString &functionName, const TFunction *EmulatePrecision::getInternalFunction(const ImmutableString &functionName,
const TType &returnType, const TType &returnType,
TIntermSequence *arguments, TIntermSequence *arguments,
const TVector<TConstParameter> &parameters, const TVector<const TVariable *> &parameters,
bool knownToNotHaveSideEffects) bool knownToNotHaveSideEffects)
{ {
ImmutableString mangledName = TFunctionLookup::GetMangledName(functionName.data(), *arguments); ImmutableString mangledName = TFunctionLookup::GetMangledName(functionName.data(), *arguments);
@ -735,11 +730,13 @@ TIntermAggregate *EmulatePrecision::createRoundingFunctionCallNode(TIntermTyped
TIntermSequence *arguments = new TIntermSequence(); TIntermSequence *arguments = new TIntermSequence();
arguments->push_back(roundedChild); arguments->push_back(roundedChild);
TVector<TConstParameter> parameters; TVector<const TVariable *> parameters;
TType *paramType = new TType(roundedChild->getType()); TType *paramType = new TType(roundedChild->getType());
paramType->setPrecision(EbpHigh); paramType->setPrecision(EbpHigh);
paramType->setQualifier(EvqIn); paramType->setQualifier(EvqIn);
parameters.push_back(TConstParameter(kParamXName, static_cast<const TType *>(paramType))); parameters.push_back(new TVariable(mSymbolTable, kParamXName,
static_cast<const TType *>(paramType),
SymbolType::AngleInternal));
return TIntermAggregate::CreateRawFunctionCall( return TIntermAggregate::CreateRawFunctionCall(
*getInternalFunction(*roundFunctionName, roundedChild->getType(), arguments, parameters, *getInternalFunction(*roundFunctionName, roundedChild->getType(), arguments, parameters,
@ -757,19 +754,23 @@ TIntermAggregate *EmulatePrecision::createCompoundAssignmentFunctionCallNode(TIn
else else
strstr << "angle_compound_" << opNameStr << "_frl"; strstr << "angle_compound_" << opNameStr << "_frl";
ImmutableString functionName = ImmutableString(strstr.str()); ImmutableString functionName = ImmutableString(strstr.str());
TIntermSequence *arguments = new TIntermSequence(); TIntermSequence *arguments = new TIntermSequence();
arguments->push_back(left); arguments->push_back(left);
arguments->push_back(right); arguments->push_back(right);
TVector<TConstParameter> parameters; TVector<const TVariable *> parameters;
TType *leftParamType = new TType(left->getType()); TType *leftParamType = new TType(left->getType());
leftParamType->setPrecision(EbpHigh); leftParamType->setPrecision(EbpHigh);
leftParamType->setQualifier(EvqOut); leftParamType->setQualifier(EvqOut);
parameters.push_back(TConstParameter(kParamXName, static_cast<const TType *>(leftParamType))); parameters.push_back(new TVariable(mSymbolTable, kParamXName,
static_cast<const TType *>(leftParamType),
SymbolType::AngleInternal));
TType *rightParamType = new TType(right->getType()); TType *rightParamType = new TType(right->getType());
rightParamType->setPrecision(EbpHigh); rightParamType->setPrecision(EbpHigh);
rightParamType->setQualifier(EvqIn); rightParamType->setQualifier(EvqIn);
parameters.push_back(TConstParameter(kParamYName, static_cast<const TType *>(rightParamType))); parameters.push_back(new TVariable(mSymbolTable, kParamYName,
static_cast<const TType *>(rightParamType),
SymbolType::AngleInternal));
return TIntermAggregate::CreateRawFunctionCall( return TIntermAggregate::CreateRawFunctionCall(
*getInternalFunction(functionName, left->getType(), arguments, parameters, false), *getInternalFunction(functionName, left->getType(), arguments, parameters, false),

View File

@ -4,14 +4,14 @@
// found in the LICENSE file. // found in the LICENSE file.
// //
#ifndef COMPILER_TRANSLATOR_EMULATE_PRECISION_H_ #ifndef COMPILER_TRANSLATOR_TREEOPS_EMULATE_PRECISION_H_
#define COMPILER_TRANSLATOR_EMULATE_PRECISION_H_ #define COMPILER_TRANSLATOR_TREEOPS_EMULATE_PRECISION_H_
#include "GLSLANG/ShaderLang.h" #include "GLSLANG/ShaderLang.h"
#include "common/angleutils.h" #include "common/angleutils.h"
#include "compiler/translator/Compiler.h" #include "compiler/translator/Compiler.h"
#include "compiler/translator/InfoSink.h" #include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermTraverse.h" #include "compiler/translator/tree_util/IntermTraverse.h"
// This class gathers all compound assignments from the AST and can then write // This class gathers all compound assignments from the AST and can then write
// the functions required for their precision emulation. This way there is no // the functions required for their precision emulation. This way there is no
@ -32,7 +32,6 @@ class EmulatePrecision : public TLValueTrackingTraverser
bool visitAggregate(Visit visit, TIntermAggregate *node) override; bool visitAggregate(Visit visit, TIntermAggregate *node) override;
bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override; bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override;
bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
void writeEmulationHelpers(TInfoSinkBase &sink, void writeEmulationHelpers(TInfoSinkBase &sink,
const int shaderVersion, const int shaderVersion,
@ -62,7 +61,7 @@ class EmulatePrecision : public TLValueTrackingTraverser
const TFunction *getInternalFunction(const ImmutableString &functionName, const TFunction *getInternalFunction(const ImmutableString &functionName,
const TType &returnType, const TType &returnType,
TIntermSequence *arguments, TIntermSequence *arguments,
const TVector<TConstParameter> &parameters, const TVector<const TVariable *> &parameters,
bool knownToNotHaveSideEffects); bool knownToNotHaveSideEffects);
TIntermAggregate *createRoundingFunctionCallNode(TIntermTyped *roundedChild); TIntermAggregate *createRoundingFunctionCallNode(TIntermTyped *roundedChild);
TIntermAggregate *createCompoundAssignmentFunctionCallNode(TIntermTyped *left, TIntermAggregate *createCompoundAssignmentFunctionCallNode(TIntermTyped *left,
@ -83,4 +82,4 @@ class EmulatePrecision : public TLValueTrackingTraverser
} // namespace sh } // namespace sh
#endif // COMPILER_TRANSLATOR_EMULATE_PRECISION_H_ #endif // COMPILER_TRANSLATOR_TREEOPS_EMULATE_PRECISION_H_

View File

@ -6,13 +6,13 @@
// Implementation of the integer pow expressions HLSL bug workaround. // Implementation of the integer pow expressions HLSL bug workaround.
// See header for more info. // See header for more info.
#include "compiler/translator/ExpandIntegerPowExpressions.h" #include "compiler/translator/tree_ops/ExpandIntegerPowExpressions.h"
#include <cmath> #include <cmath>
#include <cstdlib> #include <cstdlib>
#include "compiler/translator/IntermNode_util.h" #include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/IntermTraverse.h" #include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh namespace sh
{ {

View File

@ -13,8 +13,8 @@
// The workaround is to replace the pow with a series of multiplies. // The workaround is to replace the pow with a series of multiplies.
// See http://anglebug.com/851 // See http://anglebug.com/851
#ifndef COMPILER_TRANSLATOR_EXPANDINTEGERPOWEXPRESSIONS_H_ #ifndef COMPILER_TRANSLATOR_TREEOPS_EXPANDINTEGERPOWEXPRESSIONS_H_
#define COMPILER_TRANSLATOR_EXPANDINTEGERPOWEXPRESSIONS_H_ #define COMPILER_TRANSLATOR_TREEOPS_EXPANDINTEGERPOWEXPRESSIONS_H_
namespace sh namespace sh
{ {
@ -26,4 +26,4 @@ void ExpandIntegerPowExpressions(TIntermNode *root, TSymbolTable *symbolTable);
} // namespace sh } // namespace sh
#endif // COMPILER_TRANSLATOR_EXPANDINTEGERPOWEXPRESSIONS_H_ #endif // COMPILER_TRANSLATOR_TREEOPS_EXPANDINTEGERPOWEXPRESSIONS_H_

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