Copy depth buffer with non-lockable format (D24S8) to system memory with Direct3D9, Win 8.1

纵饮孤独 提交于 2020-01-07 05:48:06

问题


EDIT: As ozeanix points out in the comments it is not possible to copy a D24S8 surface to system memory. Unfortunately you also cannot bind the surface (or rather its containing texture) to a pixel shader.

I ended up going the reimplementation way, intercepting all D3D9 calls. If the graphics card supports it - all cards with DX10+ should do - it is sometimes possible to exchange the D24S8 format with FOURCC INTZ, which has the same memory layout, but can be bound to a pixel shader's texture sampler and thus copied to a different texture in video memory. This texture's content can then be copied to a system memory texture with GetRenderTargetData.


Original post:

I am developing a plugin which should calculate the world position of each pixel contained in a Direct3D surface. The plugin gets called via callback when there is a newly rendered image waiting in the back buffer.

Given are two pointers (IDirect3DSurface9*) to the render target surface (D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE) and the depth buffer surface (D3DFMT_D24S8, D3DMULTISAMPLE_NONMASKABLE). The linked device's display mode is also set to "D3DFMT_X8R8G8B8"

The settings above cannot be changed!

To be able to calculate the world position I also need access to the depth buffer values. So my first attempt was to create an offscreen plain surface with format "D24S8" in system memory, use "GetRenderTargetData" to copy the data and then lock this offscreen surface (with LockRect). Unfortunately, the very first command failed already - apparently this format is not allowed in system memory (there is no problem creating such an offscreen surface in the default pool). So I used the DirectX Caps Viewer ...

D3D Device Type "HAL" and Adapter Format "D3DFMT_X8R8G8B8":

Depth/Stencil Formats: 
    "D3DFMT_D24S8", "D3DFMT_D24X8", "D3DFMT_D16", "D3DFMT_D32F_LOCKABLE"

Texture Formats (only mentioning the depth/stencil & depth formats):
    "D3DFMT_D24S8", "D3DFMT_D24X8", "D3DFMT_D16", "D3DFMT_D32F_LOCKABLE",
    "DXT1" through "DXT5" 
    - but all are only supported in conjunction with usage type "0 (Plain)".

Plain Surface Formats: No depth stencil formats at all are listed.

What I also tried:

  1. Create a texture with only one level and format set to D3DFMT_D24S8, placed in D3DPOOL_SYSTEMMEM (also failed)

  2. Create a surface of type D32F_LOCKABLE in D3DPOOL_DEFAULT (successful) and use D3DXLoadSurfaceFromSurface to convert and copy the data so that a subsequent call to LockRect would provide a handle to the data (failed)

  3. Create depth/stencil surface with disabled multisampling (successful) and use StretchRect to copy from source to destination (failed) and check if multisampling is part of the problem

My questions

  1. According to DirectX Caps Viewer D24S8 should be supported on textures. Are those lists only applicable for ressources in default memory pool?

  2. Is there any way I can copy the depth values to system memory at all?

  3. Is there any possibility to enable extended error reporting for DirectX calls on Windows 8.1? I know that beginning with Win8.1 the OS itself uses the same API and thus the DirectX runtime cannot be set to debug mode, but perhaps I have missed an appropriate option


By the way, with D3DDevice Type "REF" there are a few depth and stencil formats listed for Plain Surfaces (D16_LOCKABLE, D16, D32F_LOCKABLE, D32_LOCKABLE, S8_LOCKABLE) and no depth/stencil entries available in the list of texture formats, but I need to use hardware acceleration, otherwise my application renders way too slow.

来源:https://stackoverflow.com/questions/44501884/copy-depth-buffer-with-non-lockable-format-d24s8-to-system-memory-with-direct3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!