示例#1
0
        public static ShaderProgramChunk Parse(BytecodeReader reader)
        {
            var program = new ShaderProgramChunk
            {
                Version = ShaderVersion.ParseShex(reader),

                // Length Token (LenTok)
                // Always follows VerTok
                // [31:00] Unsigned integer count of number of DWORDs in program code, including version and length tokens.
                // So the minimum value is 0x00000002 (if an empty program is ever valid).
                Length = reader.ReadUInt32()
            };

            while (!reader.EndOfBuffer)
            {
                // Opcode Format (OpcodeToken0)
                //
                // [10:00] D3D10_SB_OPCODE_TYPE
                // if( [10:00] == D3D10_SB_OPCODE_CUSTOMDATA )
                // {
                //    Token starts a custom-data block.  See "Custom-Data Block Format".
                // }
                // else // standard opcode token
                // {
                //    [23:11] Opcode-Specific Controls
                //    [30:24] Instruction length in DWORDs including the opcode token.
                //    [31]    0 normally. 1 if extended operand definition, meaning next DWORD
                //            contains extended opcode token.
                // }
                var opcodeHeaderReader = reader.CopyAtCurrentPosition();
                var opcodeToken0       = opcodeHeaderReader.ReadUInt32();
                var opcodeHeader       = new OpcodeHeader
                {
                    OpcodeType = opcodeToken0.DecodeValue <OpcodeType>(0, 10),
                    Length     = opcodeToken0.DecodeValue(24, 30),
                    IsExtended = (opcodeToken0.DecodeValue(31, 31) == 1)
                };

                OpcodeToken opcodeToken;
                if (opcodeHeader.OpcodeType == OpcodeType.CustomData)
                {
                    opcodeToken = CustomDataToken.Parse(reader, opcodeToken0);
                }
                else if (opcodeHeader.OpcodeType.IsDeclaration())
                {
                    opcodeToken = DeclarationToken.Parse(reader, opcodeHeader.OpcodeType);
                }
                else                 // Not custom data or declaration, so must be instruction.
                {
                    opcodeToken = InstructionToken.Parse(reader, opcodeHeader);
                }

                opcodeToken.Header = opcodeHeader;
                program.Tokens.Add(opcodeToken);
            }

            program.LinkControlFlowInstructions();

            return(program);
        }
示例#2
0
        //Note:
        //result += tex.Load(index1).sValue2[0];
        //ld_structured_indexable(structured_buffer, stride=160)(mixed,mixed,mixed,mixed) o0.xyzw, cb0[0].x, l(80), t0.xyzw
        //dynamic indexing is translated into a series of conditional reads
        void AddLoadStructured(InstructionToken token)
        {
            AddIndent();
            AddAssignToDest(token.Operands[0]);
            var tex = token.Header.OpcodeType.IsFeedbackResourceAccess() ?
                      token.Operands[4] :
                      token.Operands[3];
            // tex.OperandType is Resource for texture reads, OperandType.UnorderedAccessView for UAV reads
            uint structSize = 16;

            if (tex.OperandType == OperandType.ThreadGroupSharedMemory)
            {
                var dcl = Container.Shader.DeclarationTokens
                          .OfType <StructuredThreadGroupSharedMemoryDeclarationToken>()
                          .First(d => d.Operand.Indices[0].Value == tex.Indices[0].Value);
                structSize = dcl.StructByteStride * dcl.StructCount * 4;
            }
            else
            {
                var buffer = GetConstantBuffer(tex.OperandType, (uint)tex.Indices[0].Value);
                structSize = buffer.Variables[0].Size;
            }
            Output.AppendFormat("((float4[{0}])", structSize / 16);
            WriteOperandWithMask(token.Operands[3], ComponentMask.None);
            Output.Append(".Load(");
            WriteOperand(token.Operands[1]);
            Output.AppendFormat("))[{0}]", token.Operands[2].ImmediateValues.GetNumber(0).UInt / 16);

            Output.AppendLine(";");
        }
示例#3
0
            public void When_WithTypeKeyLineEndingAndValue(InstructionType type, LineEnding lineEnding)
            {
                var instruction = new InstructionToken(type, "key", "value", lineEnding);

                Assert.That(instruction.InstructionType, Is.EqualTo(type));
                Assert.That(instruction.Key, Is.EqualTo("key"));
                Assert.That(instruction.Value, Is.EqualTo("value"));
                Assert.That(instruction.LineEnding, Is.EqualTo(lineEnding));
            }
示例#4
0
            public void When_WithTypeAndKey(InstructionType type)
            {
                var instruction = new InstructionToken(type, "key");

                Assert.That(instruction.InstructionType, Is.EqualTo(type));
                Assert.That(instruction.Key, Is.EqualTo("key"));
                Assert.That(instruction.Value, Is.Null);
                Assert.That(instruction.LineEnding, Is.EqualTo(LineEnding.Unknown));
            }
示例#5
0
            public void When_WithoutArguments()
            {
                var instruction = new InstructionToken();

                Assert.That(instruction.InstructionType, Is.EqualTo(InstructionType.Set));
                Assert.That(instruction.Key, Is.Null);
                Assert.That(instruction.Value, Is.Null);
                Assert.That(instruction.LineEnding, Is.EqualTo(LineEnding.Unknown));
            }
示例#6
0
 void CallBinaryOp(string symbol, InstructionToken instruction, int dest, int src0, int src1)
 {
     AddIndent();
     WriteOperand(instruction.Operands[dest]);
     Output.Append(" = ");
     WriteOperand(instruction.Operands[src0]);
     Output.AppendFormat(" {0} ", symbol);
     WriteOperand(instruction.Operands[src1]);
     Output.AppendLine(";");
 }
示例#7
0
 void CallTernaryOp(string op1, string op2, InstructionToken instruction, int dest, int src0, int src1, int src2)
 {
     AddIndent();
     AddAssignToDest(instruction.Operands[dest]);
     WriteOperand(instruction.Operands[src0]);
     Output.AppendFormat(" {0} ", op1);
     WriteOperand(instruction.Operands[src1]);
     Output.AppendFormat(" {0} ", op2);
     WriteOperand(instruction.Operands[src2]);
     Output.AppendLine(";");
 }
示例#8
0
 void CallHelper(string name, InstructionToken instruction, int dest, params int[] srcs)
 {
     AddIndent();
     WriteOperand(instruction.Operands[dest]);
     Output.AppendFormat(" = {0}(", name);
     for (int i = 0; i < srcs.Length; i++)
     {
         WriteOperand(instruction.Operands[srcs[i]]);
         if (i < srcs.Length - 1)
         {
             Output.Append(", ");
         }
     }
     Output.AppendLine(");");
 }
示例#9
0
 void AddCallInterfaceNoDest(string method, InstructionToken inst, int src0, params int[] args)
 {
     AddIndent();
     WriteOperandWithMask(inst.Operands[src0], ComponentMask.None);
     Output.AppendFormat(".{0}(", method);
     for (int i = 0; i < args.Length; i++)
     {
         if (i > 0)
         {
             Output.Append(", ");
         }
         WriteOperand(inst.Operands[args[i]]);
     }
     Output.AppendLine(");");
 }
示例#10
0
        void WriteConditional(InstructionToken instruction)
        {
            AddIndent();
            Output.Append("if((");
            WriteOperand(instruction.Operands[0]);
            string statement = "";

            if (instruction.Header.OpcodeType == OpcodeType.BreakC)
            {
                statement = "break";
            }
            else if (instruction.Header.OpcodeType == OpcodeType.ContinueC)
            {
                statement = "continue";
            }
            else if (instruction.Header.OpcodeType == OpcodeType.RetC)
            {
                statement = "return";
            }
            else if (instruction.Header.OpcodeType == OpcodeType.Discard)
            {
                statement = "discard";
            }
            if (instruction.TestBoolean == InstructionTestBoolean.Zero)
            {
                if (instruction.Header.OpcodeType == OpcodeType.If)
                {
                    Output.AppendLine(") == 0u){");
                    indent++;
                }
                else
                {
                    Output.AppendFormat(") == 0u){{ {0}; }}\n", statement);
                }
            }
            else
            {
                if (instruction.Header.OpcodeType == OpcodeType.If)
                {
                    Output.AppendLine(") != 0u){");
                    indent++;
                }
                else
                {
                    Output.AppendFormat(") != 0u){{ {0}; }}\n", statement);
                }
            }
        }
示例#11
0
        static IrInstruction ParseInstruction(InstructionToken instruction)
        {
            var result = new IrInstruction()
            {
                AsmDebug = instruction.ToString(),
                Operands = new List <IrOperand>(
                    instruction.Operands.Select(OperandParser.Parse)),
                Opcode = (IrInstructionOpcode)instruction.Header.OpcodeType,
            };

            switch (instruction.Header.OpcodeType)
            {
            case OpcodeType.Ld:
                Swap(result.Operands, 1, 2);
                break;
            }
            return(result);
        }
示例#12
0
        public Register GetRegister(InstructionToken token)
        {
            switch (token.Header.OpcodeType)
            {
            case OpcodeType.InterfaceCall:
            {
                var operand           = token.Operands[0];
                int functionBodyIndex = (int)token.FunctionIndex;
                int interfaceIndex    = (int)operand.Indices[0].Value;
                int elementIndex      = (int)operand.Indices[1].Value;
                Registers.TryGetValue($"fp{interfaceIndex}[{functionBodyIndex}]", out var regs);
                return(regs?.First());
            }

            default:
                throw new Exception($"Couldn't find register {token}");
            }
        }
示例#13
0
        public bool ExpectInstructionToken(out InstructionToken instructionToken)
        {
            instructionToken = null;
            if (this.IsAtEnd())
            {
                return(false);
            }

            var token = this.Advance() as InstructionToken;

            if (token == null)
            {
                return(false);
            }

            instructionToken = token;
            return(true);
        }
示例#14
0
        void AddLoad(InstructionToken token)
        {
            AddIndent();
            AddAssignToDest(token.Operands[0]);
            var tex             = token.Operands[2];
            var resourceBinding = GetResourceBinding(tex.OperandType, (uint)tex.Indices[0].Value);

            if (resourceBinding.Type == ShaderInputType.TBuffer)
            {
                var  buffer     = GetConstantBuffer(tex.OperandType, (uint)tex.Indices[0].Value);
                var  variable   = buffer.Variables[0];
                bool castNeeded = variable.ShaderType.VariableClass != ShaderVariableClass.Vector ||
                                  variable.ShaderType.ElementCount < 2;
                if (castNeeded)
                {
                    Output.AppendFormat("((float4[{0}])", buffer.Size / 16);
                }
                WriteOperandWithMask(tex, ComponentMask.None);
                if (castNeeded)
                {
                    Output.Append(")");
                }
                Output.Append("[");
                if (token.Operands[1].OperandType == OperandType.Immediate32)
                {
                    Output.Append(token.Operands[1].ImmediateValues.Int0);
                }
                else
                {
                    WriteOperand(token.Operands[1]);
                }
                Output.Append("]");
                Output.AppendLine(";");
            }
            else
            {
                WriteOperandWithMask(tex, ComponentMask.None);
                Output.Append(".Load(");
                WriteOperand(token.Operands[1]);
                Output.Append(")");
                Output.AppendLine(";");
            }
        }
示例#15
0
        void AddComparision(InstructionToken inst, ComparisonType cmpType)
        {
            string[] ops = new string[] {
                "==",
                "<",
                ">=",
                "!=",
            };
            AddIndent();
            AddAssignToDest(inst.Operands[0]);
            Output.Append("( ");

            WriteOperand(inst.Operands[1]);

            Output.AppendFormat(" {0} ", ops[(int)cmpType]);

            WriteOperand(inst.Operands[2]);

            Output.AppendLine(" ) ? 1.0 : 0.0;");
        }
示例#16
0
        /// <summary>
        /// Executes a single instruction, modifying the <see cref="values"/> of a property.
        /// </summary>
        /// <param name="instruction">The instruction to be executed</param>
        /// <param name="propertyValues">The values of the property the instruction will be executed for. Will be modified by execution.</param>
        public void ExecutePropertyInstruction(InstructionToken instruction, IList <string> propertyValues)
        {
            switch (instruction.InstructionType)
            {
            case InstructionType.Add:
                if (!propertyValues.Contains(instruction.Value))
                {
                    propertyValues.Add(instruction.Value);
                }
                break;

            case InstructionType.AddForce:
                propertyValues.Add(instruction.Value);
                break;

            case InstructionType.Remove:
                bool wasRemoved = false;
                do
                {
                    wasRemoved = propertyValues.Remove(instruction.Value);
                } while (wasRemoved);
                break;

            case InstructionType.RemoveAll:
                propertyValues.Clear();
                break;

            case InstructionType.Set:
                propertyValues.Clear();
                propertyValues.Add(instruction.Value);
                break;

            default:
                throw new InvalidEnumArgumentException(nameof(instruction.InstructionType), (int)instruction.InstructionType, typeof(InstructionType));
            }
        }
示例#17
0
        private void Tokenize()
        {
            this.tokenStartLine = this.line;
            this.tokenStartCol  = this.col - 1;

            while (!this.IsAtEnd())
            {
                char c = this.ReadNext();

                tokenStartLine = this.line;
                tokenStartCol  = this.col - 1; // because `current` points to the next char

                if (this.IsLetter(c))
                {
                    Token tok;

                    string word = this.ScanWord(c);

                    if (InstructionToken.IsKeywordValid(word))
                    {
                        Instructions instr = InstructionToken.GetTypeFromKeyword(word);
                        tok = new InstructionToken(this.tokenStartLine, this.tokenStartCol, instr);
                    }
                    else if (RegisterToken.IsKeywordValid(word))
                    {
                        Registers reg = RegisterToken.GetTypeFromKeyword(word);
                        tok = new RegisterToken(this.tokenStartLine, this.tokenStartCol, reg);
                    }
                    else
                    {
                        this.LogUnknownKeywordError(word);
                        continue;
                    }

                    this.tokens.Add(tok);
                }
                else if (c == '#')
                {
                    byte nb;
                    if (this.ExpectNumber(out nb))
                    {
                        var tok = new NumericalValueToken(this.tokenStartLine, this.tokenStartCol, nb);
                        this.tokens.Add(tok);
                    }
                    else
                    {
                        this.LogExpectedNumberError();
                    }
                }
                else if (c == '&')
                {
                    Registers reg;
                    byte      nb;
                    if (this.ExpectRegister(out reg))
                    {
                        var tok = new AddressRegisterToken(this.tokenStartLine, this.tokenStartCol, reg);
                        this.tokens.Add(tok);
                    }
                    else if (this.ExpectNumber(out nb))
                    {
                        var tok = new AddressValueToken(this.tokenStartLine, this.tokenStartCol, nb);
                        this.tokens.Add(tok);
                    }
                    else
                    {
                        this.LogUnexpectedTokenForAddressError();
                    }
                }
                else if (c != '\0')
                {
                    this.LogUnexpectedCharError(c);
                    //continue;
                }
            }

            if (this.errorsCount != 0)
            {
                Console.WriteLine(this.errorsCount + " errors found.");
                Console.WriteLine("---");

                throw new SyntaxErrorsException();
            }
        }
示例#18
0
        public Task <IParserResult> RunAsync(IDocument document, ITextSnapshot version, ITokenizerCollection <TrackingToken> trackingTokens, CancellationToken cancellation)
        {
            var    definitions = new Dictionary <string, DefinitionToken>();
            IBlock rootBlock   = new Block();
            var    blocks      = new List <IBlock>()
            {
                rootBlock
            };
            var tokens = trackingTokens
                         .Where(t => t.Type != RadAsmDocLexer.WHITESPACE && t.Type != RadAsmDocLexer.BLOCK_COMMENT)
                         .AsParallel()
                         .AsOrdered()
                         .WithCancellation(cancellation)
                         .ToArray();

            InstructionToken currentInstruction = null;

            for (int i = 0; i < tokens.Length; i++)
            {
                cancellation.ThrowIfCancellationRequested();
                var token = tokens[i];

                if (token.Type == RadAsmDocLexer.LET)
                {
                    if (tokens.Length - i > 1 && tokens[i + 1].Type == RadAsmDocLexer.IDENTIFIER)
                    {
                        var definition = new VariableToken(RadAsmTokenType.GlobalVariable, tokens[i + 1], version);
                        definitions.Add(definition.GetText(), definition);
                        i += 1;
                    }
                }
                else if (tokens.Length - i > 1 && token.Type == RadAsmDocLexer.EOL && tokens[i + 1].Type == RadAsmDocLexer.IDENTIFIER)
                {
                    currentInstruction = new InstructionToken(RadAsmTokenType.Instruction, tokens[i + 1], version);
                    rootBlock.AddToken(currentInstruction);
                    i += 1;
                }
                else if (token.Type == RadAsmDocLexer.IDENTIFIER)
                {
                    var text = token.GetText(version);

                    if (definitions.TryGetValue(text, out var definition))
                    {
                        var reference = new ReferenceToken(RadAsmTokenType.GlobalVariableReference, token, version, definition);
                        rootBlock.AddToken(reference);
                        currentInstruction?.Parameters.Add(reference);
                    }
                    else if (currentInstruction != null)
                    {
                        var parameter = new AnalysisToken(RadAsmTokenType.GlobalVariableReference, token, version);
                        currentInstruction.Parameters.Add(parameter);
                    }
                }
                else if (token.Type == RadAsmDocLexer.LCURVEBRACKET || token.Type == RadAsmDocLexer.EOL)
                {
                    currentInstruction = null;
                }
            }

            var result = new ParserResult(blocks, new List <IErrorToken>());

            return(Task.FromResult((IParserResult)result));
        }
示例#19
0
 public override string ToString()
 {
     return(InstructionToken.ToString());
 }
示例#20
0
        void TranslateTextureSample(InstructionToken inst)
        {
            AddIndent();
            AddAssignToDest(inst.Operands[0]);
            WriteOperandWithMask(inst.Operands[2], ComponentMask.None);
            switch (inst.Header.OpcodeType)
            {
            case OpcodeType.Sample:
                Output.Append(".Sample(");
                break;

            case OpcodeType.SampleBClS:
                Output.Append(".SampleBias(");
                break;

            case OpcodeType.SampleB:
                Output.Append(".SampleBias(");
                break;

            case OpcodeType.SampleClS:
                Output.Append(".SampleCmp(");
                break;

            case OpcodeType.SampleC:
                Output.Append(".SampleCmp(");
                break;

            case OpcodeType.SampleCLzS:
                Output.Append(".SampleCmpLevelZero(");
                break;

            case OpcodeType.SampleCLz:
                Output.Append(".SampleCmpLevelZero(");
                break;

            case OpcodeType.SampleDClS:
                Output.Append(".SampleGrad(");
                break;

            case OpcodeType.SampleD:
                Output.Append(".SampleGrad(");
                break;

            case OpcodeType.SampleLS:
                Output.Append(".SampleLevel(");
                break;

            case OpcodeType.SampleL:
                Output.Append(".SampleLevel(");
                break;

            case OpcodeType.SampleCClS:
                Output.Append(".Unknown(");
                break;

            case OpcodeType.Gather4:
            case OpcodeType.Gather4C:
            case OpcodeType.Gather4CS:
            case OpcodeType.Gather4Po:
            case OpcodeType.Gather4PoC:
            case OpcodeType.Gather4PoCS:
            case OpcodeType.Gather4PoS:
            case OpcodeType.Gather4S:
                Output.Append(".Gather4(");
                break;

            case OpcodeType.Lod:
            {
                Output.Append(".CalculateLevelOfDetail(");
                break;
            }

            case OpcodeType.Resinfo:
                Output.Append(".GetDimensions(");
                break;

            default:
                throw new InvalidOperationException($"Unexpected token {inst}");
            }
            WriteOperandWithMask(inst.Operands[3], ComponentMask.None);
            Output.Append(", ");
            WriteOperand(inst.Operands[1]);
            Output.AppendLine(");");
        }
 public NonDivergentExecutableInstruction(InstructionToken instructionToken)
     : base(instructionToken)
 {
 }
示例#22
0
        internal void TranslateInstruction(InstructionToken token)
        {
            DebugLog(token);
            switch (token.Header.OpcodeType)
            {
            case OpcodeType.Dtoi:
            case OpcodeType.Dtou:
            case OpcodeType.FtoI:
            case OpcodeType.FtoU:
            {
                var constructorType = (token.Header.OpcodeType == OpcodeType.FtoI ||
                                       token.Header.OpcodeType == OpcodeType.Dtoi) ?
                                      ShaderVariableType.Int :
                                      ShaderVariableType.UInt;
                var dest      = token.Operands[0];
                var src       = token.Operands[1];
                var destCount = dest.GetNumSwizzleElements();
                var srcCount  = src.GetNumSwizzleElements();
                AddIndent();
                AddAssignToDest(token.Operands[0]);
                Output.Append(GetConstructorForType(constructorType,
                                                    srcCount == destCount ? destCount : 4));
                Output.Append("(");
                WriteOperand(src);
                Output.AppendLine(");");
                break;
            }

            case OpcodeType.DToF:
            case OpcodeType.ItoF:
            case OpcodeType.Utof:
            {
                var dest      = token.Operands[0];
                var src       = token.Operands[1];
                var destCount = dest.GetNumSwizzleElements();
                var srcCount  = src.GetNumSwizzleElements();
                AddIndent();
                AddAssignToDest(token.Operands[0]);
                Output.Append(GetConstructorForType(ShaderVariableType.Float,
                                                    srcCount == destCount ? destCount : 4));
                Output.Append("(");
                WriteOperand(src);
                Output.AppendLine(");");
                break;
            }

            case OpcodeType.Itod:
            case OpcodeType.Utod:
            case OpcodeType.FToD:
            {
                var dest      = token.Operands[0];
                var src       = token.Operands[1];
                var destCount = dest.GetNumSwizzleElements();
                var srcCount  = src.GetNumSwizzleElements();
                AddIndent();
                AddAssignToDest(token.Operands[0]);
                Output.Append(GetConstructorForType(ShaderVariableType.Double,
                                                    srcCount == destCount ? destCount : 4));
                Output.Append("(");
                WriteOperand(src);
                Output.AppendLine(");");
                break;
            }

            case OpcodeType.DMov:
            case OpcodeType.Mov:
            {
                WriteMoveBinaryOp(token.Operands[0], token.Operands[1]);
                break;
            }

            case OpcodeType.DAdd:
            case OpcodeType.IAdd:
            case OpcodeType.Add:
            {
                CallBinaryOp("+", token, 0, 1, 2);
                break;
            }

            case OpcodeType.Dfma:
            case OpcodeType.IMad:
            case OpcodeType.Mad:
            {
                CallTernaryOp("*", "+", token, 0, 1, 2, 3);
                break;
            }

            case OpcodeType.DMul:
            case OpcodeType.IMul:
            case OpcodeType.Mul:
            {
                CallBinaryOp("*", token, 0, 1, 2);
                break;
            }

            case OpcodeType.UDiv:
            case OpcodeType.Ddiv:
            case OpcodeType.Div:
            {
                CallBinaryOp("/", token, 0, 1, 2);
                break;
            }

            // Bitwise operations
            case OpcodeType.Or:
            {
                CallBinaryOp("|", token, 0, 1, 2);
                break;
            }

            case OpcodeType.And:
            {
                CallBinaryOp("&", token, 0, 1, 2);
                break;
            }

            case OpcodeType.FirstBitHi:
            {
                CallHelper("firstbithigh", token, 0, 1);
                break;
            }

            case OpcodeType.FirstBitSHi:
            {
                CallHelper("firstbithigh", token, 0, 1);
                break;
            }

            case OpcodeType.BfRev:
            {
                CallHelper("reversebits ", token, 0, 1);
                break;
            }

            case OpcodeType.Bfi:
            {
                string bfiFunc = @"int4 BFI(uint4 src0, uint4 src1, uint4 src2, uint4 src3){
	uint4 width = src0 & 0x1f;
	uint4 offset = src1 & 0x1f;
	uint4 mask = (((1 << width)-1) << offset) & 0xffffffff;
	int4 dest = ((src2 << offset) & bitmask) | (src3 & ~bitmask)
	return dest;
}";
                AddFunction("BFI", bfiFunc);
                CallHelper("BFI", token, 0, 1, 2, 3, 4);
                break;
            }

            case OpcodeType.UShr:
            {
                CallBinaryOp(">>", token, 0, 1, 2);
                break;
            }

            case OpcodeType.IShr:
            {
                CallBinaryOp(">>", token, 0, 1, 2);
                break;
            }

            case OpcodeType.IShl:
            {
                CallBinaryOp("<<", token, 0, 1, 2);
                break;
            }

            case OpcodeType.UBfe:
            case OpcodeType.IBfe:
            {
                string name = token.Header.OpcodeType == OpcodeType.UBfe ?
                              "UBFE" : "IBFE";
                string returnType = token.Header.OpcodeType == OpcodeType.UBfe ?
                                    "uint4" : "int4";
                string template = @"{0} {1}(uint4 src1, uint4 src2, {0} value){{
	{0} result = 0;
	for(uint i = 0; i < 4; i++){{
		uint width = src1[i] & 0x1f;
		uint offset =src2[i] & 0x1f;
		if(width == 0){{
			result[i] = 0;
		}} else if(width + offset < 32){{
			result[i] = value << (32-(width + offset));
			result[i] = result[i] >> (32 - width);
		}} else {{
			result[i] = value >> (32 - width);
		}}
	}}
	return result;
}}";
                AddFunction(name, string.Format(template, returnType, name));
                CallHelper(name, token, 0, 1, 2, 3);
                break;
            }

            case OpcodeType.Not:
            {
                AddIndent();
                AddAssignToDest(token.Operands[0]);
                Output.Append("~");
                WriteOperand(token.Operands[1]);
                Output.AppendLine(";");
                break;
            }

            case OpcodeType.Xor:
            {
                CallBinaryOp("^", token, 0, 1, 2);
                break;
            }

            case OpcodeType.CountBits:
            {
                AddIndent();
                AddAssignToDest(token.Operands[0]);
                Output.Append(" = bitCount(");
                WriteOperand(token.Operands[1]);
                Output.AppendLine(");");
                break;
            }

            //Comparisons
            case OpcodeType.DNe:
            case OpcodeType.INe:
            case OpcodeType.Ne:
            {
                AddComparision(token, ComparisonType.Ne);
                break;
            }

            case OpcodeType.ILt:
            case OpcodeType.DLt:
            case OpcodeType.ULt:
            case OpcodeType.Lt:
            {
                AddComparision(token, ComparisonType.Lt);
                break;
            }

            case OpcodeType.IGe:
            case OpcodeType.UGe:
            case OpcodeType.DGe:
            case OpcodeType.Ge:
            {
                AddComparision(token, ComparisonType.Ge);
                break;
            }

            case OpcodeType.DEq:
            case OpcodeType.IEq:
            case OpcodeType.Eq:
            {
                AddComparision(token, ComparisonType.Eq);
                break;
            }

            case OpcodeType.DMovC:
            case OpcodeType.MovC:
            {
                AddMOVCBinaryOp(token.Operands[0], token.Operands[1],
                                token.Operands[2], token.Operands[3]);
                break;
            }

            case OpcodeType.SwapC:
            {
                // TODO needs temps!!
                AddMOVCBinaryOp(token.Operands[0], token.Operands[2], token.Operands[4], token.Operands[3]);
                AddMOVCBinaryOp(token.Operands[1], token.Operands[2], token.Operands[3], token.Operands[4]);
                break;
            }

            //ControlFlow
            case OpcodeType.Loop:
            {
                AddIndent();
                Output.AppendLine("while(true){");
                indent++;
                break;
            }

            case OpcodeType.EndLoop:
            {
                indent--;
                AddIndent();
                Output.AppendLine("}");
                break;
            }

            case OpcodeType.Break:
            {
                AddIndent();
                Output.AppendLine("break;");
                break;
            }

            case OpcodeType.BreakC:
            {
                WriteConditional(token);
                break;
            }

            case OpcodeType.ContinueC:
            {
                WriteConditional(token);
                break;
            }

            case OpcodeType.If:
            {
                WriteConditional(token);
                break;
            }

            case OpcodeType.RetC:
            {
                WriteConditional(token);
                break;
            }

            case OpcodeType.Else:
            {
                indent--;
                AddIndent();
                Output.AppendLine("} else {");
                indent++;
                break;
            }

            case OpcodeType.EndSwitch:
            case OpcodeType.EndIf:
            {
                indent--;
                AddIndent();
                Output.AppendLine("}");
                break;
            }

            case OpcodeType.Continue:
            {
                Output.AppendLine("continue;");
                break;
            }

            case OpcodeType.Switch:
            {
                AddIndent();
                indent++;
                Output.Append("switch(int(");
                WriteOperand(token.Operands[0]);
                Output.AppendLine(")){");
                break;
            }

            case OpcodeType.Case:
            {
                AddIndent();
                indent++;
                Output.Append("case ");
                WriteOperand(token.Operands[0]);
                Output.AppendLine(":");
                break;
            }

            case OpcodeType.Default:
            {
                AddIndent();
                Output.AppendLine("default:");
                break;
            }

            case OpcodeType.Ret:
            {
                if (Container.Shader.Version.ProgramType != ProgramType.ComputeShader &&
                    Container.Shader.Version.ProgramType != ProgramType.GeometryShader)
                {
                    AddIndent();
                    Output.AppendLine($"return output;");
                }
                break;
            }

            case OpcodeType.Label:
            {
                break;
            }

            //Functions
            case OpcodeType.Sincos:
            {
                if (token.Operands[0].OperandType == token.Operands[2].OperandType &&
                    token.Operands[0].Indices[0].Value == token.Operands[2].Indices[0].Value)
                {
                    if (token.Operands[1].OperandType != OperandType.Null)
                    {
                        CallHelper("cos", token, 1, 2);
                    }
                    if (token.Operands[0].OperandType != OperandType.Null)
                    {
                        CallHelper("cos", token, 0, 2);
                    }
                }
                else
                {
                    if (token.Operands[0].OperandType != OperandType.Null)
                    {
                        CallHelper("sin", token, 0, 2);
                    }
                    if (token.Operands[1].OperandType != OperandType.Null)
                    {
                        CallHelper("cos", token, 1, 2);
                    }
                }
                break;
            }

            case OpcodeType.Dp2:
            {
                CallHelper("dot", token, 0, 1, 2);
                break;
            }

            case OpcodeType.Dp3:
            {
                CallHelper("dot", token, 0, 1, 2);
                break;
            }

            case OpcodeType.Dp4:
            {
                CallHelper("dot", token, 0, 1, 2);
                break;
            }

            case OpcodeType.Log:
            {
                CallHelper("log", token, 0, 1);
                break;
            }

            case OpcodeType.Rsq:
            {
                CallHelper("normalize", token, 0, 1);
                break;
            }

            case OpcodeType.Exp:
            {
                CallHelper("exp2", token, 0, 1);
                break;
            }

            case OpcodeType.Sqrt:
            {
                CallHelper("sqrt", token, 0, 1);
                break;
            }

            case OpcodeType.RoundPi:
            {
                CallHelper("ceil", token, 0, 1);
                break;
            }

            case OpcodeType.RoundNi:
            {
                CallHelper("floor", token, 0, 1);
                break;
            }

            case OpcodeType.RoundZ:
            {
                CallHelper("trunc", token, 0, 1);
                break;
            }

            case OpcodeType.RoundNe:
            {
                CallHelper("roundEven", token, 0, 1);
                break;
            }

            case OpcodeType.Frc:
            {
                CallHelper("frac", token, 0, 1);
                break;
            }

            case OpcodeType.IMax:
            case OpcodeType.UMax:
            case OpcodeType.DMax:
            case OpcodeType.Max:
            {
                CallHelper("max", token, 0, 1, 2);
                break;
            }

            case OpcodeType.IMin:
            case OpcodeType.UMin:
            case OpcodeType.DMin:
            case OpcodeType.Min:
            {
                CallHelper("min", token, 0, 1, 2);
                break;
            }

            //Resource Operations
            case OpcodeType.Gather4:
            case OpcodeType.Gather4S:
            case OpcodeType.Gather4Po:
            case OpcodeType.Gather4C:
            case OpcodeType.Gather4PoC:
            case OpcodeType.Gather4PoS:
            case OpcodeType.Gather4CS:
            case OpcodeType.Gather4PoCS:
            {
                TranslateTextureSample(token);
                break;
            }

            case OpcodeType.SampleLS:
            {
                TranslateTextureSample(token);
                break;
            }

            case OpcodeType.SampleDClS:
            {
                TranslateTextureSample(token);
                break;
            }

            case OpcodeType.SampleCClS:
            {
                TranslateTextureSample(token);
                break;
            }

            case OpcodeType.SampleBClS:
            {
                TranslateTextureSample(token);
                break;
            }

            case OpcodeType.SampleClS:
            {
                TranslateTextureSample(token);
                break;
            }

            case OpcodeType.SampleCLzS:
            {
                TranslateTextureSample(token);
                break;
            }

            case OpcodeType.Sample:
            {
                TranslateTextureSample(token);
                break;
            }

            case OpcodeType.SampleL:
            {
                TranslateTextureSample(token);
                break;
            }

            case OpcodeType.SampleC:
            {
                TranslateTextureSample(token);
                break;
            }

            case OpcodeType.SampleCLz:
            {
                TranslateTextureSample(token);
                break;
            }

            case OpcodeType.SampleD:
            {
                TranslateTextureSample(token);
                break;
            }

            case OpcodeType.SampleB:
            {
                TranslateTextureSample(token);
                break;
            }

            case OpcodeType.StoreRaw:
            {
                if (token.Operands[0].OperandType == OperandType.UnorderedAccessView)
                {
                    AddCallInterfaceNoDest("Store", token, 0, 1, 2);
                }
                else
                {
                    //TODO: use dstByteOffset (Operands[0]) to select the correct dest
                    AddIndent();
                    AddAssignToDest(token.Operands[0]);
                    WriteOperand(token.Operands[2]);
                    Output.AppendLine(";");
                }
                break;
            }

            case OpcodeType.StoreStructured:
            {
                AddCallInterfaceNoDest("Store", token, 0, 1, 2, 3);
                break;
            }

            case OpcodeType.StoreUavTyped:
            {
                AddCallInterfaceNoDest("Store", token, 0, 1, 2);
                break;
            }

            case OpcodeType.Ld:
            {
                AddLoad(token);
                break;
            }

            case OpcodeType.LdS:
                AddIndent();
                AddCallInterface("Load", token, 0, 2, 1, 3);
                break;

            case OpcodeType.LdMsS:
            case OpcodeType.LdMs:
            {
                AddCallInterface("LoadMs", token, 0, 2, 1);
                break;
            }

            case OpcodeType.LdStructuredS:
            case OpcodeType.LdStructured:
            {
                AddLoadStructured(token);
                break;
            }

            case OpcodeType.LdUavTypedS:
            case OpcodeType.LdUavTyped:
            {
                AddCallInterface("Load", token, 0, 2, 1);
                break;
            }

            case OpcodeType.LdRawS:
            case OpcodeType.LdRaw:
            {
                AddCallInterface("Load", token, 0, 2, 1);
                break;
            }

            case OpcodeType.Lod:
            {
                TranslateTextureSample(token);
                break;
            }

            case OpcodeType.Resinfo:
            {
                int parameterCount = token.Operands[0].GetNumSwizzleElements();
                for (int i = 0; i < 3 - parameterCount; i++)
                {
                    AddIndent();
                    Output.AppendLine($"float unused{i};");
                }
                AddIndent();
                WriteOperandWithMask(token.Operands[2], ComponentMask.None);
                Output.Append(".GetDimensions(");
                WriteOperand(token.Operands[1]);
                var usedMask = token.Operands[0].GetUsedComponents();
                for (int i = 0; i < 4; i++)
                {
                    var mask = (ComponentMask)(1 << i);
                    if (!usedMask.HasFlag(mask))
                    {
                        continue;
                    }
                    Output.Append(", ");
                    WriteOperandWithMask(token.Operands[0], mask);
                }
                for (int i = 0; i < 3 - parameterCount; i++)
                {
                    Output.Append($", unused{i}");
                }
                Output.AppendLine(");");
                break;
            }

            //Atomic Operations
            case OpcodeType.AtomicAnd:
            {
                AddCallInterfaceNoDest("InterlockedAnd", token, 0, 1, 2);
                break;
            }

            case OpcodeType.AtomicOr:
            {
                AddCallInterfaceNoDest("InterlockedOr", token, 0, 1, 2);
                break;
            }

            case OpcodeType.AtomicXor:
            {
                AddCallInterfaceNoDest("InterlockedXor", token, 0, 1, 2);
                break;
            }

            case OpcodeType.AtomicCmpStore:
            {
                AddCallInterfaceNoDest("InterlockedCompareStore", token, 0, 1, 2, 3);
                break;
            }

            case OpcodeType.AtomicIAdd:
            {
                AddCallInterfaceNoDest("InterlockedAdd", token, 0, 1, 2);
                break;
            }

            case OpcodeType.AtomicIMax:
            {
                AddCallInterfaceNoDest("InterlockedMax", token, 0, 1, 2);
                break;
            }

            case OpcodeType.AtomicIMin:
            {
                AddCallInterfaceNoDest("InterlockedMin", token, 0, 1, 2);
                break;
            }

            case OpcodeType.AtomicUMax:
            {
                AddCallInterfaceNoDest("InterlockedMax", token, 0, 1, 2);
                break;
            }

            case OpcodeType.AtomicUMin:
            {
                AddCallInterfaceNoDest("InterlockedMin", token, 0, 1, 2);
                break;
            }

            case OpcodeType.ImmAtomicIAdd:
            {
                AddCallInterfaceNoDest("InterlockedAnd", token, 1, 2, 3, 0);
                break;
            }

            case OpcodeType.ImmAtomicAnd:
            {
                AddCallInterfaceNoDest("InterlockedAnd", token, 1, 2, 3, 0);
                break;
            }

            case OpcodeType.ImmAtomicOr:
            {
                AddCallInterfaceNoDest("InterlockedOr", token, 1, 2, 3, 0);
                break;
            }

            case OpcodeType.ImmAtomicXor:
            {
                AddCallInterfaceNoDest("InterlockedXor", token, 1, 2, 3, 0);
                break;
            }

            case OpcodeType.ImmAtomicExch:
            {
                AddCallInterfaceNoDest("InterlockedExchange", token, 1, 2, 3, 0);
                break;
            }

            case OpcodeType.ImmAtomicCmpExch:
            {
                AddCallInterfaceNoDest("InterlockedCompareExchange", token, 1, 2, 3, 4, 0);
                break;
            }

            case OpcodeType.ImmAtomicIMax:
            {
                AddCallInterfaceNoDest("InterlockedMax", token, 1, 2, 3, 0);
                break;
            }

            case OpcodeType.ImmAtomicIMin:
            {
                AddCallInterfaceNoDest("InterlockedMin", token, 1, 2, 3, 0);
                break;
            }

            case OpcodeType.ImmAtomicUMax:
            {
                AddCallInterfaceNoDest("InterlockedMax", token, 1, 2, 3, 0);
                break;
            }

            case OpcodeType.ImmAtomicUMin:
            {
                AddCallInterfaceNoDest("InterlockedMin", token, 1, 2, 3, 0);
                break;
            }

            case OpcodeType.ImmAtomicAlloc:
            {
                AddCallInterfaceNoDest("Append", token, 1, 0);
                break;
            }

            case OpcodeType.ImmAtomicConsume:
            {
                AddCallInterface("Consume", token, 0, 1);
                break;
            }

            // Misc
            case OpcodeType.Nop:
            {
                break;
            }

            case OpcodeType.InterfaceCall:
            {
                AddIndent();
                var register = RegisterState.GetRegister(token);
                Output.AppendFormat("{0}();\n", register?.Name ?? token.ToString());
                break;
            }

            case OpcodeType.Emit:
            {
                AddIndent();
                Output.Append("TODO_Get_Stream");
                Output.AppendLine(".Append(output);");
                break;
            }

            case OpcodeType.Cut:
            {
                AddIndent();
                Output.Append("TODO_Get_Stream");
                Output.AppendLine(".RestartStrip();");
                break;
            }

            case OpcodeType.CutStream:
            {
                AddIndent();
                WriteOperand(token.Operands[0]);
                Output.AppendLine(".RestartStrip();");
                break;
            }

            case OpcodeType.EmitStream:
            {
                AddIndent();
                WriteOperand(token.Operands[0]);
                Output.AppendLine(".Append(output);");
                break;
            }

            case OpcodeType.EmitThenCutStream:
            {
                break;
            }

            case OpcodeType.Sync:
            {
                AddIndent();
                if (token.SyncFlags == SyncFlags.UnorderedAccessViewGlobal)
                {
                    Output.AppendLine("DeviceMemoryBarrier();");
                }
                else if (token.SyncFlags == SyncFlags.SharedMemory)
                {
                    Output.AppendLine("GroupMemoryBarrier();");
                }
                else if (token.SyncFlags == (SyncFlags.SharedMemory | SyncFlags.UnorderedAccessViewGlobal))
                {
                    Output.AppendLine("AllMemoryBarrier();");
                }
                else if (token.SyncFlags == (SyncFlags.ThreadsInGroup | SyncFlags.UnorderedAccessViewGlobal))
                {
                    Output.AppendLine("DeviceMemoryBarrierWithGroupSync();");
                }
                else if (token.SyncFlags == (SyncFlags.ThreadsInGroup | SyncFlags.SharedMemory))
                {
                    Output.AppendLine("GroupMemoryBarrierWithGroupSync();");
                }
                else if (token.SyncFlags == (SyncFlags.ThreadsInGroup | SyncFlags.SharedMemory | SyncFlags.UnorderedAccessViewGlobal))
                {
                    Output.AppendLine("AllMemoryBarrierWithGroupSync();");
                }
                else
                {
                    throw new Exception($"Unknown Memory Sync Flags {token.SyncFlags}");
                }
                break;
            }

            case OpcodeType.Discard:
            {
                if (token.Operands[0].OperandType == OperandType.Immediate32 ||
                    token.Operands[0].OperandType == OperandType.Immediate64)
                {
                    AddIndent();
                    Output.Append("discard;");
                }
                else
                {
                    WriteConditional(token);
                }
                break;
            }

            case OpcodeType.EvalCentroid:
            {
                CallHelper("EvaluateAttributeCentroid", token, 0, 1);
                break;
            }

            case OpcodeType.EvalSampleIndex:
            {
                CallHelper("EvaluateAttributeAtSample", token, 0, 1, 2);
                break;
            }

            case OpcodeType.EvalSnapped:
            {
                CallHelper("EvaluateAttributeSnapped", token, 0, 1, 2);
                break;
            }

            case OpcodeType.Drcp:
            case OpcodeType.Rcp:
            {
                CallHelper("rcp", token, 0, 1);
                break;
            }

            case OpcodeType.F32ToF16:
            {
                CallHelper("f32tof16", token, 0, 1);
                break;
            }

            case OpcodeType.F16ToF32:
            {
                CallHelper("f16tof32", token, 0, 1);
                break;
            }

            case OpcodeType.INeg:
            {
                CallHelper("negate", token, 0, 1);
                break;
            }

            case OpcodeType.DerivRtx:
            {
                CallHelper("ddx", token, 0, 1);
                break;
            }

            case OpcodeType.RtxCoarse:
            {
                CallHelper("ddx_coarse", token, 0, 1);
                break;
            }

            case OpcodeType.RtxFine:
            {
                CallHelper("ddx_fine", token, 0, 1);
                break;
            }

            case OpcodeType.DerivRty:
            {
                CallHelper("ddy", token, 0, 1);
                break;
            }

            case OpcodeType.RtyCoarse:
            {
                CallHelper("ddy_coarse", token, 0, 1);
                break;
            }

            case OpcodeType.RtyFine:
            {
                CallHelper("ddy_fine", token, 0, 1);
                break;
            }

            case OpcodeType.SamplePos:
            {
                if (token.Operands[1].OperandType == OperandType.Rasterizer)
                {
                    CallHelper("GetRenderTargetSamplePosition", token, 0, 2);
                }
                else
                {
                    AddCallInterface("GetSamplePosition", token, 0, 1, 2);
                }
                break;
            }

            case OpcodeType.Abort:
            {
                AddIndent();
                Output.AppendLine("abort();");
                break;
            }

            case OpcodeType.Msad:
                CallHelper("msad4", token, 0, 1, 2);
                break;

            case OpcodeType.Bufinfo:
                //TODO: need to mask op[0] with no swizzle
                AddCallInterfaceNoDest("GetDimensions", token, 1, 0);
                break;

            case OpcodeType.FirstBitLo:
                CallHelper("firstbitlow", token, 0, 1);
                break;

            case OpcodeType.SampleInfo:
                AddIndent();
                AddAssignToDest(token.Operands[0]);
                Output.AppendLine("GetRenderTargetSampleCount();");
                break;

            case OpcodeType.HsForkPhase:
                break;

            case OpcodeType.HsJoinPhase:
                break;

            case OpcodeType.CheckAccessFullyMapped:
                CallHelper("CheckAccessFullyMapped", token, 0, 1);
                break;

            default:
                throw new Exception($"Unexpected token {token}");
            }
        }
示例#23
0
 public DivergentExecutableInstruction(InstructionToken instructionToken, bool branchIfPositive)
     : base(instructionToken)
 {
     _branchIfPositive = branchIfPositive;
 }
 protected ExecutableInstruction(InstructionToken instructionToken)
 {
     _instructionToken = instructionToken;
 }