2013-03-06 70 views
3

我在建設我的3D仿真項目的DirectX :: XMMATRIX __declspec(對齊('16' ))將不會對齊

void SetConstantBuffer(ID3D11DeviceContext*_device_context, DirectX::XMMATRIX _world, DirectX::XMMATRIX _view, DirectX::XMMATRIX _projection) 
    { 
     ConstantBuffer const_buffer; 
     const_buffer.View = DirectX::XMMatrixTranspose(_world); 
     const_buffer.World = DirectX::XMMatrixTranspose(_view); 
     const_buffer.Projection = DirectX::XMMatrixTranspose(_projection); 
     _device_context->UpdateSubresource(m_const_buffer, 0, NULL, &const_buffer, 0, 0); 
    } 

使用DirectXMath我得到這些類型的編譯器錯誤的可能對SIMD標誌內DirectXMath:

錯誤C2719: '_world':用__declspec(對齊('16' 形式參數))不會被對齊
錯誤C2719: '_view':用__declspec形式參數(對齊('16 '))將不會對齊
錯誤C2719:'_projection ':用__declspec形式參數(對齊('16'))將不會對齊

是否有任何其他方式而不將其轉換爲DirectX :: XMFLOAT4X4?
順便說一下,我正在使用x86機器並在Visual Studio 2012 Express上進行編譯。

+1

x86編譯器不執行堆棧對齊,所以它不能保證參數結束。 – 2013-03-06 11:14:02

+0

如果沒有'__declspec(align('16'))'聲明,但使用對齊類型(如「XMFLOAT4A」),則可能引發此錯誤。以下解決方案也適用。 – PinkTurtle 2015-08-16 21:54:00

回答

5

通過const引用而不是按值傳遞值。

void SetConstantBuffer(
    ID3D11DeviceContext*_device_context, 
    const DirectX::XMMATRIX &_world, 
    const DirectX::XMMATRIX &_view, 
    const DirectX::XMMATRIX &_projection) 
+4

嗨,你能告訴我爲什麼這個工程? – poncho 2013-08-08 10:01:51

+0

即使這個評論是相當古老的,這裏我的理解是:對象(XMMATRIX)最初是16字節對齊的。如果您按值傳遞它們,則將這些值複製到不再保證爲16字節對齊的函數堆棧中。如果通過const引用傳遞它們,請確保對象不會更改,並且2.對象不在堆棧上(因此仍然對齊)。 – puelo 2016-03-05 13:35:39

+0

如果您編譯爲C,該怎麼辦?我不能在C代碼中使用引用。我在函數的__m256參數上得到這個錯誤,沒有decl規範。 – Bram 2016-03-29 21:29:22

0

__declspec(對齊(16))不適用根據微軟堆棧變量:MSDN Align。我的測試表明,這也適用於包裝的#pragma(16)

因此,堆棧變量需要被存儲爲XMFLOAT4X4和轉換,並從XMMATRIX使用XMLoadFloat4x4和XMStoreFloat4x4(你試圖避免)。

幸運的是,Direct3D中的大部分處理都是在視頻卡中執行的。偶爾的,不必要的64字節拷貝是因爲微軟的糟糕設計決定應該是不可察覺的。

+0

你的第二個陳述是錯誤的。首先,如果您始終保證自己的正確對齊方式(堆棧和堆),則不需要**使用「XMLoadFloat4x4」和「XMStoreFloat4x4」。其次,根據架構(arm64),您可以通過值來傳遞'XMMATRIX'。 – Matthias 2017-12-10 09:36:34

0

MSDN: DirectXMath Library Internals

的FXMMATRIX和CXMMATRIX別名幫助支持採取與__vectorcall傳遞HVA參數的優勢。

使用FXMMATRIX別名將第一個XMMATRIX作爲參數傳遞給函數 。這假定您沒有兩個以上的FXMVECTOR 參數或多於兩個float,double或FXMVECTOR參數到 矩陣的「右」。有關其他注意事項的信息,請參閱__vectorcall文檔。

否則使用CXMMATRIX別名。

DirectXMath Code

// Fix-up for (1st) XMMATRIX parameter to pass in-register for ARM64 and vector call; by reference otherwise 
#if (defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || _XM_VECTORCALL_) && !defined(_XM_NO_INTRINSICS_) 
typedef const XMMATRIX FXMMATRIX; 
#else 
typedef const XMMATRIX& FXMMATRIX; 
#endif 

// Fix-up for (2nd+) XMMATRIX parameters to pass by reference 
typedef const XMMATRIX& CXMMATRIX; 

解決方案

如果你想支持更廣泛的處理器架構,你最好使用XM_CALLCONV宏指定調用約定而不是硬編碼__vectorcall

void XM_CALLCONV SetConstantBuffer(
    FXMMATRIX _world, 
    CXMMATRIX _view, 
    CXMMATRIX _projection, 
    ID3D11DeviceContext *_device_context) { 
}