1 /************************************************************************** 2 * 3 * Copyright 2013 VMware, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 #include "draw_prim_assembler.h" 29 30 #include "draw_fs.h" 31 #include "draw_gs.h" 32 33 #include "util/u_debug.h" 34 #include "util/u_memory.h" 35 #include "util/u_prim.h" 36 37 #include "pipe/p_defines.h" 38 39 struct draw_assembler 40 { 41 struct draw_context *draw; 42 43 struct draw_prim_info *output_prims; 44 struct draw_vertex_info *output_verts; 45 46 const struct draw_prim_info *input_prims; 47 const struct draw_vertex_info *input_verts; 48 49 boolean needs_primid; 50 int primid_slot; 51 unsigned primid; 52 53 unsigned num_prims; 54 }; 55 56 57 static boolean 58 needs_primid(const struct draw_context *draw) 59 { 60 const struct draw_fragment_shader *fs = draw->fs.fragment_shader; 61 const struct draw_geometry_shader *gs = draw->gs.geometry_shader; 62 if (fs && fs->info.uses_primid) { 63 return !gs || !gs->info.uses_primid; 64 } 65 return FALSE; 66 } 67 68 boolean 69 draw_prim_assembler_is_required(const struct draw_context *draw, 70 const struct draw_prim_info *prim_info, 71 const struct draw_vertex_info *vert_info) 72 { 73 switch (prim_info->prim) { 74 case PIPE_PRIM_LINES_ADJACENCY: 75 case PIPE_PRIM_LINE_STRIP_ADJACENCY: 76 case PIPE_PRIM_TRIANGLES_ADJACENCY: 77 case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: 78 return TRUE; 79 default: 80 return needs_primid(draw); 81 } 82 } 83 84 /* 85 * Copy the vertex header along with its data from the current 86 * vertex buffer into a buffer holding vertices arranged 87 * into decomposed primitives (i.e. buffer without the 88 * adjacency vertices) 89 */ 90 static void 91 copy_verts(struct draw_assembler *asmblr, 92 unsigned *indices, unsigned num_indices) 93 { 94 unsigned i; 95 96 char *output = (char*)asmblr->output_verts->verts; 97 const char *input = (const char*)asmblr->input_verts->verts; 98 99 for (i = 0; i < num_indices; ++i) { 100 unsigned idx = indices[i]; 101 unsigned output_offset = 102 asmblr->output_verts->count * asmblr->output_verts->stride; 103 unsigned input_offset = asmblr->input_verts->stride * idx; 104 memcpy(output + output_offset, input + input_offset, 105 asmblr->input_verts->vertex_size); 106 asmblr->output_verts->count += 1; 107 } 108 ++asmblr->num_prims; 109 } 110 111 112 static void 113 inject_primid(struct draw_assembler *asmblr, 114 unsigned idx, 115 unsigned primid) 116 { 117 int slot = asmblr->primid_slot; 118 char *input = (char*)asmblr->input_verts->verts; 119 unsigned input_offset = asmblr->input_verts->stride * idx; 120 struct vertex_header *v = (struct vertex_header*)(input + input_offset); 121 122 /* In case the backend doesn't care about it */ 123 if (slot < 0) { 124 return; 125 } 126 127 memcpy(&v->data[slot][0], &primid, sizeof(primid)); 128 memcpy(&v->data[slot][1], &primid, sizeof(primid)); 129 memcpy(&v->data[slot][2], &primid, sizeof(primid)); 130 memcpy(&v->data[slot][3], &primid, sizeof(primid)); 131 } 132 133 134 static void 135 prim_point(struct draw_assembler *asmblr, 136 unsigned idx) 137 { 138 unsigned indices[1]; 139 140 if (asmblr->needs_primid) { 141 inject_primid(asmblr, idx, asmblr->primid++); 142 } 143 indices[0] = idx; 144 145 copy_verts(asmblr, indices, 1); 146 } 147 148 static void 149 prim_line(struct draw_assembler *asmblr, 150 unsigned i0, unsigned i1) 151 { 152 unsigned indices[2]; 153 154 if (asmblr->needs_primid) { 155 inject_primid(asmblr, i0, asmblr->primid); 156 inject_primid(asmblr, i1, asmblr->primid++); 157 } 158 indices[0] = i0; 159 indices[1] = i1; 160 161 copy_verts(asmblr, indices, 2); 162 } 163 164 static void 165 prim_tri(struct draw_assembler *asmblr, 166 unsigned i0, unsigned i1, unsigned i2) 167 { 168 unsigned indices[3]; 169 170 if (asmblr->needs_primid) { 171 inject_primid(asmblr, i0, asmblr->primid); 172 inject_primid(asmblr, i1, asmblr->primid); 173 inject_primid(asmblr, i2, asmblr->primid++); 174 } 175 indices[0] = i0; 176 indices[1] = i1; 177 indices[2] = i2; 178 179 copy_verts(asmblr, indices, 3); 180 } 181 182 void 183 draw_prim_assembler_prepare_outputs(struct draw_assembler *ia) 184 { 185 struct draw_context *draw = ia->draw; 186 if (needs_primid(draw)) { 187 ia->primid_slot = draw_alloc_extra_vertex_attrib( 188 ia->draw, TGSI_SEMANTIC_PRIMID, 0); 189 } else { 190 ia->primid_slot = -1; 191 } 192 } 193 194 195 #define FUNC assembler_run_linear 196 #define GET_ELT(idx) (start + (idx)) 197 #include "draw_prim_assembler_tmp.h" 198 199 #define FUNC assembler_run_elts 200 #define LOCAL_VARS const ushort *elts = input_prims->elts; 201 #define GET_ELT(idx) (elts[start + (idx)]) 202 #include "draw_prim_assembler_tmp.h" 203 204 205 206 /* 207 * Primitive assembler breaks up adjacency primitives and assembles 208 * the base primitives they represent, e.g. vertices forming 209 * PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY 210 * become vertices forming PIPE_PRIM_TRIANGLES 211 * This is needed because specification says that the adjacency 212 * primitives are only visible in the geometry shader so we need 213 * to get rid of them so that the rest of the pipeline can 214 * process the inputs. 215 */ 216 void 217 draw_prim_assembler_run(struct draw_context *draw, 218 const struct draw_prim_info *input_prims, 219 const struct draw_vertex_info *input_verts, 220 struct draw_prim_info *output_prims, 221 struct draw_vertex_info *output_verts) 222 { 223 struct draw_assembler *asmblr = draw->ia; 224 unsigned start, i; 225 unsigned assembled_prim = u_reduced_prim(input_prims->prim); 226 unsigned max_primitives = u_decomposed_prims_for_vertices( 227 input_prims->prim, input_prims->count); 228 unsigned max_verts = u_vertices_per_prim(assembled_prim) * max_primitives; 229 230 asmblr->output_prims = output_prims; 231 asmblr->output_verts = output_verts; 232 asmblr->input_prims = input_prims; 233 asmblr->input_verts = input_verts; 234 asmblr->needs_primid = needs_primid(asmblr->draw); 235 asmblr->num_prims = 0; 236 237 output_prims->linear = TRUE; 238 output_prims->elts = NULL; 239 output_prims->start = 0; 240 output_prims->prim = assembled_prim; 241 output_prims->flags = 0x0; 242 output_prims->primitive_lengths = MALLOC(sizeof(unsigned)); 243 output_prims->primitive_lengths[0] = 0; 244 output_prims->primitive_count = 1; 245 246 output_verts->vertex_size = input_verts->vertex_size; 247 output_verts->stride = input_verts->stride; 248 output_verts->verts = (struct vertex_header*)MALLOC( 249 input_verts->vertex_size * max_verts); 250 output_verts->count = 0; 251 252 253 for (start = i = 0; i < input_prims->primitive_count; 254 start += input_prims->primitive_lengths[i], i++) 255 { 256 unsigned count = input_prims->primitive_lengths[i]; 257 if (input_prims->linear) { 258 assembler_run_linear(asmblr, input_prims, input_verts, 259 start, count); 260 } else { 261 assembler_run_elts(asmblr, input_prims, input_verts, 262 start, count); 263 } 264 } 265 266 output_prims->primitive_lengths[0] = output_verts->count; 267 output_prims->count = output_verts->count; 268 } 269 270 struct draw_assembler * 271 draw_prim_assembler_create(struct draw_context *draw) 272 { 273 struct draw_assembler *ia = CALLOC_STRUCT( draw_assembler ); 274 275 ia->draw = draw; 276 277 return ia; 278 } 279 280 void 281 draw_prim_assembler_destroy(struct draw_assembler *ia) 282 { 283 FREE(ia); 284 } 285 286 287 /* 288 * Called at the very begin of the draw call with a new instance 289 * Used to reset state that should persist between primitive restart. 290 */ 291 void 292 draw_prim_assembler_new_instance(struct draw_assembler *asmblr) 293 { 294 asmblr->primid = 0; 295 } 296