1/* 2 * Copyright © 2015 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 27static nir_intrinsic_instr * 28as_intrinsic(nir_instr *instr, nir_intrinsic_op op) 29{ 30 if (instr->type != nir_instr_type_intrinsic) 31 return NULL; 32 33 nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); 34 if (intrin->intrinsic != op) 35 return NULL; 36 37 return intrin; 38} 39 40static nir_intrinsic_instr * 41as_set_vertex_and_primitive_count(nir_instr *instr) 42{ 43 return as_intrinsic(instr, nir_intrinsic_set_vertex_and_primitive_count); 44} 45 46/** 47 * Count the number of vertices/primitives emitted by a geometry shader per stream. 48 * If a constant number of vertices is emitted, the output is set to 49 * that number, otherwise it is unknown at compile time and the 50 * result will be -1. 51 * 52 * This only works if you've used nir_lower_gs_intrinsics() to do vertex 53 * counting at the NIR level. 54 */ 55void 56nir_gs_count_vertices_and_primitives(const nir_shader *shader, 57 int *out_vtxcnt, 58 int *out_prmcnt, 59 unsigned num_streams) 60{ 61 assert(num_streams); 62 63 int vtxcnt_arr[4] = {-1, -1, -1, -1}; 64 int prmcnt_arr[4] = {-1, -1, -1, -1}; 65 bool cnt_found[4] = {false, false, false, false}; 66 67 nir_foreach_function(function, shader) { 68 if (!function->impl) 69 continue; 70 71 /* set_vertex_and_primitive_count intrinsics only appear in predecessors of the 72 * end block. So we don't need to walk all of them. 73 */ 74 set_foreach(function->impl->end_block->predecessors, entry) { 75 nir_block *block = (nir_block *) entry->key; 76 77 nir_foreach_instr_reverse(instr, block) { 78 nir_intrinsic_instr *intrin = as_set_vertex_and_primitive_count(instr); 79 if (!intrin) 80 continue; 81 82 unsigned stream = nir_intrinsic_stream_id(intrin); 83 if (stream >= num_streams) 84 continue; 85 86 int vtxcnt = -1; 87 int prmcnt = -1; 88 89 /* If the number of vertices/primitives is compile-time known, we use that, 90 * otherwise we leave it at -1 which means that it's unknown. 91 */ 92 if (nir_src_is_const(intrin->src[0])) 93 vtxcnt = nir_src_as_int(intrin->src[0]); 94 if (nir_src_is_const(intrin->src[1])) 95 prmcnt = nir_src_as_int(intrin->src[1]); 96 97 /* We've found contradictory set_vertex_and_primitive_count intrinsics. 98 * This can happen if there are early-returns in main() and 99 * different paths emit different numbers of vertices. 100 */ 101 if (cnt_found[stream] && vtxcnt != vtxcnt_arr[stream]) 102 vtxcnt = -1; 103 if (cnt_found[stream] && prmcnt != prmcnt_arr[stream]) 104 prmcnt = -1; 105 106 vtxcnt_arr[stream] = vtxcnt; 107 prmcnt_arr[stream] = prmcnt; 108 cnt_found[stream] = true; 109 } 110 } 111 } 112 113 if (out_vtxcnt) 114 memcpy(out_vtxcnt, vtxcnt_arr, num_streams * sizeof(int)); 115 if (out_prmcnt) 116 memcpy(out_prmcnt, prmcnt_arr, num_streams * sizeof(int)); 117} 118