1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © Microsoft Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 8bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 9bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "nir.h" 25bf215546Sopenharmony_ci#include "nir_builder.h" 26bf215546Sopenharmony_ci#include "nir_builtin_builder.h" 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_cistatic bool 29bf215546Sopenharmony_cinir_lower_tex_shadow_filter(const nir_instr *instr, 30bf215546Sopenharmony_ci UNUSED const void *_options) 31bf215546Sopenharmony_ci{ 32bf215546Sopenharmony_ci if (instr->type != nir_instr_type_tex) 33bf215546Sopenharmony_ci return false; 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci /* To be consistent we also want to lower tex when we lower anything, 36bf215546Sopenharmony_ci * otherwise the differences in evaluating the shadow value might lead 37bf215546Sopenharmony_ci * to artifacts. */ 38bf215546Sopenharmony_ci nir_tex_instr *tex = nir_instr_as_tex(instr); 39bf215546Sopenharmony_ci if (tex->op != nir_texop_txb && 40bf215546Sopenharmony_ci tex->op != nir_texop_txl && 41bf215546Sopenharmony_ci tex->op != nir_texop_txd && 42bf215546Sopenharmony_ci tex->op != nir_texop_tex) 43bf215546Sopenharmony_ci return false; 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci return tex->is_shadow; 46bf215546Sopenharmony_ci} 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_cistatic const struct glsl_type * 49bf215546Sopenharmony_cistrip_shadow(const struct glsl_type *type) 50bf215546Sopenharmony_ci{ 51bf215546Sopenharmony_ci const struct glsl_type *new_type = 52bf215546Sopenharmony_ci glsl_sampler_type( 53bf215546Sopenharmony_ci glsl_get_sampler_dim(type), 54bf215546Sopenharmony_ci false, glsl_sampler_type_is_array(type), 55bf215546Sopenharmony_ci GLSL_TYPE_FLOAT); 56bf215546Sopenharmony_ci return new_type; 57bf215546Sopenharmony_ci} 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_cistatic const struct glsl_type * 61bf215546Sopenharmony_cistrip_shadow_with_array(const struct glsl_type *type) 62bf215546Sopenharmony_ci{ 63bf215546Sopenharmony_ci if (glsl_type_is_array(type)) 64bf215546Sopenharmony_ci return glsl_array_type(strip_shadow(glsl_without_array(type)), 65bf215546Sopenharmony_ci glsl_get_length(type), 0); 66bf215546Sopenharmony_ci return strip_shadow(type); 67bf215546Sopenharmony_ci} 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_citypedef struct { 70bf215546Sopenharmony_ci unsigned n_states; 71bf215546Sopenharmony_ci enum compare_func *compare_func; 72bf215546Sopenharmony_ci nir_lower_tex_shadow_swizzle *tex_swizzles; 73bf215546Sopenharmony_ci} sampler_state; 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_cistatic nir_ssa_def * 76bf215546Sopenharmony_cinir_lower_tex_shadow_impl(nir_builder *b, nir_instr *instr, void *options) 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci{ 79bf215546Sopenharmony_ci nir_tex_instr *tex = nir_instr_as_tex(instr); 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci sampler_state *state = (sampler_state *)options; 82bf215546Sopenharmony_ci unsigned num_components = nir_tex_instr_result_size(tex); 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci b->cursor = nir_after_instr(instr); 85bf215546Sopenharmony_ci tex->is_shadow = false; 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci int comp_index = nir_tex_instr_src_index(tex, nir_tex_src_comparator); 88bf215546Sopenharmony_ci unsigned sampler_binding = tex->texture_index; 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci nir_deref_instr *sampler_deref = NULL; 91bf215546Sopenharmony_ci nir_variable *sampler = NULL; 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_ci int sampler_index = nir_tex_instr_src_index(tex, nir_tex_src_sampler_deref); 94bf215546Sopenharmony_ci if (sampler_index >= 0) { 95bf215546Sopenharmony_ci sampler_deref = nir_instr_as_deref(tex->src[sampler_index].src.ssa->parent_instr); 96bf215546Sopenharmony_ci sampler = nir_deref_instr_get_variable(sampler_deref); 97bf215546Sopenharmony_ci sampler_binding = sampler ? sampler->data.binding : 0; 98bf215546Sopenharmony_ci } 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci /* NIR expects a vec4 result from the above texture instructions */ 101bf215546Sopenharmony_ci nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, NULL); 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci nir_ssa_def *tex_r = nir_channel(b, &tex->dest.ssa, 0); 104bf215546Sopenharmony_ci nir_ssa_def *cmp = tex->src[comp_index].src.ssa; 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ci int proj_index = nir_tex_instr_src_index(tex, nir_tex_src_projector); 107bf215546Sopenharmony_ci if (proj_index >= 0) 108bf215546Sopenharmony_ci cmp = nir_fmul(b, cmp, nir_frcp(b, tex->src[proj_index].src.ssa)); 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci nir_ssa_def * result = 111bf215546Sopenharmony_ci nir_compare_func(b, 112bf215546Sopenharmony_ci sampler_binding < state->n_states ? 113bf215546Sopenharmony_ci state->compare_func[sampler_binding] : COMPARE_FUNC_ALWAYS, 114bf215546Sopenharmony_ci cmp, tex_r); 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_ci result = nir_b2f32(b, result); 117bf215546Sopenharmony_ci nir_ssa_def *one = nir_imm_float(b, 1.0); 118bf215546Sopenharmony_ci nir_ssa_def *zero = nir_imm_float(b, 0.0); 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci nir_ssa_def *lookup[6] = {result, NULL, NULL, NULL, zero, one}; 121bf215546Sopenharmony_ci nir_ssa_def *r[4] = {lookup[state->tex_swizzles[sampler_binding].swizzle_r], 122bf215546Sopenharmony_ci lookup[state->tex_swizzles[sampler_binding].swizzle_g], 123bf215546Sopenharmony_ci lookup[state->tex_swizzles[sampler_binding].swizzle_b], 124bf215546Sopenharmony_ci lookup[state->tex_swizzles[sampler_binding].swizzle_a] 125bf215546Sopenharmony_ci }; 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci result = nir_vec(b, r, num_components); 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci if (sampler_index >= 0) { 130bf215546Sopenharmony_ci sampler->type = strip_shadow_with_array(sampler->type); 131bf215546Sopenharmony_ci sampler_deref->type = sampler->type; 132bf215546Sopenharmony_ci } 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci tex->is_shadow = false; 135bf215546Sopenharmony_ci nir_tex_instr_remove_src(tex, comp_index); 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci return result; 138bf215546Sopenharmony_ci} 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_cibool 141bf215546Sopenharmony_cinir_lower_tex_shadow(nir_shader *s, 142bf215546Sopenharmony_ci unsigned n_states, 143bf215546Sopenharmony_ci enum compare_func *compare_func, 144bf215546Sopenharmony_ci nir_lower_tex_shadow_swizzle *tex_swizzles) 145bf215546Sopenharmony_ci{ 146bf215546Sopenharmony_ci sampler_state state = {n_states, compare_func, tex_swizzles}; 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci bool result = 149bf215546Sopenharmony_ci nir_shader_lower_instructions(s, 150bf215546Sopenharmony_ci nir_lower_tex_shadow_filter, 151bf215546Sopenharmony_ci nir_lower_tex_shadow_impl, 152bf215546Sopenharmony_ci &state); 153bf215546Sopenharmony_ci return result; 154bf215546Sopenharmony_ci} 155