1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2022 Advanced Micro Devices, Inc. 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 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * 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 NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * 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_ci/** 29bf215546Sopenharmony_ci * This NIR lowers pass for point smoothing by modifying the alpha value of 30bf215546Sopenharmony_ci * fragment outputs using the distance from the center of the point. 31bf215546Sopenharmony_ci * Anti-aliased points get rounded with respect to their radius. 32bf215546Sopenharmony_ci */ 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_cistatic bool 35bf215546Sopenharmony_cilower_point_smooth(nir_builder *b, nir_instr *instr, UNUSED void *_state) 36bf215546Sopenharmony_ci{ 37bf215546Sopenharmony_ci if (instr->type != nir_instr_type_intrinsic) 38bf215546Sopenharmony_ci return false; 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci if (intr->intrinsic != nir_intrinsic_store_output) 43bf215546Sopenharmony_ci return false; 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci int location = nir_intrinsic_io_semantics(intr).location; 46bf215546Sopenharmony_ci if ((location != FRAG_RESULT_COLOR && location < FRAG_RESULT_DATA0) || 47bf215546Sopenharmony_ci nir_intrinsic_src_type(intr) != nir_type_float32) 48bf215546Sopenharmony_ci return false; 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci assert(intr->src[0].is_ssa); 51bf215546Sopenharmony_ci assert(intr->num_components == 4); 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci b->cursor = nir_before_instr(&intr->instr); 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci nir_ssa_def *coord = nir_build_load_point_coord_maybe_flipped(b); 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ci /* point_size = 1.0 / dFdx(gl_PointCoord.x); */ 58bf215546Sopenharmony_ci nir_ssa_def *point_size = nir_frcp(b, nir_fddx(b, nir_channel(b, coord, 0))); 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ci /* radius = point_size * 0.5 */ 61bf215546Sopenharmony_ci nir_ssa_def *radius = nir_fmul_imm(b, point_size, 0.5);; 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci /** 64bf215546Sopenharmony_ci * Compute the distance of point from centre 65bf215546Sopenharmony_ci * distance = √ (x - 0.5)^2 + (y - 0.5)^2 66bf215546Sopenharmony_ci */ 67bf215546Sopenharmony_ci nir_ssa_def *distance = nir_fast_distance(b, coord, 68bf215546Sopenharmony_ci nir_imm_vec2(b, 0.5, 0.5)); 69bf215546Sopenharmony_ci distance = nir_fmul(b, distance, point_size); 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci /* alpha = min(max(radius - distance, 0.0), 1.0) */ 72bf215546Sopenharmony_ci nir_ssa_def *coverage = nir_fsat(b, nir_fsub(b, radius, distance)); 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci /* Discard fragments that are not covered by the point */ 75bf215546Sopenharmony_ci nir_discard_if(b, nir_feq(b, nir_imm_float(b, 0.0f), coverage)); 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_ci /* Write out the fragment color*vec4(1, 1, 1, coverage)*/ 78bf215546Sopenharmony_ci nir_ssa_def *one = nir_imm_float(b, 1.0f); 79bf215546Sopenharmony_ci nir_ssa_def *new_val = nir_fmul(b, nir_vec4(b, one, one, one, coverage), 80bf215546Sopenharmony_ci intr->src[0].ssa); 81bf215546Sopenharmony_ci nir_instr_rewrite_src(instr, &intr->src[0], nir_src_for_ssa(new_val)); 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci return true; 84bf215546Sopenharmony_ci} 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_cibool 87bf215546Sopenharmony_cinir_lower_point_smooth(nir_shader *shader) 88bf215546Sopenharmony_ci{ 89bf215546Sopenharmony_ci assert(shader->info.stage == MESA_SHADER_FRAGMENT); 90bf215546Sopenharmony_ci return nir_shader_instructions_pass(shader, lower_point_smooth, 91bf215546Sopenharmony_ci nir_metadata_loop_analysis | 92bf215546Sopenharmony_ci nir_metadata_block_index | 93bf215546Sopenharmony_ci nir_metadata_dominance, NULL); 94bf215546Sopenharmony_ci} 95