From: José Fonseca Date: Wed, 14 Nov 2012 11:46:58 +0000 (+0000) Subject: d3dretrace: Basic D3D11 snap-shooting. X-Git-Url: https://git.cworth.org/git?p=apitrace;a=commitdiff_plain;h=5773beb571a3a696b4020aee5d3ce1a47efd81be d3dretrace: Basic D3D11 snap-shooting. --- diff --git a/retrace/CMakeLists.txt b/retrace/CMakeLists.txt index 5a46d3e..bc2c303 100644 --- a/retrace/CMakeLists.txt +++ b/retrace/CMakeLists.txt @@ -147,25 +147,29 @@ if (WIN32 AND DirectX_D3DX9_INCLUDE_DIR) if (DirectX_D3D10_INCLUDE_DIR) include_directories (SYSTEM ${DirectX_D3D10_INCLUDE_DIR}) - set (MODULES d3d10) + set (D3D10_MODULES d3d10) if (DirectX_D3D10_1_INCLUDE_DIR) include_directories (SYSTEM ${DirectX_D3D10_1_INCLUDE_DIR}) - set (MODULES ${MODULES} d3d10_1) + set (D3D10_MODULES ${D3D10_MODULES} d3d10_1) endif () endif () if (DirectX_D3D11_INCLUDE_DIR) include_directories (SYSTEM ${DirectX_D3D11_INCLUDE_DIR}) - set (MODULES ${MODULES} d3d11) + set (D3D10_MODULES ${D3D10_MODULES} d3d11) if (DirectX_D3D11_1_INCLUDE_DIR) include_directories (SYSTEM ${DirectX_D3D11_1_INCLUDE_DIR}) - set (MODULES ${MODULES} d3d11_1) + set (D3D10_MODULES ${D3D10_MODULES} d3d11_1) endif () + set (D3D11STATE_SOURCES + d3d11state.cpp + d3d11state_images.cpp + ) endif () add_custom_command ( OUTPUT d3dretrace_d3d10.cpp - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3dcommonretrace.py ${MODULES} > ${CMAKE_CURRENT_BINARY_DIR}/d3dretrace_d3d10.cpp + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3dcommonretrace.py ${D3D10_MODULES} > ${CMAKE_CURRENT_BINARY_DIR}/d3dretrace_d3d10.cpp DEPENDS d3dcommonretrace.py dllretrace.py @@ -195,6 +199,7 @@ if (WIN32 AND DirectX_D3DX9_INCLUDE_DIR) d3dretrace_ws.cpp d3d9state.cpp d3d9state_images.cpp + ${D3D11STATE_SOURCES} ) target_link_libraries (d3dretrace retrace_common diff --git a/retrace/d3d11state.cpp b/retrace/d3d11state.cpp new file mode 100644 index 0000000..602f05f --- /dev/null +++ b/retrace/d3d11state.cpp @@ -0,0 +1,47 @@ +/************************************************************************** + * + * Copyright 2011 Jose Fonseca + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + **************************************************************************/ + + +#include + +#include + +#include "d3d11imports.hpp" +#include "json.hpp" + + +namespace d3dstate { + + +void +dumpDevice(std::ostream &os, ID3D11DeviceContext *pDevice) +{ + JSONWriter json(os); + + /* TODO */ +} + + +} /* namespace d3dstate */ diff --git a/retrace/d3d11state_images.cpp b/retrace/d3d11state_images.cpp new file mode 100644 index 0000000..6e0d7c9 --- /dev/null +++ b/retrace/d3d11state_images.cpp @@ -0,0 +1,263 @@ +/************************************************************************** + * + * Copyright 2011 Jose Fonseca + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + **************************************************************************/ + + +#include + +#include +#include + +#include "image.hpp" +#include "d3d11imports.hpp" + + +namespace d3dstate { + +static HRESULT +stageResource(ID3D11DeviceContext *pDeviceContext, + ID3D11Resource *pResource, + ID3D11Resource **ppStagingResource, + UINT *pWidth, UINT *pHeight, UINT *pDepth) { + D3D11_USAGE Usage = D3D11_USAGE_STAGING; + UINT BindFlags = 0; + UINT CPUAccessFlags = D3D11_CPU_ACCESS_READ; + UINT MiscFlags = 0; + union { + ID3D11Resource *pStagingResource; + ID3D11Buffer *pStagingBuffer; + ID3D11Texture1D *pStagingTexture1D; + ID3D11Texture2D *pStagingTexture2D; + ID3D11Texture3D *pStagingTexture3D; + }; + HRESULT hr; + + ID3D11Device *pDevice = NULL; + pDeviceContext->GetDevice(&pDevice); + + D3D11_RESOURCE_DIMENSION Type = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pResource->GetType(&Type); + switch (Type) { + case D3D11_RESOURCE_DIMENSION_BUFFER: + { + D3D11_BUFFER_DESC Desc; + static_cast(pResource)->GetDesc(&Desc); + Desc.Usage = Usage; + Desc.BindFlags = BindFlags; + Desc.CPUAccessFlags = CPUAccessFlags; + Desc.MiscFlags = MiscFlags; + + *pWidth = Desc.ByteWidth; + *pHeight = 1; + *pDepth = 1; + + hr = pDevice->CreateBuffer(&Desc, NULL, &pStagingBuffer); + } + break; + case D3D11_RESOURCE_DIMENSION_TEXTURE1D: + { + D3D11_TEXTURE1D_DESC Desc; + static_cast(pResource)->GetDesc(&Desc); + Desc.Usage = Usage; + Desc.BindFlags = BindFlags; + Desc.CPUAccessFlags = CPUAccessFlags; + Desc.MiscFlags = MiscFlags; + + *pWidth = Desc.Width; + *pHeight = 1; + *pDepth = 1; + + hr = pDevice->CreateTexture1D(&Desc, NULL, &pStagingTexture1D); + } + break; + case D3D11_RESOURCE_DIMENSION_TEXTURE2D: + { + D3D11_TEXTURE2D_DESC Desc; + static_cast(pResource)->GetDesc(&Desc); + Desc.Usage = Usage; + Desc.BindFlags = BindFlags; + Desc.CPUAccessFlags = CPUAccessFlags; + Desc.MiscFlags &= ~D3D11_RESOURCE_MISC_TEXTURECUBE; + + *pWidth = Desc.Width; + *pHeight = Desc.Height; + *pDepth = 1; + + hr = pDevice->CreateTexture2D(&Desc, NULL, &pStagingTexture2D); + } + break; + case D3D11_RESOURCE_DIMENSION_TEXTURE3D: + { + D3D11_TEXTURE3D_DESC Desc; + static_cast(pResource)->GetDesc(&Desc); + Desc.Usage = Usage; + Desc.BindFlags = BindFlags; + Desc.CPUAccessFlags = CPUAccessFlags; + Desc.MiscFlags = MiscFlags; + + *pWidth = Desc.Width; + *pHeight = Desc.Height; + *pDepth = Desc.Depth; + + hr = pDevice->CreateTexture3D(&Desc, NULL, &pStagingTexture3D); + } + break; + default: + assert(0); + hr = E_NOTIMPL; + break; + } + + if (SUCCEEDED(hr)) { + *ppStagingResource = pStagingResource; + pDeviceContext->CopyResource(pStagingResource, pResource); + } + + pDevice->Release(); + + return hr; +} + +image::Image * +getRenderTargetImage(ID3D11DeviceContext *pDevice) { + image::Image *image = NULL; + ID3D11RenderTargetView *pRenderTargetView = NULL; + D3D11_RENDER_TARGET_VIEW_DESC Desc; + ID3D11Resource *pResource = NULL; + ID3D11Resource *pStagingResource = NULL; + UINT Width, Height, Depth; + UINT MipSlice; + UINT Subresource; + D3D11_MAPPED_SUBRESOURCE MappedSubresource; + HRESULT hr; + const unsigned char *src; + unsigned char *dst; + + pDevice->OMGetRenderTargets(1, &pRenderTargetView, NULL); + if (!pRenderTargetView) { + goto no_rendertarget; + } + + pRenderTargetView->GetResource(&pResource); + assert(pResource); + + pRenderTargetView->GetDesc(&Desc); + if (Desc.Format != DXGI_FORMAT_R8G8B8A8_UNORM && + Desc.Format != DXGI_FORMAT_R32G32B32A32_FLOAT) { + std::cerr << "warning: unsupported DXGI format " << Desc.Format << "\n"; + goto no_staging; + } + + hr = stageResource(pDevice, pResource, &pStagingResource, &Width, &Height, &Depth); + if (FAILED(hr)) { + goto no_staging; + } + + // TODO: Take the slice in consideration + switch (Desc.ViewDimension) { + case D3D11_RTV_DIMENSION_BUFFER: + MipSlice = 0; + break; + case D3D11_RTV_DIMENSION_TEXTURE1D: + MipSlice = Desc.Texture1D.MipSlice; + break; + case D3D11_RTV_DIMENSION_TEXTURE1DARRAY: + MipSlice = Desc.Texture1DArray.MipSlice; + break; + case D3D11_RTV_DIMENSION_TEXTURE2D: + MipSlice = Desc.Texture2D.MipSlice; + MipSlice = 0; + break; + case D3D11_RTV_DIMENSION_TEXTURE2DARRAY: + MipSlice = Desc.Texture2DArray.MipSlice; + break; + case D3D11_RTV_DIMENSION_TEXTURE2DMS: + MipSlice = 0; + break; + case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY: + MipSlice = 0; + break; + case D3D11_RTV_DIMENSION_TEXTURE3D: + MipSlice = Desc.Texture3D.MipSlice; + break; + case D3D11_SRV_DIMENSION_UNKNOWN: + default: + assert(0); + goto no_map; + } + Subresource = MipSlice; + + Width = std::max(Width >> MipSlice, 1U); + Height = std::max(Height >> MipSlice, 1U); + Depth = std::max(Depth >> MipSlice, 1U); + + hr = pDevice->Map(pStagingResource, Subresource, D3D11_MAP_READ, 0, &MappedSubresource); + if (FAILED(hr)) { + goto no_map; + } + + image = new image::Image(Width, Height, 4, true); + if (!image) { + goto no_image; + } + + dst = image->start(); + src = (const unsigned char *)MappedSubresource.pData; + for (unsigned y = 0; y < Height; ++y) { + if (Desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM) { + memcpy(dst, src, Width * 4); + } else if (Desc.Format == DXGI_FORMAT_R32G32B32A32_FLOAT) { + float scale = 1.0f/255.0f; + for (unsigned x = 0; x < Width; ++x) { + dst[4*x + 0] = ((float *)src)[4*x + 0] * scale; + dst[4*x + 1] = ((float *)src)[4*x + 1] * scale; + dst[4*x + 2] = ((float *)src)[4*x + 2] * scale; + dst[4*x + 3] = ((float *)src)[4*x + 3] * scale; + } + } else { + assert(0); + } + src += MappedSubresource.RowPitch; + dst += image->stride(); + } + +no_image: + pDevice->Unmap(pStagingResource, Subresource); +no_map: + if (pStagingResource) { + pStagingResource->Release(); + } +no_staging: + if (pResource) { + pResource->Release(); + } + if (pRenderTargetView) { + pRenderTargetView->Release(); + } +no_rendertarget: + return image; +} + + +} /* namespace d3dstate */ diff --git a/retrace/d3d9retrace.py b/retrace/d3d9retrace.py index 9884d92..7c292f9 100644 --- a/retrace/d3d9retrace.py +++ b/retrace/d3d9retrace.py @@ -35,49 +35,8 @@ from specs.d3d9 import * class D3DRetracer(Retracer): def retraceApi(self, api): - print ''' - -class D3D9Dumper : public retrace::Dumper { -public: - IDirect3DDevice9 *pLastDirect3DDevice9; - - D3D9Dumper() : - pLastDirect3DDevice9(NULL) - {} - - image::Image * - getSnapshot(void) { - if (!pLastDirect3DDevice9) { - return NULL; - } - return d3dstate::getRenderTargetImage(pLastDirect3DDevice9); - } - - bool - dumpState(std::ostream &os) { - if (!pLastDirect3DDevice9) { - return false; - } - d3dstate::dumpDevice(os, pLastDirect3DDevice9); - return true; - } - - inline void - bindDevice(IDirect3DDevice9 *pDevice) { - pLastDirect3DDevice9 = pDevice; - retrace::dumper = this; - } - - inline void - unbindDevice(IDirect3DDevice9 *pDevice) { - if (pLastDirect3DDevice9 == pDevice) { - pLastDirect3DDevice9 = NULL; - } - } -}; - -static D3D9Dumper d3d9Dumper; -''' + print '''static d3dretrace::D3DDumper d3d9Dumper;''' + print print '// Swizzling mapping for lock addresses' print 'static std::map _maps;' @@ -167,7 +126,7 @@ if __name__ == '__main__': #include "d3d9imports.hpp" #include "d3d9size.hpp" #include "d3dretrace.hpp" -#include "d3d9state.hpp" +#include "d3dstate.hpp" ''' diff --git a/retrace/d3d9state.hpp b/retrace/d3d9state.hpp deleted file mode 100644 index 053e7df..0000000 --- a/retrace/d3d9state.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/************************************************************************** - * - * Copyright 2011 Jose Fonseca - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - **************************************************************************/ - -#ifndef _D3D9STATE_HPP_ -#define _D3D9STATE_HPP_ - - -#include - - -struct IDirect3DDevice9; - - -namespace image { - class Image; -} - - -namespace d3dstate { - - -image::Image * -getRenderTargetImage(IDirect3DDevice9 *pDevice); - - -void -dumpDevice(std::ostream &os, IDirect3DDevice9 *pDevice); - - -} /* namespace d3dstate */ - - -#endif /* _D3DSTATE_HPP_ */ diff --git a/retrace/d3dcommonretrace.py b/retrace/d3dcommonretrace.py index add1a50..d3d68d1 100644 --- a/retrace/d3dcommonretrace.py +++ b/retrace/d3dcommonretrace.py @@ -63,8 +63,11 @@ class D3DRetracer(Retracer): 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;' + 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': @@ -135,7 +138,12 @@ def main(): print '#include ' import specs.d3d11_1 print r'#include "d3d11size.hpp"' + print r'#include "d3dstate.hpp"' api.addModule(d3d11) + + print + print '''static d3dretrace::D3DDumper d3d11Dumper;''' + print retracer = D3DRetracer() retracer.retraceApi(api) diff --git a/retrace/d3dretrace.hpp b/retrace/d3dretrace.hpp index 5a45d36..144a5c4 100644 --- a/retrace/d3dretrace.hpp +++ b/retrace/d3dretrace.hpp @@ -30,6 +30,7 @@ #include #include "retrace.hpp" +#include "d3dstate.hpp" namespace d3dretrace { @@ -39,6 +40,47 @@ extern const retrace::Entry d3d9_callbacks[]; extern const retrace::Entry d3d10_callbacks[]; +template< class Device > +class D3DDumper : public retrace::Dumper { +public: + Device *pLastDevice; + + D3DDumper() : + pLastDevice(NULL) + {} + + image::Image * + getSnapshot(void) { + if (!pLastDevice) { + return NULL; + } + return d3dstate::getRenderTargetImage(pLastDevice); + } + + bool + dumpState(std::ostream &os) { + if (!pLastDevice) { + return false; + } + d3dstate::dumpDevice(os, pLastDevice); + return true; + } + + inline void + bindDevice(Device *pDevice) { + pLastDevice = pDevice; + retrace::dumper = this; + } + + inline void + unbindDevice(Device *pDevice) { + if (pLastDevice == pDevice) { + pLastDevice = NULL; + } + } +}; + + HWND createWindow(int width, int height); diff --git a/retrace/d3dretrace_main.cpp b/retrace/d3dretrace_main.cpp index 440d5b1..e62b761 100644 --- a/retrace/d3dretrace_main.cpp +++ b/retrace/d3dretrace_main.cpp @@ -28,7 +28,7 @@ #include "os_string.hpp" -#include "d3d9state.hpp" +#include "d3dstate.hpp" #include "retrace.hpp" #include "d3dretrace.hpp" diff --git a/retrace/d3dstate.hpp b/retrace/d3dstate.hpp new file mode 100644 index 0000000..941d82d --- /dev/null +++ b/retrace/d3dstate.hpp @@ -0,0 +1,62 @@ +/************************************************************************** + * + * Copyright 2011 Jose Fonseca + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + **************************************************************************/ + +#ifndef _D3DSTATE_HPP_ +#define _D3DSTATE_HPP_ + + +#include + + +struct IDirect3DDevice9; +struct ID3D11DeviceContext; + + +namespace image { + class Image; +} + + +namespace d3dstate { + + +image::Image * +getRenderTargetImage(IDirect3DDevice9 *pDevice); + +void +dumpDevice(std::ostream &os, IDirect3DDevice9 *pDevice); + + +image::Image * +getRenderTargetImage(ID3D11DeviceContext *pDeviceContext); + +void +dumpDevice(std::ostream &os, ID3D11DeviceContext *pDeviceContext); + + +} /* namespace d3dstate */ + + +#endif /* _D3DSTATE_HPP_ */