1 /************************************************************************** 2 * 3 * Copyright 2007 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 /* 29 * Authors: 30 * Keith Whitwell <keithw (at) vmware.com> 31 * Brian Paul 32 */ 33 34 #include "util/u_math.h" 35 #include "util/u_memory.h" 36 37 #include "pipe/p_shader_tokens.h" 38 39 #include "draw_private.h" 40 #include "draw_context.h" 41 #include "draw_vs.h" 42 43 #include "translate/translate.h" 44 #include "translate/translate_cache.h" 45 46 #include "tgsi/tgsi_dump.h" 47 #include "tgsi/tgsi_exec.h" 48 49 DEBUG_GET_ONCE_BOOL_OPTION(gallium_dump_vs, "GALLIUM_DUMP_VS", FALSE) 50 51 52 struct draw_vertex_shader * 53 draw_create_vertex_shader(struct draw_context *draw, 54 const struct pipe_shader_state *shader) 55 { 56 struct draw_vertex_shader *vs = NULL; 57 58 if (draw->dump_vs) { 59 tgsi_dump(shader->tokens, 0); 60 } 61 62 #if HAVE_LLVM 63 if (draw->pt.middle.llvm) { 64 vs = draw_create_vs_llvm(draw, shader); 65 } 66 #endif 67 68 if (!vs) { 69 vs = draw_create_vs_exec( draw, shader ); 70 } 71 72 if (vs) 73 { 74 uint i; 75 bool found_clipvertex = FALSE; 76 vs->position_output = -1; 77 for (i = 0; i < vs->info.num_outputs; i++) { 78 if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_POSITION && 79 vs->info.output_semantic_index[i] == 0) 80 vs->position_output = i; 81 else if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_EDGEFLAG && 82 vs->info.output_semantic_index[i] == 0) 83 vs->edgeflag_output = i; 84 else if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_CLIPVERTEX && 85 vs->info.output_semantic_index[i] == 0) { 86 found_clipvertex = TRUE; 87 vs->clipvertex_output = i; 88 } else if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_VIEWPORT_INDEX) 89 vs->viewport_index_output = i; 90 else if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_CLIPDIST) { 91 debug_assert(vs->info.output_semantic_index[i] < 92 PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT); 93 vs->ccdistance_output[vs->info.output_semantic_index[i]] = i; 94 } 95 } 96 if (!found_clipvertex) 97 vs->clipvertex_output = vs->position_output; 98 } 99 100 assert(vs); 101 return vs; 102 } 103 104 105 void 106 draw_bind_vertex_shader(struct draw_context *draw, 107 struct draw_vertex_shader *dvs) 108 { 109 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 110 111 if (dvs) 112 { 113 draw->vs.vertex_shader = dvs; 114 draw->vs.num_vs_outputs = dvs->info.num_outputs; 115 draw->vs.position_output = dvs->position_output; 116 draw->vs.edgeflag_output = dvs->edgeflag_output; 117 draw->vs.clipvertex_output = dvs->clipvertex_output; 118 draw->vs.ccdistance_output[0] = dvs->ccdistance_output[0]; 119 draw->vs.ccdistance_output[1] = dvs->ccdistance_output[1]; 120 dvs->prepare( dvs, draw ); 121 draw_update_clip_flags(draw); 122 draw_update_viewport_flags(draw); 123 } 124 else { 125 draw->vs.vertex_shader = NULL; 126 draw->vs.num_vs_outputs = 0; 127 } 128 } 129 130 131 void 132 draw_delete_vertex_shader(struct draw_context *draw, 133 struct draw_vertex_shader *dvs) 134 { 135 unsigned i; 136 137 for (i = 0; i < dvs->nr_variants; i++) 138 dvs->variant[i]->destroy( dvs->variant[i] ); 139 140 dvs->nr_variants = 0; 141 142 dvs->delete( dvs ); 143 } 144 145 146 147 boolean 148 draw_vs_init( struct draw_context *draw ) 149 { 150 draw->dump_vs = debug_get_option_gallium_dump_vs(); 151 152 if (!draw->llvm) { 153 draw->vs.tgsi.machine = tgsi_exec_machine_create(PIPE_SHADER_VERTEX); 154 if (!draw->vs.tgsi.machine) 155 return FALSE; 156 } 157 158 draw->vs.emit_cache = translate_cache_create(); 159 if (!draw->vs.emit_cache) 160 return FALSE; 161 162 draw->vs.fetch_cache = translate_cache_create(); 163 if (!draw->vs.fetch_cache) 164 return FALSE; 165 166 return TRUE; 167 } 168 169 void 170 draw_vs_destroy( struct draw_context *draw ) 171 { 172 if (draw->vs.fetch_cache) 173 translate_cache_destroy(draw->vs.fetch_cache); 174 175 if (draw->vs.emit_cache) 176 translate_cache_destroy(draw->vs.emit_cache); 177 178 if (!draw->llvm) 179 tgsi_exec_machine_destroy(draw->vs.tgsi.machine); 180 } 181 182 183 struct draw_vs_variant * 184 draw_vs_lookup_variant( struct draw_vertex_shader *vs, 185 const struct draw_vs_variant_key *key ) 186 { 187 struct draw_vs_variant *variant; 188 unsigned i; 189 190 /* Lookup existing variant: 191 */ 192 for (i = 0; i < vs->nr_variants; i++) 193 if (draw_vs_variant_key_compare(key, &vs->variant[i]->key) == 0) 194 return vs->variant[i]; 195 196 /* Else have to create a new one: 197 */ 198 variant = vs->create_variant( vs, key ); 199 if (!variant) 200 return NULL; 201 202 /* Add it to our list, could be smarter: 203 */ 204 if (vs->nr_variants < ARRAY_SIZE(vs->variant)) { 205 vs->variant[vs->nr_variants++] = variant; 206 } 207 else { 208 vs->last_variant++; 209 vs->last_variant %= ARRAY_SIZE(vs->variant); 210 vs->variant[vs->last_variant]->destroy(vs->variant[vs->last_variant]); 211 vs->variant[vs->last_variant] = variant; 212 } 213 214 /* Done 215 */ 216 return variant; 217 } 218 219 220 struct translate * 221 draw_vs_get_fetch( struct draw_context *draw, 222 struct translate_key *key ) 223 { 224 if (!draw->vs.fetch || 225 translate_key_compare(&draw->vs.fetch->key, key) != 0) 226 { 227 translate_key_sanitize(key); 228 draw->vs.fetch = translate_cache_find(draw->vs.fetch_cache, key); 229 } 230 231 return draw->vs.fetch; 232 } 233 234 struct translate * 235 draw_vs_get_emit( struct draw_context *draw, 236 struct translate_key *key ) 237 { 238 if (!draw->vs.emit || 239 translate_key_compare(&draw->vs.emit->key, key) != 0) 240 { 241 translate_key_sanitize(key); 242 draw->vs.emit = translate_cache_find(draw->vs.emit_cache, key); 243 } 244 245 return draw->vs.emit; 246 } 247 248 void 249 draw_vs_attach_so(struct draw_vertex_shader *dvs, 250 const struct pipe_stream_output_info *info) 251 { 252 dvs->state.stream_output = *info; 253 } 254 255 void 256 draw_vs_reset_so(struct draw_vertex_shader *dvs) 257 { 258 memset(&dvs->state.stream_output, 0, sizeof(dvs->state.stream_output)); 259 } 260