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