UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
cuda_dxt.cu File Reference

CUDA implementation of DXT compression. More...

#include <cuda_runtime_api.h>
#include <stdio.h>
#include "cuda_dxt.h"
Include dependency graph for cuda_dxt.cu:

Go to the source code of this file.

Classes

struct  uvec2
 
struct  uvec3
 
struct  vec2
 
struct  vec3
 

Typedefs

typedef unsigned int u32
 
typedef u32 UINT
 

Functions

static __device__ vec2 abs (const vec2 &v)
 
static __device__ float clamp (const float &v, float min_val, float max_val)
 
static __device__ vec2 clamp (const vec2 &v, float min_val, float max_val)
 
static __device__ float colorDistance (vec2 c0, vec2 c1)
 
static __device__ vec3 ConvertRGBToYCoCg (vec3 color)
 
int cuda_rgb_to_dxt1 (const void *src, void *out, int size_x, int size_y, cuda_wrapper_stream_t stream)
 
int cuda_rgb_to_dxt6 (const void *src, void *out, int size_x, int size_y, cuda_wrapper_stream_t stream)
 
int cuda_yuv422_to_yuv444 (const void *src, void *out, int pix_count, cuda_wrapper_stream_t str)
 
int cuda_yuv_to_dxt1 (const void *src, void *out, int size_x, int size_y, cuda_wrapper_stream_t stream)
 
int cuda_yuv_to_dxt6 (const void *src, void *out, int size_x, int size_y, cuda_wrapper_stream_t stream)
 
static __device__ float dot (const vec3 &a, const vec3 &b)
 
template<int DXT_TYPE>
__device__ void dxt_encode (void *out, const int block_idx, float r[16], float g[16], float b[16])
 Encodes and saves the block.
 
template<>
__device__ void dxt_encode< 1 > (void *out, const int block_idx, float r[16], float g[16], float b[16])
 Encodes the block into DXT1 format and saves it into output buffer.
 
template<>
__device__ void dxt_encode< 6 > (void *out, const int block_idx, float r[16], float g[16], float b[16])
 
template<bool YUV_TO_RGB, bool VERTICAL_MIRRORING, int DXT_TYPE>
static __global__ void dxt_kernel (const void *src, void *out, int size_x, int size_y)
 
template<bool YUV_TO_RGB, int DXT_TYPE>
static int dxt_launch (const void *src, void *out, int sx, int sy, cudaStream_t str)
 Compute grid size and launch DXT kernel.
 
static __device__ UINT EmitAlphaEndPointsYCoCgDXT5 (float mincol, float maxcol)
 
static __device__ uvec2 EmitAlphaIndicesYCoCgDXT5 (vec3 block[16], float minAlpha, float maxAlpha)
 
static __device__ UINT EmitEndPointsYCoCgDXT5 (float &mincol_r, float &mincol_g, float &maxcol_r, float &maxcol_g, UINT scale)
 
static __device__ UINT EmitIndicesYCoCgDXT5 (vec3 block[16], vec2 mincol, vec2 maxcol)
 
static __device__ u32 encode_endpoint (float &r, float &g, float &b)
 Encodes color palette endpoint into 565 code and adjusts input values.
 
static __device__ void FindMinMaxColorsBox (vec3 block[16], vec3 &mincol, vec3 &maxcol)
 
static __device__ void InsetCoCgBBox (vec2 &mincol, vec2 &maxcol)
 
static __device__ void InsetYBBox (float &mincol, float &maxcol)
 
static __device__ vec3 lerp (const vec3 &a, const vec3 &b, const float q)
 
static __device__ vec2 max (const vec2 &a, const vec2 &b)
 
static __device__ vec3 max (const vec3 &a, const vec3 &b)
 
static __device__ vec2 min (const vec2 &a, const vec2 &b)
 
static __device__ vec3 min (const vec3 &a, const vec3 &b)
 
static __device__ vec3 round (const vec3 &v)
 
static __device__ UINT ScaleYCoCg (vec2 minColor, vec2 maxColor)
 
static __device__ bool SelectYCoCgDiagonal (const vec3 block[16], vec2 minColor, vec2 maxColor)
 
template<typename T >
static __device__ void swap (T &a, T &b)
 Swaps two referenced values.
 
static __global__ void yuv422_to_yuv444_kernel (const void *src, void *out, int pix_count)
 
static __device__ void yuv_to_rgb (float &r, float &g, float &b)
 Transform YUV to RGB.
 

Variables

static __device__ const float offset = 128.0 / 255.0
 

Detailed Description

CUDA implementation of DXT compression.


Author
Martin Jirman jirma.nosp@m.n@ce.nosp@m.snet..nosp@m.cz

Definition in file cuda_dxt.cu.

Typedef Documentation

◆ u32

typedef unsigned int u32

Definition at line 12 of file cuda_dxt.cu.

◆ UINT

typedef u32 UINT

Definition at line 13 of file cuda_dxt.cu.

Function Documentation

◆ abs()

static __device__ vec2 abs ( const vec2 & v)
static

◆ clamp() [1/2]

static __device__ float clamp ( const float & v,
float min_val,
float max_val )
static

Definition at line 114 of file cuda_dxt.cu.

114 {
115 return min(max_val, max(min_val, v));
116}
#define min(a, b)
Definition rtp.c:99
#define max(a, b)
Definition rtp.c:98

References max, and min.

◆ clamp() [2/2]

static __device__ vec2 clamp ( const vec2 & v,
float min_val,
float max_val )
static

Definition at line 110 of file cuda_dxt.cu.

110 {
111 return min(vec2(max_val), max(vec2(min_val), v));
112}

References max, and min.

Referenced by fill_full_to_limited_lut(), fill_limited_to_full_lut(), InsetCoCgBBox(), and InsetYBBox().

◆ colorDistance()

static __device__ float colorDistance ( vec2 c0,
vec2 c1 )
static

Definition at line 154 of file cuda_dxt.cu.

155{
156 return dot(c0-c1, c0-c1);
157}
static __device__ float dot(const vec3 &a, const vec3 &b)
Definition cuda_dxt.cu:106

References dot().

Referenced by EmitIndicesYCoCgDXT5().

Here is the call graph for this function:

◆ ConvertRGBToYCoCg()

static __device__ vec3 ConvertRGBToYCoCg ( vec3 color)
static

Definition at line 141 of file cuda_dxt.cu.

142{
143 float Y = (color.r + 2.0 * color.g + color.b) * 0.25;
144 float Co = ( ( 2.0 * color.r - 2.0 * color.b ) * 0.25 + offset );
145 float Cg = ( ( -color.r + 2.0 * color.g - color.b) * 0.25 + offset );
146
147 return vec3(Y, Co, Cg);
148}
static __device__ const float offset
Definition cuda_dxt.cu:139
float b
Definition cuda_dxt.cu:56

References vec3::b, vec2::g, offset, and vec2::r.

Referenced by dxt_encode< 6 >().

◆ cuda_rgb_to_dxt1()

int cuda_rgb_to_dxt1 ( const void * src,
void * out,
int size_x,
int size_y,
cuda_wrapper_stream_t stream )

CUDA DXT1 compression (only RGB without alpha).

Parameters
srcPointer to top-left source pixel in device-memory buffer. 8bit RGB samples are expected (no alpha and no padding). (Pointer must be aligned to multiples of 16 bytes.)
outPointer to output buffer in device memory. (Must be aligned to multiples of 8 bytes.)
size_xWidth of the input image (must be divisible by 4).
size_yHeight of the input image (must be divisible by 4).
streamCUDA stream to run in, or 0 for default stream.
Returns
0 if OK, nonzero if failed.

Definition at line 782 of file cuda_dxt.cu.

783 {
784 return dxt_launch<false, 1>(src, out, size_x, size_y, (cudaStream_t) stream);
785}
static int dxt_launch(const void *src, void *out, int sx, int sy, cudaStream_t str)
Compute grid size and launch DXT kernel.
Definition cuda_dxt.cu:736

References dxt_launch().

Referenced by main(), and worker_thread().

Here is the call graph for this function:

◆ cuda_rgb_to_dxt6()

int cuda_rgb_to_dxt6 ( const void * src,
void * out,
int size_x,
int size_y,
cuda_wrapper_stream_t stream )

CUDA DXT6 (DXT5-YcOcG) compression (only RGB without alpha).

Parameters
srcPointer to top-left source pixel in device-memory buffer. 8bit RGB samples are expected (no alpha and no padding). (Pointer must be aligned to multiples of 16 bytes.)
outPointer to output buffer in device memory. (Must be aligned to multiples of 8 bytes.)
size_xWidth of the input image (must be divisible by 4).
size_yHeight of the input image (must be divisible by 4). (Input is read bottom up if negative)
streamCUDA stream to run in, or 0 for default stream.
Returns
0 if OK, nonzero if failed.

Definition at line 816 of file cuda_dxt.cu.

817 {
818 return dxt_launch<false, 6>(src, out, size_x, size_y, (cudaStream_t) stream);
819}

References dxt_launch().

Referenced by main(), and worker_thread().

Here is the call graph for this function:

◆ cuda_yuv422_to_yuv444()

int cuda_yuv422_to_yuv444 ( const void * src,
void * out,
int pix_count,
cuda_wrapper_stream_t str )

Definition at line 762 of file cuda_dxt.cu.

763 {
764 // grid and threadblock sizes
765 const dim3 tsiz(64, 1);
766 int thread_count = pix_count / 4; // we process block of 4 pixels
767 const dim3 gsiz((thread_count + tsiz.x - 1) / tsiz.x, 1);
768 yuv422_to_yuv444_kernel<<<gsiz, tsiz, 0, (cudaStream_t) str>>>(src, out, pix_count);
769 return cudaSuccess != cudaStreamSynchronize((cudaStream_t) str) ? -3 : 0;
770}
static __global__ void yuv422_to_yuv444_kernel(const void *src, void *out, int pix_count)
Definition cuda_dxt.cu:697
#define cudaSuccess

References cudaSuccess, and yuv422_to_yuv444_kernel().

Here is the call graph for this function:

◆ cuda_yuv_to_dxt1()

int cuda_yuv_to_dxt1 ( const void * src,
void * out,
int size_x,
int size_y,
cuda_wrapper_stream_t stream )

CUDA DXT1 compression (only RGB without alpha). Converts input from YUV to RGB color space.

Parameters
srcPointer to top-left source pixel in device-memory buffer. 8bit RGB samples are expected (no alpha and no padding). (Pointer must be aligned to multiples of 16 bytes.)
outPointer to output buffer in device memory. (Must be aligned to multiples of 8 bytes.)
size_xWidth of the input image (must be divisible by 4).
size_yHeight of the input image (must be divisible by 4).
streamCUDA stream to run in, or 0 for default stream.
Returns
0 if OK, nonzero if failed.

Definition at line 799 of file cuda_dxt.cu.

800 {
801 return dxt_launch<true, 1>(src, out, size_x, size_y, (cudaStream_t) stream);
802}

References dxt_launch().

Here is the call graph for this function:

◆ cuda_yuv_to_dxt6()

int cuda_yuv_to_dxt6 ( const void * src,
void * out,
int size_x,
int size_y,
cuda_wrapper_stream_t stream )

Definition at line 821 of file cuda_dxt.cu.

822 {
823 return dxt_launch<true, 6>(src, out, size_x, size_y, (cudaStream_t) stream);
824}

References dxt_launch().

Here is the call graph for this function:

◆ dot()

static __device__ float dot ( const vec3 & a,
const vec3 & b )
static

Definition at line 106 of file cuda_dxt.cu.

106 {
107 return a.r * b.r + a.g * b.g + a.b * b.b;
108}

References vec3::b, vec2::g, and vec2::r.

Referenced by colorDistance().

◆ dxt_encode()

template<int DXT_TYPE>
__device__ void dxt_encode ( void * out,
const int block_idx,
float r[16],
float g[16],
float b[16] )

Encodes and saves the block.

Referenced by dxt_kernel().

◆ dxt_encode< 1 >()

template<>
__device__ void dxt_encode< 1 > ( void * out,
const int block_idx,
float r[16],
float g[16],
float b[16] )

Encodes the block into DXT1 format and saves it into output buffer.

Definition at line 513 of file cuda_dxt.cu.

514 {
515 // find min and max sample values for each component
516 float mincol_r = r[0];
517 float mincol_g = g[0];
518 float mincol_b = b[0];
519 float maxcol_r = r[0];
520 float maxcol_g = g[0];
521 float maxcol_b = b[0];
522 for(int i = 1; i < 16; i++) {
523 mincol_r = min(mincol_r, r[i]);
524 mincol_g = min(mincol_g, g[i]);
525 mincol_b = min(mincol_b, b[i]);
526 maxcol_r = max(maxcol_r, r[i]);
527 maxcol_g = max(maxcol_g, g[i]);
528 maxcol_b = max(maxcol_b, b[i]);
529 }
530
531 // inset the bounding box
532 const float inset_r = (maxcol_r - mincol_r) * 0.0625f;
533 const float inset_g = (maxcol_g - mincol_g) * 0.0625f;
534 const float inset_b = (maxcol_b - mincol_b) * 0.0625f;
535 mincol_r += inset_r;
536 mincol_g += inset_g;
537 mincol_b += inset_b;
538 maxcol_r -= inset_r;
539 maxcol_g -= inset_g;
540 maxcol_b -= inset_b;
541
542 // select diagonal
543 const float center_r = (mincol_r + maxcol_r) * 0.5f;
544 const float center_g = (mincol_g + maxcol_g) * 0.5f;
545 const float center_b = (mincol_b + maxcol_b) * 0.5f;
546 float cov_x = 0.0f;
547 float cov_y = 0.0f;
548 for(int i = 0; i < 16; i++) {
549 const float dir_r = r[i] - center_r;
550 const float dir_g = g[i] - center_g;
551 const float dir_b = b[i] - center_b;
552 cov_x += dir_r * dir_b;
553 cov_y += dir_g * dir_b;
554 }
555 if(cov_x < 0.0f) {
556 swap(maxcol_r, mincol_r);
557 }
558 if(cov_y < 0.0f) {
559 swap(maxcol_g, mincol_g);
560 }
561
562 // encode both endpoints into 565 color format
563 const u32 max_code = encode_endpoint(maxcol_r, maxcol_g, maxcol_b);
564 const u32 min_code = encode_endpoint(mincol_r, mincol_g, mincol_b);
565
566 // swap palette end colors if 'max' code is less than 'min' color code
567 // (Palette color #3 would otherwise be interpreted as 'transparent'.)
568 const bool swap_end_colors = max_code < min_code;
569
570 // encode the palette into 32 bits (Only 2 end colors are stored.)
571 const u32 palette_code = swap_end_colors ?
572 min_code + (max_code << 16): max_code + (min_code << 16);
573
574 // pack palette color indices (if both endpoint colors are not equal)
575 u32 indices = 0;
576 if(max_code != min_code) {
577 // project each color to line maxcol-mincol, represent it as
578 // "mincol + t * (maxcol - mincol)" and then use 't' to find closest
579 // palette color index.
580 const float dir_r = mincol_r - maxcol_r;
581 const float dir_g = mincol_g - maxcol_g;
582 const float dir_b = mincol_b - maxcol_b;
583 const float dir_sqr_len = dir_r * dir_r + dir_g * dir_g + dir_b * dir_b;
584 const float dir_inv_sqr_len = __fdividef(1.0f, dir_sqr_len);
585 const float t_r = dir_r * dir_inv_sqr_len;
586 const float t_g = dir_g * dir_inv_sqr_len;
587 const float t_b = dir_b * dir_inv_sqr_len;
588 const float t_bias = t_r * maxcol_r + t_g * maxcol_g + t_b * maxcol_b;
589
590 // for each pixel color:
591 for(int i = 0; i < 16; i++) {
592 // get 't' for the color
593 const float col_t = r[i] * t_r + g[i] * t_g + b[i] * t_b - t_bias;
594
595 // scale the range of the 't' to [0..3] and convert to integer
596 // to get the index of palette color
597 const u32 col_idx = (u32)(3.0f * __saturatef(col_t) + 0.5f);
598
599 // pack the color palette index with others
600 indices += col_idx << (i * 2);
601 }
602 }
603
604 // possibly invert indices if end colors must be swapped
605 if(swap_end_colors) {
606 indices = ~indices;
607 }
608
609 // substitute all packed indices (each index is packed into two bits)
610 // 00 -> 00, 01 -> 10, 10 -> 11 and 11 -> 01
611 const u32 lsbs = indices & 0x55555555;
612 const u32 msbs = indices & 0xaaaaaaaa;
613 indices = msbs ^ (2 * lsbs + (msbs >> 1));
614
615 // compose and save output
616 ((uint2*)out)[block_idx] = make_uint2(palette_code, indices);
617}
unsigned int u32
Definition cuda_dxt.cu:12
static __device__ void swap(T &a, T &b)
Swaps two referenced values.
Definition cuda_dxt.cu:456
static __device__ u32 encode_endpoint(float &r, float &g, float &b)
Encodes color palette endpoint into 565 code and adjusts input values.
Definition cuda_dxt.cu:424

References encode_endpoint(), max, min, and swap().

Here is the call graph for this function:

◆ dxt_encode< 6 >()

template<>
__device__ void dxt_encode< 6 > ( void * out,
const int block_idx,
float r[16],
float g[16],
float b[16] )

Encodes the block into DXT6 format (DXT5-YcOcG) and saves it into output buffer

Definition at line 472 of file cuda_dxt.cu.

473 {
474 // Read block of data
475 vec3 block[16];
476
477 for(int i = 0; i < 16; i++) {
478 block[i] = ConvertRGBToYCoCg(vec3(r[i], g[i], b[i]));
479 }
480
481 // Find min and max colors
482 vec3 mincol, maxcol;
483 FindMinMaxColorsBox(block, mincol, maxcol);
484
485 if(SelectYCoCgDiagonal(block, mincol.gb(), maxcol.gb())) {
486 float tmp = maxcol.b;
487 maxcol.b = mincol.b;
488 mincol.b = tmp;
489 }
490
491 u32 scale = ScaleYCoCg(mincol.gb(), maxcol.gb());
492// printf("Scale: %u.\n", scale);
493 // Output CoCg in DXT1 block.
494 uint4 outp;
495 outp.z = EmitEndPointsYCoCgDXT5(mincol.g, mincol.b, maxcol.g, maxcol.b, scale);
496 outp.w = EmitIndicesYCoCgDXT5(block, mincol.gb(), maxcol.gb());
497
498 InsetYBBox(mincol.r, maxcol.r);
499
500 // Output Y in DXT5 alpha block.
501 outp.x = EmitAlphaEndPointsYCoCgDXT5(mincol.r, maxcol.r);
502
503 uvec2 indices = EmitAlphaIndicesYCoCgDXT5(block, mincol.r, maxcol.r);
504 outp.x |= indices.r;
505 outp.y = indices.g;
506
507 ((uint4*)out)[block_idx] = outp;
508
509}
static __device__ void InsetYBBox(float &mincol, float &maxcol)
Definition cuda_dxt.cu:176
static __device__ uvec2 EmitAlphaIndicesYCoCgDXT5(vec3 block[16], float minAlpha, float maxAlpha)
Definition cuda_dxt.cu:360
static __device__ vec3 ConvertRGBToYCoCg(vec3 color)
Definition cuda_dxt.cu:141
static __device__ void FindMinMaxColorsBox(vec3 block[16], vec3 &mincol, vec3 &maxcol)
Definition cuda_dxt.cu:159
static __device__ UINT EmitEndPointsYCoCgDXT5(float &mincol_r, float &mincol_g, float &maxcol_r, float &maxcol_g, UINT scale)
Definition cuda_dxt.cu:272
static __device__ bool SelectYCoCgDiagonal(const vec3 block[16], vec2 minColor, vec2 maxColor)
Definition cuda_dxt.cu:260
static __device__ UINT ScaleYCoCg(vec2 minColor, vec2 maxColor)
Definition cuda_dxt.cu:241
static __device__ UINT EmitIndicesYCoCgDXT5(vec3 block[16], vec2 mincol, vec2 maxcol)
Definition cuda_dxt.cu:315
static __device__ UINT EmitAlphaEndPointsYCoCgDXT5(float mincol, float maxcol)
Definition cuda_dxt.cu:350
u32 g
Definition cuda_dxt.cu:49
u32 r
Definition cuda_dxt.cu:49
__device__ vec2 gb() const
Definition cuda_dxt.cu:79

References vec3::b, ConvertRGBToYCoCg(), EmitAlphaEndPointsYCoCgDXT5(), EmitAlphaIndicesYCoCgDXT5(), EmitEndPointsYCoCgDXT5(), EmitIndicesYCoCgDXT5(), FindMinMaxColorsBox(), uvec2::g, vec2::g, vec3::gb(), InsetYBBox(), uvec2::r, vec2::r, ScaleYCoCg(), and SelectYCoCgDiagonal().

Here is the call graph for this function:

◆ dxt_kernel()

template<bool YUV_TO_RGB, bool VERTICAL_MIRRORING, int DXT_TYPE>
static __global__ void dxt_kernel ( const void * src,
void * out,
int size_x,
int size_y )
static

DXT compression - each thread compresses one 4x4 DXT block. Alpha-color palette mode is not used (always emmits 4color palette code).

Definition at line 623 of file cuda_dxt.cu.

623 {
624 // coordinates of this thread's 4x4 block
625 const int block_idx_x = threadIdx.x + blockIdx.x * blockDim.x;
626 const int block_idx_y = threadIdx.y + blockIdx.y * blockDim.y;
627
628 // coordinates of block's top-left pixel
629 const int block_x = block_idx_x * 4;
630 const int block_y = block_idx_y * 4;
631
632 // raster order index of the block
633 const int block_idx = block_idx_x + (size_x >> 2) * block_idx_y;
634
635 // skip if out of bounds
636 if(block_y >= size_y || block_x >= size_x) {
637 return;
638 }
639
640 // samples of 16 pixels
641 float r[16];
642 float g[16];
643 float b[16];
644
645 // load RGB samples for all 16 input pixels
646 const int src_stride = (size_x >> 2) * 3;
647 for(int y = 0; y < 4; y++) {
648 // offset of loaded pixels in the buffer
649 const int load_offset = y * 4;
650
651 // pointer to source of this input row
652 int row_idx = block_y + y;
653 if(VERTICAL_MIRRORING) {
654 row_idx = size_y - 1 - row_idx;
655 }
656 const uchar4 * const row_src = (uchar4*)src
657 + src_stride * row_idx
658 + block_idx_x * 3;
659
660 // load all 4 3component pixels of the row
661 const uchar4 p0 = row_src[0];
662 const uchar4 p1 = row_src[1];
663 const uchar4 p2 = row_src[2];
664
665 // pixel #0
666 r[load_offset + 0] = p0.x * 0.00392156862745f;
667 g[load_offset + 0] = p0.y * 0.00392156862745f;
668 b[load_offset + 0] = p0.z * 0.00392156862745f;
669
670 // pixel #1
671 r[load_offset + 1] = p0.w * 0.00392156862745f;
672 g[load_offset + 1] = p1.x * 0.00392156862745f;
673 b[load_offset + 1] = p1.y * 0.00392156862745f;
674
675 // pixel #2
676 r[load_offset + 2] = p1.z * 0.00392156862745f;
677 g[load_offset + 2] = p1.w * 0.00392156862745f;
678 b[load_offset + 2] = p2.x * 0.00392156862745f;
679
680 // pixel #3
681 r[load_offset + 3] = p2.y * 0.00392156862745f;
682 g[load_offset + 3] = p2.z * 0.00392156862745f;
683 b[load_offset + 3] = p2.w * 0.00392156862745f;
684 }
685
686 // transform colors from YUV to RGB if required
687 if(YUV_TO_RGB) {
688 for(int i = 0; i < 16; i++) {
689 yuv_to_rgb(r[i], g[i], b[i]);
690 }
691 }
692
693 // Select the right DXT type transform
694 dxt_encode<DXT_TYPE>(out, block_idx, r, g, b);
695}
__device__ void dxt_encode(void *out, const int block_idx, float r[16], float g[16], float b[16])
Encodes and saves the block.
static __device__ void yuv_to_rgb(float &r, float &g, float &b)
Transform YUV to RGB.
Definition cuda_dxt.cu:444

References dxt_encode(), and yuv_to_rgb().

Referenced by dxt_launch().

Here is the call graph for this function:

◆ dxt_launch()

template<bool YUV_TO_RGB, int DXT_TYPE>
static int dxt_launch ( const void * src,
void * out,
int sx,
int sy,
cudaStream_t str )
static

Compute grid size and launch DXT kernel.

Definition at line 736 of file cuda_dxt.cu.

736 {
737 // vertical mirroring?
738 bool mirrored = false;
739 if(sy < 0) {
740 mirrored = true;
741 sy = -sy;
742 }
743
744 // check image size and alignment
745 if((sx & 3) || (sy & 3) || (15 & (size_t)src) || (7 & (size_t)out)) {
746 return -1;
747 }
748
749 // grid and threadblock sizes
750 const dim3 tsiz(16, 16);
751 const dim3 gsiz((sx + tsiz.x - 1) / tsiz.x, (sy + tsiz.y - 1) / tsiz.y);
752
753 // launch kernel, sync and check the result
754 if(mirrored) {
755 dxt_kernel<YUV_TO_RGB, true, DXT_TYPE><<<gsiz, tsiz, 0, str>>>(src, out, sx, sy);
756 } else {
757 dxt_kernel<YUV_TO_RGB, false, DXT_TYPE><<<gsiz, tsiz, 0, str>>>(src, out, sx, sy);
758 }
759 return cudaSuccess != cudaStreamSynchronize(str) ? -3 : 0;
760}
static __global__ void dxt_kernel(const void *src, void *out, int size_x, int size_y)
Definition cuda_dxt.cu:623

References cudaSuccess, and dxt_kernel().

Referenced by cuda_rgb_to_dxt1(), cuda_rgb_to_dxt6(), cuda_yuv_to_dxt1(), and cuda_yuv_to_dxt6().

Here is the call graph for this function:

◆ EmitAlphaEndPointsYCoCgDXT5()

static __device__ UINT EmitAlphaEndPointsYCoCgDXT5 ( float mincol,
float maxcol )
static

Definition at line 350 of file cuda_dxt.cu.

351{
352 uvec2 tmp = uvec2(roundf(mincol * 255.0), roundf(maxcol * 255.0));
353 UINT c0 = tmp.r;
354 UINT c1 = tmp.g;
355
356 return (c0 << 8u) | c1;
357}
u32 UINT
Definition cuda_dxt.cu:13

References uvec2::g, and uvec2::r.

Referenced by dxt_encode< 6 >().

◆ EmitAlphaIndicesYCoCgDXT5()

static __device__ uvec2 EmitAlphaIndicesYCoCgDXT5 ( vec3 block[16],
float minAlpha,
float maxAlpha )
static

Definition at line 360 of file cuda_dxt.cu.

361{
362 const float ALPHA_RANGE = 7.0;
363
364 float mid = (maxAlpha - minAlpha) / (2.0 * ALPHA_RANGE);
365
366 float ab1 = minAlpha + mid;
367 float ab2 = (6.0 * maxAlpha + 1.0 * minAlpha) * (1.0 / ALPHA_RANGE) + mid;
368 float ab3 = (5.0 * maxAlpha + 2.0 * minAlpha) * (1.0 / ALPHA_RANGE) + mid;
369 float ab4 = (4.0 * maxAlpha + 3.0 * minAlpha) * (1.0 / ALPHA_RANGE) + mid;
370 float ab5 = (3.0 * maxAlpha + 4.0 * minAlpha) * (1.0 / ALPHA_RANGE) + mid;
371 float ab6 = (2.0 * maxAlpha + 5.0 * minAlpha) * (1.0 / ALPHA_RANGE) + mid;
372 float ab7 = (1.0 * maxAlpha + 6.0 * minAlpha) * (1.0 / ALPHA_RANGE) + mid;
373
374 uvec2 indices = uvec2(0, 0);
375
376 UINT index = 1u;
377 for ( int i = 0; i < 6; i++ ) {
378 float a = block[i].r;
379 index = 1u;
380 index += (a <= ab1) ? 1u : 0u;
381 index += (a <= ab2) ? 1u : 0u;
382 index += (a <= ab3) ? 1u : 0u;
383 index += (a <= ab4) ? 1u : 0u;
384 index += (a <= ab5) ? 1u : 0u;
385 index += (a <= ab6) ? 1u : 0u;
386 index += (a <= ab7) ? 1u : 0u;
387 index &= 7u;
388 index ^= (2u > index) ? 1u : 0u;
389 indices.r |= index << (3u * UINT(i) + 16u);
390 }
391
392 indices.g = index >> 1u;
393
394 for ( int i = 6; i < 16; i++ ) {
395 float a = block[i].r;
396 index = 1u;
397 index += (a <= ab1) ? 1u : 0u;
398 index += (a <= ab2) ? 1u : 0u;
399 index += (a <= ab3) ? 1u : 0u;
400 index += (a <= ab4) ? 1u : 0u;
401 index += (a <= ab5) ? 1u : 0u;
402 index += (a <= ab6) ? 1u : 0u;
403 index += (a <= ab7) ? 1u : 0u;
404 index &= 7u;
405 index ^= (2u > index) ? 1u : 0u;
406 indices.g |= index << (3u * UINT(i) - 16u);
407 }
408
409 return indices;
410}

References uvec2::g, uvec2::r, and vec2::r.

Referenced by dxt_encode< 6 >().

◆ EmitEndPointsYCoCgDXT5()

static __device__ UINT EmitEndPointsYCoCgDXT5 ( float & mincol_r,
float & mincol_g,
float & maxcol_r,
float & maxcol_g,
UINT scale )
static

Definition at line 272 of file cuda_dxt.cu.

275{
276 vec2 mincol = vec2(mincol_r, mincol_g);
277 vec2 maxcol = vec2(maxcol_r, maxcol_g);
278
279 maxcol = (maxcol - offset) * float(scale) + float(offset);
280 mincol = (mincol - offset) * float(scale) + float(offset);
281
282 InsetCoCgBBox(mincol, maxcol);
283
284 maxcol = round(maxcol * vec2(31, 63));
285 mincol = round(mincol * vec2(31, 63));
286
287 uvec2 imaxcol = uvec2(maxcol);
288 uvec2 imincol = uvec2(mincol);
289
290 uvec2 outp;
291 outp.r = (imaxcol.r << 11u) | (imaxcol.g << 5u) | (scale - UINT(1));
292 outp.g = (imincol.r << 11u) | (imincol.g << 5u) | (scale - UINT(1));
293
294 imaxcol.r = (imaxcol.r << 3u) | (imaxcol.r >> 2u);
295 imaxcol.g = (imaxcol.g << 2u) | (imaxcol.g >> 4u);
296 imincol.r = (imincol.r << 3u) | (imincol.r >> 2u);
297 imincol.g = (imincol.g << 2u) | (imincol.g >> 4u);
298
299 maxcol = vec2(imaxcol) * (1.0 / 255.0);
300 mincol = vec2(imincol) * (1.0 / 255.0);
301
302 // Undo rescale.
303 maxcol = (maxcol - offset) / float(scale) + float(offset);
304 mincol = (mincol - offset) / float(scale) + float(offset);
305
306 // distribute back
307 mincol_r = mincol.r;
308 mincol_g = mincol.g;
309 maxcol_r = maxcol.r;
310 maxcol_g = maxcol.g;
311
312 return outp.r | (outp.g << 16u);
313}
static __device__ void InsetCoCgBBox(vec2 &mincol, vec2 &maxcol)
Definition cuda_dxt.cu:182
static __device__ vec3 round(const vec3 &v)
Definition cuda_dxt.cu:122

References uvec2::g, vec2::g, InsetCoCgBBox(), offset, uvec2::r, vec2::r, and round().

Referenced by dxt_encode< 6 >().

Here is the call graph for this function:

◆ EmitIndicesYCoCgDXT5()

static __device__ UINT EmitIndicesYCoCgDXT5 ( vec3 block[16],
vec2 mincol,
vec2 maxcol )
static

Definition at line 315 of file cuda_dxt.cu.

316{
317 // Compute palette
318 vec2 c[4];
319 c[0] = maxcol;
320 c[1] = mincol;
321 c[2] = lerp(c[0], c[1], 1.0/3.0);
322 c[3] = lerp(c[0], c[1], 2.0/3.0);
323
324 // Compute indices
325 UINT indices = 0u;
326 for ( int i = 0; i < 16; i++ )
327 {
328 // find index of closest color
329 float4 dist;
330 dist.x = colorDistance(block[i].gb(), c[0]);
331 dist.y = colorDistance(block[i].gb(), c[1]);
332 dist.z = colorDistance(block[i].gb(), c[2]);
333 dist.w = colorDistance(block[i].gb(), c[3]);
334
335 uint4 b;
336 b.x = dist.x > dist.w ? 1u : 0u;
337 b.y = dist.y > dist.z ? 1u : 0u;
338 b.z = dist.x > dist.z ? 1u : 0u;
339 b.w = dist.y > dist.w ? 1u : 0u;
340 UINT b4 = dist.z > dist.w ? 1u : 0u;
341
342 UINT index = (b.x & b4) | (((b.y & b.z) | (b.x & b.w)) << 1u);
343 indices |= index << (UINT(i) * 2u);
344 }
345
346 // Output indices
347 return indices;
348}
static __device__ vec3 lerp(const vec3 &a, const vec3 &b, const float q)
Definition cuda_dxt.cu:126
static __device__ float colorDistance(vec2 c0, vec2 c1)
Definition cuda_dxt.cu:154

References colorDistance(), and lerp().

Referenced by dxt_encode< 6 >().

Here is the call graph for this function:

◆ encode_endpoint()

static __device__ u32 encode_endpoint ( float & r,
float & g,
float & b )
static

Encodes color palette endpoint into 565 code and adjusts input values.

Definition at line 424 of file cuda_dxt.cu.

424 {
425 // clamp to range [0,1] and use full output range for each component
426 r = rintf(__saturatef(r) * 31.0f);
427 g = rintf(__saturatef(g) * 63.0f); // 6 bits for green sample
428 b = rintf(__saturatef(b) * 31.0f);
429
430 // compose output 16bit code representing the endpoint color
431 const u32 code = ((u32)r << 11) + ((u32)g << 5) + (u32)b;
432
433 // convert all 3 endpoint component samples back to unit range
434 r *= 0.0322580645161f; // divide by 31
435 g *= 0.015873015873f; // divide by 63
436 b *= 0.0322580645161f; // divide by 31
437
438 // return output 16bit code for the endpoint
439 return code;
440}

Referenced by dxt_encode< 1 >().

◆ FindMinMaxColorsBox()

static __device__ void FindMinMaxColorsBox ( vec3 block[16],
vec3 & mincol,
vec3 & maxcol )
static

Definition at line 159 of file cuda_dxt.cu.

160{
161 mincol = block[0];
162 maxcol = block[0];
163
164 for ( int i = 1; i < 16; i++ ) {
165 mincol = min(mincol, block[i]);
166 maxcol = max(maxcol, block[i]);
167 }
168}

References max, and min.

Referenced by dxt_encode< 6 >().

◆ InsetCoCgBBox()

static __device__ void InsetCoCgBBox ( vec2 & mincol,
vec2 & maxcol )
static

Definition at line 182 of file cuda_dxt.cu.

183{
184 vec2 inset = (maxcol - mincol) / 16.0 - (8.0 / 255.0) / 16.0;
185 mincol = clamp(mincol + inset, 0.0, 1.0);
186 maxcol = clamp(maxcol - inset, 0.0, 1.0);
187}
static __device__ vec2 clamp(const vec2 &v, float min_val, float max_val)
Definition cuda_dxt.cu:110

References clamp().

Referenced by EmitEndPointsYCoCgDXT5().

Here is the call graph for this function:

◆ InsetYBBox()

static __device__ void InsetYBBox ( float & mincol,
float & maxcol )
static

Definition at line 176 of file cuda_dxt.cu.

177{
178 float inset = (maxcol - mincol) / 32.0 - (16.0 / 255.0) / 32.0;
179 mincol = clamp(mincol + inset, 0.0, 1.0);
180 maxcol = clamp(maxcol - inset, 0.0, 1.0);
181}

References clamp().

Referenced by dxt_encode< 6 >().

Here is the call graph for this function:

◆ lerp()

static __device__ vec3 lerp ( const vec3 & a,
const vec3 & b,
const float q )
static

Definition at line 126 of file cuda_dxt.cu.

126 {
127 return a * (1.0f - q) + b * q;
128}

Referenced by EmitIndicesYCoCgDXT5().

◆ max() [1/2]

static __device__ vec2 max ( const vec2 & a,
const vec2 & b )
static

Definition at line 102 of file cuda_dxt.cu.

102 {
103 return vec2(max(a.r, b.r), max(a.g, b.g));
104}

References vec2::g, max, and vec2::r.

◆ max() [2/2]

static __device__ vec3 max ( const vec3 & a,
const vec3 & b )
static

Definition at line 94 of file cuda_dxt.cu.

94 {
95 return vec3(max(a.r, b.r), max(a.g, b.g), max(a.b, b.b));
96}

References vec3::b, vec2::g, max, and vec2::r.

◆ min() [1/2]

static __device__ vec2 min ( const vec2 & a,
const vec2 & b )
static

Definition at line 98 of file cuda_dxt.cu.

98 {
99 return vec2(min(a.r, b.r), min(a.g, b.g));
100}

References vec2::g, min, and vec2::r.

◆ min() [2/2]

static __device__ vec3 min ( const vec3 & a,
const vec3 & b )
static

Definition at line 90 of file cuda_dxt.cu.

90 {
91 return vec3(min(a.r, b.r), min(a.g, b.g), min(a.b, b.b));
92}

References vec3::b, vec2::g, min, and vec2::r.

◆ round()

◆ ScaleYCoCg()

static __device__ UINT ScaleYCoCg ( vec2 minColor,
vec2 maxColor )
static

Definition at line 241 of file cuda_dxt.cu.

242{
243 vec2 m0 = abs(minColor - offset);
244 vec2 m1 = abs(maxColor - offset);
245
246 float m = max(max(m0.r, m0.g), max(m1.r, m1.g));
247
248 const float s0 = 64.0 / 255.0;
249 const float s1 = 32.0 / 255.0;
250
251 UINT scale = 1u;
252 if ( m < s0 )
253 scale = 2u;
254 if ( m < s1 )
255 scale = 4u;
256
257 return scale;
258}
static __device__ vec2 abs(const vec2 &v)
Definition cuda_dxt.cu:118

References abs(), vec2::g, max, offset, and vec2::r.

Referenced by dxt_encode< 6 >().

Here is the call graph for this function:

◆ SelectYCoCgDiagonal()

static __device__ bool SelectYCoCgDiagonal ( const vec3 block[16],
vec2 minColor,
vec2 maxColor )
static

Definition at line 260 of file cuda_dxt.cu.

261{
262 vec2 mid = (maxColor + minColor) * 0.5;
263
264 float cov = 0.0;
265 for ( int i = 0; i < 16; i++ ) {
266 vec2 t = block[i].gb() - mid;
267 cov += t.r * t.g;
268 }
269 return cov < 0.0;
270}

References vec2::g, vec3::gb(), and vec2::r.

Referenced by dxt_encode< 6 >().

Here is the call graph for this function:

◆ swap()

template<typename T >
static __device__ void swap ( T & a,
T & b )
static

Swaps two referenced values.

Definition at line 456 of file cuda_dxt.cu.

456 {
457 const T temp = a;
458 a = b;
459 b = temp;
460}

Referenced by dxt_encode< 1 >(), gl_process_frames(), and vidcap_deltacast_dvi_grab().

◆ yuv422_to_yuv444_kernel()

static __global__ void yuv422_to_yuv444_kernel ( const void * src,
void * out,
int pix_count )
static

Definition at line 697 of file cuda_dxt.cu.

697 {
698 // coordinates of this thread
699 const int block_idx_x = threadIdx.x + blockIdx.x * blockDim.x;
700
701 // skip if out of bounds
702 if(block_idx_x >= pix_count / 2) {
703 return;
704 }
705
706 uchar4 *this_src = ((uchar4 *) src) + block_idx_x * 2;
707 uchar4 *this_out = ((uchar4 *) out) + block_idx_x * 3;
708
709 uchar4 pix12 = this_src[0];
710 uchar4 pix34 = this_src[1];
711
712 uchar4 out_pix[3];
713 out_pix[0].x = pix12.y;
714 out_pix[0].y = pix12.x;
715 out_pix[0].z = pix12.z;
716
717 out_pix[0].w = pix12.w;
718 out_pix[1].x = pix12.x;
719 out_pix[1].y = pix12.z;
720
721 out_pix[1].z = pix34.y;
722 out_pix[1].w = pix34.x;
723 out_pix[2].x = pix34.z;
724
725 out_pix[2].y = pix34.w;
726 out_pix[2].z = pix34.x;
727 out_pix[2].w = pix34.z;
728
729 this_out[0] = out_pix[0];
730 this_out[1] = out_pix[1];
731 this_out[2] = out_pix[2];
732}

Referenced by cuda_yuv422_to_yuv444().

◆ yuv_to_rgb()

static __device__ void yuv_to_rgb ( float & r,
float & g,
float & b )
static

Transform YUV to RGB.

Definition at line 444 of file cuda_dxt.cu.

444 {
445 const float y = 1.1643f * (r - 0.0625f); // TODO: convert to FFMA
446 const float u = g - 0.5f;
447 const float v = b - 0.5f;
448 r = y + 1.7926f * v;
449 g = y - 0.2132f * u - 0.5328f * v;
450 b = y + 2.1124f * u;
451}

Referenced by dxt_kernel().

Variable Documentation

◆ offset