// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "SpirvShader.hpp"

#include <spirv/unified1/spirv.hpp>

namespace sw {

struct SpirvShader::Impl::Group
{
	// Template function to perform a binary operation.
	// |TYPE| should be the type of the binary operation (as a SIMD::<ScalarType>).
	// |I| should be a type suitable to initialize the identity value.
	// |APPLY| should be a callable object that takes two RValue<TYPE> parameters
	// and returns a new RValue<TYPE> corresponding to the operation's result.
	template<typename TYPE, typename I, typename APPLY>
	static void BinaryOperation(
	    const SpirvShader *shader,
	    const SpirvShader::InsnIterator &insn,
	    const SpirvShader::EmitState *state,
	    Intermediate &dst,
	    const I identityValue,
	    APPLY &&apply)
	{
		SpirvShader::Operand value(shader, state, insn.word(5));
		auto &type = shader->getType(SpirvShader::Type::ID(insn.word(1)));
		for(auto i = 0u; i < type.componentCount; i++)
		{
			auto mask = As<SIMD::UInt>(state->activeLaneMask());  // Considers helper invocations active. See b/151137030
			auto identity = TYPE(identityValue);
			SIMD::UInt v_uint = (value.UInt(i) & mask) | (As<SIMD::UInt>(identity) & ~mask);
			TYPE v = As<TYPE>(v_uint);
			switch(spv::GroupOperation(insn.word(4)))
			{
				case spv::GroupOperationReduce:
				{
					// NOTE: floating-point add and multiply are not really commutative so
					//       ensure that all values in the final lanes are identical
					TYPE v2 = apply(v.xxzz, v.yyww);    // [xy]   [xy]   [zw]   [zw]
					TYPE v3 = apply(v2.xxxx, v2.zzzz);  // [xyzw] [xyzw] [xyzw] [xyzw]
					dst.move(i, v3);
					break;
				}
				case spv::GroupOperationInclusiveScan:
				{
					TYPE v2 = apply(v, Shuffle(v, identity, 0x4012) /* [id, v.y, v.z, v.w] */);      // [x] [xy] [yz]  [zw]
					TYPE v3 = apply(v2, Shuffle(v2, identity, 0x4401) /* [id,  id, v2.x, v2.y] */);  // [x] [xy] [xyz] [xyzw]
					dst.move(i, v3);
					break;
				}
				case spv::GroupOperationExclusiveScan:
				{
					TYPE v2 = apply(v, Shuffle(v, identity, 0x4012) /* [id, v.y, v.z, v.w] */);      // [x] [xy] [yz]  [zw]
					TYPE v3 = apply(v2, Shuffle(v2, identity, 0x4401) /* [id,  id, v2.x, v2.y] */);  // [x] [xy] [xyz] [xyzw]
					auto v4 = Shuffle(v3, identity, 0x4012 /* [id, v3.x, v3.y, v3.z] */);            // [i] [x]  [xy]  [xyz]
					dst.move(i, v4);
					break;
				}
				default:
					UNSUPPORTED("EmitGroupNonUniform op: %s Group operation: %d",
					            SpirvShader::OpcodeName(type.opcode()), insn.word(4));
			}
		}
	}
};

SpirvShader::EmitResult SpirvShader::EmitGroupNonUniform(InsnIterator insn, EmitState *state) const
{
	static_assert(SIMD::Width == 4, "EmitGroupNonUniform makes many assumptions that the SIMD vector width is 4");

	auto &type = getType(Type::ID(insn.word(1)));
	Object::ID resultId = insn.word(2);
	auto scope = spv::Scope(GetConstScalarInt(insn.word(3)));
	ASSERT_MSG(scope == spv::ScopeSubgroup, "Scope for Non Uniform Group Operations must be Subgroup for Vulkan 1.1");

	auto &dst = state->createIntermediate(resultId, type.componentCount);

	switch(insn.opcode())
	{
		case spv::OpGroupNonUniformElect:
		{
			// Result is true only in the active invocation with the lowest id
			// in the group, otherwise result is false.
			SIMD::Int active = state->activeLaneMask();  // Considers helper invocations active. See b/151137030
			// TODO: Would be nice if we could write this as:
			//   elect = active & ~(active.Oxyz | active.OOxy | active.OOOx)
			auto v0111 = SIMD::Int(0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
			auto elect = active & ~(v0111 & (active.xxyz | active.xxxy | active.xxxx));
			dst.move(0, elect);
			break;
		}

		case spv::OpGroupNonUniformAll:
		{
			Operand predicate(this, state, insn.word(4));
			dst.move(0, AndAll(predicate.UInt(0) | ~As<SIMD::UInt>(state->activeLaneMask())));  // Considers helper invocations active. See b/151137030
			break;
		}

		case spv::OpGroupNonUniformAny:
		{
			Operand predicate(this, state, insn.word(4));
			dst.move(0, OrAll(predicate.UInt(0) & As<SIMD::UInt>(state->activeLaneMask())));  // Considers helper invocations active. See b/151137030
			break;
		}

		case spv::OpGroupNonUniformAllEqual:
		{
			Operand value(this, state, insn.word(4));
			auto res = SIMD::UInt(0xffffffff);
			SIMD::UInt active = As<SIMD::UInt>(state->activeLaneMask());  // Considers helper invocations active. See b/151137030
			SIMD::UInt inactive = ~active;
			for(auto i = 0u; i < type.componentCount; i++)
			{
				SIMD::UInt v = value.UInt(i) & active;
				SIMD::UInt filled = v;
				for(int j = 0; j < SIMD::Width - 1; j++)
				{
					filled |= filled.yzwx & inactive;  // Populate inactive 'holes' with a live value
				}
				res &= AndAll(CmpEQ(filled.xyzw, filled.yzwx));
			}
			dst.move(0, res);
			break;
		}

		case spv::OpGroupNonUniformBroadcast:
		{
			auto valueId = Object::ID(insn.word(4));
			auto idId = Object::ID(insn.word(5));
			Operand value(this, state, valueId);

			// Decide between the fast path for constants and the slow path for
			// intermediates.
			if(getObject(idId).kind == SpirvShader::Object::Kind::Constant)
			{
				auto id = SIMD::Int(GetConstScalarInt(insn.word(5)));
				auto mask = CmpEQ(id, SIMD::Int(0, 1, 2, 3));
				for(auto i = 0u; i < type.componentCount; i++)
				{
					dst.move(i, OrAll(value.Int(i) & mask));
				}
			}
			else
			{
				Operand id(this, state, idId);

				SIMD::UInt active = As<SIMD::UInt>(state->activeLaneMask());  // Considers helper invocations active. See b/151137030
				SIMD::UInt inactive = ~active;
				SIMD::UInt filled = id.UInt(0) & active;

				for(int j = 0; j < SIMD::Width - 1; j++)
				{
					filled |= filled.yzwx & inactive;  // Populate inactive 'holes' with a live value
				}

				auto mask = CmpEQ(filled, SIMD::UInt(0, 1, 2, 3));

				for(uint32_t i = 0u; i < type.componentCount; i++)
				{
					dst.move(i, OrAll(value.UInt(i) & mask));
				}
			}
			break;
		}

		case spv::OpGroupNonUniformBroadcastFirst:
		{
			auto valueId = Object::ID(insn.word(4));
			Operand value(this, state, valueId);
			// Result is true only in the active invocation with the lowest id
			// in the group, otherwise result is false.
			SIMD::Int active = state->activeLaneMask();  // Considers helper invocations active. See b/151137030
			// TODO: Would be nice if we could write this as:
			//   elect = active & ~(active.Oxyz | active.OOxy | active.OOOx)
			auto v0111 = SIMD::Int(0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
			auto elect = active & ~(v0111 & (active.xxyz | active.xxxy | active.xxxx));
			for(auto i = 0u; i < type.componentCount; i++)
			{
				dst.move(i, OrAll(value.Int(i) & elect));
			}
			break;
		}

		case spv::OpGroupNonUniformBallot:
		{
			ASSERT(type.componentCount == 4);
			Operand predicate(this, state, insn.word(4));
			dst.move(0, SIMD::Int(SignMask(state->activeLaneMask() & predicate.Int(0))));  // Considers helper invocations active. See b/151137030
			dst.move(1, SIMD::Int(0));
			dst.move(2, SIMD::Int(0));
			dst.move(3, SIMD::Int(0));
			break;
		}

		case spv::OpGroupNonUniformInverseBallot:
		{
			auto valueId = Object::ID(insn.word(4));
			ASSERT(type.componentCount == 1);
			ASSERT(getType(getObject(valueId)).componentCount == 4);
			Operand value(this, state, valueId);
			auto bit = (value.Int(0) >> SIMD::Int(0, 1, 2, 3)) & SIMD::Int(1);
			dst.move(0, -bit);
			break;
		}

		case spv::OpGroupNonUniformBallotBitExtract:
		{
			auto valueId = Object::ID(insn.word(4));
			auto indexId = Object::ID(insn.word(5));
			ASSERT(type.componentCount == 1);
			ASSERT(getType(getObject(valueId)).componentCount == 4);
			ASSERT(getType(getObject(indexId)).componentCount == 1);
			Operand value(this, state, valueId);
			Operand index(this, state, indexId);
			auto vecIdx = index.Int(0) / SIMD::Int(32);
			auto bitIdx = index.Int(0) & SIMD::Int(31);
			auto bits = (value.Int(0) & CmpEQ(vecIdx, SIMD::Int(0))) |
			            (value.Int(1) & CmpEQ(vecIdx, SIMD::Int(1))) |
			            (value.Int(2) & CmpEQ(vecIdx, SIMD::Int(2))) |
			            (value.Int(3) & CmpEQ(vecIdx, SIMD::Int(3)));
			dst.move(0, -((bits >> bitIdx) & SIMD::Int(1)));
			break;
		}

		case spv::OpGroupNonUniformBallotBitCount:
		{
			auto operation = spv::GroupOperation(insn.word(4));
			auto valueId = Object::ID(insn.word(5));
			ASSERT(type.componentCount == 1);
			ASSERT(getType(getObject(valueId)).componentCount == 4);
			Operand value(this, state, valueId);
			switch(operation)
			{
				case spv::GroupOperationReduce:
					dst.move(0, CountBits(value.UInt(0) & SIMD::UInt(15)));
					break;
				case spv::GroupOperationInclusiveScan:
					dst.move(0, CountBits(value.UInt(0) & SIMD::UInt(1, 3, 7, 15)));
					break;
				case spv::GroupOperationExclusiveScan:
					dst.move(0, CountBits(value.UInt(0) & SIMD::UInt(0, 1, 3, 7)));
					break;
				default:
					UNSUPPORTED("GroupOperation %d", int(operation));
			}
			break;
		}

		case spv::OpGroupNonUniformBallotFindLSB:
		{
			auto valueId = Object::ID(insn.word(4));
			ASSERT(type.componentCount == 1);
			ASSERT(getType(getObject(valueId)).componentCount == 4);
			Operand value(this, state, valueId);
			dst.move(0, Cttz(value.UInt(0) & SIMD::UInt(15), true));
			break;
		}

		case spv::OpGroupNonUniformBallotFindMSB:
		{
			auto valueId = Object::ID(insn.word(4));
			ASSERT(type.componentCount == 1);
			ASSERT(getType(getObject(valueId)).componentCount == 4);
			Operand value(this, state, valueId);
			dst.move(0, SIMD::UInt(31) - Ctlz(value.UInt(0) & SIMD::UInt(15), false));
			break;
		}

		case spv::OpGroupNonUniformShuffle:
		{
			Operand value(this, state, insn.word(4));
			Operand id(this, state, insn.word(5));
			auto x = CmpEQ(SIMD::Int(0), id.Int(0));
			auto y = CmpEQ(SIMD::Int(1), id.Int(0));
			auto z = CmpEQ(SIMD::Int(2), id.Int(0));
			auto w = CmpEQ(SIMD::Int(3), id.Int(0));
			for(auto i = 0u; i < type.componentCount; i++)
			{
				SIMD::Int v = value.Int(i);
				dst.move(i, (x & v.xxxx) | (y & v.yyyy) | (z & v.zzzz) | (w & v.wwww));
			}
			break;
		}

		case spv::OpGroupNonUniformShuffleXor:
		{
			Operand value(this, state, insn.word(4));
			Operand mask(this, state, insn.word(5));
			auto x = CmpEQ(SIMD::Int(0), SIMD::Int(0, 1, 2, 3) ^ mask.Int(0));
			auto y = CmpEQ(SIMD::Int(1), SIMD::Int(0, 1, 2, 3) ^ mask.Int(0));
			auto z = CmpEQ(SIMD::Int(2), SIMD::Int(0, 1, 2, 3) ^ mask.Int(0));
			auto w = CmpEQ(SIMD::Int(3), SIMD::Int(0, 1, 2, 3) ^ mask.Int(0));
			for(auto i = 0u; i < type.componentCount; i++)
			{
				SIMD::Int v = value.Int(i);
				dst.move(i, (x & v.xxxx) | (y & v.yyyy) | (z & v.zzzz) | (w & v.wwww));
			}
			break;
		}

		case spv::OpGroupNonUniformShuffleUp:
		{
			Operand value(this, state, insn.word(4));
			Operand delta(this, state, insn.word(5));
			auto d0 = CmpEQ(SIMD::Int(0), delta.Int(0));
			auto d1 = CmpEQ(SIMD::Int(1), delta.Int(0));
			auto d2 = CmpEQ(SIMD::Int(2), delta.Int(0));
			auto d3 = CmpEQ(SIMD::Int(3), delta.Int(0));
			for(auto i = 0u; i < type.componentCount; i++)
			{
				SIMD::Int v = value.Int(i);
				dst.move(i, (d0 & v.xyzw) | (d1 & v.xxyz) | (d2 & v.xxxy) | (d3 & v.xxxx));
			}
			break;
		}

		case spv::OpGroupNonUniformShuffleDown:
		{
			Operand value(this, state, insn.word(4));
			Operand delta(this, state, insn.word(5));
			auto d0 = CmpEQ(SIMD::Int(0), delta.Int(0));
			auto d1 = CmpEQ(SIMD::Int(1), delta.Int(0));
			auto d2 = CmpEQ(SIMD::Int(2), delta.Int(0));
			auto d3 = CmpEQ(SIMD::Int(3), delta.Int(0));
			for(auto i = 0u; i < type.componentCount; i++)
			{
				SIMD::Int v = value.Int(i);
				dst.move(i, (d0 & v.xyzw) | (d1 & v.yzww) | (d2 & v.zwww) | (d3 & v.wwww));
			}
			break;
		}

		case spv::OpGroupNonUniformIAdd:
			Impl::Group::BinaryOperation<SIMD::Int>(
			    this, insn, state, dst, 0,
			    [](auto a, auto b) { return a + b; });
			break;

		case spv::OpGroupNonUniformFAdd:
			Impl::Group::BinaryOperation<SIMD::Float>(
			    this, insn, state, dst, 0.0f,
			    [](auto a, auto b) { return a + b; });
			break;

		case spv::OpGroupNonUniformIMul:
			Impl::Group::BinaryOperation<SIMD::Int>(
			    this, insn, state, dst, 1,
			    [](auto a, auto b) { return a * b; });
			break;

		case spv::OpGroupNonUniformFMul:
			Impl::Group::BinaryOperation<SIMD::Float>(
			    this, insn, state, dst, 1.0f,
			    [](auto a, auto b) { return a * b; });
			break;

		case spv::OpGroupNonUniformBitwiseAnd:
			Impl::Group::BinaryOperation<SIMD::UInt>(
			    this, insn, state, dst, ~0u,
			    [](auto a, auto b) { return a & b; });
			break;

		case spv::OpGroupNonUniformBitwiseOr:
			Impl::Group::BinaryOperation<SIMD::UInt>(
			    this, insn, state, dst, 0,
			    [](auto a, auto b) { return a | b; });
			break;

		case spv::OpGroupNonUniformBitwiseXor:
			Impl::Group::BinaryOperation<SIMD::UInt>(
			    this, insn, state, dst, 0,
			    [](auto a, auto b) { return a ^ b; });
			break;

		case spv::OpGroupNonUniformSMin:
			Impl::Group::BinaryOperation<SIMD::Int>(
			    this, insn, state, dst, INT32_MAX,
			    [](auto a, auto b) { return Min(a, b); });
			break;

		case spv::OpGroupNonUniformUMin:
			Impl::Group::BinaryOperation<SIMD::UInt>(
			    this, insn, state, dst, ~0u,
			    [](auto a, auto b) { return Min(a, b); });
			break;

		case spv::OpGroupNonUniformFMin:
			Impl::Group::BinaryOperation<SIMD::Float>(
			    this, insn, state, dst, SIMD::Float::infinity(),
			    [](auto a, auto b) { return NMin(a, b); });
			break;

		case spv::OpGroupNonUniformSMax:
			Impl::Group::BinaryOperation<SIMD::Int>(
			    this, insn, state, dst, INT32_MIN,
			    [](auto a, auto b) { return Max(a, b); });
			break;

		case spv::OpGroupNonUniformUMax:
			Impl::Group::BinaryOperation<SIMD::UInt>(
			    this, insn, state, dst, 0,
			    [](auto a, auto b) { return Max(a, b); });
			break;

		case spv::OpGroupNonUniformFMax:
			Impl::Group::BinaryOperation<SIMD::Float>(
			    this, insn, state, dst, -SIMD::Float::infinity(),
			    [](auto a, auto b) { return NMax(a, b); });
			break;

		case spv::OpGroupNonUniformLogicalAnd:
			Impl::Group::BinaryOperation<SIMD::UInt>(
			    this, insn, state, dst, ~0u,
			    [](auto a, auto b) {
				    SIMD::UInt zero = SIMD::UInt(0);
				    return CmpNEQ(a, zero) & CmpNEQ(b, zero);
			    });
			break;

		case spv::OpGroupNonUniformLogicalOr:
			Impl::Group::BinaryOperation<SIMD::UInt>(
			    this, insn, state, dst, 0,
			    [](auto a, auto b) {
				    SIMD::UInt zero = SIMD::UInt(0);
				    return CmpNEQ(a, zero) | CmpNEQ(b, zero);
			    });
			break;

		case spv::OpGroupNonUniformLogicalXor:
			Impl::Group::BinaryOperation<SIMD::UInt>(
			    this, insn, state, dst, 0,
			    [](auto a, auto b) {
				    SIMD::UInt zero = SIMD::UInt(0);
				    return CmpNEQ(a, zero) ^ CmpNEQ(b, zero);
			    });
			break;

		default:
			UNSUPPORTED("EmitGroupNonUniform op: %s", OpcodeName(type.opcode()));
	}
	return EmitResult::Continue;
}

}  // namespace sw
