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 "nir_vulkan.h"
28 y_range(nir_builder
*b
,
29 nir_ssa_def
*y_channel
,
31 VkSamplerYcbcrRange range
)
34 case VK_SAMPLER_YCBCR_RANGE_ITU_FULL
:
36 case VK_SAMPLER_YCBCR_RANGE_ITU_NARROW
:
39 nir_fmul(b
, y_channel
,
40 nir_imm_float(b
, pow(2, bpc
) - 1)),
41 nir_imm_float(b
, -16.0f
* pow(2, bpc
- 8))),
42 nir_frcp(b
, nir_imm_float(b
, 219.0f
* pow(2, bpc
- 8))));
44 unreachable("missing Ycbcr range");
50 chroma_range(nir_builder
*b
,
51 nir_ssa_def
*chroma_channel
,
53 VkSamplerYcbcrRange range
)
56 case VK_SAMPLER_YCBCR_RANGE_ITU_FULL
:
57 return nir_fadd(b
, chroma_channel
,
58 nir_imm_float(b
, -pow(2, bpc
- 1) / (pow(2, bpc
) - 1.0f
)));
59 case VK_SAMPLER_YCBCR_RANGE_ITU_NARROW
:
62 nir_fmul(b
, chroma_channel
,
63 nir_imm_float(b
, pow(2, bpc
) - 1)),
64 nir_imm_float(b
, -128.0f
* pow(2, bpc
- 8))),
65 nir_frcp(b
, nir_imm_float(b
, 224.0f
* pow(2, bpc
- 8))));
67 unreachable("missing Ycbcr range");
72 typedef struct nir_const_value_3_4
{
73 nir_const_value v
[3][4];
74 } nir_const_value_3_4
;
76 static const nir_const_value_3_4
*
77 ycbcr_model_to_rgb_matrix(VkSamplerYcbcrModelConversion model
)
80 case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601
: {
81 static const nir_const_value_3_4 bt601
= { {
82 { { .f32
= 1.402f
}, { .f32
= 1.0f
}, { .f32
= 0.0f
}, { .f32
= 0.0f
} },
83 { { .f32
= -0.714136286201022f
}, { .f32
= 1.0f
}, { .f32
= -0.344136286201022f
}, { .f32
= 0.0f
} },
84 { { .f32
= 0.0f
}, { .f32
= 1.0f
}, { .f32
= 1.772f
}, { .f32
= 0.0f
} },
89 case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709
: {
90 static const nir_const_value_3_4 bt709
= { {
91 { { .f32
= 1.5748031496063f
}, { .f32
= 1.0f
}, { .f32
= 0.0f
}, { .f32
= 0.0f
} },
92 { { .f32
= -0.468125209181067f
}, { .f32
= 1.0f
}, { .f32
= -0.187327487470334f
}, { .f32
= 0.0f
} },
93 { { .f32
= 0.0f
}, { .f32
= 1.0f
}, { .f32
= 1.85563184264242f
}, { .f32
= 0.0f
} },
98 case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020
: {
99 static const nir_const_value_3_4 bt2020
= { {
100 { { .f32
= 1.4746f
}, { .f32
= 1.0f
}, { .f32
= 0.0f
}, { .f32
= 0.0f
} },
101 { { .f32
= -0.571353126843658f
}, { .f32
= 1.0f
}, { .f32
= -0.164553126843658f
}, { .f32
= 0.0f
} },
102 { { .f32
= 0.0f
}, { .f32
= 1.0f
}, { .f32
= 1.8814f
}, { .f32
= 0.0f
} },
108 unreachable("missing Ycbcr model");
114 nir_convert_ycbcr_to_rgb(nir_builder
*b
,
115 VkSamplerYcbcrModelConversion model
,
116 VkSamplerYcbcrRange range
,
117 nir_ssa_def
*raw_channels
,
120 nir_ssa_def
*expanded_channels
=
122 chroma_range(b
, nir_channel(b
, raw_channels
, 0), bpcs
[0], range
),
123 y_range(b
, nir_channel(b
, raw_channels
, 1), bpcs
[1], range
),
124 chroma_range(b
, nir_channel(b
, raw_channels
, 2), bpcs
[2], range
),
125 nir_channel(b
, raw_channels
, 3));
127 if (model
== VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY
)
128 return expanded_channels
;
130 const nir_const_value_3_4
*conversion_matrix
=
131 ycbcr_model_to_rgb_matrix(model
);
133 nir_ssa_def
*converted_channels
[] = {
134 nir_fdot4(b
, expanded_channels
, nir_build_imm(b
, 4, 32, conversion_matrix
->v
[0])),
135 nir_fdot4(b
, expanded_channels
, nir_build_imm(b
, 4, 32, conversion_matrix
->v
[1])),
136 nir_fdot4(b
, expanded_channels
, nir_build_imm(b
, 4, 32, conversion_matrix
->v
[2]))
140 converted_channels
[0], converted_channels
[1],
141 converted_channels
[2], nir_channel(b
, raw_channels
, 3));