hlslpp icon indicating copy to clipboard operation
hlslpp copied to clipboard

Add boolN types

Open redorav opened this issue 7 years ago • 8 comments

redorav avatar Apr 02 '18 09:04 redorav

@redorav Is this feature still planned? I find myself frequently using HLSL's any, all, select, or and and intrinsics with vector bool components. It would be really helpful for adoption on my end if these were added (if not already)

natevm avatar Sep 01 '24 18:09 natevm

Hi @natevm let me respond in parts

  1. any and all already return a single bool, and in hlsl always return a bool you can put into a conditional so that's something that already has the correct functionality and you can use

  2. select already exists. It returns a float4 that can be used with any or all

  3. or and and are not possible to implement in C++ because of old and silly operator rules that I haven't been able to work around. In short, one cannot create a function called and or or. This gets really annoying considering that the latest HLSL standard deprecates && and || in favor of and and or. I don't really know how to get around this other than perhaps create another set of functions called or_vec or and_vec but I haven't made up my mind and you can still use the traditional operators to get what you need

The only reason boolN might be desirable is that it avoids an intermediate check for 0 so it would be slightly faster. However, the cost to pay is quite big in terms of implementation and I never really got to it and no one found it useful anyway.

Hopefully that answers your question, if you have more questions let me know

redorav avatar Sep 02 '24 21:09 redorav

Really, I’m aiming for a framework where I can share slang code with the host. I agree that the direction HLSL went with this is frustrating…

In slang, both && and || are legal, so I don’t actually use and or or. However, slang throws a warning whenever integers are implicitly cast to Booleans, which happens with select where the first operator is a Boolean of a given component t width. So a lot of code there ends up having vectorized Boolean types.

Would it be less work to implement some sort of typedef to have BoolN’s map to uintN’s?

natevm avatar Sep 02 '24 21:09 natevm

What does your code look like so I can get an idea of what you're looking to make work?

A boolN is not like a uintN as far as I can tell, a boolN as far as I know only takes 2 values, 0 and 0xffffffff, and those are used as masks.

HLSL++ treats floatN and uintN and "bools" when they return from a function like == or != in the sense that they get preemptively masked so they can be passed to other functions that require masks.

In HLSL these implicit conversions have never been warnings so I'm not sure why Slang would be more pedantic about these. I have a feeling you'll have an easier time convincing Slang to be less strict about it.

In any case let's see the code and discuss it

redorav avatar Sep 02 '24 22:09 redorav

I’m working on some BVH traversal code where a BVH node has 8 children. I loop over two sets of four, and have several vectorized tests producing flags per child node processed per-component. I have a bool4 isHit which comes from a four-wide box intersection test, and a bool4 isNode, bool4 isEmpty, and bool4 isLeaf as well, which are logically combined together in a SIMD-style way to reduce thread diverge and instruction counts.

Slang targets more than just DXIR. I’m less familiar there, but with SPIR-V, there is no assumption about true values being 0xffffffff. image

In any case, incompatibilities like this are a really unfortunate deal breaker.

natevm avatar Sep 02 '24 23:09 natevm

HLSL++ treats floatN and uintN and "bools" when they return from a function like == or != in the sense that they get preemptively masked so they can be passed to other functions that require masks.

floatN and uintN are not Boolean’s, but the binary comparison operators == and != return component-wise boolean vectors in both HLSL and in Slang. You’d then use an any or all to reduce the vector down to a single Boolean value.

Iiuc, the motivation behind these intrinsics, beyond performance, are to give HLSL more well defined behavior for shortcircuiting.

natevm avatar Sep 02 '24 23:09 natevm

In HLSL these implicit conversions have never been warnings so I'm not sure why Slang would be more pedantic about these. I have a feeling you'll have an easier time convincing Slang to be less strict about it.

One of the motivating reasons for why folks use slang at the moment is the more strict type behavior. How strict the type safeness is becomes more of a subjective debate, and there is a compiler flag to disable the warnings, but personally I find that they help me avoid bugs. I’m not really willing to disable those warnings to adopt a library like this.

natevm avatar Sep 02 '24 23:09 natevm

I understand that you don't want to disable the warnings in Slang, and that's fine. However, consider that this is a library that takes HLSL as the model and not GLSL for example. There are compromises and things it cannot or are inconvenient to do. There are also concessions where it is simple to do so. Ultimately, the library may not work for you or you may want to fork it.

I have been thinking about how to best implement boolN types. First off there are some requirements. Certain implicit conversions happen all the time. This works float4 mask = (a != b); and swizzles such as float4 mask = (a != b).xxyy also work, both in HLSL and currently in hlsl++

Simply adding a boolN type means that I now lose the swizzle functionality or I need to implement a full-on type to interact with the existing ones. I hesitate to add those because of compile times, but I also don't know how these interact with e.g. double types. Those would also need to interact with bools but now conversions with doubles become more difficult instead of staying in double land.

In turn something like select() becomes more complicated because it needs to turn a boolN into a size that is compatible with the size of double. double4 result = select(boolVector, result1, result2) means that I need to turn boolVector into a mask somehow whereas the current implementation already works.

None of these are huge problems, but I don't plan on doing this in the near term and I'd have to think it through properly. If you have a proposal and would like to suggest something I'm all ears

redorav avatar Sep 03 '24 12:09 redorav