Пример #1
0
        public static void Atoms(EmitterContext context)
        {
            InstAtoms op = context.GetOp <InstAtoms>();

            Operand offset = context.ShiftRightU32(GetSrcReg(context, op.SrcA), Const(2));

            int sOffset = (op.Imm22 << 10) >> 10;

            offset = context.IAdd(offset, Const(sOffset));

            Operand value = GetSrcReg(context, op.SrcB);

            AtomSize size = op.AtomsSize switch
            {
                AtomsSize.S32 => AtomSize.S32,
                AtomsSize.U64 => AtomSize.U64,
                AtomsSize.S64 => AtomSize.S64,
                _ => AtomSize.U32
            };

            Operand res = EmitAtomicOp(context, Instruction.MrShared, op.AtomOp, size, offset, Const(0), value);

            context.Copy(GetDest(op.Dest), res);
        }
Пример #2
0
        private static Operand EmitAtomicOp(
            EmitterContext context,
            Instruction mr,
            AtomOp op,
            AtomSize type,
            Operand addrLow,
            Operand addrHigh,
            Operand value)
        {
            Operand res = Const(0);

            switch (op)
            {
            case AtomOp.Add:
                if (type == AtomSize.S32 || type == AtomSize.U32)
                {
                    res = context.AtomicAdd(mr, addrLow, addrHigh, value);
                }
                else
                {
                    context.Config.GpuAccessor.Log($"Invalid reduction type: {type}.");
                }
                break;

            case AtomOp.And:
                if (type == AtomSize.S32 || type == AtomSize.U32)
                {
                    res = context.AtomicAnd(mr, addrLow, addrHigh, value);
                }
                else
                {
                    context.Config.GpuAccessor.Log($"Invalid reduction type: {type}.");
                }
                break;

            case AtomOp.Xor:
                if (type == AtomSize.S32 || type == AtomSize.U32)
                {
                    res = context.AtomicXor(mr, addrLow, addrHigh, value);
                }
                else
                {
                    context.Config.GpuAccessor.Log($"Invalid reduction type: {type}.");
                }
                break;

            case AtomOp.Or:
                if (type == AtomSize.S32 || type == AtomSize.U32)
                {
                    res = context.AtomicOr(mr, addrLow, addrHigh, value);
                }
                else
                {
                    context.Config.GpuAccessor.Log($"Invalid reduction type: {type}.");
                }
                break;

            case AtomOp.Max:
                if (type == AtomSize.S32)
                {
                    res = context.AtomicMaxS32(mr, addrLow, addrHigh, value);
                }
                else if (type == AtomSize.U32)
                {
                    res = context.AtomicMaxU32(mr, addrLow, addrHigh, value);
                }
                else
                {
                    context.Config.GpuAccessor.Log($"Invalid reduction type: {type}.");
                }
                break;

            case AtomOp.Min:
                if (type == AtomSize.S32)
                {
                    res = context.AtomicMinS32(mr, addrLow, addrHigh, value);
                }
                else if (type == AtomSize.U32)
                {
                    res = context.AtomicMinU32(mr, addrLow, addrHigh, value);
                }
                else
                {
                    context.Config.GpuAccessor.Log($"Invalid reduction type: {type}.");
                }
                break;
            }

            return(res);
        }