1/* 2 * Copyright © 2021 Intel Corporation 3 * 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: 10 * 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 13 * Software. 14 * 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 21 * IN THE SOFTWARE. 22 */ 23 24#include "nir.h" 25#include "nir_builder.h" 26 27#include "util/set.h" 28#include "util/macros.h" 29 30/** @file nir_opt_ray_queries.c 31 * 32 * Remove ray queries that the shader is not using the result of. 33 */ 34 35static void 36mark_query_read(struct set *queries, 37 nir_intrinsic_instr *intrin) 38{ 39 nir_ssa_def *rq_def = intrin->src[0].ssa; 40 41 nir_variable *query; 42 if (rq_def->parent_instr->type == nir_instr_type_intrinsic) { 43 nir_intrinsic_instr *load_deref = 44 nir_instr_as_intrinsic(rq_def->parent_instr); 45 assert(load_deref->intrinsic == nir_intrinsic_load_deref); 46 47 query = nir_intrinsic_get_var(load_deref, 0); 48 } else if (rq_def->parent_instr->type == nir_instr_type_deref) { 49 query = nir_deref_instr_get_variable( 50 nir_instr_as_deref(rq_def->parent_instr)); 51 } else { 52 return; 53 } 54 assert(query); 55 56 _mesa_set_add(queries, query); 57} 58 59static void 60nir_find_ray_queries_read(struct set *queries, 61 nir_shader *shader) 62{ 63 nir_foreach_function(function, shader) { 64 nir_function_impl *impl = function->impl; 65 66 if (!impl) 67 continue; 68 69 nir_foreach_block(block, impl) { 70 nir_foreach_instr(instr, block) { 71 if (instr->type != nir_instr_type_intrinsic) 72 continue; 73 74 nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); 75 switch (intrin->intrinsic) { 76 case nir_intrinsic_rq_proceed: 77 if (list_length(&intrin->dest.ssa.uses) > 0 || 78 list_length(&intrin->dest.ssa.if_uses) > 0) 79 mark_query_read(queries, intrin); 80 break; 81 case nir_intrinsic_rq_load: 82 mark_query_read(queries, intrin); 83 break; 84 default: 85 break; 86 } 87 } 88 } 89 } 90} 91 92static bool 93nir_replace_unread_queries_instr(nir_builder *b, nir_instr *instr, void *data) 94{ 95 struct set *queries = data; 96 97 if (instr->type != nir_instr_type_intrinsic) 98 return false; 99 100 nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); 101 switch (intrin->intrinsic) { 102 case nir_intrinsic_rq_initialize: 103 case nir_intrinsic_rq_terminate: 104 case nir_intrinsic_rq_generate_intersection: 105 case nir_intrinsic_rq_confirm_intersection: 106 break; 107 case nir_intrinsic_rq_proceed: 108 break; 109 default: 110 return false; 111 } 112 113 nir_variable *query = nir_intrinsic_get_var(intrin, 0); 114 assert(query); 115 116 struct set_entry *entry = _mesa_set_search(queries, query); 117 if (entry) 118 return false; 119 120 if (intrin->intrinsic == nir_intrinsic_rq_load) { 121 assert(list_is_empty(&intrin->dest.ssa.uses)); 122 assert(list_is_empty(&intrin->dest.ssa.if_uses)); 123 } 124 125 nir_instr_remove(instr); 126 127 return true; 128} 129 130bool 131nir_opt_ray_queries(nir_shader *shader) 132{ 133 struct set *read_queries = _mesa_pointer_set_create(NULL); 134 nir_find_ray_queries_read(read_queries, shader); 135 136 bool progress = 137 nir_shader_instructions_pass(shader, 138 nir_replace_unread_queries_instr, 139 nir_metadata_block_index | 140 nir_metadata_dominance, 141 read_queries); 142 143 /* Update the number of queries if some have been removed. */ 144 if (progress) { 145 nir_remove_dead_derefs(shader); 146 nir_remove_dead_variables(shader, 147 nir_var_shader_temp | nir_var_function_temp, 148 NULL); 149 nir_shader_gather_info(shader, nir_shader_get_entrypoint(shader)); 150 } 151 152 _mesa_set_destroy(read_queries, NULL); 153 154 return progress; 155} 156