複製效果
複製效果會建立一個幾乎完全相同效果的第二個複本。 如需為何不精確的說明,請參閱下列單一限定詞。 當想要在多個執行緒上使用效果架構時,效果的第二個複本很有用,因為效果執行時間不是安全線程,可維持高效能。
由於裝置內容也是非安全線程,因此不同的執行緒應該將不同的裝置內容傳遞至 ID3DX11EffectPass::Apply 方法。
您可以使用下列語法複製效果:
ID3DX11Effect* pClonedEffect = NULL;
UINT Flags = D3DX11_EFFECT_CLONE_FORCE_NONSINGLE;
HRESULT hr = pEffect->CloneEffect( Flags, &pClonedEffect );
在上述範例中,複製的複本會封裝與原始效果相同的狀態,而不論原始效果所在的狀態為何。 尤其是:
- 如果 pEffect 已優化,pCloned 效果就會優化
- 如果 pEffect 有一些使用者管理的變數,pCloned Effect 將會有相同的使用者管理變數, (請參閱下列單一描述)
- 在 pEffect 中套用呼叫更新裝置狀態) 在 pClonedEffect 中擱置之前,任何擱置中的變數更新 (
下列 Direct3D 11 裝置物件不可變或永遠不會由效果架構更新,因此複製的效果會指向與原始效果相同的物件:
- 狀態欄塊物件 (ID3D11BlendState、ID3D11RasterizerState、ID3D11DepthStencilState、ID3D11SamplerState)
- 著色器
- 類別實例
- 紋理 (不包含紋理緩衝區)
- 未排序的存取檢視
下列 Direct3D 11 裝置物件都是不可變且由效果執行時間 (修改,除非使用者管理或複製效果中的單一) ;當非單一時,會建立這些物件的新複本:
- 常數緩衝區
- 紋理緩衝區
單一常數緩衝區和紋理緩衝區
請注意,此討論同時適用于常數緩衝區和紋理,但會假設常數緩衝區容易閱讀。
在某些情況下,常數緩衝區只會由一個執行緒更新,但由複製效果設定的裝置狀態將會使用此資料。 例如,主要效果可能會更新世界,並檢視從複製效果中參考的矩陣,這些矩陣不會變更世界和檢視矩陣。 在這些情況下,複製的效果必須參考目前的常數緩衝區,而不是重新建立一個。
有兩種方式可以達成此預期的結果:
- 在複製的效果上使用 ID3DX11EffectConstantBuffer::SetConstantBuffer,讓它成為使用者管理
- 將常數緩衝區標示為 HLSL 程式碼中的「單一」,強制效果執行時間在複製之後視為使用者管理
上述兩種方法之間有兩個差異。 首先,在方法 1 中,會先建立新的 ID3D11Buffer,並在呼叫 SetConstantBuffer 之前建立和使用者。 此外,在複製效果中呼叫 UndoSetConstantBuffer 之後,方法 1 中變數指向新建立的緩衝區 (此方法 2 中的變數將會在 Apply) 上更新,而方法 2 中的變數會繼續指向原始緩衝區, (在 Apply) 上更新它。
請參閱 HLSL 中的下列範例:
cbuffer ObjectData
{
float4 Position;
};
single cbuffer ViewData
{
float4x4 ViewMatrix;
};
複製時,複製的效果會為 ObjectData 建立新的 ID3D11Buffer,並在 Apply 上填滿其內容,但參考 ViewData 的原始 ID3D11Buffer。 您可以藉由設定D3DX11_EFFECT_CLONE_FORCE_NONSINGLE旗標,在複製程式中忽略單一限定詞。
相關主題