17ec681f3Smrg/* 27ec681f3Smrg * Copyright © 2017 Intel Corporation 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 207ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 217ec681f3Smrg * IN THE SOFTWARE. 227ec681f3Smrg */ 237ec681f3Smrg 247ec681f3Smrg#include "nir_vulkan.h" 257ec681f3Smrg#include <math.h> 267ec681f3Smrg 277ec681f3Smrgstatic nir_ssa_def * 287ec681f3Smrgy_range(nir_builder *b, 297ec681f3Smrg nir_ssa_def *y_channel, 307ec681f3Smrg int bpc, 317ec681f3Smrg VkSamplerYcbcrRange range) 327ec681f3Smrg{ 337ec681f3Smrg switch (range) { 347ec681f3Smrg case VK_SAMPLER_YCBCR_RANGE_ITU_FULL: 357ec681f3Smrg return y_channel; 367ec681f3Smrg case VK_SAMPLER_YCBCR_RANGE_ITU_NARROW: 377ec681f3Smrg return nir_fmul(b, 387ec681f3Smrg nir_fadd(b, 397ec681f3Smrg nir_fmul(b, y_channel, 407ec681f3Smrg nir_imm_float(b, pow(2, bpc) - 1)), 417ec681f3Smrg nir_imm_float(b, -16.0f * pow(2, bpc - 8))), 427ec681f3Smrg nir_frcp(b, nir_imm_float(b, 219.0f * pow(2, bpc - 8)))); 437ec681f3Smrg default: 447ec681f3Smrg unreachable("missing Ycbcr range"); 457ec681f3Smrg return NULL; 467ec681f3Smrg } 477ec681f3Smrg} 487ec681f3Smrg 497ec681f3Smrgstatic nir_ssa_def * 507ec681f3Smrgchroma_range(nir_builder *b, 517ec681f3Smrg nir_ssa_def *chroma_channel, 527ec681f3Smrg int bpc, 537ec681f3Smrg VkSamplerYcbcrRange range) 547ec681f3Smrg{ 557ec681f3Smrg switch (range) { 567ec681f3Smrg case VK_SAMPLER_YCBCR_RANGE_ITU_FULL: 577ec681f3Smrg return nir_fadd(b, chroma_channel, 587ec681f3Smrg nir_imm_float(b, -pow(2, bpc - 1) / (pow(2, bpc) - 1.0f))); 597ec681f3Smrg case VK_SAMPLER_YCBCR_RANGE_ITU_NARROW: 607ec681f3Smrg return nir_fmul(b, 617ec681f3Smrg nir_fadd(b, 627ec681f3Smrg nir_fmul(b, chroma_channel, 637ec681f3Smrg nir_imm_float(b, pow(2, bpc) - 1)), 647ec681f3Smrg nir_imm_float(b, -128.0f * pow(2, bpc - 8))), 657ec681f3Smrg nir_frcp(b, nir_imm_float(b, 224.0f * pow(2, bpc - 8)))); 667ec681f3Smrg default: 677ec681f3Smrg unreachable("missing Ycbcr range"); 687ec681f3Smrg return NULL; 697ec681f3Smrg } 707ec681f3Smrg} 717ec681f3Smrg 727ec681f3Smrgtypedef struct nir_const_value_3_4 { 737ec681f3Smrg nir_const_value v[3][4]; 747ec681f3Smrg} nir_const_value_3_4; 757ec681f3Smrg 767ec681f3Smrgstatic const nir_const_value_3_4 * 777ec681f3Smrgycbcr_model_to_rgb_matrix(VkSamplerYcbcrModelConversion model) 787ec681f3Smrg{ 797ec681f3Smrg switch (model) { 807ec681f3Smrg case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601: { 817ec681f3Smrg static const nir_const_value_3_4 bt601 = { { 827ec681f3Smrg { { .f32 = 1.402f }, { .f32 = 1.0f }, { .f32 = 0.0f }, { .f32 = 0.0f } }, 837ec681f3Smrg { { .f32 = -0.714136286201022f }, { .f32 = 1.0f }, { .f32 = -0.344136286201022f }, { .f32 = 0.0f } }, 847ec681f3Smrg { { .f32 = 0.0f }, { .f32 = 1.0f }, { .f32 = 1.772f }, { .f32 = 0.0f } }, 857ec681f3Smrg } }; 867ec681f3Smrg 877ec681f3Smrg return &bt601; 887ec681f3Smrg } 897ec681f3Smrg case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709: { 907ec681f3Smrg static const nir_const_value_3_4 bt709 = { { 917ec681f3Smrg { { .f32 = 1.5748031496063f }, { .f32 = 1.0f }, { .f32 = 0.0f }, { .f32 = 0.0f } }, 927ec681f3Smrg { { .f32 = -0.468125209181067f }, { .f32 = 1.0f }, { .f32 = -0.187327487470334f }, { .f32 = 0.0f } }, 937ec681f3Smrg { { .f32 = 0.0f }, { .f32 = 1.0f }, { .f32 = 1.85563184264242f }, { .f32 = 0.0f } }, 947ec681f3Smrg } }; 957ec681f3Smrg 967ec681f3Smrg return &bt709; 977ec681f3Smrg } 987ec681f3Smrg case VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020: { 997ec681f3Smrg static const nir_const_value_3_4 bt2020 = { { 1007ec681f3Smrg { { .f32 = 1.4746f }, { .f32 = 1.0f }, { .f32 = 0.0f }, { .f32 = 0.0f } }, 1017ec681f3Smrg { { .f32 = -0.571353126843658f }, { .f32 = 1.0f }, { .f32 = -0.164553126843658f }, { .f32 = 0.0f } }, 1027ec681f3Smrg { { .f32 = 0.0f }, { .f32 = 1.0f }, { .f32 = 1.8814f }, { .f32 = 0.0f } }, 1037ec681f3Smrg } }; 1047ec681f3Smrg 1057ec681f3Smrg return &bt2020; 1067ec681f3Smrg } 1077ec681f3Smrg default: 1087ec681f3Smrg unreachable("missing Ycbcr model"); 1097ec681f3Smrg return NULL; 1107ec681f3Smrg } 1117ec681f3Smrg} 1127ec681f3Smrg 1137ec681f3Smrgnir_ssa_def * 1147ec681f3Smrgnir_convert_ycbcr_to_rgb(nir_builder *b, 1157ec681f3Smrg VkSamplerYcbcrModelConversion model, 1167ec681f3Smrg VkSamplerYcbcrRange range, 1177ec681f3Smrg nir_ssa_def *raw_channels, 1187ec681f3Smrg uint32_t *bpcs) 1197ec681f3Smrg{ 1207ec681f3Smrg nir_ssa_def *expanded_channels = 1217ec681f3Smrg nir_vec4(b, 1227ec681f3Smrg chroma_range(b, nir_channel(b, raw_channels, 0), bpcs[0], range), 1237ec681f3Smrg y_range(b, nir_channel(b, raw_channels, 1), bpcs[1], range), 1247ec681f3Smrg chroma_range(b, nir_channel(b, raw_channels, 2), bpcs[2], range), 1257ec681f3Smrg nir_channel(b, raw_channels, 3)); 1267ec681f3Smrg 1277ec681f3Smrg if (model == VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY) 1287ec681f3Smrg return expanded_channels; 1297ec681f3Smrg 1307ec681f3Smrg const nir_const_value_3_4 *conversion_matrix = 1317ec681f3Smrg ycbcr_model_to_rgb_matrix(model); 1327ec681f3Smrg 1337ec681f3Smrg nir_ssa_def *converted_channels[] = { 1347ec681f3Smrg nir_fdot(b, expanded_channels, nir_build_imm(b, 4, 32, conversion_matrix->v[0])), 1357ec681f3Smrg nir_fdot(b, expanded_channels, nir_build_imm(b, 4, 32, conversion_matrix->v[1])), 1367ec681f3Smrg nir_fdot(b, expanded_channels, nir_build_imm(b, 4, 32, conversion_matrix->v[2])) 1377ec681f3Smrg }; 1387ec681f3Smrg 1397ec681f3Smrg return nir_vec4(b, 1407ec681f3Smrg converted_channels[0], converted_channels[1], 1417ec681f3Smrg converted_channels[2], nir_channel(b, raw_channels, 3)); 1427ec681f3Smrg} 143