]> git.cworth.org Git - apitrace/commitdiff
Preserve both D3D9 shader byte code, and disassembly.
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Fri, 27 Apr 2012 16:15:32 +0000 (17:15 +0100)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Fri, 27 Apr 2012 16:15:32 +0000 (17:15 +0100)
16 files changed:
common/trace_dump.cpp
common/trace_format.hpp
common/trace_model.cpp
common/trace_model.hpp
common/trace_parser.cpp
common/trace_parser.hpp
common/trace_writer.cpp
common/trace_writer.hpp
common/trace_writer_model.cpp
gui/apitracecall.cpp
gui/apitracecall.h
helpers/d3dsize.hpp
retrace/d3dretrace.py
specs/d3d9.py
wrappers/d3d9trace.py
wrappers/d3dshader.cpp

index 06c0079a5e2a8d9436a20ee91e3c71527fd12766..f40e549bacec9d1556c1141c982fb12ef4c26406 100644 (file)
@@ -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;
         
index 4e1d9a9911d265bac1a9ef4462c174e21637704c..d5fd81b5b9eeacd6f9a6f2da06ac78a90c5353d9 100644 (file)
@@ -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,
 };
 
 
index 7e926ba46db70e65c5e8ee1a732f7ce9dcde784e..86527a1f900f59959691ca740656199c417b5280 100644 (file)
@@ -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<bool>(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<signed long long>(value) >= 0); return static_cast<signed long long>(value); }
 signed long long Float  ::toSInt(void) const { return static_cast<signed long long>(value); }
 signed long long Double ::toSInt(void) const { return static_cast<signed long long>(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<unsigned long long>(value); }
 unsigned long long Double ::toUInt(void) const { return static_cast<unsigned long long>(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<float>(value); }
 float UInt   ::toFloat(void) const { return static_cast<float>(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<double>(value); }
 double UInt   ::toDouble(void) const { return static_cast<double>(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;
index 3ddd9a0db13dc81bf5b7f959ecc64ededef67a69..bb8936e32946bc78763edb025802ce1f6adfccc4 100644 (file)
@@ -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) {
index 0e4fba098db597d4e782251e7149d7c36ee80a0c..3b159017eabc4c5b5be76d7e138d14ee320bff39 100644 (file)
@@ -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];
index 43c13563a639cb59e535dff580be1e39d22ff28f..0ae3a28d682b80ad6034e1c8daa88fec91362064 100644 (file)
@@ -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);
 
index f4b82d8f300e0084eb5b6e0943afa49f4be8b2fd..d69e93fc9650211ca8d6418d173b027a4fa3cc26 100644 (file)
@@ -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);
 }
index 5f18f74e1b257dc80ba70c7c157a3d2ad7f54fe1..a46b43edc487f15faff6f22bc68fade0a57924fa 100644 (file)
@@ -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);
index 9bd9ae6022cbf5ec895e42455f752ec35fcec97e..2e858a233971e3434410b8daba6fb5601c66e3a9 100644 (file)
@@ -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) {
index 25b035d2ca90e82b8cfe2733b29fe2098e2a83c4..907e10aa08294fc878549708a92e074fc9eb2681 100644 (file)
@@ -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;
index 945ab0cb8eedbff9cf1c29389c1a06bc839ea2e9..6c6b6074b6dcae2799e1f4a750cdc293120c3f53 100644 (file)
@@ -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
     {
index 79095011873501ad6791988fbb25247775102b16..ef3bdff85e69f6f5b1e9ae6c260aa85652bec186 100644 (file)
@@ -37,6 +37,8 @@
 /* We purposedly don't include any D3D header, so that this header can be used
  * with all D3D versions. */
 
+#include <assert.h>
+
 #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_ */
index a04e01def391870b815a68ff54884f3685561f0d..29d81dcbd2bfab0c089a213e3ba6bcf47a15d347 100644 (file)
@@ -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'):
index 6f81ce5327ef64590333d17c8a5c3ac4c6203734..2fd7755d8a972209454c4637115b22b68f0f15d1 100644 (file)
@@ -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",
index 708f05ad13d2c8a91a0e2bfd9f6b315c8686ae1c..ebf5489352f259721da9b3f5bfc8b0fd90da5160 100644 (file)
 
 
 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
 
index ee9cd9a55d8f1516d9def454f122a3511904aa37..7a1e5520796c0f7527c292aa1384180423530933 100644 (file)
@@ -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();
+    }
 }