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;
* | 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
TYPE_ARRAY,
TYPE_STRUCT,
TYPE_OPAQUE,
+ TYPE_REPR,
};
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
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
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
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
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
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()
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); }
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;
};
+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:
virtual void visit(Array *);
virtual void visit(Blob *);
virtual void visit(Pointer *);
+ virtual void visit(Repr *);
protected:
inline void _visit(Value *value) {
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);
case trace::TYPE_OPAQUE:
scan_opaque();
break;
+ case trace::TYPE_REPR:
+ scan_repr();
+ break;
default:
std::cerr << "error: unknown type " << c << "\n";
exit(1);
}
+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];
Value *parse_opaque();
void scan_opaque();
+ Value *parse_repr();
+ void scan_repr();
+
const char * read_string(void);
void skip_string(void);
}
}
+void Writer::beginRepr(void) {
+ _writeByte(trace::TYPE_REPR);
+}
+
void Writer::writeBool(bool value) {
_writeByte(value ? trace::TYPE_TRUE : trace::TYPE_FALSE);
}
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);
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) {
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;
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
{
/* 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"
}
+#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_ */
'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'):
from d3d9caps import *
-D3DSHADER9 = OpaquePointer(Const(DWORD))
+D3DSHADER9 = Blob(Const(DWORD), "_shaderSize(pFunction)")
D3DSPD = Flags(DWORD, [
"D3DSPD_IUNKNOWN",
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
#include "d3dshader.hpp"
#include "d3d9imports.hpp"
+#include "d3dsize.hpp"
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;
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();
+ }
}