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); }
//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(";"); }
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)); }
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)); }
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)); }
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(";"); }
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(";"); }
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(");"); }
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(");"); }
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); } } }
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); }
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}"); } }
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); }
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(";"); } }
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;"); }
/// <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)); } }
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(); } }
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)); }
public override string ToString() { return(InstructionToken.ToString()); }
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) { }
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}"); } }
public DivergentExecutableInstruction(InstructionToken instructionToken, bool branchIfPositive) : base(instructionToken) { _branchIfPositive = branchIfPositive; }
protected ExecutableInstruction(InstructionToken instructionToken) { _instructionToken = instructionToken; }