#pragma once #include #include "util_bit.h" #include "util_math.h" namespace dxvk { template struct Vector4Base { Vector4Base() : x{ }, y{ }, z{ }, w{ } { } Vector4Base(T splat) : x(splat), y(splat), z(splat), w(splat) { } Vector4Base(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) { } Vector4Base(const T xyzw[4]) : x(xyzw[0]), y(xyzw[1]), z(xyzw[2]), w(xyzw[3]) { } Vector4Base(const Vector4Base& other) = default; Vector4Base& operator=(const Vector4Base& other) = default; inline T& operator[](size_t index) { return data[index]; } inline const T& operator[](size_t index) const { return data[index]; } bool operator==(const Vector4Base& other) const { for (uint32_t i = 0; i < 4; i++) { if (data[i] != other.data[i]) return false; } return true; } bool operator!=(const Vector4Base& other) const { return !operator==(other); } Vector4Base operator-() const { return {-x, -y, -z, -w}; } Vector4Base operator+(const Vector4Base& other) const { return {x + other.x, y + other.y, z + other.z, w + other.w}; } Vector4Base operator-(const Vector4Base& other) const { return {x - other.x, y - other.y, z - other.z, w - other.w}; } Vector4Base operator*(T scalar) const { return {scalar * x, scalar * y, scalar * z, scalar * w}; } Vector4Base operator*(const Vector4Base& other) const { Vector4Base result; for (uint32_t i = 0; i < 4; i++) result[i] = data[i] * other.data[i]; return result; } Vector4Base operator/(const Vector4Base& other) const { Vector4Base result; for (uint32_t i = 0; i < 4; i++) result[i] = data[i] / other.data[i]; return result; } Vector4Base operator/(T scalar) const { return {x / scalar, y / scalar, z / scalar, w / scalar}; } Vector4Base& operator+=(const Vector4Base& other) { x += other.x; y += other.y; z += other.z; w += other.w; return *this; } Vector4Base& operator-=(const Vector4Base& other) { x -= other.x; y -= other.y; z -= other.z; w -= other.w; return *this; } Vector4Base& operator*=(T scalar) { x *= scalar; y *= scalar; z *= scalar; w *= scalar; return *this; } Vector4Base& operator/=(T scalar) { x /= scalar; y /= scalar; z /= scalar; w /= scalar; return *this; } union { T data[4]; struct { T x, y, z, w; }; struct { T r, g, b, a; }; }; }; template inline Vector4Base operator*(T scalar, const Vector4Base& vector) { return vector * scalar; } template float dot(const Vector4Base& a, const Vector4Base& b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; } template T lengthSqr(const Vector4Base& a) { return dot(a, a); } template float length(const Vector4Base& a) { return std::sqrt(float(lengthSqr(a))); } template Vector4Base normalize(const Vector4Base& a) { return a * T(1.0f / length(a)); } template std::ostream& operator<<(std::ostream& os, const Vector4Base& v) { return os << "Vector4(" << v[0] << ", " << v[1] << ", " << v[2] << ", " << v[3] << ")"; } using Vector4 = Vector4Base; using Vector4i = Vector4Base; static_assert(sizeof(Vector4) == sizeof(float) * 4); static_assert(sizeof(Vector4i) == sizeof(int) * 4); inline Vector4 replaceNaN(Vector4 a) { #ifdef DXVK_ARCH_X86 alignas(16) Vector4 result; __m128 value = _mm_loadu_ps(a.data); __m128 mask = _mm_cmpeq_ps(value, value); value = _mm_and_ps(value, mask); _mm_store_ps(result.data, value); return result; #else for (int i = 0; i < 4; i++) a[i] = std::isnan(a[i]) ? 0.0f : a[i]; return a; #endif } }