shader-slang / slang

Making it easier to work with shaders
MIT License
2.06k stars 177 forks source link

Lower integer/bool matrix types to arrays of vectors on targets without native support. #4386

Open natevm opened 3 months ago

natevm commented 3 months ago

Odd bug I just hit.

I had some HLSL code that was recently ported over, which had something like this:

float3x4 mat = buffer[0];
if (any(isnan(mat)) return; // skip this one
// logic operating on mat below...

With the "emit spirv directly" backend, Slang seems to generate invalid SPIRV, creating a %mat3v4bool = OpTypeMatrix %v4bool 3 type.

This results vkCreateShaderModule throwing an error:

VUID-VkShaderModuleCreateInfo-pCode-08737(ERROR / SPEC): msgNum: -1520283006 - Validation Error: [ VUID-VkShaderModuleCreateInfo-pCode-08737 ] | MessageID = 0xa5625282 | vkCreateShaderModule(): pCreateInfo->pCode is not valid SPIR-V: Matrix types can only be parameterized with floating-point types. %mat3v4bool = OpTypeMatrix %v4bool 3 . The Vulkan spec states: If pCode is a pointer to SPIR-V code, pCode must adhere to the validation rules described by the Validation Rules within a Module section of the SPIR-V Environment appendix (https://vulkan.lunarg.com/doc/view/1.3.268.0/windows/1.3-extensions/vkspec.html#VUID-VkShaderModuleCreateInfo-pCode-08737)

To be honest, I'm not really sure how DXC handles this...

natevm commented 3 months ago

As a workaround, I can do if (any(isnan(mat[0])) || any(isnan(mat[1])) || any(isnan(mat[2]))) return; and then this doesn't seem to generate boolean typed matrices.

csyonghe commented 3 months ago

DXC simply errors out on this code:

fatal error: generated SPIR-V is invalid: Expected bool scalar or vector type as Result Type: IsNan
  %30 = OpIsNan %v4float %29
csyonghe commented 3 months ago

In the long term, Slang should support integer and bool matrices on targets that doesn't have native support. We should just lower them into arrays of vectors.

ArielG-NV commented 2 months ago

Note: Related to: #4291 Addition would enable the following tests to work with the Metal backend: