зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1459785 - Update ANGLE to chromium/3396.
MozReview-Commit-ID: EA39lUfXuPI
This commit is contained in:
Родитель
416785bdf0
Коммит
a4c2e92cc1
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#define ANGLE_COMMIT_HASH "fcbca0e873c3"
|
||||
#define ANGLE_COMMIT_HASH "595ccab4acc3"
|
||||
#define ANGLE_COMMIT_HASH_SIZE 12
|
||||
#define ANGLE_COMMIT_DATE "2018-04-20 16:07:35 -0700"
|
||||
#define ANGLE_COMMIT_DATE "2018-06-01 17:26:22 -0700"
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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_
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -937,6 +937,7 @@ typedef pp::SourceLocation YYLTYPE;
|
|||
yyextra->lineStart = true; \
|
||||
} while(0);
|
||||
|
||||
#define YY_NO_INPUT
|
||||
#define YY_USER_ACTION \
|
||||
do \
|
||||
{ \
|
||||
|
|
|
@ -64,6 +64,7 @@ typedef pp::SourceLocation YYLTYPE;
|
|||
yyextra->lineStart = true; \
|
||||
} while(0);
|
||||
|
||||
#define YY_NO_INPUT
|
||||
#define YY_USER_ACTION \
|
||||
do \
|
||||
{ \
|
||||
|
|
|
@ -48,23 +48,17 @@ 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.
|
||||
|
||||
// Android NDK forbids access to locales by always throwing instead of only accepting the C locale.
|
||||
#if !defined(ANGLE_PLATFORM_ANDROID)
|
||||
// Force "C" locale so that decimal character is always '.', and not dependent on the current
|
||||
// locale.
|
||||
stream.imbue(std::locale::classic());
|
||||
#endif
|
||||
|
||||
stream >> (*value);
|
||||
return !stream.fail() && std::isfinite(*value);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace pp.
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 ¶m)
|
||||
{
|
||||
return setFunctionCalled(FunctionId(op, ¶m));
|
||||
}
|
||||
|
||||
bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
|
||||
const TType ¶m1,
|
||||
const TType ¶m2)
|
||||
{
|
||||
return setFunctionCalled(FunctionId(op, ¶m1, ¶m2));
|
||||
}
|
||||
|
||||
bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
|
||||
const TType ¶m1,
|
||||
const TType ¶m2,
|
||||
const TType ¶m3)
|
||||
{
|
||||
return setFunctionCalled(FunctionId(op, ¶m1, ¶m2, ¶m3));
|
||||
}
|
||||
|
||||
bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
|
||||
const TType ¶m1,
|
||||
const TType ¶m2,
|
||||
const TType ¶m3,
|
||||
const TType ¶m4)
|
||||
{
|
||||
return setFunctionCalled(FunctionId(op, ¶m1, ¶m2, ¶m3, ¶m4));
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -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 ¶m);
|
||||
bool setFunctionCalled(TOperator op, const TType ¶m1, const TType ¶m2);
|
||||
bool setFunctionCalled(TOperator op,
|
||||
const TType ¶m1,
|
||||
const TType ¶m2,
|
||||
const TType ¶m3);
|
||||
bool setFunctionCalled(TOperator op,
|
||||
const TType ¶m1,
|
||||
const TType ¶m2,
|
||||
const TType ¶m3,
|
||||
const TType ¶m4);
|
||||
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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ void CollectVariables(TIntermBlock *root,
|
|||
std::vector<InterfaceBlock> *inBlocks,
|
||||
ShHashFunction64 hashFunction,
|
||||
TSymbolTable *symbolTable,
|
||||
int shaderVersion,
|
||||
GLenum shaderType,
|
||||
const TExtensionBehavior &extensionBehavior);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "compiler/translator/IntermTraverse.h"
|
||||
#include "compiler/translator/tree_util/IntermTraverse.h"
|
||||
|
||||
namespace sh
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()))
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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_
|
|
@ -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 ¶m = 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 ¶m = 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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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_
|
|
@ -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
|
|
@ -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_
|
|
@ -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
|
|
@ -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_
|
|
@ -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;
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 ¶metersSource);
|
||||
|
||||
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;
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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_
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -15,6 +15,33 @@
|
|||
namespace sh
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void DisambiguateFunctionNameForParameterType(const TType ¶mType,
|
||||
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 ¶mType = 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;
|
||||
}
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -105,15 +105,16 @@ bool TVersionGLSL::visitInvariantDeclaration(Visit, TIntermInvariantDeclaration
|
|||
return true;
|
||||
}
|
||||
|
||||
bool TVersionGLSL::visitFunctionPrototype(Visit, TIntermFunctionPrototype *node)
|
||||
void TVersionGLSL::visitFunctionPrototype(TIntermFunctionPrototype *node)
|
||||
{
|
||||
const TIntermSequence ¶ms = *(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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
|
@ -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_
|
|
@ -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
|
|
@ -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_
|
|
@ -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)
|
|
@ -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_
|
|
@ -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
|
|
@ -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_
|
|
@ -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));
|
||||
|
|
@ -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_
|
|
@ -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);
|
|
@ -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_
|
|
@ -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
|
|
@ -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_
|
|
@ -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
|
||||
{
|
|
@ -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_
|
|
@ -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
|
||||
{
|
|
@ -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_
|
|
@ -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> ¶meters,
|
||||
const TVector<const TVariable *> ¶meters,
|
||||
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),
|
|
@ -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> ¶meters,
|
||||
const TVector<const TVariable *> ¶meters,
|
||||
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_
|
|
@ -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
|
||||
{
|
|
@ -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_
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче