def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('IDirect3DDevice9', 'IDirect3DDevice9Ex'): print r' d3dretrace::pLastDirect3DDevice9 = _this;' # create windows as neccessary if method.name in ('CreateDevice', 'CreateDeviceEx', 'CreateAdditionalSwapChain'): print r' HWND hWnd = d3dretrace::createWindow(pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);' print r' pPresentationParameters->hDeviceWindow = hWnd;' if 'hFocusWindow' in method.argNames(): print r' hFocusWindow = hWnd;' if method.name in ('Reset', 'ResetEx'): print r' if (pPresentationParameters->Windowed) {' print r' d3dretrace::resizeWindow(pPresentationParameters->hDeviceWindow, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);' print r' }' # notify frame has been completed if method.name == 'Present': print r' retrace::frameComplete(call);' print r' hDestWindowOverride = NULL;' if 'pSharedHandle' in method.argNames(): print r' if (pSharedHandle) {' print r' retrace::warning(call) << "shared surfaces unsupported\n";' print r' pSharedHandle = NULL;' print r' }' Retracer.invokeInterfaceMethod(self, interface, method) # process events after presents if method.name == 'Present': print r' d3dretrace::processEvents();' # check errors if str(method.type) == 'HRESULT': print r' if (FAILED(_result)) {' print r' retrace::warning(call) << "failed\n";' print r' }' if method.name in ('Lock', 'LockRect', 'LockBox'): print ' VOID *_pbData = NULL;' print ' size_t _LockedSize = 0;' print ' _getLockInfo(_this, %s, _pbData, _LockedSize);' % ', '.join(method.argNames()[:-1]) print ' _this->SetPrivateData(GUID_D3DRETRACE, &_pbData, sizeof _pbData, 0);' if method.name in ('Unlock', 'UnlockRect', 'UnlockBox'): print ' VOID *_pbData = 0;' print ' DWORD dwSizeOfData = sizeof _pbData;' print ' _this->GetPrivateData(GUID_D3DRETRACE, &_pbData, &dwSizeOfData);' print ' if (_pbData) {' print ' retrace::delRegionByPointer(_pbData);' print ' }'
def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('IDirect3DDevice9', 'IDirect3DDevice9Ex'): print r' d3dretrace::pLastDirect3DDevice9 = _this;' # create windows as neccessary if method.name in ('CreateDevice', 'CreateDeviceEx', 'CreateAdditionalSwapChain'): print r' HWND hWnd = d3dretrace::createWindow(pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);' print r' pPresentationParameters->hDeviceWindow = hWnd;' if 'hFocusWindow' in method.argNames(): print r' hFocusWindow = hWnd;' # notify frame has been completed if method.name == 'Present': print r' retrace::frameComplete(call);' print r' hDestWindowOverride = NULL;' if 'pSharedHandle' in method.argNames(): print r' if (pSharedHandle) {' print r' retrace::warning(call) << "shared surfaces unsupported\n";' print r' pSharedHandle = NULL;' print r' }' Retracer.invokeInterfaceMethod(self, interface, method) # check errors if str(method.type) == 'HRESULT': print r' if (FAILED(_result)) {' print r' retrace::warning(call) << "failed\n";' print r' }' if method.name in ('Lock', 'LockRect', 'LockBox'): print ' VOID *_pbData = NULL;' print ' size_t _LockedSize = 0;' print ' _getLockInfo(_this, %s, _pbData, _LockedSize);' % ', '.join( method.argNames()[:-1]) print ' _this->SetPrivateData(GUID_D3DRETRACE, &_pbData, sizeof _pbData, 0);' if method.name in ('Unlock', 'UnlockRect', 'UnlockBox'): print ' VOID *_pbData = 0;' print ' DWORD dwSizeOfData = sizeof _pbData;' print ' _this->GetPrivateData(GUID_D3DRETRACE, &_pbData, &dwSizeOfData);' print ' if (_pbData) {' print ' retrace::delRegionByPointer(_pbData);' print ' }'
def invokeInterfaceMethod(self, interface, method): if interface.name == 'IDirect3D9' and method.name == 'CreateDevice': print 'HWND hWnd = createWindow(pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);' print 'pPresentationParameters->hDeviceWindow = hWnd;' print 'hFocusWindow = hWnd;' Retracer.invokeInterfaceMethod(self, interface, method) if str(method.type) == 'HRESULT': print r' if (__result != S_OK) {' print r' retrace::warning(call) << "failed\n";' print r' }' if interface.name == 'IDirect3DVertexBuffer9' and method.name == 'Lock': print ' if (!SizeToLock) {' print ' D3DVERTEXBUFFER_DESC Desc;' print ' _this->GetDesc(&Desc);' print ' SizeToLock = Desc.Size;' print ' }'
def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('ID3D10Device', 'ID3D10Device1'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d10Dumper.unbindDevice(_this);' print r' }' else: print r' d3d10Dumper.bindDevice(_this);' if interface.name.startswith('ID3D11DeviceContext'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d11Dumper.unbindDevice(_this);' print r' }' else: print r' d3d11Dumper.bindDevice(_this);' # intercept private interfaces if method.name == 'QueryInterface': print r' if (!d3dretrace::overrideQueryInterface(_this, riid, ppvObj, &_result)) {' Retracer.invokeInterfaceMethod(self, interface, method) print r' }' return # create windows as neccessary if method.name == 'CreateSwapChain': print r' d3dretrace::createWindowForSwapChain(pDesc);' if method.name == 'CreateSwapChainForHwnd': print r' WindowHandle = d3dretrace::createWindow(pDesc->Width, pDesc->Height);' print r' // DXGI_SCALING_NONE is only supported on Win8 and beyond' print r' if (pDesc->Scaling == DXGI_SCALING_NONE && !IsWindows8OrGreater()) {' print r' pDesc->Scaling = DXGI_SCALING_STRETCH;' print r' }' if method.name == 'CreateSwapChainForComposition': print r' HWND hWnd = d3dretrace::createWindow(pDesc->Width, pDesc->Height);' print r' _result = _this->CreateSwapChainForHwnd(pDevice, hWnd, pDesc, NULL, pRestrictToOutput, ppSwapChain);' self.checkResult(interface, method) return if method.name == 'CreateTargetForHwnd': print r' hwnd = d3dretrace::createWindow(1024, 768);' if method.name == 'SetFullscreenState': print r' if (retrace::forceWindowed) {' print r' Fullscreen = FALSE;' print r' pTarget = NULL;' print r' }' # notify frame has been completed if interface.name.startswith( 'IDXGISwapChain') and method.name.startswith('Present'): if interface.name.startswith('IDXGISwapChainDWM'): print r' com_ptr<IDXGISwapChain> pSwapChain;' print r' if (SUCCEEDED(_this->QueryInterface(IID_IDXGISwapChain, (void **) &pSwapChain))) {' print r' dxgiDumper.bindDevice(pSwapChain);' print r' } else {' print r' assert(0);' print r' }' else: print r' dxgiDumper.bindDevice(_this);' print r' retrace::frameComplete(call);' if 'pSharedResource' in method.argNames(): print r' if (pSharedResource) {' print r' retrace::warning(call) << "shared surfaces unsupported\n";' print r' pSharedResource = NULL;' print r' }' # Force driver if interface.name.startswith( 'IDXGIFactory') and method.name.startswith('EnumAdapters'): print r' const char *szSoftware = NULL;' print r' switch (retrace::driver) {' print r' case retrace::DRIVER_REFERENCE:' print r' case retrace::DRIVER_SOFTWARE:' print r' szSoftware = "d3d10warp.dll";' print r' break;' print r' case retrace::DRIVER_MODULE:' print r' szSoftware = retrace::driverModule;' print r' break;' print r' default:' print r' break;' print r' }' print r' HMODULE hSoftware = NULL;' print r' if (szSoftware) {' print r' hSoftware = LoadLibraryA(szSoftware);' print r' if (!hSoftware) {' print r' retrace::warning(call) << "failed to load " << szSoftware << "\n";' print r' }' print r' }' print r' if (hSoftware) {' print r' _result = _this->CreateSoftwareAdapter(hSoftware, reinterpret_cast<IDXGIAdapter **>(ppAdapter));' print r' } else {' Retracer.invokeInterfaceMethod(self, interface, method) print r' }' return if interface.name.startswith( 'ID3D10Device') and method.name.startswith( 'OpenSharedResource'): print r' retrace::warning(call) << "replacing shared resource with checker pattern\n";' print r' _result = d3dretrace::createSharedResource(_this, ReturnedInterface, ppResource);' self.checkResult(interface, method) return if interface.name.startswith( 'ID3D11Device') and method.name == 'OpenSharedResource': # Some applications (e.g., video playing in IE11) create shared resources within the same process. # TODO: Generalize to other OpenSharedResource variants print r' retrace::map<HANDLE>::const_iterator it = _shared_handle_map.find(hResource);' print r' if (it == _shared_handle_map.end()) {' print r' retrace::warning(call) << "replacing shared resource with checker pattern\n";' print r' _result = d3dretrace::createSharedResource(_this, ReturnedInterface, ppResource);' self.checkResult(interface, method) print r' } else {' print r' hResource = it->second;' Retracer.invokeInterfaceMethod(self, interface, method) print r' }' return if interface.name.startswith( 'ID3D11Device') and method.name.startswith( 'OpenSharedResource'): print r' retrace::warning(call) << "replacing shared resource with checker pattern\n";' print r' _result = d3dretrace::createSharedResource(_this, ReturnedInterface, ppResource);' if method.name == 'OpenSharedResourceByName': print r' (void)lpName;' print r' (void)dwDesiredAccess;' else: print r' (void)hResource;' self.checkResult(interface, method) return if method.name == 'Map': # Reset _DO_NOT_WAIT flags. Otherwise they may fail, and we have no # way to cope with it (other than retry). mapFlagsArg = method.getArgByName('MapFlags') for flag in mapFlagsArg.type.values: if flag.endswith('_MAP_FLAG_DO_NOT_WAIT'): print r' MapFlags &= ~%s;' % flag if method.name.startswith('UpdateSubresource'): # The D3D10 debug layer is buggy (or at least inconsistent with the # runtime), as it seems to estimate and enforce the data size based on the # SrcDepthPitch, even for non 3D textures, but in some traces # SrcDepthPitch is garbagge for non 3D textures. # XXX: It also seems to expect padding bytes at the end of the last # row, but we never record (or allocate) those... print r' if (retrace::debug && pDstBox && pDstBox->front == 0 && pDstBox->back == 1) {' print r' SrcDepthPitch = 0;' print r' }' if method.name == 'SetGammaControl': # This method is only supported while in full-screen mode print r' if (retrace::forceWindowed) {' print r' return;' print r' }' if method.name == 'GetData': print r' pData = _allocator.alloc(DataSize);' print r' do {' self.doInvokeInterfaceMethod(interface, method) print r' GetDataFlags = 0; // Prevent infinite loop' print r' } while (_result == S_FALSE);' self.checkResult(interface, method) print r' return;' Retracer.invokeInterfaceMethod(self, interface, method) if method.name in ('AcquireSync', 'ReleaseSync'): print r' if (SUCCEEDED(_result) && _result != S_OK) {' print r' retrace::warning(call) << " returned " << _result << "\n";' print r' }' # process events after presents if interface.name.startswith( 'IDXGISwapChain') and method.name.startswith('Present'): print r' d3dretrace::processEvents();' if method.name in ('Map', 'Unmap'): if interface.name.startswith('ID3D11DeviceContext'): print ' void * & _pbData = g_Maps[_this][SubresourceKey(pResource, Subresource)];' else: subresourceArg = method.getArgByName('Subresource') if subresourceArg is None: print ' UINT Subresource = 0;' print ' void * & _pbData = g_Maps[0][SubresourceKey(_this, Subresource)];' if method.name == 'Map': print ' _MAP_DESC _MapDesc;' print ' _getMapDesc(_this, %s, _MapDesc);' % ', '.join( method.argNames()) print ' size_t _MappedSize = _MapDesc.Size;' print ' if (_MapDesc.Size) {' print ' _pbData = _MapDesc.pData;' if interface.name.startswith('ID3D11DeviceContext'): # Prevent false warnings on 1D and 2D resources, since the # pitches are often junk there... print ' _normalizeMap(pResource, pMappedResource);' else: print ' _pbData = _MapDesc.pData;' print ' } else {' print ' return;' print ' }' if method.name == 'Unmap': print ' if (_pbData) {' print ' retrace::delRegionByPointer(_pbData);' print ' _pbData = 0;' print ' }' if interface.name.startswith('ID3D11VideoContext'): if method.name == 'GetDecoderBuffer': print ' if (*ppBuffer && *pBufferSize) {' print ' g_Maps[nullptr][SubresourceKey(_this, Type)] = *ppBuffer;' print ' }' if method.name == 'ReleaseDecoderBuffer': print ' SubresourceKey _mappingKey(_this, Type);' print ' void *_pBuffer = g_Maps[nullptr][_mappingKey];' print ' if (_pBuffer) {' print ' retrace::delRegionByPointer(_pBuffer);' print ' g_Maps[nullptr][_mappingKey] = 0;' print ' }' # Attach shader byte code for lookup if 'pShaderBytecode' in method.argNames(): ppShader = method.args[-1] assert ppShader.output print r' if (retrace::dumpingState && SUCCEEDED(_result)) {' print r' (*%s)->SetPrivateData(d3dstate::GUID_D3DSTATE, BytecodeLength, pShaderBytecode);' % ppShader.name print r' }'
def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('ID3D10Device', 'ID3D10Device1'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d10Dumper.unbindDevice(_this);' print r' }' else: print r' d3d10Dumper.bindDevice(_this);' if interface.name in ('ID3D11DeviceContext', 'ID3D11DeviceContext1'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d11Dumper.unbindDevice(_this);' print r' }' else: print r' if (_this->GetType() == D3D11_DEVICE_CONTEXT_IMMEDIATE) {' print r' d3d11Dumper.bindDevice(_this);' print r' }' if interface.name == 'IDXGIFactory' and method.name == 'QueryInterface': print r' if (riid == IID_IDXGIFactoryDWM) {' print r' _this->AddRef();' print r' *ppvObj = new d3dretrace::CDXGIFactoryDWM(_this);' print r' _result = S_OK;' print r' } else {' Retracer.invokeInterfaceMethod(self, interface, method) print r' }' return # create windows as neccessary if method.name == 'CreateSwapChain': print r' createWindow(pDesc);' # notify frame has been completed if method.name == 'Present': if interface.name == 'IDXGISwapChainDWM': print r' dxgiDumper.bindDevice(reinterpret_cast<d3dretrace::CDXGISwapChainDWM *>(_this)->m_pSwapChain);' else: print r' dxgiDumper.bindDevice(_this);' print r' retrace::frameComplete(call);' if 'pSharedResource' in method.argNames(): print r' if (pSharedResource) {' print r' retrace::warning(call) << "shared surfaces unsupported\n";' print r' pSharedResource = NULL;' print r' }' # Force driver if interface.name.startswith( 'IDXGIFactory') and method.name.startswith('EnumAdapters'): print r' const char *szSoftware = NULL;' print r' switch (retrace::driver) {' print r' case retrace::DRIVER_REFERENCE:' print r' case retrace::DRIVER_SOFTWARE:' print r' szSoftware = "d3d10warp.dll";' print r' break;' print r' case retrace::DRIVER_MODULE:' print r' szSoftware = retrace::driverModule;' print r' break;' print r' default:' print r' break;' print r' }' print r' HMODULE hSoftware = NULL;' print r' if (szSoftware) {' print r' hSoftware = LoadLibraryA(szSoftware);' print r' if (!hSoftware) {' print r' retrace::warning(call) << "failed to load " << szSoftware << "\n";' print r' }' print r' }' print r' if (hSoftware) {' print r' _result = _this->CreateSoftwareAdapter(hSoftware, reinterpret_cast<IDXGIAdapter **>(ppAdapter));' print r' } else {' Retracer.invokeInterfaceMethod(self, interface, method) print r' }' return if interface.name.startswith( 'ID3D10Device') and method.name == 'OpenSharedResource': print r' retrace::warning(call) << "replacing shared resource with checker pattern\n";' print r' D3D10_TEXTURE2D_DESC Desc;' print r' memset(&Desc, 0, sizeof Desc);' print r' Desc.Width = 8;' print r' Desc.Height = 8;' print r' Desc.MipLevels = 1;' print r' Desc.ArraySize = 1;' print r' Desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;' print r' Desc.SampleDesc.Count = 1;' print r' Desc.SampleDesc.Quality = 0;' print r' Desc.Usage = D3D10_USAGE_DEFAULT;' print r' Desc.BindFlags = D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET;' print r' Desc.CPUAccessFlags = 0x0;' print r' Desc.MiscFlags = 0 /* D3D10_RESOURCE_MISC_SHARED */;' print r''' static const DWORD Checker[8][8] = { { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U }, {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U }, { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U }, {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U }, { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U }, {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U }, { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U }, {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U } }; static const D3D10_SUBRESOURCE_DATA InitialData = {Checker, sizeof Checker[0], sizeof Checker}; ''' print r' _result = _this->CreateTexture2D(&Desc, &InitialData, (ID3D10Texture2D**)ppResource);' self.checkResult(method.type) return if method.name == 'Map': # Reset _DO_NOT_WAIT flags. Otherwise they may fail, and we have no # way to cope with it (other than retry). mapFlagsArg = method.getArgByName('MapFlags') for flag in mapFlagsArg.type.values: if flag.endswith('_MAP_FLAG_DO_NOT_WAIT'): print r' MapFlags &= ~%s;' % flag if method.name == 'UpdateSubresource': # The D3D10 debug layer is buggy (or at least inconsistent with the # runtime), as it seems to estimate and enforce the data size based on the # SrcDepthPitch, even for non 3D textures, but in some traces # SrcDepthPitch is garbagge for non 3D textures. # XXX: It also seems to expect padding bytes at the end of the last # row, but we never record (or allocate) those... print r' if (retrace::debug && pDstBox && pDstBox->front == 0 && pDstBox->back == 1) {' print r' SrcDepthPitch = 0;' print r' }' Retracer.invokeInterfaceMethod(self, interface, method) # process events after presents if method.name == 'Present': print r' d3dretrace::processEvents();' if method.name == 'Map': print ' _MAP_DESC _MapDesc;' print ' _getMapDesc(_this, %s, _MapDesc);' % ', '.join( method.argNames()) print ' size_t _MappedSize = _MapDesc.Size;' print ' if (_MapDesc.Size) {' if interface.name.startswith('ID3D11DeviceContext'): print ' _maps[pResource] = _MapDesc.pData;' else: print ' _maps[_this] = _MapDesc.pData;' print ' } else {' print ' return;' print ' }' if method.name == 'Unmap': if interface.name.startswith('ID3D11DeviceContext'): print ' VOID *_pbData = 0;' print ' _pbData = _maps[pResource];' print ' if (_pbData) {' print ' retrace::delRegionByPointer(_pbData);' print ' _maps[pResource] = 0;' print ' }' else: print ' VOID *_pbData = 0;' print ' _pbData = _maps[_this];' print ' if (_pbData) {' print ' retrace::delRegionByPointer(_pbData);' print ' _maps[_this] = 0;' print ' }' # Attach shader byte code for lookup if 'pShaderBytecode' in method.argNames(): ppShader = method.args[-1] assert ppShader.output print r' if (retrace::dumpingState && SUCCEEDED(_result)) {' print r' (*%s)->SetPrivateData(d3dstate::GUID_D3DSTATE, BytecodeLength, pShaderBytecode);' % ppShader.name print r' }'
def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('IDirect3DDevice9', 'IDirect3DDevice9Ex'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d9Dumper.unbindDevice(_this);' print r' }' else: print r' d3d9Dumper.bindDevice(_this);' if interface.name in ('IDirect3DDevice8', 'IDirect3DDevice8Ex'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d8Dumper.unbindDevice(_this);' print r' }' else: print r' d3d8Dumper.bindDevice(_this);' # create windows as neccessary if method.name in ('CreateDevice', 'CreateDeviceEx', 'CreateAdditionalSwapChain'): print r' HWND hWnd = d3dretrace::createWindow(pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);' print r' pPresentationParameters->hDeviceWindow = hWnd;' if 'hFocusWindow' in method.argNames(): print r' hFocusWindow = hWnd;' # force windowed mode print r' if (retrace::forceWindowed) {' print r' pPresentationParameters->Windowed = TRUE;' print r' pPresentationParameters->FullScreen_RefreshRateInHz = 0;' print r' }' if method.name in self.createDeviceMethodNames: # override the device type print r' switch (retrace::driver) {' print r' case retrace::DRIVER_HARDWARE:' print r' DeviceType = D3DDEVTYPE_HAL;' print r' break;' print r' case retrace::DRIVER_SOFTWARE:' print r' case retrace::DRIVER_REFERENCE:' print r' DeviceType = D3DDEVTYPE_REF;' print r' break;' print r' case retrace::DRIVER_NULL:' if interface.name.startswith('IDirect3D9'): print r' DeviceType = D3DDEVTYPE_NULLREF;' else: print r' retrace::warning(call) << "null driver not supported\n";' print r' break;' print r' case retrace::DRIVER_MODULE:' print r' retrace::warning(call) << "driver module not supported\n";' print r' break;' print r' default:' print r' assert(0);' print r' /* fall-through */' print r' case retrace::DRIVER_DEFAULT:' print r' break;' print r' }' if method.name in ('Reset', 'ResetEx'): # force windowed mode print r' if (retrace::forceWindowed) {' print r' pPresentationParameters->Windowed = TRUE;' print r' pPresentationParameters->FullScreen_RefreshRateInHz = 0;' print r' }' # resize window print r' if (pPresentationParameters->Windowed) {' print r' d3dretrace::resizeWindow(pPresentationParameters->hDeviceWindow, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);' print r' }' # notify frame has been completed if method.name in ('Present', 'PresentEx'): print r' retrace::frameComplete(call);' print r' hDestWindowOverride = NULL;' if 'pSharedHandle' in method.argNames(): print r' if (pSharedHandle) {' print r' retrace::warning(call) << "shared surfaces unsupported\n";' print r' pSharedHandle = NULL;' print r' }' Retracer.invokeInterfaceMethod(self, interface, method) if method.name in self.createDeviceMethodNames: print r' if (FAILED(_result)) {' print r' exit(1);' print r' }' # process events after presents if method.name == 'Present': print r' d3dretrace::processEvents();' if method.name in ('Lock', 'LockRect', 'LockBox'): print ' VOID *_pbData = NULL;' print ' size_t _MappedSize = 0;' print ' _getMapInfo(_this, %s, _pbData, _MappedSize);' % ', '.join( method.argNames()[:-1]) print ' if (_MappedSize) {' print ' _maps[_this] = _pbData;' print ' } else {' print ' return;' print ' }' if method.name in ('Unlock', 'UnlockRect', 'UnlockBox'): print ' VOID *_pbData = 0;' print ' _pbData = _maps[_this];' print ' if (_pbData) {' print ' retrace::delRegionByPointer(_pbData);' print ' _maps[_this] = 0;' print ' }'
def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('ID3D10Device', 'ID3D10Device1'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d10Dumper.unbindDevice(_this);' print r' }' else: print r' d3d10Dumper.bindDevice(_this);' if interface.name.startswith('ID3D11DeviceContext'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d11Dumper.unbindDevice(_this);' print r' }' else: print r' if (_this->GetType() == D3D11_DEVICE_CONTEXT_IMMEDIATE) {' print r' d3d11Dumper.bindDevice(_this);' print r' }' # intercept private interfaces if method.name == 'QueryInterface': print r' if (!d3dretrace::overrideQueryInterface(_this, riid, ppvObj, &_result)) {' Retracer.invokeInterfaceMethod(self, interface, method) print r' }' return # create windows as neccessary if method.name == 'CreateSwapChain': print r' d3dretrace::createWindowForSwapChain(pDesc);' if method.name == 'CreateSwapChainForHwnd': print r' WindowHandle = d3dretrace::createWindow(pDesc->Width, pDesc->Height);' print r' // DXGI_SCALING_NONE is only supported on Win8 and beyond' print r' if (pDesc->Scaling == DXGI_SCALING_NONE && !IsWindows8OrGreater()) {' print r' pDesc->Scaling = DXGI_SCALING_STRETCH;' print r' }' if method.name == 'CreateSwapChainForComposition': print r' HWND hWnd = d3dretrace::createWindow(pDesc->Width, pDesc->Height);' print r' _result = _this->CreateSwapChainForHwnd(pDevice, hWnd, pDesc, NULL, pRestrictToOutput, ppSwapChain);' self.checkResult(interface, method) return if method.name == 'CreateTargetForHwnd': print r' hwnd = d3dretrace::createWindow(1024, 768);' if method.name == 'SetFullscreenState': print r' if (retrace::forceWindowed) {' print r' Fullscreen = FALSE;' print r' pTarget = NULL;' print r' }' # notify frame has been completed if interface.name.startswith('IDXGISwapChain') and method.name.startswith('Present'): if interface.name.startswith('IDXGISwapChainDWM'): print r' com_ptr<IDXGISwapChain> pSwapChain;' print r' if (SUCCEEDED(_this->QueryInterface(IID_IDXGISwapChain, (void **) &pSwapChain))) {' print r' dxgiDumper.bindDevice(pSwapChain);' print r' } else {' print r' assert(0);' print r' }' else: print r' dxgiDumper.bindDevice(_this);' print r' retrace::frameComplete(call);' if 'pSharedResource' in method.argNames(): print r' if (pSharedResource) {' print r' retrace::warning(call) << "shared surfaces unsupported\n";' print r' pSharedResource = NULL;' print r' }' # Force driver if interface.name.startswith('IDXGIFactory') and method.name.startswith('EnumAdapters'): print r' const char *szSoftware = NULL;' print r' switch (retrace::driver) {' print r' case retrace::DRIVER_REFERENCE:' print r' case retrace::DRIVER_SOFTWARE:' print r' szSoftware = "d3d10warp.dll";' print r' break;' print r' case retrace::DRIVER_MODULE:' print r' szSoftware = retrace::driverModule;' print r' break;' print r' default:' print r' break;' print r' }' print r' HMODULE hSoftware = NULL;' print r' if (szSoftware) {' print r' hSoftware = LoadLibraryA(szSoftware);' print r' if (!hSoftware) {' print r' retrace::warning(call) << "failed to load " << szSoftware << "\n";' print r' }' print r' }' print r' if (hSoftware) {' print r' _result = _this->CreateSoftwareAdapter(hSoftware, reinterpret_cast<IDXGIAdapter **>(ppAdapter));' print r' } else {' Retracer.invokeInterfaceMethod(self, interface, method) print r' }' return if interface.name.startswith('ID3D10Device') and method.name.startswith('OpenSharedResource'): print r' retrace::warning(call) << "replacing shared resource with checker pattern\n";' print r' _result = d3dretrace::createSharedResource(_this, ReturnedInterface, ppResource);' self.checkResult(interface, method) return if interface.name.startswith('ID3D11Device') and method.name == 'OpenSharedResource': # Some applications (e.g., video playing in IE11) create shared resources within the same process. # TODO: Generalize to other OpenSharedResource variants print r' retrace::map<HANDLE>::const_iterator it = _shared_handle_map.find(hResource);' print r' if (it == _shared_handle_map.end()) {' print r' retrace::warning(call) << "replacing shared resource with checker pattern\n";' print r' _result = d3dretrace::createSharedResource(_this, ReturnedInterface, ppResource);' self.checkResult(interface, method) print r' } else {' print r' hResource = it->second;' Retracer.invokeInterfaceMethod(self, interface, method) print r' }' return if interface.name.startswith('ID3D11Device') and method.name.startswith('OpenSharedResource'): print r' retrace::warning(call) << "replacing shared resource with checker pattern\n";' print r' _result = d3dretrace::createSharedResource(_this, ReturnedInterface, ppResource);' if method.name == 'OpenSharedResourceByName': print r' (void)lpName;' print r' (void)dwDesiredAccess;' else: print r' (void)hResource;' self.checkResult(interface, method) return if method.name == 'Map': # Reset _DO_NOT_WAIT flags. Otherwise they may fail, and we have no # way to cope with it (other than retry). mapFlagsArg = method.getArgByName('MapFlags') for flag in mapFlagsArg.type.values: if flag.endswith('_MAP_FLAG_DO_NOT_WAIT'): print r' MapFlags &= ~%s;' % flag if method.name.startswith('UpdateSubresource'): # The D3D10 debug layer is buggy (or at least inconsistent with the # runtime), as it seems to estimate and enforce the data size based on the # SrcDepthPitch, even for non 3D textures, but in some traces # SrcDepthPitch is garbagge for non 3D textures. # XXX: It also seems to expect padding bytes at the end of the last # row, but we never record (or allocate) those... print r' if (retrace::debug && pDstBox && pDstBox->front == 0 && pDstBox->back == 1) {' print r' SrcDepthPitch = 0;' print r' }' if method.name == 'SetGammaControl': # This method is only supported while in full-screen mode print r' if (retrace::forceWindowed) {' print r' return;' print r' }' if method.name == 'GetData': print r' pData = _allocator.alloc(DataSize);' print r' do {' self.doInvokeInterfaceMethod(interface, method) print r' GetDataFlags = 0; // Prevent infinite loop' print r' } while (_result == S_FALSE);' self.checkResult(interface, method) print r' return;' Retracer.invokeInterfaceMethod(self, interface, method) if method.name in ('AcquireSync', 'ReleaseSync'): print r' if (SUCCEEDED(_result) && _result != S_OK) {' print r' retrace::warning(call) << " returned " << _result << "\n";' print r' }' # process events after presents if interface.name.startswith('IDXGISwapChain') and method.name.startswith('Present'): print r' d3dretrace::processEvents();' if method.name in ('Map', 'Unmap'): if interface.name.startswith('ID3D11DeviceContext'): print ' void * & _pbData = g_Maps[_this][SubresourceKey(pResource, Subresource)];' else: subresourceArg = method.getArgByName('Subresource') if subresourceArg is None: print ' UINT Subresource = 0;' print ' void * & _pbData = g_Maps[0][SubresourceKey(_this, Subresource)];' if method.name == 'Map': print ' _MAP_DESC _MapDesc;' print ' _getMapDesc(_this, %s, _MapDesc);' % ', '.join(method.argNames()) print ' size_t _MappedSize = _MapDesc.Size;' print ' if (_MapDesc.Size) {' print ' _pbData = _MapDesc.pData;' if interface.name.startswith('ID3D11DeviceContext'): # Prevent false warnings on 1D and 2D resources, since the # pitches are often junk there... print ' _normalizeMap(pResource, pMappedResource);' else: print ' _pbData = _MapDesc.pData;' print ' } else {' print ' return;' print ' }' if method.name == 'Unmap': print ' if (_pbData) {' print ' retrace::delRegionByPointer(_pbData);' print ' _pbData = 0;' print ' }' if interface.name.startswith('ID3D11VideoContext'): if method.name == 'GetDecoderBuffer': print ' if (*ppBuffer && *pBufferSize) {' print ' g_Maps[nullptr][SubresourceKey(_this, Type)] = *ppBuffer;' print ' }' if method.name == 'ReleaseDecoderBuffer': print ' SubresourceKey _mappingKey(_this, Type);' print ' void *_pBuffer = g_Maps[nullptr][_mappingKey];' print ' if (_pBuffer) {' print ' retrace::delRegionByPointer(_pBuffer);' print ' g_Maps[nullptr][_mappingKey] = 0;' print ' }' # Attach shader byte code for lookup if 'pShaderBytecode' in method.argNames(): ppShader = method.args[-1] assert ppShader.output print r' if (retrace::dumpingState && SUCCEEDED(_result)) {' print r' (*%s)->SetPrivateData(d3dstate::GUID_D3DSTATE, BytecodeLength, pShaderBytecode);' % ppShader.name print r' }'
def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('ID3D10Device', 'ID3D10Device1'): if method.name == 'Release': print(r' if (call.ret->toUInt() == 0) {') print(r' d3d10Dumper.unbindDevice(_this);') print(r' }') else: print(r' d3d10Dumper.bindDevice(_this);') if interface.name.startswith('ID3D11DeviceContext'): if method.name == 'Release': print(r' if (call.ret->toUInt() == 0) {') print(r' d3d11Dumper.unbindDevice(_this);') print(r' }') else: print(r' d3d11Dumper.bindDevice(_this);') # intercept private interfaces if method.name == 'QueryInterface': print( r' if (!d3dretrace::overrideQueryInterface(_this, riid, ppvObj, &_result)) {' ) Retracer.invokeInterfaceMethod(self, interface, method) print(r' }') return # create windows as neccessary if method.name == 'CreateSwapChain': print(r' d3dretrace::createWindowForSwapChain(pDesc);') if method.name == 'CreateSwapChainForHwnd': print( r' hWnd = d3dretrace::createWindow(pDesc->Width, pDesc->Height);' ) print( r' // DXGI_SCALING_NONE is only supported on Win8 and beyond' ) print( r' if (pDesc->Scaling == DXGI_SCALING_NONE && !IsWindows8OrGreater()) {' ) print(r' pDesc->Scaling = DXGI_SCALING_STRETCH;') print(r' }') if method.name == 'CreateSwapChainForComposition': print( r' HWND hWnd = d3dretrace::createWindow(pDesc->Width, pDesc->Height);' ) print( r' _result = _this->CreateSwapChainForHwnd(pDevice, hWnd, pDesc, NULL, pRestrictToOutput, ppSwapChain);' ) self.checkResult(interface, method) return if method.name == 'CreateTargetForHwnd': print(r' hwnd = d3dretrace::createWindow(1024, 768);') if method.name == 'SetFullscreenState': print(r' if (retrace::forceWindowed) {') print(r' DXGI_SWAP_CHAIN_DESC Desc;') print(r' _this->GetDesc(&Desc);') print( r' if (Desc.BufferDesc.Format != DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM) {' ) print(r' Fullscreen = FALSE;') print(r' pTarget = nullptr;') print(r' }') print(r' }') # notify frame has been completed if interface.name.startswith( 'IDXGISwapChain') and method.name.startswith('Present'): if interface.name.startswith('IDXGISwapChainDWM'): print(r' com_ptr<IDXGISwapChain> pSwapChain;') print( r' if (SUCCEEDED(_this->QueryInterface(IID_IDXGISwapChain, (void **) &pSwapChain))) {' ) print(r' dxgiDumper.bindDevice(pSwapChain);') print(r' } else {') print(r' assert(0);') print(r' }') else: print(r' dxgiDumper.bindDevice(_this);') print(r' retrace::frameComplete(call);') if 'pSharedResource' in method.argNames(): print(r' if (pSharedResource) {') print( r' retrace::warning(call) << "shared surfaces unsupported\n";' ) print(r' pSharedResource = NULL;') print(r' }') if interface.name.startswith( 'ID3D10Device') and method.name.startswith( 'OpenSharedResource'): print( r' retrace::warning(call) << "replacing shared resource with checker pattern\n";' ) print( r' _result = d3dretrace::createSharedResource(_this, ReturnedInterface, ppResource);' ) self.checkResult(interface, method) return if interface.name.startswith( 'ID3D11Device') and method.name == 'OpenSharedResource': # Some applications (e.g., video playing in IE11) create shared resources within the same process. # TODO: Generalize to other OpenSharedResource variants print( r' retrace::map<HANDLE>::const_iterator it = _shared_handle_map.find(hResource);' ) print(r' if (it == _shared_handle_map.end()) {') print( r' retrace::warning(call) << "replacing shared resource with checker pattern\n";' ) print( r' _result = d3dretrace::createSharedResource(_this, ReturnedInterface, ppResource);' ) self.checkResult(interface, method) print(r' } else {') print(r' hResource = it->second;') Retracer.invokeInterfaceMethod(self, interface, method) print(r' }') return if interface.name.startswith( 'ID3D11Device') and method.name.startswith( 'OpenSharedResource'): print( r' retrace::warning(call) << "replacing shared resource with checker pattern\n";' ) print( r' _result = d3dretrace::createSharedResource(_this, ReturnedInterface, ppResource);' ) if method.name == 'OpenSharedResourceByName': print(r' (void)lpName;') print(r' (void)dwDesiredAccess;') else: print(r' (void)hResource;') self.checkResult(interface, method) return if method.name == 'Map': # Reset _DO_NOT_WAIT flags. Otherwise they may fail, and we have no # way to cope with it (other than retry). mapFlagsArg = method.getArgByName('MapFlags') for flag in mapFlagsArg.type.values: if flag.endswith('_MAP_FLAG_DO_NOT_WAIT'): print(r' MapFlags &= ~%s;' % flag) if method.name.startswith('UpdateSubresource'): # The D3D10 debug layer is buggy (or at least inconsistent with the # runtime), as it seems to estimate and enforce the data size based on the # SrcDepthPitch, even for non 3D textures, but in some traces # SrcDepthPitch is garbagge for non 3D textures. # XXX: It also seems to expect padding bytes at the end of the last # row, but we never record (or allocate) those... print( r' if (retrace::debug >= 2 && pDstBox && pDstBox->front == 0 && pDstBox->back == 1) {' ) print(r' SrcDepthPitch = 0;') print(r' }') if method.name == 'SetGammaControl': # This method is only supported while in full-screen mode print(r' if (retrace::forceWindowed) {') print(r' return;') print(r' }') if method.name == 'GetData': print(r' pData = _allocator.alloc(DataSize);') print(r' do {') self.doInvokeInterfaceMethod(interface, method) print(r' GetDataFlags = 0; // Prevent infinite loop') print(r' } while (_result == S_FALSE);') self.checkResult(interface, method) print(r' return;') if method.name in ('CreateTexture1D', 'CreateTexture2D', 'CreateTexture3D', 'CreateBuffer'): # We don't capture multiple processes, so ignore keyed mutexes to avoid deadlocks print( r' if (pDesc->MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) {' ) print( r' pDesc->MiscFlags &= ~D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;' ) print(r' pDesc->MiscFlags |= D3D11_RESOURCE_MISC_SHARED;') print(r' }') Retracer.invokeInterfaceMethod(self, interface, method) if method.name in ('AcquireSync', 'ReleaseSync'): print(r' if (SUCCEEDED(_result) && _result != S_OK) {') print( r' retrace::warning(call) << " returned " << _result << "\n";' ) print(r' }') # process events after presents if interface.name.startswith( 'IDXGISwapChain') and method.name.startswith('Present'): print(r' d3dretrace::processEvents();') if method.name in ('Map', 'Unmap'): if interface.name.startswith('ID3D11DeviceContext'): print( ' void * & _pbData = g_Maps[_this][SubresourceKey(pResource, Subresource)];' ) else: subresourceArg = method.getArgByName('Subresource') if subresourceArg is None: print(' UINT Subresource = 0;') print( ' void * & _pbData = g_Maps[0][SubresourceKey(_this, Subresource)];' ) if method.name == 'Map': print(' _MAP_DESC _MapDesc;') print(' _getMapDesc(_this, %s, _MapDesc);' % ', '.join(method.argNames())) print(' size_t _MappedSize = _MapDesc.Size;') print(' if (_MapDesc.Size) {') print(' _pbData = _MapDesc.pData;') if interface.name.startswith('ID3D11DeviceContext'): # Prevent false warnings on 1D and 2D resources, since the # pitches are often junk there... print(' _normalizeMap(pResource, pMappedResource);') else: print(' _pbData = _MapDesc.pData;') print(' } else {') print(' return;') print(' }') if method.name == 'Unmap': print(' if (_pbData) {') print(' retrace::delRegionByPointer(_pbData);') print(' _pbData = 0;') print(' }') if interface.name.startswith('ID3D11VideoContext'): if method.name == 'GetDecoderBuffer': print(' if (*ppBuffer && *pBufferSize) {') print( ' g_Maps[nullptr][SubresourceKey(_this, Type)] = *ppBuffer;' ) print(' }') if method.name == 'ReleaseDecoderBuffer': print(' SubresourceKey _mappingKey(_this, Type);') print(' void *_pBuffer = g_Maps[nullptr][_mappingKey];') print(' if (_pBuffer) {') print(' retrace::delRegionByPointer(_pBuffer);') print(' g_Maps[nullptr][_mappingKey] = 0;') print(' }') # Attach shader byte code for lookup if 'pShaderBytecode' in method.argNames(): ppShader = method.args[-1] assert ppShader.output print(r' if (retrace::dumpingState && SUCCEEDED(_result)) {') print( r' (*%s)->SetPrivateData(d3dstate::GUID_D3DSTATE, BytecodeLength, pShaderBytecode);' % ppShader.name) print(r' }') if method.name == 'CreateBuffer': ppBuffer = method.args[-1] print(r' if (retrace::dumpingState && SUCCEEDED(_result)) {') print(r' char label[32];') print( r' _snprintf(label, sizeof label, "0x%%llx", call.arg(%u).toArray()->values[0]->toUIntPtr());' % ppBuffer.index) print( r' (*%s)->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(label)+1, label);' % ppBuffer.name) print(r' }')
def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('ID3D10Device', 'ID3D10Device1'): if method.name == 'Release': print r' d3d10Dumper.unbindDevice(_this);' else: print r' d3d10Dumper.bindDevice(_this);' if interface.name in ('ID3D11DeviceContext',): if method.name == 'Release': print r' d3d11Dumper.unbindDevice(_this);' else: print r' d3d11Dumper.bindDevice(_this);' # create windows as neccessary if method.name == 'CreateSwapChain': print r' createWindow(pDesc);' # notify frame has been completed if method.name == 'Present': print r' retrace::frameComplete(call);' if 'pSharedResource' in method.argNames(): print r' if (pSharedResource) {' print r' retrace::warning(call) << "shared surfaces unsupported\n";' print r' pSharedResource = NULL;' print r' }' # Force driver if interface.name.startswith('IDXGIFactory') and method.name == 'EnumAdapters': print r' const char *szSoftware = NULL;' print r' switch (retrace::driver) {' print r' case retrace::DRIVER_REFERENCE:' print r' case retrace::DRIVER_SOFTWARE:' print r' szSoftware = "d3d10warp.dll";' print r' break;' print r' case retrace::DRIVER_MODULE:' print r' szSoftware = retrace::driverModule;' print r' break;' print r' default:' print r' break;' print r' }' print r' HMODULE hSoftware = NULL;' print r' if (szSoftware) {' print r' hSoftware = LoadLibraryA(szSoftware);' print r' if (!hSoftware) {' print r' retrace::warning(call) << "failed to load " << szSoftware << "\n";' print r' }' print r' }' print r' if (hSoftware) {' print r' _result = _this->CreateSoftwareAdapter(hSoftware, ppAdapter);' print r' } else {' Retracer.invokeInterfaceMethod(self, interface, method) print r' }' return Retracer.invokeInterfaceMethod(self, interface, method) # process events after presents if method.name == 'Present': print r' d3dretrace::processEvents();' if method.name == 'Map': print ' VOID *_pbData = NULL;' print ' size_t _MappedSize = 0;' print ' _getMapInfo(_this, %s, _pbData, _MappedSize);' % ', '.join(method.argNames()) print ' if (_MappedSize) {' print ' _maps[_this] = _pbData;' print ' } else {' print ' return;' print ' }' if method.name == 'Unmap': print ' VOID *_pbData = 0;' print ' _pbData = _maps[_this];' print ' if (_pbData) {' print ' retrace::delRegionByPointer(_pbData);' print ' _maps[_this] = 0;' print ' }' # Attach shader byte code for lookup if 'pShaderBytecode' in method.argNames(): ppShader = method.args[-1] assert ppShader.output print r' if (retrace::dumpingState && SUCCEEDED(_result)) {' print r' (*%s)->SetPrivateData(d3dstate::GUID_D3DSTATE, BytecodeLength, pShaderBytecode);' % ppShader.name print r' }'
def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ("ID3D10Device", "ID3D10Device1"): if method.name == "Release": print r" d3d10Dumper.unbindDevice(_this);" else: print r" d3d10Dumper.bindDevice(_this);" if interface.name in ("ID3D11DeviceContext",): if method.name == "Release": print r" d3d11Dumper.unbindDevice(_this);" else: print r" d3d11Dumper.bindDevice(_this);" if interface.name == "IDXGIFactory" and method.name == "QueryInterface": print r" if (riid == IID_IDXGIFactoryDWM) {" print r" _this->AddRef();" print r" *ppvObj = new d3dretrace::CDXGIFactoryDWM(_this);" print r" _result = S_OK;" print r" } else {" Retracer.invokeInterfaceMethod(self, interface, method) print r" }" return # create windows as neccessary if method.name == "CreateSwapChain": print r" createWindow(pDesc);" # notify frame has been completed if method.name == "Present": print r" retrace::frameComplete(call);" if "pSharedResource" in method.argNames(): print r" if (pSharedResource) {" print r' retrace::warning(call) << "shared surfaces unsupported\n";' print r" pSharedResource = NULL;" print r" }" # Force driver if interface.name.startswith("IDXGIFactory") and method.name == "EnumAdapters": print r" const char *szSoftware = NULL;" print r" switch (retrace::driver) {" print r" case retrace::DRIVER_REFERENCE:" print r" case retrace::DRIVER_SOFTWARE:" print r' szSoftware = "d3d10warp.dll";' print r" break;" print r" case retrace::DRIVER_MODULE:" print r" szSoftware = retrace::driverModule;" print r" break;" print r" default:" print r" break;" print r" }" print r" HMODULE hSoftware = NULL;" print r" if (szSoftware) {" print r" hSoftware = LoadLibraryA(szSoftware);" print r" if (!hSoftware) {" print r' retrace::warning(call) << "failed to load " << szSoftware << "\n";' print r" }" print r" }" print r" if (hSoftware) {" print r" _result = _this->CreateSoftwareAdapter(hSoftware, ppAdapter);" print r" } else {" Retracer.invokeInterfaceMethod(self, interface, method) print r" }" return if interface.name.startswith("ID3D10Device") and method.name == "OpenSharedResource": print r' retrace::warning(call) << "replacing shared resource with checker pattern\n";' print r" D3D10_TEXTURE2D_DESC Desc;" print r" memset(&Desc, 0, sizeof Desc);" print r" Desc.Width = 8;" print r" Desc.Height = 8;" print r" Desc.MipLevels = 1;" print r" Desc.ArraySize = 1;" print r" Desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;" print r" Desc.SampleDesc.Count = 1;" print r" Desc.SampleDesc.Quality = 0;" print r" Desc.Usage = D3D10_USAGE_DEFAULT;" print r" Desc.BindFlags = D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET;" print r" Desc.CPUAccessFlags = 0x0;" print r" Desc.MiscFlags = 0 /* D3D10_RESOURCE_MISC_SHARED */;" print r""" const DWORD Checker[8][8] = { { 0, ~0, 0, ~0, 0, ~0, 0, ~0, }, {~0, 0, ~0, 0, ~0, 0, ~0, 0, }, { 0, ~0, 0, ~0, 0, ~0, 0, ~0, }, {~0, 0, ~0, 0, ~0, 0, ~0, 0, }, { 0, ~0, 0, ~0, 0, ~0, 0, ~0, }, {~0, 0, ~0, 0, ~0, 0, ~0, 0, }, { 0, ~0, 0, ~0, 0, ~0, 0, ~0, }, {~0, 0, ~0, 0, ~0, 0, ~0, 0, } }; const D3D10_SUBRESOURCE_DATA InitialData = {Checker, sizeof Checker[0], sizeof Checker}; """ print r" _result = _this->CreateTexture2D(&Desc, &InitialData, (ID3D10Texture2D**)ppResource);" self.checkResult(method.type) return if method.name == "Map": # Reset _DO_NOT_WAIT flags. Otherwise they may fail, and we have no # way to cope with it (other than retry). mapFlagsArg = method.getArgByName("MapFlags") for flag in mapFlagsArg.type.values: if flag.endswith("_MAP_FLAG_DO_NOT_WAIT"): print r" MapFlags &= ~%s;" % flag Retracer.invokeInterfaceMethod(self, interface, method) # process events after presents if method.name == "Present": print r" d3dretrace::processEvents();" if method.name == "Map": print " VOID *_pbData = NULL;" print " size_t _MappedSize = 0;" print " _getMapInfo(_this, %s, _pbData, _MappedSize);" % ", ".join(method.argNames()) print " if (_MappedSize) {" print " _maps[_this] = _pbData;" print " } else {" print " return;" print " }" if method.name == "Unmap": print " VOID *_pbData = 0;" print " _pbData = _maps[_this];" print " if (_pbData) {" print " retrace::delRegionByPointer(_pbData);" print " _maps[_this] = 0;" print " }" # Attach shader byte code for lookup if "pShaderBytecode" in method.argNames(): ppShader = method.args[-1] assert ppShader.output print r" if (retrace::dumpingState && SUCCEEDED(_result)) {" print r" (*%s)->SetPrivateData(d3dstate::GUID_D3DSTATE, BytecodeLength, pShaderBytecode);" % ppShader.name print r" }"
def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('IDirect3DDevice9', 'IDirect3DDevice9Ex'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d9Dumper.unbindDevice(_this);' print r' }' else: print r' d3d9Dumper.bindDevice(_this);' if interface.name in ('IDirect3DDevice8', 'IDirect3DDevice8Ex'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d8Dumper.unbindDevice(_this);' print r' }' else: print r' d3d8Dumper.bindDevice(_this);' # create windows as neccessary if method.name in ('CreateDevice', 'CreateDeviceEx', 'CreateAdditionalSwapChain'): print r' HWND hWnd = d3dretrace::createWindow(pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);' print r' pPresentationParameters->hDeviceWindow = hWnd;' if 'hFocusWindow' in method.argNames(): print r' hFocusWindow = hWnd;' # force windowed mode print r' if (retrace::forceWindowed) {' print r' pPresentationParameters->Windowed = TRUE;' print r' pPresentationParameters->FullScreen_RefreshRateInHz = 0;' print r' }' if method.name in self.createDeviceMethodNames: # override the device type print r' switch (retrace::driver) {' print r' case retrace::DRIVER_HARDWARE:' print r' DeviceType = D3DDEVTYPE_HAL;' print r' break;' print r' case retrace::DRIVER_SOFTWARE:' print r' case retrace::DRIVER_REFERENCE:' print r' DeviceType = D3DDEVTYPE_REF;' print r' break;' print r' case retrace::DRIVER_NULL:' if interface.name.startswith('IDirect3D9'): print r' DeviceType = D3DDEVTYPE_NULLREF;' else: print r' retrace::warning(call) << "null driver not supported\n";' print r' break;' print r' case retrace::DRIVER_MODULE:' print r' retrace::warning(call) << "driver module not supported\n";' print r' break;' print r' default:' print r' assert(0);' print r' /* fall-through */' print r' case retrace::DRIVER_DEFAULT:' print r' break;' print r' }' if method.name in ('Reset', 'ResetEx'): # force windowed mode print r' if (retrace::forceWindowed) {' print r' pPresentationParameters->Windowed = TRUE;' print r' pPresentationParameters->FullScreen_RefreshRateInHz = 0;' print r' }' # resize window print r' if (pPresentationParameters->Windowed) {' print r' d3dretrace::resizeWindow(pPresentationParameters->hDeviceWindow, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);' print r' }' # notify frame has been completed if method.name in ('Present', 'PresentEx'): print r' retrace::frameComplete(call);' print r' hDestWindowOverride = NULL;' if 'pSharedHandle' in method.argNames(): print r' if (pSharedHandle) {' print r' retrace::warning(call) << "shared surfaces unsupported\n";' print r' pSharedHandle = NULL;' print r' }' if method.name in ('Lock', 'LockRect', 'LockBox'): # Reset _DONOTWAIT flags. Otherwise they may fail, and we have no # way to cope with it (other than retry). mapFlagsArg = method.getArgByName('Flags') for flag in mapFlagsArg.type.values: if flag.endswith('_DONOTWAIT'): print r' Flags &= ~%s;' % flag Retracer.invokeInterfaceMethod(self, interface, method) if method.name in self.createDeviceMethodNames: print r' if (FAILED(_result)) {' print r' exit(1);' print r' }' # process events after presents if method.name == 'Present': print r' d3dretrace::processEvents();' if method.name in ('Lock', 'LockRect', 'LockBox'): print ' VOID *_pbData = NULL;' print ' size_t _MappedSize = 0;' print ' _getMapInfo(_this, %s, _pbData, _MappedSize);' % ', '.join(method.argNames()[:-1]) print ' if (_MappedSize) {' print ' _maps[_this] = _pbData;' print ' } else {' print ' return;' print ' }' if method.name in ('Unlock', 'UnlockRect', 'UnlockBox'): print ' VOID *_pbData = 0;' print ' _pbData = _maps[_this];' print ' if (_pbData) {' print ' retrace::delRegionByPointer(_pbData);' print ' _maps[_this] = 0;' print ' }'
def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('IDirect3DDevice9', 'IDirect3DDevice9Ex'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d9Dumper.unbindDevice(_this);' print r' }' else: print r' d3d9Dumper.bindDevice(_this);' if interface.name in ('IDirect3DDevice8', 'IDirect3DDevice8Ex'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d8Dumper.unbindDevice(_this);' print r' }' else: print r' d3d8Dumper.bindDevice(_this);' # create windows as neccessary if method.name in ('CreateDevice', 'CreateDeviceEx', 'CreateAdditionalSwapChain'): print r' HWND hWnd = d3dretrace::createWindow(pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);' print r' pPresentationParameters->hDeviceWindow = hWnd;' if 'hFocusWindow' in method.argNames(): print r' hFocusWindow = hWnd;' # force windowed mode print r' if (retrace::forceWindowed) {' print r' pPresentationParameters->Windowed = TRUE;' print r' pPresentationParameters->FullScreen_RefreshRateInHz = 0;' print r' }' if method.name in self.createDeviceMethodNames: # override the device type print r' switch (retrace::driver) {' print r' case retrace::DRIVER_HARDWARE:' print r' DeviceType = D3DDEVTYPE_HAL;' print r' break;' print r' case retrace::DRIVER_SOFTWARE:' print r' case retrace::DRIVER_REFERENCE:' print r' DeviceType = D3DDEVTYPE_REF;' print r' break;' print r' case retrace::DRIVER_NULL:' if interface.name.startswith('IDirect3D9'): print r' DeviceType = D3DDEVTYPE_NULLREF;' else: print r' retrace::warning(call) << "null driver not supported\n";' print r' break;' print r' case retrace::DRIVER_MODULE:' print r' retrace::warning(call) << "driver module not supported\n";' print r' break;' print r' default:' print r' assert(0);' print r' /* fall-through */' print r' case retrace::DRIVER_DEFAULT:' print r' break;' print r' }' if method.name in ('Reset', 'ResetEx'): # force windowed mode print r' if (retrace::forceWindowed) {' print r' pPresentationParameters->Windowed = TRUE;' print r' pPresentationParameters->FullScreen_RefreshRateInHz = 0;' print r' }' # resize window print r' if (pPresentationParameters->Windowed) {' print r' d3dretrace::resizeWindow(pPresentationParameters->hDeviceWindow, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);' print r' }' # notify frame has been completed if method.name in ('Present', 'PresentEx'): print r' retrace::frameComplete(call);' print r' if (retrace::profiling) {' print r' retrace::profiler.addFrameEnd();' print r' }' print r' hDestWindowOverride = NULL;' # Ensure textures can be locked when dumping # TODO: Pre-check with CheckDeviceFormat if method.name in ('CreateVertexShader', 'CreatePixelShader'): print r' pFunction = d3dretrace::CheckReplaceShader(pFunction,call);' if method.name in ('CreateTexture', 'CreateCubeTexture', 'CreateVolumeTexture'): print r' if (retrace::dumpingState &&' print r' Pool == D3DPOOL_DEFAULT &&' print r' !(Usage & (D3DUSAGE_RENDERTARGET|D3DUSAGE_DEPTHSTENCIL))) {' print r' Usage |= D3DUSAGE_DYNAMIC;' print r' }' if 'pSharedHandle' in method.argNames(): print r' if (pSharedHandle) {' print r' retrace::warning(call) << "shared surfaces unsupported\n";' print r' pSharedHandle = NULL;' print r' }' if method.name in ('Lock', 'LockRect', 'LockBox'): # Reset _DONOTWAIT flags. Otherwise they may fail, and we have no # way to cope with it (other than retry). mapFlagsArg = method.getArgByName('Flags') for flag in mapFlagsArg.type.values: if flag.endswith('_DONOTWAIT'): print r' Flags &= ~%s;' % flag if method.name.startswith("Draw"): print r' if (retrace::profiling) {' print r' d3dretrace::beginProfileDX9(call, true);' print r' }' Retracer.invokeInterfaceMethod(self, interface, method) if method.name.startswith("Draw"): print r' if (retrace::profiling) {' print r' d3dretrace::endProfileDX9(call, true);' print r' }' if method.name in self.createDeviceMethodNames: print r' if (FAILED(_result)) {' print r' exit(1);' print r' }' # process events after presents if method.name == 'Present': print r' d3dretrace::processEvents();' def mapping_subkey(): if 'Level' in method.argNames(): return ('Level',) else: return ('0',) if method.name in ('Lock', 'LockRect', 'LockBox'): print ' VOID *_pbData = NULL;' print ' size_t _MappedSize = 0;' print ' _getMapInfo(_this, %s, _pbData, _MappedSize);' % ', '.join(method.argNames()[:-1]) print ' if (_MappedSize) {' print ' _maps[MappingKey(_this, %s)] = _pbData;' % mapping_subkey() self.checkPitchMismatch(method) print ' } else {' print ' return;' print ' }' if method.name in ('Unlock', 'UnlockRect', 'UnlockBox'): print ' VOID *_pbData = 0;' print ' MappingKey _mappingKey(_this, %s);' % mapping_subkey() print ' _pbData = _maps[_mappingKey];' print ' if (_pbData) {' print ' retrace::delRegionByPointer(_pbData);' print ' _maps[_mappingKey] = 0;' print ' }'
def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('ID3D10Device', 'ID3D10Device1'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d10Dumper.unbindDevice(_this);' print r' }' else: print r' d3d10Dumper.bindDevice(_this);' if interface.name in ('ID3D11DeviceContext', 'ID3D11DeviceContext1'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d11Dumper.unbindDevice(_this);' print r' }' else: print r' if (_this->GetType() == D3D11_DEVICE_CONTEXT_IMMEDIATE) {' print r' d3d11Dumper.bindDevice(_this);' print r' }' if interface.name == 'IDXGIFactory' and method.name == 'QueryInterface': print r' if (riid == IID_IDXGIFactoryDWM) {' print r' _this->AddRef();' print r' *ppvObj = new d3dretrace::CDXGIFactoryDWM(_this);' print r' _result = S_OK;' print r' } else {' Retracer.invokeInterfaceMethod(self, interface, method) print r' }' return # create windows as neccessary if method.name == 'CreateSwapChain': print r' createWindow(pDesc);' # notify frame has been completed if method.name == 'Present': print r' retrace::frameComplete(call);' if 'pSharedResource' in method.argNames(): print r' if (pSharedResource) {' print r' retrace::warning(call) << "shared surfaces unsupported\n";' print r' pSharedResource = NULL;' print r' }' # Force driver if interface.name.startswith('IDXGIFactory') and method.name == 'EnumAdapters': print r' const char *szSoftware = NULL;' print r' switch (retrace::driver) {' print r' case retrace::DRIVER_REFERENCE:' print r' case retrace::DRIVER_SOFTWARE:' print r' szSoftware = "d3d10warp.dll";' print r' break;' print r' case retrace::DRIVER_MODULE:' print r' szSoftware = retrace::driverModule;' print r' break;' print r' default:' print r' break;' print r' }' print r' HMODULE hSoftware = NULL;' print r' if (szSoftware) {' print r' hSoftware = LoadLibraryA(szSoftware);' print r' if (!hSoftware) {' print r' retrace::warning(call) << "failed to load " << szSoftware << "\n";' print r' }' print r' }' print r' if (hSoftware) {' print r' _result = _this->CreateSoftwareAdapter(hSoftware, ppAdapter);' print r' } else {' Retracer.invokeInterfaceMethod(self, interface, method) print r' }' return if interface.name.startswith('ID3D10Device') and method.name == 'OpenSharedResource': print r' retrace::warning(call) << "replacing shared resource with checker pattern\n";' print r' D3D10_TEXTURE2D_DESC Desc;' print r' memset(&Desc, 0, sizeof Desc);' print r' Desc.Width = 8;' print r' Desc.Height = 8;' print r' Desc.MipLevels = 1;' print r' Desc.ArraySize = 1;' print r' Desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;' print r' Desc.SampleDesc.Count = 1;' print r' Desc.SampleDesc.Quality = 0;' print r' Desc.Usage = D3D10_USAGE_DEFAULT;' print r' Desc.BindFlags = D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET;' print r' Desc.CPUAccessFlags = 0x0;' print r' Desc.MiscFlags = 0 /* D3D10_RESOURCE_MISC_SHARED */;' print r''' const DWORD Checker[8][8] = { { 0, ~0, 0, ~0, 0, ~0, 0, ~0, }, {~0, 0, ~0, 0, ~0, 0, ~0, 0, }, { 0, ~0, 0, ~0, 0, ~0, 0, ~0, }, {~0, 0, ~0, 0, ~0, 0, ~0, 0, }, { 0, ~0, 0, ~0, 0, ~0, 0, ~0, }, {~0, 0, ~0, 0, ~0, 0, ~0, 0, }, { 0, ~0, 0, ~0, 0, ~0, 0, ~0, }, {~0, 0, ~0, 0, ~0, 0, ~0, 0, } }; const D3D10_SUBRESOURCE_DATA InitialData = {Checker, sizeof Checker[0], sizeof Checker}; ''' print r' _result = _this->CreateTexture2D(&Desc, &InitialData, (ID3D10Texture2D**)ppResource);' self.checkResult(method.type) return if method.name == 'Map': # Reset _DO_NOT_WAIT flags. Otherwise they may fail, and we have no # way to cope with it (other than retry). mapFlagsArg = method.getArgByName('MapFlags') for flag in mapFlagsArg.type.values: if flag.endswith('_MAP_FLAG_DO_NOT_WAIT'): print r' MapFlags &= ~%s;' % flag Retracer.invokeInterfaceMethod(self, interface, method) # process events after presents if method.name == 'Present': print r' d3dretrace::processEvents();' if method.name == 'Map': print ' _MAP_DESC _MapDesc;' print ' _getMapDesc(_this, %s, _MapDesc);' % ', '.join(method.argNames()) print ' size_t _MappedSize = _MapDesc.Size;' print ' if (_MapDesc.Size) {' print ' _maps[_this] = _MapDesc.pData;' print ' } else {' print ' return;' print ' }' if method.name == 'Unmap': print ' VOID *_pbData = 0;' print ' _pbData = _maps[_this];' print ' if (_pbData) {' print ' retrace::delRegionByPointer(_pbData);' print ' _maps[_this] = 0;' print ' }' # Attach shader byte code for lookup if 'pShaderBytecode' in method.argNames(): ppShader = method.args[-1] assert ppShader.output print r' if (retrace::dumpingState && SUCCEEDED(_result)) {' print r' (*%s)->SetPrivateData(d3dstate::GUID_D3DSTATE, BytecodeLength, pShaderBytecode);' % ppShader.name print r' }'
def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ("IDirect3DDevice9", "IDirect3DDevice9Ex"): if method.name == "Release": print r" if (call.ret->toUInt() == 0) {" print r" d3d9Dumper.unbindDevice(_this);" print r" }" else: print r" d3d9Dumper.bindDevice(_this);" if interface.name in ("IDirect3DDevice8", "IDirect3DDevice8Ex"): if method.name == "Release": print r" if (call.ret->toUInt() == 0) {" print r" d3d8Dumper.unbindDevice(_this);" print r" }" else: print r" d3d8Dumper.bindDevice(_this);" # create windows as neccessary if method.name in ("CreateDevice", "CreateDeviceEx", "CreateAdditionalSwapChain"): print r" HWND hWnd = pPresentationParameters->hDeviceWindow;" if "hFocusWindow" in method.argNames(): print r" if (hWnd == NULL) {" print r" hWnd = hFocusWindow;" print r" }" print r" hWnd = d3dretrace::createWindow(hWnd, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);" print r" pPresentationParameters->hDeviceWindow = hWnd;" if "hFocusWindow" in method.argNames(): print r" hFocusWindow = hWnd;" # force windowed mode print r" if (retrace::forceWindowed) {" print r" pPresentationParameters->Windowed = TRUE;" print r" pPresentationParameters->FullScreen_RefreshRateInHz = 0;" if interface.name.startswith("IDirect3D8"): print r" pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;" print r" }" if "BehaviorFlags" in method.argNames(): print r" if (retrace::dumpingState) {" print r" BehaviorFlags &= ~D3DCREATE_PUREDEVICE;" print r" }" # On D3D8, ensure we use BackBufferFormat compatible with the # current DisplayFormat. # # TODO: BackBufferFormat doesn't need to be always exectly to # DisplayFormat. For example, if DisplayFormat is D3DFMT_X1R5G5B5, # valid values for BackBufferFormat include D3DFMT_X1R5G5B5 and # D3DFMT_A1R5G5B5, but exclude D3DFMT_R5G6B5. if interface.name.startswith("IDirect3D8"): print r" if (pPresentationParameters->Windowed) {" print r" D3DDISPLAYMODE Mode;" print r" HRESULT hr;" print r" hr = _this->GetAdapterDisplayMode(Adapter, &Mode);" print r" assert(SUCCEEDED(hr));" print r" hr = _this->CheckDeviceType(Adapter, DeviceType, Mode.Format, pPresentationParameters->BackBufferFormat, pPresentationParameters->Windowed);" print r" if (hr == D3DERR_NOTAVAILABLE) {" print r' retrace::warning(call) << "forcing back buffer format to match display mode format\n";' print r" pPresentationParameters->BackBufferFormat = Mode.Format;" print r" }" print r" }" if method.name in self.createDeviceMethodNames: # override the device type print r" switch (retrace::driver) {" print r" case retrace::DRIVER_HARDWARE:" print r" DeviceType = D3DDEVTYPE_HAL;" print r" break;" print r" case retrace::DRIVER_SOFTWARE:" print r" case retrace::DRIVER_REFERENCE:" print r" DeviceType = D3DDEVTYPE_REF;" print r" break;" print r" case retrace::DRIVER_NULL:" if interface.name.startswith("IDirect3D9"): print r" DeviceType = D3DDEVTYPE_NULLREF;" else: print r' retrace::warning(call) << "null driver not supported\n";' print r" break;" print r" case retrace::DRIVER_MODULE:" print r' retrace::warning(call) << "driver module not supported\n";' print r" break;" print r" default:" print r" assert(0);" print r" /* fall-through */" print r" case retrace::DRIVER_DEFAULT:" print r" break;" print r" }" if method.name in ("Reset", "ResetEx"): # force windowed mode print r" if (retrace::forceWindowed) {" print r" pPresentationParameters->Windowed = TRUE;" print r" pPresentationParameters->FullScreen_RefreshRateInHz = 0;" print r" }" # resize window print r" if (pPresentationParameters->Windowed) {" print r" d3dretrace::resizeWindow(pPresentationParameters->hDeviceWindow, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);" print r" }" # notify frame has been completed if method.name in ("Present", "PresentEx"): if interface.name.startswith("IDirect3DSwapChain9"): print r" d3d9scDumper.bindDevice(_this);" print r" retrace::frameComplete(call);" print r" hDestWindowOverride = NULL;" # Ensure textures can be locked when dumping # TODO: Pre-check with CheckDeviceFormat if method.name in ("CreateTexture", "CreateCubeTexture", "CreateVolumeTexture"): print r" if (retrace::dumpingState &&" print r" Pool == D3DPOOL_DEFAULT &&" print r" !(Usage & (D3DUSAGE_RENDERTARGET|D3DUSAGE_DEPTHSTENCIL))) {" print r" Usage |= D3DUSAGE_DYNAMIC;" print r" }" # Deal with shared surfaces # https://msdn.microsoft.com/en-us/library/windows/desktop/bb219800.aspx # https://msdn.microsoft.com/en-gb/library/windows/desktop/ee913554.aspx pSharedHandleArg = method.getArgByName("pSharedHandle") if pSharedHandleArg: print r" if (pSharedHandle) {" if method.name == "CreateTexture": # Some applications (e.g., DOTA2) create shared resources within the same process. # https://msdn.microsoft.com/en-us/library/windows/desktop/bb219800.aspx#Textures print r" if (Pool == D3DPOOL_SYSTEMMEM) {" print r" // Ensure the memory stays around." print r" trace::Blob *blob = call.arg(%u).toArray()->values[0]->toBlob();" % pSharedHandleArg.index print r" if (blob) {" print r" blob->toPointer(true);" print r" } else {" print r' retrace::warning(call) << "invalid system memory\n";' print r" pSharedHandle = NULL;" print r" }" print r" } else {" print r' retrace::warning(call) << "shared surfaces unsupported\n";' print r" pSharedHandle = NULL;" if method.name == "CreateTexture": print r" }" print r" }" if method.name in ("Lock", "LockRect", "LockBox"): # Reset _DONOTWAIT flags. Otherwise they may fail, and we have no # way to cope with it (other than retry). mapFlagsArg = method.getArgByName("Flags") for flag in mapFlagsArg.type.values: if flag.endswith("_DONOTWAIT"): print r" Flags &= ~%s;" % flag Retracer.invokeInterfaceMethod(self, interface, method) if method.name in self.createDeviceMethodNames: print r" if (FAILED(_result)) {" print r" exit(1);" print r" }" # process events after presents if method.name == "Present": print r" d3dretrace::processEvents();" def mapping_subkey(): if "Level" in method.argNames(): return ("Level",) else: return ("0",) if method.name in ("Lock", "LockRect", "LockBox"): print " VOID *_pbData = NULL;" print " size_t _MappedSize = 0;" print " if (!(Flags & D3DLOCK_READONLY)) {" print " _getMapInfo(_this, %s, _pbData, _MappedSize);" % ", ".join(method.argNames()[:-1]) print " }" print " if (_MappedSize) {" print " _maps[MappingKey(_this, %s)] = _pbData;" % mapping_subkey() self.checkPitchMismatch(method) print " } else {" print " return;" print " }" if method.name in ("Unlock", "UnlockRect", "UnlockBox"): print " VOID *_pbData = 0;" print " MappingKey _mappingKey(_this, %s);" % mapping_subkey() print " _pbData = _maps[_mappingKey];" print " if (_pbData) {" print " retrace::delRegionByPointer(_pbData);" print " _maps[_mappingKey] = 0;" print " }"
def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('IDirect3DDevice9', 'IDirect3DDevice9Ex'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d9Dumper.unbindDevice(_this);' print r' }' else: print r' d3d9Dumper.bindDevice(_this);' if interface.name in ('IDirect3DDevice8', 'IDirect3DDevice8Ex'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d8Dumper.unbindDevice(_this);' print r' }' else: print r' d3d8Dumper.bindDevice(_this);' # create windows as neccessary if method.name in ('CreateDevice', 'CreateDeviceEx', 'CreateAdditionalSwapChain'): print r' HWND hWnd = d3dretrace::createWindow(pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);' print r' pPresentationParameters->hDeviceWindow = hWnd;' if 'hFocusWindow' in method.argNames(): print r' hFocusWindow = hWnd;' # force windowed mode print r' if (retrace::forceWindowed) {' print r' pPresentationParameters->Windowed = TRUE;' print r' pPresentationParameters->FullScreen_RefreshRateInHz = 0;' print r' }' # On D3D8, ensure we use BackBufferFormat compatible with the # current DisplayFormat. # # TODO: BackBufferFormat doesn't need to be always exectly to # DisplayFormat. For example, if DisplayFormat is D3DFMT_X1R5G5B5, # valid values for BackBufferFormat include D3DFMT_X1R5G5B5 and # D3DFMT_A1R5G5B5, but exclude D3DFMT_R5G6B5. if interface.name.startswith('IDirect3D8'): print r' D3DDISPLAYMODE Mode;' print r' HRESULT hr;' print r' hr = _this->GetAdapterDisplayMode(Adapter, &Mode);' print r' hr = _this->CheckDeviceType(Adapter, DeviceType, Mode.Format, pPresentationParameters->BackBufferFormat, pPresentationParameters->Windowed);' print r' if (hr == D3DERR_NOTAVAILABLE) {' print r' retrace::warning(call) << "forcing back buffer format to match display mode format\n";' print r' pPresentationParameters->BackBufferFormat = Mode.Format;' print r' };' if method.name in self.createDeviceMethodNames: # override the device type print r' switch (retrace::driver) {' print r' case retrace::DRIVER_HARDWARE:' print r' DeviceType = D3DDEVTYPE_HAL;' print r' break;' print r' case retrace::DRIVER_SOFTWARE:' print r' case retrace::DRIVER_REFERENCE:' print r' DeviceType = D3DDEVTYPE_REF;' print r' break;' print r' case retrace::DRIVER_NULL:' if interface.name.startswith('IDirect3D9'): print r' DeviceType = D3DDEVTYPE_NULLREF;' else: print r' retrace::warning(call) << "null driver not supported\n";' print r' break;' print r' case retrace::DRIVER_MODULE:' print r' retrace::warning(call) << "driver module not supported\n";' print r' break;' print r' default:' print r' assert(0);' print r' /* fall-through */' print r' case retrace::DRIVER_DEFAULT:' print r' break;' print r' }' if method.name in ('Reset', 'ResetEx'): # force windowed mode print r' if (retrace::forceWindowed) {' print r' pPresentationParameters->Windowed = TRUE;' print r' pPresentationParameters->FullScreen_RefreshRateInHz = 0;' print r' }' # resize window print r' if (pPresentationParameters->Windowed) {' print r' d3dretrace::resizeWindow(pPresentationParameters->hDeviceWindow, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);' print r' }' # notify frame has been completed if method.name in ('Present', 'PresentEx'): print r' retrace::frameComplete(call);' print r' hDestWindowOverride = NULL;' # Ensure textures can be locked when dumping # TODO: Pre-check with CheckDeviceFormat if method.name in ('CreateTexture', 'CreateCubeTexture', 'CreateVolumeTexture'): print r' if (retrace::dumpingState &&' print r' Pool == D3DPOOL_DEFAULT &&' print r' !(Usage & (D3DUSAGE_RENDERTARGET|D3DUSAGE_DEPTHSTENCIL))) {' print r' Usage |= D3DUSAGE_DYNAMIC;' print r' }' if 'pSharedHandle' in method.argNames(): print r' if (pSharedHandle) {' print r' retrace::warning(call) << "shared surfaces unsupported\n";' print r' pSharedHandle = NULL;' print r' }' if method.name in ('Lock', 'LockRect', 'LockBox'): # Reset _DONOTWAIT flags. Otherwise they may fail, and we have no # way to cope with it (other than retry). mapFlagsArg = method.getArgByName('Flags') for flag in mapFlagsArg.type.values: if flag.endswith('_DONOTWAIT'): print r' Flags &= ~%s;' % flag Retracer.invokeInterfaceMethod(self, interface, method) if method.name in self.createDeviceMethodNames: print r' if (FAILED(_result)) {' print r' exit(1);' print r' }' # process events after presents if method.name == 'Present': print r' d3dretrace::processEvents();' def mapping_subkey(): if 'Level' in method.argNames(): return ('Level',) else: return ('0',) if method.name in ('Lock', 'LockRect', 'LockBox'): print ' VOID *_pbData = NULL;' print ' size_t _MappedSize = 0;' print ' _getMapInfo(_this, %s, _pbData, _MappedSize);' % ', '.join(method.argNames()[:-1]) print ' if (_MappedSize) {' print ' _maps[MappingKey(_this, %s)] = _pbData;' % mapping_subkey() self.checkPitchMismatch(method) print ' } else {' print ' return;' print ' }' if method.name in ('Unlock', 'UnlockRect', 'UnlockBox'): print ' VOID *_pbData = 0;' print ' MappingKey _mappingKey(_this, %s);' % mapping_subkey() print ' _pbData = _maps[_mappingKey];' print ' if (_pbData) {' print ' retrace::delRegionByPointer(_pbData);' print ' _maps[_mappingKey] = 0;' print ' }'
def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('IDirect3DDevice9', 'IDirect3DDevice9Ex'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d9Dumper.unbindDevice(_this);' print r' }' else: print r' d3d9Dumper.bindDevice(_this);' if interface.name in ('IDirect3DDevice8', 'IDirect3DDevice8Ex'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d8Dumper.unbindDevice(_this);' print r' }' else: print r' d3d8Dumper.bindDevice(_this);' # create windows as neccessary if method.name in ('CreateDevice', 'CreateDeviceEx', 'CreateAdditionalSwapChain'): print r' HWND hWnd = d3dretrace::createWindow(pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);' print r' pPresentationParameters->hDeviceWindow = hWnd;' if 'hFocusWindow' in method.argNames(): print r' hFocusWindow = hWnd;' # force windowed mode print r' if (retrace::forceWindowed) {' print r' pPresentationParameters->Windowed = TRUE;' print r' pPresentationParameters->FullScreen_RefreshRateInHz = 0;' print r' }' if method.name in self.createDeviceMethodNames: # override the device type print r' switch (retrace::driver) {' print r' case retrace::DRIVER_HARDWARE:' print r' DeviceType = D3DDEVTYPE_HAL;' print r' break;' print r' case retrace::DRIVER_SOFTWARE:' print r' case retrace::DRIVER_REFERENCE:' print r' DeviceType = D3DDEVTYPE_REF;' print r' break;' print r' case retrace::DRIVER_NULL:' if interface.name.startswith('IDirect3D9'): print r' DeviceType = D3DDEVTYPE_NULLREF;' else: print r' retrace::warning(call) << "null driver not supported\n";' print r' break;' print r' case retrace::DRIVER_MODULE:' print r' retrace::warning(call) << "driver module not supported\n";' print r' break;' print r' default:' print r' assert(0);' print r' /* fall-through */' print r' case retrace::DRIVER_DEFAULT:' print r' break;' print r' }' if method.name in ('Reset', 'ResetEx'): # force windowed mode print r' if (retrace::forceWindowed) {' print r' pPresentationParameters->Windowed = TRUE;' print r' pPresentationParameters->FullScreen_RefreshRateInHz = 0;' print r' }' # resize window print r' if (pPresentationParameters->Windowed) {' print r' d3dretrace::resizeWindow(pPresentationParameters->hDeviceWindow, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);' print r' }' # notify frame has been completed if method.name in ('Present', 'PresentEx'): print r' retrace::frameComplete(call);' print r' hDestWindowOverride = NULL;' # Ensure textures can be locked when dumping # TODO: Pre-check with CheckDeviceFormat if method.name in ('CreateTexture', 'CreateCubeTexture', 'CreateVolumeTexture'): print r' if (retrace::dumpingState &&' print r' Pool == D3DPOOL_DEFAULT &&' print r' !(Usage & (D3DUSAGE_RENDERTARGET|D3DUSAGE_DEPTHSTENCIL))) {' print r' Usage |= D3DUSAGE_DYNAMIC;' print r' }' if 'pSharedHandle' in method.argNames(): print r' if (pSharedHandle) {' print r' retrace::warning(call) << "shared surfaces unsupported\n";' print r' pSharedHandle = NULL;' print r' }' if method.name in ('Lock', 'LockRect', 'LockBox'): # Reset _DONOTWAIT flags. Otherwise they may fail, and we have no # way to cope with it (other than retry). mapFlagsArg = method.getArgByName('Flags') for flag in mapFlagsArg.type.values: if flag.endswith('_DONOTWAIT'): print r' Flags &= ~%s;' % flag Retracer.invokeInterfaceMethod(self, interface, method) if method.name in self.createDeviceMethodNames: print r' if (FAILED(_result)) {' print r' exit(1);' print r' }' # process events after presents if method.name == 'Present': print r' d3dretrace::processEvents();' if method.name in ('Lock', 'LockRect', 'LockBox'): print ' VOID *_pbData = NULL;' print ' size_t _MappedSize = 0;' print ' _getMapInfo(_this, %s, _pbData, _MappedSize);' % ', '.join(method.argNames()[:-1]) print ' if (_MappedSize) {' print ' _maps[_this] = _pbData;' self.checkPitchMismatch(method) print ' } else {' print ' return;' print ' }' if method.name in ('Unlock', 'UnlockRect', 'UnlockBox'): print ' VOID *_pbData = 0;' print ' _pbData = _maps[_this];' print ' if (_pbData) {' print ' retrace::delRegionByPointer(_pbData);' print ' _maps[_this] = 0;' print ' }'
def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('IDirect3DDevice9', 'IDirect3DDevice9Ex'): if method.name == 'Release': print r' d3d9Dumper.unbindDevice(_this);' else: print r' d3d9Dumper.bindDevice(_this);' if interface.name in ('IDirect3DDevice8', 'IDirect3DDevice8Ex'): if method.name == 'Release': print r' d3d8Dumper.unbindDevice(_this);' else: print r' d3d8Dumper.bindDevice(_this);' # create windows as neccessary if method.name in ('CreateDevice', 'CreateDeviceEx', 'CreateAdditionalSwapChain'): print r' HWND hWnd = d3dretrace::createWindow(pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);' print r' pPresentationParameters->hDeviceWindow = hWnd;' if 'hFocusWindow' in method.argNames(): print r' hFocusWindow = hWnd;' if method.name in ('CreateDevice', 'CreateDeviceEx'): print r' switch (retrace::driver) {' print r' case retrace::DRIVER_HARDWARE:' print r' DeviceType = D3DDEVTYPE_HAL;' print r' break;' print r' case retrace::DRIVER_SOFTWARE:' print r' case retrace::DRIVER_REFERENCE:' print r' DeviceType = D3DDEVTYPE_REF;' print r' break;' print r' case retrace::DRIVER_NULL:' if interface.name.startswith('IDirect3D9'): print r' DeviceType = D3DDEVTYPE_NULLREF;' else: print r' retrace::warning(call) << "null driver not supported\n";' print r' break;' print r' case retrace::DRIVER_MODULE:' print r' retrace::warning(call) << "driver module not supported\n";' print r' break;' print r' default:' print r' assert(0);' print r' /* fall-through */' print r' case retrace::DRIVER_DEFAULT:' print r' break;' print r' }' if method.name in ('Reset', 'ResetEx'): print r' if (pPresentationParameters->Windowed) {' print r' d3dretrace::resizeWindow(pPresentationParameters->hDeviceWindow, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);' print r' }' # notify frame has been completed if method.name == 'Present': print r' retrace::frameComplete(call);' print r' hDestWindowOverride = NULL;' if 'pSharedHandle' in method.argNames(): print r' if (pSharedHandle) {' print r' retrace::warning(call) << "shared surfaces unsupported\n";' print r' pSharedHandle = NULL;' print r' }' Retracer.invokeInterfaceMethod(self, interface, method) # process events after presents if method.name == 'Present': print r' d3dretrace::processEvents();' print r' Sleep(500);' if method.name in ('Lock', 'LockRect', 'LockBox'): print ' VOID *_pbData = NULL;' print ' size_t _MappedSize = 0;' print ' _getMapInfo(_this, %s, _pbData, _MappedSize);' % ', '.join(method.argNames()[:-1]) print ' if (_MappedSize) {' print ' _maps[_this] = _pbData;' print ' } else {' print ' return;' print ' }' if method.name in ('Unlock', 'UnlockRect', 'UnlockBox'): print ' VOID *_pbData = 0;' print ' _pbData = _maps[_this];' print ' if (_pbData) {' print ' retrace::delRegionByPointer(_pbData);' print ' _maps[_this] = 0;' print ' }'
def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('IDirect3DDevice7',): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d7Dumper.unbindDevice(_this);' print r' }' else: print r' d3d7Dumper.bindDevice(_this);' # create windows as neccessary hWndArg = method.getArgByType(HWND) if hWndArg is not None: # FIXME: Try to guess the window size (e.g., from IDirectDrawSurface7::Blt) print r' if (!g_hWnd) {' print r' g_hWnd = d3dretrace::createWindow(512, 512);' print r' }' print r' %s = g_hWnd;' % hWndArg.name if method.name == 'Lock': # Reset _DONOTWAIT flags. Otherwise they may fail, and we have no # way to cope with it (other than retry). mapFlagsArg = method.getArgByName('dwFlags') if mapFlagsArg is not None: print r' dwFlags &= DDLOCK_DONOTWAIT;' print r' dwFlags |= DDLOCK_WAIT;' Retracer.invokeInterfaceMethod(self, interface, method) if method.name == 'CreateDevice': print r' if (FAILED(_result)) {' print r' exit(1);' print r' }' # notify frame has been completed # process events after presents if interface.name == 'IDirectDrawSurface7' and method.name == 'Blt': print r' DDSCAPS2 ddsCaps;' print r' if (SUCCEEDED(_this->GetCaps(&ddsCaps)) &&' print r' (ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) {' print r' retrace::frameComplete(call);' print r' d3dretrace::processEvents();' print r' }' if method.name == 'Lock': print ' VOID *_pbData = NULL;' print ' size_t _MappedSize = 0;' # FIXME: determine the mapping size #print ' _getMapInfo(_this, %s, _pbData, _MappedSize);' % ', '.join(method.argNames()[:-1]) print ' if (_MappedSize) {' print ' _maps[_this] = _pbData;' # TODO: check pitches match print ' } else {' print ' return;' print ' }' if method.name == 'Unlock': print ' VOID *_pbData = 0;' print ' _pbData = _maps[_this];' print ' if (_pbData) {' print ' retrace::delRegionByPointer(_pbData);' print ' _maps[_this] = 0;' print ' }'
def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('ID3D10Device', 'ID3D10Device1'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d10Dumper.unbindDevice(_this);' print r' }' else: print r' d3d10Dumper.bindDevice(_this);' if interface.name in ('ID3D11DeviceContext', 'ID3D11DeviceContext1'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d11Dumper.unbindDevice(_this);' print r' }' else: print r' if (_this->GetType() == D3D11_DEVICE_CONTEXT_IMMEDIATE) {' print r' d3d11Dumper.bindDevice(_this);' print r' }' # intercept private interfaces if method.name == 'QueryInterface': print r' if (!d3dretrace::overrideQueryInterface(_this, riid, ppvObj, &_result)) {' Retracer.invokeInterfaceMethod(self, interface, method) print r' }' return # create windows as neccessary if method.name == 'CreateSwapChain': print r' d3dretrace::createWindowForSwapChain(pDesc);' if method.name == 'CreateSwapChainForComposition': print r' HWND hWnd = d3dretrace::createWindow(pDesc->Width, pDesc->Height);' print r' _result = _this->CreateSwapChainForHwnd(pDevice, hWnd, pDesc, NULL, pRestrictToOutput, ppSwapChain);' self.checkResult(method.type) return if method.name == 'SetFullscreenState': print r' if (retrace::forceWindowed) {' print r' Fullscreen = FALSE;' print r' pTarget = NULL;' print r' }' # notify frame has been completed if method.name == 'Present': if interface.name == 'IDXGISwapChainDWM': print r' com_ptr<IDXGISwapChain> pSwapChain;' print r' if (SUCCEEDED(_this->QueryInterface(IID_IDXGISwapChain, (void **) &pSwapChain))) {' print r' dxgiDumper.bindDevice(pSwapChain);' print r' } else {' print r' assert(0);' print r' }' else: print r' dxgiDumper.bindDevice(_this);' print r' retrace::frameComplete(call);' if 'pSharedResource' in method.argNames(): print r' if (pSharedResource) {' print r' retrace::warning(call) << "shared surfaces unsupported\n";' print r' pSharedResource = NULL;' print r' }' # Force driver if interface.name.startswith('IDXGIFactory') and method.name.startswith('EnumAdapters'): print r' const char *szSoftware = NULL;' print r' switch (retrace::driver) {' print r' case retrace::DRIVER_REFERENCE:' print r' case retrace::DRIVER_SOFTWARE:' print r' szSoftware = "d3d10warp.dll";' print r' break;' print r' case retrace::DRIVER_MODULE:' print r' szSoftware = retrace::driverModule;' print r' break;' print r' default:' print r' break;' print r' }' print r' HMODULE hSoftware = NULL;' print r' if (szSoftware) {' print r' hSoftware = LoadLibraryA(szSoftware);' print r' if (!hSoftware) {' print r' retrace::warning(call) << "failed to load " << szSoftware << "\n";' print r' }' print r' }' print r' if (hSoftware) {' print r' _result = _this->CreateSoftwareAdapter(hSoftware, reinterpret_cast<IDXGIAdapter **>(ppAdapter));' print r' } else {' Retracer.invokeInterfaceMethod(self, interface, method) print r' }' return if interface.name.startswith('ID3D10Device') and method.name.startswith('OpenSharedResource'): print r' retrace::warning(call) << "replacing shared resource with checker pattern\n";' print r' D3D10_TEXTURE2D_DESC Desc;' print r' memset(&Desc, 0, sizeof Desc);' print r' Desc.Width = 8;' print r' Desc.Height = 8;' print r' Desc.MipLevels = 1;' print r' Desc.ArraySize = 1;' print r' Desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;' print r' Desc.SampleDesc.Count = 1;' print r' Desc.SampleDesc.Quality = 0;' print r' Desc.Usage = D3D10_USAGE_DEFAULT;' print r' Desc.BindFlags = D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET;' print r' Desc.CPUAccessFlags = 0x0;' print r' Desc.MiscFlags = 0 /* D3D10_RESOURCE_MISC_SHARED */;' print r''' static const DWORD Checker[8][8] = { { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U }, {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U }, { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U }, {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U }, { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U }, {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U }, { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U }, {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U } }; static const D3D10_SUBRESOURCE_DATA InitialData = {Checker, sizeof Checker[0], sizeof Checker}; ''' print r' com_ptr<ID3D10Texture2D> pResource;' print r' _result = _this->CreateTexture2D(&Desc, &InitialData, &pResource);' print r' if (SUCCEEDED(_result)) {' print r' _result = pResource->QueryInterface(ReturnedInterface, ppResource);' print r' }' self.checkResult(method.type) return if interface.name.startswith('ID3D11Device') and method.name.startswith('OpenSharedResource'): print r' retrace::warning(call) << "replacing shared resource with checker pattern\n";' print if method.name == 'OpenSharedResourceByName': print r' (void)lpName;' print r' (void)dwDesiredAccess;' print print r' D3D11_TEXTURE2D_DESC Desc;' print r' memset(&Desc, 0, sizeof Desc);' print r' Desc.Width = 8;' print r' Desc.Height = 8;' print r' Desc.MipLevels = 1;' print r' Desc.ArraySize = 1;' print r' Desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;' print r' Desc.SampleDesc.Count = 1;' print r' Desc.SampleDesc.Quality = 0;' print r' Desc.Usage = D3D11_USAGE_DEFAULT;' print r' Desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;' print r' Desc.CPUAccessFlags = 0x0;' print r' Desc.MiscFlags = 0 /* D3D11_RESOURCE_MISC_SHARED */;' print r''' static const DWORD Checker[8][8] = { { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U }, {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U }, { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U }, {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U }, { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U }, {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U }, { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U }, {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U } }; static const D3D11_SUBRESOURCE_DATA InitialData = {Checker, sizeof Checker[0], sizeof Checker}; ''' print r' com_ptr<ID3D11Texture2D> pResource;' print r' _result = _this->CreateTexture2D(&Desc, &InitialData, &pResource);' print r' if (SUCCEEDED(_result)) {' print r' _result = pResource->QueryInterface(ReturnedInterface, ppResource);' print r' }' self.checkResult(method.type) return if method.name == 'Map': # Reset _DO_NOT_WAIT flags. Otherwise they may fail, and we have no # way to cope with it (other than retry). mapFlagsArg = method.getArgByName('MapFlags') for flag in mapFlagsArg.type.values: if flag.endswith('_MAP_FLAG_DO_NOT_WAIT'): print r' MapFlags &= ~%s;' % flag if method.name.startswith('UpdateSubresource'): # The D3D10 debug layer is buggy (or at least inconsistent with the # runtime), as it seems to estimate and enforce the data size based on the # SrcDepthPitch, even for non 3D textures, but in some traces # SrcDepthPitch is garbagge for non 3D textures. # XXX: It also seems to expect padding bytes at the end of the last # row, but we never record (or allocate) those... print r' if (retrace::debug && pDstBox && pDstBox->front == 0 && pDstBox->back == 1) {' print r' SrcDepthPitch = 0;' print r' }' if method.name == 'SetGammaControl': # This method is only supported while in full-screen mode print r' if (retrace::forceWindowed) {' print r' return;' print r' }' Retracer.invokeInterfaceMethod(self, interface, method) # process events after presents if method.name == 'Present': print r' d3dretrace::processEvents();' if method.name in ('Map', 'Unmap'): if interface.name.startswith('ID3D11DeviceContext'): print ' void * & _pbData = g_Maps[_this][SubresourceKey(pResource, Subresource)];' else: subresourceArg = method.getArgByName('Subresource') if subresourceArg is None: print ' UINT Subresource = 0;' print ' void * & _pbData = g_Maps[0][SubresourceKey(_this, Subresource)];' if method.name == 'Map': print ' _MAP_DESC _MapDesc;' print ' _getMapDesc(_this, %s, _MapDesc);' % ', '.join(method.argNames()) print ' size_t _MappedSize = _MapDesc.Size;' print ' if (_MapDesc.Size) {' print ' _pbData = _MapDesc.pData;' if interface.name.startswith('ID3D11DeviceContext'): # XXX: Unforunately this cause many false warnings on 1D and 2D # resources, since the pitches are junk there... #self.checkPitchMismatch(method) pass else: print ' _pbData = _MapDesc.pData;' self.checkPitchMismatch(method) print ' } else {' print ' return;' print ' }' if method.name == 'Unmap': print ' if (_pbData) {' print ' retrace::delRegionByPointer(_pbData);' print ' _pbData = 0;' print ' }' # Attach shader byte code for lookup if 'pShaderBytecode' in method.argNames(): ppShader = method.args[-1] assert ppShader.output print r' if (retrace::dumpingState && SUCCEEDED(_result)) {' print r' (*%s)->SetPrivateData(d3dstate::GUID_D3DSTATE, BytecodeLength, pShaderBytecode);' % ppShader.name print r' }'
def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('ID3D10Device', 'ID3D10Device1'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d10Dumper.unbindDevice(_this);' print r' }' else: print r' d3d10Dumper.bindDevice(_this);' if interface.name in ('ID3D11DeviceContext', 'ID3D11DeviceContext1'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d11Dumper.unbindDevice(_this);' print r' }' else: print r' if (_this->GetType() == D3D11_DEVICE_CONTEXT_IMMEDIATE) {' print r' d3d11Dumper.bindDevice(_this);' print r' }' # intercept private interfaces if method.name == 'QueryInterface': print r' if (!d3dretrace::overrideQueryInterface(_this, riid, ppvObj, &_result)) {' Retracer.invokeInterfaceMethod(self, interface, method) print r' }' return # create windows as neccessary if method.name == 'CreateSwapChain': print r' d3dretrace::createWindowForSwapChain(pDesc);' if method.name == 'CreateSwapChainForComposition': print r' HWND hWnd = d3dretrace::createWindow(pDesc->Width, pDesc->Height);' print r' _result = _this->CreateSwapChainForHwnd(pDevice, hWnd, pDesc, NULL, pRestrictToOutput, ppSwapChain);' self.checkResult(interface, method) return if method.name == 'SetFullscreenState': print r' if (retrace::forceWindowed) {' print r' Fullscreen = FALSE;' print r' pTarget = NULL;' print r' }' # notify frame has been completed if method.name == 'Present': if interface.name == 'IDXGISwapChainDWM': print r' com_ptr<IDXGISwapChain> pSwapChain;' print r' if (SUCCEEDED(_this->QueryInterface(IID_IDXGISwapChain, (void **) &pSwapChain))) {' print r' dxgiDumper.bindDevice(pSwapChain);' print r' } else {' print r' assert(0);' print r' }' else: print r' dxgiDumper.bindDevice(_this);' print r' retrace::frameComplete(call);' if 'pSharedResource' in method.argNames(): print r' if (pSharedResource) {' print r' retrace::warning(call) << "shared surfaces unsupported\n";' print r' pSharedResource = NULL;' print r' }' # Force driver if interface.name.startswith( 'IDXGIFactory') and method.name.startswith('EnumAdapters'): print r' const char *szSoftware = NULL;' print r' switch (retrace::driver) {' print r' case retrace::DRIVER_REFERENCE:' print r' case retrace::DRIVER_SOFTWARE:' print r' szSoftware = "d3d10warp.dll";' print r' break;' print r' case retrace::DRIVER_MODULE:' print r' szSoftware = retrace::driverModule;' print r' break;' print r' default:' print r' break;' print r' }' print r' HMODULE hSoftware = NULL;' print r' if (szSoftware) {' print r' hSoftware = LoadLibraryA(szSoftware);' print r' if (!hSoftware) {' print r' retrace::warning(call) << "failed to load " << szSoftware << "\n";' print r' }' print r' }' print r' if (hSoftware) {' print r' _result = _this->CreateSoftwareAdapter(hSoftware, reinterpret_cast<IDXGIAdapter **>(ppAdapter));' print r' } else {' Retracer.invokeInterfaceMethod(self, interface, method) print r' }' return if interface.name.startswith( 'ID3D10Device') and method.name.startswith( 'OpenSharedResource'): print r' retrace::warning(call) << "replacing shared resource with checker pattern\n";' print r' D3D10_TEXTURE2D_DESC Desc;' print r' memset(&Desc, 0, sizeof Desc);' print r' Desc.Width = 8;' print r' Desc.Height = 8;' print r' Desc.MipLevels = 1;' print r' Desc.ArraySize = 1;' print r' Desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;' print r' Desc.SampleDesc.Count = 1;' print r' Desc.SampleDesc.Quality = 0;' print r' Desc.Usage = D3D10_USAGE_DEFAULT;' print r' Desc.BindFlags = D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET;' print r' Desc.CPUAccessFlags = 0x0;' print r' Desc.MiscFlags = 0 /* D3D10_RESOURCE_MISC_SHARED */;' print r''' static const DWORD Checker[8][8] = { { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U }, {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U }, { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U }, {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U }, { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U }, {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U }, { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U }, {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U } }; static const D3D10_SUBRESOURCE_DATA InitialData = {Checker, sizeof Checker[0], sizeof Checker}; ''' print r' com_ptr<ID3D10Texture2D> pResource;' print r' _result = _this->CreateTexture2D(&Desc, &InitialData, &pResource);' print r' if (SUCCEEDED(_result)) {' print r' _result = pResource->QueryInterface(ReturnedInterface, ppResource);' print r' }' self.checkResult(interface, method) return if interface.name.startswith( 'ID3D11Device') and method.name.startswith( 'OpenSharedResource'): print r' retrace::warning(call) << "replacing shared resource with checker pattern\n";' print if method.name == 'OpenSharedResourceByName': print r' (void)lpName;' print r' (void)dwDesiredAccess;' print print r' D3D11_TEXTURE2D_DESC Desc;' print r' memset(&Desc, 0, sizeof Desc);' print r' Desc.Width = 8;' print r' Desc.Height = 8;' print r' Desc.MipLevels = 1;' print r' Desc.ArraySize = 1;' print r' Desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;' print r' Desc.SampleDesc.Count = 1;' print r' Desc.SampleDesc.Quality = 0;' print r' Desc.Usage = D3D11_USAGE_DEFAULT;' print r' Desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;' print r' Desc.CPUAccessFlags = 0x0;' print r' Desc.MiscFlags = 0 /* D3D11_RESOURCE_MISC_SHARED */;' print r''' static const DWORD Checker[8][8] = { { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U }, {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U }, { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U }, {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U }, { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U }, {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U }, { 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U }, {~0U, 0U, ~0U, 0U, ~0U, 0U, ~0U, 0U } }; static const D3D11_SUBRESOURCE_DATA InitialData = {Checker, sizeof Checker[0], sizeof Checker}; ''' print r' com_ptr<ID3D11Texture2D> pResource;' print r' _result = _this->CreateTexture2D(&Desc, &InitialData, &pResource);' print r' if (SUCCEEDED(_result)) {' print r' _result = pResource->QueryInterface(ReturnedInterface, ppResource);' print r' }' self.checkResult(interface, method) return if method.name == 'Map': # Reset _DO_NOT_WAIT flags. Otherwise they may fail, and we have no # way to cope with it (other than retry). mapFlagsArg = method.getArgByName('MapFlags') for flag in mapFlagsArg.type.values: if flag.endswith('_MAP_FLAG_DO_NOT_WAIT'): print r' MapFlags &= ~%s;' % flag if method.name.startswith('UpdateSubresource'): # The D3D10 debug layer is buggy (or at least inconsistent with the # runtime), as it seems to estimate and enforce the data size based on the # SrcDepthPitch, even for non 3D textures, but in some traces # SrcDepthPitch is garbagge for non 3D textures. # XXX: It also seems to expect padding bytes at the end of the last # row, but we never record (or allocate) those... print r' if (retrace::debug && pDstBox && pDstBox->front == 0 && pDstBox->back == 1) {' print r' SrcDepthPitch = 0;' print r' }' if method.name == 'SetGammaControl': # This method is only supported while in full-screen mode print r' if (retrace::forceWindowed) {' print r' return;' print r' }' Retracer.invokeInterfaceMethod(self, interface, method) # process events after presents if method.name == 'Present': print r' d3dretrace::processEvents();' if method.name in ('Map', 'Unmap'): if interface.name.startswith('ID3D11DeviceContext'): print ' void * & _pbData = g_Maps[_this][SubresourceKey(pResource, Subresource)];' else: subresourceArg = method.getArgByName('Subresource') if subresourceArg is None: print ' UINT Subresource = 0;' print ' void * & _pbData = g_Maps[0][SubresourceKey(_this, Subresource)];' if method.name == 'Map': print ' _MAP_DESC _MapDesc;' print ' _getMapDesc(_this, %s, _MapDesc);' % ', '.join( method.argNames()) print ' size_t _MappedSize = _MapDesc.Size;' print ' if (_MapDesc.Size) {' print ' _pbData = _MapDesc.pData;' if interface.name.startswith('ID3D11DeviceContext'): # XXX: Unforunately this cause many false warnings on 1D and 2D # resources, since the pitches are junk there... #self.checkPitchMismatch(method) pass else: print ' _pbData = _MapDesc.pData;' self.checkPitchMismatch(method) print ' } else {' print ' return;' print ' }' if method.name == 'Unmap': print ' if (_pbData) {' print ' retrace::delRegionByPointer(_pbData);' print ' _pbData = 0;' print ' }' # Attach shader byte code for lookup if 'pShaderBytecode' in method.argNames(): ppShader = method.args[-1] assert ppShader.output print r' if (retrace::dumpingState && SUCCEEDED(_result)) {' print r' (*%s)->SetPrivateData(d3dstate::GUID_D3DSTATE, BytecodeLength, pShaderBytecode);' % ppShader.name print r' }'
def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('IDirect3DDevice9', 'IDirect3DDevice9Ex'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d9Dumper.unbindDevice(_this);' print r' }' else: print r' d3d9Dumper.bindDevice(_this);' if interface.name in ('IDirect3DDevice8', 'IDirect3DDevice8Ex'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d8Dumper.unbindDevice(_this);' print r' }' else: print r' d3d8Dumper.bindDevice(_this);' # create windows as neccessary if method.name in ('CreateDevice', 'CreateDeviceEx', 'CreateAdditionalSwapChain'): print r' HWND hWnd = pPresentationParameters->hDeviceWindow;' if 'hFocusWindow' in method.argNames(): print r' if (hWnd == NULL) {' print r' hWnd = hFocusWindow;' print r' }' print r' hWnd = d3dretrace::createWindow(hWnd, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);' print r' pPresentationParameters->hDeviceWindow = hWnd;' if 'hFocusWindow' in method.argNames(): print r' hFocusWindow = hWnd;' # force windowed mode print r' if (retrace::forceWindowed) {' print r' pPresentationParameters->Windowed = TRUE;' print r' pPresentationParameters->FullScreen_RefreshRateInHz = 0;' if interface.name.startswith('IDirect3D8'): print r' pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;' print r' }' if 'BehaviorFlags' in method.argNames(): print r' if (retrace::dumpingState) {' print r' BehaviorFlags &= ~D3DCREATE_PUREDEVICE;' print r' }' # On D3D8, ensure we use BackBufferFormat compatible with the # current DisplayFormat. # # TODO: BackBufferFormat doesn't need to be always exectly to # DisplayFormat. For example, if DisplayFormat is D3DFMT_X1R5G5B5, # valid values for BackBufferFormat include D3DFMT_X1R5G5B5 and # D3DFMT_A1R5G5B5, but exclude D3DFMT_R5G6B5. if interface.name.startswith('IDirect3D8'): print r' if (pPresentationParameters->Windowed) {' print r' D3DDISPLAYMODE Mode;' print r' HRESULT hr;' print r' hr = _this->GetAdapterDisplayMode(Adapter, &Mode);' print r' assert(SUCCEEDED(hr));' print r' hr = _this->CheckDeviceType(Adapter, DeviceType, Mode.Format, pPresentationParameters->BackBufferFormat, pPresentationParameters->Windowed);' print r' if (hr == D3DERR_NOTAVAILABLE) {' print r' retrace::warning(call) << "forcing back buffer format to match display mode format\n";' print r' pPresentationParameters->BackBufferFormat = Mode.Format;' print r' }' print r' }' if method.name in self.createDeviceMethodNames: # override the device type print r' switch (retrace::driver) {' print r' case retrace::DRIVER_HARDWARE:' print r' DeviceType = D3DDEVTYPE_HAL;' print r' break;' print r' case retrace::DRIVER_SOFTWARE:' print r' case retrace::DRIVER_REFERENCE:' print r' DeviceType = D3DDEVTYPE_REF;' print r' break;' print r' case retrace::DRIVER_NULL:' if interface.name.startswith('IDirect3D9'): print r' DeviceType = D3DDEVTYPE_NULLREF;' else: print r' retrace::warning(call) << "null driver not supported\n";' print r' break;' print r' case retrace::DRIVER_MODULE:' print r' retrace::warning(call) << "driver module not supported\n";' print r' break;' print r' default:' print r' assert(0);' print r' /* fall-through */' print r' case retrace::DRIVER_DEFAULT:' print r' break;' print r' }' if method.name in ('Reset', 'ResetEx'): # force windowed mode print r' if (retrace::forceWindowed) {' print r' pPresentationParameters->Windowed = TRUE;' print r' pPresentationParameters->FullScreen_RefreshRateInHz = 0;' print r' }' # resize window print r' if (pPresentationParameters->Windowed) {' print r' d3dretrace::resizeWindow(pPresentationParameters->hDeviceWindow, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);' print r' }' # notify frame has been completed if method.name in ('Present', 'PresentEx'): if interface.name.startswith('IDirect3DSwapChain9'): print r' d3d9scDumper.bindDevice(_this);' print r' retrace::frameComplete(call);' print r' hDestWindowOverride = NULL;' # Ensure textures can be locked when dumping # TODO: Pre-check with CheckDeviceFormat if method.name in ('CreateTexture', 'CreateCubeTexture', 'CreateVolumeTexture'): print r' if (retrace::dumpingState &&' print r' Pool == D3DPOOL_DEFAULT &&' print r' !(Usage & (D3DUSAGE_RENDERTARGET|D3DUSAGE_DEPTHSTENCIL))) {' print r' Usage |= D3DUSAGE_DYNAMIC;' print r' }' if 'pSharedHandle' in method.argNames(): print r' if (pSharedHandle) {' print r' retrace::warning(call) << "shared surfaces unsupported\n";' print r' pSharedHandle = NULL;' print r' }' if method.name in ('Lock', 'LockRect', 'LockBox'): # Reset _DONOTWAIT flags. Otherwise they may fail, and we have no # way to cope with it (other than retry). mapFlagsArg = method.getArgByName('Flags') for flag in mapFlagsArg.type.values: if flag.endswith('_DONOTWAIT'): print r' Flags &= ~%s;' % flag Retracer.invokeInterfaceMethod(self, interface, method) if method.name in self.createDeviceMethodNames: print r' if (FAILED(_result)) {' print r' exit(1);' print r' }' # process events after presents if method.name == 'Present': print r' d3dretrace::processEvents();' def mapping_subkey(): if 'Level' in method.argNames(): return ('Level', ) else: return ('0', ) if method.name in ('Lock', 'LockRect', 'LockBox'): print ' VOID *_pbData = NULL;' print ' size_t _MappedSize = 0;' print ' if (!(Flags & D3DLOCK_READONLY)) {' print ' _getMapInfo(_this, %s, _pbData, _MappedSize);' % ', '.join( method.argNames()[:-1]) print ' }' print ' if (_MappedSize) {' print ' _maps[MappingKey(_this, %s)] = _pbData;' % mapping_subkey( ) self.checkPitchMismatch(method) print ' } else {' print ' return;' print ' }' if method.name in ('Unlock', 'UnlockRect', 'UnlockBox'): print ' VOID *_pbData = 0;' print ' MappingKey _mappingKey(_this, %s);' % mapping_subkey() print ' _pbData = _maps[_mappingKey];' print ' if (_pbData) {' print ' retrace::delRegionByPointer(_pbData);' print ' _maps[_mappingKey] = 0;' print ' }'
def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('IDirect3DDevice7', ): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d7Dumper.unbindDevice(_this);' print r' }' else: print r' d3d7Dumper.bindDevice(_this);' # create windows as neccessary hWndArg = method.getArgByType(HWND) if hWndArg is not None: # FIXME: Try to guess the window size (e.g., from IDirectDrawSurface7::Blt) print r' if (!g_hWnd) {' print r' g_hWnd = d3dretrace::createWindow(512, 512);' print r' }' print r' %s = g_hWnd;' % hWndArg.name if method.name == 'Lock': # Reset _DONOTWAIT flags. Otherwise they may fail, and we have no # way to cope with it (other than retry). mapFlagsArg = method.getArgByName('dwFlags') if mapFlagsArg is not None: print r' dwFlags &= ~DDLOCK_DONOTWAIT;' print r' dwFlags |= DDLOCK_WAIT;' Retracer.invokeInterfaceMethod(self, interface, method) if method.name == 'CreateDevice': print r' if (FAILED(_result)) {' print r' exit(1);' print r' }' # notify frame has been completed # process events after presents if interface.name == 'IDirectDrawSurface7' and method.name == 'Blt': print r' DDSCAPS2 ddsCaps;' print r' if (SUCCEEDED(_this->GetCaps(&ddsCaps)) &&' print r' (ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) {' print r' retrace::frameComplete(call);' print r' d3dretrace::processEvents();' print r' }' if method.name == 'Lock': print ' VOID *_pbData = NULL;' print ' size_t _MappedSize = 0;' # FIXME: determine the mapping size #print ' _getMapInfo(_this, %s, _pbData, _MappedSize);' % ', '.join(method.argNames()[:-1]) print ' if (_MappedSize) {' print ' _maps[_this] = _pbData;' # TODO: check pitches match print ' } else {' print ' return;' print ' }' if method.name == 'Unlock': print ' VOID *_pbData = 0;' print ' _pbData = _maps[_this];' print ' if (_pbData) {' print ' retrace::delRegionByPointer(_pbData);' print ' _maps[_this] = 0;' print ' }'
def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('IDirect3DDevice9', 'IDirect3DDevice9Ex'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d9Dumper.unbindDevice(_this);' print r' }' else: print r' d3d9Dumper.bindDevice(_this);' if interface.name in ('IDirect3DDevice8', 'IDirect3DDevice8Ex'): if method.name == 'Release': print r' if (call.ret->toUInt() == 0) {' print r' d3d8Dumper.unbindDevice(_this);' print r' }' else: print r' d3d8Dumper.bindDevice(_this);' if method.name in self.createDeviceMethodNames: # override the device type print r' switch (retrace::driver) {' print r' case retrace::DRIVER_HARDWARE:' print r' case retrace::DRIVER_DISCRETE:' print r' case retrace::DRIVER_INTEGRATED:' print r' DeviceType = D3DDEVTYPE_HAL;' print r' break;' print r' case retrace::DRIVER_SOFTWARE:' print r' BehaviorFlags &= ~D3DCREATE_PUREDEVICE;' print r' BehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING;' print r' BehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;' print r' break;' print r' case retrace::DRIVER_REFERENCE:' print r' DeviceType = D3DDEVTYPE_REF;' print r' BehaviorFlags &= ~D3DCREATE_PUREDEVICE;' print r' BehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING;' print r' BehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;' print r' break;' print r' case retrace::DRIVER_NULL:' if interface.name.startswith('IDirect3D9'): print r' DeviceType = D3DDEVTYPE_NULLREF;' else: print r' retrace::warning(call) << "null driver not supported\n";' print r' break;' print r' case retrace::DRIVER_MODULE:' print r' retrace::warning(call) << "driver module not supported\n";' print r' break;' print r' default:' print r' assert(0);' print r' /* fall-through */' print r' case retrace::DRIVER_DEFAULT:' print r' break;' print r' }' # create windows as neccessary if method.name in ('CreateDevice', 'CreateDeviceEx', 'CreateAdditionalSwapChain'): print r' HWND hWnd = pPresentationParameters->hDeviceWindow;' if 'hFocusWindow' in method.argNames(): print r' if (hWnd == NULL) {' print r' hWnd = hFocusWindow;' print r' }' print r' hWnd = d3dretrace::createWindow(hWnd, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);' print r' pPresentationParameters->hDeviceWindow = hWnd;' if 'hFocusWindow' in method.argNames(): print r' hFocusWindow = hWnd;' # force windowed mode print r' if (retrace::forceWindowed) {' print r' pPresentationParameters->Windowed = TRUE;' print r' pPresentationParameters->FullScreen_RefreshRateInHz = 0;' if interface.name.startswith('IDirect3D8'): print r' pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;' print r' }' if 'BehaviorFlags' in method.argNames(): print r' if (retrace::dumpingState) {' print r' BehaviorFlags &= ~D3DCREATE_PUREDEVICE;' print r' }' # On D3D8, ensure we use BackBufferFormat compatible with the # current DisplayFormat. # # TODO: BackBufferFormat doesn't need to be always exectly to # DisplayFormat. For example, if DisplayFormat is D3DFMT_X1R5G5B5, # valid values for BackBufferFormat include D3DFMT_X1R5G5B5 and # D3DFMT_A1R5G5B5, but exclude D3DFMT_R5G6B5. if interface.name.startswith('IDirect3D8'): print r' if (pPresentationParameters->Windowed) {' print r' D3DDISPLAYMODE Mode;' print r' HRESULT hr;' print r' hr = _this->GetAdapterDisplayMode(Adapter, &Mode);' print r' assert(SUCCEEDED(hr));' print r' hr = _this->CheckDeviceType(Adapter, DeviceType, Mode.Format, pPresentationParameters->BackBufferFormat, pPresentationParameters->Windowed);' print r' if (hr == D3DERR_NOTAVAILABLE) {' print r' retrace::warning(call) << "forcing back buffer format to match display mode format\n";' print r' pPresentationParameters->BackBufferFormat = Mode.Format;' print r' }' print r' }' if method.name in ('Reset', 'ResetEx'): # force windowed mode print r' if (retrace::forceWindowed) {' print r' pPresentationParameters->Windowed = TRUE;' print r' pPresentationParameters->FullScreen_RefreshRateInHz = 0;' print r' }' # resize window print r' if (pPresentationParameters->Windowed) {' print r' d3dretrace::resizeWindow(pPresentationParameters->hDeviceWindow, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);' print r' }' # notify frame has been completed if method.name in ('Present', 'PresentEx'): if interface.name.startswith('IDirect3DSwapChain9'): print r' d3d9scDumper.bindDevice(_this);' print r' retrace::frameComplete(call);' print r' hDestWindowOverride = NULL;' # Ensure textures can be locked when dumping # TODO: Pre-check with CheckDeviceFormat if method.name in ('CreateTexture', 'CreateCubeTexture', 'CreateVolumeTexture'): print r' if (retrace::dumpingState &&' print r' Pool == D3DPOOL_DEFAULT &&' print r' !(Usage & (D3DUSAGE_RENDERTARGET|D3DUSAGE_DEPTHSTENCIL))) {' print r' Usage |= D3DUSAGE_DYNAMIC;' print r' }' # Deal with shared surfaces # https://msdn.microsoft.com/en-us/library/windows/desktop/bb219800.aspx # https://msdn.microsoft.com/en-gb/library/windows/desktop/ee913554.aspx pSharedHandleArg = method.getArgByName('pSharedHandle') if pSharedHandleArg: print r' if (pSharedHandle) {' if method.name == 'CreateTexture': # Some applications (e.g., DOTA2) create shared resources within the same process. # https://msdn.microsoft.com/en-us/library/windows/desktop/bb219800.aspx#Textures print r' if (Pool == D3DPOOL_SYSTEMMEM) {' print r' // Ensure the memory stays around.' print r' trace::Blob *blob = call.arg(%u).toArray()->values[0]->toBlob();' % pSharedHandleArg.index print r' if (blob) {' print r' blob->toPointer(true);' print r' } else {' print r' retrace::warning(call) << "invalid system memory\n";' print r' pSharedHandle = NULL;' print r' }' print r' } else {' print r' retrace::warning(call) << "shared surfaces unsupported\n";' print r' pSharedHandle = NULL;' if method.name == 'CreateTexture': print r' }' print r' }' if method.name in ('Lock', 'LockRect', 'LockBox'): # Reset _DONOTWAIT flags. Otherwise they may fail, and we have no # way to cope with it (other than retry). mapFlagsArg = method.getArgByName('Flags') for flag in mapFlagsArg.type.values: if flag.endswith('_DONOTWAIT'): print r' Flags &= ~%s;' % flag Retracer.invokeInterfaceMethod(self, interface, method) # process events after presents if method.name == 'Present': print r' d3dretrace::processEvents();' def mapping_subkey(): # A single texture object might have multiple mappings. This key # allows to tell them apart. if 'FaceType' in method.argNames(): return ('static_cast<UINT>(FaceType) + Level*6',) elif 'Level' in method.argNames(): return ('Level',) else: return ('0',) if method.name in ('Lock', 'LockRect', 'LockBox'): print ' VOID *_pbData = nullptr;' print ' size_t _MappedSize = 0;' if method.name == 'Lock': # Ignore D3DLOCK_READONLY for buffers. # https://github.com/apitrace/apitrace/issues/435 print ' if (true) {' else: print ' if (!(Flags & D3DLOCK_READONLY)) {' print ' _getMapInfo(_this, %s, _pbData, _MappedSize);' % ', '.join(method.argNames()[:-1]) print ' }' print ' if (_MappedSize) {' print ' _maps[MappingKey(_this, %s)] = _pbData;' % mapping_subkey() self.checkPitchMismatch(method) print ' } else {' print ' return;' print ' }' if method.name in ('Unlock', 'UnlockRect', 'UnlockBox'): print ' VOID *_pbData = nullptr;' print ' MappingKey _mappingKey(_this, %s);' % mapping_subkey() print ' _pbData = _maps[_mappingKey];' print ' if (_pbData) {' print ' retrace::delRegionByPointer(_pbData);' print ' _maps[_mappingKey] = nullptr;' print ' }' if interface.name == 'IDirectXVideoDecoder': if method.name == 'GetBuffer': print ' if (*ppBuffer && *pBufferSize) {' print ' _maps[MappingKey(_this, BufferType)] = *ppBuffer;' print ' }' if method.name == 'ReleaseBuffer': print ' MappingKey _mappingKey(_this, BufferType);' print ' void *_pBuffer = _maps[_mappingKey];' print ' if (_pBuffer) {' print ' retrace::delRegionByPointer(_pBuffer);' print ' _maps[_mappingKey] = nullptr;' print ' }'
def invokeInterfaceMethod(self, interface, method): # keep track of the last used device for state dumping if interface.name in ('ID3D10Device', 'ID3D10Device1'): if method.name == 'Release': print r' d3d10Dumper.unbindDevice(_this);' else: print r' d3d10Dumper.bindDevice(_this);' if interface.name in ('ID3D11DeviceContext', 'ID3D11DeviceContext1'): if method.name == 'Release': print r' d3d11Dumper.unbindDevice(_this);' else: print r' d3d11Dumper.bindDevice(_this);' if interface.name == 'IDXGIFactory' and method.name == 'QueryInterface': print r' if (riid == IID_IDXGIFactoryDWM) {' print r' _this->AddRef();' print r' *ppvObj = new d3dretrace::CDXGIFactoryDWM(_this);' print r' _result = S_OK;' print r' } else {' Retracer.invokeInterfaceMethod(self, interface, method) print r' }' return # create windows as neccessary if method.name == 'CreateSwapChain': print r' createWindow(pDesc);' # notify frame has been completed if method.name == 'Present': print r' retrace::frameComplete(call);' if 'pSharedResource' in method.argNames(): print r' if (pSharedResource) {' print r' retrace::warning(call) << "shared surfaces unsupported\n";' print r' pSharedResource = NULL;' print r' }' # Force driver if interface.name.startswith( 'IDXGIFactory') and method.name == 'EnumAdapters': print r' const char *szSoftware = NULL;' print r' switch (retrace::driver) {' print r' case retrace::DRIVER_REFERENCE:' print r' case retrace::DRIVER_SOFTWARE:' print r' szSoftware = "d3d10warp.dll";' print r' break;' print r' case retrace::DRIVER_MODULE:' print r' szSoftware = retrace::driverModule;' print r' break;' print r' default:' print r' break;' print r' }' print r' HMODULE hSoftware = NULL;' print r' if (szSoftware) {' print r' hSoftware = LoadLibraryA(szSoftware);' print r' if (!hSoftware) {' print r' retrace::warning(call) << "failed to load " << szSoftware << "\n";' print r' }' print r' }' print r' if (hSoftware) {' print r' _result = _this->CreateSoftwareAdapter(hSoftware, ppAdapter);' print r' } else {' Retracer.invokeInterfaceMethod(self, interface, method) print r' }' return if interface.name.startswith( 'ID3D10Device') and method.name == 'OpenSharedResource': print r' retrace::warning(call) << "replacing shared resource with checker pattern\n";' print r' D3D10_TEXTURE2D_DESC Desc;' print r' memset(&Desc, 0, sizeof Desc);' print r' Desc.Width = 8;' print r' Desc.Height = 8;' print r' Desc.MipLevels = 1;' print r' Desc.ArraySize = 1;' print r' Desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;' print r' Desc.SampleDesc.Count = 1;' print r' Desc.SampleDesc.Quality = 0;' print r' Desc.Usage = D3D10_USAGE_DEFAULT;' print r' Desc.BindFlags = D3D10_BIND_SHADER_RESOURCE | D3D10_BIND_RENDER_TARGET;' print r' Desc.CPUAccessFlags = 0x0;' print r' Desc.MiscFlags = 0 /* D3D10_RESOURCE_MISC_SHARED */;' print r''' const DWORD Checker[8][8] = { { 0, ~0, 0, ~0, 0, ~0, 0, ~0, }, {~0, 0, ~0, 0, ~0, 0, ~0, 0, }, { 0, ~0, 0, ~0, 0, ~0, 0, ~0, }, {~0, 0, ~0, 0, ~0, 0, ~0, 0, }, { 0, ~0, 0, ~0, 0, ~0, 0, ~0, }, {~0, 0, ~0, 0, ~0, 0, ~0, 0, }, { 0, ~0, 0, ~0, 0, ~0, 0, ~0, }, {~0, 0, ~0, 0, ~0, 0, ~0, 0, } }; const D3D10_SUBRESOURCE_DATA InitialData = {Checker, sizeof Checker[0], sizeof Checker}; ''' print r' _result = _this->CreateTexture2D(&Desc, &InitialData, (ID3D10Texture2D**)ppResource);' self.checkResult(method.type) return if method.name == 'Map': # Reset _DO_NOT_WAIT flags. Otherwise they may fail, and we have no # way to cope with it (other than retry). mapFlagsArg = method.getArgByName('MapFlags') for flag in mapFlagsArg.type.values: if flag.endswith('_MAP_FLAG_DO_NOT_WAIT'): print r' MapFlags &= ~%s;' % flag Retracer.invokeInterfaceMethod(self, interface, method) # process events after presents if method.name == 'Present': print r' d3dretrace::processEvents();' if method.name == 'Map': print ' VOID *_pbData = NULL;' print ' size_t _MappedSize = 0;' print ' _getMapInfo(_this, %s, _pbData, _MappedSize);' % ', '.join( method.argNames()) print ' if (_MappedSize) {' print ' _maps[_this] = _pbData;' print ' } else {' print ' return;' print ' }' if method.name == 'Unmap': print ' VOID *_pbData = 0;' print ' _pbData = _maps[_this];' print ' if (_pbData) {' print ' retrace::delRegionByPointer(_pbData);' print ' _maps[_this] = 0;' print ' }' # Attach shader byte code for lookup if 'pShaderBytecode' in method.argNames(): ppShader = method.args[-1] assert ppShader.output print r' if (retrace::dumpingState && SUCCEEDED(_result)) {' print r' (*%s)->SetPrivateData(d3dstate::GUID_D3DSTATE, BytecodeLength, pShaderBytecode);' % ppShader.name print r' }'