Jump to content

  • Log In with Google      Sign In   
  • Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

How to use a bitmask with flags that use more than one bit?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
3 replies to this topic

#1 Icebone1000   Members   -  Reputation: 400

Like
0Likes
Like

Posted 13 March 2013 - 12:16 PM

[edit] actually I cant compare bits using bitfields with more then one bit, so no need to bother reading further..[/edit]

 

Say you have those flags in a bitfield:

 

setViewport  1 bit (on off)

setCbuffer    4 bits (slots 0 to 15)

setTexture    4 bits (slots 0 to 15)

setBlendSate 1 bit (on off)

...

(totally based on Hodgman pseudo codes I found around graphics forum)

 

You need to put it on a state:

uint64 stateMask;

So that you can check witch flags are set, set new flags, and so on..

 

 

stateMask &= command[it].stateBits;
if( stateMask & command[it].stateBits)
...
 

 

 

How do you define all possible values? How do you assign the command.stateBits a value?

I tried a enum, but VS complains about it being > than 32, and says its undefined behavior('<<' : shift count negative or too big, undefined behavior.), if Id define in hexa maybe it would work(a quick search and I found that enums can fit in any integral type theyd need, not sure), but godam, too fancy. Defining the values for the enums is a pain in the ass.

Than I created a union between a struct bitfield and a uint64...seens nice but thats a type, not a value..Its kinda stupid but I dont know how to do it elegantly.

If I use the struct bitfield, each state value will need to be initialized in the constructor of the command objects:

 

 

union Bitfield{
   uint64 asInt64;
   struct{
     bool Viewport : 1;
     uint CBuffer : 4;
     uint Texture : 4;
     bool BlendState : 1;
     ...
   }
}

struct SetCBuffer4Command{
   Bitfield stateBits;
   SetCBuffer4Command(){
      stateBits.CBuffer = 4; // intead of stateBits = 4<<1, where id need to remind of the bits position;
   }
}
...
stateMask &= command[it].stateBits.asInt64;

 

Any suggestion? Ive heard bitfields arent guaranteed of preserving its order, with means I just cant do that...


Edited by Icebone1000, 13 March 2013 - 02:27 PM.


Ad:

#2 TheChubu   Members   -  Reputation: 1079

Like
1Likes
Like

Posted 13 March 2013 - 01:21 PM

I don't understand. If texture needs 4 bits it means that it needs 4 yes/no parameters right? Isn't the whole idea to do a check per each bit instead of the combinations of them?

 

For texture alone you have 16 combinations of its 4 bits. Why not instead to do a check for each bit which are just 4 in total?

 

Just define all values that enable one bit of your bit mask, ie, 1 and every multiple of 2 that you need (viewport = 1, CBuffer1 = 2, CBuffer2 = 4, CBuffer3 = 8, etc) and check for all of them, they're surely going to be less than checking for each single combination of your bigger-than-one-bit flags.

 

EDIT: No wait. I don't think what I'm saying makes sense. What exactly does, say, the 4 bits of CBuffer represent? What do you need of it?


Edited by TheChubu, 13 March 2013 - 01:26 PM.


#3 Icebone1000   Members   -  Reputation: 400

Like
0Likes
Like

Posted 13 March 2013 - 02:21 PM

I don't understand. If texture needs 4 bits it means that it needs 4 yes/no parameters right? Isn't the whole idea to do a check per each bit instead of the combinations of them?

 

For texture alone you have 16 combinations of its 4 bits. Why not instead to do a check for each bit which are just 4 in total?

 

Just define all values that enable one bit of your bit mask, ie, 1 and every multiple of 2 that you need (viewport = 1, CBuffer1 = 2, CBuffer2 = 4, CBuffer3 = 8, etc) and check for all of them, they're surely going to be less than checking for each single combination of your bigger-than-one-bit flags.

 

EDIT: No wait. I don't think what I'm saying makes sense. What exactly does, say, the 4 bits of CBuffer represent? What do you need of it?

Actually, it wouldnt work as I imagined..with the bit setting and comparing that is...I was trying to find a alternative for the enum.

The point is their not yes and no, they are a integer, instead of using 16 bits, you use 4. With 4 bits you represent up to 16 values(a number), instead of wasting 16 bits for on and off. But doesnt work with the bits comparison, so basically my whole post was lame as shit.

I didnt want to create consts for every value possible, its terrible if you need edit, as things will get out of order, you need to edit everything downwards again, messy code.



#4 ifthen   Members   -  Reputation: 606

Like
0Likes
Like

Posted 13 March 2013 - 03:55 PM

It can be done quite easily. There are many uses of this technique, e.g. packets.

When retrieving those data, bit AND them by the bits you want to retrieve and right shift them so the least significant bit you want is lowest in the retrieved value. Example: You want bits ...00xxxx00 in the int you have. You bit AND 00111100 (called the mask, this number is hex 0x3C) with your int and right shift it by 2 (the offset).

 

 

int result = (myInt & 0x3C) >> 2;
 

 

("I grab only the bits that interest me and shift them so I get a number with values starting from zero.")

 

Setting the value is quite similar - you bit AND with the inverse of 0x3C (that means 0x3C EXCLUSIVE OR (^) 0), so the bits that interest us are zeroed (not needed when you know all of those bits are already zeroed), and then OR the left-shifted setValue. Note that having the value larger than your storage limit overwrites upper bits, so be wary of what you are doing!

 

 

int modified = ((0x3C ^ 0) & (myInt)) | (setValue << 2)
 

 

("I decide which bits interest me, get the opposite (those that don't interest me) and leave only them, effectively zeroing the bits that interest me. Then I shift the setValue so I write it to right bits and add it to the modified number, effectively setting the bits that interest me and are 1 in the setValue.")

 

Also, you can compute the mask (0x3C) like this:

 

 

 

int mask = 0;
for (int i = 0; i < numInterestingBits; i++)
{
  mask << 1;
  mask += 1;
}
mask = mask << offset; //also written mask <<= offset;

And that is it. Be sure to make your own functions for it so you don't rewrite it for every value retrieval!


Edited by ifthen, 13 March 2013 - 03:56 PM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS