SpirvShader: Implement GLSLstd450Fma

Bug: b/126873455
Tests: dEQP-VK.glsl.builtin.function.common.fma.*
Change-Id: I00e890a6a051b45bc552944ec5364f070ee3a768
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/28629
Tested-by: Ben Clayton <bclayton@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index 0c1f43d..fb7e620 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -50,6 +50,15 @@
 	{
 		return NthBit32(bitCount) - sw::SIMD::UInt(1);
 	}
+
+	// Performs a fused-multiply add, returning a * b + c.
+	rr::RValue<sw::SIMD::Float> FMA(
+			rr::RValue<sw::SIMD::Float> const &a,
+			rr::RValue<sw::SIMD::Float> const &b,
+			rr::RValue<sw::SIMD::Float> const &c)
+	{
+		return a * b + c;
+	}
 }
 
 namespace sw
@@ -3179,6 +3188,17 @@
 			dst.move(1, HalfToFloatBits((val.UInt(0) & SIMD::UInt(0xFFFF0000)) >> 16));
 			break;
 		}
+		case GLSLstd450Fma:
+		{
+			auto a = GenericValue(this, routine, insn.word(5));
+			auto b = GenericValue(this, routine, insn.word(6));
+			auto c = GenericValue(this, routine, insn.word(7));
+			for (auto i = 0u; i < type.sizeInComponents; i++)
+			{
+				dst.move(i, FMA(a.Float(i), b.Float(i), c.Float(i)));
+			}
+			break;
+		}
 		case GLSLstd450Frexp:
 		{
 			auto val = GenericValue(this, routine, insn.word(5));