此代码段如何将纹理数据从位图源复制到缓冲区?

时间:2016-02-23 08:48:12

标签: bitmap directx direct3d

我正在阅读Direct3D中的内存管理MSDN文档,标题为" Uploading Texture Data Through Buffers"。我想知道这段代码(下面)如何将纹理数据从位图源复制到缓冲区,还有什么是pBitmap的像素方法,我试图搜索它,但无法找到。

//将纹理数据从pBitmap复制到缓冲区。 //

for (UINT y = 0; y < pitchedDesc.Height; y++)
{
    UINT8 *pScan = m_pDataBegin + placedTexture2D.Offset 
                   + y * pitchedDesc.RowPitch;
    memcpy( pScan, &(pBitmap->pixels[y * pitchedDesc.Width]), 
        sizeof(DWORD) * pitchedDesc.Width );
}

1 个答案:

答案 0 :(得分:1)

MSDN页面在顶部告诉您:

// Prepare a pBitmap in memory, with bitmapWidth, bitmapHeight, and pixel format of DXGI_FORMAT_B8G8R8A8_UNORM. 

它只是一个32位像素的通用2D数组。它的来源根本不在MSDN上。

代码有点令人困惑,因为它只有在pBitmap->pixels本身是DWORD数组时才有效 - 这是隐含的,因为上面的注释状态是DXGI_FORMAT_B8G8R8A8_UNORM格式,这是一个每像素32位格式。该代码还复制了比像素数组中必需的数据更多的数据,除非它与D3D12正在使用的音高精确对齐。

更清晰&amp;正确的代码段将是:

//
// Copy texture data from DWORD* pBitmap->pixels to the buffer
//

for (UINT y = 0; y < bitmapHeight; y++)
{
    UINT8 *pScan = m_pDataBegin + placedTexture2D.Offset 
                   + y * pitchedDesc.RowPitch;
    memcpy( pScan, &(pBitmap->pixels[y * bitmapWidth]), 
        sizeof(DWORD) * bitmapWidth );
}
  

如果您在使用此代码时遇到困难,那么您应该重新考虑是否已准备好使用Direct3D 12.也许您现在应该坚持使用Direct3D 11。见this thread

通常,图像阅读器将在没有任何特殊音高对齐的情况下以简单的打包数组返回像素数据(默认值通常是字节对齐的)。 Direct3D使用一些更具体的对齐间距来布局资源,这些间距可以随驱动器而变化,这取决于资源类型和格式。它可能是字节对齐,4字节对齐,16字节对齐,64字节对齐或完全不同。因此,执行复制的唯一可靠方法是“逐行”执行此操作,其中目标由请求的行间距确定,并且源间距通常等于或小于对齐的间距。

通常类似于:

const uint8_t* sptr = reinterpret_cast<const uint8_t*>( srcImage.pixels );
auto dptr = reinterpret_cast<uint8_t*>( destImage.pixels );

size_t spitch = srcImage.rowPitch;
size_t dpitch = destImage.rowPitch;

size_t size = std::min<size_t>( dpitch, spitch );

for( size_t y = 0; y < height; ++y )
{
    memcpy_s( dptr, dpitch, sptr, size );
    sptr += spitch;
    dptr += dpitch;
}

您可以在DirectXTex中找到这种“逐行”像素操作代码的负载。