diff options
Diffstat (limited to 'src/shader_recompiler/frontend/ir')
| -rw-r--r-- | src/shader_recompiler/frontend/ir/ir_emitter.cpp | 275 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/ir_emitter.h | 69 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/opcode.inc | 200 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/type.cpp | 4 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/type.h | 15 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/value.cpp | 28 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/value.h | 10 |
7 files changed, 389 insertions, 212 deletions
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index 1c5ae0109..9d7dc034c 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp | |||
| @@ -32,16 +32,16 @@ U32 IREmitter::Imm32(s32 value) const { | |||
| 32 | return U32{Value{static_cast<u32>(value)}}; | 32 | return U32{Value{static_cast<u32>(value)}}; |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | U32 IREmitter::Imm32(f32 value) const { | 35 | F32 IREmitter::Imm32(f32 value) const { |
| 36 | return U32{Value{Common::BitCast<u32>(value)}}; | 36 | return F32{Value{value}}; |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | U64 IREmitter::Imm64(u64 value) const { | 39 | U64 IREmitter::Imm64(u64 value) const { |
| 40 | return U64{Value{value}}; | 40 | return U64{Value{value}}; |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | U64 IREmitter::Imm64(f64 value) const { | 43 | F64 IREmitter::Imm64(f64 value) const { |
| 44 | return U64{Value{Common::BitCast<u64>(value)}}; | 44 | return F64{Value{value}}; |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | void IREmitter::Branch(IR::Block* label) { | 47 | void IREmitter::Branch(IR::Block* label) { |
| @@ -121,11 +121,11 @@ void IREmitter::SetOFlag(const U1& value) { | |||
| 121 | Inst(Opcode::SetOFlag, value); | 121 | Inst(Opcode::SetOFlag, value); |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | U32 IREmitter::GetAttribute(IR::Attribute attribute) { | 124 | F32 IREmitter::GetAttribute(IR::Attribute attribute) { |
| 125 | return Inst<U32>(Opcode::GetAttribute, attribute); | 125 | return Inst<F32>(Opcode::GetAttribute, attribute); |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | void IREmitter::SetAttribute(IR::Attribute attribute, const U32& value) { | 128 | void IREmitter::SetAttribute(IR::Attribute attribute, const F32& value) { |
| 129 | Inst(Opcode::SetAttribute, attribute, value); | 129 | Inst(Opcode::SetAttribute, attribute, value); |
| 130 | } | 130 | } |
| 131 | 131 | ||
| @@ -225,50 +225,113 @@ U1 IREmitter::GetOverflowFromOp(const Value& op) { | |||
| 225 | return Inst<U1>(Opcode::GetOverflowFromOp, op); | 225 | return Inst<U1>(Opcode::GetOverflowFromOp, op); |
| 226 | } | 226 | } |
| 227 | 227 | ||
| 228 | U16U32U64 IREmitter::FPAdd(const U16U32U64& a, const U16U32U64& b, FpControl control) { | 228 | F16F32F64 IREmitter::FPAdd(const F16F32F64& a, const F16F32F64& b, FpControl control) { |
| 229 | if (a.Type() != a.Type()) { | 229 | if (a.Type() != a.Type()) { |
| 230 | throw InvalidArgument("Mismatching types {} and {}", a.Type(), b.Type()); | 230 | throw InvalidArgument("Mismatching types {} and {}", a.Type(), b.Type()); |
| 231 | } | 231 | } |
| 232 | switch (a.Type()) { | 232 | switch (a.Type()) { |
| 233 | case Type::U16: | 233 | case Type::F16: |
| 234 | return Inst<U16>(Opcode::FPAdd16, Flags{control}, a, b); | 234 | return Inst<F16>(Opcode::FPAdd16, Flags{control}, a, b); |
| 235 | case Type::U32: | 235 | case Type::F32: |
| 236 | return Inst<U32>(Opcode::FPAdd32, Flags{control}, a, b); | 236 | return Inst<F32>(Opcode::FPAdd32, Flags{control}, a, b); |
| 237 | case Type::U64: | 237 | case Type::F64: |
| 238 | return Inst<U64>(Opcode::FPAdd64, Flags{control}, a, b); | 238 | return Inst<F64>(Opcode::FPAdd64, Flags{control}, a, b); |
| 239 | default: | 239 | default: |
| 240 | ThrowInvalidType(a.Type()); | 240 | ThrowInvalidType(a.Type()); |
| 241 | } | 241 | } |
| 242 | } | 242 | } |
| 243 | 243 | ||
| 244 | Value IREmitter::CompositeConstruct(const UAny& e1, const UAny& e2) { | 244 | Value IREmitter::CompositeConstruct(const Value& e1, const Value& e2) { |
| 245 | if (e1.Type() != e2.Type()) { | 245 | if (e1.Type() != e2.Type()) { |
| 246 | throw InvalidArgument("Mismatching types {} and {}", e1.Type(), e2.Type()); | 246 | throw InvalidArgument("Mismatching types {} and {}", e1.Type(), e2.Type()); |
| 247 | } | 247 | } |
| 248 | return Inst(Opcode::CompositeConstruct2, e1, e2); | 248 | switch (e1.Type()) { |
| 249 | case Type::U32: | ||
| 250 | return Inst(Opcode::CompositeConstructU32x2, e1, e2); | ||
| 251 | case Type::F16: | ||
| 252 | return Inst(Opcode::CompositeConstructF16x2, e1, e2); | ||
| 253 | case Type::F32: | ||
| 254 | return Inst(Opcode::CompositeConstructF32x2, e1, e2); | ||
| 255 | case Type::F64: | ||
| 256 | return Inst(Opcode::CompositeConstructF64x2, e1, e2); | ||
| 257 | default: | ||
| 258 | ThrowInvalidType(e1.Type()); | ||
| 259 | } | ||
| 249 | } | 260 | } |
| 250 | 261 | ||
| 251 | Value IREmitter::CompositeConstruct(const UAny& e1, const UAny& e2, const UAny& e3) { | 262 | Value IREmitter::CompositeConstruct(const Value& e1, const Value& e2, const Value& e3) { |
| 252 | if (e1.Type() != e2.Type() || e1.Type() != e3.Type()) { | 263 | if (e1.Type() != e2.Type() || e1.Type() != e3.Type()) { |
| 253 | throw InvalidArgument("Mismatching types {}, {}, and {}", e1.Type(), e2.Type(), e3.Type()); | 264 | throw InvalidArgument("Mismatching types {}, {}, and {}", e1.Type(), e2.Type(), e3.Type()); |
| 254 | } | 265 | } |
| 255 | return Inst(Opcode::CompositeConstruct3, e1, e2, e3); | 266 | switch (e1.Type()) { |
| 267 | case Type::U32: | ||
| 268 | return Inst(Opcode::CompositeConstructU32x3, e1, e2, e3); | ||
| 269 | case Type::F16: | ||
| 270 | return Inst(Opcode::CompositeConstructF16x3, e1, e2, e3); | ||
| 271 | case Type::F32: | ||
| 272 | return Inst(Opcode::CompositeConstructF32x3, e1, e2, e3); | ||
| 273 | case Type::F64: | ||
| 274 | return Inst(Opcode::CompositeConstructF64x3, e1, e2, e3); | ||
| 275 | default: | ||
| 276 | ThrowInvalidType(e1.Type()); | ||
| 277 | } | ||
| 256 | } | 278 | } |
| 257 | 279 | ||
| 258 | Value IREmitter::CompositeConstruct(const UAny& e1, const UAny& e2, const UAny& e3, | 280 | Value IREmitter::CompositeConstruct(const Value& e1, const Value& e2, const Value& e3, |
| 259 | const UAny& e4) { | 281 | const Value& e4) { |
| 260 | if (e1.Type() != e2.Type() || e1.Type() != e3.Type() || e1.Type() != e4.Type()) { | 282 | if (e1.Type() != e2.Type() || e1.Type() != e3.Type() || e1.Type() != e4.Type()) { |
| 261 | throw InvalidArgument("Mismatching types {}, {}, {}, and {}", e1.Type(), e2.Type(), | 283 | throw InvalidArgument("Mismatching types {}, {}, {}, and {}", e1.Type(), e2.Type(), |
| 262 | e3.Type(), e4.Type()); | 284 | e3.Type(), e4.Type()); |
| 263 | } | 285 | } |
| 264 | return Inst(Opcode::CompositeConstruct4, e1, e2, e3, e4); | 286 | switch (e1.Type()) { |
| 287 | case Type::U32: | ||
| 288 | return Inst(Opcode::CompositeConstructU32x4, e1, e2, e3, e4); | ||
| 289 | case Type::F16: | ||
| 290 | return Inst(Opcode::CompositeConstructF16x4, e1, e2, e3, e4); | ||
| 291 | case Type::F32: | ||
| 292 | return Inst(Opcode::CompositeConstructF32x4, e1, e2, e3, e4); | ||
| 293 | case Type::F64: | ||
| 294 | return Inst(Opcode::CompositeConstructF64x4, e1, e2, e3, e4); | ||
| 295 | default: | ||
| 296 | ThrowInvalidType(e1.Type()); | ||
| 297 | } | ||
| 265 | } | 298 | } |
| 266 | 299 | ||
| 267 | UAny IREmitter::CompositeExtract(const Value& vector, size_t element) { | 300 | Value IREmitter::CompositeExtract(const Value& vector, size_t element) { |
| 268 | if (element >= 4) { | 301 | const auto read = [&](Opcode opcode, size_t limit) -> Value { |
| 269 | throw InvalidArgument("Out of bounds element {}", element); | 302 | if (element >= limit) { |
| 303 | throw InvalidArgument("Out of bounds element {}", element); | ||
| 304 | } | ||
| 305 | return Inst(opcode, vector, Value{static_cast<u32>(element)}); | ||
| 306 | }; | ||
| 307 | switch (vector.Type()) { | ||
| 308 | case Type::U32x2: | ||
| 309 | return read(Opcode::CompositeExtractU32x2, 2); | ||
| 310 | case Type::U32x3: | ||
| 311 | return read(Opcode::CompositeExtractU32x3, 3); | ||
| 312 | case Type::U32x4: | ||
| 313 | return read(Opcode::CompositeExtractU32x4, 4); | ||
| 314 | case Type::F16x2: | ||
| 315 | return read(Opcode::CompositeExtractF16x2, 2); | ||
| 316 | case Type::F16x3: | ||
| 317 | return read(Opcode::CompositeExtractF16x3, 3); | ||
| 318 | case Type::F16x4: | ||
| 319 | return read(Opcode::CompositeExtractF16x4, 4); | ||
| 320 | case Type::F32x2: | ||
| 321 | return read(Opcode::CompositeExtractF32x2, 2); | ||
| 322 | case Type::F32x3: | ||
| 323 | return read(Opcode::CompositeExtractF32x3, 3); | ||
| 324 | case Type::F32x4: | ||
| 325 | return read(Opcode::CompositeExtractF32x4, 4); | ||
| 326 | case Type::F64x2: | ||
| 327 | return read(Opcode::CompositeExtractF64x2, 2); | ||
| 328 | case Type::F64x3: | ||
| 329 | return read(Opcode::CompositeExtractF64x3, 3); | ||
| 330 | case Type::F64x4: | ||
| 331 | return read(Opcode::CompositeExtractF64x4, 4); | ||
| 332 | default: | ||
| 333 | ThrowInvalidType(vector.Type()); | ||
| 270 | } | 334 | } |
| 271 | return Inst<UAny>(Opcode::CompositeExtract, vector, Imm32(static_cast<u32>(element))); | ||
| 272 | } | 335 | } |
| 273 | 336 | ||
| 274 | UAny IREmitter::Select(const U1& condition, const UAny& true_value, const UAny& false_value) { | 337 | UAny IREmitter::Select(const U1& condition, const UAny& true_value, const UAny& false_value) { |
| @@ -289,6 +352,36 @@ UAny IREmitter::Select(const U1& condition, const UAny& true_value, const UAny& | |||
| 289 | } | 352 | } |
| 290 | } | 353 | } |
| 291 | 354 | ||
| 355 | template <> | ||
| 356 | IR::U32 IREmitter::BitCast<IR::U32, IR::F32>(const IR::F32& value) { | ||
| 357 | return Inst<IR::U32>(Opcode::BitCastU32F32, value); | ||
| 358 | } | ||
| 359 | |||
| 360 | template <> | ||
| 361 | IR::F32 IREmitter::BitCast<IR::F32, IR::U32>(const IR::U32& value) { | ||
| 362 | return Inst<IR::F32>(Opcode::BitCastF32U32, value); | ||
| 363 | } | ||
| 364 | |||
| 365 | template <> | ||
| 366 | IR::U16 IREmitter::BitCast<IR::U16, IR::F16>(const IR::F16& value) { | ||
| 367 | return Inst<IR::U16>(Opcode::BitCastU16F16, value); | ||
| 368 | } | ||
| 369 | |||
| 370 | template <> | ||
| 371 | IR::F16 IREmitter::BitCast<IR::F16, IR::U16>(const IR::U16& value) { | ||
| 372 | return Inst<IR::F16>(Opcode::BitCastF16U16, value); | ||
| 373 | } | ||
| 374 | |||
| 375 | template <> | ||
| 376 | IR::U64 IREmitter::BitCast<IR::U64, IR::F64>(const IR::F64& value) { | ||
| 377 | return Inst<IR::U64>(Opcode::BitCastU64F64, value); | ||
| 378 | } | ||
| 379 | |||
| 380 | template <> | ||
| 381 | IR::F64 IREmitter::BitCast<IR::F64, IR::U64>(const IR::U64& value) { | ||
| 382 | return Inst<IR::F64>(Opcode::BitCastF64U64, value); | ||
| 383 | } | ||
| 384 | |||
| 292 | U64 IREmitter::PackUint2x32(const Value& vector) { | 385 | U64 IREmitter::PackUint2x32(const Value& vector) { |
| 293 | return Inst<U64>(Opcode::PackUint2x32, vector); | 386 | return Inst<U64>(Opcode::PackUint2x32, vector); |
| 294 | } | 387 | } |
| @@ -305,75 +398,75 @@ Value IREmitter::UnpackFloat2x16(const U32& value) { | |||
| 305 | return Inst<Value>(Opcode::UnpackFloat2x16, value); | 398 | return Inst<Value>(Opcode::UnpackFloat2x16, value); |
| 306 | } | 399 | } |
| 307 | 400 | ||
| 308 | U64 IREmitter::PackDouble2x32(const Value& vector) { | 401 | F64 IREmitter::PackDouble2x32(const Value& vector) { |
| 309 | return Inst<U64>(Opcode::PackDouble2x32, vector); | 402 | return Inst<F64>(Opcode::PackDouble2x32, vector); |
| 310 | } | 403 | } |
| 311 | 404 | ||
| 312 | Value IREmitter::UnpackDouble2x32(const U64& value) { | 405 | Value IREmitter::UnpackDouble2x32(const F64& value) { |
| 313 | return Inst<Value>(Opcode::UnpackDouble2x32, value); | 406 | return Inst<Value>(Opcode::UnpackDouble2x32, value); |
| 314 | } | 407 | } |
| 315 | 408 | ||
| 316 | U16U32U64 IREmitter::FPMul(const U16U32U64& a, const U16U32U64& b, FpControl control) { | 409 | F16F32F64 IREmitter::FPMul(const F16F32F64& a, const F16F32F64& b, FpControl control) { |
| 317 | if (a.Type() != b.Type()) { | 410 | if (a.Type() != b.Type()) { |
| 318 | throw InvalidArgument("Mismatching types {} and {}", a.Type(), b.Type()); | 411 | throw InvalidArgument("Mismatching types {} and {}", a.Type(), b.Type()); |
| 319 | } | 412 | } |
| 320 | switch (a.Type()) { | 413 | switch (a.Type()) { |
| 321 | case Type::U16: | 414 | case Type::F16: |
| 322 | return Inst<U16>(Opcode::FPMul16, Flags{control}, a, b); | 415 | return Inst<F16>(Opcode::FPMul16, Flags{control}, a, b); |
| 323 | case Type::U32: | 416 | case Type::F32: |
| 324 | return Inst<U32>(Opcode::FPMul32, Flags{control}, a, b); | 417 | return Inst<F32>(Opcode::FPMul32, Flags{control}, a, b); |
| 325 | case Type::U64: | 418 | case Type::F64: |
| 326 | return Inst<U64>(Opcode::FPMul64, Flags{control}, a, b); | 419 | return Inst<F64>(Opcode::FPMul64, Flags{control}, a, b); |
| 327 | default: | 420 | default: |
| 328 | ThrowInvalidType(a.Type()); | 421 | ThrowInvalidType(a.Type()); |
| 329 | } | 422 | } |
| 330 | } | 423 | } |
| 331 | 424 | ||
| 332 | U16U32U64 IREmitter::FPFma(const U16U32U64& a, const U16U32U64& b, const U16U32U64& c, | 425 | F16F32F64 IREmitter::FPFma(const F16F32F64& a, const F16F32F64& b, const F16F32F64& c, |
| 333 | FpControl control) { | 426 | FpControl control) { |
| 334 | if (a.Type() != b.Type() || a.Type() != c.Type()) { | 427 | if (a.Type() != b.Type() || a.Type() != c.Type()) { |
| 335 | throw InvalidArgument("Mismatching types {}, {}, and {}", a.Type(), b.Type(), c.Type()); | 428 | throw InvalidArgument("Mismatching types {}, {}, and {}", a.Type(), b.Type(), c.Type()); |
| 336 | } | 429 | } |
| 337 | switch (a.Type()) { | 430 | switch (a.Type()) { |
| 338 | case Type::U16: | 431 | case Type::F16: |
| 339 | return Inst<U16>(Opcode::FPFma16, Flags{control}, a, b, c); | 432 | return Inst<F16>(Opcode::FPFma16, Flags{control}, a, b, c); |
| 340 | case Type::U32: | 433 | case Type::F32: |
| 341 | return Inst<U32>(Opcode::FPFma32, Flags{control}, a, b, c); | 434 | return Inst<F32>(Opcode::FPFma32, Flags{control}, a, b, c); |
| 342 | case Type::U64: | 435 | case Type::F64: |
| 343 | return Inst<U64>(Opcode::FPFma64, Flags{control}, a, b, c); | 436 | return Inst<F64>(Opcode::FPFma64, Flags{control}, a, b, c); |
| 344 | default: | 437 | default: |
| 345 | ThrowInvalidType(a.Type()); | 438 | ThrowInvalidType(a.Type()); |
| 346 | } | 439 | } |
| 347 | } | 440 | } |
| 348 | 441 | ||
| 349 | U16U32U64 IREmitter::FPAbs(const U16U32U64& value) { | 442 | F16F32F64 IREmitter::FPAbs(const F16F32F64& value) { |
| 350 | switch (value.Type()) { | 443 | switch (value.Type()) { |
| 351 | case Type::U16: | 444 | case Type::U16: |
| 352 | return Inst<U16>(Opcode::FPAbs16, value); | 445 | return Inst<F16>(Opcode::FPAbs16, value); |
| 353 | case Type::U32: | 446 | case Type::U32: |
| 354 | return Inst<U32>(Opcode::FPAbs32, value); | 447 | return Inst<F32>(Opcode::FPAbs32, value); |
| 355 | case Type::U64: | 448 | case Type::U64: |
| 356 | return Inst<U64>(Opcode::FPAbs64, value); | 449 | return Inst<F64>(Opcode::FPAbs64, value); |
| 357 | default: | 450 | default: |
| 358 | ThrowInvalidType(value.Type()); | 451 | ThrowInvalidType(value.Type()); |
| 359 | } | 452 | } |
| 360 | } | 453 | } |
| 361 | 454 | ||
| 362 | U16U32U64 IREmitter::FPNeg(const U16U32U64& value) { | 455 | F16F32F64 IREmitter::FPNeg(const F16F32F64& value) { |
| 363 | switch (value.Type()) { | 456 | switch (value.Type()) { |
| 364 | case Type::U16: | 457 | case Type::U16: |
| 365 | return Inst<U16>(Opcode::FPNeg16, value); | 458 | return Inst<F16>(Opcode::FPNeg16, value); |
| 366 | case Type::U32: | 459 | case Type::U32: |
| 367 | return Inst<U32>(Opcode::FPNeg32, value); | 460 | return Inst<F32>(Opcode::FPNeg32, value); |
| 368 | case Type::U64: | 461 | case Type::U64: |
| 369 | return Inst<U64>(Opcode::FPNeg64, value); | 462 | return Inst<F64>(Opcode::FPNeg64, value); |
| 370 | default: | 463 | default: |
| 371 | ThrowInvalidType(value.Type()); | 464 | ThrowInvalidType(value.Type()); |
| 372 | } | 465 | } |
| 373 | } | 466 | } |
| 374 | 467 | ||
| 375 | U16U32U64 IREmitter::FPAbsNeg(const U16U32U64& value, bool abs, bool neg) { | 468 | F16F32F64 IREmitter::FPAbsNeg(const F16F32F64& value, bool abs, bool neg) { |
| 376 | U16U32U64 result{value}; | 469 | F16F32F64 result{value}; |
| 377 | if (abs) { | 470 | if (abs) { |
| 378 | result = FPAbs(value); | 471 | result = FPAbs(value); |
| 379 | } | 472 | } |
| @@ -383,108 +476,108 @@ U16U32U64 IREmitter::FPAbsNeg(const U16U32U64& value, bool abs, bool neg) { | |||
| 383 | return result; | 476 | return result; |
| 384 | } | 477 | } |
| 385 | 478 | ||
| 386 | U32 IREmitter::FPCosNotReduced(const U32& value) { | 479 | F32 IREmitter::FPCosNotReduced(const F32& value) { |
| 387 | return Inst<U32>(Opcode::FPCosNotReduced, value); | 480 | return Inst<F32>(Opcode::FPCosNotReduced, value); |
| 388 | } | 481 | } |
| 389 | 482 | ||
| 390 | U32 IREmitter::FPExp2NotReduced(const U32& value) { | 483 | F32 IREmitter::FPExp2NotReduced(const F32& value) { |
| 391 | return Inst<U32>(Opcode::FPExp2NotReduced, value); | 484 | return Inst<F32>(Opcode::FPExp2NotReduced, value); |
| 392 | } | 485 | } |
| 393 | 486 | ||
| 394 | U32 IREmitter::FPLog2(const U32& value) { | 487 | F32 IREmitter::FPLog2(const F32& value) { |
| 395 | return Inst<U32>(Opcode::FPLog2, value); | 488 | return Inst<F32>(Opcode::FPLog2, value); |
| 396 | } | 489 | } |
| 397 | 490 | ||
| 398 | U32U64 IREmitter::FPRecip(const U32U64& value) { | 491 | F32F64 IREmitter::FPRecip(const F32F64& value) { |
| 399 | switch (value.Type()) { | 492 | switch (value.Type()) { |
| 400 | case Type::U32: | 493 | case Type::U32: |
| 401 | return Inst<U32>(Opcode::FPRecip32, value); | 494 | return Inst<F32>(Opcode::FPRecip32, value); |
| 402 | case Type::U64: | 495 | case Type::U64: |
| 403 | return Inst<U64>(Opcode::FPRecip64, value); | 496 | return Inst<F64>(Opcode::FPRecip64, value); |
| 404 | default: | 497 | default: |
| 405 | ThrowInvalidType(value.Type()); | 498 | ThrowInvalidType(value.Type()); |
| 406 | } | 499 | } |
| 407 | } | 500 | } |
| 408 | 501 | ||
| 409 | U32U64 IREmitter::FPRecipSqrt(const U32U64& value) { | 502 | F32F64 IREmitter::FPRecipSqrt(const F32F64& value) { |
| 410 | switch (value.Type()) { | 503 | switch (value.Type()) { |
| 411 | case Type::U32: | 504 | case Type::U32: |
| 412 | return Inst<U32>(Opcode::FPRecipSqrt32, value); | 505 | return Inst<F32>(Opcode::FPRecipSqrt32, value); |
| 413 | case Type::U64: | 506 | case Type::U64: |
| 414 | return Inst<U64>(Opcode::FPRecipSqrt64, value); | 507 | return Inst<F64>(Opcode::FPRecipSqrt64, value); |
| 415 | default: | 508 | default: |
| 416 | ThrowInvalidType(value.Type()); | 509 | ThrowInvalidType(value.Type()); |
| 417 | } | 510 | } |
| 418 | } | 511 | } |
| 419 | 512 | ||
| 420 | U32 IREmitter::FPSinNotReduced(const U32& value) { | 513 | F32 IREmitter::FPSinNotReduced(const F32& value) { |
| 421 | return Inst<U32>(Opcode::FPSinNotReduced, value); | 514 | return Inst<F32>(Opcode::FPSinNotReduced, value); |
| 422 | } | 515 | } |
| 423 | 516 | ||
| 424 | U32 IREmitter::FPSqrt(const U32& value) { | 517 | F32 IREmitter::FPSqrt(const F32& value) { |
| 425 | return Inst<U32>(Opcode::FPSqrt, value); | 518 | return Inst<F32>(Opcode::FPSqrt, value); |
| 426 | } | 519 | } |
| 427 | 520 | ||
| 428 | U16U32U64 IREmitter::FPSaturate(const U16U32U64& value) { | 521 | F16F32F64 IREmitter::FPSaturate(const F16F32F64& value) { |
| 429 | switch (value.Type()) { | 522 | switch (value.Type()) { |
| 430 | case Type::U16: | 523 | case Type::U16: |
| 431 | return Inst<U16>(Opcode::FPSaturate16, value); | 524 | return Inst<F16>(Opcode::FPSaturate16, value); |
| 432 | case Type::U32: | 525 | case Type::U32: |
| 433 | return Inst<U32>(Opcode::FPSaturate32, value); | 526 | return Inst<F32>(Opcode::FPSaturate32, value); |
| 434 | case Type::U64: | 527 | case Type::U64: |
| 435 | return Inst<U64>(Opcode::FPSaturate64, value); | 528 | return Inst<F64>(Opcode::FPSaturate64, value); |
| 436 | default: | 529 | default: |
| 437 | ThrowInvalidType(value.Type()); | 530 | ThrowInvalidType(value.Type()); |
| 438 | } | 531 | } |
| 439 | } | 532 | } |
| 440 | 533 | ||
| 441 | U16U32U64 IREmitter::FPRoundEven(const U16U32U64& value) { | 534 | F16F32F64 IREmitter::FPRoundEven(const F16F32F64& value) { |
| 442 | switch (value.Type()) { | 535 | switch (value.Type()) { |
| 443 | case Type::U16: | 536 | case Type::U16: |
| 444 | return Inst<U16>(Opcode::FPRoundEven16, value); | 537 | return Inst<F16>(Opcode::FPRoundEven16, value); |
| 445 | case Type::U32: | 538 | case Type::U32: |
| 446 | return Inst<U32>(Opcode::FPRoundEven32, value); | 539 | return Inst<F32>(Opcode::FPRoundEven32, value); |
| 447 | case Type::U64: | 540 | case Type::U64: |
| 448 | return Inst<U64>(Opcode::FPRoundEven64, value); | 541 | return Inst<F64>(Opcode::FPRoundEven64, value); |
| 449 | default: | 542 | default: |
| 450 | ThrowInvalidType(value.Type()); | 543 | ThrowInvalidType(value.Type()); |
| 451 | } | 544 | } |
| 452 | } | 545 | } |
| 453 | 546 | ||
| 454 | U16U32U64 IREmitter::FPFloor(const U16U32U64& value) { | 547 | F16F32F64 IREmitter::FPFloor(const F16F32F64& value) { |
| 455 | switch (value.Type()) { | 548 | switch (value.Type()) { |
| 456 | case Type::U16: | 549 | case Type::U16: |
| 457 | return Inst<U16>(Opcode::FPFloor16, value); | 550 | return Inst<F16>(Opcode::FPFloor16, value); |
| 458 | case Type::U32: | 551 | case Type::U32: |
| 459 | return Inst<U32>(Opcode::FPFloor32, value); | 552 | return Inst<F32>(Opcode::FPFloor32, value); |
| 460 | case Type::U64: | 553 | case Type::U64: |
| 461 | return Inst<U64>(Opcode::FPFloor64, value); | 554 | return Inst<F64>(Opcode::FPFloor64, value); |
| 462 | default: | 555 | default: |
| 463 | ThrowInvalidType(value.Type()); | 556 | ThrowInvalidType(value.Type()); |
| 464 | } | 557 | } |
| 465 | } | 558 | } |
| 466 | 559 | ||
| 467 | U16U32U64 IREmitter::FPCeil(const U16U32U64& value) { | 560 | F16F32F64 IREmitter::FPCeil(const F16F32F64& value) { |
| 468 | switch (value.Type()) { | 561 | switch (value.Type()) { |
| 469 | case Type::U16: | 562 | case Type::U16: |
| 470 | return Inst<U16>(Opcode::FPCeil16, value); | 563 | return Inst<F16>(Opcode::FPCeil16, value); |
| 471 | case Type::U32: | 564 | case Type::U32: |
| 472 | return Inst<U32>(Opcode::FPCeil32, value); | 565 | return Inst<F32>(Opcode::FPCeil32, value); |
| 473 | case Type::U64: | 566 | case Type::U64: |
| 474 | return Inst<U64>(Opcode::FPCeil64, value); | 567 | return Inst<F64>(Opcode::FPCeil64, value); |
| 475 | default: | 568 | default: |
| 476 | ThrowInvalidType(value.Type()); | 569 | ThrowInvalidType(value.Type()); |
| 477 | } | 570 | } |
| 478 | } | 571 | } |
| 479 | 572 | ||
| 480 | U16U32U64 IREmitter::FPTrunc(const U16U32U64& value) { | 573 | F16F32F64 IREmitter::FPTrunc(const F16F32F64& value) { |
| 481 | switch (value.Type()) { | 574 | switch (value.Type()) { |
| 482 | case Type::U16: | 575 | case Type::U16: |
| 483 | return Inst<U16>(Opcode::FPTrunc16, value); | 576 | return Inst<F16>(Opcode::FPTrunc16, value); |
| 484 | case Type::U32: | 577 | case Type::U32: |
| 485 | return Inst<U32>(Opcode::FPTrunc32, value); | 578 | return Inst<F32>(Opcode::FPTrunc32, value); |
| 486 | case Type::U64: | 579 | case Type::U64: |
| 487 | return Inst<U64>(Opcode::FPTrunc64, value); | 580 | return Inst<F64>(Opcode::FPTrunc64, value); |
| 488 | default: | 581 | default: |
| 489 | ThrowInvalidType(value.Type()); | 582 | ThrowInvalidType(value.Type()); |
| 490 | } | 583 | } |
| @@ -605,7 +698,7 @@ U1 IREmitter::LogicalNot(const U1& value) { | |||
| 605 | return Inst<U1>(Opcode::LogicalNot, value); | 698 | return Inst<U1>(Opcode::LogicalNot, value); |
| 606 | } | 699 | } |
| 607 | 700 | ||
| 608 | U32U64 IREmitter::ConvertFToS(size_t bitsize, const U16U32U64& value) { | 701 | U32U64 IREmitter::ConvertFToS(size_t bitsize, const F16F32F64& value) { |
| 609 | switch (bitsize) { | 702 | switch (bitsize) { |
| 610 | case 16: | 703 | case 16: |
| 611 | switch (value.Type()) { | 704 | switch (value.Type()) { |
| @@ -645,7 +738,7 @@ U32U64 IREmitter::ConvertFToS(size_t bitsize, const U16U32U64& value) { | |||
| 645 | } | 738 | } |
| 646 | } | 739 | } |
| 647 | 740 | ||
| 648 | U32U64 IREmitter::ConvertFToU(size_t bitsize, const U16U32U64& value) { | 741 | U32U64 IREmitter::ConvertFToU(size_t bitsize, const F16F32F64& value) { |
| 649 | switch (bitsize) { | 742 | switch (bitsize) { |
| 650 | case 16: | 743 | case 16: |
| 651 | switch (value.Type()) { | 744 | switch (value.Type()) { |
| @@ -685,7 +778,7 @@ U32U64 IREmitter::ConvertFToU(size_t bitsize, const U16U32U64& value) { | |||
| 685 | } | 778 | } |
| 686 | } | 779 | } |
| 687 | 780 | ||
| 688 | U32U64 IREmitter::ConvertFToI(size_t bitsize, bool is_signed, const U16U32U64& value) { | 781 | U32U64 IREmitter::ConvertFToI(size_t bitsize, bool is_signed, const F16F32F64& value) { |
| 689 | if (is_signed) { | 782 | if (is_signed) { |
| 690 | return ConvertFToS(bitsize, value); | 783 | return ConvertFToS(bitsize, value); |
| 691 | } else { | 784 | } else { |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index 84b844898..bfd9916cc 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h | |||
| @@ -27,9 +27,9 @@ public: | |||
| 27 | [[nodiscard]] U16 Imm16(u16 value) const; | 27 | [[nodiscard]] U16 Imm16(u16 value) const; |
| 28 | [[nodiscard]] U32 Imm32(u32 value) const; | 28 | [[nodiscard]] U32 Imm32(u32 value) const; |
| 29 | [[nodiscard]] U32 Imm32(s32 value) const; | 29 | [[nodiscard]] U32 Imm32(s32 value) const; |
| 30 | [[nodiscard]] U32 Imm32(f32 value) const; | 30 | [[nodiscard]] F32 Imm32(f32 value) const; |
| 31 | [[nodiscard]] U64 Imm64(u64 value) const; | 31 | [[nodiscard]] U64 Imm64(u64 value) const; |
| 32 | [[nodiscard]] U64 Imm64(f64 value) const; | 32 | [[nodiscard]] F64 Imm64(f64 value) const; |
| 33 | 33 | ||
| 34 | void Branch(IR::Block* label); | 34 | void Branch(IR::Block* label); |
| 35 | void BranchConditional(const U1& cond, IR::Block* true_label, IR::Block* false_label); | 35 | void BranchConditional(const U1& cond, IR::Block* true_label, IR::Block* false_label); |
| @@ -55,8 +55,8 @@ public: | |||
| 55 | void SetCFlag(const U1& value); | 55 | void SetCFlag(const U1& value); |
| 56 | void SetOFlag(const U1& value); | 56 | void SetOFlag(const U1& value); |
| 57 | 57 | ||
| 58 | [[nodiscard]] U32 GetAttribute(IR::Attribute attribute); | 58 | [[nodiscard]] F32 GetAttribute(IR::Attribute attribute); |
| 59 | void SetAttribute(IR::Attribute attribute, const U32& value); | 59 | void SetAttribute(IR::Attribute attribute, const F32& value); |
| 60 | 60 | ||
| 61 | [[nodiscard]] U32 WorkgroupIdX(); | 61 | [[nodiscard]] U32 WorkgroupIdX(); |
| 62 | [[nodiscard]] U32 WorkgroupIdY(); | 62 | [[nodiscard]] U32 WorkgroupIdY(); |
| @@ -87,44 +87,47 @@ public: | |||
| 87 | [[nodiscard]] U1 GetCarryFromOp(const Value& op); | 87 | [[nodiscard]] U1 GetCarryFromOp(const Value& op); |
| 88 | [[nodiscard]] U1 GetOverflowFromOp(const Value& op); | 88 | [[nodiscard]] U1 GetOverflowFromOp(const Value& op); |
| 89 | 89 | ||
| 90 | [[nodiscard]] Value CompositeConstruct(const UAny& e1, const UAny& e2); | 90 | [[nodiscard]] Value CompositeConstruct(const Value& e1, const Value& e2); |
| 91 | [[nodiscard]] Value CompositeConstruct(const UAny& e1, const UAny& e2, const UAny& e3); | 91 | [[nodiscard]] Value CompositeConstruct(const Value& e1, const Value& e2, const Value& e3); |
| 92 | [[nodiscard]] Value CompositeConstruct(const UAny& e1, const UAny& e2, const UAny& e3, | 92 | [[nodiscard]] Value CompositeConstruct(const Value& e1, const Value& e2, const Value& e3, |
| 93 | const UAny& e4); | 93 | const Value& e4); |
| 94 | [[nodiscard]] UAny CompositeExtract(const Value& vector, size_t element); | 94 | [[nodiscard]] Value CompositeExtract(const Value& vector, size_t element); |
| 95 | 95 | ||
| 96 | [[nodiscard]] UAny Select(const U1& condition, const UAny& true_value, const UAny& false_value); | 96 | [[nodiscard]] UAny Select(const U1& condition, const UAny& true_value, const UAny& false_value); |
| 97 | 97 | ||
| 98 | template <typename Dest, typename Source> | ||
| 99 | [[nodiscard]] Dest BitCast(const Source& value); | ||
| 100 | |||
| 98 | [[nodiscard]] U64 PackUint2x32(const Value& vector); | 101 | [[nodiscard]] U64 PackUint2x32(const Value& vector); |
| 99 | [[nodiscard]] Value UnpackUint2x32(const U64& value); | 102 | [[nodiscard]] Value UnpackUint2x32(const U64& value); |
| 100 | 103 | ||
| 101 | [[nodiscard]] U32 PackFloat2x16(const Value& vector); | 104 | [[nodiscard]] U32 PackFloat2x16(const Value& vector); |
| 102 | [[nodiscard]] Value UnpackFloat2x16(const U32& value); | 105 | [[nodiscard]] Value UnpackFloat2x16(const U32& value); |
| 103 | 106 | ||
| 104 | [[nodiscard]] U64 PackDouble2x32(const Value& vector); | 107 | [[nodiscard]] F64 PackDouble2x32(const Value& vector); |
| 105 | [[nodiscard]] Value UnpackDouble2x32(const U64& value); | 108 | [[nodiscard]] Value UnpackDouble2x32(const F64& value); |
| 106 | 109 | ||
| 107 | [[nodiscard]] U16U32U64 FPAdd(const U16U32U64& a, const U16U32U64& b, FpControl control = {}); | 110 | [[nodiscard]] F16F32F64 FPAdd(const F16F32F64& a, const F16F32F64& b, FpControl control = {}); |
| 108 | [[nodiscard]] U16U32U64 FPMul(const U16U32U64& a, const U16U32U64& b, FpControl control = {}); | 111 | [[nodiscard]] F16F32F64 FPMul(const F16F32F64& a, const F16F32F64& b, FpControl control = {}); |
| 109 | [[nodiscard]] U16U32U64 FPFma(const U16U32U64& a, const U16U32U64& b, const U16U32U64& c, | 112 | [[nodiscard]] F16F32F64 FPFma(const F16F32F64& a, const F16F32F64& b, const F16F32F64& c, |
| 110 | FpControl control = {}); | 113 | FpControl control = {}); |
| 111 | 114 | ||
| 112 | [[nodiscard]] U16U32U64 FPAbs(const U16U32U64& value); | 115 | [[nodiscard]] F16F32F64 FPAbs(const F16F32F64& value); |
| 113 | [[nodiscard]] U16U32U64 FPNeg(const U16U32U64& value); | 116 | [[nodiscard]] F16F32F64 FPNeg(const F16F32F64& value); |
| 114 | [[nodiscard]] U16U32U64 FPAbsNeg(const U16U32U64& value, bool abs, bool neg); | 117 | [[nodiscard]] F16F32F64 FPAbsNeg(const F16F32F64& value, bool abs, bool neg); |
| 115 | 118 | ||
| 116 | [[nodiscard]] U32 FPCosNotReduced(const U32& value); | 119 | [[nodiscard]] F32 FPCosNotReduced(const F32& value); |
| 117 | [[nodiscard]] U32 FPExp2NotReduced(const U32& value); | 120 | [[nodiscard]] F32 FPExp2NotReduced(const F32& value); |
| 118 | [[nodiscard]] U32 FPLog2(const U32& value); | 121 | [[nodiscard]] F32 FPLog2(const F32& value); |
| 119 | [[nodiscard]] U32U64 FPRecip(const U32U64& value); | 122 | [[nodiscard]] F32F64 FPRecip(const F32F64& value); |
| 120 | [[nodiscard]] U32U64 FPRecipSqrt(const U32U64& value); | 123 | [[nodiscard]] F32F64 FPRecipSqrt(const F32F64& value); |
| 121 | [[nodiscard]] U32 FPSinNotReduced(const U32& value); | 124 | [[nodiscard]] F32 FPSinNotReduced(const F32& value); |
| 122 | [[nodiscard]] U32 FPSqrt(const U32& value); | 125 | [[nodiscard]] F32 FPSqrt(const F32& value); |
| 123 | [[nodiscard]] U16U32U64 FPSaturate(const U16U32U64& value); | 126 | [[nodiscard]] F16F32F64 FPSaturate(const F16F32F64& value); |
| 124 | [[nodiscard]] U16U32U64 FPRoundEven(const U16U32U64& value); | 127 | [[nodiscard]] F16F32F64 FPRoundEven(const F16F32F64& value); |
| 125 | [[nodiscard]] U16U32U64 FPFloor(const U16U32U64& value); | 128 | [[nodiscard]] F16F32F64 FPFloor(const F16F32F64& value); |
| 126 | [[nodiscard]] U16U32U64 FPCeil(const U16U32U64& value); | 129 | [[nodiscard]] F16F32F64 FPCeil(const F16F32F64& value); |
| 127 | [[nodiscard]] U16U32U64 FPTrunc(const U16U32U64& value); | 130 | [[nodiscard]] F16F32F64 FPTrunc(const F16F32F64& value); |
| 128 | 131 | ||
| 129 | [[nodiscard]] U32U64 IAdd(const U32U64& a, const U32U64& b); | 132 | [[nodiscard]] U32U64 IAdd(const U32U64& a, const U32U64& b); |
| 130 | [[nodiscard]] U32U64 ISub(const U32U64& a, const U32U64& b); | 133 | [[nodiscard]] U32U64 ISub(const U32U64& a, const U32U64& b); |
| @@ -154,9 +157,9 @@ public: | |||
| 154 | [[nodiscard]] U1 LogicalXor(const U1& a, const U1& b); | 157 | [[nodiscard]] U1 LogicalXor(const U1& a, const U1& b); |
| 155 | [[nodiscard]] U1 LogicalNot(const U1& value); | 158 | [[nodiscard]] U1 LogicalNot(const U1& value); |
| 156 | 159 | ||
| 157 | [[nodiscard]] U32U64 ConvertFToS(size_t bitsize, const U16U32U64& value); | 160 | [[nodiscard]] U32U64 ConvertFToS(size_t bitsize, const F16F32F64& value); |
| 158 | [[nodiscard]] U32U64 ConvertFToU(size_t bitsize, const U16U32U64& value); | 161 | [[nodiscard]] U32U64 ConvertFToU(size_t bitsize, const F16F32F64& value); |
| 159 | [[nodiscard]] U32U64 ConvertFToI(size_t bitsize, bool is_signed, const U16U32U64& value); | 162 | [[nodiscard]] U32U64 ConvertFToI(size_t bitsize, bool is_signed, const F16F32F64& value); |
| 160 | 163 | ||
| 161 | [[nodiscard]] U32U64 ConvertU(size_t result_bitsize, const U32U64& value); | 164 | [[nodiscard]] U32U64 ConvertU(size_t result_bitsize, const U32U64& value); |
| 162 | 165 | ||
diff --git a/src/shader_recompiler/frontend/ir/opcode.inc b/src/shader_recompiler/frontend/ir/opcode.inc index 4596bf39f..6eb105d92 100644 --- a/src/shader_recompiler/frontend/ir/opcode.inc +++ b/src/shader_recompiler/frontend/ir/opcode.inc | |||
| @@ -52,15 +52,15 @@ OPCODE(LoadGlobalS8, U32, U64, | |||
| 52 | OPCODE(LoadGlobalU16, U32, U64, ) | 52 | OPCODE(LoadGlobalU16, U32, U64, ) |
| 53 | OPCODE(LoadGlobalS16, U32, U64, ) | 53 | OPCODE(LoadGlobalS16, U32, U64, ) |
| 54 | OPCODE(LoadGlobal32, U32, U64, ) | 54 | OPCODE(LoadGlobal32, U32, U64, ) |
| 55 | OPCODE(LoadGlobal64, Opaque, U64, ) | 55 | OPCODE(LoadGlobal64, U32x2, U64, ) |
| 56 | OPCODE(LoadGlobal128, Opaque, U64, ) | 56 | OPCODE(LoadGlobal128, U32x4, U64, ) |
| 57 | OPCODE(WriteGlobalU8, Void, U64, U32, ) | 57 | OPCODE(WriteGlobalU8, Void, U64, U32, ) |
| 58 | OPCODE(WriteGlobalS8, Void, U64, U32, ) | 58 | OPCODE(WriteGlobalS8, Void, U64, U32, ) |
| 59 | OPCODE(WriteGlobalU16, Void, U64, U32, ) | 59 | OPCODE(WriteGlobalU16, Void, U64, U32, ) |
| 60 | OPCODE(WriteGlobalS16, Void, U64, U32, ) | 60 | OPCODE(WriteGlobalS16, Void, U64, U32, ) |
| 61 | OPCODE(WriteGlobal32, Void, U64, U32, ) | 61 | OPCODE(WriteGlobal32, Void, U64, U32, ) |
| 62 | OPCODE(WriteGlobal64, Void, U64, Opaque, ) | 62 | OPCODE(WriteGlobal64, Void, U64, U32x2, ) |
| 63 | OPCODE(WriteGlobal128, Void, U64, Opaque, ) | 63 | OPCODE(WriteGlobal128, Void, U64, U32x4, ) |
| 64 | 64 | ||
| 65 | // Storage buffer operations | 65 | // Storage buffer operations |
| 66 | OPCODE(LoadStorageU8, U32, U32, U32, ) | 66 | OPCODE(LoadStorageU8, U32, U32, U32, ) |
| @@ -68,21 +68,41 @@ OPCODE(LoadStorageS8, U32, U32, | |||
| 68 | OPCODE(LoadStorageU16, U32, U32, U32, ) | 68 | OPCODE(LoadStorageU16, U32, U32, U32, ) |
| 69 | OPCODE(LoadStorageS16, U32, U32, U32, ) | 69 | OPCODE(LoadStorageS16, U32, U32, U32, ) |
| 70 | OPCODE(LoadStorage32, U32, U32, U32, ) | 70 | OPCODE(LoadStorage32, U32, U32, U32, ) |
| 71 | OPCODE(LoadStorage64, Opaque, U32, U32, ) | 71 | OPCODE(LoadStorage64, U32x2, U32, U32, ) |
| 72 | OPCODE(LoadStorage128, Opaque, U32, U32, ) | 72 | OPCODE(LoadStorage128, U32x4, U32, U32, ) |
| 73 | OPCODE(WriteStorageU8, Void, U32, U32, U32, ) | 73 | OPCODE(WriteStorageU8, Void, U32, U32, U32, ) |
| 74 | OPCODE(WriteStorageS8, Void, U32, U32, U32, ) | 74 | OPCODE(WriteStorageS8, Void, U32, U32, U32, ) |
| 75 | OPCODE(WriteStorageU16, Void, U32, U32, U32, ) | 75 | OPCODE(WriteStorageU16, Void, U32, U32, U32, ) |
| 76 | OPCODE(WriteStorageS16, Void, U32, U32, U32, ) | 76 | OPCODE(WriteStorageS16, Void, U32, U32, U32, ) |
| 77 | OPCODE(WriteStorage32, Void, U32, U32, U32, ) | 77 | OPCODE(WriteStorage32, Void, U32, U32, U32, ) |
| 78 | OPCODE(WriteStorage64, Void, U32, U32, Opaque, ) | 78 | OPCODE(WriteStorage64, Void, U32, U32, U32x2, ) |
| 79 | OPCODE(WriteStorage128, Void, U32, U32, Opaque, ) | 79 | OPCODE(WriteStorage128, Void, U32, U32, U32x4, ) |
| 80 | 80 | ||
| 81 | // Vector utility | 81 | // Vector utility |
| 82 | OPCODE(CompositeConstruct2, Opaque, Opaque, Opaque, ) | 82 | OPCODE(CompositeConstructU32x2, U32x2, U32, U32, ) |
| 83 | OPCODE(CompositeConstruct3, Opaque, Opaque, Opaque, Opaque, ) | 83 | OPCODE(CompositeConstructU32x3, U32x3, U32, U32, U32, ) |
| 84 | OPCODE(CompositeConstruct4, Opaque, Opaque, Opaque, Opaque, Opaque, ) | 84 | OPCODE(CompositeConstructU32x4, U32x4, U32, U32, U32, U32, ) |
| 85 | OPCODE(CompositeExtract, Opaque, Opaque, U32, ) | 85 | OPCODE(CompositeExtractU32x2, U32, U32x2, U32, ) |
| 86 | OPCODE(CompositeExtractU32x3, U32, U32x3, U32, ) | ||
| 87 | OPCODE(CompositeExtractU32x4, U32, U32x4, U32, ) | ||
| 88 | OPCODE(CompositeConstructF16x2, F16x2, F16, F16, ) | ||
| 89 | OPCODE(CompositeConstructF16x3, F16x3, F16, F16, F16, ) | ||
| 90 | OPCODE(CompositeConstructF16x4, F16x4, F16, F16, F16, F16, ) | ||
| 91 | OPCODE(CompositeExtractF16x2, F16, F16x2, U32, ) | ||
| 92 | OPCODE(CompositeExtractF16x3, F16, F16x3, U32, ) | ||
| 93 | OPCODE(CompositeExtractF16x4, F16, F16x4, U32, ) | ||
| 94 | OPCODE(CompositeConstructF32x2, F32x2, F32, F32, ) | ||
| 95 | OPCODE(CompositeConstructF32x3, F32x3, F32, F32, F32, ) | ||
| 96 | OPCODE(CompositeConstructF32x4, F32x4, F32, F32, F32, F32, ) | ||
| 97 | OPCODE(CompositeExtractF32x2, F32, F32x2, U32, ) | ||
| 98 | OPCODE(CompositeExtractF32x3, F32, F32x3, U32, ) | ||
| 99 | OPCODE(CompositeExtractF32x4, F32, F32x4, U32, ) | ||
| 100 | OPCODE(CompositeConstructF64x2, F64x2, F64, F64, ) | ||
| 101 | OPCODE(CompositeConstructF64x3, F64x3, F64, F64, F64, ) | ||
| 102 | OPCODE(CompositeConstructF64x4, F64x4, F64, F64, F64, F64, ) | ||
| 103 | OPCODE(CompositeExtractF64x2, F64, F64x2, U32, ) | ||
| 104 | OPCODE(CompositeExtractF64x3, F64, F64x3, U32, ) | ||
| 105 | OPCODE(CompositeExtractF64x4, F64, F64x4, U32, ) | ||
| 86 | 106 | ||
| 87 | // Select operations | 107 | // Select operations |
| 88 | OPCODE(Select8, U8, U1, U8, U8, ) | 108 | OPCODE(Select8, U8, U1, U8, U8, ) |
| @@ -91,12 +111,18 @@ OPCODE(Select32, U32, U1, | |||
| 91 | OPCODE(Select64, U64, U1, U64, U64, ) | 111 | OPCODE(Select64, U64, U1, U64, U64, ) |
| 92 | 112 | ||
| 93 | // Bitwise conversions | 113 | // Bitwise conversions |
| 94 | OPCODE(PackUint2x32, U64, Opaque, ) | 114 | OPCODE(BitCastU16F16, U16, F16, ) |
| 95 | OPCODE(UnpackUint2x32, Opaque, U64, ) | 115 | OPCODE(BitCastU32F32, U32, F32, ) |
| 96 | OPCODE(PackFloat2x16, U32, Opaque, ) | 116 | OPCODE(BitCastU64F64, U64, F64, ) |
| 97 | OPCODE(UnpackFloat2x16, Opaque, U32, ) | 117 | OPCODE(BitCastF16U16, F16, U16, ) |
| 98 | OPCODE(PackDouble2x32, U64, Opaque, ) | 118 | OPCODE(BitCastF32U32, F32, U32, ) |
| 99 | OPCODE(UnpackDouble2x32, Opaque, U64, ) | 119 | OPCODE(BitCastF64U64, F64, U64, ) |
| 120 | OPCODE(PackUint2x32, U64, U32x2, ) | ||
| 121 | OPCODE(UnpackUint2x32, U32x2, U64, ) | ||
| 122 | OPCODE(PackFloat2x16, U32, F16x2, ) | ||
| 123 | OPCODE(UnpackFloat2x16, F16x2, U32, ) | ||
| 124 | OPCODE(PackDouble2x32, U64, U32x2, ) | ||
| 125 | OPCODE(UnpackDouble2x32, U32x2, U64, ) | ||
| 100 | 126 | ||
| 101 | // Pseudo-operation, handled specially at final emit | 127 | // Pseudo-operation, handled specially at final emit |
| 102 | OPCODE(GetZeroFromOp, U1, Opaque, ) | 128 | OPCODE(GetZeroFromOp, U1, Opaque, ) |
| @@ -105,52 +131,52 @@ OPCODE(GetCarryFromOp, U1, Opaq | |||
| 105 | OPCODE(GetOverflowFromOp, U1, Opaque, ) | 131 | OPCODE(GetOverflowFromOp, U1, Opaque, ) |
| 106 | 132 | ||
| 107 | // Floating-point operations | 133 | // Floating-point operations |
| 108 | OPCODE(FPAbs16, U16, U16, ) | 134 | OPCODE(FPAbs16, F16, F16, ) |
| 109 | OPCODE(FPAbs32, U32, U32, ) | 135 | OPCODE(FPAbs32, F32, F32, ) |
| 110 | OPCODE(FPAbs64, U64, U64, ) | 136 | OPCODE(FPAbs64, F64, F64, ) |
| 111 | OPCODE(FPAdd16, U16, U16, U16, ) | 137 | OPCODE(FPAdd16, F16, F16, F16, ) |
| 112 | OPCODE(FPAdd32, U32, U32, U32, ) | 138 | OPCODE(FPAdd32, F32, F32, F32, ) |
| 113 | OPCODE(FPAdd64, U64, U64, U64, ) | 139 | OPCODE(FPAdd64, F64, F64, F64, ) |
| 114 | OPCODE(FPFma16, U16, U16, U16, U16, ) | 140 | OPCODE(FPFma16, F16, F16, F16, F16, ) |
| 115 | OPCODE(FPFma32, U32, U32, U32, U32, ) | 141 | OPCODE(FPFma32, F32, F32, F32, F32, ) |
| 116 | OPCODE(FPFma64, U64, U64, U64, U64, ) | 142 | OPCODE(FPFma64, F64, F64, F64, F64, ) |
| 117 | OPCODE(FPMax32, U32, U32, U32, ) | 143 | OPCODE(FPMax32, F32, F32, F32, ) |
| 118 | OPCODE(FPMax64, U64, U64, U64, ) | 144 | OPCODE(FPMax64, F64, F64, F64, ) |
| 119 | OPCODE(FPMin32, U32, U32, U32, ) | 145 | OPCODE(FPMin32, F32, F32, F32, ) |
| 120 | OPCODE(FPMin64, U64, U64, U64, ) | 146 | OPCODE(FPMin64, F64, F64, F64, ) |
| 121 | OPCODE(FPMul16, U16, U16, U16, ) | 147 | OPCODE(FPMul16, F16, F16, F16, ) |
| 122 | OPCODE(FPMul32, U32, U32, U32, ) | 148 | OPCODE(FPMul32, F32, F32, F32, ) |
| 123 | OPCODE(FPMul64, U64, U64, U64, ) | 149 | OPCODE(FPMul64, F64, F64, F64, ) |
| 124 | OPCODE(FPNeg16, U16, U16, ) | 150 | OPCODE(FPNeg16, F16, F16, ) |
| 125 | OPCODE(FPNeg32, U32, U32, ) | 151 | OPCODE(FPNeg32, F32, F32, ) |
| 126 | OPCODE(FPNeg64, U64, U64, ) | 152 | OPCODE(FPNeg64, F64, F64, ) |
| 127 | OPCODE(FPRecip32, U32, U32, ) | 153 | OPCODE(FPRecip32, F32, F32, ) |
| 128 | OPCODE(FPRecip64, U64, U64, ) | 154 | OPCODE(FPRecip64, F64, F64, ) |
| 129 | OPCODE(FPRecipSqrt32, U32, U32, ) | 155 | OPCODE(FPRecipSqrt32, F32, F32, ) |
| 130 | OPCODE(FPRecipSqrt64, U64, U64, ) | 156 | OPCODE(FPRecipSqrt64, F64, F64, ) |
| 131 | OPCODE(FPSqrt, U32, U32, ) | 157 | OPCODE(FPSqrt, F32, F32, ) |
| 132 | OPCODE(FPSin, U32, U32, ) | 158 | OPCODE(FPSin, F32, F32, ) |
| 133 | OPCODE(FPSinNotReduced, U32, U32, ) | 159 | OPCODE(FPSinNotReduced, F32, F32, ) |
| 134 | OPCODE(FPExp2, U32, U32, ) | 160 | OPCODE(FPExp2, F32, F32, ) |
| 135 | OPCODE(FPExp2NotReduced, U32, U32, ) | 161 | OPCODE(FPExp2NotReduced, F32, F32, ) |
| 136 | OPCODE(FPCos, U32, U32, ) | 162 | OPCODE(FPCos, F32, F32, ) |
| 137 | OPCODE(FPCosNotReduced, U32, U32, ) | 163 | OPCODE(FPCosNotReduced, F32, F32, ) |
| 138 | OPCODE(FPLog2, U32, U32, ) | 164 | OPCODE(FPLog2, F32, F32, ) |
| 139 | OPCODE(FPSaturate16, U16, U16, ) | 165 | OPCODE(FPSaturate16, F16, F16, ) |
| 140 | OPCODE(FPSaturate32, U32, U32, ) | 166 | OPCODE(FPSaturate32, F32, F32, ) |
| 141 | OPCODE(FPSaturate64, U64, U64, ) | 167 | OPCODE(FPSaturate64, F64, F64, ) |
| 142 | OPCODE(FPRoundEven16, U16, U16, ) | 168 | OPCODE(FPRoundEven16, F16, F16, ) |
| 143 | OPCODE(FPRoundEven32, U32, U32, ) | 169 | OPCODE(FPRoundEven32, F32, F32, ) |
| 144 | OPCODE(FPRoundEven64, U64, U64, ) | 170 | OPCODE(FPRoundEven64, F64, F64, ) |
| 145 | OPCODE(FPFloor16, U16, U16, ) | 171 | OPCODE(FPFloor16, F16, F16, ) |
| 146 | OPCODE(FPFloor32, U32, U32, ) | 172 | OPCODE(FPFloor32, F32, F32, ) |
| 147 | OPCODE(FPFloor64, U64, U64, ) | 173 | OPCODE(FPFloor64, F64, F64, ) |
| 148 | OPCODE(FPCeil16, U16, U16, ) | 174 | OPCODE(FPCeil16, F16, F16, ) |
| 149 | OPCODE(FPCeil32, U32, U32, ) | 175 | OPCODE(FPCeil32, F32, F32, ) |
| 150 | OPCODE(FPCeil64, U64, U64, ) | 176 | OPCODE(FPCeil64, F64, F64, ) |
| 151 | OPCODE(FPTrunc16, U16, U16, ) | 177 | OPCODE(FPTrunc16, F16, F16, ) |
| 152 | OPCODE(FPTrunc32, U32, U32, ) | 178 | OPCODE(FPTrunc32, F32, F32, ) |
| 153 | OPCODE(FPTrunc64, U64, U64, ) | 179 | OPCODE(FPTrunc64, F64, F64, ) |
| 154 | 180 | ||
| 155 | // Integer operations | 181 | // Integer operations |
| 156 | OPCODE(IAdd32, U32, U32, U32, ) | 182 | OPCODE(IAdd32, U32, U32, U32, ) |
| @@ -188,24 +214,24 @@ OPCODE(LogicalXor, U1, U1, | |||
| 188 | OPCODE(LogicalNot, U1, U1, ) | 214 | OPCODE(LogicalNot, U1, U1, ) |
| 189 | 215 | ||
| 190 | // Conversion operations | 216 | // Conversion operations |
| 191 | OPCODE(ConvertS16F16, U32, U16, ) | 217 | OPCODE(ConvertS16F16, U32, F16, ) |
| 192 | OPCODE(ConvertS16F32, U32, U32, ) | 218 | OPCODE(ConvertS16F32, U32, F32, ) |
| 193 | OPCODE(ConvertS16F64, U32, U64, ) | 219 | OPCODE(ConvertS16F64, U32, F64, ) |
| 194 | OPCODE(ConvertS32F16, U32, U16, ) | 220 | OPCODE(ConvertS32F16, U32, F16, ) |
| 195 | OPCODE(ConvertS32F32, U32, U32, ) | 221 | OPCODE(ConvertS32F32, U32, F32, ) |
| 196 | OPCODE(ConvertS32F64, U32, U64, ) | 222 | OPCODE(ConvertS32F64, U32, F64, ) |
| 197 | OPCODE(ConvertS64F16, U64, U16, ) | 223 | OPCODE(ConvertS64F16, U64, F16, ) |
| 198 | OPCODE(ConvertS64F32, U64, U32, ) | 224 | OPCODE(ConvertS64F32, U64, F32, ) |
| 199 | OPCODE(ConvertS64F64, U64, U64, ) | 225 | OPCODE(ConvertS64F64, U64, F64, ) |
| 200 | OPCODE(ConvertU16F16, U32, U16, ) | 226 | OPCODE(ConvertU16F16, U32, F16, ) |
| 201 | OPCODE(ConvertU16F32, U32, U32, ) | 227 | OPCODE(ConvertU16F32, U32, F32, ) |
| 202 | OPCODE(ConvertU16F64, U32, U64, ) | 228 | OPCODE(ConvertU16F64, U32, F64, ) |
| 203 | OPCODE(ConvertU32F16, U32, U16, ) | 229 | OPCODE(ConvertU32F16, U32, F16, ) |
| 204 | OPCODE(ConvertU32F32, U32, U32, ) | 230 | OPCODE(ConvertU32F32, U32, F32, ) |
| 205 | OPCODE(ConvertU32F64, U32, U64, ) | 231 | OPCODE(ConvertU32F64, U32, F64, ) |
| 206 | OPCODE(ConvertU64F16, U64, U16, ) | 232 | OPCODE(ConvertU64F16, U64, F16, ) |
| 207 | OPCODE(ConvertU64F32, U64, U32, ) | 233 | OPCODE(ConvertU64F32, U64, F32, ) |
| 208 | OPCODE(ConvertU64F64, U64, U64, ) | 234 | OPCODE(ConvertU64F64, U64, F64, ) |
| 209 | 235 | ||
| 210 | OPCODE(ConvertU64U32, U64, U32, ) | 236 | OPCODE(ConvertU64U32, U64, U32, ) |
| 211 | OPCODE(ConvertU32U64, U32, U64, ) | 237 | OPCODE(ConvertU32U64, U32, U64, ) |
diff --git a/src/shader_recompiler/frontend/ir/type.cpp b/src/shader_recompiler/frontend/ir/type.cpp index 13cc09195..f28341bfe 100644 --- a/src/shader_recompiler/frontend/ir/type.cpp +++ b/src/shader_recompiler/frontend/ir/type.cpp | |||
| @@ -11,7 +11,9 @@ namespace Shader::IR { | |||
| 11 | 11 | ||
| 12 | std::string NameOf(Type type) { | 12 | std::string NameOf(Type type) { |
| 13 | static constexpr std::array names{ | 13 | static constexpr std::array names{ |
| 14 | "Opaque", "Label", "Reg", "Pred", "Attribute", "U1", "U8", "U16", "U32", "U64", | 14 | "Opaque", "Label", "Reg", "Pred", "Attribute", "U1", "U8", "U16", "U32", |
| 15 | "U64", "F16", "F32", "F64", "U32x2", "U32x3", "U32x4", "F16x2", "F16x3", | ||
| 16 | "F16x4", "F32x2", "F32x3", "F32x4", "F64x2", "F64x3", "F64x4", | ||
| 15 | }; | 17 | }; |
| 16 | const size_t bits{static_cast<size_t>(type)}; | 18 | const size_t bits{static_cast<size_t>(type)}; |
| 17 | if (bits == 0) { | 19 | if (bits == 0) { |
diff --git a/src/shader_recompiler/frontend/ir/type.h b/src/shader_recompiler/frontend/ir/type.h index 397875018..9a32ca1e8 100644 --- a/src/shader_recompiler/frontend/ir/type.h +++ b/src/shader_recompiler/frontend/ir/type.h | |||
| @@ -25,6 +25,21 @@ enum class Type { | |||
| 25 | U16 = 1 << 7, | 25 | U16 = 1 << 7, |
| 26 | U32 = 1 << 8, | 26 | U32 = 1 << 8, |
| 27 | U64 = 1 << 9, | 27 | U64 = 1 << 9, |
| 28 | F16 = 1 << 10, | ||
| 29 | F32 = 1 << 11, | ||
| 30 | F64 = 1 << 12, | ||
| 31 | U32x2 = 1 << 13, | ||
| 32 | U32x3 = 1 << 14, | ||
| 33 | U32x4 = 1 << 15, | ||
| 34 | F16x2 = 1 << 16, | ||
| 35 | F16x3 = 1 << 17, | ||
| 36 | F16x4 = 1 << 18, | ||
| 37 | F32x2 = 1 << 19, | ||
| 38 | F32x3 = 1 << 20, | ||
| 39 | F32x4 = 1 << 21, | ||
| 40 | F64x2 = 1 << 22, | ||
| 41 | F64x3 = 1 << 23, | ||
| 42 | F64x4 = 1 << 24, | ||
| 28 | }; | 43 | }; |
| 29 | DECLARE_ENUM_FLAG_OPERATORS(Type) | 44 | DECLARE_ENUM_FLAG_OPERATORS(Type) |
| 30 | 45 | ||
diff --git a/src/shader_recompiler/frontend/ir/value.cpp b/src/shader_recompiler/frontend/ir/value.cpp index 59a9b10dc..93ff8ccf1 100644 --- a/src/shader_recompiler/frontend/ir/value.cpp +++ b/src/shader_recompiler/frontend/ir/value.cpp | |||
| @@ -26,8 +26,12 @@ Value::Value(u16 value) noexcept : type{Type::U16}, imm_u16{value} {} | |||
| 26 | 26 | ||
| 27 | Value::Value(u32 value) noexcept : type{Type::U32}, imm_u32{value} {} | 27 | Value::Value(u32 value) noexcept : type{Type::U32}, imm_u32{value} {} |
| 28 | 28 | ||
| 29 | Value::Value(f32 value) noexcept : type{Type::F32}, imm_f32{value} {} | ||
| 30 | |||
| 29 | Value::Value(u64 value) noexcept : type{Type::U64}, imm_u64{value} {} | 31 | Value::Value(u64 value) noexcept : type{Type::U64}, imm_u64{value} {} |
| 30 | 32 | ||
| 33 | Value::Value(f64 value) noexcept : type{Type::F64}, imm_f64{value} {} | ||
| 34 | |||
| 31 | bool Value::IsIdentity() const noexcept { | 35 | bool Value::IsIdentity() const noexcept { |
| 32 | return type == Type::Opaque && inst->Opcode() == Opcode::Identity; | 36 | return type == Type::Opaque && inst->Opcode() == Opcode::Identity; |
| 33 | } | 37 | } |
| @@ -122,6 +126,14 @@ u32 Value::U32() const { | |||
| 122 | return imm_u32; | 126 | return imm_u32; |
| 123 | } | 127 | } |
| 124 | 128 | ||
| 129 | f32 Value::F32() const { | ||
| 130 | if (IsIdentity()) { | ||
| 131 | return inst->Arg(0).F32(); | ||
| 132 | } | ||
| 133 | ValidateAccess(Type::F32); | ||
| 134 | return imm_f32; | ||
| 135 | } | ||
| 136 | |||
| 125 | u64 Value::U64() const { | 137 | u64 Value::U64() const { |
| 126 | if (IsIdentity()) { | 138 | if (IsIdentity()) { |
| 127 | return inst->Arg(0).U64(); | 139 | return inst->Arg(0).U64(); |
| @@ -152,11 +164,27 @@ bool Value::operator==(const Value& other) const { | |||
| 152 | case Type::U8: | 164 | case Type::U8: |
| 153 | return imm_u8 == other.imm_u8; | 165 | return imm_u8 == other.imm_u8; |
| 154 | case Type::U16: | 166 | case Type::U16: |
| 167 | case Type::F16: | ||
| 155 | return imm_u16 == other.imm_u16; | 168 | return imm_u16 == other.imm_u16; |
| 156 | case Type::U32: | 169 | case Type::U32: |
| 170 | case Type::F32: | ||
| 157 | return imm_u32 == other.imm_u32; | 171 | return imm_u32 == other.imm_u32; |
| 158 | case Type::U64: | 172 | case Type::U64: |
| 173 | case Type::F64: | ||
| 159 | return imm_u64 == other.imm_u64; | 174 | return imm_u64 == other.imm_u64; |
| 175 | case Type::U32x2: | ||
| 176 | case Type::U32x3: | ||
| 177 | case Type::U32x4: | ||
| 178 | case Type::F16x2: | ||
| 179 | case Type::F16x3: | ||
| 180 | case Type::F16x4: | ||
| 181 | case Type::F32x2: | ||
| 182 | case Type::F32x3: | ||
| 183 | case Type::F32x4: | ||
| 184 | case Type::F64x2: | ||
| 185 | case Type::F64x3: | ||
| 186 | case Type::F64x4: | ||
| 187 | break; | ||
| 160 | } | 188 | } |
| 161 | throw LogicError("Invalid type {}", type); | 189 | throw LogicError("Invalid type {}", type); |
| 162 | } | 190 | } |
diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h index 31f831794..2f3688c73 100644 --- a/src/shader_recompiler/frontend/ir/value.h +++ b/src/shader_recompiler/frontend/ir/value.h | |||
| @@ -28,7 +28,9 @@ public: | |||
| 28 | explicit Value(u8 value) noexcept; | 28 | explicit Value(u8 value) noexcept; |
| 29 | explicit Value(u16 value) noexcept; | 29 | explicit Value(u16 value) noexcept; |
| 30 | explicit Value(u32 value) noexcept; | 30 | explicit Value(u32 value) noexcept; |
| 31 | explicit Value(f32 value) noexcept; | ||
| 31 | explicit Value(u64 value) noexcept; | 32 | explicit Value(u64 value) noexcept; |
| 33 | explicit Value(f64 value) noexcept; | ||
| 32 | 34 | ||
| 33 | [[nodiscard]] bool IsIdentity() const noexcept; | 35 | [[nodiscard]] bool IsIdentity() const noexcept; |
| 34 | [[nodiscard]] bool IsEmpty() const noexcept; | 36 | [[nodiscard]] bool IsEmpty() const noexcept; |
| @@ -46,6 +48,7 @@ public: | |||
| 46 | [[nodiscard]] u8 U8() const; | 48 | [[nodiscard]] u8 U8() const; |
| 47 | [[nodiscard]] u16 U16() const; | 49 | [[nodiscard]] u16 U16() const; |
| 48 | [[nodiscard]] u32 U32() const; | 50 | [[nodiscard]] u32 U32() const; |
| 51 | [[nodiscard]] f32 F32() const; | ||
| 49 | [[nodiscard]] u64 U64() const; | 52 | [[nodiscard]] u64 U64() const; |
| 50 | 53 | ||
| 51 | [[nodiscard]] bool operator==(const Value& other) const; | 54 | [[nodiscard]] bool operator==(const Value& other) const; |
| @@ -65,7 +68,9 @@ private: | |||
| 65 | u8 imm_u8; | 68 | u8 imm_u8; |
| 66 | u16 imm_u16; | 69 | u16 imm_u16; |
| 67 | u32 imm_u32; | 70 | u32 imm_u32; |
| 71 | f32 imm_f32; | ||
| 68 | u64 imm_u64; | 72 | u64 imm_u64; |
| 73 | f64 imm_f64; | ||
| 69 | }; | 74 | }; |
| 70 | }; | 75 | }; |
| 71 | 76 | ||
| @@ -93,8 +98,13 @@ using U8 = TypedValue<Type::U8>; | |||
| 93 | using U16 = TypedValue<Type::U16>; | 98 | using U16 = TypedValue<Type::U16>; |
| 94 | using U32 = TypedValue<Type::U32>; | 99 | using U32 = TypedValue<Type::U32>; |
| 95 | using U64 = TypedValue<Type::U64>; | 100 | using U64 = TypedValue<Type::U64>; |
| 101 | using F16 = TypedValue<Type::F16>; | ||
| 102 | using F32 = TypedValue<Type::F32>; | ||
| 103 | using F64 = TypedValue<Type::F64>; | ||
| 96 | using U32U64 = TypedValue<Type::U32 | Type::U64>; | 104 | using U32U64 = TypedValue<Type::U32 | Type::U64>; |
| 105 | using F32F64 = TypedValue<Type::F32 | Type::F64>; | ||
| 97 | using U16U32U64 = TypedValue<Type::U16 | Type::U32 | Type::U64>; | 106 | using U16U32U64 = TypedValue<Type::U16 | Type::U32 | Type::U64>; |
| 107 | using F16F32F64 = TypedValue<Type::F16 | Type::F32 | Type::F64>; | ||
| 98 | using UAny = TypedValue<Type::U8 | Type::U16 | Type::U32 | Type::U64>; | 108 | using UAny = TypedValue<Type::U8 | Type::U16 | Type::U32 | Type::U64>; |
| 99 | 109 | ||
| 100 | } // namespace Shader::IR | 110 | } // namespace Shader::IR |