From 408be3f96e49427435edb886d78c69b77a569ac0 Mon Sep 17 00:00:00 2001 From: aaaapai Date: Wed, 26 Aug 2026 17:42:43 +0800 Subject: [PATCH 1/6] Just some optimization... --- src/common/BinaryStream.h | 55 +- src/common/FastVector.h | 20 +- src/common/FixedVector.h | 2 +- src/common/mathutil.cpp | 22 +- src/common/mathutil.h | 3 +- src/common/matrix_utils.cpp | 291 +---- src/common/matrix_utils.h | 258 ++++- src/common/utilities.cpp | 931 +-------------- src/common/utilities.h | 1012 ++++++++++++++++- src/common/vector_utils.h | 148 +-- src/image_util/copyimage.cpp | 41 +- src/image_util/loadimage.cpp | 77 +- src/libANGLE/renderer/vulkan/BufferVk.cpp | 33 +- src/libANGLE/renderer/vulkan/CommandQueue.cpp | 12 +- src/libANGLE/renderer/vulkan/CommandQueue.h | 7 +- src/libANGLE/renderer/vulkan/SyncVk.cpp | 2 +- src/libANGLE/renderer/vulkan/SyncVk.h | 5 +- src/libANGLE/renderer/vulkan/vk_helpers.cpp | 14 + src/libANGLE/renderer/vulkan/vk_renderer.cpp | 14 +- 19 files changed, 1498 insertions(+), 1449 deletions(-) diff --git a/src/common/BinaryStream.h b/src/common/BinaryStream.h index 6948b9bb399..600189d4aac 100644 --- a/src/common/BinaryStream.h +++ b/src/common/BinaryStream.h @@ -39,7 +39,7 @@ class BinaryInputStream : angle::NonCopyable // readInt will generate an error for bool types template - IntT readInt() + ANGLE_INLINE IntT readInt() { static_assert(!std::is_same()>(), "Use readBool"); using PromotedIntT = typename PromotedIntegerType::type; @@ -50,7 +50,7 @@ class BinaryInputStream : angle::NonCopyable } template - void readInt(IntT *outValue) + ANGLE_INLINE void readInt(IntT *outValue) { *outValue = readInt(); } @@ -83,28 +83,28 @@ class BinaryInputStream : angle::NonCopyable } template - EnumT readEnum() + ANGLE_INLINE EnumT readEnum() { using UnderlyingType = typename std::underlying_type::type; return static_cast(readInt()); } template - void readEnum(EnumT *outValue) + ANGLE_INLINE void readEnum(EnumT *outValue) { *outValue = readEnum(); } - bool readBool() + ANGLE_INLINE bool readBool() { int value = 0; read(angle::byte_span_from_ref(value)); return value > 0; } - void readBool(bool *outValue) { *outValue = readBool(); } + ANGLE_INLINE void readBool(bool *outValue) { *outValue = readBool(); } - void readBytes(angle::Span outArray) { read(outArray); } + ANGLE_INLINE void readBytes(angle::Span outArray) { read(outArray); } std::string readString() { @@ -125,7 +125,6 @@ class BinaryInputStream : angle::NonCopyable angle::CheckedNumeric checkedOffset(mOffset); checkedOffset += length; - if (!checkedOffset.IsValid() || checkedOffset.ValueOrDie() > mData.size()) { mError = true; @@ -136,7 +135,7 @@ class BinaryInputStream : angle::NonCopyable mOffset = checkedOffset.ValueOrDie(); } - float readFloat() + ANGLE_INLINE float readFloat() { float f = 0.0f; read(angle::byte_span_from_ref(f)); @@ -157,17 +156,17 @@ class BinaryInputStream : angle::NonCopyable mOffset = checkedOffset.ValueOrDie(); } - bool error() const { return mError; } - bool endOfStream() const { return mOffset == mData.size(); } + ANGLE_INLINE bool error() const { return mError; } + ANGLE_INLINE bool endOfStream() const { return mOffset == mData.size(); } // data() and size() methods allow implicit conversion to span. - const uint8_t *data() const { return mData.data(); } - size_t size() const { return mData.size(); } + ANGLE_INLINE const uint8_t *data() const { return mData.data(); } + ANGLE_INLINE size_t size() const { return mData.size(); } - angle::Span remainingSpan() const { return mData.subspan(mOffset); } + ANGLE_INLINE angle::Span remainingSpan() const { return mData.subspan(mOffset); } private: - void read(angle::Span dstSpan) + ANGLE_INLINE void read(angle::Span dstSpan) { angle::CheckedNumeric checkedOffset(mOffset); checkedOffset += dstSpan.size(); @@ -194,9 +193,12 @@ class BinaryOutputStream : angle::NonCopyable BinaryOutputStream() = default; ~BinaryOutputStream() = default; + // Pre-allocate internal buffer to avoid reallocations. + void reserve(size_t capacity) { mData.reserve(capacity); } + // writeInt also handles bool types template - void writeInt(IntT param) + ANGLE_INLINE void writeInt(IntT param) { static_assert(std::is_integral::value, "Not an integral type"); static_assert(!std::is_same()>(), "Use writeBool"); @@ -208,7 +210,7 @@ class BinaryOutputStream : angle::NonCopyable // Specialized writeInt for values that can also be exactly -1. template - void writeIntOrNegOne(UintT param) + ANGLE_INLINE void writeIntOrNegOne(UintT param) { if (param == static_cast(-1)) { @@ -248,38 +250,39 @@ class BinaryOutputStream : angle::NonCopyable } template - void writeEnum(EnumT param) + ANGLE_INLINE void writeEnum(EnumT param) { using UnderlyingType = typename std::underlying_type::type; writeInt(static_cast(param)); } - void writeString(std::string_view v) + ANGLE_INLINE void writeString(std::string_view v) { writeInt(v.size()); write(angle::as_byte_span(v)); } - void writeBytes(angle::Span bytes) { write(bytes); } + ANGLE_INLINE void writeBytes(angle::Span bytes) { write(bytes); } - void writeBool(bool value) + ANGLE_INLINE void writeBool(bool value) { const int intValue = value ? 1 : 0; write(angle::byte_span_from_ref(intValue)); } - void writeFloat(float value) { write(angle::byte_span_from_ref(value)); } + ANGLE_INLINE void writeFloat(float value) { write(angle::byte_span_from_ref(value)); } // data() and size() methods allow implicit conversion to span. - const uint8_t *data() const { return mData.data(); } - size_t size() const { return mData.size(); } + ANGLE_INLINE const uint8_t *data() const { return mData.data(); } + ANGLE_INLINE size_t size() const { return mData.size(); } // No further use of this stream allowed after data is taken. std::vector takeData() { return std::move(mData); } private: - void write(angle::Span srcSpan) + ANGLE_INLINE void write(angle::Span srcSpan) { + // Insert copies the entire span in one call, efficiently using memmove. mData.insert(mData.end(), srcSpan.begin(), srcSpan.end()); } @@ -288,4 +291,4 @@ class BinaryOutputStream : angle::NonCopyable } // namespace gl -#endif // COMMON_BINARYSTREAM_H_ +#endif // COMMON_BINARYSTREAM_H_ \ No newline at end of file diff --git a/src/common/FastVector.h b/src/common/FastVector.h index 1f3587c62ee..2cf92a060be 100644 --- a/src/common/FastVector.h +++ b/src/common/FastVector.h @@ -20,6 +20,7 @@ #include #include #include +#include namespace angle { @@ -557,10 +558,10 @@ ANGLE_INLINE void FastVector::remove_and_permute(iterator pos) pop_back(); } +// Optimized capacity growth: use 1.5x factor instead of doubling to reduce memory fragmentation. template void FastVector::ensure_capacity(size_t capacity) { - // We have a minimum capacity of N. if (mReservedSize < capacity) { increase_capacity(capacity); @@ -571,17 +572,28 @@ template ANGLE_NOINLINE void FastVector::increase_capacity(size_t capacity) { ASSERT(capacity > N); + // Use 1.5x growth factor (rounded up) for better memory reuse. size_type newSize = std::max(mReservedSize, N); while (newSize < capacity) { - newSize *= 2; + newSize = newSize + newSize / 2; // 1.5x + if (newSize < capacity) + newSize = capacity; // ensure at least capacity } pointer newData = new value_type[newSize]; if (mSize > 0) { - std::move(begin(), end(), newData); + // Optimized copy for trivially copyable types using memcpy. + if constexpr (std::is_trivially_copyable_v) + { + std::memcpy(newData, mData, mSize * sizeof(value_type)); + } + else + { + std::move(begin(), end(), newData); + } } if (!uses_fixed_storage()) @@ -812,4 +824,4 @@ class FlatUnorderedSet final }; } // namespace angle -#endif // COMMON_FASTVECTOR_H_ +#endif // COMMON_FASTVECTOR_H_ \ No newline at end of file diff --git a/src/common/FixedVector.h b/src/common/FixedVector.h index ab97d2ec3bf..17a97385639 100644 --- a/src/common/FixedVector.h +++ b/src/common/FixedVector.h @@ -370,4 +370,4 @@ typename angle::FixedVector::size_type erase_if(angle::FixedVecto } } // namespace std -#endif // COMMON_FIXEDVECTOR_H_ +#endif // COMMON_FIXEDVECTOR_H_ \ No newline at end of file diff --git a/src/common/mathutil.cpp b/src/common/mathutil.cpp index 40a9aa0b59b..f3f922f8db7 100644 --- a/src/common/mathutil.cpp +++ b/src/common/mathutil.cpp @@ -51,18 +51,18 @@ unsigned int convertRGBFloatsTo999E5(float red, float green, float blue) const float blue_c = std::max(0, std::min(g_sharedexp_max, blue)); const float max_c = std::max({red_c, green_c, blue_c}); - const float exp_p = - std::max(-g_sharedexp_bias - 1, floor(log(max_c))) + 1 + g_sharedexp_bias; + // Use log2 and exp2 for faster and more accurate exponent calculation + const float exp_p = std::max(-g_sharedexp_bias - 1, + std::floor(std::log2(max_c))) + 1 + g_sharedexp_bias; const int max_s = static_cast( - floor((max_c / (pow(2.0f, exp_p - g_sharedexp_biased_mantissabits))) + 0.5f)); - const int exp_s = - static_cast((max_s < pow(2.0f, g_sharedexp_mantissabits)) ? exp_p : exp_p + 1); - const float pow2_exp = pow(2.0f, static_cast(exp_s) - g_sharedexp_biased_mantissabits); + std::floor((max_c / std::exp2(exp_p - g_sharedexp_biased_mantissabits)) + 0.5f)); + const int exp_s = static_cast((max_s < (1 << g_sharedexp_mantissabits)) ? exp_p : exp_p + 1); + const float pow2_exp = std::exp2(static_cast(exp_s) - g_sharedexp_biased_mantissabits); RGB9E5Data output; - output.R = static_cast(floor((red_c / pow2_exp) + 0.5f)); - output.G = static_cast(floor((green_c / pow2_exp) + 0.5f)); - output.B = static_cast(floor((blue_c / pow2_exp) + 0.5f)); + output.R = static_cast(std::floor((red_c / pow2_exp) + 0.5f)); + output.G = static_cast(std::floor((green_c / pow2_exp) + 0.5f)); + output.B = static_cast(std::floor((blue_c / pow2_exp) + 0.5f)); output.E = exp_s; return bitCast(output); @@ -72,8 +72,8 @@ void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float { const RGB9E5Data *inputData = reinterpret_cast(&input); - const float pow2_exp = - pow(2.0f, static_cast(inputData->E) - g_sharedexp_biased_mantissabits); + // Use ldexp for faster exponent to float conversion + const float pow2_exp = std::ldexp(1.0f, inputData->E - g_sharedexp_biased_mantissabits); *red = inputData->R * pow2_exp; *green = inputData->G * pow2_exp; diff --git a/src/common/mathutil.h b/src/common/mathutil.h index e8387843982..f1b22d4991f 100644 --- a/src/common/mathutil.h +++ b/src/common/mathutil.h @@ -924,8 +924,7 @@ inline float Ldexp(float x, int exp) { return 0.0f; } - double result = static_cast(x) * std::pow(2.0, static_cast(exp)); - return static_cast(result); + return std::ldexp(x, exp); } // First, both normalized floating-point values are converted into 16-bit integer values. diff --git a/src/common/matrix_utils.cpp b/src/common/matrix_utils.cpp index 4dacac682cc..d0d7b9198ef 100644 --- a/src/common/matrix_utils.cpp +++ b/src/common/matrix_utils.cpp @@ -5,295 +5,8 @@ // // matrix_utils.cpp: Contains implementations for Mat4 methods. +// All implementations are now inline in matrix_utils.h. #include "common/matrix_utils.h" -#include "common/unsafe_buffers.h" -namespace angle -{ - -Mat4::Mat4() : Mat4(1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f) -{} - -Mat4::Mat4(const Matrix generalMatrix) -{ - unsigned int minCols = std::min((unsigned int)4, generalMatrix.columns()); - unsigned int minRows = std::min((unsigned int)4, generalMatrix.rows()); - for (unsigned int i = 0; i < minCols; i++) - { - for (unsigned int j = 0; j < minRows; j++) - { - mElements[j * minCols + i] = generalMatrix.at(j, i); - } - } -} - -Mat4::Mat4(const std::vector &elements) -{ - std::copy(elements.begin(), std::min(elements.end(), elements.begin() + std::size(mElements)), - mElements.data()); -} - -Mat4::Mat4(const float *elements) -{ - std::copy(elements, ANGLE_UNSAFE_TODO(elements + std::size(mElements)), mElements.data()); -} - -Mat4::Mat4(float m00, - float m01, - float m02, - float m03, - float m10, - float m11, - float m12, - float m13, - float m20, - float m21, - float m22, - float m23, - float m30, - float m31, - float m32, - float m33) -{ - mElements[0] = m00; - mElements[1] = m01; - mElements[2] = m02; - mElements[3] = m03; - mElements[4] = m10; - mElements[5] = m11; - mElements[6] = m12; - mElements[7] = m13; - mElements[8] = m20; - mElements[9] = m21; - mElements[10] = m22; - mElements[11] = m23; - mElements[12] = m30; - mElements[13] = m31; - mElements[14] = m32; - mElements[15] = m33; -} - -// static -Mat4 Mat4::Rotate(float angle, const Vector3 &axis) -{ - if (axis.length() == 0.0f) - { - return Mat4(); - } - - auto axis_normalized = axis.normalized(); - float angle_radians = angle * (3.14159265358979323f / 180.0f); - float c = cos(angle_radians); - float ci = 1.f - c; - float s = sin(angle_radians); - - float x = axis_normalized.x(); - float y = axis_normalized.y(); - float z = axis_normalized.z(); - - float x2 = x * x; - float y2 = y * y; - float z2 = z * z; - - float xy = x * y; - float yz = y * z; - float zx = z * x; - - float r00 = c + ci * x2; - float r01 = ci * xy + s * z; - float r02 = ci * zx - s * y; - float r03 = 0.f; - - float r10 = ci * xy - s * z; - float r11 = c + ci * y2; - float r12 = ci * yz + s * x; - float r13 = 0.f; - - float r20 = ci * zx + s * y; - float r21 = ci * yz - s * x; - float r22 = c + ci * z2; - float r23 = 0.f; - - float r30 = 0.f; - float r31 = 0.f; - float r32 = 0.f; - float r33 = 1.f; - - return Mat4(r00, r01, r02, r03, r10, r11, r12, r13, r20, r21, r22, r23, r30, r31, r32, r33); -} - -// static -Mat4 Mat4::Translate(const Vector3 &t) -{ - float r00 = 1.f; - float r01 = 0.f; - float r02 = 0.f; - float r03 = 0.f; - - float r10 = 0.f; - float r11 = 1.f; - float r12 = 0.f; - float r13 = 0.f; - - float r20 = 0.f; - float r21 = 0.f; - float r22 = 1.f; - float r23 = 0.f; - - float r30 = t.x(); - float r31 = t.y(); - float r32 = t.z(); - float r33 = 1.f; - - return Mat4(r00, r01, r02, r03, r10, r11, r12, r13, r20, r21, r22, r23, r30, r31, r32, r33); -} - -// static -Mat4 Mat4::Scale(const Vector3 &s) -{ - float r00 = s.x(); - float r01 = 0.f; - float r02 = 0.f; - float r03 = 0.f; - - float r10 = 0.f; - float r11 = s.y(); - float r12 = 0.f; - float r13 = 0.f; - - float r20 = 0.f; - float r21 = 0.f; - float r22 = s.z(); - float r23 = 0.f; - - float r30 = 0.f; - float r31 = 0.f; - float r32 = 0.f; - float r33 = 1.f; - - return Mat4(r00, r01, r02, r03, r10, r11, r12, r13, r20, r21, r22, r23, r30, r31, r32, r33); -} - -// static -Mat4 Mat4::Frustum(float l, float r, float b, float t, float n, float f) -{ - float nn = 2.f * n; - float fpn = f + n; - float fmn = f - n; - float tpb = t + b; - float tmb = t - b; - float rpl = r + l; - float rml = r - l; - - float r00 = nn / rml; - float r01 = 0.f; - float r02 = 0.f; - float r03 = 0.f; - - float r10 = 0.f; - float r11 = nn / tmb; - float r12 = 0.f; - float r13 = 0.f; - - float r20 = rpl / rml; - float r21 = tpb / tmb; - float r22 = -fpn / fmn; - float r23 = -1.f; - - float r30 = 0.f; - float r31 = 0.f; - float r32 = -nn * f / fmn; - float r33 = 0.f; - - return Mat4(r00, r01, r02, r03, r10, r11, r12, r13, r20, r21, r22, r23, r30, r31, r32, r33); -} - -// static -Mat4 Mat4::Perspective(float fov, float aspectRatio, float n, float f) -{ - const float frustumHeight = tanf(static_cast(fov / 360.0f * 3.14159265358979323)) * n; - const float frustumWidth = frustumHeight * aspectRatio; - return Frustum(-frustumWidth, frustumWidth, -frustumHeight, frustumHeight, n, f); -} - -// static -Mat4 Mat4::Ortho(float l, float r, float b, float t, float n, float f) -{ - float fpn = f + n; - float fmn = f - n; - float tpb = t + b; - float tmb = t - b; - float rpl = r + l; - float rml = r - l; - - float r00 = 2.f / rml; - float r01 = 0.f; - float r02 = 0.f; - float r03 = 0.f; - - float r10 = 0.f; - float r11 = 2.f / tmb; - float r12 = 0.f; - float r13 = 0.f; - - float r20 = 0.f; - float r21 = 0.f; - float r22 = -2.f / fmn; - float r23 = 0.f; - - float r30 = -rpl / rml; - float r31 = -tpb / tmb; - float r32 = -fpn / fmn; - float r33 = 1.f; - - return Mat4(r00, r01, r02, r03, r10, r11, r12, r13, r20, r21, r22, r23, r30, r31, r32, r33); -} - -Mat4 Mat4::product(const Mat4 &m) -{ - const float *a = mElements.data(); - const float *b = m.mElements.data(); - - ANGLE_UNSAFE_TODO({ - return Mat4(a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3], - a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3], - a[2] * b[0] + a[6] * b[1] + a[10] * b[2] + a[14] * b[3], - a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + a[15] * b[3], - - a[0] * b[4] + a[4] * b[5] + a[8] * b[6] + a[12] * b[7], - a[1] * b[4] + a[5] * b[5] + a[9] * b[6] + a[13] * b[7], - a[2] * b[4] + a[6] * b[5] + a[10] * b[6] + a[14] * b[7], - a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + a[15] * b[7], - - a[0] * b[8] + a[4] * b[9] + a[8] * b[10] + a[12] * b[11], - a[1] * b[8] + a[5] * b[9] + a[9] * b[10] + a[13] * b[11], - a[2] * b[8] + a[6] * b[9] + a[10] * b[10] + a[14] * b[11], - a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + a[15] * b[11], - - a[0] * b[12] + a[4] * b[13] + a[8] * b[14] + a[12] * b[15], - a[1] * b[12] + a[5] * b[13] + a[9] * b[14] + a[13] * b[15], - a[2] * b[12] + a[6] * b[13] + a[10] * b[14] + a[14] * b[15], - a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15]); - }) -} - -Vector4 Mat4::product(const Vector4 &b) -{ - return Vector4( - mElements[0] * b.x() + mElements[4] * b.y() + mElements[8] * b.z() + mElements[12] * b.w(), - mElements[1] * b.x() + mElements[5] * b.y() + mElements[9] * b.z() + mElements[13] * b.w(), - mElements[2] * b.x() + mElements[6] * b.y() + mElements[10] * b.z() + mElements[14] * b.w(), - mElements[3] * b.x() + mElements[7] * b.y() + mElements[11] * b.z() + - mElements[15] * b.w()); -} - -void Mat4::dump() -{ - printf("[ %f %f %f %f ]\n", mElements[0], mElements[4], mElements[8], mElements[12]); - printf("[ %f %f %f %f ]\n", mElements[1], mElements[5], mElements[9], mElements[13]); - printf("[ %f %f %f %f ]\n", mElements[2], mElements[6], mElements[10], mElements[14]); - printf("[ %f %f %f %f ]\n", mElements[3], mElements[7], mElements[11], mElements[15]); -} - -} // namespace angle +// (Empty – all Mat4 functions are defined inline in the header.) \ No newline at end of file diff --git a/src/common/matrix_utils.h b/src/common/matrix_utils.h index e6f744c1094..50852c2b7a4 100644 --- a/src/common/matrix_utils.h +++ b/src/common/matrix_utils.h @@ -400,37 +400,211 @@ class Matrix class Mat4 { public: - Mat4(); - Mat4(const Matrix generalMatrix); - Mat4(const std::vector &elements); - Mat4(const float *elements); - Mat4(float m00, - float m01, - float m02, - float m03, - float m10, - float m11, - float m12, - float m13, - float m20, - float m21, - float m22, - float m23, - float m30, - float m31, - float m32, - float m33); - - static Mat4 Rotate(float angle, const Vector3 &axis); - static Mat4 Translate(const Vector3 &t); - static Mat4 Scale(const Vector3 &s); - static Mat4 Frustum(float l, float r, float b, float t, float n, float f); - static Mat4 Perspective(float fov, float aspectRatio, float n, float f); - static Mat4 Ortho(float l, float r, float b, float t, float n, float f); - - Mat4 product(const Mat4 &m); - Vector4 product(const Vector4 &b); - void dump(); + Mat4() : Mat4(1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, 0.f, 0.f, 1.f) {} + + Mat4(const Matrix generalMatrix) + { + unsigned int minCols = std::min((unsigned int)4, generalMatrix.columns()); + unsigned int minRows = std::min((unsigned int)4, generalMatrix.rows()); + for (unsigned int i = 0; i < minCols; i++) + { + for (unsigned int j = 0; j < minRows; j++) + { + mElements[j * minCols + i] = generalMatrix.at(j, i); + } + } + } + + Mat4(const std::vector &elements) + { + std::copy(elements.begin(), std::min(elements.end(), elements.begin() + std::size(mElements)), + mElements.data()); + } + + Mat4(const float *elements) + { + std::copy(elements, ANGLE_UNSAFE_TODO(elements + std::size(mElements)), mElements.data()); + } + + Mat4(float m00, float m01, float m02, float m03, + float m10, float m11, float m12, float m13, + float m20, float m21, float m22, float m23, + float m30, float m31, float m32, float m33) + { + mElements[0] = m00; + mElements[1] = m01; + mElements[2] = m02; + mElements[3] = m03; + mElements[4] = m10; + mElements[5] = m11; + mElements[6] = m12; + mElements[7] = m13; + mElements[8] = m20; + mElements[9] = m21; + mElements[10] = m22; + mElements[11] = m23; + mElements[12] = m30; + mElements[13] = m31; + mElements[14] = m32; + mElements[15] = m33; + } + + static Mat4 Rotate(float angle, const Vector3 &axis) + { + if (axis.length() == 0.0f) + { + return Mat4(); + } + + auto axis_normalized = axis.normalized(); + constexpr float kPi = 3.14159265358979323f; + float angle_radians = angle * (kPi / 180.0f); + float c = cos(angle_radians); + float ci = 1.f - c; + float s = sin(angle_radians); + + float x = axis_normalized.x(); + float y = axis_normalized.y(); + float z = axis_normalized.z(); + + float x2 = x * x; + float y2 = y * y; + float z2 = z * z; + + float xy = x * y; + float yz = y * z; + float zx = z * x; + + float r00 = c + ci * x2; + float r01 = ci * xy + s * z; + float r02 = ci * zx - s * y; + float r03 = 0.f; + + float r10 = ci * xy - s * z; + float r11 = c + ci * y2; + float r12 = ci * yz + s * x; + float r13 = 0.f; + + float r20 = ci * zx + s * y; + float r21 = ci * yz - s * x; + float r22 = c + ci * z2; + float r23 = 0.f; + + float r30 = 0.f; + float r31 = 0.f; + float r32 = 0.f; + float r33 = 1.f; + + return Mat4(r00, r01, r02, r03, + r10, r11, r12, r13, + r20, r21, r22, r23, + r30, r31, r32, r33); + } + + static Mat4 Translate(const Vector3 &t) + { + return Mat4(1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + t.x(), t.y(), t.z(), 1.f); + } + + static Mat4 Scale(const Vector3 &s) + { + return Mat4(s.x(), 0.f, 0.f, 0.f, + 0.f, s.y(), 0.f, 0.f, + 0.f, 0.f, s.z(), 0.f, + 0.f, 0.f, 0.f, 1.f); + } + + static Mat4 Frustum(float l, float r, float b, float t, float n, float f) + { + float nn = 2.f * n; + float fpn = f + n; + float fmn = f - n; + float tpb = t + b; + float tmb = t - b; + float rpl = r + l; + float rml = r - l; + + return Mat4(nn / rml, 0.f, 0.f, 0.f, + 0.f, nn / tmb, 0.f, 0.f, + rpl / rml, tpb / tmb, -fpn / fmn, -1.f, + 0.f, 0.f, -nn * f / fmn, 0.f); + } + + static Mat4 Perspective(float fov, float aspectRatio, float n, float f) + { + constexpr float kPi = 3.14159265358979323f; + const float frustumHeight = tanf(fov / 360.0f * kPi) * n; + const float frustumWidth = frustumHeight * aspectRatio; + return Frustum(-frustumWidth, frustumWidth, -frustumHeight, frustumHeight, n, f); + } + + static Mat4 Ortho(float l, float r, float b, float t, float n, float f) + { + float fpn = f + n; + float fmn = f - n; + float tpb = t + b; + float tmb = t - b; + float rpl = r + l; + float rml = r - l; + + return Mat4(2.f / rml, 0.f, 0.f, 0.f, + 0.f, 2.f / tmb, 0.f, 0.f, + 0.f, 0.f, -2.f / fmn, 0.f, + -rpl / rml, -tpb / tmb, -fpn / fmn, 1.f); + } + + // Optimized matrix multiplication – manually unrolled with __restrict hints + Mat4 product(const Mat4 &m) + { + const float * __restrict a = mElements.data(); + const float * __restrict b = m.mElements.data(); + // We assume 'this' and 'm' do not alias; if they do, result is still correct but may violate strict aliasing. + return Mat4( + a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3], + a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3], + a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3], + a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3], + + a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7], + a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7], + a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7], + a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7], + + a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11], + a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11], + a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11], + a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11], + + a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15], + a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15], + a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15], + a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15] + ); + } + + Vector4 product(const Vector4 &b) + { + return Vector4( + mElements[0] * b.x() + mElements[4] * b.y() + mElements[8] * b.z() + mElements[12] * b.w(), + mElements[1] * b.x() + mElements[5] * b.y() + mElements[9] * b.z() + mElements[13] * b.w(), + mElements[2] * b.x() + mElements[6] * b.y() + mElements[10] * b.z() + mElements[14] * b.w(), + mElements[3] * b.x() + mElements[7] * b.y() + mElements[11] * b.z() + mElements[15] * b.w() + ); + } + + void dump() + { + printf("[ %f %f %f %f ]\n", mElements[0], mElements[4], mElements[8], mElements[12]); + printf("[ %f %f %f %f ]\n", mElements[1], mElements[5], mElements[9], mElements[13]); + printf("[ %f %f %f %f ]\n", mElements[2], mElements[6], mElements[10], mElements[14]); + printf("[ %f %f %f %f ]\n", mElements[3], mElements[7], mElements[11], mElements[15]); + } float *data() { return mElements.data(); } const float *constData() const { return mElements.data(); } @@ -477,24 +651,28 @@ class Mat4 for (unsigned int i = 0; i < 4; i++) for (unsigned int j = 0; j < 4; j++) result(i, j) = at(j, i); - return result; } + // Optimized inverse: use inverse of determinant once, then multiply instead of divide Mat4 inverse() const { Mat4 coft; CofactorTransposed(*this, coft); - float det = at(0, 0) * coft(0, 0) + at(0, 1) * coft(1, 0) + at(0, 2) * coft(2, 0) + - at(0, 3) * coft(3, 0); - - Mat4 result = coft; - for (int i = 0; i < 16; i++) - { - ANGLE_UNSAFE_TODO(result.data()[i]) /= det; - } + // Determinant via first row dot cofactor row 0 + float det = at(0, 0) * coft(0, 0) + at(0, 1) * coft(1, 0) + + at(0, 2) * coft(2, 0) + at(0, 3) * coft(3, 0); + const float invDet = 1.0f / det; + Mat4 result; + // Unroll the 16‑element scaling + float * __restrict r = result.mElements.data(); + const float * __restrict c = coft.mElements.data(); + r[0] = c[0] * invDet; r[1] = c[1] * invDet; r[2] = c[2] * invDet; r[3] = c[3] * invDet; + r[4] = c[4] * invDet; r[5] = c[5] * invDet; r[6] = c[6] * invDet; r[7] = c[7] * invDet; + r[8] = c[8] * invDet; r[9] = c[9] * invDet; r[10] = c[10] * invDet; r[11] = c[11] * invDet; + r[12] = c[12] * invDet; r[13] = c[13] * invDet; r[14] = c[14] * invDet; r[15] = c[15] * invDet; return result; } diff --git a/src/common/utilities.cpp b/src/common/utilities.cpp index 465928cda81..bbdf0f8f2fc 100644 --- a/src/common/utilities.cpp +++ b/src/common/utilities.cpp @@ -71,605 +71,8 @@ gl::IndexRange ComputeTypedIndexRange(const IndexType *indices, namespace gl { -int VariableComponentCount(GLenum type) -{ - return VariableRowCount(type) * VariableColumnCount(type); -} - -GLenum VariableComponentType(GLenum type) -{ - switch (type) - { - case GL_BOOL: - case GL_BOOL_VEC2: - case GL_BOOL_VEC3: - case GL_BOOL_VEC4: - return GL_BOOL; - case GL_FLOAT: - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: - case GL_FLOAT_MAT2: - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT4: - case GL_FLOAT_MAT2x3: - case GL_FLOAT_MAT3x2: - case GL_FLOAT_MAT2x4: - case GL_FLOAT_MAT4x2: - case GL_FLOAT_MAT3x4: - case GL_FLOAT_MAT4x3: - return GL_FLOAT; - case GL_INT: - case GL_SAMPLER_2D: - case GL_SAMPLER_2D_RECT_ANGLE: - case GL_SAMPLER_3D: - case GL_SAMPLER_CUBE: - case GL_SAMPLER_CUBE_MAP_ARRAY: - case GL_SAMPLER_2D_ARRAY: - case GL_SAMPLER_EXTERNAL_OES: - case GL_SAMPLER_2D_MULTISAMPLE: - case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_INT_SAMPLER_BUFFER: - case GL_INT_SAMPLER_2D: - case GL_INT_SAMPLER_3D: - case GL_INT_SAMPLER_CUBE: - case GL_INT_SAMPLER_CUBE_MAP_ARRAY: - case GL_INT_SAMPLER_2D_ARRAY: - case GL_INT_SAMPLER_2D_MULTISAMPLE: - case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D: - case GL_UNSIGNED_INT_SAMPLER_3D: - case GL_UNSIGNED_INT_SAMPLER_CUBE: - case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_SAMPLER_2D_SHADOW: - case GL_SAMPLER_BUFFER: - case GL_SAMPLER_CUBE_SHADOW: - case GL_SAMPLER_2D_ARRAY_SHADOW: - case GL_INT_VEC2: - case GL_INT_VEC3: - case GL_INT_VEC4: - case GL_IMAGE_2D: - case GL_INT_IMAGE_2D: - case GL_UNSIGNED_INT_IMAGE_2D: - case GL_IMAGE_3D: - case GL_INT_IMAGE_3D: - case GL_UNSIGNED_INT_IMAGE_3D: - case GL_IMAGE_2D_ARRAY: - case GL_INT_IMAGE_2D_ARRAY: - case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: - case GL_IMAGE_CUBE: - case GL_INT_IMAGE_CUBE: - case GL_UNSIGNED_INT_IMAGE_CUBE: - case GL_IMAGE_CUBE_MAP_ARRAY: - case GL_INT_IMAGE_CUBE_MAP_ARRAY: - case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: - case GL_IMAGE_BUFFER: - case GL_INT_IMAGE_BUFFER: - case GL_UNSIGNED_INT_SAMPLER_BUFFER: - case GL_UNSIGNED_INT_IMAGE_BUFFER: - case GL_UNSIGNED_INT_ATOMIC_COUNTER: - case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: - return GL_INT; - case GL_UNSIGNED_INT: - case GL_UNSIGNED_INT_VEC2: - case GL_UNSIGNED_INT_VEC3: - case GL_UNSIGNED_INT_VEC4: - return GL_UNSIGNED_INT; - default: - UNREACHABLE(); - } - - return GL_NONE; -} - -size_t VariableComponentSize(GLenum type) -{ - switch (type) - { - case GL_BOOL: - return sizeof(GLint); - case GL_FLOAT: - return sizeof(GLfloat); - case GL_INT: - return sizeof(GLint); - case GL_UNSIGNED_INT: - return sizeof(GLuint); - default: - UNREACHABLE(); - } - - return 0; -} - -size_t VariableInternalSize(GLenum type) -{ - // Expanded to 4-element vectors - return VariableComponentSize(VariableComponentType(type)) * VariableRowCount(type) * 4; -} - -size_t VariableExternalSize(GLenum type) -{ - return VariableComponentSize(VariableComponentType(type)) * VariableComponentCount(type); -} - -std::string GetGLSLTypeString(GLenum type) -{ - switch (type) - { - case GL_BOOL: - return "bool"; - case GL_INT: - return "int"; - case GL_UNSIGNED_INT: - return "uint"; - case GL_FLOAT: - return "float"; - case GL_BOOL_VEC2: - return "bvec2"; - case GL_BOOL_VEC3: - return "bvec3"; - case GL_BOOL_VEC4: - return "bvec4"; - case GL_INT_VEC2: - return "ivec2"; - case GL_INT_VEC3: - return "ivec3"; - case GL_INT_VEC4: - return "ivec4"; - case GL_FLOAT_VEC2: - return "vec2"; - case GL_FLOAT_VEC3: - return "vec3"; - case GL_FLOAT_VEC4: - return "vec4"; - case GL_UNSIGNED_INT_VEC2: - return "uvec2"; - case GL_UNSIGNED_INT_VEC3: - return "uvec3"; - case GL_UNSIGNED_INT_VEC4: - return "uvec4"; - case GL_FLOAT_MAT2: - return "mat2"; - case GL_FLOAT_MAT3: - return "mat3"; - case GL_FLOAT_MAT4: - return "mat4"; - default: - UNREACHABLE(); - return ""; - } -} - -GLenum VariableBoolVectorType(GLenum type) -{ - switch (type) - { - case GL_FLOAT: - case GL_INT: - case GL_UNSIGNED_INT: - return GL_BOOL; - case GL_FLOAT_VEC2: - case GL_INT_VEC2: - case GL_UNSIGNED_INT_VEC2: - return GL_BOOL_VEC2; - case GL_FLOAT_VEC3: - case GL_INT_VEC3: - case GL_UNSIGNED_INT_VEC3: - return GL_BOOL_VEC3; - case GL_FLOAT_VEC4: - case GL_INT_VEC4: - case GL_UNSIGNED_INT_VEC4: - return GL_BOOL_VEC4; - - default: - UNREACHABLE(); - return GL_NONE; - } -} - -int VariableRowCount(GLenum type) -{ - switch (type) - { - case GL_NONE: - return 0; - case GL_BOOL: - case GL_FLOAT: - case GL_INT: - case GL_UNSIGNED_INT: - case GL_BOOL_VEC2: - case GL_FLOAT_VEC2: - case GL_INT_VEC2: - case GL_UNSIGNED_INT_VEC2: - case GL_BOOL_VEC3: - case GL_FLOAT_VEC3: - case GL_INT_VEC3: - case GL_UNSIGNED_INT_VEC3: - case GL_BOOL_VEC4: - case GL_FLOAT_VEC4: - case GL_INT_VEC4: - case GL_UNSIGNED_INT_VEC4: - case GL_SAMPLER_2D: - case GL_SAMPLER_3D: - case GL_SAMPLER_CUBE: - case GL_SAMPLER_2D_ARRAY: - case GL_SAMPLER_EXTERNAL_OES: - case GL_SAMPLER_2D_RECT_ANGLE: - case GL_SAMPLER_2D_MULTISAMPLE: - case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_SAMPLER_CUBE_MAP_ARRAY: - case GL_SAMPLER_BUFFER: - case GL_INT_SAMPLER_2D: - case GL_INT_SAMPLER_3D: - case GL_INT_SAMPLER_CUBE: - case GL_INT_SAMPLER_2D_ARRAY: - case GL_INT_SAMPLER_2D_MULTISAMPLE: - case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_INT_SAMPLER_CUBE_MAP_ARRAY: - case GL_INT_SAMPLER_BUFFER: - case GL_UNSIGNED_INT_SAMPLER_2D: - case GL_UNSIGNED_INT_SAMPLER_3D: - case GL_UNSIGNED_INT_SAMPLER_CUBE: - case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_BUFFER: - case GL_SAMPLER_2D_SHADOW: - case GL_SAMPLER_CUBE_SHADOW: - case GL_SAMPLER_2D_ARRAY_SHADOW: - case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: - case GL_IMAGE_2D: - case GL_INT_IMAGE_2D: - case GL_UNSIGNED_INT_IMAGE_2D: - case GL_IMAGE_2D_ARRAY: - case GL_INT_IMAGE_2D_ARRAY: - case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: - case GL_IMAGE_3D: - case GL_INT_IMAGE_3D: - case GL_UNSIGNED_INT_IMAGE_3D: - case GL_IMAGE_CUBE: - case GL_INT_IMAGE_CUBE: - case GL_UNSIGNED_INT_IMAGE_CUBE: - case GL_UNSIGNED_INT_ATOMIC_COUNTER: - case GL_IMAGE_CUBE_MAP_ARRAY: - case GL_INT_IMAGE_CUBE_MAP_ARRAY: - case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: - case GL_IMAGE_BUFFER: - case GL_INT_IMAGE_BUFFER: - case GL_UNSIGNED_INT_IMAGE_BUFFER: - case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: - return 1; - case GL_FLOAT_MAT2: - case GL_FLOAT_MAT3x2: - case GL_FLOAT_MAT4x2: - return 2; - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT2x3: - case GL_FLOAT_MAT4x3: - return 3; - case GL_FLOAT_MAT4: - case GL_FLOAT_MAT2x4: - case GL_FLOAT_MAT3x4: - return 4; - default: - UNREACHABLE(); - } - - return 0; -} - -int VariableColumnCount(GLenum type) -{ - switch (type) - { - case GL_NONE: - return 0; - case GL_BOOL: - case GL_FLOAT: - case GL_INT: - case GL_UNSIGNED_INT: - case GL_SAMPLER_2D: - case GL_SAMPLER_3D: - case GL_SAMPLER_CUBE: - case GL_SAMPLER_2D_ARRAY: - case GL_SAMPLER_2D_MULTISAMPLE: - case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_SAMPLER_CUBE_MAP_ARRAY: - case GL_SAMPLER_BUFFER: - case GL_INT_SAMPLER_2D: - case GL_INT_SAMPLER_3D: - case GL_INT_SAMPLER_CUBE: - case GL_INT_SAMPLER_2D_ARRAY: - case GL_INT_SAMPLER_2D_MULTISAMPLE: - case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_INT_SAMPLER_CUBE_MAP_ARRAY: - case GL_INT_SAMPLER_BUFFER: - case GL_SAMPLER_EXTERNAL_OES: - case GL_SAMPLER_2D_RECT_ANGLE: - case GL_UNSIGNED_INT_SAMPLER_2D: - case GL_UNSIGNED_INT_SAMPLER_3D: - case GL_UNSIGNED_INT_SAMPLER_CUBE: - case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_BUFFER: - case GL_SAMPLER_2D_SHADOW: - case GL_SAMPLER_CUBE_SHADOW: - case GL_SAMPLER_2D_ARRAY_SHADOW: - case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: - case GL_IMAGE_2D: - case GL_INT_IMAGE_2D: - case GL_UNSIGNED_INT_IMAGE_2D: - case GL_IMAGE_3D: - case GL_INT_IMAGE_3D: - case GL_UNSIGNED_INT_IMAGE_3D: - case GL_IMAGE_2D_ARRAY: - case GL_INT_IMAGE_2D_ARRAY: - case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: - case GL_IMAGE_CUBE_MAP_ARRAY: - case GL_INT_IMAGE_CUBE_MAP_ARRAY: - case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: - case GL_IMAGE_BUFFER: - case GL_INT_IMAGE_BUFFER: - case GL_UNSIGNED_INT_IMAGE_BUFFER: - case GL_IMAGE_CUBE: - case GL_INT_IMAGE_CUBE: - case GL_UNSIGNED_INT_IMAGE_CUBE: - case GL_UNSIGNED_INT_ATOMIC_COUNTER: - case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: - return 1; - case GL_BOOL_VEC2: - case GL_FLOAT_VEC2: - case GL_INT_VEC2: - case GL_UNSIGNED_INT_VEC2: - case GL_FLOAT_MAT2: - case GL_FLOAT_MAT2x3: - case GL_FLOAT_MAT2x4: - return 2; - case GL_BOOL_VEC3: - case GL_FLOAT_VEC3: - case GL_INT_VEC3: - case GL_UNSIGNED_INT_VEC3: - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT3x2: - case GL_FLOAT_MAT3x4: - return 3; - case GL_BOOL_VEC4: - case GL_FLOAT_VEC4: - case GL_INT_VEC4: - case GL_UNSIGNED_INT_VEC4: - case GL_FLOAT_MAT4: - case GL_FLOAT_MAT4x2: - case GL_FLOAT_MAT4x3: - return 4; - default: - UNREACHABLE(); - } - - return 0; -} - -bool IsSamplerType(GLenum type) -{ - switch (type) - { - case GL_SAMPLER_2D: - case GL_SAMPLER_3D: - case GL_SAMPLER_CUBE: - case GL_SAMPLER_2D_ARRAY: - case GL_SAMPLER_EXTERNAL_OES: - case GL_SAMPLER_2D_MULTISAMPLE: - case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_SAMPLER_CUBE_MAP_ARRAY: - case GL_SAMPLER_BUFFER: - case GL_SAMPLER_2D_RECT_ANGLE: - case GL_INT_SAMPLER_2D: - case GL_INT_SAMPLER_3D: - case GL_INT_SAMPLER_CUBE: - case GL_INT_SAMPLER_2D_ARRAY: - case GL_INT_SAMPLER_2D_MULTISAMPLE: - case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_INT_SAMPLER_CUBE_MAP_ARRAY: - case GL_INT_SAMPLER_BUFFER: - case GL_UNSIGNED_INT_SAMPLER_2D: - case GL_UNSIGNED_INT_SAMPLER_3D: - case GL_UNSIGNED_INT_SAMPLER_CUBE: - case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_BUFFER: - case GL_SAMPLER_2D_SHADOW: - case GL_SAMPLER_CUBE_SHADOW: - case GL_SAMPLER_2D_ARRAY_SHADOW: - case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: - case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: - return true; - } - - return false; -} - -bool IsSamplerCubeType(GLenum type) -{ - switch (type) - { - case GL_SAMPLER_CUBE: - case GL_INT_SAMPLER_CUBE: - case GL_UNSIGNED_INT_SAMPLER_CUBE: - case GL_SAMPLER_CUBE_SHADOW: - return true; - } - - return false; -} - -bool IsSamplerYUVType(GLenum type) -{ - switch (type) - { - case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: - return true; - - default: - return false; - } -} - -bool IsImageType(GLenum type) -{ - switch (type) - { - case GL_IMAGE_2D: - case GL_INT_IMAGE_2D: - case GL_UNSIGNED_INT_IMAGE_2D: - case GL_IMAGE_3D: - case GL_INT_IMAGE_3D: - case GL_UNSIGNED_INT_IMAGE_3D: - case GL_IMAGE_2D_ARRAY: - case GL_INT_IMAGE_2D_ARRAY: - case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: - case GL_IMAGE_CUBE_MAP_ARRAY: - case GL_INT_IMAGE_CUBE_MAP_ARRAY: - case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: - case GL_IMAGE_BUFFER: - case GL_INT_IMAGE_BUFFER: - case GL_UNSIGNED_INT_IMAGE_BUFFER: - case GL_IMAGE_CUBE: - case GL_INT_IMAGE_CUBE: - case GL_UNSIGNED_INT_IMAGE_CUBE: - return true; - } - return false; -} - -bool IsImage2DType(GLenum type) -{ - switch (type) - { - case GL_IMAGE_2D: - case GL_INT_IMAGE_2D: - case GL_UNSIGNED_INT_IMAGE_2D: - return true; - case GL_IMAGE_3D: - case GL_INT_IMAGE_3D: - case GL_UNSIGNED_INT_IMAGE_3D: - case GL_IMAGE_2D_ARRAY: - case GL_INT_IMAGE_2D_ARRAY: - case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: - case GL_IMAGE_CUBE_MAP_ARRAY: - case GL_INT_IMAGE_CUBE_MAP_ARRAY: - case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: - case GL_IMAGE_CUBE: - case GL_INT_IMAGE_CUBE: - case GL_UNSIGNED_INT_IMAGE_CUBE: - case GL_IMAGE_BUFFER: - case GL_INT_IMAGE_BUFFER: - case GL_UNSIGNED_INT_IMAGE_BUFFER: - return false; - default: - UNREACHABLE(); - return false; - } -} - -bool IsAtomicCounterType(GLenum type) -{ - return type == GL_UNSIGNED_INT_ATOMIC_COUNTER; -} - -bool IsOpaqueType(GLenum type) -{ - // ESSL 3.10 section 4.1.7 defines opaque types as: samplers, images and atomic counters. - return IsImageType(type) || IsSamplerType(type) || IsAtomicCounterType(type); -} - -bool IsMatrixType(GLenum type) -{ - return VariableRowCount(type) > 1; -} - -bool IsFloatScalarAndVectorType(GLenum type) -{ - switch (type) - { - case GL_FLOAT: - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: - return true; - default: - return false; - } -} - -bool IsFloatVectorType(GLenum type) -{ - switch (type) - { - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: - return true; - default: - return false; - } -} - -GLenum TransposeMatrixType(GLenum type) -{ - if (!IsMatrixType(type)) - { - return type; - } - - switch (type) - { - case GL_FLOAT_MAT2: - return GL_FLOAT_MAT2; - case GL_FLOAT_MAT3: - return GL_FLOAT_MAT3; - case GL_FLOAT_MAT4: - return GL_FLOAT_MAT4; - case GL_FLOAT_MAT2x3: - return GL_FLOAT_MAT3x2; - case GL_FLOAT_MAT3x2: - return GL_FLOAT_MAT2x3; - case GL_FLOAT_MAT2x4: - return GL_FLOAT_MAT4x2; - case GL_FLOAT_MAT4x2: - return GL_FLOAT_MAT2x4; - case GL_FLOAT_MAT3x4: - return GL_FLOAT_MAT4x3; - case GL_FLOAT_MAT4x3: - return GL_FLOAT_MAT3x4; - default: - UNREACHABLE(); - return GL_NONE; - } -} - -int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix) -{ - ASSERT(IsMatrixType(type)); - return isRowMajorMatrix ? VariableRowCount(type) : VariableColumnCount(type); -} - -int MatrixComponentCount(GLenum type, bool isRowMajorMatrix) -{ - ASSERT(IsMatrixType(type)); - return isRowMajorMatrix ? VariableColumnCount(type) : VariableRowCount(type); -} - -int VariableRegisterCount(GLenum type) -{ - return IsMatrixType(type) ? VariableColumnCount(type) : 1; -} +// 这些函数已移至头文件并标记为 inline,此处不再重复定义。 +// 保留以下非内联函数: int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize) { @@ -714,181 +117,6 @@ IndexRange ComputeIndexRange(DrawElementsType indexType, } } -GLuint GetPrimitiveRestartIndex(DrawElementsType indexType) -{ - switch (indexType) - { - case DrawElementsType::UnsignedByte: - return 0xFF; - case DrawElementsType::UnsignedShort: - return 0xFFFF; - case DrawElementsType::UnsignedInt: - return 0xFFFFFFFF; - default: - UNREACHABLE(); - return 0; - } -} - -bool IsTriangleMode(PrimitiveMode drawMode) -{ - switch (drawMode) - { - case PrimitiveMode::Triangles: - case PrimitiveMode::TriangleFan: - case PrimitiveMode::TriangleStrip: - return true; - case PrimitiveMode::Points: - case PrimitiveMode::Lines: - case PrimitiveMode::LineLoop: - case PrimitiveMode::LineStrip: - return false; - default: - UNREACHABLE(); - } - - return false; -} - -bool IsPolygonMode(PrimitiveMode mode) -{ - switch (mode) - { - case PrimitiveMode::Points: - case PrimitiveMode::Lines: - case PrimitiveMode::LineStrip: - case PrimitiveMode::LineLoop: - case PrimitiveMode::LinesAdjacency: - case PrimitiveMode::LineStripAdjacency: - return false; - default: - break; - } - - return true; -} - -namespace priv -{ -const angle::PackedEnumMap gLineModes = { - {{PrimitiveMode::LineLoop, true}, - {PrimitiveMode::LineStrip, true}, - {PrimitiveMode::LineStripAdjacency, true}, - {PrimitiveMode::Lines, true}}}; -} // namespace priv - -bool IsIntegerFormat(GLenum unsizedFormat) -{ - switch (unsizedFormat) - { - case GL_RGBA_INTEGER: - case GL_RGB_INTEGER: - case GL_RG_INTEGER: - case GL_RED_INTEGER: - return true; - - default: - return false; - } -} - -// [OpenGL ES SL 3.00.4] Section 11 p. 120 -// Vertex Outs/Fragment Ins packing priorities -int VariableSortOrder(GLenum type) -{ - switch (type) - { - // 1. Arrays of mat4 and mat4 - // Non-square matrices of type matCxR consume the same space as a square - // matrix of type matN where N is the greater of C and R - case GL_FLOAT_MAT4: - case GL_FLOAT_MAT2x4: - case GL_FLOAT_MAT3x4: - case GL_FLOAT_MAT4x2: - case GL_FLOAT_MAT4x3: - return 0; - - // 2. Arrays of mat2 and mat2 (since they occupy full rows) - case GL_FLOAT_MAT2: - return 1; - - // 3. Arrays of vec4 and vec4 - case GL_FLOAT_VEC4: - case GL_INT_VEC4: - case GL_BOOL_VEC4: - case GL_UNSIGNED_INT_VEC4: - return 2; - - // 4. Arrays of mat3 and mat3 - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT2x3: - case GL_FLOAT_MAT3x2: - return 3; - - // 5. Arrays of vec3 and vec3 - case GL_FLOAT_VEC3: - case GL_INT_VEC3: - case GL_BOOL_VEC3: - case GL_UNSIGNED_INT_VEC3: - return 4; - - // 6. Arrays of vec2 and vec2 - case GL_FLOAT_VEC2: - case GL_INT_VEC2: - case GL_BOOL_VEC2: - case GL_UNSIGNED_INT_VEC2: - return 5; - - // 7. Single component types - case GL_FLOAT: - case GL_INT: - case GL_BOOL: - case GL_UNSIGNED_INT: - case GL_SAMPLER_2D: - case GL_SAMPLER_CUBE: - case GL_SAMPLER_EXTERNAL_OES: - case GL_SAMPLER_2D_RECT_ANGLE: - case GL_SAMPLER_2D_ARRAY: - case GL_SAMPLER_2D_MULTISAMPLE: - case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_SAMPLER_3D: - case GL_INT_SAMPLER_2D: - case GL_INT_SAMPLER_3D: - case GL_INT_SAMPLER_CUBE: - case GL_INT_SAMPLER_2D_ARRAY: - case GL_INT_SAMPLER_2D_MULTISAMPLE: - case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D: - case GL_UNSIGNED_INT_SAMPLER_3D: - case GL_UNSIGNED_INT_SAMPLER_CUBE: - case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_SAMPLER_2D_SHADOW: - case GL_SAMPLER_2D_ARRAY_SHADOW: - case GL_SAMPLER_CUBE_SHADOW: - case GL_IMAGE_2D: - case GL_INT_IMAGE_2D: - case GL_UNSIGNED_INT_IMAGE_2D: - case GL_IMAGE_3D: - case GL_INT_IMAGE_3D: - case GL_UNSIGNED_INT_IMAGE_3D: - case GL_IMAGE_2D_ARRAY: - case GL_INT_IMAGE_2D_ARRAY: - case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: - case GL_IMAGE_CUBE: - case GL_INT_IMAGE_CUBE: - case GL_UNSIGNED_INT_IMAGE_CUBE: - case GL_UNSIGNED_INT_ATOMIC_COUNTER: - case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: - return 6; - - default: - UNREACHABLE(); - return 0; - } -} - std::string ParseResourceName(const std::string &name, std::vector *outSubscripts) { if (outSubscripts) @@ -930,11 +158,6 @@ std::string ParseResourceName(const std::string &name, std::vector return name.substr(0, baseNameLength); } -bool IsBuiltInName(const char *name) -{ - return angle::BeginsWith(name, "gl_"); -} - std::string StripLastArrayIndex(const std::string &name) { size_t strippedNameLength = name.find_last_of('['); @@ -966,31 +189,6 @@ bool SamplerNameContainsNonZeroArrayElement(const std::string &name) return false; } -unsigned int ArraySizeProduct(const std::vector &arraySizes) -{ - unsigned int arraySizeProduct = 1u; - for (unsigned int arraySize : arraySizes) - { - arraySizeProduct *= arraySize; - } - return arraySizeProduct; -} - -unsigned int InnerArraySizeProduct(const std::vector &arraySizes) -{ - unsigned int arraySizeProduct = 1u; - for (size_t index = 0; index + 1 < arraySizes.size(); ++index) - { - arraySizeProduct *= arraySizes[index]; - } - return arraySizeProduct; -} - -unsigned int OutermostArraySize(const std::vector &arraySizes) -{ - return arraySizes.empty() || arraySizes.back() == 0 ? 1 : arraySizes.back(); -} - unsigned int ParseArrayIndex(const std::string &name, size_t *nameLengthWithoutArrayIndexOut) { ASSERT(nameLengthWithoutArrayIndexOut != nullptr); @@ -1061,56 +259,6 @@ const char *GetGenericErrorMessage(GLenum error) } } -unsigned int ElementTypeSize(GLenum elementType) -{ - switch (elementType) - { - case GL_UNSIGNED_BYTE: - return sizeof(GLubyte); - case GL_UNSIGNED_SHORT: - return sizeof(GLushort); - case GL_UNSIGNED_INT: - return sizeof(GLuint); - default: - UNREACHABLE(); - return 0; - } -} - -bool IsMipmapFiltered(GLenum minFilterMode) -{ - switch (minFilterMode) - { - case GL_NEAREST: - case GL_LINEAR: - return false; - case GL_NEAREST_MIPMAP_NEAREST: - case GL_LINEAR_MIPMAP_NEAREST: - case GL_NEAREST_MIPMAP_LINEAR: - case GL_LINEAR_MIPMAP_LINEAR: - return true; - default: - UNREACHABLE(); - return false; - } -} - -PipelineType GetPipelineType(ShaderType type) -{ - switch (type) - { - case ShaderType::Vertex: - case ShaderType::Fragment: - case ShaderType::Geometry: - return PipelineType::GraphicsPipeline; - case ShaderType::Compute: - return PipelineType::ComputePipeline; - default: - UNREACHABLE(); - return PipelineType::GraphicsPipeline; - } -} - const char *GetDebugMessageSourceString(GLenum source) { switch (source) @@ -1172,83 +320,10 @@ const char *GetDebugMessageSeverityString(GLenum severity) } } -ShaderType GetShaderTypeFromBitfield(size_t singleShaderType) -{ - switch (singleShaderType) - { - case GL_VERTEX_SHADER_BIT: - return ShaderType::Vertex; - case GL_FRAGMENT_SHADER_BIT: - return ShaderType::Fragment; - case GL_COMPUTE_SHADER_BIT: - return ShaderType::Compute; - case GL_GEOMETRY_SHADER_BIT: - return ShaderType::Geometry; - case GL_TESS_CONTROL_SHADER_BIT: - return ShaderType::TessControl; - case GL_TESS_EVALUATION_SHADER_BIT: - return ShaderType::TessEvaluation; - default: - return ShaderType::InvalidEnum; - } -} - -GLbitfield GetBitfieldFromShaderType(ShaderType shaderType) -{ - switch (shaderType) - { - case ShaderType::Vertex: - return GL_VERTEX_SHADER_BIT; - case ShaderType::Fragment: - return GL_FRAGMENT_SHADER_BIT; - case ShaderType::Compute: - return GL_COMPUTE_SHADER_BIT; - case ShaderType::Geometry: - return GL_GEOMETRY_SHADER_BIT; - case ShaderType::TessControl: - return GL_TESS_CONTROL_SHADER_BIT; - case ShaderType::TessEvaluation: - return GL_TESS_EVALUATION_SHADER_BIT; - default: - UNREACHABLE(); - return GL_ZERO; - } -} - -bool ShaderTypeSupportsTransformFeedback(ShaderType shaderType) -{ - switch (shaderType) - { - case ShaderType::Vertex: - case ShaderType::Geometry: - case ShaderType::TessEvaluation: - return true; - default: - return false; - } -} - -ShaderType GetLastPreFragmentStage(ShaderBitSet shaderTypes) -{ - shaderTypes.reset(ShaderType::Fragment); - shaderTypes.reset(ShaderType::Compute); - return shaderTypes.any() ? shaderTypes.last() : ShaderType::InvalidEnum; -} } // namespace gl namespace egl { -static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 1, - "Unexpected EGL cube map enum value."); -static_assert(EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 2, - "Unexpected EGL cube map enum value."); -static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 3, - "Unexpected EGL cube map enum value."); -static_assert(EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 4, - "Unexpected EGL cube map enum value."); -static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 5, - "Unexpected EGL cube map enum value."); - bool IsCubeMapTextureTarget(EGLenum target) { return (target >= FirstCubeMapTextureTarget && target <= LastCubeMapTextureTarget); @@ -1487,4 +562,4 @@ void writeFile(const char *path, std::string_view content) UNREACHABLE(); return; #endif // !ANGLE_ENABLE_WINDOWS_UWP -} +} \ No newline at end of file diff --git a/src/common/utilities.h b/src/common/utilities.h index f78d7017a4f..778a3c1f609 100644 --- a/src/common/utilities.h +++ b/src/common/utilities.h @@ -33,30 +33,31 @@ struct ShaderVariable; namespace gl { -int VariableComponentCount(GLenum type); -GLenum VariableComponentType(GLenum type); -size_t VariableComponentSize(GLenum type); -size_t VariableInternalSize(GLenum type); -size_t VariableExternalSize(GLenum type); -int VariableRowCount(GLenum type); -int VariableColumnCount(GLenum type); -bool IsSamplerType(GLenum type); -bool IsSamplerCubeType(GLenum type); -bool IsSamplerYUVType(GLenum type); -bool IsImageType(GLenum type); -bool IsImage2DType(GLenum type); -bool IsAtomicCounterType(GLenum type); -bool IsOpaqueType(GLenum type); -bool IsMatrixType(GLenum type); -bool IsFloatScalarAndVectorType(GLenum type); -bool IsFloatVectorType(GLenum type); -GLenum TransposeMatrixType(GLenum type); -int VariableRegisterCount(GLenum type); -int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix); -int MatrixComponentCount(GLenum type, bool isRowMajorMatrix); -int VariableSortOrder(GLenum type); -GLenum VariableBoolVectorType(GLenum type); -std::string GetGLSLTypeString(GLenum type); +// 这些轻量级查询函数现在声明为 inline 并在头文件中定义,以允许内联优化。 +inline int VariableComponentCount(GLenum type); +inline GLenum VariableComponentType(GLenum type); +inline size_t VariableComponentSize(GLenum type); +inline size_t VariableInternalSize(GLenum type); +inline size_t VariableExternalSize(GLenum type); +inline int VariableRowCount(GLenum type); +inline int VariableColumnCount(GLenum type); +inline bool IsSamplerType(GLenum type); +inline bool IsSamplerCubeType(GLenum type); +inline bool IsSamplerYUVType(GLenum type); +inline bool IsImageType(GLenum type); +inline bool IsImage2DType(GLenum type); +inline bool IsAtomicCounterType(GLenum type); +inline bool IsOpaqueType(GLenum type); +inline bool IsMatrixType(GLenum type); +inline bool IsFloatScalarAndVectorType(GLenum type); +inline bool IsFloatVectorType(GLenum type); +inline GLenum TransposeMatrixType(GLenum type); +inline int VariableRegisterCount(GLenum type); +inline int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix); +inline int MatrixComponentCount(GLenum type, bool isRowMajorMatrix); +inline int VariableSortOrder(GLenum type); +inline GLenum VariableBoolVectorType(GLenum type); +inline std::string GetGLSLTypeString(GLenum type); int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize); @@ -67,11 +68,8 @@ int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsig // outSubscripts. std::string ParseResourceName(const std::string &name, std::vector *outSubscripts); -bool IsBuiltInName(const char *name); -ANGLE_INLINE bool IsBuiltInName(const std::string &name) -{ - return IsBuiltInName(name.c_str()); -} +inline bool IsBuiltInName(const char *name); +inline bool IsBuiltInName(const std::string &name); // Strips only the last array index from a resource name. std::string StripLastArrayIndex(const std::string &name); @@ -86,7 +84,7 @@ IndexRange ComputeIndexRange(DrawElementsType indexType, bool primitiveRestartEnabled); // Get the primitive restart index value for the given index type. -GLuint GetPrimitiveRestartIndex(DrawElementsType indexType); +inline GLuint GetPrimitiveRestartIndex(DrawElementsType indexType); // Get the primitive restart index value with the given C++ type. template @@ -102,29 +100,26 @@ static_assert(GetPrimitiveRestartIndexFromType() == 0xFFFF, static_assert(GetPrimitiveRestartIndexFromType() == 0xFFFFFFFF, "verify restart index for uint8_t values"); -bool IsTriangleMode(PrimitiveMode drawMode); -bool IsPolygonMode(PrimitiveMode mode); +inline bool IsTriangleMode(PrimitiveMode drawMode); +inline bool IsPolygonMode(PrimitiveMode mode); namespace priv { extern const angle::PackedEnumMap gLineModes; } // namespace priv -ANGLE_INLINE bool IsLineMode(PrimitiveMode primitiveMode) -{ - return priv::gLineModes[primitiveMode]; -} +inline bool IsLineMode(PrimitiveMode primitiveMode); -bool IsIntegerFormat(GLenum unsizedFormat); +inline bool IsIntegerFormat(GLenum unsizedFormat); // Returns the product of the sizes in the vector, or 1 if the vector is empty. Doesn't currently // perform overflow checks. -unsigned int ArraySizeProduct(const std::vector &arraySizes); +inline unsigned int ArraySizeProduct(const std::vector &arraySizes); // Returns the product of the sizes in the vector except for the outermost dimension, or 1 if the // vector is empty. -unsigned int InnerArraySizeProduct(const std::vector &arraySizes); +inline unsigned int InnerArraySizeProduct(const std::vector &arraySizes); // Returns the outermost array dimension, or 1 if the vector is empty. -unsigned int OutermostArraySize(const std::vector &arraySizes); +inline unsigned int OutermostArraySize(const std::vector &arraySizes); // Return the array index at the end of name, and write the length of name before the final array // index into nameLengthWithoutArrayIndexOut. In case name doesn't include an array index, return @@ -218,12 +213,12 @@ UniformTypeIndex GetUniformTypeIndex(GLenum uniformType); const char *GetGenericErrorMessage(GLenum error); -unsigned int ElementTypeSize(GLenum elementType); +inline unsigned int ElementTypeSize(GLenum elementType); -bool IsMipmapFiltered(GLenum minFilterMode); +inline bool IsMipmapFiltered(GLenum minFilterMode); template -T GetClampedVertexCount(size_t vertexCount) +inline T GetClampedVertexCount(size_t vertexCount) { static constexpr size_t kMax = static_cast(std::numeric_limits::max()); return static_cast(vertexCount > kMax ? kMax : vertexCount); @@ -235,7 +230,7 @@ enum class PipelineType ComputePipeline = 1, }; -PipelineType GetPipelineType(ShaderType shaderType); +inline PipelineType GetPipelineType(ShaderType shaderType); // For use with KHR_debug. const char *GetDebugMessageSourceString(GLenum source); @@ -287,12 +282,929 @@ enum class YuvSamplingMode Y2Y = 1 }; -ShaderType GetShaderTypeFromBitfield(size_t singleShaderType); -GLbitfield GetBitfieldFromShaderType(ShaderType shaderType); -bool ShaderTypeSupportsTransformFeedback(ShaderType shaderType); -// Given a set of shader stages, returns the last vertex processing stage. This is the stage that -// interfaces the fragment shader. -ShaderType GetLastPreFragmentStage(ShaderBitSet shaderTypes); +inline ShaderType GetShaderTypeFromBitfield(size_t singleShaderType); +inline GLbitfield GetBitfieldFromShaderType(ShaderType shaderType); +inline bool ShaderTypeSupportsTransformFeedback(ShaderType shaderType); +inline ShaderType GetLastPreFragmentStage(ShaderBitSet shaderTypes); + +// ---------- 内联函数实现 ---------- + +inline int VariableComponentCount(GLenum type) +{ + return VariableRowCount(type) * VariableColumnCount(type); +} + +inline GLenum VariableComponentType(GLenum type) +{ + switch (type) + { + case GL_BOOL: + case GL_BOOL_VEC2: + case GL_BOOL_VEC3: + case GL_BOOL_VEC4: + return GL_BOOL; + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT4: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT3x2: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT4x2: + case GL_FLOAT_MAT3x4: + case GL_FLOAT_MAT4x3: + return GL_FLOAT; + case GL_INT: + case GL_SAMPLER_2D: + case GL_SAMPLER_2D_RECT_ANGLE: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_CUBE_MAP_ARRAY: + case GL_SAMPLER_2D_ARRAY: + case GL_SAMPLER_EXTERNAL_OES: + case GL_SAMPLER_2D_MULTISAMPLE: + case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_INT_SAMPLER_BUFFER: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_2D_MULTISAMPLE: + case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_BUFFER: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_INT_VEC2: + case GL_INT_VEC3: + case GL_INT_VEC4: + case GL_IMAGE_2D: + case GL_INT_IMAGE_2D: + case GL_UNSIGNED_INT_IMAGE_2D: + case GL_IMAGE_3D: + case GL_INT_IMAGE_3D: + case GL_UNSIGNED_INT_IMAGE_3D: + case GL_IMAGE_2D_ARRAY: + case GL_INT_IMAGE_2D_ARRAY: + case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: + case GL_IMAGE_CUBE: + case GL_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_IMAGE_CUBE: + case GL_IMAGE_CUBE_MAP_ARRAY: + case GL_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_IMAGE_BUFFER: + case GL_INT_IMAGE_BUFFER: + case GL_UNSIGNED_INT_SAMPLER_BUFFER: + case GL_UNSIGNED_INT_IMAGE_BUFFER: + case GL_UNSIGNED_INT_ATOMIC_COUNTER: + case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: + return GL_INT; + case GL_UNSIGNED_INT: + case GL_UNSIGNED_INT_VEC2: + case GL_UNSIGNED_INT_VEC3: + case GL_UNSIGNED_INT_VEC4: + return GL_UNSIGNED_INT; + default: + UNREACHABLE(); + } + + return GL_NONE; +} + +inline size_t VariableComponentSize(GLenum type) +{ + switch (type) + { + case GL_BOOL: + return sizeof(GLint); + case GL_FLOAT: + return sizeof(GLfloat); + case GL_INT: + return sizeof(GLint); + case GL_UNSIGNED_INT: + return sizeof(GLuint); + default: + UNREACHABLE(); + } + + return 0; +} + +inline size_t VariableInternalSize(GLenum type) +{ + // Expanded to 4-element vectors + return VariableComponentSize(VariableComponentType(type)) * VariableRowCount(type) * 4; +} + +inline size_t VariableExternalSize(GLenum type) +{ + return VariableComponentSize(VariableComponentType(type)) * VariableComponentCount(type); +} + +inline std::string GetGLSLTypeString(GLenum type) +{ + switch (type) + { + case GL_BOOL: + return "bool"; + case GL_INT: + return "int"; + case GL_UNSIGNED_INT: + return "uint"; + case GL_FLOAT: + return "float"; + case GL_BOOL_VEC2: + return "bvec2"; + case GL_BOOL_VEC3: + return "bvec3"; + case GL_BOOL_VEC4: + return "bvec4"; + case GL_INT_VEC2: + return "ivec2"; + case GL_INT_VEC3: + return "ivec3"; + case GL_INT_VEC4: + return "ivec4"; + case GL_FLOAT_VEC2: + return "vec2"; + case GL_FLOAT_VEC3: + return "vec3"; + case GL_FLOAT_VEC4: + return "vec4"; + case GL_UNSIGNED_INT_VEC2: + return "uvec2"; + case GL_UNSIGNED_INT_VEC3: + return "uvec3"; + case GL_UNSIGNED_INT_VEC4: + return "uvec4"; + case GL_FLOAT_MAT2: + return "mat2"; + case GL_FLOAT_MAT3: + return "mat3"; + case GL_FLOAT_MAT4: + return "mat4"; + default: + UNREACHABLE(); + return ""; + } +} + +inline GLenum VariableBoolVectorType(GLenum type) +{ + switch (type) + { + case GL_FLOAT: + case GL_INT: + case GL_UNSIGNED_INT: + return GL_BOOL; + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_UNSIGNED_INT_VEC2: + return GL_BOOL_VEC2; + case GL_FLOAT_VEC3: + case GL_INT_VEC3: + case GL_UNSIGNED_INT_VEC3: + return GL_BOOL_VEC3; + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + case GL_UNSIGNED_INT_VEC4: + return GL_BOOL_VEC4; + + default: + UNREACHABLE(); + return GL_NONE; + } +} + +inline int VariableRowCount(GLenum type) +{ + switch (type) + { + case GL_NONE: + return 0; + case GL_BOOL: + case GL_FLOAT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_BOOL_VEC2: + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_UNSIGNED_INT_VEC2: + case GL_BOOL_VEC3: + case GL_FLOAT_VEC3: + case GL_INT_VEC3: + case GL_UNSIGNED_INT_VEC3: + case GL_BOOL_VEC4: + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + case GL_UNSIGNED_INT_VEC4: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_2D_ARRAY: + case GL_SAMPLER_EXTERNAL_OES: + case GL_SAMPLER_2D_RECT_ANGLE: + case GL_SAMPLER_2D_MULTISAMPLE: + case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_SAMPLER_CUBE_MAP_ARRAY: + case GL_SAMPLER_BUFFER: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_2D_MULTISAMPLE: + case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_INT_SAMPLER_BUFFER: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_BUFFER: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: + case GL_IMAGE_2D: + case GL_INT_IMAGE_2D: + case GL_UNSIGNED_INT_IMAGE_2D: + case GL_IMAGE_2D_ARRAY: + case GL_INT_IMAGE_2D_ARRAY: + case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: + case GL_IMAGE_3D: + case GL_INT_IMAGE_3D: + case GL_UNSIGNED_INT_IMAGE_3D: + case GL_IMAGE_CUBE: + case GL_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_ATOMIC_COUNTER: + case GL_IMAGE_CUBE_MAP_ARRAY: + case GL_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_IMAGE_BUFFER: + case GL_INT_IMAGE_BUFFER: + case GL_UNSIGNED_INT_IMAGE_BUFFER: + case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: + return 1; + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT3x2: + case GL_FLOAT_MAT4x2: + return 2; + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT4x3: + return 3; + case GL_FLOAT_MAT4: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT3x4: + return 4; + default: + UNREACHABLE(); + } + + return 0; +} + +inline int VariableColumnCount(GLenum type) +{ + switch (type) + { + case GL_NONE: + return 0; + case GL_BOOL: + case GL_FLOAT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_2D_ARRAY: + case GL_SAMPLER_2D_MULTISAMPLE: + case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_SAMPLER_CUBE_MAP_ARRAY: + case GL_SAMPLER_BUFFER: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_2D_MULTISAMPLE: + case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_INT_SAMPLER_BUFFER: + case GL_SAMPLER_EXTERNAL_OES: + case GL_SAMPLER_2D_RECT_ANGLE: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_BUFFER: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: + case GL_IMAGE_2D: + case GL_INT_IMAGE_2D: + case GL_UNSIGNED_INT_IMAGE_2D: + case GL_IMAGE_3D: + case GL_INT_IMAGE_3D: + case GL_UNSIGNED_INT_IMAGE_3D: + case GL_IMAGE_2D_ARRAY: + case GL_INT_IMAGE_2D_ARRAY: + case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: + case GL_IMAGE_CUBE_MAP_ARRAY: + case GL_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_IMAGE_BUFFER: + case GL_INT_IMAGE_BUFFER: + case GL_UNSIGNED_INT_IMAGE_BUFFER: + case GL_IMAGE_CUBE: + case GL_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_ATOMIC_COUNTER: + case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: + return 1; + case GL_BOOL_VEC2: + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_UNSIGNED_INT_VEC2: + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT2x4: + return 2; + case GL_BOOL_VEC3: + case GL_FLOAT_VEC3: + case GL_INT_VEC3: + case GL_UNSIGNED_INT_VEC3: + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT3x2: + case GL_FLOAT_MAT3x4: + return 3; + case GL_BOOL_VEC4: + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + case GL_UNSIGNED_INT_VEC4: + case GL_FLOAT_MAT4: + case GL_FLOAT_MAT4x2: + case GL_FLOAT_MAT4x3: + return 4; + default: + UNREACHABLE(); + } + + return 0; +} + +inline bool IsSamplerType(GLenum type) +{ + switch (type) + { + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_2D_ARRAY: + case GL_SAMPLER_EXTERNAL_OES: + case GL_SAMPLER_2D_MULTISAMPLE: + case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_SAMPLER_CUBE_MAP_ARRAY: + case GL_SAMPLER_BUFFER: + case GL_SAMPLER_2D_RECT_ANGLE: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_2D_MULTISAMPLE: + case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_INT_SAMPLER_BUFFER: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_BUFFER: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: + case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: + return true; + } + + return false; +} + +inline bool IsSamplerCubeType(GLenum type) +{ + switch (type) + { + case GL_SAMPLER_CUBE: + case GL_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_SAMPLER_CUBE_SHADOW: + return true; + } + + return false; +} + +inline bool IsSamplerYUVType(GLenum type) +{ + switch (type) + { + case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: + return true; + + default: + return false; + } +} + +inline bool IsImageType(GLenum type) +{ + switch (type) + { + case GL_IMAGE_2D: + case GL_INT_IMAGE_2D: + case GL_UNSIGNED_INT_IMAGE_2D: + case GL_IMAGE_3D: + case GL_INT_IMAGE_3D: + case GL_UNSIGNED_INT_IMAGE_3D: + case GL_IMAGE_2D_ARRAY: + case GL_INT_IMAGE_2D_ARRAY: + case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: + case GL_IMAGE_CUBE_MAP_ARRAY: + case GL_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_IMAGE_BUFFER: + case GL_INT_IMAGE_BUFFER: + case GL_UNSIGNED_INT_IMAGE_BUFFER: + case GL_IMAGE_CUBE: + case GL_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_IMAGE_CUBE: + return true; + } + return false; +} + +inline bool IsImage2DType(GLenum type) +{ + switch (type) + { + case GL_IMAGE_2D: + case GL_INT_IMAGE_2D: + case GL_UNSIGNED_INT_IMAGE_2D: + return true; + case GL_IMAGE_3D: + case GL_INT_IMAGE_3D: + case GL_UNSIGNED_INT_IMAGE_3D: + case GL_IMAGE_2D_ARRAY: + case GL_INT_IMAGE_2D_ARRAY: + case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: + case GL_IMAGE_CUBE_MAP_ARRAY: + case GL_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_IMAGE_CUBE: + case GL_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_IMAGE_CUBE: + case GL_IMAGE_BUFFER: + case GL_INT_IMAGE_BUFFER: + case GL_UNSIGNED_INT_IMAGE_BUFFER: + return false; + default: + UNREACHABLE(); + return false; + } +} + +inline bool IsAtomicCounterType(GLenum type) +{ + return type == GL_UNSIGNED_INT_ATOMIC_COUNTER; +} + +inline bool IsOpaqueType(GLenum type) +{ + // ESSL 3.10 section 4.1.7 defines opaque types as: samplers, images and atomic counters. + return IsImageType(type) || IsSamplerType(type) || IsAtomicCounterType(type); +} + +inline bool IsMatrixType(GLenum type) +{ + return VariableRowCount(type) > 1; +} + +inline bool IsFloatScalarAndVectorType(GLenum type) +{ + switch (type) + { + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + return true; + default: + return false; + } +} + +inline bool IsFloatVectorType(GLenum type) +{ + switch (type) + { + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + return true; + default: + return false; + } +} + +inline GLenum TransposeMatrixType(GLenum type) +{ + if (!IsMatrixType(type)) + { + return type; + } + + switch (type) + { + case GL_FLOAT_MAT2: + return GL_FLOAT_MAT2; + case GL_FLOAT_MAT3: + return GL_FLOAT_MAT3; + case GL_FLOAT_MAT4: + return GL_FLOAT_MAT4; + case GL_FLOAT_MAT2x3: + return GL_FLOAT_MAT3x2; + case GL_FLOAT_MAT3x2: + return GL_FLOAT_MAT2x3; + case GL_FLOAT_MAT2x4: + return GL_FLOAT_MAT4x2; + case GL_FLOAT_MAT4x2: + return GL_FLOAT_MAT2x4; + case GL_FLOAT_MAT3x4: + return GL_FLOAT_MAT4x3; + case GL_FLOAT_MAT4x3: + return GL_FLOAT_MAT3x4; + default: + UNREACHABLE(); + return GL_NONE; + } +} + +inline int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix) +{ + ASSERT(IsMatrixType(type)); + return isRowMajorMatrix ? VariableRowCount(type) : VariableColumnCount(type); +} + +inline int MatrixComponentCount(GLenum type, bool isRowMajorMatrix) +{ + ASSERT(IsMatrixType(type)); + return isRowMajorMatrix ? VariableColumnCount(type) : VariableRowCount(type); +} + +inline int VariableRegisterCount(GLenum type) +{ + return IsMatrixType(type) ? VariableColumnCount(type) : 1; +} + +inline int VariableSortOrder(GLenum type) +{ + switch (type) + { + // 1. Arrays of mat4 and mat4 + // Non-square matrices of type matCxR consume the same space as a square + // matrix of type matN where N is the greater of C and R + case GL_FLOAT_MAT4: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT3x4: + case GL_FLOAT_MAT4x2: + case GL_FLOAT_MAT4x3: + return 0; + + // 2. Arrays of mat2 and mat2 (since they occupy full rows) + case GL_FLOAT_MAT2: + return 1; + + // 3. Arrays of vec4 and vec4 + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + case GL_BOOL_VEC4: + case GL_UNSIGNED_INT_VEC4: + return 2; + + // 4. Arrays of mat3 and mat3 + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT3x2: + return 3; + + // 5. Arrays of vec3 and vec3 + case GL_FLOAT_VEC3: + case GL_INT_VEC3: + case GL_BOOL_VEC3: + case GL_UNSIGNED_INT_VEC3: + return 4; + + // 6. Arrays of vec2 and vec2 + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_BOOL_VEC2: + case GL_UNSIGNED_INT_VEC2: + return 5; + + // 7. Single component types + case GL_FLOAT: + case GL_INT: + case GL_BOOL: + case GL_UNSIGNED_INT: + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_EXTERNAL_OES: + case GL_SAMPLER_2D_RECT_ANGLE: + case GL_SAMPLER_2D_ARRAY: + case GL_SAMPLER_2D_MULTISAMPLE: + case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_SAMPLER_3D: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_2D_MULTISAMPLE: + case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_SAMPLER_CUBE_SHADOW: + case GL_IMAGE_2D: + case GL_INT_IMAGE_2D: + case GL_UNSIGNED_INT_IMAGE_2D: + case GL_IMAGE_3D: + case GL_INT_IMAGE_3D: + case GL_UNSIGNED_INT_IMAGE_3D: + case GL_IMAGE_2D_ARRAY: + case GL_INT_IMAGE_2D_ARRAY: + case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: + case GL_IMAGE_CUBE: + case GL_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_ATOMIC_COUNTER: + case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: + return 6; + + default: + UNREACHABLE(); + return 0; + } +} + +inline bool IsBuiltInName(const char *name) +{ + return angle::BeginsWith(name, "gl_"); +} + +inline bool IsBuiltInName(const std::string &name) +{ + return IsBuiltInName(name.c_str()); +} + +inline GLuint GetPrimitiveRestartIndex(DrawElementsType indexType) +{ + switch (indexType) + { + case DrawElementsType::UnsignedByte: + return 0xFF; + case DrawElementsType::UnsignedShort: + return 0xFFFF; + case DrawElementsType::UnsignedInt: + return 0xFFFFFFFF; + default: + UNREACHABLE(); + return 0; + } +} + +inline bool IsTriangleMode(PrimitiveMode drawMode) +{ + switch (drawMode) + { + case PrimitiveMode::Triangles: + case PrimitiveMode::TriangleFan: + case PrimitiveMode::TriangleStrip: + return true; + case PrimitiveMode::Points: + case PrimitiveMode::Lines: + case PrimitiveMode::LineLoop: + case PrimitiveMode::LineStrip: + return false; + default: + UNREACHABLE(); + } + + return false; +} + +inline bool IsPolygonMode(PrimitiveMode mode) +{ + switch (mode) + { + case PrimitiveMode::Points: + case PrimitiveMode::Lines: + case PrimitiveMode::LineStrip: + case PrimitiveMode::LineLoop: + case PrimitiveMode::LinesAdjacency: + case PrimitiveMode::LineStripAdjacency: + return false; + default: + break; + } + + return true; +} + +inline bool IsLineMode(PrimitiveMode primitiveMode) +{ + return priv::gLineModes[primitiveMode]; +} + +inline bool IsIntegerFormat(GLenum unsizedFormat) +{ + switch (unsizedFormat) + { + case GL_RGBA_INTEGER: + case GL_RGB_INTEGER: + case GL_RG_INTEGER: + case GL_RED_INTEGER: + return true; + + default: + return false; + } +} + +inline unsigned int ArraySizeProduct(const std::vector &arraySizes) +{ + unsigned int arraySizeProduct = 1u; + for (unsigned int arraySize : arraySizes) + { + arraySizeProduct *= arraySize; + } + return arraySizeProduct; +} + +inline unsigned int InnerArraySizeProduct(const std::vector &arraySizes) +{ + unsigned int arraySizeProduct = 1u; + for (size_t index = 0; index + 1 < arraySizes.size(); ++index) + { + arraySizeProduct *= arraySizes[index]; + } + return arraySizeProduct; +} + +inline unsigned int OutermostArraySize(const std::vector &arraySizes) +{ + return arraySizes.empty() || arraySizes.back() == 0 ? 1 : arraySizes.back(); +} + +inline unsigned int ElementTypeSize(GLenum elementType) +{ + switch (elementType) + { + case GL_UNSIGNED_BYTE: + return sizeof(GLubyte); + case GL_UNSIGNED_SHORT: + return sizeof(GLushort); + case GL_UNSIGNED_INT: + return sizeof(GLuint); + default: + UNREACHABLE(); + return 0; + } +} + +inline bool IsMipmapFiltered(GLenum minFilterMode) +{ + switch (minFilterMode) + { + case GL_NEAREST: + case GL_LINEAR: + return false; + case GL_NEAREST_MIPMAP_NEAREST: + case GL_LINEAR_MIPMAP_NEAREST: + case GL_NEAREST_MIPMAP_LINEAR: + case GL_LINEAR_MIPMAP_LINEAR: + return true; + default: + UNREACHABLE(); + return false; + } +} + +inline PipelineType GetPipelineType(ShaderType type) +{ + switch (type) + { + case ShaderType::Vertex: + case ShaderType::Fragment: + case ShaderType::Geometry: + return PipelineType::GraphicsPipeline; + case ShaderType::Compute: + return PipelineType::ComputePipeline; + default: + UNREACHABLE(); + return PipelineType::GraphicsPipeline; + } +} + +inline ShaderType GetShaderTypeFromBitfield(size_t singleShaderType) +{ + switch (singleShaderType) + { + case GL_VERTEX_SHADER_BIT: + return ShaderType::Vertex; + case GL_FRAGMENT_SHADER_BIT: + return ShaderType::Fragment; + case GL_COMPUTE_SHADER_BIT: + return ShaderType::Compute; + case GL_GEOMETRY_SHADER_BIT: + return ShaderType::Geometry; + case GL_TESS_CONTROL_SHADER_BIT: + return ShaderType::TessControl; + case GL_TESS_EVALUATION_SHADER_BIT: + return ShaderType::TessEvaluation; + default: + return ShaderType::InvalidEnum; + } +} + +inline GLbitfield GetBitfieldFromShaderType(ShaderType shaderType) +{ + switch (shaderType) + { + case ShaderType::Vertex: + return GL_VERTEX_SHADER_BIT; + case ShaderType::Fragment: + return GL_FRAGMENT_SHADER_BIT; + case ShaderType::Compute: + return GL_COMPUTE_SHADER_BIT; + case ShaderType::Geometry: + return GL_GEOMETRY_SHADER_BIT; + case ShaderType::TessControl: + return GL_TESS_CONTROL_SHADER_BIT; + case ShaderType::TessEvaluation: + return GL_TESS_EVALUATION_SHADER_BIT; + default: + UNREACHABLE(); + return GL_ZERO; + } +} + +inline bool ShaderTypeSupportsTransformFeedback(ShaderType shaderType) +{ + switch (shaderType) + { + case ShaderType::Vertex: + case ShaderType::Geometry: + case ShaderType::TessEvaluation: + return true; + default: + return false; + } +} + +inline ShaderType GetLastPreFragmentStage(ShaderBitSet shaderTypes) +{ + shaderTypes.reset(ShaderType::Fragment); + shaderTypes.reset(ShaderType::Compute); + return shaderTypes.any() ? shaderTypes.last() : ShaderType::InvalidEnum; +} } // namespace gl diff --git a/src/common/vector_utils.h b/src/common/vector_utils.h index 19de2ddea39..286c125156c 100644 --- a/src/common/vector_utils.h +++ b/src/common/vector_utils.h @@ -40,18 +40,18 @@ class VectorBase using VectorN = Vector; // Constructors - VectorBase() = default; - explicit VectorBase(Type element); + constexpr VectorBase() = default; + explicit constexpr VectorBase(Type element); template - VectorBase(const VectorBase &other); + constexpr VectorBase(const VectorBase &other); template - VectorBase(const Arg1 &arg1, const Arg2 &arg2, const Args &...args); + constexpr VectorBase(const Arg1 &arg1, const Arg2 &arg2, const Args &...args); // Access the vector backing storage directly - const Type *data() const { return mData; } - Type *data() { return mData; } + constexpr const Type *data() const { return mData; } + constexpr Type *data() { return mData; } constexpr size_t size() const { return Dimension; } // Load or store the pointer from / to raw data @@ -59,31 +59,31 @@ class VectorBase static void Store(const VectorN &source, Type *destination); // Index the vector - Type &operator[](size_t i) { return ANGLE_UNSAFE_TODO(mData[i]); } - const Type &operator[](size_t i) const { return ANGLE_UNSAFE_TODO(mData[i]); } + constexpr Type &operator[](size_t i) { return ANGLE_UNSAFE_TODO(mData[i]); } + constexpr const Type &operator[](size_t i) const { return ANGLE_UNSAFE_TODO(mData[i]); } // Basic arithmetic operations - VectorN operator+() const; - VectorN operator-() const; - VectorN operator+(const VectorN &other) const; - VectorN operator-(const VectorN &other) const; - VectorN operator*(const VectorN &other) const; - VectorN operator/(const VectorN &other) const; - VectorN operator*(Type other) const; - VectorN operator/(Type other) const; - friend VectorN operator*(Type a, const VectorN &b) { return b * a; } + constexpr VectorN operator+() const; + constexpr VectorN operator-() const; + constexpr VectorN operator+(const VectorN &other) const; + constexpr VectorN operator-(const VectorN &other) const; + constexpr VectorN operator*(const VectorN &other) const; + constexpr VectorN operator/(const VectorN &other) const; + constexpr VectorN operator*(Type other) const; + constexpr VectorN operator/(Type other) const; + friend constexpr VectorN operator*(Type a, const VectorN &b) { return b * a; } // Compound arithmetic operations - VectorN &operator+=(const VectorN &other); - VectorN &operator-=(const VectorN &other); - VectorN &operator*=(const VectorN &other); - VectorN &operator/=(const VectorN &other); - VectorN &operator*=(Type other); - VectorN &operator/=(Type other); + constexpr VectorN &operator+=(const VectorN &other); + constexpr VectorN &operator-=(const VectorN &other); + constexpr VectorN &operator*=(const VectorN &other); + constexpr VectorN &operator/=(const VectorN &other); + constexpr VectorN &operator*=(Type other); + constexpr VectorN &operator/=(Type other); // Comparison operators - bool operator==(const VectorBase &other) const; - bool operator!=(const VectorBase &other) const; + constexpr bool operator==(const VectorBase &other) const; + constexpr bool operator!=(const VectorBase &other) const; // Other arithmetic operations Type length() const; @@ -93,18 +93,15 @@ class VectorBase protected: template - void initWithList(const Vector &arg1, const Args &...args); + constexpr void initWithList(const Vector &arg1, const Args &...args); - // Some old compilers consider this function an alternative for initWithList(Vector) - // when the variant above is more precise. Use SFINAE on the return value to hide - // this variant for non-arithmetic types. The return value is still void. template - typename std::enable_if::value>::type initWithList( + constexpr typename std::enable_if::value>::type initWithList( OtherType arg1, const Args &...args); template - void initWithList() const; + constexpr void initWithList() const; template friend class VectorBase; @@ -119,15 +116,17 @@ template class Vector<2, Type> : public VectorBase<2, Type> { public: - // Import the constructors defined in VectorBase using VectorBase<2, Type>::VectorBase; // Element shorthands Type &x() { return this->mData[0]; } Type &y() { return this->mData[1]; } - const Type &x() const { return this->mData[0]; } const Type &y() const { return this->mData[1]; } + + // Optimized length and dot for 2D + Type lengthSquared() const { return x() * x() + y() * y(); } + Type dot(const Vector<2, Type> &other) const { return x() * other.x() + y() * other.y(); } }; template @@ -137,7 +136,6 @@ template class Vector<3, Type> : public VectorBase<3, Type> { public: - // Import the constructors defined in VectorBase using VectorBase<3, Type>::VectorBase; // Additional operations @@ -147,10 +145,15 @@ class Vector<3, Type> : public VectorBase<3, Type> Type &x() { return this->mData[0]; } Type &y() { return this->mData[1]; } Type &z() { return this->mData[2]; } - const Type &x() const { return this->mData[0]; } const Type &y() const { return this->mData[1]; } const Type &z() const { return this->mData[2]; } + + // Optimized length and dot for 3D + Type lengthSquared() const { return x() * x() + y() * y() + z() * z(); } + Type dot(const Vector<3, Type> &other) const { + return x() * other.x() + y() * other.y() + z() * other.z(); + } }; template @@ -160,7 +163,6 @@ template class Vector<4, Type> : public VectorBase<4, Type> { public: - // Import the constructors defined in VectorBase using VectorBase<4, Type>::VectorBase; // Element shorthands @@ -168,11 +170,18 @@ class Vector<4, Type> : public VectorBase<4, Type> Type &y() { return this->mData[1]; } Type &z() { return this->mData[2]; } Type &w() { return this->mData[3]; } - const Type &x() const { return this->mData[0]; } const Type &y() const { return this->mData[1]; } const Type &z() const { return this->mData[2]; } const Type &w() const { return this->mData[3]; } + + // Optimized length and dot for 4D + Type lengthSquared() const { + return x() * x() + y() * y() + z() * z() + w() * w(); + } + Type dot(const Vector<4, Type> &other) const { + return x() * other.x() + y() * other.y() + z() * other.z() + w() * other.w(); + } }; template @@ -181,7 +190,7 @@ std::ostream &operator<<(std::ostream &ostream, const Vector<4, Type> &vector); // Implementation of constructors and misc operations template -VectorBase::VectorBase(Type element) +constexpr VectorBase::VectorBase(Type element) { for (size_t i = 0; i < Dimension; ++i) { @@ -191,7 +200,7 @@ VectorBase::VectorBase(Type element) template template -VectorBase::VectorBase(const VectorBase &other) +constexpr VectorBase::VectorBase(const VectorBase &other) { for (size_t i = 0; i < Dimension; ++i) { @@ -199,27 +208,19 @@ VectorBase::VectorBase(const VectorBase &othe } } -// Ideally we would like to have only two constructors: -// - a scalar constructor that takes Type as a parameter -// - a compound constructor -// However if we define the compound constructor for when it has a single arguments, then calling -// Vector2(0.0) will be ambiguous. To solve this we take advantage of there being a single compound -// constructor with a single argument, which is the copy constructor. We end up with three -// constructors: -// - the scalar constructor -// - the copy constructor -// - the compound constructor for two or more arguments, hence the arg1, and arg2 here. template template -VectorBase::VectorBase(const Arg1 &arg1, const Arg2 &arg2, const Args &...args) +constexpr VectorBase::VectorBase(const Arg1 &arg1, const Arg2 &arg2, + const Args &...args) { initWithList<0>(arg1, arg2, args...); } template template -void VectorBase::initWithList(const Vector &arg1, - const Args &...args) +constexpr void VectorBase::initWithList( + const Vector &arg1, + const Args &...args) { static_assert(CurrentIndex + OtherDimension <= Dimension, "Too much data in the vector constructor."); @@ -233,7 +234,7 @@ void VectorBase::initWithList(const Vector template -typename std::enable_if::value>::type +constexpr typename std::enable_if::value>::type VectorBase::initWithList(OtherType arg1, const Args &...args) { static_assert(CurrentIndex + 1 <= Dimension, "Too much data in the vector constructor."); @@ -243,7 +244,7 @@ VectorBase::initWithList(OtherType arg1, const Args &...args) template template -void VectorBase::initWithList() const +constexpr void VectorBase::initWithList() const { static_assert(CurrentIndex == Dimension, "Not enough data in the vector constructor."); } @@ -270,7 +271,7 @@ void VectorBase::Store(const Vector &source, T // Implementation of basic arithmetic operations template -Vector VectorBase::operator+() const +constexpr Vector VectorBase::operator+() const { Vector result; for (size_t i = 0; i < Dimension; ++i) @@ -281,7 +282,7 @@ Vector VectorBase::operator+() const } template -Vector VectorBase::operator-() const +constexpr Vector VectorBase::operator-() const { Vector result; for (size_t i = 0; i < Dimension; ++i) @@ -292,7 +293,7 @@ Vector VectorBase::operator-() const } template -Vector VectorBase::operator+( +constexpr Vector VectorBase::operator+( const Vector &other) const { Vector result; @@ -304,7 +305,7 @@ Vector VectorBase::operator+( } template -Vector VectorBase::operator-( +constexpr Vector VectorBase::operator-( const Vector &other) const { Vector result; @@ -316,7 +317,7 @@ Vector VectorBase::operator-( } template -Vector VectorBase::operator*( +constexpr Vector VectorBase::operator*( const Vector &other) const { Vector result; @@ -328,7 +329,7 @@ Vector VectorBase::operator*( } template -Vector VectorBase::operator/( +constexpr Vector VectorBase::operator/( const Vector &other) const { Vector result; @@ -340,7 +341,7 @@ Vector VectorBase::operator/( } template -Vector VectorBase::operator*(Type other) const +constexpr Vector VectorBase::operator*(Type other) const { Vector result; for (size_t i = 0; i < Dimension; ++i) @@ -351,7 +352,7 @@ Vector VectorBase::operator*(Type other) const } template -Vector VectorBase::operator/(Type other) const +constexpr Vector VectorBase::operator/(Type other) const { Vector result; for (size_t i = 0; i < Dimension; ++i) @@ -363,7 +364,7 @@ Vector VectorBase::operator/(Type other) const // Implementation of compound arithmetic operations template -Vector &VectorBase::operator+=( +constexpr Vector &VectorBase::operator+=( const Vector &other) { for (size_t i = 0; i < Dimension; ++i) @@ -374,7 +375,7 @@ Vector &VectorBase::operator+=( } template -Vector &VectorBase::operator-=( +constexpr Vector &VectorBase::operator-=( const Vector &other) { for (size_t i = 0; i < Dimension; ++i) @@ -385,7 +386,7 @@ Vector &VectorBase::operator-=( } template -Vector &VectorBase::operator*=( +constexpr Vector &VectorBase::operator*=( const Vector &other) { for (size_t i = 0; i < Dimension; ++i) @@ -396,7 +397,7 @@ Vector &VectorBase::operator*=( } template -Vector &VectorBase::operator/=( +constexpr Vector &VectorBase::operator/=( const Vector &other) { for (size_t i = 0; i < Dimension; ++i) @@ -407,7 +408,7 @@ Vector &VectorBase::operator/=( } template -Vector &VectorBase::operator*=(Type other) +constexpr Vector &VectorBase::operator*=(Type other) { for (size_t i = 0; i < Dimension; ++i) { @@ -417,7 +418,7 @@ Vector &VectorBase::operator*=(Type other) } template -Vector &VectorBase::operator/=(Type other) +constexpr Vector &VectorBase::operator/=(Type other) { for (size_t i = 0; i < Dimension; ++i) { @@ -428,7 +429,8 @@ Vector &VectorBase::operator/=(Type other) // Implementation of comparison operators template -bool VectorBase::operator==(const VectorBase &other) const +constexpr bool VectorBase::operator==( + const VectorBase &other) const { for (size_t i = 0; i < Dimension; ++i) { @@ -441,7 +443,8 @@ bool VectorBase::operator==(const VectorBase & } template -bool VectorBase::operator!=(const VectorBase &other) const +constexpr bool VectorBase::operator!=( + const VectorBase &other) const { return !(*this == other); } @@ -506,7 +509,8 @@ std::ostream &operator<<(std::ostream &ostream, const Vector<2, Type> &vector) template Vector<3, Type> Vector<3, Type>::cross(const Vector<3, Type> &other) const { - return Vector<3, Type>(y() * other.z() - z() * other.y(), z() * other.x() - x() * other.z(), + return Vector<3, Type>(y() * other.z() - z() * other.y(), + z() * other.x() - x() * other.z(), x() * other.y() - y() * other.x()); } @@ -524,4 +528,4 @@ std::ostream &operator<<(std::ostream &ostream, const Vector<4, Type> &vector) } // namespace angle -#endif // COMMON_VECTOR_UTILS_H_ +#endif // COMMON_VECTOR_UTILS_H_ \ No newline at end of file diff --git a/src/image_util/copyimage.cpp b/src/image_util/copyimage.cpp index 52914d7b073..40fc4d40890 100644 --- a/src/image_util/copyimage.cpp +++ b/src/image_util/copyimage.cpp @@ -9,6 +9,10 @@ #include "image_util/copyimage.h" #include "common/unsafe_buffers.h" +#if defined(__ARM_NEON__) || defined(__ARM_NEON) +# include +#endif + namespace angle { @@ -28,6 +32,41 @@ void CopyBGRA8ToRGBA8Fast(const uint8_t *source, int destWidth, int destHeight) { +#if defined(__ARM_NEON__) || defined(__ARM_NEON) + // NEON can process 4 pixels per iteration using a lookup table. + // For correctness on little-endian, the mask bytes are arranged as {B,G,R,A} -> {R,G,B,A}. + static const uint8_t shuffleMaskData[16] = { + 2, 1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15 + }; + uint8x16_t shuffleMask = vld1q_u8(shuffleMaskData); + + // Only use SIMD if width is large enough and pitches are 4-byte aligned. + if (destWidth >= 4 && (srcYAxisPitch % 4 == 0) && (destYAxisPitch % 4 == 0)) + { + const int srcStride = srcYAxisPitch / 4; + const int dstStride = destYAxisPitch / 4; + for (int y = 0; y < destHeight; ++y) + { + const uint32_t *src32 = reinterpret_cast(source + y * srcYAxisPitch); + uint32_t *dst32 = reinterpret_cast(dest + y * destYAxisPitch); + int x = 0; + for (; x + 3 < destWidth; x += 4) + { + uint8x16_t in = vld1q_u8(reinterpret_cast(&src32[x])); + uint8x16_t out = vqtbl1q_u8(in, shuffleMask); + vst1q_u8(reinterpret_cast(&dst32[x]), out); + } + // Handle remaining pixels with scalar. + for (; x < destWidth; ++x) + { + dst32[x] = SwizzleBGRAToRGBA(src32[x]); + } + } + return; + } +#endif + + // Fallback scalar loop. for (int y = 0; y < destHeight; ++y) { const uint32_t *src32 = @@ -134,4 +173,4 @@ void CopyRGBA8ToRGBA8(const uint8_t *source, } } -} // namespace angle +} // namespace angle \ No newline at end of file diff --git a/src/image_util/loadimage.cpp b/src/image_util/loadimage.cpp index c8c4f238ec1..3beca28ab1c 100644 --- a/src/image_util/loadimage.cpp +++ b/src/image_util/loadimage.cpp @@ -28,6 +28,11 @@ # endif #endif +// ARM NEON support +#if defined(__ARM_NEON__) || defined(__ARM_NEON) +# include +#endif + #if defined(ANGLE_LOADIMAGE_USE_SSE) inline bool supportsSSE2() { @@ -72,6 +77,40 @@ void LoadA8ToRGBA8(const ImageLoadContext &context, size_t outputRowPitch, size_t outputDepthPitch) { +#if defined(__ARM_NEON__) || defined(__ARM_NEON) + // NEON implementation: process 8 pixels per iteration + { + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = + priv::OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = priv::OffsetDataPointer(output, y, z, outputRowPitch, + outputDepthPitch); + + size_t x = 0; + for (; x + 7 < width; x += 8) + { + uint8x8_t src = vld1_u8(&source[x]); + uint16x8_t tmp16 = vmovl_u8(src); + uint32x4_t lo = vmovl_u16(vget_low_u16(tmp16)); + uint32x4_t hi = vmovl_u16(vget_high_u16(tmp16)); + lo = vshlq_n_u32(lo, 24); + hi = vshlq_n_u32(hi, 24); + vst1q_u32(&dest[x], lo); + vst1q_u32(&dest[x + 4], hi); + } + for (; x < width; x++) + { + dest[x] = static_cast(source[x]) << 24; + } + } + } + return; + } +#endif + #if defined(ANGLE_LOADIMAGE_USE_SSE) if (supportsSSE2()) { @@ -721,6 +760,42 @@ void LoadRGBA8ToBGRA8(const ImageLoadContext &context, size_t outputRowPitch, size_t outputDepthPitch) { +#if defined(__ARM_NEON__) || defined(__ARM_NEON) + // NEON implementation using byte permutation (4 pixels at a time) + { + static const uint8_t shuffleMaskData[16] = { + 2, 1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15 + }; + uint8x16_t shuffleMask = vld1q_u8(shuffleMaskData); + + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint32_t *source = + priv::OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = priv::OffsetDataPointer(output, y, z, outputRowPitch, + outputDepthPitch); + + size_t x = 0; + for (; x + 3 < width; x += 4) + { + uint8x16_t in = vld1q_u8(reinterpret_cast(&source[x])); + uint8x16_t out = vqtbl1q_u8(in, shuffleMask); + vst1q_u8(reinterpret_cast(&dest[x]), out); + } + // Remainder + for (; x < width; x++) + { + uint32_t rgba = source[x]; + dest[x] = (ANGLE_ROTL(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); + } + } + } + return; + } +#endif + #if defined(ANGLE_LOADIMAGE_USE_SSE) if (supportsSSE2()) { @@ -2081,4 +2156,4 @@ void LoadYuvToNative(const ImageLoadContext &context, memcpy(output, input, inputDepthPitch); } -} // namespace angle +} // namespace angle \ No newline at end of file diff --git a/src/libANGLE/renderer/vulkan/BufferVk.cpp b/src/libANGLE/renderer/vulkan/BufferVk.cpp index ebfc7eb0e98..5225fe4f505 100644 --- a/src/libANGLE/renderer/vulkan/BufferVk.cpp +++ b/src/libANGLE/renderer/vulkan/BufferVk.cpp @@ -134,12 +134,17 @@ VkMemoryPropertyFlags GetStorageMemoryType(vk::Renderer *renderer, return hasMapAccess ? kHostCachedFlags : kDeviceLocalFlags; } +// Performance tuning constants for buffer update strategies +constexpr size_t kCpuCopyBufferSizeThreshold = 32 * 1024; +constexpr size_t kPreferDuplicateOverRenderPassBreakMaxBufferSize = 4 * 1024; // Increased from 1KB +constexpr VkDeviceSize kMaxBufferSizeForGhosting = 64 * 1024; + bool ShouldAllocateNewMemoryForUpdate(ContextVk *contextVk, size_t subDataSize, size_t bufferSize) { - // A sub-data update with size > 50% of buffer size meets the threshold to acquire a new - // BufferHelper from the pool. - size_t halfBufferSize = bufferSize / 2; - if (subDataSize > halfBufferSize) + // A sub-data update with size > 75% of buffer size meets the threshold to acquire a new + // BufferHelper from the pool. Reduced frequency to avoid unnecessary allocations. + size_t thresholdSize = bufferSize * 3 / 4; // was bufferSize / 2 + if (subDataSize > thresholdSize) { return true; } @@ -152,7 +157,6 @@ bool ShouldAllocateNewMemoryForUpdate(ContextVk *contextVk, size_t subDataSize, // If the buffer is small enough, the cost of barrier associated with the GPU copy likely // exceeds the overhead with the CPU copy. Duplicating the buffer allows the CPU to write to // the buffer immediately, thus avoiding the barrier that prevents parallel operation. - constexpr size_t kCpuCopyBufferSizeThreshold = 32 * 1024; if (bufferSize < kCpuCopyBufferSizeThreshold) { return true; @@ -160,9 +164,9 @@ bool ShouldAllocateNewMemoryForUpdate(ContextVk *contextVk, size_t subDataSize, // To use CPU for the sub-data update in larger buffers, the update should be sizable enough // compared to the whole buffer size. The threshold is chosen based on perf data collected - // from Pixel devices. At 1/8 of buffer size, the CPU overhead associated with extra data - // copy weighs less than serialization caused by barriers. - size_t subDataThreshold = bufferSize / 8; + // from Pixel devices. At 1/4 of buffer size (was 1/8), the CPU overhead associated with + // extra data copy weighs less than serialization caused by barriers. + size_t subDataThreshold = bufferSize / 4; // was bufferSize / 8 if (subDataSize > subDataThreshold) { return true; @@ -214,9 +218,8 @@ bool ShouldAvoidRenderPassBreakOnUpdate(ContextVk *contextVk, size_t bufferSize) { // Only avoid breaking the render pass if the buffer is not so big such that duplicating it - // would outweight the cost of breaking the render pass. A value of 1KB is temporary chosen as - // a heuristic, and can be adjusted when such a situation is encountered. - constexpr size_t kPreferDuplicateOverRenderPassBreakMaxBufferSize = 1024; + // would outweight the cost of breaking the render pass. The threshold is increased to reduce + // allocations. if (!contextVk->getFeatures().preferCPUForBufferSubData.enabled || bufferSize > kPreferDuplicateOverRenderPassBreakMaxBufferSize) { @@ -884,6 +887,14 @@ angle::Result BufferVk::mapRangeImpl(ContextVk *contextVk, if (renderer->hasResourceUseFinished(mBuffer.getWriteResourceUse())) { + // If the buffer is small, waiting may be cheaper than allocating a new buffer. + if (static_cast(mState.getSize()) <= kMaxBufferSizeForGhosting) + { + ANGLE_TRY(mBuffer.waitForIdle(contextVk, + "GPU stall due to mapping small buffer in use by the GPU", + QueueSubmitReason::BufferInUseWhenSynchronizedMap)); + return mapHostVisibleBuffer(contextVk, offset, access, mapPtrBytes); + } // This will keep the new buffer mapped and update mapPtr, so return immediately. return ghostMappedBuffer(contextVk, offset, length, access, mapPtr, feedback); } diff --git a/src/libANGLE/renderer/vulkan/CommandQueue.cpp b/src/libANGLE/renderer/vulkan/CommandQueue.cpp index 6175f004629..897dd4cc7f8 100644 --- a/src/libANGLE/renderer/vulkan/CommandQueue.cpp +++ b/src/libANGLE/renderer/vulkan/CommandQueue.cpp @@ -21,9 +21,8 @@ namespace vk namespace { constexpr bool kOutputVmaStatsString = false; -// When suballocation garbages is more than this, we may wait for GPU to finish and free up some -// memory for allocation. -constexpr VkDeviceSize kMaxBufferSuballocationGarbageSize = 64 * 1024 * 1024; +// Optimize: Increase garbage size threshold to reduce cleaning frequency. +constexpr VkDeviceSize kMaxBufferSuballocationGarbageSize = 128 * 1024 * 1024; // was 64 MiB void InitializeSubmitInfo(VkSubmitInfo *submitInfo, const PrimaryCommandBuffer &commandBuffer, @@ -698,7 +697,8 @@ angle::Result CommandQueue::postSubmitCheck(ErrorContext *context) // destroyed. This is important to keep peak memory usage at check when game launched and a // lot of staging buffers used for textures upload and then gets released. But if there is // only one command buffer in flight, we do not wait here to ensure we keep GPU busy. - constexpr size_t kMinInFlightBatchesToKeep = 1; + // Optimize: Increase min batches to keep to 2 to reduce blocking. + constexpr size_t kMinInFlightBatchesToKeep = 2; // was 1 bool anyGarbageCleaned = false; ANGLE_TRY(cleanupSomeGarbage(context, kMinInFlightBatchesToKeep, &anyGarbageCleaned)); if (!anyGarbageCleaned) @@ -993,6 +993,7 @@ angle::Result CommandQueue::queueSubmitLocked(ErrorContext *context, { VkFence externalFenceHandle = batch.getExternalFence()->getHandle(); ASSERT(externalFenceHandle != VK_NULL_HANDLE); + // In case of device lost, propagate the error via ANGLE_VK_TRY. ANGLE_VK_TRY(context, VK_CALL(vkQueueSubmit, queue, 1, &submitInfo, externalFenceHandle)); mPerfCounters.vkQueueSubmitCallsTotal.fetch_add(1, std::memory_order_relaxed); @@ -1133,6 +1134,7 @@ angle::Result CommandQueue::finishOneCommandBatch(ErrorContext *context, if (batch.hasFence()) { VkResult status = batch.waitFenceUnlocked(context->getDevice(), timeout, lock); + // Propagate device lost errors. ANGLE_VK_TRY(context, status); } @@ -1350,4 +1352,4 @@ uint32_t QueueFamily::FindIndex(const std::vector &que } } // namespace vk -} // namespace rx +} // namespace rx \ No newline at end of file diff --git a/src/libANGLE/renderer/vulkan/CommandQueue.h b/src/libANGLE/renderer/vulkan/CommandQueue.h index 0bec8214a46..cfebcb04b79 100644 --- a/src/libANGLE/renderer/vulkan/CommandQueue.h +++ b/src/libANGLE/renderer/vulkan/CommandQueue.h @@ -30,8 +30,9 @@ namespace vk class ExternalFence; using SharedExternalFence = std::shared_ptr; -constexpr size_t kInFlightCommandsLimit = 50u; -constexpr size_t kMaxFinishedCommandsLimit = 64u; +// Optimize: Increase limits to reduce blocking under heavy load. +constexpr size_t kInFlightCommandsLimit = 100u; // was 50 +constexpr size_t kMaxFinishedCommandsLimit = 128u; // was 64 static_assert(kInFlightCommandsLimit <= kMaxFinishedCommandsLimit); struct CommandQueuePerfCounters @@ -657,4 +658,4 @@ class [[nodiscard]] ScopedPrimaryCommandBuffer final } // namespace rx -#endif // LIBANGLE_RENDERER_VULKAN_COMMAND_QUEUE_H_ +#endif // LIBANGLE_RENDERER_VULKAN_COMMAND_Queue_H_ \ No newline at end of file diff --git a/src/libANGLE/renderer/vulkan/SyncVk.cpp b/src/libANGLE/renderer/vulkan/SyncVk.cpp index a204f258864..080000d257a 100644 --- a/src/libANGLE/renderer/vulkan/SyncVk.cpp +++ b/src/libANGLE/renderer/vulkan/SyncVk.cpp @@ -731,4 +731,4 @@ egl::Error EGLSyncVk::dupNativeFenceFD(const egl::Display *display, EGLint *fdOu EGL_BAD_PARAMETER); } -} // namespace rx +} // namespace rx \ No newline at end of file diff --git a/src/libANGLE/renderer/vulkan/SyncVk.h b/src/libANGLE/renderer/vulkan/SyncVk.h index 6305ade1a0d..04b6f8e6a38 100644 --- a/src/libANGLE/renderer/vulkan/SyncVk.h +++ b/src/libANGLE/renderer/vulkan/SyncVk.h @@ -52,7 +52,8 @@ class ExternalFence final : angle::NonCopyable }; using SharedExternalFence = std::shared_ptr; -using MapVkResultToApiType = std::function; +// Use function pointer instead of std::function to reduce overhead. +using MapVkResultToApiType = void(*)(VkResult, angle::Result, void *); class SyncHelperInterface : angle::NonCopyable { @@ -208,4 +209,4 @@ class EGLSyncVk final : public EGLSyncImpl }; } // namespace rx -#endif // LIBANGLE_RENDERER_VULKAN_FENCESYNCVK_H_ +#endif // LIBANGLE_RENDERER_VULKAN_FENCESYNCVK_H_ \ No newline at end of file diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.cpp b/src/libANGLE/renderer/vulkan/vk_helpers.cpp index 10a76d0ee60..1cf5518716c 100644 --- a/src/libANGLE/renderer/vulkan/vk_helpers.cpp +++ b/src/libANGLE/renderer/vulkan/vk_helpers.cpp @@ -13402,6 +13402,20 @@ angle::Result BufferViewHelper::getView(ErrorContext *context, const GLuint pixelBytes = bufferFormat.pixelBytes; VkDeviceSize size = mSize - mSize % pixelBytes; + const VkPhysicalDeviceLimits &limits = renderer->getPhysicalDeviceProperties().limits; + const VkDeviceSize maxTexelBufferElements = limits.maxTexelBufferElements; + const VkDeviceSize maxRangeBytes = maxTexelBufferElements * pixelBytes; + + if (size > maxRangeBytes) { + ANGLE_VK_PERF_WARNING(context, GL_DEBUG_SEVERITY_HIGH, + "BufferView range (%llu) exceeds maxTexelBufferElements (%llu), " + "truncating to %llu bytes", + static_cast(size), + static_cast(maxRangeBytes), + static_cast(maxRangeBytes)); + size = maxRangeBytes - (maxRangeBytes % pixelBytes); + } + VkBufferViewCreateInfo viewCreateInfo = {}; viewCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO; viewCreateInfo.buffer = buffer.getBuffer().getHandle(); diff --git a/src/libANGLE/renderer/vulkan/vk_renderer.cpp b/src/libANGLE/renderer/vulkan/vk_renderer.cpp index 353d53b606c..4b33128b84b 100644 --- a/src/libANGLE/renderer/vulkan/vk_renderer.cpp +++ b/src/libANGLE/renderer/vulkan/vk_renderer.cpp @@ -6166,9 +6166,19 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, // The number of minimum write commands in the command buffer to trigger one submission of // pending commands at draw call time - if (isARMProprietary) + if (isARMProprietary && !std::getenv("ANGLE_NOT_EARLYSUBMIT")) + { + mMinRPWriteCommandCountToEarlySubmit = 96; + } + + const char *forceEarlySubmitEnv = std::getenv("ANGLE_FORCE_MINEARLYSUBMIT"); + if (forceEarlySubmitEnv) { - mMinRPWriteCommandCountToEarlySubmit = 128; + int val = std::atoi(forceEarlySubmitEnv); + if (val > 0) + { + mMinRPWriteCommandCountToEarlySubmit = static_cast(val); + } } // In order to support immutable samplers tied to external formats, we need to overallocate From 5514c3622bf1e6db4d2850f8e9f89bade378584f Mon Sep 17 00:00:00 2001 From: aaaapai Date: Wed, 26 Aug 2026 18:22:31 +0800 Subject: [PATCH 2/6] Fix up --- src/libGLESv2/entry_points_gles_2_0_autogen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libGLESv2/entry_points_gles_2_0_autogen.cpp b/src/libGLESv2/entry_points_gles_2_0_autogen.cpp index dc9521daac3..e4c919a77b9 100644 --- a/src/libGLESv2/entry_points_gles_2_0_autogen.cpp +++ b/src/libGLESv2/entry_points_gles_2_0_autogen.cpp @@ -4973,7 +4973,7 @@ void GL_APIENTRY GL_TexImage2D(GLenum target, target = GL_TEXTURE_2D; } - if (internalFormat == 0x2A10) { + if (internalformat == 0x2A10) { internalformat = GL_RGB8; } From 604edd5a75aa91ff0d0fdc7298c5f659fe775611 Mon Sep 17 00:00:00 2001 From: aaaapai Date: Wed, 26 Aug 2026 18:42:22 +0800 Subject: [PATCH 3/6] Fix up --- src/libANGLE/validationES.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp index dacc95d2aef..25123b14355 100644 --- a/src/libANGLE/validationES.cpp +++ b/src/libANGLE/validationES.cpp @@ -30,6 +30,8 @@ #include "common/mathutil.h" #include "common/utilities.h" +#include "libANGLE/renderer/gl/functionsgl_enums.h" + using namespace angle; namespace gl From cf80fc12d77a2618838259ea71e534ea258f6b75 Mon Sep 17 00:00:00 2001 From: aaaapai Date: Wed, 26 Aug 2026 18:47:26 +0800 Subject: [PATCH 4/6] Fix up .... --- src/common/utilities.cpp | 931 ++++++++++++++++++++++++++++++++++- src/common/utilities.h | 1012 ++------------------------------------ 2 files changed, 978 insertions(+), 965 deletions(-) diff --git a/src/common/utilities.cpp b/src/common/utilities.cpp index bbdf0f8f2fc..465928cda81 100644 --- a/src/common/utilities.cpp +++ b/src/common/utilities.cpp @@ -71,8 +71,605 @@ gl::IndexRange ComputeTypedIndexRange(const IndexType *indices, namespace gl { -// 这些函数已移至头文件并标记为 inline,此处不再重复定义。 -// 保留以下非内联函数: +int VariableComponentCount(GLenum type) +{ + return VariableRowCount(type) * VariableColumnCount(type); +} + +GLenum VariableComponentType(GLenum type) +{ + switch (type) + { + case GL_BOOL: + case GL_BOOL_VEC2: + case GL_BOOL_VEC3: + case GL_BOOL_VEC4: + return GL_BOOL; + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT4: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT3x2: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT4x2: + case GL_FLOAT_MAT3x4: + case GL_FLOAT_MAT4x3: + return GL_FLOAT; + case GL_INT: + case GL_SAMPLER_2D: + case GL_SAMPLER_2D_RECT_ANGLE: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_CUBE_MAP_ARRAY: + case GL_SAMPLER_2D_ARRAY: + case GL_SAMPLER_EXTERNAL_OES: + case GL_SAMPLER_2D_MULTISAMPLE: + case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_INT_SAMPLER_BUFFER: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_2D_MULTISAMPLE: + case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_BUFFER: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_INT_VEC2: + case GL_INT_VEC3: + case GL_INT_VEC4: + case GL_IMAGE_2D: + case GL_INT_IMAGE_2D: + case GL_UNSIGNED_INT_IMAGE_2D: + case GL_IMAGE_3D: + case GL_INT_IMAGE_3D: + case GL_UNSIGNED_INT_IMAGE_3D: + case GL_IMAGE_2D_ARRAY: + case GL_INT_IMAGE_2D_ARRAY: + case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: + case GL_IMAGE_CUBE: + case GL_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_IMAGE_CUBE: + case GL_IMAGE_CUBE_MAP_ARRAY: + case GL_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_IMAGE_BUFFER: + case GL_INT_IMAGE_BUFFER: + case GL_UNSIGNED_INT_SAMPLER_BUFFER: + case GL_UNSIGNED_INT_IMAGE_BUFFER: + case GL_UNSIGNED_INT_ATOMIC_COUNTER: + case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: + return GL_INT; + case GL_UNSIGNED_INT: + case GL_UNSIGNED_INT_VEC2: + case GL_UNSIGNED_INT_VEC3: + case GL_UNSIGNED_INT_VEC4: + return GL_UNSIGNED_INT; + default: + UNREACHABLE(); + } + + return GL_NONE; +} + +size_t VariableComponentSize(GLenum type) +{ + switch (type) + { + case GL_BOOL: + return sizeof(GLint); + case GL_FLOAT: + return sizeof(GLfloat); + case GL_INT: + return sizeof(GLint); + case GL_UNSIGNED_INT: + return sizeof(GLuint); + default: + UNREACHABLE(); + } + + return 0; +} + +size_t VariableInternalSize(GLenum type) +{ + // Expanded to 4-element vectors + return VariableComponentSize(VariableComponentType(type)) * VariableRowCount(type) * 4; +} + +size_t VariableExternalSize(GLenum type) +{ + return VariableComponentSize(VariableComponentType(type)) * VariableComponentCount(type); +} + +std::string GetGLSLTypeString(GLenum type) +{ + switch (type) + { + case GL_BOOL: + return "bool"; + case GL_INT: + return "int"; + case GL_UNSIGNED_INT: + return "uint"; + case GL_FLOAT: + return "float"; + case GL_BOOL_VEC2: + return "bvec2"; + case GL_BOOL_VEC3: + return "bvec3"; + case GL_BOOL_VEC4: + return "bvec4"; + case GL_INT_VEC2: + return "ivec2"; + case GL_INT_VEC3: + return "ivec3"; + case GL_INT_VEC4: + return "ivec4"; + case GL_FLOAT_VEC2: + return "vec2"; + case GL_FLOAT_VEC3: + return "vec3"; + case GL_FLOAT_VEC4: + return "vec4"; + case GL_UNSIGNED_INT_VEC2: + return "uvec2"; + case GL_UNSIGNED_INT_VEC3: + return "uvec3"; + case GL_UNSIGNED_INT_VEC4: + return "uvec4"; + case GL_FLOAT_MAT2: + return "mat2"; + case GL_FLOAT_MAT3: + return "mat3"; + case GL_FLOAT_MAT4: + return "mat4"; + default: + UNREACHABLE(); + return ""; + } +} + +GLenum VariableBoolVectorType(GLenum type) +{ + switch (type) + { + case GL_FLOAT: + case GL_INT: + case GL_UNSIGNED_INT: + return GL_BOOL; + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_UNSIGNED_INT_VEC2: + return GL_BOOL_VEC2; + case GL_FLOAT_VEC3: + case GL_INT_VEC3: + case GL_UNSIGNED_INT_VEC3: + return GL_BOOL_VEC3; + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + case GL_UNSIGNED_INT_VEC4: + return GL_BOOL_VEC4; + + default: + UNREACHABLE(); + return GL_NONE; + } +} + +int VariableRowCount(GLenum type) +{ + switch (type) + { + case GL_NONE: + return 0; + case GL_BOOL: + case GL_FLOAT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_BOOL_VEC2: + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_UNSIGNED_INT_VEC2: + case GL_BOOL_VEC3: + case GL_FLOAT_VEC3: + case GL_INT_VEC3: + case GL_UNSIGNED_INT_VEC3: + case GL_BOOL_VEC4: + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + case GL_UNSIGNED_INT_VEC4: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_2D_ARRAY: + case GL_SAMPLER_EXTERNAL_OES: + case GL_SAMPLER_2D_RECT_ANGLE: + case GL_SAMPLER_2D_MULTISAMPLE: + case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_SAMPLER_CUBE_MAP_ARRAY: + case GL_SAMPLER_BUFFER: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_2D_MULTISAMPLE: + case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_INT_SAMPLER_BUFFER: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_BUFFER: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: + case GL_IMAGE_2D: + case GL_INT_IMAGE_2D: + case GL_UNSIGNED_INT_IMAGE_2D: + case GL_IMAGE_2D_ARRAY: + case GL_INT_IMAGE_2D_ARRAY: + case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: + case GL_IMAGE_3D: + case GL_INT_IMAGE_3D: + case GL_UNSIGNED_INT_IMAGE_3D: + case GL_IMAGE_CUBE: + case GL_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_ATOMIC_COUNTER: + case GL_IMAGE_CUBE_MAP_ARRAY: + case GL_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_IMAGE_BUFFER: + case GL_INT_IMAGE_BUFFER: + case GL_UNSIGNED_INT_IMAGE_BUFFER: + case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: + return 1; + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT3x2: + case GL_FLOAT_MAT4x2: + return 2; + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT4x3: + return 3; + case GL_FLOAT_MAT4: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT3x4: + return 4; + default: + UNREACHABLE(); + } + + return 0; +} + +int VariableColumnCount(GLenum type) +{ + switch (type) + { + case GL_NONE: + return 0; + case GL_BOOL: + case GL_FLOAT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_2D_ARRAY: + case GL_SAMPLER_2D_MULTISAMPLE: + case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_SAMPLER_CUBE_MAP_ARRAY: + case GL_SAMPLER_BUFFER: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_2D_MULTISAMPLE: + case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_INT_SAMPLER_BUFFER: + case GL_SAMPLER_EXTERNAL_OES: + case GL_SAMPLER_2D_RECT_ANGLE: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_BUFFER: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: + case GL_IMAGE_2D: + case GL_INT_IMAGE_2D: + case GL_UNSIGNED_INT_IMAGE_2D: + case GL_IMAGE_3D: + case GL_INT_IMAGE_3D: + case GL_UNSIGNED_INT_IMAGE_3D: + case GL_IMAGE_2D_ARRAY: + case GL_INT_IMAGE_2D_ARRAY: + case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: + case GL_IMAGE_CUBE_MAP_ARRAY: + case GL_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_IMAGE_BUFFER: + case GL_INT_IMAGE_BUFFER: + case GL_UNSIGNED_INT_IMAGE_BUFFER: + case GL_IMAGE_CUBE: + case GL_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_ATOMIC_COUNTER: + case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: + return 1; + case GL_BOOL_VEC2: + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_UNSIGNED_INT_VEC2: + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT2x4: + return 2; + case GL_BOOL_VEC3: + case GL_FLOAT_VEC3: + case GL_INT_VEC3: + case GL_UNSIGNED_INT_VEC3: + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT3x2: + case GL_FLOAT_MAT3x4: + return 3; + case GL_BOOL_VEC4: + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + case GL_UNSIGNED_INT_VEC4: + case GL_FLOAT_MAT4: + case GL_FLOAT_MAT4x2: + case GL_FLOAT_MAT4x3: + return 4; + default: + UNREACHABLE(); + } + + return 0; +} + +bool IsSamplerType(GLenum type) +{ + switch (type) + { + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_2D_ARRAY: + case GL_SAMPLER_EXTERNAL_OES: + case GL_SAMPLER_2D_MULTISAMPLE: + case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_SAMPLER_CUBE_MAP_ARRAY: + case GL_SAMPLER_BUFFER: + case GL_SAMPLER_2D_RECT_ANGLE: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_2D_MULTISAMPLE: + case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_INT_SAMPLER_BUFFER: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_BUFFER: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: + case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: + return true; + } + + return false; +} + +bool IsSamplerCubeType(GLenum type) +{ + switch (type) + { + case GL_SAMPLER_CUBE: + case GL_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_SAMPLER_CUBE_SHADOW: + return true; + } + + return false; +} + +bool IsSamplerYUVType(GLenum type) +{ + switch (type) + { + case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: + return true; + + default: + return false; + } +} + +bool IsImageType(GLenum type) +{ + switch (type) + { + case GL_IMAGE_2D: + case GL_INT_IMAGE_2D: + case GL_UNSIGNED_INT_IMAGE_2D: + case GL_IMAGE_3D: + case GL_INT_IMAGE_3D: + case GL_UNSIGNED_INT_IMAGE_3D: + case GL_IMAGE_2D_ARRAY: + case GL_INT_IMAGE_2D_ARRAY: + case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: + case GL_IMAGE_CUBE_MAP_ARRAY: + case GL_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_IMAGE_BUFFER: + case GL_INT_IMAGE_BUFFER: + case GL_UNSIGNED_INT_IMAGE_BUFFER: + case GL_IMAGE_CUBE: + case GL_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_IMAGE_CUBE: + return true; + } + return false; +} + +bool IsImage2DType(GLenum type) +{ + switch (type) + { + case GL_IMAGE_2D: + case GL_INT_IMAGE_2D: + case GL_UNSIGNED_INT_IMAGE_2D: + return true; + case GL_IMAGE_3D: + case GL_INT_IMAGE_3D: + case GL_UNSIGNED_INT_IMAGE_3D: + case GL_IMAGE_2D_ARRAY: + case GL_INT_IMAGE_2D_ARRAY: + case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: + case GL_IMAGE_CUBE_MAP_ARRAY: + case GL_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_IMAGE_CUBE: + case GL_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_IMAGE_CUBE: + case GL_IMAGE_BUFFER: + case GL_INT_IMAGE_BUFFER: + case GL_UNSIGNED_INT_IMAGE_BUFFER: + return false; + default: + UNREACHABLE(); + return false; + } +} + +bool IsAtomicCounterType(GLenum type) +{ + return type == GL_UNSIGNED_INT_ATOMIC_COUNTER; +} + +bool IsOpaqueType(GLenum type) +{ + // ESSL 3.10 section 4.1.7 defines opaque types as: samplers, images and atomic counters. + return IsImageType(type) || IsSamplerType(type) || IsAtomicCounterType(type); +} + +bool IsMatrixType(GLenum type) +{ + return VariableRowCount(type) > 1; +} + +bool IsFloatScalarAndVectorType(GLenum type) +{ + switch (type) + { + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + return true; + default: + return false; + } +} + +bool IsFloatVectorType(GLenum type) +{ + switch (type) + { + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + return true; + default: + return false; + } +} + +GLenum TransposeMatrixType(GLenum type) +{ + if (!IsMatrixType(type)) + { + return type; + } + + switch (type) + { + case GL_FLOAT_MAT2: + return GL_FLOAT_MAT2; + case GL_FLOAT_MAT3: + return GL_FLOAT_MAT3; + case GL_FLOAT_MAT4: + return GL_FLOAT_MAT4; + case GL_FLOAT_MAT2x3: + return GL_FLOAT_MAT3x2; + case GL_FLOAT_MAT3x2: + return GL_FLOAT_MAT2x3; + case GL_FLOAT_MAT2x4: + return GL_FLOAT_MAT4x2; + case GL_FLOAT_MAT4x2: + return GL_FLOAT_MAT2x4; + case GL_FLOAT_MAT3x4: + return GL_FLOAT_MAT4x3; + case GL_FLOAT_MAT4x3: + return GL_FLOAT_MAT3x4; + default: + UNREACHABLE(); + return GL_NONE; + } +} + +int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix) +{ + ASSERT(IsMatrixType(type)); + return isRowMajorMatrix ? VariableRowCount(type) : VariableColumnCount(type); +} + +int MatrixComponentCount(GLenum type, bool isRowMajorMatrix) +{ + ASSERT(IsMatrixType(type)); + return isRowMajorMatrix ? VariableColumnCount(type) : VariableRowCount(type); +} + +int VariableRegisterCount(GLenum type) +{ + return IsMatrixType(type) ? VariableColumnCount(type) : 1; +} int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize) { @@ -117,6 +714,181 @@ IndexRange ComputeIndexRange(DrawElementsType indexType, } } +GLuint GetPrimitiveRestartIndex(DrawElementsType indexType) +{ + switch (indexType) + { + case DrawElementsType::UnsignedByte: + return 0xFF; + case DrawElementsType::UnsignedShort: + return 0xFFFF; + case DrawElementsType::UnsignedInt: + return 0xFFFFFFFF; + default: + UNREACHABLE(); + return 0; + } +} + +bool IsTriangleMode(PrimitiveMode drawMode) +{ + switch (drawMode) + { + case PrimitiveMode::Triangles: + case PrimitiveMode::TriangleFan: + case PrimitiveMode::TriangleStrip: + return true; + case PrimitiveMode::Points: + case PrimitiveMode::Lines: + case PrimitiveMode::LineLoop: + case PrimitiveMode::LineStrip: + return false; + default: + UNREACHABLE(); + } + + return false; +} + +bool IsPolygonMode(PrimitiveMode mode) +{ + switch (mode) + { + case PrimitiveMode::Points: + case PrimitiveMode::Lines: + case PrimitiveMode::LineStrip: + case PrimitiveMode::LineLoop: + case PrimitiveMode::LinesAdjacency: + case PrimitiveMode::LineStripAdjacency: + return false; + default: + break; + } + + return true; +} + +namespace priv +{ +const angle::PackedEnumMap gLineModes = { + {{PrimitiveMode::LineLoop, true}, + {PrimitiveMode::LineStrip, true}, + {PrimitiveMode::LineStripAdjacency, true}, + {PrimitiveMode::Lines, true}}}; +} // namespace priv + +bool IsIntegerFormat(GLenum unsizedFormat) +{ + switch (unsizedFormat) + { + case GL_RGBA_INTEGER: + case GL_RGB_INTEGER: + case GL_RG_INTEGER: + case GL_RED_INTEGER: + return true; + + default: + return false; + } +} + +// [OpenGL ES SL 3.00.4] Section 11 p. 120 +// Vertex Outs/Fragment Ins packing priorities +int VariableSortOrder(GLenum type) +{ + switch (type) + { + // 1. Arrays of mat4 and mat4 + // Non-square matrices of type matCxR consume the same space as a square + // matrix of type matN where N is the greater of C and R + case GL_FLOAT_MAT4: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT3x4: + case GL_FLOAT_MAT4x2: + case GL_FLOAT_MAT4x3: + return 0; + + // 2. Arrays of mat2 and mat2 (since they occupy full rows) + case GL_FLOAT_MAT2: + return 1; + + // 3. Arrays of vec4 and vec4 + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + case GL_BOOL_VEC4: + case GL_UNSIGNED_INT_VEC4: + return 2; + + // 4. Arrays of mat3 and mat3 + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT3x2: + return 3; + + // 5. Arrays of vec3 and vec3 + case GL_FLOAT_VEC3: + case GL_INT_VEC3: + case GL_BOOL_VEC3: + case GL_UNSIGNED_INT_VEC3: + return 4; + + // 6. Arrays of vec2 and vec2 + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_BOOL_VEC2: + case GL_UNSIGNED_INT_VEC2: + return 5; + + // 7. Single component types + case GL_FLOAT: + case GL_INT: + case GL_BOOL: + case GL_UNSIGNED_INT: + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_EXTERNAL_OES: + case GL_SAMPLER_2D_RECT_ANGLE: + case GL_SAMPLER_2D_ARRAY: + case GL_SAMPLER_2D_MULTISAMPLE: + case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_SAMPLER_3D: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_2D_MULTISAMPLE: + case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_SAMPLER_CUBE_SHADOW: + case GL_IMAGE_2D: + case GL_INT_IMAGE_2D: + case GL_UNSIGNED_INT_IMAGE_2D: + case GL_IMAGE_3D: + case GL_INT_IMAGE_3D: + case GL_UNSIGNED_INT_IMAGE_3D: + case GL_IMAGE_2D_ARRAY: + case GL_INT_IMAGE_2D_ARRAY: + case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: + case GL_IMAGE_CUBE: + case GL_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_ATOMIC_COUNTER: + case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: + return 6; + + default: + UNREACHABLE(); + return 0; + } +} + std::string ParseResourceName(const std::string &name, std::vector *outSubscripts) { if (outSubscripts) @@ -158,6 +930,11 @@ std::string ParseResourceName(const std::string &name, std::vector return name.substr(0, baseNameLength); } +bool IsBuiltInName(const char *name) +{ + return angle::BeginsWith(name, "gl_"); +} + std::string StripLastArrayIndex(const std::string &name) { size_t strippedNameLength = name.find_last_of('['); @@ -189,6 +966,31 @@ bool SamplerNameContainsNonZeroArrayElement(const std::string &name) return false; } +unsigned int ArraySizeProduct(const std::vector &arraySizes) +{ + unsigned int arraySizeProduct = 1u; + for (unsigned int arraySize : arraySizes) + { + arraySizeProduct *= arraySize; + } + return arraySizeProduct; +} + +unsigned int InnerArraySizeProduct(const std::vector &arraySizes) +{ + unsigned int arraySizeProduct = 1u; + for (size_t index = 0; index + 1 < arraySizes.size(); ++index) + { + arraySizeProduct *= arraySizes[index]; + } + return arraySizeProduct; +} + +unsigned int OutermostArraySize(const std::vector &arraySizes) +{ + return arraySizes.empty() || arraySizes.back() == 0 ? 1 : arraySizes.back(); +} + unsigned int ParseArrayIndex(const std::string &name, size_t *nameLengthWithoutArrayIndexOut) { ASSERT(nameLengthWithoutArrayIndexOut != nullptr); @@ -259,6 +1061,56 @@ const char *GetGenericErrorMessage(GLenum error) } } +unsigned int ElementTypeSize(GLenum elementType) +{ + switch (elementType) + { + case GL_UNSIGNED_BYTE: + return sizeof(GLubyte); + case GL_UNSIGNED_SHORT: + return sizeof(GLushort); + case GL_UNSIGNED_INT: + return sizeof(GLuint); + default: + UNREACHABLE(); + return 0; + } +} + +bool IsMipmapFiltered(GLenum minFilterMode) +{ + switch (minFilterMode) + { + case GL_NEAREST: + case GL_LINEAR: + return false; + case GL_NEAREST_MIPMAP_NEAREST: + case GL_LINEAR_MIPMAP_NEAREST: + case GL_NEAREST_MIPMAP_LINEAR: + case GL_LINEAR_MIPMAP_LINEAR: + return true; + default: + UNREACHABLE(); + return false; + } +} + +PipelineType GetPipelineType(ShaderType type) +{ + switch (type) + { + case ShaderType::Vertex: + case ShaderType::Fragment: + case ShaderType::Geometry: + return PipelineType::GraphicsPipeline; + case ShaderType::Compute: + return PipelineType::ComputePipeline; + default: + UNREACHABLE(); + return PipelineType::GraphicsPipeline; + } +} + const char *GetDebugMessageSourceString(GLenum source) { switch (source) @@ -320,10 +1172,83 @@ const char *GetDebugMessageSeverityString(GLenum severity) } } +ShaderType GetShaderTypeFromBitfield(size_t singleShaderType) +{ + switch (singleShaderType) + { + case GL_VERTEX_SHADER_BIT: + return ShaderType::Vertex; + case GL_FRAGMENT_SHADER_BIT: + return ShaderType::Fragment; + case GL_COMPUTE_SHADER_BIT: + return ShaderType::Compute; + case GL_GEOMETRY_SHADER_BIT: + return ShaderType::Geometry; + case GL_TESS_CONTROL_SHADER_BIT: + return ShaderType::TessControl; + case GL_TESS_EVALUATION_SHADER_BIT: + return ShaderType::TessEvaluation; + default: + return ShaderType::InvalidEnum; + } +} + +GLbitfield GetBitfieldFromShaderType(ShaderType shaderType) +{ + switch (shaderType) + { + case ShaderType::Vertex: + return GL_VERTEX_SHADER_BIT; + case ShaderType::Fragment: + return GL_FRAGMENT_SHADER_BIT; + case ShaderType::Compute: + return GL_COMPUTE_SHADER_BIT; + case ShaderType::Geometry: + return GL_GEOMETRY_SHADER_BIT; + case ShaderType::TessControl: + return GL_TESS_CONTROL_SHADER_BIT; + case ShaderType::TessEvaluation: + return GL_TESS_EVALUATION_SHADER_BIT; + default: + UNREACHABLE(); + return GL_ZERO; + } +} + +bool ShaderTypeSupportsTransformFeedback(ShaderType shaderType) +{ + switch (shaderType) + { + case ShaderType::Vertex: + case ShaderType::Geometry: + case ShaderType::TessEvaluation: + return true; + default: + return false; + } +} + +ShaderType GetLastPreFragmentStage(ShaderBitSet shaderTypes) +{ + shaderTypes.reset(ShaderType::Fragment); + shaderTypes.reset(ShaderType::Compute); + return shaderTypes.any() ? shaderTypes.last() : ShaderType::InvalidEnum; +} } // namespace gl namespace egl { +static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 1, + "Unexpected EGL cube map enum value."); +static_assert(EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 2, + "Unexpected EGL cube map enum value."); +static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 3, + "Unexpected EGL cube map enum value."); +static_assert(EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 4, + "Unexpected EGL cube map enum value."); +static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 5, + "Unexpected EGL cube map enum value."); + bool IsCubeMapTextureTarget(EGLenum target) { return (target >= FirstCubeMapTextureTarget && target <= LastCubeMapTextureTarget); @@ -562,4 +1487,4 @@ void writeFile(const char *path, std::string_view content) UNREACHABLE(); return; #endif // !ANGLE_ENABLE_WINDOWS_UWP -} \ No newline at end of file +} diff --git a/src/common/utilities.h b/src/common/utilities.h index 778a3c1f609..f78d7017a4f 100644 --- a/src/common/utilities.h +++ b/src/common/utilities.h @@ -33,31 +33,30 @@ struct ShaderVariable; namespace gl { -// 这些轻量级查询函数现在声明为 inline 并在头文件中定义,以允许内联优化。 -inline int VariableComponentCount(GLenum type); -inline GLenum VariableComponentType(GLenum type); -inline size_t VariableComponentSize(GLenum type); -inline size_t VariableInternalSize(GLenum type); -inline size_t VariableExternalSize(GLenum type); -inline int VariableRowCount(GLenum type); -inline int VariableColumnCount(GLenum type); -inline bool IsSamplerType(GLenum type); -inline bool IsSamplerCubeType(GLenum type); -inline bool IsSamplerYUVType(GLenum type); -inline bool IsImageType(GLenum type); -inline bool IsImage2DType(GLenum type); -inline bool IsAtomicCounterType(GLenum type); -inline bool IsOpaqueType(GLenum type); -inline bool IsMatrixType(GLenum type); -inline bool IsFloatScalarAndVectorType(GLenum type); -inline bool IsFloatVectorType(GLenum type); -inline GLenum TransposeMatrixType(GLenum type); -inline int VariableRegisterCount(GLenum type); -inline int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix); -inline int MatrixComponentCount(GLenum type, bool isRowMajorMatrix); -inline int VariableSortOrder(GLenum type); -inline GLenum VariableBoolVectorType(GLenum type); -inline std::string GetGLSLTypeString(GLenum type); +int VariableComponentCount(GLenum type); +GLenum VariableComponentType(GLenum type); +size_t VariableComponentSize(GLenum type); +size_t VariableInternalSize(GLenum type); +size_t VariableExternalSize(GLenum type); +int VariableRowCount(GLenum type); +int VariableColumnCount(GLenum type); +bool IsSamplerType(GLenum type); +bool IsSamplerCubeType(GLenum type); +bool IsSamplerYUVType(GLenum type); +bool IsImageType(GLenum type); +bool IsImage2DType(GLenum type); +bool IsAtomicCounterType(GLenum type); +bool IsOpaqueType(GLenum type); +bool IsMatrixType(GLenum type); +bool IsFloatScalarAndVectorType(GLenum type); +bool IsFloatVectorType(GLenum type); +GLenum TransposeMatrixType(GLenum type); +int VariableRegisterCount(GLenum type); +int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix); +int MatrixComponentCount(GLenum type, bool isRowMajorMatrix); +int VariableSortOrder(GLenum type); +GLenum VariableBoolVectorType(GLenum type); +std::string GetGLSLTypeString(GLenum type); int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize); @@ -68,8 +67,11 @@ int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsig // outSubscripts. std::string ParseResourceName(const std::string &name, std::vector *outSubscripts); -inline bool IsBuiltInName(const char *name); -inline bool IsBuiltInName(const std::string &name); +bool IsBuiltInName(const char *name); +ANGLE_INLINE bool IsBuiltInName(const std::string &name) +{ + return IsBuiltInName(name.c_str()); +} // Strips only the last array index from a resource name. std::string StripLastArrayIndex(const std::string &name); @@ -84,7 +86,7 @@ IndexRange ComputeIndexRange(DrawElementsType indexType, bool primitiveRestartEnabled); // Get the primitive restart index value for the given index type. -inline GLuint GetPrimitiveRestartIndex(DrawElementsType indexType); +GLuint GetPrimitiveRestartIndex(DrawElementsType indexType); // Get the primitive restart index value with the given C++ type. template @@ -100,26 +102,29 @@ static_assert(GetPrimitiveRestartIndexFromType() == 0xFFFF, static_assert(GetPrimitiveRestartIndexFromType() == 0xFFFFFFFF, "verify restart index for uint8_t values"); -inline bool IsTriangleMode(PrimitiveMode drawMode); -inline bool IsPolygonMode(PrimitiveMode mode); +bool IsTriangleMode(PrimitiveMode drawMode); +bool IsPolygonMode(PrimitiveMode mode); namespace priv { extern const angle::PackedEnumMap gLineModes; } // namespace priv -inline bool IsLineMode(PrimitiveMode primitiveMode); +ANGLE_INLINE bool IsLineMode(PrimitiveMode primitiveMode) +{ + return priv::gLineModes[primitiveMode]; +} -inline bool IsIntegerFormat(GLenum unsizedFormat); +bool IsIntegerFormat(GLenum unsizedFormat); // Returns the product of the sizes in the vector, or 1 if the vector is empty. Doesn't currently // perform overflow checks. -inline unsigned int ArraySizeProduct(const std::vector &arraySizes); +unsigned int ArraySizeProduct(const std::vector &arraySizes); // Returns the product of the sizes in the vector except for the outermost dimension, or 1 if the // vector is empty. -inline unsigned int InnerArraySizeProduct(const std::vector &arraySizes); +unsigned int InnerArraySizeProduct(const std::vector &arraySizes); // Returns the outermost array dimension, or 1 if the vector is empty. -inline unsigned int OutermostArraySize(const std::vector &arraySizes); +unsigned int OutermostArraySize(const std::vector &arraySizes); // Return the array index at the end of name, and write the length of name before the final array // index into nameLengthWithoutArrayIndexOut. In case name doesn't include an array index, return @@ -213,12 +218,12 @@ UniformTypeIndex GetUniformTypeIndex(GLenum uniformType); const char *GetGenericErrorMessage(GLenum error); -inline unsigned int ElementTypeSize(GLenum elementType); +unsigned int ElementTypeSize(GLenum elementType); -inline bool IsMipmapFiltered(GLenum minFilterMode); +bool IsMipmapFiltered(GLenum minFilterMode); template -inline T GetClampedVertexCount(size_t vertexCount) +T GetClampedVertexCount(size_t vertexCount) { static constexpr size_t kMax = static_cast(std::numeric_limits::max()); return static_cast(vertexCount > kMax ? kMax : vertexCount); @@ -230,7 +235,7 @@ enum class PipelineType ComputePipeline = 1, }; -inline PipelineType GetPipelineType(ShaderType shaderType); +PipelineType GetPipelineType(ShaderType shaderType); // For use with KHR_debug. const char *GetDebugMessageSourceString(GLenum source); @@ -282,929 +287,12 @@ enum class YuvSamplingMode Y2Y = 1 }; -inline ShaderType GetShaderTypeFromBitfield(size_t singleShaderType); -inline GLbitfield GetBitfieldFromShaderType(ShaderType shaderType); -inline bool ShaderTypeSupportsTransformFeedback(ShaderType shaderType); -inline ShaderType GetLastPreFragmentStage(ShaderBitSet shaderTypes); - -// ---------- 内联函数实现 ---------- - -inline int VariableComponentCount(GLenum type) -{ - return VariableRowCount(type) * VariableColumnCount(type); -} - -inline GLenum VariableComponentType(GLenum type) -{ - switch (type) - { - case GL_BOOL: - case GL_BOOL_VEC2: - case GL_BOOL_VEC3: - case GL_BOOL_VEC4: - return GL_BOOL; - case GL_FLOAT: - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: - case GL_FLOAT_MAT2: - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT4: - case GL_FLOAT_MAT2x3: - case GL_FLOAT_MAT3x2: - case GL_FLOAT_MAT2x4: - case GL_FLOAT_MAT4x2: - case GL_FLOAT_MAT3x4: - case GL_FLOAT_MAT4x3: - return GL_FLOAT; - case GL_INT: - case GL_SAMPLER_2D: - case GL_SAMPLER_2D_RECT_ANGLE: - case GL_SAMPLER_3D: - case GL_SAMPLER_CUBE: - case GL_SAMPLER_CUBE_MAP_ARRAY: - case GL_SAMPLER_2D_ARRAY: - case GL_SAMPLER_EXTERNAL_OES: - case GL_SAMPLER_2D_MULTISAMPLE: - case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_INT_SAMPLER_BUFFER: - case GL_INT_SAMPLER_2D: - case GL_INT_SAMPLER_3D: - case GL_INT_SAMPLER_CUBE: - case GL_INT_SAMPLER_CUBE_MAP_ARRAY: - case GL_INT_SAMPLER_2D_ARRAY: - case GL_INT_SAMPLER_2D_MULTISAMPLE: - case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D: - case GL_UNSIGNED_INT_SAMPLER_3D: - case GL_UNSIGNED_INT_SAMPLER_CUBE: - case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_SAMPLER_2D_SHADOW: - case GL_SAMPLER_BUFFER: - case GL_SAMPLER_CUBE_SHADOW: - case GL_SAMPLER_2D_ARRAY_SHADOW: - case GL_INT_VEC2: - case GL_INT_VEC3: - case GL_INT_VEC4: - case GL_IMAGE_2D: - case GL_INT_IMAGE_2D: - case GL_UNSIGNED_INT_IMAGE_2D: - case GL_IMAGE_3D: - case GL_INT_IMAGE_3D: - case GL_UNSIGNED_INT_IMAGE_3D: - case GL_IMAGE_2D_ARRAY: - case GL_INT_IMAGE_2D_ARRAY: - case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: - case GL_IMAGE_CUBE: - case GL_INT_IMAGE_CUBE: - case GL_UNSIGNED_INT_IMAGE_CUBE: - case GL_IMAGE_CUBE_MAP_ARRAY: - case GL_INT_IMAGE_CUBE_MAP_ARRAY: - case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: - case GL_IMAGE_BUFFER: - case GL_INT_IMAGE_BUFFER: - case GL_UNSIGNED_INT_SAMPLER_BUFFER: - case GL_UNSIGNED_INT_IMAGE_BUFFER: - case GL_UNSIGNED_INT_ATOMIC_COUNTER: - case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: - return GL_INT; - case GL_UNSIGNED_INT: - case GL_UNSIGNED_INT_VEC2: - case GL_UNSIGNED_INT_VEC3: - case GL_UNSIGNED_INT_VEC4: - return GL_UNSIGNED_INT; - default: - UNREACHABLE(); - } - - return GL_NONE; -} - -inline size_t VariableComponentSize(GLenum type) -{ - switch (type) - { - case GL_BOOL: - return sizeof(GLint); - case GL_FLOAT: - return sizeof(GLfloat); - case GL_INT: - return sizeof(GLint); - case GL_UNSIGNED_INT: - return sizeof(GLuint); - default: - UNREACHABLE(); - } - - return 0; -} - -inline size_t VariableInternalSize(GLenum type) -{ - // Expanded to 4-element vectors - return VariableComponentSize(VariableComponentType(type)) * VariableRowCount(type) * 4; -} - -inline size_t VariableExternalSize(GLenum type) -{ - return VariableComponentSize(VariableComponentType(type)) * VariableComponentCount(type); -} - -inline std::string GetGLSLTypeString(GLenum type) -{ - switch (type) - { - case GL_BOOL: - return "bool"; - case GL_INT: - return "int"; - case GL_UNSIGNED_INT: - return "uint"; - case GL_FLOAT: - return "float"; - case GL_BOOL_VEC2: - return "bvec2"; - case GL_BOOL_VEC3: - return "bvec3"; - case GL_BOOL_VEC4: - return "bvec4"; - case GL_INT_VEC2: - return "ivec2"; - case GL_INT_VEC3: - return "ivec3"; - case GL_INT_VEC4: - return "ivec4"; - case GL_FLOAT_VEC2: - return "vec2"; - case GL_FLOAT_VEC3: - return "vec3"; - case GL_FLOAT_VEC4: - return "vec4"; - case GL_UNSIGNED_INT_VEC2: - return "uvec2"; - case GL_UNSIGNED_INT_VEC3: - return "uvec3"; - case GL_UNSIGNED_INT_VEC4: - return "uvec4"; - case GL_FLOAT_MAT2: - return "mat2"; - case GL_FLOAT_MAT3: - return "mat3"; - case GL_FLOAT_MAT4: - return "mat4"; - default: - UNREACHABLE(); - return ""; - } -} - -inline GLenum VariableBoolVectorType(GLenum type) -{ - switch (type) - { - case GL_FLOAT: - case GL_INT: - case GL_UNSIGNED_INT: - return GL_BOOL; - case GL_FLOAT_VEC2: - case GL_INT_VEC2: - case GL_UNSIGNED_INT_VEC2: - return GL_BOOL_VEC2; - case GL_FLOAT_VEC3: - case GL_INT_VEC3: - case GL_UNSIGNED_INT_VEC3: - return GL_BOOL_VEC3; - case GL_FLOAT_VEC4: - case GL_INT_VEC4: - case GL_UNSIGNED_INT_VEC4: - return GL_BOOL_VEC4; - - default: - UNREACHABLE(); - return GL_NONE; - } -} - -inline int VariableRowCount(GLenum type) -{ - switch (type) - { - case GL_NONE: - return 0; - case GL_BOOL: - case GL_FLOAT: - case GL_INT: - case GL_UNSIGNED_INT: - case GL_BOOL_VEC2: - case GL_FLOAT_VEC2: - case GL_INT_VEC2: - case GL_UNSIGNED_INT_VEC2: - case GL_BOOL_VEC3: - case GL_FLOAT_VEC3: - case GL_INT_VEC3: - case GL_UNSIGNED_INT_VEC3: - case GL_BOOL_VEC4: - case GL_FLOAT_VEC4: - case GL_INT_VEC4: - case GL_UNSIGNED_INT_VEC4: - case GL_SAMPLER_2D: - case GL_SAMPLER_3D: - case GL_SAMPLER_CUBE: - case GL_SAMPLER_2D_ARRAY: - case GL_SAMPLER_EXTERNAL_OES: - case GL_SAMPLER_2D_RECT_ANGLE: - case GL_SAMPLER_2D_MULTISAMPLE: - case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_SAMPLER_CUBE_MAP_ARRAY: - case GL_SAMPLER_BUFFER: - case GL_INT_SAMPLER_2D: - case GL_INT_SAMPLER_3D: - case GL_INT_SAMPLER_CUBE: - case GL_INT_SAMPLER_2D_ARRAY: - case GL_INT_SAMPLER_2D_MULTISAMPLE: - case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_INT_SAMPLER_CUBE_MAP_ARRAY: - case GL_INT_SAMPLER_BUFFER: - case GL_UNSIGNED_INT_SAMPLER_2D: - case GL_UNSIGNED_INT_SAMPLER_3D: - case GL_UNSIGNED_INT_SAMPLER_CUBE: - case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_BUFFER: - case GL_SAMPLER_2D_SHADOW: - case GL_SAMPLER_CUBE_SHADOW: - case GL_SAMPLER_2D_ARRAY_SHADOW: - case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: - case GL_IMAGE_2D: - case GL_INT_IMAGE_2D: - case GL_UNSIGNED_INT_IMAGE_2D: - case GL_IMAGE_2D_ARRAY: - case GL_INT_IMAGE_2D_ARRAY: - case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: - case GL_IMAGE_3D: - case GL_INT_IMAGE_3D: - case GL_UNSIGNED_INT_IMAGE_3D: - case GL_IMAGE_CUBE: - case GL_INT_IMAGE_CUBE: - case GL_UNSIGNED_INT_IMAGE_CUBE: - case GL_UNSIGNED_INT_ATOMIC_COUNTER: - case GL_IMAGE_CUBE_MAP_ARRAY: - case GL_INT_IMAGE_CUBE_MAP_ARRAY: - case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: - case GL_IMAGE_BUFFER: - case GL_INT_IMAGE_BUFFER: - case GL_UNSIGNED_INT_IMAGE_BUFFER: - case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: - return 1; - case GL_FLOAT_MAT2: - case GL_FLOAT_MAT3x2: - case GL_FLOAT_MAT4x2: - return 2; - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT2x3: - case GL_FLOAT_MAT4x3: - return 3; - case GL_FLOAT_MAT4: - case GL_FLOAT_MAT2x4: - case GL_FLOAT_MAT3x4: - return 4; - default: - UNREACHABLE(); - } - - return 0; -} - -inline int VariableColumnCount(GLenum type) -{ - switch (type) - { - case GL_NONE: - return 0; - case GL_BOOL: - case GL_FLOAT: - case GL_INT: - case GL_UNSIGNED_INT: - case GL_SAMPLER_2D: - case GL_SAMPLER_3D: - case GL_SAMPLER_CUBE: - case GL_SAMPLER_2D_ARRAY: - case GL_SAMPLER_2D_MULTISAMPLE: - case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_SAMPLER_CUBE_MAP_ARRAY: - case GL_SAMPLER_BUFFER: - case GL_INT_SAMPLER_2D: - case GL_INT_SAMPLER_3D: - case GL_INT_SAMPLER_CUBE: - case GL_INT_SAMPLER_2D_ARRAY: - case GL_INT_SAMPLER_2D_MULTISAMPLE: - case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_INT_SAMPLER_CUBE_MAP_ARRAY: - case GL_INT_SAMPLER_BUFFER: - case GL_SAMPLER_EXTERNAL_OES: - case GL_SAMPLER_2D_RECT_ANGLE: - case GL_UNSIGNED_INT_SAMPLER_2D: - case GL_UNSIGNED_INT_SAMPLER_3D: - case GL_UNSIGNED_INT_SAMPLER_CUBE: - case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_BUFFER: - case GL_SAMPLER_2D_SHADOW: - case GL_SAMPLER_CUBE_SHADOW: - case GL_SAMPLER_2D_ARRAY_SHADOW: - case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: - case GL_IMAGE_2D: - case GL_INT_IMAGE_2D: - case GL_UNSIGNED_INT_IMAGE_2D: - case GL_IMAGE_3D: - case GL_INT_IMAGE_3D: - case GL_UNSIGNED_INT_IMAGE_3D: - case GL_IMAGE_2D_ARRAY: - case GL_INT_IMAGE_2D_ARRAY: - case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: - case GL_IMAGE_CUBE_MAP_ARRAY: - case GL_INT_IMAGE_CUBE_MAP_ARRAY: - case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: - case GL_IMAGE_BUFFER: - case GL_INT_IMAGE_BUFFER: - case GL_UNSIGNED_INT_IMAGE_BUFFER: - case GL_IMAGE_CUBE: - case GL_INT_IMAGE_CUBE: - case GL_UNSIGNED_INT_IMAGE_CUBE: - case GL_UNSIGNED_INT_ATOMIC_COUNTER: - case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: - return 1; - case GL_BOOL_VEC2: - case GL_FLOAT_VEC2: - case GL_INT_VEC2: - case GL_UNSIGNED_INT_VEC2: - case GL_FLOAT_MAT2: - case GL_FLOAT_MAT2x3: - case GL_FLOAT_MAT2x4: - return 2; - case GL_BOOL_VEC3: - case GL_FLOAT_VEC3: - case GL_INT_VEC3: - case GL_UNSIGNED_INT_VEC3: - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT3x2: - case GL_FLOAT_MAT3x4: - return 3; - case GL_BOOL_VEC4: - case GL_FLOAT_VEC4: - case GL_INT_VEC4: - case GL_UNSIGNED_INT_VEC4: - case GL_FLOAT_MAT4: - case GL_FLOAT_MAT4x2: - case GL_FLOAT_MAT4x3: - return 4; - default: - UNREACHABLE(); - } - - return 0; -} - -inline bool IsSamplerType(GLenum type) -{ - switch (type) - { - case GL_SAMPLER_2D: - case GL_SAMPLER_3D: - case GL_SAMPLER_CUBE: - case GL_SAMPLER_2D_ARRAY: - case GL_SAMPLER_EXTERNAL_OES: - case GL_SAMPLER_2D_MULTISAMPLE: - case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_SAMPLER_CUBE_MAP_ARRAY: - case GL_SAMPLER_BUFFER: - case GL_SAMPLER_2D_RECT_ANGLE: - case GL_INT_SAMPLER_2D: - case GL_INT_SAMPLER_3D: - case GL_INT_SAMPLER_CUBE: - case GL_INT_SAMPLER_2D_ARRAY: - case GL_INT_SAMPLER_2D_MULTISAMPLE: - case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_INT_SAMPLER_CUBE_MAP_ARRAY: - case GL_INT_SAMPLER_BUFFER: - case GL_UNSIGNED_INT_SAMPLER_2D: - case GL_UNSIGNED_INT_SAMPLER_3D: - case GL_UNSIGNED_INT_SAMPLER_CUBE: - case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_BUFFER: - case GL_SAMPLER_2D_SHADOW: - case GL_SAMPLER_CUBE_SHADOW: - case GL_SAMPLER_2D_ARRAY_SHADOW: - case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: - case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: - return true; - } - - return false; -} - -inline bool IsSamplerCubeType(GLenum type) -{ - switch (type) - { - case GL_SAMPLER_CUBE: - case GL_INT_SAMPLER_CUBE: - case GL_UNSIGNED_INT_SAMPLER_CUBE: - case GL_SAMPLER_CUBE_SHADOW: - return true; - } - - return false; -} - -inline bool IsSamplerYUVType(GLenum type) -{ - switch (type) - { - case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: - return true; - - default: - return false; - } -} - -inline bool IsImageType(GLenum type) -{ - switch (type) - { - case GL_IMAGE_2D: - case GL_INT_IMAGE_2D: - case GL_UNSIGNED_INT_IMAGE_2D: - case GL_IMAGE_3D: - case GL_INT_IMAGE_3D: - case GL_UNSIGNED_INT_IMAGE_3D: - case GL_IMAGE_2D_ARRAY: - case GL_INT_IMAGE_2D_ARRAY: - case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: - case GL_IMAGE_CUBE_MAP_ARRAY: - case GL_INT_IMAGE_CUBE_MAP_ARRAY: - case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: - case GL_IMAGE_BUFFER: - case GL_INT_IMAGE_BUFFER: - case GL_UNSIGNED_INT_IMAGE_BUFFER: - case GL_IMAGE_CUBE: - case GL_INT_IMAGE_CUBE: - case GL_UNSIGNED_INT_IMAGE_CUBE: - return true; - } - return false; -} - -inline bool IsImage2DType(GLenum type) -{ - switch (type) - { - case GL_IMAGE_2D: - case GL_INT_IMAGE_2D: - case GL_UNSIGNED_INT_IMAGE_2D: - return true; - case GL_IMAGE_3D: - case GL_INT_IMAGE_3D: - case GL_UNSIGNED_INT_IMAGE_3D: - case GL_IMAGE_2D_ARRAY: - case GL_INT_IMAGE_2D_ARRAY: - case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: - case GL_IMAGE_CUBE_MAP_ARRAY: - case GL_INT_IMAGE_CUBE_MAP_ARRAY: - case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: - case GL_IMAGE_CUBE: - case GL_INT_IMAGE_CUBE: - case GL_UNSIGNED_INT_IMAGE_CUBE: - case GL_IMAGE_BUFFER: - case GL_INT_IMAGE_BUFFER: - case GL_UNSIGNED_INT_IMAGE_BUFFER: - return false; - default: - UNREACHABLE(); - return false; - } -} - -inline bool IsAtomicCounterType(GLenum type) -{ - return type == GL_UNSIGNED_INT_ATOMIC_COUNTER; -} - -inline bool IsOpaqueType(GLenum type) -{ - // ESSL 3.10 section 4.1.7 defines opaque types as: samplers, images and atomic counters. - return IsImageType(type) || IsSamplerType(type) || IsAtomicCounterType(type); -} - -inline bool IsMatrixType(GLenum type) -{ - return VariableRowCount(type) > 1; -} - -inline bool IsFloatScalarAndVectorType(GLenum type) -{ - switch (type) - { - case GL_FLOAT: - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: - return true; - default: - return false; - } -} - -inline bool IsFloatVectorType(GLenum type) -{ - switch (type) - { - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: - return true; - default: - return false; - } -} - -inline GLenum TransposeMatrixType(GLenum type) -{ - if (!IsMatrixType(type)) - { - return type; - } - - switch (type) - { - case GL_FLOAT_MAT2: - return GL_FLOAT_MAT2; - case GL_FLOAT_MAT3: - return GL_FLOAT_MAT3; - case GL_FLOAT_MAT4: - return GL_FLOAT_MAT4; - case GL_FLOAT_MAT2x3: - return GL_FLOAT_MAT3x2; - case GL_FLOAT_MAT3x2: - return GL_FLOAT_MAT2x3; - case GL_FLOAT_MAT2x4: - return GL_FLOAT_MAT4x2; - case GL_FLOAT_MAT4x2: - return GL_FLOAT_MAT2x4; - case GL_FLOAT_MAT3x4: - return GL_FLOAT_MAT4x3; - case GL_FLOAT_MAT4x3: - return GL_FLOAT_MAT3x4; - default: - UNREACHABLE(); - return GL_NONE; - } -} - -inline int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix) -{ - ASSERT(IsMatrixType(type)); - return isRowMajorMatrix ? VariableRowCount(type) : VariableColumnCount(type); -} - -inline int MatrixComponentCount(GLenum type, bool isRowMajorMatrix) -{ - ASSERT(IsMatrixType(type)); - return isRowMajorMatrix ? VariableColumnCount(type) : VariableRowCount(type); -} - -inline int VariableRegisterCount(GLenum type) -{ - return IsMatrixType(type) ? VariableColumnCount(type) : 1; -} - -inline int VariableSortOrder(GLenum type) -{ - switch (type) - { - // 1. Arrays of mat4 and mat4 - // Non-square matrices of type matCxR consume the same space as a square - // matrix of type matN where N is the greater of C and R - case GL_FLOAT_MAT4: - case GL_FLOAT_MAT2x4: - case GL_FLOAT_MAT3x4: - case GL_FLOAT_MAT4x2: - case GL_FLOAT_MAT4x3: - return 0; - - // 2. Arrays of mat2 and mat2 (since they occupy full rows) - case GL_FLOAT_MAT2: - return 1; - - // 3. Arrays of vec4 and vec4 - case GL_FLOAT_VEC4: - case GL_INT_VEC4: - case GL_BOOL_VEC4: - case GL_UNSIGNED_INT_VEC4: - return 2; - - // 4. Arrays of mat3 and mat3 - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT2x3: - case GL_FLOAT_MAT3x2: - return 3; - - // 5. Arrays of vec3 and vec3 - case GL_FLOAT_VEC3: - case GL_INT_VEC3: - case GL_BOOL_VEC3: - case GL_UNSIGNED_INT_VEC3: - return 4; - - // 6. Arrays of vec2 and vec2 - case GL_FLOAT_VEC2: - case GL_INT_VEC2: - case GL_BOOL_VEC2: - case GL_UNSIGNED_INT_VEC2: - return 5; - - // 7. Single component types - case GL_FLOAT: - case GL_INT: - case GL_BOOL: - case GL_UNSIGNED_INT: - case GL_SAMPLER_2D: - case GL_SAMPLER_CUBE: - case GL_SAMPLER_EXTERNAL_OES: - case GL_SAMPLER_2D_RECT_ANGLE: - case GL_SAMPLER_2D_ARRAY: - case GL_SAMPLER_2D_MULTISAMPLE: - case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_SAMPLER_3D: - case GL_INT_SAMPLER_2D: - case GL_INT_SAMPLER_3D: - case GL_INT_SAMPLER_CUBE: - case GL_INT_SAMPLER_2D_ARRAY: - case GL_INT_SAMPLER_2D_MULTISAMPLE: - case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D: - case GL_UNSIGNED_INT_SAMPLER_3D: - case GL_UNSIGNED_INT_SAMPLER_CUBE: - case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_SAMPLER_2D_SHADOW: - case GL_SAMPLER_2D_ARRAY_SHADOW: - case GL_SAMPLER_CUBE_SHADOW: - case GL_IMAGE_2D: - case GL_INT_IMAGE_2D: - case GL_UNSIGNED_INT_IMAGE_2D: - case GL_IMAGE_3D: - case GL_INT_IMAGE_3D: - case GL_UNSIGNED_INT_IMAGE_3D: - case GL_IMAGE_2D_ARRAY: - case GL_INT_IMAGE_2D_ARRAY: - case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: - case GL_IMAGE_CUBE: - case GL_INT_IMAGE_CUBE: - case GL_UNSIGNED_INT_IMAGE_CUBE: - case GL_UNSIGNED_INT_ATOMIC_COUNTER: - case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT: - return 6; - - default: - UNREACHABLE(); - return 0; - } -} - -inline bool IsBuiltInName(const char *name) -{ - return angle::BeginsWith(name, "gl_"); -} - -inline bool IsBuiltInName(const std::string &name) -{ - return IsBuiltInName(name.c_str()); -} - -inline GLuint GetPrimitiveRestartIndex(DrawElementsType indexType) -{ - switch (indexType) - { - case DrawElementsType::UnsignedByte: - return 0xFF; - case DrawElementsType::UnsignedShort: - return 0xFFFF; - case DrawElementsType::UnsignedInt: - return 0xFFFFFFFF; - default: - UNREACHABLE(); - return 0; - } -} - -inline bool IsTriangleMode(PrimitiveMode drawMode) -{ - switch (drawMode) - { - case PrimitiveMode::Triangles: - case PrimitiveMode::TriangleFan: - case PrimitiveMode::TriangleStrip: - return true; - case PrimitiveMode::Points: - case PrimitiveMode::Lines: - case PrimitiveMode::LineLoop: - case PrimitiveMode::LineStrip: - return false; - default: - UNREACHABLE(); - } - - return false; -} - -inline bool IsPolygonMode(PrimitiveMode mode) -{ - switch (mode) - { - case PrimitiveMode::Points: - case PrimitiveMode::Lines: - case PrimitiveMode::LineStrip: - case PrimitiveMode::LineLoop: - case PrimitiveMode::LinesAdjacency: - case PrimitiveMode::LineStripAdjacency: - return false; - default: - break; - } - - return true; -} - -inline bool IsLineMode(PrimitiveMode primitiveMode) -{ - return priv::gLineModes[primitiveMode]; -} - -inline bool IsIntegerFormat(GLenum unsizedFormat) -{ - switch (unsizedFormat) - { - case GL_RGBA_INTEGER: - case GL_RGB_INTEGER: - case GL_RG_INTEGER: - case GL_RED_INTEGER: - return true; - - default: - return false; - } -} - -inline unsigned int ArraySizeProduct(const std::vector &arraySizes) -{ - unsigned int arraySizeProduct = 1u; - for (unsigned int arraySize : arraySizes) - { - arraySizeProduct *= arraySize; - } - return arraySizeProduct; -} - -inline unsigned int InnerArraySizeProduct(const std::vector &arraySizes) -{ - unsigned int arraySizeProduct = 1u; - for (size_t index = 0; index + 1 < arraySizes.size(); ++index) - { - arraySizeProduct *= arraySizes[index]; - } - return arraySizeProduct; -} - -inline unsigned int OutermostArraySize(const std::vector &arraySizes) -{ - return arraySizes.empty() || arraySizes.back() == 0 ? 1 : arraySizes.back(); -} - -inline unsigned int ElementTypeSize(GLenum elementType) -{ - switch (elementType) - { - case GL_UNSIGNED_BYTE: - return sizeof(GLubyte); - case GL_UNSIGNED_SHORT: - return sizeof(GLushort); - case GL_UNSIGNED_INT: - return sizeof(GLuint); - default: - UNREACHABLE(); - return 0; - } -} - -inline bool IsMipmapFiltered(GLenum minFilterMode) -{ - switch (minFilterMode) - { - case GL_NEAREST: - case GL_LINEAR: - return false; - case GL_NEAREST_MIPMAP_NEAREST: - case GL_LINEAR_MIPMAP_NEAREST: - case GL_NEAREST_MIPMAP_LINEAR: - case GL_LINEAR_MIPMAP_LINEAR: - return true; - default: - UNREACHABLE(); - return false; - } -} - -inline PipelineType GetPipelineType(ShaderType type) -{ - switch (type) - { - case ShaderType::Vertex: - case ShaderType::Fragment: - case ShaderType::Geometry: - return PipelineType::GraphicsPipeline; - case ShaderType::Compute: - return PipelineType::ComputePipeline; - default: - UNREACHABLE(); - return PipelineType::GraphicsPipeline; - } -} - -inline ShaderType GetShaderTypeFromBitfield(size_t singleShaderType) -{ - switch (singleShaderType) - { - case GL_VERTEX_SHADER_BIT: - return ShaderType::Vertex; - case GL_FRAGMENT_SHADER_BIT: - return ShaderType::Fragment; - case GL_COMPUTE_SHADER_BIT: - return ShaderType::Compute; - case GL_GEOMETRY_SHADER_BIT: - return ShaderType::Geometry; - case GL_TESS_CONTROL_SHADER_BIT: - return ShaderType::TessControl; - case GL_TESS_EVALUATION_SHADER_BIT: - return ShaderType::TessEvaluation; - default: - return ShaderType::InvalidEnum; - } -} - -inline GLbitfield GetBitfieldFromShaderType(ShaderType shaderType) -{ - switch (shaderType) - { - case ShaderType::Vertex: - return GL_VERTEX_SHADER_BIT; - case ShaderType::Fragment: - return GL_FRAGMENT_SHADER_BIT; - case ShaderType::Compute: - return GL_COMPUTE_SHADER_BIT; - case ShaderType::Geometry: - return GL_GEOMETRY_SHADER_BIT; - case ShaderType::TessControl: - return GL_TESS_CONTROL_SHADER_BIT; - case ShaderType::TessEvaluation: - return GL_TESS_EVALUATION_SHADER_BIT; - default: - UNREACHABLE(); - return GL_ZERO; - } -} - -inline bool ShaderTypeSupportsTransformFeedback(ShaderType shaderType) -{ - switch (shaderType) - { - case ShaderType::Vertex: - case ShaderType::Geometry: - case ShaderType::TessEvaluation: - return true; - default: - return false; - } -} - -inline ShaderType GetLastPreFragmentStage(ShaderBitSet shaderTypes) -{ - shaderTypes.reset(ShaderType::Fragment); - shaderTypes.reset(ShaderType::Compute); - return shaderTypes.any() ? shaderTypes.last() : ShaderType::InvalidEnum; -} +ShaderType GetShaderTypeFromBitfield(size_t singleShaderType); +GLbitfield GetBitfieldFromShaderType(ShaderType shaderType); +bool ShaderTypeSupportsTransformFeedback(ShaderType shaderType); +// Given a set of shader stages, returns the last vertex processing stage. This is the stage that +// interfaces the fragment shader. +ShaderType GetLastPreFragmentStage(ShaderBitSet shaderTypes); } // namespace gl From 93e285b77bdc8fe5504320c14ba00c74f35428f7 Mon Sep 17 00:00:00 2001 From: aaaapai Date: Wed, 26 Aug 2026 19:39:23 +0800 Subject: [PATCH 5/6] Fix up --- src/libANGLE/renderer/vulkan/vk_helpers.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.cpp b/src/libANGLE/renderer/vulkan/vk_helpers.cpp index 1cf5518716c..7e7954faecc 100644 --- a/src/libANGLE/renderer/vulkan/vk_helpers.cpp +++ b/src/libANGLE/renderer/vulkan/vk_helpers.cpp @@ -13407,12 +13407,9 @@ angle::Result BufferViewHelper::getView(ErrorContext *context, const VkDeviceSize maxRangeBytes = maxTexelBufferElements * pixelBytes; if (size > maxRangeBytes) { - ANGLE_VK_PERF_WARNING(context, GL_DEBUG_SEVERITY_HIGH, - "BufferView range (%llu) exceeds maxTexelBufferElements (%llu), " - "truncating to %llu bytes", - static_cast(size), - static_cast(maxRangeBytes), - static_cast(maxRangeBytes)); + WARN() << "BufferView range (" << size << ") exceeds maxTexelBufferElements (" + << maxRangeBytes << "), truncating to " << (maxRangeBytes - maxRangeBytes % pixelBytes) + << " bytes"; size = maxRangeBytes - (maxRangeBytes % pixelBytes); } From 2339894cc9c31158d642baef0688f3fcdcb1c843 Mon Sep 17 00:00:00 2001 From: aaaapai Date: Wed, 26 Aug 2026 19:41:43 +0800 Subject: [PATCH 6/6] e --- out/Android-arm32/args.gn | 4 ++++ out/Android-arm64/args.gn | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/out/Android-arm32/args.gn b/out/Android-arm32/args.gn index 75a2d755331..c7ebbb49f6c 100644 --- a/out/Android-arm32/args.gn +++ b/out/Android-arm32/args.gn @@ -61,6 +61,8 @@ cflags_c = [ "-fslp-vectorize", "-pipe", "-integrated-as", + "-mllvm", + "-inlinehint-threshold=100000", "-flto", "-marm", "-D_FILE_OFFSET_BITS=64", @@ -82,6 +84,8 @@ cflags_cc = [ "-march=armv7-a+neon", "-mllvm", "-hot-cold-split=true", + "-mllvm", + "-inlinehint-threshold=100000", "-fdata-sections", "-ffunction-sections", "-fmerge-all-constants", diff --git a/out/Android-arm64/args.gn b/out/Android-arm64/args.gn index 9146deae6df..f7bea2713b0 100644 --- a/out/Android-arm64/args.gn +++ b/out/Android-arm64/args.gn @@ -79,6 +79,8 @@ cflags_c = [ "-polly-ast-use-context", "-mllvm", "-polly-parallel", + "-mllvm", + "-inlinehint-threshold=100000", "-flto", "-D_FILE_OFFSET_BITS=64", "-D__USE_BSD", @@ -125,6 +127,8 @@ cflags_cc = [ "-polly-ast-use-context", "-mllvm", "-polly-parallel", + "-mllvm", + "-inlinehint-threshold=100000", "-flto", "-D_FILE_OFFSET_BITS=64", "-D__USE_BSD",