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