ID3D11DeviceContext::UpdateSubresource 方法 (d3d11.h)

请参阅 基本全息影像示例

CPU 将数据从内存复制到不可映射内存中创建的子资源。

语法

void UpdateSubresource(
  [in]           ID3D11Resource  *pDstResource,
  [in]           UINT            DstSubresource,
  [in, optional] const D3D11_BOX *pDstBox,
  [in]           const void      *pSrcData,
  [in]           UINT            SrcRowPitch,
  [in]           UINT            SrcDepthPitch
);

参数

[in] pDstResource

类型: ID3D11Resource*

指向目标资源的指针, (ID3D11Resource) 。

[in] DstSubresource

类型: UINT

一个从零开始的索引,用于标识目标子资源。 有关更多详细信息,请参阅 D3D11CalcSubresource

[in, optional] pDstBox

类型: const D3D11_BOX*

指向框的指针,该框定义要将资源数据复制到其中的目标子资源部分。 缓冲区的坐标以字节为单位,纹理的纹素以字节为单位。 如果 为 NULL,则数据将写入目标子资源,且没有偏移量。 源的维度必须符合目标, (看到 D3D11_BOX) 。

空框导致无操作。 如果顶部值大于或等于底部值,或者左值大于或等于右值,或者前值大于或等于后的值,则框为空。 当框为空时, UpdateSubresource 不执行更新操作。

[in] pSrcData

类型: const void*

指向内存中源数据的指针。

[in] SrcRowPitch

类型: UINT

源数据一行的大小。

[in] SrcDepthPitch

类型: UINT

源数据一个深度切片的大小。

返回值

备注

对于着色器常量缓冲区;将 pDstBox 设置为 NULL。 不能使用此方法部分更新着色器常量缓冲区。

在如下的情况下,资源不能用作目标:

  • 资源是使用 不可变动态 使用情况创建的。
  • 资源创建为深度模具资源。
  • 资源是使用多重采样功能创建的, (请参阅 DXGI_SAMPLE_DESC) 。
当 UpdateSubresource 返回时,应用程序可以自由更改甚至释放 pSrcData 指向的数据,因为该方法已复制/贴靠原始内容。

UpdateSubresource 的性能取决于目标资源是否存在争用。 例如,当应用程序执行 Draw 调用并在 GPU 实际执行 绘图 调用之前在同一顶点缓冲区上调用 UpdateSubresource 时,将发生 点缓冲区资源的争用。

  • 当资源争用时, UpdateSubresource 将执行源数据的 2 个副本。 首先,由 CPU 将数据复制到命令缓冲区可访问的临时存储空间。 此复制发生在 方法返回之前。 然后,GPU 执行第二次复制,将源数据复制到不可映射的内存中。 第二次复制以异步方式发生,因为它在刷新命令缓冲区时由 GPU 执行。
  • 如果没有资源争用, 则 UpdateSubresource 的行为依赖于它更快 (从 CPU 的角度来看) :将数据复制到命令缓冲区,然后在刷新命令缓冲区时执行第二次复制,或者让 CPU 将数据复制到最终资源位置。 这取决于基础系统的体系结构。
注意仅适用于硬件9_x功能级别 如果使用 UpdateSubresourceID3D11DeviceContext::CopySubresourceRegion 从过渡资源复制到默认资源,则可能会损坏目标内容。 如果传递 NULL 源框,并且源资源具有不同于目标资源的维度,或者如果使用目标偏移量, (x、y 和 z) ,则会发生此情况。 在这种情况下,始终传递源资源的完整大小的源框。
 
为了更好地了解源行间距和源深度间距参数,下图显示了 3D 体积纹理。 3D 体积纹理的插图

此视觉对象中的每个块表示一个数据元素,每个元素的大小取决于资源的格式。 例如,如果资源格式DXGI_FORMAT_R32G32B32A32_FLOAT,则每个元素的大小将为 128 位或 16 个字节。 此 3D 体积纹理的宽度为 2,高度为 3,深度为 4。

若要计算给定资源的源行间距和源深度间距,请使用以下公式:

  • 源行间距 = [以字节为单位的一个元素的大小] * [一行中的元素数]
  • 源深度间距 = [源行间距] * [行数 (高度) ]
对于每个元素的大小为 16 字节的示例 3D 卷纹理,公式如下:
  • 源行间距 = 16 * 2 = 32
  • 源深度间距 = 16 * 2 * 3 = 96
下图显示了资源在内存中布局时的资源。 内存中布局的 3D 体积纹理的插图

例如,以下代码片段演示如何在 2D 纹理中指定目标区域。 假设目标纹理为 512x512,操作会将 pData 指向的数据复制到 [ (120,100) .目标纹理中 (200,220) ]。 此外,假设 rowPitch 已使用正确的值 (初始化,如上述) 所述。 frontback 分别设置为 0 和 1,因为通过将 front 等于 back,框在技术上是空的。


D3D11_BOX destRegion;
destRegion.left = 120;
destRegion.right = 200;
destRegion.top = 100;
destRegion.bottom = 220;
destRegion.front = 0;
destRegion.back = 1;

pd3dDeviceContext->UpdateSubresource( pDestTexture, 0, &destRegion, pData, rowPitch, 0 );

一维情况类似。 以下代码片段演示如何在 1D 纹理中指定目标区域。 使用与上述相同的假设,只是纹理的长度为 512。


D3D11_BOX destRegion;
destRegion.left = 120;
destRegion.right = 200;
destRegion.top = 0;
destRegion.bottom = 1;
destRegion.front = 0;
destRegion.back = 1;

pd3dDeviceContext->UpdateSubresource( pDestTexture, 0, &destRegion, pData, rowPitch, 0 );

有关各种资源类型以及 UpdateSubresource 如何使用每种资源类型的信息,请参阅 Direct3D 11 中的资源简介

在延迟上下文上调用 UpdateSubresource

如果应用程序在具有非 (0,0,0,0) 偏移量的目标框的延迟上下文上调用 UpdateSubresource,并且如果驱动程序不支持命令列表,则 UpdateSubresource 不恰当地将该目标框偏移量应用于 pSrcData 参数。 若要解决此行为,请使用以下代码:

HRESULT UpdateSubresource_Workaround(
  ID3D11Device *pDevice,
  ID3D11DeviceContext *pDeviceContext,
  ID3D11Resource *pDstResource,
  UINT dstSubresource,
  const D3D11_BOX *pDstBox,
  const void *pSrcData,
  UINT srcBytesPerElement,
  UINT srcRowPitch,
  UINT srcDepthPitch,
  bool* pDidWorkAround )
{
     HRESULT hr = S_OK;
     bool needWorkaround = false;
     D3D11_DEVICE_CONTEXT_TYPE contextType = pDeviceContext->GetType();

     if( pDstBox && (D3D11_DEVICE_CONTEXT_DEFERRED == contextType) )
     {
          D3D11_FEATURE_DATA_THREADING threadingCaps = { FALSE, FALSE };

          hr = pDevice->CheckFeatureSupport( D3D11_FEATURE_THREADING, &threadingCaps, sizeof(threadingCaps) );
          if( SUCCEEDED(hr) )
          {
               if( !threadingCaps.DriverCommandLists )
               {
                    needWorkaround = true;
               }
          }
     }

     const void* pAdjustedSrcData = pSrcData;

     if( needWorkaround )
     {
          D3D11_BOX alignedBox = *pDstBox;
		
          // convert from pixels to blocks
          if( m_bBC )
          {
               alignedBox.left     /= 4;
               alignedBox.right    /= 4;
               alignedBox.top      /= 4;
               alignedBox.bottom   /= 4;
          }

          pAdjustedSrcData = ((const BYTE*)pSrcData) - (alignedBox.front * srcDepthPitch) - (alignedBox.top * srcRowPitch) - (alignedBox.left * srcBytesPerElement);
     }

     pDeviceContext->UpdateSubresource( pDstResource, dstSubresource, pDstBox, pAdjustedSrcData, srcRowPitch, srcDepthPitch );

     if( pDidWorkAround )
     {
          *pDidWorkAround = needWorkaround;
     }

     return hr;
}

要求

   
目标平台 Windows
标头 d3d11.h
Library D3D11.lib

另请参阅

ID3D11DeviceContext

ID3D11Resource

基本全息影像示例