1 #include "common/common.h"
2 #include "common/msg.h"
3 #include "video/img_format.h"
4 
5 #include "ra.h"
6 
ra_add_native_resource(struct ra * ra,const char * name,void * data)7 void ra_add_native_resource(struct ra *ra, const char *name, void *data)
8 {
9     struct ra_native_resource r = {
10         .name = name,
11         .data = data,
12     };
13     MP_TARRAY_APPEND(ra, ra->native_resources, ra->num_native_resources, r);
14 }
15 
ra_get_native_resource(struct ra * ra,const char * name)16 void *ra_get_native_resource(struct ra *ra, const char *name)
17 {
18     for (int n = 0; n < ra->num_native_resources; n++) {
19         struct ra_native_resource *r = &ra->native_resources[n];
20         if (strcmp(r->name, name) == 0)
21             return r->data;
22     }
23 
24     return NULL;
25 }
26 
ra_tex_create(struct ra * ra,const struct ra_tex_params * params)27 struct ra_tex *ra_tex_create(struct ra *ra, const struct ra_tex_params *params)
28 {
29     return ra->fns->tex_create(ra, params);
30 }
31 
ra_tex_free(struct ra * ra,struct ra_tex ** tex)32 void ra_tex_free(struct ra *ra, struct ra_tex **tex)
33 {
34     if (*tex)
35         ra->fns->tex_destroy(ra, *tex);
36     *tex = NULL;
37 }
38 
ra_buf_create(struct ra * ra,const struct ra_buf_params * params)39 struct ra_buf *ra_buf_create(struct ra *ra, const struct ra_buf_params *params)
40 {
41     return ra->fns->buf_create(ra, params);
42 }
43 
ra_buf_free(struct ra * ra,struct ra_buf ** buf)44 void ra_buf_free(struct ra *ra, struct ra_buf **buf)
45 {
46     if (*buf)
47         ra->fns->buf_destroy(ra, *buf);
48     *buf = NULL;
49 }
50 
ra_free(struct ra ** ra)51 void ra_free(struct ra **ra)
52 {
53     if (*ra)
54         (*ra)->fns->destroy(*ra);
55     talloc_free(*ra);
56     *ra = NULL;
57 }
58 
ra_vartype_size(enum ra_vartype type)59 size_t ra_vartype_size(enum ra_vartype type)
60 {
61     switch (type) {
62     case RA_VARTYPE_INT:        return sizeof(int);
63     case RA_VARTYPE_FLOAT:      return sizeof(float);
64     case RA_VARTYPE_BYTE_UNORM: return 1;
65     default: return 0;
66     }
67 }
68 
ra_renderpass_input_layout(struct ra_renderpass_input * input)69 struct ra_layout ra_renderpass_input_layout(struct ra_renderpass_input *input)
70 {
71     size_t el_size = ra_vartype_size(input->type);
72     if (!el_size)
73         return (struct ra_layout){0};
74 
75     // host data is always tightly packed
76     return (struct ra_layout) {
77         .align  = 1,
78         .stride = el_size * input->dim_v,
79         .size   = el_size * input->dim_v * input->dim_m,
80     };
81 }
82 
dup_inputs(void * ta_parent,const struct ra_renderpass_input * inputs,int num_inputs)83 static struct ra_renderpass_input *dup_inputs(void *ta_parent,
84             const struct ra_renderpass_input *inputs, int num_inputs)
85 {
86     struct ra_renderpass_input *res =
87         talloc_memdup(ta_parent, (void *)inputs, num_inputs * sizeof(inputs[0]));
88     for (int n = 0; n < num_inputs; n++)
89         res[n].name = talloc_strdup(res, res[n].name);
90     return res;
91 }
92 
93 // Return a newly allocated deep-copy of params.
ra_renderpass_params_copy(void * ta_parent,const struct ra_renderpass_params * params)94 struct ra_renderpass_params *ra_renderpass_params_copy(void *ta_parent,
95         const struct ra_renderpass_params *params)
96 {
97     struct ra_renderpass_params *res = talloc_ptrtype(ta_parent, res);
98     *res = *params;
99     res->inputs = dup_inputs(res, res->inputs, res->num_inputs);
100     res->vertex_attribs =
101         dup_inputs(res, res->vertex_attribs, res->num_vertex_attribs);
102     res->cached_program = bstrdup(res, res->cached_program);
103     res->vertex_shader = talloc_strdup(res, res->vertex_shader);
104     res->frag_shader = talloc_strdup(res, res->frag_shader);
105     res->compute_shader = talloc_strdup(res, res->compute_shader);
106     return res;
107 }
108 
109 struct glsl_fmt {
110     enum ra_ctype ctype;
111     int num_components;
112     int component_depth[4];
113     const char *glsl_format;
114 };
115 
116 // List taken from the GLSL specification, sans snorm and sint formats
117 static const struct glsl_fmt ra_glsl_fmts[] = {
118     {RA_CTYPE_FLOAT, 1, {16},             "r16f"},
119     {RA_CTYPE_FLOAT, 1, {32},             "r32f"},
120     {RA_CTYPE_FLOAT, 2, {16, 16},         "rg16f"},
121     {RA_CTYPE_FLOAT, 2, {32, 32},         "rg32f"},
122     {RA_CTYPE_FLOAT, 4, {16, 16, 16, 16}, "rgba16f"},
123     {RA_CTYPE_FLOAT, 4, {32, 32, 32, 32}, "rgba32f"},
124     {RA_CTYPE_FLOAT, 3, {11, 11, 10},     "r11f_g11f_b10f"},
125 
126     {RA_CTYPE_UNORM, 1, {8},              "r8"},
127     {RA_CTYPE_UNORM, 1, {16},             "r16"},
128     {RA_CTYPE_UNORM, 2, {8,  8},          "rg8"},
129     {RA_CTYPE_UNORM, 2, {16, 16},         "rg16"},
130     {RA_CTYPE_UNORM, 4, {8,  8,  8,  8},  "rgba8"},
131     {RA_CTYPE_UNORM, 4, {16, 16, 16, 16}, "rgba16"},
132     {RA_CTYPE_UNORM, 4, {10, 10, 10,  2}, "rgb10_a2"},
133 
134     {RA_CTYPE_UINT,  1, {8},              "r8ui"},
135     {RA_CTYPE_UINT,  1, {16},             "r16ui"},
136     {RA_CTYPE_UINT,  1, {32},             "r32ui"},
137     {RA_CTYPE_UINT,  2, {8,  8},          "rg8ui"},
138     {RA_CTYPE_UINT,  2, {16, 16},         "rg16ui"},
139     {RA_CTYPE_UINT,  2, {32, 32},         "rg32ui"},
140     {RA_CTYPE_UINT,  4, {8,  8,  8,  8},  "rgba8ui"},
141     {RA_CTYPE_UINT,  4, {16, 16, 16, 16}, "rgba16ui"},
142     {RA_CTYPE_UINT,  4, {32, 32, 32, 32}, "rgba32ui"},
143     {RA_CTYPE_UINT,  4, {10, 10, 10,  2}, "rgb10_a2ui"},
144 };
145 
ra_fmt_glsl_format(const struct ra_format * fmt)146 const char *ra_fmt_glsl_format(const struct ra_format *fmt)
147 {
148     for (int n = 0; n < MP_ARRAY_SIZE(ra_glsl_fmts); n++) {
149         const struct glsl_fmt *gfmt = &ra_glsl_fmts[n];
150 
151         if (fmt->ctype != gfmt->ctype)
152             continue;
153         if (fmt->num_components != gfmt->num_components)
154             continue;
155 
156         for (int i = 0; i < fmt->num_components; i++) {
157             if (fmt->component_depth[i] != gfmt->component_depth[i])
158                 goto next_fmt;
159         }
160 
161         return gfmt->glsl_format;
162 
163 next_fmt: ; // equivalent to `continue`
164     }
165 
166     return NULL;
167 }
168 
169 // Return whether this is a tightly packed format with no external padding and
170 // with the same bit size/depth in all components, and the shader returns
171 // components in the same order as in memory.
ra_format_is_regular(const struct ra_format * fmt)172 static bool ra_format_is_regular(const struct ra_format *fmt)
173 {
174     if (!fmt->pixel_size || !fmt->num_components || !fmt->ordered)
175         return false;
176     for (int n = 1; n < fmt->num_components; n++) {
177         if (fmt->component_size[n] != fmt->component_size[0] ||
178             fmt->component_depth[n] != fmt->component_depth[0])
179             return false;
180     }
181     if (fmt->component_size[0] * fmt->num_components != fmt->pixel_size * 8)
182         return false;
183     return true;
184 }
185 
186 // Return a regular filterable format using RA_CTYPE_UNORM.
ra_find_unorm_format(struct ra * ra,int bytes_per_component,int n_components)187 const struct ra_format *ra_find_unorm_format(struct ra *ra,
188                                              int bytes_per_component,
189                                              int n_components)
190 {
191     for (int n = 0; n < ra->num_formats; n++) {
192         const struct ra_format *fmt = ra->formats[n];
193         if (fmt->ctype == RA_CTYPE_UNORM && fmt->num_components == n_components &&
194             fmt->pixel_size == bytes_per_component * n_components &&
195             fmt->component_depth[0] == bytes_per_component * 8 &&
196             fmt->linear_filter && ra_format_is_regular(fmt))
197             return fmt;
198     }
199     return NULL;
200 }
201 
202 // Return a regular format using RA_CTYPE_UINT.
ra_find_uint_format(struct ra * ra,int bytes_per_component,int n_components)203 const struct ra_format *ra_find_uint_format(struct ra *ra,
204                                             int bytes_per_component,
205                                             int n_components)
206 {
207     for (int n = 0; n < ra->num_formats; n++) {
208         const struct ra_format *fmt = ra->formats[n];
209         if (fmt->ctype == RA_CTYPE_UINT && fmt->num_components == n_components &&
210             fmt->pixel_size == bytes_per_component * n_components &&
211             fmt->component_depth[0] == bytes_per_component * 8 &&
212             ra_format_is_regular(fmt))
213             return fmt;
214     }
215     return NULL;
216 }
217 
218 // Find a float format of any precision that matches the C type of the same
219 // size for upload.
220 // May drop bits from the mantissa (such as selecting float16 even if
221 // bytes_per_component == 32); prefers possibly faster formats first.
ra_find_float_format(struct ra * ra,int bytes_per_component,int n_components)222 static const struct ra_format *ra_find_float_format(struct ra *ra,
223                                                     int bytes_per_component,
224                                                     int n_components)
225 {
226     // Assumes ra_format are ordered by performance.
227     // The >=16 check is to avoid catching fringe formats.
228     for (int n = 0; n < ra->num_formats; n++) {
229         const struct ra_format *fmt = ra->formats[n];
230         if (fmt->ctype == RA_CTYPE_FLOAT && fmt->num_components == n_components &&
231             fmt->pixel_size == bytes_per_component * n_components &&
232             fmt->component_depth[0] >= 16 &&
233             fmt->linear_filter && ra_format_is_regular(fmt))
234             return fmt;
235     }
236     return NULL;
237 }
238 
239 // Return a filterable regular format that uses at least float16 internally, and
240 // uses a normal C float for transfer on the CPU side. (This is just so we don't
241 // need 32->16 bit conversion on CPU, which would be messy.)
ra_find_float16_format(struct ra * ra,int n_components)242 const struct ra_format *ra_find_float16_format(struct ra *ra, int n_components)
243 {
244     return ra_find_float_format(ra, sizeof(float), n_components);
245 }
246 
ra_find_named_format(struct ra * ra,const char * name)247 const struct ra_format *ra_find_named_format(struct ra *ra, const char *name)
248 {
249     for (int n = 0; n < ra->num_formats; n++) {
250         const struct ra_format *fmt = ra->formats[n];
251         if (strcmp(fmt->name, name) == 0)
252             return fmt;
253     }
254     return NULL;
255 }
256 
257 // Like ra_find_unorm_format(), but if no fixed point format is available,
258 // return an unsigned integer format.
find_plane_format(struct ra * ra,int bytes,int n_channels,enum mp_component_type ctype)259 static const struct ra_format *find_plane_format(struct ra *ra, int bytes,
260                                                  int n_channels,
261                                                  enum mp_component_type ctype)
262 {
263     switch (ctype) {
264     case MP_COMPONENT_TYPE_UINT: {
265         const struct ra_format *f = ra_find_unorm_format(ra, bytes, n_channels);
266         if (f)
267             return f;
268         return ra_find_uint_format(ra, bytes, n_channels);
269     }
270     case MP_COMPONENT_TYPE_FLOAT:
271         return ra_find_float_format(ra, bytes, n_channels);
272     default: return NULL;
273     }
274 }
275 
276 // Put a mapping of imgfmt to texture formats into *out. Basically it selects
277 // the correct texture formats needed to represent an imgfmt in a shader, with
278 // textures using the same memory organization as on the CPU.
279 // Each plane is represented by a texture, and each texture has a RGBA
280 // component order. out->components describes the meaning of them.
281 // May return integer formats for >8 bit formats, if the driver has no
282 // normalized 16 bit formats.
283 // Returns false (and *out is not touched) if no format found.
ra_get_imgfmt_desc(struct ra * ra,int imgfmt,struct ra_imgfmt_desc * out)284 bool ra_get_imgfmt_desc(struct ra *ra, int imgfmt, struct ra_imgfmt_desc *out)
285 {
286     struct ra_imgfmt_desc res = {.component_type = RA_CTYPE_UNKNOWN};
287 
288     struct mp_regular_imgfmt regfmt;
289     if (mp_get_regular_imgfmt(&regfmt, imgfmt)) {
290         res.num_planes = regfmt.num_planes;
291         res.component_bits = regfmt.component_size * 8;
292         res.component_pad = regfmt.component_pad;
293         for (int n = 0; n < regfmt.num_planes; n++) {
294             struct mp_regular_imgfmt_plane *plane = &regfmt.planes[n];
295             res.planes[n] = find_plane_format(ra, regfmt.component_size,
296                                               plane->num_components,
297                                               regfmt.component_type);
298             if (!res.planes[n])
299                 return false;
300             for (int i = 0; i < plane->num_components; i++)
301                 res.components[n][i] = plane->components[i];
302             // Dropping LSBs when shifting will lead to dropped MSBs.
303             if (res.component_bits > res.planes[n]->component_depth[0] &&
304                 res.component_pad < 0)
305                 return false;
306             // Renderer restriction, but actually an unwanted corner case.
307             if (res.component_type != RA_CTYPE_UNKNOWN &&
308                 res.component_type != res.planes[n]->ctype)
309                 return false;
310             res.component_type = res.planes[n]->ctype;
311         }
312         res.chroma_w = 1 << regfmt.chroma_xs;
313         res.chroma_h = 1 << regfmt.chroma_ys;
314         goto supported;
315     }
316 
317     for (int n = 0; n < ra->num_formats; n++) {
318         if (imgfmt && ra->formats[n]->special_imgfmt == imgfmt) {
319             res = *ra->formats[n]->special_imgfmt_desc;
320             goto supported;
321         }
322     }
323 
324     // Unsupported format
325     return false;
326 
327 supported:
328 
329     *out = res;
330     return true;
331 }
332 
ctype_to_str(enum ra_ctype ctype)333 static const char *ctype_to_str(enum ra_ctype ctype)
334 {
335     switch (ctype) {
336     case RA_CTYPE_UNORM:    return "unorm";
337     case RA_CTYPE_UINT:     return "uint ";
338     case RA_CTYPE_FLOAT:    return "float";
339     default:                return "unknown";
340     }
341 }
342 
ra_dump_tex_formats(struct ra * ra,int msgl)343 void ra_dump_tex_formats(struct ra *ra, int msgl)
344 {
345     if (!mp_msg_test(ra->log, msgl))
346         return;
347     MP_MSG(ra, msgl, "Texture formats:\n");
348     MP_MSG(ra, msgl, "  NAME       COMP*TYPE SIZE           DEPTH PER COMP.\n");
349     for (int n = 0; n < ra->num_formats; n++) {
350         const struct ra_format *fmt = ra->formats[n];
351         const char *ctype = ctype_to_str(fmt->ctype);
352         char cl[40] = "";
353         for (int i = 0; i < fmt->num_components; i++) {
354             mp_snprintf_cat(cl, sizeof(cl), "%s%d", i ? " " : "",
355                             fmt->component_size[i]);
356             if (fmt->component_size[i] != fmt->component_depth[i])
357                 mp_snprintf_cat(cl, sizeof(cl), "/%d", fmt->component_depth[i]);
358         }
359         MP_MSG(ra, msgl, "  %-10s %d*%s %3dB %s %s %s %s {%s}\n", fmt->name,
360                fmt->num_components, ctype, fmt->pixel_size,
361                fmt->luminance_alpha ? "LA" : "  ",
362                fmt->linear_filter ? "LF" : "  ",
363                fmt->renderable ? "CR" : "  ",
364                fmt->storable ? "ST" : "  ", cl);
365     }
366     MP_MSG(ra, msgl, " LA = LUMINANCE_ALPHA hack format\n");
367     MP_MSG(ra, msgl, " LF = linear filterable\n");
368     MP_MSG(ra, msgl, " CR = can be used for render targets\n");
369     MP_MSG(ra, msgl, " ST = can be used for storable images\n");
370 }
371 
ra_dump_imgfmt_desc(struct ra * ra,const struct ra_imgfmt_desc * desc,int msgl)372 void ra_dump_imgfmt_desc(struct ra *ra, const struct ra_imgfmt_desc *desc,
373                          int msgl)
374 {
375     char pl[80] = "";
376     char pf[80] = "";
377     for (int n = 0; n < desc->num_planes; n++) {
378         if (n > 0) {
379             mp_snprintf_cat(pl, sizeof(pl), "/");
380             mp_snprintf_cat(pf, sizeof(pf), "/");
381         }
382         char t[5] = {0};
383         for (int i = 0; i < 4; i++)
384             t[i] = "_rgba"[desc->components[n][i]];
385         for (int i = 3; i > 0 && t[i] == '_'; i--)
386             t[i] = '\0';
387         mp_snprintf_cat(pl, sizeof(pl), "%s", t);
388         mp_snprintf_cat(pf, sizeof(pf), "%s", desc->planes[n]->name);
389     }
390     MP_MSG(ra, msgl, "%d planes %dx%d %d/%d [%s] (%s) [%s]\n",
391            desc->num_planes, desc->chroma_w, desc->chroma_h,
392            desc->component_bits, desc->component_pad, pf, pl,
393            ctype_to_str(desc->component_type));
394 }
395 
ra_dump_img_formats(struct ra * ra,int msgl)396 void ra_dump_img_formats(struct ra *ra, int msgl)
397 {
398     if (!mp_msg_test(ra->log, msgl))
399         return;
400     MP_MSG(ra, msgl, "Image formats:\n");
401     for (int imgfmt = IMGFMT_START; imgfmt < IMGFMT_END; imgfmt++) {
402         const char *name = mp_imgfmt_to_name(imgfmt);
403         if (strcmp(name, "unknown") == 0)
404             continue;
405         MP_MSG(ra, msgl, "  %s", name);
406         struct ra_imgfmt_desc desc;
407         if (ra_get_imgfmt_desc(ra, imgfmt, &desc)) {
408             MP_MSG(ra, msgl, " => ");
409             ra_dump_imgfmt_desc(ra, &desc, msgl);
410         } else {
411             MP_MSG(ra, msgl, "\n");
412         }
413     }
414 }
415