-
Notifications
You must be signed in to change notification settings - Fork 722
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multiplication order is changing from HLSL to SPIR-V #956
Comments
The swap of operands is actually a side effect of how matrix types are handled in SPIR-V CodeGen. See the doc for details. Basically, a HLSL MxN matrix (M rows and N columns) is translated into a SPIR-V matrix with M vectors and each vector has N elements (M columns and N rows). So each matrix is conceptually represented as its transpose. To keep consistency, we need to swap the operands. This way of translation is kinda confusing, but it gets everything correct and works. DXC is consistent with glslang in handling matrices. See also KhronosGroup/glslang#433 and KhronosGroup/glslang#789 for related discussions. |
Thanks a lot for your reply. I packed matrices in row-major order (-Zpr) to fix the issue. |
If I understand correctly, the following happens:
And the justification for this is that it simplifies 1D subscripting of a matrix (i.e. While this preserves runtime semantics of HLSL (that is, matrices are column-major, and A command-line flag that instructs DXC to, instead of the above two rules, instead generate more complicated code for matrix subscripting, would therefore still be useful IMO. |
Title
Multiplication order is changed when HLSL is compiled to SPIR-V
Functional Impact
It completely changes the result of multiplication as it is not commutative.
Minimal repro steps
Download the following vertex shader:
AuxGeom.AuxTextVS_AuxTextVS_hlsl.txt
Compile it using dxc by executing: 'dxc.exe -spirv .\AuxGeom@AuxTextVS_AuxTextVS.hlsl -T vs_5_0
-E AuxTextVS' (Generated SPIR-V text can be found here:
generate_spirv_code.txt).
Expected result
I expect to get the same order of multiplication.
Actual result
The order of multiplication is changed. In other words, in HLSL we have the following multiplication:
OUT.pos=mul(cbAuxGeom.matViewProj,IN.pos);
which is compiled to the following SPIR-V multiplication:
%25 = OpLoad %v4float %in_var_POSITION
%73 = OpLoad %mat4v4float %72
%76 = OpVectorTimesMatrix %v4float %25 %73
Further technical details
I can understand that DirectX is always using row-major memory layout. A vector is usually encountered as a row and multiplication is usually mul(vec, matrix) and this needs to be changed in SPIR-V case, that is why the compiler is switching the orders but this is not a general rule. In CryEngine, the order of multiplication is usually the same as Vulkan SPIR-V which is mul(matrix, vec). So, the order does not need to change.
I think the best solution is to have a command line option to force switching the order in multiplication or not.
The text was updated successfully, but these errors were encountered: