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 #include "sp_context.h" 29 #include "sp_state.h" 30 #include "sp_fs.h" 31 #include "sp_texture.h" 32 33 #include "pipe/p_defines.h" 34 #include "util/u_memory.h" 35 #include "util/u_inlines.h" 36 #include "util/u_pstipple.h" 37 #include "draw/draw_context.h" 38 #include "draw/draw_vs.h" 39 #include "draw/draw_gs.h" 40 #include "tgsi/tgsi_dump.h" 41 #include "tgsi/tgsi_scan.h" 42 #include "tgsi/tgsi_parse.h" 43 44 45 /** 46 * Create a new fragment shader variant. 47 */ 48 static struct sp_fragment_shader_variant * 49 create_fs_variant(struct softpipe_context *softpipe, 50 struct sp_fragment_shader *fs, 51 const struct sp_fragment_shader_variant_key *key) 52 { 53 struct sp_fragment_shader_variant *var; 54 struct pipe_shader_state *curfs = &fs->shader; 55 56 /* codegen, create variant object */ 57 var = softpipe_create_fs_variant_exec(softpipe); 58 59 if (var) { 60 var->key = *key; 61 62 #if DO_PSTIPPLE_IN_HELPER_MODULE 63 if (key->polygon_stipple) { 64 /* get new shader that implements polygon stippling */ 65 var->tokens = 66 util_pstipple_create_fragment_shader(curfs->tokens, 67 &var->stipple_sampler_unit, 0, 68 TGSI_FILE_INPUT); 69 } 70 else 71 #endif 72 { 73 var->tokens = tgsi_dup_tokens(curfs->tokens); 74 var->stipple_sampler_unit = 0; 75 } 76 77 tgsi_scan_shader(var->tokens, &var->info); 78 79 /* See comments elsewhere about draw fragment shaders */ 80 #if 0 81 /* draw's fs state */ 82 var->draw_shader = draw_create_fragment_shader(softpipe->draw, 83 &fs->shader); 84 if (!var->draw_shader) { 85 var->delete(var); 86 FREE((void *) var->tokens); 87 return NULL; 88 } 89 #endif 90 91 /* insert variant into linked list */ 92 var->next = fs->variants; 93 fs->variants = var; 94 } 95 96 return var; 97 } 98 99 100 struct sp_fragment_shader_variant * 101 softpipe_find_fs_variant(struct softpipe_context *sp, 102 struct sp_fragment_shader *fs, 103 const struct sp_fragment_shader_variant_key *key) 104 { 105 struct sp_fragment_shader_variant *var; 106 107 for (var = fs->variants; var; var = var->next) { 108 if (memcmp(&var->key, key, sizeof(*key)) == 0) { 109 /* found it */ 110 return var; 111 } 112 } 113 114 return create_fs_variant(sp, fs, key); 115 } 116 117 118 static void * 119 softpipe_create_fs_state(struct pipe_context *pipe, 120 const struct pipe_shader_state *templ) 121 { 122 struct softpipe_context *softpipe = softpipe_context(pipe); 123 struct sp_fragment_shader *state = CALLOC_STRUCT(sp_fragment_shader); 124 125 /* debug */ 126 if (softpipe->dump_fs) 127 tgsi_dump(templ->tokens, 0); 128 129 /* we need to keep a local copy of the tokens */ 130 state->shader.tokens = tgsi_dup_tokens(templ->tokens); 131 132 /* draw's fs state */ 133 state->draw_shader = draw_create_fragment_shader(softpipe->draw, 134 &state->shader); 135 if (!state->draw_shader) { 136 tgsi_free_tokens(state->shader.tokens); 137 FREE(state); 138 return NULL; 139 } 140 141 return state; 142 } 143 144 145 static void 146 softpipe_bind_fs_state(struct pipe_context *pipe, void *fs) 147 { 148 struct softpipe_context *softpipe = softpipe_context(pipe); 149 struct sp_fragment_shader *state = (struct sp_fragment_shader *) fs; 150 151 if (softpipe->fs == fs) 152 return; 153 154 draw_flush(softpipe->draw); 155 156 softpipe->fs = fs; 157 158 /* This depends on the current fragment shader and must always be 159 * re-validated before use. 160 */ 161 softpipe->fs_variant = NULL; 162 163 if (state) 164 draw_bind_fragment_shader(softpipe->draw, 165 state->draw_shader); 166 else 167 draw_bind_fragment_shader(softpipe->draw, NULL); 168 169 softpipe->dirty |= SP_NEW_FS; 170 } 171 172 173 static void 174 softpipe_delete_fs_state(struct pipe_context *pipe, void *fs) 175 { 176 struct softpipe_context *softpipe = softpipe_context(pipe); 177 struct sp_fragment_shader *state = fs; 178 struct sp_fragment_shader_variant *var, *next_var; 179 180 assert(fs != softpipe->fs); 181 182 /* delete variants */ 183 for (var = state->variants; var; var = next_var) { 184 next_var = var->next; 185 186 assert(var != softpipe->fs_variant); 187 188 /* See comments elsewhere about draw fragment shaders */ 189 #if 0 190 draw_delete_fragment_shader(softpipe->draw, var->draw_shader); 191 #endif 192 193 var->delete(var, softpipe->fs_machine); 194 } 195 196 draw_delete_fragment_shader(softpipe->draw, state->draw_shader); 197 198 tgsi_free_tokens(state->shader.tokens); 199 FREE(state); 200 } 201 202 203 static void * 204 softpipe_create_vs_state(struct pipe_context *pipe, 205 const struct pipe_shader_state *templ) 206 { 207 struct softpipe_context *softpipe = softpipe_context(pipe); 208 struct sp_vertex_shader *state; 209 210 state = CALLOC_STRUCT(sp_vertex_shader); 211 if (!state) 212 goto fail; 213 214 /* copy shader tokens, the ones passed in will go away. 215 */ 216 state->shader.tokens = tgsi_dup_tokens(templ->tokens); 217 if (state->shader.tokens == NULL) 218 goto fail; 219 220 state->draw_data = draw_create_vertex_shader(softpipe->draw, templ); 221 if (state->draw_data == NULL) 222 goto fail; 223 224 state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER]; 225 226 return state; 227 228 fail: 229 if (state) { 230 tgsi_free_tokens(state->shader.tokens); 231 FREE( state->draw_data ); 232 FREE( state ); 233 } 234 return NULL; 235 } 236 237 238 static void 239 softpipe_bind_vs_state(struct pipe_context *pipe, void *vs) 240 { 241 struct softpipe_context *softpipe = softpipe_context(pipe); 242 243 softpipe->vs = (struct sp_vertex_shader *) vs; 244 245 draw_bind_vertex_shader(softpipe->draw, 246 (softpipe->vs ? softpipe->vs->draw_data : NULL)); 247 248 softpipe->dirty |= SP_NEW_VS; 249 } 250 251 252 static void 253 softpipe_delete_vs_state(struct pipe_context *pipe, void *vs) 254 { 255 struct softpipe_context *softpipe = softpipe_context(pipe); 256 257 struct sp_vertex_shader *state = (struct sp_vertex_shader *) vs; 258 259 draw_delete_vertex_shader(softpipe->draw, state->draw_data); 260 tgsi_free_tokens(state->shader.tokens); 261 FREE( state ); 262 } 263 264 265 static void * 266 softpipe_create_gs_state(struct pipe_context *pipe, 267 const struct pipe_shader_state *templ) 268 { 269 struct softpipe_context *softpipe = softpipe_context(pipe); 270 struct sp_geometry_shader *state; 271 272 state = CALLOC_STRUCT(sp_geometry_shader); 273 if (!state) 274 goto fail; 275 276 state->shader = *templ; 277 278 if (templ->tokens) { 279 /* debug */ 280 if (softpipe->dump_gs) 281 tgsi_dump(templ->tokens, 0); 282 283 /* copy shader tokens, the ones passed in will go away. 284 */ 285 state->shader.tokens = tgsi_dup_tokens(templ->tokens); 286 if (state->shader.tokens == NULL) 287 goto fail; 288 289 state->draw_data = draw_create_geometry_shader(softpipe->draw, templ); 290 if (state->draw_data == NULL) 291 goto fail; 292 293 state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER]; 294 } 295 296 return state; 297 298 fail: 299 if (state) { 300 tgsi_free_tokens(state->shader.tokens); 301 FREE( state->draw_data ); 302 FREE( state ); 303 } 304 return NULL; 305 } 306 307 308 static void 309 softpipe_bind_gs_state(struct pipe_context *pipe, void *gs) 310 { 311 struct softpipe_context *softpipe = softpipe_context(pipe); 312 313 softpipe->gs = (struct sp_geometry_shader *)gs; 314 315 draw_bind_geometry_shader(softpipe->draw, 316 (softpipe->gs ? softpipe->gs->draw_data : NULL)); 317 318 softpipe->dirty |= SP_NEW_GS; 319 } 320 321 322 static void 323 softpipe_delete_gs_state(struct pipe_context *pipe, void *gs) 324 { 325 struct softpipe_context *softpipe = softpipe_context(pipe); 326 327 struct sp_geometry_shader *state = 328 (struct sp_geometry_shader *)gs; 329 330 draw_delete_geometry_shader(softpipe->draw, 331 (state) ? state->draw_data : 0); 332 333 tgsi_free_tokens(state->shader.tokens); 334 FREE(state); 335 } 336 337 338 static void 339 softpipe_set_constant_buffer(struct pipe_context *pipe, 340 uint shader, uint index, 341 const struct pipe_constant_buffer *cb) 342 { 343 struct softpipe_context *softpipe = softpipe_context(pipe); 344 struct pipe_resource *constants = cb ? cb->buffer : NULL; 345 unsigned size; 346 const void *data; 347 348 assert(shader < PIPE_SHADER_TYPES); 349 350 if (cb && cb->user_buffer) { 351 constants = softpipe_user_buffer_create(pipe->screen, 352 (void *) cb->user_buffer, 353 cb->buffer_size, 354 PIPE_BIND_CONSTANT_BUFFER); 355 } 356 357 size = cb ? cb->buffer_size : 0; 358 data = constants ? softpipe_resource_data(constants) : NULL; 359 if (data) 360 data = (const char *) data + cb->buffer_offset; 361 362 draw_flush(softpipe->draw); 363 364 /* note: reference counting */ 365 pipe_resource_reference(&softpipe->constants[shader][index], constants); 366 367 if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) { 368 draw_set_mapped_constant_buffer(softpipe->draw, shader, index, data, size); 369 } 370 371 softpipe->mapped_constants[shader][index] = data; 372 softpipe->const_buffer_size[shader][index] = size; 373 374 softpipe->dirty |= SP_NEW_CONSTANTS; 375 376 if (cb && cb->user_buffer) { 377 pipe_resource_reference(&constants, NULL); 378 } 379 } 380 381 static void * 382 softpipe_create_compute_state(struct pipe_context *pipe, 383 const struct pipe_compute_state *templ) 384 { 385 struct softpipe_context *softpipe = softpipe_context(pipe); 386 const struct tgsi_token *tokens; 387 struct sp_compute_shader *state; 388 if (templ->ir_type != PIPE_SHADER_IR_TGSI) 389 return NULL; 390 391 tokens = templ->prog; 392 /* debug */ 393 if (softpipe->dump_cs) 394 tgsi_dump(tokens, 0); 395 396 state = CALLOC_STRUCT(sp_compute_shader); 397 398 state->shader = *templ; 399 state->tokens = tgsi_dup_tokens(tokens); 400 tgsi_scan_shader(state->tokens, &state->info); 401 402 state->max_sampler = state->info.file_max[TGSI_FILE_SAMPLER]; 403 404 return state; 405 } 406 407 static void 408 softpipe_bind_compute_state(struct pipe_context *pipe, 409 void *cs) 410 { 411 struct softpipe_context *softpipe = softpipe_context(pipe); 412 struct sp_compute_shader *state = (struct sp_compute_shader *)cs; 413 if (softpipe->cs == state) 414 return; 415 416 softpipe->cs = state; 417 } 418 419 static void 420 softpipe_delete_compute_state(struct pipe_context *pipe, 421 void *cs) 422 { 423 MAYBE_UNUSED struct softpipe_context *softpipe = softpipe_context(pipe); 424 struct sp_compute_shader *state = (struct sp_compute_shader *)cs; 425 426 assert(softpipe->cs != state); 427 tgsi_free_tokens(state->tokens); 428 FREE(state); 429 } 430 431 void 432 softpipe_init_shader_funcs(struct pipe_context *pipe) 433 { 434 pipe->create_fs_state = softpipe_create_fs_state; 435 pipe->bind_fs_state = softpipe_bind_fs_state; 436 pipe->delete_fs_state = softpipe_delete_fs_state; 437 438 pipe->create_vs_state = softpipe_create_vs_state; 439 pipe->bind_vs_state = softpipe_bind_vs_state; 440 pipe->delete_vs_state = softpipe_delete_vs_state; 441 442 pipe->create_gs_state = softpipe_create_gs_state; 443 pipe->bind_gs_state = softpipe_bind_gs_state; 444 pipe->delete_gs_state = softpipe_delete_gs_state; 445 446 pipe->set_constant_buffer = softpipe_set_constant_buffer; 447 448 pipe->create_compute_state = softpipe_create_compute_state; 449 pipe->bind_compute_state = softpipe_bind_compute_state; 450 pipe->delete_compute_state = softpipe_delete_compute_state; 451 } 452