[Mesa-dev] TGSI declarations missing type info

Jose Fonseca jfonseca at vmware.com
Mon Nov 14 12:24:46 PST 2011

----- Original Message -----
> On 11/14/2011 08:23 PM, Jose Fonseca wrote:
> > 
> > 
> > ----- Original Message -----
> >> The next open question I have is whether this warrants additions
> >> to
> >> the tgsi_opcode_info struct, mainly whether the return value is
> >> uint/int/float,
> >> and whether then src regs are uint/int/float, I'm not 100% that
> >> all
> >> opcodes always take all int/uint/float srcs, but my memory is a
> >> bit
> >> hazy on what the outliers might be.
> > 
> > I agree that adding this sort of info to tgsi_opcode_info would be
> > a code typing saver for all drivers.
> > 
> > However I never looked at the integer/double opcode set, but from
> > quickly skimming d3d10/11 headers, there are three buckets:
> > - arithmetic: (u)ints -> (u)int
> > - comparison: (u)ints -> mask (and I don't know what's the semantic
> > of these masks: 0/~0, 1.0f/0.0f, 0/1, or what)
> > - conversion: float <-> (u)int
> > 
> > 
> > And likewise to double, minus the unsigned vs signed split.
> > 
> > So, probably we need tgsi_opcode_info to distuinguish the source
> > type vs dest type, but we likely don't need per-source types.
> > 
> > 
> > 
> > A much more intricate question, is how to represent boolean mask in
> > a mixed type world. My guess is one of two:
> > 
> > a) is that there are two we should not mandate the bit
> > representation of a boolean (drivers are free to implement
> > booleans as 1.0f/0.0f, 0/~0, etc). The only constrainsts is that
> > the state tracker never tries to write a boolean directly to an
> > output.
> > 
> Booleans can be set by the user (CONST) and thus the state tracker
> has
> know what drivers want.

I forgot about those. 

One thing that's common to all representations is that 0x00000000 is false on all of them. So we could establish that as false.

Another approach, make cleaner, would be to disallow CONST booleans: i.e., the state tracker would use floats (0.0f/1.0f) or ints, and then explicitely emit a comparison against the null element to determine the boolean value:

   CONST[0] // boolean as float
   CONST[1] // boolean as integer
   CONST[2] // boolean as double
   IMM[0] = {0, 1.0f}

   // TEMP[0] == (bool)CONST[0]
   EQ TEMP[0], CONST[0], IMM[0].xxxx 

   // TEMP[1] == (bool)CONST[1]
   IEQ TEMP[1], CONST[1], IMM[0].xxxx

   // TEMP[2] == (bool)CONST[2]
   DEQ TEMP[2], CONST[2], IMM[0].xxxx 
And the inverse for outputs.

   // OUT[0] = TEMP[0] ? 1.0f : 0.0f
   SELECT OUT[0], TEMP[0], IMM[1], IMM[0] 

We need some way to encode integer/double immediates though.

> > b) if by some miracle, all hardware implements boolean vectors in
> > the same way, then we could stick to that.  (For sse/avx/llvm-2.9,
> > the natural way to represent a boolean vector is a bitmask (0/~0).
> > llvm 3.0 finally added support for bit vectors.)
> > 
> > 
> Currently, classic mesa uses 1/0, gallium uses 1.0f or ~0 depending
> on
> whether the driver supports integers.
> Also, the float SET opcodes return 1.0f/0.0f so there has to be
> conversion if the driver supports integers, and the integer SET
> opcodes
> are supposed to return ~0.

This is confusing -- so the semantics of e.g., IF's argument, depends on whether the pipe driver supports integers or not?

> In SM4, all comparison operations return ~0/0.

The way I was envisioning this was that the float SET opcodes would have to be redefined as returning these abstract booleans, and one would need to combine the SET opcode with a SELECT (i.e,  foo ? 1.0f : 0.0f) to match the old behavior.  Drivers that represent booleans as 0.0f/1.0f floats, would simply no-op on the (foo ? 1.0f : 0.0f) SELECT instruction.

> (<= nv40 only support 1.0f, nv50 supports only ~0, nvc0 can do both;
> conversion is a single instruction (convert to s32 with negation)).

The advantage of not mandating as bit-representation of booleans is that we could accommodate all these cases,  always the most efficient code without requiring peephole optimizers to remove redundant conversions between 1.0f / 0xffffffff / 1 representations.

On the other hand, if this seems too confusing, then one could just assume the pipe driver will eventually optimize these conversions away anyway, and establish all booleans are suppose to be 0.0f/1.0f (or 0/~0)  

I think that allowing multiple and slightly incompatible concepts of booleans in TGSI is a recipe for disaster. Note that 0x8000000 is zero for floats, and comparison semantics for NaNs are also special.


More information about the mesa-dev mailing list