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的效能取決於目的地資源是否有競爭。 例如,當應用程式執行Draw呼叫,並在GPU實際執行 Draw 呼叫之前,在相同的頂點緩衝區上呼叫UpdateSubresource時,就會發生頂點緩衝區資源的爭用。
- 當資源發生爭用時, UpdateSubresource 會執行 2 份來源資料複本。 首先,CPU 會將資料複製到命令緩衝區可存取的暫存儲存空間。 這個複本會在 方法傳回之前發生。 然後,GPU 會執行第二個複本,將來源資料複製到不可對應的記憶體。 第二個複本會以非同步方式進行,因為當命令緩衝區排清時,GPU 會執行此複本。
- 當沒有任何資源爭用時, UpdateSubresource 的行為取決於從 CPU 的觀點 (更快) :將資料複製到命令緩衝區,然後在命令緩衝區排清時執行第二個複本,或讓 CPU 將資料複製到最終資源位置。 這相依于基礎系統的架構。
此視覺效果中的每個區塊都代表資料元素,而每個元素的大小取決於資源的格式。 例如,如果資源格式DXGI_FORMAT_R32G32B32A32_FLOAT,則每個元素的大小會是 128 位或 16 個位元組。 這個 3D 磁片區紋理的寬度為 2、高度為 3,深度為 4。
若要計算指定資源的來源資料列間距和來源深度間距,請使用下列公式:
- Source Row Pitch = [size of one element in bytes] * [一列中的元素數目]
- 來源深度間距 = [來源資料列間距] * [ (高度) 的資料列數目]
- 來源資料列間距 = 16 * 2 = 32
- 來源深度間距 = 16 * 2 * 3 = 96
例如,下列程式碼片段示範如何在 2D 紋理中指定目的地區域。 假設目的地紋理為 512x512,且作業會將 pData 指向的資料複製到 [ (120,100) 。目的地紋理中的 (200,220) ]。 此外,假設 rowPitch 已使用適當的值 (初始化,如上述) 所述。 front 和 back 分別設定為 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 |