]> git.cworth.org Git - apitrace/blob - retrace/dxgiretrace.py
69bc3bac0966fe27c4cd08a5bacba013dd197ec8
[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 import specs.dxgi
33 from specs.stdapi import API
34 from specs.dxgi import dxgi
35 from specs.d3d10 import d3d10
36 from specs.d3d10_1 import d3d10_1
37 from specs.d3d11 import d3d11
38
39
40 class D3DRetracer(Retracer):
41
42     def retraceApi(self, api):
43         print '// Swizzling mapping for lock addresses'
44         print 'static std::map<void *, void *> _maps;'
45         print
46         print r'''
47 static void 
48 createWindow(DXGI_SWAP_CHAIN_DESC *pSwapChainDesc) {
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         self.table_name = 'd3dretrace::dxgi_callbacks'
58
59         Retracer.retraceApi(self, api)
60
61     createDeviceFunctionNames = [
62         "D3D10CreateDevice",
63         "D3D10CreateDeviceAndSwapChain",
64         "D3D10CreateDevice1",
65         "D3D10CreateDeviceAndSwapChain1",
66         "D3D11CreateDevice",
67         "D3D11CreateDeviceAndSwapChain",
68     ]
69
70     def invokeFunction(self, function):
71         if function.name in self.createDeviceFunctionNames:
72             # create windows as neccessary
73             if 'pSwapChainDesc' in function.argNames():
74                 print r'    createWindow(pSwapChainDesc);'
75
76             # Compensate for the fact we don't trace DXGI object creation
77             if function.name.startswith('D3D11CreateDevice'):
78                 print r'    if (DriverType == D3D_DRIVER_TYPE_UNKNOWN && !pAdapter) {'
79                 print r'        DriverType = D3D_DRIVER_TYPE_HARDWARE;'
80                 print r'    }'
81
82             if function.name.startswith('D3D10CreateDevice'):
83                 # Toggle debugging
84                 print r'    Flags &= ~D3D10_CREATE_DEVICE_DEBUG;'
85                 print r'    if (retrace::debug) {'
86                 print r'        if (LoadLibraryA("d3d10sdklayers")) {'
87                 print r'            Flags |= D3D10_CREATE_DEVICE_DEBUG;'
88                 print r'        }'
89                 print r'    }'
90
91                 # Force driver
92                 self.forceDriver('D3D10_DRIVER_TYPE')
93
94             if function.name.startswith('D3D11CreateDevice'):
95                 # Toggle debugging
96                 print r'    Flags &= ~D3D11_CREATE_DEVICE_DEBUG;'
97                 print r'    if (retrace::debug) {'
98                 print r'        if (LoadLibraryA("d3d11sdklayers")) {'
99                 print r'            Flags |= D3D11_CREATE_DEVICE_DEBUG;'
100                 print r'        }'
101                 print r'    }'
102
103                 # Force driver
104                 self.forceDriver('D3D_DRIVER_TYPE')
105
106         Retracer.invokeFunction(self, function)
107
108     def forceDriver(self, enum):
109         # This can only work when pAdapter is NULL. For non-NULL pAdapter we
110         # need to override inside the EnumAdapters call below
111         print r'    if (pAdapter == NULL) {'
112         print r'        switch (retrace::driver) {'
113         print r'        case retrace::DRIVER_HARDWARE:'
114         print r'            DriverType = %s_HARDWARE;' % enum
115         print r'            Software = NULL;'
116         print r'            break;'
117         print r'        case retrace::DRIVER_SOFTWARE:'
118         print r'            DriverType = %s_WARP;' % enum
119         print r'            Software = NULL;'
120         print r'            break;'
121         print r'        case retrace::DRIVER_REFERENCE:'
122         print r'            DriverType = %s_REFERENCE;' % enum
123         print r'            Software = NULL;'
124         print r'            break;'
125         print r'        case retrace::DRIVER_NULL:'
126         print r'            DriverType = %s_NULL;' % enum
127         print r'            Software = NULL;'
128         print r'            break;'
129         print r'        case retrace::DRIVER_MODULE:'
130         print r'            DriverType = %s_SOFTWARE;' % enum
131         print r'            Software = LoadLibraryA(retrace::driverModule);'
132         print r'            if (!Software) {'
133         print r'                retrace::warning(call) << "failed to load " << retrace::driverModule << "\n";'
134         print r'            }'
135         print r'            break;'
136         print r'        default:'
137         print r'            assert(0);'
138         print r'            /* fall-through */'
139         print r'        case retrace::DRIVER_DEFAULT:'
140         print r'            if (DriverType == %s_SOFTWARE) {' % enum
141         print r'                Software = LoadLibraryA("d3d10warp");'
142         print r'                if (!Software) {'
143         print r'                    retrace::warning(call) << "failed to load d3d10warp.dll\n";'
144         print r'                }'
145         print r'            }'
146         print r'            break;'
147         print r'        }'
148         print r'    } else {'
149         print r'        Software = NULL;'
150         print r'    }'
151
152     def invokeInterfaceMethod(self, interface, method):
153         # keep track of the last used device for state dumping
154         if interface.name in ('ID3D10Device', 'ID3D10Device1'):
155             if method.name == 'Release':
156                 print r'    d3d10Dumper.unbindDevice(_this);'
157             else:
158                 print r'    d3d10Dumper.bindDevice(_this);'
159         if interface.name in ('ID3D11DeviceContext',):
160             if method.name == 'Release':
161                 print r'    d3d11Dumper.unbindDevice(_this);'
162             else:
163                 print r'    d3d11Dumper.bindDevice(_this);'
164
165         if interface.name == 'IDXGIFactory' and method.name == 'QueryInterface':
166             print r'    if (riid == IID_IDXGIFactoryDWM) {'
167             print r'        _this->AddRef();'
168             print r'        *ppvObj = new d3dretrace::CDXGIFactoryDWM(_this);'
169             print r'        _result = S_OK;'
170             print r'    } else {'
171             Retracer.invokeInterfaceMethod(self, interface, method)
172             print r'    }'
173             return
174
175         # create windows as neccessary
176         if method.name == 'CreateSwapChain':
177             print r'    createWindow(pDesc);'
178
179         # notify frame has been completed
180         if method.name == 'Present':
181             print r'    retrace::frameComplete(call);'
182
183         if 'pSharedResource' in method.argNames():
184             print r'    if (pSharedResource) {'
185             print r'        retrace::warning(call) << "shared surfaces unsupported\n";'
186             print r'        pSharedResource = NULL;'
187             print r'    }'
188
189         # Force driver
190         if interface.name.startswith('IDXGIFactory') and method.name == 'EnumAdapters':
191             print r'    const char *szSoftware = NULL;'
192             print r'    switch (retrace::driver) {'
193             print r'    case retrace::DRIVER_REFERENCE:'
194             print r'    case retrace::DRIVER_SOFTWARE:'
195             print r'        szSoftware = "d3d10warp.dll";'
196             print r'        break;'
197             print r'    case retrace::DRIVER_MODULE:'
198             print r'        szSoftware = retrace::driverModule;'
199             print r'        break;'
200             print r'    default:'
201             print r'        break;'
202             print r'    }'
203             print r'    HMODULE hSoftware = NULL;'
204             print r'    if (szSoftware) {'
205             print r'        hSoftware = LoadLibraryA(szSoftware);'
206             print r'        if (!hSoftware) {'
207             print r'            retrace::warning(call) << "failed to load " << szSoftware << "\n";'
208             print r'        }'
209             print r'    }'
210             print r'    if (hSoftware) {'
211             print r'        _result = _this->CreateSoftwareAdapter(hSoftware, ppAdapter);'
212             print r'    } else {'
213             Retracer.invokeInterfaceMethod(self, interface, method)
214             print r'    }'
215             return
216
217         if interface.name.startswith('ID3D10Device') and method.name == 'OpenSharedResource':
218             print r'    retrace::warning(call) << "replacing shared resource with checker pattern\n";'
219             print r'    D3D10_TEXTURE2D_DESC Desc;'
220             print r'    memset(&Desc, 0, sizeof Desc);'
221             print r'    Desc.Width = 8;'
222             print r'    Desc.Height = 8;'
223             print r'    Desc.MipLevels = 1;'
224             print r'    Desc.ArraySize = 1;'
225             print r'    Desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;'
226             print r'    Desc.SampleDesc.Count = 1;'
227             print r'    Desc.SampleDesc.Quality = 0;'
228             print r'    Desc.Usage = D3D10_USAGE_DEFAULT;'
229             print r'    Desc.BindFlags = D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET;'
230             print r'    Desc.CPUAccessFlags = 0x0;'
231             print r'    Desc.MiscFlags = 0 /* D3D10_RESOURCE_MISC_SHARED */;'
232             print r'''
233             const DWORD Checker[8][8] = {
234                { 0, ~0,  0, ~0,  0, ~0,  0, ~0, },
235                {~0,  0, ~0,  0, ~0,  0, ~0,  0, },
236                { 0, ~0,  0, ~0,  0, ~0,  0, ~0, },
237                {~0,  0, ~0,  0, ~0,  0, ~0,  0, },
238                { 0, ~0,  0, ~0,  0, ~0,  0, ~0, },
239                {~0,  0, ~0,  0, ~0,  0, ~0,  0, },
240                { 0, ~0,  0, ~0,  0, ~0,  0, ~0, },
241                {~0,  0, ~0,  0, ~0,  0, ~0,  0, }
242             };
243             const D3D10_SUBRESOURCE_DATA InitialData = {Checker, sizeof Checker[0], sizeof Checker};
244             '''
245             print r'    _result = _this->CreateTexture2D(&Desc, &InitialData, (ID3D10Texture2D**)ppResource);'
246             self.checkResult(method.type)
247         else:
248             Retracer.invokeInterfaceMethod(self, interface, method)
249
250         # process events after presents
251         if method.name == 'Present':
252             print r'    d3dretrace::processEvents();'
253
254         if method.name == 'Map':
255             print '    VOID *_pbData = NULL;'
256             print '    size_t _MappedSize = 0;'
257             print '    _getMapInfo(_this, %s, _pbData, _MappedSize);' % ', '.join(method.argNames())
258             print '    if (_MappedSize) {'
259             print '        _maps[_this] = _pbData;'
260             print '    } else {'
261             print '        return;'
262             print '    }'
263         
264         if method.name == 'Unmap':
265             print '    VOID *_pbData = 0;'
266             print '    _pbData = _maps[_this];'
267             print '    if (_pbData) {'
268             print '        retrace::delRegionByPointer(_pbData);'
269             print '        _maps[_this] = 0;'
270             print '    }'
271
272         # Attach shader byte code for lookup
273         if 'pShaderBytecode' in method.argNames():
274             ppShader = method.args[-1]
275             assert ppShader.output
276             print r'    if (retrace::dumpingState && SUCCEEDED(_result)) {'
277             print r'        (*%s)->SetPrivateData(d3dstate::GUID_D3DSTATE, BytecodeLength, pShaderBytecode);' % ppShader.name
278             print r'    }'
279
280
281 def main():
282     print r'#define INITGUID'
283     print
284     print r'#include <string.h>'
285     print
286     print r'#include <iostream>'
287     print
288     print r'#include "d3dretrace.hpp"'
289     print
290
291     moduleNames = sys.argv[1:]
292
293     api = API()
294     
295     if moduleNames:
296         print r'#include "d3dretrace_dxgi.hpp"'
297         api.addModule(dxgi)
298     
299     if 'd3d10' in moduleNames:
300         if 'd3d10_1' in moduleNames:
301             print r'#include "d3d10_1imports.hpp"'
302             api.addModule(d3d10_1)
303         else:
304             print r'#include "d3d10imports.hpp"'
305         print r'#include "d3d10size.hpp"'
306         api.addModule(d3d10)
307         print
308         print '''static d3dretrace::D3DDumper<ID3D10Device> d3d10Dumper;'''
309         print
310
311     if 'd3d11' in moduleNames:
312         print r'#include "d3d11imports.hpp"'
313         if 'd3d11_1' in moduleNames:
314             print '#include <d3d11_1.h>'
315             import specs.d3d11_1
316         print r'#include "d3d11size.hpp"'
317         print r'#include "d3dstate.hpp"'
318         api.addModule(d3d11)
319         
320         print
321         print '''static d3dretrace::D3DDumper<ID3D11DeviceContext> d3d11Dumper;'''
322         print
323
324     retracer = D3DRetracer()
325     retracer.retraceApi(api)
326
327
328 if __name__ == '__main__':
329     main()