FreeRDP
Loading...
Searching...
No Matches
benchmark.c
1
21#include <stdio.h>
22
23#include <winpr/crypto.h>
24#include <winpr/sysinfo.h>
25#include <freerdp/primitives.h>
26
27typedef struct
28{
29 BYTE* channels[3];
30 UINT32 steps[3];
31 prim_size_t roi;
32 BYTE* outputBuffer;
33 BYTE* outputChannels[3];
34 BYTE* rgbBuffer;
35 UINT32 outputStride;
36 UINT32 testedFormat;
37} primitives_YUV_benchmark;
38
39static void primitives_YUV_benchmark_free(primitives_YUV_benchmark* bench)
40{
41 if (!bench)
42 return;
43
44 free(bench->outputBuffer);
45 free(bench->rgbBuffer);
46
47 for (size_t i = 0; i < 3; i++)
48 {
49 free(bench->outputChannels[i]);
50 free(bench->channels[i]);
51 }
52
53 const primitives_YUV_benchmark empty = { 0 };
54 *bench = empty;
55}
56
57static primitives_YUV_benchmark primitives_YUV_benchmark_init(void)
58{
59 primitives_YUV_benchmark ret = { 0 };
60 ret.roi.width = 3840 * 4;
61 ret.roi.height = 2160 * 4;
62 ret.outputStride = ret.roi.width * 4;
63 ret.testedFormat = PIXEL_FORMAT_BGRA32;
64
65 ret.outputBuffer = calloc(ret.outputStride, ret.roi.height);
66 if (!ret.outputBuffer)
67 goto fail;
68 ret.rgbBuffer = calloc(ret.outputStride, ret.roi.height);
69 if (!ret.rgbBuffer)
70 goto fail;
71 winpr_RAND(ret.rgbBuffer, 1ULL * ret.outputStride * ret.roi.height);
72
73 for (size_t i = 0; i < 3; i++)
74 {
75 ret.channels[i] = calloc(ret.roi.width, ret.roi.height);
76 ret.outputChannels[i] = calloc(ret.roi.width, ret.roi.height);
77 if (!ret.channels[i] || !ret.outputChannels[i])
78 goto fail;
79
80 winpr_RAND(ret.channels[i], 1ull * ret.roi.width * ret.roi.height);
81 ret.steps[i] = ret.roi.width;
82 }
83
84 return ret;
85
86fail:
87 primitives_YUV_benchmark_free(&ret);
88 return ret;
89}
90
91static const char* print_time(UINT64 t, char* buffer, size_t size)
92{
93 (void)_snprintf(buffer, size, "%u.%03u.%03u.%03u", (unsigned)(t / 1000000000ull),
94 (unsigned)((t / 1000000ull) % 1000), (unsigned)((t / 1000ull) % 1000),
95 (unsigned)((t) % 1000));
96 return buffer;
97}
98
99static BOOL primitives_YUV420_benchmark_run(primitives_YUV_benchmark* bench, primitives_t* prims)
100{
101 const BYTE* channels[3] = { 0 };
102
103 for (size_t i = 0; i < 3; i++)
104 channels[i] = bench->channels[i];
105
106 for (size_t x = 0; x < 10; x++)
107 {
108 const UINT64 start = winpr_GetTickCount64NS();
109 pstatus_t status =
110 prims->YUV420ToRGB_8u_P3AC4R(channels, bench->steps, bench->outputBuffer,
111 bench->outputStride, bench->testedFormat, &bench->roi);
112 const UINT64 end = winpr_GetTickCount64NS();
113 if (status != PRIMITIVES_SUCCESS)
114 {
115 (void)fprintf(stderr, "Running YUV420ToRGB_8u_P3AC4R failed\n");
116 return FALSE;
117 }
118 const UINT64 diff = end - start;
119 char buffer[32] = { 0 };
120 printf("[%" PRIuz "] YUV420ToRGB_8u_P3AC4R %" PRIu32 "x%" PRIu32 " took %sns\n", x,
121 bench->roi.width, bench->roi.height, print_time(diff, buffer, sizeof(buffer)));
122 }
123
124 return TRUE;
125}
126
127static BOOL primitives_YUV444_benchmark_run(primitives_YUV_benchmark* bench, primitives_t* prims)
128{
129 const BYTE* channels[3] = { 0 };
130
131 for (size_t i = 0; i < 3; i++)
132 channels[i] = bench->channels[i];
133
134 for (size_t x = 0; x < 10; x++)
135 {
136 const UINT64 start = winpr_GetTickCount64NS();
137 pstatus_t status =
138 prims->YUV444ToRGB_8u_P3AC4R(channels, bench->steps, bench->outputBuffer,
139 bench->outputStride, bench->testedFormat, &bench->roi);
140 const UINT64 end = winpr_GetTickCount64NS();
141 if (status != PRIMITIVES_SUCCESS)
142 {
143 (void)fprintf(stderr, "Running YUV444ToRGB_8u_P3AC4R failed\n");
144 return FALSE;
145 }
146 const UINT64 diff = end - start;
147 char buffer[32] = { 0 };
148 printf("[%" PRIuz "] YUV444ToRGB_8u_P3AC4R %" PRIu32 "x%" PRIu32 " took %sns\n", x,
149 bench->roi.width, bench->roi.height, print_time(diff, buffer, sizeof(buffer)));
150 }
151
152 return TRUE;
153}
154
155static BOOL primitives_RGB2420_benchmark_run(primitives_YUV_benchmark* bench, primitives_t* prims)
156{
157 for (size_t x = 0; x < 10; x++)
158 {
159 const UINT64 start = winpr_GetTickCount64NS();
160 pstatus_t status =
161 prims->RGBToYUV420_8u_P3AC4R(bench->rgbBuffer, bench->testedFormat, bench->outputStride,
162 bench->outputChannels, bench->steps, &bench->roi);
163 const UINT64 end = winpr_GetTickCount64NS();
164 if (status != PRIMITIVES_SUCCESS)
165 {
166 (void)fprintf(stderr, "Running RGBToYUV420_8u_P3AC4R failed\n");
167 return FALSE;
168 }
169 const UINT64 diff = end - start;
170 char buffer[32] = { 0 };
171 printf("[%" PRIuz "] RGBToYUV420_8u_P3AC4R %" PRIu32 "x%" PRIu32 " took %sns\n", x,
172 bench->roi.width, bench->roi.height, print_time(diff, buffer, sizeof(buffer)));
173 }
174
175 return TRUE;
176}
177
178static BOOL primitives_RGB2444_benchmark_run(primitives_YUV_benchmark* bench, primitives_t* prims)
179{
180 for (size_t x = 0; x < 10; x++)
181 {
182 const UINT64 start = winpr_GetTickCount64NS();
183 pstatus_t status =
184 prims->RGBToYUV444_8u_P3AC4R(bench->rgbBuffer, bench->testedFormat, bench->outputStride,
185 bench->outputChannels, bench->steps, &bench->roi);
186 const UINT64 end = winpr_GetTickCount64NS();
187 if (status != PRIMITIVES_SUCCESS)
188 {
189 (void)fprintf(stderr, "Running RGBToYUV444_8u_P3AC4R failed\n");
190 return FALSE;
191 }
192 const UINT64 diff = end - start;
193 char buffer[32] = { 0 };
194 printf("[%" PRIuz "] RGBToYUV444_8u_P3AC4R %" PRIu32 "x%" PRIu32 " took %sns\n", x,
195 bench->roi.width, bench->roi.height, print_time(diff, buffer, sizeof(buffer)));
196 }
197
198 return TRUE;
199}
200
201int main(int argc, char* argv[])
202{
203 WINPR_UNUSED(argc);
204 WINPR_UNUSED(argv);
205 primitives_YUV_benchmark bench = primitives_YUV_benchmark_init();
206
207 for (primitive_hints hint = PRIMITIVES_PURE_SOFT; hint < PRIMITIVES_AUTODETECT; hint++)
208 {
209 const char* hintstr = primtives_hint_str(hint);
210 primitives_t* prim = primitives_get_by_type(hint);
211 if (!prim)
212 {
213 (void)fprintf(stderr, "failed to get primitives: %s\n", hintstr);
214 goto fail;
215 }
216
217 printf("Running YUV420 -> RGB benchmark on %s implementation:\n", hintstr);
218 if (!primitives_YUV420_benchmark_run(&bench, prim))
219 {
220 (void)fprintf(stderr, "YUV420 -> RGB benchmark failed\n");
221 goto fail;
222 }
223 printf("\n");
224
225 printf("Running RGB -> YUV420 benchmark on %s implementation:\n", hintstr);
226 if (!primitives_RGB2420_benchmark_run(&bench, prim))
227 {
228 (void)fprintf(stderr, "RGB -> YUV420 benchmark failed\n");
229 goto fail;
230 }
231 printf("\n");
232
233 printf("Running YUV444 -> RGB benchmark on %s implementation:\n", hintstr);
234 if (!primitives_YUV444_benchmark_run(&bench, prim))
235 {
236 (void)fprintf(stderr, "YUV444 -> RGB benchmark failed\n");
237 goto fail;
238 }
239 printf("\n");
240
241 printf("Running RGB -> YUV444 benchmark on %s implementation:\n", hintstr);
242 if (!primitives_RGB2444_benchmark_run(&bench, prim))
243 {
244 (void)fprintf(stderr, "RGB -> YUV444 benchmark failed\n");
245 goto fail;
246 }
247 printf("\n");
248 }
249fail:
250 primitives_YUV_benchmark_free(&bench);
251 return 0;
252}