Hey Christian,

On 12/21/2011 07:25 PM, Christian König wrote:
> Hi guys,
>
> On 21.12.2011 17:27, Maarten Lankhorst wrote:
>> Also a remark about your patch, wish you had inlined it..
> Sorry, not at home right now and I can't get this Thunderbird here to inline 
> the patches correctly.
>
>> diff --git a/src/gallium/auxiliary/vl/vl_vlc.h 
>> b/src/gallium/auxiliary/vl/vl_vlc.h
>> index dc4faed..f961b8b 100644
>> --- a/src/gallium/auxiliary/vl/vl_vlc.h
>> +++ b/src/gallium/auxiliary/vl/vl_vlc.h
>> @@ -115,22 +164,24 @@ vl_vlc_init(struct vl_vlc *vlc, const uint8_t *data, 
>> unsigned len)
>>   static INLINE unsigned
>>   vl_vlc_bits_left(struct vl_vlc *vlc)
>>   {
>> +   unsigned i;
>>      signed bytes_left = ((uint8_t*)vlc->end)-((uint8_t*)vlc->data);
>> +   for (i = 0; i<  vlc->num_inputs; ++i)
>> +      bytes_left += vlc->sizes[i];
>> Calculating this more than once is wasteful, shouldn't this be done once in 
>> init?
> Good idea, but doesn't make so much of a difference, since vl_vlc_bits_left 
> is only called once per macroblock.
>
>>      return bytes_left * 8 + vlc->valid_bits;
>>   }
>>
>> ....
>>
>> @@ -86,28 +123,40 @@ vl_vlc_fillbits(struct vl_vlc *vlc)
>>         vlc->buffer |= (uint64_t)value<<  (32 - vlc->valid_bits);
>>         ++vlc->data;
>>         vlc->valid_bits += 32;
>> +
>> +      /* if this input is depleted, go to next one */
>> +      if (vlc->data>= vlc->end&&  vlc->num_inputs) {
>> +         unsigned bytes_overdue = 
>> ((uint8_t*)vlc->data)-((uint8_t*)vlc->end);
>> +
>> +         /* adjust valid bits */
>> +         vlc->valid_bits -= bytes_overdue * 8;
>> +
>> +         /* clear not valid bits */
>> +         vlc->buffer&= ~((1LL<<  (64 - vlc->valid_bits)) - 1);
>> +
>> +         /* go on to next input */
>> +         vl_vlc_next_input(vlc);
>> +
>> +         /* and retry to fill the buffer */
>> +     vl_vlc_fillbits(vlc);
>> Is this recursion necessary? Can't you simply change the if to a while?
>> Also if you are evil and put in a zero-sized buffer, this code will not work,
>> so the if checks needs to be reworked. Same problem with vl_vlc_next_input 
>> and
>> unaligned pointers, you can cause it to crash with alignment 4n+1 and len<= 
>> 2.
> Yeah, all the corner cases like len < 4, badly aligned start and end of 
> buffer etc where not really covered by the last version of the patch.
>
> Take a look at the attached one, does it now cover all cases?
>
> On 21.12.2011 17:24, Younes Manton wrote:
>> 2011/12/21 Maarten Lankhorst<m.b.lankho...@gmail.com>:
>>> Hey Christian,
>>>
>>> On 12/21/2011 04:41 PM, Christian König wrote:
>>>> Those functions are called a couple of million times a second, so even if 
>>>> the assertion is only tested in debug builds it has quite an effect on 
>>>> performance, sometimes even masquerading real performance problems. So my 
>>>> practice was to only uncomment them when I work on that part of the code. 
>>>> I don't want to change the Assert semantics in any way, just a simple 
>>>> define enabling certain assertions only under certain conditions should be 
>>>> sufficient.
>>> I think it makes sense to have the debug builds enabling those asserts by 
>>> default.
>>>
>>> You could always do this in vl_mpeg12_bitstream.c when testing:
>>> #include "u_debug.h"
>>> #undef assert
>>> #include "vl_vlc.h"
>>> #define assert debug_assert
>>>
>>> On a related note, why is the vl code using assert.h directly instead of 
>>> u_debug.h ?
>>>
>>> ~Maarten
>> u_debug.h didn't always have assert wrappers.
> I wasn't even aware that gallium has its own assert implementation in 
> u_debug.h, cause a whole bunch of state trackers and drivers are using 
> assert.h instead.
>
> Anyway, I have no idea what I tried the last time to make it perform so 
> awfuly that I need to comment it out. So I think just leaving the assertions 
> enabled for now should be ok. As Maarten pointed out disabling it is just a 
> two liner.
It would be nice if you inlined patches for easier reviewing. :)

+   while (vlc->valid_bits < 32) {
+      /* if this input is depleted */
+      while (vlc->data >= vlc->end) {
+         
+         if (vlc->num_inputs)
+            /* go on to next input */
+            vl_vlc_next_input(vlc);
+         else
+            /* or give up since we don't have anymore inputs */
+            return;
+      }

I'm spotting an overflow that could be triggered with 64 single-byte unaligned 
buffers, maybe this is better:

+   while (vlc->valid_bits < 32) {
+      uint32_t value;
+      if (vlc->data >= vlc->end) {
+         if (vlc->num_inputs) {
+            vl_vlc_next_input(vlc);
+            continue;
+         } else
+            return;
+      }
+      value = *(const uint32_t*)vlc->data;
+      vlc->data += 4;
 #ifndef PIPE_ARCH_BIG_ENDIAN
       value = util_bswap32(value);
 #endif
+      vlc->buffer |= (uint64_t)value << (32 - vlc->valid_bits);
+      vlc->valid_bits += 32;
+      if (vlc->data > vlc->end) {
....


With all the pointer math, maybe change the type for 'end' and 'data' to
uint8_t? Then you would only need that single cast in fillbits (which
I did above) and you can kill all the casts everywhere.

~Maarten
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to