复制渲染目标数据到D3DPOOL_MANAGED

Copying render target data to D3DPOOL_MANAGED?

本文关键字:D3DPOOL MANAGED 数据 目标 复制      更新时间:2023-10-16

我使用的是DirectX9引擎

使用

创建渲染目标
D3DXCreateTexture(
    pD3DDevice, width, height, 1, 
    D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, 
    D3DPOOL_DEFAULT, &pRT
)


和所有其他纹理创建如下:

D3DXCreateTexture(
    pD3DDevice, width, height,
    1, 0, D3DFMT_A8R8G8B8,
    D3DPOOL_MANAGED, &pTex
)

值得注意的是,后缓冲也是D3DFMT_X8R8G8B8,所以我不确定为什么纹理的创建方式不同……但我想"如果没坏,就不要修它",对吗?所有纹理看起来加载/渲染都很好。有关此引擎如何运行的更多细节,请参阅其主图形模块的代码。
(主要是注意Target_CreateTexture_Create方法)…

然而,在尝试将渲染目标纹理转换为常规纹理时,我遇到了很多麻烦,试图坚持这些规则。引擎没有内置的功能,渲染目标被视为与纹理分开的对象……反过来,这限制了我实际使用任何需要渲染目标(即像素着色器等)的能力。最终的结果是,我需要找到一种方法将这个渲染目标数据复制到如上所述创建的纹理中,这样引擎可以在没有任何冲突的情况下使用。

我试过如下:

inline PVOID LockedBits(LPDIRECT3DSURFACE9 surface, UINT w, UINT h, INT* size)
{
    D3DLOCKED_RECT lr;
    RECT rc = {0, 0, w, h};
    surface->LockRect(&lr, &rc, 0);
    if(size) *size = (w*h) * 4;
    return lr.pBits;
}
inline PVOID LockedBits(LPDIRECT3DTEXTURE9 texture, UINT w, UINT h, INT* size)
{
    D3DLOCKED_RECT lr;
    RECT rc = {0, 0, w, h};
    texture->LockRect(0, &lr, &rc, 0);
    if(size) *size = (w*h) * 4;
    return lr.pBits;
}
LPDIRECT3DTEXTURE9 CloneTextureFromTarget(LPDIRECT3DDEVICE9 device, LPDIRECT3DTEXTURE9 target, UINT w, UINT h)
{
    D3DDISPLAYMODE dm;
    device->GetDisplayMode(0, &dm);
    // Create source and destination surfaces and copy rendertarget
    LPDIRECT3DSURFACE9 dstSurf = NULL, srcSurf = NULL;
    device->CreateOffscreenPlainSurface(w, h, dm.Format, D3DPOOL_SYSTEMMEM, &dstSurf, NULL);
    target->GetSurfaceLevel(0, &srcSurf);
    device->GetRenderTargetData(srcSurf, dstSurf);
    SafeRelease(&srcSurf);
    // Create destination texture
    LPDIRECT3DTEXTURE9 dstTexture = NULL;
    D3DXCreateTexture(device, w, h, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &dstTexture);
    // Get bits for destination surface and texture
    INT dwSrc, dwDst;
    PVOID pBitsSrc = LockedBits(dstSurf, w, h, &dwSrc);
    PVOID pBitsDst = LockedBits(dstTexture, w, h, &dwDst);
    // Copy bits from surface to texture
    RtlCopyMemory(pBitsSrc, pBitsDst, dwSrc);
    dstTexture->UnlockRect(0);
    dstSurf->UnlockRect();
    SafeRelease(&dstSurf);
    /* Just to double-check if it worked... */
    D3DXSaveTextureToFileA("C:\outSrc.png", D3DXIFF_PNG, target, NULL);
    D3DXSaveTextureToFileA("C:\outDst.png", D3DXIFF_PNG, dstTexture, NULL);
    // Return the result
    return dstTexture;
}

这段代码的结果是,这两个纹理都正确地保存到磁盘,并按预期出来,但拒绝正确渲染…

我做错了什么吗?将这些数据完美地复制到使用D3DFMT_A8R8G8B8D3DPOOL_MANAGED创建的新纹理中的最佳方法是什么?

TBH修改你的复制方法如下:

char* pSrc = (char*)pBitsSrc;
char* pDst = (char*)pBitsDst;
int p = 0;
int pMax = w * h;
while( p < pMax )
{
    // Copy B
    *pDst = *pSrc;
    pDst++;
    pSrc++;
    // Copy G
    *pDst = *pSrc;
    pDst++;
    pSrc++;
    // Copy R
    *pDst = *pSrc;
    pDst++;
    pSrc++;
    // Set A
    *pDst = 0xff;
    pDst++;
    pSrc++;
    p++;
}

或者失败,简单地创建目标纹理作为D3DFMT_X8R8G8B8.