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實際執行 Draw 呼叫之前,在相同的頂點緩衝區上呼叫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。

若要計算指定資源的來源資料列間距和來源深度間距,請使用下列公式:

  • Source Row Pitch = [size of one element in bytes] * [一列中的元素數目]
  • 來源深度間距 = [來源資料列間距] * [ (高度) 的資料列數目]
在這個範例 3D 磁片區紋理中,每個元素的大小為 16 個位元組時,公式如下所示:
  • 來源資料列間距 = 16 * 2 = 32
  • 來源深度間距 = 16 * 2 * 3 = 96
下圖顯示資源在記憶體中配置時。 記憶體中配置 3D 磁片區紋理的圖例

例如,下列程式碼片段示範如何在 2D 紋理中指定目的地區域。 假設目的地紋理為 512x512,且作業會將 pData 指向的資料複製到 [ (120,100) 。目的地紋理中的 (200,220) ]。 此外,假設 rowPitch 已使用適當的值 (初始化,如上述) 所述。 frontback 分別設定為 0 和 1,因為前 等於 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 案例類似。 下列程式碼片段示範如何在 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

如果您的應用程式在延遲的內容上呼叫 UpdateSubresource ,其目的地方塊為 pDstBox 所指向的 pDstBox 點,且其非 (0,0,0) 位移,而且如果驅動程式不支援命令清單, 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
程式庫 D3D11.lib

另請參閱

ID3D11DeviceContext

ID3D11Resource

基本全像投影範例