diff options
Diffstat (limited to 'retrace/dxgistate.cpp')
-rw-r--r-- | retrace/dxgistate.cpp | 421 |
1 files changed, 421 insertions, 0 deletions
diff --git a/retrace/dxgistate.cpp b/retrace/dxgistate.cpp index 3cf4c746..d69f2421 100644 --- a/retrace/dxgistate.cpp +++ b/retrace/dxgistate.cpp @@ -29,8 +29,13 @@ #include <iostream> #include "image.hpp" +#include "state_writer.hpp" +#include "com_ptr.hpp" #include "dxgistate.hpp" +#include "d3d10state.hpp" +#include "d3d11state.hpp" +#include "d3d11imports.hpp" #ifdef __MINGW32__ #define nullptr NULL @@ -252,6 +257,30 @@ ConvertImage(DXGI_FORMAT SrcFormat, unsigned numChannels; image::ChannelType channelType; + // DirectXTex doesn't support the typeless depth-stencil variants + switch (SrcFormat) { + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + SrcFormat = DXGI_FORMAT_D24_UNORM_S8_UINT; + break; + + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + // FIXME: This will dump the depth-channel. It would be more + // adequate to dump the stencil channel, but we can't achieve + // that with DirectXTex. + SrcFormat = DXGI_FORMAT_D24_UNORM_S8_UINT; + break; + + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + SrcFormat = DXGI_FORMAT_D32_FLOAT_S8X24_UINT; + break; + + default: + break; + } + DXGI_FORMAT DstFormat = ChooseConversionFormat(SrcFormat, numChannels, channelType); if (DstFormat == DXGI_FORMAT_UNKNOWN) { return NULL; @@ -278,4 +307,396 @@ ConvertImage(DXGI_FORMAT SrcFormat, return image; } + +image::Image * +getRenderTargetImage(IDXGISwapChain *pSwapChain) +{ + HRESULT hr; + + assert(pSwapChain); + if (!pSwapChain) { + return NULL; + } + + DXGI_SWAP_CHAIN_DESC Desc; + hr = pSwapChain->GetDesc(&Desc); + assert(SUCCEEDED(hr)); + + DXGI_FORMAT Format = Desc.BufferDesc.Format; + + /* + * There is a IDXGISurface::Map method, but swapchains are not normally mappable, + * and there is no way to copy into a staging resource, which effectively means there + * is no way to read a IDXGISwapChain using DXGI interfaces alone. + * + * We must figure out + * the appropriate D3D10/D3D11 interfaces, and use them instead. + */ + + com_ptr<ID3D11Device1> pD3D11Device1; + hr = pSwapChain->GetDevice(IID_ID3D11Device1, (void **)&pD3D11Device1); + if (SUCCEEDED(hr)) { + /* + * With D3D11.1 runtime (that comes with Windows 8 and Windows 7 + * Platform Update), we can no longer guess the device interface based + * on the success of GetDevice, since it will always succeed regardless + * the requested device interface, but the returned device maight be + * inactive/lockedout, and attempt to use it will cause the call to be + * ignored, though a debug runtime will issue a + * DEVICE_LOCKEDOUT_INTERFACE warning. + * + * See also: + * - https://msdn.microsoft.com/en-us/library/windows/desktop/hh404583.aspx + * - https://social.msdn.microsoft.com/Forums/en-US/c482bcec-b094-4df0-9253-9c496b115beb/d3d11-runtime-assertion-when-using-graphics-debugger-and-other-applications-may-be-intercepting?forum=wingameswithdirectx + */ + com_ptr<ID3D11Resource> pD3D11Resource; + hr = pSwapChain->GetBuffer(0, IID_ID3D11Resource, (void **)&pD3D11Resource); + assert(SUCCEEDED(hr)); + if (FAILED(hr)) { + return NULL; + } + + com_ptr<ID3D11DeviceContext1> pD3D11DeviceContext; + pD3D11Device1->GetImmediateContext1(&pD3D11DeviceContext); + + UINT Flags = 0; + UINT DeviceFlags = pD3D11Device1->GetCreationFlags(); + if (DeviceFlags & D3D11_CREATE_DEVICE_SINGLETHREADED) { + Flags |= D3D11_1_CREATE_DEVICE_CONTEXT_STATE_SINGLETHREADED; + } + D3D_FEATURE_LEVEL FeatureLevel = pD3D11Device1->GetFeatureLevel(); + + com_ptr<ID3DDeviceContextState> pState; + hr = pD3D11Device1->CreateDeviceContextState(Flags, &FeatureLevel, 1, D3D11_SDK_VERSION, IID_ID3D11Device1, NULL, &pState); + if (SUCCEEDED(hr)) { + com_ptr<ID3DDeviceContextState> pPreviousState; + pD3D11DeviceContext->SwapDeviceContextState(pState, &pPreviousState); + + image::Image *image; + image = getSubResourceImage(pD3D11DeviceContext, pD3D11Resource, Format, 0, 0); + + pD3D11DeviceContext->SwapDeviceContextState(pPreviousState, NULL); + + return image; + } + } + + com_ptr<ID3D11Device> pD3D11Device; + hr = pSwapChain->GetDevice(IID_ID3D11Device, (void **)&pD3D11Device); + if (SUCCEEDED(hr)) { + com_ptr<ID3D11Resource> pD3D11Resource; + hr = pSwapChain->GetBuffer(0, IID_ID3D11Resource, (void **)&pD3D11Resource); + assert(SUCCEEDED(hr)); + if (FAILED(hr)) { + return NULL; + } + + com_ptr<ID3D11DeviceContext> pD3D11DeviceContext; + pD3D11Device->GetImmediateContext(&pD3D11DeviceContext); + + return getSubResourceImage(pD3D11DeviceContext, pD3D11Resource, Format, 0, 0); + } + + com_ptr<ID3D10Device> pD3D10Device; + hr = pSwapChain->GetDevice(IID_ID3D10Device, (void **)&pD3D10Device); + if (SUCCEEDED(hr)) { + com_ptr<ID3D10Resource> pD3D10Resource; + hr = pSwapChain->GetBuffer(0, IID_ID3D10Resource, (void **)&pD3D10Resource); + assert(SUCCEEDED(hr)); + if (FAILED(hr)) { + return NULL; + } + + return getSubResourceImage(pD3D10Device, pD3D10Resource, Format, 0, 0); + } + + return NULL; +} + + +void +dumpDevice(StateWriter &writer, IDXGISwapChain *pSwapChain) +{ + HRESULT hr; + + if (pSwapChain) { + com_ptr<ID3D10Device> pD3D10Device; + hr = pSwapChain->GetDevice(IID_ID3D10Device, (void **)&pD3D10Device); + if (SUCCEEDED(hr)) { + dumpDevice(writer, pD3D10Device); + return; + } + + com_ptr<ID3D11Device> pD3D11Device; + hr = pSwapChain->GetDevice(IID_ID3D11Device, (void **)&pD3D11Device); + if (SUCCEEDED(hr)) { + com_ptr<ID3D11DeviceContext> pD3D11DeviceContext; + pD3D11Device->GetImmediateContext(&pD3D11DeviceContext); + dumpDevice(writer, pD3D11DeviceContext); + return; + } + } + + // Fallback -- this should really never happen. + assert(0); + writer.beginMember("framebuffer"); + writer.beginObject(); + if (pSwapChain) { + image::Image *image; + image = getRenderTargetImage(pSwapChain); + if (image) { + writer.beginMember("SWAP_CHAIN"); + writer.writeImage(image); + writer.endMember(); + delete image; + } + } + writer.endObject(); + writer.endMember(); // framebuffer +} + + +std::string +getDXGIFormatName(DXGI_FORMAT format) +{ + switch (format) { + case DXGI_FORMAT_UNKNOWN: + return "DXGI_FORMAT_UNKNOWN"; + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + return "DXGI_FORMAT_R32G32B32A32_TYPELESS"; + case DXGI_FORMAT_R32G32B32A32_FLOAT: + return "DXGI_FORMAT_R32G32B32A32_FLOAT"; + case DXGI_FORMAT_R32G32B32A32_UINT: + return "DXGI_FORMAT_R32G32B32A32_UINT"; + case DXGI_FORMAT_R32G32B32A32_SINT: + return "DXGI_FORMAT_R32G32B32A32_SINT"; + case DXGI_FORMAT_R32G32B32_TYPELESS: + return "DXGI_FORMAT_R32G32B32_TYPELESS"; + case DXGI_FORMAT_R32G32B32_FLOAT: + return "DXGI_FORMAT_R32G32B32_FLOAT"; + case DXGI_FORMAT_R32G32B32_UINT: + return "DXGI_FORMAT_R32G32B32_UINT"; + case DXGI_FORMAT_R32G32B32_SINT: + return "DXGI_FORMAT_R32G32B32_SINT"; + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + return "DXGI_FORMAT_R16G16B16A16_TYPELESS"; + case DXGI_FORMAT_R16G16B16A16_FLOAT: + return "DXGI_FORMAT_R16G16B16A16_FLOAT"; + case DXGI_FORMAT_R16G16B16A16_UNORM: + return "DXGI_FORMAT_R16G16B16A16_UNORM"; + case DXGI_FORMAT_R16G16B16A16_UINT: + return "DXGI_FORMAT_R16G16B16A16_UINT"; + case DXGI_FORMAT_R16G16B16A16_SNORM: + return "DXGI_FORMAT_R16G16B16A16_SNORM"; + case DXGI_FORMAT_R16G16B16A16_SINT: + return "DXGI_FORMAT_R16G16B16A16_SINT"; + case DXGI_FORMAT_R32G32_TYPELESS: + return "DXGI_FORMAT_R32G32_TYPELESS"; + case DXGI_FORMAT_R32G32_FLOAT: + return "DXGI_FORMAT_R32G32_FLOAT"; + case DXGI_FORMAT_R32G32_UINT: + return "DXGI_FORMAT_R32G32_UINT"; + case DXGI_FORMAT_R32G32_SINT: + return "DXGI_FORMAT_R32G32_SINT"; + case DXGI_FORMAT_R32G8X24_TYPELESS: + return "DXGI_FORMAT_R32G8X24_TYPELESS"; + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + return "DXGI_FORMAT_D32_FLOAT_S8X24_UINT"; + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + return "DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS"; + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + return "DXGI_FORMAT_X32_TYPELESS_G8X24_UINT"; + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + return "DXGI_FORMAT_R10G10B10A2_TYPELESS"; + case DXGI_FORMAT_R10G10B10A2_UNORM: + return "DXGI_FORMAT_R10G10B10A2_UNORM"; + case DXGI_FORMAT_R10G10B10A2_UINT: + return "DXGI_FORMAT_R10G10B10A2_UINT"; + case DXGI_FORMAT_R11G11B10_FLOAT: + return "DXGI_FORMAT_R11G11B10_FLOAT"; + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + return "DXGI_FORMAT_R8G8B8A8_TYPELESS"; + case DXGI_FORMAT_R8G8B8A8_UNORM: + return "DXGI_FORMAT_R8G8B8A8_UNORM"; + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + return "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB"; + case DXGI_FORMAT_R8G8B8A8_UINT: + return "DXGI_FORMAT_R8G8B8A8_UINT"; + case DXGI_FORMAT_R8G8B8A8_SNORM: + return "DXGI_FORMAT_R8G8B8A8_SNORM"; + case DXGI_FORMAT_R8G8B8A8_SINT: + return "DXGI_FORMAT_R8G8B8A8_SINT"; + case DXGI_FORMAT_R16G16_TYPELESS: + return "DXGI_FORMAT_R16G16_TYPELESS"; + case DXGI_FORMAT_R16G16_FLOAT: + return "DXGI_FORMAT_R16G16_FLOAT"; + case DXGI_FORMAT_R16G16_UNORM: + return "DXGI_FORMAT_R16G16_UNORM"; + case DXGI_FORMAT_R16G16_UINT: + return "DXGI_FORMAT_R16G16_UINT"; + case DXGI_FORMAT_R16G16_SNORM: + return "DXGI_FORMAT_R16G16_SNORM"; + case DXGI_FORMAT_R16G16_SINT: + return "DXGI_FORMAT_R16G16_SINT"; + case DXGI_FORMAT_R32_TYPELESS: + return "DXGI_FORMAT_R32_TYPELESS"; + case DXGI_FORMAT_D32_FLOAT: + return "DXGI_FORMAT_D32_FLOAT"; + case DXGI_FORMAT_R32_FLOAT: + return "DXGI_FORMAT_R32_FLOAT"; + case DXGI_FORMAT_R32_UINT: + return "DXGI_FORMAT_R32_UINT"; + case DXGI_FORMAT_R32_SINT: + return "DXGI_FORMAT_R32_SINT"; + case DXGI_FORMAT_R24G8_TYPELESS: + return "DXGI_FORMAT_R24G8_TYPELESS"; + case DXGI_FORMAT_D24_UNORM_S8_UINT: + return "DXGI_FORMAT_D24_UNORM_S8_UINT"; + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + return "DXGI_FORMAT_R24_UNORM_X8_TYPELESS"; + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + return "DXGI_FORMAT_X24_TYPELESS_G8_UINT"; + case DXGI_FORMAT_R8G8_TYPELESS: + return "DXGI_FORMAT_R8G8_TYPELESS"; + case DXGI_FORMAT_R8G8_UNORM: + return "DXGI_FORMAT_R8G8_UNORM"; + case DXGI_FORMAT_R8G8_UINT: + return "DXGI_FORMAT_R8G8_UINT"; + case DXGI_FORMAT_R8G8_SNORM: + return "DXGI_FORMAT_R8G8_SNORM"; + case DXGI_FORMAT_R8G8_SINT: + return "DXGI_FORMAT_R8G8_SINT"; + case DXGI_FORMAT_R16_TYPELESS: + return "DXGI_FORMAT_R16_TYPELESS"; + case DXGI_FORMAT_R16_FLOAT: + return "DXGI_FORMAT_R16_FLOAT"; + case DXGI_FORMAT_D16_UNORM: + return "DXGI_FORMAT_D16_UNORM"; + case DXGI_FORMAT_R16_UNORM: + return "DXGI_FORMAT_R16_UNORM"; + case DXGI_FORMAT_R16_UINT: + return "DXGI_FORMAT_R16_UINT"; + case DXGI_FORMAT_R16_SNORM: + return "DXGI_FORMAT_R16_SNORM"; + case DXGI_FORMAT_R16_SINT: + return "DXGI_FORMAT_R16_SINT"; + case DXGI_FORMAT_R8_TYPELESS: + return "DXGI_FORMAT_R8_TYPELESS"; + case DXGI_FORMAT_R8_UNORM: + return "DXGI_FORMAT_R8_UNORM"; + case DXGI_FORMAT_R8_UINT: + return "DXGI_FORMAT_R8_UINT"; + case DXGI_FORMAT_R8_SNORM: + return "DXGI_FORMAT_R8_SNORM"; + case DXGI_FORMAT_R8_SINT: + return "DXGI_FORMAT_R8_SINT"; + case DXGI_FORMAT_A8_UNORM: + return "DXGI_FORMAT_A8_UNORM"; + case DXGI_FORMAT_R1_UNORM: + return "DXGI_FORMAT_R1_UNORM"; + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + return "DXGI_FORMAT_R9G9B9E5_SHAREDEXP"; + case DXGI_FORMAT_R8G8_B8G8_UNORM: + return "DXGI_FORMAT_R8G8_B8G8_UNORM"; + case DXGI_FORMAT_G8R8_G8B8_UNORM: + return "DXGI_FORMAT_G8R8_G8B8_UNORM"; + case DXGI_FORMAT_BC1_TYPELESS: + return "DXGI_FORMAT_BC1_TYPELESS"; + case DXGI_FORMAT_BC1_UNORM: + return "DXGI_FORMAT_BC1_UNORM"; + case DXGI_FORMAT_BC1_UNORM_SRGB: + return "DXGI_FORMAT_BC1_UNORM_SRGB"; + case DXGI_FORMAT_BC2_TYPELESS: + return "DXGI_FORMAT_BC2_TYPELESS"; + case DXGI_FORMAT_BC2_UNORM: + return "DXGI_FORMAT_BC2_UNORM"; + case DXGI_FORMAT_BC2_UNORM_SRGB: + return "DXGI_FORMAT_BC2_UNORM_SRGB"; + case DXGI_FORMAT_BC3_TYPELESS: + return "DXGI_FORMAT_BC3_TYPELESS"; + case DXGI_FORMAT_BC3_UNORM: + return "DXGI_FORMAT_BC3_UNORM"; + case DXGI_FORMAT_BC3_UNORM_SRGB: + return "DXGI_FORMAT_BC3_UNORM_SRGB"; + case DXGI_FORMAT_BC4_TYPELESS: + return "DXGI_FORMAT_BC4_TYPELESS"; + case DXGI_FORMAT_BC4_UNORM: + return "DXGI_FORMAT_BC4_UNORM"; + case DXGI_FORMAT_BC4_SNORM: + return "DXGI_FORMAT_BC4_SNORM"; + case DXGI_FORMAT_BC5_TYPELESS: + return "DXGI_FORMAT_BC5_TYPELESS"; + case DXGI_FORMAT_BC5_UNORM: + return "DXGI_FORMAT_BC5_UNORM"; + case DXGI_FORMAT_BC5_SNORM: + return "DXGI_FORMAT_BC5_SNORM"; + case DXGI_FORMAT_B5G6R5_UNORM: + return "DXGI_FORMAT_B5G6R5_UNORM"; + case DXGI_FORMAT_B5G5R5A1_UNORM: + return "DXGI_FORMAT_B5G5R5A1_UNORM"; + case DXGI_FORMAT_B8G8R8A8_UNORM: + return "DXGI_FORMAT_B8G8R8A8_UNORM"; + case DXGI_FORMAT_B8G8R8X8_UNORM: + return "DXGI_FORMAT_B8G8R8X8_UNORM"; + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + return "DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM"; + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + return "DXGI_FORMAT_B8G8R8A8_TYPELESS"; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + return "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB"; + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + return "DXGI_FORMAT_B8G8R8X8_TYPELESS"; + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + return "DXGI_FORMAT_B8G8R8X8_UNORM_SRGB"; + case DXGI_FORMAT_BC6H_TYPELESS: + return "DXGI_FORMAT_BC6H_TYPELESS"; + case DXGI_FORMAT_BC6H_UF16: + return "DXGI_FORMAT_BC6H_UF16"; + case DXGI_FORMAT_BC6H_SF16: + return "DXGI_FORMAT_BC6H_SF16"; + case DXGI_FORMAT_BC7_TYPELESS: + return "DXGI_FORMAT_BC7_TYPELESS"; + case DXGI_FORMAT_BC7_UNORM: + return "DXGI_FORMAT_BC7_UNORM"; + case DXGI_FORMAT_BC7_UNORM_SRGB: + return "DXGI_FORMAT_BC7_UNORM_SRGB"; + case DXGI_FORMAT_AYUV: + return "DXGI_FORMAT_AYUV"; + case DXGI_FORMAT_Y410: + return "DXGI_FORMAT_Y410"; + case DXGI_FORMAT_Y416: + return "DXGI_FORMAT_Y416"; + case DXGI_FORMAT_NV12: + return "DXGI_FORMAT_NV12"; + case DXGI_FORMAT_P010: + return "DXGI_FORMAT_P010"; + case DXGI_FORMAT_P016: + return "DXGI_FORMAT_P016"; + case DXGI_FORMAT_420_OPAQUE: + return "DXGI_FORMAT_420_OPAQUE"; + case DXGI_FORMAT_YUY2: + return "DXGI_FORMAT_YUY2"; + case DXGI_FORMAT_Y210: + return "DXGI_FORMAT_Y210"; + case DXGI_FORMAT_Y216: + return "DXGI_FORMAT_Y216"; + case DXGI_FORMAT_NV11: + return "DXGI_FORMAT_NV11"; + case DXGI_FORMAT_AI44: + return "DXGI_FORMAT_AI44"; + case DXGI_FORMAT_IA44: + return "DXGI_FORMAT_IA44"; + case DXGI_FORMAT_P8: + return "DXGI_FORMAT_P8"; + case DXGI_FORMAT_A8P8: + return "DXGI_FORMAT_A8P8"; + case DXGI_FORMAT_B4G4R4A4_UNORM: + return "DXGI_FORMAT_B4G4R4A4_UNORM"; + case DXGI_FORMAT_FORCE_UINT: + return "DXGI_FORMAT_FORCE_UINT"; + default: + return "DXGI_ERROR_FORMAT"; + } +} + } /* namespace d3dstate */ |