vulkanspir-v

Does `OpSDot` in SPIR-V with "Packed Vector Format" require its two inputs to be signed or unsigned?


The SPIR-V specification defines an optional Packed Vector Format switch for the operations OpSDot, OpUDot, and OpSUDot. When used, the two other inputs of the op must each be 32-bit integers, which are then interpreted as packed 4-dimensional vectors of 8-bit integers.

My question

In the "Packed Vector Format" case, does the signedness of these scalar 32-bit integer arguments have to match the (logical) signedness of their 8-bit components, or do the packed 32-bit scalars have to be unsigned regardless (as, e.g., is the case in WGSL)?

Why I'm confused about this

The spec for OpSDot and OpUDot only states that "Vector 1 and Vector 2 must have the same type", and that they "must be either 32-bit integers [...] or vectors", but it doesn't specify if they must or mustn't be signed. If they are (unpacked) vectors, it seems obvious to me that OpSDot expects signed vectors and OpUDot expects unsigned vectors. But when packing four signed 8-bit integers into a single 32-bit scalar, it seems more natural to me to treat the result as an unsigned integer (like in WGSL) because, at this point, it's just an "agglomeration of bits" for which standard arithmetic operations aren't meaningful anyway.

Validating with spirv-val seems to accept it either way, but it even accepts signed 32-bit integer inputs for unsigned packed dot products with OpUDot, which seems odd to me, so I don't trust the validator here. Adding to my confusion, the specification of OpSUDot (which performs mixed signed/unsigned integer dot product) does explicitly state that the second argument has to be unsigned, but it qualifies that this applies only if both arguments are (unpacked) vectors:

[...] When Vector 1 and Vector 2 are vectors, the components of Vector 2 must have a Signedness of 0. [← signedness defined if inputs are (unpacked) vectors]

When Vector 1 and Vector 2 are scalar integer types, Packed Vector Format must be specified to select how the integers are to be interpreted as vectors. [← case where arguments are "scalar integer types" (i.e., packed) discussed separately, without specifying signedness]

(Emphasis and annotations in [...] mine.)


Solution

  • The SPIR-V specification lays down its thinking on signed vs. unsigned by basically saying... it doesn't care. Unless an opcode explicitly says "unsigned" or "signed", it does not care which is used.

    In the mixed case you cite, it explicitly does care. But it only cares in one very particular usage of the opcode. In all other cases for that opcode, it does not care.