XNA 3.1在清除深度缓冲区之前保留深度缓冲区

XNA 3.1在清除深度缓冲区之前保留深度缓冲区,xna,directx,vtable,depth-buffer,hresult,Xna,Directx,Vtable,Depth Buffer,Hresult,我试图绕过XNA 3.1在切换渲染目标时自动清除深度缓冲区的问题,方法是在切换渲染目标之前从深度缓冲区复制IDirect3DSurface9,然后在稍后恢复深度缓冲区 在代码中,getDepthBuffer方法是指向IDirect3DDevice9 GetDepthStencilBuffer函数的指针。指向该方法的指针似乎是正确的,但当我尝试获取IDirect3DSurface9指针时,它返回一个异常(0x8876086C-D3DERR_INVALIDCALL)。surfacePtr指针最终指向

我试图绕过XNA 3.1在切换渲染目标时自动清除深度缓冲区的问题,方法是在切换渲染目标之前从深度缓冲区复制IDirect3DSurface9,然后在稍后恢复深度缓冲区

在代码中,getDepthBuffer方法是指向IDirect3DDevice9 GetDepthStencilBuffer函数的指针。指向该方法的指针似乎是正确的,但当我尝试获取IDirect3DSurface9指针时,它返回一个异常(0x8876086C-D3DERR_INVALIDCALL)。surfacePtr指针最终指向0x00000000

你知道为什么它不起作用吗?关于如何修复它有什么想法吗

代码如下:

    public static unsafe Texture2D GetDepthStencilBuffer(GraphicsDevice g)
    {
        if (g.DepthStencilBuffer.Format != DepthFormat.Depth24Stencil8)
        {
            return null;
        }

        Texture2D t2d = new Texture2D(g, g.DepthStencilBuffer.Width, g.DepthStencilBuffer.Height, 1, TextureUsage.None, SurfaceFormat.Color);
        FieldInfo f = typeof(GraphicsDevice).GetField("pComPtr", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance);
        object o = f.GetValue(g);
        void* devicePtr = Pointer.Unbox(f.GetValue(g));
        void* getDepthPtr = AccessVTable(devicePtr, 160);
        void* surfacePtr;

        var getDepthBuffer = (GetDepthStencilBufferDelegate)Marshal.GetDelegateForFunctionPointer(new IntPtr(getDepthPtr), typeof(GetDepthStencilBufferDelegate));
        var rv = getDepthBuffer(&surfacePtr);

        SetData(t2d, 0, surfacePtr, g.DepthStencilBuffer.Width, g.DepthStencilBuffer.Height, (uint)(g.DepthStencilBuffer.Width / 4), D3DFORMAT.D24S8);
        Marshal.Release(new IntPtr(devicePtr));
        Marshal.Release(new IntPtr(getDepthPtr));
        Marshal.Release(new IntPtr(surfacePtr));
        return t2d;
    }

XNA3.1不会在更改渲染目标时清除深度模具缓冲区,但如果您不小心更改渲染目标,它会解决该问题(因此深度测试无法使用该缓冲区)

例如:

SetRenderTarget(someRenderTarget)
DrawStuff()
SetRenderTarget(null)
SetRenderTarget(someOtherRenderTarget)
将导致解析深度模具缓冲区,但以下情况不会:

SetRenderTarget(someRenderTarget)
DrawStuff()
SetRenderTarget(someOtherRenderTarget)
我不确定为什么XNA3.1(以及更早的版本)会出现这种情况,但自从发现这一点后,我已经能够通过许多渲染目标更改,甚至是清除操作,只要清除指定的ClearOptions.target only,保持相同深度的模具缓冲区处于活动状态。

本文中的答案可能会有所帮助