// Autogenerated by WaveGen.py, do not edit! // #include #include #include "common.h" #include "wavelet_common.h" /// Boundaries (depends on wavelet) /// This much is reserved at the sides of the signal /// Must be even! #define BLEFT 2 #define BRIGHT 2 /// Initial shift (to keep precision in integer wavelets) #define INITIAL_SHIFT 1 #define INITIAL_OFFSET 1 #define STAGE1_OFFSET 7 #define STAGE1_SHIFT 4 #define STAGE2_OFFSET 16 #define STAGE2_SHIFT 5 /// Vertical pass row management #define RLEFT 3 #define RRIGHT 2 #define COPYROWS 3 static __global__ void s_transform_h( DATATYPE* data, int width, int stride ) { extern __shared__ DATATYPE shared[]; const int bid = blockIdx.x; // row const int tid = threadIdx.x; // thread id within row const int tidu16 = ((tid&16)>>4)|((tid&15)<<1)|(tid&~31); data += __mul24(bid, stride); int half = BLEFT+(width>>1)+BRIGHT; int ofs; if(width&3) // If width is not a multiple of 4, we need to use the slower method { /// Left part (even coefficients) /// Right part (odd coefficients) int w2 = (width>>1); uint16_t *row = (uint16_t*)data; uint16_t *row2 = (uint16_t*)&data[w2]; uint16_t *dest1 = (uint16_t*)&shared[BLEFT]; uint16_t *dest2 = (uint16_t*)&shared[half+BLEFT]; ofs = tid; while(true) { if(ofs>2); uint32_t *row = (uint32_t*)data; uint32_t *row2 = (uint32_t*)&data[width>>1]; uint32_t *dest1 = (uint32_t*)&shared[BLEFT]; uint32_t *dest2 = (uint32_t*)&shared[half+BLEFT]; /// Left part (even coefficients) ofs = tid; while(true) { if(ofs>1)] = shared[half+BLEFT+(width>>1)-1]; } __syncthreads(); // Now apply wavelet lifting to entire line at once // Process odd const int end = BLEFT+(width>>1); for(ofs = BLEFT+tidu16; ofs < end; ofs += BSH) { int acc = STAGE2_OFFSET; acc += -1*shared[half+ofs-2]; acc += __mul24(9,shared[half+ofs-1]); acc += __mul24(9,shared[half+ofs+0]); acc += -1*shared[half+ofs+1]; shared[ofs] -= acc >> STAGE2_SHIFT; } __syncthreads(); if(tidu16==0) { shared[BLEFT-1] = shared[BLEFT]; shared[BLEFT+(width>>1)] = shared[BLEFT+(width>>1)-1]; shared[BLEFT+(width>>1)+1] = shared[BLEFT+(width>>1)-1]; } __syncthreads(); // Process even for(ofs = BLEFT+tidu16; ofs < end; ofs += BSH) { int acc = STAGE1_OFFSET; acc += 1*shared[ofs-1]; acc += __mul24(-9, shared[ofs+0]); acc += __mul24(-9, shared[ofs+1]); acc += 1*shared[ofs+2]; shared[ofs + half] -= acc >> STAGE1_SHIFT; } __syncthreads(); if(width&3) { uint32_t *row = (uint32_t*)data; int16_t *src1 = (int16_t*)&shared[BLEFT]; int16_t *src2 = (int16_t*)&shared[half+BLEFT]; int w2 = (width>>1); ofs = tid; while(true) { if(ofs>INITIAL_SHIFT; int b = (src2[ofs] + INITIAL_OFFSET)>>INITIAL_SHIFT; row[ofs] = (a&0xFFFF)|((b&0xFFFF)<<16); ofs += BSH; } else break; if(ofs>INITIAL_SHIFT; int b = (src2[ofs] + INITIAL_OFFSET)>>INITIAL_SHIFT; row[ofs] = (a&0xFFFF)|((b&0xFFFF)<<16); ofs += BSH; } else break; if(ofs>INITIAL_SHIFT; int b = (src2[ofs] + INITIAL_OFFSET)>>INITIAL_SHIFT; row[ofs] = (a&0xFFFF)|((b&0xFFFF)<<16); ofs += BSH; } else break; } } else { i16_4 *row = (i16_4*)data; i16_2 *src1 = (i16_2*)&shared[BLEFT]; i16_2 *src2 = (i16_2*)&shared[half+BLEFT]; int w2 = (width>>2); ofs = tid; while(true) { if(ofs < w2) { i16_4 x; i16_2 a = src1[ofs]; x.a = (a.a + INITIAL_OFFSET)>>INITIAL_SHIFT; x.c = (a.b + INITIAL_OFFSET)>>INITIAL_SHIFT; i16_2 b = src2[ofs]; x.b = (b.a + INITIAL_OFFSET)>>INITIAL_SHIFT; x.d = (b.b + INITIAL_OFFSET)>>INITIAL_SHIFT; row[ofs] = x; ofs += BSH; } else break; if(ofs < w2) { i16_4 x; i16_2 a = src1[ofs]; x.a = (a.a + INITIAL_OFFSET)>>INITIAL_SHIFT; x.c = (a.b + INITIAL_OFFSET)>>INITIAL_SHIFT; i16_2 b = src2[ofs]; x.b = (b.a + INITIAL_OFFSET)>>INITIAL_SHIFT; x.d = (b.b + INITIAL_OFFSET)>>INITIAL_SHIFT; row[ofs] = x; ofs += BSH; } else break; if(ofs < w2) { i16_4 x; i16_2 a = src1[ofs]; x.a = (a.a + INITIAL_OFFSET)>>INITIAL_SHIFT; x.c = (a.b + INITIAL_OFFSET)>>INITIAL_SHIFT; i16_2 b = src2[ofs]; x.b = (b.a + INITIAL_OFFSET)>>INITIAL_SHIFT; x.d = (b.b + INITIAL_OFFSET)>>INITIAL_SHIFT; row[ofs] = x; ofs += BSH; } else break; } } } #define BROWS (2*BSVY+COPYROWS) /* Rows to process at once */ #define SKIPTOP COPYROWS #define PAD_ROWS (WRITEBACK-SKIPTOP+RRIGHT+COPYROWS) /* Rows below which to use s_transform_v_pad */ /// tid is BCOLSxBROWS matrix /// RLEFT+BROWS+RRIGHT rows #define TOTALROWS (RLEFT+BROWS+RRIGHT) #define OVERLAP (RLEFT+RRIGHT+COPYROWS) #define OVERLAP_OFFSET (TOTALROWS-OVERLAP) #define WRITEBACK (2*BSVY) __device__ void doTransform(int xofs) { const int tidx = (threadIdx.x<<1)+xofs; // column const int tidy = threadIdx.y; // row extern __shared__ DATATYPE shared[]; int ofs; ofs = ((RLEFT+(tidy<<1)+3)<> STAGE2_SHIFT; } __syncthreads(); ofs -= BCOLS*3; { int acc = STAGE1_OFFSET; acc += 1*shared[ofs-3*BCOLS]; acc += __mul24(-9, shared[ofs-BCOLS]); acc += __mul24(-9, shared[ofs+BCOLS]); acc += 1*shared[ofs+3*BCOLS]; shared[ofs] -= acc >> STAGE1_SHIFT; } } __device__ void doTransformTB(int xofs, unsigned int leftover) { const int tidx = (threadIdx.x<<1)+xofs; // column const int tidy = threadIdx.y; // row const int minn = (RLEFT<> STAGE2_SHIFT; } __syncthreads(); /// Process odd rows ofs += BCOLS; { int acc = STAGE1_OFFSET; acc += 1*shared[max(ofs-3*BCOLS,minn)]; acc += __mul24(-9, shared[ofs-BCOLS]); acc += __mul24(-9, shared[min(ofs+BCOLS,maxx)]); acc += 1*shared[min(ofs+3*BCOLS,maxx)]; shared[ofs] -= acc >> STAGE1_SHIFT; } } __device__ void doTransformT(int xofs) { const int tidx = (threadIdx.x<<1)+xofs; // column const int tidy = threadIdx.y; // row const int minn = ((RLEFT+SKIPTOP)<> STAGE2_SHIFT; } __syncthreads(); /// Process odd rows, except for last ofs += BCOLS; if(tidy < (BSVY-2)) { int acc = STAGE1_OFFSET; acc += 1*shared[max(ofs-3*BCOLS,minn)]; acc += __mul24(-9, shared[ofs-BCOLS]); acc += __mul24(-9, shared[ofs+BCOLS]); acc += 1*shared[ofs+3*BCOLS]; shared[ofs] -= acc >> STAGE1_SHIFT; } } // Process leftover __device__ void doTransformB(int xofs, unsigned int leftover) { const int tidx = (threadIdx.x<<1)+xofs; // column const int tidy = threadIdx.y; // row const int maxx = leftover-(2<> STAGE2_SHIFT; } __syncthreads(); for(ofs_t=ofs; ofs_t> STAGE1_SHIFT; } } #if 0 // Rolled #define READ_LOOP(rows) for(; sofs < (rows); sofs += (BCOLS*BSVY), gofs += istride) *((uint32_t*)&shared[sofs]) = *((uint32_t*)&data[gofs]); #define WRITE_LOOP(rows) for(; sofs < (rows); sofs += (BCOLS*BSVY), gofs += istride) *((uint32_t*)&data[gofs]) = *((uint32_t*)&shared[sofs]); #endif #if 1 // Unrolled #define READ_LOOP_ENTRY(rows) if(sofs < (rows)) { *((uint32_t*)&shared[sofs]) = *((uint32_t*)&data[gofs]); sofs += (BCOLS*BSVY); gofs += istride; } else break; #define READ_LOOP(rows) while(1) { READ_LOOP_ENTRY(rows); READ_LOOP_ENTRY(rows); } #define WRITE_LOOP_ENTRY(rows) if(sofs < (rows)) { *((uint32_t*)&data[gofs]) = *((uint32_t*)&shared[sofs]); sofs += (BCOLS*BSVY); gofs += istride; } else break; #define WRITE_LOOP(rows) while(1) { WRITE_LOOP_ENTRY(rows); WRITE_LOOP_ENTRY(rows); } #endif #if 0 // Unrolled #define READ_LOOP_ENTRY(rows) if(sofs < (rows)) { *((uint32_t*)&shared[sofs]) = *((uint32_t*)&data[gofs]); sofs += (BCOLS*BSVY); gofs += istride; } #define READ_LOOP(rows) READ_LOOP_ENTRY(rows); READ_LOOP_ENTRY(rows); READ_LOOP_ENTRY(rows); #define WRITE_LOOP_ENTRY(rows) if(sofs < (rows)) { *((uint32_t*)&data[gofs]) = *((uint32_t*)&shared[sofs]); sofs += (BCOLS*BSVY); gofs += istride; } #define WRITE_LOOP(rows) WRITE_LOOP_ENTRY(rows); WRITE_LOOP_ENTRY(rows); WRITE_LOOP_ENTRY(rows); #endif static __global__ void s_transform_v( DATATYPE* data, int width, int height, int stride ) { extern __shared__ DATATYPE shared[]; const unsigned int bid = blockIdx.x; // slab (BCOLS columns) const unsigned int tidx = threadIdx.x<<1; // column const unsigned int tidy = threadIdx.y; // row const unsigned int swidth = min(width-(bid<>>(d_data, lwidth, lheight, stride); else s_transform_v<<>>(d_data, lwidth, lheight, stride); #endif #ifdef HORIZONTAL block_size.x = BSH; block_size.y = 1; block_size.z = 1; grid_size.x = lheight; grid_size.y = 1; grid_size.z = 1; shared_size = (lwidth+BLEFT*2+BRIGHT*2) * sizeof(DATATYPE); s_transform_h<<>>(d_data, lwidth, stride); #endif }