Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #version 420 compatibility
- layout(r32ui) restrict readonly uniform uimage2D tex_comp;
- layout(r32ui) restrict readonly uniform uimage2D tex_offset;
- layout(r16ui) restrict writeonly uniform uimage2D tex_decomp;
- struct STREAM_DATA
- {
- uint data_buffer;
- uint patch_index_int;
- uint bits_left;
- };
- STREAM_DATA s_stream_data;
- uint s_get_bits_en(in uint bit_num );
- uint s_clz();
- uint s_texel_fetch_linearly(in uint linear_index );
- void set_offset(in uint patch_offset);
- int get_residual(uint op_k,uint qbpp,uint max_q);
- const uint tex_comp_width = uint(1024); //the width of tex_comp
- const uint glimit = uint(32); //
- const uint patch_size = uint(8); //the size of the patch
- const uint int_length = uint(32); //
- void main()
- {
- ivec2 itex_coord = ivec2(gl_Vertex.xz);
- ivec2 patch_base = ivec2(itex_coord*patch_size);
- uint patch_offset = imageLoad(tex_offset, itex_coord).r; //locate the compressed patch in the tex_comp
- set_offset(patch_offset);
- uint first_pix = s_get_bits_en(uint(16));
- uint op_k = s_get_bits_en(uint(4));
- uint qbpp = s_get_bits_en(uint(4));
- uint max_q = glimit-qbpp-uint(1);
- uint xLength = patch_size;
- uint yLength = patch_size;
- int h1 = int(first_pix);
- imageStore(tex_decomp,ivec2(0,0) + patch_base ,uvec4(first_pix,0,0,0));
- int h2;
- /******************************************************************************
- the code is a little long, but the essence is below: read, decopress, and write.
- *******************************************************************************/
- for( int i=1; i< xLength; i++ )
- {
- h2 = h1 + get_residual(op_k,qbpp,max_q);
- imageStore(tex_decomp,ivec2(i,0) + patch_base ,uvec4(h2,0,0,0));
- h1 = h2;
- }
- for( int j=1; j< yLength; j++ )
- {
- for( int i=0; i<xLength; i++ )
- {
- h2 = h1 + get_residual(op_k,qbpp,max_q);
- imageStore(tex_decomp,ivec2(i,j) + patch_base ,uvec4(h2,0,0,0));
- h1 = h2;
- }
- }
- }
- //get bit_num bits from the compressed patch
- uint s_get_bits_en(in uint bit_num )
- {
- uint value = uint(0);
- if( s_stream_data.bits_left>= bit_num )
- {
- value = s_stream_data.data_buffer>>( int_length-bit_num );
- s_stream_data.data_buffer = s_stream_data.data_buffer<<bit_num;
- s_stream_data.bits_left -= bit_num;
- }
- else
- {
- value = s_stream_data.data_buffer>>( int_length-bit_num );
- uint still_need_copy = bit_num - s_stream_data.bits_left;
- s_stream_data.data_buffer = s_texel_fetch_linearly(s_stream_data.patch_index_int);
- s_stream_data.patch_index_int += uint(1);
- s_stream_data.bits_left = int_length;
- value += s_stream_data.data_buffer>>( int_length-still_need_copy );
- s_stream_data.data_buffer = s_stream_data.data_buffer<<still_need_copy;
- if( 32 == still_need_copy )
- s_stream_data.data_buffer = 0;
- s_stream_data.bits_left -= still_need_copy;
- }
- return value;
- }
- //count leading zero
- uint s_clz()
- {
- uint value = uint(0);
- if( s_stream_data.bits_left == int_length )
- value = s_stream_data.data_buffer;
- else
- {
- value = s_stream_data.data_buffer;
- uint temp = s_texel_fetch_linearly(s_stream_data.patch_index_int);
- value += temp>>( s_stream_data.bits_left );
- }
- return int_length - findMSB(value) - uint(1);
- }
- uint s_texel_fetch_linearly(in uint linear_index )
- {
- uint cody = linear_index/tex_comp_width;
- uint codx = linear_index - tex_comp_width*cody;
- uint val = imageLoad(tex_comp,ivec2(codx,cody)).x;
- return val;
- }
- //set the position of the index for reading
- void set_offset(in uint patch_offset)
- {
- s_stream_data.patch_index_int = patch_offset/int_length;
- uint index_inside = patch_offset - s_stream_data.patch_index_int*int_length;
- s_stream_data.bits_left = uint(0);
- s_stream_data.data_buffer = uint(0);
- s_get_bits_en(index_inside);
- }
- int get_residual(uint op_k,uint qbpp,uint max_q)
- {
- uint q = s_clz();
- uint mm = ( q - max_q )>>uint(31);
- uint nn = uint(1)-mm;
- uint next_bits = op_k*mm + qbpp*nn;
- uint r = s_get_bits_en(next_bits+uint(1)+q);
- r &= ~(uint(1)<<(next_bits));
- if( 0==mm )
- r+=1;
- q = (q<<op_k)*mm;
- uint value = q+r;
- uint parity = value & uint(1);
- int even = int(value)/2;
- int odd = -(int(value)+1)/2;
- int residual_true = odd*int(parity) + even*(1-int(parity));
- return residual_true;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement