Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Directx 从Direct3D纹理和曲面执行回读_Directx_Textures_Gpgpu_Geometry Surface - Fatal编程技术网

Directx 从Direct3D纹理和曲面执行回读

Directx 从Direct3D纹理和曲面执行回读,directx,textures,gpgpu,geometry-surface,Directx,Textures,Gpgpu,Geometry Surface,我需要弄清楚如何将D3D纹理和曲面的数据返回到系统内存中。做这些事情最快的方法是什么?如何做 另外,如果我只需要一个子矩形,那么如何在不必将整个内容读回系统内存的情况下只读回该部分呢 简言之,我正在寻找如何将以下内容复制到系统内存的简明描述: a纹理 纹理的子集 a表面 曲面的子集 aD3DUSAGE\u渲染目标纹理 D3DUSAGE\U RENDERTARGET纹理的子集 这是Direct3D 9,但如果您能回答D3D较新版本的问题,我们将不胜感激。最重要的部分是从视频内存中的某个表面(“默认

我需要弄清楚如何将D3D纹理和曲面的数据返回到系统内存中。做这些事情最快的方法是什么?如何做

另外,如果我只需要一个子矩形,那么如何在不必将整个内容读回系统内存的情况下只读回该部分呢

简言之,我正在寻找如何将以下内容复制到系统内存的简明描述:

  • a纹理
  • 纹理的子集
  • a表面
  • 曲面的子集
  • aD3DUSAGE\u渲染目标纹理
  • D3DUSAGE\U RENDERTARGET纹理的子集

  • 这是Direct3D 9,但如果您能回答D3D较新版本的问题,我们将不胜感激。

    最重要的部分是从视频内存中的某个表面(“默认池”)读取数据。这通常用于渲染目标

    让我们先来看看简单的部分:

  • 从纹理读取与从该纹理的0级曲面读取相同。见下文
  • 纹理的子集也是如此
  • 从非默认内存池(“系统”或“托管”)中的表面读取只是锁定它并读取字节
  • 对于曲面的子集也是如此。只需锁定相关部分并阅读即可
  • 现在我们有了视频内存中的左表面(“默认池”)。这可能是标记为渲染目标的任何曲面/纹理,或在默认池中创建的任何常规曲面/纹理,或backbuffer本身。这里最复杂的部分是你不能锁定它

    简单的回答是:方法在D3D设备上

    较长的回答(下面将给出代码的大致轮廓):

  • rt=获取渲染目标曲面(可以是纹理的曲面,也可以是backbuffer等)
  • 如果rt是多采样的(GetDesc,选中D3DSURFACE_DESC.MultiSampleType),则:a)创建另一个具有相同大小、相同格式但没有多采样的渲染目标曲面;b) 从rt拉伸到这个新表面;c) rt=此新曲面(即,在此新曲面上继续)
  • 关闭=创建屏幕外平面(创建屏幕外平面、D3DPOOL\u系统内存池)
  • 设备->获取渲染目标数据(rt关闭
  • 现在off包含渲染目标数据。LockRect(),读取数据,然后在其上解锁
  • 清理
  • 下面是更长的答案(从我正在处理的代码库粘贴)。这不会立即编译,因为它使用了代码库其余部分中的一些类、函数、宏和实用程序;但这应该让你开始。我还记录了大多数错误检查(例如,给定的宽度/高度是否超出范围)。我还省略了读取实际像素并可能将其转换为合适的目标格式的部分(这很容易,但可能会很长,具体取决于您希望支持的格式转换的数量)

    上面代码中的
    surfaceinter
    是指向COM对象的智能指针(它在赋值或析构函数时释放对象)。大大简化了错误处理。这与VisualC++中的<>代码> 上面的代码读取整个曲面。如果你想有效地阅读其中的一部分,那么我认为最快的方法大概是:

  • 创建所需大小的默认池曲面
  • 从原始曲面的一部分拉伸到较小的曲面
  • 按照正常程序处理较小的
  • 事实上,这与上面的代码处理多采样曲面非常相似。如果你只想得到一个多采样曲面的一部分,你可以做一个多采样解析,然后在一个StretchRect中得到它的一部分,我想

    编辑:删除了一段实际读取像素和进行格式转换的代码。与问题没有直接关系,代码很长


    编辑:更新以匹配编辑的问题。

    谢谢。这确实为我指明了正确的道路。发布后不久,我确实在MSDN中发现了这样一条评论:您无法锁定D3DUSAGE_RENDERTARGET,必须使用GetRenderTargetData。真倒霉不过,如果有一个更干净、更吝啬的代码示例就好了。:-)没有像素复制代码肯定会更好。用实际的D3D名称替换非D3D类型SurfacePointer如何?LPDIRECT3DSURFACE9或IDirect3DSurface9*以及如果我想从默认池中获取纹理,但它不是rendertarget,该怎么办。锁定不起作用,我无法对非渲染目标曲面使用GetRenderTargetData()。有时可以创建中间渲染目标,但如果原始纹理采用某些格式(如D3DFORMAT_L8),则无法使用此格式创建渲染目标。所以看起来不可能得到这样的纹理。我说得对吗?
    bool GfxDeviceD3D9::ReadbackImage( /* params */ )
    {
        HRESULT hr;
        IDirect3DDevice9* dev = GetD3DDevice();
        SurfacePointer renderTarget;
        hr = dev->GetRenderTarget( 0, &renderTarget );
        if( !renderTarget || FAILED(hr) )
            return false;
    
        D3DSURFACE_DESC rtDesc;
        renderTarget->GetDesc( &rtDesc );
    
        SurfacePointer resolvedSurface;
        if( rtDesc.MultiSampleType != D3DMULTISAMPLE_NONE )
        {
            hr = dev->CreateRenderTarget( rtDesc.Width, rtDesc.Height, rtDesc.Format, D3DMULTISAMPLE_NONE, 0, FALSE, &resolvedSurface, NULL );
            if( FAILED(hr) )
                return false;
            hr = dev->StretchRect( renderTarget, NULL, resolvedSurface, NULL, D3DTEXF_NONE );
            if( FAILED(hr) )
                return false;
            renderTarget = resolvedSurface;
        }
    
        SurfacePointer offscreenSurface;
        hr = dev->CreateOffscreenPlainSurface( rtDesc.Width, rtDesc.Height, rtDesc.Format, D3DPOOL_SYSTEMMEM, &offscreenSurface, NULL );
        if( FAILED(hr) )
            return false;
    
        hr = dev->GetRenderTargetData( renderTarget, offscreenSurface );
        bool ok = SUCCEEDED(hr);
        if( ok )
        {
            // Here we have data in offscreenSurface.
            D3DLOCKED_RECT lr;
            RECT rect;
            rect.left = 0;
            rect.right = rtDesc.Width;
            rect.top = 0;
            rect.bottom = rtDesc.Height;
            // Lock the surface to read pixels
            hr = offscreenSurface->LockRect( &lr, &rect, D3DLOCK_READONLY );
            if( SUCCEEDED(hr) )
            {
                // Pointer to data is lt.pBits, each row is
                // lr.Pitch bytes apart (often it is the same as width*bpp, but
                // can be larger if driver uses padding)
    
                // Read the data here!
                offscreenSurface->UnlockRect();
            }
            else
            {
                ok = false;
            }
        }
    
        return ok;
    }