huangcm
2024-12-18 9d29be7f7249789d6ffd0440067187a9f040c2cd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/**
* \brief Image warping kernel function.
* \param[in] input Input image object.
* \param[out] output scaled output image object.
* \param[in] warp_config: image warping parameters
*/
 
#ifndef WARP_Y
#define WARP_Y 1
#endif
 
// 8 bytes for each Y pixel
#define PIXEL_X_STEP   8
 
typedef struct {
    int frame_id;
    int width;
    int height;
    float trim_ratio;
    float proj_mat[9];
} CLWarpConfig;
 
__kernel void
kernel_image_warp_8_pixel (
    __read_only image2d_t input,
    __write_only image2d_t output,
    CLWarpConfig warp_config)
{
    // dest coordinate
    int d_x = get_global_id(0);
    int d_y = get_global_id(1);
 
    int out_width = get_image_width (output);
    int out_height = get_image_height (output);
 
    const sampler_t sampler = CLK_NORMALIZED_COORDS_TRUE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_LINEAR;
 
    // source coordinate
    float s_x = 0.0f;
    float s_y = 0.0f;
    float warp_x = 0.0f;
    float warp_y = 0.0f;
    float w = 0.0f;
 
    float t_x = 0.0f;
    float t_y = 0.0f;
 
    float16 pixel = 0.0f;
    float* output_pixel = (float*)(&pixel);
    int i = 0;
 
    t_y = d_y;
#pragma unroll
    for (i = 0; i < PIXEL_X_STEP; i++) {
        t_x = (float)(PIXEL_X_STEP * d_x + i);
 
        s_x = warp_config.proj_mat[0] * t_x +
              warp_config.proj_mat[1] * t_y +
              warp_config.proj_mat[2];
        s_y = warp_config.proj_mat[3] * t_x +
              warp_config.proj_mat[4] * t_y +
              warp_config.proj_mat[5];
        w = warp_config.proj_mat[6] * t_x +
            warp_config.proj_mat[7] * t_y +
            warp_config.proj_mat[8];
        w = w != 0.0f ? 1.0f / w : 0.0f;
 
        warp_x = (s_x * w) / (float)(PIXEL_X_STEP * out_width);
        warp_y = (s_y * w) / (float)out_height;
 
#if WARP_Y
        output_pixel[i] = read_imagef(input, sampler, (float2)(warp_x, warp_y)).x;
#else
        float2 temp = read_imagef(input, sampler, (float2)(warp_x, warp_y)).xy;
        output_pixel[2 * i] = temp.x;
        output_pixel[2 * i + 1] = temp.y;
#endif
    }
 
#if WARP_Y
    write_imageui(output, (int2)(d_x, d_y), convert_uint4(as_ushort4(convert_uchar8(pixel.lo * 255.0f))));
#else
    write_imageui(output, (int2)(d_x, d_y), as_uint4(convert_uchar16(pixel * 255.0f)));
#endif
 
}
 
__kernel void
kernel_image_warp_1_pixel (
    __read_only image2d_t input,
    __write_only image2d_t output,
    CLWarpConfig warp_config)
{
    // dest coordinate
    int d_x = get_global_id(0);
    int d_y = get_global_id(1);
 
    int out_width = get_image_width (output);
    int out_height = get_image_height (output);
 
    const sampler_t sampler = CLK_NORMALIZED_COORDS_TRUE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_LINEAR;
 
    // source coordinate
    float s_x = warp_config.proj_mat[0] * d_x +
                warp_config.proj_mat[1] * d_y +
                warp_config.proj_mat[2];
    float s_y = warp_config.proj_mat[3] * d_x +
                warp_config.proj_mat[4] * d_y +
                warp_config.proj_mat[5];
    float w = warp_config.proj_mat[6] * d_x +
              warp_config.proj_mat[7] * d_y +
              warp_config.proj_mat[8];
    w = w != 0.0f ? 1.0f / w : 0.0f;
 
    float warp_x = (s_x * w) / (float)out_width;
    float warp_y = (s_y * w) / (float)out_height;
 
    float4 pixel = read_imagef(input, sampler, (float2)(warp_x, warp_y));
 
    write_imagef(output, (int2)(d_x, d_y), pixel);
}