Example #1
0
        private static void PropagateExpression(AstOperand propVar, IAstNode source)
        {
            IAstNode[] uses = propVar.Uses.ToArray();

            foreach (IAstNode useNode in uses)
            {
                if (useNode is AstBlock useBlock)
                {
                    useBlock.Condition = source;
                }
                else if (useNode is AstOperation useOperation)
                {
                    for (int srcIndex = 0; srcIndex < useOperation.SourcesCount; srcIndex++)
                    {
                        if (useOperation.GetSource(srcIndex) == propVar)
                        {
                            useOperation.SetSource(srcIndex, source);
                        }
                    }
                }
                else if (useNode is AstAssignment useAssignment)
                {
                    useAssignment.Source = source;
                }
            }
        }
Example #2
0
        public static AstOperand Local(VariableType type)
        {
            AstOperand local = new AstOperand(OperandType.LocalVariable);

            local.VarType = type;

            return(local);
        }
Example #3
0
 public static VariableType GetVarType(AstOperand operand)
 {
     if (operand.Type == OperandType.LocalVariable)
     {
         return(operand.VarType);
     }
     else
     {
         return(GetVarType(operand.Type));
     }
 }
Example #4
0
        private static void AddOperation(StructuredProgramContext context, Operation operation)
        {
            Instruction inst = operation.Inst;

            IAstNode[] sources = new IAstNode[operation.SourcesCount];

            for (int index = 0; index < sources.Length; index++)
            {
                sources[index] = context.GetOperandUse(operation.GetSource(index));
            }

            if (operation.Dest != null)
            {
                AstOperand dest = context.GetOperandDef(operation.Dest);

                if (inst == Instruction.LoadConstant)
                {
                    Operand ldcSource = operation.GetSource(0);

                    if (ldcSource.Type != OperandType.Constant)
                    {
                        throw new InvalidOperationException("Found LDC with non-constant constant buffer slot.");
                    }

                    context.Info.CBuffers.Add(ldcSource.Value);
                }

                AstAssignment assignment;

                //If all the sources are bool, it's better to use short-circuiting
                //logical operations, rather than forcing a cast to int and doing
                //a bitwise operation with the value, as it is likely to be used as
                //a bool in the end.
                if (IsBitwiseInst(inst) && AreAllSourceTypesEqual(sources, VariableType.Bool))
                {
                    inst = GetLogicalFromBitwiseInst(inst);
                }

                bool isCondSel = inst == Instruction.ConditionalSelect;
                bool isCopy    = inst == Instruction.Copy;

                if (isCondSel || isCopy)
                {
                    VariableType type = GetVarTypeFromUses(operation.Dest);

                    if (isCondSel && type == VariableType.F32)
                    {
                        inst |= Instruction.FP;
                    }

                    dest.VarType = type;
                }
                else
                {
                    dest.VarType = InstructionInfo.GetDestVarType(inst);
                }

                int componentMask = 1 << operation.ComponentIndex;

                IAstNode source;

                if (operation is TextureOperation texOp)
                {
                    AstTextureOperation astTexOp = new AstTextureOperation(
                        inst,
                        texOp.Type,
                        texOp.Flags,
                        texOp.Handle,
                        componentMask,
                        sources);

                    context.Info.Samplers.Add(astTexOp);

                    source = astTexOp;
                }
                else if (!isCopy)
                {
                    source = new AstOperation(inst, componentMask, sources);
                }
                else
                {
                    source = sources[0];
                }

                assignment = new AstAssignment(dest, source);

                context.AddNode(assignment);
            }
            else
            {
                context.AddNode(new AstOperation(inst, sources));
            }
        }
Example #5
0
        private static void AddOperation(StructuredProgramContext context, Operation operation)
        {
            Instruction inst = operation.Inst;

            if (inst == Instruction.LoadAttribute)
            {
                Operand src1 = operation.GetSource(0);
                Operand src2 = operation.GetSource(1);

                if (src1.Type == OperandType.Constant && src2.Type == OperandType.Constant)
                {
                    int attrOffset = (src1.Value & AttributeConsts.Mask) + (src2.Value << 2);
                    context.Info.Inputs.Add(attrOffset);
                }
            }

            int sourcesCount  = operation.SourcesCount;
            int outDestsCount = operation.DestsCount != 0 ? operation.DestsCount - 1 : 0;

            IAstNode[] sources = new IAstNode[sourcesCount + outDestsCount];

            for (int index = 0; index < operation.SourcesCount; index++)
            {
                sources[index] = context.GetOperandUse(operation.GetSource(index));
            }

            for (int index = 0; index < outDestsCount; index++)
            {
                AstOperand oper = context.GetOperandDef(operation.GetDest(1 + index));

                oper.VarType = InstructionInfo.GetSrcVarType(inst, sourcesCount + index);

                sources[sourcesCount + index] = oper;
            }

            AstTextureOperation GetAstTextureOperation(TextureOperation texOp)
            {
                return(new AstTextureOperation(
                           inst,
                           texOp.Type,
                           texOp.Format,
                           texOp.Flags,
                           texOp.CbufSlot,
                           texOp.Handle,
                           texOp.Index,
                           sources));
            }

            if (operation.Dest != null)
            {
                AstOperand dest = context.GetOperandDef(operation.Dest);

                // If all the sources are bool, it's better to use short-circuiting
                // logical operations, rather than forcing a cast to int and doing
                // a bitwise operation with the value, as it is likely to be used as
                // a bool in the end.
                if (IsBitwiseInst(inst) && AreAllSourceTypesEqual(sources, VariableType.Bool))
                {
                    inst = GetLogicalFromBitwiseInst(inst);
                }

                bool isCondSel = inst == Instruction.ConditionalSelect;
                bool isCopy    = inst == Instruction.Copy;

                if (isCondSel || isCopy)
                {
                    VariableType type = GetVarTypeFromUses(operation.Dest);

                    if (isCondSel && type == VariableType.F32)
                    {
                        inst |= Instruction.FP32;
                    }

                    dest.VarType = type;
                }
                else
                {
                    dest.VarType = InstructionInfo.GetDestVarType(inst);
                }

                IAstNode source;

                if (operation is TextureOperation texOp)
                {
                    if (texOp.Inst == Instruction.ImageLoad)
                    {
                        dest.VarType = texOp.Format.GetComponentType();
                    }

                    source = GetAstTextureOperation(texOp);
                }
                else if (!isCopy)
                {
                    source = new AstOperation(inst, operation.Index, sources, operation.SourcesCount);
                }
                else
                {
                    source = sources[0];
                }

                context.AddNode(new AstAssignment(dest, source));
            }
            else if (operation.Inst == Instruction.Comment)
            {
                context.AddNode(new AstComment(((CommentNode)operation).Comment));
            }
            else if (operation is TextureOperation texOp)
            {
                AstTextureOperation astTexOp = GetAstTextureOperation(texOp);

                context.AddNode(astTexOp);
            }
            else
            {
                context.AddNode(new AstOperation(inst, operation.Index, sources, operation.SourcesCount));
            }

            // Those instructions needs to be emulated by using helper functions,
            // because they are NVIDIA specific. Those flags helps the backend to
            // decide which helper functions are needed on the final generated code.
            switch (operation.Inst)
            {
            case Instruction.AtomicMaxS32 | Instruction.MrShared:
            case Instruction.AtomicMinS32 | Instruction.MrShared:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.AtomicMinMaxS32Shared;
                break;

            case Instruction.AtomicMaxS32 | Instruction.MrStorage:
            case Instruction.AtomicMinS32 | Instruction.MrStorage:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.AtomicMinMaxS32Storage;
                break;

            case Instruction.MultiplyHighS32:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.MultiplyHighS32;
                break;

            case Instruction.MultiplyHighU32:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.MultiplyHighU32;
                break;

            case Instruction.Shuffle:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.Shuffle;
                break;

            case Instruction.ShuffleDown:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.ShuffleDown;
                break;

            case Instruction.ShuffleUp:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.ShuffleUp;
                break;

            case Instruction.ShuffleXor:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.ShuffleXor;
                break;

            case Instruction.StoreShared16:
            case Instruction.StoreShared8:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.StoreSharedSmallInt;
                break;

            case Instruction.StoreStorage16:
            case Instruction.StoreStorage8:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.StoreStorageSmallInt;
                break;

            case Instruction.SwizzleAdd:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.SwizzleAdd;
                break;

            case Instruction.FSIBegin:
            case Instruction.FSIEnd:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.FSI;
                break;
            }
        }
Example #6
0
        private static void AddOperation(StructuredProgramContext context, Operation operation)
        {
            Instruction inst = operation.Inst;

            int sourcesCount  = operation.SourcesCount;
            int outDestsCount = operation.DestsCount != 0 ? operation.DestsCount - 1 : 0;

            IAstNode[] sources = new IAstNode[sourcesCount + outDestsCount];

            for (int index = 0; index < operation.SourcesCount; index++)
            {
                sources[index] = context.GetOperandUse(operation.GetSource(index));
            }

            for (int index = 0; index < outDestsCount; index++)
            {
                AstOperand oper = context.GetOperandDef(operation.GetDest(1 + index));

                oper.VarType = InstructionInfo.GetSrcVarType(inst, sourcesCount + index);

                sources[sourcesCount + index] = oper;
            }

            AstTextureOperation GetAstTextureOperation(TextureOperation texOp)
            {
                return(new AstTextureOperation(
                           inst,
                           texOp.Type,
                           texOp.Format,
                           texOp.Flags,
                           texOp.CbufSlot,
                           texOp.Handle,
                           4, // TODO: Non-hardcoded array size.
                           texOp.Index,
                           sources));
            }

            if (operation.Dest != null)
            {
                AstOperand dest = context.GetOperandDef(operation.Dest);

                if (inst == Instruction.LoadConstant)
                {
                    Operand slot = operation.GetSource(0);

                    if (slot.Type == OperandType.Constant)
                    {
                        context.Info.CBuffers.Add(slot.Value);
                    }
                    else
                    {
                        // If the value is not constant, then we don't know
                        // how many constant buffers are used, so we assume
                        // all of them are used.
                        int cbCount = 32 - BitOperations.LeadingZeroCount(context.Config.GpuAccessor.QueryConstantBufferUse());

                        for (int index = 0; index < cbCount; index++)
                        {
                            context.Info.CBuffers.Add(index);
                        }

                        context.Info.UsesCbIndexing = true;
                    }
                }
                else if (UsesStorage(inst))
                {
                    AddSBufferUse(context.Info.SBuffers, operation);
                }

                // If all the sources are bool, it's better to use short-circuiting
                // logical operations, rather than forcing a cast to int and doing
                // a bitwise operation with the value, as it is likely to be used as
                // a bool in the end.
                if (IsBitwiseInst(inst) && AreAllSourceTypesEqual(sources, VariableType.Bool))
                {
                    inst = GetLogicalFromBitwiseInst(inst);
                }

                bool isCondSel = inst == Instruction.ConditionalSelect;
                bool isCopy    = inst == Instruction.Copy;

                if (isCondSel || isCopy)
                {
                    VariableType type = GetVarTypeFromUses(operation.Dest);

                    if (isCondSel && type == VariableType.F32)
                    {
                        inst |= Instruction.FP32;
                    }

                    dest.VarType = type;
                }
                else
                {
                    dest.VarType = InstructionInfo.GetDestVarType(inst);
                }

                IAstNode source;

                if (operation is TextureOperation texOp)
                {
                    if (texOp.Inst == Instruction.ImageLoad || texOp.Inst == Instruction.ImageStore)
                    {
                        dest.VarType = texOp.Format.GetComponentType();
                    }

                    AstTextureOperation astTexOp = GetAstTextureOperation(texOp);

                    if (texOp.Inst == Instruction.ImageLoad)
                    {
                        context.Info.Images.Add(astTexOp);
                    }
                    else
                    {
                        context.Info.Samplers.Add(astTexOp);
                    }

                    source = astTexOp;
                }
                else if (!isCopy)
                {
                    source = new AstOperation(inst, operation.Index, sources, operation.SourcesCount);
                }
                else
                {
                    source = sources[0];
                }

                context.AddNode(new AstAssignment(dest, source));
            }
            else if (operation.Inst == Instruction.Comment)
            {
                context.AddNode(new AstComment(((CommentNode)operation).Comment));
            }
            else if (operation is TextureOperation texOp)
            {
                AstTextureOperation astTexOp = GetAstTextureOperation(texOp);

                context.Info.Images.Add(astTexOp);

                context.AddNode(astTexOp);
            }
            else
            {
                if (UsesStorage(inst))
                {
                    AddSBufferUse(context.Info.SBuffers, operation);
                }

                context.AddNode(new AstOperation(inst, operation.Index, sources, operation.SourcesCount));
            }

            // Those instructions needs to be emulated by using helper functions,
            // because they are NVIDIA specific. Those flags helps the backend to
            // decide which helper functions are needed on the final generated code.
            switch (operation.Inst)
            {
            case Instruction.AtomicMaxS32 | Instruction.MrShared:
            case Instruction.AtomicMinS32 | Instruction.MrShared:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.AtomicMinMaxS32Shared;
                break;

            case Instruction.AtomicMaxS32 | Instruction.MrStorage:
            case Instruction.AtomicMinS32 | Instruction.MrStorage:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.AtomicMinMaxS32Storage;
                break;

            case Instruction.MultiplyHighS32:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.MultiplyHighS32;
                break;

            case Instruction.MultiplyHighU32:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.MultiplyHighU32;
                break;

            case Instruction.Shuffle:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.Shuffle;
                break;

            case Instruction.ShuffleDown:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.ShuffleDown;
                break;

            case Instruction.ShuffleUp:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.ShuffleUp;
                break;

            case Instruction.ShuffleXor:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.ShuffleXor;
                break;

            case Instruction.SwizzleAdd:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.SwizzleAdd;
                break;
            }
        }
Example #7
0
        private static void AddOperation(StructuredProgramContext context, Operation operation)
        {
            Instruction inst = operation.Inst;

            IAstNode[] sources = new IAstNode[operation.SourcesCount];

            for (int index = 0; index < sources.Length; index++)
            {
                sources[index] = context.GetOperandUse(operation.GetSource(index));
            }

            AstTextureOperation GetAstTextureOperation(TextureOperation texOp)
            {
                return(new AstTextureOperation(
                           inst,
                           texOp.Type,
                           texOp.Flags,
                           texOp.Handle,
                           4, // TODO: Non-hardcoded array size.
                           texOp.Index,
                           sources));
            }

            if (operation.Dest != null)
            {
                AstOperand dest = context.GetOperandDef(operation.Dest);

                if (inst == Instruction.LoadConstant)
                {
                    Operand slot = operation.GetSource(0);

                    if (slot.Type != OperandType.Constant)
                    {
                        throw new InvalidOperationException("Found load with non-constant constant buffer slot.");
                    }

                    context.Info.CBuffers.Add(slot.Value);
                }
                else if (UsesStorage(inst))
                {
                    AddSBufferUse(context.Info.SBuffers, operation);
                }

                AstAssignment assignment;

                // If all the sources are bool, it's better to use short-circuiting
                // logical operations, rather than forcing a cast to int and doing
                // a bitwise operation with the value, as it is likely to be used as
                // a bool in the end.
                if (IsBitwiseInst(inst) && AreAllSourceTypesEqual(sources, VariableType.Bool))
                {
                    inst = GetLogicalFromBitwiseInst(inst);
                }

                bool isCondSel = inst == Instruction.ConditionalSelect;
                bool isCopy    = inst == Instruction.Copy;

                if (isCondSel || isCopy)
                {
                    VariableType type = GetVarTypeFromUses(operation.Dest);

                    if (isCondSel && type == VariableType.F32)
                    {
                        inst |= Instruction.FP32;
                    }

                    dest.VarType = type;
                }
                else
                {
                    dest.VarType = InstructionInfo.GetDestVarType(inst);
                }

                IAstNode source;

                if (operation is TextureOperation texOp)
                {
                    AstTextureOperation astTexOp = GetAstTextureOperation(texOp);

                    if (texOp.Inst == Instruction.ImageLoad)
                    {
                        context.Info.Images.Add(astTexOp);
                    }
                    else
                    {
                        context.Info.Samplers.Add(astTexOp);
                    }

                    source = astTexOp;
                }
                else if (!isCopy)
                {
                    source = new AstOperation(inst, operation.Index, sources);
                }
                else
                {
                    source = sources[0];
                }

                assignment = new AstAssignment(dest, source);

                context.AddNode(assignment);
            }
            else if (operation.Inst == Instruction.Comment)
            {
                context.AddNode(new AstComment(((CommentNode)operation).Comment));
            }
            else if (operation is TextureOperation texOp)
            {
                AstTextureOperation astTexOp = GetAstTextureOperation(texOp);

                context.Info.Images.Add(astTexOp);

                context.AddNode(astTexOp);
            }
            else
            {
                if (UsesStorage(inst))
                {
                    AddSBufferUse(context.Info.SBuffers, operation);
                }

                context.AddNode(new AstOperation(inst, operation.Index, sources));
            }

            // Those instructions needs to be emulated by using helper functions,
            // because they are NVIDIA specific. Those flags helps the backend to
            // decide which helper functions are needed on the final generated code.
            switch (operation.Inst)
            {
            case Instruction.MultiplyHighS32:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.MultiplyHighS32;
                break;

            case Instruction.MultiplyHighU32:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.MultiplyHighU32;
                break;

            case Instruction.Shuffle:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.Shuffle;
                break;

            case Instruction.ShuffleDown:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.ShuffleDown;
                break;

            case Instruction.ShuffleUp:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.ShuffleUp;
                break;

            case Instruction.ShuffleXor:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.ShuffleXor;
                break;

            case Instruction.SwizzleAdd:
                context.Info.HelperFunctionsMask |= HelperFunctionsMask.SwizzleAdd;
                break;
            }
        }