diff --git a/src/shader_recompiler/backend/glsl/emit_context.h b/src/shader_recompiler/backend/glsl/emit_context.h
index 423fc61046..48786a2c76 100644
--- a/src/shader_recompiler/backend/glsl/emit_context.h
+++ b/src/shader_recompiler/backend/glsl/emit_context.h
@@ -118,6 +118,16 @@ public:
         Add<GlslVarType::F32x4>(format_str, inst, args...);
     }
 
+    template <typename... Args>
+    void AddPrecF32(const char* format_str, IR::Inst& inst, Args&&... args) {
+        Add<GlslVarType::PrecF32>(format_str, inst, args...);
+    }
+
+    template <typename... Args>
+    void AddPrecF64(const char* format_str, IR::Inst& inst, Args&&... args) {
+        Add<GlslVarType::PrecF64>(format_str, inst, args...);
+    }
+
     template <typename... Args>
     void Add(const char* format_str, Args&&... args) {
         code += fmt::format(format_str, std::forward<Args>(args)...);
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp
index 5f9603602d..342d4efb2e 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_floating_point.cpp
@@ -6,6 +6,7 @@
 
 #include "shader_recompiler/backend/glsl/emit_context.h"
 #include "shader_recompiler/backend/glsl/emit_glsl_instructions.h"
+#include "shader_recompiler/frontend/ir/modifiers.h"
 #include "shader_recompiler/frontend/ir/value.h"
 
 namespace Shader::Backend::GLSL {
@@ -20,6 +21,10 @@ void Compare(EmitContext& ctx, IR::Inst& inst, std::string_view lhs, std::string
     }
     ctx.code += ";";
 }
+
+bool Precise(IR::Inst& inst) {
+    return {inst.Flags<IR::FpControl>().no_contraction};
+}
 } // namespace
 
 void EmitFPAbs16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
@@ -41,11 +46,19 @@ void EmitFPAdd16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& i
 }
 
 void EmitFPAdd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
-    ctx.AddF32("{}=float({})+float({});", inst, a, b);
+    if (Precise(inst)) {
+        ctx.AddPrecF32("{}=float({})+float({});", inst, a, b);
+    } else {
+        ctx.AddF32("{}=float({})+float({});", inst, a, b);
+    }
 }
 
 void EmitFPAdd64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
-    ctx.AddF64("{}=double({})+double({});", inst, a, b);
+    if (Precise(inst)) {
+        ctx.AddPrecF64("{}=double({})+double({});", inst, a, b);
+    } else {
+        ctx.AddF64("{}=double({})+double({});", inst, a, b);
+    }
 }
 
 void EmitFPFma16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
@@ -56,12 +69,20 @@ void EmitFPFma16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& i
 
 void EmitFPFma32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b,
                  std::string_view c) {
-    ctx.AddF32("{}=fma({},{},{});", inst, a, b, c);
+    if (Precise(inst)) {
+        ctx.AddPrecF32("{}=fma({},{},{});", inst, a, b, c);
+    } else {
+        ctx.AddF32("{}=fma({},{},{});", inst, a, b, c);
+    }
 }
 
 void EmitFPFma64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b,
                  std::string_view c) {
-    ctx.AddF64("{}=fma({},{},{});", inst, a, b, c);
+    if (Precise(inst)) {
+        ctx.AddPrecF64("{}=fma({},{},{});", inst, a, b, c);
+    } else {
+        ctx.AddF64("{}=fma({},{},{});", inst, a, b, c);
+    }
 }
 
 void EmitFPMax32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
@@ -86,11 +107,19 @@ void EmitFPMul16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& i
 }
 
 void EmitFPMul32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
-    ctx.AddF32("{}={}*{};", inst, a, b);
+    if (Precise(inst)) {
+        ctx.AddPrecF32("{}={}*{};", inst, a, b);
+    } else {
+        ctx.AddF32("{}={}*{};", inst, a, b);
+    }
 }
 
 void EmitFPMul64(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::string_view b) {
-    ctx.AddF64("{}={}*{};", inst, a, b);
+    if (Precise(inst)) {
+        ctx.AddPrecF64("{}={}*{};", inst, a, b);
+    } else {
+        ctx.AddF64("{}={}*{};", inst, a, b);
+    }
 }
 
 void EmitFPNeg16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
diff --git a/src/shader_recompiler/backend/glsl/var_alloc.cpp b/src/shader_recompiler/backend/glsl/var_alloc.cpp
index 896457248b..2ecdec7f21 100644
--- a/src/shader_recompiler/backend/glsl/var_alloc.cpp
+++ b/src/shader_recompiler/backend/glsl/var_alloc.cpp
@@ -43,6 +43,10 @@ std::string TypePrefix(GlslVarType type) {
         return "u4_";
     case GlslVarType::F32x4:
         return "f4_";
+    case GlslVarType::PrecF32:
+        return "pf_";
+    case GlslVarType::PrecF64:
+        return "pd_";
     case GlslVarType::Void:
         return "";
     default:
@@ -225,6 +229,10 @@ std::string VarAlloc::GetGlslType(GlslVarType type) const {
         return "uvec4 ";
     case GlslVarType::F32x4:
         return "vec4 ";
+    case GlslVarType::PrecF32:
+        return "precise float ";
+    case GlslVarType::PrecF64:
+        return "precise double ";
     case GlslVarType::Void:
         return "";
     default:
@@ -262,6 +270,10 @@ VarAlloc::UseTracker& VarAlloc::GetUseTracker(GlslVarType type) {
         return var_u32x4;
     case GlslVarType::F32x4:
         return var_f32x4;
+    case GlslVarType::PrecF32:
+        return var_precf32;
+    case GlslVarType::PrecF64:
+        return var_precf64;
     default:
         throw NotImplementedException("Type {}", type);
     }
@@ -297,6 +309,10 @@ const VarAlloc::UseTracker& VarAlloc::GetUseTracker(GlslVarType type) const {
         return var_u32x4;
     case GlslVarType::F32x4:
         return var_f32x4;
+    case GlslVarType::PrecF32:
+        return var_precf32;
+    case GlslVarType::PrecF64:
+        return var_precf64;
     default:
         throw NotImplementedException("Type {}", type);
     }
diff --git a/src/shader_recompiler/backend/glsl/var_alloc.h b/src/shader_recompiler/backend/glsl/var_alloc.h
index 574960b1a8..be21a87ea3 100644
--- a/src/shader_recompiler/backend/glsl/var_alloc.h
+++ b/src/shader_recompiler/backend/glsl/var_alloc.h
@@ -33,6 +33,8 @@ enum class GlslVarType : u32 {
     F32x3,
     U32x4,
     F32x4,
+    PrecF32,
+    PrecF64,
     Void,
 };
 
@@ -40,8 +42,8 @@ struct Id {
     union {
         u32 raw;
         BitField<0, 1, u32> is_valid;
-        BitField<1, 4, GlslVarType> type;
-        BitField<5, 27, u32> index;
+        BitField<1, 5, GlslVarType> type;
+        BitField<6, 26, u32> index;
     };
 
     bool operator==(Id rhs) const noexcept {
@@ -101,6 +103,8 @@ private:
     UseTracker var_u64{};
     UseTracker var_s64{};
     UseTracker var_f64{};
+    UseTracker var_precf32{};
+    UseTracker var_precf64{};
 };
 
 } // namespace Shader::Backend::GLSL