UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
kernels.cu File Reference
#include "kernels.hpp"
#include <cstdint>
#include <cstdio>
#include <cuda_runtime_api.h>
Include dependency graph for kernels.cu:

Go to the source code of this file.

Macros

#define LOG_LEVEL_DEBUG   7
 
#define MEASURE_KERNEL_DURATION_START(stream)
 
#define MEASURE_KERNEL_DURATION_STOP(stream)
 

Functions

template<typename store_t >
static __global__ void kernel_r12l_to_rg48 (uint8_t *in, uint8_t *out, unsigned size_x)
 
template<typename load_t >
static __global__ void kernel_rg48_to_r12l (uint8_t *in, uint8_t *out, unsigned size_x)
 
int postprocess_rg48_to_r12l (void *, void *, size_t, int size_x, int size_y, struct cmpto_j2k_dec_comp_format *, int, void *input_samples, size_t, void *, size_t, void *output_buffer, size_t, void *vstream)
 
int preprocess_r12l_to_rg48 (void *preprocessor, void *img_custom_data, size_t img_custom_data_size, int size_x, int size_y, struct cmpto_j2k_enc_comp_format *comp_formats, int comp_count, void *input_samples, size_t input_samples_size, void *output_samples, size_t output_samples_size, void *vstream)
 
template<typename store_t >
static __device__ void r12l_to_rg48_compute_blk (const uint8_t *in, uint8_t *out)
 adapted variant of vc_copylineR12LtoRG48
 
template<typename load_t >
static __device__ void rt48_to_r12l_compute_blk (const uint8_t *in, uint8_t *out)
 
template<typename load_t >
static __device__ void rt48_to_r12l_compute_last_blk (uint8_t *src, uint8_t *dst, unsigned width)
 

Variables

volatile int log_level
 

Detailed Description

Author
Martin Pulec pulec.nosp@m.@ces.nosp@m.net.c.nosp@m.z

This file hosts various CUDA kernels. Currently there are only kernels for cmpto_j2k compression and decompression.

Definition in file kernels.cu.

Macro Definition Documentation

◆ LOG_LEVEL_DEBUG

◆ MEASURE_KERNEL_DURATION_START

#define MEASURE_KERNEL_DURATION_START ( stream)
Value:
cudaEvent_t t0, t1; \
cudaEventCreate(&t0); \
cudaEventCreate(&t1); \
cudaEventRecord(t0, stream);

Definition at line 50 of file kernels.cu.

50#define MEASURE_KERNEL_DURATION_START(stream) \
51 cudaEvent_t t0, t1; \
52 cudaEventCreate(&t0); \
53 cudaEventCreate(&t1); \
54 cudaEventRecord(t0, stream);

Referenced by postprocess_rg48_to_r12l(), and preprocess_r12l_to_rg48().

◆ MEASURE_KERNEL_DURATION_STOP

#define MEASURE_KERNEL_DURATION_STOP ( stream)
Value:
cudaEventRecord(t1, stream); \
cudaEventSynchronize(t1); \
float elapsedTime = NAN; \
cudaEventElapsedTime(&elapsedTime, t0, t1); \
printf("%s elapsed time: %f ms\n", __func__, elapsedTime); \
} \
if (elapsedTime > 10.0) { \
fprintf( \
stderr, \
"Kernel in func %s duration %f > 10 ms, please report!\n", \
__func__, elapsedTime); \
}
#define LOG_LEVEL_DEBUG
Definition kernels.cu:48
volatile int log_level
Definition debug.cpp:65

Definition at line 55 of file kernels.cu.

55#define MEASURE_KERNEL_DURATION_STOP(stream) \
56 cudaEventRecord(t1, stream); \
57 cudaEventSynchronize(t1); \
58 float elapsedTime = NAN; \
59 cudaEventElapsedTime(&elapsedTime, t0, t1); \
60 if (log_level >= LOG_LEVEL_DEBUG) { \
61 printf("%s elapsed time: %f ms\n", __func__, elapsedTime); \
62 } \
63 if (elapsedTime > 10.0) { \
64 fprintf( \
65 stderr, \
66 "Kernel in func %s duration %f > 10 ms, please report!\n", \
67 __func__, elapsedTime); \
68 }

Referenced by postprocess_rg48_to_r12l(), and preprocess_r12l_to_rg48().

Function Documentation

◆ kernel_r12l_to_rg48()

template<typename store_t >
static __global__ void kernel_r12l_to_rg48 ( uint8_t * in,
uint8_t * out,
unsigned size_x )
static

Definition at line 318 of file kernels.cu.

319{
320 unsigned position_x = threadIdx.x + blockIdx.x * blockDim.x;
321 unsigned position_y = threadIdx.y + blockIdx.y * blockDim.y;
322 if (position_x >= (size_x + 7) / 8) {
323 return;
324 }
325 uint8_t *dst = out + 2 * (position_y * 3 * size_x + position_x * 3 * 8);
326 uint8_t *src =
327 in + (position_y * ((size_x + 7) / 8) + position_x) * 36;
328
329 if (position_x == size_x / 8) {
330 // compute the last incomplete block
331 alignas(uint32_t) uint8_t tmp[48];
333 for (unsigned i = 0; i < (size_x - position_x * 8) * 6; ++i) {
334 dst[i] = tmp[i];
335 }
336 return;
337 }
339}
static __device__ void r12l_to_rg48_compute_blk(const uint8_t *src, uint8_t *dst)
adapted variant of vc_copylineR12LtoRG48
Definition kernels.cu:344

References r12l_to_rg48_compute_blk().

Referenced by preprocess_r12l_to_rg48().

Here is the call graph for this function:

◆ kernel_rg48_to_r12l()

template<typename load_t >
static __global__ void kernel_rg48_to_r12l ( uint8_t * in,
uint8_t * out,
unsigned size_x )
static
Todo
fix the last block for widths not divisible by 8

Definition at line 238 of file kernels.cu.

239{
240 unsigned position_x = threadIdx.x + blockIdx.x * blockDim.x;
241 unsigned position_y = threadIdx.y + blockIdx.y * blockDim.y;
242 if (position_x >= (size_x + 7) / 8) {
243 return;
244 }
245 uint8_t *src = in + 2 * (position_y * 3 * size_x + position_x * 3 * 8);
246 uint8_t *dst =
247 out + (position_y * ((size_x + 7) / 8) + position_x) * 36;
248
249 // handle incomplete blocks
250 if (position_x == size_x / 8) {
252 size_x - position_x * 8);
253 return;
254 }
256}
static __device__ void rt48_to_r12l_compute_blk(const uint8_t *in, uint8_t *out)
Definition kernels.cu:80
static __device__ void rt48_to_r12l_compute_last_blk(uint8_t *src, uint8_t *dst, unsigned width)
Definition kernels.cu:224

References rt48_to_r12l_compute_blk(), and rt48_to_r12l_compute_last_blk().

Referenced by postprocess_rg48_to_r12l().

Here is the call graph for this function:

◆ postprocess_rg48_to_r12l()

int postprocess_rg48_to_r12l ( void * postprocessor,
void * img_custom_data,
size_t img_custom_data_size,
int size_x,
int size_y,
struct cmpto_j2k_dec_comp_format * comp_formats,
int comp_count,
void * input_samples,
size_t input_samples_size,
void * temp_buffer,
size_t temp_buffer_size,
void * output_buffer,
size_t output_buffer_size,
void * vstream )
See also
cmpto_j2k_dec_postprocessor_run_callback_cuda

Definition at line 261 of file kernels.cu.

276 {
277 cudaStream_t stream = (cudaStream_t) vstream;
278 dim3 threads_per_block(256);
279 dim3 blocks((((size_x + 7) / 8) + 255) / 256, size_y);
280
282
283 if (size_x % 2 == 0) {
285 <<<blocks, threads_per_block, 0, (cudaStream_t) stream>>>(
286 (uint8_t *) input_samples, (uint8_t *) output_buffer,
287 size_x);
288 } else {
289 thread_local bool warn_print;
290 if (!warn_print) {
291 fprintf(stderr,
292 "%s: Odd width %d px will use slower kernel!\n",
293 __func__, size_x);
294 warn_print = true;
295 }
297 <<<blocks, threads_per_block, 0, (cudaStream_t) stream>>>(
298 (uint8_t *) input_samples, (uint8_t *) output_buffer,
299 size_x);
300 }
301
303
304 return cudaGetLastError();
305}
#define cudaGetLastError
static __global__ void kernel_rg48_to_r12l(uint8_t *in, uint8_t *out, unsigned size_x)
Definition kernels.cu:238
#define MEASURE_KERNEL_DURATION_START(stream)
Definition kernels.cu:50
#define MEASURE_KERNEL_DURATION_STOP(stream)
Definition kernels.cu:55

References cudaGetLastError, kernel_rg48_to_r12l(), MEASURE_KERNEL_DURATION_START, and MEASURE_KERNEL_DURATION_STOP.

Here is the call graph for this function:

◆ preprocess_r12l_to_rg48()

int preprocess_r12l_to_rg48 ( void * preprocessor,
void * img_custom_data,
size_t img_custom_data_size,
int size_x,
int size_y,
struct cmpto_j2k_enc_comp_format * comp_formats,
int comp_count,
void * input_samples,
size_t input_samples_size,
void * output_samples,
size_t output_samples_size,
void * vstream )

Definition at line 453 of file kernels.cu.

459{
460 (void) preprocessor, (void) img_custom_data,
461 (void) img_custom_data_size, (void) comp_formats, (void) comp_count,
462 (void) input_samples_size, (void) output_samples_size;
463
464 cudaStream_t stream = (cudaStream_t) vstream;
465 dim3 threads_per_block(256);
466 dim3 blocks((((size_x+ 7) / 8) + 255) / 256, size_y);
467
469 if (size_x % 2 == 0) {
471 <<<blocks, threads_per_block, 0, stream>>>(
472 (uint8_t *) input_samples, (uint8_t *) output_samples,
473 size_x);
474 } else {
475 thread_local bool warn_print;
476 if (!warn_print) {
477 fprintf(stderr,
478 "%s: Odd width %d px will use slower kernel!\n",
479 __func__, size_x);
480 warn_print = true;
481 }
483 <<<blocks, threads_per_block, 0, stream>>>(
484 (uint8_t *) input_samples, (uint8_t *) output_samples,
485 size_x);
486 }
488
489 return cudaGetLastError();
490}
static __global__ void kernel_r12l_to_rg48(uint8_t *in, uint8_t *out, unsigned size_x)
Definition kernels.cu:318

References cudaGetLastError, kernel_r12l_to_rg48(), MEASURE_KERNEL_DURATION_START, and MEASURE_KERNEL_DURATION_STOP.

Here is the call graph for this function:

◆ r12l_to_rg48_compute_blk()

template<typename store_t >
static __device__ void r12l_to_rg48_compute_blk ( const uint8_t * src,
uint8_t * dst )
static

adapted variant of vc_copylineR12LtoRG48

Definition at line 344 of file kernels.cu.

345{
346 // load the data from in to src_u32
347 auto *in_u32 = (uint32_t *) in;
348 uint32_t src_u32[9];
349 for (unsigned i = 0; i < sizeof src_u32 / sizeof src_u32[0]; ++i) {
350 src_u32[i] = in_u32[i];
351 }
352
353 uint32_t dst_u32[12];
354 uint8_t *dst = (uint8_t *) dst_u32;
355 uint8_t *src = (uint8_t *) src_u32;
356
357 // 0
358 // R
359 *dst++ = src[0] << 4;
360 *dst++ = (src[1] << 4) | (src[0] >> 4);
361 // G
362 *dst++ = src[1] & 0xF0;
363 *dst++ = src[2];
364 // B
365 *dst++ = src[3] << 4;
366 *dst++ = (src[4 + 0] << 4) | (src[3] >> 4);
367
368 // 1
369 *dst++ = src[4 + 0] & 0xF0;
370 *dst++ = src[4 + 1];
371
372 *dst++ = src[4 + 2] << 4;
373 *dst++ = (src[4 + 3] << 4) | (src[4 + 2] >> 4);
374
375 *dst++ = src[4 + 3] & 0xF0;
376 *dst++ = src[8 + 0];
377
378 // 2
379 *dst++ = src[8 + 1] << 4;
380 *dst++ = (src[8 + 2] << 4) | (src[8 + 1] >> 4);
381
382 *dst++ = src[8 + 2] & 0xF0;
383 *dst++ = src[8 + 3];
384
385 *dst++ = src[12 + 0] << 4;
386 *dst++ = (src[12 + 1] << 4) | (src[12 + 0] >> 4);
387
388 // 3
389 *dst++ = src[12 + 1] & 0xF0;
390 *dst++ = src[12 + 2];
391
392 *dst++ = src[12 + 3] << 4;
393 *dst++ = (src[16 + 0] << 4) | (src[12 + 3] >> 4);
394
395 *dst++ = src[16 + 0] & 0xF0;
396 *dst++ = src[16 + 1];
397
398 // 4
399 *dst++ = src[16 + 2] << 4;
400 *dst++ = (src[16 + 3] << 4) | (src[16 + 2] >> 4);
401
402 *dst++ = src[16 + 3] & 0xF0;
403 *dst++ = src[20 + 0];
404
405 *dst++ = src[20 + 1] << 4;
406 *dst++ = (src[20 + 2] << 4) | (src[20 + 1] >> 4);
407
408 // 5
409 *dst++ = src[20 + 2] & 0xF0;
410 *dst++ = src[20 + 3];
411
412 *dst++ = src[24 + 0] << 4;
413 *dst++ = (src[24 + 1] << 4) | (src[24 + 0] >> 4);
414
415 *dst++ = src[24 + 1] & 0xF0;
416 *dst++ = src[24 + 2];
417
418 // 6
419 *dst++ = src[24 + 3] << 4;
420 *dst++ = (src[28 + 0] << 4) | (src[24 + 3] >> 4);
421
422 *dst++ = src[28 + 0] & 0xF0;
423 *dst++ = src[28 + 1];
424
425 *dst++ = src[28 + 2] << 4;
426 *dst++ = (src[28 + 3] << 4) | (src[28 + 2] >> 4);
427
428 // 7
429 *dst++ = src[28 + 3] & 0xF0;
430 *dst++ = src[32 + 0];
431
432 *dst++ = src[32 + 1] << 4;
433 *dst++ = (src[32 + 2] << 4) | (src[32 + 1] >> 4);
434
435 *dst++ = src[32 + 2] & 0xF0;
436 *dst++ = src[32 + 3];
437
438 // store the result
439 auto *out_t = (store_t *) out;
440 for (unsigned i = 0; i < sizeof dst_u32 / sizeof dst_u32[0]; ++i) {
441 static_assert(sizeof(store_t) == 2 || sizeof(store_t) == 4,
442 "Just uint{16,32} supported!");
443 if (sizeof(store_t) == 4) {
444 out_t[i] = dst_u32[i];
445 } else {
446 out_t[2 * i] = dst_u32[i] & 0xFFFFU;
447 out_t[2 * i + 1] = dst_u32[i] >> 16;
448 }
449 }
450}

Referenced by kernel_r12l_to_rg48().

◆ rt48_to_r12l_compute_blk()

template<typename load_t >
static __device__ void rt48_to_r12l_compute_blk ( const uint8_t * in,
uint8_t * out )
static

modified vc_copylineRG48toR12L

Definition at line 80 of file kernels.cu.

81{
82 // load the data from in to src_u32
83 auto *in_t = (load_t *) in;
84 uint32_t src_u32[12];
85 for (unsigned i = 0; i < sizeof src_u32 / sizeof src_u32[0]; ++i) {
86 static_assert(sizeof(load_t) == 2 || sizeof(load_t) == 4,
87 "Just uint{16,32} supported!");
88 if (sizeof(load_t) == 4) {
89 src_u32[i] = in_t[i];
90 } else {
91 src_u32[i] = in_t[2 * i] | in_t[2 * i + 1] << 16;
92 }
93 }
94
95 uint32_t dst_u32[9];
96 auto *dst = (uint8_t *) dst_u32;
97 auto *src = (uint8_t *) src_u32;
98
99 // 0
100 dst[0] = src[0] >> 4;
101 dst[0] |= src[1] << 4;
102 dst[1] = src[1] >> 4;
103 src += 2;
104
105 dst[1] |= src[0] & 0xF0;
106 dst[2] = src[1];
107 src += 2;
108
109 dst[3] = src[0] >> 4;
110 dst[3] |= src[1] << 4;
111 dst[4 + 0] = src[1] >> 4;
112 src += 2;
113
114 // 1
115 dst[4 + 0] |= src[0] & 0xF0;
116 dst[4 + 1] = src[1];
117 src += 2;
118
119 dst[4 + 2] = src[0] >> 4;
120 dst[4 + 2] |= src[1] << 4;
121 dst[4 + 3] = src[1] >> 4;
122 src += 2;
123
124 dst[4 + 3] |= src[0] & 0xF0;
125 dst[8 + 0] = src[1];
126 src += 2;
127
128 // 2
129 dst[8 + 1] = src[0] >> 4;
130 dst[8 + 1] |= src[1] << 4;
131 dst[8 + 2] = src[1] >> 4;
132 src += 2;
133
134 dst[8 + 2] |= src[0] & 0xF0;
135 dst[8 + 3] = src[1];
136 src += 2;
137
138 dst[12 + 0] = src[0] >> 4;
139 dst[12 + 0] |= src[1] << 4;
140 dst[12 + 1] = src[1] >> 4;
141 src += 2;
142
143 // 3
144 dst[12 + 1] |= src[0] & 0xF0;
145 dst[12 + 2] = src[1];
146 src += 2;
147
148 dst[12 + 3] = src[0] >> 4;
149 dst[12 + 3] |= src[1] << 4;
150 dst[16 + 0] = src[1] >> 4;
151 src += 2;
152
153 dst[16 + 0] |= src[0] & 0xF0;
154 dst[16 + 1] = src[1];
155 src += 2;
156
157 // 4
158 dst[16 + 2] = src[0] >> 4;
159 dst[16 + 2] |= src[1] << 4;
160 dst[16 + 3] = src[1] >> 4;
161 src += 2;
162
163 dst[16 + 3] |= src[0] & 0xF0;
164 dst[20 + 0] = src[1];
165 src += 2;
166
167 dst[20 + 1] = src[0] >> 4;
168 dst[20 + 1] |= src[1] << 4;
169 dst[20 + 2] = src[1] >> 4;
170 src += 2;
171
172 // 5
173 dst[20 + 2] |= src[0] & 0xF0;
174 dst[20 + 3] = src[1];
175 src += 2;
176
177 dst[24 + 0] = src[0] >> 4;
178 dst[24 + 0] |= src[1] << 4;
179 dst[24 + 1] = src[1] >> 4;
180 src += 2;
181
182 dst[24 + 1] |= src[0] & 0xF0;
183 dst[24 + 2] = src[1];
184 src += 2;
185
186 // 6
187 dst[24 + 3] = src[0] >> 4;
188 dst[24 + 3] |= src[1] << 4;
189 dst[28 + 0] = src[1] >> 4;
190 src += 2;
191
192 dst[28 + 0] |= src[0] & 0xF0;
193 dst[28 + 1] = src[1];
194 src += 2;
195
196 dst[28 + 2] = src[0] >> 4;
197 dst[28 + 2] |= src[1] << 4;
198 dst[28 + 3] = src[1] >> 4;
199 src += 2;
200
201 // 7
202 dst[28 + 3] |= src[0] & 0xF0;
203 dst[32 + 0] = src[1];
204 src += 2;
205
206 dst[32 + 1] = src[0] >> 4;
207 dst[32 + 1] |= src[1] << 4;
208 dst[32 + 2] = src[1] >> 4;
209 src += 2;
210
211 dst[32 + 2] |= src[0] & 0xF0;
212 dst[32 + 3] = src[1];
213 src += 2;
214
215 // store the result
216 auto *out_u32 = (uint32_t *) out;
217 for (unsigned i = 0; i < sizeof dst_u32 / sizeof dst_u32[0]; ++i) {
218 out_u32[i] = dst_u32[i];
219 }
220}

Referenced by kernel_rg48_to_r12l(), and rt48_to_r12l_compute_last_blk().

◆ rt48_to_r12l_compute_last_blk()

template<typename load_t >
static __device__ void rt48_to_r12l_compute_last_blk ( uint8_t * src,
uint8_t * dst,
unsigned width )
static

Definition at line 224 of file kernels.cu.

225{
226 alignas(uint32_t) uint8_t tmp[48];
227 for (unsigned i = 0; i < width * 6; ++i) {
228 tmp[i] = src[i];
229 }
231}

References rt48_to_r12l_compute_blk().

Referenced by kernel_rg48_to_r12l().

Here is the call graph for this function:

Variable Documentation

◆ log_level