Skip to content
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

Physical layout #93

Open
helviett opened this issue Jan 7, 2025 · 6 comments
Open

Physical layout #93

helviett opened this issue Jan 7, 2025 · 6 comments
Assignees
Labels

Comments

@helviett
Copy link

helviett commented Jan 7, 2025

Great library in so many ways but the only thing I'm missing to pick it as math library to use in every project is physical layout of the matrices. Logical layout allows you to create proper matrices (e.g. translation(...), orthographics(...), etc.) to multiply by vector on the right (mul(m, v)) on CPU but you have to transpose matrix if shader compiler assumes column major layout of the matrix.

@redorav
Copy link
Owner

redorav commented Jan 7, 2025

Hi @helviett thanks for wrting. Can you clarify for me what you are trying to do with some code? Give me the matrix, the vector and the expected result, and how you want them to be laid out in memory?

I can do this currently

float4x4 leMatrix = float4x4
{
	1, 0, 0, 1,
	0, 1, 0, 2,
	0, 0, 1, 3,
	0, 0, 0, 1
};

float4 leVector = float4(1, 2, 3, 1);

float4 leProductVector = mul(leMatrix, leVector);

and this ends up producing a vector 2, 4, 6 and the translation in the matrix is on "the right side" of the matrix. A bit more detail would help to see what you're unable to achieve

@redorav redorav self-assigned this Jan 7, 2025
@helviett
Copy link
Author

helviett commented Jan 7, 2025

In premake:

  defines({
    "HLSLPP_FEATURE_TRANSFORM",
    "HLSLPP_LOGICAL_LAYOUT=HLSLPP_LOGICAL_LAYOUT_COL_MAJOR",
    "HLSLPP_COORDINATES=HLSLPP_COORDINATES_RIGHT_HANDED",
  })

In cpp:

float4x4 m = float4x4::translation(1, 2, 3);
/* same as
float4x4 m = float4x4
{
  1, 0, 0, 1,
  0, 1, 0, 2,
  0, 0, 1, 3,
  0, 0, 0, 1
};
*/
float4 v = float4(1, 2, 3, 1);
float4 result = mul(m, v);

In HLSL:

struct VsOut
{
  float4 position : SV_Position;
};

VsOut
vs(VsIn input)
{
  VsOut out;
  out.position = mul(m, input.position);
  return out;
}

HLSLPP_LOGICAL_LAYOUT doesn't affect the way matrix is stored. Even though translation is generated for pre multiply (mul(M, v)) matrix is stored as row major. In HLSL matrix layout is column major, so it interprets m as:

{
  1, 0, 0, 0,
  0, 1, 0, 0
  0, 0, 1, 0
  1, 2, 3, 1
}

Which is incorrect matrix to be used as translation matrix in pre multiplied form.

@redorav
Copy link
Owner

redorav commented Jan 7, 2025

Hi @helviett I think now I see what you mean, you want a matrix that treats physical rows as if they were columns. I think that is a bit more intrusive than just changing the logical layout of the matrix because it now involves going into the matrix multiplication functions and flipping the order of operations (an effective transpose) based on a define. The functions are already written so that's not an issue but dealing with the define branches and tests, etc isn't something I was planning to do in the near future.

Would you like to contribute such a change? You can test it properly as well as your use case needs it and I can clean it up after. If you can't I'm happy to keep it open until I get to it.

@redorav
Copy link
Owner

redorav commented Jan 10, 2025

Of course as a workaround you can tag your hlsl matrices as row_major but I'm sure you know that already, just a suggestion in any case

@redorav redorav added feature and removed question labels Jan 10, 2025
@helviett
Copy link
Author

Yeah, we know about the workarounds. But for some reason it's something that is not trivial to support for all our platforms (PS4, PS5, Metal, Vulkan, D3D12(X)). There are known bugs with reading/writing matrices when dealing with DXC -> SPIRV. Adding tags or pragmas probably multiplies number of bugs.

By the way, just out of curiosity tried to run this benchmark for hlslpp. Its on par with DXM and even beats it in vector operations.

@redorav
Copy link
Owner

redorav commented Jan 11, 2025

Is DXM what you are trying to replace? I didn't know about this benchmark, I'll make a note to test, sounds more interesting than the small microbenchmarks I have.

In terms of the feature, I figured changing the shader wasn't going to be that simple and in an established engine probably less so.

In hlsl++, I was thinking whether return types need to change for non-square matrices (?) and other bits of complexity that might be a bit annoying, although some matrices (e.g. 3x4 and 4x3) don't really have a physical layout to change (they optimize for space) so it makes it extra complicated. As in, 4x3 and 3x4 matrices are just 3 SIMD vectors, a 2x2 matrix is a single SIMD vector as well, things just don't map cleanly to shaders.

I'll give it some thought, if in the meantime you'd like to contribute something I'm open like I said. I'm on holiday as well so I have more limited access and time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants