Hey guys,
having read a lot here in the forums before, I decided to sign up and ask for help with my problem. And I would really appreciate any help!
I need to copy the contents of a D3D9 texture (1024 x 1024) of format INTZ to system memory to be able to use it in a different application. By the way, I am stuck with D3D9, the INTZ texture is part of a closed application and I get its handle via intercepting the D3D calls (proxy dll).
As far as I know (at least my attempts trying to do so failed) it is not possible to just use GetRenderDataTarget. The texture resides in the default pool and its usage is set to Depth/Stencil (2), thus the other methods like StretchRect, UpdateTexture, etc. also cannot be used.
Now I would like to use a pixel shader to sample this texture and write/copy the contents to a texture of a different format like R32F. I suppose, I can then use GetRenderTargetData to copy the contents to a third texture in system memory and lock this texture afterwards (probably with a delay so that the GPU has enough time to copy the data from video to system memory).
What I have so far is the following:
------ Pixel shader: ------
sampler2D s2d : register(s0);
struct PS_IN
{
//float4 pos : POSITION;
float2 texcoord : TEXCOORD0;
};
struct PS_OUT
{
float4 Color : COLOR;
};
// pixel shader
PS_OUT main(PS_IN input)
{
PS_OUT output;
output.Color.r = tex2D(s2d,input.texcoord).//d? or something else?;
return output;
}
------ Declaration ------
const DWORD D3DFVF_CPYVTX = D3DFVF_TEX0;
struct CPYVTX {
float tu, tv;
};
--
void Init()
{
if (FAILED(apDev->CreateRenderTarget(1024, 1024, D3DFMT_R32F, D3DMULTISAMPLE_NONE, 0, false, &gpCopyRenderTarget, 0)))
throw std::runtime_error("Failed to create render target as destination for copy pass.");
// initialize vertices to be used for texture access
if (FAILED(apDev->CreateVertexBuffer(sizeof(CPYVTX) * 4, NULL, D3DFVF_CPYVTX, D3DPOOL_DEFAULT, &gpVtxBuf, NULL))) //**should I better use vertex a declaration here?**
{
throw std::runtime_error("Failed to create vertex buffer required for copy pass.");
}
else
{
CPYVTX* lpVertices;
gpVtxBuf->Lock(0, 0, (void**)&lpVertices, NULL);
lpVertices[0].tu = 0.0f;
lpVertices[0].tv = 0.0f;
lpVertices[1].tu = 1.0f;
lpVertices[1].tv = 0.0f;
lpVertices[2].tu = 0.0f;
lpVertices[2].tv = 1.0f;
lpVertices[3].tu = 1.0f;
lpVertices[3].tv = 1.0f;
gpVtxBuf->Unlock();
}
LPD3DXBUFFER lpCPSO = NULL, lpErrBuf = NULL;
if (FAILED(D3DXCompileShaderFromFile(
gPathPS,
NULL, NULL, "main", "ps_3_0", 0, &lpCPSO, &lpErrBuf, NULL)))
{
throw std::runtime_error("Failed to compile pixel shader file.");
}
if (FAILED(apDev->CreatePixelShader((DWORD*)lpCPSO->GetBufferPointer(), &gpCopyPixelShader)))
{
throw std::runtime_error("Failed to create pixel shader from compiled object.");
}
}
-------- Draw function: ----
void RunCopy(){
IDirect3DVertexDeclaration9 *lpDecl = NULL;
IDirect3DSurface9 *lpRenderTargetSfc = NULL;
DWORD lFVF = 0;
// --- get current state
apDev->GetVertexDeclaration(&lpDecl);
apDev->GetRenderTarget(0, &lpRenderTargetSfc);
apDev->GetFVF(&lFVF);
// --- set new states required for copy pass
apDev->SetVertexDeclaration(NULL);
apDev->SetVertexShader(NULL);
apDev->SetFVF(D3DFVF_CPYVTX);
apDev->SetStreamSource(0, gpVtxBuf, 0, sizeof(CPYVTX));
apDev->SetRenderTarget(0, gpCopyRenderTarget);
apDev->SetPixelShader(gpCopyPixelShader);
apDev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
// --- reset previous state
apDev->SetVertexDeclaration(lpDecl);
apDev->SetRenderTarget(0, lpRenderTargetSfc);
apDev->SetFVF(lFVF);
}
I believe the vertex definition (CPYVTX) needs to be extended to contain D3DFVF_XYZRHW and the float members respectively, otherwise the pixel shader does not know of which pixel it should set the value. But to be honest, I don't know what the XYZRHW variables should contain. X and Y equal to the dimensions in pixels?(0|0), (0|1023), (1023|0),(1023|1023)?
How do I access an INTZ texture (which internally should be equal to D24S8) in the pixel shader and write its output to a R32F texture - is my shader syntax correct?
As I said initially, I am really grateful for every answer.
↧