]> git.cworth.org Git - apitrace/blob - retrace/dxgiretrace.py
8de3c989efa5f46057c6b04c19cbee22665af4f0
[apitrace] / retrace / dxgiretrace.py
1 ##########################################################################
2 #
3 # Copyright 2011 Jose Fonseca
4 # All Rights Reserved.
5 #
6 # Permission is hereby granted, free of charge, to any person obtaining a copy
7 # of this software and associated documentation files (the "Software"), to deal
8 # in the Software without restriction, including without limitation the rights
9 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 # copies of the Software, and to permit persons to whom the Software is
11 # furnished to do so, subject to the following conditions:
12 #
13 # The above copyright notice and this permission notice shall be included in
14 # all copies or substantial portions of the Software.
15 #
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 # THE SOFTWARE.
23 #
24 ##########################################################################/
25
26
27 """D3D retracer generator."""
28
29
30 import sys
31 from dllretrace import DllRetracer as Retracer
32 from specs.stdapi import API
33 from specs.dxgi import dxgi
34 from specs.d3d10 import d3d10
35 from specs.d3d10_1 import d3d10_1
36 from specs.d3d11 import d3d11
37
38
39 class D3DRetracer(Retracer):
40
41     def retraceApi(self, api):
42         print '// Swizzling mapping for lock addresses'
43         print 'static std::map<void *, void *> _maps;'
44         print
45         print r'''
46 static void 
47 createWindow(DXGI_SWAP_CHAIN_DESC *pSwapChainDesc) {
48     if (pSwapChainDesc->Windowed) {
49         UINT Width  = pSwapChainDesc->BufferDesc.Width;
50         UINT Height = pSwapChainDesc->BufferDesc.Height;
51         if (!Width)  Width = 1024;
52         if (!Height) Height = 768;
53         pSwapChainDesc->OutputWindow = d3dretrace::createWindow(Width, Height);
54     }
55 }
56 '''
57
58         self.table_name = 'd3dretrace::dxgi_callbacks'
59
60         Retracer.retraceApi(self, api)
61
62     createDeviceFunctionNames = [
63         "D3D10CreateDevice",
64         "D3D10CreateDeviceAndSwapChain",
65         "D3D10CreateDevice1",
66         "D3D10CreateDeviceAndSwapChain1",
67         "D3D11CreateDevice",
68         "D3D11CreateDeviceAndSwapChain",
69     ]
70
71     def invokeFunction(self, function):
72         if function.name in self.createDeviceFunctionNames:
73             # create windows as neccessary
74             if 'pSwapChainDesc' in function.argNames():
75                 print r'    createWindow(pSwapChainDesc);'
76
77             # Compensate for the fact we don't trace DXGI object creation
78             if function.name.startswith('D3D11CreateDevice'):
79                 print r'    if (DriverType == D3D_DRIVER_TYPE_UNKNOWN && !pAdapter) {'
80                 print r'        DriverType = D3D_DRIVER_TYPE_HARDWARE;'
81                 print r'    }'
82
83             if function.name.startswith('D3D10CreateDevice'):
84                 # Toggle debugging
85                 print r'    Flags &= ~D3D10_CREATE_DEVICE_DEBUG;'
86                 print r'    if (retrace::debug) {'
87                 print r'        if (LoadLibraryA("d3d10sdklayers")) {'
88                 print r'            Flags |= D3D10_CREATE_DEVICE_DEBUG;'
89                 print r'        }'
90                 print r'    }'
91
92                 # Force driver
93                 self.forceDriver('D3D10_DRIVER_TYPE')
94
95             if function.name.startswith('D3D11CreateDevice'):
96                 # Toggle debugging
97                 print r'    Flags &= ~D3D11_CREATE_DEVICE_DEBUG;'
98                 print r'    if (retrace::debug) {'
99                 print r'        if (LoadLibraryA("d3d11sdklayers")) {'
100                 print r'            Flags |= D3D11_CREATE_DEVICE_DEBUG;'
101                 print r'        }'
102                 print r'    }'
103
104                 # Force driver
105                 self.forceDriver('D3D_DRIVER_TYPE')
106
107         Retracer.invokeFunction(self, function)
108
109     def forceDriver(self, enum):
110         # This can only work when pAdapter is NULL. For non-NULL pAdapter we
111         # need to override inside the EnumAdapters call below
112         print r'    if (pAdapter == NULL) {'
113         print r'        switch (retrace::driver) {'
114         print r'        case retrace::DRIVER_HARDWARE:'
115         print r'            DriverType = %s_HARDWARE;' % enum
116         print r'            Software = NULL;'
117         print r'            break;'
118         print r'        case retrace::DRIVER_SOFTWARE:'
119         print r'            DriverType = %s_WARP;' % enum
120         print r'            Software = NULL;'
121         print r'            break;'
122         print r'        case retrace::DRIVER_REFERENCE:'
123         print r'            DriverType = %s_REFERENCE;' % enum
124         print r'            Software = NULL;'
125         print r'            break;'
126         print r'        case retrace::DRIVER_NULL:'
127         print r'            DriverType = %s_NULL;' % enum
128         print r'            Software = NULL;'
129         print r'            break;'
130         print r'        case retrace::DRIVER_MODULE:'
131         print r'            DriverType = %s_SOFTWARE;' % enum
132         print r'            Software = LoadLibraryA(retrace::driverModule);'
133         print r'            if (!Software) {'
134         print r'                retrace::warning(call) << "failed to load " << retrace::driverModule << "\n";'
135         print r'            }'
136         print r'            break;'
137         print r'        default:'
138         print r'            assert(0);'
139         print r'            /* fall-through */'
140         print r'        case retrace::DRIVER_DEFAULT:'
141         print r'            if (DriverType == %s_SOFTWARE) {' % enum
142         print r'                Software = LoadLibraryA("d3d10warp");'
143         print r'                if (!Software) {'
144         print r'                    retrace::warning(call) << "failed to load d3d10warp.dll\n";'
145         print r'                }'
146         print r'            }'
147         print r'            break;'
148         print r'        }'
149         print r'    } else {'
150         print r'        Software = NULL;'
151         print r'    }'
152
153     def invokeInterfaceMethod(self, interface, method):
154         # keep track of the last used device for state dumping
155         if interface.name in ('ID3D10Device', 'ID3D10Device1'):
156             if method.name == 'Release':
157                 print r'    d3d10Dumper.unbindDevice(_this);'
158             else:
159                 print r'    d3d10Dumper.bindDevice(_this);'
160         if interface.name in ('ID3D11DeviceContext',):
161             if method.name == 'Release':
162                 print r'    d3d11Dumper.unbindDevice(_this);'
163             else:
164                 print r'    d3d11Dumper.bindDevice(_this);'
165
166         # create windows as neccessary
167         if method.name == 'CreateSwapChain':
168             print r'    createWindow(pDesc);'
169
170         # notify frame has been completed
171         if method.name == 'Present':
172             print r'    retrace::frameComplete(call);'
173
174         if 'pSharedResource' in method.argNames():
175             print r'    if (pSharedResource) {'
176             print r'        retrace::warning(call) << "shared surfaces unsupported\n";'
177             print r'        pSharedResource = NULL;'
178             print r'    }'
179
180         # Force driver
181         if interface.name.startswith('IDXGIFactory') and method.name == 'EnumAdapters':
182             print r'    const char *szSoftware = NULL;'
183             print r'    switch (retrace::driver) {'
184             print r'    case retrace::DRIVER_REFERENCE:'
185             print r'    case retrace::DRIVER_SOFTWARE:'
186             print r'        szSoftware = "d3d10warp.dll";'
187             print r'        break;'
188             print r'    case retrace::DRIVER_MODULE:'
189             print r'        szSoftware = retrace::driverModule;'
190             print r'        break;'
191             print r'    default:'
192             print r'        break;'
193             print r'    }'
194             print r'    HMODULE hSoftware = NULL;'
195             print r'    if (szSoftware) {'
196             print r'        hSoftware = LoadLibraryA(szSoftware);'
197             print r'        if (!hSoftware) {'
198             print r'            retrace::warning(call) << "failed to load " << szSoftware << "\n";'
199             print r'        }'
200             print r'    }'
201             print r'    if (hSoftware) {'
202             print r'        _result = _this->CreateSoftwareAdapter(hSoftware, ppAdapter);'
203             print r'    } else {'
204             Retracer.invokeInterfaceMethod(self, interface, method)
205             print r'    }'
206             return
207
208         Retracer.invokeInterfaceMethod(self, interface, method)
209
210         # process events after presents
211         if method.name == 'Present':
212             print r'    d3dretrace::processEvents();'
213
214         if method.name == 'Map':
215             print '    VOID *_pbData = NULL;'
216             print '    size_t _MappedSize = 0;'
217             print '    _getMapInfo(_this, %s, _pbData, _MappedSize);' % ', '.join(method.argNames())
218             print '    if (_MappedSize) {'
219             print '        _maps[_this] = _pbData;'
220             print '    } else {'
221             print '        return;'
222             print '    }'
223         
224         if method.name == 'Unmap':
225             print '    VOID *_pbData = 0;'
226             print '    _pbData = _maps[_this];'
227             print '    if (_pbData) {'
228             print '        retrace::delRegionByPointer(_pbData);'
229             print '        _maps[_this] = 0;'
230             print '    }'
231
232         # Attach shader byte code for lookup
233         if 'pShaderBytecode' in method.argNames():
234             ppShader = method.args[-1]
235             assert ppShader.output
236             print r'    if (retrace::dumpingState && SUCCEEDED(_result)) {'
237             print r'        (*%s)->SetPrivateData(d3dstate::GUID_D3DSTATE, BytecodeLength, pShaderBytecode);' % ppShader.name
238             print r'    }'
239
240
241 def main():
242     print r'#include <string.h>'
243     print
244     print r'#include <iostream>'
245     print
246     print r'#include "d3dretrace.hpp"'
247     print
248
249     moduleNames = sys.argv[1:]
250
251     api = API()
252     
253     if moduleNames:
254         api.addModule(dxgi)
255     
256     if 'd3d10' in moduleNames:
257         if 'd3d10_1' in moduleNames:
258             print r'#include "d3d10_1imports.hpp"'
259             api.addModule(d3d10_1)
260         else:
261             print r'#include "d3d10imports.hpp"'
262         print r'#include "d3d10size.hpp"'
263         api.addModule(d3d10)
264         print
265         print '''static d3dretrace::D3DDumper<ID3D10Device> d3d10Dumper;'''
266         print
267
268     if 'd3d11' in moduleNames:
269         print r'#include "d3d11imports.hpp"'
270         if 'd3d11_1' in moduleNames:
271             print '#include <d3d11_1.h>'
272             import specs.d3d11_1
273         print r'#include "d3d11size.hpp"'
274         print r'#include "d3dstate.hpp"'
275         api.addModule(d3d11)
276         
277         print
278         print '''static d3dretrace::D3DDumper<ID3D11DeviceContext> d3d11Dumper;'''
279         print
280
281     retracer = D3DRetracer()
282     retracer.retraceApi(api)
283
284
285 if __name__ == '__main__':
286     main()