diff options
| author | 2014-08-12 20:04:28 +0200 | |
|---|---|---|
| committer | 2014-08-25 22:03:18 +0200 | |
| commit | 162d641a301d87d5e25ca5d677b7f8f07f29e748 (patch) | |
| tree | c22ef7138a8f27b9dfd363270856cceea50fd2bf | |
| parent | Pica/VertexShader: Fix a bug in the bitfield definitions and add the "negate"... (diff) | |
| download | yuzu-162d641a301d87d5e25ca5d677b7f8f07f29e748.tar.gz yuzu-162d641a301d87d5e25ca5d677b7f8f07f29e748.tar.xz yuzu-162d641a301d87d5e25ca5d677b7f8f07f29e748.zip | |
Pica/Math: Improved the design of the Vec2/Vec3/Vec4 classes and simplified rasterizer code accordingly.
- Swizzlers now return const objects so that things like "first_vec4.xyz() = some_vec3" now will fail to compile (ideally we should support some vector holding references to make this actually work).
- The methods "InsertBeforeX/Y/Z" and "Append" have been replaced by more versions of MakeVec, which now also supports building new vectors from vectors.
- Vector library now follows C++ type promotion rules (hence, the result of Vec2<u8> with another Vec2<u8> is now a Vec2<int>).
| -rw-r--r-- | src/video_core/math.h | 196 | ||||
| -rw-r--r-- | src/video_core/rasterizer.cpp | 32 | ||||
| -rw-r--r-- | src/video_core/vertex_shader.h | 3 |
3 files changed, 133 insertions, 98 deletions
diff --git a/src/video_core/math.h b/src/video_core/math.h index 7030f2cfb..ca1fb0df2 100644 --- a/src/video_core/math.h +++ b/src/video_core/math.h | |||
| @@ -39,6 +39,13 @@ template<typename T> class Vec2; | |||
| 39 | template<typename T> class Vec3; | 39 | template<typename T> class Vec3; |
| 40 | template<typename T> class Vec4; | 40 | template<typename T> class Vec4; |
| 41 | 41 | ||
| 42 | template<typename T> | ||
| 43 | static inline Vec2<T> MakeVec(const T& x, const T& y); | ||
| 44 | template<typename T> | ||
| 45 | static inline Vec3<T> MakeVec(const T& x, const T& y, const T& z); | ||
| 46 | template<typename T> | ||
| 47 | static inline Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w); | ||
| 48 | |||
| 42 | 49 | ||
| 43 | template<typename T> | 50 | template<typename T> |
| 44 | class Vec2 { | 51 | class Vec2 { |
| @@ -68,34 +75,34 @@ public: | |||
| 68 | a[0] = x; a[1] = y; | 75 | a[0] = x; a[1] = y; |
| 69 | } | 76 | } |
| 70 | 77 | ||
| 71 | Vec2 operator +(const Vec2& other) const | 78 | Vec2<decltype(T{}+T{})> operator +(const Vec2& other) const |
| 72 | { | 79 | { |
| 73 | return Vec2(x+other.x, y+other.y); | 80 | return MakeVec(x+other.x, y+other.y); |
| 74 | } | 81 | } |
| 75 | void operator += (const Vec2 &other) | 82 | void operator += (const Vec2 &other) |
| 76 | { | 83 | { |
| 77 | x+=other.x; y+=other.y; | 84 | x+=other.x; y+=other.y; |
| 78 | } | 85 | } |
| 79 | Vec2 operator -(const Vec2& other) const | 86 | Vec2<decltype(T{}-T{})> operator -(const Vec2& other) const |
| 80 | { | 87 | { |
| 81 | return Vec2(x-other.x, y-other.y); | 88 | return MakeVec(x-other.x, y-other.y); |
| 82 | } | 89 | } |
| 83 | void operator -= (const Vec2& other) | 90 | void operator -= (const Vec2& other) |
| 84 | { | 91 | { |
| 85 | x-=other.x; y-=other.y; | 92 | x-=other.x; y-=other.y; |
| 86 | } | 93 | } |
| 87 | Vec2 operator -() const | 94 | Vec2<decltype(-T{})> operator -() const |
| 88 | { | 95 | { |
| 89 | return Vec2(-x,-y); | 96 | return MakeVec(-x,-y); |
| 90 | } | 97 | } |
| 91 | Vec2 operator * (const Vec2& other) const | 98 | Vec2<decltype(T{}*T{})> operator * (const Vec2& other) const |
| 92 | { | 99 | { |
| 93 | return Vec2(x*other.x, y*other.y); | 100 | return MakeVec(x*other.x, y*other.y); |
| 94 | } | 101 | } |
| 95 | template<typename V> | 102 | template<typename V> |
| 96 | Vec2 operator * (const V& f) const | 103 | Vec2<decltype(T{}*V{})> operator * (const V& f) const |
| 97 | { | 104 | { |
| 98 | return Vec2(x*f,y*f); | 105 | return MakeVec(x*f,y*f); |
| 99 | } | 106 | } |
| 100 | template<typename V> | 107 | template<typename V> |
| 101 | void operator *= (const V& f) | 108 | void operator *= (const V& f) |
| @@ -103,9 +110,9 @@ public: | |||
| 103 | x*=f; y*=f; | 110 | x*=f; y*=f; |
| 104 | } | 111 | } |
| 105 | template<typename V> | 112 | template<typename V> |
| 106 | Vec2 operator / (const V& f) const | 113 | Vec2<decltype(T{}/V{})> operator / (const V& f) const |
| 107 | { | 114 | { |
| 108 | return Vec2(x/f,y/f); | 115 | return MakeVec(x/f,y/f); |
| 109 | } | 116 | } |
| 110 | template<typename V> | 117 | template<typename V> |
| 111 | void operator /= (const V& f) | 118 | void operator /= (const V& f) |
| @@ -152,20 +159,9 @@ public: | |||
| 152 | const T& t() const { return y; } | 159 | const T& t() const { return y; } |
| 153 | 160 | ||
| 154 | // swizzlers - create a subvector of specific components | 161 | // swizzlers - create a subvector of specific components |
| 155 | Vec2 yx() const { return Vec2(y, x); } | 162 | const Vec2 yx() const { return Vec2(y, x); } |
| 156 | Vec2 vu() const { return Vec2(y, x); } | 163 | const Vec2 vu() const { return Vec2(y, x); } |
| 157 | Vec2 ts() const { return Vec2(y, x); } | 164 | const Vec2 ts() const { return Vec2(y, x); } |
| 158 | |||
| 159 | // Inserters to add new elements to effectively create larger vectors containing this Vec2 | ||
| 160 | Vec3<T> InsertBeforeX(const T& value) { | ||
| 161 | return Vec3<T>(value, x, y); | ||
| 162 | } | ||
| 163 | Vec3<T> InsertBeforeY(const T& value) { | ||
| 164 | return Vec3<T>(x, value, y); | ||
| 165 | } | ||
| 166 | Vec3<T> Append(const T& value) { | ||
| 167 | return Vec3<T>(x, y, value); | ||
| 168 | } | ||
| 169 | }; | 165 | }; |
| 170 | 166 | ||
| 171 | template<typename T, typename V> | 167 | template<typename T, typename V> |
| @@ -193,7 +189,7 @@ public: | |||
| 193 | 189 | ||
| 194 | template<typename T2> | 190 | template<typename T2> |
| 195 | Vec3<T2> Cast() const { | 191 | Vec3<T2> Cast() const { |
| 196 | return Vec3<T2>((T2)x, (T2)y, (T2)z); | 192 | return MakeVec<T2>((T2)x, (T2)y, (T2)z); |
| 197 | } | 193 | } |
| 198 | 194 | ||
| 199 | // Only implemented for T=int and T=float | 195 | // Only implemented for T=int and T=float |
| @@ -202,7 +198,7 @@ public: | |||
| 202 | 198 | ||
| 203 | static Vec3 AssignToAll(const T& f) | 199 | static Vec3 AssignToAll(const T& f) |
| 204 | { | 200 | { |
| 205 | return Vec3<T>(f, f, f); | 201 | return MakeVec(f, f, f); |
| 206 | } | 202 | } |
| 207 | 203 | ||
| 208 | void Write(T a[3]) | 204 | void Write(T a[3]) |
| @@ -210,34 +206,34 @@ public: | |||
| 210 | a[0] = x; a[1] = y; a[2] = z; | 206 | a[0] = x; a[1] = y; a[2] = z; |
| 211 | } | 207 | } |
| 212 | 208 | ||
| 213 | Vec3 operator +(const Vec3 &other) const | 209 | Vec3<decltype(T{}+T{})> operator +(const Vec3 &other) const |
| 214 | { | 210 | { |
| 215 | return Vec3(x+other.x, y+other.y, z+other.z); | 211 | return MakeVec(x+other.x, y+other.y, z+other.z); |
| 216 | } | 212 | } |
| 217 | void operator += (const Vec3 &other) | 213 | void operator += (const Vec3 &other) |
| 218 | { | 214 | { |
| 219 | x+=other.x; y+=other.y; z+=other.z; | 215 | x+=other.x; y+=other.y; z+=other.z; |
| 220 | } | 216 | } |
| 221 | Vec3 operator -(const Vec3 &other) const | 217 | Vec3<decltype(T{}-T{})> operator -(const Vec3 &other) const |
| 222 | { | 218 | { |
| 223 | return Vec3(x-other.x, y-other.y, z-other.z); | 219 | return MakeVec(x-other.x, y-other.y, z-other.z); |
| 224 | } | 220 | } |
| 225 | void operator -= (const Vec3 &other) | 221 | void operator -= (const Vec3 &other) |
| 226 | { | 222 | { |
| 227 | x-=other.x; y-=other.y; z-=other.z; | 223 | x-=other.x; y-=other.y; z-=other.z; |
| 228 | } | 224 | } |
| 229 | Vec3 operator -() const | 225 | Vec3<decltype(-T{})> operator -() const |
| 230 | { | 226 | { |
| 231 | return Vec3(-x,-y,-z); | 227 | return MakeVec(-x,-y,-z); |
| 232 | } | 228 | } |
| 233 | Vec3 operator * (const Vec3 &other) const | 229 | Vec3<decltype(T{}*T{})> operator * (const Vec3 &other) const |
| 234 | { | 230 | { |
| 235 | return Vec3(x*other.x, y*other.y, z*other.z); | 231 | return MakeVec(x*other.x, y*other.y, z*other.z); |
| 236 | } | 232 | } |
| 237 | template<typename V> | 233 | template<typename V> |
| 238 | Vec3 operator * (const V& f) const | 234 | Vec3<decltype(T{}*V{})> operator * (const V& f) const |
| 239 | { | 235 | { |
| 240 | return Vec3(x*f,y*f,z*f); | 236 | return MakeVec(x*f,y*f,z*f); |
| 241 | } | 237 | } |
| 242 | template<typename V> | 238 | template<typename V> |
| 243 | void operator *= (const V& f) | 239 | void operator *= (const V& f) |
| @@ -245,9 +241,9 @@ public: | |||
| 245 | x*=f; y*=f; z*=f; | 241 | x*=f; y*=f; z*=f; |
| 246 | } | 242 | } |
| 247 | template<typename V> | 243 | template<typename V> |
| 248 | Vec3 operator / (const V& f) const | 244 | Vec3<decltype(T{}/V{})> operator / (const V& f) const |
| 249 | { | 245 | { |
| 250 | return Vec3(x/f,y/f,z/f); | 246 | return MakeVec(x/f,y/f,z/f); |
| 251 | } | 247 | } |
| 252 | template<typename V> | 248 | template<typename V> |
| 253 | void operator /= (const V& f) | 249 | void operator /= (const V& f) |
| @@ -310,7 +306,7 @@ public: | |||
| 310 | // swizzlers - create a subvector of specific components | 306 | // swizzlers - create a subvector of specific components |
| 311 | // e.g. Vec2 uv() { return Vec2(x,y); } | 307 | // e.g. Vec2 uv() { return Vec2(x,y); } |
| 312 | // _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all component names (x<->r) and permutations (xy<->yx) | 308 | // _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all component names (x<->r) and permutations (xy<->yx) |
| 313 | #define _DEFINE_SWIZZLER2(a, b, name) Vec2<T> name() const { return Vec2<T>(a, b); } | 309 | #define _DEFINE_SWIZZLER2(a, b, name) const Vec2<T> name() const { return Vec2<T>(a, b); } |
| 314 | #define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \ | 310 | #define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \ |
| 315 | _DEFINE_SWIZZLER2(a, b, a##b); \ | 311 | _DEFINE_SWIZZLER2(a, b, a##b); \ |
| 316 | _DEFINE_SWIZZLER2(a, b, a2##b2); \ | 312 | _DEFINE_SWIZZLER2(a, b, a2##b2); \ |
| @@ -326,20 +322,6 @@ public: | |||
| 326 | DEFINE_SWIZZLER2(y, z, g, b, v, w, t, q); | 322 | DEFINE_SWIZZLER2(y, z, g, b, v, w, t, q); |
| 327 | #undef DEFINE_SWIZZLER2 | 323 | #undef DEFINE_SWIZZLER2 |
| 328 | #undef _DEFINE_SWIZZLER2 | 324 | #undef _DEFINE_SWIZZLER2 |
| 329 | |||
| 330 | // Inserters to add new elements to effectively create larger vectors containing this Vec2 | ||
| 331 | Vec4<T> InsertBeforeX(const T& value) { | ||
| 332 | return Vec4<T>(value, x, y, z); | ||
| 333 | } | ||
| 334 | Vec4<T> InsertBeforeY(const T& value) { | ||
| 335 | return Vec4<T>(x, value, y, z); | ||
| 336 | } | ||
| 337 | Vec4<T> InsertBeforeZ(const T& value) { | ||
| 338 | return Vec4<T>(x, y, value, z); | ||
| 339 | } | ||
| 340 | Vec4<T> Append(const T& value) { | ||
| 341 | return Vec4<T>(x, y, z, value); | ||
| 342 | } | ||
| 343 | }; | 325 | }; |
| 344 | 326 | ||
| 345 | template<typename T, typename V> | 327 | template<typename T, typename V> |
| @@ -383,34 +365,34 @@ public: | |||
| 383 | a[0] = x; a[1] = y; a[2] = z; a[3] = w; | 365 | a[0] = x; a[1] = y; a[2] = z; a[3] = w; |
| 384 | } | 366 | } |
| 385 | 367 | ||
| 386 | Vec4 operator +(const Vec4& other) const | 368 | Vec4<decltype(T{}+T{})> operator +(const Vec4& other) const |
| 387 | { | 369 | { |
| 388 | return Vec4(x+other.x, y+other.y, z+other.z, w+other.w); | 370 | return MakeVec(x+other.x, y+other.y, z+other.z, w+other.w); |
| 389 | } | 371 | } |
| 390 | void operator += (const Vec4& other) | 372 | void operator += (const Vec4& other) |
| 391 | { | 373 | { |
| 392 | x+=other.x; y+=other.y; z+=other.z; w+=other.w; | 374 | x+=other.x; y+=other.y; z+=other.z; w+=other.w; |
| 393 | } | 375 | } |
| 394 | Vec4 operator -(const Vec4 &other) const | 376 | Vec4<decltype(T{}-T{})> operator -(const Vec4 &other) const |
| 395 | { | 377 | { |
| 396 | return Vec4(x-other.x, y-other.y, z-other.z, w-other.w); | 378 | return MakeVec(x-other.x, y-other.y, z-other.z, w-other.w); |
| 397 | } | 379 | } |
| 398 | void operator -= (const Vec4 &other) | 380 | void operator -= (const Vec4 &other) |
| 399 | { | 381 | { |
| 400 | x-=other.x; y-=other.y; z-=other.z; w-=other.w; | 382 | x-=other.x; y-=other.y; z-=other.z; w-=other.w; |
| 401 | } | 383 | } |
| 402 | Vec4 operator -() const | 384 | Vec4<decltype(-T{})> operator -() const |
| 403 | { | 385 | { |
| 404 | return Vec4(-x,-y,-z,-w); | 386 | return MakeVec(-x,-y,-z,-w); |
| 405 | } | 387 | } |
| 406 | Vec4 operator * (const Vec4 &other) const | 388 | Vec4<decltype(T{}*T{})> operator * (const Vec4 &other) const |
| 407 | { | 389 | { |
| 408 | return Vec4(x*other.x, y*other.y, z*other.z, w*other.w); | 390 | return MakeVec(x*other.x, y*other.y, z*other.z, w*other.w); |
| 409 | } | 391 | } |
| 410 | template<typename V> | 392 | template<typename V> |
| 411 | Vec4 operator * (const V& f) const | 393 | Vec4<decltype(T{}*V{})> operator * (const V& f) const |
| 412 | { | 394 | { |
| 413 | return Vec4(x*f,y*f,z*f,w*f); | 395 | return MakeVec(x*f,y*f,z*f,w*f); |
| 414 | } | 396 | } |
| 415 | template<typename V> | 397 | template<typename V> |
| 416 | void operator *= (const V& f) | 398 | void operator *= (const V& f) |
| @@ -418,9 +400,9 @@ public: | |||
| 418 | x*=f; y*=f; z*=f; w*=f; | 400 | x*=f; y*=f; z*=f; w*=f; |
| 419 | } | 401 | } |
| 420 | template<typename V> | 402 | template<typename V> |
| 421 | Vec4 operator / (const V& f) const | 403 | Vec4<decltype(T{}/V{})> operator / (const V& f) const |
| 422 | { | 404 | { |
| 423 | return Vec4(x/f,y/f,z/f,w/f); | 405 | return MakeVec(x/f,y/f,z/f,w/f); |
| 424 | } | 406 | } |
| 425 | template<typename V> | 407 | template<typename V> |
| 426 | void operator /= (const V& f) | 408 | void operator /= (const V& f) |
| @@ -469,7 +451,7 @@ public: | |||
| 469 | // swizzlers - create a subvector of specific components | 451 | // swizzlers - create a subvector of specific components |
| 470 | // e.g. Vec2 uv() { return Vec2(x,y); } | 452 | // e.g. Vec2 uv() { return Vec2(x,y); } |
| 471 | // _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all component names (x<->r) and permutations (xy<->yx) | 453 | // _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all component names (x<->r) and permutations (xy<->yx) |
| 472 | #define _DEFINE_SWIZZLER2(a, b, name) Vec2<T> name() const { return Vec2<T>(a, b); } | 454 | #define _DEFINE_SWIZZLER2(a, b, name) const Vec2<T> name() const { return Vec2<T>(a, b); } |
| 473 | #define DEFINE_SWIZZLER2(a, b, a2, b2) \ | 455 | #define DEFINE_SWIZZLER2(a, b, a2, b2) \ |
| 474 | _DEFINE_SWIZZLER2(a, b, a##b); \ | 456 | _DEFINE_SWIZZLER2(a, b, a##b); \ |
| 475 | _DEFINE_SWIZZLER2(a, b, a2##b2); \ | 457 | _DEFINE_SWIZZLER2(a, b, a2##b2); \ |
| @@ -485,7 +467,7 @@ public: | |||
| 485 | #undef DEFINE_SWIZZLER2 | 467 | #undef DEFINE_SWIZZLER2 |
| 486 | #undef _DEFINE_SWIZZLER2 | 468 | #undef _DEFINE_SWIZZLER2 |
| 487 | 469 | ||
| 488 | #define _DEFINE_SWIZZLER3(a, b, c, name) Vec3<T> name() const { return Vec3<T>(a, b, c); } | 470 | #define _DEFINE_SWIZZLER3(a, b, c, name) const Vec3<T> name() const { return Vec3<T>(a, b, c); } |
| 489 | #define DEFINE_SWIZZLER3(a, b, c, a2, b2, c2) \ | 471 | #define DEFINE_SWIZZLER3(a, b, c, a2, b2, c2) \ |
| 490 | _DEFINE_SWIZZLER3(a, b, c, a##b##c); \ | 472 | _DEFINE_SWIZZLER3(a, b, c, a##b##c); \ |
| 491 | _DEFINE_SWIZZLER3(a, c, b, a##c##b); \ | 473 | _DEFINE_SWIZZLER3(a, c, b, a##c##b); \ |
| @@ -510,69 +492,121 @@ public: | |||
| 510 | 492 | ||
| 511 | 493 | ||
| 512 | template<typename T, typename V> | 494 | template<typename T, typename V> |
| 513 | Vec4<T> operator * (const V& f, const Vec4<T>& vec) | 495 | Vec4<decltype(V{}*T{})> operator * (const V& f, const Vec4<T>& vec) |
| 514 | { | 496 | { |
| 515 | return Vec4<T>(f*vec.x,f*vec.y,f*vec.z,f*vec.w); | 497 | return MakeVec(f*vec.x,f*vec.y,f*vec.z,f*vec.w); |
| 516 | } | 498 | } |
| 517 | 499 | ||
| 518 | typedef Vec4<float> Vec4f; | 500 | typedef Vec4<float> Vec4f; |
| 519 | 501 | ||
| 520 | 502 | ||
| 521 | template<typename T> | 503 | template<typename T> |
| 522 | static inline T Dot(const Vec2<T>& a, const Vec2<T>& b) | 504 | static inline decltype(T{}*T{}+T{}*T{}) Dot(const Vec2<T>& a, const Vec2<T>& b) |
| 523 | { | 505 | { |
| 524 | return a.x*b.x + a.y*b.y; | 506 | return a.x*b.x + a.y*b.y; |
| 525 | } | 507 | } |
| 526 | 508 | ||
| 527 | template<typename T> | 509 | template<typename T> |
| 528 | static inline T Dot(const Vec3<T>& a, const Vec3<T>& b) | 510 | static inline decltype(T{}*T{}+T{}*T{}) Dot(const Vec3<T>& a, const Vec3<T>& b) |
| 529 | { | 511 | { |
| 530 | return a.x*b.x + a.y*b.y + a.z*b.z; | 512 | return a.x*b.x + a.y*b.y + a.z*b.z; |
| 531 | } | 513 | } |
| 532 | 514 | ||
| 533 | template<typename T> | 515 | template<typename T> |
| 534 | static inline T Dot(const Vec4<T>& a, const Vec4<T>& b) | 516 | static inline decltype(T{}*T{}+T{}*T{}) Dot(const Vec4<T>& a, const Vec4<T>& b) |
| 535 | { | 517 | { |
| 536 | return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w; | 518 | return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w; |
| 537 | } | 519 | } |
| 538 | 520 | ||
| 539 | template<typename T> | 521 | template<typename T> |
| 540 | static inline Vec3<T> Cross(const Vec3<T>& a, const Vec3<T>& b) | 522 | static inline Vec3<decltype(T{}*T{}-T{}*T{})> Cross(const Vec3<T>& a, const Vec3<T>& b) |
| 541 | { | 523 | { |
| 542 | return Vec3<T>(a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x); | 524 | return MakeVec(a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x); |
| 543 | } | 525 | } |
| 544 | 526 | ||
| 545 | // linear interpolation via float: 0.0=begin, 1.0=end | 527 | // linear interpolation via float: 0.0=begin, 1.0=end |
| 546 | template<typename X> | 528 | template<typename X> |
| 547 | static inline X Lerp(const X& begin, const X& end, const float t) | 529 | static inline decltype(X{}*float{}+X{}*float{}) Lerp(const X& begin, const X& end, const float t) |
| 548 | { | 530 | { |
| 549 | return begin*(1.f-t) + end*t; | 531 | return begin*(1.f-t) + end*t; |
| 550 | } | 532 | } |
| 551 | 533 | ||
| 552 | // linear interpolation via int: 0=begin, base=end | 534 | // linear interpolation via int: 0=begin, base=end |
| 553 | template<typename X, int base> | 535 | template<typename X, int base> |
| 554 | static inline X LerpInt(const X& begin, const X& end, const int t) | 536 | static inline decltype((X{}*int{}+X{}*int{}) / base) LerpInt(const X& begin, const X& end, const int t) |
| 555 | { | 537 | { |
| 556 | return (begin*(base-t) + end*t) / base; | 538 | return (begin*(base-t) + end*t) / base; |
| 557 | } | 539 | } |
| 558 | 540 | ||
| 559 | // Utility vector factories | 541 | // Utility vector factories |
| 560 | template<typename T> | 542 | template<typename T> |
| 561 | static inline Vec2<T> MakeVec2(const T& x, const T& y) | 543 | static inline Vec2<T> MakeVec(const T& x, const T& y) |
| 562 | { | 544 | { |
| 563 | return Vec2<T>{x, y}; | 545 | return Vec2<T>{x, y}; |
| 564 | } | 546 | } |
| 565 | 547 | ||
| 566 | template<typename T> | 548 | template<typename T> |
| 567 | static inline Vec3<T> MakeVec3(const T& x, const T& y, const T& z) | 549 | static inline Vec3<T> MakeVec(const T& x, const T& y, const T& z) |
| 568 | { | 550 | { |
| 569 | return Vec3<T>{x, y, z}; | 551 | return Vec3<T>{x, y, z}; |
| 570 | } | 552 | } |
| 571 | 553 | ||
| 572 | template<typename T> | 554 | template<typename T> |
| 573 | static inline Vec4<T> MakeVec4(const T& x, const T& y, const T& z, const T& w) | 555 | static inline Vec4<T> MakeVec(const T& x, const T& y, const Vec2<T>& zw) |
| 556 | { | ||
| 557 | return MakeVec(x, y, zw[0], zw[1]); | ||
| 558 | } | ||
| 559 | |||
| 560 | template<typename T> | ||
| 561 | static inline Vec3<T> MakeVec(const Vec2<T>& xy, const T& z) | ||
| 562 | { | ||
| 563 | return MakeVec(xy[0], xy[1], z); | ||
| 564 | } | ||
| 565 | |||
| 566 | template<typename T> | ||
| 567 | static inline Vec3<T> MakeVec(const T& x, const Vec2<T>& yz) | ||
| 568 | { | ||
| 569 | return MakeVec(x, yz[0], yz[1]); | ||
| 570 | } | ||
| 571 | |||
| 572 | template<typename T> | ||
| 573 | static inline Vec4<T> MakeVec(const T& x, const T& y, const T& z, const T& w) | ||
| 574 | { | 574 | { |
| 575 | return Vec4<T>{x, y, z, w}; | 575 | return Vec4<T>{x, y, z, w}; |
| 576 | } | 576 | } |
| 577 | 577 | ||
| 578 | template<typename T> | ||
| 579 | static inline Vec4<T> MakeVec(const Vec2<T>& xy, const T& z, const T& w) | ||
| 580 | { | ||
| 581 | return MakeVec(xy[0], xy[1], z, w); | ||
| 582 | } | ||
| 583 | |||
| 584 | template<typename T> | ||
| 585 | static inline Vec4<T> MakeVec(const T& x, const Vec2<T>& yz, const T& w) | ||
| 586 | { | ||
| 587 | return MakeVec(x, yz[0], yz[1], w); | ||
| 588 | } | ||
| 589 | |||
| 590 | // NOTE: This has priority over "Vec2<Vec2<T>> MakeVec(const Vec2<T>& x, const Vec2<T>& y)". | ||
| 591 | // Even if someone wanted to use an odd object like Vec2<Vec2<T>>, the compiler would error | ||
| 592 | // out soon enough due to misuse of the returned structure. | ||
| 593 | template<typename T> | ||
| 594 | static inline Vec4<T> MakeVec(const Vec2<T>& xy, const Vec2<T>& zw) | ||
| 595 | { | ||
| 596 | return MakeVec(xy[0], xy[1], zw[0], zw[1]); | ||
| 597 | } | ||
| 598 | |||
| 599 | template<typename T> | ||
| 600 | static inline Vec4<T> MakeVec(const Vec3<T>& xyz, const T& w) | ||
| 601 | { | ||
| 602 | return MakeVec(xyz[0], xyz[1], xyz[2], w); | ||
| 603 | } | ||
| 604 | |||
| 605 | template<typename T> | ||
| 606 | static inline Vec4<T> MakeVec(const T& x, const Vec2<T>& yzw) | ||
| 607 | { | ||
| 608 | return MakeVec(x, yzw[0], yzw[1], yzw[2]); | ||
| 609 | } | ||
| 610 | |||
| 611 | |||
| 578 | } // namespace | 612 | } // namespace |
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp index a7c1bab3e..f418518a1 100644 --- a/src/video_core/rasterizer.cpp +++ b/src/video_core/rasterizer.cpp | |||
| @@ -78,10 +78,10 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, | |||
| 78 | u16 max_x = std::max({vtxpos[0].x, vtxpos[1].x, vtxpos[2].x}); | 78 | u16 max_x = std::max({vtxpos[0].x, vtxpos[1].x, vtxpos[2].x}); |
| 79 | u16 max_y = std::max({vtxpos[0].y, vtxpos[1].y, vtxpos[2].y}); | 79 | u16 max_y = std::max({vtxpos[0].y, vtxpos[1].y, vtxpos[2].y}); |
| 80 | 80 | ||
| 81 | min_x = min_x & Fix12P4::IntMask(); | 81 | min_x &= Fix12P4::IntMask(); |
| 82 | min_y = min_y & Fix12P4::IntMask(); | 82 | min_y &= Fix12P4::IntMask(); |
| 83 | max_x = (max_x + Fix12P4::FracMask()) & Fix12P4::IntMask(); | 83 | max_x = ((max_x + Fix12P4::FracMask()) & Fix12P4::IntMask()); |
| 84 | max_y = (max_y + Fix12P4::FracMask()) & Fix12P4::IntMask(); | 84 | max_y = ((max_y + Fix12P4::FracMask()) & Fix12P4::IntMask()); |
| 85 | 85 | ||
| 86 | // Triangle filling rules: Pixels on the right-sided edge or on flat bottom edges are not | 86 | // Triangle filling rules: Pixels on the right-sided edge or on flat bottom edges are not |
| 87 | // drawn. Pixels on any other triangle border are drawn. This is implemented with three bias | 87 | // drawn. Pixels on any other triangle border are drawn. This is implemented with three bias |
| @@ -112,10 +112,10 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, | |||
| 112 | auto orient2d = [](const Math::Vec2<Fix12P4>& vtx1, | 112 | auto orient2d = [](const Math::Vec2<Fix12P4>& vtx1, |
| 113 | const Math::Vec2<Fix12P4>& vtx2, | 113 | const Math::Vec2<Fix12P4>& vtx2, |
| 114 | const Math::Vec2<Fix12P4>& vtx3) { | 114 | const Math::Vec2<Fix12P4>& vtx3) { |
| 115 | const auto vec1 = (vtx2.Cast<int>() - vtx1.Cast<int>()).Append(0); | 115 | const auto vec1 = Math::MakeVec(vtx2 - vtx1, 0); |
| 116 | const auto vec2 = (vtx3.Cast<int>() - vtx1.Cast<int>()).Append(0); | 116 | const auto vec2 = Math::MakeVec(vtx3 - vtx1, 0); |
| 117 | // TODO: There is a very small chance this will overflow for sizeof(int) == 4 | 117 | // TODO: There is a very small chance this will overflow for sizeof(int) == 4 |
| 118 | return Cross(vec1, vec2).z; | 118 | return Math::Cross(vec1, vec2).z; |
| 119 | }; | 119 | }; |
| 120 | 120 | ||
| 121 | int w0 = bias0 + orient2d(vtxpos[1].xy(), vtxpos[2].xy(), {x, y}); | 121 | int w0 = bias0 + orient2d(vtxpos[1].xy(), vtxpos[2].xy(), {x, y}); |
| @@ -143,15 +143,15 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, | |||
| 143 | // | 143 | // |
| 144 | // The generalization to three vertices is straightforward in baricentric coordinates. | 144 | // The generalization to three vertices is straightforward in baricentric coordinates. |
| 145 | auto GetInterpolatedAttribute = [&](float24 attr0, float24 attr1, float24 attr2) { | 145 | auto GetInterpolatedAttribute = [&](float24 attr0, float24 attr1, float24 attr2) { |
| 146 | auto attr_over_w = Math::MakeVec3(attr0 / v0.pos.w, | 146 | auto attr_over_w = Math::MakeVec(attr0 / v0.pos.w, |
| 147 | attr1 / v1.pos.w, | 147 | attr1 / v1.pos.w, |
| 148 | attr2 / v2.pos.w); | 148 | attr2 / v2.pos.w); |
| 149 | auto w_inverse = Math::MakeVec3(float24::FromFloat32(1.f) / v0.pos.w, | 149 | auto w_inverse = Math::MakeVec(float24::FromFloat32(1.f) / v0.pos.w, |
| 150 | float24::FromFloat32(1.f) / v1.pos.w, | 150 | float24::FromFloat32(1.f) / v1.pos.w, |
| 151 | float24::FromFloat32(1.f) / v2.pos.w); | 151 | float24::FromFloat32(1.f) / v2.pos.w); |
| 152 | auto baricentric_coordinates = Math::MakeVec3(float24::FromFloat32(w0), | 152 | auto baricentric_coordinates = Math::MakeVec(float24::FromFloat32(w0), |
| 153 | float24::FromFloat32(w1), | 153 | float24::FromFloat32(w1), |
| 154 | float24::FromFloat32(w2)); | 154 | float24::FromFloat32(w2)); |
| 155 | 155 | ||
| 156 | float24 interpolated_attr_over_w = Math::Dot(attr_over_w, baricentric_coordinates); | 156 | float24 interpolated_attr_over_w = Math::Dot(attr_over_w, baricentric_coordinates); |
| 157 | float24 interpolated_w_inverse = Math::Dot(w_inverse, baricentric_coordinates); | 157 | float24 interpolated_w_inverse = Math::Dot(w_inverse, baricentric_coordinates); |
diff --git a/src/video_core/vertex_shader.h b/src/video_core/vertex_shader.h index f0a8a5b60..847fdc450 100644 --- a/src/video_core/vertex_shader.h +++ b/src/video_core/vertex_shader.h | |||
| @@ -27,7 +27,6 @@ struct OutputVertex { | |||
| 27 | Math::Vec4<float24> dummy; // quaternions (not implemented, yet) | 27 | Math::Vec4<float24> dummy; // quaternions (not implemented, yet) |
| 28 | Math::Vec4<float24> color; | 28 | Math::Vec4<float24> color; |
| 29 | Math::Vec2<float24> tc0; | 29 | Math::Vec2<float24> tc0; |
| 30 | float24 tc0_v; | ||
| 31 | 30 | ||
| 32 | // Padding for optimal alignment | 31 | // Padding for optimal alignment |
| 33 | float24 pad[14]; | 32 | float24 pad[14]; |
| @@ -36,6 +35,7 @@ struct OutputVertex { | |||
| 36 | 35 | ||
| 37 | // position after perspective divide | 36 | // position after perspective divide |
| 38 | Math::Vec3<float24> screenpos; | 37 | Math::Vec3<float24> screenpos; |
| 38 | float24 pad2; | ||
| 39 | 39 | ||
| 40 | // Linear interpolation | 40 | // Linear interpolation |
| 41 | // factor: 0=this, 1=vtx | 41 | // factor: 0=this, 1=vtx |
| @@ -59,6 +59,7 @@ struct OutputVertex { | |||
| 59 | } | 59 | } |
| 60 | }; | 60 | }; |
| 61 | static_assert(std::is_pod<OutputVertex>::value, "Structure is not POD"); | 61 | static_assert(std::is_pod<OutputVertex>::value, "Structure is not POD"); |
| 62 | static_assert(sizeof(OutputVertex) == 32 * sizeof(float), "OutputVertex has invalid size"); | ||
| 62 | 63 | ||
| 63 | union Instruction { | 64 | union Instruction { |
| 64 | enum class OpCode : u32 { | 65 | enum class OpCode : u32 { |