XNA 3.1 Сохранение буфера глубины до его очистки

Я пытаюсь обойти автоматическую очистку 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;
    }

person Enigami    schedule 30.11.2011    source источник
comment
Ответ в этом посте с неверным вызовом d3derr invalidcall 200553051"> stackoverflow.com/questions/2497641/ может быть полезно   -  person Petr Abdulin    schedule 01.12.2011


Ответы (1)


XNA3.1 не очистит ваш буфер трафарета глубины при изменении целей рендеринга, однако он разрешит его (так что его нельзя будет использовать для тестов глубины), если вы не будете осторожны с изменениями цели рендеринга.

Например:

SetRenderTarget(someRenderTarget)
DrawStuff()
SetRenderTarget(null)
SetRenderTarget(someOtherRenderTarget)

Приводит к разрешению буфера трафарета глубины, но не к следующему:

SetRenderTarget(someRenderTarget)
DrawStuff()
SetRenderTarget(someOtherRenderTarget)

Я не уверен, почему это происходит с XNA3.1 (и более ранними версиями), но с тех пор, как я понял это, я смог сохранить один и тот же буфер трафарета глубины при многих изменениях цели рендеринга, даже при операциях очистки, пока очистить только указанный ClearOptions.Target.

person default ex    schedule 11.01.2012