blob: 0da7bf5df9d56b3f48ca8d3bd2afc1aa83392e70 [file] [log] [blame]
José Fonseca2cce1922012-12-11 19:51:26 +00001#!/usr/bin/env python
2##########################################################################
3#
4# Copyright 2012 VMware Inc.
5# All Rights Reserved.
6#
7# Permission is hereby granted, free of charge, to any person obtaining a copy
8# of this software and associated documentation files (the 'Software'), to deal
9# in the Software without restriction, including without limitation the rights
10# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11# copies of the Software, and to permit persons to whom the Software is
12# furnished to do so, subject to the following conditions:
13#
14# The above copyright notice and this permission notice shall be included in
15# all copies or substantial portions of the Software.
16#
17# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23# THE SOFTWARE.
24#
25##########################################################################/
26
27'''Convert traces to/from PIX.
28'''
29
30
31import optparse
32import os.path
33import subprocess
34import platform
35import sys
36
37
José Fonsecaf3cb6202015-02-08 00:05:35 +000038def callProcess(cmd):
39 if options.verbose:
40 sys.stderr.write(' '.join(cmd) + '\n')
41 ret = subprocess.call(cmd)
42 if ret:
43 exeName = os.path.basename(cmd[0])
44 sys.stderr.write('error: %s failed with exit code %u\n' % (exeName, ret))
45 sys.exit(ret)
46 return ret
47
48
49def verifyTrace(outTrace):
50 if os.path.exists(outTrace):
51 sys.stderr.write('info: %s written\n' % outTrace)
52 if options.verify:
53 callProcess([options.retrace, os.path.abspath(outTrace)])
54 else:
55 sys.stderr.write('error: %s not written\n' % outTrace)
56 sys.exit(1)
57
58
José Fonseca8b9f78b2013-04-25 15:22:53 +010059def getPixExe():
José Fonseca2cce1922012-12-11 19:51:26 +000060 try:
José Fonseca87f97d22012-12-11 20:37:39 +000061 programFiles = os.environ['ProgramFiles(x86)']
62 except KeyError:
63 programFiles = os.environ['ProgramFiles']
64 try:
José Fonseca2cce1922012-12-11 19:51:26 +000065 dxsdkDir = os.environ['DXSDK_DIR']
66 except KeyError:
67 dxsdkDir = os.path.join(programFiles, "Microsoft DirectX SDL (June 2010)")
José Fonseca8b9f78b2013-04-25 15:22:53 +010068 pixExe = os.path.join(dxsdkDir, "Utilities", "bin", 'x86', 'PIXwin.exe')
69 return pixExe
70
71
José Fonseca8b9f78b2013-04-25 15:22:53 +010072def convertToPix(inTrace, outPixrun):
José Fonsecaf3cb6202015-02-08 00:05:35 +000073 pixExe = getPixExe()
José Fonseca2cce1922012-12-11 19:51:26 +000074
75 pixExp = os.path.join(os.path.dirname(__file__), 'apitrace.PIXExp')
76
77 # http://social.msdn.microsoft.com/Forums/sv/devdocs/thread/15addc0c-036d-413a-854a-35637ccbb834
78 # http://src.chromium.org/svn/trunk/o3d/tests/test_driver.py
79 cmd = [
José Fonseca8b9f78b2013-04-25 15:22:53 +010080 getPixExe(),
José Fonseca2cce1922012-12-11 19:51:26 +000081 pixExp,
82 '-start',
83 '-runfile', os.path.abspath(outPixrun),
84 '-targetpath', os.path.abspath(options.retrace),
85 #'-targetstartfolder', ...,
86 '-targetargs', os.path.abspath(inTrace),
87 ]
88
José Fonseca8b9f78b2013-04-25 15:22:53 +010089 callProcess(cmd)
José Fonseca2cce1922012-12-11 19:51:26 +000090 if os.path.exists(outPixrun):
91 sys.stderr.write('info: %s written\n' % outPixrun)
José Fonseca8b9f78b2013-04-25 15:22:53 +010092 if options.verify:
José Fonsecaf3cb6202015-02-08 00:05:35 +000093 subprocess.call([pixExe, os.path.abspath(outPixrun)])
José Fonseca2cce1922012-12-11 19:51:26 +000094 else:
95 sys.stderr.write('error: %s not written\n' % outPixrun)
96 sys.exit(1)
97
98
José Fonseca7b5e68d2015-03-26 15:21:46 +000099def detectApiFromCsv(inCsv):
100 import csv
101 csvReader = csv.reader(open(inCsv, 'rt'), )
102 for row in csvReader:
103 print row
104 event = row[2]
105 print event
106 if event.startswith("Direct3DCreate9"):
107 return "d3d9"
108 if event.startswith("CreateDXGIFactory"):
109 return "dxgi"
110 if event.startswith("D3D10CreateDevice"):
111 return "d3d10"
112 if event.startswith("D3D11CreateDevice"):
113 return "d3d11"
114 assert False
115
116
José Fonseca8b9f78b2013-04-25 15:22:53 +0100117def convertFromPix(inPix, outTrace):
118 pixExe = getPixExe()
119
José Fonseca7b5e68d2015-03-26 15:21:46 +0000120 api = options.api
121
122 if True:
123 # Use -exporttocsv option to detect which API to use
José Fonseca8b9f78b2013-04-25 15:22:53 +0100124 cmd = [
125 pixExe,
126 inPix,
José Fonseca7b5e68d2015-03-26 15:21:46 +0000127 '-exporttocsv',
José Fonseca8b9f78b2013-04-25 15:22:53 +0100128 ]
José Fonseca7b5e68d2015-03-26 15:21:46 +0000129
130 # XXX: output filename is ignored
131 inPixDir, inPixFileName = os.path.split(inPix)
132 inPixName, inPixExt = os.path.splitext(inPixFileName)
133 outCsv = os.path.join(inPixDir, inPixName + '.csv')
134
135 if os.path.exists(outCsv):
136 os.remove(outCsv)
137
José Fonseca8b9f78b2013-04-25 15:22:53 +0100138 callProcess(cmd)
139
José Fonseca7b5e68d2015-03-26 15:21:46 +0000140 if os.path.isfile(outCsv):
141 api = detectApiFromCsv(outCsv)
142
José Fonseca8b9f78b2013-04-25 15:22:53 +0100143 cmd = [
144 options.apitrace,
145 'trace',
José Fonseca7b5e68d2015-03-26 15:21:46 +0000146 '-a', api,
José Fonseca8b9f78b2013-04-25 15:22:53 +0100147 '-o', outTrace,
148 pixExe,
149 inPix,
150 '-playstandalone',
151 ]
152
153 callProcess(cmd)
José Fonsecaf3cb6202015-02-08 00:05:35 +0000154 verifyTrace(outTrace)
155
156
157def getDxcapExe():
158 winDir = os.environ['windir']
159 if 'ProgramFiles(x86)' in os.environ:
160 sysSubDir = 'SysWOW64'
José Fonseca8b9f78b2013-04-25 15:22:53 +0100161 else:
José Fonsecaf3cb6202015-02-08 00:05:35 +0000162 sysSubDir = 'System32'
163 dxcapExe = os.path.join(winDir, sysSubDir, 'dxcap.exe')
164 return dxcapExe
165
166
167def convertToDxcap(inTrace, outDxcaprun):
168 # https://msdn.microsoft.com/en-us/library/vstudio/dn774939.aspx
169
170 dxcapExe = getDxcapExe()
171
172 cmd = [
173 getDxcapExe(),
174 '-rawmode',
175 '-file', os.path.abspath(outDxcaprun),
176 '-c',
177 options.retrace,
178 '-b',
179 os.path.abspath(inTrace),
180 ]
181
182 callProcess(cmd)
183 if os.path.exists(outDxcaprun):
184 sys.stderr.write('info: %s written\n' % outDxcaprun)
185 if options.verify:
186 callProcess([dxcapExe, '-p', os.path.abspath(outDxcaprun)])
187 else:
188 sys.stderr.write('error: %s not written\n' % outDxcaprun)
José Fonseca8b9f78b2013-04-25 15:22:53 +0100189 sys.exit(1)
190
191
José Fonsecaf3cb6202015-02-08 00:05:35 +0000192def convertFromDxcap(inDxcap, outTrace):
193 dxcapExe = getDxcapExe()
194
195 cmd = [
196 options.apitrace,
197 'trace',
198 '-a', options.api,
199 '-o', outTrace,
200 '--',
201 dxcapExe,
202 '-rawmode',
203 '-p', inDxcap,
204 ]
205
206 callProcess(cmd)
207 verifyTrace(outTrace)
208
209
José Fonseca2cce1922012-12-11 19:51:26 +0000210def main():
211 global options
212
213 # Parse command line options
214 optparser = optparse.OptionParser(
215 usage='\n\t%prog [options] <trace> ...',
216 version='%%prog')
217 optparser.add_option(
José Fonseca8b9f78b2013-04-25 15:22:53 +0100218 '--apitrace', metavar='PROGRAM',
219 type='string', dest='apitrace', default='apitrace.exe',
José Fonsecacd442802013-06-08 14:05:19 +0100220 help='path to apitrace command [default: %default]')
José Fonseca8b9f78b2013-04-25 15:22:53 +0100221 optparser.add_option(
222 '-a', '--api', metavar='API',
José Fonsecaf3cb6202015-02-08 00:05:35 +0000223 type='string', dest='api', default='dxgi',
José Fonseca8b9f78b2013-04-25 15:22:53 +0100224 help='api [default: %default]')
225 optparser.add_option(
José Fonseca2cce1922012-12-11 19:51:26 +0000226 '-r', '--retrace', metavar='PROGRAM',
José Fonseca8b9f78b2013-04-25 15:22:53 +0100227 type='string', dest='retrace', default='d3dretrace.exe',
José Fonsecacd442802013-06-08 14:05:19 +0100228 help='path to retrace command [default: %default]')
José Fonseca2cce1922012-12-11 19:51:26 +0000229 optparser.add_option(
230 '-v', '--verbose',
231 action='store_true', dest='verbose', default=False,
232 help='verbose output')
233 optparser.add_option(
234 '-o', '--output', metavar='FILE',
235 type="string", dest="output",
236 help="output file [default: stdout]")
José Fonseca8b9f78b2013-04-25 15:22:53 +0100237 optparser.add_option(
238 '--verify',
239 action='store_true', dest='verify', default=False,
240 help='verify output by replaying it')
José Fonseca2cce1922012-12-11 19:51:26 +0000241
242 (options, args) = optparser.parse_args(sys.argv[1:])
243 if not args:
244 optparser.error("incorrect number of arguments")
245
José Fonseca8b9f78b2013-04-25 15:22:53 +0100246 for inFile in args:
247 name, inExt = os.path.splitext(os.path.basename(inFile))
José Fonseca8b9f78b2013-04-25 15:22:53 +0100248 if inExt.lower() == '.trace':
José Fonsecaf3cb6202015-02-08 00:05:35 +0000249 convert = convertToDxcap
250 outExt = '.vsglog'
251 if options.output:
252 _, outExt = os.path.splitext(options.output)
253 if outExt.lower() == '.pixrun':
254 convert = convertToPix
255 elif inExt.lower() == '.vsglog':
256 convert = convertFromDxcap
257 outExt = '.trace'
José Fonseca8b9f78b2013-04-25 15:22:53 +0100258 elif inExt.lower() == '.pixrun':
259 convert = convertFromPix
260 outExt = '.trace'
José Fonseca2cce1922012-12-11 19:51:26 +0000261 else:
José Fonseca8b9f78b2013-04-25 15:22:53 +0100262 optparser.error("unexpected file extensions `%s`" % inExt)
263 if options.output:
264 outFile = options.output
265 else:
266 outFile = name + outExt
267 convert(inFile, outFile)
José Fonseca2cce1922012-12-11 19:51:26 +0000268
269
270if __name__ == '__main__':
271 main()