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 "util/u_string.h"
33 #include "compiler/nir/nir.h"
34 #include "compiler/nir/nir_builder.h"
38 struct nir_shader
*shader
;
40 unsigned lower_2plane
;
41 unsigned lower_3plane
;
43 /* Maps a primary sampler (used for Y) to the U or UV sampler. In
44 * case of 3-plane YUV format, the V plane is next sampler after U.
46 unsigned char sampler_map
[PIPE_MAX_SAMPLERS
][2];
47 } lower_tex_src_state
;
50 find_sampler(lower_tex_src_state
*state
, unsigned samp
)
52 /* NOTE: arrays of samplerExternalOES do not appear to be allowed: */
53 nir_foreach_variable(var
, &state
->shader
->uniforms
)
54 if (var
->data
.binding
== samp
)
60 add_sampler(lower_tex_src_state
*state
, unsigned orig_binding
,
61 unsigned new_binding
, const char *ext
)
63 const struct glsl_type
*samplerExternalOES
=
64 glsl_sampler_type(GLSL_SAMPLER_DIM_EXTERNAL
, false, false, GLSL_TYPE_FLOAT
);
65 nir_variable
*new_sampler
, *orig_sampler
=
66 find_sampler(state
, orig_binding
);
69 UNUSED
int r
= asprintf(&name
, "%s:%s", orig_sampler
->name
, ext
);
70 new_sampler
= nir_variable_create(state
->shader
, nir_var_uniform
,
71 samplerExternalOES
, name
);
74 new_sampler
->data
.binding
= new_binding
;
78 assign_extra_samplers(lower_tex_src_state
*state
, unsigned free_slots
)
80 unsigned mask
= state
->lower_2plane
| state
->lower_3plane
;
83 unsigned extra
, y_samp
= u_bit_scan(&mask
);
85 if (state
->lower_3plane
& (1 << y_samp
)) {
86 /* two additional planes (U and V): */
87 extra
= u_bit_scan(&free_slots
);
88 state
->sampler_map
[y_samp
][0] = extra
;
90 add_sampler(state
, y_samp
, extra
, "u");
92 extra
= u_bit_scan(&free_slots
);
93 state
->sampler_map
[y_samp
][1] = extra
;
95 add_sampler(state
, y_samp
, extra
, "v");
97 /* single additional UV plane: */
98 extra
= u_bit_scan(&free_slots
);
99 state
->sampler_map
[y_samp
][0] = extra
;
101 add_sampler(state
, y_samp
, extra
, "uv");
107 lower_tex_src_plane_block(nir_builder
*b
, lower_tex_src_state
*state
, nir_block
*block
)
109 nir_foreach_instr(instr
, block
) {
110 if (instr
->type
!= nir_instr_type_tex
)
113 nir_tex_instr
*tex
= nir_instr_as_tex(instr
);
114 int plane_index
= nir_tex_instr_src_index(tex
, nir_tex_src_plane
);
119 nir_const_value
*plane
= nir_src_as_const_value(tex
->src
[plane_index
].src
);
122 if (plane
[0].i32
> 0) {
123 unsigned y_samp
= tex
->texture_index
;
125 assume(tex
->texture_index
== tex
->sampler_index
);
126 assume(((state
->lower_3plane
& (1 << y_samp
)) && plane
[0].i32
< 3) ||
129 tex
->texture_index
= tex
->sampler_index
=
130 state
->sampler_map
[y_samp
][plane
[0].i32
- 1];
132 state
->shader
->info
.textures_used
|= 1u << tex
->texture_index
;
134 /* For drivers using PIPE_CAP_NIR_SAMPLERS_AS_DEREF, we need
135 * to reference the correct sampler nir variable.
137 int tex_index
= nir_tex_instr_src_index(tex
, nir_tex_src_texture_deref
);
138 int samp_index
= nir_tex_instr_src_index(tex
, nir_tex_src_sampler_deref
);
139 if (tex_index
>= 0 && samp_index
>= 0) {
140 b
->cursor
= nir_before_instr(&tex
->instr
);
142 nir_variable
* samp
= find_sampler(state
, plane
[0].i32
);
145 nir_deref_instr
*tex_deref_instr
= nir_build_deref_var(b
, samp
);
146 nir_ssa_def
*tex_deref
= &tex_deref_instr
->dest
.ssa
;
148 nir_instr_rewrite_src(&tex
->instr
,
149 &tex
->src
[tex_index
].src
,
150 nir_src_for_ssa(tex_deref
));
151 nir_instr_rewrite_src(&tex
->instr
,
152 &tex
->src
[samp_index
].src
,
153 nir_src_for_ssa(tex_deref
));
157 nir_tex_instr_remove_src(tex
, plane_index
);
162 lower_tex_src_plane_impl(lower_tex_src_state
*state
, nir_function_impl
*impl
)
165 nir_builder_init(&b
, impl
);
167 nir_foreach_block(block
, impl
) {
168 lower_tex_src_plane_block(&b
, state
, block
);
171 nir_metadata_preserve(impl
, nir_metadata_block_index
|
172 nir_metadata_dominance
);
176 st_nir_lower_tex_src_plane(struct nir_shader
*shader
, unsigned free_slots
,
177 unsigned lower_2plane
, unsigned lower_3plane
)
179 lower_tex_src_state state
= {0};
181 state
.shader
= shader
;
182 state
.lower_2plane
= lower_2plane
;
183 state
.lower_3plane
= lower_3plane
;
185 assign_extra_samplers(&state
, free_slots
);
187 nir_foreach_function(function
, shader
) {
189 lower_tex_src_plane_impl(&state
, function
->impl
);