2 * Copyright © 2016 Red Hat
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 /* Lowers the additional tex_src_plane src, generated by nir_lower_tex
25 * for planar YUV textures, into separate samplers, matching the logic
26 * that mesa/st uses to insert additional sampler view/state (since both
27 * sides need to agree).
29 * This should run after nir_lower_samplers.
32 #include "compiler/nir/nir.h"
36 struct nir_shader
*shader
;
38 unsigned lower_2plane
;
39 unsigned lower_3plane
;
41 /* Maps a primary sampler (used for Y) to the U or UV sampler. In
42 * case of 3-plane YUV format, the V plane is next sampler after U.
44 unsigned char sampler_map
[PIPE_MAX_SAMPLERS
][2];
45 } lower_tex_src_state
;
48 find_sampler(lower_tex_src_state
*state
, unsigned samp
)
50 /* NOTE: arrays of samplerExternalOES do not appear to be allowed: */
51 nir_foreach_variable(var
, &state
->shader
->uniforms
)
52 if (var
->data
.binding
== samp
)
58 add_sampler(lower_tex_src_state
*state
, unsigned orig_binding
,
59 unsigned new_binding
, const char *ext
)
61 const struct glsl_type
*samplerExternalOES
=
62 glsl_sampler_type(GLSL_SAMPLER_DIM_EXTERNAL
, false, false, GLSL_TYPE_FLOAT
);
63 nir_variable
*new_sampler
, *orig_sampler
=
64 find_sampler(state
, orig_binding
);
67 asprintf(&name
, "%s:%s", orig_sampler
->name
, ext
);
68 new_sampler
= nir_variable_create(state
->shader
, nir_var_uniform
,
69 samplerExternalOES
, name
);
72 new_sampler
->data
.binding
= new_binding
;
76 assign_extra_samplers(lower_tex_src_state
*state
, unsigned free_slots
)
78 unsigned mask
= state
->lower_2plane
| state
->lower_3plane
;
81 unsigned extra
, y_samp
= u_bit_scan(&mask
);
83 if (state
->lower_3plane
& (1 << y_samp
)) {
84 /* two additional planes (U and V): */
85 extra
= u_bit_scan(&free_slots
);
86 state
->sampler_map
[y_samp
][0] = extra
;
88 add_sampler(state
, y_samp
, extra
, "u");
90 extra
= u_bit_scan(&free_slots
);
91 state
->sampler_map
[y_samp
][1] = extra
;
93 add_sampler(state
, y_samp
, extra
, "v");
95 /* single additional UV plane: */
96 extra
= u_bit_scan(&free_slots
);
97 state
->sampler_map
[y_samp
][0] = extra
;
99 add_sampler(state
, y_samp
, extra
, "uv");
105 lower_tex_src_plane_block(lower_tex_src_state
*state
, nir_block
*block
)
107 nir_foreach_instr(instr
, block
) {
108 if (instr
->type
!= nir_instr_type_tex
)
111 nir_tex_instr
*tex
= nir_instr_as_tex(instr
);
112 int plane_index
= nir_tex_instr_src_index(tex
, nir_tex_src_plane
);
117 nir_const_value
*plane
= nir_src_as_const_value(tex
->src
[plane_index
].src
);
120 if (plane
[0].i32
> 0) {
121 unsigned y_samp
= tex
->texture_index
;
123 assume(tex
->texture_index
== tex
->sampler_index
);
124 assume(((state
->lower_3plane
& (1 << y_samp
)) && plane
[0].i32
< 3) ||
127 tex
->texture_index
= tex
->sampler_index
=
128 state
->sampler_map
[y_samp
][plane
[0].i32
- 1];
130 state
->shader
->info
.textures_used
|= 1u << tex
->texture_index
;
133 nir_tex_instr_remove_src(tex
, plane_index
);
138 lower_tex_src_plane_impl(lower_tex_src_state
*state
, nir_function_impl
*impl
)
140 nir_foreach_block(block
, impl
) {
141 lower_tex_src_plane_block(state
, block
);
144 nir_metadata_preserve(impl
, nir_metadata_block_index
|
145 nir_metadata_dominance
);
149 st_nir_lower_tex_src_plane(struct nir_shader
*shader
, unsigned free_slots
,
150 unsigned lower_2plane
, unsigned lower_3plane
)
152 lower_tex_src_state state
= {0};
154 state
.shader
= shader
;
155 state
.lower_2plane
= lower_2plane
;
156 state
.lower_3plane
= lower_3plane
;
158 assign_extra_samplers(&state
, free_slots
);
160 nir_foreach_function(function
, shader
) {
162 lower_tex_src_plane_impl(&state
, function
->impl
);