From 112a1329ecceaca7386369a1cc685af44dd34738 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Fri, 27 Apr 2012 17:15:32 +0100 Subject: [PATCH] Preserve both D3D9 shader byte code, and disassembly. --- common/trace_dump.cpp | 4 ++++ common/trace_format.hpp | 4 +++- common/trace_model.cpp | 13 +++++++++++- common/trace_model.hpp | 30 ++++++++++++++++++++++++++++ common/trace_parser.cpp | 19 ++++++++++++++++++ common/trace_parser.hpp | 3 +++ common/trace_writer.cpp | 4 ++++ common/trace_writer.hpp | 3 +++ common/trace_writer_model.cpp | 7 +++++++ gui/apitracecall.cpp | 6 ++++++ gui/apitracecall.h | 1 + helpers/d3dsize.hpp | 32 ++++++++++++++++++++++++++++++ retrace/d3dretrace.py | 11 ----------- specs/d3d9.py | 2 +- wrappers/d3d9trace.py | 4 ++-- wrappers/d3dshader.cpp | 37 ++++++++++++++++++++++------------- 16 files changed, 150 insertions(+), 30 deletions(-) diff --git a/common/trace_dump.cpp b/common/trace_dump.cpp index 06c0079..f40e549 100644 --- a/common/trace_dump.cpp +++ b/common/trace_dump.cpp @@ -200,6 +200,10 @@ public: os << pointer << "0x" << std::hex << p->value << std::dec << normal; } + void visit(Repr *r) { + _visit(r->humanValue); + } + void visit(Call *call) { CallFlags callFlags = call->flags; diff --git a/common/trace_format.hpp b/common/trace_format.hpp index 4e1d9a9..d5fd81b 100644 --- a/common/trace_format.hpp +++ b/common/trace_format.hpp @@ -96,11 +96,12 @@ namespace trace { * | DOUBLE double * | STRING string * | BLOB string - * | ENUM enum_sig + * | ENUM enum_sig value * | BITMASK bitmask_sig value * | ARRAY length value+ * | STRUCT struct_sig value+ * | OPAQUE int + * | REPR value value * * call_sig = id name arg_name* * | id @@ -143,6 +144,7 @@ enum Type { TYPE_ARRAY, TYPE_STRUCT, TYPE_OPAQUE, + TYPE_REPR, }; diff --git a/common/trace_model.cpp b/common/trace_model.cpp index 7e926ba..86527a1 100644 --- a/common/trace_model.cpp +++ b/common/trace_model.cpp @@ -85,6 +85,7 @@ bool Struct ::toBool(void) const { return true; } bool Array ::toBool(void) const { return true; } bool Blob ::toBool(void) const { return true; } bool Pointer::toBool(void) const { return value != 0; } +bool Repr ::toBool(void) const { return static_cast(machineValue); } // signed integer cast @@ -95,6 +96,7 @@ signed long long SInt ::toSInt(void) const { return value; } signed long long UInt ::toSInt(void) const { assert(static_cast(value) >= 0); return static_cast(value); } signed long long Float ::toSInt(void) const { return static_cast(value); } signed long long Double ::toSInt(void) const { return static_cast(value); } +signed long long Repr ::toSInt(void) const { return machineValue->toSInt(); } // unsigned integer cast @@ -105,6 +107,7 @@ unsigned long long SInt ::toUInt(void) const { assert(value >= 0); return stat unsigned long long UInt ::toUInt(void) const { return value; } unsigned long long Float ::toUInt(void) const { return static_cast(value); } unsigned long long Double ::toUInt(void) const { return static_cast(value); } +unsigned long long Repr ::toUInt(void) const { return machineValue->toUInt(); } // floating point cast @@ -115,6 +118,7 @@ float SInt ::toFloat(void) const { return static_cast(value); } float UInt ::toFloat(void) const { return static_cast(value); } float Float ::toFloat(void) const { return value; } float Double ::toFloat(void) const { return value; } +float Repr ::toFloat(void) const { return machineValue->toFloat(); } // floating point cast @@ -125,6 +129,7 @@ double SInt ::toDouble(void) const { return static_cast(value); } double UInt ::toDouble(void) const { return static_cast(value); } double Float ::toDouble(void) const { return value; } double Double ::toDouble(void) const { return value; } +double Repr ::toDouble(void) const { return machineValue->toDouble(); } // pointer cast @@ -132,23 +137,27 @@ void * Value ::toPointer(void) const { assert(0); return NULL; } void * Null ::toPointer(void) const { return NULL; } void * Blob ::toPointer(void) const { return buf; } void * Pointer::toPointer(void) const { return (void *)value; } +void * Repr ::toPointer(void) const { return machineValue->toPointer(); } void * Value ::toPointer(bool bind) { assert(0); return NULL; } void * Null ::toPointer(bool bind) { return NULL; } void * Blob ::toPointer(bool bind) { if (bind) bound = true; return buf; } void * Pointer::toPointer(bool bind) { return (void *)value; } +void * Repr ::toPointer(bool bind) { return machineValue->toPointer(bind); } -// pointer cast +// unsigned int pointer cast unsigned long long Value ::toUIntPtr(void) const { assert(0); return 0; } unsigned long long Null ::toUIntPtr(void) const { return 0; } unsigned long long Pointer::toUIntPtr(void) const { return value; } +unsigned long long Repr ::toUIntPtr(void) const { return machineValue->toUIntPtr(); } // string cast const char * Value ::toString(void) const { assert(0); return NULL; } const char * Null ::toString(void) const { return NULL; } const char * String::toString(void) const { return value; } +const char * Repr ::toString(void) const { return machineValue->toString(); } // virtual Value::visit() @@ -165,6 +174,7 @@ void Struct ::visit(Visitor &visitor) { visitor.visit(this); } void Array ::visit(Visitor &visitor) { visitor.visit(this); } void Blob ::visit(Visitor &visitor) { visitor.visit(this); } void Pointer::visit(Visitor &visitor) { visitor.visit(this); } +void Repr ::visit(Visitor &visitor) { visitor.visit(this); } void Visitor::visit(Null *) { assert(0); } @@ -180,6 +190,7 @@ void Visitor::visit(Struct *) { assert(0); } void Visitor::visit(Array *) { assert(0); } void Visitor::visit(Blob *) { assert(0); } void Visitor::visit(Pointer *) { assert(0); } +void Visitor::visit(Repr *node) { node->machineValue->visit(*this); } static Null null; diff --git a/common/trace_model.hpp b/common/trace_model.hpp index 3ddd9a0..bb8936e 100644 --- a/common/trace_model.hpp +++ b/common/trace_model.hpp @@ -320,6 +320,35 @@ public: }; +class Repr : public Value +{ +public: + Repr(Value *human, Value *machine) : + humanValue(human), + machineValue(machine) + {} + + /** Human-readible value */ + Value *humanValue; + + /** Machine-readible value */ + Value *machineValue; + + virtual bool toBool(void) const; + virtual signed long long toSInt(void) const; + virtual unsigned long long toUInt(void) const; + virtual float toFloat(void) const; + virtual double toDouble(void) const; + + virtual void *toPointer(void) const; + virtual void *toPointer(bool bind); + virtual unsigned long long toUIntPtr(void) const; + virtual const char *toString(void) const; + + void visit(Visitor &visitor); +}; + + class Visitor { public: @@ -336,6 +365,7 @@ public: virtual void visit(Array *); virtual void visit(Blob *); virtual void visit(Pointer *); + virtual void visit(Repr *); protected: inline void _visit(Value *value) { diff --git a/common/trace_parser.cpp b/common/trace_parser.cpp index 0e4fba0..3b15901 100644 --- a/common/trace_parser.cpp +++ b/common/trace_parser.cpp @@ -557,6 +557,9 @@ Value *Parser::parse_value(void) { case trace::TYPE_OPAQUE: value = parse_opaque(); break; + case trace::TYPE_REPR: + value = parse_repr(); + break; default: std::cerr << "error: unknown type " << c << "\n"; exit(1); @@ -613,6 +616,9 @@ void Parser::scan_value(void) { case trace::TYPE_OPAQUE: scan_opaque(); break; + case trace::TYPE_REPR: + scan_repr(); + break; default: std::cerr << "error: unknown type " << c << "\n"; exit(1); @@ -784,6 +790,19 @@ void Parser::scan_opaque() { } +Value *Parser::parse_repr() { + Value *humanValue = parse_value(); + Value *machineValue = parse_value(); + return new Repr(humanValue, machineValue); +} + + +void Parser::scan_repr() { + scan_value(); + scan_value(); +} + + const char * Parser::read_string(void) { size_t len = read_uint(); char * value = new char[len + 1]; diff --git a/common/trace_parser.hpp b/common/trace_parser.hpp index 43c1356..0ae3a28 100644 --- a/common/trace_parser.hpp +++ b/common/trace_parser.hpp @@ -195,6 +195,9 @@ protected: Value *parse_opaque(); void scan_opaque(); + Value *parse_repr(); + void scan_repr(); + const char * read_string(void); void skip_string(void); diff --git a/common/trace_writer.cpp b/common/trace_writer.cpp index f4b82d8..d69e93f 100644 --- a/common/trace_writer.cpp +++ b/common/trace_writer.cpp @@ -190,6 +190,10 @@ void Writer::beginStruct(const StructSig *sig) { } } +void Writer::beginRepr(void) { + _writeByte(trace::TYPE_REPR); +} + void Writer::writeBool(bool value) { _writeByte(value ? trace::TYPE_TRUE : trace::TYPE_FALSE); } diff --git a/common/trace_writer.hpp b/common/trace_writer.hpp index 5f18f74..a46b43e 100644 --- a/common/trace_writer.hpp +++ b/common/trace_writer.hpp @@ -79,6 +79,9 @@ namespace trace { void beginStruct(const StructSig *sig); inline void endStruct(void) {} + void beginRepr(void); + inline void endRepr(void) {} + void writeBool(bool value); void writeSInt(signed long long value); void writeUInt(unsigned long long value); diff --git a/common/trace_writer_model.cpp b/common/trace_writer_model.cpp index 9bd9ae6..2e858a2 100644 --- a/common/trace_writer_model.cpp +++ b/common/trace_writer_model.cpp @@ -100,6 +100,13 @@ public: writer.writePointer(node->value); } + void visit(Repr *node) { + writer.beginRepr(); + _visit(node->humanValue); + _visit(node->machineValue); + writer.endRepr(); + } + void visit(Call *call) { unsigned call_no = writer.beginEnter(call->sig, call->thread_id); for (unsigned i = 0; i < call->args.size(); ++i) { diff --git a/gui/apitracecall.cpp b/gui/apitracecall.cpp index 25b035d..907e10a 100644 --- a/gui/apitracecall.cpp +++ b/gui/apitracecall.cpp @@ -227,6 +227,12 @@ void VariantVisitor::visit(trace::Pointer *ptr) m_variant = QVariant::fromValue(ApiPointer(ptr->value)); } +void VariantVisitor::visit(trace::Repr *repr) +{ + /* TODO: Preserve both the human and machine value */ + repr->humanValue->visit(*this); +} + ApiTraceEnumSignature::ApiTraceEnumSignature(const trace::EnumSig *sig) { for (const trace::EnumValue *it = sig->values; diff --git a/gui/apitracecall.h b/gui/apitracecall.h index 945ab0c..6c6b607 100644 --- a/gui/apitracecall.h +++ b/gui/apitracecall.h @@ -33,6 +33,7 @@ public: virtual void visit(trace::Array *array); virtual void visit(trace::Blob *blob); virtual void visit(trace::Pointer *ptr); + virtual void visit(trace::Repr *ptr); QVariant variant() const { diff --git a/helpers/d3dsize.hpp b/helpers/d3dsize.hpp index 7909501..ef3bdff 100644 --- a/helpers/d3dsize.hpp +++ b/helpers/d3dsize.hpp @@ -37,6 +37,8 @@ /* We purposedly don't include any D3D header, so that this header can be used * with all D3D versions. */ +#include + #include "os.hpp" @@ -87,4 +89,34 @@ _indexDataSize(D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, D3DFORMAT In } +#if DIRECT3D_VERSION >= 0x0800 + +/* + * Return the number of tokens for a given shader. + */ +static inline size_t +_shaderSize(const DWORD *pFunction) +{ + DWORD dwLength = 0; + + while (true) { + DWORD dwToken = pFunction[dwLength++]; + + switch (dwToken & D3DSI_OPCODE_MASK) { + case D3DSIO_COMMENT: + dwLength += (dwToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT; + break; + + case D3DSIO_END: + if (dwToken != D3DSIO_END) { + os::log("apitrace: warning: %s: malformed END token\n", __FUNCTION__); + } + return dwLength * sizeof *pFunction; + } + } +} + +#endif /* DIRECT3D_VERSION >= 0x0800 */ + + #endif /* _D3D_SIZE_HPP_ */ diff --git a/retrace/d3dretrace.py b/retrace/d3dretrace.py index a04e01d..29d81dc 100644 --- a/retrace/d3dretrace.py +++ b/retrace/d3dretrace.py @@ -41,17 +41,6 @@ class D3DRetracer(Retracer): 'IDirect3DIndexBuffer9', ] - def extractArg(self, function, arg, arg_type, lvalue, rvalue): - if arg.type is D3DSHADER9: - print r' %s = extractShader((%s).toString());' % (lvalue, rvalue) - print r' if (!%s) {' % lvalue - print r' retrace::warning(call) << "failed to assemble shader\n";' - print r' return;' - print r' }' - return - - Retracer.extractArg(self, function, arg, arg_type, lvalue, rvalue) - def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('IDirect3DDevice9', 'IDirect3DDevice9Ex'): diff --git a/specs/d3d9.py b/specs/d3d9.py index 6f81ce5..2fd7755 100644 --- a/specs/d3d9.py +++ b/specs/d3d9.py @@ -30,7 +30,7 @@ from d3d9types import * from d3d9caps import * -D3DSHADER9 = OpaquePointer(Const(DWORD)) +D3DSHADER9 = Blob(Const(DWORD), "_shaderSize(pFunction)") D3DSPD = Flags(DWORD, [ "D3DSPD_IUNKNOWN", diff --git a/wrappers/d3d9trace.py b/wrappers/d3d9trace.py index 708f05a..ebf5489 100644 --- a/wrappers/d3d9trace.py +++ b/wrappers/d3d9trace.py @@ -25,14 +25,14 @@ from dlltrace import DllTracer -from specs.d3d9 import d3d9 +from specs.d3d9 import d3d9, D3DSHADER9 class D3D9Tracer(DllTracer): def serializeArgValue(self, function, arg): # Dump shaders as strings - if function.name in ('CreateVertexShader', 'CreatePixelShader') and arg.name == 'pFunction': + if arg.type is D3DSHADER9: print ' DumpShader(trace::localWriter, %s);' % (arg.name) return diff --git a/wrappers/d3dshader.cpp b/wrappers/d3dshader.cpp index ee9cd9a..7a1e552 100644 --- a/wrappers/d3dshader.cpp +++ b/wrappers/d3dshader.cpp @@ -29,6 +29,7 @@ #include "d3dshader.hpp" #include "d3d9imports.hpp" +#include "d3dsize.hpp" typedef HRESULT @@ -43,6 +44,12 @@ typedef HRESULT void DumpShader(trace::Writer &writer, const DWORD *tokens) { static BOOL firsttime = TRUE; + + /* + * TODO: Consider using d3dcompile_xx.dll per + * http://msdn.microsoft.com/en-us/library/windows/desktop/ee663275.aspx + */ + static HMODULE hD3DXModule = NULL; static PD3DXDISASSEMBLESHADER pfnD3DXDisassembleShader = NULL; @@ -74,23 +81,25 @@ found: firsttime = FALSE; } - if (pfnD3DXDisassembleShader) { - LPD3DXBUFFER pDisassembly = NULL; - HRESULT hr; + LPD3DXBUFFER pDisassembly = NULL; + HRESULT hr = E_FAIL; + if (pfnD3DXDisassembleShader) { hr = pfnD3DXDisassembleShader(tokens, FALSE, NULL, &pDisassembly); - if (hr == D3D_OK) { - writer.writeString((const char *)pDisassembly->GetBufferPointer()); - } - - if (pDisassembly) { - pDisassembly->Release(); - } + } - if (hr == D3D_OK) { - return; - } + if (hr == D3D_OK) { + writer.beginRepr(); + writer.writeString((const char *)pDisassembly->GetBufferPointer(), pDisassembly->GetBufferSize()); } - writer.writePointer((UINT_PTR)tokens); + writer.writeBlob(tokens, _shaderSize(tokens)); + + if (pDisassembly) { + pDisassembly->Release(); + } + + if (hr == D3D_OK) { + writer.endRepr(); + } } -- 2.43.0