summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/frontend')
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.cpp32
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.h8
-rw-r--r--src/shader_recompiler/frontend/ir/modifiers.h23
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp19
4 files changed, 49 insertions, 33 deletions
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
index 559ab9cca..8f120a2f6 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
@@ -558,53 +558,53 @@ F16F32F64 IREmitter::FPSaturate(const F16F32F64& value) {
558 } 558 }
559} 559}
560 560
561F16F32F64 IREmitter::FPRoundEven(const F16F32F64& value) { 561F16F32F64 IREmitter::FPRoundEven(const F16F32F64& value, FpControl control) {
562 switch (value.Type()) { 562 switch (value.Type()) {
563 case Type::F16: 563 case Type::F16:
564 return Inst<F16>(Opcode::FPRoundEven16, value); 564 return Inst<F16>(Opcode::FPRoundEven16, Flags{control}, value);
565 case Type::F32: 565 case Type::F32:
566 return Inst<F32>(Opcode::FPRoundEven32, value); 566 return Inst<F32>(Opcode::FPRoundEven32, Flags{control}, value);
567 case Type::F64: 567 case Type::F64:
568 return Inst<F64>(Opcode::FPRoundEven64, value); 568 return Inst<F64>(Opcode::FPRoundEven64, Flags{control}, value);
569 default: 569 default:
570 ThrowInvalidType(value.Type()); 570 ThrowInvalidType(value.Type());
571 } 571 }
572} 572}
573 573
574F16F32F64 IREmitter::FPFloor(const F16F32F64& value) { 574F16F32F64 IREmitter::FPFloor(const F16F32F64& value, FpControl control) {
575 switch (value.Type()) { 575 switch (value.Type()) {
576 case Type::F16: 576 case Type::F16:
577 return Inst<F16>(Opcode::FPFloor16, value); 577 return Inst<F16>(Opcode::FPFloor16, Flags{control}, value);
578 case Type::F32: 578 case Type::F32:
579 return Inst<F32>(Opcode::FPFloor32, value); 579 return Inst<F32>(Opcode::FPFloor32, Flags{control}, value);
580 case Type::F64: 580 case Type::F64:
581 return Inst<F64>(Opcode::FPFloor64, value); 581 return Inst<F64>(Opcode::FPFloor64, Flags{control}, value);
582 default: 582 default:
583 ThrowInvalidType(value.Type()); 583 ThrowInvalidType(value.Type());
584 } 584 }
585} 585}
586 586
587F16F32F64 IREmitter::FPCeil(const F16F32F64& value) { 587F16F32F64 IREmitter::FPCeil(const F16F32F64& value, FpControl control) {
588 switch (value.Type()) { 588 switch (value.Type()) {
589 case Type::F16: 589 case Type::F16:
590 return Inst<F16>(Opcode::FPCeil16, value); 590 return Inst<F16>(Opcode::FPCeil16, Flags{control}, value);
591 case Type::F32: 591 case Type::F32:
592 return Inst<F32>(Opcode::FPCeil32, value); 592 return Inst<F32>(Opcode::FPCeil32, Flags{control}, value);
593 case Type::F64: 593 case Type::F64:
594 return Inst<F64>(Opcode::FPCeil64, value); 594 return Inst<F64>(Opcode::FPCeil64, Flags{control}, value);
595 default: 595 default:
596 ThrowInvalidType(value.Type()); 596 ThrowInvalidType(value.Type());
597 } 597 }
598} 598}
599 599
600F16F32F64 IREmitter::FPTrunc(const F16F32F64& value) { 600F16F32F64 IREmitter::FPTrunc(const F16F32F64& value, FpControl control) {
601 switch (value.Type()) { 601 switch (value.Type()) {
602 case Type::F16: 602 case Type::F16:
603 return Inst<F16>(Opcode::FPTrunc16, value); 603 return Inst<F16>(Opcode::FPTrunc16, Flags{control}, value);
604 case Type::F32: 604 case Type::F32:
605 return Inst<F32>(Opcode::FPTrunc32, value); 605 return Inst<F32>(Opcode::FPTrunc32, Flags{control}, value);
606 case Type::F64: 606 case Type::F64:
607 return Inst<F64>(Opcode::FPTrunc64, value); 607 return Inst<F64>(Opcode::FPTrunc64, Flags{control}, value);
608 default: 608 default:
609 ThrowInvalidType(value.Type()); 609 ThrowInvalidType(value.Type());
610 } 610 }
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h
index 24b012a39..959f4f9da 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.h
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.h
@@ -129,10 +129,10 @@ public:
129 [[nodiscard]] F32 FPSinNotReduced(const F32& value); 129 [[nodiscard]] F32 FPSinNotReduced(const F32& value);
130 [[nodiscard]] F32 FPSqrt(const F32& value); 130 [[nodiscard]] F32 FPSqrt(const F32& value);
131 [[nodiscard]] F16F32F64 FPSaturate(const F16F32F64& value); 131 [[nodiscard]] F16F32F64 FPSaturate(const F16F32F64& value);
132 [[nodiscard]] F16F32F64 FPRoundEven(const F16F32F64& value); 132 [[nodiscard]] F16F32F64 FPRoundEven(const F16F32F64& value, FpControl control = {});
133 [[nodiscard]] F16F32F64 FPFloor(const F16F32F64& value); 133 [[nodiscard]] F16F32F64 FPFloor(const F16F32F64& value, FpControl control = {});
134 [[nodiscard]] F16F32F64 FPCeil(const F16F32F64& value); 134 [[nodiscard]] F16F32F64 FPCeil(const F16F32F64& value, FpControl control = {});
135 [[nodiscard]] F16F32F64 FPTrunc(const F16F32F64& value); 135 [[nodiscard]] F16F32F64 FPTrunc(const F16F32F64& value, FpControl control = {});
136 136
137 [[nodiscard]] U32U64 IAdd(const U32U64& a, const U32U64& b); 137 [[nodiscard]] U32U64 IAdd(const U32U64& a, const U32U64& b);
138 [[nodiscard]] U32U64 ISub(const U32U64& a, const U32U64& b); 138 [[nodiscard]] U32U64 ISub(const U32U64& a, const U32U64& b);
diff --git a/src/shader_recompiler/frontend/ir/modifiers.h b/src/shader_recompiler/frontend/ir/modifiers.h
index c288eede0..44652eae7 100644
--- a/src/shader_recompiler/frontend/ir/modifiers.h
+++ b/src/shader_recompiler/frontend/ir/modifiers.h
@@ -4,25 +4,30 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h"
8
7namespace Shader::IR { 9namespace Shader::IR {
8 10
9enum class FmzMode : u8 { 11enum class FmzMode : u8 {
10 None, // Denorms are not flushed, NAN is propagated (nouveau) 12 DontCare, // Not specified for this instruction
11 FTZ, // Flush denorms to zero, NAN is propagated (D3D11, NVN, GL, VK) 13 FTZ, // Flush denorms to zero, NAN is propagated (D3D11, NVN, GL, VK)
12 FMZ, // Flush denorms to zero, x * 0 == 0 (D3D9) 14 FMZ, // Flush denorms to zero, x * 0 == 0 (D3D9)
15 None, // Denorms are not flushed, NAN is propagated (nouveau)
13}; 16};
14 17
15enum class FpRounding : u8 { 18enum class FpRounding : u8 {
16 RN, // Round to nearest even, 19 DontCare, // Not specified for this instruction
17 RM, // Round towards negative infinity 20 RN, // Round to nearest even,
18 RP, // Round towards positive infinity 21 RM, // Round towards negative infinity
19 RZ, // Round towards zero 22 RP, // Round towards positive infinity
23 RZ, // Round towards zero
20}; 24};
21 25
22struct FpControl { 26struct FpControl {
23 bool no_contraction{false}; 27 bool no_contraction{false};
24 FpRounding rounding{FpRounding::RN}; 28 FpRounding rounding{FpRounding::DontCare};
25 FmzMode fmz_mode{FmzMode::FTZ}; 29 FmzMode fmz_mode{FmzMode::DontCare};
26}; 30};
27static_assert(sizeof(FpControl) <= sizeof(u32)); 31static_assert(sizeof(FpControl) <= sizeof(u32));
32
28} // namespace Shader::IR 33} // namespace Shader::IR
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 ae2d37405..4d82a0009 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
@@ -81,17 +81,28 @@ void TranslateF2I(TranslatorVisitor& v, u64 insn, const IR::F16F32F64& src_a) {
81 // F2I is used to convert from a floating point value to an integer 81 // F2I is used to convert from a floating point value to an integer
82 const F2I f2i{insn}; 82 const F2I f2i{insn};
83 83
84 const bool denorm_cares{f2i.src_format != SrcFormat::F16 && f2i.src_format != SrcFormat::F64 &&
85 f2i.dest_format != DestFormat::I64};
86 IR::FmzMode fmz_mode{IR::FmzMode::DontCare};
87 if (denorm_cares) {
88 fmz_mode = f2i.ftz != 0 ? IR::FmzMode::FTZ : IR::FmzMode::None;
89 }
90 const IR::FpControl fp_control{
91 .no_contraction{true},
92 .rounding{IR::FpRounding::DontCare},
93 .fmz_mode{fmz_mode},
94 };
84 const IR::F16F32F64 op_a{v.ir.FPAbsNeg(src_a, f2i.abs != 0, f2i.neg != 0)}; 95 const IR::F16F32F64 op_a{v.ir.FPAbsNeg(src_a, f2i.abs != 0, f2i.neg != 0)};
85 const IR::F16F32F64 rounded_value{[&] { 96 const IR::F16F32F64 rounded_value{[&] {
86 switch (f2i.rounding) { 97 switch (f2i.rounding) {
87 case Rounding::Round: 98 case Rounding::Round:
88 return v.ir.FPRoundEven(op_a); 99 return v.ir.FPRoundEven(op_a, fp_control);
89 case Rounding::Floor: 100 case Rounding::Floor:
90 return v.ir.FPFloor(op_a); 101 return v.ir.FPFloor(op_a, fp_control);
91 case Rounding::Ceil: 102 case Rounding::Ceil:
92 return v.ir.FPCeil(op_a); 103 return v.ir.FPCeil(op_a, fp_control);
93 case Rounding::Trunc: 104 case Rounding::Trunc:
94 return v.ir.FPTrunc(op_a); 105 return v.ir.FPTrunc(op_a, fp_control);
95 default: 106 default:
96 throw NotImplementedException("Invalid F2I rounding {}", f2i.rounding.Value()); 107 throw NotImplementedException("Invalid F2I rounding {}", f2i.rounding.Value());
97 } 108 }