blob: e67e06e3fb1e99f797bc1c1b22c35024a8043a0e [file] [log] [blame]
/**************************************************************************
*
* 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 <assert.h>
#include <stdint.h>
#include <stdio.h>
#include "image.hpp"
#include "state_writer.hpp"
#include "com_ptr.hpp"
#include "d3d9state.hpp"
#include "d3dstate.hpp"
#include "d3d9size.hpp"
#include <vector>
namespace d3dstate {
static image::Image *
getSurfaceImage(IDirect3DDevice9 *pDevice,
IDirect3DSurface9 *pSurface,
struct StateWriter::ImageDesc &imageDesc) {
image::Image *image = NULL;
HRESULT hr;
if (!pSurface) {
return NULL;
}
D3DSURFACE_DESC Desc;
hr = pSurface->GetDesc(&Desc);
assert(SUCCEEDED(hr));
if (Desc.Format == D3DFMT_NULL) {
// dummy rendertarget
return NULL;
}
D3DLOCKED_RECT LockedRect;
hr = pSurface->LockRect(&LockedRect, NULL, D3DLOCK_READONLY);
if (FAILED(hr)) {
return NULL;
}
image = ConvertImage(Desc.Format, LockedRect.pBits, LockedRect.Pitch, Desc.Width, Desc.Height);
pSurface->UnlockRect();
imageDesc.format = formatToString(Desc.Format);
return image;
}
static image::Image *
getRenderTargetImage(IDirect3DDevice9 *pDevice,
IDirect3DSurface9 *pRenderTarget,
struct StateWriter::ImageDesc &imageDesc) {
HRESULT hr;
if (!pRenderTarget) {
return NULL;
}
D3DSURFACE_DESC Desc;
hr = pRenderTarget->GetDesc(&Desc);
assert(SUCCEEDED(hr));
if (Desc.Format == D3DFMT_NULL) {
// dummy rendertarget
return NULL;
}
com_ptr<IDirect3DSurface9> pResolveSurface;
if (Desc.MultiSampleType == D3DMULTISAMPLE_NONE) {
pResolveSurface = pRenderTarget;
} else {
hr = pDevice->CreateRenderTarget(Desc.Width, Desc.Height, Desc.Format, D3DMULTISAMPLE_NONE, 0, FALSE, &pResolveSurface, nullptr);
if (FAILED(hr)) {
std::cerr << "warning: failed to create resolve rendertarget\n";
return nullptr;
}
hr = pDevice->StretchRect(pRenderTarget, nullptr, pResolveSurface, nullptr, D3DTEXF_NONE);
if (FAILED(hr)) {
std::cerr << "warning: failed to resolve render target\n";
return nullptr;
}
}
com_ptr<IDirect3DSurface9> pStagingSurface;
hr = pDevice->CreateOffscreenPlainSurface(Desc.Width, Desc.Height, Desc.Format, D3DPOOL_SYSTEMMEM, &pStagingSurface, NULL);
if (FAILED(hr)) {
return NULL;
}
hr = pDevice->GetRenderTargetData(pResolveSurface, pStagingSurface);
if (FAILED(hr)) {
std::cerr << "warning: GetRenderTargetData failed\n";
return NULL;
}
return getSurfaceImage(pDevice, pStagingSurface, imageDesc);
}
image::Image *
getRenderTargetImage(IDirect3DDevice9 *pDevice) {
HRESULT hr;
struct StateWriter::ImageDesc imageDesc;
com_ptr<IDirect3DSurface9> pRenderTarget;
hr = pDevice->GetRenderTarget(0, &pRenderTarget);
if (FAILED(hr)) {
return NULL;
}
assert(pRenderTarget);
return getRenderTargetImage(pDevice, pRenderTarget, imageDesc);
}
image::Image *
getRenderTargetImage(IDirect3DSwapChain9 *pSwapChain) {
HRESULT hr;
struct StateWriter::ImageDesc imageDesc;
com_ptr<IDirect3DDevice9> pDevice;
hr = pSwapChain->GetDevice(&pDevice);
if (FAILED(hr)) {
return NULL;
}
// TODO: Use GetFrontBufferData instead??
com_ptr<IDirect3DSurface9> pBackBuffer;
hr = pSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
if (FAILED(hr)) {
return NULL;
}
assert(pBackBuffer);
return getRenderTargetImage(pDevice, pBackBuffer, imageDesc);
}
static HRESULT
getLockableRenderTargetForDepth(IDirect3DDevice9 *pDevice,
int w,
int h,
com_ptr<IDirect3DSurface9> &pRenderTarget)
{
HRESULT hr;
std::vector<D3DFORMAT> fmts ({D3DFMT_R32F, D3DFMT_G32R32F, D3DFMT_R16F, D3DFMT_X8R8G8B8});
pRenderTarget = NULL;
for (UINT i = 0; i < fmts.size(); i++) {
hr = pDevice->CreateRenderTarget(w, h, fmts[i], D3DMULTISAMPLE_NONE,
0, TRUE, &pRenderTarget, NULL);
if (SUCCEEDED(hr))
break;
}
return hr;
}
static HRESULT
blitTexturetoRendertarget(IDirect3DDevice9 *pDevice,
IDirect3DBaseTexture9 *pSourceTex,
IDirect3DSurface9 *pRenderTarget)
{
com_ptr<IDirect3DPixelShader9> pPS;
HRESULT hr;
/* state */
com_ptr<IDirect3DSurface9> pOldRenderTarget;
com_ptr<IDirect3DSurface9> pOldDepthStencil;
D3DVIEWPORT9 oldViewport;
D3DMATRIX oldProj, oldView, oldWorld;
com_ptr<IDirect3DPixelShader9> pOldPixelShader;
com_ptr<IDirect3DVertexShader9> pOldVertexShader;
DWORD oldFVF;
com_ptr<IDirect3DBaseTexture9> pOldTexture;
com_ptr<IDirect3DStateBlock9> pState;
static const DWORD ps_code[] =
{
0xffff0200, /* ps_2_0 */
0x0200001f, 0x90000000, 0xa00f0800, /* dcl_2d s0 */
0x0200001f, 0x80000000, 0xb00f0000, /* dcl t0 */
0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.0, 0.0, 0.0, 0.0 */
0x02000001, 0x800f0000, 0xa0e40000, /* mov r0, c0 */
0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800, /* texld r0, t0, s0 */
0x02000001, 0x800f0800, 0x80e40000, /* mov oC0, r0 */
0x0000ffff, /* end */
};
static const struct
{
float x, y, z;
float s, t, p, q;
}
quad[] =
{
{ -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f},
{ 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f},
{ -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f},
{ 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.5f},
};
hr = pDevice->CreatePixelShader(ps_code, &pPS);
if (!SUCCEEDED(hr))
return hr;
/* Store state */
pDevice->GetTransform(D3DTS_PROJECTION, &oldProj);
pDevice->GetTransform(D3DTS_VIEW, &oldView);
pDevice->GetTransform(D3DTS_WORLD, &oldWorld);
pDevice->GetPixelShader(&pOldPixelShader);
pDevice->GetVertexShader(&pOldVertexShader);
pDevice->GetFVF(&oldFVF);
pDevice->GetViewport(&oldViewport);
pDevice->GetTexture(0, &pOldTexture);
pDevice->GetRenderTarget(0, &pOldRenderTarget);
pDevice->GetDepthStencilSurface(&pOldDepthStencil);
/* Store samplerstates and texture and sampler states */
pDevice->CreateStateBlock(D3DSBT_ALL, &pState);
/* Set source */
pDevice->SetTexture(0, pSourceTex);
/* Set destination */
pDevice->SetRenderTarget(0, pRenderTarget);
pDevice->SetDepthStencilSurface(NULL);
pDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
pDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
pDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
pDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_ALWAYS);
pDevice->SetRenderState(D3DRS_ALPHAREF, 0);
pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
pDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
pDevice->SetRenderState(D3DRS_SPECULARENABLE, FALSE);
pDevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE);
pDevice->SetRenderState(D3DRS_RANGEFOGENABLE, FALSE);
pDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
pDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
pDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
pDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_ZERO);
pDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
pDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
pDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
pDevice->SetRenderState(D3DRS_STENCILREF, 0);
D3DSURFACE_DESC desc;
pRenderTarget->GetDesc(&desc);
D3DVIEWPORT9 vp;
vp.X = 0;
vp.Y = 0;
vp.Height = desc.Height;
vp.Width = desc.Width;
vp.MaxZ = 1.0f;
vp.MinZ = 0.0f;
pDevice->SetViewport(&vp);
static const D3DMATRIX identity =
{{{
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f,
}}};
pDevice->SetTransform(D3DTS_PROJECTION, &identity);
pDevice->SetTransform(D3DTS_VIEW, &identity);
pDevice->SetTransform(D3DTS_WORLD, &identity);
pDevice->SetPixelShader(pPS);
pDevice->SetVertexShader(NULL);
pDevice->SetFVF(D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE4(0));
pDevice->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, 0);
pDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
pDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
pDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
pDevice->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, 0);
pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
pDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
/* Blit texture to rendertarget */
pDevice->BeginScene();
pDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
pDevice->EndScene();
/* Restore state */
pDevice->SetTransform(D3DTS_PROJECTION, &oldProj);
pDevice->SetTransform(D3DTS_VIEW, &oldView);
pDevice->SetTransform(D3DTS_WORLD, &oldWorld);
pDevice->SetPixelShader(pOldPixelShader);
pDevice->SetVertexShader(pOldVertexShader);
pDevice->SetFVF(oldFVF);
pDevice->SetViewport(&oldViewport);
pDevice->SetTexture(0, pOldTexture);
pDevice->SetRenderTarget(0, pOldRenderTarget);
pDevice->SetDepthStencilSurface(pOldDepthStencil);
pState->Apply();
return D3D_OK;
}
static bool
isDepthSamplerFormat(D3DFORMAT fmt)
{
return (fmt == D3DFMT_DF24 ||
fmt == D3DFMT_DF16 ||
fmt == D3DFMT_INTZ);
}
static image::Image *
getTextureImage(IDirect3DDevice9 *pDevice,
IDirect3DBaseTexture9 *pTexture,
D3DCUBEMAP_FACES FaceType,
UINT Level,
struct StateWriter::ImageDesc &imageDesc)
{
HRESULT hr;
if (!pTexture) {
return NULL;
}
com_ptr<IDirect3DSurface9> pSurface;
D3DRESOURCETYPE Type = pTexture->GetType();
switch (Type) {
case D3DRTYPE_TEXTURE:
assert(FaceType == D3DCUBEMAP_FACE_POSITIVE_X);
hr = reinterpret_cast<IDirect3DTexture9 *>(pTexture)->GetSurfaceLevel(Level, &pSurface);
break;
case D3DRTYPE_CUBETEXTURE:
hr = reinterpret_cast<IDirect3DCubeTexture9 *>(pTexture)->GetCubeMapSurface(FaceType, Level, &pSurface);
break;
default:
/* TODO: support volume textures */
return NULL;
}
if (FAILED(hr) || !pSurface) {
return NULL;
}
D3DSURFACE_DESC Desc;
hr = pSurface->GetDesc(&Desc);
assert(SUCCEEDED(hr));
if (Type == D3DRTYPE_TEXTURE && isDepthSamplerFormat(Desc.Format)) {
/* Special case for depth sampling formats.
* Blit to temporary rendertarget and dump it.
* Finally replace the format string to avoid confusion.
*/
com_ptr<IDirect3DSurface9> pTempSurf;
hr = getLockableRenderTargetForDepth(pDevice, Desc.Width, Desc.Height, pTempSurf);
if (FAILED(hr) || !pTempSurf) {
return NULL;
}
hr = blitTexturetoRendertarget(pDevice, pTexture, pTempSurf);
if (FAILED(hr)) {
return NULL;
}
image::Image *image;
image = getRenderTargetImage(pDevice, pTempSurf, imageDesc);
/* Replace rendertarget format with depth format */
imageDesc.format = formatToString(Desc.Format);
return image;
} else if (Desc.Pool != D3DPOOL_DEFAULT ||
Desc.Usage & D3DUSAGE_DYNAMIC) {
// Lockable texture
return getSurfaceImage(pDevice, pSurface, imageDesc);
} else if (Desc.Usage & D3DUSAGE_RENDERTARGET) {
// Rendertarget texture
return getRenderTargetImage(pDevice, pSurface, imageDesc);
} else {
// D3D constraints are such there is not much else that can be done.
return NULL;
}
}
void
dumpTextures(StateWriter &writer, IDirect3DDevice9 *pDevice)
{
HRESULT hr;
writer.beginMember("textures");
writer.beginObject();
for (DWORD Stage = 0; Stage < 16; ++Stage) {
com_ptr<IDirect3DBaseTexture9> pTexture;
hr = pDevice->GetTexture(Stage, &pTexture);
if (FAILED(hr)) {
continue;
}
if (!pTexture) {
continue;
}
D3DRESOURCETYPE Type = pTexture->GetType();
DWORD NumFaces = Type == D3DRTYPE_CUBETEXTURE ? 6 : 1;
DWORD NumLevels = pTexture->GetLevelCount();
for (DWORD Face = 0; Face < NumFaces; ++Face) {
for (DWORD Level = 0; Level < NumLevels; ++Level) {
image::Image *image;
struct StateWriter::ImageDesc imageDesc;
image = getTextureImage(pDevice, pTexture, static_cast<D3DCUBEMAP_FACES>(Face), Level, imageDesc);
if (image) {
char label[128];
if (Type == D3DRTYPE_CUBETEXTURE) {
_snprintf(label, sizeof label, "PS_RESOURCE_%lu_FACE_%lu_LEVEL_%lu", Stage, Face, Level);
} else {
_snprintf(label, sizeof label, "PS_RESOURCE_%lu_LEVEL_%lu", Stage, Level);
}
writer.beginMember(label);
writer.writeImage(image, imageDesc);
writer.endMember(); // PS_RESOURCE_*
delete image;
}
}
}
}
writer.endObject();
writer.endMember(); // textures
}
static void
dumpRenderTargets(StateWriter &writer,
IDirect3DDevice9 *pDevice)
{
HRESULT hr;
D3DCAPS9 Caps;
pDevice->GetDeviceCaps(&Caps);
for (UINT i = 0; i < Caps.NumSimultaneousRTs; ++i) {
com_ptr<IDirect3DSurface9> pRenderTarget;
hr = pDevice->GetRenderTarget(i, &pRenderTarget);
if (FAILED(hr)) {
continue;
}
if (!pRenderTarget) {
continue;
}
image::Image *image;
struct StateWriter::ImageDesc imageDesc;
image = getRenderTargetImage(pDevice, pRenderTarget, imageDesc);
if (image) {
char label[64];
_snprintf(label, sizeof label, "RENDER_TARGET_%u", i);
writer.beginMember(label);
writer.writeImage(image, imageDesc);
writer.endMember(); // RENDER_TARGET_*
delete image;
}
}
}
static void
dumpDepthStencil(StateWriter &writer,
IDirect3DDevice9 *pDevice,
com_ptr<IDirect3DSurface9> &pDepthStencil,
D3DFORMAT format)
{
image::Image *image;
struct StateWriter::ImageDesc imageDesc;
if (!pDepthStencil)
return;
D3DSURFACE_DESC Desc;
pDepthStencil->GetDesc(&Desc);
if (Desc.Usage & D3DUSAGE_RENDERTARGET) {
/* RESZ hack: depth has been uploaded to rendertarget */
image = getRenderTargetImage(pDevice, pDepthStencil, imageDesc);
imageDesc.format = formatToString(format);
} else {
image = getSurfaceImage(pDevice, pDepthStencil, imageDesc);
}
if (image) {
writer.beginMember("DEPTH_STENCIL");
writer.writeImage(image, imageDesc);
writer.endMember(); // DEPTH_STENCIL
delete image;
}
}
static bool
isLockableFormat(D3DFORMAT fmt)
{
return (fmt == D3DFMT_D16_LOCKABLE ||
fmt == D3DFMT_D32F_LOCKABLE ||
fmt == D3DFMT_S8_LOCKABLE ||
fmt == D3DFMT_D32_LOCKABLE);
}
static bool
isRESZSupported(IDirect3DDevice9 *pDevice)
{
com_ptr<IDirect3D9> pD3D9;
HRESULT hr;
pDevice->GetDirect3D(&pD3D9);
hr = pD3D9->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_RESZ);
return SUCCEEDED(hr);
}
static HRESULT
blitDepthRESZ(IDirect3DDevice9 *pDevice, com_ptr<IDirect3DTexture9> &pDestTex)
{
D3DVECTOR vDummyPoint = {0.0f, 0.0f, 0.0f};
HRESULT hr;
DWORD oldZEnable, oldZWriteEnable, oldColorWriteEnable;
com_ptr<IDirect3DBaseTexture9> pOldTex;
/* Store current state */
pDevice->GetTexture(0, &pOldTex);
pDevice->GetRenderState(D3DRS_ZENABLE, &oldZEnable);
pDevice->GetRenderState(D3DRS_ZWRITEENABLE, &oldZWriteEnable);
pDevice->GetRenderState(D3DRS_COLORWRITEENABLE, &oldColorWriteEnable);
pDevice->SetTexture(0, pDestTex);
pDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
pDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
pDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
/* Dummy draw call */
hr = pDevice->DrawPrimitiveUP(D3DPT_POINTLIST, 1, &vDummyPoint, sizeof(vDummyPoint));
pDevice->SetRenderState(D3DRS_ZWRITEENABLE, oldZEnable);
pDevice->SetRenderState(D3DRS_ZENABLE, oldZWriteEnable);
pDevice->SetRenderState(D3DRS_COLORWRITEENABLE, oldColorWriteEnable);
/* Trigger RESZ hack, upload depth to texture bound at sampler 0 */
pDevice->SetRenderState(D3DRS_POINTSIZE, RESZ_CODE);
pDevice->SetRenderState(D3DRS_POINTSIZE, 0);
/* Restore state */
pDevice->SetTexture(0, pOldTex);
return hr;
}
static HRESULT
getTextureforDepthAsTexture(IDirect3DDevice9 *pDevice, int w, int h, com_ptr<IDirect3DTexture9> &pDestTex)
{
HRESULT hr;
std::vector<D3DFORMAT> fmts ({D3DFMT_INTZ, D3DFMT_DF24, D3DFMT_DF16});
for (int i = 0; i < fmts.size(); i++) {
hr = pDevice->CreateTexture(w, h, 1, D3DUSAGE_DEPTHSTENCIL,
fmts[i], D3DPOOL_DEFAULT, &pDestTex, NULL);
if (SUCCEEDED(hr))
break;
}
return hr;
}
void
dumpFramebuffer(StateWriter &writer, IDirect3DDevice9 *pDevice)
{
HRESULT hr;
writer.beginMember("framebuffer");
writer.beginObject();
dumpRenderTargets(writer, pDevice);
com_ptr<IDirect3DSurface9> pDepthStencil;
hr = pDevice->GetDepthStencilSurface(&pDepthStencil);
if (SUCCEEDED(hr)) {
D3DSURFACE_DESC Desc;
pDepthStencil->GetDesc(&Desc);
if (isLockableFormat(Desc.Format)) {
dumpDepthStencil(writer, pDevice, pDepthStencil, Desc.Format);
} else if(isRESZSupported(pDevice)) {
/* Use RESZ hack to copy depth to a readable format.
* This is working on AMD, Intel and WINE.
* 1. Copy to depth sampling format using RESZ hack.
* 2. Blit to temporary rendertarget and dump it.
*/
com_ptr<IDirect3DTexture9> pTextureDepthSampler;
hr = getTextureforDepthAsTexture(pDevice, Desc.Width, Desc.Height, pTextureDepthSampler);
if (SUCCEEDED(hr)) {
hr = blitDepthRESZ(pDevice, pTextureDepthSampler);
if (SUCCEEDED(hr)) {
com_ptr<IDirect3DSurface9> pTempSurf;
hr = getLockableRenderTargetForDepth(pDevice, Desc.Width, Desc.Height, pTempSurf);
if (SUCCEEDED(hr)) {
hr = blitTexturetoRendertarget(pDevice, pTextureDepthSampler, pTempSurf);
if (SUCCEEDED(hr)) {
dumpDepthStencil(writer, pDevice, pTempSurf, Desc.Format);
}
}
}
}
} else {
// Can't to anything about it
}
}
writer.endObject();
writer.endMember(); // framebuffer
}
} /* namespace d3dstate */