diff options
| author | 2021-02-05 19:19:36 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:21 -0400 | |
| commit | be94ee88d227d0d3dbeabe9ade98bacd910c7a7e (patch) | |
| tree | 68a2043d48b8d1ecb7df23d03c1f92f277c70f9a /src/shader_recompiler/frontend | |
| parent | shader: Remove illegal character in SSA pass (diff) | |
| download | yuzu-be94ee88d227d0d3dbeabe9ade98bacd910c7a7e.tar.gz yuzu-be94ee88d227d0d3dbeabe9ade98bacd910c7a7e.tar.xz yuzu-be94ee88d227d0d3dbeabe9ade98bacd910c7a7e.zip | |
shader: Make typed IR
Diffstat (limited to 'src/shader_recompiler/frontend')
16 files changed, 463 insertions, 258 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 |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_add.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_add.cpp index d2c44b9cc..cb3a326cf 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_add.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_add.cpp | |||
| @@ -11,7 +11,7 @@ namespace Shader::Maxwell { | |||
| 11 | namespace { | 11 | namespace { |
| 12 | 12 | ||
| 13 | void FADD(TranslatorVisitor& v, u64 insn, bool sat, bool cc, bool ftz, FpRounding fp_rounding, | 13 | void FADD(TranslatorVisitor& v, u64 insn, bool sat, bool cc, bool ftz, FpRounding fp_rounding, |
| 14 | const IR::U32& src_b, bool abs_a, bool neg_a, bool abs_b, bool neg_b) { | 14 | const IR::F32& src_b, bool abs_a, bool neg_a, bool abs_b, bool neg_b) { |
| 15 | union { | 15 | union { |
| 16 | u64 raw; | 16 | u64 raw; |
| 17 | BitField<0, 8, IR::Reg> dest_reg; | 17 | BitField<0, 8, IR::Reg> dest_reg; |
| @@ -24,17 +24,17 @@ void FADD(TranslatorVisitor& v, u64 insn, bool sat, bool cc, bool ftz, FpRoundin | |||
| 24 | if (cc) { | 24 | if (cc) { |
| 25 | throw NotImplementedException("FADD CC"); | 25 | throw NotImplementedException("FADD CC"); |
| 26 | } | 26 | } |
| 27 | const IR::U32 op_a{v.ir.FPAbsNeg(v.X(fadd.src_a), abs_a, neg_a)}; | 27 | const IR::F32 op_a{v.ir.FPAbsNeg(v.F(fadd.src_a), abs_a, neg_a)}; |
| 28 | const IR::U32 op_b{v.ir.FPAbsNeg(src_b, abs_b, neg_b)}; | 28 | const IR::F32 op_b{v.ir.FPAbsNeg(src_b, abs_b, neg_b)}; |
| 29 | IR::FpControl control{ | 29 | IR::FpControl control{ |
| 30 | .no_contraction{true}, | 30 | .no_contraction{true}, |
| 31 | .rounding{CastFpRounding(fp_rounding)}, | 31 | .rounding{CastFpRounding(fp_rounding)}, |
| 32 | .fmz_mode{ftz ? IR::FmzMode::FTZ : IR::FmzMode::None}, | 32 | .fmz_mode{ftz ? IR::FmzMode::FTZ : IR::FmzMode::None}, |
| 33 | }; | 33 | }; |
| 34 | v.X(fadd.dest_reg, v.ir.FPAdd(op_a, op_b, control)); | 34 | v.F(fadd.dest_reg, v.ir.FPAdd(op_a, op_b, control)); |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | void FADD(TranslatorVisitor& v, u64 insn, const IR::U32& src_b) { | 37 | void FADD(TranslatorVisitor& v, u64 insn, const IR::F32& src_b) { |
| 38 | union { | 38 | union { |
| 39 | u64 raw; | 39 | u64 raw; |
| 40 | BitField<39, 2, FpRounding> fp_rounding; | 40 | BitField<39, 2, FpRounding> fp_rounding; |
| @@ -53,7 +53,7 @@ void FADD(TranslatorVisitor& v, u64 insn, const IR::U32& src_b) { | |||
| 53 | } // Anonymous namespace | 53 | } // Anonymous namespace |
| 54 | 54 | ||
| 55 | void TranslatorVisitor::FADD_reg(u64 insn) { | 55 | void TranslatorVisitor::FADD_reg(u64 insn) { |
| 56 | FADD(*this, insn, GetReg20(insn)); | 56 | FADD(*this, insn, GetReg20F(insn)); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | void TranslatorVisitor::FADD_cbuf(u64) { | 59 | void TranslatorVisitor::FADD_cbuf(u64) { |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp index c4288d9a8..acd8445ad 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp | |||
| @@ -55,21 +55,21 @@ size_t BitSize(DestFormat dest_format) { | |||
| 55 | } | 55 | } |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | void TranslateF2I(TranslatorVisitor& v, u64 insn, const IR::U16U32U64& op_a) { | 58 | void TranslateF2I(TranslatorVisitor& v, u64 insn, const IR::F16F32F64& src_a) { |
| 59 | // F2I is used to convert from a floating point value to an integer | 59 | // F2I is used to convert from a floating point value to an integer |
| 60 | const F2I f2i{insn}; | 60 | const F2I f2i{insn}; |
| 61 | 61 | ||
| 62 | const IR::U16U32U64 float_value{v.ir.FPAbsNeg(op_a, f2i.abs != 0, f2i.neg != 0)}; | 62 | const IR::F16F32F64 op_a{v.ir.FPAbsNeg(src_a, f2i.abs != 0, f2i.neg != 0)}; |
| 63 | const IR::U16U32U64 rounded_value{[&] { | 63 | const IR::F16F32F64 rounded_value{[&] { |
| 64 | switch (f2i.rounding) { | 64 | switch (f2i.rounding) { |
| 65 | case Rounding::Round: | 65 | case Rounding::Round: |
| 66 | return v.ir.FPRoundEven(float_value); | 66 | return v.ir.FPRoundEven(op_a); |
| 67 | case Rounding::Floor: | 67 | case Rounding::Floor: |
| 68 | return v.ir.FPFloor(float_value); | 68 | return v.ir.FPFloor(op_a); |
| 69 | case Rounding::Ceil: | 69 | case Rounding::Ceil: |
| 70 | return v.ir.FPCeil(float_value); | 70 | return v.ir.FPCeil(op_a); |
| 71 | case Rounding::Trunc: | 71 | case Rounding::Trunc: |
| 72 | return v.ir.FPTrunc(float_value); | 72 | return v.ir.FPTrunc(op_a); |
| 73 | default: | 73 | default: |
| 74 | throw NotImplementedException("Invalid F2I rounding {}", f2i.rounding.Value()); | 74 | throw NotImplementedException("Invalid F2I rounding {}", f2i.rounding.Value()); |
| 75 | } | 75 | } |
| @@ -105,12 +105,12 @@ void TranslatorVisitor::F2I_reg(u64 insn) { | |||
| 105 | BitField<20, 8, IR::Reg> src_reg; | 105 | BitField<20, 8, IR::Reg> src_reg; |
| 106 | } const f2i{insn}; | 106 | } const f2i{insn}; |
| 107 | 107 | ||
| 108 | const IR::U16U32U64 op_a{[&]() -> IR::U16U32U64 { | 108 | const IR::F16F32F64 op_a{[&]() -> IR::F16F32F64 { |
| 109 | switch (f2i.base.src_format) { | 109 | switch (f2i.base.src_format) { |
| 110 | case SrcFormat::F16: | 110 | case SrcFormat::F16: |
| 111 | return ir.CompositeExtract(ir.UnpackFloat2x16(X(f2i.src_reg)), f2i.base.half); | 111 | return IR::F16{ir.CompositeExtract(ir.UnpackFloat2x16(X(f2i.src_reg)), f2i.base.half)}; |
| 112 | case SrcFormat::F32: | 112 | case SrcFormat::F32: |
| 113 | return X(f2i.src_reg); | 113 | return F(f2i.src_reg); |
| 114 | case SrcFormat::F64: | 114 | case SrcFormat::F64: |
| 115 | return ir.PackDouble2x32(ir.CompositeConstruct(X(f2i.src_reg), X(f2i.src_reg + 1))); | 115 | return ir.PackDouble2x32(ir.CompositeConstruct(X(f2i.src_reg), X(f2i.src_reg + 1))); |
| 116 | default: | 116 | default: |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_fused_multiply_add.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_fused_multiply_add.cpp index 30ca052ec..1464f2807 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_fused_multiply_add.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_fused_multiply_add.cpp | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | 9 | ||
| 10 | namespace Shader::Maxwell { | 10 | namespace Shader::Maxwell { |
| 11 | namespace { | 11 | namespace { |
| 12 | void FFMA(TranslatorVisitor& v, u64 insn, const IR::U32& src_b, const IR::U32& src_c, bool neg_a, | 12 | void FFMA(TranslatorVisitor& v, u64 insn, const IR::F32& src_b, const IR::F32& src_c, bool neg_a, |
| 13 | bool neg_b, bool neg_c, bool sat, bool cc, FmzMode fmz_mode, FpRounding fp_rounding) { | 13 | bool neg_b, bool neg_c, bool sat, bool cc, FmzMode fmz_mode, FpRounding fp_rounding) { |
| 14 | union { | 14 | union { |
| 15 | u64 raw; | 15 | u64 raw; |
| @@ -23,18 +23,18 @@ void FFMA(TranslatorVisitor& v, u64 insn, const IR::U32& src_b, const IR::U32& s | |||
| 23 | if (cc) { | 23 | if (cc) { |
| 24 | throw NotImplementedException("FFMA CC"); | 24 | throw NotImplementedException("FFMA CC"); |
| 25 | } | 25 | } |
| 26 | const IR::U32 op_a{v.ir.FPAbsNeg(v.X(ffma.src_a), false, neg_a)}; | 26 | const IR::F32 op_a{v.ir.FPAbsNeg(v.F(ffma.src_a), false, neg_a)}; |
| 27 | const IR::U32 op_b{v.ir.FPAbsNeg(src_b, false, neg_b)}; | 27 | const IR::F32 op_b{v.ir.FPAbsNeg(src_b, false, neg_b)}; |
| 28 | const IR::U32 op_c{v.ir.FPAbsNeg(src_c, false, neg_c)}; | 28 | const IR::F32 op_c{v.ir.FPAbsNeg(src_c, false, neg_c)}; |
| 29 | const IR::FpControl fp_control{ | 29 | const IR::FpControl fp_control{ |
| 30 | .no_contraction{true}, | 30 | .no_contraction{true}, |
| 31 | .rounding{CastFpRounding(fp_rounding)}, | 31 | .rounding{CastFpRounding(fp_rounding)}, |
| 32 | .fmz_mode{CastFmzMode(fmz_mode)}, | 32 | .fmz_mode{CastFmzMode(fmz_mode)}, |
| 33 | }; | 33 | }; |
| 34 | v.X(ffma.dest_reg, v.ir.FPFma(op_a, op_b, op_c, fp_control)); | 34 | v.F(ffma.dest_reg, v.ir.FPFma(op_a, op_b, op_c, fp_control)); |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | void FFMA(TranslatorVisitor& v, u64 insn, const IR::U32& src_b, const IR::U32& src_c) { | 37 | void FFMA(TranslatorVisitor& v, u64 insn, const IR::F32& src_b, const IR::F32& src_c) { |
| 38 | union { | 38 | union { |
| 39 | u64 raw; | 39 | u64 raw; |
| 40 | BitField<47, 1, u64> cc; | 40 | BitField<47, 1, u64> cc; |
| @@ -51,7 +51,7 @@ void FFMA(TranslatorVisitor& v, u64 insn, const IR::U32& src_b, const IR::U32& s | |||
| 51 | } // Anonymous namespace | 51 | } // Anonymous namespace |
| 52 | 52 | ||
| 53 | void TranslatorVisitor::FFMA_reg(u64 insn) { | 53 | void TranslatorVisitor::FFMA_reg(u64 insn) { |
| 54 | FFMA(*this, insn, GetReg20(insn), GetReg39(insn)); | 54 | FFMA(*this, insn, GetReg20F(insn), GetReg39F(insn)); |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | void TranslatorVisitor::FFMA_rc(u64) { | 57 | void TranslatorVisitor::FFMA_rc(u64) { |
| @@ -59,7 +59,7 @@ void TranslatorVisitor::FFMA_rc(u64) { | |||
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | void TranslatorVisitor::FFMA_cr(u64 insn) { | 61 | void TranslatorVisitor::FFMA_cr(u64 insn) { |
| 62 | FFMA(*this, insn, GetCbuf(insn), GetReg39(insn)); | 62 | FFMA(*this, insn, GetCbufF(insn), GetReg39F(insn)); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | void TranslatorVisitor::FFMA_imm(u64) { | 65 | void TranslatorVisitor::FFMA_imm(u64) { |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multi_function.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multi_function.cpp index e2ab0dab2..90cddb18b 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multi_function.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multi_function.cpp | |||
| @@ -35,8 +35,8 @@ void TranslatorVisitor::MUFU(u64 insn) { | |||
| 35 | BitField<50, 1, u64> sat; | 35 | BitField<50, 1, u64> sat; |
| 36 | } const mufu{insn}; | 36 | } const mufu{insn}; |
| 37 | 37 | ||
| 38 | const IR::U32 op_a{ir.FPAbsNeg(X(mufu.src_reg), mufu.abs != 0, mufu.neg != 0)}; | 38 | const IR::F32 op_a{ir.FPAbsNeg(F(mufu.src_reg), mufu.abs != 0, mufu.neg != 0)}; |
| 39 | IR::U32 value{[&]() -> IR::U32 { | 39 | IR::F32 value{[&]() -> IR::F32 { |
| 40 | switch (mufu.operation) { | 40 | switch (mufu.operation) { |
| 41 | case Operation::Cos: | 41 | case Operation::Cos: |
| 42 | return ir.FPCosNotReduced(op_a); | 42 | return ir.FPCosNotReduced(op_a); |
| @@ -65,7 +65,7 @@ void TranslatorVisitor::MUFU(u64 insn) { | |||
| 65 | value = ir.FPSaturate(value); | 65 | value = ir.FPSaturate(value); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | X(mufu.dest_reg, value); | 68 | F(mufu.dest_reg, value); |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | } // namespace Shader::Maxwell | 71 | } // namespace Shader::Maxwell |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multiply.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multiply.cpp index 743a1e2f0..1b1d38be7 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multiply.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_multiply.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/bit_field.h" | 5 | #include "common/bit_field.h" |
| 6 | #include "common/common_types.h" | 6 | #include "common/common_types.h" |
| 7 | #include "shader_recompiler/frontend/ir/ir_emitter.h" | ||
| 7 | #include "shader_recompiler/frontend/ir/modifiers.h" | 8 | #include "shader_recompiler/frontend/ir/modifiers.h" |
| 8 | #include "shader_recompiler/frontend/maxwell/translate/impl/common_encoding.h" | 9 | #include "shader_recompiler/frontend/maxwell/translate/impl/common_encoding.h" |
| 9 | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | 10 | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" |
| @@ -43,7 +44,7 @@ float ScaleFactor(Scale scale) { | |||
| 43 | throw NotImplementedException("Invalid FMUL scale {}", scale); | 44 | throw NotImplementedException("Invalid FMUL scale {}", scale); |
| 44 | } | 45 | } |
| 45 | 46 | ||
| 46 | void FMUL(TranslatorVisitor& v, u64 insn, const IR::U32& src_b, FmzMode fmz_mode, | 47 | void FMUL(TranslatorVisitor& v, u64 insn, const IR::F32& src_b, FmzMode fmz_mode, |
| 47 | FpRounding fp_rounding, Scale scale, bool sat, bool cc, bool neg_b) { | 48 | FpRounding fp_rounding, Scale scale, bool sat, bool cc, bool neg_b) { |
| 48 | union { | 49 | union { |
| 49 | u64 raw; | 50 | u64 raw; |
| @@ -57,23 +58,23 @@ void FMUL(TranslatorVisitor& v, u64 insn, const IR::U32& src_b, FmzMode fmz_mode | |||
| 57 | if (sat) { | 58 | if (sat) { |
| 58 | throw NotImplementedException("FMUL SAT"); | 59 | throw NotImplementedException("FMUL SAT"); |
| 59 | } | 60 | } |
| 60 | IR::U32 op_a{v.X(fmul.src_a)}; | 61 | IR::F32 op_a{v.F(fmul.src_a)}; |
| 61 | if (scale != Scale::None) { | 62 | if (scale != Scale::None) { |
| 62 | if (fmz_mode != FmzMode::FTZ || fp_rounding != FpRounding::RN) { | 63 | if (fmz_mode != FmzMode::FTZ || fp_rounding != FpRounding::RN) { |
| 63 | throw NotImplementedException("FMUL scale with non-FMZ or non-RN modifiers"); | 64 | throw NotImplementedException("FMUL scale with non-FMZ or non-RN modifiers"); |
| 64 | } | 65 | } |
| 65 | op_a = v.ir.FPMul(op_a, v.ir.Imm32(ScaleFactor(scale))); | 66 | op_a = v.ir.FPMul(op_a, v.ir.Imm32(ScaleFactor(scale))); |
| 66 | } | 67 | } |
| 67 | const IR::U32 op_b{v.ir.FPAbsNeg(src_b, false, neg_b)}; | 68 | const IR::F32 op_b{v.ir.FPAbsNeg(src_b, false, neg_b)}; |
| 68 | const IR::FpControl fp_control{ | 69 | const IR::FpControl fp_control{ |
| 69 | .no_contraction{true}, | 70 | .no_contraction{true}, |
| 70 | .rounding{CastFpRounding(fp_rounding)}, | 71 | .rounding{CastFpRounding(fp_rounding)}, |
| 71 | .fmz_mode{CastFmzMode(fmz_mode)}, | 72 | .fmz_mode{CastFmzMode(fmz_mode)}, |
| 72 | }; | 73 | }; |
| 73 | v.X(fmul.dest_reg, v.ir.FPMul(op_a, op_b, fp_control)); | 74 | v.F(fmul.dest_reg, v.ir.FPMul(op_a, op_b, fp_control)); |
| 74 | } | 75 | } |
| 75 | 76 | ||
| 76 | void FMUL(TranslatorVisitor& v, u64 insn, const IR::U32& src_b) { | 77 | void FMUL(TranslatorVisitor& v, u64 insn, const IR::F32& src_b) { |
| 77 | union { | 78 | union { |
| 78 | u64 raw; | 79 | u64 raw; |
| 79 | BitField<39, 2, FpRounding> fp_rounding; | 80 | BitField<39, 2, FpRounding> fp_rounding; |
| @@ -90,7 +91,7 @@ void FMUL(TranslatorVisitor& v, u64 insn, const IR::U32& src_b) { | |||
| 90 | } // Anonymous namespace | 91 | } // Anonymous namespace |
| 91 | 92 | ||
| 92 | void TranslatorVisitor::FMUL_reg(u64 insn) { | 93 | void TranslatorVisitor::FMUL_reg(u64 insn) { |
| 93 | return FMUL(*this, insn, GetReg20(insn)); | 94 | return FMUL(*this, insn, GetReg20F(insn)); |
| 94 | } | 95 | } |
| 95 | 96 | ||
| 96 | void TranslatorVisitor::FMUL_cbuf(u64) { | 97 | void TranslatorVisitor::FMUL_cbuf(u64) { |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp index 548c7f611..3c9eaddd9 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp | |||
| @@ -12,10 +12,18 @@ IR::U32 TranslatorVisitor::X(IR::Reg reg) { | |||
| 12 | return ir.GetReg(reg); | 12 | return ir.GetReg(reg); |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | IR::F32 TranslatorVisitor::F(IR::Reg reg) { | ||
| 16 | return ir.BitCast<IR::F32>(X(reg)); | ||
| 17 | } | ||
| 18 | |||
| 15 | void TranslatorVisitor::X(IR::Reg dest_reg, const IR::U32& value) { | 19 | void TranslatorVisitor::X(IR::Reg dest_reg, const IR::U32& value) { |
| 16 | ir.SetReg(dest_reg, value); | 20 | ir.SetReg(dest_reg, value); |
| 17 | } | 21 | } |
| 18 | 22 | ||
| 23 | void TranslatorVisitor::F(IR::Reg dest_reg, const IR::F32& value) { | ||
| 24 | X(dest_reg, ir.BitCast<IR::U32>(value)); | ||
| 25 | } | ||
| 26 | |||
| 19 | IR::U32 TranslatorVisitor::GetReg20(u64 insn) { | 27 | IR::U32 TranslatorVisitor::GetReg20(u64 insn) { |
| 20 | union { | 28 | union { |
| 21 | u64 raw; | 29 | u64 raw; |
| @@ -32,6 +40,14 @@ IR::U32 TranslatorVisitor::GetReg39(u64 insn) { | |||
| 32 | return X(reg.index); | 40 | return X(reg.index); |
| 33 | } | 41 | } |
| 34 | 42 | ||
| 43 | IR::F32 TranslatorVisitor::GetReg20F(u64 insn) { | ||
| 44 | return ir.BitCast<IR::F32>(GetReg20(insn)); | ||
| 45 | } | ||
| 46 | |||
| 47 | IR::F32 TranslatorVisitor::GetReg39F(u64 insn) { | ||
| 48 | return ir.BitCast<IR::F32>(GetReg39(insn)); | ||
| 49 | } | ||
| 50 | |||
| 35 | IR::U32 TranslatorVisitor::GetCbuf(u64 insn) { | 51 | IR::U32 TranslatorVisitor::GetCbuf(u64 insn) { |
| 36 | union { | 52 | union { |
| 37 | u64 raw; | 53 | u64 raw; |
| @@ -49,6 +65,10 @@ IR::U32 TranslatorVisitor::GetCbuf(u64 insn) { | |||
| 49 | return ir.GetCbuf(binding, byte_offset); | 65 | return ir.GetCbuf(binding, byte_offset); |
| 50 | } | 66 | } |
| 51 | 67 | ||
| 68 | IR::F32 TranslatorVisitor::GetCbufF(u64 insn) { | ||
| 69 | return ir.BitCast<IR::F32>(GetCbuf(insn)); | ||
| 70 | } | ||
| 71 | |||
| 52 | IR::U32 TranslatorVisitor::GetImm20(u64 insn) { | 72 | IR::U32 TranslatorVisitor::GetImm20(u64 insn) { |
| 53 | union { | 73 | union { |
| 54 | u64 raw; | 74 | u64 raw; |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h index ef6d977fe..b701605d7 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h | |||
| @@ -296,12 +296,18 @@ public: | |||
| 296 | void XMAD_imm(u64 insn); | 296 | void XMAD_imm(u64 insn); |
| 297 | 297 | ||
| 298 | [[nodiscard]] IR::U32 X(IR::Reg reg); | 298 | [[nodiscard]] IR::U32 X(IR::Reg reg); |
| 299 | [[nodiscard]] IR::F32 F(IR::Reg reg); | ||
| 300 | |||
| 299 | void X(IR::Reg dest_reg, const IR::U32& value); | 301 | void X(IR::Reg dest_reg, const IR::U32& value); |
| 302 | void F(IR::Reg dest_reg, const IR::F32& value); | ||
| 300 | 303 | ||
| 301 | [[nodiscard]] IR::U32 GetReg20(u64 insn); | 304 | [[nodiscard]] IR::U32 GetReg20(u64 insn); |
| 302 | [[nodiscard]] IR::U32 GetReg39(u64 insn); | 305 | [[nodiscard]] IR::U32 GetReg39(u64 insn); |
| 306 | [[nodiscard]] IR::F32 GetReg20F(u64 insn); | ||
| 307 | [[nodiscard]] IR::F32 GetReg39F(u64 insn); | ||
| 303 | 308 | ||
| 304 | [[nodiscard]] IR::U32 GetCbuf(u64 insn); | 309 | [[nodiscard]] IR::U32 GetCbuf(u64 insn); |
| 310 | [[nodiscard]] IR::F32 GetCbufF(u64 insn); | ||
| 305 | 311 | ||
| 306 | [[nodiscard]] IR::U32 GetImm20(u64 insn); | 312 | [[nodiscard]] IR::U32 GetImm20(u64 insn); |
| 307 | 313 | ||
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp index 23512db1a..de65173e8 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp | |||
| @@ -5,22 +5,23 @@ | |||
| 5 | #include "common/bit_field.h" | 5 | #include "common/bit_field.h" |
| 6 | #include "common/common_types.h" | 6 | #include "common/common_types.h" |
| 7 | #include "shader_recompiler/exception.h" | 7 | #include "shader_recompiler/exception.h" |
| 8 | #include "shader_recompiler/frontend/ir/ir_emitter.h" | ||
| 8 | #include "shader_recompiler/frontend/maxwell/opcode.h" | 9 | #include "shader_recompiler/frontend/maxwell/opcode.h" |
| 9 | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | 10 | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" |
| 10 | 11 | ||
| 11 | namespace Shader::Maxwell { | 12 | namespace Shader::Maxwell { |
| 12 | namespace { | 13 | namespace { |
| 13 | enum class InterpolationMode : u64 { | 14 | enum class InterpolationMode : u64 { |
| 14 | Pass = 0, | 15 | Pass, |
| 15 | Multiply = 1, | 16 | Multiply, |
| 16 | Constant = 2, | 17 | Constant, |
| 17 | Sc = 3, | 18 | Sc, |
| 18 | }; | 19 | }; |
| 19 | 20 | ||
| 20 | enum class SampleMode : u64 { | 21 | enum class SampleMode : u64 { |
| 21 | Default = 0, | 22 | Default, |
| 22 | Centroid = 1, | 23 | Centroid, |
| 23 | Offset = 2, | 24 | Offset, |
| 24 | }; | 25 | }; |
| 25 | } // Anonymous namespace | 26 | } // Anonymous namespace |
| 26 | 27 | ||
| @@ -54,12 +55,12 @@ void TranslatorVisitor::IPA(u64 insn) { | |||
| 54 | } | 55 | } |
| 55 | 56 | ||
| 56 | const IR::Attribute attribute{ipa.attribute}; | 57 | const IR::Attribute attribute{ipa.attribute}; |
| 57 | IR::U32 value{ir.GetAttribute(attribute)}; | 58 | IR::F32 value{ir.GetAttribute(attribute)}; |
| 58 | if (IR::IsGeneric(attribute)) { | 59 | if (IR::IsGeneric(attribute)) { |
| 59 | // const bool is_perspective{UnimplementedReadHeader(GenericAttributeIndex(attribute))}; | 60 | // const bool is_perspective{UnimplementedReadHeader(GenericAttributeIndex(attribute))}; |
| 60 | const bool is_perspective{false}; | 61 | const bool is_perspective{false}; |
| 61 | if (is_perspective) { | 62 | if (is_perspective) { |
| 62 | const IR::U32 rcp_position_w{ir.FPRecip(ir.GetAttribute(IR::Attribute::PositionW))}; | 63 | const IR::F32 rcp_position_w{ir.FPRecip(ir.GetAttribute(IR::Attribute::PositionW))}; |
| 63 | value = ir.FPMul(value, rcp_position_w); | 64 | value = ir.FPMul(value, rcp_position_w); |
| 64 | } | 65 | } |
| 65 | } | 66 | } |
| @@ -68,7 +69,7 @@ void TranslatorVisitor::IPA(u64 insn) { | |||
| 68 | case InterpolationMode::Pass: | 69 | case InterpolationMode::Pass: |
| 69 | break; | 70 | break; |
| 70 | case InterpolationMode::Multiply: | 71 | case InterpolationMode::Multiply: |
| 71 | value = ir.FPMul(value, ir.GetReg(ipa.multiplier)); | 72 | value = ir.FPMul(value, F(ipa.multiplier)); |
| 72 | break; | 73 | break; |
| 73 | case InterpolationMode::Constant: | 74 | case InterpolationMode::Constant: |
| 74 | throw NotImplementedException("IPA.CONSTANT"); | 75 | throw NotImplementedException("IPA.CONSTANT"); |
| @@ -86,7 +87,7 @@ void TranslatorVisitor::IPA(u64 insn) { | |||
| 86 | value = ir.FPSaturate(value); | 87 | value = ir.FPSaturate(value); |
| 87 | } | 88 | } |
| 88 | 89 | ||
| 89 | ir.SetReg(ipa.dest_reg, value); | 90 | F(ipa.dest_reg, value); |
| 90 | } | 91 | } |
| 91 | 92 | ||
| 92 | } // namespace Shader::Maxwell | 93 | } // namespace Shader::Maxwell |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_memory.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_memory.cpp index c9669c617..9f1570479 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_memory.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_memory.cpp | |||
| @@ -114,7 +114,7 @@ void TranslatorVisitor::LDG(u64 insn) { | |||
| 114 | } | 114 | } |
| 115 | const IR::Value vector{ir.LoadGlobal64(address)}; | 115 | const IR::Value vector{ir.LoadGlobal64(address)}; |
| 116 | for (int i = 0; i < 2; ++i) { | 116 | for (int i = 0; i < 2; ++i) { |
| 117 | X(dest_reg + i, ir.CompositeExtract(vector, i)); | 117 | X(dest_reg + i, IR::U32{ir.CompositeExtract(vector, i)}); |
| 118 | } | 118 | } |
| 119 | break; | 119 | break; |
| 120 | } | 120 | } |
| @@ -124,7 +124,7 @@ void TranslatorVisitor::LDG(u64 insn) { | |||
| 124 | } | 124 | } |
| 125 | const IR::Value vector{ir.LoadGlobal128(address)}; | 125 | const IR::Value vector{ir.LoadGlobal128(address)}; |
| 126 | for (int i = 0; i < 4; ++i) { | 126 | for (int i = 0; i < 4; ++i) { |
| 127 | X(dest_reg + i, ir.CompositeExtract(vector, i)); | 127 | X(dest_reg + i, IR::U32{ir.CompositeExtract(vector, i)}); |
| 128 | } | 128 | } |
| 129 | break; | 129 | break; |
| 130 | } | 130 | } |