mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-05 01:24:14 +01:00
5d29140f74
There is no good reason to expect games will have aligned the data they're passing in.
169 lines
4.0 KiB
C++
169 lines
4.0 KiB
C++
#pragma once
|
|
|
|
#include <iostream>
|
|
|
|
#include "util_bit.h"
|
|
#include "util_math.h"
|
|
|
|
namespace dxvk {
|
|
|
|
template <typename T>
|
|
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<T>& other) = default;
|
|
Vector4Base& operator=(const Vector4Base<T>& 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<T>& other) const {
|
|
for (uint32_t i = 0; i < 4; i++) {
|
|
if (data[i] != other.data[i])
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool operator!=(const Vector4Base<T>& other) const {
|
|
return !operator==(other);
|
|
}
|
|
|
|
Vector4Base operator-() const { return {-x, -y, -z, -w}; }
|
|
|
|
Vector4Base operator+(const Vector4Base<T>& other) const {
|
|
return {x + other.x, y + other.y, z + other.z, w + other.w};
|
|
}
|
|
|
|
Vector4Base operator-(const Vector4Base<T>& 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<T>& 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<T>& 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<T>& other) {
|
|
x += other.x;
|
|
y += other.y;
|
|
z += other.z;
|
|
w += other.w;
|
|
|
|
return *this;
|
|
}
|
|
|
|
Vector4Base& operator-=(const Vector4Base<T>& 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 <typename T>
|
|
inline Vector4Base<T> operator*(T scalar, const Vector4Base<T>& vector) {
|
|
return vector * scalar;
|
|
}
|
|
|
|
template <typename T>
|
|
float dot(const Vector4Base<T>& a, const Vector4Base<T>& b) {
|
|
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
|
|
}
|
|
|
|
template <typename T>
|
|
T lengthSqr(const Vector4Base<T>& a) { return dot(a, a); }
|
|
|
|
template <typename T>
|
|
float length(const Vector4Base<T>& a) { return std::sqrt(float(lengthSqr(a))); }
|
|
|
|
template <typename T>
|
|
Vector4Base<T> normalize(const Vector4Base<T>& a) { return a * T(1.0f / length(a)); }
|
|
|
|
template <typename T>
|
|
std::ostream& operator<<(std::ostream& os, const Vector4Base<T>& v) {
|
|
return os << "Vector4(" << v[0] << ", " << v[1] << ", " << v[2] << ", " << v[3] << ")";
|
|
}
|
|
|
|
using Vector4 = Vector4Base<float>;
|
|
using Vector4i = Vector4Base<int>;
|
|
|
|
static_assert(sizeof(Vector4) == sizeof(float) * 4);
|
|
static_assert(sizeof(Vector4i) == sizeof(int) * 4);
|
|
|
|
inline Vector4 replaceNaN(Vector4 a) {
|
|
#ifdef DXVK_ARCH_X86
|
|
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
|
|
}
|
|
|
|
}
|