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
#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
#endif // INCLUDE_EGL_EGLEXT_ANGLE_

View File

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

View File

@ -126,7 +126,12 @@ struct ShaderVariable
// and flattenedOffsetInParentArrays of a[2][1] would be 2*4 + 1 = 9.
unsigned int flattenedOffsetInParentArrays;
// Static use means that the variable is accessed somewhere in the shader source.
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::string structName;
@ -279,6 +284,7 @@ struct InterfaceBlock
int binding;
bool staticUse;
bool active;
BlockType blockType;
std::vector<InterfaceBlockField> fields;
};

View File

@ -2,7 +2,7 @@
#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
** copy of this software and/or associated documentation files (the
@ -26,18 +26,16 @@
/* 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
* encouraged to submit platform specific modifications to the Khronos
* group so that they can be included in future versions of this file.
* Please submit changes by sending them to the public Khronos Bugzilla
* (http://khronos.org/bugzilla) by filing a bug against product
* "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.
* Please submit changes by filing pull requests or issues on
* the EGL Registry repository linked above.
*
*
* See the Implementer's Guidelines for information about where this file
@ -102,8 +100,7 @@
#elif defined (__SYMBIAN32__)
# define KHRONOS_APICALL IMPORT_C
#elif defined(__ANDROID__)
# include <sys/cdefs.h>
# define KHRONOS_APICALL __attribute__((visibility("default"))) __NDK_FPABI__
# define KHRONOS_APICALL __attribute__((visibility("default")))
#else
# define KHRONOS_APICALL
#endif
@ -282,4 +279,4 @@ typedef enum {
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
} 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_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>
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 green;
T blue;
T alpha;
Color();
Color(T r, T g, T b, T a);
};
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
#endif
#define GL_A1RGB5_ANGLEX 0x6AC5
#define GL_BGRX8_ANGLEX 0x6ABA
#define GL_BGR565_ANGLEX 0x6ABB
#define GL_BGRA4_ANGLEX 0x6ABC

View File

@ -40,10 +40,10 @@ class BitSetT final
private:
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;
std::size_t mBit;
ParamT mBit;
};
class Iterator final
@ -64,8 +64,7 @@ class BitSetT final
};
BitSetT();
BitSetT(BitsT value);
~BitSetT();
constexpr explicit BitSetT(BitsT value);
BitSetT(const BitSetT &other);
BitSetT &operator=(const BitSetT &other);
@ -90,6 +89,10 @@ class BitSetT final
BitSetT &operator^=(const BitSetT &other);
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);
BitSetT operator>>(std::size_t pos) const;
@ -115,7 +118,11 @@ class BitSetT final
{
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;
};
@ -213,12 +220,7 @@ BitSetT<N, BitsT, ParamT>::BitSetT() : mBits(0)
}
template <size_t N, typename BitsT, typename ParamT>
BitSetT<N, BitsT, ParamT>::BitSetT(BitsT value) : mBits(value & Mask(N))
{
}
template <size_t N, typename BitsT, typename ParamT>
BitSetT<N, BitsT, ParamT>::~BitSetT()
constexpr BitSetT<N, BitsT, ParamT>::BitSetT(BitsT value) : mBits(value & Mask(N))
{
}
@ -312,6 +314,27 @@ BitSetT<N, BitsT, ParamT> BitSetT<N, BitsT, ParamT>::operator~() const
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>
BitSetT<N, BitsT, ParamT> BitSetT<N, BitsT, ParamT>::operator<<(std::size_t pos) const
{

View File

@ -9,12 +9,12 @@
#ifndef COMMON_MATHUTIL_H_
#define COMMON_MATHUTIL_H_
#include <limits>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <limits>
#include <anglebase/numerics/safe_math.h>
@ -30,10 +30,10 @@ using base::IsValueInRangeForNumericType;
namespace gl
{
const unsigned int Float32One = 0x3F800000;
const unsigned int Float32One = 0x3F800000;
const unsigned short Float16One = 0x3C00;
template<typename T>
template <typename T>
inline bool isPow2(T x)
{
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)
{
int r = 0;
while ((x >> r) > 1) r++;
while ((x >> r) > 1)
r++;
return r;
}
inline unsigned int ceilPow2(unsigned int x)
{
if (x != 0) x--;
if (x != 0)
x--;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
@ -108,7 +110,7 @@ inline int clampCast(bool 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)
{
// 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);
}
template<const int n>
template <const int n>
inline unsigned int unorm(float x)
{
const unsigned int max = 0xFFFFFFFF >> (32 - n);
@ -142,7 +144,7 @@ inline unsigned int unorm(float x)
inline bool supportsSSE2()
{
#if defined(ANGLE_USE_SSE)
static bool checked = false;
static bool checked = false;
static bool supports = false;
if (checked)
@ -182,19 +184,19 @@ destType bitCast(const sourceType &source)
inline unsigned short float32ToFloat16(float fp32)
{
unsigned int fp32i = bitCast<unsigned int>(fp32);
unsigned int sign = (fp32i & 0x80000000) >> 16;
unsigned int abs = fp32i & 0x7FFFFFFF;
unsigned int sign = (fp32i & 0x80000000) >> 16;
unsigned int abs = fp32i & 0x7FFFFFFF;
if(abs > 0x47FFEFFF) // Infinity
if (abs > 0x47FFEFFF) // Infinity
{
return static_cast<unsigned short>(sign | 0x7FFF);
}
else if(abs < 0x38800000) // Denormal
else if (abs < 0x38800000) // Denormal
{
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;
}
@ -207,7 +209,8 @@ inline unsigned short float32ToFloat16(float fp32)
}
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)
{
const unsigned int float32MantissaMask = 0x7FFFFF;
const unsigned int float32ExponentMask = 0x7F800000;
const unsigned int float32SignMask = 0x80000000;
const unsigned int float32ValueMask = ~float32SignMask;
const unsigned int float32MantissaMask = 0x7FFFFF;
const unsigned int float32ExponentMask = 0x7F800000;
const unsigned int float32SignMask = 0x80000000;
const unsigned int float32ValueMask = ~float32SignMask;
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 float11ExponentMask = 0x7C0;
const unsigned short float11BitMask = 0x7FF;
const unsigned int float11ExponentBias = 14;
const unsigned short float11BitMask = 0x7FF;
const unsigned int float11ExponentBias = 14;
const unsigned int float32Maxfloat11 = 0x477E0000;
const unsigned int float32Minfloat11 = 0x38800000;
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;
@ -244,7 +247,9 @@ inline unsigned short float32ToFloat11(float fp32)
// INF or NAN
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)
{
@ -272,8 +277,10 @@ inline unsigned short float32ToFloat11(float fp32)
{
// The number is too small to be represented as a normalized float11
// Convert it to a denormalized value.
const unsigned int shift = (float32ExponentBias - float11ExponentBias) - (float32Val >> float32ExponentFirstBit);
float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
const unsigned int shift = (float32ExponentBias - float11ExponentBias) -
(float32Val >> float32ExponentFirstBit);
float32Val =
((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
}
else
{
@ -287,24 +294,24 @@ inline unsigned short float32ToFloat11(float fp32)
inline unsigned short float32ToFloat10(float fp32)
{
const unsigned int float32MantissaMask = 0x7FFFFF;
const unsigned int float32ExponentMask = 0x7F800000;
const unsigned int float32SignMask = 0x80000000;
const unsigned int float32ValueMask = ~float32SignMask;
const unsigned int float32MantissaMask = 0x7FFFFF;
const unsigned int float32ExponentMask = 0x7F800000;
const unsigned int float32SignMask = 0x80000000;
const unsigned int float32ValueMask = ~float32SignMask;
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 float10ExponentMask = 0x3E0;
const unsigned short float10BitMask = 0x3FF;
const unsigned int float10ExponentBias = 14;
const unsigned short float10BitMask = 0x3FF;
const unsigned int float10ExponentBias = 14;
const unsigned int float32Maxfloat10 = 0x477C0000;
const unsigned int float32Minfloat10 = 0x38800000;
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;
@ -313,7 +320,9 @@ inline unsigned short float32ToFloat10(float fp32)
// INF or NAN
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)
{
@ -341,8 +350,10 @@ inline unsigned short float32ToFloat10(float fp32)
{
// The number is too small to be represented as a normalized float11
// Convert it to a denormalized value.
const unsigned int shift = (float32ExponentBias - float10ExponentBias) - (float32Val >> float32ExponentFirstBit);
float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
const unsigned int shift = (float32ExponentBias - float10ExponentBias) -
(float32Val >> float32ExponentFirstBit);
float32Val =
((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
}
else
{
@ -379,12 +390,11 @@ inline float float11ToFloat32(unsigned short fp11)
{
exponent--;
mantissa <<= 1;
}
while ((mantissa & 0x40) == 0);
} while ((mantissa & 0x40) == 0);
mantissa = mantissa & 0x3F;
}
else // The value is zero
else // The value is zero
{
exponent = static_cast<unsigned short>(-112);
}
@ -418,12 +428,11 @@ inline float float10ToFloat32(unsigned short fp11)
{
exponent--;
mantissa <<= 1;
}
while ((mantissa & 0x20) == 0);
} while ((mantissa & 0x20) == 0);
mantissa = mantissa & 0x1F;
}
else // The value is zero
else // The value is zero
{
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>
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)
{
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)
{
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>
@ -687,21 +726,21 @@ inline float Ldexp(float x, int exp)
inline uint32_t packSnorm2x16(float f1, float f2)
{
int16_t leastSignificantBits = static_cast<int16_t>(roundf(clamp(f1, -1.0f, 1.0f) * 32767.0f));
int16_t mostSignificantBits = static_cast<int16_t>(roundf(clamp(f2, -1.0f, 1.0f) * 32767.0f));
int16_t mostSignificantBits = static_cast<int16_t>(roundf(clamp(f2, -1.0f, 1.0f) * 32767.0f));
return static_cast<uint32_t>(mostSignificantBits) << 16 |
(static_cast<uint32_t>(leastSignificantBits) & 0xFFFF);
}
// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then, each
// component is converted to a normalized floating-point value to generate the returned two float values.
// The first float value will be extracted from the least significant bits of the input;
// the last float value will be extracted from the most-significant bits.
// The conversion for unpacked fixed-point value to floating point is done as follows:
// unpackSnorm2x16 : clamp(f / 32767.0, -1, +1)
// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then,
// each component is converted to a normalized floating-point value to generate the returned two
// float values. The first float value will be extracted from the least significant bits of the
// input; the last float value will be extracted from the most-significant bits. The conversion for
// unpacked fixed-point value to floating point is done as follows: unpackSnorm2x16 : clamp(f /
// 32767.0, -1, +1)
inline void unpackSnorm2x16(uint32_t u, float *f1, float *f2)
{
int16_t leastSignificantBits = static_cast<int16_t>(u & 0xFFFF);
int16_t mostSignificantBits = static_cast<int16_t>(u >> 16);
int16_t mostSignificantBits = static_cast<int16_t>(u >> 16);
*f1 = clamp(static_cast<float>(leastSignificantBits) / 32767.0f, -1.0f, 1.0f);
*f2 = clamp(static_cast<float>(mostSignificantBits) / 32767.0f, -1.0f, 1.0f);
}
@ -715,22 +754,22 @@ inline void unpackSnorm2x16(uint32_t u, 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 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);
uint16_t mostSignificantBits = static_cast<uint16_t>(roundf(clamp(f2, 0.0f, 1.0f) * 65535.0f));
return static_cast<uint32_t>(mostSignificantBits) << 16 |
static_cast<uint32_t>(leastSignificantBits);
}
// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then, each
// component is converted to a normalized floating-point value to generate the returned two float values.
// The first float value will be extracted from the least significant bits of the input;
// the last float value will be extracted from the most-significant bits.
// The conversion for unpacked fixed-point value to floating point is done as follows:
// unpackUnorm2x16 : f / 65535.0
// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then,
// each component is converted to a normalized floating-point value to generate the returned two
// float values. The first float value will be extracted from the least significant bits of the
// input; the last float value will be extracted from the most-significant bits. The conversion for
// unpacked fixed-point value to floating point is done as follows: unpackUnorm2x16 : f / 65535.0
inline void unpackUnorm2x16(uint32_t u, float *f1, float *f2)
{
uint16_t leastSignificantBits = static_cast<uint16_t>(u & 0xFFFF);
uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16);
*f1 = static_cast<float>(leastSignificantBits) / 65535.0f;
*f2 = static_cast<float>(mostSignificantBits) / 65535.0f;
uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16);
*f1 = static_cast<float>(leastSignificantBits) / 65535.0f;
*f2 = static_cast<float>(mostSignificantBits) / 65535.0f;
}
// 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)
{
uint16_t leastSignificantBits = static_cast<uint16_t>(float32ToFloat16(f1));
uint16_t mostSignificantBits = static_cast<uint16_t>(float32ToFloat16(f2));
return static_cast<uint32_t>(mostSignificantBits) << 16 | static_cast<uint32_t>(leastSignificantBits);
uint16_t mostSignificantBits = static_cast<uint16_t>(float32ToFloat16(f2));
return static_cast<uint32_t>(mostSignificantBits) << 16 |
static_cast<uint32_t>(leastSignificantBits);
}
// Returns two floating-point values obtained by unpacking a 32-bit unsigned integer into a pair of 16-bit values,
// interpreting those values as 16-bit floating-point numbers according to the OpenGL ES Specification,
// and converting them to 32-bit floating-point values.
// The first float value is obtained from the 16 least-significant bits of u;
// the second component is obtained from the 16 most-significant bits of u.
// Returns two floating-point values obtained by unpacking a 32-bit unsigned integer into a pair of
// 16-bit values, interpreting those values as 16-bit floating-point numbers according to the OpenGL
// ES Specification, and converting them to 32-bit floating-point values. The first float value is
// obtained from the 16 least-significant bits of u; the second component is obtained from the 16
// most-significant bits of u.
inline void unpackHalf2x16(uint32_t u, float *f1, float *f2)
{
uint16_t leastSignificantBits = static_cast<uint16_t>(u & 0xFFFF);
uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16);
uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16);
*f1 = float16ToFloat32(leastSignificantBits);
*f2 = float16ToFloat32(mostSignificantBits);
@ -1004,21 +1044,25 @@ int FindMSB(T bits)
}
// 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)
{
// Exponent mask: ((1u << 8) - 1u) << 23 = 0x7f800000u
// Mantissa mask: ((1u << 23) - 1u) = 0x7fffffu
return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) && (bitCast<uint32_t>(f) & 0x7fffffu);
return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) &&
(bitCast<uint32_t>(f) & 0x7fffffu);
}
// Returns whether the argument is infinity.
// IEEE 754 single precision infinity representation: Exponent(8 bits) - 255, Mantissa(23 bits) - zero.
// IEEE 754 single precision infinity representation: Exponent(8 bits) - 255, Mantissa(23 bits) -
// zero.
inline bool isInf(float f)
{
// Exponent mask: ((1u << 8) - 1u) << 23 = 0x7f800000u
// Mantissa mask: ((1u << 23) - 1u) = 0x7fffffu
return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) && !(bitCast<uint32_t>(f) & 0x7fffffu);
return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) &&
!(bitCast<uint32_t>(f) & 0x7fffffu);
}
namespace priv
@ -1117,8 +1161,8 @@ inline unsigned int UnsignedCeilDivide(unsigned int value, unsigned int divisor)
#if defined(_MSC_VER)
#define ANGLE_ROTL(x,y) _rotl(x,y)
#define ANGLE_ROTR16(x,y) _rotr16(x,y)
#define ANGLE_ROTL(x, y) _rotl(x, y)
#define ANGLE_ROTR16(x, y) _rotr16(x, y)
#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_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));
}
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
{
ASSERT(rows() == columns());

View File

@ -437,50 +437,6 @@ bool IsOpaqueType(GLenum 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)
{
return VariableRowCount(type) > 1;
@ -545,29 +501,6 @@ int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsig
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,
const GLvoid *indices,
size_t count,
@ -996,52 +929,6 @@ const char *GetGenericErrorMessage(EGLint error)
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)
{
return static_cast<GLuint>(reinterpret_cast<uintptr_t>(buffer));

View File

@ -38,7 +38,6 @@ bool IsSamplerType(GLenum type);
bool IsImageType(GLenum type);
bool IsAtomicCounterType(GLenum type);
bool IsOpaqueType(GLenum type);
GLenum SamplerTypeToTextureType(GLenum samplerType);
bool IsMatrixType(GLenum type);
GLenum TransposeMatrixType(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);
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.
// 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
@ -161,9 +154,6 @@ const char *GetGenericErrorMessage(EGLint error);
namespace egl_gl
{
GLenum EGLCubeMapTargetToGLCubeMapTarget(EGLenum eglTarget);
GLenum EGLImageTargetToGLTextureTarget(EGLenum eglTarget);
GLenum EGLTextureTargetToGLTextureTarget(EGLenum eglTarget);
GLuint EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer);
}

View File

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

View File

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

View File

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

View File

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

View File

@ -57,18 +57,12 @@ enum TBasicType
EbtInt,
EbtUInt,
EbtBool,
EbtGVec4, // non type: represents vec4, ivec4, and uvec4
EbtGenType, // non type: represents float, vec2, vec3, and vec4
EbtGenIType, // non type: represents int, ivec2, ivec3, and ivec4
EbtGenUType, // non type: represents uint, uvec2, uvec3, and uvec4
EbtGenBType, // non type: represents bool, bvec2, bvec3, and bvec4
EbtVec, // non type: represents vec2, vec3, and vec4
EbtIVec, // non type: represents ivec2, ivec3, and ivec4
EbtUVec, // non type: represents uvec2, uvec3, and uvec4
EbtBVec, // non type: represents bvec2, bvec3, and bvec4
EbtAtomicCounter,
EbtYuvCscStandardEXT, // Only valid if EXT_YUV_target exists.
EbtGuardSamplerBegin, // non type: see implementation of IsSampler()
EbtSampler2D,
EbtSampler2D = EbtGuardSamplerBegin,
EbtSampler3D,
EbtSamplerCube,
EbtSampler2DArray,
@ -89,17 +83,11 @@ enum TBasicType
EbtSampler2DShadow,
EbtSamplerCubeShadow,
EbtSampler2DArrayShadow,
EbtGuardSamplerEnd, // non type: see implementation of IsSampler()
EbtGSampler2D, // non type: represents sampler2D, isampler2D, and usampler2D
EbtGSampler3D, // non type: represents sampler3D, isampler3D, and usampler3D
EbtGSamplerCube, // non type: represents samplerCube, isamplerCube, and usamplerCube
EbtGSampler2DArray, // non type: represents sampler2DArray, isampler2DArray, and
// usampler2DArray
EbtGSampler2DMS, // non type: represents sampler2DMS, isampler2DMS, and usampler2DMS
EbtGuardSamplerEnd = EbtSampler2DArrayShadow, // non type: see implementation of IsSampler()
// images
EbtGuardImageBegin,
EbtImage2D,
EbtImage2D = EbtGuardImageBegin,
EbtIImage2D,
EbtUImage2D,
EbtImage3D,
@ -111,131 +99,41 @@ enum TBasicType
EbtImageCube,
EbtIImageCube,
EbtUImageCube,
EbtGuardImageEnd,
EbtGuardImageEnd = EbtUImageCube,
EbtGuardGImageBegin,
EbtGImage2D, // non type: represents image2D, uimage2D, iimage2D
EbtGImage3D, // non type: represents image3D, uimage3D, iimage3D
EbtGImage2DArray, // non type: represents image2DArray, uimage2DArray, iimage2DArray
EbtGImageCube, // non type: represents imageCube, uimageCube, iimageCube
EbtGuardGImageEnd,
EbtLastSimpleType = EbtGuardImageEnd,
EbtStruct,
EbtInterfaceBlock,
EbtAddress, // should be deprecated??
EbtAtomicCounter,
// 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 "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 "";
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);
inline bool IsSampler(TBasicType type)
{
return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd;
return type >= EbtGuardSamplerBegin && type <= EbtGuardSamplerEnd;
}
inline bool IsImage(TBasicType type)
{
return type > EbtGuardImageBegin && type < EbtGuardImageEnd;
}
inline bool IsGImage(TBasicType type)
{
return type > EbtGuardGImageBegin && type < EbtGuardGImageEnd;
return type >= EbtGuardImageBegin && type <= EbtGuardImageEnd;
}
inline bool IsAtomicCounter(TBasicType type)

View File

@ -6,9 +6,9 @@
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "angle_gl.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/StaticType.h"
#include "compiler/translator/Symbol.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh
{
@ -23,10 +23,9 @@ class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTr
bool visitUnary(Visit visit, TIntermUnary *node) override
{
if (visit == PreVisit)
if (node->getFunction())
{
bool needToEmulate =
mEmulator.setFunctionCalled(node->getOp(), node->getOperand()->getType());
bool needToEmulate = mEmulator.setFunctionCalled(node->getFunction());
if (needToEmulate)
node->setUseEmulatedFunction();
}
@ -35,56 +34,15 @@ class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTr
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
// 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();
return true;
}
bool needToEmulate = mEmulator.setFunctionCalled(node->getFunction());
if (needToEmulate)
node->setUseEmulatedFunction();
return true;
}
@ -96,74 +54,19 @@ BuiltInFunctionEmulator::BuiltInFunctionEmulator()
{
}
FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
const TType *param,
const char *emulatedFunctionDefinition)
void BuiltInFunctionEmulator::addEmulatedFunction(const TSymbolUniqueId &uniqueId,
const char *emulatedFunctionDefinition)
{
FunctionId id(op, param);
mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
return id;
mEmulatedFunctions[uniqueId.get()] = std::string(emulatedFunctionDefinition);
}
FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
const TType *param1,
const TType *param2,
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,
void BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
const TSymbolUniqueId &dependency,
const TSymbolUniqueId &uniqueId,
const char *emulatedFunctionDefinition)
{
FunctionId id(op, param1, param2);
mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
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;
mEmulatedFunctions[uniqueId.get()] = std::string(emulatedFunctionDefinition);
mFunctionDependencies[uniqueId.get()] = dependency.get();
}
bool BuiltInFunctionEmulator::isOutputEmpty() const
@ -182,47 +85,18 @@ void BuiltInFunctionEmulator::outputEmulatedFunctions(TInfoSinkBase &out) const
}
}
bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, const TType &param)
{
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
const char *BuiltInFunctionEmulator::findEmulatedFunction(int uniqueId) const
{
for (const auto &queryFunction : mQueryFunctions)
{
const char *result = queryFunction(functionId);
const char *result = queryFunction(uniqueId);
if (result)
{
return result;
}
}
const auto &result = mEmulatedFunctions.find(functionId);
const auto &result = mEmulatedFunctions.find(uniqueId);
if (result != mEmulatedFunctions.end())
{
return result->second.c_str();
@ -231,27 +105,31 @@ const char *BuiltInFunctionEmulator::findEmulatedFunction(const FunctionId &func
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;
}
for (size_t i = 0; i < mFunctions.size(); ++i)
{
if (mFunctions[i] == functionId)
if (mFunctions[i] == uniqueId)
return true;
}
// 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())
{
setFunctionCalled((*dependency).second);
}
// Copy the functionId if it needs to be stored, to make sure that the TType pointers inside
// remain valid and constant.
mFunctions.push_back(functionId.getCopy());
mFunctions.push_back(uniqueId);
return true;
}
@ -284,76 +162,4 @@ void BuiltInFunctionEmulator::WriteEmulatedFunctionName(TInfoSinkBase &out, cons
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

View File

@ -8,82 +8,15 @@
#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/ParamType.h"
namespace sh
{
struct MiniFunctionId
{
constexpr MiniFunctionId(TOperator op = EOpNull,
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)
{
}
class TIntermNode;
class TFunction;
class TSymbolUniqueId;
TOperator op;
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 &);
using BuiltinQueryFunc = const char *(int);
//
// 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;
// Add functions that need to be emulated.
FunctionId addEmulatedFunction(TOperator op,
const TType *param,
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);
void addEmulatedFunction(const TSymbolUniqueId &uniqueId,
const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency,
TOperator op,
const TType *param1,
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 addEmulatedFunctionWithDependency(const TSymbolUniqueId &dependency,
const TSymbolUniqueId &uniqueId,
const char *emulatedFunctionDefinition);
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
// function is not in mEmulatedFunctions, this becomes a no-op. Returns true if the function
// call needs to be replaced with an emulated one.
bool setFunctionCalled(TOperator op, const TType &param);
bool setFunctionCalled(TOperator op, const TType &param1, const TType &param2);
bool setFunctionCalled(TOperator op,
const TType &param1,
const TType &param2,
const TType &param3);
bool setFunctionCalled(TOperator op,
const TType &param1,
const TType &param2,
const TType &param3,
const TType &param4);
bool setFunctionCalled(const TFunction *function);
bool setFunctionCalled(int uniqueId);
bool setFunctionCalled(const FunctionId &functionId);
const char *findEmulatedFunction(int uniqueId) const;
const char *findEmulatedFunction(const FunctionId &functionId) const;
// Map from function id to emulated function definition
std::map<FunctionId, std::string> mEmulatedFunctions;
// Map from function unique id to emulated function definition
std::map<int, std::string> mEmulatedFunctions;
// Map from dependent functions to their dependencies. This structure allows each function to
// have at most one dependency.
std::map<FunctionId, FunctionId> mFunctionDependencies;
std::map<int, int> mFunctionDependencies;
// Called function ids
std::vector<FunctionId> mFunctions;
std::vector<int> mFunctions;
// Constexpr function tables.
std::vector<BuiltinQueryFunc *> mQueryFunctions;

View File

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

View File

@ -4,17 +4,17 @@
// found in the LICENSE file.
//
#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
#include "angle_gl.h"
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/VersionGLSL.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
namespace sh
{
// Defined in emulated_builtin_functions_hlsl_autogen.cpp.
const char *FindHLSLFunction(const FunctionId &functionID);
const char *FindHLSLFunction(int uniqueId);
void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu,
int targetGLSLVersion)
@ -22,12 +22,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
if (targetGLSLVersion < GLSL_VERSION_130)
return;
TType *float1 = new TType(EbtFloat);
TType *float2 = new TType(EbtFloat, 2);
TType *float3 = new TType(EbtFloat, 3);
TType *float4 = new TType(EbtFloat, 4);
emu->addEmulatedFunction(EOpIsnan, float1,
emu->addEmulatedFunction(BuiltInId::isnan_Float1,
"bool isnan_emu(float x)\n"
"{\n"
" return (x > 0.0 || x < 0.0) ? false : x != 0.0;\n"
@ -35,7 +30,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
"\n");
emu->addEmulatedFunction(
EOpIsnan, float2,
BuiltInId::isnan_Float2,
"bool2 isnan_emu(float2 x)\n"
"{\n"
" bool2 isnan;\n"
@ -47,7 +42,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
"}\n");
emu->addEmulatedFunction(
EOpIsnan, float3,
BuiltInId::isnan_Float3,
"bool3 isnan_emu(float3 x)\n"
"{\n"
" bool3 isnan;\n"
@ -59,7 +54,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
"}\n");
emu->addEmulatedFunction(
EOpIsnan, float4,
BuiltInId::isnan_Float4,
"bool4 isnan_emu(float4 x)\n"
"{\n"
" bool4 isnan;\n"
@ -73,43 +68,35 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
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);
// (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:
// a <= 0xffff, d <= 0xffff, ((a * c) >> 16) <= 0xffff and 0xffff * 0xffff + 0xffff = 0xffff0000
FunctionId umulExtendedUint1 = emu->addEmulatedFunction(
EOpUmulExtended, uint1, uint1, uint1, uint1,
"void umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n"
"{\n"
" lsb = x * y;\n"
" uint a = (x & 0xffffu);\n"
" uint b = (x >> 16);\n"
" uint c = (y & 0xffffu);\n"
" uint d = (y >> 16);\n"
" uint ad = a * d + ((a * c) >> 16);\n"
" uint bc = b * c;\n"
" uint carry = uint(ad > (0xffffffffu - bc));\n"
" msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n"
"}\n");
emu->addEmulatedFunction(BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
"void umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n"
"{\n"
" lsb = x * y;\n"
" uint a = (x & 0xffffu);\n"
" uint b = (x >> 16);\n"
" uint c = (y & 0xffffu);\n"
" uint d = (y >> 16);\n"
" uint ad = a * d + ((a * c) >> 16);\n"
" uint bc = b * c;\n"
" uint carry = uint(ad > (0xffffffffu - bc));\n"
" msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n"
"}\n");
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"
"{\n"
" umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
" umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
"}\n");
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"
"{\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"
"}\n");
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"
"{\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.
// 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.
FunctionId imulExtendedInt1 = emu->addEmulatedFunctionWithDependency(
umulExtendedUint1, EOpImulExtended, int1, int1, int1, int1,
emu->addEmulatedFunctionWithDependency(
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"
"{\n"
" uint unsignedMsb;\n"
@ -156,14 +145,14 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
" }\n"
"}\n");
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"
"{\n"
" imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
" imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
"}\n");
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"
"{\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"
"}\n");
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"
"{\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/Diagnostics.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh
{
@ -116,16 +116,13 @@ class CallDAG::CallDAGCreator : public TIntermTraverser
return false;
}
bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override
void visitFunctionPrototype(TIntermFunctionPrototype *node) override
{
ASSERT(mCurrentFunction == nullptr);
// Function declaration, create an empty record.
auto &record = mFunctions[node->getFunction()->uniqueId().get()];
record.name = node->getFunction()->name();
// No need to traverse the parameters.
return false;
}
// Track functions called from another function.

View File

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

View File

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

View File

@ -10,43 +10,43 @@
#include "angle_gl.h"
#include "common/utilities.h"
#include "compiler/translator/AddAndTrueToLoopCondition.h"
#include "compiler/translator/CallDAG.h"
#include "compiler/translator/ClampFragDepth.h"
#include "compiler/translator/ClampPointSize.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/InitializeVariables.h"
#include "compiler/translator/IntermNodePatternMatcher.h"
#include "compiler/translator/IsASTDepthBelowLimit.h"
#include "compiler/translator/OutputTree.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/ValidateMaxParameters.h"
#include "compiler/translator/ValidateOutputs.h"
#include "compiler/translator/ValidateVaryingLocations.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 "third_party/compiler/ArrayBoundsClamper.h"
@ -193,12 +193,12 @@ class TScopedSymbolTableLevel
public:
TScopedSymbolTableLevel(TSymbolTable *table) : mTable(table)
{
ASSERT(mTable->atBuiltInLevel());
ASSERT(mTable->isEmpty());
mTable->push();
}
~TScopedSymbolTableLevel()
{
while (!mTable->atBuiltInLevel())
while (!mTable->isEmpty())
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
TShHandleBase::TShHandleBase()
@ -451,6 +496,11 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
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
// parsing.
FoldExpressions(root, &mDiagnostics);
@ -466,16 +516,6 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
// After this empty declarations are not allowed in the AST.
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
if (!initCallDag(root))
{
@ -548,7 +588,7 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
if (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT)
{
RemovePow(root);
RemovePow(root, &symbolTable);
}
if (compileOptions & SH_REGENERATE_STRUCT_NAMES)
@ -588,6 +628,14 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
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.
// TODO(jmadill): Remove global pool allocator.
GetGlobalPoolAllocator()->lock();
@ -605,7 +653,7 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
ASSERT(!variablesCollected);
CollectVariables(root, &attributes, &outputVariables, &uniforms, &inputVaryings,
&outputVaryings, &uniformBlocks, &shaderStorageBlocks, &inBlocks,
hashFunction, &symbolTable, shaderVersion, shaderType, extensionBehavior);
hashFunction, &symbolTable, shaderType, extensionBehavior);
collectInterfaceBlocks();
variablesCollected = true;
if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS)

View File

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

View File

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

View File

@ -35,17 +35,35 @@ template <>
const size_t ImmutableString::FowlerNollVoHash<8>::kFnvOffsetBasis =
static_cast<size_t>(0xcbf29ce484222325ull);
uint32_t ImmutableString::hash32() const
uint32_t ImmutableString::mangledNameHash() const
{
const char *data_ptr = data();
uint32_t hash = static_cast<uint32_t>(FowlerNollVoHash<4>::kFnvOffsetBasis);
while ((*data_ptr) != '\0')
const char *dataPtr = data();
uint32_t hash = static_cast<uint32_t>(FowlerNollVoHash<4>::kFnvOffsetBasis);
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);
++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

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:
const char *mData;

View File

@ -47,7 +47,7 @@ class ImmutableStringBuilder
while (index >= 0)
{
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;
--index;
}

View File

@ -264,7 +264,7 @@ bool TIntermBlock::replaceChildNode(TIntermNode *original, TIntermNode *replacem
bool TIntermFunctionPrototype::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{
return replaceChildNodeInternal(original, replacement);
return false;
}
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)
{
ASSERT(declarator != nullptr);
@ -801,6 +795,7 @@ TIntermSwizzle::TIntermSwizzle(const TIntermSwizzle &node) : TIntermExpression(n
ASSERT(operandCopy != nullptr);
mOperand = operandCopy;
mSwizzleOffsets = node.mSwizzleOffsets;
mHasFoldedDuplicateOffsets = node.mHasFoldedDuplicateOffsets;
}
TIntermBinary::TIntermBinary(const TIntermBinary &node)
@ -814,7 +809,9 @@ TIntermBinary::TIntermBinary(const TIntermBinary &node)
}
TIntermUnary::TIntermUnary(const TIntermUnary &node)
: TIntermOperator(node), mUseEmulatedFunction(node.mUseEmulatedFunction)
: TIntermOperator(node),
mUseEmulatedFunction(node.mUseEmulatedFunction),
mFunction(node.mFunction)
{
TIntermTyped *operandCopy = node.mOperand->deepCopy();
ASSERT(operandCopy != nullptr);
@ -1047,14 +1044,15 @@ void TIntermUnary::promote()
TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets)
: TIntermExpression(TType(EbtFloat, EbpUndefined)),
mOperand(operand),
mSwizzleOffsets(swizzleOffsets)
mSwizzleOffsets(swizzleOffsets),
mHasFoldedDuplicateOffsets(false)
{
ASSERT(mSwizzleOffsets.size() <= 4);
promote();
}
TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand)
: TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false)
TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand, const TFunction *function)
: TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false), mFunction(function)
{
promote();
}
@ -1173,6 +1171,10 @@ void TIntermSwizzle::promote()
bool TIntermSwizzle::hasDuplicateOffsets() const
{
if (mHasFoldedDuplicateOffsets)
{
return true;
}
int offsetCount[4] = {0u, 0u, 0u, 0u};
for (const auto offset : mSwizzleOffsets)
{
@ -1185,6 +1187,11 @@ bool TIntermSwizzle::hasDuplicateOffsets() const
return false;
}
void TIntermSwizzle::setHasFoldedDuplicateOffsets(bool hasFoldedDuplicateOffsets)
{
mHasFoldedDuplicateOffsets = hasFoldedDuplicateOffsets;
}
bool TIntermSwizzle::offsetsMatch(int offset) const
{
return mSwizzleOffsets.size() == 1 && mSwizzleOffsets[0] == offset;
@ -1478,6 +1485,24 @@ const TConstantUnion *TIntermConstantUnion::FoldIndexing(const TType &type,
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();
if (operandConstant == nullptr)
{

View File

@ -431,6 +431,7 @@ class TIntermSwizzle : public TIntermExpression
void writeOffsetsAsXYZW(TInfoSinkBase *out) const;
bool hasDuplicateOffsets() const;
void setHasFoldedDuplicateOffsets(bool hasFoldedDuplicateOffsets);
bool offsetsMatch(int offset) const;
TIntermTyped *fold(TDiagnostics *diagnostics) override;
@ -438,6 +439,7 @@ class TIntermSwizzle : public TIntermExpression
protected:
TIntermTyped *mOperand;
TVector<int> mSwizzleOffsets;
bool mHasFoldedDuplicateOffsets;
private:
void promote();
@ -503,7 +505,7 @@ class TIntermBinary : public TIntermOperator
class TIntermUnary : public TIntermOperator
{
public:
TIntermUnary(TOperator op, TIntermTyped *operand);
TIntermUnary(TOperator op, TIntermTyped *operand, const TFunction *function);
TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); }
@ -516,6 +518,8 @@ class TIntermUnary : public TIntermOperator
TIntermTyped *getOperand() { return mOperand; }
TIntermTyped *fold(TDiagnostics *diagnostics) override;
const TFunction *getFunction() const { return mFunction; }
void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
@ -526,6 +530,8 @@ class TIntermUnary : public TIntermOperator
// to work around driver bugs.
bool mUseEmulatedFunction;
const TFunction *const mFunction;
private:
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
// a function definition. The type of the node is the function return type.
class TIntermFunctionPrototype : public TIntermTyped, public TIntermAggregateBase
class TIntermFunctionPrototype : public TIntermTyped
{
public:
TIntermFunctionPrototype(const TFunction *function);
@ -683,17 +689,9 @@ class TIntermFunctionPrototype : public TIntermTyped, public TIntermAggregateBas
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; }
protected:
TIntermSequence mParameters;
const TFunction *const mFunction;
};

View File

@ -6,7 +6,7 @@
#include "compiler/translator/IsASTDepthBelowLimit.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh
{
@ -18,24 +18,10 @@ namespace
class MaxDepthTraverser : public TIntermTraverser
{
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

View File

@ -94,8 +94,8 @@ ImmutableString TOutputGLSL::translateTextureFunction(const ImmutableString &nam
nullptr};
static const char *legacyToCoreRename[] = {
"texture2D", "texture", "texture2DProj", "textureProj", "texture2DLod", "textureLod",
"texture2DProjLod", "textureProjLod", "texture2DRect", "texture", "textureCube", "texture",
"textureCubeLod", "textureLod",
"texture2DProjLod", "textureProjLod", "texture2DRect", "texture", "texture2DRectProj",
"textureProj", "textureCube", "texture", "textureCubeLod", "textureLod",
// Extensions
"texture2DLodEXT", "textureLod", "texture2DProjLodEXT", "textureProjLod",
"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();
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();
ASSERT(arg != nullptr);
const TType &type = arg->getType();
const TVariable *param = func->getParam(i);
const TType &type = param->getType();
writeVariableType(type);
if (arg->variable().symbolType() != SymbolType::Empty)
out << " " << hashName(&arg->variable());
if (param->symbolType() != SymbolType::Empty)
out << " " << hashName(param);
if (type.isArray())
out << ArrayString(type);
// Put a comma if this is not the last argument.
if (iter != args.end() - 1)
if (i != paramCount - 1)
out << ", ";
}
}
@ -847,7 +846,7 @@ bool TOutputGLSLBase::visitBlock(Visit visit, TIntermBlock *node)
{
TInfoSinkBase &out = objSink();
// Scope the blocks except when at the global scope.
if (mDepth > 0)
if (getCurrentTraversalDepth() > 0)
{
out << "{\n";
}
@ -864,7 +863,7 @@ bool TOutputGLSLBase::visitBlock(Visit visit, TIntermBlock *node)
}
// Scope the blocks except when at the global scope.
if (mDepth > 0)
if (getCurrentTraversalDepth() > 0)
{
out << "}\n";
}
@ -890,10 +889,9 @@ bool TOutputGLSLBase::visitInvariantDeclaration(Visit visit, TIntermInvariantDec
return false;
}
bool TOutputGLSLBase::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node)
void TOutputGLSLBase::visitFunctionPrototype(TIntermFunctionPrototype *node)
{
TInfoSinkBase &out = objSink();
ASSERT(visit == PreVisit);
const TType &type = node->getType();
writeVariableType(type);
@ -903,10 +901,8 @@ bool TOutputGLSLBase::visitFunctionPrototype(Visit visit, TIntermFunctionPrototy
out << " " << hashFunctionNameIfNeeded(node->getFunction());
out << "(";
writeFunctionParameters(*(node->getSequence()));
writeFunctionParameters(node->getFunction());
out << ")";
return false;
}
bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)

View File

@ -11,7 +11,7 @@
#include "compiler/translator/HashNames.h"
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh
{
@ -44,7 +44,7 @@ class TOutputGLSLBase : public TIntermTraverser
void writeInvariantQualifier(const TType &type);
void writeVariableType(const TType &type);
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);
void writeConstructorTriplet(Visit visit, const TType &type);
ImmutableString getTypeName(const TType &type);
@ -58,7 +58,7 @@ class TOutputGLSLBase : public TIntermTraverser
bool visitIfElse(Visit visit, TIntermIfElse *node) override;
bool visitSwitch(Visit visit, TIntermSwitch *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 visitAggregate(Visit visit, TIntermAggregate *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
virtual ImmutableString translateTextureFunction(const ImmutableString &name) { return name; }
void declareStruct(const TStructure *structure);
private:
bool structDeclared(const TStructure *structure) const;
void declareStruct(const TStructure *structure);
void declareInterfaceBlockLayout(const TInterfaceBlock *interfaceBlock);
void declareInterfaceBlock(const TInterfaceBlock *interfaceBlock);

View File

@ -15,17 +15,17 @@
#include "common/utilities.h"
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
#include "compiler/translator/FindSymbolNode.h"
#include "compiler/translator/ImageFunctionHLSL.h"
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/NodeSearch.h"
#include "compiler/translator/RemoveSwitchFallThrough.h"
#include "compiler/translator/StructureHLSL.h"
#include "compiler/translator/TextureFunctionHLSL.h"
#include "compiler/translator/TranslatorHLSL.h"
#include "compiler/translator/UniformHLSL.h"
#include "compiler/translator/UtilsHLSL.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"
namespace sh
@ -1756,35 +1756,30 @@ bool OutputHLSL::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition
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(";
}
else
{
out << DecorateFunctionIfNeeded(node->getFunction()) << DisambiguateFunctionName(parameters)
out << DecorateFunctionIfNeeded(func) << DisambiguateFunctionName(func)
<< (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());
writeParameter(symbol, out);
if (i < parameters->size() - 1)
{
out << ", ";
}
out << ", ";
}
else
UNREACHABLE();
}
out << ")\n";
@ -1871,32 +1866,29 @@ bool OutputHLSL::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclarat
return false;
}
bool OutputHLSL::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node)
void OutputHLSL::visitFunctionPrototype(TIntermFunctionPrototype *node)
{
TInfoSinkBase &out = getInfoSink();
ASSERT(visit == PreVisit);
size_t index = mCallDag.findIndex(node->getFunction()->uniqueId());
// Skip the prototype if it is not implemented (and thus not used)
if (index == CallDAG::InvalidIndex)
{
return false;
return;
}
TIntermSequence *arguments = node->getSequence();
const TFunction *func = node->getFunction();
TString name = DecorateFunctionIfNeeded(node->getFunction());
out << TypeString(node->getType()) << " " << name << DisambiguateFunctionName(arguments)
TString name = DecorateFunctionIfNeeded(func);
out << TypeString(node->getType()) << " " << name << DisambiguateFunctionName(func)
<< (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();
ASSERT(symbol != nullptr);
writeParameter(func->getParam(i), out);
writeParameter(symbol, out);
if (i < arguments->size() - 1)
if (i < paramCount - 1)
{
out << ", ";
}
@ -1912,8 +1904,6 @@ bool OutputHLSL::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *n
node->traverse(this);
mOutputLod0Function = false;
}
return false;
}
bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
@ -2128,6 +2118,24 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
ASSERT(node->getUseEmulatedFunction());
writeEmulatedFunctionTriplet(out, visit, node->getOp());
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:
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 = symbol->getType();
const TVariable &variable = symbol->variable();
TString nameStr;
const TType &type = param->getType();
TQualifier qualifier = type.getQualifier();
if (variable.symbolType() ==
SymbolType::Empty) // HLSL demands named arguments, also for prototypes
{
nameStr = "x" + str(mUniqueIndex++);
}
else
{
nameStr = DecorateVariableIfNeeded(variable);
}
TString nameStr = DecorateVariableIfNeeded(*param);
ASSERT(nameStr != ""); // HLSL demands named arguments, also for prototypes
if (IsSampler(type.getBasicType()))
{

View File

@ -16,7 +16,7 @@
#include "compiler/translator/Compiler.h"
#include "compiler/translator/FlagStd140Structs.h"
#include "compiler/translator/ImmutableString.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
class BuiltInFunctionEmulator;
@ -93,7 +93,7 @@ class OutputHLSL : public TIntermTraverser
bool visitIfElse(Visit visit, TIntermIfElse *) override;
bool visitSwitch(Visit visit, TIntermSwitch *) 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 visitAggregate(Visit visit, TIntermAggregate *) override;
bool visitBlock(Visit visit, TIntermBlock *node) override;
@ -112,7 +112,7 @@ class OutputHLSL : public TIntermTraverser
const char *inString,
const char *postString);
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);
const TConstantUnion *writeConstantUnion(TInfoSinkBase &out,

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh
{
@ -31,7 +31,10 @@ void OutputFunction(TInfoSinkBase &out, const char *str, const TFunction *func)
class TOutputTraverser : public TIntermTraverser
{
public:
TOutputTraverser(TInfoSinkBase &out) : TIntermTraverser(true, false, false), mOut(out) {}
TOutputTraverser(TInfoSinkBase &out)
: TIntermTraverser(true, false, false), mOut(out), mIndentDepth(0)
{
}
protected:
void visitSymbol(TIntermSymbol *) override;
@ -43,7 +46,7 @@ class TOutputTraverser : public TIntermTraverser
bool visitIfElse(Visit visit, TIntermIfElse *node) override;
bool visitSwitch(Visit visit, TIntermSwitch *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 visitAggregate(Visit visit, TIntermAggregate *) override;
bool visitBlock(Visit visit, TIntermBlock *) override;
@ -52,7 +55,10 @@ class TOutputTraverser : public TIntermTraverser
bool visitLoop(Visit visit, TIntermLoop *) override;
bool visitBranch(Visit visit, TIntermBranch *) override;
int getCurrentIndentDepth() const { return mIndentDepth + getCurrentTraversalDepth(); }
TInfoSinkBase &mOut;
int mIndentDepth;
};
//
@ -79,7 +85,7 @@ void OutputTreeText(TInfoSinkBase &out, TIntermNode *node, const int depth)
void TOutputTraverser::visitSymbol(TIntermSymbol *node)
{
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
if (node->variable().symbolType() == SymbolType::Empty)
{
@ -96,7 +102,7 @@ void TOutputTraverser::visitSymbol(TIntermSymbol *node)
bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node)
{
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "vector swizzle (";
node->writeOffsetsAsXYZW(&mOut);
mOut << ")";
@ -108,7 +114,7 @@ bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node)
bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
{
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
switch (node->getOp())
{
@ -270,7 +276,7 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
TIntermConstantUnion *intermConstantUnion = node->getRight()->getAsConstantUnion();
ASSERT(intermConstantUnion);
OutputTreeText(mOut, intermConstantUnion, mDepth + 1);
OutputTreeText(mOut, intermConstantUnion, getCurrentIndentDepth() + 1);
// The following code finds the field name from the constant union
const TConstantUnion *constantUnion = intermConstantUnion->getConstantValue();
@ -294,7 +300,7 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
{
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
switch (node->getOp())
{
@ -348,32 +354,37 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
bool TOutputTraverser::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
{
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "Function Definition:\n";
mOut << "\n";
return true;
}
bool TOutputTraverser::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node)
{
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "Invariant Declaration:\n";
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());
mOut << " (" << node->getCompleteString() << ")";
mOut << "\n";
return true;
size_t paramCount = node->getFunction()->getParamCount();
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)
{
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
if (node->getOp() == EOpNull)
{
@ -445,7 +456,7 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
bool TOutputTraverser::visitBlock(Visit visit, TIntermBlock *node)
{
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "Code block\n";
return true;
@ -453,7 +464,7 @@ bool TOutputTraverser::visitBlock(Visit visit, TIntermBlock *node)
bool TOutputTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node)
{
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "Declaration\n";
return true;
@ -461,18 +472,18 @@ bool TOutputTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node)
bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node)
{
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "Ternary selection";
mOut << " (" << node->getCompleteString() << ")\n";
++mDepth;
++mIndentDepth;
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "Condition\n";
node->getCondition()->traverse(this);
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
if (node->getTrueExpression())
{
mOut << "true case\n";
@ -480,29 +491,29 @@ bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node)
}
if (node->getFalseExpression())
{
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "false case\n";
node->getFalseExpression()->traverse(this);
}
--mDepth;
--mIndentDepth;
return false;
}
bool TOutputTraverser::visitIfElse(Visit visit, TIntermIfElse *node)
{
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "If test\n";
++mDepth;
++mIndentDepth;
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "Condition\n";
node->getCondition()->traverse(this);
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
if (node->getTrueBlock())
{
mOut << "true case\n";
@ -515,19 +526,19 @@ bool TOutputTraverser::visitIfElse(Visit visit, TIntermIfElse *node)
if (node->getFalseBlock())
{
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "false case\n";
node->getFalseBlock()->traverse(this);
}
--mDepth;
--mIndentDepth;
return false;
}
bool TOutputTraverser::visitSwitch(Visit visit, TIntermSwitch *node)
{
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "Switch\n";
@ -536,7 +547,7 @@ bool TOutputTraverser::visitSwitch(Visit visit, TIntermSwitch *node)
bool TOutputTraverser::visitCase(Visit visit, TIntermCase *node)
{
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
if (node->getCondition() == nullptr)
{
@ -556,7 +567,7 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion *node)
for (size_t i = 0; i < size; i++)
{
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
switch (node->getConstantValue()[i].getType())
{
case EbtBool:
@ -597,16 +608,16 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion *node)
bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop *node)
{
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "Loop with condition ";
if (node->getType() == ELoopDoWhile)
mOut << "not ";
mOut << "tested first\n";
++mDepth;
++mIndentDepth;
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
if (node->getCondition())
{
mOut << "Loop Condition\n";
@ -617,7 +628,7 @@ bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop *node)
mOut << "No loop condition\n";
}
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
if (node->getBody())
{
mOut << "Loop Body\n";
@ -630,19 +641,19 @@ bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop *node)
if (node->getExpression())
{
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "Loop Terminal Expression\n";
node->getExpression()->traverse(this);
}
--mDepth;
--mIndentDepth;
return false;
}
bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node)
{
OutputTreeText(mOut, node, mDepth);
OutputTreeText(mOut, node, getCurrentIndentDepth());
switch (node->getFlowOp())
{
@ -666,9 +677,9 @@ bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node)
if (node->getExpression())
{
mOut << " with expression\n";
++mDepth;
++mIndentDepth;
node->getExpression()->traverse(this);
--mDepth;
--mIndentDepth;
}
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 "compiler/preprocessor/SourceLocation.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/ValidateGlobalInitializer.h"
#include "compiler/translator/ValidateSwitch.h"
#include "compiler/translator/glslang.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/util.h"
namespace sh
@ -33,33 +34,6 @@ namespace
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 TType &type)
@ -222,9 +196,6 @@ TParseContext::TParseContext(TSymbolTable &symt,
resources.WEBGL_debug_shader_precision == 1),
mPreprocessor(mDiagnostics, &mDirectiveHandler, pp::PreprocessorSettings()),
mScanner(nullptr),
mUsesFragData(false),
mUsesFragColor(false),
mUsesSecondaryOutputs(false),
mMinProgramTexelOffset(resources.MinProgramTexelOffset),
mMaxProgramTexelOffset(resources.MaxProgramTexelOffset),
mMinProgramTextureGatherOffset(resources.MinProgramTextureGatherOffset),
@ -245,8 +216,7 @@ TParseContext::TParseContext(TSymbolTable &symt,
mGeometryShaderInvocations(0),
mGeometryShaderMaxVertices(-1),
mMaxGeometryShaderInvocations(resources.MaxGeometryShaderInvocations),
mMaxGeometryShaderMaxVertices(resources.MaxGeometryOutputVertices),
mGlInVariableWithArraySize(nullptr)
mMaxGeometryShaderMaxVertices(resources.MaxGeometryOutputVertices)
{
}
@ -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
// an l-value that can be operated on this way.
bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node)
{
TIntermSymbol *symNode = node->getAsSymbolNode();
TIntermBinary *binaryNode = node->getAsBinaryNode();
TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
if (swizzleNode)
{
bool ok = checkCanBeLValue(line, op, swizzleNode->getOperand());
@ -488,6 +485,7 @@ bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIn
return ok;
}
TIntermBinary *binaryNode = node->getAsBinaryNode();
if (binaryNode)
{
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);
return false;
}
//
// Everything else is okay, no error.
//
if (message.empty())
symbolTable.markStaticWrite(symNode->variable());
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;
reasonStream << "l-value required (" << message << ")";
std::string reason = reasonStream.str();
error(line, reason.c_str(), op);
if (symNode)
{
// Symbol inside an expression can't be nameless.
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;
}
@ -726,6 +716,7 @@ bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
for (TIntermNode *arg : arguments)
{
markStaticReadIfSymbol(arg);
const TIntermTyped *argTyped = arg->getAsTyped();
ASSERT(argTyped != nullptr);
if (type.getBasicType() != EbtStruct && IsOpaqueType(argTyped->getBasicType()))
@ -1169,7 +1160,7 @@ bool TParseContext::declareVariable(const TSourceLoc &line,
if (needsReservedCheck && !checkIsNotReserved(line, identifier))
return false;
if (!symbolTable.declareVariable(*variable))
if (!symbolTable.declare(*variable))
{
error(line, "redefinition", identifier);
return false;
@ -1700,17 +1691,22 @@ void TParseContext::functionCallRValueLValueErrorCheck(const TFunction *fnCandid
{
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();
if (!IsImage(argument->getBasicType()) && (IsQualifierUnspecified(qual) || qual == EvqIn ||
qual == EvqInOut || qual == EvqConstReadOnly))
bool argumentIsRead = (IsQualifierUnspecified(qual) || qual == EvqIn || qual == EvqInOut ||
qual == EvqConstReadOnly);
if (argumentIsRead)
{
if (argument->getMemoryQualifier().writeonly)
markStaticReadIfSymbol(argument);
if (!IsImage(argument->getBasicType()))
{
error(argument->getLine(),
"Writeonly value cannot be passed for 'in' or 'inout' parameters.",
fnCall->functionName());
return;
if (argument->getMemoryQualifier().writeonly)
{
error(argument->getLine(),
"Writeonly value cannot be passed for 'in' or 'inout' parameters.",
fnCall->functionName());
return;
}
}
}
if (qual == EvqOut || qual == EvqInOut)
@ -1831,40 +1827,9 @@ const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
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
if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
qualifier == EvqWorkGroupSize)
variable->getType().getQualifier() == EvqWorkGroupSize)
{
error(location,
"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) &&
(variableType.getQualifier() == EvqPerVertexIn))
{
ASSERT(mGlInVariableWithArraySize != nullptr);
node = new TIntermSymbol(mGlInVariableWithArraySize);
ASSERT(symbolTable.getGlInVariableWithArraySize() != nullptr);
node = new TIntermSymbol(symbolTable.getGlInVariableWithArraySize());
}
else
{
@ -2031,6 +1996,7 @@ bool TParseContext::executeInitializer(const TSourceLoc &line,
}
*initNode = new TIntermBinary(EOpInitialize, intermSymbol, initializer);
markStaticReadIfSymbol(initializer);
(*initNode)->setLine(line);
return true;
}
@ -2073,8 +2039,19 @@ TIntermNode *TParseContext::addLoop(TLoopType type,
TIntermTyped *typedCond = nullptr;
if (cond)
{
markStaticReadIfSymbol(cond);
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 (type == ELoopDoWhile)
@ -2121,6 +2098,16 @@ TIntermNode *TParseContext::addIfElse(TIntermTyped *cond,
const TSourceLoc &loc)
{
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.
if (isScalarBool && cond->getAsConstantUnion())
@ -2136,6 +2123,7 @@ TIntermNode *TParseContext::addIfElse(TIntermTyped *cond,
}
TIntermIfElse *node = new TIntermIfElse(cond, EnsureBlock(code.node1), EnsureBlock(code.node2));
markStaticReadIfSymbol(cond);
node->setLine(loc);
return node;
@ -2383,9 +2371,9 @@ void TParseContext::checkGeometryShaderInputAndSetArraySize(const TSourceLoc &lo
// input primitive declaration.
if (mGeometryShaderInputPrimitiveType != EptUndefined)
{
ASSERT(mGlInVariableWithArraySize != nullptr);
ASSERT(symbolTable.getGlInVariableWithArraySize() != nullptr);
type->sizeOutermostUnsizedArray(
mGlInVariableWithArraySize->getType().getOutermostArraySize());
symbolTable.getGlInVariableWithArraySize()->getType().getOutermostArraySize());
}
else
{
@ -2855,17 +2843,7 @@ bool TParseContext::checkPrimitiveTypeMatchesTypeQualifier(const TTypeQualifier
void TParseContext::setGeometryShaderInputArraySize(unsigned int inputArraySize,
const TSourceLoc &line)
{
if (mGlInVariableWithArraySize == nullptr)
{
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)
if (!symbolTable.setGlInArraySize(inputArraySize))
{
error(line,
"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++)
{
const TConstParameter &param = function.getParam(i);
TIntermSymbol *symbol = nullptr;
const TVariable *param = function.getParam(i);
// 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).
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 (!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.
ASSERT(!param.type->isUnsizedArray());
ASSERT(!param->getType().isUnsizedArray());
}
else
{
if (param.type->isUnsizedArray())
if (param->getType().isUnsizedArray())
{
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
// 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;
}
@ -3313,8 +3275,8 @@ TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TF
for (size_t i = 0u; i < function->getParamCount(); ++i)
{
auto &param = function->getParam(i);
if (param.type->isStructSpecifier())
const TVariable *param = function->getParam(i);
if (param->getType().isStructSpecifier())
{
// ESSL 3.00.6 section 12.10.
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)
{
if (prevDec->getParam(i).type->getQualifier() !=
function->getParam(i).type->getQualifier())
if (prevDec->getParam(i)->getType().getQualifier() !=
function->getParam(i)->getType().getQualifier())
{
error(location,
"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(
&symbolTable, blockName, fieldList, blockLayoutQualifier, SymbolType::UserDefined);
if (!symbolTable.declareInterfaceBlock(interfaceBlock))
if (!symbolTable.declare(interfaceBlock))
{
error(nameLine, "redefinition of an interface block name", blockName);
}
@ -3826,7 +3788,7 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
TVariable *fieldVariable =
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",
field->name());
@ -3838,7 +3800,7 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
checkIsNotReserved(instanceLine, instanceName);
// 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);
}
@ -4063,6 +4025,7 @@ TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
}
}
markStaticReadIfSymbol(indexExpression);
TIntermBinary *node = new TIntermBinary(EOpIndexIndirect, baseExpression, indexExpression);
node->setLine(location);
// Indirect indexing can never be constant folded.
@ -4778,7 +4741,7 @@ TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
if (structSymbolType != SymbolType::Empty)
{
checkIsNotReserved(nameLine, structName);
if (!symbolTable.declareStructType(structure))
if (!symbolTable.declare(structure))
{
error(nameLine, "redefinition of a struct", structName);
}
@ -4840,12 +4803,13 @@ TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
}
ASSERT(statementList);
if (!ValidateSwitchStatementList(switchType, mShaderVersion, mDiagnostics, statementList, loc))
if (!ValidateSwitchStatementList(switchType, mDiagnostics, statementList, loc))
{
ASSERT(mDiagnostics->numErrors() > 0);
return nullptr;
}
markStaticReadIfSymbol(init);
TIntermSwitch *node = new TIntermSwitch(init, statementList);
node->setLine(loc);
return node;
@ -4895,7 +4859,8 @@ TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
TIntermTyped *TParseContext::createUnaryMath(TOperator op,
TIntermTyped *child,
const TSourceLoc &loc)
const TSourceLoc &loc,
const TFunction *func)
{
ASSERT(child != nullptr);
@ -4942,7 +4907,8 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op,
return nullptr;
}
TIntermUnary *node = new TIntermUnary(op, child);
markStaticReadIfSymbol(child);
TIntermUnary *node = new TIntermUnary(op, child, func);
node->setLine(loc);
return node->fold(mDiagnostics);
@ -4951,7 +4917,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op,
TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
{
ASSERT(op != EOpNull);
TIntermTyped *node = createUnaryMath(op, child, loc);
TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
if (node == nullptr)
{
return child;
@ -5345,6 +5311,9 @@ TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
}
TIntermBinary *node = new TIntermBinary(op, left, right);
ASSERT(op != EOpAssign);
markStaticReadIfSymbol(left);
markStaticReadIfSymbol(right);
node->setLine(loc);
return expressionOrFoldedResult(node);
}
@ -5380,41 +5349,39 @@ TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
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 *left,
TIntermTyped *right,
const TSourceLoc &loc)
{
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)
{
assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
return left;
}
if (op != EOpAssign)
{
markStaticReadIfSymbol(left);
}
markStaticReadIfSymbol(right);
node->setLine(loc);
return node;
}
@ -5435,6 +5402,9 @@ TIntermTyped *TParseContext::addComma(TIntermTyped *left,
}
TIntermBinary *commaNode = TIntermBinary::CreateComma(left, right, mShaderVersion);
markStaticReadIfSymbol(left);
markStaticReadIfSymbol(right);
commaNode->setLine(loc);
return expressionOrFoldedResult(commaNode);
}
@ -5480,6 +5450,7 @@ TIntermBranch *TParseContext::addBranch(TOperator op,
{
if (expression != nullptr)
{
markStaticReadIfSymbol(expression);
ASSERT(op == EOpReturn);
mFunctionReturnsValue = true;
if (mCurrentFunctionType->getBasicType() == EbtVoid)
@ -5496,14 +5467,22 @@ TIntermBranch *TParseContext::addBranch(TOperator op,
return node;
}
void TParseContext::appendStatement(TIntermBlock *block, TIntermNode *statement)
{
if (statement != nullptr)
{
markStaticReadIfSymbol(statement);
block->appendStatement(statement);
}
}
void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
{
ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
const ImmutableString &name = functionCall->getFunction()->name();
bool isTextureGather = name == kTextureGatherName;
bool isTextureGatherOffset = name == kTextureGatherOffsetName;
if (isTextureGather || isTextureGatherOffset)
const TFunction *func = functionCall->getFunction();
if (BuiltInGroup::isTextureGather(func))
{
bool isTextureGatherOffset = BuiltInGroup::isTextureGatherOffset(func);
TIntermNode *componentNode = nullptr;
TIntermSequence *arguments = functionCall->getSequence();
ASSERT(arguments->size() >= 2u && arguments->size() <= 4u);
@ -5517,7 +5496,7 @@ void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
case EbtSampler2DArray:
case EbtISampler2DArray:
case EbtUSampler2DArray:
if ((isTextureGather && arguments->size() == 3u) ||
if ((!isTextureGatherOffset && arguments->size() == 3u) ||
(isTextureGatherOffset && arguments->size() == 4u))
{
componentNode = arguments->back();
@ -5547,14 +5526,15 @@ void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
if (componentNode->getAsTyped()->getQualifier() != EvqConst || !componentConstantUnion)
{
error(functionCall->getLine(), "Texture component must be a constant expression",
name);
func->name());
}
else
{
int component = componentConstantUnion->getIConst(0);
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)
{
ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
const ImmutableString &name = functionCall->getFunction()->name();
const TFunction *func = functionCall->getFunction();
TIntermNode *offset = nullptr;
TIntermSequence *arguments = functionCall->getSequence();
bool useTextureGatherOffsetConstraints = false;
if (name == kTexelFetchOffsetName || name == kTextureLodOffsetName ||
name == kTextureProjLodOffsetName || name == kTextureGradOffsetName ||
name == kTextureProjGradOffsetName)
if (BuiltInGroup::isTextureOffsetNoBias(func))
{
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);
offset = (*arguments)[2];
}
else if (name == kTextureGatherOffsetName)
else if (BuiltInGroup::isTextureGatherOffset(func))
{
ASSERT(arguments->size() >= 3u);
const TIntermTyped *sampler = arguments->front()->getAsTyped();
@ -5610,7 +5588,8 @@ void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
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
{
@ -5640,8 +5619,8 @@ void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
void TParseContext::checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall)
{
ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
const ImmutableString &functionName = functionCall->getFunction()->name();
if (IsAtomicBuiltin(functionName))
const TFunction *func = functionCall->getFunction();
if (BuiltInGroup::isAtomicMemory(func))
{
TIntermSequence *arguments = functionCall->getSequence();
TIntermTyped *memNode = (*arguments)[0]->getAsTyped();
@ -5663,7 +5642,7 @@ void TParseContext::checkAtomicMemoryBuiltinFunctions(TIntermAggregate *function
error(memNode->getLine(),
"The value passed to the mem argument of an atomic memory function does not "
"correspond to a buffer or shared variable.",
functionName);
func->name());
}
}
@ -5672,15 +5651,16 @@ void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *
{
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();
TIntermTyped *imageNode = (*arguments)[0]->getAsTyped();
const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier();
if (strcmp(name.data() + 5u, "Store") == 0)
if (BuiltInGroup::isImageStore(func))
{
if (memoryQualifier.readonly)
{
@ -5689,7 +5669,7 @@ void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *
GetImageArgumentToken(imageNode));
}
}
else if (strcmp(name.data() + 5u, "Load") == 0)
else if (BuiltInGroup::isImageLoad(func))
{
if (memoryQualifier.writeonly)
{
@ -5716,7 +5696,7 @@ void TParseContext::checkImageMemoryAccessForUserDefinedFunctions(
{
TIntermTyped *typedArgument = arguments[i]->getAsTyped();
const TType &functionArgumentType = typedArgument->getType();
const TType &functionParameterType = *functionDefinition->getParam(i).type;
const TType &functionParameterType = functionDefinition->getParam(i)->getType();
ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType());
if (IsImage(functionArgumentType.getBasicType()))
@ -5800,7 +5780,7 @@ TIntermTyped *TParseContext::addMethod(TFunctionLookup *fnCall, const TSourceLoc
}
else
{
TIntermUnary *node = new TIntermUnary(EOpArrayLength, thisNode);
TIntermUnary *node = new TIntermUnary(EOpArrayLength, thisNode, nullptr);
node->setLine(loc);
return node->fold(mDiagnostics);
}
@ -5858,7 +5838,8 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunctionLookup *fnCa
{
// Treat it like a built-in unary operator.
TIntermNode *unaryParamNode = fnCall->arguments().front();
TIntermTyped *callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc);
TIntermTyped *callNode =
createUnaryMath(op, unaryParamNode->getAsTyped(), loc, fnCandidate);
ASSERT(callNode != nullptr);
return callNode;
}
@ -5955,6 +5936,9 @@ TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
}
TIntermTernary *node = new TIntermTernary(cond, trueExpression, falseExpression);
markStaticReadIfSymbol(cond);
markStaticReadIfSymbol(trueExpression);
markStaticReadIfSymbol(falseExpression);
node->setLine(loc);
return expressionOrFoldedResult(node);
}

View File

@ -419,6 +419,8 @@ class TParseContext : angle::NonCopyable
TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc);
TIntermBranch *addBranch(TOperator op, TIntermTyped *expression, const TSourceLoc &loc);
void appendStatement(TIntermBlock *block, TIntermNode *statement);
void checkTextureGather(TIntermAggregate *functionCall);
void checkTextureOffsetConst(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.
constexpr static size_t kAtomicCounterArrayStride = 4;
void markStaticReadIfSymbol(TIntermNode *node);
// Returns a clamped index. If it prints out an error message, the token is "[]".
int checkIndexLessThan(bool outOfRangeIndexIsError,
const TSourceLoc &location,
@ -545,11 +549,10 @@ class TParseContext : angle::NonCopyable
TIntermTyped *left,
TIntermTyped *right,
const TSourceLoc &loc);
TIntermBinary *createAssign(TOperator op,
TIntermTyped *left,
TIntermTyped *right,
const TSourceLoc &loc);
TIntermTyped *createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
TIntermTyped *createUnaryMath(TOperator op,
TIntermTyped *child,
const TSourceLoc &loc,
const TFunction *func);
TIntermTyped *addMethod(TFunctionLookup *fnCall, const TSourceLoc &loc);
TIntermTyped *addConstructor(TFunctionLookup *fnCall, const TSourceLoc &line);
@ -606,10 +609,6 @@ class TParseContext : angle::NonCopyable
TDirectiveHandler mDirectiveHandler;
pp::Preprocessor mPreprocessor;
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 mMaxProgramTexelOffset;
@ -642,10 +641,6 @@ class TParseContext : angle::NonCopyable
int mGeometryShaderMaxVertices;
int mMaxGeometryShaderInvocations;
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,

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()
: type(0), precision(0), flattenedOffsetInParentArrays(0), staticUse(false)
: type(0), precision(0), flattenedOffsetInParentArrays(0), staticUse(false), active(false)
{
}
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)
: type(typeIn), precision(0), flattenedOffsetInParentArrays(0), staticUse(false)
: type(typeIn), precision(0), flattenedOffsetInParentArrays(0), staticUse(false), active(false)
{
ASSERT(arraySizeIn != 0);
arraySizes.push_back(arraySizeIn);
@ -60,6 +60,7 @@ ShaderVariable::ShaderVariable(const ShaderVariable &other)
arraySizes(other.arraySizes),
flattenedOffsetInParentArrays(other.flattenedOffsetInParentArrays),
staticUse(other.staticUse),
active(other.active),
fields(other.fields),
structName(other.structName)
{
@ -73,6 +74,7 @@ ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other)
mappedName = other.mappedName;
arraySizes = other.arraySizes;
staticUse = other.staticUse;
active = other.active;
flattenedOffsetInParentArrays = other.flattenedOffsetInParentArrays;
fields = other.fields;
structName = other.structName;
@ -83,8 +85,8 @@ bool ShaderVariable::operator==(const ShaderVariable &other) const
{
if (type != other.type || precision != other.precision || name != other.name ||
mappedName != other.mappedName || arraySizes != other.arraySizes ||
staticUse != other.staticUse || fields.size() != other.fields.size() ||
structName != other.structName)
staticUse != other.staticUse || active != other.active ||
fields.size() != other.fields.size() || structName != other.structName)
{
return false;
}
@ -454,6 +456,7 @@ InterfaceBlock::InterfaceBlock()
isRowMajorLayout(false),
binding(-1),
staticUse(false),
active(false),
blockType(BlockType::BLOCK_UNIFORM)
{
}
@ -471,6 +474,7 @@ InterfaceBlock::InterfaceBlock(const InterfaceBlock &other)
isRowMajorLayout(other.isRowMajorLayout),
binding(other.binding),
staticUse(other.staticUse),
active(other.active),
blockType(other.blockType),
fields(other.fields)
{
@ -486,6 +490,7 @@ InterfaceBlock &InterfaceBlock::operator=(const InterfaceBlock &other)
isRowMajorLayout = other.isRowMajorLayout;
binding = other.binding;
staticUse = other.staticUse;
active = other.active;
blockType = other.blockType;
fields = other.fields;
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.
//
// 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.
static constexpr size_t kStaticMangledNameMaxLength = 10;
static constexpr size_t kStaticMangledNameLength = 2;
// 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.
struct StaticMangledName
{
// 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.
@ -45,40 +45,9 @@ constexpr StaticMangledName BuildStaticMangledName(TBasicType basicType,
unsigned char secondarySize)
{
StaticMangledName name = {};
// When this function is executed constexpr (should be always),
// name.name[at] is guaranteed by the compiler to never go out of bounds.
size_t at = 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';
name.name[0] = TType::GetSizeMangledName(primarySize, secondarySize);
name.name[1] = GetBasicMangledName(basicType);
name.name[2] = '\0';
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 sh

View File

@ -46,11 +46,13 @@ TSymbol::TSymbol(TSymbolTable *symbolTable,
ImmutableString TSymbol::name() const
{
if (mName != "")
if (!mName.empty())
{
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();
ImmutableStringBuilder symbolNameOut(sizeof(uniqueId) * 2u + 1u);
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,
const TString &apiNamePrefix,
TVector<const TVariable *> *outputSymbols,
@ -124,6 +134,17 @@ TInterfaceBlock::TInterfaceBlock(TSymbolTable *symbolTable,
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,
const ImmutableString &name,
SymbolType symbolType,
@ -145,32 +166,7 @@ TFunction::TFunction(TSymbolTable *symbolTable,
ASSERT(name != nullptr || symbolType == SymbolType::AngleInternal);
}
TFunction::TFunction(TSymbolTable *symbolTable,
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)
void TFunction::addParameter(const TVariable *p)
{
ASSERT(mParametersVector);
mParametersVector->push_back(p);
@ -195,7 +191,7 @@ ImmutableString TFunction::buildMangledName() const
for (size_t i = 0u; i < mParamCount; ++i)
{
newName += mParameters[i].type->getMangledName();
newName += mParameters[i]->getType().getMangledName();
}
return ImmutableString(newName);
}

View File

@ -42,8 +42,10 @@ class TSymbol : angle::NonCopyable
// either statically allocated or pool allocated.
~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;
// Don't call getMangledName() for empty symbols (symbolType == SymbolType::Empty).
virtual ImmutableString getMangledName() const;
virtual bool isFunction() const { return false; }
@ -89,7 +91,7 @@ class TVariable : public TSymbol
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,
const ImmutableString &name,
SymbolType symbolType,
@ -99,6 +101,7 @@ class TVariable : public TSymbol
{
}
private:
const TType *mType;
const TConstantUnion *unionArray;
};
@ -125,6 +128,13 @@ class TStructure : public TSymbol, public TFieldListCollection
bool atGlobalScope() const { return mAtGlobalScope; }
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
// setName(). At the moment keep this function private so only
// friend class RegenerateStructNames may call it.
@ -150,44 +160,33 @@ class TInterfaceBlock : public TSymbol, public TFieldListCollection
int blockBinding() const { return mBinding; }
private:
friend class TSymbolTable;
// For creating built-in interface blocks.
TInterfaceBlock(const TSymbolUniqueId &id,
const ImmutableString &name,
TExtension extension,
const TFieldList *fields);
TLayoutBlockStorage mBlockStorage;
int mBinding;
// Note that we only record matrix packing on a per-field granularity.
};
// Immutable version of TParameter.
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.
// Parameter class used for parsing user-defined function parameters.
struct TParameter
{
// Destructively converts to TConstParameter.
// Destructively converts to TVariable.
// This method resets name and type to nullptrs to make sure
// their content cannot be modified after the call.
TConstParameter turnToConst()
const TVariable *createVariable(TSymbolTable *symbolTable)
{
const ImmutableString constName(name);
const TType *constType = type;
name = 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.
@ -205,24 +204,15 @@ class TFunction : public TSymbol
const TType *retType,
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; }
void addParameter(const TConstParameter &p);
void addParameter(const TVariable *p);
void shareParameters(const TFunction &parametersSource);
ImmutableString getMangledName() const override
{
if (mMangledName == "")
ASSERT(symbolType() != SymbolType::BuiltIn);
if (mMangledName.empty())
{
mMangledName = buildMangledName();
}
@ -239,21 +229,20 @@ class TFunction : public TSymbol
bool hasPrototypeDeclaration() const { return mHasPrototypeDeclaration; }
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 isMain() const;
bool isImageFunction() const;
private:
// Note: Only to be used for static built-in functions!
constexpr TFunction(const TSymbolUniqueId &id,
const ImmutableString &name,
TExtension extension,
const TConstParameter *parameters,
const TVariable *const *parameters,
size_t paramCount,
const TType *retType,
const ImmutableString &mangledName,
TOperator op,
bool knownToNotHaveSideEffects)
: TSymbol(id, name, SymbolType::BuiltIn, extension),
@ -261,7 +250,7 @@ class TFunction : public TSymbol
mParameters(parameters),
mParamCount(paramCount),
returnType(retType),
mMangledName(mangledName),
mMangledName(nullptr),
mOp(op),
defined(false),
mHasPrototypeDeclaration(false),
@ -269,11 +258,12 @@ class TFunction : public TSymbol
{
}
private:
ImmutableString buildMangledName() const;
typedef TVector<TConstParameter> TParamVector;
typedef TVector<const TVariable *> TParamVector;
TParamVector *mParametersVector;
const TConstParameter *mParameters;
const TVariable *const *mParameters;
size_t mParamCount;
const TType *const returnType;
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.
//
#include <array>
#include <memory>
#include "common/angleutils.h"
@ -39,13 +38,12 @@
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/Symbol.h"
#include "compiler/translator/SymbolTable_autogen.h"
namespace sh
{
// Define ESymbolLevel as int rather than an enum since level can go
// above GLOBAL_LEVEL and cause atBuiltInLevel() to fail if the
// compiler optimizes the >= of the last element to ==.
// Define ESymbolLevel as int rather than an enum so that we can do arithmetic on it.
typedef int ESymbolLevel;
const int COMMON_BUILTINS = 0;
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.
const int GLSL_BUILTINS = 4;
const int LAST_BUILTIN_LEVEL = GLSL_BUILTINS;
const int GLOBAL_LEVEL = 5;
struct UnmangledBuiltIn
{
constexpr UnmangledBuiltIn() : extension(TExtension::UNDEFINED) {}
constexpr UnmangledBuiltIn(TExtension extension) : extension(extension) {}
TExtension extension;
};
class TSymbolTable : angle::NonCopyable
class TSymbolTable : angle::NonCopyable, TSymbolTableBase
{
public:
TSymbolTable();
@ -76,22 +71,16 @@ class TSymbolTable : angle::NonCopyable
~TSymbolTable();
// When the symbol table is initialized with the built-ins, there should
// 'push' calls, so that built-ins are at level 0 and the shader
// 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; }
bool isEmpty() const;
bool atGlobalLevel() const;
void push();
void pop();
// The declare* entry points are used when parsing and declare symbols at the current scope.
// They return the created true in case the declaration was successful, and false if the
// declaration failed due to redefinition.
bool declareVariable(TVariable *variable);
bool declareStructType(TStructure *str);
bool declareInterfaceBlock(TInterfaceBlock *interfaceBlock);
// Declare a non-function symbol at the current scope. Return true in case the declaration was
// successful, and false if the declaration failed due to redefinition.
bool declare(TSymbol *symbol);
// Functions are always declared at global scope.
void declareUserDefinedFunction(TFunction *function, bool insertUnmangledName);
@ -101,6 +90,19 @@ class TSymbolTable : angle::NonCopyable
const TFunction *setFunctionParameterNamesFromDefinition(const TFunction *function,
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
// with a reference to a short-lived char * is fine to pass here.
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,
bool includeGLSLBuiltins) const;
void setDefaultPrecision(TBasicType type, TPrecision prec);
// Searches down the precisionStack for a precision qualifier
@ -146,138 +144,16 @@ class TSymbolTable : angle::NonCopyable
friend class TSymbolUniqueId;
int nextUniqueIdValue();
class TSymbolTableBuiltInLevel;
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;
// 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 initializeBuiltInFunctions(sh::GLenum type);
void initializeBuiltInVariables(sh::GLenum type,
void initializeBuiltInVariables(sh::GLenum shaderType,
ShShaderSpec spec,
const ShBuiltInResources &resources);
void markBuiltInInitializationFinished();
std::vector<std::unique_ptr<TSymbolTableBuiltInLevel>> mBuiltInTable;
std::vector<std::unique_ptr<TSymbolTableLevel>> mTable;
// 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;
// -1 before built-in init has finished, one past the last built-in id afterwards.
// TODO(oetuaho): Make this a compile-time constant once the symbol table is initialized at
// compile time. http://anglebug.com/1432
int mUserDefinedUniqueIdsStart;
static const int kLastBuiltInId;
sh::GLenum mShaderType;
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

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;
int TSymbolUniqueId::get() const
{
return mId;
}
bool TSymbolUniqueId::operator==(const TSymbolUniqueId &other) const
{
return mId == other.mId;

View File

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

View File

@ -6,11 +6,11 @@
#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 "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
{

View File

@ -8,12 +8,12 @@
#include "angle_gl.h"
#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
#include "compiler/translator/EmulatePrecision.h"
#include "compiler/translator/ExtensionGLSL.h"
#include "compiler/translator/OutputGLSL.h"
#include "compiler/translator/RewriteTexelFetchOffset.h"
#include "compiler/translator/RewriteUnaryMinusOperatorFloat.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
{

View File

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

View File

@ -479,14 +479,10 @@ bool TType::canReplaceWithConstantUnion() const
//
const char *TType::buildMangledName() const
{
TString mangledName;
if (isMatrix())
mangledName += 'm';
else if (isVector())
mangledName += 'v';
TString mangledName(1, GetSizeMangledName(primarySize, secondarySize));
const char *basicMangledName = GetBasicMangledName(type);
if (basicMangledName != nullptr)
char basicMangledName = GetBasicMangledName(type);
if (basicMangledName != '{')
{
mangledName += basicMangledName;
}
@ -496,17 +492,19 @@ const char *TType::buildMangledName() const
switch (type)
{
case EbtStruct:
mangledName += "struct-";
mangledName += "{s";
if (mStructure->symbolType() != SymbolType::Empty)
{
mangledName += mStructure->name().data();
}
mangledName += mStructure->mangledFieldList();
mangledName += '}';
break;
case EbtInterfaceBlock:
mangledName += "iblock-";
mangledName += "{i";
mangledName += mInterfaceBlock->name().data();
mangledName += mInterfaceBlock->mangledFieldList();
mangledName += '}';
break;
default:
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)
{
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.
return AllocatePoolCharArray(mangledName.c_str(), mangledName.size());
}
@ -779,11 +764,6 @@ void TType::realize()
getMangledName();
}
bool TType::isRealized() const
{
return mMangledName != nullptr;
}
void TType::invalidateMangledName()
{
mMangledName = nullptr;
@ -884,7 +864,6 @@ TString TFieldListCollection::buildMangledFieldList() const
TString mangledName;
for (const auto *field : *mFields)
{
mangledName += '-';
mangledName += field->type()->getMangledName();
}
return mangledName;

View File

@ -229,6 +229,15 @@ class TType
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;
bool sameNonArrayType(const TType &right) const;
@ -319,8 +328,6 @@ class TType
// Initializes all lazily-initialized members.
void realize();
bool isRealized() const;
private:
void invalidateMangledName();
const char *buildMangledName() const;

View File

@ -15,6 +15,33 @@
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)
{
if (IsShadowSampler(type))
@ -802,8 +829,10 @@ TString Decorate(const ImmutableString &string)
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();
// The name should not have a prefix reserved for user-defined variables or functions.
ASSERT(!name.beginsWith("f_"));
@ -1025,29 +1054,26 @@ const char *QualifierString(TQualifier qualifier)
return "";
}
TString DisambiguateFunctionName(const TIntermSequence *parameters)
TString DisambiguateFunctionName(const TFunction *func)
{
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();
// 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.
disambiguatingString += "_" + 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);
disambiguatingString += "_" + TypeString(paramType);
}
DisambiguateFunctionNameForParameterType(func->getParam(i)->getType(),
&disambiguatingString);
}
return disambiguatingString;
}
TString DisambiguateFunctionName(const TIntermSequence *args)
{
TString disambiguatingString;
for (TIntermNode *arg : *args)
{
ASSERT(arg->getAsTyped());
DisambiguateFunctionNameForParameterType(arg->getAsTyped()->getType(),
&disambiguatingString);
}
return disambiguatingString;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -105,15 +105,16 @@ bool TVersionGLSL::visitInvariantDeclaration(Visit, TIntermInvariantDeclaration
return true;
}
bool TVersionGLSL::visitFunctionPrototype(Visit, TIntermFunctionPrototype *node)
void TVersionGLSL::visitFunctionPrototype(TIntermFunctionPrototype *node)
{
const TIntermSequence &params = *(node->getSequence());
for (TIntermSequence::const_iterator iter = params.begin(); iter != params.end(); ++iter)
size_t paramCount = node->getFunction()->getParamCount();
for (size_t i = 0; i < paramCount; ++i)
{
const TIntermTyped *param = (*iter)->getAsTyped();
if (param->isArray())
const TVariable *param = node->getFunction()->getParam(i);
const TType &type = param->getType();
if (type.isArray())
{
TQualifier qualifier = param->getQualifier();
TQualifier qualifier = type.getQualifier();
if ((qualifier == EvqOut) || (qualifier == EvqInOut))
{
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)

View File

@ -7,7 +7,7 @@
#ifndef 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"
@ -62,7 +62,7 @@ class TVersionGLSL : public TIntermTraverser
void visitSymbol(TIntermSymbol *node) override;
bool visitAggregate(Visit, TIntermAggregate *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;
private:

View File

@ -2,7 +2,7 @@
// Generated by gen_emulated_builtin_function_tables.py using data from
// 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
// found in the LICENSE file.
//
@ -10,6 +10,7 @@
// HLSL code for emulating GLSL builtin functions not present in HLSL.
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
namespace sh
{
@ -19,51 +20,52 @@ namespace
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;
};
constexpr FunctionPair g_hlslFunctions[] = {
{{EOpMod, ParamType::Float1, ParamType::Float1},
{BuiltInId::mod_Float1_Float1,
"float mod_emu(float x, float y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"},
{{EOpMod, ParamType::Float2, ParamType::Float2},
{BuiltInId::mod_Float2_Float2,
"float2 mod_emu(float2 x, float2 y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"},
{{EOpMod, ParamType::Float2, ParamType::Float1},
{BuiltInId::mod_Float2_Float1,
"float2 mod_emu(float2 x, float y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"},
{{EOpMod, ParamType::Float3, ParamType::Float3},
{BuiltInId::mod_Float3_Float3,
"float3 mod_emu(float3 x, float3 y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"},
{{EOpMod, ParamType::Float3, ParamType::Float1},
{BuiltInId::mod_Float3_Float1,
"float3 mod_emu(float3 x, float y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"},
{{EOpMod, ParamType::Float4, ParamType::Float4},
{BuiltInId::mod_Float4_Float4,
"float4 mod_emu(float4 x, float4 y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"},
{{EOpMod, ParamType::Float4, ParamType::Float1},
{BuiltInId::mod_Float4_Float1,
"float4 mod_emu(float4 x, float y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"},
{{EOpFrexp, ParamType::Float1, ParamType::Int1},
{BuiltInId::frexp_Float1_Int1,
"float frexp_emu(float x, out int exp)\n"
"{\n"
" float fexp;\n"
@ -71,7 +73,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" exp = int(fexp);\n"
" return mantissa;\n"
"}\n"},
{{EOpFrexp, ParamType::Float2, ParamType::Int2},
{BuiltInId::frexp_Float2_Int2,
"float2 frexp_emu(float2 x, out int2 exp)\n"
"{\n"
" float2 fexp;\n"
@ -79,7 +81,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" exp = int2(fexp);\n"
" return mantissa;\n"
"}\n"},
{{EOpFrexp, ParamType::Float3, ParamType::Int3},
{BuiltInId::frexp_Float3_Int3,
"float3 frexp_emu(float3 x, out int3 exp)\n"
"{\n"
" float3 fexp;\n"
@ -87,7 +89,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" exp = int3(fexp);\n"
" return mantissa;\n"
"}\n"},
{{EOpFrexp, ParamType::Float4, ParamType::Int4},
{BuiltInId::frexp_Float4_Int4,
"float4 frexp_emu(float4 x, out int4 exp)\n"
"{\n"
" float4 fexp;\n"
@ -95,27 +97,27 @@ constexpr FunctionPair g_hlslFunctions[] = {
" exp = int4(fexp);\n"
" return mantissa;\n"
"}\n"},
{{EOpLdexp, ParamType::Float1, ParamType::Int1},
{BuiltInId::ldexp_Float1_Int1,
"float ldexp_emu(float x, int exp)\n"
"{\n"
" return ldexp(x, float(exp));\n"
"}\n"},
{{EOpLdexp, ParamType::Float2, ParamType::Int2},
{BuiltInId::ldexp_Float2_Int2,
"float2 ldexp_emu(float2 x, int2 exp)\n"
"{\n"
" return ldexp(x, float2(exp));\n"
"}\n"},
{{EOpLdexp, ParamType::Float3, ParamType::Int3},
{BuiltInId::ldexp_Float3_Int3,
"float3 ldexp_emu(float3 x, int3 exp)\n"
"{\n"
" return ldexp(x, float3(exp));\n"
"}\n"},
{{EOpLdexp, ParamType::Float4, ParamType::Int4},
{BuiltInId::ldexp_Float4_Int4,
"float4 ldexp_emu(float4 x, int4 exp)\n"
"{\n"
" return ldexp(x, float4(exp));\n"
"}\n"},
{{EOpFaceforward, ParamType::Float1, ParamType::Float1, ParamType::Float1},
{BuiltInId::faceforward_Float1_Float1_Float1,
"float faceforward_emu(float N, float I, float Nref)\n"
"{\n"
" if(dot(Nref, I) >= 0)\n"
@ -127,7 +129,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return 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"
"{\n"
" if(dot(Nref, I) >= 0)\n"
@ -139,7 +141,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return 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"
"{\n"
" if(dot(Nref, I) >= 0)\n"
@ -151,7 +153,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return 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"
"{\n"
" if(dot(Nref, I) >= 0)\n"
@ -163,20 +165,20 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return N;\n"
" }\n"
"}\n"},
{{EOpAtan, ParamType::Float1, ParamType::Float1},
{BuiltInId::atan_Float1_Float1,
"float atan_emu(float y, float x)\n"
"{\n"
" if(x == 0 && y == 0) x = 1;\n"
" return atan2(y, x);\n"
"}\n"},
{{EOpAtan, ParamType::Float2, ParamType::Float2},
{BuiltInId::atan_Float2_Float2,
"float2 atan_emu(float2 y, float2 x)\n"
"{\n"
" if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
" if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
" return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n"
"}\n"},
{{EOpAtan, ParamType::Float3, ParamType::Float3},
{BuiltInId::atan_Float3_Float3,
"float3 atan_emu(float3 y, float3 x)\n"
"{\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"
" return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n"
"}\n"},
{{EOpAtan, ParamType::Float4, ParamType::Float4},
{BuiltInId::atan_Float4_Float4,
"float4 atan_emu(float4 y, float4 x)\n"
"{\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"
" x[2]), atan2(y[3], x[3]));\n"
"}\n"},
{{EOpAsinh, ParamType::Float1},
{BuiltInId::asinh_Float1,
"float asinh_emu(in float x)\n"
"{\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n"},
{{EOpAsinh, ParamType::Float2},
{BuiltInId::asinh_Float2,
"float2 asinh_emu(in float2 x)\n"
"{\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n"},
{{EOpAsinh, ParamType::Float3},
{BuiltInId::asinh_Float3,
"float3 asinh_emu(in float3 x)\n"
"{\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n"},
{{EOpAsinh, ParamType::Float4},
{BuiltInId::asinh_Float4,
"float4 asinh_emu(in float4 x)\n"
"{\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n"},
{{EOpAcosh, ParamType::Float1},
{BuiltInId::acosh_Float1,
"float acosh_emu(in float x)\n"
"{\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n"},
{{EOpAcosh, ParamType::Float2},
{BuiltInId::acosh_Float2,
"float2 acosh_emu(in float2 x)\n"
"{\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n"},
{{EOpAcosh, ParamType::Float3},
{BuiltInId::acosh_Float3,
"float3 acosh_emu(in float3 x)\n"
"{\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n"},
{{EOpAcosh, ParamType::Float4},
{BuiltInId::acosh_Float4,
"float4 acosh_emu(in float4 x)\n"
"{\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n"},
{{EOpAtanh, ParamType::Float1},
{BuiltInId::atanh_Float1,
"float atanh_emu(in float x)\n"
"{\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n"},
{{EOpAtanh, ParamType::Float2},
{BuiltInId::atanh_Float2,
"float2 atanh_emu(in float2 x)\n"
"{\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n"},
{{EOpAtanh, ParamType::Float3},
{BuiltInId::atanh_Float3,
"float3 atanh_emu(in float3 x)\n"
"{\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n"},
{{EOpAtanh, ParamType::Float4},
{BuiltInId::atanh_Float4,
"float4 atanh_emu(in float4 x)\n"
"{\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n"},
{{EOpRoundEven, ParamType::Float1},
{BuiltInId::roundEven_Float1,
"float roundEven_emu(in float x)\n"
"{\n"
" return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);\n"
"}\n"},
{{EOpRoundEven, ParamType::Float2},
{BuiltInId::roundEven_Float2,
"float2 roundEven_emu(in float2 x)\n"
"{\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"
" return v;\n"
"}\n"},
{{EOpRoundEven, ParamType::Float3},
{BuiltInId::roundEven_Float3,
"float3 roundEven_emu(in float3 x)\n"
"{\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"
" return v;\n"
"}\n"},
{{EOpRoundEven, ParamType::Float4},
{BuiltInId::roundEven_Float4,
"float4 roundEven_emu(in float4 x)\n"
"{\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"
" return v;\n"
"}\n"},
{{EOpPackSnorm2x16, ParamType::Float2},
{BuiltInId::packSnorm2x16_Float2,
"int webgl_toSnorm16(in float x) {\n"
" return int(round(clamp(x, -1.0, 1.0) * 32767.0));\n"
"}\n"
@ -296,7 +298,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" int y = webgl_toSnorm16(v.y);\n"
" return (asuint(y) << 16) | (asuint(x) & 0xffffu);\n"
"}\n"},
{{EOpPackUnorm2x16, ParamType::Float2},
{BuiltInId::packUnorm2x16_Float2,
"uint webgl_toUnorm16(in float x) {\n"
" return uint(round(clamp(x, 0.0, 1.0) * 65535.0));\n"
"}\n"
@ -306,14 +308,14 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint y = webgl_toUnorm16(v.y);\n"
" return (y << 16) | x;\n"
"}\n"},
{{EOpPackHalf2x16, ParamType::Float2},
{BuiltInId::packHalf2x16_Float2,
"uint packHalf2x16_emu(in float2 v)\n"
"{\n"
" uint x = f32tof16(v.x);\n"
" uint y = f32tof16(v.y);\n"
" return (y << 16) | x;\n"
"}\n"},
{{EOpUnpackSnorm2x16, ParamType::Uint1},
{BuiltInId::unpackSnorm2x16_UInt1,
"float webgl_fromSnorm16(in uint x) {\n"
" int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);\n"
" return clamp(float(xi) / 32767.0, -1.0, 1.0);\n"
@ -324,7 +326,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint x = u;\n"
" return float2(webgl_fromSnorm16(x), webgl_fromSnorm16(y));\n"
"}\n"},
{{EOpUnpackUnorm2x16, ParamType::Uint1},
{BuiltInId::unpackUnorm2x16_UInt1,
"float webgl_fromUnorm16(in uint x) {\n"
" return float(x) / 65535.0;\n"
"}\n"
@ -334,14 +336,14 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint x = u & 0xffffu;\n"
" return float2(webgl_fromUnorm16(x), webgl_fromUnorm16(y));\n"
"}\n"},
{{EOpUnpackHalf2x16, ParamType::Uint1},
{BuiltInId::unpackHalf2x16_UInt1,
"float2 unpackHalf2x16_emu(in uint u)\n"
"{\n"
" uint y = (u >> 16);\n"
" uint x = u & 0xffffu;\n"
" return float2(f16tof32(x), f16tof32(y));\n"
"}\n"},
{{EOpPackSnorm4x8, ParamType::Float4},
{BuiltInId::packSnorm4x8_Float4,
"int webgl_toSnorm8(in float x) {\n"
" return int(round(clamp(x, -1.0, 1.0) * 127.0));\n"
"}\n"
@ -354,7 +356,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return ((asuint(w) & 0xffu) << 24) | ((asuint(z) & 0xffu) << 16) \n"
" | ((asuint(y) & 0xffu) << 8) | (asuint(x) & 0xffu);\n"
"}\n"},
{{EOpPackUnorm4x8, ParamType::Float4},
{BuiltInId::packUnorm4x8_Float4,
"uint webgl_toUnorm8(in float x) {\n"
" return uint(round(clamp(x, 0.0, 1.0) * 255.0));\n"
"}\n"
@ -366,7 +368,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint w = webgl_toUnorm8(v.w);\n"
" return (w << 24) | (z << 16) | (y << 8) | x;\n"
"}\n"},
{{EOpUnpackSnorm4x8, ParamType::Uint1},
{BuiltInId::unpackSnorm4x8_UInt1,
"float webgl_fromSnorm8(in uint x) {\n"
" int xi = asint(x & 0x7fu) - asint(x & 0x80u);\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"
" webgl_fromSnorm8(z), webgl_fromSnorm8(w));\n"
"}\n"},
{{EOpUnpackUnorm4x8, ParamType::Uint1},
{BuiltInId::unpackUnorm4x8_UInt1,
"float webgl_fromUnorm8(in uint x) {\n"
" return float(x) / 255.0;\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 of r, we simply can build a column matrix out of the original
// 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"
"{\n"
" return mul(float2x1(r), float1x2(c));\n"
"}\n"},
{{EOpOuterProduct, ParamType::Float3, ParamType::Float3},
{BuiltInId::outerProduct_Float3_Float3,
"float3x3 outerProduct_emu(in float3 c, in float3 r)\n"
"{\n"
" return mul(float3x1(r), float1x3(c));\n"
"}\n"},
{{EOpOuterProduct, ParamType::Float4, ParamType::Float4},
{BuiltInId::outerProduct_Float4_Float4,
"float4x4 outerProduct_emu(in float4 c, in float4 r)\n"
"{\n"
" return mul(float4x1(r), float1x4(c));\n"
"}\n"},
{{EOpOuterProduct, ParamType::Float3, ParamType::Float2},
{BuiltInId::outerProduct_Float3_Float2,
"float2x3 outerProduct_emu(in float3 c, in float2 r)\n"
"{\n"
" return mul(float2x1(r), float1x3(c));\n"
"}\n"},
{{EOpOuterProduct, ParamType::Float2, ParamType::Float3},
{BuiltInId::outerProduct_Float2_Float3,
"float3x2 outerProduct_emu(in float2 c, in float3 r)\n"
"{\n"
" return mul(float3x1(r), float1x2(c));\n"
"}\n"},
{{EOpOuterProduct, ParamType::Float4, ParamType::Float2},
{BuiltInId::outerProduct_Float4_Float2,
"float2x4 outerProduct_emu(in float4 c, in float2 r)\n"
"{\n"
" return mul(float2x1(r), float1x4(c));\n"
"}\n"},
{{EOpOuterProduct, ParamType::Float2, ParamType::Float4},
{BuiltInId::outerProduct_Float2_Float4,
"float4x2 outerProduct_emu(in float2 c, in float4 r)\n"
"{\n"
" return mul(float4x1(r), float1x2(c));\n"
"}\n"},
{{EOpOuterProduct, ParamType::Float4, ParamType::Float3},
{BuiltInId::outerProduct_Float4_Float3,
"float3x4 outerProduct_emu(in float4 c, in float3 r)\n"
"{\n"
" return mul(float3x1(r), float1x4(c));\n"
"}\n"},
{{EOpOuterProduct, ParamType::Float3, ParamType::Float4},
{BuiltInId::outerProduct_Float3_Float4,
"float4x3 outerProduct_emu(in float3 c, in float4 r)\n"
"{\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'.
// We don't need to care about divide-by-zero since results are undefined
// for singular or poorly-conditioned matrices.
{{EOpInverse, ParamType::Mat2},
{BuiltInId::inverse_Float2x2,
"float2x2 inverse_emu(in float2x2 m)\n"
"{\n"
" float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };\n"
" return cof / determinant(transpose(m));\n"
"}\n"},
// cofAB is the cofactor for column A and row B.
{{EOpInverse, ParamType::Mat3},
{BuiltInId::inverse_Float3x3,
"float3x3 inverse_emu(in float3x3 m)\n"
"{\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"
" return cof / determinant(transpose(m));\n"
"}\n"},
{{EOpInverse, ParamType::Mat4},
{BuiltInId::inverse_Float4x4,
"float4x4 inverse_emu(in float4x4 m)\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"
@ -556,27 +558,27 @@ constexpr FunctionPair g_hlslFunctions[] = {
// 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.
{{EOpMix, ParamType::Float1, ParamType::Float1, ParamType::Bool1},
{BuiltInId::mix_Float1_Float1_Bool1,
"float mix_emu(float x, float y, bool a)\n"
"{\n"
" return a ? y : x;\n"
"}\n"},
{{EOpMix, ParamType::Float2, ParamType::Float2, ParamType::Bool2},
{BuiltInId::mix_Float2_Float2_Bool2,
"float2 mix_emu(float2 x, float2 y, bool2 a)\n"
"{\n"
" return a ? y : x;\n"
"}\n"},
{{EOpMix, ParamType::Float3, ParamType::Float3, ParamType::Bool3},
{BuiltInId::mix_Float3_Float3_Bool3,
"float3 mix_emu(float3 x, float3 y, bool3 a)\n"
"{\n"
" return a ? y : x;\n"
"}\n"},
{{EOpMix, ParamType::Float4, ParamType::Float4, ParamType::Bool4},
{BuiltInId::mix_Float4_Float4_Bool4,
"float4 mix_emu(float4 x, float4 y, bool4 a)\n"
"{\n"
" return a ? y : x;\n"
"}\n"},
{{EOpBitfieldExtract, ParamType::Uint1, ParamType::Int1, ParamType::Int1},
{BuiltInId::bitfieldExtract_UInt1_Int1_Int1,
"uint bitfieldExtract_emu(uint value, int offset, int bits)\n"
"{\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"
" return (value & mask) >> offset;\n"
"}\n"},
{{EOpBitfieldExtract, ParamType::Uint2, ParamType::Int1, ParamType::Int1},
{BuiltInId::bitfieldExtract_UInt2_Int1_Int1,
"uint2 bitfieldExtract_emu(uint2 value, int offset, int bits)\n"
"{\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"
" return (value & mask) >> offset;\n"
"}\n"},
{{EOpBitfieldExtract, ParamType::Uint3, ParamType::Int1, ParamType::Int1},
{BuiltInId::bitfieldExtract_UInt3_Int1_Int1,
"uint3 bitfieldExtract_emu(uint3 value, int offset, int bits)\n"
"{\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"
" return (value & mask) >> offset;\n"
"}\n"},
{{EOpBitfieldExtract, ParamType::Uint4, ParamType::Int1, ParamType::Int1},
{BuiltInId::bitfieldExtract_UInt4_Int1_Int1,
"uint4 bitfieldExtract_emu(uint4 value, int offset, int bits)\n"
"{\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"
" return (value & mask) >> offset;\n"
"}\n"},
{{EOpBitfieldExtract, ParamType::Int1, ParamType::Int1, ParamType::Int1},
{BuiltInId::bitfieldExtract_Int1_Int1_Int1,
"int bitfieldExtract_emu(int value, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -637,7 +639,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" }\n"
" return asint(resultUnsigned);\n"
"}\n"},
{{EOpBitfieldExtract, ParamType::Int2, ParamType::Int1, ParamType::Int1},
{BuiltInId::bitfieldExtract_Int2_Int1_Int1,
"int2 bitfieldExtract_emu(int2 value, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -654,7 +656,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" }\n"
" return asint(resultUnsigned);\n"
"}\n"},
{{EOpBitfieldExtract, ParamType::Int3, ParamType::Int1, ParamType::Int1},
{BuiltInId::bitfieldExtract_Int3_Int1_Int1,
"int3 bitfieldExtract_emu(int3 value, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -671,7 +673,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" }\n"
" return asint(resultUnsigned);\n"
"}\n"},
{{EOpBitfieldExtract, ParamType::Int4, ParamType::Int1, ParamType::Int1},
{BuiltInId::bitfieldExtract_Int4_Int1_Int1,
"int4 bitfieldExtract_emu(int4 value, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -688,7 +690,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" }\n"
" return asint(resultUnsigned);\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"
"{\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"
" return (base & baseMask) | ((insert << offset) & insertMask);\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"
"{\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"
" return (base & baseMask) | ((insert << offset) & insertMask);\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"
"{\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"
" return (base & baseMask) | ((insert << offset) & insertMask);\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"
"{\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"
" return (base & baseMask) | ((insert << offset) & insertMask);\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"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -750,7 +752,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" insertMask);\n"
" return asint(resultUnsigned);\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"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -764,7 +766,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" insertMask);\n"
" return asint(resultUnsigned);\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"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -778,7 +780,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" insertMask);\n"
" return asint(resultUnsigned);\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"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
@ -792,71 +794,71 @@ constexpr FunctionPair g_hlslFunctions[] = {
" insertMask);\n"
" return asint(resultUnsigned);\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"
"{\n"
" carry = uint(x > (0xffffffffu - y));\n"
" return x + y;\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"
"{\n"
" carry = uint2(x > (0xffffffffu - y));\n"
" return x + y;\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"
"{\n"
" carry = uint3(x > (0xffffffffu - y));\n"
" return x + y;\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"
"{\n"
" carry = uint4(x > (0xffffffffu - y));\n"
" return x + y;\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"
"{\n"
" borrow = uint(x < y);\n"
" return x - y;\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"
"{\n"
" borrow = uint2(x < y);\n"
" return x - y;\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"
"{\n"
" borrow = uint3(x < y);\n"
" return x - y;\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"
"{\n"
" borrow = uint4(x < y);\n"
" return x - y;\n"
"}\n"},
// We emulate tanh just to avoid overflow on large arguments.
{{EOpTanh, ParamType::Float1},
{BuiltInId::tanh_Float1,
"float tanh_emu(float x)\n"
"{\n"
" return (abs(x) > 15.0) ? sign(x) : tanh(x);\n"
"}\n"},
{{EOpTanh, ParamType::Float2},
{BuiltInId::tanh_Float2,
"float2 tanh_emu(float2 x)\n"
"{\n"
" return (abs(x) > 15.0) ? sign(x) : tanh(x);\n"
"}\n"},
{{EOpTanh, ParamType::Float3},
{BuiltInId::tanh_Float3,
"float3 tanh_emu(float3 x)\n"
"{\n"
" return (abs(x) > 15.0) ? sign(x) : tanh(x);\n"
"}\n"},
{{EOpTanh, ParamType::Float4},
{BuiltInId::tanh_Float4,
"float4 tanh_emu(float4 x)\n"
"{\n"
" return (abs(x) > 15.0) ? sign(x) : tanh(x);\n"
@ -864,12 +866,12 @@ constexpr FunctionPair g_hlslFunctions[] = {
};
} // anonymous namespace
const char *FindHLSLFunction(const FunctionId &functionID)
const char *FindHLSLFunction(int uniqueId)
{
for (size_t index = 0; index < ArraySize(g_hlslFunctions); ++index)
{
const auto &function = g_hlslFunctions[index];
if (function.id == functionID)
if (function.id == uniqueId)
{
return function.body;
}

View File

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

View File

@ -3268,7 +3268,7 @@ yyreduce:
(yyval.interm.function) = (yyvsp[-1].interm.function);
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
{
(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)->appendStatement((yyvsp[0].interm.intermNode));
context->appendStatement((yyval.interm.intermBlock), (yyvsp[0].interm.intermNode));
}
break;
@ -4639,7 +4639,7 @@ yyreduce:
{
(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;

View File

@ -4,10 +4,10 @@
// 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/IntermTraverse.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh
{

View File

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

View File

@ -7,10 +7,10 @@
// return.
//
#include "compiler/translator/AddDefaultReturnStatements.h"
#include "compiler/translator/tree_ops/AddDefaultReturnStatements.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"
namespace sh

View File

@ -7,8 +7,8 @@
// return.
//
#ifndef COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_
#define COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_
#ifndef COMPILER_TRANSLATOR_TREEOPS_ADDDEFAULTRETURNSTATEMENTS_H_
#define COMPILER_TRANSLATOR_TREEOPS_ADDDEFAULTRETURNSTATEMENTS_H_
class TIntermBlock;
@ -19,4 +19,4 @@ void AddDefaultReturnStatements(TIntermBlock *root);
} // 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
// parameters in function definitions, prototypes, and call sites.
#include "compiler/translator/ArrayReturnValueToOutParameter.h"
#include "compiler/translator/tree_ops/ArrayReturnValueToOutParameter.h"
#include <map>
#include "compiler/translator/IntermNode_util.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/StaticType.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh
{
@ -23,15 +23,6 @@ namespace
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
{
public:
@ -40,7 +31,7 @@ class ArrayReturnValueToOutParameterTraverser : private TIntermTraverser
private:
ArrayReturnValueToOutParameterTraverser(TSymbolTable *symbolTable);
bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
void visitFunctionPrototype(TIntermFunctionPrototype *node) override;
bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
bool visitBranch(Visit visit, TIntermBranch *node) override;
@ -110,10 +101,9 @@ bool ArrayReturnValueToOutParameterTraverser::visitFunctionDefinition(
return true;
}
bool ArrayReturnValueToOutParameterTraverser::visitFunctionPrototype(Visit visit,
TIntermFunctionPrototype *node)
void ArrayReturnValueToOutParameterTraverser::visitFunctionPrototype(TIntermFunctionPrototype *node)
{
if (visit == PreVisit && node->isArray())
if (node->isArray())
{
// Replace the whole prototype node with another node that has the out parameter
// 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(TConstParameter(
kReturnValueVariableName, static_cast<const TType *>(returnValueVariableType)));
func->addParameter(changedFunction.returnValueVariable);
changedFunction.func = func;
mChangedFunctions[functionId.get()] = changedFunction;
}
TIntermFunctionPrototype *replacement =
new TIntermFunctionPrototype(mChangedFunctions[functionId.get()].func);
CopyAggregateChildren(node, replacement);
replacement->getSequence()->push_back(
new TIntermSymbol(mChangedFunctions[functionId.get()].returnValueVariable));
replacement->setLine(node->getLine());
queueReplacement(replacement, OriginalNode::IS_DROPPED);
}
return false;
}
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
// parameters in function definitions, prototypes and call sites.
#ifndef COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
#define COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
#ifndef COMPILER_TRANSLATOR_TREEOPS_ARRAYRETURNVALUETOOUTPARAMETER_H_
#define COMPILER_TRANSLATOR_TREEOPS_ARRAYRETURNVALUETOOUTPARAMETER_H_
namespace sh
{
@ -19,4 +19,4 @@ void ArrayReturnValueToOutParameter(TIntermNode *root, TSymbolTable *symbolTable
} // namespace sh
#endif // COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
#endif // COMPILER_TRANSLATOR_TREEOPS_ARRAYRETURNVALUETOOUTPARAMETER_H_

View File

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

View File

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

View File

@ -8,13 +8,14 @@
// 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/IntermNode_util.h"
#include "compiler/translator/RunAtTheEndOfShader.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
{
@ -27,8 +28,7 @@ void ClampFragDepth(TIntermBlock *root, TSymbolTable *symbolTable)
return;
}
TIntermSymbol *fragDepthNode =
ReferenceBuiltInVariable(ImmutableString("gl_FragDepth"), *symbolTable, 300);
TIntermSymbol *fragDepthNode = new TIntermSymbol(BuiltInVariable::gl_FragDepth());
TIntermTyped *minFragDepthNode = CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));

View File

@ -8,8 +8,8 @@
// statically accesses gl_FragDepth.
//
#ifndef COMPILER_TRANSLATOR_CLAMPFRAGDEPTH_H_
#define COMPILER_TRANSLATOR_CLAMPFRAGDEPTH_H_
#ifndef COMPILER_TRANSLATOR_TREEOPS_CLAMPFRAGDEPTH_H_
#define COMPILER_TRANSLATOR_TREEOPS_CLAMPFRAGDEPTH_H_
namespace sh
{
@ -21,4 +21,4 @@ void ClampFragDepth(TIntermBlock *root, TSymbolTable *symbolTable);
} // 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.
//
#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/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
{
@ -24,8 +25,7 @@ void ClampPointSize(TIntermBlock *root, float maxPointSize, TSymbolTable *symbol
return;
}
TIntermSymbol *pointSizeNode =
ReferenceBuiltInVariable(ImmutableString("gl_PointSize"), *symbolTable, 100);
TIntermSymbol *pointSizeNode = new TIntermSymbol(BuiltInVariable::gl_PointSize());
TConstantUnion *maxPointSizeConstant = new TConstantUnion();
maxPointSizeConstant->setFConst(maxPointSize);

View File

@ -6,8 +6,8 @@
// ClampPointSize.h: Limit the value that is written to gl_PointSize.
//
#ifndef COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_
#define COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_
#ifndef COMPILER_TRANSLATOR_TREEOPS_CLAMPPOINTSIZE_H_
#define COMPILER_TRANSLATOR_TREEOPS_CLAMPPOINTSIZE_H_
namespace sh
{
@ -19,4 +19,4 @@ void ClampPointSize(TIntermBlock *root, float maxPointSize, TSymbolTable *symbol
} // 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.
//
#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/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"
namespace sh
@ -24,20 +25,11 @@ namespace sh
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 kInstanceIDVariableName("InstanceID");
constexpr const ImmutableString kMultiviewBaseViewLayerIndexVariableName(
"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.
void InitializeViewIDAndInstanceID(const TVariable *viewID,
const TVariable *instanceID,
@ -53,7 +45,7 @@ void InitializeViewIDAndInstanceID(const TVariable *viewID,
// Create a uint(gl_InstanceID) node.
TIntermSequence *glInstanceIDSymbolCastArguments = new TIntermSequence();
glInstanceIDSymbolCastArguments->push_back(CreateGLInstanceIDSymbol(symbolTable));
glInstanceIDSymbolCastArguments->push_back(new TIntermSymbol(BuiltInVariable::gl_InstanceID()));
TIntermAggregate *glInstanceIDAsUint = TIntermAggregate::CreateConstructor(
TType(EbtUInt, EbpHigh, EvqTemporary), glInstanceIDSymbolCastArguments);
@ -105,8 +97,7 @@ void SelectViewIndexInVertexShader(const TVariable *viewID,
TType(EbtInt, EbpHigh, EvqTemporary), viewIDSymbolCastArguments);
// Create a gl_ViewportIndex node.
TIntermSymbol *viewportIndexSymbol =
ReferenceBuiltInVariable(kGlViewportIndexString, symbolTable, 0);
TIntermSymbol *viewportIndexSymbol = new TIntermSymbol(BuiltInVariable::gl_ViewportIndex());
// Create a { gl_ViewportIndex = int(ViewID_OVR) } node.
TIntermBlock *viewportIndexInitializerInBlock = new TIntermBlock();
@ -114,7 +105,7 @@ void SelectViewIndexInVertexShader(const TVariable *viewID,
new TIntermBinary(EOpAssign, viewportIndexSymbol, viewIDAsInt));
// 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
TIntermBinary *sumOfViewIDAndBaseViewIndex = new TIntermBinary(
@ -149,29 +140,23 @@ void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root,
{
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 =
new TVariable(symbolTable, kViewIDVariableName,
new TType(EbtUInt, EbpHigh, viewIDQualifier), SymbolType::AngleInternal);
DeclareGlobalVariable(root, viewID);
ReplaceVariable(
root,
static_cast<const TVariable *>(symbolTable->findBuiltIn(kGlViewIdOVRString, 300, true)),
viewID);
ReplaceVariable(root, BuiltInVariable::gl_ViewID_OVR(), viewID);
if (shaderType == GL_VERTEX_SHADER)
{
// Replacing gl_InstanceID with InstanceID should happen before adding the initializers of
// 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 =
new TVariable(symbolTable, kInstanceIDVariableName, instanceIDVariableType,
SymbolType::AngleInternal);
DeclareGlobalVariable(root, instanceID);
ReplaceVariable(root,
static_cast<const TVariable *>(
symbolTable->findBuiltIn(kGlInstanceIdString, 300, true)),
instanceID);
ReplaceVariable(root, BuiltInVariable::gl_InstanceID(), instanceID);
TIntermSequence *initializers = new TIntermSequence();
InitializeViewIDAndInstanceID(viewID, instanceID, numberOfViews, *symbolTable,
@ -207,4 +192,4 @@ void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root,
}
}
} // namespace sh
} // namespace sh

View File

@ -24,8 +24,8 @@
// uniform.
//
#ifndef COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_
#define COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_
#ifndef COMPILER_TRANSLATOR_TREEOPS_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_
#define COMPILER_TRANSLATOR_TREEOPS_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_
#include "GLSLANG/ShaderLang.h"
#include "angle_gl.h"
@ -45,4 +45,4 @@ void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root,
} // 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.
//
#include "compiler/translator/DeferGlobalInitializers.h"
#include "compiler/translator/tree_ops/DeferGlobalInitializers.h"
#include <vector>
#include "compiler/translator/FindMain.h"
#include "compiler/translator/InitializeVariables.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/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
{

View File

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

View File

@ -11,12 +11,12 @@
// 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/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
#include "compiler/translator/tree_util/RunAtTheEndOfShader.h"
namespace sh
{

View File

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

View File

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

View File

@ -4,14 +4,14 @@
// found in the LICENSE file.
//
#ifndef COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
#define COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
#ifndef COMPILER_TRANSLATOR_TREEOPS_EMULATE_PRECISION_H_
#define COMPILER_TRANSLATOR_TREEOPS_EMULATE_PRECISION_H_
#include "GLSLANG/ShaderLang.h"
#include "common/angleutils.h"
#include "compiler/translator/Compiler.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
// 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 visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override;
bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
void writeEmulationHelpers(TInfoSinkBase &sink,
const int shaderVersion,
@ -62,7 +61,7 @@ class EmulatePrecision : public TLValueTrackingTraverser
const TFunction *getInternalFunction(const ImmutableString &functionName,
const TType &returnType,
TIntermSequence *arguments,
const TVector<TConstParameter> &parameters,
const TVector<const TVariable *> &parameters,
bool knownToNotHaveSideEffects);
TIntermAggregate *createRoundingFunctionCallNode(TIntermTyped *roundedChild);
TIntermAggregate *createCompoundAssignmentFunctionCallNode(TIntermTyped *left,
@ -83,4 +82,4 @@ class EmulatePrecision : public TLValueTrackingTraverser
} // 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.
// See header for more info.
#include "compiler/translator/ExpandIntegerPowExpressions.h"
#include "compiler/translator/tree_ops/ExpandIntegerPowExpressions.h"
#include <cmath>
#include <cstdlib>
#include "compiler/translator/IntermNode_util.h"
#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh
{

View File

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