2 * Copyright © 2017 Intel Corporation
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
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 #include "radv_private.h"
25 #include "radv_shader.h"
26 #include "vk_format.h"
28 #include "nir/nir_builder.h"
32 nir_ssa_def
*image_size
;
33 nir_tex_instr
*origin_tex
;
34 nir_deref_instr
*tex_deref
;
35 const struct radv_sampler_ycbcr_conversion
*conversion
;
39 y_range(nir_builder
*b
,
40 nir_ssa_def
*y_channel
,
42 VkSamplerYcbcrRange range
)
45 case VK_SAMPLER_YCBCR_RANGE_ITU_FULL
:
47 case VK_SAMPLER_YCBCR_RANGE_ITU_NARROW
:
50 nir_fmul(b
, y_channel
,
51 nir_imm_float(b
, pow(2, bpc
) - 1)),
52 nir_imm_float(b
, -16.0f
* pow(2, bpc
- 8))),
53 nir_frcp(b
, nir_imm_float(b
, 219.0f
* pow(2, bpc
- 8))));
55 unreachable("missing Ycbcr range");
61 chroma_range(nir_builder
*b
,
62 nir_ssa_def
*chroma_channel
,
64 VkSamplerYcbcrRange range
)
67 case VK_SAMPLER_YCBCR_RANGE_ITU_FULL
:
68 return nir_fadd(b
, chroma_channel
,
69 nir_imm_float(b
, -pow(2, bpc
- 1) / (pow(2, bpc
) - 1.0f
)));
70 case VK_SAMPLER_YCBCR_RANGE_ITU_NARROW
:
73 nir_fmul(b
, chroma_channel
,
74 nir_imm_float(b
, pow(2, bpc
) - 1)),
75 nir_imm_float(b
, -128.0f
* pow(2, bpc
- 8))),
76 nir_frcp(b
, nir_imm_float(b
, 224.0f
* pow(2, bpc
- 8))));
78 unreachable("missing Ycbcr range");
83 typedef struct nir_const_value_3_4
{
84 nir_const_value v
[3][4];
85 } nir_const_value_3_4
;
87 static const nir_const_value_3_4
*
88 ycbcr_model_to_rgb_matrix(VkSamplerYcbcrModelConversion model
)
91 case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601
: {
92 static const nir_const_value_3_4 bt601
= { {
93 { { .f32
= 1.402f
}, { .f32
= 1.0f
}, { .f32
= 0.0f
}, { .f32
= 0.0f
} },
94 { { .f32
= -0.714136286201022f
}, { .f32
= 1.0f
}, { .f32
= -0.344136286201022f
}, { .f32
= 0.0f
} },
95 { { .f32
= 0.0f
}, { .f32
= 1.0f
}, { .f32
= 1.772f
}, { .f32
= 0.0f
} },
100 case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709
: {
101 static const nir_const_value_3_4 bt709
= { {
102 { { .f32
= 1.5748031496063f
}, { .f32
= 1.0f
}, { .f32
= 0.0f
}, { .f32
= 0.0f
} },
103 { { .f32
= -0.468125209181067f
}, { .f32
= 1.0f
}, { .f32
= -0.187327487470334f
}, { .f32
= 0.0f
} },
104 { { .f32
= 0.0f
}, { .f32
= 1.0f
}, { .f32
= 1.85563184264242f
}, { .f32
= 0.0f
} },
109 case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020
: {
110 static const nir_const_value_3_4 bt2020
= { {
111 { { .f32
= 1.4746f
}, { .f32
= 1.0f
}, { .f32
= 0.0f
}, { .f32
= 0.0f
} },
112 { { .f32
= -0.571353126843658f
}, { .f32
= 1.0f
}, { .f32
= -0.164553126843658f
}, { .f32
= 0.0f
} },
113 { { .f32
= 0.0f
}, { .f32
= 1.0f
}, { .f32
= 1.8814f
}, { .f32
= 0.0f
} },
119 unreachable("missing Ycbcr model");
125 convert_ycbcr(struct ycbcr_state
*state
,
126 nir_ssa_def
*raw_channels
,
129 nir_builder
*b
= state
->builder
;
130 const struct radv_sampler_ycbcr_conversion
*conversion
= state
->conversion
;
132 nir_ssa_def
*expanded_channels
=
134 chroma_range(b
, nir_channel(b
, raw_channels
, 0),
135 bits
, conversion
->ycbcr_range
),
136 y_range(b
, nir_channel(b
, raw_channels
, 1),
137 bits
, conversion
->ycbcr_range
),
138 chroma_range(b
, nir_channel(b
, raw_channels
, 2),
139 bits
, conversion
->ycbcr_range
),
140 nir_imm_float(b
, 1.0f
));
142 if (conversion
->ycbcr_model
== VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY
)
143 return expanded_channels
;
145 const nir_const_value_3_4
*conversion_matrix
=
146 ycbcr_model_to_rgb_matrix(conversion
->ycbcr_model
);
148 nir_ssa_def
*converted_channels
[] = {
149 nir_fdot4(b
, expanded_channels
, nir_build_imm(b
, 4, 32, conversion_matrix
->v
[0])),
150 nir_fdot4(b
, expanded_channels
, nir_build_imm(b
, 4, 32, conversion_matrix
->v
[1])),
151 nir_fdot4(b
, expanded_channels
, nir_build_imm(b
, 4, 32, conversion_matrix
->v
[2]))
155 converted_channels
[0], converted_channels
[1],
156 converted_channels
[2], nir_imm_float(b
, 1.0f
));
160 create_plane_tex_instr_implicit(struct ycbcr_state
*state
,
163 nir_builder
*b
= state
->builder
;
164 nir_tex_instr
*old_tex
= state
->origin_tex
;
165 nir_tex_instr
*tex
= nir_tex_instr_create(b
->shader
, old_tex
->num_srcs
+ 1);
167 for (uint32_t i
= 0; i
< old_tex
->num_srcs
; i
++) {
168 tex
->src
[i
].src_type
= old_tex
->src
[i
].src_type
;
169 nir_src_copy(&tex
->src
[i
].src
, &old_tex
->src
[i
].src
, tex
);
172 tex
->src
[tex
->num_srcs
- 1].src
= nir_src_for_ssa(nir_imm_int(b
, plane
));
173 tex
->src
[tex
->num_srcs
- 1].src_type
= nir_tex_src_plane
;
175 tex
->sampler_dim
= old_tex
->sampler_dim
;
176 tex
->dest_type
= old_tex
->dest_type
;
177 tex
->is_array
= old_tex
->is_array
;
179 tex
->op
= old_tex
->op
;
180 tex
->coord_components
= old_tex
->coord_components
;
181 tex
->is_new_style_shadow
= old_tex
->is_new_style_shadow
;
182 tex
->component
= old_tex
->component
;
184 tex
->texture_index
= old_tex
->texture_index
;
185 tex
->texture_array_size
= old_tex
->texture_array_size
;
186 tex
->sampler_index
= old_tex
->sampler_index
;
188 nir_ssa_dest_init(&tex
->instr
, &tex
->dest
,
189 old_tex
->dest
.ssa
.num_components
,
190 nir_dest_bit_size(old_tex
->dest
), NULL
);
191 nir_builder_instr_insert(b
, &tex
->instr
);
193 return &tex
->dest
.ssa
;
196 struct swizzle_info
{
201 static struct swizzle_info
202 get_plane_swizzles(VkFormat format
)
204 int planes
= vk_format_get_plane_count(format
);
207 return (struct swizzle_info
) {
212 return (struct swizzle_info
) {
217 return (struct swizzle_info
) {
222 unreachable("unhandled plane count for ycbcr swizzling");
228 build_swizzled_components(nir_builder
*builder
,
230 VkComponentMapping mapping
,
231 nir_ssa_def
**plane_values
)
233 struct swizzle_info plane_swizzle
= get_plane_swizzles(format
);
234 enum vk_swizzle swizzles
[4];
235 nir_ssa_def
*values
[4];
237 vk_format_compose_swizzles(&mapping
, (const unsigned char[4]){0,1,2,3}, swizzles
);
239 nir_ssa_def
*zero
= nir_imm_float(builder
, 0.0f
);
240 nir_ssa_def
*one
= nir_imm_float(builder
, 1.0f
);
242 for (unsigned i
= 0; i
< 4; ++i
) {
243 switch(swizzles
[i
]) {
248 unsigned channel
= swizzles
[i
] - VK_SWIZZLE_X
;
249 values
[i
] = nir_channel(builder
,
250 plane_values
[plane_swizzle
.plane
[channel
]],
251 plane_swizzle
.swizzle
[channel
]);
261 unreachable("unhandled swizzle");
264 return nir_vec(builder
, values
, 4);
268 try_lower_tex_ycbcr(const struct radv_pipeline_layout
*layout
,
269 nir_builder
*builder
,
272 int deref_src_idx
= nir_tex_instr_src_index(tex
, nir_tex_src_texture_deref
);
273 assert(deref_src_idx
>= 0);
274 nir_deref_instr
*deref
= nir_src_as_deref(tex
->src
[deref_src_idx
].src
);
276 nir_variable
*var
= nir_deref_instr_get_variable(deref
);
277 const struct radv_descriptor_set_layout
*set_layout
=
278 layout
->set
[var
->data
.descriptor_set
].layout
;
279 const struct radv_descriptor_set_binding_layout
*binding
=
280 &set_layout
->binding
[var
->data
.binding
];
281 const struct radv_sampler_ycbcr_conversion
*ycbcr_samplers
=
282 radv_immutable_ycbcr_samplers(set_layout
, var
->data
.binding
);
287 /* For the following instructions, we don't apply any change and let the
288 * instruction apply to the first plane.
290 if (tex
->op
== nir_texop_txs
||
291 tex
->op
== nir_texop_query_levels
||
292 tex
->op
== nir_texop_lod
)
295 assert(tex
->texture_index
== 0);
296 unsigned array_index
= 0;
297 if (deref
->deref_type
!= nir_deref_type_var
) {
298 assert(deref
->deref_type
== nir_deref_type_array
);
299 if (!nir_src_is_const(deref
->arr
.index
))
301 array_index
= nir_src_as_uint(deref
->arr
.index
);
302 array_index
= MIN2(array_index
, binding
->array_size
- 1);
304 const struct radv_sampler_ycbcr_conversion
*ycbcr_sampler
= ycbcr_samplers
+ array_index
;
306 if (ycbcr_sampler
->format
== VK_FORMAT_UNDEFINED
)
309 struct ycbcr_state state
= {
313 .conversion
= ycbcr_sampler
,
316 builder
->cursor
= nir_before_instr(&tex
->instr
);
318 VkFormat format
= state
.conversion
->format
;
319 const int plane_count
= vk_format_get_plane_count(format
);
320 nir_ssa_def
*plane_values
[3];
322 for (int p
= 0; p
< plane_count
; ++p
) {
323 plane_values
[p
] = create_plane_tex_instr_implicit(&state
, p
);
326 nir_ssa_def
*result
= build_swizzled_components(builder
, format
, ycbcr_sampler
->components
, plane_values
);
327 if (state
.conversion
->ycbcr_model
!= VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY
) {
328 VkFormat first_format
= vk_format_get_plane_format(format
, 0);
329 result
= convert_ycbcr(&state
, result
, vk_format_get_component_bits(first_format
, VK_FORMAT_COLORSPACE_RGB
, VK_SWIZZLE_X
));
332 nir_ssa_def_rewrite_uses(&tex
->dest
.ssa
, nir_src_for_ssa(result
));
333 nir_instr_remove(&tex
->instr
);
339 radv_nir_lower_ycbcr_textures(nir_shader
*shader
,
340 const struct radv_pipeline_layout
*layout
)
342 bool progress
= false;
344 nir_foreach_function(function
, shader
) {
348 bool function_progress
= false;
350 nir_builder_init(&builder
, function
->impl
);
352 nir_foreach_block(block
, function
->impl
) {
353 nir_foreach_instr_safe(instr
, block
) {
354 if (instr
->type
!= nir_instr_type_tex
)
357 nir_tex_instr
*tex
= nir_instr_as_tex(instr
);
358 function_progress
|= try_lower_tex_ycbcr(layout
, &builder
, tex
);
362 if (function_progress
) {
363 nir_metadata_preserve(function
->impl
,
364 nir_metadata_block_index
|
365 nir_metadata_dominance
);
368 progress
|= function_progress
;