Skip to content

Instantly share code, notes, and snippets.

@mattleibow
Created January 31, 2021 03:51
Show Gist options
  • Save mattleibow/0974824b9c9e8fdb7079af56f8795207 to your computer and use it in GitHub Desktop.
Save mattleibow/0974824b9c9e8fdb7079af56f8795207 to your computer and use it in GitHub Desktop.
// All Vec have the same simple memory layout, the same as `T vec[N]`.
template <int N, typename T>
struct alignas(N * sizeof(T)) Vec {
static_assert((N& (N - 1)) == 0, "N must be a power of 2.");
static_assert(sizeof(T) >= alignof(T), "What kind of crazy T is this?");
Vec<N / 2, T> lo, hi;
// Methods belong here in the class declaration of Vec only if:
// - they must be here, like constructors or operator[];
// - they'll definitely never want a specialized implementation.
// Other operations on Vec should be defined outside the type.
__forceinline Vec() = default;
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
__forceinline
Vec(U x) : lo(x), hi(x) {}
__forceinline Vec(std::initializer_list<T> xs) {
T vals[N] = { 0 };
memcpy(vals, xs.begin(), std::min(xs.size(), (size_t)N) * sizeof(T));
lo = Vec<N / 2, T>::Load(vals + 0);
hi = Vec<N / 2, T>::Load(vals + N / 2);
}
__forceinline T operator[](int i) const { return i < N / 2 ? lo[i] : hi[i - N / 2]; }
__forceinline T& operator[](int i) { return i < N / 2 ? lo[i] : hi[i - N / 2]; }
__forceinline static Vec Load(const void* ptr) {
Vec v;
memcpy(&v, ptr, sizeof(Vec));
return v;
}
__forceinline void store(void* ptr) const {
memcpy(ptr, this, sizeof(Vec));
}
};
template <typename T>
struct Vec<1, T> {
T val;
__forceinline Vec() = default;
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
__forceinline
Vec(U x) : val(x) {}
__forceinline Vec(std::initializer_list<T> xs) : val(xs.size() ? *xs.begin() : 0) {}
__forceinline T operator[](int) const { return val; }
__forceinline T& operator[](int) { return val; }
__forceinline static Vec Load(const void* ptr) {
Vec v;
memcpy(&v, ptr, sizeof(Vec));
return v;
}
__forceinline void store(void* ptr) const {
memcpy(ptr, this, sizeof(Vec));
}
};
class GrVectorXform {
public:
using float2 = Vec<2, float>;
using float4 = Vec<4, float>;
explicit GrVectorXform() : fType(Type::kIdentity) {}
float2 operator()(float2 vector) const {
switch (fType) {
case Type::kIdentity:
return vector;
}
}
float4 operator()(float4 vectors) const {
switch (fType) {
case Type::kIdentity:
return vectors;
}
}
private:
enum class Type { kIdentity, kScale, kAffine } fType;
union { float2 fScaleXY, fScaleXSkewY; };
float2 fSkewXScaleY;
float4 fScaleXYXY;
float4 fSkewXYXY;
};
@mattleibow
Copy link
Author

mattleibow commented Jan 31, 2021

I get an error on line 78 when building with ARM. x86, x64 and ARM64 are all good.

float4 operator()(float4 vectors) const {
C2719	'vectors': formal parameter with requested alignment of 16 won't be aligned.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment