From c8742a1456194f4537b5eeecc44abe728258fa56 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 9 Jun 2020 13:38:18 +0100 Subject: [PATCH] Handle extract/insert/shuffle vector and aggregate operations * DXIL supposedly won't use these, but handle them just in case --- .../driver/shaders/dxil/dxil_bytecode.cpp | 117 +++++++++++++++++- renderdoc/driver/shaders/dxil/dxil_bytecode.h | 4 + .../driver/shaders/dxil/dxil_disassemble.cpp | 40 ++++++ 3 files changed, 158 insertions(+), 3 deletions(-) diff --git a/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp b/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp index 67eeb104b..5d30743be 100644 --- a/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp @@ -1561,7 +1561,8 @@ Program::Program(const byte *bytes, size_t length) } } - RDCASSERT(inst.type->type == argType->type); + RDCASSERT(inst.type->type == argType->type && + inst.type->elemCount == argType->elemCount); m_Symbols.push_back({SymbolType::Instruction, f.instructions.size()}); @@ -1587,13 +1588,123 @@ Program::Program(const byte *bytes, size_t length) f.instructions.push_back(inst); } + else if(IS_KNOWN(op.id, FunctionRecord::INST_EXTRACTELT)) + { + // DXIL claims to be scalarised so should this appear? + RDCWARN("Unexpected vector instruction extractelement in DXIL"); + + Instruction inst; + + inst.op = Instruction::ExtractElement; + + // vector + inst.args.push_back(getSymbol(op.ops[0])); + // index + inst.args.push_back(getSymbol(op.ops[1])); + + // result is the scalar type within the vector + inst.type = GetSymbolType(f, inst.args[0])->inner; + + m_Symbols.push_back({SymbolType::Instruction, f.instructions.size()}); + + f.instructions.push_back(inst); + } + else if(IS_KNOWN(op.id, FunctionRecord::INST_INSERTELT)) + { + // DXIL claims to be scalarised so should this appear? + RDCWARN("Unexpected vector instruction insertelement in DXIL"); + + Instruction inst; + + inst.op = Instruction::InsertElement; + + // vector + inst.args.push_back(getSymbol(op.ops[0])); + // replacement element + inst.args.push_back(getSymbol(op.ops[1])); + // index + inst.args.push_back(getSymbol(op.ops[2])); + + // result is the vector type + inst.type = GetSymbolType(f, inst.args[0]); + + m_Symbols.push_back({SymbolType::Instruction, f.instructions.size()}); + + f.instructions.push_back(inst); + } + else if(IS_KNOWN(op.id, FunctionRecord::INST_SHUFFLEVEC)) + { + // DXIL claims to be scalarised so should this appear? + RDCWARN("Unexpected vector instruction shufflevector in DXIL"); + + Instruction inst; + + inst.op = Instruction::ShuffleVector; + + // vector 1 + inst.args.push_back(getSymbol(op.ops[0])); + // vector 2 + inst.args.push_back(getSymbol(op.ops[1])); + // indexes + inst.args.push_back(getSymbol(op.ops[2])); + + // result is a vector with the inner type of the first two vectors and the element + // count of the last vector + const Type *vecType = GetSymbolType(f, inst.args[0]); + const Type *maskType = GetSymbolType(f, inst.args[2]); + + for(const Type &t : m_Types) + { + if(t.type == Type::Vector && t.inner == vecType->inner && + t.elemCount == maskType->elemCount) + { + inst.type = &t; + break; + } + } + + RDCASSERT(inst.type); + + m_Symbols.push_back({SymbolType::Instruction, f.instructions.size()}); + + f.instructions.push_back(inst); + } + else if(IS_KNOWN(op.id, FunctionRecord::INST_INSERTVAL)) + { + // DXIL claims to be scalarised so should this appear? + RDCWARN("Unexpected aggregate instruction insertvalue in DXIL"); + + Instruction inst; + + inst.op = Instruction::InsertValue; + + // aggregate + inst.args.push_back(getSymbol(op.ops[0])); + // replacement element + inst.args.push_back(getSymbol(op.ops[1])); + // indices as literals + for(size_t a = 2; a < op.ops.size(); a++) + inst.args.push_back(Symbol(SymbolType::Literal, op.ops[a])); + + // result is the aggregate type + inst.type = GetSymbolType(f, inst.args[0]); + + m_Symbols.push_back({SymbolType::Instruction, f.instructions.size()}); + + f.instructions.push_back(inst); + } + else if(IS_KNOWN(op.id, FunctionRecord::INST_VAARG)) + { + // don't expect vararg instructions + RDCERR("Unexpected vararg instruction %u in DXIL", op.id); + } else if(IS_KNOWN(op.id, FunctionRecord::INST_LANDINGPAD) || IS_KNOWN(op.id, FunctionRecord::INST_LANDINGPAD_OLD) || - IS_KNOWN(op.id, FunctionRecord::INST_VAARG) || IS_KNOWN(op.id, FunctionRecord::INST_INVOKE) || IS_KNOWN(op.id, FunctionRecord::INST_RESUME)) { - RDCERR("Unexpected instruction %u in DXIL", op.id); + // don't expect exception handling instructions + RDCERR("Unexpected exception handling instruction %u in DXIL", op.id); } else { diff --git a/renderdoc/driver/shaders/dxil/dxil_bytecode.h b/renderdoc/driver/shaders/dxil/dxil_bytecode.h index 94642b40c..3fd0864c9 100644 --- a/renderdoc/driver/shaders/dxil/dxil_bytecode.h +++ b/renderdoc/driver/shaders/dxil/dxil_bytecode.h @@ -363,6 +363,10 @@ struct Instruction SLess, SLessEqual, Select, + ExtractElement, + InsertElement, + ShuffleVector, + InsertValue, } op = Unknown; InstructionFlags opFlags = InstructionFlags::NoFlags; diff --git a/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp b/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp index ec041939d..e76a067c0 100644 --- a/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp @@ -734,6 +734,46 @@ void Program::MakeDisassemblyString() m_Disassembly += argToString(inst.args[1], true); break; } + case Instruction::ExtractElement: + { + m_Disassembly += "extractelement "; + m_Disassembly += argToString(inst.args[0], true); + m_Disassembly += ", "; + m_Disassembly += argToString(inst.args[1], true); + break; + } + case Instruction::InsertElement: + { + m_Disassembly += "insertelement "; + m_Disassembly += argToString(inst.args[0], true); + m_Disassembly += ", "; + m_Disassembly += argToString(inst.args[1], true); + m_Disassembly += ", "; + m_Disassembly += argToString(inst.args[2], true); + break; + } + case Instruction::ShuffleVector: + { + m_Disassembly += "shufflevector "; + m_Disassembly += argToString(inst.args[0], true); + m_Disassembly += ", "; + m_Disassembly += argToString(inst.args[1], true); + m_Disassembly += ", "; + m_Disassembly += argToString(inst.args[2], true); + break; + } + case Instruction::InsertValue: + { + m_Disassembly += "insertvalue "; + m_Disassembly += argToString(inst.args[0], true); + m_Disassembly += ", "; + m_Disassembly += argToString(inst.args[1], true); + for(size_t a = 2; a < inst.args.size(); a++) + { + m_Disassembly += ", " + ToStr(inst.args[2].idx); + } + break; + } } if(inst.debugLoc != ~0U)