1 /* 2 * GLSL pixel and vertex shader implementation 3 * 4 * Copyright 2006 Jason Green 5 * Copyright 2006-2007 Henri Verbeet 6 * Copyright 2007-2009, 2013 Stefan Dösinger for CodeWeavers 7 * Copyright 2009-2011 Henri Verbeet for CodeWeavers 8 * 9 * This library is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Lesser General Public 11 * License as published by the Free Software Foundation; either 12 * version 2.1 of the License, or (at your option) any later version. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public 20 * License along with this library; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 22 */ 23 24 /* 25 * D3D shader asm has swizzles on source parameters, and write masks for 26 * destination parameters. GLSL uses swizzles for both. The result of this is 27 * that for example "mov dst.xw, src.zyxw" becomes "dst.xw = src.zw" in GLSL. 28 * Ie, to generate a proper GLSL source swizzle, we need to take the D3D write 29 * mask for the destination parameter into account. 30 */ 31 32 #include "config.h" 33 #include "wine/port.h" 34 35 #include <limits.h> 36 #include <stdio.h> 37 #ifdef HAVE_FLOAT_H 38 # include <float.h> 39 #endif 40 41 #include "wined3d_private.h" 42 43 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader); 44 WINE_DECLARE_DEBUG_CHANNEL(d3d); 45 WINE_DECLARE_DEBUG_CHANNEL(winediag); 46 47 #define WINED3D_GLSL_SAMPLE_PROJECTED 0x01 48 #define WINED3D_GLSL_SAMPLE_LOD 0x02 49 #define WINED3D_GLSL_SAMPLE_GRAD 0x04 50 #define WINED3D_GLSL_SAMPLE_LOAD 0x08 51 #define WINED3D_GLSL_SAMPLE_OFFSET 0x10 52 53 static const struct 54 { 55 unsigned int coord_size; 56 unsigned int resinfo_size; 57 const char *type_part; 58 } 59 resource_type_info[] = 60 { 61 {0, 0, ""}, /* WINED3D_SHADER_RESOURCE_NONE */ 62 {1, 1, "Buffer"}, /* WINED3D_SHADER_RESOURCE_BUFFER */ 63 {1, 1, "1D"}, /* WINED3D_SHADER_RESOURCE_TEXTURE_1D */ 64 {2, 2, "2D"}, /* WINED3D_SHADER_RESOURCE_TEXTURE_2D */ 65 {2, 2, ""}, /* WINED3D_SHADER_RESOURCE_TEXTURE_2DMS */ 66 {3, 3, "3D"}, /* WINED3D_SHADER_RESOURCE_TEXTURE_3D */ 67 {3, 2, "Cube"}, /* WINED3D_SHADER_RESOURCE_TEXTURE_CUBE */ 68 {2, 2, ""}, /* WINED3D_SHADER_RESOURCE_TEXTURE_1DARRAY */ 69 {3, 3, "2DArray"}, /* WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY */ 70 {3, 3, ""}, /* WINED3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY */ 71 {4, 3, ""}, /* WINED3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY */ 72 }; 73 74 struct glsl_dst_param 75 { 76 char reg_name[150]; 77 char mask_str[6]; 78 }; 79 80 struct glsl_src_param 81 { 82 char reg_name[150]; 83 char param_str[200]; 84 }; 85 86 struct glsl_sample_function 87 { 88 struct wined3d_string_buffer *name; 89 unsigned int coord_mask; 90 unsigned int deriv_mask; 91 enum wined3d_data_type data_type; 92 BOOL output_single_component; 93 unsigned int offset_size; 94 enum wined3d_shader_resource_type emulate_lod; 95 }; 96 97 enum heap_node_op 98 { 99 HEAP_NODE_TRAVERSE_LEFT, 100 HEAP_NODE_TRAVERSE_RIGHT, 101 HEAP_NODE_POP, 102 }; 103 104 struct constant_entry 105 { 106 unsigned int idx; 107 unsigned int version; 108 }; 109 110 struct constant_heap 111 { 112 struct constant_entry *entries; 113 BOOL *contained; 114 unsigned int *positions; 115 unsigned int size; 116 }; 117 118 /* GLSL shader private data */ 119 struct shader_glsl_priv 120 { 121 struct wined3d_string_buffer shader_buffer; 122 struct wined3d_string_buffer_list string_buffers; 123 struct wine_rb_tree program_lookup; 124 struct constant_heap vconst_heap; 125 struct constant_heap pconst_heap; 126 unsigned char *stack; 127 UINT next_constant_version; 128 129 const struct wined3d_vertex_pipe_ops *vertex_pipe; 130 const struct fragment_pipeline *fragment_pipe; 131 struct wine_rb_tree ffp_vertex_shaders; 132 struct wine_rb_tree ffp_fragment_shaders; 133 BOOL ffp_proj_control; 134 BOOL legacy_lighting; 135 }; 136 137 struct glsl_vs_program 138 { 139 struct list shader_entry; 140 GLuint id; 141 GLenum vertex_color_clamp; 142 GLint uniform_f_locations[WINED3D_MAX_VS_CONSTS_F]; 143 GLint uniform_i_locations[WINED3D_MAX_CONSTS_I]; 144 GLint uniform_b_locations[WINED3D_MAX_CONSTS_B]; 145 GLint pos_fixup_location; 146 147 GLint modelview_matrix_location[MAX_VERTEX_INDEX_BLENDS]; 148 GLint normal_matrix_location[MAX_VERTEX_INDEX_BLENDS]; 149 GLint projection_matrix_location; 150 GLint texture_matrix_location[MAX_TEXTURES]; 151 GLint material_ambient_location; 152 GLint material_diffuse_location; 153 GLint material_specular_location; 154 GLint material_emissive_location; 155 GLint material_shininess_location; 156 GLint light_ambient_location; 157 struct 158 { 159 GLint diffuse; 160 GLint specular; 161 GLint ambient; 162 GLint position; 163 GLint direction; 164 GLint range; 165 GLint falloff; 166 GLint c_att; 167 GLint l_att; 168 GLint q_att; 169 GLint cos_htheta; 170 GLint cos_hphi; 171 } light_location[MAX_ACTIVE_LIGHTS]; 172 GLint pointsize_location; 173 GLint pointsize_min_location; 174 GLint pointsize_max_location; 175 GLint pointsize_c_att_location; 176 GLint pointsize_l_att_location; 177 GLint pointsize_q_att_location; 178 GLint clip_planes_location; 179 }; 180 181 struct glsl_hs_program 182 { 183 struct list shader_entry; 184 GLuint id; 185 }; 186 187 struct glsl_ds_program 188 { 189 struct list shader_entry; 190 GLuint id; 191 192 GLint pos_fixup_location; 193 }; 194 195 struct glsl_gs_program 196 { 197 struct list shader_entry; 198 GLuint id; 199 200 GLint pos_fixup_location; 201 }; 202 203 struct glsl_ps_program 204 { 205 struct list shader_entry; 206 GLuint id; 207 GLint uniform_f_locations[WINED3D_MAX_PS_CONSTS_F]; 208 GLint uniform_i_locations[WINED3D_MAX_CONSTS_I]; 209 GLint uniform_b_locations[WINED3D_MAX_CONSTS_B]; 210 GLint bumpenv_mat_location[MAX_TEXTURES]; 211 GLint bumpenv_lum_scale_location[MAX_TEXTURES]; 212 GLint bumpenv_lum_offset_location[MAX_TEXTURES]; 213 GLint tss_constant_location[MAX_TEXTURES]; 214 GLint tex_factor_location; 215 GLint specular_enable_location; 216 GLint fog_color_location; 217 GLint fog_density_location; 218 GLint fog_end_location; 219 GLint fog_scale_location; 220 GLint alpha_test_ref_location; 221 GLint ycorrection_location; 222 GLint np2_fixup_location; 223 GLint color_key_location; 224 const struct ps_np2fixup_info *np2_fixup_info; 225 }; 226 227 struct glsl_cs_program 228 { 229 struct list shader_entry; 230 GLuint id; 231 }; 232 233 /* Struct to maintain data about a linked GLSL program */ 234 struct glsl_shader_prog_link 235 { 236 struct wine_rb_entry program_lookup_entry; 237 struct glsl_vs_program vs; 238 struct glsl_hs_program hs; 239 struct glsl_ds_program ds; 240 struct glsl_gs_program gs; 241 struct glsl_ps_program ps; 242 struct glsl_cs_program cs; 243 GLuint id; 244 DWORD constant_update_mask; 245 unsigned int constant_version; 246 DWORD shader_controlled_clip_distances : 1; 247 DWORD clip_distance_mask : 8; /* MAX_CLIP_DISTANCES, 8 */ 248 DWORD padding : 23; 249 }; 250 251 struct glsl_program_key 252 { 253 GLuint vs_id; 254 GLuint hs_id; 255 GLuint ds_id; 256 GLuint gs_id; 257 GLuint ps_id; 258 GLuint cs_id; 259 }; 260 261 struct shader_glsl_ctx_priv { 262 const struct vs_compile_args *cur_vs_args; 263 const struct ds_compile_args *cur_ds_args; 264 const struct ps_compile_args *cur_ps_args; 265 struct ps_np2fixup_info *cur_np2fixup_info; 266 struct wined3d_string_buffer_list *string_buffers; 267 }; 268 269 struct glsl_context_data 270 { 271 struct glsl_shader_prog_link *glsl_program; 272 GLenum vertex_color_clamp; 273 BOOL rasterization_disabled; 274 }; 275 276 struct glsl_ps_compiled_shader 277 { 278 struct ps_compile_args args; 279 struct ps_np2fixup_info np2fixup; 280 GLuint id; 281 }; 282 283 struct glsl_vs_compiled_shader 284 { 285 struct vs_compile_args args; 286 GLuint id; 287 }; 288 289 struct glsl_hs_compiled_shader 290 { 291 GLuint id; 292 }; 293 294 struct glsl_ds_compiled_shader 295 { 296 struct ds_compile_args args; 297 GLuint id; 298 }; 299 300 struct glsl_gs_compiled_shader 301 { 302 struct gs_compile_args args; 303 GLuint id; 304 }; 305 306 struct glsl_cs_compiled_shader 307 { 308 GLuint id; 309 }; 310 311 struct glsl_shader_private 312 { 313 union 314 { 315 struct glsl_vs_compiled_shader *vs; 316 struct glsl_hs_compiled_shader *hs; 317 struct glsl_ds_compiled_shader *ds; 318 struct glsl_gs_compiled_shader *gs; 319 struct glsl_ps_compiled_shader *ps; 320 struct glsl_cs_compiled_shader *cs; 321 } gl_shaders; 322 unsigned int num_gl_shaders, shader_array_size; 323 }; 324 325 struct glsl_ffp_vertex_shader 326 { 327 struct wined3d_ffp_vs_desc desc; 328 GLuint id; 329 struct list linked_programs; 330 }; 331 332 struct glsl_ffp_fragment_shader 333 { 334 struct ffp_frag_desc entry; 335 GLuint id; 336 struct list linked_programs; 337 }; 338 339 struct glsl_ffp_destroy_ctx 340 { 341 struct shader_glsl_priv *priv; 342 const struct wined3d_gl_info *gl_info; 343 }; 344 345 static void shader_glsl_generate_shader_epilogue(const struct wined3d_shader_context *ctx); 346 347 static const char *debug_gl_shader_type(GLenum type) 348 { 349 switch (type) 350 { 351 #define WINED3D_TO_STR(u) case u: return #u 352 WINED3D_TO_STR(GL_VERTEX_SHADER); 353 WINED3D_TO_STR(GL_TESS_CONTROL_SHADER); 354 WINED3D_TO_STR(GL_TESS_EVALUATION_SHADER); 355 WINED3D_TO_STR(GL_GEOMETRY_SHADER); 356 WINED3D_TO_STR(GL_FRAGMENT_SHADER); 357 WINED3D_TO_STR(GL_COMPUTE_SHADER); 358 #undef WINED3D_TO_STR 359 default: 360 return wine_dbg_sprintf("UNKNOWN(%#x)", type); 361 } 362 } 363 364 static const char *shader_glsl_get_prefix(enum wined3d_shader_type type) 365 { 366 switch (type) 367 { 368 case WINED3D_SHADER_TYPE_VERTEX: 369 return "vs"; 370 371 case WINED3D_SHADER_TYPE_HULL: 372 return "hs"; 373 374 case WINED3D_SHADER_TYPE_DOMAIN: 375 return "ds"; 376 377 case WINED3D_SHADER_TYPE_GEOMETRY: 378 return "gs"; 379 380 case WINED3D_SHADER_TYPE_PIXEL: 381 return "ps"; 382 383 case WINED3D_SHADER_TYPE_COMPUTE: 384 return "cs"; 385 386 default: 387 FIXME("Unhandled shader type %#x.\n", type); 388 return "unknown"; 389 } 390 } 391 392 static unsigned int shader_glsl_get_version(const struct wined3d_gl_info *gl_info) 393 { 394 if (gl_info->glsl_version >= MAKEDWORD_VERSION(4, 40)) 395 return 440; 396 else if (gl_info->glsl_version >= MAKEDWORD_VERSION(1, 50)) 397 return 150; 398 else if (gl_info->glsl_version >= MAKEDWORD_VERSION(1, 30)) 399 return 130; 400 else 401 return 120; 402 } 403 404 static void shader_glsl_add_version_declaration(struct wined3d_string_buffer *buffer, 405 const struct wined3d_gl_info *gl_info) 406 { 407 shader_addline(buffer, "#version %u\n", shader_glsl_get_version(gl_info)); 408 } 409 410 static void shader_glsl_append_imm_vec4(struct wined3d_string_buffer *buffer, const float *values) 411 { 412 char str[4][17]; 413 414 wined3d_ftoa(values[0], str[0]); 415 wined3d_ftoa(values[1], str[1]); 416 wined3d_ftoa(values[2], str[2]); 417 wined3d_ftoa(values[3], str[3]); 418 shader_addline(buffer, "vec4(%s, %s, %s, %s)", str[0], str[1], str[2], str[3]); 419 } 420 421 static void shader_glsl_append_imm_ivec(struct wined3d_string_buffer *buffer, 422 const int *values, unsigned int size) 423 { 424 int i; 425 426 if (!size || size > 4) 427 { 428 ERR("Invalid vector size %u.\n", size); 429 return; 430 } 431 432 if (size > 1) 433 shader_addline(buffer, "ivec%u(", size); 434 435 for (i = 0; i < size; ++i) 436 shader_addline(buffer, i ? ", %#x" : "%#x", values[i]); 437 438 if (size > 1) 439 shader_addline(buffer, ")"); 440 } 441 442 static const char *get_info_log_line(const char **ptr) 443 { 444 const char *p, *q; 445 446 p = *ptr; 447 if (!(q = strstr(p, "\n"))) 448 { 449 if (!*p) return NULL; 450 *ptr += strlen(p); 451 return p; 452 } 453 *ptr = q + 1; 454 455 return p; 456 } 457 458 /* Context activation is done by the caller. */ 459 void print_glsl_info_log(const struct wined3d_gl_info *gl_info, GLuint id, BOOL program) 460 { 461 int length = 0; 462 char *log; 463 464 if (!WARN_ON(d3d_shader) && !FIXME_ON(d3d_shader)) 465 return; 466 467 if (program) 468 GL_EXTCALL(glGetProgramiv(id, GL_INFO_LOG_LENGTH, &length)); 469 else 470 GL_EXTCALL(glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length)); 471 472 /* A size of 1 is just a null-terminated string, so the log should be bigger than 473 * that if there are errors. */ 474 if (length > 1) 475 { 476 const char *ptr, *line; 477 478 log = heap_alloc(length); 479 /* The info log is supposed to be zero-terminated, but at least some 480 * versions of fglrx don't terminate the string properly. The reported 481 * length does include the terminator, so explicitly set it to zero 482 * here. */ 483 log[length - 1] = 0; 484 if (program) 485 GL_EXTCALL(glGetProgramInfoLog(id, length, NULL, log)); 486 else 487 GL_EXTCALL(glGetShaderInfoLog(id, length, NULL, log)); 488 489 ptr = log; 490 if (gl_info->quirks & WINED3D_QUIRK_INFO_LOG_SPAM) 491 { 492 WARN("Info log received from GLSL shader #%u:\n", id); 493 while ((line = get_info_log_line(&ptr))) WARN(" %.*s", (int)(ptr - line), line); 494 } 495 else 496 { 497 FIXME("Info log received from GLSL shader #%u:\n", id); 498 while ((line = get_info_log_line(&ptr))) FIXME(" %.*s", (int)(ptr - line), line); 499 } 500 heap_free(log); 501 } 502 } 503 504 /* Context activation is done by the caller. */ 505 static void shader_glsl_compile(const struct wined3d_gl_info *gl_info, GLuint shader, const char *src) 506 { 507 const char *ptr, *line; 508 509 TRACE("Compiling shader object %u.\n", shader); 510 511 if (TRACE_ON(d3d_shader)) 512 { 513 ptr = src; 514 while ((line = get_info_log_line(&ptr))) TRACE_(d3d_shader)(" %.*s", (int)(ptr - line), line); 515 } 516 517 GL_EXTCALL(glShaderSource(shader, 1, &src, NULL)); 518 checkGLcall("glShaderSource"); 519 GL_EXTCALL(glCompileShader(shader)); 520 checkGLcall("glCompileShader"); 521 print_glsl_info_log(gl_info, shader, FALSE); 522 } 523 524 /* Context activation is done by the caller. */ 525 static void shader_glsl_dump_program_source(const struct wined3d_gl_info *gl_info, GLuint program) 526 { 527 GLint i, shader_count, source_size = -1; 528 GLuint *shaders; 529 char *source = NULL; 530 531 GL_EXTCALL(glGetProgramiv(program, GL_ATTACHED_SHADERS, &shader_count)); 532 if (!(shaders = heap_calloc(shader_count, sizeof(*shaders)))) 533 { 534 ERR("Failed to allocate shader array memory.\n"); 535 return; 536 } 537 538 GL_EXTCALL(glGetAttachedShaders(program, shader_count, NULL, shaders)); 539 for (i = 0; i < shader_count; ++i) 540 { 541 const char *ptr, *line; 542 GLint tmp; 543 544 GL_EXTCALL(glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &tmp)); 545 546 if (source_size < tmp) 547 { 548 heap_free(source); 549 550 if (!(source = heap_alloc_zero(tmp))) 551 { 552 ERR("Failed to allocate %d bytes for shader source.\n", tmp); 553 heap_free(shaders); 554 return; 555 } 556 source_size = tmp; 557 } 558 559 FIXME("Shader %u:\n", shaders[i]); 560 GL_EXTCALL(glGetShaderiv(shaders[i], GL_SHADER_TYPE, &tmp)); 561 FIXME(" GL_SHADER_TYPE: %s.\n", debug_gl_shader_type(tmp)); 562 GL_EXTCALL(glGetShaderiv(shaders[i], GL_COMPILE_STATUS, &tmp)); 563 FIXME(" GL_COMPILE_STATUS: %d.\n", tmp); 564 FIXME("\n"); 565 566 ptr = source; 567 GL_EXTCALL(glGetShaderSource(shaders[i], source_size, NULL, source)); 568 while ((line = get_info_log_line(&ptr))) FIXME(" %.*s", (int)(ptr - line), line); 569 FIXME("\n"); 570 } 571 572 heap_free(source); 573 heap_free(shaders); 574 } 575 576 /* Context activation is done by the caller. */ 577 void shader_glsl_validate_link(const struct wined3d_gl_info *gl_info, GLuint program) 578 { 579 GLint tmp; 580 581 if (!TRACE_ON(d3d_shader) && !FIXME_ON(d3d_shader)) 582 return; 583 584 GL_EXTCALL(glGetProgramiv(program, GL_LINK_STATUS, &tmp)); 585 if (!tmp) 586 { 587 FIXME("Program %u link status invalid.\n", program); 588 shader_glsl_dump_program_source(gl_info, program); 589 } 590 591 print_glsl_info_log(gl_info, program, TRUE); 592 } 593 594 static BOOL shader_glsl_use_layout_qualifier(const struct wined3d_gl_info *gl_info) 595 { 596 /* Layout qualifiers were introduced in GLSL 1.40. The Nvidia Legacy GPU 597 * driver (series 340.xx) doesn't parse layout qualifiers in older GLSL 598 * versions. */ 599 return shader_glsl_get_version(gl_info) >= 140; 600 } 601 602 static BOOL shader_glsl_use_layout_binding_qualifier(const struct wined3d_gl_info *gl_info) 603 { 604 return gl_info->supported[ARB_SHADING_LANGUAGE_420PACK] && shader_glsl_use_layout_qualifier(gl_info); 605 } 606 607 static void shader_glsl_init_uniform_block_bindings(const struct wined3d_gl_info *gl_info, 608 struct shader_glsl_priv *priv, GLuint program_id, 609 const struct wined3d_shader_reg_maps *reg_maps) 610 { 611 const char *prefix = shader_glsl_get_prefix(reg_maps->shader_version.type); 612 struct wined3d_string_buffer *name; 613 unsigned int i, base, count; 614 GLuint block_idx; 615 616 if (shader_glsl_use_layout_binding_qualifier(gl_info)) 617 return; 618 619 name = string_buffer_get(&priv->string_buffers); 620 wined3d_gl_limits_get_uniform_block_range(&gl_info->limits, reg_maps->shader_version.type, &base, &count); 621 for (i = 0; i < count; ++i) 622 { 623 if (!reg_maps->cb_sizes[i]) 624 continue; 625 626 string_buffer_sprintf(name, "block_%s_cb%u", prefix, i); 627 block_idx = GL_EXTCALL(glGetUniformBlockIndex(program_id, name->buffer)); 628 GL_EXTCALL(glUniformBlockBinding(program_id, block_idx, base + i)); 629 } 630 checkGLcall("glUniformBlockBinding"); 631 string_buffer_release(&priv->string_buffers, name); 632 } 633 634 /* Context activation is done by the caller. */ 635 static void shader_glsl_load_samplers_range(const struct wined3d_gl_info *gl_info, 636 struct shader_glsl_priv *priv, GLuint program_id, const char *prefix, 637 unsigned int base, unsigned int count, const DWORD *tex_unit_map) 638 { 639 struct wined3d_string_buffer *sampler_name = string_buffer_get(&priv->string_buffers); 640 unsigned int i, mapped_unit; 641 GLint name_loc; 642 643 for (i = 0; i < count; ++i) 644 { 645 string_buffer_sprintf(sampler_name, "%s_sampler%u", prefix, i); 646 name_loc = GL_EXTCALL(glGetUniformLocation(program_id, sampler_name->buffer)); 647 if (name_loc == -1) 648 continue; 649 650 mapped_unit = tex_unit_map ? tex_unit_map[base + i] : base + i; 651 if (mapped_unit == WINED3D_UNMAPPED_STAGE || mapped_unit >= gl_info->limits.combined_samplers) 652 { 653 ERR("Trying to load sampler %s on unsupported unit %u.\n", sampler_name->buffer, mapped_unit); 654 continue; 655 } 656 657 TRACE("Loading sampler %s on unit %u.\n", sampler_name->buffer, mapped_unit); 658 GL_EXTCALL(glUniform1i(name_loc, mapped_unit)); 659 } 660 checkGLcall("Load sampler bindings"); 661 string_buffer_release(&priv->string_buffers, sampler_name); 662 } 663 664 static unsigned int shader_glsl_map_tex_unit(const struct wined3d_context *context, 665 const struct wined3d_shader_version *shader_version, unsigned int sampler_idx) 666 { 667 const DWORD *tex_unit_map; 668 unsigned int base, count; 669 670 tex_unit_map = context_get_tex_unit_mapping(context, shader_version, &base, &count); 671 if (sampler_idx >= count) 672 return WINED3D_UNMAPPED_STAGE; 673 if (!tex_unit_map) 674 return base + sampler_idx; 675 return tex_unit_map[base + sampler_idx]; 676 } 677 678 static void shader_glsl_append_sampler_binding_qualifier(struct wined3d_string_buffer *buffer, 679 const struct wined3d_context *context, const struct wined3d_shader_version *shader_version, 680 unsigned int sampler_idx) 681 { 682 unsigned int mapped_unit = shader_glsl_map_tex_unit(context, shader_version, sampler_idx); 683 if (mapped_unit != WINED3D_UNMAPPED_STAGE) 684 shader_addline(buffer, "layout(binding = %u)\n", mapped_unit); 685 else 686 ERR("Unmapped sampler %u.\n", sampler_idx); 687 } 688 689 /* Context activation is done by the caller. */ 690 static void shader_glsl_load_samplers(const struct wined3d_context *context, 691 struct shader_glsl_priv *priv, GLuint program_id, const struct wined3d_shader_reg_maps *reg_maps) 692 { 693 const struct wined3d_gl_info *gl_info = context->gl_info; 694 const struct wined3d_shader_version *shader_version; 695 const DWORD *tex_unit_map; 696 unsigned int base, count; 697 const char *prefix; 698 699 if (shader_glsl_use_layout_binding_qualifier(gl_info)) 700 return; 701 702 shader_version = reg_maps ? ®_maps->shader_version : NULL; 703 prefix = shader_glsl_get_prefix(shader_version ? shader_version->type : WINED3D_SHADER_TYPE_PIXEL); 704 tex_unit_map = context_get_tex_unit_mapping(context, shader_version, &base, &count); 705 shader_glsl_load_samplers_range(gl_info, priv, program_id, prefix, base, count, tex_unit_map); 706 } 707 708 static void shader_glsl_load_icb(const struct wined3d_gl_info *gl_info, struct shader_glsl_priv *priv, 709 GLuint program_id, const struct wined3d_shader_reg_maps *reg_maps) 710 { 711 const struct wined3d_shader_immediate_constant_buffer *icb = reg_maps->icb; 712 713 if (icb) 714 { 715 struct wined3d_string_buffer *icb_name = string_buffer_get(&priv->string_buffers); 716 const char *prefix = shader_glsl_get_prefix(reg_maps->shader_version.type); 717 GLint icb_location; 718 719 string_buffer_sprintf(icb_name, "%s_icb", prefix); 720 icb_location = GL_EXTCALL(glGetUniformLocation(program_id, icb_name->buffer)); 721 GL_EXTCALL(glUniform4fv(icb_location, icb->vec4_count, (const GLfloat *)icb->data)); 722 checkGLcall("Load immediate constant buffer"); 723 724 string_buffer_release(&priv->string_buffers, icb_name); 725 } 726 } 727 728 /* Context activation is done by the caller. */ 729 static void shader_glsl_load_images(const struct wined3d_gl_info *gl_info, struct shader_glsl_priv *priv, 730 GLuint program_id, const struct wined3d_shader_reg_maps *reg_maps) 731 { 732 const char *prefix = shader_glsl_get_prefix(reg_maps->shader_version.type); 733 struct wined3d_string_buffer *name; 734 GLint location; 735 unsigned int i; 736 737 if (shader_glsl_use_layout_binding_qualifier(gl_info)) 738 return; 739 740 name = string_buffer_get(&priv->string_buffers); 741 for (i = 0; i < MAX_UNORDERED_ACCESS_VIEWS; ++i) 742 { 743 if (!reg_maps->uav_resource_info[i].type) 744 continue; 745 746 string_buffer_sprintf(name, "%s_image%u", prefix, i); 747 location = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 748 if (location == -1) 749 continue; 750 751 TRACE("Loading image %s on unit %u.\n", name->buffer, i); 752 GL_EXTCALL(glUniform1i(location, i)); 753 } 754 checkGLcall("Load image bindings"); 755 string_buffer_release(&priv->string_buffers, name); 756 } 757 758 /* Context activation is done by the caller. */ 759 static void shader_glsl_load_program_resources(const struct wined3d_context *context, 760 struct shader_glsl_priv *priv, GLuint program_id, const struct wined3d_shader *shader) 761 { 762 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; 763 764 shader_glsl_init_uniform_block_bindings(context->gl_info, priv, program_id, reg_maps); 765 shader_glsl_load_icb(context->gl_info, priv, program_id, reg_maps); 766 /* Texture unit mapping is set up to be the same each time the shader 767 * program is used so we can hardcode the sampler uniform values. */ 768 shader_glsl_load_samplers(context, priv, program_id, reg_maps); 769 } 770 771 static void append_transform_feedback_varying(const char **varyings, unsigned int *varying_count, 772 char **strings, unsigned int *strings_length, struct wined3d_string_buffer *buffer) 773 { 774 if (varyings && *strings) 775 { 776 char *ptr = *strings; 777 778 varyings[*varying_count] = ptr; 779 780 memcpy(ptr, buffer->buffer, buffer->content_size + 1); 781 ptr += buffer->content_size + 1; 782 783 *strings = ptr; 784 } 785 786 *strings_length += buffer->content_size + 1; 787 ++(*varying_count); 788 } 789 790 static void append_transform_feedback_skip_components(const char **varyings, 791 unsigned int *varying_count, char **strings, unsigned int *strings_length, 792 struct wined3d_string_buffer *buffer, unsigned int component_count) 793 { 794 unsigned int j; 795 796 for (j = 0; j < component_count / 4; ++j) 797 { 798 string_buffer_sprintf(buffer, "gl_SkipComponents4"); 799 append_transform_feedback_varying(varyings, varying_count, strings, strings_length, buffer); 800 } 801 if (component_count % 4) 802 { 803 string_buffer_sprintf(buffer, "gl_SkipComponents%u", component_count % 4); 804 append_transform_feedback_varying(varyings, varying_count, strings, strings_length, buffer); 805 } 806 } 807 808 static void shader_glsl_generate_transform_feedback_varyings(const struct wined3d_stream_output_desc *so_desc, 809 struct wined3d_string_buffer *buffer, const char **varyings, unsigned int *varying_count, 810 char *strings, unsigned int *strings_length, GLenum buffer_mode) 811 { 812 unsigned int i, buffer_idx, count, length, highest_output_slot, stride; 813 814 count = length = 0; 815 highest_output_slot = 0; 816 for (buffer_idx = 0; buffer_idx < WINED3D_MAX_STREAM_OUTPUT_BUFFERS; ++buffer_idx) 817 { 818 stride = 0; 819 820 for (i = 0; i < so_desc->element_count; ++i) 821 { 822 const struct wined3d_stream_output_element *e = &so_desc->elements[i]; 823 824 highest_output_slot = max(highest_output_slot, e->output_slot); 825 if (e->output_slot != buffer_idx) 826 continue; 827 828 if (e->stream_idx) 829 { 830 FIXME("Unhandled stream %u.\n", e->stream_idx); 831 continue; 832 } 833 834 stride += e->component_count; 835 836 if (e->register_idx == WINED3D_STREAM_OUTPUT_GAP) 837 { 838 append_transform_feedback_skip_components(varyings, &count, 839 &strings, &length, buffer, e->component_count); 840 continue; 841 } 842 843 if (e->component_idx || e->component_count != 4) 844 { 845 if (so_desc->rasterizer_stream_idx != WINED3D_NO_RASTERIZER_STREAM) 846 { 847 FIXME("Unsupported component range %u-%u.\n", e->component_idx, e->component_count); 848 append_transform_feedback_skip_components(varyings, &count, 849 &strings, &length, buffer, e->component_count); 850 continue; 851 } 852 853 string_buffer_sprintf(buffer, "shader_in_out.reg%u_%u_%u", 854 e->register_idx, e->component_idx, e->component_idx + e->component_count - 1); 855 append_transform_feedback_varying(varyings, &count, &strings, &length, buffer); 856 } 857 else 858 { 859 string_buffer_sprintf(buffer, "shader_in_out.reg%u", e->register_idx); 860 append_transform_feedback_varying(varyings, &count, &strings, &length, buffer); 861 } 862 } 863 864 if (buffer_idx < so_desc->buffer_stride_count 865 && stride < so_desc->buffer_strides[buffer_idx] / 4) 866 { 867 unsigned int component_count = so_desc->buffer_strides[buffer_idx] / 4 - stride; 868 append_transform_feedback_skip_components(varyings, &count, 869 &strings, &length, buffer, component_count); 870 } 871 872 if (highest_output_slot <= buffer_idx) 873 break; 874 875 if (buffer_mode == GL_INTERLEAVED_ATTRIBS) 876 { 877 string_buffer_sprintf(buffer, "gl_NextBuffer"); 878 append_transform_feedback_varying(varyings, &count, &strings, &length, buffer); 879 } 880 } 881 882 if (varying_count) 883 *varying_count = count; 884 if (strings_length) 885 *strings_length = length; 886 } 887 888 static void shader_glsl_init_transform_feedback(const struct wined3d_context *context, 889 struct shader_glsl_priv *priv, GLuint program_id, const struct wined3d_shader *shader) 890 { 891 const struct wined3d_stream_output_desc *so_desc = &shader->u.gs.so_desc; 892 const struct wined3d_gl_info *gl_info = context->gl_info; 893 struct wined3d_string_buffer *buffer; 894 unsigned int i, count, length; 895 const char **varyings; 896 char *strings; 897 GLenum mode; 898 899 if (!so_desc->element_count) 900 return; 901 902 if (gl_info->supported[ARB_TRANSFORM_FEEDBACK3]) 903 { 904 mode = GL_INTERLEAVED_ATTRIBS; 905 } 906 else 907 { 908 unsigned int element_count[WINED3D_MAX_STREAM_OUTPUT_BUFFERS] = {0}; 909 910 for (i = 0; i < so_desc->element_count; ++i) 911 { 912 if (so_desc->elements[i].register_idx == WINED3D_STREAM_OUTPUT_GAP) 913 { 914 FIXME("ARB_transform_feedback3 is needed for stream output gaps.\n"); 915 return; 916 } 917 ++element_count[so_desc->elements[i].output_slot]; 918 } 919 920 if (element_count[0] == so_desc->element_count) 921 { 922 mode = GL_INTERLEAVED_ATTRIBS; 923 } 924 else 925 { 926 mode = GL_SEPARATE_ATTRIBS; 927 for (i = 0; i < ARRAY_SIZE(element_count); ++i) 928 { 929 if (element_count[i] != 1) 930 break; 931 } 932 for (; i < ARRAY_SIZE(element_count); ++i) 933 { 934 if (element_count[i]) 935 { 936 FIXME("Only single element per buffer is allowed in separate mode.\n"); 937 return; 938 } 939 } 940 } 941 } 942 943 buffer = string_buffer_get(&priv->string_buffers); 944 945 shader_glsl_generate_transform_feedback_varyings(so_desc, buffer, NULL, &count, NULL, &length, mode); 946 947 if (!(varyings = heap_calloc(count, sizeof(*varyings)))) 948 { 949 ERR("Out of memory.\n"); 950 string_buffer_release(&priv->string_buffers, buffer); 951 return; 952 } 953 if (!(strings = heap_calloc(length, sizeof(*strings)))) 954 { 955 ERR("Out of memory.\n"); 956 heap_free(varyings); 957 string_buffer_release(&priv->string_buffers, buffer); 958 return; 959 } 960 961 shader_glsl_generate_transform_feedback_varyings(so_desc, buffer, varyings, NULL, strings, NULL, mode); 962 GL_EXTCALL(glTransformFeedbackVaryings(program_id, count, varyings, mode)); 963 checkGLcall("glTransformFeedbackVaryings"); 964 965 heap_free(varyings); 966 heap_free(strings); 967 string_buffer_release(&priv->string_buffers, buffer); 968 } 969 970 /* Context activation is done by the caller. */ 971 static inline void walk_constant_heap(const struct wined3d_gl_info *gl_info, const struct wined3d_vec4 *constants, 972 const GLint *constant_locations, const struct constant_heap *heap, unsigned char *stack, DWORD version) 973 { 974 unsigned int start = ~0U, end = 0; 975 int stack_idx = 0; 976 unsigned int heap_idx = 1; 977 unsigned int idx; 978 979 if (heap->entries[heap_idx].version <= version) return; 980 981 idx = heap->entries[heap_idx].idx; 982 if (constant_locations[idx] != -1) 983 start = end = idx; 984 stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; 985 986 while (stack_idx >= 0) 987 { 988 /* Note that we fall through to the next case statement. */ 989 switch(stack[stack_idx]) 990 { 991 case HEAP_NODE_TRAVERSE_LEFT: 992 { 993 unsigned int left_idx = heap_idx << 1; 994 if (left_idx < heap->size && heap->entries[left_idx].version > version) 995 { 996 heap_idx = left_idx; 997 idx = heap->entries[heap_idx].idx; 998 if (constant_locations[idx] != -1) 999 { 1000 if (start > idx) 1001 start = idx; 1002 if (end < idx) 1003 end = idx; 1004 } 1005 1006 stack[stack_idx++] = HEAP_NODE_TRAVERSE_RIGHT; 1007 stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; 1008 break; 1009 } 1010 } 1011 1012 case HEAP_NODE_TRAVERSE_RIGHT: 1013 { 1014 unsigned int right_idx = (heap_idx << 1) + 1; 1015 if (right_idx < heap->size && heap->entries[right_idx].version > version) 1016 { 1017 heap_idx = right_idx; 1018 idx = heap->entries[heap_idx].idx; 1019 if (constant_locations[idx] != -1) 1020 { 1021 if (start > idx) 1022 start = idx; 1023 if (end < idx) 1024 end = idx; 1025 } 1026 1027 stack[stack_idx++] = HEAP_NODE_POP; 1028 stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; 1029 break; 1030 } 1031 } 1032 1033 case HEAP_NODE_POP: 1034 heap_idx >>= 1; 1035 --stack_idx; 1036 break; 1037 } 1038 } 1039 if (start <= end) 1040 GL_EXTCALL(glUniform4fv(constant_locations[start], end - start + 1, &constants[start].x)); 1041 checkGLcall("walk_constant_heap()"); 1042 } 1043 1044 /* Context activation is done by the caller. */ 1045 static inline void apply_clamped_constant(const struct wined3d_gl_info *gl_info, 1046 GLint location, const struct wined3d_vec4 *data) 1047 { 1048 GLfloat clamped_constant[4]; 1049 1050 if (location == -1) return; 1051 1052 clamped_constant[0] = data->x < -1.0f ? -1.0f : data->x > 1.0f ? 1.0f : data->x; 1053 clamped_constant[1] = data->y < -1.0f ? -1.0f : data->y > 1.0f ? 1.0f : data->y; 1054 clamped_constant[2] = data->z < -1.0f ? -1.0f : data->z > 1.0f ? 1.0f : data->z; 1055 clamped_constant[3] = data->w < -1.0f ? -1.0f : data->w > 1.0f ? 1.0f : data->w; 1056 1057 GL_EXTCALL(glUniform4fv(location, 1, clamped_constant)); 1058 } 1059 1060 /* Context activation is done by the caller. */ 1061 static inline void walk_constant_heap_clamped(const struct wined3d_gl_info *gl_info, 1062 const struct wined3d_vec4 *constants, const GLint *constant_locations, 1063 const struct constant_heap *heap, unsigned char *stack, DWORD version) 1064 { 1065 int stack_idx = 0; 1066 unsigned int heap_idx = 1; 1067 unsigned int idx; 1068 1069 if (heap->entries[heap_idx].version <= version) return; 1070 1071 idx = heap->entries[heap_idx].idx; 1072 apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx]); 1073 stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; 1074 1075 while (stack_idx >= 0) 1076 { 1077 /* Note that we fall through to the next case statement. */ 1078 switch(stack[stack_idx]) 1079 { 1080 case HEAP_NODE_TRAVERSE_LEFT: 1081 { 1082 unsigned int left_idx = heap_idx << 1; 1083 if (left_idx < heap->size && heap->entries[left_idx].version > version) 1084 { 1085 heap_idx = left_idx; 1086 idx = heap->entries[heap_idx].idx; 1087 apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx]); 1088 1089 stack[stack_idx++] = HEAP_NODE_TRAVERSE_RIGHT; 1090 stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; 1091 break; 1092 } 1093 } 1094 1095 case HEAP_NODE_TRAVERSE_RIGHT: 1096 { 1097 unsigned int right_idx = (heap_idx << 1) + 1; 1098 if (right_idx < heap->size && heap->entries[right_idx].version > version) 1099 { 1100 heap_idx = right_idx; 1101 idx = heap->entries[heap_idx].idx; 1102 apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx]); 1103 1104 stack[stack_idx++] = HEAP_NODE_POP; 1105 stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; 1106 break; 1107 } 1108 } 1109 1110 case HEAP_NODE_POP: 1111 heap_idx >>= 1; 1112 --stack_idx; 1113 break; 1114 } 1115 } 1116 checkGLcall("walk_constant_heap_clamped()"); 1117 } 1118 1119 /* Context activation is done by the caller. */ 1120 static void shader_glsl_load_constants_f(const struct wined3d_shader *shader, const struct wined3d_gl_info *gl_info, 1121 const struct wined3d_vec4 *constants, const GLint *constant_locations, const struct constant_heap *heap, 1122 unsigned char *stack, unsigned int version) 1123 { 1124 const struct wined3d_shader_lconst *lconst; 1125 1126 /* 1.X pshaders have the constants clamped to [-1;1] implicitly. */ 1127 if (shader->reg_maps.shader_version.major == 1 1128 && shader->reg_maps.shader_version.type == WINED3D_SHADER_TYPE_PIXEL) 1129 walk_constant_heap_clamped(gl_info, constants, constant_locations, heap, stack, version); 1130 else 1131 walk_constant_heap(gl_info, constants, constant_locations, heap, stack, version); 1132 1133 if (!shader->load_local_constsF) 1134 { 1135 TRACE("No need to load local float constants for this shader.\n"); 1136 return; 1137 } 1138 1139 /* Immediate constants are clamped to [-1;1] at shader creation time if needed */ 1140 LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry) 1141 { 1142 GL_EXTCALL(glUniform4fv(constant_locations[lconst->idx], 1, (const GLfloat *)lconst->value)); 1143 } 1144 checkGLcall("glUniform4fv()"); 1145 } 1146 1147 /* Context activation is done by the caller. */ 1148 static void shader_glsl_load_constants_i(const struct wined3d_shader *shader, const struct wined3d_gl_info *gl_info, 1149 const struct wined3d_ivec4 *constants, const GLint locations[WINED3D_MAX_CONSTS_I], WORD constants_set) 1150 { 1151 unsigned int i; 1152 struct list* ptr; 1153 1154 for (i = 0; constants_set; constants_set >>= 1, ++i) 1155 { 1156 if (!(constants_set & 1)) continue; 1157 1158 /* We found this uniform name in the program - go ahead and send the data */ 1159 GL_EXTCALL(glUniform4iv(locations[i], 1, &constants[i].x)); 1160 } 1161 1162 /* Load immediate constants */ 1163 ptr = list_head(&shader->constantsI); 1164 while (ptr) 1165 { 1166 const struct wined3d_shader_lconst *lconst = LIST_ENTRY(ptr, const struct wined3d_shader_lconst, entry); 1167 unsigned int idx = lconst->idx; 1168 const GLint *values = (const GLint *)lconst->value; 1169 1170 /* We found this uniform name in the program - go ahead and send the data */ 1171 GL_EXTCALL(glUniform4iv(locations[idx], 1, values)); 1172 ptr = list_next(&shader->constantsI, ptr); 1173 } 1174 checkGLcall("glUniform4iv()"); 1175 } 1176 1177 /* Context activation is done by the caller. */ 1178 static void shader_glsl_load_constantsB(const struct wined3d_shader *shader, const struct wined3d_gl_info *gl_info, 1179 const GLint locations[WINED3D_MAX_CONSTS_B], const BOOL *constants, WORD constants_set) 1180 { 1181 unsigned int i; 1182 struct list* ptr; 1183 1184 for (i = 0; constants_set; constants_set >>= 1, ++i) 1185 { 1186 if (!(constants_set & 1)) continue; 1187 1188 GL_EXTCALL(glUniform1iv(locations[i], 1, &constants[i])); 1189 } 1190 1191 /* Load immediate constants */ 1192 ptr = list_head(&shader->constantsB); 1193 while (ptr) 1194 { 1195 const struct wined3d_shader_lconst *lconst = LIST_ENTRY(ptr, const struct wined3d_shader_lconst, entry); 1196 unsigned int idx = lconst->idx; 1197 const GLint *values = (const GLint *)lconst->value; 1198 1199 GL_EXTCALL(glUniform1iv(locations[idx], 1, values)); 1200 ptr = list_next(&shader->constantsB, ptr); 1201 } 1202 checkGLcall("glUniform1iv()"); 1203 } 1204 1205 static void reset_program_constant_version(struct wine_rb_entry *entry, void *context) 1206 { 1207 WINE_RB_ENTRY_VALUE(entry, struct glsl_shader_prog_link, program_lookup_entry)->constant_version = 0; 1208 } 1209 1210 /* Context activation is done by the caller (state handler). */ 1211 static void shader_glsl_load_np2fixup_constants(const struct glsl_ps_program *ps, 1212 const struct wined3d_gl_info *gl_info, const struct wined3d_state *state) 1213 { 1214 struct 1215 { 1216 float sx, sy; 1217 } 1218 np2fixup_constants[MAX_FRAGMENT_SAMPLERS]; 1219 UINT fixup = ps->np2_fixup_info->active; 1220 UINT i; 1221 1222 for (i = 0; fixup; fixup >>= 1, ++i) 1223 { 1224 const struct wined3d_texture *tex = state->textures[i]; 1225 unsigned char idx = ps->np2_fixup_info->idx[i]; 1226 1227 if (!tex) 1228 { 1229 ERR("Nonexistent texture is flagged for NP2 texcoord fixup.\n"); 1230 continue; 1231 } 1232 1233 np2fixup_constants[idx].sx = tex->pow2_matrix[0]; 1234 np2fixup_constants[idx].sy = tex->pow2_matrix[5]; 1235 } 1236 1237 GL_EXTCALL(glUniform4fv(ps->np2_fixup_location, ps->np2_fixup_info->num_consts, &np2fixup_constants[0].sx)); 1238 } 1239 1240 static void shader_glsl_ffp_vertex_texmatrix_uniform(const struct wined3d_context *context, 1241 const struct wined3d_state *state, unsigned int tex, struct glsl_shader_prog_link *prog) 1242 { 1243 const struct wined3d_gl_info *gl_info = context->gl_info; 1244 struct wined3d_matrix mat; 1245 1246 if (tex >= MAX_TEXTURES) 1247 return; 1248 if (prog->vs.texture_matrix_location[tex] == -1) 1249 return; 1250 1251 get_texture_matrix(context, state, tex, &mat); 1252 GL_EXTCALL(glUniformMatrix4fv(prog->vs.texture_matrix_location[tex], 1, FALSE, &mat._11)); 1253 checkGLcall("glUniformMatrix4fv"); 1254 } 1255 1256 static void shader_glsl_ffp_vertex_material_uniform(const struct wined3d_context *context, 1257 const struct wined3d_state *state, struct glsl_shader_prog_link *prog) 1258 { 1259 const struct wined3d_gl_info *gl_info = context->gl_info; 1260 1261 if (state->render_states[WINED3D_RS_SPECULARENABLE]) 1262 { 1263 GL_EXTCALL(glUniform4fv(prog->vs.material_specular_location, 1, &state->material.specular.r)); 1264 GL_EXTCALL(glUniform1f(prog->vs.material_shininess_location, state->material.power)); 1265 } 1266 else 1267 { 1268 static const float black[] = {0.0f, 0.0f, 0.0f, 0.0f}; 1269 1270 GL_EXTCALL(glUniform4fv(prog->vs.material_specular_location, 1, black)); 1271 } 1272 GL_EXTCALL(glUniform4fv(prog->vs.material_ambient_location, 1, &state->material.ambient.r)); 1273 GL_EXTCALL(glUniform4fv(prog->vs.material_diffuse_location, 1, &state->material.diffuse.r)); 1274 GL_EXTCALL(glUniform4fv(prog->vs.material_emissive_location, 1, &state->material.emissive.r)); 1275 checkGLcall("setting FFP material uniforms"); 1276 } 1277 1278 static void shader_glsl_ffp_vertex_lightambient_uniform(const struct wined3d_context *context, 1279 const struct wined3d_state *state, struct glsl_shader_prog_link *prog) 1280 { 1281 const struct wined3d_gl_info *gl_info = context->gl_info; 1282 struct wined3d_color color; 1283 1284 wined3d_color_from_d3dcolor(&color, state->render_states[WINED3D_RS_AMBIENT]); 1285 GL_EXTCALL(glUniform3fv(prog->vs.light_ambient_location, 1, &color.r)); 1286 checkGLcall("glUniform3fv"); 1287 } 1288 1289 static void multiply_vector_matrix(struct wined3d_vec4 *dest, const struct wined3d_vec4 *src1, 1290 const struct wined3d_matrix *src2) 1291 { 1292 struct wined3d_vec4 temp; 1293 1294 temp.x = (src1->x * src2->_11) + (src1->y * src2->_21) + (src1->z * src2->_31) + (src1->w * src2->_41); 1295 temp.y = (src1->x * src2->_12) + (src1->y * src2->_22) + (src1->z * src2->_32) + (src1->w * src2->_42); 1296 temp.z = (src1->x * src2->_13) + (src1->y * src2->_23) + (src1->z * src2->_33) + (src1->w * src2->_43); 1297 temp.w = (src1->x * src2->_14) + (src1->y * src2->_24) + (src1->z * src2->_34) + (src1->w * src2->_44); 1298 1299 *dest = temp; 1300 } 1301 1302 static void shader_glsl_ffp_vertex_light_uniform(const struct wined3d_context *context, 1303 const struct wined3d_state *state, unsigned int light, const struct wined3d_light_info *light_info, 1304 struct glsl_shader_prog_link *prog) 1305 { 1306 const struct wined3d_matrix *view = &state->transforms[WINED3D_TS_VIEW]; 1307 const struct wined3d_gl_info *gl_info = context->gl_info; 1308 struct wined3d_vec4 vec4; 1309 1310 GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].diffuse, 1, &light_info->OriginalParms.diffuse.r)); 1311 GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].specular, 1, &light_info->OriginalParms.specular.r)); 1312 GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].ambient, 1, &light_info->OriginalParms.ambient.r)); 1313 1314 switch (light_info->OriginalParms.type) 1315 { 1316 case WINED3D_LIGHT_POINT: 1317 multiply_vector_matrix(&vec4, &light_info->position, view); 1318 GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].position, 1, &vec4.x)); 1319 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].range, light_info->OriginalParms.range)); 1320 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].c_att, light_info->OriginalParms.attenuation0)); 1321 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].l_att, light_info->OriginalParms.attenuation1)); 1322 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].q_att, light_info->OriginalParms.attenuation2)); 1323 break; 1324 1325 case WINED3D_LIGHT_SPOT: 1326 multiply_vector_matrix(&vec4, &light_info->position, view); 1327 GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].position, 1, &vec4.x)); 1328 1329 multiply_vector_matrix(&vec4, &light_info->direction, view); 1330 GL_EXTCALL(glUniform3fv(prog->vs.light_location[light].direction, 1, &vec4.x)); 1331 1332 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].range, light_info->OriginalParms.range)); 1333 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].falloff, light_info->OriginalParms.falloff)); 1334 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].c_att, light_info->OriginalParms.attenuation0)); 1335 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].l_att, light_info->OriginalParms.attenuation1)); 1336 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].q_att, light_info->OriginalParms.attenuation2)); 1337 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].cos_htheta, cosf(light_info->OriginalParms.theta / 2.0f))); 1338 GL_EXTCALL(glUniform1f(prog->vs.light_location[light].cos_hphi, cosf(light_info->OriginalParms.phi / 2.0f))); 1339 break; 1340 1341 case WINED3D_LIGHT_DIRECTIONAL: 1342 multiply_vector_matrix(&vec4, &light_info->direction, view); 1343 GL_EXTCALL(glUniform3fv(prog->vs.light_location[light].direction, 1, &vec4.x)); 1344 break; 1345 1346 case WINED3D_LIGHT_PARALLELPOINT: 1347 multiply_vector_matrix(&vec4, &light_info->position, view); 1348 GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].position, 1, &vec4.x)); 1349 break; 1350 1351 default: 1352 FIXME("Unrecognized light type %#x.\n", light_info->OriginalParms.type); 1353 } 1354 checkGLcall("setting FFP lights uniforms"); 1355 } 1356 1357 static void shader_glsl_pointsize_uniform(const struct wined3d_context *context, 1358 const struct wined3d_state *state, struct glsl_shader_prog_link *prog) 1359 { 1360 const struct wined3d_gl_info *gl_info = context->gl_info; 1361 float min, max; 1362 float size, att[3]; 1363 1364 get_pointsize_minmax(context, state, &min, &max); 1365 1366 GL_EXTCALL(glUniform1f(prog->vs.pointsize_min_location, min)); 1367 checkGLcall("glUniform1f"); 1368 GL_EXTCALL(glUniform1f(prog->vs.pointsize_max_location, max)); 1369 checkGLcall("glUniform1f"); 1370 1371 get_pointsize(context, state, &size, att); 1372 1373 GL_EXTCALL(glUniform1f(prog->vs.pointsize_location, size)); 1374 checkGLcall("glUniform1f"); 1375 GL_EXTCALL(glUniform1f(prog->vs.pointsize_c_att_location, att[0])); 1376 checkGLcall("glUniform1f"); 1377 GL_EXTCALL(glUniform1f(prog->vs.pointsize_l_att_location, att[1])); 1378 checkGLcall("glUniform1f"); 1379 GL_EXTCALL(glUniform1f(prog->vs.pointsize_q_att_location, att[2])); 1380 checkGLcall("glUniform1f"); 1381 } 1382 1383 static void shader_glsl_load_fog_uniform(const struct wined3d_context *context, 1384 const struct wined3d_state *state, struct glsl_shader_prog_link *prog) 1385 { 1386 const struct wined3d_gl_info *gl_info = context->gl_info; 1387 struct wined3d_color color; 1388 float start, end, scale; 1389 union 1390 { 1391 DWORD d; 1392 float f; 1393 } tmpvalue; 1394 1395 wined3d_color_from_d3dcolor(&color, state->render_states[WINED3D_RS_FOGCOLOR]); 1396 GL_EXTCALL(glUniform4fv(prog->ps.fog_color_location, 1, &color.r)); 1397 tmpvalue.d = state->render_states[WINED3D_RS_FOGDENSITY]; 1398 GL_EXTCALL(glUniform1f(prog->ps.fog_density_location, tmpvalue.f)); 1399 get_fog_start_end(context, state, &start, &end); 1400 scale = 1.0f / (end - start); 1401 GL_EXTCALL(glUniform1f(prog->ps.fog_end_location, end)); 1402 GL_EXTCALL(glUniform1f(prog->ps.fog_scale_location, scale)); 1403 checkGLcall("fog emulation uniforms"); 1404 } 1405 1406 static void shader_glsl_clip_plane_uniform(const struct wined3d_context *context, 1407 const struct wined3d_state *state, unsigned int index, struct glsl_shader_prog_link *prog) 1408 { 1409 const struct wined3d_gl_info *gl_info = context->gl_info; 1410 struct wined3d_matrix matrix; 1411 struct wined3d_vec4 plane; 1412 1413 plane = state->clip_planes[index]; 1414 1415 /* Clip planes are affected by the view transform in d3d for FFP draws. */ 1416 if (!use_vs(state)) 1417 { 1418 invert_matrix(&matrix, &state->transforms[WINED3D_TS_VIEW]); 1419 transpose_matrix(&matrix, &matrix); 1420 multiply_vector_matrix(&plane, &plane, &matrix); 1421 } 1422 1423 GL_EXTCALL(glUniform4fv(prog->vs.clip_planes_location + index, 1, &plane.x)); 1424 } 1425 1426 /* Context activation is done by the caller (state handler). */ 1427 static void shader_glsl_load_color_key_constant(const struct glsl_ps_program *ps, 1428 const struct wined3d_gl_info *gl_info, const struct wined3d_state *state) 1429 { 1430 struct wined3d_color float_key[2]; 1431 const struct wined3d_texture *texture = state->textures[0]; 1432 1433 wined3d_format_get_float_color_key(texture->resource.format, &texture->async.src_blt_color_key, float_key); 1434 GL_EXTCALL(glUniform4fv(ps->color_key_location, 2, &float_key[0].r)); 1435 } 1436 1437 /* Context activation is done by the caller. */ 1438 static void get_normal_matrix(struct wined3d_context *context, struct wined3d_matrix *mat, float *normal) 1439 { 1440 int i, j; 1441 1442 if (context->d3d_info->wined3d_creation_flags & WINED3D_LEGACY_FFP_LIGHTING) 1443 invert_matrix_3d(mat, mat); 1444 else 1445 invert_matrix(mat, mat); 1446 /* Tests show that singular modelview matrices are used unchanged as normal 1447 * matrices on D3D3 and older. There seems to be no clearly consistent 1448 * behavior on newer D3D versions so always follow older ddraw behavior. */ 1449 for (i = 0; i < 3; ++i) 1450 for (j = 0; j < 3; ++j) 1451 normal[i * 3 + j] = (&mat->_11)[j * 4 + i]; 1452 } 1453 1454 /* Context activation is done by the caller (state handler). */ 1455 static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context *context, 1456 const struct wined3d_state *state) 1457 { 1458 const struct glsl_context_data *ctx_data = context->shader_backend_data; 1459 const struct wined3d_shader *vshader = state->shader[WINED3D_SHADER_TYPE_VERTEX]; 1460 const struct wined3d_shader *pshader = state->shader[WINED3D_SHADER_TYPE_PIXEL]; 1461 const struct wined3d_gl_info *gl_info = context->gl_info; 1462 struct shader_glsl_priv *priv = shader_priv; 1463 float position_fixup[4]; 1464 float normal[3 * 3]; 1465 DWORD update_mask; 1466 1467 struct glsl_shader_prog_link *prog = ctx_data->glsl_program; 1468 UINT constant_version; 1469 int i; 1470 1471 if (!prog) { 1472 /* No GLSL program set - nothing to do. */ 1473 return; 1474 } 1475 constant_version = prog->constant_version; 1476 update_mask = context->constant_update_mask & prog->constant_update_mask; 1477 1478 if (update_mask & WINED3D_SHADER_CONST_VS_F) 1479 shader_glsl_load_constants_f(vshader, gl_info, state->vs_consts_f, 1480 prog->vs.uniform_f_locations, &priv->vconst_heap, priv->stack, constant_version); 1481 1482 if (update_mask & WINED3D_SHADER_CONST_VS_I) 1483 shader_glsl_load_constants_i(vshader, gl_info, state->vs_consts_i, 1484 prog->vs.uniform_i_locations, vshader->reg_maps.integer_constants); 1485 1486 if (update_mask & WINED3D_SHADER_CONST_VS_B) 1487 shader_glsl_load_constantsB(vshader, gl_info, prog->vs.uniform_b_locations, state->vs_consts_b, 1488 vshader->reg_maps.boolean_constants); 1489 1490 if (update_mask & WINED3D_SHADER_CONST_VS_CLIP_PLANES) 1491 { 1492 for (i = 0; i < gl_info->limits.user_clip_distances; ++i) 1493 shader_glsl_clip_plane_uniform(context, state, i, prog); 1494 } 1495 1496 if (update_mask & WINED3D_SHADER_CONST_VS_POINTSIZE) 1497 shader_glsl_pointsize_uniform(context, state, prog); 1498 1499 if (update_mask & WINED3D_SHADER_CONST_POS_FIXUP) 1500 { 1501 shader_get_position_fixup(context, state, position_fixup); 1502 if (state->shader[WINED3D_SHADER_TYPE_GEOMETRY]) 1503 GL_EXTCALL(glUniform4fv(prog->gs.pos_fixup_location, 1, position_fixup)); 1504 else if (state->shader[WINED3D_SHADER_TYPE_DOMAIN]) 1505 GL_EXTCALL(glUniform4fv(prog->ds.pos_fixup_location, 1, position_fixup)); 1506 else 1507 GL_EXTCALL(glUniform4fv(prog->vs.pos_fixup_location, 1, position_fixup)); 1508 checkGLcall("glUniform4fv"); 1509 } 1510 1511 if (update_mask & WINED3D_SHADER_CONST_FFP_MODELVIEW) 1512 { 1513 struct wined3d_matrix mat; 1514 1515 get_modelview_matrix(context, state, 0, &mat); 1516 GL_EXTCALL(glUniformMatrix4fv(prog->vs.modelview_matrix_location[0], 1, FALSE, &mat._11)); 1517 checkGLcall("glUniformMatrix4fv"); 1518 1519 get_normal_matrix(context, &mat, normal); 1520 GL_EXTCALL(glUniformMatrix3fv(prog->vs.normal_matrix_location[0], 1, FALSE, normal)); 1521 checkGLcall("glUniformMatrix3fv"); 1522 } 1523 1524 if (update_mask & WINED3D_SHADER_CONST_FFP_VERTEXBLEND) 1525 { 1526 struct wined3d_matrix mat; 1527 1528 for (i = 1; i < MAX_VERTEX_INDEX_BLENDS; ++i) 1529 { 1530 if (prog->vs.modelview_matrix_location[i] == -1) 1531 break; 1532 if (!(update_mask & WINED3D_SHADER_CONST_FFP_VERTEXBLEND_INDEX(i))) 1533 continue; 1534 1535 get_modelview_matrix(context, state, i, &mat); 1536 GL_EXTCALL(glUniformMatrix4fv(prog->vs.modelview_matrix_location[i], 1, FALSE, &mat._11)); 1537 checkGLcall("glUniformMatrix4fv"); 1538 1539 get_normal_matrix(context, &mat, normal); 1540 GL_EXTCALL(glUniformMatrix3fv(prog->vs.normal_matrix_location[i], 1, FALSE, normal)); 1541 checkGLcall("glUniformMatrix3fv"); 1542 } 1543 } 1544 1545 if (update_mask & WINED3D_SHADER_CONST_FFP_PROJ) 1546 { 1547 struct wined3d_matrix projection; 1548 1549 get_projection_matrix(context, state, &projection); 1550 GL_EXTCALL(glUniformMatrix4fv(prog->vs.projection_matrix_location, 1, FALSE, &projection._11)); 1551 checkGLcall("glUniformMatrix4fv"); 1552 } 1553 1554 if (update_mask & WINED3D_SHADER_CONST_FFP_TEXMATRIX) 1555 { 1556 for (i = 0; i < MAX_TEXTURES; ++i) 1557 shader_glsl_ffp_vertex_texmatrix_uniform(context, state, i, prog); 1558 } 1559 1560 if (update_mask & WINED3D_SHADER_CONST_FFP_MATERIAL) 1561 shader_glsl_ffp_vertex_material_uniform(context, state, prog); 1562 1563 if (update_mask & WINED3D_SHADER_CONST_FFP_LIGHTS) 1564 { 1565 unsigned int point_idx, spot_idx, directional_idx, parallel_point_idx; 1566 DWORD point_count = 0; 1567 DWORD spot_count = 0; 1568 DWORD directional_count = 0; 1569 DWORD parallel_point_count = 0; 1570 1571 for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i) 1572 { 1573 if (!state->lights[i]) 1574 continue; 1575 1576 switch (state->lights[i]->OriginalParms.type) 1577 { 1578 case WINED3D_LIGHT_POINT: 1579 ++point_count; 1580 break; 1581 case WINED3D_LIGHT_SPOT: 1582 ++spot_count; 1583 break; 1584 case WINED3D_LIGHT_DIRECTIONAL: 1585 ++directional_count; 1586 break; 1587 case WINED3D_LIGHT_PARALLELPOINT: 1588 ++parallel_point_count; 1589 break; 1590 default: 1591 FIXME("Unhandled light type %#x.\n", state->lights[i]->OriginalParms.type); 1592 break; 1593 } 1594 } 1595 point_idx = 0; 1596 spot_idx = point_idx + point_count; 1597 directional_idx = spot_idx + spot_count; 1598 parallel_point_idx = directional_idx + directional_count; 1599 1600 shader_glsl_ffp_vertex_lightambient_uniform(context, state, prog); 1601 for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i) 1602 { 1603 const struct wined3d_light_info *light_info = state->lights[i]; 1604 unsigned int idx; 1605 1606 if (!light_info) 1607 continue; 1608 1609 switch (light_info->OriginalParms.type) 1610 { 1611 case WINED3D_LIGHT_POINT: 1612 idx = point_idx++; 1613 break; 1614 case WINED3D_LIGHT_SPOT: 1615 idx = spot_idx++; 1616 break; 1617 case WINED3D_LIGHT_DIRECTIONAL: 1618 idx = directional_idx++; 1619 break; 1620 case WINED3D_LIGHT_PARALLELPOINT: 1621 idx = parallel_point_idx++; 1622 break; 1623 default: 1624 FIXME("Unhandled light type %#x.\n", light_info->OriginalParms.type); 1625 continue; 1626 } 1627 shader_glsl_ffp_vertex_light_uniform(context, state, idx, light_info, prog); 1628 } 1629 } 1630 1631 if (update_mask & WINED3D_SHADER_CONST_PS_F) 1632 shader_glsl_load_constants_f(pshader, gl_info, state->ps_consts_f, 1633 prog->ps.uniform_f_locations, &priv->pconst_heap, priv->stack, constant_version); 1634 1635 if (update_mask & WINED3D_SHADER_CONST_PS_I) 1636 shader_glsl_load_constants_i(pshader, gl_info, state->ps_consts_i, 1637 prog->ps.uniform_i_locations, pshader->reg_maps.integer_constants); 1638 1639 if (update_mask & WINED3D_SHADER_CONST_PS_B) 1640 shader_glsl_load_constantsB(pshader, gl_info, prog->ps.uniform_b_locations, state->ps_consts_b, 1641 pshader->reg_maps.boolean_constants); 1642 1643 if (update_mask & WINED3D_SHADER_CONST_PS_BUMP_ENV) 1644 { 1645 for (i = 0; i < MAX_TEXTURES; ++i) 1646 { 1647 if (prog->ps.bumpenv_mat_location[i] == -1) 1648 continue; 1649 1650 GL_EXTCALL(glUniformMatrix2fv(prog->ps.bumpenv_mat_location[i], 1, 0, 1651 (const GLfloat *)&state->texture_states[i][WINED3D_TSS_BUMPENV_MAT00])); 1652 1653 if (prog->ps.bumpenv_lum_scale_location[i] != -1) 1654 { 1655 GL_EXTCALL(glUniform1fv(prog->ps.bumpenv_lum_scale_location[i], 1, 1656 (const GLfloat *)&state->texture_states[i][WINED3D_TSS_BUMPENV_LSCALE])); 1657 GL_EXTCALL(glUniform1fv(prog->ps.bumpenv_lum_offset_location[i], 1, 1658 (const GLfloat *)&state->texture_states[i][WINED3D_TSS_BUMPENV_LOFFSET])); 1659 } 1660 } 1661 1662 checkGLcall("bump env uniforms"); 1663 } 1664 1665 if (update_mask & WINED3D_SHADER_CONST_PS_Y_CORR) 1666 { 1667 const struct wined3d_vec4 correction_params = 1668 { 1669 /* Position is relative to the framebuffer, not the viewport. */ 1670 context->render_offscreen ? 0.0f : (float)state->fb->render_targets[0]->height, 1671 context->render_offscreen ? 1.0f : -1.0f, 1672 0.0f, 1673 0.0f, 1674 }; 1675 1676 GL_EXTCALL(glUniform4fv(prog->ps.ycorrection_location, 1, &correction_params.x)); 1677 } 1678 1679 if (update_mask & WINED3D_SHADER_CONST_PS_NP2_FIXUP) 1680 shader_glsl_load_np2fixup_constants(&prog->ps, gl_info, state); 1681 if (update_mask & WINED3D_SHADER_CONST_FFP_COLOR_KEY) 1682 shader_glsl_load_color_key_constant(&prog->ps, gl_info, state); 1683 1684 if (update_mask & WINED3D_SHADER_CONST_FFP_PS) 1685 { 1686 struct wined3d_color color; 1687 1688 if (prog->ps.tex_factor_location != -1) 1689 { 1690 wined3d_color_from_d3dcolor(&color, state->render_states[WINED3D_RS_TEXTUREFACTOR]); 1691 GL_EXTCALL(glUniform4fv(prog->ps.tex_factor_location, 1, &color.r)); 1692 } 1693 1694 if (state->render_states[WINED3D_RS_SPECULARENABLE]) 1695 GL_EXTCALL(glUniform4f(prog->ps.specular_enable_location, 1.0f, 1.0f, 1.0f, 0.0f)); 1696 else 1697 GL_EXTCALL(glUniform4f(prog->ps.specular_enable_location, 0.0f, 0.0f, 0.0f, 0.0f)); 1698 1699 for (i = 0; i < MAX_TEXTURES; ++i) 1700 { 1701 if (prog->ps.tss_constant_location[i] == -1) 1702 continue; 1703 1704 wined3d_color_from_d3dcolor(&color, state->texture_states[i][WINED3D_TSS_CONSTANT]); 1705 GL_EXTCALL(glUniform4fv(prog->ps.tss_constant_location[i], 1, &color.r)); 1706 } 1707 1708 checkGLcall("fixed function uniforms"); 1709 } 1710 1711 if (update_mask & WINED3D_SHADER_CONST_PS_FOG) 1712 shader_glsl_load_fog_uniform(context, state, prog); 1713 1714 if (update_mask & WINED3D_SHADER_CONST_PS_ALPHA_TEST) 1715 { 1716 float ref = state->render_states[WINED3D_RS_ALPHAREF] / 255.0f; 1717 1718 GL_EXTCALL(glUniform1f(prog->ps.alpha_test_ref_location, ref)); 1719 checkGLcall("alpha test emulation uniform"); 1720 } 1721 1722 if (priv->next_constant_version == UINT_MAX) 1723 { 1724 TRACE("Max constant version reached, resetting to 0.\n"); 1725 wine_rb_for_each_entry(&priv->program_lookup, reset_program_constant_version, NULL); 1726 priv->next_constant_version = 1; 1727 } 1728 else 1729 { 1730 prog->constant_version = priv->next_constant_version++; 1731 } 1732 } 1733 1734 static void update_heap_entry(struct constant_heap *heap, unsigned int idx, DWORD new_version) 1735 { 1736 struct constant_entry *entries = heap->entries; 1737 unsigned int *positions = heap->positions; 1738 unsigned int heap_idx, parent_idx; 1739 1740 if (!heap->contained[idx]) 1741 { 1742 heap_idx = heap->size++; 1743 heap->contained[idx] = TRUE; 1744 } 1745 else 1746 { 1747 heap_idx = positions[idx]; 1748 } 1749 1750 while (heap_idx > 1) 1751 { 1752 parent_idx = heap_idx >> 1; 1753 1754 if (new_version <= entries[parent_idx].version) break; 1755 1756 entries[heap_idx] = entries[parent_idx]; 1757 positions[entries[parent_idx].idx] = heap_idx; 1758 heap_idx = parent_idx; 1759 } 1760 1761 entries[heap_idx].version = new_version; 1762 entries[heap_idx].idx = idx; 1763 positions[idx] = heap_idx; 1764 } 1765 1766 static void shader_glsl_update_float_vertex_constants(struct wined3d_device *device, UINT start, UINT count) 1767 { 1768 struct shader_glsl_priv *priv = device->shader_priv; 1769 struct constant_heap *heap = &priv->vconst_heap; 1770 UINT i; 1771 1772 for (i = start; i < count + start; ++i) 1773 { 1774 update_heap_entry(heap, i, priv->next_constant_version); 1775 } 1776 } 1777 1778 static void shader_glsl_update_float_pixel_constants(struct wined3d_device *device, UINT start, UINT count) 1779 { 1780 struct shader_glsl_priv *priv = device->shader_priv; 1781 struct constant_heap *heap = &priv->pconst_heap; 1782 UINT i; 1783 1784 for (i = start; i < count + start; ++i) 1785 { 1786 update_heap_entry(heap, i, priv->next_constant_version); 1787 } 1788 } 1789 1790 static unsigned int vec4_varyings(DWORD shader_major, const struct wined3d_gl_info *gl_info) 1791 { 1792 unsigned int ret = gl_info->limits.glsl_varyings / 4; 1793 /* 4.0 shaders do not write clip coords because d3d10 does not support user clipplanes */ 1794 if(shader_major > 3) return ret; 1795 1796 /* 3.0 shaders may need an extra varying for the clip coord on some cards(mostly dx10 ones) */ 1797 if (gl_info->quirks & WINED3D_QUIRK_GLSL_CLIP_VARYING) ret -= 1; 1798 return ret; 1799 } 1800 1801 static BOOL needs_legacy_glsl_syntax(const struct wined3d_gl_info *gl_info) 1802 { 1803 return gl_info->glsl_version < MAKEDWORD_VERSION(1, 30); 1804 } 1805 1806 static BOOL shader_glsl_use_explicit_attrib_location(const struct wined3d_gl_info *gl_info) 1807 { 1808 return gl_info->supported[ARB_EXPLICIT_ATTRIB_LOCATION] 1809 && shader_glsl_use_layout_qualifier(gl_info) && !needs_legacy_glsl_syntax(gl_info); 1810 } 1811 1812 static BOOL shader_glsl_use_interface_blocks(const struct wined3d_gl_info *gl_info) 1813 { 1814 return shader_glsl_get_version(gl_info) >= 150; 1815 } 1816 1817 static const char *get_attribute_keyword(const struct wined3d_gl_info *gl_info) 1818 { 1819 return needs_legacy_glsl_syntax(gl_info) ? "attribute" : "in"; 1820 } 1821 1822 static void PRINTF_ATTR(4, 5) declare_in_varying(const struct wined3d_gl_info *gl_info, 1823 struct wined3d_string_buffer *buffer, BOOL flat, const char *format, ...) 1824 { 1825 va_list args; 1826 int ret; 1827 1828 shader_addline(buffer, "%s%s ", flat ? "flat " : "", 1829 needs_legacy_glsl_syntax(gl_info) ? "varying" : "in"); 1830 for (;;) 1831 { 1832 va_start(args, format); 1833 ret = shader_vaddline(buffer, format, args); 1834 va_end(args); 1835 if (!ret) 1836 return; 1837 if (!string_buffer_resize(buffer, ret)) 1838 return; 1839 } 1840 } 1841 1842 static void PRINTF_ATTR(4, 5) declare_out_varying(const struct wined3d_gl_info *gl_info, 1843 struct wined3d_string_buffer *buffer, BOOL flat, const char *format, ...) 1844 { 1845 va_list args; 1846 int ret; 1847 1848 shader_addline(buffer, "%s%s ", flat ? "flat " : "", 1849 needs_legacy_glsl_syntax(gl_info) ? "varying" : "out"); 1850 for (;;) 1851 { 1852 va_start(args, format); 1853 ret = shader_vaddline(buffer, format, args); 1854 va_end(args); 1855 if (!ret) 1856 return; 1857 if (!string_buffer_resize(buffer, ret)) 1858 return; 1859 } 1860 } 1861 1862 static const char *shader_glsl_shader_input_name(const struct wined3d_gl_info *gl_info) 1863 { 1864 return shader_glsl_use_interface_blocks(gl_info) ? "shader_in.reg" : "ps_link"; 1865 } 1866 1867 static const char *shader_glsl_shader_output_name(const struct wined3d_gl_info *gl_info) 1868 { 1869 return shader_glsl_use_interface_blocks(gl_info) ? "shader_out.reg" : "ps_link"; 1870 } 1871 1872 static const char *shader_glsl_interpolation_qualifiers(enum wined3d_shader_interpolation_mode mode) 1873 { 1874 switch (mode) 1875 { 1876 case WINED3DSIM_CONSTANT: 1877 return "flat"; 1878 case WINED3DSIM_LINEAR_NOPERSPECTIVE: 1879 return "noperspective"; 1880 default: 1881 FIXME("Unhandled interpolation mode %#x.\n", mode); 1882 case WINED3DSIM_NONE: 1883 case WINED3DSIM_LINEAR: 1884 return ""; 1885 } 1886 } 1887 1888 static enum wined3d_shader_interpolation_mode wined3d_extract_interpolation_mode( 1889 const DWORD *packed_interpolation_mode, unsigned int register_idx) 1890 { 1891 return wined3d_extract_bits(packed_interpolation_mode, 1892 register_idx * WINED3D_PACKED_INTERPOLATION_BIT_COUNT, WINED3D_PACKED_INTERPOLATION_BIT_COUNT); 1893 } 1894 1895 static void shader_glsl_declare_shader_inputs(const struct wined3d_gl_info *gl_info, 1896 struct wined3d_string_buffer *buffer, unsigned int element_count, 1897 const DWORD *interpolation_mode, BOOL unroll) 1898 { 1899 enum wined3d_shader_interpolation_mode mode; 1900 unsigned int i; 1901 1902 if (shader_glsl_use_interface_blocks(gl_info)) 1903 { 1904 if (unroll) 1905 { 1906 shader_addline(buffer, "in shader_in_out {\n"); 1907 for (i = 0; i < element_count; ++i) 1908 { 1909 mode = wined3d_extract_interpolation_mode(interpolation_mode, i); 1910 shader_addline(buffer, "%s vec4 reg%u;\n", shader_glsl_interpolation_qualifiers(mode), i); 1911 } 1912 shader_addline(buffer, "} shader_in;\n"); 1913 } 1914 else 1915 { 1916 shader_addline(buffer, "in shader_in_out { vec4 reg[%u]; } shader_in;\n", element_count); 1917 } 1918 } 1919 else 1920 { 1921 declare_in_varying(gl_info, buffer, FALSE, "vec4 ps_link[%u];\n", element_count); 1922 } 1923 } 1924 1925 static void shader_glsl_declare_shader_outputs(const struct wined3d_gl_info *gl_info, 1926 struct wined3d_string_buffer *buffer, unsigned int element_count, BOOL rasterizer_setup, 1927 const DWORD *interpolation_mode) 1928 { 1929 enum wined3d_shader_interpolation_mode mode; 1930 unsigned int i; 1931 1932 if (shader_glsl_use_interface_blocks(gl_info)) 1933 { 1934 if (rasterizer_setup) 1935 { 1936 shader_addline(buffer, "out shader_in_out {\n"); 1937 for (i = 0; i < element_count; ++i) 1938 { 1939 const char *interpolation_qualifiers = ""; 1940 if (needs_interpolation_qualifiers_for_shader_outputs(gl_info)) 1941 { 1942 mode = wined3d_extract_interpolation_mode(interpolation_mode, i); 1943 interpolation_qualifiers = shader_glsl_interpolation_qualifiers(mode); 1944 } 1945 shader_addline(buffer, "%s vec4 reg%u;\n", interpolation_qualifiers, i); 1946 } 1947 shader_addline(buffer, "} shader_out;\n"); 1948 } 1949 else 1950 { 1951 shader_addline(buffer, "out shader_in_out { vec4 reg[%u]; } shader_out;\n", element_count); 1952 } 1953 } 1954 else 1955 { 1956 declare_out_varying(gl_info, buffer, FALSE, "vec4 ps_link[%u];\n", element_count); 1957 } 1958 } 1959 1960 static const char *glsl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type) 1961 { 1962 switch (primitive_type) 1963 { 1964 case WINED3D_PT_POINTLIST: 1965 return "points"; 1966 1967 case WINED3D_PT_LINELIST: 1968 return "lines"; 1969 1970 case WINED3D_PT_LINESTRIP: 1971 return "line_strip"; 1972 1973 case WINED3D_PT_TRIANGLELIST: 1974 return "triangles"; 1975 1976 case WINED3D_PT_TRIANGLESTRIP: 1977 return "triangle_strip"; 1978 1979 case WINED3D_PT_LINELIST_ADJ: 1980 return "lines_adjacency"; 1981 1982 case WINED3D_PT_TRIANGLELIST_ADJ: 1983 return "triangles_adjacency"; 1984 1985 default: 1986 FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(primitive_type)); 1987 return ""; 1988 } 1989 } 1990 1991 static BOOL glsl_is_color_reg_read(const struct wined3d_shader *shader, unsigned int idx) 1992 { 1993 const struct wined3d_shader_signature *input_signature = &shader->input_signature; 1994 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; 1995 DWORD input_reg_used = shader->u.ps.input_reg_used; 1996 unsigned int i; 1997 1998 if (reg_maps->shader_version.major < 3) 1999 return input_reg_used & (1u << idx); 2000 2001 for (i = 0; i < input_signature->element_count; ++i) 2002 { 2003 const struct wined3d_shader_signature_element *input = &input_signature->elements[i]; 2004 2005 if (!(reg_maps->input_registers & (1u << input->register_idx))) 2006 continue; 2007 2008 if (shader_match_semantic(input->semantic_name, WINED3D_DECL_USAGE_COLOR) 2009 && input->semantic_idx == idx) 2010 return input_reg_used & (1u << input->register_idx); 2011 } 2012 return FALSE; 2013 } 2014 2015 static BOOL glsl_is_shadow_sampler(const struct wined3d_shader *shader, 2016 const struct ps_compile_args *ps_args, unsigned int resource_idx, unsigned int sampler_idx) 2017 { 2018 const struct wined3d_shader_version *version = &shader->reg_maps.shader_version; 2019 2020 if (version->major >= 4) 2021 return shader->reg_maps.sampler_comparison_mode & (1u << sampler_idx); 2022 else 2023 return version->type == WINED3D_SHADER_TYPE_PIXEL && (ps_args->shadow & (1u << resource_idx)); 2024 } 2025 2026 static void shader_glsl_declare_typed_vertex_attribute(struct wined3d_string_buffer *buffer, 2027 const struct wined3d_gl_info *gl_info, const char *vector_type, const char *scalar_type, 2028 unsigned int index) 2029 { 2030 shader_addline(buffer, "%s %s4 vs_in_%s%u;\n", 2031 get_attribute_keyword(gl_info), vector_type, scalar_type, index); 2032 shader_addline(buffer, "vec4 vs_in%u = %sBitsToFloat(vs_in_%s%u);\n", 2033 index, scalar_type, scalar_type, index); 2034 } 2035 2036 static void shader_glsl_declare_generic_vertex_attribute(struct wined3d_string_buffer *buffer, 2037 const struct wined3d_gl_info *gl_info, const struct wined3d_shader_signature_element *e) 2038 { 2039 unsigned int index = e->register_idx; 2040 2041 if (e->sysval_semantic == WINED3D_SV_VERTEX_ID) 2042 { 2043 shader_addline(buffer, "vec4 vs_in%u = vec4(intBitsToFloat(gl_VertexID), 0.0, 0.0, 0.0);\n", 2044 index); 2045 return; 2046 } 2047 if (e->sysval_semantic == WINED3D_SV_INSTANCE_ID) 2048 { 2049 shader_addline(buffer, "vec4 vs_in%u = vec4(intBitsToFloat(gl_InstanceID), 0.0, 0.0, 0.0);\n", 2050 index); 2051 return; 2052 } 2053 if (e->sysval_semantic && e->sysval_semantic != WINED3D_SV_POSITION) 2054 FIXME("Unhandled sysval semantic %#x.\n", e->sysval_semantic); 2055 2056 if (shader_glsl_use_explicit_attrib_location(gl_info)) 2057 shader_addline(buffer, "layout(location = %u) ", index); 2058 2059 switch (e->component_type) 2060 { 2061 case WINED3D_TYPE_UINT: 2062 shader_glsl_declare_typed_vertex_attribute(buffer, gl_info, "uvec", "uint", index); 2063 break; 2064 case WINED3D_TYPE_INT: 2065 shader_glsl_declare_typed_vertex_attribute(buffer, gl_info, "ivec", "int", index); 2066 break; 2067 2068 default: 2069 FIXME("Unhandled type %#x.\n", e->component_type); 2070 /* Fall through. */ 2071 case WINED3D_TYPE_UNKNOWN: 2072 case WINED3D_TYPE_FLOAT: 2073 shader_addline(buffer, "%s vec4 vs_in%u;\n", get_attribute_keyword(gl_info), index); 2074 break; 2075 } 2076 } 2077 2078 /** Generate the variable & register declarations for the GLSL output target */ 2079 static void shader_generate_glsl_declarations(const struct wined3d_context *context, 2080 struct wined3d_string_buffer *buffer, const struct wined3d_shader *shader, 2081 const struct wined3d_shader_reg_maps *reg_maps, const struct shader_glsl_ctx_priv *ctx_priv) 2082 { 2083 const struct wined3d_shader_version *version = ®_maps->shader_version; 2084 const struct vs_compile_args *vs_args = ctx_priv->cur_vs_args; 2085 const struct ps_compile_args *ps_args = ctx_priv->cur_ps_args; 2086 const struct wined3d_gl_info *gl_info = context->gl_info; 2087 const struct wined3d_shader_indexable_temp *idx_temp_reg; 2088 unsigned int uniform_block_base, uniform_block_count; 2089 const struct wined3d_shader_lconst *lconst; 2090 const char *prefix; 2091 unsigned int i; 2092 DWORD map; 2093 2094 prefix = shader_glsl_get_prefix(version->type); 2095 2096 /* Prototype the subroutines */ 2097 for (i = 0, map = reg_maps->labels; map; map >>= 1, ++i) 2098 { 2099 if (map & 1) shader_addline(buffer, "void subroutine%u();\n", i); 2100 } 2101 2102 /* Declare the constants (aka uniforms) */ 2103 if (shader->limits->constant_float > 0) 2104 { 2105 unsigned max_constantsF; 2106 2107 /* Unless the shader uses indirect addressing, always declare the 2108 * maximum array size and ignore that we need some uniforms privately. 2109 * E.g. if GL supports 256 uniforms, and we need 2 for the pos fixup 2110 * and immediate values, still declare VC[256]. If the shader needs 2111 * more uniforms than we have it won't work in any case. If it uses 2112 * less, the compiler will figure out which uniforms are really used 2113 * and strip them out. This allows a shader to use c255 on a dx9 card, 2114 * as long as it doesn't also use all the other constants. 2115 * 2116 * If the shader uses indirect addressing the compiler must assume 2117 * that all declared uniforms are used. In this case, declare only the 2118 * amount that we're assured to have. 2119 * 2120 * Thus we run into problems in these two cases: 2121 * 1) The shader really uses more uniforms than supported. 2122 * 2) The shader uses indirect addressing, less constants than 2123 * supported, but uses a constant index > #supported consts. */ 2124 if (version->type == WINED3D_SHADER_TYPE_PIXEL) 2125 { 2126 /* No indirect addressing here. */ 2127 max_constantsF = gl_info->limits.glsl_ps_float_constants; 2128 } 2129 else 2130 { 2131 if (reg_maps->usesrelconstF) 2132 { 2133 /* Subtract the other potential uniforms from the max 2134 * available (bools, ints, and 1 row of projection matrix). 2135 * Subtract another uniform for immediate values, which have 2136 * to be loaded via uniform by the driver as well. The shader 2137 * code only uses 0.5, 2.0, 1.0, 128 and -128 in vertex 2138 * shader code, so one vec4 should be enough. (Unfortunately 2139 * the Nvidia driver doesn't store 128 and -128 in one float). 2140 * 2141 * Writing gl_ClipVertex requires one uniform for each 2142 * clipplane as well. */ 2143 max_constantsF = gl_info->limits.glsl_vs_float_constants - 3; 2144 if (vs_args->clip_enabled) 2145 max_constantsF -= gl_info->limits.user_clip_distances; 2146 max_constantsF -= wined3d_popcount(reg_maps->integer_constants); 2147 /* Strictly speaking a bool only uses one scalar, but the nvidia(Linux) compiler doesn't pack them properly, 2148 * so each scalar requires a full vec4. We could work around this by packing the booleans ourselves, but 2149 * for now take this into account when calculating the number of available constants 2150 */ 2151 max_constantsF -= wined3d_popcount(reg_maps->boolean_constants); 2152 /* Set by driver quirks in directx.c */ 2153 max_constantsF -= gl_info->reserved_glsl_constants; 2154 2155 if (max_constantsF < shader->limits->constant_float) 2156 { 2157 static unsigned int once; 2158 2159 if (!once++) 2160 ERR_(winediag)("The hardware does not support enough uniform components to run this shader," 2161 " it may not render correctly.\n"); 2162 else 2163 WARN("The hardware does not support enough uniform components to run this shader.\n"); 2164 } 2165 } 2166 else 2167 { 2168 max_constantsF = gl_info->limits.glsl_vs_float_constants; 2169 } 2170 } 2171 max_constantsF = min(shader->limits->constant_float, max_constantsF); 2172 shader_addline(buffer, "uniform vec4 %s_c[%u];\n", prefix, max_constantsF); 2173 } 2174 2175 /* Always declare the full set of constants, the compiler can remove the 2176 * unused ones because d3d doesn't (yet) support indirect int and bool 2177 * constant addressing. This avoids problems if the app uses e.g. i0 and i9. */ 2178 if (shader->limits->constant_int > 0 && reg_maps->integer_constants) 2179 shader_addline(buffer, "uniform ivec4 %s_i[%u];\n", prefix, shader->limits->constant_int); 2180 2181 if (shader->limits->constant_bool > 0 && reg_maps->boolean_constants) 2182 shader_addline(buffer, "uniform bool %s_b[%u];\n", prefix, shader->limits->constant_bool); 2183 2184 /* Declare immediate constant buffer */ 2185 if (reg_maps->icb) 2186 shader_addline(buffer, "uniform vec4 %s_icb[%u];\n", prefix, reg_maps->icb->vec4_count); 2187 2188 /* Declare constant buffers */ 2189 wined3d_gl_limits_get_uniform_block_range(&gl_info->limits, version->type, 2190 &uniform_block_base, &uniform_block_count); 2191 for (i = 0; i < min(uniform_block_count, WINED3D_MAX_CBS); ++i) 2192 { 2193 if (reg_maps->cb_sizes[i]) 2194 { 2195 shader_addline(buffer, "layout(std140"); 2196 if (shader_glsl_use_layout_binding_qualifier(gl_info)) 2197 shader_addline(buffer, ", binding = %u", uniform_block_base + i); 2198 shader_addline(buffer, ") uniform block_%s_cb%u { vec4 %s_cb%u[%u]; };\n", 2199 prefix, i, prefix, i, reg_maps->cb_sizes[i]); 2200 } 2201 } 2202 2203 /* Declare texture samplers */ 2204 for (i = 0; i < reg_maps->sampler_map.count; ++i) 2205 { 2206 struct wined3d_shader_sampler_map_entry *entry; 2207 const char *sampler_type_prefix, *sampler_type; 2208 BOOL shadow_sampler, tex_rect; 2209 2210 entry = ®_maps->sampler_map.entries[i]; 2211 2212 if (entry->resource_idx >= ARRAY_SIZE(reg_maps->resource_info)) 2213 { 2214 ERR("Invalid resource index %u.\n", entry->resource_idx); 2215 continue; 2216 } 2217 2218 switch (reg_maps->resource_info[entry->resource_idx].data_type) 2219 { 2220 case WINED3D_DATA_FLOAT: 2221 case WINED3D_DATA_UNORM: 2222 case WINED3D_DATA_SNORM: 2223 sampler_type_prefix = ""; 2224 break; 2225 2226 case WINED3D_DATA_INT: 2227 sampler_type_prefix = "i"; 2228 break; 2229 2230 case WINED3D_DATA_UINT: 2231 sampler_type_prefix = "u"; 2232 break; 2233 2234 default: 2235 sampler_type_prefix = ""; 2236 ERR("Unhandled resource data type %#x.\n", reg_maps->resource_info[i].data_type); 2237 break; 2238 } 2239 2240 shadow_sampler = glsl_is_shadow_sampler(shader, ps_args, entry->resource_idx, entry->sampler_idx); 2241 switch (reg_maps->resource_info[entry->resource_idx].type) 2242 { 2243 case WINED3D_SHADER_RESOURCE_BUFFER: 2244 sampler_type = "samplerBuffer"; 2245 break; 2246 2247 case WINED3D_SHADER_RESOURCE_TEXTURE_1D: 2248 if (shadow_sampler) 2249 sampler_type = "sampler1DShadow"; 2250 else 2251 sampler_type = "sampler1D"; 2252 break; 2253 2254 case WINED3D_SHADER_RESOURCE_TEXTURE_2D: 2255 tex_rect = version->type == WINED3D_SHADER_TYPE_PIXEL 2256 && (ps_args->np2_fixup & (1u << entry->resource_idx)) 2257 && gl_info->supported[ARB_TEXTURE_RECTANGLE]; 2258 if (shadow_sampler) 2259 { 2260 if (tex_rect) 2261 sampler_type = "sampler2DRectShadow"; 2262 else 2263 sampler_type = "sampler2DShadow"; 2264 } 2265 else 2266 { 2267 if (tex_rect) 2268 sampler_type = "sampler2DRect"; 2269 else 2270 sampler_type = "sampler2D"; 2271 } 2272 break; 2273 2274 case WINED3D_SHADER_RESOURCE_TEXTURE_3D: 2275 if (shadow_sampler) 2276 FIXME("Unsupported 3D shadow sampler.\n"); 2277 sampler_type = "sampler3D"; 2278 break; 2279 2280 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBE: 2281 if (shadow_sampler) 2282 sampler_type = "samplerCubeShadow"; 2283 else 2284 sampler_type = "samplerCube"; 2285 break; 2286 2287 case WINED3D_SHADER_RESOURCE_TEXTURE_1DARRAY: 2288 if (shadow_sampler) 2289 sampler_type = "sampler1DArrayShadow"; 2290 else 2291 sampler_type = "sampler1DArray"; 2292 break; 2293 2294 case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY: 2295 if (shadow_sampler) 2296 sampler_type = "sampler2DArrayShadow"; 2297 else 2298 sampler_type = "sampler2DArray"; 2299 break; 2300 2301 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY: 2302 if (shadow_sampler) 2303 sampler_type = "samplerCubeArrayShadow"; 2304 else 2305 sampler_type = "samplerCubeArray"; 2306 break; 2307 2308 case WINED3D_SHADER_RESOURCE_TEXTURE_2DMS: 2309 sampler_type = "sampler2DMS"; 2310 break; 2311 2312 case WINED3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY: 2313 sampler_type = "sampler2DMSArray"; 2314 break; 2315 2316 default: 2317 sampler_type = "unsupported_sampler"; 2318 FIXME("Unhandled resource type %#x.\n", reg_maps->resource_info[entry->resource_idx].type); 2319 break; 2320 } 2321 2322 if (shader_glsl_use_layout_binding_qualifier(gl_info)) 2323 shader_glsl_append_sampler_binding_qualifier(buffer, context, version, entry->bind_idx); 2324 shader_addline(buffer, "uniform %s%s %s_sampler%u;\n", 2325 sampler_type_prefix, sampler_type, prefix, entry->bind_idx); 2326 } 2327 2328 /* Declare images */ 2329 for (i = 0; i < ARRAY_SIZE(reg_maps->uav_resource_info); ++i) 2330 { 2331 const char *image_type_prefix, *image_type, *read_format; 2332 2333 if (!reg_maps->uav_resource_info[i].type) 2334 continue; 2335 2336 switch (reg_maps->uav_resource_info[i].data_type) 2337 { 2338 case WINED3D_DATA_FLOAT: 2339 case WINED3D_DATA_UNORM: 2340 case WINED3D_DATA_SNORM: 2341 image_type_prefix = ""; 2342 read_format = "r32f"; 2343 break; 2344 2345 case WINED3D_DATA_INT: 2346 image_type_prefix = "i"; 2347 read_format = "r32i"; 2348 break; 2349 2350 case WINED3D_DATA_UINT: 2351 image_type_prefix = "u"; 2352 read_format = "r32ui"; 2353 break; 2354 2355 default: 2356 image_type_prefix = ""; 2357 read_format = ""; 2358 ERR("Unhandled resource data type %#x.\n", reg_maps->uav_resource_info[i].data_type); 2359 break; 2360 } 2361 2362 switch (reg_maps->uav_resource_info[i].type) 2363 { 2364 case WINED3D_SHADER_RESOURCE_BUFFER: 2365 image_type = "imageBuffer"; 2366 break; 2367 2368 case WINED3D_SHADER_RESOURCE_TEXTURE_2D: 2369 image_type = "image2D"; 2370 break; 2371 2372 case WINED3D_SHADER_RESOURCE_TEXTURE_3D: 2373 image_type = "image3D"; 2374 break; 2375 2376 case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY: 2377 image_type = "image2DArray"; 2378 break; 2379 2380 default: 2381 image_type = "unsupported_image"; 2382 FIXME("Unhandled resource type %#x.\n", reg_maps->uav_resource_info[i].type); 2383 break; 2384 } 2385 2386 if (shader_glsl_use_layout_binding_qualifier(gl_info)) 2387 shader_addline(buffer, "layout(binding = %u)\n", i); 2388 if (reg_maps->uav_read_mask & (1u << i)) 2389 shader_addline(buffer, "layout(%s) uniform %s%s %s_image%u;\n", 2390 read_format, image_type_prefix, image_type, prefix, i); 2391 else 2392 shader_addline(buffer, "writeonly uniform %s%s %s_image%u;\n", 2393 image_type_prefix, image_type, prefix, i); 2394 2395 if (reg_maps->uav_counter_mask & (1u << i)) 2396 shader_addline(buffer, "layout(binding = %u) uniform atomic_uint %s_counter%u;\n", 2397 i, prefix, i); 2398 } 2399 2400 /* Declare address variables */ 2401 for (i = 0, map = reg_maps->address; map; map >>= 1, ++i) 2402 { 2403 if (map & 1) shader_addline(buffer, "ivec4 A%u;\n", i); 2404 } 2405 2406 /* Declare output register temporaries */ 2407 if (shader->limits->packed_output) 2408 shader_addline(buffer, "vec4 %s_out[%u];\n", prefix, shader->limits->packed_output); 2409 2410 /* Declare temporary variables */ 2411 if (reg_maps->temporary_count) 2412 { 2413 for (i = 0; i < reg_maps->temporary_count; ++i) 2414 shader_addline(buffer, "vec4 R%u;\n", i); 2415 } 2416 else if (version->major < 4) 2417 { 2418 for (i = 0, map = reg_maps->temporary; map; map >>= 1, ++i) 2419 { 2420 if (map & 1) 2421 shader_addline(buffer, "vec4 R%u;\n", i); 2422 } 2423 } 2424 2425 /* Declare indexable temporary variables */ 2426 LIST_FOR_EACH_ENTRY(idx_temp_reg, ®_maps->indexable_temps, struct wined3d_shader_indexable_temp, entry) 2427 { 2428 if (idx_temp_reg->component_count != 4) 2429 FIXME("Ignoring component count %u.\n", idx_temp_reg->component_count); 2430 shader_addline(buffer, "vec4 X%u[%u];\n", idx_temp_reg->register_idx, idx_temp_reg->register_size); 2431 } 2432 2433 /* Declare loop registers aLx */ 2434 if (version->major < 4) 2435 { 2436 for (i = 0; i < reg_maps->loop_depth; ++i) 2437 { 2438 shader_addline(buffer, "int aL%u;\n", i); 2439 shader_addline(buffer, "int tmpInt%u;\n", i); 2440 } 2441 } 2442 2443 /* Temporary variables for matrix operations */ 2444 shader_addline(buffer, "vec4 tmp0;\n"); 2445 shader_addline(buffer, "vec4 tmp1;\n"); 2446 2447 if (!shader->load_local_constsF) 2448 { 2449 LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry) 2450 { 2451 shader_addline(buffer, "const vec4 %s_lc%u = ", prefix, lconst->idx); 2452 shader_glsl_append_imm_vec4(buffer, (const float *)lconst->value); 2453 shader_addline(buffer, ";\n"); 2454 } 2455 } 2456 } 2457 2458 /* Prototypes */ 2459 static void shader_glsl_add_src_param(const struct wined3d_shader_instruction *ins, 2460 const struct wined3d_shader_src_param *wined3d_src, DWORD mask, struct glsl_src_param *glsl_src); 2461 2462 /** Used for opcode modifiers - They multiply the result by the specified amount */ 2463 static const char * const shift_glsl_tab[] = { 2464 "", /* 0 (none) */ 2465 "2.0 * ", /* 1 (x2) */ 2466 "4.0 * ", /* 2 (x4) */ 2467 "8.0 * ", /* 3 (x8) */ 2468 "16.0 * ", /* 4 (x16) */ 2469 "32.0 * ", /* 5 (x32) */ 2470 "", /* 6 (x64) */ 2471 "", /* 7 (x128) */ 2472 "", /* 8 (d256) */ 2473 "", /* 9 (d128) */ 2474 "", /* 10 (d64) */ 2475 "", /* 11 (d32) */ 2476 "0.0625 * ", /* 12 (d16) */ 2477 "0.125 * ", /* 13 (d8) */ 2478 "0.25 * ", /* 14 (d4) */ 2479 "0.5 * " /* 15 (d2) */ 2480 }; 2481 2482 /* Generate a GLSL parameter that does the input modifier computation and return the input register/mask to use */ 2483 static void shader_glsl_gen_modifier(enum wined3d_shader_src_modifier src_modifier, 2484 const char *in_reg, const char *in_regswizzle, char *out_str) 2485 { 2486 switch (src_modifier) 2487 { 2488 case WINED3DSPSM_DZ: /* Need to handle this in the instructions itself (texld & texcrd). */ 2489 case WINED3DSPSM_DW: 2490 case WINED3DSPSM_NONE: 2491 sprintf(out_str, "%s%s", in_reg, in_regswizzle); 2492 break; 2493 case WINED3DSPSM_NEG: 2494 sprintf(out_str, "-%s%s", in_reg, in_regswizzle); 2495 break; 2496 case WINED3DSPSM_NOT: 2497 sprintf(out_str, "!%s%s", in_reg, in_regswizzle); 2498 break; 2499 case WINED3DSPSM_BIAS: 2500 sprintf(out_str, "(%s%s - vec4(0.5)%s)", in_reg, in_regswizzle, in_regswizzle); 2501 break; 2502 case WINED3DSPSM_BIASNEG: 2503 sprintf(out_str, "-(%s%s - vec4(0.5)%s)", in_reg, in_regswizzle, in_regswizzle); 2504 break; 2505 case WINED3DSPSM_SIGN: 2506 sprintf(out_str, "(2.0 * (%s%s - 0.5))", in_reg, in_regswizzle); 2507 break; 2508 case WINED3DSPSM_SIGNNEG: 2509 sprintf(out_str, "-(2.0 * (%s%s - 0.5))", in_reg, in_regswizzle); 2510 break; 2511 case WINED3DSPSM_COMP: 2512 sprintf(out_str, "(1.0 - %s%s)", in_reg, in_regswizzle); 2513 break; 2514 case WINED3DSPSM_X2: 2515 sprintf(out_str, "(2.0 * %s%s)", in_reg, in_regswizzle); 2516 break; 2517 case WINED3DSPSM_X2NEG: 2518 sprintf(out_str, "-(2.0 * %s%s)", in_reg, in_regswizzle); 2519 break; 2520 case WINED3DSPSM_ABS: 2521 sprintf(out_str, "abs(%s%s)", in_reg, in_regswizzle); 2522 break; 2523 case WINED3DSPSM_ABSNEG: 2524 sprintf(out_str, "-abs(%s%s)", in_reg, in_regswizzle); 2525 break; 2526 default: 2527 FIXME("Unhandled modifier %u\n", src_modifier); 2528 sprintf(out_str, "%s%s", in_reg, in_regswizzle); 2529 } 2530 } 2531 2532 static void shader_glsl_fixup_scalar_register_variable(char *register_name, 2533 const char *glsl_variable, const struct wined3d_gl_info *gl_info) 2534 { 2535 /* The ARB_shading_language_420pack extension allows swizzle operations on 2536 * scalars. */ 2537 if (gl_info->supported[ARB_SHADING_LANGUAGE_420PACK]) 2538 sprintf(register_name, "%s", glsl_variable); 2539 else 2540 sprintf(register_name, "ivec2(%s, 0)", glsl_variable); 2541 } 2542 2543 /** Writes the GLSL variable name that corresponds to the register that the 2544 * DX opcode parameter is trying to access */ 2545 static void shader_glsl_get_register_name(const struct wined3d_shader_register *reg, 2546 enum wined3d_data_type data_type, char *register_name, BOOL *is_color, 2547 const struct wined3d_shader_instruction *ins) 2548 { 2549 /* oPos, oFog and oPts in D3D */ 2550 static const char * const hwrastout_reg_names[] = {"vs_out[10]", "vs_out[11].x", "vs_out[11].y"}; 2551 2552 const struct wined3d_shader *shader = ins->ctx->shader; 2553 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; 2554 const struct wined3d_shader_version *version = ®_maps->shader_version; 2555 const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; 2556 const char *prefix = shader_glsl_get_prefix(version->type); 2557 struct glsl_src_param rel_param0, rel_param1; 2558 char imm_str[4][17]; 2559 2560 if (reg->idx[0].offset != ~0U && reg->idx[0].rel_addr) 2561 shader_glsl_add_src_param(ins, reg->idx[0].rel_addr, WINED3DSP_WRITEMASK_0, &rel_param0); 2562 if (reg->idx[1].offset != ~0U && reg->idx[1].rel_addr) 2563 shader_glsl_add_src_param(ins, reg->idx[1].rel_addr, WINED3DSP_WRITEMASK_0, &rel_param1); 2564 *is_color = FALSE; 2565 2566 switch (reg->type) 2567 { 2568 case WINED3DSPR_TEMP: 2569 sprintf(register_name, "R%u", reg->idx[0].offset); 2570 break; 2571 2572 case WINED3DSPR_INPUT: 2573 case WINED3DSPR_INCONTROLPOINT: 2574 if (version->type == WINED3D_SHADER_TYPE_VERTEX) 2575 { 2576 struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; 2577 2578 if (reg->idx[0].rel_addr) 2579 FIXME("VS3 input registers relative addressing.\n"); 2580 if (priv->cur_vs_args->swizzle_map & (1u << reg->idx[0].offset)) 2581 *is_color = TRUE; 2582 if (reg->idx[0].rel_addr) 2583 { 2584 sprintf(register_name, "%s_in[%s + %u]", 2585 prefix, rel_param0.param_str, reg->idx[0].offset); 2586 } 2587 else 2588 { 2589 sprintf(register_name, "%s_in%u", prefix, reg->idx[0].offset); 2590 } 2591 break; 2592 } 2593 2594 if (version->type == WINED3D_SHADER_TYPE_HULL 2595 || version->type == WINED3D_SHADER_TYPE_DOMAIN 2596 || version->type == WINED3D_SHADER_TYPE_GEOMETRY) 2597 { 2598 if (reg->idx[0].rel_addr) 2599 { 2600 if (reg->idx[1].rel_addr) 2601 sprintf(register_name, "shader_in[%s + %u].reg[%s + %u]", 2602 rel_param0.param_str, reg->idx[0].offset, 2603 rel_param1.param_str, reg->idx[1].offset); 2604 else 2605 sprintf(register_name, "shader_in[%s + %u].reg[%u]", 2606 rel_param0.param_str, reg->idx[0].offset, 2607 reg->idx[1].offset); 2608 } 2609 else if (reg->idx[1].rel_addr) 2610 sprintf(register_name, "shader_in[%u].reg[%s + %u]", reg->idx[0].offset, 2611 rel_param1.param_str, reg->idx[1].offset); 2612 else 2613 sprintf(register_name, "shader_in[%u].reg[%u]", 2614 reg->idx[0].offset, reg->idx[1].offset); 2615 break; 2616 } 2617 2618 /* pixel shaders >= 3.0 */ 2619 if (version->major >= 3) 2620 { 2621 DWORD idx = shader->u.ps.input_reg_map[reg->idx[0].offset]; 2622 unsigned int in_count = vec4_varyings(version->major, gl_info); 2623 2624 if (reg->idx[0].rel_addr) 2625 { 2626 /* Removing a + 0 would be an obvious optimization, but 2627 * OS X doesn't see the NOP operation there. */ 2628 if (idx) 2629 { 2630 if (needs_legacy_glsl_syntax(gl_info) 2631 && shader->u.ps.declared_in_count > in_count) 2632 { 2633 sprintf(register_name, 2634 "((%s + %u) > %u ? (%s + %u) > %u ? gl_SecondaryColor : gl_Color : %s_in[%s + %u])", 2635 rel_param0.param_str, idx, in_count - 1, rel_param0.param_str, idx, in_count, 2636 prefix, rel_param0.param_str, idx); 2637 } 2638 else 2639 { 2640 sprintf(register_name, "%s_in[%s + %u]", prefix, rel_param0.param_str, idx); 2641 } 2642 } 2643 else 2644 { 2645 if (needs_legacy_glsl_syntax(gl_info) 2646 && shader->u.ps.declared_in_count > in_count) 2647 { 2648 sprintf(register_name, "((%s) > %u ? (%s) > %u ? gl_SecondaryColor : gl_Color : %s_in[%s])", 2649 rel_param0.param_str, in_count - 1, rel_param0.param_str, in_count, 2650 prefix, rel_param0.param_str); 2651 } 2652 else 2653 { 2654 sprintf(register_name, "%s_in[%s]", prefix, rel_param0.param_str); 2655 } 2656 } 2657 } 2658 else 2659 { 2660 if (idx == in_count) sprintf(register_name, "gl_Color"); 2661 else if (idx == in_count + 1) sprintf(register_name, "gl_SecondaryColor"); 2662 else sprintf(register_name, "%s_in[%u]", prefix, idx); 2663 } 2664 } 2665 else 2666 { 2667 if (!reg->idx[0].offset) 2668 strcpy(register_name, "ffp_varying_diffuse"); 2669 else 2670 strcpy(register_name, "ffp_varying_specular"); 2671 break; 2672 } 2673 break; 2674 2675 case WINED3DSPR_CONST: 2676 { 2677 /* Relative addressing */ 2678 if (reg->idx[0].rel_addr) 2679 { 2680 if (wined3d_settings.check_float_constants) 2681 sprintf(register_name, "(%s + %u >= 0 && %s + %u < %u ? %s_c[%s + %u] : vec4(0.0))", 2682 rel_param0.param_str, reg->idx[0].offset, 2683 rel_param0.param_str, reg->idx[0].offset, shader->limits->constant_float, 2684 prefix, rel_param0.param_str, reg->idx[0].offset); 2685 else if (reg->idx[0].offset) 2686 sprintf(register_name, "%s_c[%s + %u]", prefix, rel_param0.param_str, reg->idx[0].offset); 2687 else 2688 sprintf(register_name, "%s_c[%s]", prefix, rel_param0.param_str); 2689 } 2690 else 2691 { 2692 if (shader_constant_is_local(shader, reg->idx[0].offset)) 2693 sprintf(register_name, "%s_lc%u", prefix, reg->idx[0].offset); 2694 else 2695 sprintf(register_name, "%s_c[%u]", prefix, reg->idx[0].offset); 2696 } 2697 } 2698 break; 2699 2700 case WINED3DSPR_CONSTINT: 2701 sprintf(register_name, "%s_i[%u]", prefix, reg->idx[0].offset); 2702 break; 2703 2704 case WINED3DSPR_CONSTBOOL: 2705 sprintf(register_name, "%s_b[%u]", prefix, reg->idx[0].offset); 2706 break; 2707 2708 case WINED3DSPR_TEXTURE: /* case WINED3DSPR_ADDR: */ 2709 if (version->type == WINED3D_SHADER_TYPE_PIXEL) 2710 sprintf(register_name, "T%u", reg->idx[0].offset); 2711 else 2712 sprintf(register_name, "A%u", reg->idx[0].offset); 2713 break; 2714 2715 case WINED3DSPR_LOOP: 2716 sprintf(register_name, "aL%u", ins->ctx->state->current_loop_reg - 1); 2717 break; 2718 2719 case WINED3DSPR_SAMPLER: 2720 sprintf(register_name, "%s_sampler%u", prefix, reg->idx[0].offset); 2721 break; 2722 2723 case WINED3DSPR_COLOROUT: 2724 /* FIXME: should check dual_buffers when dual blending is enabled */ 2725 if (reg->idx[0].offset >= gl_info->limits.buffers) 2726 WARN("Write to render target %u, only %d supported.\n", 2727 reg->idx[0].offset, gl_info->limits.buffers); 2728 2729 sprintf(register_name, needs_legacy_glsl_syntax(gl_info) ? "gl_FragData[%u]" : "ps_out%u", 2730 reg->idx[0].offset); 2731 break; 2732 2733 case WINED3DSPR_RASTOUT: 2734 sprintf(register_name, "%s", hwrastout_reg_names[reg->idx[0].offset]); 2735 break; 2736 2737 case WINED3DSPR_DEPTHOUT: 2738 case WINED3DSPR_DEPTHOUTGE: 2739 case WINED3DSPR_DEPTHOUTLE: 2740 sprintf(register_name, "gl_FragDepth"); 2741 break; 2742 2743 case WINED3DSPR_ATTROUT: 2744 if (!reg->idx[0].offset) 2745 sprintf(register_name, "%s_out[8]", prefix); 2746 else 2747 sprintf(register_name, "%s_out[9]", prefix); 2748 break; 2749 2750 case WINED3DSPR_TEXCRDOUT: 2751 /* Vertex shaders >= 3.0: WINED3DSPR_OUTPUT */ 2752 if (reg->idx[0].rel_addr) 2753 sprintf(register_name, "%s_out[%s + %u]", 2754 prefix, rel_param0.param_str, reg->idx[0].offset); 2755 else 2756 sprintf(register_name, "%s_out[%u]", prefix, reg->idx[0].offset); 2757 break; 2758 2759 case WINED3DSPR_MISCTYPE: 2760 if (!reg->idx[0].offset) 2761 { 2762 /* vPos */ 2763 sprintf(register_name, "vpos"); 2764 } 2765 else if (reg->idx[0].offset == 1) 2766 { 2767 /* Note that gl_FrontFacing is a bool, while vFace is 2768 * a float for which the sign determines front/back */ 2769 sprintf(register_name, "(gl_FrontFacing ? 1.0 : -1.0)"); 2770 } 2771 else 2772 { 2773 FIXME("Unhandled misctype register %u.\n", reg->idx[0].offset); 2774 sprintf(register_name, "unrecognized_register"); 2775 } 2776 break; 2777 2778 case WINED3DSPR_IMMCONST: 2779 switch (reg->immconst_type) 2780 { 2781 case WINED3D_IMMCONST_SCALAR: 2782 switch (data_type) 2783 { 2784 case WINED3D_DATA_FLOAT: 2785 if (gl_info->supported[ARB_SHADER_BIT_ENCODING]) 2786 sprintf(register_name, "uintBitsToFloat(%#xu)", reg->u.immconst_data[0]); 2787 else 2788 wined3d_ftoa(*(const float *)reg->u.immconst_data, register_name); 2789 break; 2790 case WINED3D_DATA_INT: 2791 sprintf(register_name, "%#x", reg->u.immconst_data[0]); 2792 break; 2793 case WINED3D_DATA_RESOURCE: 2794 case WINED3D_DATA_SAMPLER: 2795 case WINED3D_DATA_UINT: 2796 sprintf(register_name, "%#xu", reg->u.immconst_data[0]); 2797 break; 2798 default: 2799 sprintf(register_name, "<unhandled data type %#x>", data_type); 2800 break; 2801 } 2802 break; 2803 2804 case WINED3D_IMMCONST_VEC4: 2805 switch (data_type) 2806 { 2807 case WINED3D_DATA_FLOAT: 2808 if (gl_info->supported[ARB_SHADER_BIT_ENCODING]) 2809 { 2810 sprintf(register_name, "uintBitsToFloat(uvec4(%#xu, %#xu, %#xu, %#xu))", 2811 reg->u.immconst_data[0], reg->u.immconst_data[1], 2812 reg->u.immconst_data[2], reg->u.immconst_data[3]); 2813 } 2814 else 2815 { 2816 wined3d_ftoa(*(const float *)®->u.immconst_data[0], imm_str[0]); 2817 wined3d_ftoa(*(const float *)®->u.immconst_data[1], imm_str[1]); 2818 wined3d_ftoa(*(const float *)®->u.immconst_data[2], imm_str[2]); 2819 wined3d_ftoa(*(const float *)®->u.immconst_data[3], imm_str[3]); 2820 sprintf(register_name, "vec4(%s, %s, %s, %s)", 2821 imm_str[0], imm_str[1], imm_str[2], imm_str[3]); 2822 } 2823 break; 2824 case WINED3D_DATA_INT: 2825 sprintf(register_name, "ivec4(%#x, %#x, %#x, %#x)", 2826 reg->u.immconst_data[0], reg->u.immconst_data[1], 2827 reg->u.immconst_data[2], reg->u.immconst_data[3]); 2828 break; 2829 case WINED3D_DATA_RESOURCE: 2830 case WINED3D_DATA_SAMPLER: 2831 case WINED3D_DATA_UINT: 2832 sprintf(register_name, "uvec4(%#xu, %#xu, %#xu, %#xu)", 2833 reg->u.immconst_data[0], reg->u.immconst_data[1], 2834 reg->u.immconst_data[2], reg->u.immconst_data[3]); 2835 break; 2836 default: 2837 sprintf(register_name, "<unhandled data type %#x>", data_type); 2838 break; 2839 } 2840 break; 2841 2842 default: 2843 FIXME("Unhandled immconst type %#x\n", reg->immconst_type); 2844 sprintf(register_name, "<unhandled_immconst_type %#x>", reg->immconst_type); 2845 } 2846 break; 2847 2848 case WINED3DSPR_CONSTBUFFER: 2849 if (reg->idx[1].rel_addr) 2850 sprintf(register_name, "%s_cb%u[%s + %u]", 2851 prefix, reg->idx[0].offset, rel_param1.param_str, reg->idx[1].offset); 2852 else 2853 sprintf(register_name, "%s_cb%u[%u]", prefix, reg->idx[0].offset, reg->idx[1].offset); 2854 break; 2855 2856 case WINED3DSPR_IMMCONSTBUFFER: 2857 if (reg->idx[0].rel_addr) 2858 sprintf(register_name, "%s_icb[%s + %u]", prefix, rel_param0.param_str, reg->idx[0].offset); 2859 else 2860 sprintf(register_name, "%s_icb[%u]", prefix, reg->idx[0].offset); 2861 break; 2862 2863 case WINED3DSPR_PRIMID: 2864 if (version->type == WINED3D_SHADER_TYPE_GEOMETRY) 2865 sprintf(register_name, "gl_PrimitiveIDIn"); 2866 else 2867 sprintf(register_name, "gl_PrimitiveID"); 2868 break; 2869 2870 case WINED3DSPR_IDXTEMP: 2871 if (reg->idx[1].rel_addr) 2872 sprintf(register_name, "X%u[%s + %u]", reg->idx[0].offset, rel_param1.param_str, reg->idx[1].offset); 2873 else 2874 sprintf(register_name, "X%u[%u]", reg->idx[0].offset, reg->idx[1].offset); 2875 break; 2876 2877 case WINED3DSPR_LOCALTHREADINDEX: 2878 shader_glsl_fixup_scalar_register_variable(register_name, 2879 "int(gl_LocalInvocationIndex)", gl_info); 2880 break; 2881 2882 case WINED3DSPR_GSINSTID: 2883 case WINED3DSPR_OUTPOINTID: 2884 shader_glsl_fixup_scalar_register_variable(register_name, 2885 "gl_InvocationID", gl_info); 2886 break; 2887 2888 case WINED3DSPR_THREADID: 2889 sprintf(register_name, "ivec3(gl_GlobalInvocationID)"); 2890 break; 2891 2892 case WINED3DSPR_THREADGROUPID: 2893 sprintf(register_name, "ivec3(gl_WorkGroupID)"); 2894 break; 2895 2896 case WINED3DSPR_LOCALTHREADID: 2897 sprintf(register_name, "ivec3(gl_LocalInvocationID)"); 2898 break; 2899 2900 case WINED3DSPR_FORKINSTID: 2901 case WINED3DSPR_JOININSTID: 2902 shader_glsl_fixup_scalar_register_variable(register_name, 2903 "phase_instance_id", gl_info); 2904 break; 2905 2906 case WINED3DSPR_TESSCOORD: 2907 sprintf(register_name, "gl_TessCoord"); 2908 break; 2909 2910 case WINED3DSPR_OUTCONTROLPOINT: 2911 if (reg->idx[0].rel_addr) 2912 { 2913 if (reg->idx[1].rel_addr) 2914 sprintf(register_name, "shader_out[%s + %u].reg[%s + %u]", 2915 rel_param0.param_str, reg->idx[0].offset, 2916 rel_param1.param_str, reg->idx[1].offset); 2917 else 2918 sprintf(register_name, "shader_out[%s + %u].reg[%u]", 2919 rel_param0.param_str, reg->idx[0].offset, 2920 reg->idx[1].offset); 2921 } 2922 else if (reg->idx[1].rel_addr) 2923 { 2924 sprintf(register_name, "shader_out[%u].reg[%s + %u]", 2925 reg->idx[0].offset, rel_param1.param_str, 2926 reg->idx[1].offset); 2927 } 2928 else 2929 { 2930 sprintf(register_name, "shader_out[%u].reg[%u]", 2931 reg->idx[0].offset, reg->idx[1].offset); 2932 } 2933 break; 2934 2935 case WINED3DSPR_PATCHCONST: 2936 if (version->type == WINED3D_SHADER_TYPE_HULL) 2937 sprintf(register_name, "hs_out[%u]", reg->idx[0].offset); 2938 else 2939 sprintf(register_name, "vpc[%u]", reg->idx[0].offset); 2940 break; 2941 2942 default: 2943 FIXME("Unhandled register type %#x.\n", reg->type); 2944 sprintf(register_name, "unrecognized_register"); 2945 break; 2946 } 2947 } 2948 2949 static void shader_glsl_write_mask_to_str(DWORD write_mask, char *str) 2950 { 2951 *str++ = '.'; 2952 if (write_mask & WINED3DSP_WRITEMASK_0) *str++ = 'x'; 2953 if (write_mask & WINED3DSP_WRITEMASK_1) *str++ = 'y'; 2954 if (write_mask & WINED3DSP_WRITEMASK_2) *str++ = 'z'; 2955 if (write_mask & WINED3DSP_WRITEMASK_3) *str++ = 'w'; 2956 *str = '\0'; 2957 } 2958 2959 /* Get the GLSL write mask for the destination register */ 2960 static DWORD shader_glsl_get_write_mask(const struct wined3d_shader_dst_param *param, char *write_mask) 2961 { 2962 DWORD mask = param->write_mask; 2963 2964 if (shader_is_scalar(¶m->reg)) 2965 { 2966 mask = WINED3DSP_WRITEMASK_0; 2967 *write_mask = '\0'; 2968 } 2969 else 2970 { 2971 shader_glsl_write_mask_to_str(mask, write_mask); 2972 } 2973 2974 return mask; 2975 } 2976 2977 static unsigned int shader_glsl_get_write_mask_size(DWORD write_mask) 2978 { 2979 unsigned int size = 0; 2980 2981 if (write_mask & WINED3DSP_WRITEMASK_0) ++size; 2982 if (write_mask & WINED3DSP_WRITEMASK_1) ++size; 2983 if (write_mask & WINED3DSP_WRITEMASK_2) ++size; 2984 if (write_mask & WINED3DSP_WRITEMASK_3) ++size; 2985 2986 return size; 2987 } 2988 2989 static unsigned int shader_glsl_swizzle_get_component(DWORD swizzle, 2990 unsigned int component_idx) 2991 { 2992 /* swizzle bits fields: wwzzyyxx */ 2993 return (swizzle >> (2 * component_idx)) & 0x3; 2994 } 2995 2996 static void shader_glsl_swizzle_to_str(DWORD swizzle, BOOL fixup, DWORD mask, char *str) 2997 { 2998 /* For registers of type WINED3DDECLTYPE_D3DCOLOR, data is stored as "bgra", 2999 * but addressed as "rgba". To fix this we need to swap the register's x 3000 * and z components. */ 3001 const char *swizzle_chars = fixup ? "zyxw" : "xyzw"; 3002 unsigned int i; 3003 3004 *str++ = '.'; 3005 for (i = 0; i < 4; ++i) 3006 { 3007 if (mask & (WINED3DSP_WRITEMASK_0 << i)) 3008 *str++ = swizzle_chars[shader_glsl_swizzle_get_component(swizzle, i)]; 3009 } 3010 *str = '\0'; 3011 } 3012 3013 static void shader_glsl_get_swizzle(const struct wined3d_shader_src_param *param, 3014 BOOL fixup, DWORD mask, char *swizzle_str) 3015 { 3016 if (shader_is_scalar(¶m->reg)) 3017 *swizzle_str = '\0'; 3018 else 3019 shader_glsl_swizzle_to_str(param->swizzle, fixup, mask, swizzle_str); 3020 } 3021 3022 static void shader_glsl_sprintf_cast(struct wined3d_string_buffer *dst_param, const char *src_param, 3023 enum wined3d_data_type dst_data_type, enum wined3d_data_type src_data_type) 3024 { 3025 if (dst_data_type == src_data_type) 3026 { 3027 string_buffer_sprintf(dst_param, "%s", src_param); 3028 return; 3029 } 3030 3031 if (src_data_type == WINED3D_DATA_FLOAT) 3032 { 3033 switch (dst_data_type) 3034 { 3035 case WINED3D_DATA_INT: 3036 string_buffer_sprintf(dst_param, "floatBitsToInt(%s)", src_param); 3037 return; 3038 case WINED3D_DATA_RESOURCE: 3039 case WINED3D_DATA_SAMPLER: 3040 case WINED3D_DATA_UINT: 3041 string_buffer_sprintf(dst_param, "floatBitsToUint(%s)", src_param); 3042 return; 3043 default: 3044 break; 3045 } 3046 } 3047 3048 if (src_data_type == WINED3D_DATA_UINT && dst_data_type == WINED3D_DATA_FLOAT) 3049 { 3050 string_buffer_sprintf(dst_param, "uintBitsToFloat(%s)", src_param); 3051 return; 3052 } 3053 3054 if (src_data_type == WINED3D_DATA_INT && dst_data_type == WINED3D_DATA_FLOAT) 3055 { 3056 string_buffer_sprintf(dst_param, "intBitsToFloat(%s)", src_param); 3057 return; 3058 } 3059 3060 FIXME("Unhandled cast from %#x to %#x.\n", src_data_type, dst_data_type); 3061 string_buffer_sprintf(dst_param, "%s", src_param); 3062 } 3063 3064 /* From a given parameter token, generate the corresponding GLSL string. 3065 * Also, return the actual register name and swizzle in case the 3066 * caller needs this information as well. */ 3067 static void shader_glsl_add_src_param_ext(const struct wined3d_shader_instruction *ins, 3068 const struct wined3d_shader_src_param *wined3d_src, DWORD mask, struct glsl_src_param *glsl_src, 3069 enum wined3d_data_type data_type) 3070 { 3071 struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; 3072 struct wined3d_string_buffer *reg_name = string_buffer_get(priv->string_buffers); 3073 enum wined3d_data_type param_data_type; 3074 BOOL is_color = FALSE; 3075 char swizzle_str[6]; 3076 3077 glsl_src->reg_name[0] = '\0'; 3078 glsl_src->param_str[0] = '\0'; 3079 swizzle_str[0] = '\0'; 3080 3081 shader_glsl_get_register_name(&wined3d_src->reg, data_type, glsl_src->reg_name, &is_color, ins); 3082 shader_glsl_get_swizzle(wined3d_src, is_color, mask, swizzle_str); 3083 3084 switch (wined3d_src->reg.type) 3085 { 3086 case WINED3DSPR_IMMCONST: 3087 param_data_type = data_type; 3088 break; 3089 case WINED3DSPR_FORKINSTID: 3090 case WINED3DSPR_GSINSTID: 3091 case WINED3DSPR_JOININSTID: 3092 case WINED3DSPR_LOCALTHREADID: 3093 case WINED3DSPR_LOCALTHREADINDEX: 3094 case WINED3DSPR_OUTPOINTID: 3095 case WINED3DSPR_PRIMID: 3096 case WINED3DSPR_THREADGROUPID: 3097 case WINED3DSPR_THREADID: 3098 param_data_type = WINED3D_DATA_INT; 3099 break; 3100 default: 3101 param_data_type = WINED3D_DATA_FLOAT; 3102 break; 3103 } 3104 3105 shader_glsl_sprintf_cast(reg_name, glsl_src->reg_name, data_type, param_data_type); 3106 shader_glsl_gen_modifier(wined3d_src->modifiers, reg_name->buffer, swizzle_str, glsl_src->param_str); 3107 3108 string_buffer_release(priv->string_buffers, reg_name); 3109 } 3110 3111 static void shader_glsl_add_src_param(const struct wined3d_shader_instruction *ins, 3112 const struct wined3d_shader_src_param *wined3d_src, DWORD mask, struct glsl_src_param *glsl_src) 3113 { 3114 shader_glsl_add_src_param_ext(ins, wined3d_src, mask, glsl_src, wined3d_src->reg.data_type); 3115 } 3116 3117 /* From a given parameter token, generate the corresponding GLSL string. 3118 * Also, return the actual register name and swizzle in case the 3119 * caller needs this information as well. */ 3120 static DWORD shader_glsl_add_dst_param(const struct wined3d_shader_instruction *ins, 3121 const struct wined3d_shader_dst_param *wined3d_dst, struct glsl_dst_param *glsl_dst) 3122 { 3123 BOOL is_color = FALSE; 3124 3125 glsl_dst->mask_str[0] = '\0'; 3126 glsl_dst->reg_name[0] = '\0'; 3127 3128 shader_glsl_get_register_name(&wined3d_dst->reg, wined3d_dst->reg.data_type, 3129 glsl_dst->reg_name, &is_color, ins); 3130 return shader_glsl_get_write_mask(wined3d_dst, glsl_dst->mask_str); 3131 } 3132 3133 /* Append the destination part of the instruction to the buffer, return the effective write mask */ 3134 static DWORD shader_glsl_append_dst_ext(struct wined3d_string_buffer *buffer, 3135 const struct wined3d_shader_instruction *ins, const struct wined3d_shader_dst_param *dst, 3136 enum wined3d_data_type data_type) 3137 { 3138 struct glsl_dst_param glsl_dst; 3139 DWORD mask; 3140 3141 if ((mask = shader_glsl_add_dst_param(ins, dst, &glsl_dst))) 3142 { 3143 switch (data_type) 3144 { 3145 case WINED3D_DATA_FLOAT: 3146 shader_addline(buffer, "%s%s = %s(", 3147 glsl_dst.reg_name, glsl_dst.mask_str, shift_glsl_tab[dst->shift]); 3148 break; 3149 case WINED3D_DATA_INT: 3150 shader_addline(buffer, "%s%s = %sintBitsToFloat(", 3151 glsl_dst.reg_name, glsl_dst.mask_str, shift_glsl_tab[dst->shift]); 3152 break; 3153 case WINED3D_DATA_RESOURCE: 3154 case WINED3D_DATA_SAMPLER: 3155 case WINED3D_DATA_UINT: 3156 shader_addline(buffer, "%s%s = %suintBitsToFloat(", 3157 glsl_dst.reg_name, glsl_dst.mask_str, shift_glsl_tab[dst->shift]); 3158 break; 3159 default: 3160 FIXME("Unhandled data type %#x.\n", data_type); 3161 shader_addline(buffer, "%s%s = %s(", 3162 glsl_dst.reg_name, glsl_dst.mask_str, shift_glsl_tab[dst->shift]); 3163 break; 3164 } 3165 } 3166 3167 return mask; 3168 } 3169 3170 /* Append the destination part of the instruction to the buffer, return the effective write mask */ 3171 static DWORD shader_glsl_append_dst(struct wined3d_string_buffer *buffer, const struct wined3d_shader_instruction *ins) 3172 { 3173 return shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], ins->dst[0].reg.data_type); 3174 } 3175 3176 /** Process GLSL instruction modifiers */ 3177 static void shader_glsl_add_instruction_modifiers(const struct wined3d_shader_instruction *ins) 3178 { 3179 struct glsl_dst_param dst_param; 3180 DWORD modifiers; 3181 3182 if (!ins->dst_count) return; 3183 3184 modifiers = ins->dst[0].modifiers; 3185 if (!modifiers) return; 3186 3187 shader_glsl_add_dst_param(ins, &ins->dst[0], &dst_param); 3188 3189 if (modifiers & WINED3DSPDM_SATURATE) 3190 { 3191 /* _SAT means to clamp the value of the register to between 0 and 1 */ 3192 shader_addline(ins->ctx->buffer, "%s%s = clamp(%s%s, 0.0, 1.0);\n", dst_param.reg_name, 3193 dst_param.mask_str, dst_param.reg_name, dst_param.mask_str); 3194 } 3195 3196 if (modifiers & WINED3DSPDM_MSAMPCENTROID) 3197 { 3198 FIXME("_centroid modifier not handled\n"); 3199 } 3200 3201 if (modifiers & WINED3DSPDM_PARTIALPRECISION) 3202 { 3203 /* MSDN says this modifier can be safely ignored, so that's what we'll do. */ 3204 } 3205 } 3206 3207 static const char *shader_glsl_get_rel_op(enum wined3d_shader_rel_op op) 3208 { 3209 switch (op) 3210 { 3211 case WINED3D_SHADER_REL_OP_GT: return ">"; 3212 case WINED3D_SHADER_REL_OP_EQ: return "=="; 3213 case WINED3D_SHADER_REL_OP_GE: return ">="; 3214 case WINED3D_SHADER_REL_OP_LT: return "<"; 3215 case WINED3D_SHADER_REL_OP_NE: return "!="; 3216 case WINED3D_SHADER_REL_OP_LE: return "<="; 3217 default: 3218 FIXME("Unrecognized operator %#x.\n", op); 3219 return "(\?\?)"; 3220 } 3221 } 3222 3223 static BOOL shader_glsl_has_core_grad(const struct wined3d_gl_info *gl_info) 3224 { 3225 return shader_glsl_get_version(gl_info) >= 130 || gl_info->supported[EXT_GPU_SHADER4]; 3226 } 3227 3228 static void shader_glsl_get_coord_size(enum wined3d_shader_resource_type resource_type, 3229 unsigned int *coord_size, unsigned int *deriv_size) 3230 { 3231 const BOOL is_array = resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_1DARRAY 3232 || resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY; 3233 3234 *coord_size = resource_type_info[resource_type].coord_size; 3235 *deriv_size = *coord_size; 3236 if (is_array) 3237 --(*deriv_size); 3238 } 3239 3240 static void shader_glsl_get_sample_function(const struct wined3d_shader_context *ctx, 3241 DWORD resource_idx, DWORD sampler_idx, DWORD flags, struct glsl_sample_function *sample_function) 3242 { 3243 enum wined3d_shader_resource_type resource_type = ctx->reg_maps->resource_info[resource_idx].type; 3244 struct shader_glsl_ctx_priv *priv = ctx->backend_data; 3245 const struct wined3d_gl_info *gl_info = ctx->gl_info; 3246 BOOL legacy_syntax = needs_legacy_glsl_syntax(gl_info); 3247 BOOL shadow = glsl_is_shadow_sampler(ctx->shader, priv->cur_ps_args, resource_idx, sampler_idx); 3248 BOOL projected = flags & WINED3D_GLSL_SAMPLE_PROJECTED; 3249 BOOL texrect = ctx->reg_maps->shader_version.type == WINED3D_SHADER_TYPE_PIXEL 3250 && priv->cur_ps_args->np2_fixup & (1u << resource_idx) 3251 && gl_info->supported[ARB_TEXTURE_RECTANGLE]; 3252 BOOL lod = flags & WINED3D_GLSL_SAMPLE_LOD; 3253 BOOL grad = flags & WINED3D_GLSL_SAMPLE_GRAD; 3254 BOOL offset = flags & WINED3D_GLSL_SAMPLE_OFFSET; 3255 const char *base = "texture", *type_part = "", *suffix = ""; 3256 unsigned int coord_size, deriv_size; 3257 3258 sample_function->data_type = ctx->reg_maps->resource_info[resource_idx].data_type; 3259 sample_function->emulate_lod = WINED3D_SHADER_RESOURCE_NONE; 3260 3261 if (resource_type >= ARRAY_SIZE(resource_type_info)) 3262 { 3263 ERR("Unexpected resource type %#x.\n", resource_type); 3264 resource_type = WINED3D_SHADER_RESOURCE_TEXTURE_2D; 3265 } 3266 3267 /* Note that there's no such thing as a projected cube texture. */ 3268 if (resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_CUBE) 3269 projected = FALSE; 3270 3271 if (shadow && lod) 3272 { 3273 switch (resource_type) 3274 { 3275 /* emulate textureLod(sampler2DArrayShadow, ...) using textureGradOffset */ 3276 case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY: 3277 sample_function->emulate_lod = resource_type; 3278 grad = offset = TRUE; 3279 lod = FALSE; 3280 break; 3281 3282 /* emulate textureLod(samplerCubeShadow, ...) using shadowCubeGrad */ 3283 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBE: 3284 sample_function->emulate_lod = resource_type; 3285 grad = legacy_syntax = TRUE; 3286 lod = FALSE; 3287 break; 3288 3289 default: 3290 break; 3291 } 3292 } 3293 3294 if (legacy_syntax) 3295 { 3296 if (shadow) 3297 base = "shadow"; 3298 3299 type_part = resource_type_info[resource_type].type_part; 3300 if (resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_2D && texrect) 3301 type_part = "2DRect"; 3302 if (!type_part[0] && resource_type != WINED3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY) 3303 FIXME("Unhandled resource type %#x.\n", resource_type); 3304 3305 if (!lod && grad && !shader_glsl_has_core_grad(gl_info)) 3306 { 3307 if (gl_info->supported[ARB_SHADER_TEXTURE_LOD]) 3308 suffix = "ARB"; 3309 else 3310 FIXME("Unsupported grad function.\n"); 3311 } 3312 } 3313 3314 if (flags & WINED3D_GLSL_SAMPLE_LOAD) 3315 { 3316 static const DWORD texel_fetch_flags = WINED3D_GLSL_SAMPLE_LOAD | WINED3D_GLSL_SAMPLE_OFFSET; 3317 if (flags & ~texel_fetch_flags) 3318 ERR("Unexpected flags %#x for texelFetch.\n", flags & ~texel_fetch_flags); 3319 3320 base = "texelFetch"; 3321 type_part = ""; 3322 } 3323 3324 sample_function->name = string_buffer_get(priv->string_buffers); 3325 string_buffer_sprintf(sample_function->name, "%s%s%s%s%s%s", base, type_part, projected ? "Proj" : "", 3326 lod ? "Lod" : grad ? "Grad" : "", offset ? "Offset" : "", suffix); 3327 3328 shader_glsl_get_coord_size(resource_type, &coord_size, &deriv_size); 3329 if (shadow) 3330 ++coord_size; 3331 sample_function->offset_size = offset ? deriv_size : 0; 3332 sample_function->coord_mask = (1u << coord_size) - 1; 3333 sample_function->deriv_mask = (1u << deriv_size) - 1; 3334 sample_function->output_single_component = shadow && !legacy_syntax; 3335 } 3336 3337 static void shader_glsl_release_sample_function(const struct wined3d_shader_context *ctx, 3338 struct glsl_sample_function *sample_function) 3339 { 3340 const struct shader_glsl_ctx_priv *priv = ctx->backend_data; 3341 3342 string_buffer_release(priv->string_buffers, sample_function->name); 3343 } 3344 3345 static void shader_glsl_append_fixup_arg(char *arguments, const char *reg_name, 3346 BOOL sign_fixup, enum fixup_channel_source channel_source) 3347 { 3348 switch(channel_source) 3349 { 3350 case CHANNEL_SOURCE_ZERO: 3351 strcat(arguments, "0.0"); 3352 break; 3353 3354 case CHANNEL_SOURCE_ONE: 3355 strcat(arguments, "1.0"); 3356 break; 3357 3358 case CHANNEL_SOURCE_X: 3359 strcat(arguments, reg_name); 3360 strcat(arguments, ".x"); 3361 break; 3362 3363 case CHANNEL_SOURCE_Y: 3364 strcat(arguments, reg_name); 3365 strcat(arguments, ".y"); 3366 break; 3367 3368 case CHANNEL_SOURCE_Z: 3369 strcat(arguments, reg_name); 3370 strcat(arguments, ".z"); 3371 break; 3372 3373 case CHANNEL_SOURCE_W: 3374 strcat(arguments, reg_name); 3375 strcat(arguments, ".w"); 3376 break; 3377 3378 default: 3379 FIXME("Unhandled channel source %#x\n", channel_source); 3380 strcat(arguments, "undefined"); 3381 break; 3382 } 3383 3384 if (sign_fixup) strcat(arguments, " * 2.0 - 1.0"); 3385 } 3386 3387 static void shader_glsl_color_correction_ext(struct wined3d_string_buffer *buffer, 3388 const char *reg_name, DWORD mask, struct color_fixup_desc fixup) 3389 { 3390 unsigned int mask_size, remaining; 3391 DWORD fixup_mask = 0; 3392 char arguments[256]; 3393 char mask_str[6]; 3394 3395 if (fixup.x_sign_fixup || fixup.x_source != CHANNEL_SOURCE_X) fixup_mask |= WINED3DSP_WRITEMASK_0; 3396 if (fixup.y_sign_fixup || fixup.y_source != CHANNEL_SOURCE_Y) fixup_mask |= WINED3DSP_WRITEMASK_1; 3397 if (fixup.z_sign_fixup || fixup.z_source != CHANNEL_SOURCE_Z) fixup_mask |= WINED3DSP_WRITEMASK_2; 3398 if (fixup.w_sign_fixup || fixup.w_source != CHANNEL_SOURCE_W) fixup_mask |= WINED3DSP_WRITEMASK_3; 3399 if (!(mask &= fixup_mask)) 3400 return; 3401 3402 if (is_complex_fixup(fixup)) 3403 { 3404 enum complex_fixup complex_fixup = get_complex_fixup(fixup); 3405 FIXME("Complex fixup (%#x) not supported\n",complex_fixup); 3406 return; 3407 } 3408 3409 shader_glsl_write_mask_to_str(mask, mask_str); 3410 mask_size = shader_glsl_get_write_mask_size(mask); 3411 3412 arguments[0] = '\0'; 3413 remaining = mask_size; 3414 if (mask & WINED3DSP_WRITEMASK_0) 3415 { 3416 shader_glsl_append_fixup_arg(arguments, reg_name, fixup.x_sign_fixup, fixup.x_source); 3417 if (--remaining) strcat(arguments, ", "); 3418 } 3419 if (mask & WINED3DSP_WRITEMASK_1) 3420 { 3421 shader_glsl_append_fixup_arg(arguments, reg_name, fixup.y_sign_fixup, fixup.y_source); 3422 if (--remaining) strcat(arguments, ", "); 3423 } 3424 if (mask & WINED3DSP_WRITEMASK_2) 3425 { 3426 shader_glsl_append_fixup_arg(arguments, reg_name, fixup.z_sign_fixup, fixup.z_source); 3427 if (--remaining) strcat(arguments, ", "); 3428 } 3429 if (mask & WINED3DSP_WRITEMASK_3) 3430 { 3431 shader_glsl_append_fixup_arg(arguments, reg_name, fixup.w_sign_fixup, fixup.w_source); 3432 if (--remaining) strcat(arguments, ", "); 3433 } 3434 3435 if (mask_size > 1) 3436 shader_addline(buffer, "%s%s = vec%u(%s);\n", reg_name, mask_str, mask_size, arguments); 3437 else 3438 shader_addline(buffer, "%s%s = %s;\n", reg_name, mask_str, arguments); 3439 } 3440 3441 static void shader_glsl_color_correction(const struct wined3d_shader_instruction *ins, struct color_fixup_desc fixup) 3442 { 3443 char reg_name[256]; 3444 BOOL is_color; 3445 3446 shader_glsl_get_register_name(&ins->dst[0].reg, ins->dst[0].reg.data_type, reg_name, &is_color, ins); 3447 shader_glsl_color_correction_ext(ins->ctx->buffer, reg_name, ins->dst[0].write_mask, fixup); 3448 } 3449 3450 static void PRINTF_ATTR(9, 10) shader_glsl_gen_sample_code(const struct wined3d_shader_instruction *ins, 3451 unsigned int sampler_bind_idx, const struct glsl_sample_function *sample_function, DWORD swizzle, 3452 const char *dx, const char *dy, const char *bias, const struct wined3d_shader_texel_offset *offset, 3453 const char *coord_reg_fmt, ...) 3454 { 3455 static const struct wined3d_shader_texel_offset dummy_offset = {0, 0, 0}; 3456 const struct wined3d_shader_version *version = &ins->ctx->reg_maps->shader_version; 3457 char dst_swizzle[6]; 3458 struct color_fixup_desc fixup; 3459 BOOL np2_fixup = FALSE; 3460 va_list args; 3461 int ret; 3462 3463 shader_glsl_swizzle_to_str(swizzle, FALSE, ins->dst[0].write_mask, dst_swizzle); 3464 3465 /* If ARB_texture_swizzle is supported we don't need to do anything here. 3466 * We actually rely on it for vertex shaders and SM4+. */ 3467 if (version->type == WINED3D_SHADER_TYPE_PIXEL && version->major < 4) 3468 { 3469 const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; 3470 fixup = priv->cur_ps_args->color_fixup[sampler_bind_idx]; 3471 3472 if (priv->cur_ps_args->np2_fixup & (1u << sampler_bind_idx)) 3473 np2_fixup = TRUE; 3474 } 3475 else 3476 { 3477 fixup = COLOR_FIXUP_IDENTITY; 3478 } 3479 3480 shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &ins->dst[0], sample_function->data_type); 3481 3482 if (sample_function->output_single_component) 3483 shader_addline(ins->ctx->buffer, "vec4("); 3484 3485 shader_addline(ins->ctx->buffer, "%s(%s_sampler%u, ", 3486 sample_function->name->buffer, shader_glsl_get_prefix(version->type), sampler_bind_idx); 3487 3488 for (;;) 3489 { 3490 va_start(args, coord_reg_fmt); 3491 ret = shader_vaddline(ins->ctx->buffer, coord_reg_fmt, args); 3492 va_end(args); 3493 if (!ret) 3494 break; 3495 if (!string_buffer_resize(ins->ctx->buffer, ret)) 3496 break; 3497 } 3498 3499 if (np2_fixup) 3500 { 3501 const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; 3502 const unsigned char idx = priv->cur_np2fixup_info->idx[sampler_bind_idx]; 3503 3504 switch (shader_glsl_get_write_mask_size(sample_function->coord_mask)) 3505 { 3506 case 1: 3507 shader_addline(ins->ctx->buffer, " * ps_samplerNP2Fixup[%u].%s", 3508 idx >> 1, (idx % 2) ? "z" : "x"); 3509 break; 3510 case 2: 3511 shader_addline(ins->ctx->buffer, " * ps_samplerNP2Fixup[%u].%s", 3512 idx >> 1, (idx % 2) ? "zw" : "xy"); 3513 break; 3514 case 3: 3515 shader_addline(ins->ctx->buffer, " * vec3(ps_samplerNP2Fixup[%u].%s, 1.0)", 3516 idx >> 1, (idx % 2) ? "zw" : "xy"); 3517 break; 3518 case 4: 3519 shader_addline(ins->ctx->buffer, " * vec4(ps_samplerNP2Fixup[%u].%s, 1.0, 1.0)", 3520 idx >> 1, (idx % 2) ? "zw" : "xy"); 3521 break; 3522 } 3523 } 3524 if (sample_function->emulate_lod) 3525 { 3526 if (strcmp(bias, "0")) FIXME("Don't know how to emulate lod level %s\n", bias); 3527 switch (sample_function->emulate_lod) 3528 { 3529 case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY: 3530 if (!dx) dx = "vec2(0.0, 0.0)"; 3531 if (!dy) dy = "vec2(0.0, 0.0)"; 3532 break; 3533 3534 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBE: 3535 if (!dx) dx = "vec3(0.0, 0.0, 0.0)"; 3536 if (!dy) dy = "vec3(0.0, 0.0, 0.0)"; 3537 break; 3538 3539 default: 3540 break; 3541 } 3542 if (!offset) offset = &dummy_offset; 3543 } 3544 if (dx && dy) 3545 shader_addline(ins->ctx->buffer, ", %s, %s", dx, dy); 3546 else if (bias) 3547 shader_addline(ins->ctx->buffer, ", %s", bias); 3548 if (sample_function->offset_size) 3549 { 3550 int offset_immdata[4] = {offset->u, offset->v, offset->w}; 3551 shader_addline(ins->ctx->buffer, ", "); 3552 shader_glsl_append_imm_ivec(ins->ctx->buffer, offset_immdata, sample_function->offset_size); 3553 } 3554 shader_addline(ins->ctx->buffer, ")"); 3555 3556 if (sample_function->output_single_component) 3557 shader_addline(ins->ctx->buffer, ")"); 3558 3559 shader_addline(ins->ctx->buffer, "%s);\n", dst_swizzle); 3560 3561 if (!is_identity_fixup(fixup)) 3562 shader_glsl_color_correction(ins, fixup); 3563 } 3564 3565 static void shader_glsl_fixup_position(struct wined3d_string_buffer *buffer) 3566 { 3567 /* Write the final position. 3568 * 3569 * OpenGL coordinates specify the center of the pixel while D3D coords 3570 * specify the corner. The offsets are stored in z and w in 3571 * pos_fixup. pos_fixup.y contains 1.0 or -1.0 to turn the rendering 3572 * upside down for offscreen rendering. pos_fixup.x contains 1.0 to allow 3573 * a MAD. */ 3574 shader_addline(buffer, "gl_Position.y = gl_Position.y * pos_fixup.y;\n"); 3575 shader_addline(buffer, "gl_Position.xy += pos_fixup.zw * gl_Position.ww;\n"); 3576 3577 /* Z coord [0;1]->[-1;1] mapping, see comment in get_projection_matrix() 3578 * in utils.c 3579 * 3580 * Basically we want (in homogeneous coordinates) z = z * 2 - 1. However, 3581 * shaders are run before the homogeneous divide, so we have to take the w 3582 * into account: z = ((z / w) * 2 - 1) * w, which is the same as 3583 * z = z * 2 - w. */ 3584 shader_addline(buffer, "gl_Position.z = gl_Position.z * 2.0 - gl_Position.w;\n"); 3585 } 3586 3587 /***************************************************************************** 3588 * Begin processing individual instruction opcodes 3589 ****************************************************************************/ 3590 3591 static void shader_glsl_binop(const struct wined3d_shader_instruction *ins) 3592 { 3593 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 3594 struct glsl_src_param src0_param; 3595 struct glsl_src_param src1_param; 3596 DWORD write_mask; 3597 const char *op; 3598 3599 /* Determine the GLSL operator to use based on the opcode */ 3600 switch (ins->handler_idx) 3601 { 3602 case WINED3DSIH_ADD: op = "+"; break; 3603 case WINED3DSIH_AND: op = "&"; break; 3604 case WINED3DSIH_DIV: op = "/"; break; 3605 case WINED3DSIH_IADD: op = "+"; break; 3606 case WINED3DSIH_ISHL: op = "<<"; break; 3607 case WINED3DSIH_ISHR: op = ">>"; break; 3608 case WINED3DSIH_MUL: op = "*"; break; 3609 case WINED3DSIH_OR: op = "|"; break; 3610 case WINED3DSIH_SUB: op = "-"; break; 3611 case WINED3DSIH_USHR: op = ">>"; break; 3612 case WINED3DSIH_XOR: op = "^"; break; 3613 default: 3614 op = "<unhandled operator>"; 3615 FIXME("Opcode %s not yet handled in GLSL.\n", debug_d3dshaderinstructionhandler(ins->handler_idx)); 3616 break; 3617 } 3618 3619 write_mask = shader_glsl_append_dst(buffer, ins); 3620 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 3621 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 3622 shader_addline(buffer, "%s %s %s);\n", src0_param.param_str, op, src1_param.param_str); 3623 } 3624 3625 static void shader_glsl_relop(const struct wined3d_shader_instruction *ins) 3626 { 3627 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 3628 struct glsl_src_param src0_param; 3629 struct glsl_src_param src1_param; 3630 unsigned int mask_size; 3631 DWORD write_mask; 3632 const char *op; 3633 3634 write_mask = shader_glsl_append_dst(buffer, ins); 3635 mask_size = shader_glsl_get_write_mask_size(write_mask); 3636 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 3637 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 3638 3639 if (mask_size > 1) 3640 { 3641 switch (ins->handler_idx) 3642 { 3643 case WINED3DSIH_EQ: op = "equal"; break; 3644 case WINED3DSIH_IEQ: op = "equal"; break; 3645 case WINED3DSIH_GE: op = "greaterThanEqual"; break; 3646 case WINED3DSIH_IGE: op = "greaterThanEqual"; break; 3647 case WINED3DSIH_UGE: op = "greaterThanEqual"; break; 3648 case WINED3DSIH_LT: op = "lessThan"; break; 3649 case WINED3DSIH_ILT: op = "lessThan"; break; 3650 case WINED3DSIH_ULT: op = "lessThan"; break; 3651 case WINED3DSIH_NE: op = "notEqual"; break; 3652 case WINED3DSIH_INE: op = "notEqual"; break; 3653 default: 3654 op = "<unhandled operator>"; 3655 ERR("Unhandled opcode %#x.\n", ins->handler_idx); 3656 break; 3657 } 3658 3659 shader_addline(buffer, "uvec%u(%s(%s, %s)) * 0xffffffffu);\n", 3660 mask_size, op, src0_param.param_str, src1_param.param_str); 3661 } 3662 else 3663 { 3664 switch (ins->handler_idx) 3665 { 3666 case WINED3DSIH_EQ: op = "=="; break; 3667 case WINED3DSIH_IEQ: op = "=="; break; 3668 case WINED3DSIH_GE: op = ">="; break; 3669 case WINED3DSIH_IGE: op = ">="; break; 3670 case WINED3DSIH_UGE: op = ">="; break; 3671 case WINED3DSIH_LT: op = "<"; break; 3672 case WINED3DSIH_ILT: op = "<"; break; 3673 case WINED3DSIH_ULT: op = "<"; break; 3674 case WINED3DSIH_NE: op = "!="; break; 3675 case WINED3DSIH_INE: op = "!="; break; 3676 default: 3677 op = "<unhandled operator>"; 3678 ERR("Unhandled opcode %#x.\n", ins->handler_idx); 3679 break; 3680 } 3681 3682 shader_addline(buffer, "%s %s %s ? 0xffffffffu : 0u);\n", 3683 src0_param.param_str, op, src1_param.param_str); 3684 } 3685 } 3686 3687 static void shader_glsl_unary_op(const struct wined3d_shader_instruction *ins) 3688 { 3689 struct glsl_src_param src_param; 3690 DWORD write_mask; 3691 const char *op; 3692 3693 switch (ins->handler_idx) 3694 { 3695 case WINED3DSIH_INEG: op = "-"; break; 3696 case WINED3DSIH_NOT: op = "~"; break; 3697 default: 3698 op = "<unhandled operator>"; 3699 ERR("Unhandled opcode %s.\n", 3700 debug_d3dshaderinstructionhandler(ins->handler_idx)); 3701 break; 3702 } 3703 3704 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); 3705 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param); 3706 shader_addline(ins->ctx->buffer, "%s%s);\n", op, src_param.param_str); 3707 } 3708 3709 static void shader_glsl_mul_extended(const struct wined3d_shader_instruction *ins) 3710 { 3711 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 3712 struct glsl_src_param src0_param; 3713 struct glsl_src_param src1_param; 3714 DWORD write_mask; 3715 3716 /* If we have ARB_gpu_shader5, we can use imulExtended() / umulExtended(). 3717 * If not, we can emulate it. */ 3718 if (ins->dst[0].reg.type != WINED3DSPR_NULL) 3719 FIXME("64-bit integer multiplies not implemented.\n"); 3720 3721 if (ins->dst[1].reg.type != WINED3DSPR_NULL) 3722 { 3723 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1], ins->dst[1].reg.data_type); 3724 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 3725 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 3726 3727 shader_addline(ins->ctx->buffer, "%s * %s);\n", 3728 src0_param.param_str, src1_param.param_str); 3729 } 3730 } 3731 3732 static void shader_glsl_udiv(const struct wined3d_shader_instruction *ins) 3733 { 3734 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 3735 struct glsl_src_param src0_param, src1_param; 3736 DWORD write_mask; 3737 3738 if (ins->dst[0].reg.type != WINED3DSPR_NULL) 3739 { 3740 if (ins->dst[1].reg.type != WINED3DSPR_NULL) 3741 { 3742 char dst_mask[6]; 3743 3744 write_mask = shader_glsl_get_write_mask(&ins->dst[0], dst_mask); 3745 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 3746 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 3747 shader_addline(buffer, "tmp0%s = uintBitsToFloat(%s / %s);\n", 3748 dst_mask, src0_param.param_str, src1_param.param_str); 3749 3750 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1], ins->dst[1].reg.data_type); 3751 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 3752 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 3753 shader_addline(buffer, "%s %% %s);\n", src0_param.param_str, src1_param.param_str); 3754 3755 shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], WINED3D_DATA_FLOAT); 3756 shader_addline(buffer, "tmp0%s);\n", dst_mask); 3757 } 3758 else 3759 { 3760 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], ins->dst[0].reg.data_type); 3761 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 3762 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 3763 shader_addline(buffer, "%s / %s);\n", src0_param.param_str, src1_param.param_str); 3764 } 3765 } 3766 else if (ins->dst[1].reg.type != WINED3DSPR_NULL) 3767 { 3768 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1], ins->dst[1].reg.data_type); 3769 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 3770 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 3771 shader_addline(buffer, "%s %% %s);\n", src0_param.param_str, src1_param.param_str); 3772 } 3773 } 3774 3775 /* Process the WINED3DSIO_MOV opcode using GLSL (dst = src) */ 3776 static void shader_glsl_mov(const struct wined3d_shader_instruction *ins) 3777 { 3778 const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; 3779 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 3780 struct glsl_src_param src0_param; 3781 DWORD write_mask; 3782 3783 write_mask = shader_glsl_append_dst(buffer, ins); 3784 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 3785 3786 /* In vs_1_1 WINED3DSIO_MOV can write to the address register. In later 3787 * shader versions WINED3DSIO_MOVA is used for this. */ 3788 if (ins->ctx->reg_maps->shader_version.major == 1 3789 && ins->ctx->reg_maps->shader_version.type == WINED3D_SHADER_TYPE_VERTEX 3790 && ins->dst[0].reg.type == WINED3DSPR_ADDR) 3791 { 3792 /* This is a simple floor() */ 3793 unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask); 3794 if (mask_size > 1) { 3795 shader_addline(buffer, "ivec%d(floor(%s)));\n", mask_size, src0_param.param_str); 3796 } else { 3797 shader_addline(buffer, "int(floor(%s)));\n", src0_param.param_str); 3798 } 3799 } 3800 else if (ins->handler_idx == WINED3DSIH_MOVA) 3801 { 3802 unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask); 3803 3804 if (shader_glsl_get_version(gl_info) >= 130 || gl_info->supported[EXT_GPU_SHADER4]) 3805 { 3806 if (mask_size > 1) 3807 shader_addline(buffer, "ivec%d(round(%s)));\n", mask_size, src0_param.param_str); 3808 else 3809 shader_addline(buffer, "int(round(%s)));\n", src0_param.param_str); 3810 } 3811 else 3812 { 3813 if (mask_size > 1) 3814 shader_addline(buffer, "ivec%d(floor(abs(%s) + vec%d(0.5)) * sign(%s)));\n", 3815 mask_size, src0_param.param_str, mask_size, src0_param.param_str); 3816 else 3817 shader_addline(buffer, "int(floor(abs(%s) + 0.5) * sign(%s)));\n", 3818 src0_param.param_str, src0_param.param_str); 3819 } 3820 } 3821 else 3822 { 3823 shader_addline(buffer, "%s);\n", src0_param.param_str); 3824 } 3825 } 3826 3827 /* Process the dot product operators DP3 and DP4 in GLSL (dst = dot(src0, src1)) */ 3828 static void shader_glsl_dot(const struct wined3d_shader_instruction *ins) 3829 { 3830 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 3831 struct glsl_src_param src0_param; 3832 struct glsl_src_param src1_param; 3833 DWORD dst_write_mask, src_write_mask; 3834 unsigned int dst_size; 3835 3836 dst_write_mask = shader_glsl_append_dst(buffer, ins); 3837 dst_size = shader_glsl_get_write_mask_size(dst_write_mask); 3838 3839 /* dp4 works on vec4, dp3 on vec3, etc. */ 3840 if (ins->handler_idx == WINED3DSIH_DP4) 3841 src_write_mask = WINED3DSP_WRITEMASK_ALL; 3842 else if (ins->handler_idx == WINED3DSIH_DP3) 3843 src_write_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 3844 else 3845 src_write_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1; 3846 3847 shader_glsl_add_src_param(ins, &ins->src[0], src_write_mask, &src0_param); 3848 shader_glsl_add_src_param(ins, &ins->src[1], src_write_mask, &src1_param); 3849 3850 if (dst_size > 1) { 3851 shader_addline(buffer, "vec%d(dot(%s, %s)));\n", dst_size, src0_param.param_str, src1_param.param_str); 3852 } else { 3853 shader_addline(buffer, "dot(%s, %s));\n", src0_param.param_str, src1_param.param_str); 3854 } 3855 } 3856 3857 /* Note that this instruction has some restrictions. The destination write mask 3858 * can't contain the w component, and the source swizzles have to be .xyzw */ 3859 static void shader_glsl_cross(const struct wined3d_shader_instruction *ins) 3860 { 3861 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 3862 struct glsl_src_param src0_param; 3863 struct glsl_src_param src1_param; 3864 char dst_mask[6]; 3865 3866 shader_glsl_get_write_mask(&ins->dst[0], dst_mask); 3867 shader_glsl_append_dst(ins->ctx->buffer, ins); 3868 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); 3869 shader_glsl_add_src_param(ins, &ins->src[1], src_mask, &src1_param); 3870 shader_addline(ins->ctx->buffer, "cross(%s, %s)%s);\n", src0_param.param_str, src1_param.param_str, dst_mask); 3871 } 3872 3873 static void shader_glsl_cut(const struct wined3d_shader_instruction *ins) 3874 { 3875 unsigned int stream = ins->handler_idx == WINED3DSIH_CUT ? 0 : ins->src[0].reg.idx[0].offset; 3876 3877 if (!stream) 3878 shader_addline(ins->ctx->buffer, "EndPrimitive();\n"); 3879 else 3880 FIXME("Unhandled primitive stream %u.\n", stream); 3881 } 3882 3883 /* Process the WINED3DSIO_POW instruction in GLSL (dst = |src0|^src1) 3884 * Src0 and src1 are scalars. Note that D3D uses the absolute of src0, while 3885 * GLSL uses the value as-is. */ 3886 static void shader_glsl_pow(const struct wined3d_shader_instruction *ins) 3887 { 3888 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 3889 struct glsl_src_param src0_param; 3890 struct glsl_src_param src1_param; 3891 DWORD dst_write_mask; 3892 unsigned int dst_size; 3893 3894 dst_write_mask = shader_glsl_append_dst(buffer, ins); 3895 dst_size = shader_glsl_get_write_mask_size(dst_write_mask); 3896 3897 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); 3898 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param); 3899 3900 if (dst_size > 1) 3901 { 3902 shader_addline(buffer, "vec%u(%s == 0.0 ? 1.0 : pow(abs(%s), %s)));\n", 3903 dst_size, src1_param.param_str, src0_param.param_str, src1_param.param_str); 3904 } 3905 else 3906 { 3907 shader_addline(buffer, "%s == 0.0 ? 1.0 : pow(abs(%s), %s));\n", 3908 src1_param.param_str, src0_param.param_str, src1_param.param_str); 3909 } 3910 } 3911 3912 /* Map the opcode 1-to-1 to the GL code (arg->dst = instruction(src0, src1, ...) */ 3913 static void shader_glsl_map2gl(const struct wined3d_shader_instruction *ins) 3914 { 3915 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 3916 struct glsl_src_param src_param; 3917 const char *instruction; 3918 DWORD write_mask; 3919 unsigned i; 3920 3921 /* Determine the GLSL function to use based on the opcode */ 3922 /* TODO: Possibly make this a table for faster lookups */ 3923 switch (ins->handler_idx) 3924 { 3925 case WINED3DSIH_ABS: instruction = "abs"; break; 3926 case WINED3DSIH_BFREV: instruction = "bitfieldReverse"; break; 3927 case WINED3DSIH_COUNTBITS: instruction = "bitCount"; break; 3928 case WINED3DSIH_DSX: instruction = "dFdx"; break; 3929 case WINED3DSIH_DSX_COARSE: instruction = "dFdxCoarse"; break; 3930 case WINED3DSIH_DSX_FINE: instruction = "dFdxFine"; break; 3931 case WINED3DSIH_DSY: instruction = "ycorrection.y * dFdy"; break; 3932 case WINED3DSIH_DSY_COARSE: instruction = "ycorrection.y * dFdyCoarse"; break; 3933 case WINED3DSIH_DSY_FINE: instruction = "ycorrection.y * dFdyFine"; break; 3934 case WINED3DSIH_FIRSTBIT_HI: instruction = "findMSB"; break; 3935 case WINED3DSIH_FIRSTBIT_LO: instruction = "findLSB"; break; 3936 case WINED3DSIH_FIRSTBIT_SHI: instruction = "findMSB"; break; 3937 case WINED3DSIH_FRC: instruction = "fract"; break; 3938 case WINED3DSIH_IMAX: instruction = "max"; break; 3939 case WINED3DSIH_IMIN: instruction = "min"; break; 3940 case WINED3DSIH_MAX: instruction = "max"; break; 3941 case WINED3DSIH_MIN: instruction = "min"; break; 3942 case WINED3DSIH_ROUND_NE: instruction = "roundEven"; break; 3943 case WINED3DSIH_ROUND_NI: instruction = "floor"; break; 3944 case WINED3DSIH_ROUND_PI: instruction = "ceil"; break; 3945 case WINED3DSIH_ROUND_Z: instruction = "trunc"; break; 3946 case WINED3DSIH_SQRT: instruction = "sqrt"; break; 3947 case WINED3DSIH_UMAX: instruction = "max"; break; 3948 case WINED3DSIH_UMIN: instruction = "min"; break; 3949 default: instruction = ""; 3950 ERR("Opcode %s not yet handled in GLSL.\n", debug_d3dshaderinstructionhandler(ins->handler_idx)); 3951 break; 3952 } 3953 3954 write_mask = shader_glsl_append_dst(buffer, ins); 3955 3956 /* In D3D bits are numbered from the most significant bit. */ 3957 if (ins->handler_idx == WINED3DSIH_FIRSTBIT_HI || ins->handler_idx == WINED3DSIH_FIRSTBIT_SHI) 3958 shader_addline(buffer, "31 - "); 3959 shader_addline(buffer, "%s(", instruction); 3960 3961 if (ins->src_count) 3962 { 3963 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param); 3964 shader_addline(buffer, "%s", src_param.param_str); 3965 for (i = 1; i < ins->src_count; ++i) 3966 { 3967 shader_glsl_add_src_param(ins, &ins->src[i], write_mask, &src_param); 3968 shader_addline(buffer, ", %s", src_param.param_str); 3969 } 3970 } 3971 3972 shader_addline(buffer, "));\n"); 3973 } 3974 3975 static void shader_glsl_float16(const struct wined3d_shader_instruction *ins) 3976 { 3977 struct wined3d_shader_dst_param dst; 3978 struct glsl_src_param src; 3979 DWORD write_mask; 3980 const char *fmt; 3981 unsigned int i; 3982 3983 fmt = ins->handler_idx == WINED3DSIH_F16TOF32 3984 ? "unpackHalf2x16(%s).x);\n" : "packHalf2x16(vec2(%s, 0.0)));\n"; 3985 3986 dst = ins->dst[0]; 3987 for (i = 0; i < 4; ++i) 3988 { 3989 dst.write_mask = ins->dst[0].write_mask & (WINED3DSP_WRITEMASK_0 << i); 3990 if (!(write_mask = shader_glsl_append_dst_ext(ins->ctx->buffer, ins, 3991 &dst, dst.reg.data_type))) 3992 continue; 3993 3994 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src); 3995 shader_addline(ins->ctx->buffer, fmt, src.param_str); 3996 } 3997 } 3998 3999 static void shader_glsl_bitwise_op(const struct wined3d_shader_instruction *ins) 4000 { 4001 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 4002 struct wined3d_shader_dst_param dst; 4003 struct glsl_src_param src[4]; 4004 const char *instruction; 4005 BOOL tmp_dst = FALSE; 4006 char mask_char[6]; 4007 unsigned int i, j; 4008 DWORD write_mask; 4009 4010 switch (ins->handler_idx) 4011 { 4012 case WINED3DSIH_BFI: instruction = "bitfieldInsert"; break; 4013 case WINED3DSIH_IBFE: instruction = "bitfieldExtract"; break; 4014 case WINED3DSIH_UBFE: instruction = "bitfieldExtract"; break; 4015 default: 4016 ERR("Unhandled opcode %#x.\n", ins->handler_idx); 4017 return; 4018 } 4019 4020 for (i = 0; i < ins->src_count; ++i) 4021 { 4022 if (ins->dst[0].reg.idx[0].offset == ins->src[i].reg.idx[0].offset 4023 && ins->dst[0].reg.type == ins->src[i].reg.type) 4024 tmp_dst = TRUE; 4025 } 4026 4027 dst = ins->dst[0]; 4028 for (i = 0; i < 4; ++i) 4029 { 4030 dst.write_mask = ins->dst[0].write_mask & (WINED3DSP_WRITEMASK_0 << i); 4031 if (tmp_dst && (write_mask = shader_glsl_get_write_mask(&dst, mask_char))) 4032 shader_addline(buffer, "tmp0%s = %sBitsToFloat(", mask_char, 4033 dst.reg.data_type == WINED3D_DATA_INT ? "int" : "uint"); 4034 else if (!(write_mask = shader_glsl_append_dst_ext(buffer, ins, &dst, dst.reg.data_type))) 4035 continue; 4036 4037 for (j = 0; j < ins->src_count; ++j) 4038 shader_glsl_add_src_param(ins, &ins->src[j], write_mask, &src[j]); 4039 shader_addline(buffer, "%s(", instruction); 4040 for (j = 0; j < ins->src_count - 2; ++j) 4041 shader_addline(buffer, "%s, ", src[ins->src_count - j - 1].param_str); 4042 shader_addline(buffer, "%s & 0x1f, %s & 0x1f));\n", src[1].param_str, src[0].param_str); 4043 } 4044 4045 if (tmp_dst) 4046 { 4047 shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], WINED3D_DATA_FLOAT); 4048 shader_glsl_get_write_mask(&ins->dst[0], mask_char); 4049 shader_addline(buffer, "tmp0%s);\n", mask_char); 4050 } 4051 } 4052 4053 static void shader_glsl_nop(const struct wined3d_shader_instruction *ins) {} 4054 4055 static void shader_glsl_nrm(const struct wined3d_shader_instruction *ins) 4056 { 4057 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 4058 struct glsl_src_param src_param; 4059 unsigned int mask_size; 4060 DWORD write_mask; 4061 char dst_mask[6]; 4062 4063 write_mask = shader_glsl_get_write_mask(ins->dst, dst_mask); 4064 mask_size = shader_glsl_get_write_mask_size(write_mask); 4065 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param); 4066 4067 shader_addline(buffer, "tmp0.x = dot(%s, %s);\n", 4068 src_param.param_str, src_param.param_str); 4069 shader_glsl_append_dst(buffer, ins); 4070 4071 if (mask_size > 1) 4072 { 4073 shader_addline(buffer, "tmp0.x == 0.0 ? vec%u(0.0) : (%s * inversesqrt(tmp0.x)));\n", 4074 mask_size, src_param.param_str); 4075 } 4076 else 4077 { 4078 shader_addline(buffer, "tmp0.x == 0.0 ? 0.0 : (%s * inversesqrt(tmp0.x)));\n", 4079 src_param.param_str); 4080 } 4081 } 4082 4083 static void shader_glsl_scalar_op(const struct wined3d_shader_instruction *ins) 4084 { 4085 DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major, 4086 ins->ctx->reg_maps->shader_version.minor); 4087 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 4088 struct glsl_src_param src0_param; 4089 const char *prefix, *suffix; 4090 unsigned int dst_size; 4091 DWORD dst_write_mask; 4092 4093 dst_write_mask = shader_glsl_append_dst(buffer, ins); 4094 dst_size = shader_glsl_get_write_mask_size(dst_write_mask); 4095 4096 if (shader_version < WINED3D_SHADER_VERSION(4, 0)) 4097 dst_write_mask = WINED3DSP_WRITEMASK_3; 4098 4099 shader_glsl_add_src_param(ins, &ins->src[0], dst_write_mask, &src0_param); 4100 4101 switch (ins->handler_idx) 4102 { 4103 case WINED3DSIH_EXP: 4104 case WINED3DSIH_EXPP: 4105 prefix = "exp2("; 4106 suffix = ")"; 4107 break; 4108 4109 case WINED3DSIH_LOG: 4110 case WINED3DSIH_LOGP: 4111 prefix = "log2(abs("; 4112 suffix = "))"; 4113 break; 4114 4115 case WINED3DSIH_RCP: 4116 prefix = "1.0 / "; 4117 suffix = ""; 4118 break; 4119 4120 case WINED3DSIH_RSQ: 4121 prefix = "inversesqrt(abs("; 4122 suffix = "))"; 4123 break; 4124 4125 default: 4126 prefix = ""; 4127 suffix = ""; 4128 FIXME("Unhandled instruction %#x.\n", ins->handler_idx); 4129 break; 4130 } 4131 4132 if (dst_size > 1 && shader_version < WINED3D_SHADER_VERSION(4, 0)) 4133 shader_addline(buffer, "vec%u(%s%s%s));\n", dst_size, prefix, src0_param.param_str, suffix); 4134 else 4135 shader_addline(buffer, "%s%s%s);\n", prefix, src0_param.param_str, suffix); 4136 } 4137 4138 /** Process the WINED3DSIO_EXPP instruction in GLSL: 4139 * For shader model 1.x, do the following (and honor the writemask, so use a temporary variable): 4140 * dst.x = 2^(floor(src)) 4141 * dst.y = src - floor(src) 4142 * dst.z = 2^src (partial precision is allowed, but optional) 4143 * dst.w = 1.0; 4144 * For 2.0 shaders, just do this (honoring writemask and swizzle): 4145 * dst = 2^src; (partial precision is allowed, but optional) 4146 */ 4147 static void shader_glsl_expp(const struct wined3d_shader_instruction *ins) 4148 { 4149 if (ins->ctx->reg_maps->shader_version.major < 2) 4150 { 4151 struct glsl_src_param src_param; 4152 char dst_mask[6]; 4153 4154 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &src_param); 4155 4156 shader_addline(ins->ctx->buffer, "tmp0.x = exp2(floor(%s));\n", src_param.param_str); 4157 shader_addline(ins->ctx->buffer, "tmp0.y = %s - floor(%s);\n", src_param.param_str, src_param.param_str); 4158 shader_addline(ins->ctx->buffer, "tmp0.z = exp2(%s);\n", src_param.param_str); 4159 shader_addline(ins->ctx->buffer, "tmp0.w = 1.0;\n"); 4160 4161 shader_glsl_append_dst(ins->ctx->buffer, ins); 4162 shader_glsl_get_write_mask(&ins->dst[0], dst_mask); 4163 shader_addline(ins->ctx->buffer, "tmp0%s);\n", dst_mask); 4164 return; 4165 } 4166 4167 shader_glsl_scalar_op(ins); 4168 } 4169 4170 static void shader_glsl_cast(const struct wined3d_shader_instruction *ins, 4171 const char *vector_constructor, const char *scalar_constructor) 4172 { 4173 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 4174 struct glsl_src_param src_param; 4175 unsigned int mask_size; 4176 DWORD write_mask; 4177 4178 write_mask = shader_glsl_append_dst(buffer, ins); 4179 mask_size = shader_glsl_get_write_mask_size(write_mask); 4180 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param); 4181 4182 if (mask_size > 1) 4183 shader_addline(buffer, "%s%u(%s));\n", vector_constructor, mask_size, src_param.param_str); 4184 else 4185 shader_addline(buffer, "%s(%s));\n", scalar_constructor, src_param.param_str); 4186 } 4187 4188 static void shader_glsl_to_int(const struct wined3d_shader_instruction *ins) 4189 { 4190 shader_glsl_cast(ins, "ivec", "int"); 4191 } 4192 4193 static void shader_glsl_to_uint(const struct wined3d_shader_instruction *ins) 4194 { 4195 shader_glsl_cast(ins, "uvec", "uint"); 4196 } 4197 4198 static void shader_glsl_to_float(const struct wined3d_shader_instruction *ins) 4199 { 4200 shader_glsl_cast(ins, "vec", "float"); 4201 } 4202 4203 /** Process signed comparison opcodes in GLSL. */ 4204 static void shader_glsl_compare(const struct wined3d_shader_instruction *ins) 4205 { 4206 struct glsl_src_param src0_param; 4207 struct glsl_src_param src1_param; 4208 DWORD write_mask; 4209 unsigned int mask_size; 4210 4211 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); 4212 mask_size = shader_glsl_get_write_mask_size(write_mask); 4213 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 4214 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 4215 4216 if (mask_size > 1) { 4217 const char *compare; 4218 4219 switch(ins->handler_idx) 4220 { 4221 case WINED3DSIH_SLT: compare = "lessThan"; break; 4222 case WINED3DSIH_SGE: compare = "greaterThanEqual"; break; 4223 default: compare = ""; 4224 FIXME("Can't handle opcode %s.\n", debug_d3dshaderinstructionhandler(ins->handler_idx)); 4225 } 4226 4227 shader_addline(ins->ctx->buffer, "vec%d(%s(%s, %s)));\n", mask_size, compare, 4228 src0_param.param_str, src1_param.param_str); 4229 } else { 4230 switch(ins->handler_idx) 4231 { 4232 case WINED3DSIH_SLT: 4233 /* Step(src0, src1) is not suitable here because if src0 == src1 SLT is supposed, 4234 * to return 0.0 but step returns 1.0 because step is not < x 4235 * An alternative is a bvec compare padded with an unused second component. 4236 * step(src1 * -1.0, src0 * -1.0) is not an option because it suffers from the same 4237 * issue. Playing with not() is not possible either because not() does not accept 4238 * a scalar. 4239 */ 4240 shader_addline(ins->ctx->buffer, "(%s < %s) ? 1.0 : 0.0);\n", 4241 src0_param.param_str, src1_param.param_str); 4242 break; 4243 case WINED3DSIH_SGE: 4244 /* Here we can use the step() function and safe a conditional */ 4245 shader_addline(ins->ctx->buffer, "step(%s, %s));\n", src1_param.param_str, src0_param.param_str); 4246 break; 4247 default: 4248 FIXME("Can't handle opcode %s.\n", debug_d3dshaderinstructionhandler(ins->handler_idx)); 4249 } 4250 4251 } 4252 } 4253 4254 static void shader_glsl_swapc(const struct wined3d_shader_instruction *ins) 4255 { 4256 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 4257 struct wined3d_shader_dst_param dst[2]; 4258 struct glsl_src_param src[3]; 4259 unsigned int i, j, k; 4260 char mask_char[6]; 4261 DWORD write_mask; 4262 BOOL tmp_dst[2]; 4263 4264 for (i = 0; i < ins->dst_count; ++i) 4265 { 4266 tmp_dst[i] = FALSE; 4267 for (j = 0; j < ins->src_count; ++j) 4268 { 4269 if (ins->dst[i].reg.idx[0].offset == ins->src[j].reg.idx[0].offset 4270 && ins->dst[i].reg.type == ins->src[j].reg.type) 4271 tmp_dst[i] = TRUE; 4272 } 4273 } 4274 4275 dst[0] = ins->dst[0]; 4276 dst[1] = ins->dst[1]; 4277 for (i = 0; i < 4; ++i) 4278 { 4279 for (j = 0; j < ARRAY_SIZE(dst); ++j) 4280 { 4281 dst[j].write_mask = ins->dst[j].write_mask & (WINED3DSP_WRITEMASK_0 << i); 4282 if (tmp_dst[j] && (write_mask = shader_glsl_get_write_mask(&dst[j], mask_char))) 4283 shader_addline(buffer, "tmp%u%s = (", j, mask_char); 4284 else if (!(write_mask = shader_glsl_append_dst_ext(buffer, ins, &dst[j], dst[j].reg.data_type))) 4285 continue; 4286 4287 for (k = 0; k < ARRAY_SIZE(src); ++k) 4288 shader_glsl_add_src_param(ins, &ins->src[k], write_mask, &src[k]); 4289 4290 shader_addline(buffer, "%sbool(%s) ? %s : %s);\n", !j ? "!" : "", 4291 src[0].param_str, src[1].param_str, src[2].param_str); 4292 } 4293 } 4294 4295 for (i = 0; i < ARRAY_SIZE(tmp_dst); ++i) 4296 { 4297 if (tmp_dst[i]) 4298 { 4299 shader_glsl_get_write_mask(&ins->dst[i], mask_char); 4300 shader_glsl_append_dst_ext(buffer, ins, &ins->dst[i], ins->dst[i].reg.data_type); 4301 shader_addline(buffer, "tmp%u%s);\n", i, mask_char); 4302 } 4303 } 4304 } 4305 4306 static void shader_glsl_conditional_move(const struct wined3d_shader_instruction *ins) 4307 { 4308 const char *condition_prefix, *condition_suffix; 4309 struct wined3d_shader_dst_param dst; 4310 struct glsl_src_param src0_param; 4311 struct glsl_src_param src1_param; 4312 struct glsl_src_param src2_param; 4313 BOOL temp_destination = FALSE; 4314 DWORD cmp_channel = 0; 4315 unsigned int i, j; 4316 char mask_char[6]; 4317 DWORD write_mask; 4318 4319 switch (ins->handler_idx) 4320 { 4321 case WINED3DSIH_CMP: 4322 condition_prefix = ""; 4323 condition_suffix = " >= 0.0"; 4324 break; 4325 4326 case WINED3DSIH_CND: 4327 condition_prefix = ""; 4328 condition_suffix = " > 0.5"; 4329 break; 4330 4331 case WINED3DSIH_MOVC: 4332 condition_prefix = "bool("; 4333 condition_suffix = ")"; 4334 break; 4335 4336 default: 4337 FIXME("Unhandled instruction %#x.\n", ins->handler_idx); 4338 condition_prefix = "<unhandled prefix>"; 4339 condition_suffix = "<unhandled suffix>"; 4340 break; 4341 } 4342 4343 if (shader_is_scalar(&ins->dst[0].reg) || shader_is_scalar(&ins->src[0].reg)) 4344 { 4345 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); 4346 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 4347 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 4348 shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param); 4349 4350 shader_addline(ins->ctx->buffer, "%s%s%s ? %s : %s);\n", 4351 condition_prefix, src0_param.param_str, condition_suffix, 4352 src1_param.param_str, src2_param.param_str); 4353 return; 4354 } 4355 4356 dst = ins->dst[0]; 4357 4358 /* Splitting the instruction up in multiple lines imposes a problem: 4359 * The first lines may overwrite source parameters of the following lines. 4360 * Deal with that by using a temporary destination register if needed. */ 4361 if ((ins->src[0].reg.idx[0].offset == dst.reg.idx[0].offset 4362 && ins->src[0].reg.type == dst.reg.type) 4363 || (ins->src[1].reg.idx[0].offset == dst.reg.idx[0].offset 4364 && ins->src[1].reg.type == dst.reg.type) 4365 || (ins->src[2].reg.idx[0].offset == dst.reg.idx[0].offset 4366 && ins->src[2].reg.type == dst.reg.type)) 4367 temp_destination = TRUE; 4368 4369 /* Cycle through all source0 channels. */ 4370 for (i = 0; i < 4; ++i) 4371 { 4372 write_mask = 0; 4373 /* Find the destination channels which use the current source0 channel. */ 4374 for (j = 0; j < 4; ++j) 4375 { 4376 if (shader_glsl_swizzle_get_component(ins->src[0].swizzle, j) == i) 4377 { 4378 write_mask |= WINED3DSP_WRITEMASK_0 << j; 4379 cmp_channel = WINED3DSP_WRITEMASK_0 << j; 4380 } 4381 } 4382 dst.write_mask = ins->dst[0].write_mask & write_mask; 4383 4384 if (temp_destination) 4385 { 4386 if (!(write_mask = shader_glsl_get_write_mask(&dst, mask_char))) 4387 continue; 4388 shader_addline(ins->ctx->buffer, "tmp0%s = (", mask_char); 4389 } 4390 else if (!(write_mask = shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &dst, dst.reg.data_type))) 4391 continue; 4392 4393 shader_glsl_add_src_param(ins, &ins->src[0], cmp_channel, &src0_param); 4394 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 4395 shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param); 4396 4397 shader_addline(ins->ctx->buffer, "%s%s%s ? %s : %s);\n", 4398 condition_prefix, src0_param.param_str, condition_suffix, 4399 src1_param.param_str, src2_param.param_str); 4400 } 4401 4402 if (temp_destination) 4403 { 4404 shader_glsl_get_write_mask(&ins->dst[0], mask_char); 4405 shader_glsl_append_dst(ins->ctx->buffer, ins); 4406 shader_addline(ins->ctx->buffer, "tmp0%s);\n", mask_char); 4407 } 4408 } 4409 4410 /** Process the CND opcode in GLSL (dst = (src0 > 0.5) ? src1 : src2) */ 4411 /* For ps 1.1-1.3, only a single component of src0 is used. For ps 1.4 4412 * the compare is done per component of src0. */ 4413 static void shader_glsl_cnd(const struct wined3d_shader_instruction *ins) 4414 { 4415 struct glsl_src_param src0_param; 4416 struct glsl_src_param src1_param; 4417 struct glsl_src_param src2_param; 4418 DWORD write_mask; 4419 DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major, 4420 ins->ctx->reg_maps->shader_version.minor); 4421 4422 if (shader_version < WINED3D_SHADER_VERSION(1, 4)) 4423 { 4424 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); 4425 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); 4426 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 4427 shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param); 4428 4429 if (ins->coissue && ins->dst->write_mask != WINED3DSP_WRITEMASK_3) 4430 shader_addline(ins->ctx->buffer, "%s /* COISSUE! */);\n", src1_param.param_str); 4431 else 4432 shader_addline(ins->ctx->buffer, "%s > 0.5 ? %s : %s);\n", 4433 src0_param.param_str, src1_param.param_str, src2_param.param_str); 4434 return; 4435 } 4436 4437 shader_glsl_conditional_move(ins); 4438 } 4439 4440 /** GLSL code generation for WINED3DSIO_MAD: Multiply the first 2 opcodes, then add the last */ 4441 static void shader_glsl_mad(const struct wined3d_shader_instruction *ins) 4442 { 4443 struct glsl_src_param src0_param; 4444 struct glsl_src_param src1_param; 4445 struct glsl_src_param src2_param; 4446 DWORD write_mask; 4447 4448 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); 4449 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 4450 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 4451 shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param); 4452 shader_addline(ins->ctx->buffer, "(%s * %s) + %s);\n", 4453 src0_param.param_str, src1_param.param_str, src2_param.param_str); 4454 } 4455 4456 /* Handles transforming all WINED3DSIO_M?x? opcodes for 4457 Vertex shaders to GLSL codes */ 4458 static void shader_glsl_mnxn(const struct wined3d_shader_instruction *ins) 4459 { 4460 int i; 4461 int nComponents = 0; 4462 struct wined3d_shader_dst_param tmp_dst = {{0}}; 4463 struct wined3d_shader_src_param tmp_src[2] = {{{0}}}; 4464 struct wined3d_shader_instruction tmp_ins; 4465 4466 memset(&tmp_ins, 0, sizeof(tmp_ins)); 4467 4468 /* Set constants for the temporary argument */ 4469 tmp_ins.ctx = ins->ctx; 4470 tmp_ins.dst_count = 1; 4471 tmp_ins.dst = &tmp_dst; 4472 tmp_ins.src_count = 2; 4473 tmp_ins.src = tmp_src; 4474 4475 switch(ins->handler_idx) 4476 { 4477 case WINED3DSIH_M4x4: 4478 nComponents = 4; 4479 tmp_ins.handler_idx = WINED3DSIH_DP4; 4480 break; 4481 case WINED3DSIH_M4x3: 4482 nComponents = 3; 4483 tmp_ins.handler_idx = WINED3DSIH_DP4; 4484 break; 4485 case WINED3DSIH_M3x4: 4486 nComponents = 4; 4487 tmp_ins.handler_idx = WINED3DSIH_DP3; 4488 break; 4489 case WINED3DSIH_M3x3: 4490 nComponents = 3; 4491 tmp_ins.handler_idx = WINED3DSIH_DP3; 4492 break; 4493 case WINED3DSIH_M3x2: 4494 nComponents = 2; 4495 tmp_ins.handler_idx = WINED3DSIH_DP3; 4496 break; 4497 default: 4498 break; 4499 } 4500 4501 tmp_dst = ins->dst[0]; 4502 tmp_src[0] = ins->src[0]; 4503 tmp_src[1] = ins->src[1]; 4504 for (i = 0; i < nComponents; ++i) 4505 { 4506 tmp_dst.write_mask = WINED3DSP_WRITEMASK_0 << i; 4507 shader_glsl_dot(&tmp_ins); 4508 ++tmp_src[1].reg.idx[0].offset; 4509 } 4510 } 4511 4512 /** 4513 The LRP instruction performs a component-wise linear interpolation 4514 between the second and third operands using the first operand as the 4515 blend factor. Equation: (dst = src2 + src0 * (src1 - src2)) 4516 This is equivalent to mix(src2, src1, src0); 4517 */ 4518 static void shader_glsl_lrp(const struct wined3d_shader_instruction *ins) 4519 { 4520 struct glsl_src_param src0_param; 4521 struct glsl_src_param src1_param; 4522 struct glsl_src_param src2_param; 4523 DWORD write_mask; 4524 4525 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); 4526 4527 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 4528 shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param); 4529 shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param); 4530 4531 shader_addline(ins->ctx->buffer, "mix(%s, %s, %s));\n", 4532 src2_param.param_str, src1_param.param_str, src0_param.param_str); 4533 } 4534 4535 /** Process the WINED3DSIO_LIT instruction in GLSL: 4536 * dst.x = dst.w = 1.0 4537 * dst.y = (src0.x > 0) ? src0.x 4538 * dst.z = (src0.x > 0) ? ((src0.y > 0) ? pow(src0.y, src.w) : 0) : 0 4539 * where src.w is clamped at +- 128 4540 */ 4541 static void shader_glsl_lit(const struct wined3d_shader_instruction *ins) 4542 { 4543 struct glsl_src_param src0_param; 4544 struct glsl_src_param src1_param; 4545 struct glsl_src_param src3_param; 4546 char dst_mask[6]; 4547 4548 shader_glsl_append_dst(ins->ctx->buffer, ins); 4549 shader_glsl_get_write_mask(&ins->dst[0], dst_mask); 4550 4551 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); 4552 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_1, &src1_param); 4553 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &src3_param); 4554 4555 /* The sdk specifies the instruction like this 4556 * dst.x = 1.0; 4557 * if(src.x > 0.0) dst.y = src.x 4558 * else dst.y = 0.0. 4559 * if(src.x > 0.0 && src.y > 0.0) dst.z = pow(src.y, power); 4560 * else dst.z = 0.0; 4561 * dst.w = 1.0; 4562 * (where power = src.w clamped between -128 and 128) 4563 * 4564 * Obviously that has quite a few conditionals in it which we don't like. So the first step is this: 4565 * dst.x = 1.0 ... No further explanation needed 4566 * dst.y = max(src.y, 0.0); ... If x < 0.0, use 0.0, otherwise x. Same as the conditional 4567 * dst.z = x > 0.0 ? pow(max(y, 0.0), p) : 0; ... 0 ^ power is 0, and otherwise we use y anyway 4568 * dst.w = 1.0. ... Nothing fancy. 4569 * 4570 * So we still have one conditional in there. So do this: 4571 * dst.z = pow(max(0.0, src.y) * step(0.0, src.x), power); 4572 * 4573 * step(0.0, x) will return 1 if src.x > 0.0, and 0 otherwise. So if y is 0 we get pow(0.0 * 1.0, power), 4574 * which sets dst.z to 0. If y > 0, but x = 0.0, we get pow(y * 0.0, power), which results in 0 too. 4575 * if both x and y are > 0, we get pow(y * 1.0, power), as it is supposed to. 4576 * 4577 * Unfortunately pow(0.0 ^ 0.0) returns NaN on most GPUs, but lit with src.y = 0 and src.w = 0 returns 4578 * a non-NaN value in dst.z. What we return doesn't matter, as long as it is not NaN. Return 0, which is 4579 * what all Windows HW drivers and GL_ARB_vertex_program's LIT do. 4580 */ 4581 shader_addline(ins->ctx->buffer, 4582 "vec4(1.0, max(%s, 0.0), %s == 0.0 ? 0.0 : " 4583 "pow(max(0.0, %s) * step(0.0, %s), clamp(%s, -128.0, 128.0)), 1.0)%s);\n", 4584 src0_param.param_str, src3_param.param_str, src1_param.param_str, 4585 src0_param.param_str, src3_param.param_str, dst_mask); 4586 } 4587 4588 /** Process the WINED3DSIO_DST instruction in GLSL: 4589 * dst.x = 1.0 4590 * dst.y = src0.x * src0.y 4591 * dst.z = src0.z 4592 * dst.w = src1.w 4593 */ 4594 static void shader_glsl_dst(const struct wined3d_shader_instruction *ins) 4595 { 4596 struct glsl_src_param src0y_param; 4597 struct glsl_src_param src0z_param; 4598 struct glsl_src_param src1y_param; 4599 struct glsl_src_param src1w_param; 4600 char dst_mask[6]; 4601 4602 shader_glsl_append_dst(ins->ctx->buffer, ins); 4603 shader_glsl_get_write_mask(&ins->dst[0], dst_mask); 4604 4605 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_1, &src0y_param); 4606 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_2, &src0z_param); 4607 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_1, &src1y_param); 4608 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_3, &src1w_param); 4609 4610 shader_addline(ins->ctx->buffer, "vec4(1.0, %s * %s, %s, %s))%s;\n", 4611 src0y_param.param_str, src1y_param.param_str, src0z_param.param_str, src1w_param.param_str, dst_mask); 4612 } 4613 4614 /** Process the WINED3DSIO_SINCOS instruction in GLSL: 4615 * VS 2.0 requires that specific cosine and sine constants be passed to this instruction so the hardware 4616 * can handle it. But, these functions are built-in for GLSL, so we can just ignore the last 2 params. 4617 * 4618 * dst.x = cos(src0.?) 4619 * dst.y = sin(src0.?) 4620 * dst.z = dst.z 4621 * dst.w = dst.w 4622 */ 4623 static void shader_glsl_sincos(const struct wined3d_shader_instruction *ins) 4624 { 4625 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 4626 struct glsl_src_param src0_param; 4627 DWORD write_mask; 4628 4629 if (ins->ctx->reg_maps->shader_version.major < 4) 4630 { 4631 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); 4632 4633 write_mask = shader_glsl_append_dst(buffer, ins); 4634 switch (write_mask) 4635 { 4636 case WINED3DSP_WRITEMASK_0: 4637 shader_addline(buffer, "cos(%s));\n", src0_param.param_str); 4638 break; 4639 4640 case WINED3DSP_WRITEMASK_1: 4641 shader_addline(buffer, "sin(%s));\n", src0_param.param_str); 4642 break; 4643 4644 case (WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1): 4645 shader_addline(buffer, "vec2(cos(%s), sin(%s)));\n", 4646 src0_param.param_str, src0_param.param_str); 4647 break; 4648 4649 default: 4650 ERR("Write mask should be .x, .y or .xy\n"); 4651 break; 4652 } 4653 4654 return; 4655 } 4656 4657 if (ins->dst[0].reg.type != WINED3DSPR_NULL) 4658 { 4659 4660 if (ins->dst[1].reg.type != WINED3DSPR_NULL) 4661 { 4662 char dst_mask[6]; 4663 4664 write_mask = shader_glsl_get_write_mask(&ins->dst[0], dst_mask); 4665 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 4666 shader_addline(buffer, "tmp0%s = sin(%s);\n", dst_mask, src0_param.param_str); 4667 4668 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1], ins->dst[1].reg.data_type); 4669 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 4670 shader_addline(buffer, "cos(%s));\n", src0_param.param_str); 4671 4672 shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], ins->dst[0].reg.data_type); 4673 shader_addline(buffer, "tmp0%s);\n", dst_mask); 4674 } 4675 else 4676 { 4677 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], ins->dst[0].reg.data_type); 4678 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 4679 shader_addline(buffer, "sin(%s));\n", src0_param.param_str); 4680 } 4681 } 4682 else if (ins->dst[1].reg.type != WINED3DSPR_NULL) 4683 { 4684 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1], ins->dst[1].reg.data_type); 4685 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 4686 shader_addline(buffer, "cos(%s));\n", src0_param.param_str); 4687 } 4688 } 4689 4690 /* sgn in vs_2_0 has 2 extra parameters(registers for temporary storage) which we don't use 4691 * here. But those extra parameters require a dedicated function for sgn, since map2gl would 4692 * generate invalid code 4693 */ 4694 static void shader_glsl_sgn(const struct wined3d_shader_instruction *ins) 4695 { 4696 struct glsl_src_param src0_param; 4697 DWORD write_mask; 4698 4699 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); 4700 shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param); 4701 4702 shader_addline(ins->ctx->buffer, "sign(%s));\n", src0_param.param_str); 4703 } 4704 4705 /** Process the WINED3DSIO_LOOP instruction in GLSL: 4706 * Start a for() loop where src1.y is the initial value of aL, 4707 * increment aL by src1.z for a total of src1.x iterations. 4708 * Need to use a temporary variable for this operation. 4709 */ 4710 /* FIXME: I don't think nested loops will work correctly this way. */ 4711 static void shader_glsl_loop(const struct wined3d_shader_instruction *ins) 4712 { 4713 struct wined3d_shader_parser_state *state = ins->ctx->state; 4714 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 4715 const struct wined3d_shader *shader = ins->ctx->shader; 4716 const struct wined3d_shader_lconst *constant; 4717 struct glsl_src_param src1_param; 4718 const DWORD *control_values = NULL; 4719 4720 if (ins->ctx->reg_maps->shader_version.major < 4) 4721 { 4722 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_ALL, &src1_param); 4723 4724 /* Try to hardcode the loop control parameters if possible. Direct3D 9 4725 * class hardware doesn't support real varying indexing, but Microsoft 4726 * designed this feature for Shader model 2.x+. If the loop control is 4727 * known at compile time, the GLSL compiler can unroll the loop, and 4728 * replace indirect addressing with direct addressing. */ 4729 if (ins->src[1].reg.type == WINED3DSPR_CONSTINT) 4730 { 4731 LIST_FOR_EACH_ENTRY(constant, &shader->constantsI, struct wined3d_shader_lconst, entry) 4732 { 4733 if (constant->idx == ins->src[1].reg.idx[0].offset) 4734 { 4735 control_values = constant->value; 4736 break; 4737 } 4738 } 4739 } 4740 4741 if (control_values) 4742 { 4743 struct wined3d_shader_loop_control loop_control; 4744 loop_control.count = control_values[0]; 4745 loop_control.start = control_values[1]; 4746 loop_control.step = (int)control_values[2]; 4747 4748 if (loop_control.step > 0) 4749 { 4750 shader_addline(buffer, "for (aL%u = %u; aL%u < (%u * %d + %u); aL%u += %d)\n{\n", 4751 state->current_loop_depth, loop_control.start, 4752 state->current_loop_depth, loop_control.count, loop_control.step, loop_control.start, 4753 state->current_loop_depth, loop_control.step); 4754 } 4755 else if (loop_control.step < 0) 4756 { 4757 shader_addline(buffer, "for (aL%u = %u; aL%u > (%u * %d + %u); aL%u += %d)\n{\n", 4758 state->current_loop_depth, loop_control.start, 4759 state->current_loop_depth, loop_control.count, loop_control.step, loop_control.start, 4760 state->current_loop_depth, loop_control.step); 4761 } 4762 else 4763 { 4764 shader_addline(buffer, "for (aL%u = %u, tmpInt%u = 0; tmpInt%u < %u; tmpInt%u++)\n{\n", 4765 state->current_loop_depth, loop_control.start, state->current_loop_depth, 4766 state->current_loop_depth, loop_control.count, 4767 state->current_loop_depth); 4768 } 4769 } 4770 else 4771 { 4772 shader_addline(buffer, "for (tmpInt%u = 0, aL%u = %s.y; tmpInt%u < %s.x; tmpInt%u++, aL%u += %s.z)\n{\n", 4773 state->current_loop_depth, state->current_loop_reg, 4774 src1_param.reg_name, state->current_loop_depth, src1_param.reg_name, 4775 state->current_loop_depth, state->current_loop_reg, src1_param.reg_name); 4776 } 4777 4778 ++state->current_loop_reg; 4779 } 4780 else 4781 { 4782 shader_addline(buffer, "for (;;)\n{\n"); 4783 } 4784 4785 ++state->current_loop_depth; 4786 } 4787 4788 static void shader_glsl_end(const struct wined3d_shader_instruction *ins) 4789 { 4790 struct wined3d_shader_parser_state *state = ins->ctx->state; 4791 4792 shader_addline(ins->ctx->buffer, "}\n"); 4793 4794 if (ins->handler_idx == WINED3DSIH_ENDLOOP) 4795 { 4796 --state->current_loop_depth; 4797 --state->current_loop_reg; 4798 } 4799 4800 if (ins->handler_idx == WINED3DSIH_ENDREP) 4801 { 4802 --state->current_loop_depth; 4803 } 4804 } 4805 4806 static void shader_glsl_rep(const struct wined3d_shader_instruction *ins) 4807 { 4808 struct wined3d_shader_parser_state *state = ins->ctx->state; 4809 const struct wined3d_shader *shader = ins->ctx->shader; 4810 const struct wined3d_shader_lconst *constant; 4811 struct glsl_src_param src0_param; 4812 const DWORD *control_values = NULL; 4813 4814 /* Try to hardcode local values to help the GLSL compiler to unroll and optimize the loop */ 4815 if (ins->src[0].reg.type == WINED3DSPR_CONSTINT) 4816 { 4817 LIST_FOR_EACH_ENTRY(constant, &shader->constantsI, struct wined3d_shader_lconst, entry) 4818 { 4819 if (constant->idx == ins->src[0].reg.idx[0].offset) 4820 { 4821 control_values = constant->value; 4822 break; 4823 } 4824 } 4825 } 4826 4827 if (control_values) 4828 { 4829 shader_addline(ins->ctx->buffer, "for (tmpInt%d = 0; tmpInt%d < %d; tmpInt%d++) {\n", 4830 state->current_loop_depth, state->current_loop_depth, 4831 control_values[0], state->current_loop_depth); 4832 } 4833 else 4834 { 4835 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); 4836 shader_addline(ins->ctx->buffer, "for (tmpInt%d = 0; tmpInt%d < %s; tmpInt%d++) {\n", 4837 state->current_loop_depth, state->current_loop_depth, 4838 src0_param.param_str, state->current_loop_depth); 4839 } 4840 4841 ++state->current_loop_depth; 4842 } 4843 4844 static void shader_glsl_switch(const struct wined3d_shader_instruction *ins) 4845 { 4846 struct glsl_src_param src0_param; 4847 4848 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); 4849 shader_addline(ins->ctx->buffer, "switch (%s)\n{\n", src0_param.param_str); 4850 } 4851 4852 static void shader_glsl_case(const struct wined3d_shader_instruction *ins) 4853 { 4854 struct glsl_src_param src0_param; 4855 4856 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); 4857 shader_addline(ins->ctx->buffer, "case %s:\n", src0_param.param_str); 4858 } 4859 4860 static void shader_glsl_default(const struct wined3d_shader_instruction *ins) 4861 { 4862 shader_addline(ins->ctx->buffer, "default:\n"); 4863 } 4864 4865 static void shader_glsl_generate_conditional_op(const struct wined3d_shader_instruction *ins, 4866 const char *op) 4867 { 4868 struct glsl_src_param src_param; 4869 const char *condition; 4870 4871 condition = ins->flags == WINED3D_SHADER_CONDITIONAL_OP_NZ ? "bool" : "!bool"; 4872 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src_param); 4873 shader_addline(ins->ctx->buffer, "if (%s(%s)) %s\n", condition, src_param.param_str, op); 4874 } 4875 4876 static void shader_glsl_if(const struct wined3d_shader_instruction *ins) 4877 { 4878 shader_glsl_generate_conditional_op(ins, "{"); 4879 } 4880 4881 static void shader_glsl_ifc(const struct wined3d_shader_instruction *ins) 4882 { 4883 struct glsl_src_param src0_param; 4884 struct glsl_src_param src1_param; 4885 4886 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); 4887 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param); 4888 4889 shader_addline(ins->ctx->buffer, "if (%s %s %s) {\n", 4890 src0_param.param_str, shader_glsl_get_rel_op(ins->flags), src1_param.param_str); 4891 } 4892 4893 static void shader_glsl_else(const struct wined3d_shader_instruction *ins) 4894 { 4895 shader_addline(ins->ctx->buffer, "} else {\n"); 4896 } 4897 4898 static void shader_glsl_emit(const struct wined3d_shader_instruction *ins) 4899 { 4900 unsigned int stream = ins->handler_idx == WINED3DSIH_EMIT ? 0 : ins->src[0].reg.idx[0].offset; 4901 4902 shader_addline(ins->ctx->buffer, "setup_gs_output(gs_out);\n"); 4903 if (!ins->ctx->gl_info->supported[ARB_CLIP_CONTROL]) 4904 shader_glsl_fixup_position(ins->ctx->buffer); 4905 4906 if (!stream) 4907 shader_addline(ins->ctx->buffer, "EmitVertex();\n"); 4908 else 4909 FIXME("Unhandled primitive stream %u.\n", stream); 4910 } 4911 4912 static void shader_glsl_break(const struct wined3d_shader_instruction *ins) 4913 { 4914 shader_addline(ins->ctx->buffer, "break;\n"); 4915 } 4916 4917 /* FIXME: According to MSDN the compare is done per component. */ 4918 static void shader_glsl_breakc(const struct wined3d_shader_instruction *ins) 4919 { 4920 struct glsl_src_param src0_param; 4921 struct glsl_src_param src1_param; 4922 4923 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param); 4924 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param); 4925 4926 shader_addline(ins->ctx->buffer, "if (%s %s %s) break;\n", 4927 src0_param.param_str, shader_glsl_get_rel_op(ins->flags), src1_param.param_str); 4928 } 4929 4930 static void shader_glsl_conditional_op(const struct wined3d_shader_instruction *ins) 4931 { 4932 const char *op; 4933 4934 switch (ins->handler_idx) 4935 { 4936 case WINED3DSIH_BREAKP: op = "break;"; break; 4937 case WINED3DSIH_CONTINUEP: op = "continue;"; break; 4938 case WINED3DSIH_RETP: op = "return;"; break; 4939 default: 4940 ERR("Unhandled opcode %#x.\n", ins->handler_idx); 4941 return; 4942 } 4943 4944 shader_glsl_generate_conditional_op(ins, op); 4945 } 4946 4947 static void shader_glsl_continue(const struct wined3d_shader_instruction *ins) 4948 { 4949 shader_addline(ins->ctx->buffer, "continue;\n"); 4950 } 4951 4952 static void shader_glsl_label(const struct wined3d_shader_instruction *ins) 4953 { 4954 shader_addline(ins->ctx->buffer, "}\n"); 4955 shader_addline(ins->ctx->buffer, "void subroutine%u()\n{\n", ins->src[0].reg.idx[0].offset); 4956 4957 /* Subroutines appear at the end of the shader. */ 4958 ins->ctx->state->in_subroutine = TRUE; 4959 } 4960 4961 static void shader_glsl_call(const struct wined3d_shader_instruction *ins) 4962 { 4963 shader_addline(ins->ctx->buffer, "subroutine%u();\n", ins->src[0].reg.idx[0].offset); 4964 } 4965 4966 static void shader_glsl_callnz(const struct wined3d_shader_instruction *ins) 4967 { 4968 struct glsl_src_param src1_param; 4969 4970 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param); 4971 shader_addline(ins->ctx->buffer, "if (%s) subroutine%u();\n", 4972 src1_param.param_str, ins->src[0].reg.idx[0].offset); 4973 } 4974 4975 static void shader_glsl_ret(const struct wined3d_shader_instruction *ins) 4976 { 4977 const struct wined3d_shader_version *version = &ins->ctx->shader->reg_maps.shader_version; 4978 4979 if (version->major >= 4 && !ins->ctx->state->in_subroutine) 4980 { 4981 shader_glsl_generate_shader_epilogue(ins->ctx); 4982 shader_addline(ins->ctx->buffer, "return;\n"); 4983 } 4984 } 4985 4986 static void shader_glsl_tex(const struct wined3d_shader_instruction *ins) 4987 { 4988 DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major, 4989 ins->ctx->reg_maps->shader_version.minor); 4990 struct glsl_sample_function sample_function; 4991 DWORD sample_flags = 0; 4992 DWORD resource_idx; 4993 DWORD mask = 0, swizzle; 4994 const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; 4995 4996 /* 1.0-1.4: Use destination register as sampler source. 4997 * 2.0+: Use provided sampler source. */ 4998 if (shader_version < WINED3D_SHADER_VERSION(2,0)) 4999 resource_idx = ins->dst[0].reg.idx[0].offset; 5000 else 5001 resource_idx = ins->src[1].reg.idx[0].offset; 5002 5003 if (shader_version < WINED3D_SHADER_VERSION(1,4)) 5004 { 5005 DWORD flags = (priv->cur_ps_args->tex_transform >> resource_idx * WINED3D_PSARGS_TEXTRANSFORM_SHIFT) 5006 & WINED3D_PSARGS_TEXTRANSFORM_MASK; 5007 enum wined3d_shader_resource_type resource_type = ins->ctx->reg_maps->resource_info[resource_idx].type; 5008 5009 /* Projected cube textures don't make a lot of sense, the resulting coordinates stay the same. */ 5010 if (flags & WINED3D_PSARGS_PROJECTED && resource_type != WINED3D_SHADER_RESOURCE_TEXTURE_CUBE) 5011 { 5012 sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED; 5013 switch (flags & ~WINED3D_PSARGS_PROJECTED) 5014 { 5015 case WINED3D_TTFF_COUNT1: 5016 FIXME("WINED3D_TTFF_PROJECTED with WINED3D_TTFF_COUNT1?\n"); 5017 break; 5018 case WINED3D_TTFF_COUNT2: 5019 mask = WINED3DSP_WRITEMASK_1; 5020 break; 5021 case WINED3D_TTFF_COUNT3: 5022 mask = WINED3DSP_WRITEMASK_2; 5023 break; 5024 case WINED3D_TTFF_COUNT4: 5025 case WINED3D_TTFF_DISABLE: 5026 mask = WINED3DSP_WRITEMASK_3; 5027 break; 5028 } 5029 } 5030 } 5031 else if (shader_version < WINED3D_SHADER_VERSION(2,0)) 5032 { 5033 enum wined3d_shader_src_modifier src_mod = ins->src[0].modifiers; 5034 5035 if (src_mod == WINED3DSPSM_DZ) { 5036 sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED; 5037 mask = WINED3DSP_WRITEMASK_2; 5038 } else if (src_mod == WINED3DSPSM_DW) { 5039 sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED; 5040 mask = WINED3DSP_WRITEMASK_3; 5041 } 5042 } 5043 else 5044 { 5045 if ((ins->flags & WINED3DSI_TEXLD_PROJECT) 5046 && ins->ctx->reg_maps->resource_info[resource_idx].type != WINED3D_SHADER_RESOURCE_TEXTURE_CUBE) 5047 { 5048 /* ps 2.0 texldp instruction always divides by the fourth component. */ 5049 sample_flags |= WINED3D_GLSL_SAMPLE_PROJECTED; 5050 mask = WINED3DSP_WRITEMASK_3; 5051 } 5052 } 5053 5054 shader_glsl_get_sample_function(ins->ctx, resource_idx, resource_idx, sample_flags, &sample_function); 5055 mask |= sample_function.coord_mask; 5056 sample_function.coord_mask = mask; 5057 5058 if (shader_version < WINED3D_SHADER_VERSION(2,0)) swizzle = WINED3DSP_NOSWIZZLE; 5059 else swizzle = ins->src[1].swizzle; 5060 5061 /* 1.0-1.3: Use destination register as coordinate source. 5062 1.4+: Use provided coordinate source register. */ 5063 if (shader_version < WINED3D_SHADER_VERSION(1,4)) 5064 { 5065 char coord_mask[6]; 5066 shader_glsl_write_mask_to_str(mask, coord_mask); 5067 shader_glsl_gen_sample_code(ins, resource_idx, &sample_function, swizzle, NULL, NULL, NULL, NULL, 5068 "T%u%s", resource_idx, coord_mask); 5069 } 5070 else 5071 { 5072 struct glsl_src_param coord_param; 5073 shader_glsl_add_src_param(ins, &ins->src[0], mask, &coord_param); 5074 if (ins->flags & WINED3DSI_TEXLD_BIAS) 5075 { 5076 struct glsl_src_param bias; 5077 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &bias); 5078 shader_glsl_gen_sample_code(ins, resource_idx, &sample_function, swizzle, NULL, NULL, bias.param_str, 5079 NULL, "%s", coord_param.param_str); 5080 } else { 5081 shader_glsl_gen_sample_code(ins, resource_idx, &sample_function, swizzle, NULL, NULL, NULL, NULL, 5082 "%s", coord_param.param_str); 5083 } 5084 } 5085 shader_glsl_release_sample_function(ins->ctx, &sample_function); 5086 } 5087 5088 static void shader_glsl_texldd(const struct wined3d_shader_instruction *ins) 5089 { 5090 const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; 5091 struct glsl_src_param coord_param, dx_param, dy_param; 5092 struct glsl_sample_function sample_function; 5093 DWORD sampler_idx; 5094 DWORD swizzle = ins->src[1].swizzle; 5095 5096 if (!shader_glsl_has_core_grad(gl_info) && !gl_info->supported[ARB_SHADER_TEXTURE_LOD]) 5097 { 5098 FIXME("texldd used, but not supported by hardware. Falling back to regular tex.\n"); 5099 shader_glsl_tex(ins); 5100 return; 5101 } 5102 5103 sampler_idx = ins->src[1].reg.idx[0].offset; 5104 5105 shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, WINED3D_GLSL_SAMPLE_GRAD, &sample_function); 5106 shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param); 5107 shader_glsl_add_src_param(ins, &ins->src[2], sample_function.deriv_mask, &dx_param); 5108 shader_glsl_add_src_param(ins, &ins->src[3], sample_function.deriv_mask, &dy_param); 5109 5110 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, dx_param.param_str, dy_param.param_str, 5111 NULL, NULL, "%s", coord_param.param_str); 5112 shader_glsl_release_sample_function(ins->ctx, &sample_function); 5113 } 5114 5115 static void shader_glsl_texldl(const struct wined3d_shader_instruction *ins) 5116 { 5117 const struct wined3d_shader_version *shader_version = &ins->ctx->reg_maps->shader_version; 5118 const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; 5119 struct glsl_src_param coord_param, lod_param; 5120 struct glsl_sample_function sample_function; 5121 DWORD swizzle = ins->src[1].swizzle; 5122 DWORD sampler_idx; 5123 5124 sampler_idx = ins->src[1].reg.idx[0].offset; 5125 5126 shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, WINED3D_GLSL_SAMPLE_LOD, &sample_function); 5127 shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param); 5128 5129 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &lod_param); 5130 5131 if (shader_version->type == WINED3D_SHADER_TYPE_PIXEL && !shader_glsl_has_core_grad(gl_info) 5132 && !gl_info->supported[ARB_SHADER_TEXTURE_LOD]) 5133 { 5134 /* Plain GLSL only supports Lod sampling functions in vertex shaders. 5135 * However, the NVIDIA drivers allow them in fragment shaders as well, 5136 * even without the appropriate extension. */ 5137 WARN("Using %s in fragment shader.\n", sample_function.name->buffer); 5138 } 5139 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, swizzle, NULL, NULL, lod_param.param_str, NULL, 5140 "%s", coord_param.param_str); 5141 shader_glsl_release_sample_function(ins->ctx, &sample_function); 5142 } 5143 5144 static unsigned int shader_glsl_find_sampler(const struct wined3d_shader_sampler_map *sampler_map, 5145 unsigned int resource_idx, unsigned int sampler_idx) 5146 { 5147 struct wined3d_shader_sampler_map_entry *entries = sampler_map->entries; 5148 unsigned int i; 5149 5150 for (i = 0; i < sampler_map->count; ++i) 5151 { 5152 if (entries[i].resource_idx == resource_idx && entries[i].sampler_idx == sampler_idx) 5153 return entries[i].bind_idx; 5154 } 5155 5156 ERR("No GLSL sampler found for resource %u / sampler %u.\n", resource_idx, sampler_idx); 5157 5158 return ~0u; 5159 } 5160 5161 static void shader_glsl_atomic(const struct wined3d_shader_instruction *ins) 5162 { 5163 const BOOL is_imm_instruction = WINED3DSIH_IMM_ATOMIC_AND <= ins->handler_idx 5164 && ins->handler_idx <= WINED3DSIH_IMM_ATOMIC_XOR; 5165 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; 5166 const struct wined3d_shader_version *version = ®_maps->shader_version; 5167 struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; 5168 struct glsl_src_param structure_idx, offset, data, data2; 5169 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 5170 enum wined3d_shader_resource_type resource_type; 5171 struct wined3d_string_buffer *address; 5172 enum wined3d_data_type data_type; 5173 unsigned int resource_idx, stride; 5174 const char *op, *resource; 5175 DWORD coord_mask; 5176 BOOL is_tgsm; 5177 5178 resource_idx = ins->dst[is_imm_instruction].reg.idx[0].offset; 5179 is_tgsm = ins->dst[is_imm_instruction].reg.type == WINED3DSPR_GROUPSHAREDMEM; 5180 if (is_tgsm) 5181 { 5182 if (resource_idx >= reg_maps->tgsm_count) 5183 { 5184 ERR("Invalid TGSM index %u.\n", resource_idx); 5185 return; 5186 } 5187 resource = "g"; 5188 data_type = WINED3D_DATA_UINT; 5189 coord_mask = 1; 5190 stride = reg_maps->tgsm[resource_idx].stride; 5191 } 5192 else 5193 { 5194 if (resource_idx >= ARRAY_SIZE(reg_maps->uav_resource_info)) 5195 { 5196 ERR("Invalid UAV index %u.\n", resource_idx); 5197 return; 5198 } 5199 resource_type = reg_maps->uav_resource_info[resource_idx].type; 5200 if (resource_type >= ARRAY_SIZE(resource_type_info)) 5201 { 5202 ERR("Unexpected resource type %#x.\n", resource_type); 5203 return; 5204 } 5205 resource = "image"; 5206 data_type = reg_maps->uav_resource_info[resource_idx].data_type; 5207 coord_mask = (1u << resource_type_info[resource_type].coord_size) - 1; 5208 stride = reg_maps->uav_resource_info[resource_idx].stride; 5209 } 5210 5211 switch (ins->handler_idx) 5212 { 5213 case WINED3DSIH_ATOMIC_AND: 5214 case WINED3DSIH_IMM_ATOMIC_AND: 5215 if (is_tgsm) 5216 op = "atomicAnd"; 5217 else 5218 op = "imageAtomicAnd"; 5219 break; 5220 case WINED3DSIH_ATOMIC_CMP_STORE: 5221 case WINED3DSIH_IMM_ATOMIC_CMP_EXCH: 5222 if (is_tgsm) 5223 op = "atomicCompSwap"; 5224 else 5225 op = "imageAtomicCompSwap"; 5226 break; 5227 case WINED3DSIH_ATOMIC_IADD: 5228 case WINED3DSIH_IMM_ATOMIC_IADD: 5229 if (is_tgsm) 5230 op = "atomicAdd"; 5231 else 5232 op = "imageAtomicAdd"; 5233 break; 5234 case WINED3DSIH_ATOMIC_IMAX: 5235 case WINED3DSIH_IMM_ATOMIC_IMAX: 5236 if (is_tgsm) 5237 op = "atomicMax"; 5238 else 5239 op = "imageAtomicMax"; 5240 if (data_type != WINED3D_DATA_INT) 5241 { 5242 FIXME("Unhandled opcode %#x for unsigned integers.\n", ins->handler_idx); 5243 return; 5244 } 5245 break; 5246 case WINED3DSIH_ATOMIC_IMIN: 5247 case WINED3DSIH_IMM_ATOMIC_IMIN: 5248 if (is_tgsm) 5249 op = "atomicMin"; 5250 else 5251 op = "imageAtomicMin"; 5252 if (data_type != WINED3D_DATA_INT) 5253 { 5254 FIXME("Unhandled opcode %#x for unsigned integers.\n", ins->handler_idx); 5255 return; 5256 } 5257 break; 5258 case WINED3DSIH_ATOMIC_OR: 5259 case WINED3DSIH_IMM_ATOMIC_OR: 5260 if (is_tgsm) 5261 op = "atomicOr"; 5262 else 5263 op = "imageAtomicOr"; 5264 break; 5265 case WINED3DSIH_ATOMIC_UMAX: 5266 case WINED3DSIH_IMM_ATOMIC_UMAX: 5267 if (is_tgsm) 5268 op = "atomicMax"; 5269 else 5270 op = "imageAtomicMax"; 5271 if (data_type != WINED3D_DATA_UINT) 5272 { 5273 FIXME("Unhandled opcode %#x for signed integers.\n", ins->handler_idx); 5274 return; 5275 } 5276 break; 5277 case WINED3DSIH_ATOMIC_UMIN: 5278 case WINED3DSIH_IMM_ATOMIC_UMIN: 5279 if (is_tgsm) 5280 op = "atomicMin"; 5281 else 5282 op = "imageAtomicMin"; 5283 if (data_type != WINED3D_DATA_UINT) 5284 { 5285 FIXME("Unhandled opcode %#x for signed integers.\n", ins->handler_idx); 5286 return; 5287 } 5288 break; 5289 case WINED3DSIH_ATOMIC_XOR: 5290 case WINED3DSIH_IMM_ATOMIC_XOR: 5291 if (is_tgsm) 5292 op = "atomicXor"; 5293 else 5294 op = "imageAtomicXor"; 5295 break; 5296 case WINED3DSIH_IMM_ATOMIC_EXCH: 5297 if (is_tgsm) 5298 op = "atomicExchange"; 5299 else 5300 op = "imageAtomicExchange"; 5301 break; 5302 default: 5303 ERR("Unhandled opcode %#x.\n", ins->handler_idx); 5304 return; 5305 } 5306 5307 address = string_buffer_get(priv->string_buffers); 5308 if (stride) 5309 { 5310 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &structure_idx); 5311 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_1, &offset); 5312 string_buffer_sprintf(address, "%s * %u + %s / 4", structure_idx.param_str, stride, offset.param_str); 5313 } 5314 else 5315 { 5316 shader_glsl_add_src_param(ins, &ins->src[0], coord_mask, &offset); 5317 string_buffer_sprintf(address, "%s", offset.param_str); 5318 if (is_tgsm || (reg_maps->uav_resource_info[resource_idx].flags & WINED3D_VIEW_BUFFER_RAW)) 5319 shader_addline(address, "/ 4"); 5320 } 5321 5322 if (is_imm_instruction) 5323 shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &ins->dst[0], data_type); 5324 5325 if (is_tgsm) 5326 shader_addline(buffer, "%s(%s_%s%u[%s], ", 5327 op, shader_glsl_get_prefix(version->type), resource, resource_idx, address->buffer); 5328 else 5329 shader_addline(buffer, "%s(%s_%s%u, %s, ", 5330 op, shader_glsl_get_prefix(version->type), resource, resource_idx, address->buffer); 5331 5332 shader_glsl_add_src_param_ext(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &data, data_type); 5333 shader_addline(buffer, "%s", data.param_str); 5334 if (ins->src_count >= 3) 5335 { 5336 shader_glsl_add_src_param_ext(ins, &ins->src[2], WINED3DSP_WRITEMASK_0, &data2, data_type); 5337 shader_addline(buffer, ", %s", data2.param_str); 5338 } 5339 5340 if (is_imm_instruction) 5341 shader_addline(buffer, ")"); 5342 shader_addline(buffer, ");\n"); 5343 5344 string_buffer_release(priv->string_buffers, address); 5345 } 5346 5347 static void shader_glsl_uav_counter(const struct wined3d_shader_instruction *ins) 5348 { 5349 const char *prefix = shader_glsl_get_prefix(ins->ctx->reg_maps->shader_version.type); 5350 const char *op; 5351 5352 if (ins->handler_idx == WINED3DSIH_IMM_ATOMIC_ALLOC) 5353 op = "atomicCounterIncrement"; 5354 else 5355 op = "atomicCounterDecrement"; 5356 5357 shader_glsl_append_dst(ins->ctx->buffer, ins); 5358 shader_addline(ins->ctx->buffer, "%s(%s_counter%u));\n", op, prefix, ins->src[0].reg.idx[0].offset); 5359 } 5360 5361 static void shader_glsl_ld_uav(const struct wined3d_shader_instruction *ins) 5362 { 5363 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; 5364 const struct wined3d_shader_version *version = ®_maps->shader_version; 5365 enum wined3d_shader_resource_type resource_type; 5366 struct glsl_src_param image_coord_param; 5367 enum wined3d_data_type data_type; 5368 DWORD coord_mask, write_mask; 5369 unsigned int uav_idx; 5370 char dst_swizzle[6]; 5371 5372 uav_idx = ins->src[1].reg.idx[0].offset; 5373 if (uav_idx >= ARRAY_SIZE(reg_maps->uav_resource_info)) 5374 { 5375 ERR("Invalid UAV index %u.\n", uav_idx); 5376 return; 5377 } 5378 resource_type = reg_maps->uav_resource_info[uav_idx].type; 5379 if (resource_type >= ARRAY_SIZE(resource_type_info)) 5380 { 5381 ERR("Unexpected resource type %#x.\n", resource_type); 5382 resource_type = WINED3D_SHADER_RESOURCE_TEXTURE_2D; 5383 } 5384 data_type = reg_maps->uav_resource_info[uav_idx].data_type; 5385 coord_mask = (1u << resource_type_info[resource_type].coord_size) - 1; 5386 5387 write_mask = shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &ins->dst[0], data_type); 5388 shader_glsl_get_swizzle(&ins->src[1], FALSE, write_mask, dst_swizzle); 5389 5390 shader_glsl_add_src_param(ins, &ins->src[0], coord_mask, &image_coord_param); 5391 shader_addline(ins->ctx->buffer, "imageLoad(%s_image%u, %s)%s);\n", 5392 shader_glsl_get_prefix(version->type), uav_idx, image_coord_param.param_str, dst_swizzle); 5393 } 5394 5395 static void shader_glsl_ld_raw_structured(const struct wined3d_shader_instruction *ins) 5396 { 5397 const char *prefix = shader_glsl_get_prefix(ins->ctx->reg_maps->shader_version.type); 5398 const struct wined3d_shader_src_param *src = &ins->src[ins->src_count - 1]; 5399 unsigned int i, swizzle, resource_idx, bind_idx, stride, src_idx = 0; 5400 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; 5401 struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; 5402 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 5403 struct glsl_src_param structure_idx, offset; 5404 struct wined3d_string_buffer *address; 5405 struct wined3d_shader_dst_param dst; 5406 const char *function, *resource; 5407 5408 resource_idx = src->reg.idx[0].offset; 5409 if (src->reg.type == WINED3DSPR_RESOURCE) 5410 { 5411 if (resource_idx >= ARRAY_SIZE(reg_maps->resource_info)) 5412 { 5413 ERR("Invalid resource index %u.\n", resource_idx); 5414 return; 5415 } 5416 stride = reg_maps->resource_info[resource_idx].stride; 5417 bind_idx = shader_glsl_find_sampler(®_maps->sampler_map, resource_idx, WINED3D_SAMPLER_DEFAULT); 5418 function = "texelFetch"; 5419 resource = "sampler"; 5420 } 5421 else if (src->reg.type == WINED3DSPR_UAV) 5422 { 5423 if (resource_idx >= ARRAY_SIZE(reg_maps->uav_resource_info)) 5424 { 5425 ERR("Invalid UAV index %u.\n", resource_idx); 5426 return; 5427 } 5428 stride = reg_maps->uav_resource_info[resource_idx].stride; 5429 bind_idx = resource_idx; 5430 function = "imageLoad"; 5431 resource = "image"; 5432 } 5433 else 5434 { 5435 if (resource_idx >= reg_maps->tgsm_count) 5436 { 5437 ERR("Invalid TGSM index %u.\n", resource_idx); 5438 return; 5439 } 5440 stride = reg_maps->tgsm[resource_idx].stride; 5441 bind_idx = resource_idx; 5442 function = NULL; 5443 resource = "g"; 5444 } 5445 5446 address = string_buffer_get(priv->string_buffers); 5447 if (ins->handler_idx == WINED3DSIH_LD_STRUCTURED) 5448 { 5449 shader_glsl_add_src_param(ins, &ins->src[src_idx++], WINED3DSP_WRITEMASK_0, &structure_idx); 5450 shader_addline(address, "%s * %u + ", structure_idx.param_str, stride); 5451 } 5452 shader_glsl_add_src_param(ins, &ins->src[src_idx++], WINED3DSP_WRITEMASK_0, &offset); 5453 shader_addline(address, "%s / 4", offset.param_str); 5454 5455 dst = ins->dst[0]; 5456 if (shader_glsl_get_write_mask_size(dst.write_mask) > 1) 5457 { 5458 /* The instruction is split into multiple lines. The first lines may 5459 * overwrite source parameters of the following lines. */ 5460 shader_addline(buffer, "tmp0.x = intBitsToFloat(%s);\n", address->buffer); 5461 string_buffer_sprintf(address, "floatBitsToInt(tmp0.x)"); 5462 } 5463 5464 for (i = 0; i < 4; ++i) 5465 { 5466 dst.write_mask = ins->dst[0].write_mask & (WINED3DSP_WRITEMASK_0 << i); 5467 if (!shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &dst, dst.reg.data_type)) 5468 continue; 5469 5470 swizzle = shader_glsl_swizzle_get_component(src->swizzle, i); 5471 if (function) 5472 shader_addline(buffer, "%s(%s_%s%u, %s + %u).x);\n", 5473 function, prefix, resource, bind_idx, address->buffer, swizzle); 5474 else 5475 shader_addline(buffer, "%s_%s%u[%s + %u]);\n", 5476 prefix, resource, bind_idx, address->buffer, swizzle); 5477 } 5478 5479 string_buffer_release(priv->string_buffers, address); 5480 } 5481 5482 static void shader_glsl_store_uav(const struct wined3d_shader_instruction *ins) 5483 { 5484 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; 5485 const struct wined3d_shader_version *version = ®_maps->shader_version; 5486 struct glsl_src_param image_coord_param, image_data_param; 5487 enum wined3d_shader_resource_type resource_type; 5488 enum wined3d_data_type data_type; 5489 unsigned int uav_idx; 5490 DWORD coord_mask; 5491 5492 uav_idx = ins->dst[0].reg.idx[0].offset; 5493 if (uav_idx >= ARRAY_SIZE(reg_maps->uav_resource_info)) 5494 { 5495 ERR("Invalid UAV index %u.\n", uav_idx); 5496 return; 5497 } 5498 resource_type = reg_maps->uav_resource_info[uav_idx].type; 5499 if (resource_type >= ARRAY_SIZE(resource_type_info)) 5500 { 5501 ERR("Unexpected resource type %#x.\n", resource_type); 5502 return; 5503 } 5504 data_type = reg_maps->uav_resource_info[uav_idx].data_type; 5505 coord_mask = (1u << resource_type_info[resource_type].coord_size) - 1; 5506 5507 shader_glsl_add_src_param(ins, &ins->src[0], coord_mask, &image_coord_param); 5508 shader_glsl_add_src_param_ext(ins, &ins->src[1], WINED3DSP_WRITEMASK_ALL, &image_data_param, data_type); 5509 shader_addline(ins->ctx->buffer, "imageStore(%s_image%u, %s, %s);\n", 5510 shader_glsl_get_prefix(version->type), uav_idx, 5511 image_coord_param.param_str, image_data_param.param_str); 5512 } 5513 5514 static void shader_glsl_store_raw_structured(const struct wined3d_shader_instruction *ins) 5515 { 5516 const char *prefix = shader_glsl_get_prefix(ins->ctx->reg_maps->shader_version.type); 5517 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; 5518 struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; 5519 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 5520 struct glsl_src_param structure_idx, offset, data; 5521 unsigned int i, resource_idx, stride, src_idx = 0; 5522 struct wined3d_string_buffer *address; 5523 DWORD write_mask; 5524 BOOL is_tgsm; 5525 5526 resource_idx = ins->dst[0].reg.idx[0].offset; 5527 is_tgsm = ins->dst[0].reg.type == WINED3DSPR_GROUPSHAREDMEM; 5528 if (is_tgsm) 5529 { 5530 if (resource_idx >= reg_maps->tgsm_count) 5531 { 5532 ERR("Invalid TGSM index %u.\n", resource_idx); 5533 return; 5534 } 5535 stride = reg_maps->tgsm[resource_idx].stride; 5536 } 5537 else 5538 { 5539 if (resource_idx >= ARRAY_SIZE(reg_maps->uav_resource_info)) 5540 { 5541 ERR("Invalid UAV index %u.\n", resource_idx); 5542 return; 5543 } 5544 stride = reg_maps->uav_resource_info[resource_idx].stride; 5545 } 5546 5547 address = string_buffer_get(priv->string_buffers); 5548 if (ins->handler_idx == WINED3DSIH_STORE_STRUCTURED) 5549 { 5550 shader_glsl_add_src_param(ins, &ins->src[src_idx++], WINED3DSP_WRITEMASK_0, &structure_idx); 5551 shader_addline(address, "%s * %u + ", structure_idx.param_str, stride); 5552 } 5553 shader_glsl_add_src_param(ins, &ins->src[src_idx++], WINED3DSP_WRITEMASK_0, &offset); 5554 shader_addline(address, "%s / 4", offset.param_str); 5555 5556 for (i = 0; i < 4; ++i) 5557 { 5558 if (!(write_mask = ins->dst[0].write_mask & (WINED3DSP_WRITEMASK_0 << i))) 5559 continue; 5560 5561 shader_glsl_add_src_param(ins, &ins->src[src_idx], write_mask, &data); 5562 5563 if (is_tgsm) 5564 shader_addline(buffer, "%s_g%u[%s + %u] = %s;\n", 5565 prefix, resource_idx, address->buffer, i, data.param_str); 5566 else 5567 shader_addline(buffer, "imageStore(%s_image%u, %s + %u, uvec4(%s, 0, 0, 0));\n", 5568 prefix, resource_idx, address->buffer, i, data.param_str); 5569 } 5570 5571 string_buffer_release(priv->string_buffers, address); 5572 } 5573 5574 static void shader_glsl_sync(const struct wined3d_shader_instruction *ins) 5575 { 5576 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 5577 unsigned int sync_flags = ins->flags; 5578 5579 if (sync_flags & WINED3DSSF_THREAD_GROUP) 5580 { 5581 shader_addline(buffer, "barrier();\n"); 5582 sync_flags &= ~(WINED3DSSF_THREAD_GROUP | WINED3DSSF_GROUP_SHARED_MEMORY); 5583 } 5584 5585 if (sync_flags & WINED3DSSF_GROUP_SHARED_MEMORY) 5586 { 5587 shader_addline(buffer, "memoryBarrierShared();\n"); 5588 sync_flags &= ~WINED3DSSF_GROUP_SHARED_MEMORY; 5589 } 5590 5591 if (sync_flags) 5592 FIXME("Unhandled sync flags %#x.\n", sync_flags); 5593 } 5594 5595 static const struct wined3d_shader_resource_info *shader_glsl_get_resource_info( 5596 const struct wined3d_shader_instruction *ins, const struct wined3d_shader_register *reg) 5597 { 5598 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; 5599 unsigned int idx = reg->idx[0].offset; 5600 5601 if (reg->type == WINED3DSPR_RESOURCE) 5602 { 5603 if (idx >= ARRAY_SIZE(reg_maps->resource_info)) 5604 { 5605 ERR("Invalid resource index %u.\n", idx); 5606 return NULL; 5607 } 5608 return ®_maps->resource_info[idx]; 5609 } 5610 5611 if (reg->type == WINED3DSPR_UAV) 5612 { 5613 if (idx >= ARRAY_SIZE(reg_maps->uav_resource_info)) 5614 { 5615 ERR("Invalid UAV index %u.\n", idx); 5616 return NULL; 5617 } 5618 return ®_maps->uav_resource_info[idx]; 5619 } 5620 5621 FIXME("Unhandled register type %#x.\n", reg->type); 5622 return NULL; 5623 } 5624 5625 static void shader_glsl_bufinfo(const struct wined3d_shader_instruction *ins) 5626 { 5627 const char *prefix = shader_glsl_get_prefix(ins->ctx->reg_maps->shader_version.type); 5628 const struct wined3d_shader_resource_info *resource_info; 5629 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 5630 unsigned int resource_idx; 5631 char dst_swizzle[6]; 5632 DWORD write_mask; 5633 5634 write_mask = shader_glsl_append_dst(buffer, ins); 5635 shader_glsl_get_swizzle(&ins->src[0], FALSE, write_mask, dst_swizzle); 5636 5637 if (!(resource_info = shader_glsl_get_resource_info(ins, &ins->src[0].reg))) 5638 return; 5639 resource_idx = ins->src[0].reg.idx[0].offset; 5640 5641 shader_addline(buffer, "ivec2("); 5642 if (ins->src[0].reg.type == WINED3DSPR_RESOURCE) 5643 { 5644 unsigned int bind_idx = shader_glsl_find_sampler(&ins->ctx->reg_maps->sampler_map, 5645 resource_idx, WINED3D_SAMPLER_DEFAULT); 5646 shader_addline(buffer, "textureSize(%s_sampler%u)", prefix, bind_idx); 5647 } 5648 else 5649 { 5650 shader_addline(buffer, "imageSize(%s_image%u)", prefix, resource_idx); 5651 } 5652 if (resource_info->stride) 5653 shader_addline(buffer, " / %u", resource_info->stride); 5654 else if (resource_info->flags & WINED3D_VIEW_BUFFER_RAW) 5655 shader_addline(buffer, " * 4"); 5656 shader_addline(buffer, ", %u)%s);\n", resource_info->stride, dst_swizzle); 5657 } 5658 5659 static BOOL is_multisampled(enum wined3d_shader_resource_type resource_type) 5660 { 5661 return resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_2DMS 5662 || resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY; 5663 } 5664 5665 static BOOL is_mipmapped(enum wined3d_shader_resource_type resource_type) 5666 { 5667 return resource_type != WINED3D_SHADER_RESOURCE_BUFFER && !is_multisampled(resource_type); 5668 } 5669 5670 static void shader_glsl_resinfo(const struct wined3d_shader_instruction *ins) 5671 { 5672 const struct wined3d_shader_version *version = &ins->ctx->reg_maps->shader_version; 5673 const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; 5674 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 5675 enum wined3d_shader_resource_type resource_type; 5676 enum wined3d_shader_register_type reg_type; 5677 unsigned int resource_idx, bind_idx, i; 5678 enum wined3d_data_type dst_data_type; 5679 struct glsl_src_param lod_param; 5680 BOOL supports_mipmaps; 5681 char dst_swizzle[6]; 5682 DWORD write_mask; 5683 5684 dst_data_type = ins->dst[0].reg.data_type; 5685 if (ins->flags == WINED3DSI_RESINFO_UINT) 5686 dst_data_type = WINED3D_DATA_UINT; 5687 else if (ins->flags) 5688 FIXME("Unhandled flags %#x.\n", ins->flags); 5689 5690 reg_type = ins->src[1].reg.type; 5691 resource_idx = ins->src[1].reg.idx[0].offset; 5692 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &lod_param); 5693 if (reg_type == WINED3DSPR_RESOURCE) 5694 { 5695 resource_type = ins->ctx->reg_maps->resource_info[resource_idx].type; 5696 bind_idx = shader_glsl_find_sampler(&ins->ctx->reg_maps->sampler_map, 5697 resource_idx, WINED3D_SAMPLER_DEFAULT); 5698 } 5699 else 5700 { 5701 resource_type = ins->ctx->reg_maps->uav_resource_info[resource_idx].type; 5702 bind_idx = resource_idx; 5703 } 5704 5705 if (resource_type >= ARRAY_SIZE(resource_type_info)) 5706 { 5707 ERR("Unexpected resource type %#x.\n", resource_type); 5708 return; 5709 } 5710 5711 write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], dst_data_type); 5712 shader_glsl_get_swizzle(&ins->src[1], FALSE, write_mask, dst_swizzle); 5713 5714 if (dst_data_type == WINED3D_DATA_UINT) 5715 shader_addline(buffer, "uvec4("); 5716 else 5717 shader_addline(buffer, "vec4("); 5718 5719 if (reg_type == WINED3DSPR_RESOURCE) 5720 { 5721 shader_addline(buffer, "textureSize(%s_sampler%u", 5722 shader_glsl_get_prefix(version->type), bind_idx); 5723 } 5724 else 5725 { 5726 shader_addline(buffer, "imageSize(%s_image%u", 5727 shader_glsl_get_prefix(version->type), bind_idx); 5728 } 5729 5730 supports_mipmaps = is_mipmapped(resource_type) && reg_type != WINED3DSPR_UAV; 5731 if (supports_mipmaps) 5732 shader_addline(buffer, ", %s", lod_param.param_str); 5733 shader_addline(buffer, "), "); 5734 5735 for (i = 0; i < 3 - resource_type_info[resource_type].resinfo_size; ++i) 5736 shader_addline(buffer, "0, "); 5737 5738 if (supports_mipmaps) 5739 { 5740 if (gl_info->supported[ARB_TEXTURE_QUERY_LEVELS]) 5741 { 5742 shader_addline(buffer, "textureQueryLevels(%s_sampler%u)", 5743 shader_glsl_get_prefix(version->type), bind_idx); 5744 } 5745 else 5746 { 5747 FIXME("textureQueryLevels is not supported, returning 1 level.\n"); 5748 shader_addline(buffer, "1"); 5749 } 5750 } 5751 else 5752 { 5753 shader_addline(buffer, "1"); 5754 } 5755 5756 shader_addline(buffer, ")%s);\n", dst_swizzle); 5757 } 5758 5759 static void shader_glsl_ld(const struct wined3d_shader_instruction *ins) 5760 { 5761 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; 5762 struct glsl_src_param coord_param, lod_param, sample_param; 5763 unsigned int resource_idx, sampler_idx, sampler_bind_idx; 5764 struct glsl_sample_function sample_function; 5765 DWORD flags = WINED3D_GLSL_SAMPLE_LOAD; 5766 BOOL has_lod_param; 5767 5768 if (wined3d_shader_instruction_has_texel_offset(ins)) 5769 flags |= WINED3D_GLSL_SAMPLE_OFFSET; 5770 5771 resource_idx = ins->src[1].reg.idx[0].offset; 5772 sampler_idx = WINED3D_SAMPLER_DEFAULT; 5773 5774 if (resource_idx >= ARRAY_SIZE(reg_maps->resource_info)) 5775 { 5776 ERR("Invalid resource index %u.\n", resource_idx); 5777 return; 5778 } 5779 has_lod_param = is_mipmapped(reg_maps->resource_info[resource_idx].type); 5780 5781 shader_glsl_get_sample_function(ins->ctx, resource_idx, sampler_idx, flags, &sample_function); 5782 shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param); 5783 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &lod_param); 5784 sampler_bind_idx = shader_glsl_find_sampler(®_maps->sampler_map, resource_idx, sampler_idx); 5785 if (is_multisampled(reg_maps->resource_info[resource_idx].type)) 5786 { 5787 shader_glsl_add_src_param(ins, &ins->src[2], WINED3DSP_WRITEMASK_0, &sample_param); 5788 shader_glsl_gen_sample_code(ins, sampler_bind_idx, &sample_function, ins->src[1].swizzle, 5789 NULL, NULL, NULL, &ins->texel_offset, "%s, %s", coord_param.param_str, sample_param.param_str); 5790 } 5791 else 5792 { 5793 shader_glsl_gen_sample_code(ins, sampler_bind_idx, &sample_function, ins->src[1].swizzle, 5794 NULL, NULL, has_lod_param ? lod_param.param_str : NULL, &ins->texel_offset, 5795 "%s", coord_param.param_str); 5796 } 5797 shader_glsl_release_sample_function(ins->ctx, &sample_function); 5798 } 5799 5800 static void shader_glsl_sample(const struct wined3d_shader_instruction *ins) 5801 { 5802 const char *lod_param_str = NULL, *dx_param_str = NULL, *dy_param_str = NULL; 5803 struct glsl_src_param coord_param, lod_param, dx_param, dy_param; 5804 unsigned int resource_idx, sampler_idx, sampler_bind_idx; 5805 struct glsl_sample_function sample_function; 5806 DWORD flags = 0; 5807 5808 if (ins->handler_idx == WINED3DSIH_SAMPLE_GRAD) 5809 flags |= WINED3D_GLSL_SAMPLE_GRAD; 5810 if (ins->handler_idx == WINED3DSIH_SAMPLE_LOD) 5811 flags |= WINED3D_GLSL_SAMPLE_LOD; 5812 if (wined3d_shader_instruction_has_texel_offset(ins)) 5813 flags |= WINED3D_GLSL_SAMPLE_OFFSET; 5814 5815 resource_idx = ins->src[1].reg.idx[0].offset; 5816 sampler_idx = ins->src[2].reg.idx[0].offset; 5817 5818 shader_glsl_get_sample_function(ins->ctx, resource_idx, sampler_idx, flags, &sample_function); 5819 shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param); 5820 5821 switch (ins->handler_idx) 5822 { 5823 case WINED3DSIH_SAMPLE: 5824 break; 5825 case WINED3DSIH_SAMPLE_B: 5826 shader_glsl_add_src_param(ins, &ins->src[3], WINED3DSP_WRITEMASK_0, &lod_param); 5827 lod_param_str = lod_param.param_str; 5828 break; 5829 case WINED3DSIH_SAMPLE_GRAD: 5830 shader_glsl_add_src_param(ins, &ins->src[3], sample_function.deriv_mask, &dx_param); 5831 shader_glsl_add_src_param(ins, &ins->src[4], sample_function.deriv_mask, &dy_param); 5832 dx_param_str = dx_param.param_str; 5833 dy_param_str = dy_param.param_str; 5834 break; 5835 case WINED3DSIH_SAMPLE_LOD: 5836 shader_glsl_add_src_param(ins, &ins->src[3], WINED3DSP_WRITEMASK_0, &lod_param); 5837 lod_param_str = lod_param.param_str; 5838 break; 5839 default: 5840 ERR("Unhandled opcode %s.\n", debug_d3dshaderinstructionhandler(ins->handler_idx)); 5841 break; 5842 } 5843 5844 sampler_bind_idx = shader_glsl_find_sampler(&ins->ctx->reg_maps->sampler_map, resource_idx, sampler_idx); 5845 shader_glsl_gen_sample_code(ins, sampler_bind_idx, &sample_function, ins->src[1].swizzle, 5846 dx_param_str, dy_param_str, lod_param_str, &ins->texel_offset, "%s", coord_param.param_str); 5847 shader_glsl_release_sample_function(ins->ctx, &sample_function); 5848 } 5849 5850 /* GLSL doesn't provide a function to sample from level zero with depth 5851 * comparison for array textures and cube textures. We use textureGrad*() 5852 * to implement sample_c_lz. 5853 */ 5854 static void shader_glsl_gen_sample_c_lz(const struct wined3d_shader_instruction *ins, 5855 unsigned int sampler_bind_idx, const struct glsl_sample_function *sample_function, 5856 unsigned int coord_size, const char *coord_param, const char *ref_param) 5857 { 5858 const struct wined3d_shader_version *version = &ins->ctx->reg_maps->shader_version; 5859 unsigned int deriv_size = wined3d_popcount(sample_function->deriv_mask); 5860 const struct wined3d_shader_texel_offset *offset = &ins->texel_offset; 5861 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 5862 char dst_swizzle[6]; 5863 5864 WARN("Emitting textureGrad() for sample_c_lz.\n"); 5865 5866 shader_glsl_swizzle_to_str(WINED3DSP_NOSWIZZLE, FALSE, ins->dst[0].write_mask, dst_swizzle); 5867 shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], sample_function->data_type); 5868 shader_addline(buffer, "vec4(textureGrad%s(%s_sampler%u, vec%u(%s, %s), vec%u(0.0), vec%u(0.0)", 5869 sample_function->offset_size ? "Offset" : "", 5870 shader_glsl_get_prefix(version->type), sampler_bind_idx, 5871 coord_size, coord_param, ref_param, deriv_size, deriv_size); 5872 if (sample_function->offset_size) 5873 { 5874 int offset_immdata[4] = {offset->u, offset->v, offset->w}; 5875 shader_addline(buffer, ", "); 5876 shader_glsl_append_imm_ivec(buffer, offset_immdata, sample_function->offset_size); 5877 } 5878 shader_addline(buffer, "))%s);\n", dst_swizzle); 5879 } 5880 5881 static void shader_glsl_sample_c(const struct wined3d_shader_instruction *ins) 5882 { 5883 unsigned int resource_idx, sampler_idx, sampler_bind_idx; 5884 const struct wined3d_shader_resource_info *resource_info; 5885 struct glsl_src_param coord_param, compare_param; 5886 struct glsl_sample_function sample_function; 5887 const char *lod_param = NULL; 5888 unsigned int coord_size; 5889 DWORD flags = 0; 5890 5891 if (ins->handler_idx == WINED3DSIH_SAMPLE_C_LZ) 5892 { 5893 lod_param = "0"; 5894 flags |= WINED3D_GLSL_SAMPLE_LOD; 5895 } 5896 5897 if (wined3d_shader_instruction_has_texel_offset(ins)) 5898 flags |= WINED3D_GLSL_SAMPLE_OFFSET; 5899 5900 if (!(resource_info = shader_glsl_get_resource_info(ins, &ins->src[1].reg))) 5901 return; 5902 resource_idx = ins->src[1].reg.idx[0].offset; 5903 sampler_idx = ins->src[2].reg.idx[0].offset; 5904 5905 shader_glsl_get_sample_function(ins->ctx, resource_idx, sampler_idx, flags, &sample_function); 5906 coord_size = shader_glsl_get_write_mask_size(sample_function.coord_mask); 5907 shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask >> 1, &coord_param); 5908 shader_glsl_add_src_param(ins, &ins->src[3], WINED3DSP_WRITEMASK_0, &compare_param); 5909 sampler_bind_idx = shader_glsl_find_sampler(&ins->ctx->reg_maps->sampler_map, resource_idx, sampler_idx); 5910 if (ins->handler_idx == WINED3DSIH_SAMPLE_C_LZ 5911 && (resource_info->type == WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY 5912 || resource_info->type == WINED3D_SHADER_RESOURCE_TEXTURE_CUBE)) 5913 { 5914 shader_glsl_gen_sample_c_lz(ins, sampler_bind_idx, &sample_function, 5915 coord_size, coord_param.param_str, compare_param.param_str); 5916 } 5917 else 5918 { 5919 shader_glsl_gen_sample_code(ins, sampler_bind_idx, &sample_function, WINED3DSP_NOSWIZZLE, 5920 NULL, NULL, lod_param, &ins->texel_offset, "vec%u(%s, %s)", 5921 coord_size, coord_param.param_str, compare_param.param_str); 5922 } 5923 shader_glsl_release_sample_function(ins->ctx, &sample_function); 5924 } 5925 5926 static void shader_glsl_gather4(const struct wined3d_shader_instruction *ins) 5927 { 5928 unsigned int resource_param_idx, resource_idx, sampler_idx, sampler_bind_idx, component_idx; 5929 const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps; 5930 const char *prefix = shader_glsl_get_prefix(reg_maps->shader_version.type); 5931 struct glsl_src_param coord_param, compare_param, offset_param; 5932 const struct wined3d_gl_info *gl_info = ins->ctx->gl_info; 5933 const struct wined3d_shader_resource_info *resource_info; 5934 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 5935 unsigned int coord_size, offset_size; 5936 char dst_swizzle[6]; 5937 BOOL has_offset; 5938 5939 if (!gl_info->supported[ARB_TEXTURE_GATHER]) 5940 { 5941 FIXME("OpenGL implementation does not support textureGather.\n"); 5942 return; 5943 } 5944 5945 has_offset = ins->handler_idx == WINED3DSIH_GATHER4_PO 5946 || ins->handler_idx == WINED3DSIH_GATHER4_PO_C 5947 || wined3d_shader_instruction_has_texel_offset(ins); 5948 5949 resource_param_idx = 5950 (ins->handler_idx == WINED3DSIH_GATHER4_PO || ins->handler_idx == WINED3DSIH_GATHER4_PO_C) ? 2 : 1; 5951 resource_idx = ins->src[resource_param_idx].reg.idx[0].offset; 5952 sampler_idx = ins->src[resource_param_idx + 1].reg.idx[0].offset; 5953 component_idx = shader_glsl_swizzle_get_component(ins->src[resource_param_idx + 1].swizzle, 0); 5954 sampler_bind_idx = shader_glsl_find_sampler(®_maps->sampler_map, resource_idx, sampler_idx); 5955 5956 if (!(resource_info = shader_glsl_get_resource_info(ins, &ins->src[resource_param_idx].reg))) 5957 return; 5958 5959 if (resource_info->type >= ARRAY_SIZE(resource_type_info)) 5960 { 5961 ERR("Unexpected resource type %#x.\n", resource_info->type); 5962 return; 5963 } 5964 shader_glsl_get_coord_size(resource_info->type, &coord_size, &offset_size); 5965 5966 shader_glsl_swizzle_to_str(ins->src[resource_param_idx].swizzle, FALSE, ins->dst[0].write_mask, dst_swizzle); 5967 shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], resource_info->data_type); 5968 5969 shader_glsl_add_src_param(ins, &ins->src[0], (1u << coord_size) - 1, &coord_param); 5970 5971 shader_addline(buffer, "textureGather%s(%s_sampler%u, %s", 5972 has_offset ? "Offset" : "", prefix, sampler_bind_idx, coord_param.param_str); 5973 if (ins->handler_idx == WINED3DSIH_GATHER4_C || ins->handler_idx == WINED3DSIH_GATHER4_PO_C) 5974 { 5975 shader_glsl_add_src_param(ins, &ins->src[resource_param_idx + 2], WINED3DSP_WRITEMASK_0, &compare_param); 5976 shader_addline(buffer, ", %s", compare_param.param_str); 5977 } 5978 if (ins->handler_idx == WINED3DSIH_GATHER4_PO || ins->handler_idx == WINED3DSIH_GATHER4_PO_C) 5979 { 5980 shader_glsl_add_src_param(ins, &ins->src[1], (1u << offset_size) - 1, &offset_param); 5981 shader_addline(buffer, ", %s", offset_param.param_str); 5982 } 5983 else if (has_offset) 5984 { 5985 int offset_immdata[4] = {ins->texel_offset.u, ins->texel_offset.v, ins->texel_offset.w}; 5986 shader_addline(buffer, ", "); 5987 shader_glsl_append_imm_ivec(buffer, offset_immdata, offset_size); 5988 } 5989 if (component_idx) 5990 shader_addline(buffer, ", %u", component_idx); 5991 5992 shader_addline(buffer, ")%s);\n", dst_swizzle); 5993 } 5994 5995 static void shader_glsl_texcoord(const struct wined3d_shader_instruction *ins) 5996 { 5997 /* FIXME: Make this work for more than just 2D textures */ 5998 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 5999 DWORD write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); 6000 6001 if (!(ins->ctx->reg_maps->shader_version.major == 1 && ins->ctx->reg_maps->shader_version.minor == 4)) 6002 { 6003 char dst_mask[6]; 6004 6005 shader_glsl_get_write_mask(&ins->dst[0], dst_mask); 6006 shader_addline(buffer, "clamp(ffp_texcoord[%u], 0.0, 1.0)%s);\n", 6007 ins->dst[0].reg.idx[0].offset, dst_mask); 6008 } 6009 else 6010 { 6011 enum wined3d_shader_src_modifier src_mod = ins->src[0].modifiers; 6012 DWORD reg = ins->src[0].reg.idx[0].offset; 6013 char dst_swizzle[6]; 6014 6015 shader_glsl_get_swizzle(&ins->src[0], FALSE, write_mask, dst_swizzle); 6016 6017 if (src_mod == WINED3DSPSM_DZ || src_mod == WINED3DSPSM_DW) 6018 { 6019 unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask); 6020 struct glsl_src_param div_param; 6021 DWORD src_writemask = src_mod == WINED3DSPSM_DZ ? WINED3DSP_WRITEMASK_2 : WINED3DSP_WRITEMASK_3; 6022 6023 shader_glsl_add_src_param(ins, &ins->src[0], src_writemask, &div_param); 6024 6025 if (mask_size > 1) 6026 shader_addline(buffer, "ffp_texcoord[%u]%s / vec%d(%s));\n", reg, dst_swizzle, mask_size, div_param.param_str); 6027 else 6028 shader_addline(buffer, "ffp_texcoord[%u]%s / %s);\n", reg, dst_swizzle, div_param.param_str); 6029 } 6030 else 6031 { 6032 shader_addline(buffer, "ffp_texcoord[%u]%s);\n", reg, dst_swizzle); 6033 } 6034 } 6035 } 6036 6037 /** Process the WINED3DSIO_TEXDP3TEX instruction in GLSL: 6038 * Take a 3-component dot product of the TexCoord[dstreg] and src, 6039 * then perform a 1D texture lookup from stage dstregnum, place into dst. */ 6040 static void shader_glsl_texdp3tex(const struct wined3d_shader_instruction *ins) 6041 { 6042 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 6043 DWORD sampler_idx = ins->dst[0].reg.idx[0].offset; 6044 struct glsl_sample_function sample_function; 6045 struct glsl_src_param src0_param; 6046 UINT mask_size; 6047 6048 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); 6049 6050 /* Do I have to take care about the projected bit? I don't think so, since the dp3 returns only one 6051 * scalar, and projected sampling would require 4. 6052 * 6053 * It is a dependent read - not valid with conditional NP2 textures 6054 */ 6055 shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, 0, &sample_function); 6056 mask_size = shader_glsl_get_write_mask_size(sample_function.coord_mask); 6057 6058 switch(mask_size) 6059 { 6060 case 1: 6061 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, 6062 NULL, "dot(ffp_texcoord[%u].xyz, %s)", sampler_idx, src0_param.param_str); 6063 break; 6064 6065 case 2: 6066 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, 6067 NULL, "vec2(dot(ffp_texcoord[%u].xyz, %s), 0.0)", sampler_idx, src0_param.param_str); 6068 break; 6069 6070 case 3: 6071 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, 6072 NULL, "vec3(dot(ffp_texcoord[%u].xyz, %s), 0.0, 0.0)", sampler_idx, src0_param.param_str); 6073 break; 6074 6075 default: 6076 FIXME("Unexpected mask size %u\n", mask_size); 6077 break; 6078 } 6079 shader_glsl_release_sample_function(ins->ctx, &sample_function); 6080 } 6081 6082 /** Process the WINED3DSIO_TEXDP3 instruction in GLSL: 6083 * Take a 3-component dot product of the TexCoord[dstreg] and src. */ 6084 static void shader_glsl_texdp3(const struct wined3d_shader_instruction *ins) 6085 { 6086 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 6087 DWORD dstreg = ins->dst[0].reg.idx[0].offset; 6088 struct glsl_src_param src0_param; 6089 DWORD dst_mask; 6090 unsigned int mask_size; 6091 6092 dst_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); 6093 mask_size = shader_glsl_get_write_mask_size(dst_mask); 6094 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); 6095 6096 if (mask_size > 1) { 6097 shader_addline(ins->ctx->buffer, "vec%d(dot(T%u.xyz, %s)));\n", mask_size, dstreg, src0_param.param_str); 6098 } else { 6099 shader_addline(ins->ctx->buffer, "dot(T%u.xyz, %s));\n", dstreg, src0_param.param_str); 6100 } 6101 } 6102 6103 /** Process the WINED3DSIO_TEXDEPTH instruction in GLSL: 6104 * Calculate the depth as dst.x / dst.y */ 6105 static void shader_glsl_texdepth(const struct wined3d_shader_instruction *ins) 6106 { 6107 struct glsl_dst_param dst_param; 6108 6109 shader_glsl_add_dst_param(ins, &ins->dst[0], &dst_param); 6110 6111 /* Tests show that texdepth never returns anything below 0.0, and that r5.y is clamped to 1.0. 6112 * Negative input is accepted, -0.25 / -0.5 returns 0.5. GL should clamp gl_FragDepth to [0;1], but 6113 * this doesn't always work, so clamp the results manually. Whether or not the x value is clamped at 1 6114 * too is irrelevant, since if x = 0, any y value < 1.0 (and > 1.0 is not allowed) results in a result 6115 * >= 1.0 or < 0.0 6116 */ 6117 shader_addline(ins->ctx->buffer, "gl_FragDepth = clamp((%s.x / min(%s.y, 1.0)), 0.0, 1.0);\n", 6118 dst_param.reg_name, dst_param.reg_name); 6119 } 6120 6121 /** Process the WINED3DSIO_TEXM3X2DEPTH instruction in GLSL: 6122 * Last row of a 3x2 matrix multiply, use the result to calculate the depth: 6123 * Calculate tmp0.y = TexCoord[dstreg] . src.xyz; (tmp0.x has already been calculated) 6124 * depth = (tmp0.y == 0.0) ? 1.0 : tmp0.x / tmp0.y 6125 */ 6126 static void shader_glsl_texm3x2depth(const struct wined3d_shader_instruction *ins) 6127 { 6128 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 6129 DWORD dstreg = ins->dst[0].reg.idx[0].offset; 6130 struct glsl_src_param src0_param; 6131 6132 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); 6133 6134 shader_addline(ins->ctx->buffer, "tmp0.y = dot(T%u.xyz, %s);\n", dstreg, src0_param.param_str); 6135 shader_addline(ins->ctx->buffer, "gl_FragDepth = (tmp0.y == 0.0) ? 1.0 : clamp(tmp0.x / tmp0.y, 0.0, 1.0);\n"); 6136 } 6137 6138 /** Process the WINED3DSIO_TEXM3X2PAD instruction in GLSL 6139 * Calculate the 1st of a 2-row matrix multiplication. */ 6140 static void shader_glsl_texm3x2pad(const struct wined3d_shader_instruction *ins) 6141 { 6142 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 6143 DWORD reg = ins->dst[0].reg.idx[0].offset; 6144 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 6145 struct glsl_src_param src0_param; 6146 6147 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); 6148 shader_addline(buffer, "tmp0.x = dot(T%u.xyz, %s);\n", reg, src0_param.param_str); 6149 } 6150 6151 /** Process the WINED3DSIO_TEXM3X3PAD instruction in GLSL 6152 * Calculate the 1st or 2nd row of a 3-row matrix multiplication. */ 6153 static void shader_glsl_texm3x3pad(const struct wined3d_shader_instruction *ins) 6154 { 6155 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 6156 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 6157 struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx; 6158 DWORD reg = ins->dst[0].reg.idx[0].offset; 6159 struct glsl_src_param src0_param; 6160 6161 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); 6162 shader_addline(buffer, "tmp0.%c = dot(T%u.xyz, %s);\n", 'x' + tex_mx->current_row, reg, src0_param.param_str); 6163 tex_mx->texcoord_w[tex_mx->current_row++] = reg; 6164 } 6165 6166 static void shader_glsl_texm3x2tex(const struct wined3d_shader_instruction *ins) 6167 { 6168 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 6169 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 6170 struct glsl_sample_function sample_function; 6171 DWORD reg = ins->dst[0].reg.idx[0].offset; 6172 struct glsl_src_param src0_param; 6173 6174 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); 6175 shader_addline(buffer, "tmp0.y = dot(T%u.xyz, %s);\n", reg, src0_param.param_str); 6176 6177 shader_glsl_get_sample_function(ins->ctx, reg, reg, 0, &sample_function); 6178 6179 /* Sample the texture using the calculated coordinates */ 6180 shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL, "tmp0.xy"); 6181 shader_glsl_release_sample_function(ins->ctx, &sample_function); 6182 } 6183 6184 /** Process the WINED3DSIO_TEXM3X3TEX instruction in GLSL 6185 * Perform the 3rd row of a 3x3 matrix multiply, then sample the texture using the calculated coordinates */ 6186 static void shader_glsl_texm3x3tex(const struct wined3d_shader_instruction *ins) 6187 { 6188 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 6189 struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx; 6190 struct glsl_sample_function sample_function; 6191 DWORD reg = ins->dst[0].reg.idx[0].offset; 6192 struct glsl_src_param src0_param; 6193 6194 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); 6195 shader_addline(ins->ctx->buffer, "tmp0.z = dot(T%u.xyz, %s);\n", reg, src0_param.param_str); 6196 6197 /* Dependent read, not valid with conditional NP2 */ 6198 shader_glsl_get_sample_function(ins->ctx, reg, reg, 0, &sample_function); 6199 6200 /* Sample the texture using the calculated coordinates */ 6201 shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL, "tmp0.xyz"); 6202 shader_glsl_release_sample_function(ins->ctx, &sample_function); 6203 6204 tex_mx->current_row = 0; 6205 } 6206 6207 /** Process the WINED3DSIO_TEXM3X3 instruction in GLSL 6208 * Perform the 3rd row of a 3x3 matrix multiply */ 6209 static void shader_glsl_texm3x3(const struct wined3d_shader_instruction *ins) 6210 { 6211 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 6212 struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx; 6213 DWORD reg = ins->dst[0].reg.idx[0].offset; 6214 struct glsl_src_param src0_param; 6215 char dst_mask[6]; 6216 6217 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); 6218 6219 shader_glsl_append_dst(ins->ctx->buffer, ins); 6220 shader_glsl_get_write_mask(&ins->dst[0], dst_mask); 6221 shader_addline(ins->ctx->buffer, "vec4(tmp0.xy, dot(T%u.xyz, %s), 1.0)%s);\n", reg, src0_param.param_str, dst_mask); 6222 6223 tex_mx->current_row = 0; 6224 } 6225 6226 /* Process the WINED3DSIO_TEXM3X3SPEC instruction in GLSL 6227 * Perform the final texture lookup based on the previous 2 3x3 matrix multiplies */ 6228 static void shader_glsl_texm3x3spec(const struct wined3d_shader_instruction *ins) 6229 { 6230 struct glsl_src_param src0_param; 6231 struct glsl_src_param src1_param; 6232 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 6233 struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx; 6234 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 6235 struct glsl_sample_function sample_function; 6236 DWORD reg = ins->dst[0].reg.idx[0].offset; 6237 char coord_mask[6]; 6238 6239 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); 6240 shader_glsl_add_src_param(ins, &ins->src[1], src_mask, &src1_param); 6241 6242 /* Perform the last matrix multiply operation */ 6243 shader_addline(buffer, "tmp0.z = dot(T%u.xyz, %s);\n", reg, src0_param.param_str); 6244 /* Reflection calculation */ 6245 shader_addline(buffer, "tmp0.xyz = -reflect((%s), normalize(tmp0.xyz));\n", src1_param.param_str); 6246 6247 /* Dependent read, not valid with conditional NP2 */ 6248 shader_glsl_get_sample_function(ins->ctx, reg, reg, 0, &sample_function); 6249 shader_glsl_write_mask_to_str(sample_function.coord_mask, coord_mask); 6250 6251 /* Sample the texture */ 6252 shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, 6253 NULL, NULL, NULL, NULL, "tmp0%s", coord_mask); 6254 shader_glsl_release_sample_function(ins->ctx, &sample_function); 6255 6256 tex_mx->current_row = 0; 6257 } 6258 6259 /* Process the WINED3DSIO_TEXM3X3VSPEC instruction in GLSL 6260 * Perform the final texture lookup based on the previous 2 3x3 matrix multiplies */ 6261 static void shader_glsl_texm3x3vspec(const struct wined3d_shader_instruction *ins) 6262 { 6263 struct wined3d_string_buffer *buffer = ins->ctx->buffer; 6264 struct wined3d_shader_tex_mx *tex_mx = ins->ctx->tex_mx; 6265 DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2; 6266 struct glsl_sample_function sample_function; 6267 DWORD reg = ins->dst[0].reg.idx[0].offset; 6268 struct glsl_src_param src0_param; 6269 char coord_mask[6]; 6270 6271 shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param); 6272 6273 /* Perform the last matrix multiply operation */ 6274 shader_addline(buffer, "tmp0.z = dot(vec3(T%u), vec3(%s));\n", reg, src0_param.param_str); 6275 6276 /* Construct the eye-ray vector from w coordinates */ 6277 shader_addline(buffer, "tmp1.xyz = normalize(vec3(ffp_texcoord[%u].w, ffp_texcoord[%u].w, ffp_texcoord[%u].w));\n", 6278 tex_mx->texcoord_w[0], tex_mx->texcoord_w[1], reg); 6279 shader_addline(buffer, "tmp0.xyz = -reflect(tmp1.xyz, normalize(tmp0.xyz));\n"); 6280 6281 /* Dependent read, not valid with conditional NP2 */ 6282 shader_glsl_get_sample_function(ins->ctx, reg, reg, 0, &sample_function); 6283 shader_glsl_write_mask_to_str(sample_function.coord_mask, coord_mask); 6284 6285 /* Sample the texture using the calculated coordinates */ 6286 shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, 6287 NULL, NULL, NULL, NULL, "tmp0%s", coord_mask); 6288 shader_glsl_release_sample_function(ins->ctx, &sample_function); 6289 6290 tex_mx->current_row = 0; 6291 } 6292 6293 /** Process the WINED3DSIO_TEXBEM instruction in GLSL. 6294 * Apply a fake bump map transform. 6295 * texbem is pshader <= 1.3 only, this saves a few version checks 6296 */ 6297 static void shader_glsl_texbem(const struct wined3d_shader_instruction *ins) 6298 { 6299 const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; 6300 struct glsl_sample_function sample_function; 6301 struct glsl_src_param coord_param; 6302 DWORD sampler_idx; 6303 DWORD mask; 6304 DWORD flags; 6305 char coord_mask[6]; 6306 6307 sampler_idx = ins->dst[0].reg.idx[0].offset; 6308 flags = (priv->cur_ps_args->tex_transform >> sampler_idx * WINED3D_PSARGS_TEXTRANSFORM_SHIFT) 6309 & WINED3D_PSARGS_TEXTRANSFORM_MASK; 6310 6311 /* Dependent read, not valid with conditional NP2 */ 6312 shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, 0, &sample_function); 6313 mask = sample_function.coord_mask; 6314 6315 shader_glsl_write_mask_to_str(mask, coord_mask); 6316 6317 /* With projected textures, texbem only divides the static texture coord, 6318 * not the displacement, so we can't let GL handle this. */ 6319 if (flags & WINED3D_PSARGS_PROJECTED) 6320 { 6321 DWORD div_mask=0; 6322 char coord_div_mask[3]; 6323 switch (flags & ~WINED3D_PSARGS_PROJECTED) 6324 { 6325 case WINED3D_TTFF_COUNT1: 6326 FIXME("WINED3D_TTFF_PROJECTED with WINED3D_TTFF_COUNT1?\n"); 6327 break; 6328 case WINED3D_TTFF_COUNT2: 6329 div_mask = WINED3DSP_WRITEMASK_1; 6330 break; 6331 case WINED3D_TTFF_COUNT3: 6332 div_mask = WINED3DSP_WRITEMASK_2; 6333 break; 6334 case WINED3D_TTFF_COUNT4: 6335 case WINED3D_TTFF_DISABLE: 6336 div_mask = WINED3DSP_WRITEMASK_3; 6337 break; 6338 } 6339 shader_glsl_write_mask_to_str(div_mask, coord_div_mask); 6340 shader_addline(ins->ctx->buffer, "T%u%s /= T%u%s;\n", sampler_idx, coord_mask, sampler_idx, coord_div_mask); 6341 } 6342 6343 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &coord_param); 6344 6345 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL, 6346 "T%u%s + vec4(bumpenv_mat%u * %s, 0.0, 0.0)%s", sampler_idx, coord_mask, sampler_idx, 6347 coord_param.param_str, coord_mask); 6348 6349 if (ins->handler_idx == WINED3DSIH_TEXBEML) 6350 { 6351 struct glsl_src_param luminance_param; 6352 struct glsl_dst_param dst_param; 6353 6354 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_2, &luminance_param); 6355 shader_glsl_add_dst_param(ins, &ins->dst[0], &dst_param); 6356 6357 shader_addline(ins->ctx->buffer, "%s%s *= (%s * bumpenv_lum_scale%u + bumpenv_lum_offset%u);\n", 6358 dst_param.reg_name, dst_param.mask_str, 6359 luminance_param.param_str, sampler_idx, sampler_idx); 6360 } 6361 shader_glsl_release_sample_function(ins->ctx, &sample_function); 6362 } 6363 6364 static void shader_glsl_bem(const struct wined3d_shader_instruction *ins) 6365 { 6366 DWORD sampler_idx = ins->dst[0].reg.idx[0].offset; 6367 struct glsl_src_param src0_param, src1_param; 6368 6369 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src0_param); 6370 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src1_param); 6371 6372 shader_glsl_append_dst(ins->ctx->buffer, ins); 6373 shader_addline(ins->ctx->buffer, "%s + bumpenv_mat%u * %s);\n", 6374 src0_param.param_str, sampler_idx, src1_param.param_str); 6375 } 6376 6377 /** Process the WINED3DSIO_TEXREG2AR instruction in GLSL 6378 * Sample 2D texture at dst using the alpha & red (wx) components of src as texture coordinates */ 6379 static void shader_glsl_texreg2ar(const struct wined3d_shader_instruction *ins) 6380 { 6381 DWORD sampler_idx = ins->dst[0].reg.idx[0].offset; 6382 struct glsl_sample_function sample_function; 6383 struct glsl_src_param src0_param; 6384 6385 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_ALL, &src0_param); 6386 6387 shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, 0, &sample_function); 6388 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL, 6389 "%s.wx", src0_param.reg_name); 6390 shader_glsl_release_sample_function(ins->ctx, &sample_function); 6391 } 6392 6393 /** Process the WINED3DSIO_TEXREG2GB instruction in GLSL 6394 * Sample 2D texture at dst using the green & blue (yz) components of src as texture coordinates */ 6395 static void shader_glsl_texreg2gb(const struct wined3d_shader_instruction *ins) 6396 { 6397 DWORD sampler_idx = ins->dst[0].reg.idx[0].offset; 6398 struct glsl_sample_function sample_function; 6399 struct glsl_src_param src0_param; 6400 6401 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_ALL, &src0_param); 6402 6403 shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, 0, &sample_function); 6404 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL, 6405 "%s.yz", src0_param.reg_name); 6406 shader_glsl_release_sample_function(ins->ctx, &sample_function); 6407 } 6408 6409 /** Process the WINED3DSIO_TEXREG2RGB instruction in GLSL 6410 * Sample texture at dst using the rgb (xyz) components of src as texture coordinates */ 6411 static void shader_glsl_texreg2rgb(const struct wined3d_shader_instruction *ins) 6412 { 6413 DWORD sampler_idx = ins->dst[0].reg.idx[0].offset; 6414 struct glsl_sample_function sample_function; 6415 struct glsl_src_param src0_param; 6416 6417 /* Dependent read, not valid with conditional NP2 */ 6418 shader_glsl_get_sample_function(ins->ctx, sampler_idx, sampler_idx, 0, &sample_function); 6419 shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &src0_param); 6420 6421 shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, NULL, 6422 "%s", src0_param.param_str); 6423 shader_glsl_release_sample_function(ins->ctx, &sample_function); 6424 } 6425 6426 /** Process the WINED3DSIO_TEXKILL instruction in GLSL. 6427 * If any of the first 3 components are < 0, discard this pixel */ 6428 static void shader_glsl_texkill(const struct wined3d_shader_instruction *ins) 6429 { 6430 if (ins->ctx->reg_maps->shader_version.major >= 4) 6431 { 6432 shader_glsl_generate_conditional_op(ins, "discard;"); 6433 } 6434 else 6435 { 6436 struct glsl_dst_param dst_param; 6437 6438 /* The argument is a destination parameter, and no writemasks are allowed */ 6439 shader_glsl_add_dst_param(ins, &ins->dst[0], &dst_param); 6440 6441 /* 2.0 shaders compare all 4 components in texkill. */ 6442 if (ins->ctx->reg_maps->shader_version.major >= 2) 6443 shader_addline(ins->ctx->buffer, "if (any(lessThan(%s.xyzw, vec4(0.0)))) discard;\n", dst_param.reg_name); 6444 /* 1.x shaders only compare the first 3 components, probably due to 6445 * the nature of the texkill instruction as a tex* instruction, and 6446 * phase, which kills all .w components. Even if all 4 components are 6447 * defined, only the first 3 are used. */ 6448 else 6449 shader_addline(ins->ctx->buffer, "if (any(lessThan(%s.xyz, vec3(0.0)))) discard;\n", dst_param.reg_name); 6450 } 6451 } 6452 6453 /** Process the WINED3DSIO_DP2ADD instruction in GLSL. 6454 * dst = dot2(src0, src1) + src2 */ 6455 static void shader_glsl_dp2add(const struct wined3d_shader_instruction *ins) 6456 { 6457 struct glsl_src_param src0_param; 6458 struct glsl_src_param src1_param; 6459 struct glsl_src_param src2_param; 6460 DWORD write_mask; 6461 unsigned int mask_size; 6462 6463 write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins); 6464 mask_size = shader_glsl_get_write_mask_size(write_mask); 6465 6466 shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src0_param); 6467 shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src1_param); 6468 shader_glsl_add_src_param(ins, &ins->src[2], WINED3DSP_WRITEMASK_0, &src2_param); 6469 6470 if (mask_size > 1) { 6471 shader_addline(ins->ctx->buffer, "vec%d(dot(%s, %s) + %s));\n", 6472 mask_size, src0_param.param_str, src1_param.param_str, src2_param.param_str); 6473 } else { 6474 shader_addline(ins->ctx->buffer, "dot(%s, %s) + %s);\n", 6475 src0_param.param_str, src1_param.param_str, src2_param.param_str); 6476 } 6477 } 6478 6479 static void shader_glsl_input_pack(const struct wined3d_shader *shader, struct wined3d_string_buffer *buffer, 6480 const struct wined3d_shader_signature *input_signature, 6481 const struct wined3d_shader_reg_maps *reg_maps, 6482 const struct ps_compile_args *args, const struct wined3d_gl_info *gl_info, BOOL unroll) 6483 { 6484 unsigned int i; 6485 6486 for (i = 0; i < input_signature->element_count; ++i) 6487 { 6488 const struct wined3d_shader_signature_element *input = &input_signature->elements[i]; 6489 const char *semantic_name; 6490 UINT semantic_idx; 6491 char reg_mask[6]; 6492 6493 /* Unused */ 6494 if (!(reg_maps->input_registers & (1u << input->register_idx))) 6495 continue; 6496 6497 semantic_name = input->semantic_name; 6498 semantic_idx = input->semantic_idx; 6499 shader_glsl_write_mask_to_str(input->mask, reg_mask); 6500 6501 if (args->vp_mode == vertexshader) 6502 { 6503 if (input->sysval_semantic == WINED3D_SV_POSITION && !semantic_idx) 6504 { 6505 shader_addline(buffer, "ps_in[%u]%s = vpos%s;\n", 6506 shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask); 6507 } 6508 else if (args->pointsprite && shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD)) 6509 { 6510 shader_addline(buffer, "ps_in[%u] = vec4(gl_PointCoord.xy, 0.0, 0.0);\n", input->register_idx); 6511 } 6512 else if (input->sysval_semantic == WINED3D_SV_IS_FRONT_FACE) 6513 { 6514 shader_addline(buffer, "ps_in[%u]%s = uintBitsToFloat(gl_FrontFacing ? 0xffffffffu : 0u);\n", 6515 input->register_idx, reg_mask); 6516 } 6517 else if (input->sysval_semantic == WINED3D_SV_RENDER_TARGET_ARRAY_INDEX && !semantic_idx) 6518 { 6519 if (gl_info->supported[ARB_FRAGMENT_LAYER_VIEWPORT]) 6520 shader_addline(buffer, "ps_in[%u]%s = intBitsToFloat(gl_Layer);\n", 6521 input->register_idx, reg_mask); 6522 else 6523 FIXME("ARB_fragment_layer_viewport is not supported.\n"); 6524 } 6525 else 6526 { 6527 if (input->sysval_semantic) 6528 FIXME("Unhandled sysval semantic %#x.\n", input->sysval_semantic); 6529 shader_addline(buffer, unroll ? "ps_in[%u]%s = %s%u%s;\n" : "ps_in[%u]%s = %s[%u]%s;\n", 6530 shader->u.ps.input_reg_map[input->register_idx], reg_mask, 6531 shader_glsl_shader_input_name(gl_info), 6532 shader->u.ps.input_reg_map[input->register_idx], reg_mask); 6533 } 6534 } 6535 else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD)) 6536 { 6537 if (args->pointsprite) 6538 shader_addline(buffer, "ps_in[%u] = vec4(gl_PointCoord.xy, 0.0, 0.0);\n", 6539 shader->u.ps.input_reg_map[input->register_idx]); 6540 else if (args->vp_mode == pretransformed && args->texcoords_initialized & (1u << semantic_idx)) 6541 shader_addline(buffer, "ps_in[%u]%s = %s[%u]%s;\n", 6542 shader->u.ps.input_reg_map[input->register_idx], reg_mask, 6543 needs_legacy_glsl_syntax(gl_info) 6544 ? "gl_TexCoord" : "ffp_varying_texcoord", semantic_idx, reg_mask); 6545 else 6546 shader_addline(buffer, "ps_in[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", 6547 shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask); 6548 } 6549 else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_COLOR)) 6550 { 6551 if (!semantic_idx) 6552 shader_addline(buffer, "ps_in[%u]%s = vec4(ffp_varying_diffuse)%s;\n", 6553 shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask); 6554 else if (semantic_idx == 1) 6555 shader_addline(buffer, "ps_in[%u]%s = vec4(ffp_varying_specular)%s;\n", 6556 shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask); 6557 else 6558 shader_addline(buffer, "ps_in[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", 6559 shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask); 6560 } 6561 else 6562 { 6563 shader_addline(buffer, "ps_in[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n", 6564 shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask); 6565 } 6566 } 6567 } 6568 6569 static void add_glsl_program_entry(struct shader_glsl_priv *priv, struct glsl_shader_prog_link *entry) 6570 { 6571 struct glsl_program_key key; 6572 6573 key.vs_id = entry->vs.id; 6574 key.hs_id = entry->hs.id; 6575 key.ds_id = entry->ds.id; 6576 key.gs_id = entry->gs.id; 6577 key.ps_id = entry->ps.id; 6578 key.cs_id = entry->cs.id; 6579 6580 if (wine_rb_put(&priv->program_lookup, &key, &entry->program_lookup_entry) == -1) 6581 { 6582 ERR("Failed to insert program entry.\n"); 6583 } 6584 } 6585 6586 static struct glsl_shader_prog_link *get_glsl_program_entry(const struct shader_glsl_priv *priv, 6587 const struct glsl_program_key *key) 6588 { 6589 struct wine_rb_entry *entry; 6590 6591 entry = wine_rb_get(&priv->program_lookup, key); 6592 return entry ? WINE_RB_ENTRY_VALUE(entry, struct glsl_shader_prog_link, program_lookup_entry) : NULL; 6593 } 6594 6595 /* Context activation is done by the caller. */ 6596 static void delete_glsl_program_entry(struct shader_glsl_priv *priv, const struct wined3d_gl_info *gl_info, 6597 struct glsl_shader_prog_link *entry) 6598 { 6599 wine_rb_remove(&priv->program_lookup, &entry->program_lookup_entry); 6600 6601 GL_EXTCALL(glDeleteProgram(entry->id)); 6602 if (entry->vs.id) 6603 list_remove(&entry->vs.shader_entry); 6604 if (entry->hs.id) 6605 list_remove(&entry->hs.shader_entry); 6606 if (entry->ds.id) 6607 list_remove(&entry->ds.shader_entry); 6608 if (entry->gs.id) 6609 list_remove(&entry->gs.shader_entry); 6610 if (entry->ps.id) 6611 list_remove(&entry->ps.shader_entry); 6612 if (entry->cs.id) 6613 list_remove(&entry->cs.shader_entry); 6614 heap_free(entry); 6615 } 6616 6617 static void shader_glsl_setup_vs3_output(struct shader_glsl_priv *priv, 6618 const struct wined3d_gl_info *gl_info, const DWORD *map, 6619 const struct wined3d_shader_signature *input_signature, 6620 const struct wined3d_shader_reg_maps *reg_maps_in, 6621 const struct wined3d_shader_signature *output_signature, 6622 const struct wined3d_shader_reg_maps *reg_maps_out) 6623 { 6624 struct wined3d_string_buffer *destination = string_buffer_get(&priv->string_buffers); 6625 const char *out_array_name = shader_glsl_shader_output_name(gl_info); 6626 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 6627 unsigned int in_count = vec4_varyings(3, gl_info); 6628 unsigned int max_varyings = needs_legacy_glsl_syntax(gl_info) ? in_count + 2 : in_count; 6629 DWORD in_idx, *set = NULL; 6630 unsigned int i, j; 6631 char reg_mask[6]; 6632 6633 set = heap_calloc(max_varyings, sizeof(*set)); 6634 6635 for (i = 0; i < input_signature->element_count; ++i) 6636 { 6637 const struct wined3d_shader_signature_element *input = &input_signature->elements[i]; 6638 6639 if (!(reg_maps_in->input_registers & (1u << input->register_idx))) 6640 continue; 6641 6642 in_idx = map[input->register_idx]; 6643 /* Declared, but not read register */ 6644 if (in_idx == ~0u) 6645 continue; 6646 if (in_idx >= max_varyings) 6647 { 6648 FIXME("More input varyings declared than supported, expect issues.\n"); 6649 continue; 6650 } 6651 6652 if (in_idx == in_count) 6653 string_buffer_sprintf(destination, "gl_FrontColor"); 6654 else if (in_idx == in_count + 1) 6655 string_buffer_sprintf(destination, "gl_FrontSecondaryColor"); 6656 else 6657 string_buffer_sprintf(destination, "%s[%u]", out_array_name, in_idx); 6658 6659 if (!set[in_idx]) 6660 set[in_idx] = ~0u; 6661 6662 for (j = 0; j < output_signature->element_count; ++j) 6663 { 6664 const struct wined3d_shader_signature_element *output = &output_signature->elements[j]; 6665 DWORD mask; 6666 6667 if (!(reg_maps_out->output_registers & (1u << output->register_idx)) 6668 || input->semantic_idx != output->semantic_idx 6669 || strcmp(input->semantic_name, output->semantic_name) 6670 || !(mask = input->mask & output->mask)) 6671 continue; 6672 6673 if (set[in_idx] == ~0u) 6674 set[in_idx] = 0; 6675 set[in_idx] |= mask & reg_maps_out->u.output_registers_mask[output->register_idx]; 6676 shader_glsl_write_mask_to_str(mask, reg_mask); 6677 6678 shader_addline(buffer, "%s%s = outputs[%u]%s;\n", 6679 destination->buffer, reg_mask, output->register_idx, reg_mask); 6680 } 6681 } 6682 6683 for (i = 0; i < max_varyings; ++i) 6684 { 6685 unsigned int size; 6686 6687 if (!set[i] || set[i] == WINED3DSP_WRITEMASK_ALL) 6688 continue; 6689 6690 if (set[i] == ~0u) 6691 set[i] = 0; 6692 6693 size = 0; 6694 if (!(set[i] & WINED3DSP_WRITEMASK_0)) 6695 reg_mask[size++] = 'x'; 6696 if (!(set[i] & WINED3DSP_WRITEMASK_1)) 6697 reg_mask[size++] = 'y'; 6698 if (!(set[i] & WINED3DSP_WRITEMASK_2)) 6699 reg_mask[size++] = 'z'; 6700 if (!(set[i] & WINED3DSP_WRITEMASK_3)) 6701 reg_mask[size++] = 'w'; 6702 reg_mask[size] = '\0'; 6703 6704 if (i == in_count) 6705 string_buffer_sprintf(destination, "gl_FrontColor"); 6706 else if (i == in_count + 1) 6707 string_buffer_sprintf(destination, "gl_FrontSecondaryColor"); 6708 else 6709 string_buffer_sprintf(destination, "%s[%u]", out_array_name, i); 6710 6711 if (size == 1) 6712 shader_addline(buffer, "%s.%s = 0.0;\n", destination->buffer, reg_mask); 6713 else 6714 shader_addline(buffer, "%s.%s = vec%u(0.0);\n", destination->buffer, reg_mask, size); 6715 } 6716 6717 heap_free(set); 6718 string_buffer_release(&priv->string_buffers, destination); 6719 } 6720 6721 static void shader_glsl_setup_sm4_shader_output(struct shader_glsl_priv *priv, 6722 unsigned int input_count, const struct wined3d_shader_signature *output_signature, 6723 const struct wined3d_shader_reg_maps *reg_maps_out, const char *output_variable_name, 6724 BOOL rasterizer_setup) 6725 { 6726 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 6727 char reg_mask[6]; 6728 unsigned int i; 6729 6730 for (i = 0; i < output_signature->element_count; ++i) 6731 { 6732 const struct wined3d_shader_signature_element *output = &output_signature->elements[i]; 6733 6734 if (!(reg_maps_out->output_registers & (1u << output->register_idx))) 6735 continue; 6736 6737 if (output->stream_idx) 6738 continue; 6739 6740 if (output->register_idx >= input_count) 6741 continue; 6742 6743 shader_glsl_write_mask_to_str(output->mask, reg_mask); 6744 6745 shader_addline(buffer, 6746 rasterizer_setup ? "%s.reg%u%s = outputs[%u]%s;\n" : "%s.reg[%u]%s = outputs[%u]%s;\n", 6747 output_variable_name, output->register_idx, reg_mask, output->register_idx, reg_mask); 6748 } 6749 } 6750 6751 static void shader_glsl_generate_clip_or_cull_distances(struct wined3d_string_buffer *buffer, 6752 const struct wined3d_shader_signature_element *element, DWORD clip_or_cull_distance_mask) 6753 { 6754 unsigned int i, clip_or_cull_index; 6755 const char *name; 6756 char reg_mask[6]; 6757 6758 name = element->sysval_semantic == WINED3D_SV_CLIP_DISTANCE ? "Clip" : "Cull"; 6759 /* Assign consecutive indices starting from 0. */ 6760 clip_or_cull_index = element->semantic_idx ? wined3d_popcount(clip_or_cull_distance_mask & 0xf) : 0; 6761 for (i = 0; i < 4; ++i) 6762 { 6763 if (!(element->mask & (WINED3DSP_WRITEMASK_0 << i))) 6764 continue; 6765 6766 shader_glsl_write_mask_to_str(WINED3DSP_WRITEMASK_0 << i, reg_mask); 6767 shader_addline(buffer, "gl_%sDistance[%u] = outputs[%u]%s;\n", 6768 name, clip_or_cull_index, element->register_idx, reg_mask); 6769 ++clip_or_cull_index; 6770 } 6771 } 6772 6773 static void shader_glsl_setup_sm3_rasterizer_input(struct shader_glsl_priv *priv, 6774 const struct wined3d_gl_info *gl_info, const DWORD *map, 6775 const struct wined3d_shader_signature *input_signature, 6776 const struct wined3d_shader_reg_maps *reg_maps_in, unsigned int input_count, 6777 const struct wined3d_shader_signature *output_signature, 6778 const struct wined3d_shader_reg_maps *reg_maps_out, BOOL per_vertex_point_size) 6779 { 6780 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 6781 const char *semantic_name; 6782 unsigned int semantic_idx; 6783 char reg_mask[6]; 6784 unsigned int i; 6785 6786 /* First, sort out position and point size system values. */ 6787 for (i = 0; i < output_signature->element_count; ++i) 6788 { 6789 const struct wined3d_shader_signature_element *output = &output_signature->elements[i]; 6790 6791 if (!(reg_maps_out->output_registers & (1u << output->register_idx))) 6792 continue; 6793 6794 if (output->stream_idx) 6795 continue; 6796 6797 semantic_name = output->semantic_name; 6798 semantic_idx = output->semantic_idx; 6799 shader_glsl_write_mask_to_str(output->mask, reg_mask); 6800 6801 if (output->sysval_semantic == WINED3D_SV_POSITION && !semantic_idx) 6802 { 6803 shader_addline(buffer, "gl_Position%s = outputs[%u]%s;\n", 6804 reg_mask, output->register_idx, reg_mask); 6805 } 6806 else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_PSIZE) && per_vertex_point_size) 6807 { 6808 shader_addline(buffer, "gl_PointSize = clamp(outputs[%u].%c, " 6809 "ffp_point.size_min, ffp_point.size_max);\n", output->register_idx, reg_mask[1]); 6810 } 6811 else if (output->sysval_semantic == WINED3D_SV_RENDER_TARGET_ARRAY_INDEX && !semantic_idx) 6812 { 6813 shader_addline(buffer, "gl_Layer = floatBitsToInt(outputs[%u])%s;\n", 6814 output->register_idx, reg_mask); 6815 } 6816 else if (output->sysval_semantic == WINED3D_SV_CLIP_DISTANCE) 6817 { 6818 shader_glsl_generate_clip_or_cull_distances(buffer, output, reg_maps_out->clip_distance_mask); 6819 } 6820 else if (output->sysval_semantic == WINED3D_SV_CULL_DISTANCE) 6821 { 6822 shader_glsl_generate_clip_or_cull_distances(buffer, output, reg_maps_out->cull_distance_mask); 6823 } 6824 else if (output->sysval_semantic) 6825 { 6826 FIXME("Unhandled sysval semantic %#x.\n", output->sysval_semantic); 6827 } 6828 } 6829 6830 /* Then, setup the pixel shader input. */ 6831 if (reg_maps_out->shader_version.major < 4) 6832 shader_glsl_setup_vs3_output(priv, gl_info, map, input_signature, reg_maps_in, 6833 output_signature, reg_maps_out); 6834 else 6835 shader_glsl_setup_sm4_shader_output(priv, input_count, output_signature, reg_maps_out, "shader_out", TRUE); 6836 } 6837 6838 /* Context activation is done by the caller. */ 6839 static GLuint shader_glsl_generate_vs3_rasterizer_input_setup(struct shader_glsl_priv *priv, 6840 const struct wined3d_shader *vs, const struct wined3d_shader *ps, 6841 BOOL per_vertex_point_size, BOOL flatshading, const struct wined3d_gl_info *gl_info) 6842 { 6843 const BOOL legacy_syntax = needs_legacy_glsl_syntax(gl_info); 6844 DWORD ps_major = ps ? ps->reg_maps.shader_version.major : 0; 6845 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 6846 const char *semantic_name; 6847 UINT semantic_idx; 6848 char reg_mask[6]; 6849 unsigned int i; 6850 GLuint ret; 6851 6852 string_buffer_clear(buffer); 6853 6854 shader_glsl_add_version_declaration(buffer, gl_info); 6855 6856 if (per_vertex_point_size) 6857 { 6858 shader_addline(buffer, "uniform struct\n{\n"); 6859 shader_addline(buffer, " float size_min;\n"); 6860 shader_addline(buffer, " float size_max;\n"); 6861 shader_addline(buffer, "} ffp_point;\n"); 6862 } 6863 6864 if (ps_major < 3) 6865 { 6866 DWORD colors_written_mask[2] = {0}; 6867 DWORD texcoords_written_mask[MAX_TEXTURES] = {0}; 6868 6869 if (!legacy_syntax) 6870 { 6871 declare_out_varying(gl_info, buffer, flatshading, "vec4 ffp_varying_diffuse;\n"); 6872 declare_out_varying(gl_info, buffer, flatshading, "vec4 ffp_varying_specular;\n"); 6873 declare_out_varying(gl_info, buffer, FALSE, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES); 6874 declare_out_varying(gl_info, buffer, FALSE, "float ffp_varying_fogcoord;\n"); 6875 } 6876 6877 shader_addline(buffer, "void setup_vs_output(in vec4 outputs[%u])\n{\n", vs->limits->packed_output); 6878 6879 for (i = 0; i < vs->output_signature.element_count; ++i) 6880 { 6881 const struct wined3d_shader_signature_element *output = &vs->output_signature.elements[i]; 6882 DWORD write_mask; 6883 6884 if (!(vs->reg_maps.output_registers & (1u << output->register_idx))) 6885 continue; 6886 6887 semantic_name = output->semantic_name; 6888 semantic_idx = output->semantic_idx; 6889 write_mask = output->mask; 6890 shader_glsl_write_mask_to_str(write_mask, reg_mask); 6891 6892 if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_COLOR) && semantic_idx < 2) 6893 { 6894 if (legacy_syntax) 6895 shader_addline(buffer, "gl_Front%sColor%s = outputs[%u]%s;\n", 6896 semantic_idx ? "Secondary" : "", reg_mask, output->register_idx, reg_mask); 6897 else 6898 shader_addline(buffer, "ffp_varying_%s%s = clamp(outputs[%u]%s, 0.0, 1.0);\n", 6899 semantic_idx ? "specular" : "diffuse", reg_mask, output->register_idx, reg_mask); 6900 6901 colors_written_mask[semantic_idx] = write_mask; 6902 } 6903 else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_POSITION) && !semantic_idx) 6904 { 6905 shader_addline(buffer, "gl_Position%s = outputs[%u]%s;\n", 6906 reg_mask, output->register_idx, reg_mask); 6907 } 6908 else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD)) 6909 { 6910 if (semantic_idx < MAX_TEXTURES) 6911 { 6912 shader_addline(buffer, "%s[%u]%s = outputs[%u]%s;\n", 6913 legacy_syntax ? "gl_TexCoord" : "ffp_varying_texcoord", 6914 semantic_idx, reg_mask, output->register_idx, reg_mask); 6915 texcoords_written_mask[semantic_idx] = write_mask; 6916 } 6917 } 6918 else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_PSIZE) && per_vertex_point_size) 6919 { 6920 shader_addline(buffer, "gl_PointSize = clamp(outputs[%u].%c, " 6921 "ffp_point.size_min, ffp_point.size_max);\n", output->register_idx, reg_mask[1]); 6922 } 6923 else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_FOG)) 6924 { 6925 shader_addline(buffer, "%s = clamp(outputs[%u].%c, 0.0, 1.0);\n", 6926 legacy_syntax ? "gl_FogFragCoord" : "ffp_varying_fogcoord", 6927 output->register_idx, reg_mask[1]); 6928 } 6929 } 6930 6931 for (i = 0; i < 2; ++i) 6932 { 6933 if (colors_written_mask[i] != WINED3DSP_WRITEMASK_ALL) 6934 { 6935 shader_glsl_write_mask_to_str(~colors_written_mask[i] & WINED3DSP_WRITEMASK_ALL, reg_mask); 6936 if (!i) 6937 shader_addline(buffer, "%s%s = vec4(1.0)%s;\n", 6938 legacy_syntax ? "gl_FrontColor" : "ffp_varying_diffuse", 6939 reg_mask, reg_mask); 6940 else 6941 shader_addline(buffer, "%s%s = vec4(0.0)%s;\n", 6942 legacy_syntax ? "gl_FrontSecondaryColor" : "ffp_varying_specular", 6943 reg_mask, reg_mask); 6944 } 6945 } 6946 for (i = 0; i < MAX_TEXTURES; ++i) 6947 { 6948 if (ps && !(ps->reg_maps.texcoord & (1u << i))) 6949 continue; 6950 6951 if (texcoords_written_mask[i] != WINED3DSP_WRITEMASK_ALL) 6952 { 6953 if (gl_info->limits.glsl_varyings < wined3d_max_compat_varyings(gl_info) 6954 && !texcoords_written_mask[i]) 6955 continue; 6956 6957 shader_glsl_write_mask_to_str(~texcoords_written_mask[i] & WINED3DSP_WRITEMASK_ALL, reg_mask); 6958 shader_addline(buffer, "%s[%u]%s = vec4(0.0)%s;\n", 6959 legacy_syntax ? "gl_TexCoord" : "ffp_varying_texcoord", i, reg_mask, reg_mask); 6960 } 6961 } 6962 } 6963 else 6964 { 6965 unsigned int in_count = min(vec4_varyings(ps_major, gl_info), ps->limits->packed_input); 6966 6967 shader_glsl_declare_shader_outputs(gl_info, buffer, in_count, FALSE, NULL); 6968 shader_addline(buffer, "void setup_vs_output(in vec4 outputs[%u])\n{\n", vs->limits->packed_output); 6969 shader_glsl_setup_sm3_rasterizer_input(priv, gl_info, ps->u.ps.input_reg_map, &ps->input_signature, 6970 &ps->reg_maps, 0, &vs->output_signature, &vs->reg_maps, per_vertex_point_size); 6971 } 6972 6973 shader_addline(buffer, "}\n"); 6974 6975 ret = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER)); 6976 checkGLcall("glCreateShader(GL_VERTEX_SHADER)"); 6977 shader_glsl_compile(gl_info, ret, buffer->buffer); 6978 6979 return ret; 6980 } 6981 6982 static void shader_glsl_generate_stream_output_setup(struct shader_glsl_priv *priv, 6983 const struct wined3d_shader *shader, const struct wined3d_stream_output_desc *so_desc) 6984 { 6985 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 6986 unsigned int i; 6987 6988 shader_addline(buffer, "out shader_in_out\n{\n"); 6989 for (i = 0; i < so_desc->element_count; ++i) 6990 { 6991 const struct wined3d_stream_output_element *e = &so_desc->elements[i]; 6992 6993 if (e->stream_idx) 6994 { 6995 FIXME("Unhandled stream %u.\n", e->stream_idx); 6996 continue; 6997 } 6998 if (e->register_idx == WINED3D_STREAM_OUTPUT_GAP) 6999 continue; 7000 7001 if (e->component_idx || e->component_count != 4) 7002 { 7003 if (e->component_count == 1) 7004 shader_addline(buffer, "float"); 7005 else 7006 shader_addline(buffer, "vec%u", e->component_count); 7007 shader_addline(buffer, " reg%u_%u_%u;\n", 7008 e->register_idx, e->component_idx, e->component_idx + e->component_count - 1); 7009 } 7010 else 7011 { 7012 shader_addline(buffer, "vec4 reg%u;\n", e->register_idx); 7013 } 7014 } 7015 shader_addline(buffer, "} shader_out;\n"); 7016 7017 shader_addline(buffer, "void setup_gs_output(in vec4 outputs[%u])\n{\n", 7018 shader->limits->packed_output); 7019 for (i = 0; i < so_desc->element_count; ++i) 7020 { 7021 const struct wined3d_stream_output_element *e = &so_desc->elements[i]; 7022 7023 if (e->stream_idx) 7024 { 7025 FIXME("Unhandled stream %u.\n", e->stream_idx); 7026 continue; 7027 } 7028 if (e->register_idx == WINED3D_STREAM_OUTPUT_GAP) 7029 continue; 7030 7031 if (e->component_idx || e->component_count != 4) 7032 { 7033 DWORD write_mask; 7034 char str_mask[6]; 7035 7036 write_mask = ((1u << e->component_count) - 1) << e->component_idx; 7037 shader_glsl_write_mask_to_str(write_mask, str_mask); 7038 shader_addline(buffer, "shader_out.reg%u_%u_%u = outputs[%u]%s;\n", 7039 e->register_idx, e->component_idx, e->component_idx + e->component_count - 1, 7040 e->register_idx, str_mask); 7041 } 7042 else 7043 { 7044 shader_addline(buffer, "shader_out.reg%u = outputs[%u];\n", 7045 e->register_idx, e->register_idx); 7046 } 7047 } 7048 shader_addline(buffer, "}\n"); 7049 } 7050 7051 static void shader_glsl_generate_sm4_output_setup(struct shader_glsl_priv *priv, 7052 const struct wined3d_shader *shader, unsigned int input_count, 7053 const struct wined3d_gl_info *gl_info, BOOL rasterizer_setup, const DWORD *interpolation_mode) 7054 { 7055 const char *prefix = shader_glsl_get_prefix(shader->reg_maps.shader_version.type); 7056 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 7057 7058 if (rasterizer_setup) 7059 input_count = min(vec4_varyings(4, gl_info), input_count); 7060 7061 if (input_count) 7062 shader_glsl_declare_shader_outputs(gl_info, buffer, input_count, rasterizer_setup, interpolation_mode); 7063 7064 shader_addline(buffer, "void setup_%s_output(in vec4 outputs[%u])\n{\n", 7065 prefix, shader->limits->packed_output); 7066 7067 if (rasterizer_setup) 7068 shader_glsl_setup_sm3_rasterizer_input(priv, gl_info, NULL, NULL, 7069 NULL, input_count, &shader->output_signature, &shader->reg_maps, FALSE); 7070 else 7071 shader_glsl_setup_sm4_shader_output(priv, input_count, &shader->output_signature, 7072 &shader->reg_maps, "shader_out", rasterizer_setup); 7073 7074 shader_addline(buffer, "}\n"); 7075 } 7076 7077 static void shader_glsl_generate_patch_constant_name(struct wined3d_string_buffer *buffer, 7078 const struct wined3d_shader_signature_element *constant, unsigned int *user_constant_idx, 7079 const char *reg_mask) 7080 { 7081 if (!constant->sysval_semantic) 7082 { 7083 shader_addline(buffer, "user_patch_constant[%u]%s", (*user_constant_idx)++, reg_mask); 7084 return; 7085 } 7086 7087 switch (constant->sysval_semantic) 7088 { 7089 case WINED3D_SV_TESS_FACTOR_QUADEDGE: 7090 case WINED3D_SV_TESS_FACTOR_TRIEDGE: 7091 case WINED3D_SV_TESS_FACTOR_LINEDET: 7092 case WINED3D_SV_TESS_FACTOR_LINEDEN: 7093 shader_addline(buffer, "gl_TessLevelOuter[%u]", constant->semantic_idx); 7094 break; 7095 case WINED3D_SV_TESS_FACTOR_QUADINT: 7096 case WINED3D_SV_TESS_FACTOR_TRIINT: 7097 shader_addline(buffer, "gl_TessLevelInner[%u]", constant->semantic_idx); 7098 break; 7099 default: 7100 FIXME("Unhandled sysval semantic %#x.\n", constant->sysval_semantic); 7101 shader_addline(buffer, "vec4(0.0)%s", reg_mask); 7102 } 7103 } 7104 7105 static void shader_glsl_generate_patch_constant_setup(struct wined3d_string_buffer *buffer, 7106 const struct wined3d_shader_signature *signature, BOOL input_setup) 7107 { 7108 unsigned int i, register_count, user_constant_index, user_constant_count; 7109 7110 register_count = user_constant_count = 0; 7111 for (i = 0; i < signature->element_count; ++i) 7112 { 7113 const struct wined3d_shader_signature_element *constant = &signature->elements[i]; 7114 register_count = max(constant->register_idx + 1, register_count); 7115 if (!constant->sysval_semantic) 7116 ++user_constant_count; 7117 } 7118 7119 if (user_constant_count) 7120 shader_addline(buffer, "patch %s vec4 user_patch_constant[%u];\n", 7121 input_setup ? "in" : "out", user_constant_count); 7122 if (input_setup) 7123 shader_addline(buffer, "vec4 vpc[%u];\n", register_count); 7124 7125 shader_addline(buffer, "void setup_patch_constant_%s()\n{\n", input_setup ? "input" : "output"); 7126 for (i = 0, user_constant_index = 0; i < signature->element_count; ++i) 7127 { 7128 const struct wined3d_shader_signature_element *constant = &signature->elements[i]; 7129 char reg_mask[6]; 7130 7131 shader_glsl_write_mask_to_str(constant->mask, reg_mask); 7132 7133 if (input_setup) 7134 shader_addline(buffer, "vpc[%u]%s", constant->register_idx, reg_mask); 7135 else 7136 shader_glsl_generate_patch_constant_name(buffer, constant, &user_constant_index, reg_mask); 7137 7138 shader_addline(buffer, " = "); 7139 7140 if (input_setup) 7141 shader_glsl_generate_patch_constant_name(buffer, constant, &user_constant_index, reg_mask); 7142 else 7143 shader_addline(buffer, "hs_out[%u]%s", constant->register_idx, reg_mask); 7144 7145 shader_addline(buffer, ";\n"); 7146 } 7147 shader_addline(buffer, "}\n"); 7148 } 7149 7150 static void shader_glsl_generate_srgb_write_correction(struct wined3d_string_buffer *buffer, 7151 const struct wined3d_gl_info *gl_info) 7152 { 7153 const char *output = needs_legacy_glsl_syntax(gl_info) ? "gl_FragData[0]" : "ps_out0"; 7154 7155 shader_addline(buffer, "tmp0.xyz = pow(%s.xyz, vec3(srgb_const0.x));\n", output); 7156 shader_addline(buffer, "tmp0.xyz = tmp0.xyz * vec3(srgb_const0.y) - vec3(srgb_const0.z);\n"); 7157 shader_addline(buffer, "tmp1.xyz = %s.xyz * vec3(srgb_const0.w);\n", output); 7158 shader_addline(buffer, "bvec3 srgb_compare = lessThan(%s.xyz, vec3(srgb_const1.x));\n", output); 7159 shader_addline(buffer, "%s.xyz = mix(tmp0.xyz, tmp1.xyz, vec3(srgb_compare));\n", output); 7160 shader_addline(buffer, "%s = clamp(%s, 0.0, 1.0);\n", output, output); 7161 } 7162 7163 static void shader_glsl_generate_fog_code(struct wined3d_string_buffer *buffer, 7164 const struct wined3d_gl_info *gl_info, enum wined3d_ffp_ps_fog_mode mode) 7165 { 7166 const char *output = needs_legacy_glsl_syntax(gl_info) ? "gl_FragData[0]" : "ps_out0"; 7167 7168 switch (mode) 7169 { 7170 case WINED3D_FFP_PS_FOG_OFF: 7171 return; 7172 7173 case WINED3D_FFP_PS_FOG_LINEAR: 7174 shader_addline(buffer, "float fog = (ffp_fog.end - ffp_varying_fogcoord) * ffp_fog.scale;\n"); 7175 break; 7176 7177 case WINED3D_FFP_PS_FOG_EXP: 7178 shader_addline(buffer, "float fog = exp(-ffp_fog.density * ffp_varying_fogcoord);\n"); 7179 break; 7180 7181 case WINED3D_FFP_PS_FOG_EXP2: 7182 shader_addline(buffer, "float fog = exp(-ffp_fog.density * ffp_fog.density" 7183 " * ffp_varying_fogcoord * ffp_varying_fogcoord);\n"); 7184 break; 7185 7186 default: 7187 ERR("Invalid fog mode %#x.\n", mode); 7188 return; 7189 } 7190 7191 shader_addline(buffer, "%s.xyz = mix(ffp_fog.color.xyz, %s.xyz, clamp(fog, 0.0, 1.0));\n", 7192 output, output); 7193 } 7194 7195 static void shader_glsl_generate_alpha_test(struct wined3d_string_buffer *buffer, 7196 const struct wined3d_gl_info *gl_info, enum wined3d_cmp_func alpha_func) 7197 { 7198 const char *output = needs_legacy_glsl_syntax(gl_info) ? "gl_FragData[0]" : "ps_out0"; 7199 7200 /* alpha_func is the PASS condition, not the DISCARD condition. Instead of 7201 * flipping all the operators here, just negate the comparison below. */ 7202 static const char * const comparison_operator[] = 7203 { 7204 "", /* WINED3D_CMP_NEVER */ 7205 "<", /* WINED3D_CMP_LESS */ 7206 "==", /* WINED3D_CMP_EQUAL */ 7207 "<=", /* WINED3D_CMP_LESSEQUAL */ 7208 ">", /* WINED3D_CMP_GREATER */ 7209 "!=", /* WINED3D_CMP_NOTEQUAL */ 7210 ">=", /* WINED3D_CMP_GREATEREQUAL */ 7211 "" /* WINED3D_CMP_ALWAYS */ 7212 }; 7213 7214 if (alpha_func == WINED3D_CMP_ALWAYS) 7215 return; 7216 7217 if (alpha_func != WINED3D_CMP_NEVER) 7218 shader_addline(buffer, "if (!(%s.a %s alpha_test_ref))\n", 7219 output, comparison_operator[alpha_func - WINED3D_CMP_NEVER]); 7220 shader_addline(buffer, " discard;\n"); 7221 } 7222 7223 static void shader_glsl_enable_extensions(struct wined3d_string_buffer *buffer, 7224 const struct wined3d_gl_info *gl_info) 7225 { 7226 if (gl_info->supported[ARB_CULL_DISTANCE]) 7227 shader_addline(buffer, "#extension GL_ARB_cull_distance : enable\n"); 7228 if (gl_info->supported[ARB_GPU_SHADER5]) 7229 shader_addline(buffer, "#extension GL_ARB_gpu_shader5 : enable\n"); 7230 if (gl_info->supported[ARB_SHADER_ATOMIC_COUNTERS]) 7231 shader_addline(buffer, "#extension GL_ARB_shader_atomic_counters : enable\n"); 7232 if (gl_info->supported[ARB_SHADER_BIT_ENCODING]) 7233 shader_addline(buffer, "#extension GL_ARB_shader_bit_encoding : enable\n"); 7234 if (gl_info->supported[ARB_SHADER_IMAGE_LOAD_STORE]) 7235 shader_addline(buffer, "#extension GL_ARB_shader_image_load_store : enable\n"); 7236 if (gl_info->supported[ARB_SHADER_IMAGE_SIZE]) 7237 shader_addline(buffer, "#extension GL_ARB_shader_image_size : enable\n"); 7238 if (gl_info->supported[ARB_SHADER_STORAGE_BUFFER_OBJECT]) 7239 shader_addline(buffer, "#extension GL_ARB_shader_storage_buffer_object : enable\n"); 7240 if (gl_info->supported[ARB_SHADING_LANGUAGE_420PACK]) 7241 shader_addline(buffer, "#extension GL_ARB_shading_language_420pack : enable\n"); 7242 if (gl_info->supported[ARB_SHADING_LANGUAGE_PACKING]) 7243 shader_addline(buffer, "#extension GL_ARB_shading_language_packing : enable\n"); 7244 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP_ARRAY]) 7245 shader_addline(buffer, "#extension GL_ARB_texture_cube_map_array : enable\n"); 7246 if (gl_info->supported[ARB_TEXTURE_GATHER]) 7247 shader_addline(buffer, "#extension GL_ARB_texture_gather : enable\n"); 7248 if (gl_info->supported[ARB_TEXTURE_QUERY_LEVELS]) 7249 shader_addline(buffer, "#extension GL_ARB_texture_query_levels : enable\n"); 7250 if (gl_info->supported[ARB_UNIFORM_BUFFER_OBJECT]) 7251 shader_addline(buffer, "#extension GL_ARB_uniform_buffer_object : enable\n"); 7252 if (gl_info->supported[EXT_GPU_SHADER4]) 7253 shader_addline(buffer, "#extension GL_EXT_gpu_shader4 : enable\n"); 7254 if (gl_info->supported[EXT_TEXTURE_ARRAY]) 7255 shader_addline(buffer, "#extension GL_EXT_texture_array : enable\n"); 7256 } 7257 7258 static void shader_glsl_generate_ps_epilogue(const struct wined3d_gl_info *gl_info, 7259 struct wined3d_string_buffer *buffer, const struct wined3d_shader *shader, 7260 const struct ps_compile_args *args) 7261 { 7262 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; 7263 const char *output = needs_legacy_glsl_syntax(gl_info) ? "gl_FragData[0]" : "ps_out0"; 7264 7265 /* Pixel shaders < 2.0 place the resulting color in R0 implicitly. */ 7266 if (reg_maps->shader_version.major < 2) 7267 shader_addline(buffer, "%s = R0;\n", output); 7268 7269 if (args->srgb_correction) 7270 shader_glsl_generate_srgb_write_correction(buffer, gl_info); 7271 7272 /* SM < 3 does not replace the fog stage. */ 7273 if (reg_maps->shader_version.major < 3) 7274 shader_glsl_generate_fog_code(buffer, gl_info, args->fog); 7275 7276 shader_glsl_generate_alpha_test(buffer, gl_info, args->alpha_test_func + 1); 7277 } 7278 7279 /* Context activation is done by the caller. */ 7280 static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context, 7281 struct wined3d_string_buffer *buffer, struct wined3d_string_buffer_list *string_buffers, 7282 const struct wined3d_shader *shader, 7283 const struct ps_compile_args *args, struct ps_np2fixup_info *np2fixup_info) 7284 { 7285 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; 7286 const struct wined3d_shader_version *version = ®_maps->shader_version; 7287 const char *prefix = shader_glsl_get_prefix(version->type); 7288 const struct wined3d_gl_info *gl_info = context->gl_info; 7289 const BOOL legacy_syntax = needs_legacy_glsl_syntax(gl_info); 7290 unsigned int i, extra_constants_needed = 0; 7291 struct shader_glsl_ctx_priv priv_ctx; 7292 GLuint shader_id; 7293 DWORD map; 7294 7295 memset(&priv_ctx, 0, sizeof(priv_ctx)); 7296 priv_ctx.cur_ps_args = args; 7297 priv_ctx.cur_np2fixup_info = np2fixup_info; 7298 priv_ctx.string_buffers = string_buffers; 7299 7300 shader_glsl_add_version_declaration(buffer, gl_info); 7301 7302 shader_glsl_enable_extensions(buffer, gl_info); 7303 if (gl_info->supported[ARB_CONSERVATIVE_DEPTH]) 7304 shader_addline(buffer, "#extension GL_ARB_conservative_depth : enable\n"); 7305 if (gl_info->supported[ARB_DERIVATIVE_CONTROL]) 7306 shader_addline(buffer, "#extension GL_ARB_derivative_control : enable\n"); 7307 if (shader_glsl_use_explicit_attrib_location(gl_info)) 7308 shader_addline(buffer, "#extension GL_ARB_explicit_attrib_location : enable\n"); 7309 if (gl_info->supported[ARB_FRAGMENT_COORD_CONVENTIONS]) 7310 shader_addline(buffer, "#extension GL_ARB_fragment_coord_conventions : enable\n"); 7311 if (gl_info->supported[ARB_FRAGMENT_LAYER_VIEWPORT]) 7312 shader_addline(buffer, "#extension GL_ARB_fragment_layer_viewport : enable\n"); 7313 if (gl_info->supported[ARB_SHADER_TEXTURE_LOD]) 7314 shader_addline(buffer, "#extension GL_ARB_shader_texture_lod : enable\n"); 7315 /* The spec says that it doesn't have to be explicitly enabled, but the 7316 * nvidia drivers write a warning if we don't do so. */ 7317 if (gl_info->supported[ARB_TEXTURE_RECTANGLE]) 7318 shader_addline(buffer, "#extension GL_ARB_texture_rectangle : enable\n"); 7319 7320 /* Base Declarations */ 7321 shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx); 7322 7323 if (gl_info->supported[ARB_CONSERVATIVE_DEPTH]) 7324 { 7325 if (shader->u.ps.depth_output == WINED3DSPR_DEPTHOUTGE) 7326 shader_addline(buffer, "layout (depth_greater) out float gl_FragDepth;\n"); 7327 else if (shader->u.ps.depth_output == WINED3DSPR_DEPTHOUTLE) 7328 shader_addline(buffer, "layout (depth_less) out float gl_FragDepth;\n"); 7329 } 7330 7331 /* Declare uniforms for NP2 texcoord fixup: 7332 * This is NOT done inside the loop that declares the texture samplers 7333 * since the NP2 fixup code is currently only used for the GeforceFX 7334 * series and when forcing the ARB_npot extension off. Modern cards just 7335 * skip the code anyway, so put it inside a separate loop. */ 7336 if (args->np2_fixup) 7337 { 7338 struct ps_np2fixup_info *fixup = priv_ctx.cur_np2fixup_info; 7339 unsigned int cur = 0; 7340 7341 /* NP2/RECT textures in OpenGL use texcoords in the range [0,width]x[0,height] 7342 * while D3D has them in the (normalized) [0,1]x[0,1] range. 7343 * samplerNP2Fixup stores texture dimensions and is updated through 7344 * shader_glsl_load_np2fixup_constants when the sampler changes. */ 7345 7346 for (i = 0; i < shader->limits->sampler; ++i) 7347 { 7348 if (!reg_maps->resource_info[i].type || !(args->np2_fixup & (1u << i))) 7349 continue; 7350 7351 if (reg_maps->resource_info[i].type != WINED3D_SHADER_RESOURCE_TEXTURE_2D) 7352 { 7353 FIXME("Non-2D texture is flagged for NP2 texcoord fixup.\n"); 7354 continue; 7355 } 7356 7357 fixup->idx[i] = cur++; 7358 } 7359 7360 fixup->num_consts = (cur + 1) >> 1; 7361 fixup->active = args->np2_fixup; 7362 shader_addline(buffer, "uniform vec4 %s_samplerNP2Fixup[%u];\n", prefix, fixup->num_consts); 7363 } 7364 7365 if (version->major < 3 || args->vp_mode != vertexshader) 7366 { 7367 shader_addline(buffer, "uniform struct\n{\n"); 7368 shader_addline(buffer, " vec4 color;\n"); 7369 shader_addline(buffer, " float density;\n"); 7370 shader_addline(buffer, " float end;\n"); 7371 shader_addline(buffer, " float scale;\n"); 7372 shader_addline(buffer, "} ffp_fog;\n"); 7373 7374 if (needs_legacy_glsl_syntax(gl_info)) 7375 { 7376 if (glsl_is_color_reg_read(shader, 0)) 7377 shader_addline(buffer, "vec4 ffp_varying_diffuse;\n"); 7378 if (glsl_is_color_reg_read(shader, 1)) 7379 shader_addline(buffer, "vec4 ffp_varying_specular;\n"); 7380 shader_addline(buffer, "vec4 ffp_texcoord[%u];\n", MAX_TEXTURES); 7381 shader_addline(buffer, "float ffp_varying_fogcoord;\n"); 7382 } 7383 else 7384 { 7385 if (glsl_is_color_reg_read(shader, 0)) 7386 declare_in_varying(gl_info, buffer, args->flatshading, "vec4 ffp_varying_diffuse;\n"); 7387 if (glsl_is_color_reg_read(shader, 1)) 7388 declare_in_varying(gl_info, buffer, args->flatshading, "vec4 ffp_varying_specular;\n"); 7389 declare_in_varying(gl_info, buffer, FALSE, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES); 7390 shader_addline(buffer, "vec4 ffp_texcoord[%u];\n", MAX_TEXTURES); 7391 declare_in_varying(gl_info, buffer, FALSE, "float ffp_varying_fogcoord;\n"); 7392 } 7393 } 7394 7395 if (version->major >= 3) 7396 { 7397 unsigned int in_count = min(vec4_varyings(version->major, gl_info), shader->limits->packed_input); 7398 7399 if (args->vp_mode == vertexshader && reg_maps->input_registers) 7400 shader_glsl_declare_shader_inputs(gl_info, buffer, in_count, 7401 shader->u.ps.interpolation_mode, version->major >= 4); 7402 shader_addline(buffer, "vec4 %s_in[%u];\n", prefix, in_count); 7403 } 7404 7405 for (i = 0, map = reg_maps->bumpmat; map; map >>= 1, ++i) 7406 { 7407 if (!(map & 1)) 7408 continue; 7409 7410 shader_addline(buffer, "uniform mat2 bumpenv_mat%u;\n", i); 7411 7412 if (reg_maps->luminanceparams & (1u << i)) 7413 { 7414 shader_addline(buffer, "uniform float bumpenv_lum_scale%u;\n", i); 7415 shader_addline(buffer, "uniform float bumpenv_lum_offset%u;\n", i); 7416 extra_constants_needed++; 7417 } 7418 7419 extra_constants_needed++; 7420 } 7421 7422 if (args->srgb_correction) 7423 { 7424 shader_addline(buffer, "const vec4 srgb_const0 = "); 7425 shader_glsl_append_imm_vec4(buffer, wined3d_srgb_const0); 7426 shader_addline(buffer, ";\n"); 7427 shader_addline(buffer, "const vec4 srgb_const1 = "); 7428 shader_glsl_append_imm_vec4(buffer, wined3d_srgb_const1); 7429 shader_addline(buffer, ";\n"); 7430 } 7431 if (reg_maps->vpos || reg_maps->usesdsy) 7432 { 7433 if (reg_maps->usesdsy || !gl_info->supported[ARB_FRAGMENT_COORD_CONVENTIONS]) 7434 { 7435 ++extra_constants_needed; 7436 shader_addline(buffer, "uniform vec4 ycorrection;\n"); 7437 } 7438 if (reg_maps->vpos) 7439 { 7440 if (gl_info->supported[ARB_FRAGMENT_COORD_CONVENTIONS]) 7441 { 7442 if (context->d3d_info->wined3d_creation_flags & WINED3D_PIXEL_CENTER_INTEGER) 7443 shader_addline(buffer, "layout(%spixel_center_integer) in vec4 gl_FragCoord;\n", 7444 args->render_offscreen ? "" : "origin_upper_left, "); 7445 else if (!args->render_offscreen) 7446 shader_addline(buffer, "layout(origin_upper_left) in vec4 gl_FragCoord;\n"); 7447 } 7448 shader_addline(buffer, "vec4 vpos;\n"); 7449 } 7450 } 7451 7452 if (args->alpha_test_func + 1 != WINED3D_CMP_ALWAYS) 7453 shader_addline(buffer, "uniform float alpha_test_ref;\n"); 7454 7455 if (!needs_legacy_glsl_syntax(gl_info)) 7456 { 7457 if (args->dual_source_blend) 7458 { 7459 for (i = 0; i < gl_info->limits.dual_buffers * 2; i++) 7460 { 7461 if (shader_glsl_use_explicit_attrib_location(gl_info)) 7462 shader_addline(buffer, "layout(location = %u, index = %u) ", i / 2, i % 2); 7463 shader_addline(buffer, "out vec4 ps_out%u;\n", i); 7464 } 7465 } 7466 else 7467 { 7468 for (i = 0; i < gl_info->limits.buffers; i++) 7469 { 7470 if (shader_glsl_use_explicit_attrib_location(gl_info)) 7471 shader_addline(buffer, "layout(location = %u) ", i); 7472 shader_addline(buffer, "out vec4 ps_out%u;\n", i); 7473 } 7474 } 7475 } 7476 7477 if (shader->limits->constant_float + extra_constants_needed >= gl_info->limits.glsl_ps_float_constants) 7478 FIXME("Insufficient uniforms to run this shader.\n"); 7479 7480 if (shader->u.ps.force_early_depth_stencil) 7481 shader_addline(buffer, "layout(early_fragment_tests) in;\n"); 7482 7483 shader_addline(buffer, "void main()\n{\n"); 7484 7485 /* Direct3D applications expect integer vPos values, while OpenGL drivers 7486 * add approximately 0.5. This causes off-by-one problems as spotted by 7487 * the vPos d3d9 visual test. Unfortunately ATI cards do not add exactly 7488 * 0.5, but rather something like 0.49999999 or 0.50000001, which still 7489 * causes precision troubles when we just subtract 0.5. 7490 * 7491 * To deal with that, just floor() the position. This will eliminate the 7492 * fraction on all cards. 7493 * 7494 * TODO: Test how this behaves with multisampling. 7495 * 7496 * An advantage of floor is that it works even if the driver doesn't add 7497 * 0.5. It is somewhat questionable if 1.5, 2.5, ... are the proper values 7498 * to return in gl_FragCoord, even though coordinates specify the pixel 7499 * centers instead of the pixel corners. This code will behave correctly 7500 * on drivers that returns integer values. */ 7501 if (reg_maps->vpos) 7502 { 7503 if (gl_info->supported[ARB_FRAGMENT_COORD_CONVENTIONS]) 7504 shader_addline(buffer, "vpos = gl_FragCoord;\n"); 7505 else if (context->d3d_info->wined3d_creation_flags & WINED3D_PIXEL_CENTER_INTEGER) 7506 shader_addline(buffer, 7507 "vpos = floor(vec4(0, ycorrection[0], 0, 0) + gl_FragCoord * vec4(1, ycorrection[1], 1, 1));\n"); 7508 else 7509 shader_addline(buffer, 7510 "vpos = vec4(0, ycorrection[0], 0, 0) + gl_FragCoord * vec4(1, ycorrection[1], 1, 1);\n"); 7511 } 7512 7513 if (reg_maps->shader_version.major < 3 || args->vp_mode != vertexshader) 7514 { 7515 unsigned int i; 7516 WORD map = reg_maps->texcoord; 7517 7518 if (legacy_syntax) 7519 { 7520 if (glsl_is_color_reg_read(shader, 0)) 7521 shader_addline(buffer, "ffp_varying_diffuse = gl_Color;\n"); 7522 if (glsl_is_color_reg_read(shader, 1)) 7523 shader_addline(buffer, "ffp_varying_specular = gl_SecondaryColor;\n"); 7524 } 7525 7526 for (i = 0; map; map >>= 1, ++i) 7527 { 7528 if (map & 1) 7529 { 7530 if (args->pointsprite) 7531 shader_addline(buffer, "ffp_texcoord[%u] = vec4(gl_PointCoord.xy, 0.0, 0.0);\n", i); 7532 else if (args->texcoords_initialized & (1u << i)) 7533 shader_addline(buffer, "ffp_texcoord[%u] = %s[%u];\n", i, 7534 legacy_syntax ? "gl_TexCoord" : "ffp_varying_texcoord", i); 7535 else 7536 shader_addline(buffer, "ffp_texcoord[%u] = vec4(0.0);\n", i); 7537 shader_addline(buffer, "vec4 T%u = ffp_texcoord[%u];\n", i, i); 7538 } 7539 } 7540 7541 if (legacy_syntax) 7542 shader_addline(buffer, "ffp_varying_fogcoord = gl_FogFragCoord;\n"); 7543 } 7544 7545 /* Pack 3.0 inputs */ 7546 if (reg_maps->shader_version.major >= 3) 7547 shader_glsl_input_pack(shader, buffer, &shader->input_signature, reg_maps, args, gl_info, 7548 reg_maps->shader_version.major >= 4); 7549 7550 /* Base Shader Body */ 7551 if (FAILED(shader_generate_code(shader, buffer, reg_maps, &priv_ctx, NULL, NULL))) 7552 return 0; 7553 7554 /* In SM4+ the shader epilogue is generated by the "ret" instruction. */ 7555 if (reg_maps->shader_version.major < 4) 7556 shader_glsl_generate_ps_epilogue(gl_info, buffer, shader, args); 7557 7558 shader_addline(buffer, "}\n"); 7559 7560 shader_id = GL_EXTCALL(glCreateShader(GL_FRAGMENT_SHADER)); 7561 TRACE("Compiling shader object %u.\n", shader_id); 7562 shader_glsl_compile(gl_info, shader_id, buffer->buffer); 7563 7564 return shader_id; 7565 } 7566 7567 static void shader_glsl_generate_vs_epilogue(const struct wined3d_gl_info *gl_info, 7568 struct wined3d_string_buffer *buffer, const struct wined3d_shader *shader, 7569 const struct vs_compile_args *args) 7570 { 7571 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; 7572 const BOOL legacy_syntax = needs_legacy_glsl_syntax(gl_info); 7573 unsigned int i; 7574 7575 /* Unpack outputs. */ 7576 shader_addline(buffer, "setup_vs_output(vs_out);\n"); 7577 7578 /* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used 7579 * or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE), 7580 * the fog frag coord is thrown away. If the fog frag coord is used, but not written by 7581 * the shader, it is set to 0.0(fully fogged, since start = 1.0, end = 0.0). 7582 */ 7583 if (reg_maps->shader_version.major < 3) 7584 { 7585 if (args->fog_src == VS_FOG_Z) 7586 shader_addline(buffer, "%s = gl_Position.z;\n", 7587 legacy_syntax ? "gl_FogFragCoord" : "ffp_varying_fogcoord"); 7588 else if (!reg_maps->fog) 7589 shader_addline(buffer, "%s = 0.0;\n", 7590 legacy_syntax ? "gl_FogFragCoord" : "ffp_varying_fogcoord"); 7591 } 7592 7593 /* We always store the clipplanes without y inversion. */ 7594 if (args->clip_enabled) 7595 { 7596 if (legacy_syntax) 7597 shader_addline(buffer, "gl_ClipVertex = gl_Position;\n"); 7598 else 7599 for (i = 0; i < gl_info->limits.user_clip_distances; ++i) 7600 shader_addline(buffer, "gl_ClipDistance[%u] = dot(gl_Position, clip_planes[%u]);\n", i, i); 7601 } 7602 7603 if (args->point_size && !args->per_vertex_point_size) 7604 shader_addline(buffer, "gl_PointSize = clamp(ffp_point.size, ffp_point.size_min, ffp_point.size_max);\n"); 7605 7606 if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL]) 7607 shader_glsl_fixup_position(buffer); 7608 } 7609 7610 /* Context activation is done by the caller. */ 7611 static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context, 7612 struct shader_glsl_priv *priv, const struct wined3d_shader *shader, const struct vs_compile_args *args) 7613 { 7614 struct wined3d_string_buffer_list *string_buffers = &priv->string_buffers; 7615 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; 7616 const struct wined3d_shader_version *version = ®_maps->shader_version; 7617 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 7618 const struct wined3d_gl_info *gl_info = context->gl_info; 7619 struct shader_glsl_ctx_priv priv_ctx; 7620 GLuint shader_id; 7621 unsigned int i; 7622 7623 memset(&priv_ctx, 0, sizeof(priv_ctx)); 7624 priv_ctx.cur_vs_args = args; 7625 priv_ctx.string_buffers = string_buffers; 7626 7627 shader_glsl_add_version_declaration(buffer, gl_info); 7628 7629 shader_glsl_enable_extensions(buffer, gl_info); 7630 if (gl_info->supported[ARB_DRAW_INSTANCED]) 7631 shader_addline(buffer, "#extension GL_ARB_draw_instanced : enable\n"); 7632 if (shader_glsl_use_explicit_attrib_location(gl_info)) 7633 shader_addline(buffer, "#extension GL_ARB_explicit_attrib_location : enable\n"); 7634 7635 /* Base Declarations */ 7636 shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx); 7637 7638 for (i = 0; i < shader->input_signature.element_count; ++i) 7639 shader_glsl_declare_generic_vertex_attribute(buffer, gl_info, &shader->input_signature.elements[i]); 7640 7641 if (args->point_size && !args->per_vertex_point_size) 7642 { 7643 shader_addline(buffer, "uniform struct\n{\n"); 7644 shader_addline(buffer, " float size;\n"); 7645 shader_addline(buffer, " float size_min;\n"); 7646 shader_addline(buffer, " float size_max;\n"); 7647 shader_addline(buffer, "} ffp_point;\n"); 7648 } 7649 7650 if (!needs_legacy_glsl_syntax(gl_info)) 7651 { 7652 if (args->clip_enabled) 7653 shader_addline(buffer, "uniform vec4 clip_planes[%u];\n", gl_info->limits.user_clip_distances); 7654 7655 if (version->major < 3) 7656 { 7657 declare_out_varying(gl_info, buffer, args->flatshading, "vec4 ffp_varying_diffuse;\n"); 7658 declare_out_varying(gl_info, buffer, args->flatshading, "vec4 ffp_varying_specular;\n"); 7659 declare_out_varying(gl_info, buffer, FALSE, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES); 7660 declare_out_varying(gl_info, buffer, FALSE, "float ffp_varying_fogcoord;\n"); 7661 } 7662 } 7663 7664 if (version->major < 4) 7665 shader_addline(buffer, "void setup_vs_output(in vec4[%u]);\n", shader->limits->packed_output); 7666 7667 if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL]) 7668 shader_addline(buffer, "uniform vec4 pos_fixup;\n"); 7669 7670 if (reg_maps->shader_version.major >= 4) 7671 shader_glsl_generate_sm4_output_setup(priv, shader, args->next_shader_input_count, 7672 gl_info, args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL, args->interpolation_mode); 7673 7674 shader_addline(buffer, "void main()\n{\n"); 7675 7676 if (reg_maps->input_rel_addressing) 7677 { 7678 unsigned int highest_input_register = wined3d_log2i(reg_maps->input_registers); 7679 shader_addline(buffer, "vec4 vs_in[%u];\n", highest_input_register + 1); 7680 for (i = 0; i < shader->input_signature.element_count; ++i) 7681 { 7682 const struct wined3d_shader_signature_element *e = &shader->input_signature.elements[i]; 7683 shader_addline(buffer, "vs_in[%u] = vs_in%u;\n", e->register_idx, e->register_idx); 7684 } 7685 } 7686 7687 if (FAILED(shader_generate_code(shader, buffer, reg_maps, &priv_ctx, NULL, NULL))) 7688 return 0; 7689 7690 /* In SM4+ the shader epilogue is generated by the "ret" instruction. */ 7691 if (reg_maps->shader_version.major < 4) 7692 shader_glsl_generate_vs_epilogue(gl_info, buffer, shader, args); 7693 7694 shader_addline(buffer, "}\n"); 7695 7696 shader_id = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER)); 7697 TRACE("Compiling shader object %u.\n", shader_id); 7698 shader_glsl_compile(gl_info, shader_id, buffer->buffer); 7699 7700 return shader_id; 7701 } 7702 7703 static void shader_glsl_generate_default_control_point_phase(const struct wined3d_shader *shader, 7704 struct wined3d_string_buffer *buffer, const struct wined3d_shader_reg_maps *reg_maps) 7705 { 7706 const struct wined3d_shader_signature *output_signature = &shader->output_signature; 7707 char reg_mask[6]; 7708 unsigned int i; 7709 7710 for (i = 0; i < output_signature->element_count; ++i) 7711 { 7712 const struct wined3d_shader_signature_element *output = &output_signature->elements[i]; 7713 7714 shader_glsl_write_mask_to_str(output->mask, reg_mask); 7715 shader_addline(buffer, "shader_out[gl_InvocationID].reg[%u]%s = shader_in[gl_InvocationID].reg[%u]%s;\n", 7716 output->register_idx, reg_mask, output->register_idx, reg_mask); 7717 } 7718 } 7719 7720 static HRESULT shader_glsl_generate_shader_phase(const struct wined3d_shader *shader, 7721 struct wined3d_string_buffer *buffer, const struct wined3d_shader_reg_maps *reg_maps, 7722 struct shader_glsl_ctx_priv *priv_ctx, const struct wined3d_shader_phase *phase, 7723 const char *phase_name, unsigned phase_idx) 7724 { 7725 unsigned int i; 7726 HRESULT hr; 7727 7728 shader_addline(buffer, "void hs_%s_phase%u(%s)\n{\n", 7729 phase_name, phase_idx, phase->instance_count ? "int phase_instance_id" : ""); 7730 for (i = 0; i < phase->temporary_count; ++i) 7731 shader_addline(buffer, "vec4 R%u;\n", i); 7732 hr = shader_generate_code(shader, buffer, reg_maps, priv_ctx, phase->start, phase->end); 7733 shader_addline(buffer, "}\n"); 7734 return hr; 7735 } 7736 7737 static void shader_glsl_generate_shader_phase_invocation(struct wined3d_string_buffer *buffer, 7738 const struct wined3d_shader_phase *phase, const char *phase_name, unsigned int phase_idx) 7739 { 7740 if (phase->instance_count) 7741 { 7742 shader_addline(buffer, "for (int i = 0; i < %u; ++i)\n{\n", phase->instance_count); 7743 shader_addline(buffer, "hs_%s_phase%u(i);\n", phase_name, phase_idx); 7744 shader_addline(buffer, "}\n"); 7745 } 7746 else 7747 { 7748 shader_addline(buffer, "hs_%s_phase%u();\n", phase_name, phase_idx); 7749 } 7750 } 7751 7752 static GLuint shader_glsl_generate_hull_shader(const struct wined3d_context *context, 7753 struct shader_glsl_priv *priv, const struct wined3d_shader *shader) 7754 { 7755 struct wined3d_string_buffer_list *string_buffers = &priv->string_buffers; 7756 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; 7757 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 7758 const struct wined3d_gl_info *gl_info = context->gl_info; 7759 const struct wined3d_hull_shader *hs = &shader->u.hs; 7760 const struct wined3d_shader_phase *phase; 7761 struct shader_glsl_ctx_priv priv_ctx; 7762 GLuint shader_id; 7763 unsigned int i; 7764 7765 memset(&priv_ctx, 0, sizeof(priv_ctx)); 7766 priv_ctx.string_buffers = string_buffers; 7767 7768 shader_glsl_add_version_declaration(buffer, gl_info); 7769 7770 shader_glsl_enable_extensions(buffer, gl_info); 7771 shader_addline(buffer, "#extension GL_ARB_tessellation_shader : enable\n"); 7772 7773 shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx); 7774 7775 shader_addline(buffer, "layout(vertices = %u) out;\n", hs->output_vertex_count); 7776 7777 shader_addline(buffer, "in shader_in_out { vec4 reg[%u]; } shader_in[];\n", shader->limits->packed_input); 7778 shader_addline(buffer, "out shader_in_out { vec4 reg[%u]; } shader_out[];\n", shader->limits->packed_output); 7779 7780 shader_glsl_generate_patch_constant_setup(buffer, &shader->patch_constant_signature, FALSE); 7781 7782 if (hs->phases.control_point) 7783 { 7784 shader_addline(buffer, "void setup_hs_output(in vec4 outputs[%u])\n{\n", 7785 shader->limits->packed_output); 7786 shader_glsl_setup_sm4_shader_output(priv, shader->limits->packed_output, &shader->output_signature, 7787 &shader->reg_maps, "shader_out[gl_InvocationID]", FALSE); 7788 shader_addline(buffer, "}\n"); 7789 } 7790 7791 shader_addline(buffer, "void hs_control_point_phase()\n{\n"); 7792 if ((phase = hs->phases.control_point)) 7793 { 7794 for (i = 0; i < phase->temporary_count; ++i) 7795 shader_addline(buffer, "vec4 R%u;\n", i); 7796 if (FAILED(shader_generate_code(shader, buffer, reg_maps, &priv_ctx, phase->start, phase->end))) 7797 return 0; 7798 shader_addline(buffer, "setup_hs_output(hs_out);\n"); 7799 } 7800 else 7801 { 7802 shader_glsl_generate_default_control_point_phase(shader, buffer, reg_maps); 7803 } 7804 shader_addline(buffer, "}\n"); 7805 7806 for (i = 0; i < hs->phases.fork_count; ++i) 7807 { 7808 if (FAILED(shader_glsl_generate_shader_phase(shader, buffer, reg_maps, &priv_ctx, 7809 &hs->phases.fork[i], "fork", i))) 7810 return 0; 7811 } 7812 7813 for (i = 0; i < hs->phases.join_count; ++i) 7814 { 7815 if (FAILED(shader_glsl_generate_shader_phase(shader, buffer, reg_maps, &priv_ctx, 7816 &hs->phases.join[i], "join", i))) 7817 return 0; 7818 } 7819 7820 shader_addline(buffer, "void main()\n{\n"); 7821 shader_addline(buffer, "hs_control_point_phase();\n"); 7822 if (reg_maps->vocp) 7823 shader_addline(buffer, "barrier();\n"); 7824 for (i = 0; i < hs->phases.fork_count; ++i) 7825 shader_glsl_generate_shader_phase_invocation(buffer, &hs->phases.fork[i], "fork", i); 7826 for (i = 0; i < hs->phases.join_count; ++i) 7827 shader_glsl_generate_shader_phase_invocation(buffer, &hs->phases.join[i], "join", i); 7828 shader_addline(buffer, "setup_patch_constant_output();\n"); 7829 shader_addline(buffer, "}\n"); 7830 7831 shader_id = GL_EXTCALL(glCreateShader(GL_TESS_CONTROL_SHADER)); 7832 TRACE("Compiling shader object %u.\n", shader_id); 7833 shader_glsl_compile(gl_info, shader_id, buffer->buffer); 7834 7835 return shader_id; 7836 } 7837 7838 static void shader_glsl_generate_ds_epilogue(const struct wined3d_gl_info *gl_info, 7839 struct wined3d_string_buffer *buffer, const struct wined3d_shader *shader, 7840 const struct ds_compile_args *args) 7841 { 7842 shader_addline(buffer, "setup_ds_output(ds_out);\n"); 7843 7844 if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL]) 7845 shader_glsl_fixup_position(buffer); 7846 } 7847 7848 static GLuint shader_glsl_generate_domain_shader(const struct wined3d_context *context, 7849 struct shader_glsl_priv *priv, const struct wined3d_shader *shader, const struct ds_compile_args *args) 7850 { 7851 struct wined3d_string_buffer_list *string_buffers = &priv->string_buffers; 7852 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; 7853 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 7854 const struct wined3d_gl_info *gl_info = context->gl_info; 7855 struct shader_glsl_ctx_priv priv_ctx; 7856 GLuint shader_id; 7857 7858 memset(&priv_ctx, 0, sizeof(priv_ctx)); 7859 priv_ctx.cur_ds_args = args; 7860 priv_ctx.string_buffers = string_buffers; 7861 7862 shader_glsl_add_version_declaration(buffer, gl_info); 7863 7864 shader_glsl_enable_extensions(buffer, gl_info); 7865 shader_addline(buffer, "#extension GL_ARB_tessellation_shader : enable\n"); 7866 7867 shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx); 7868 7869 shader_addline(buffer, "layout("); 7870 switch (shader->u.ds.tessellator_domain) 7871 { 7872 case WINED3D_TESSELLATOR_DOMAIN_LINE: 7873 shader_addline(buffer, "isolines"); 7874 break; 7875 case WINED3D_TESSELLATOR_DOMAIN_QUAD: 7876 shader_addline(buffer, "quads"); 7877 break; 7878 case WINED3D_TESSELLATOR_DOMAIN_TRIANGLE: 7879 shader_addline(buffer, "triangles"); 7880 break; 7881 } 7882 switch (args->tessellator_output_primitive) 7883 { 7884 case WINED3D_TESSELLATOR_OUTPUT_TRIANGLE_CW: 7885 if (args->render_offscreen) 7886 shader_addline(buffer, ", ccw"); 7887 else 7888 shader_addline(buffer, ", cw"); 7889 break; 7890 case WINED3D_TESSELLATOR_OUTPUT_TRIANGLE_CCW: 7891 if (args->render_offscreen) 7892 shader_addline(buffer, ", cw"); 7893 else 7894 shader_addline(buffer, ", ccw"); 7895 break; 7896 case WINED3D_TESSELLATOR_OUTPUT_POINT: 7897 shader_addline(buffer, ", point_mode"); 7898 break; 7899 case WINED3D_TESSELLATOR_OUTPUT_LINE: 7900 break; 7901 } 7902 switch (args->tessellator_partitioning) 7903 { 7904 case WINED3D_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD: 7905 shader_addline(buffer, ", fractional_odd_spacing"); 7906 break; 7907 case WINED3D_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN: 7908 shader_addline(buffer, ", fractional_even_spacing"); 7909 break; 7910 case WINED3D_TESSELLATOR_PARTITIONING_INTEGER: 7911 case WINED3D_TESSELLATOR_PARTITIONING_POW2: 7912 shader_addline(buffer, ", equal_spacing"); 7913 break; 7914 } 7915 shader_addline(buffer, ") in;\n"); 7916 7917 shader_addline(buffer, "in shader_in_out { vec4 reg[%u]; } shader_in[];\n", shader->limits->packed_input); 7918 7919 if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL]) 7920 shader_addline(buffer, "uniform vec4 pos_fixup;\n"); 7921 7922 shader_glsl_generate_sm4_output_setup(priv, shader, args->output_count, gl_info, 7923 args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL, args->interpolation_mode); 7924 shader_glsl_generate_patch_constant_setup(buffer, &shader->patch_constant_signature, TRUE); 7925 7926 shader_addline(buffer, "void main()\n{\n"); 7927 shader_addline(buffer, "setup_patch_constant_input();\n"); 7928 7929 if (FAILED(shader_generate_code(shader, buffer, reg_maps, &priv_ctx, NULL, NULL))) 7930 return 0; 7931 7932 shader_addline(buffer, "}\n"); 7933 7934 shader_id = GL_EXTCALL(glCreateShader(GL_TESS_EVALUATION_SHADER)); 7935 TRACE("Compiling shader object %u.\n", shader_id); 7936 shader_glsl_compile(gl_info, shader_id, buffer->buffer); 7937 7938 return shader_id; 7939 } 7940 7941 /* Context activation is done by the caller. */ 7942 static GLuint shader_glsl_generate_geometry_shader(const struct wined3d_context *context, 7943 struct shader_glsl_priv *priv, const struct wined3d_shader *shader, const struct gs_compile_args *args) 7944 { 7945 struct wined3d_string_buffer_list *string_buffers = &priv->string_buffers; 7946 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; 7947 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 7948 const struct wined3d_gl_info *gl_info = context->gl_info; 7949 struct shader_glsl_ctx_priv priv_ctx; 7950 GLuint shader_id; 7951 7952 memset(&priv_ctx, 0, sizeof(priv_ctx)); 7953 priv_ctx.string_buffers = string_buffers; 7954 7955 shader_glsl_add_version_declaration(buffer, gl_info); 7956 7957 shader_glsl_enable_extensions(buffer, gl_info); 7958 7959 shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx); 7960 7961 shader_addline(buffer, "layout(%s", glsl_primitive_type_from_d3d(shader->u.gs.input_type)); 7962 if (shader->u.gs.instance_count > 1) 7963 shader_addline(buffer, ", invocations = %u", shader->u.gs.instance_count); 7964 shader_addline(buffer, ") in;\n"); 7965 shader_addline(buffer, "layout(%s, max_vertices = %u) out;\n", 7966 glsl_primitive_type_from_d3d(shader->u.gs.output_type), shader->u.gs.vertices_out); 7967 shader_addline(buffer, "in shader_in_out { vec4 reg[%u]; } shader_in[];\n", shader->limits->packed_input); 7968 7969 if (!gl_info->supported[ARB_CLIP_CONTROL]) 7970 shader_addline(buffer, "uniform vec4 pos_fixup;\n"); 7971 7972 if (is_rasterization_disabled(shader)) 7973 { 7974 shader_glsl_generate_stream_output_setup(priv, shader, &shader->u.gs.so_desc); 7975 } 7976 else 7977 { 7978 shader_glsl_generate_sm4_output_setup(priv, shader, args->output_count, 7979 gl_info, TRUE, args->interpolation_mode); 7980 } 7981 shader_addline(buffer, "void main()\n{\n"); 7982 if (FAILED(shader_generate_code(shader, buffer, reg_maps, &priv_ctx, NULL, NULL))) 7983 return 0; 7984 shader_addline(buffer, "}\n"); 7985 7986 shader_id = GL_EXTCALL(glCreateShader(GL_GEOMETRY_SHADER)); 7987 TRACE("Compiling shader object %u.\n", shader_id); 7988 shader_glsl_compile(gl_info, shader_id, buffer->buffer); 7989 7990 return shader_id; 7991 } 7992 7993 static void shader_glsl_generate_shader_epilogue(const struct wined3d_shader_context *ctx) 7994 { 7995 const struct shader_glsl_ctx_priv *priv = ctx->backend_data; 7996 const struct wined3d_gl_info *gl_info = ctx->gl_info; 7997 struct wined3d_string_buffer *buffer = ctx->buffer; 7998 const struct wined3d_shader *shader = ctx->shader; 7999 8000 switch (shader->reg_maps.shader_version.type) 8001 { 8002 case WINED3D_SHADER_TYPE_PIXEL: 8003 shader_glsl_generate_ps_epilogue(gl_info, buffer, shader, priv->cur_ps_args); 8004 break; 8005 case WINED3D_SHADER_TYPE_VERTEX: 8006 shader_glsl_generate_vs_epilogue(gl_info, buffer, shader, priv->cur_vs_args); 8007 break; 8008 case WINED3D_SHADER_TYPE_DOMAIN: 8009 shader_glsl_generate_ds_epilogue(gl_info, buffer, shader, priv->cur_ds_args); 8010 break; 8011 case WINED3D_SHADER_TYPE_GEOMETRY: 8012 case WINED3D_SHADER_TYPE_COMPUTE: 8013 break; 8014 default: 8015 FIXME("Unhandled shader type %#x.\n", shader->reg_maps.shader_version.type); 8016 break; 8017 } 8018 } 8019 8020 /* Context activation is done by the caller. */ 8021 static GLuint shader_glsl_generate_compute_shader(const struct wined3d_context *context, 8022 struct wined3d_string_buffer *buffer, struct wined3d_string_buffer_list *string_buffers, 8023 const struct wined3d_shader *shader) 8024 { 8025 const struct wined3d_shader_thread_group_size *thread_group_size = &shader->u.cs.thread_group_size; 8026 const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps; 8027 const struct wined3d_gl_info *gl_info = context->gl_info; 8028 struct shader_glsl_ctx_priv priv_ctx; 8029 GLuint shader_id; 8030 unsigned int i; 8031 8032 memset(&priv_ctx, 0, sizeof(priv_ctx)); 8033 priv_ctx.string_buffers = string_buffers; 8034 8035 shader_glsl_add_version_declaration(buffer, gl_info); 8036 8037 shader_glsl_enable_extensions(buffer, gl_info); 8038 shader_addline(buffer, "#extension GL_ARB_compute_shader : enable\n"); 8039 8040 shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx); 8041 8042 for (i = 0; i < reg_maps->tgsm_count; ++i) 8043 { 8044 if (reg_maps->tgsm[i].size) 8045 shader_addline(buffer, "shared uint cs_g%u[%u];\n", i, reg_maps->tgsm[i].size); 8046 } 8047 8048 shader_addline(buffer, "layout(local_size_x = %u, local_size_y = %u, local_size_z = %u) in;\n", 8049 thread_group_size->x, thread_group_size->y, thread_group_size->z); 8050 8051 shader_addline(buffer, "void main()\n{\n"); 8052 shader_generate_code(shader, buffer, reg_maps, &priv_ctx, NULL, NULL); 8053 shader_addline(buffer, "}\n"); 8054 8055 shader_id = GL_EXTCALL(glCreateShader(GL_COMPUTE_SHADER)); 8056 TRACE("Compiling shader object %u.\n", shader_id); 8057 shader_glsl_compile(gl_info, shader_id, buffer->buffer); 8058 8059 return shader_id; 8060 } 8061 8062 static GLuint find_glsl_pshader(const struct wined3d_context *context, 8063 struct wined3d_string_buffer *buffer, struct wined3d_string_buffer_list *string_buffers, 8064 struct wined3d_shader *shader, 8065 const struct ps_compile_args *args, const struct ps_np2fixup_info **np2fixup_info) 8066 { 8067 struct glsl_ps_compiled_shader *gl_shaders, *new_array; 8068 struct glsl_shader_private *shader_data; 8069 struct ps_np2fixup_info *np2fixup; 8070 UINT i; 8071 DWORD new_size; 8072 GLuint ret; 8073 8074 if (!shader->backend_data) 8075 { 8076 if (!(shader->backend_data = heap_alloc_zero(sizeof(*shader_data)))) 8077 { 8078 ERR("Failed to allocate backend data.\n"); 8079 return 0; 8080 } 8081 } 8082 shader_data = shader->backend_data; 8083 gl_shaders = shader_data->gl_shaders.ps; 8084 8085 /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2), 8086 * so a linear search is more performant than a hashmap or a binary search 8087 * (cache coherency etc) 8088 */ 8089 for (i = 0; i < shader_data->num_gl_shaders; ++i) 8090 { 8091 if (!memcmp(&gl_shaders[i].args, args, sizeof(*args))) 8092 { 8093 if (args->np2_fixup) 8094 *np2fixup_info = &gl_shaders[i].np2fixup; 8095 return gl_shaders[i].id; 8096 } 8097 } 8098 8099 TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader); 8100 if (shader_data->shader_array_size == shader_data->num_gl_shaders) 8101 { 8102 if (shader_data->num_gl_shaders) 8103 { 8104 new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2); 8105 new_array = heap_realloc(shader_data->gl_shaders.ps, new_size * sizeof(*gl_shaders)); 8106 } 8107 else 8108 { 8109 new_array = heap_alloc(sizeof(*gl_shaders)); 8110 new_size = 1; 8111 } 8112 8113 if(!new_array) { 8114 ERR("Out of memory\n"); 8115 return 0; 8116 } 8117 shader_data->gl_shaders.ps = new_array; 8118 shader_data->shader_array_size = new_size; 8119 gl_shaders = new_array; 8120 } 8121 8122 gl_shaders[shader_data->num_gl_shaders].args = *args; 8123 8124 np2fixup = &gl_shaders[shader_data->num_gl_shaders].np2fixup; 8125 memset(np2fixup, 0, sizeof(*np2fixup)); 8126 *np2fixup_info = args->np2_fixup ? np2fixup : NULL; 8127 8128 pixelshader_update_resource_types(shader, args->tex_types); 8129 8130 string_buffer_clear(buffer); 8131 ret = shader_glsl_generate_pshader(context, buffer, string_buffers, shader, args, np2fixup); 8132 gl_shaders[shader_data->num_gl_shaders++].id = ret; 8133 8134 return ret; 8135 } 8136 8137 static inline BOOL vs_args_equal(const struct vs_compile_args *stored, const struct vs_compile_args *new, 8138 const DWORD use_map) 8139 { 8140 if((stored->swizzle_map & use_map) != new->swizzle_map) return FALSE; 8141 if((stored->clip_enabled) != new->clip_enabled) return FALSE; 8142 if (stored->point_size != new->point_size) 8143 return FALSE; 8144 if (stored->per_vertex_point_size != new->per_vertex_point_size) 8145 return FALSE; 8146 if (stored->flatshading != new->flatshading) 8147 return FALSE; 8148 if (stored->next_shader_type != new->next_shader_type) 8149 return FALSE; 8150 if (stored->next_shader_input_count != new->next_shader_input_count) 8151 return FALSE; 8152 return stored->fog_src == new->fog_src; 8153 } 8154 8155 static GLuint find_glsl_vshader(const struct wined3d_context *context, struct shader_glsl_priv *priv, 8156 struct wined3d_shader *shader, const struct vs_compile_args *args) 8157 { 8158 UINT i; 8159 DWORD new_size; 8160 DWORD use_map = context->stream_info.use_map; 8161 struct glsl_vs_compiled_shader *gl_shaders, *new_array; 8162 struct glsl_shader_private *shader_data; 8163 GLuint ret; 8164 8165 if (!shader->backend_data) 8166 { 8167 if (!(shader->backend_data = heap_alloc_zero(sizeof(*shader_data)))) 8168 { 8169 ERR("Failed to allocate backend data.\n"); 8170 return 0; 8171 } 8172 } 8173 shader_data = shader->backend_data; 8174 gl_shaders = shader_data->gl_shaders.vs; 8175 8176 /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2), 8177 * so a linear search is more performant than a hashmap or a binary search 8178 * (cache coherency etc) 8179 */ 8180 for (i = 0; i < shader_data->num_gl_shaders; ++i) 8181 { 8182 if (vs_args_equal(&gl_shaders[i].args, args, use_map)) 8183 return gl_shaders[i].id; 8184 } 8185 8186 TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader); 8187 8188 if (shader_data->shader_array_size == shader_data->num_gl_shaders) 8189 { 8190 if (shader_data->num_gl_shaders) 8191 { 8192 new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2); 8193 new_array = heap_realloc(shader_data->gl_shaders.vs, new_size * sizeof(*gl_shaders)); 8194 } 8195 else 8196 { 8197 new_array = heap_alloc(sizeof(*gl_shaders)); 8198 new_size = 1; 8199 } 8200 8201 if(!new_array) { 8202 ERR("Out of memory\n"); 8203 return 0; 8204 } 8205 shader_data->gl_shaders.vs = new_array; 8206 shader_data->shader_array_size = new_size; 8207 gl_shaders = new_array; 8208 } 8209 8210 gl_shaders[shader_data->num_gl_shaders].args = *args; 8211 8212 string_buffer_clear(&priv->shader_buffer); 8213 ret = shader_glsl_generate_vshader(context, priv, shader, args); 8214 gl_shaders[shader_data->num_gl_shaders++].id = ret; 8215 8216 return ret; 8217 } 8218 8219 static GLuint find_glsl_hull_shader(const struct wined3d_context *context, 8220 struct shader_glsl_priv *priv, struct wined3d_shader *shader) 8221 { 8222 struct glsl_hs_compiled_shader *gl_shaders, *new_array; 8223 struct glsl_shader_private *shader_data; 8224 unsigned int new_size; 8225 GLuint ret; 8226 8227 if (!shader->backend_data) 8228 { 8229 if (!(shader->backend_data = heap_alloc_zero(sizeof(*shader_data)))) 8230 { 8231 ERR("Failed to allocate backend data.\n"); 8232 return 0; 8233 } 8234 } 8235 shader_data = shader->backend_data; 8236 gl_shaders = shader_data->gl_shaders.hs; 8237 8238 if (shader_data->num_gl_shaders > 0) 8239 { 8240 assert(shader_data->num_gl_shaders == 1); 8241 return gl_shaders[0].id; 8242 } 8243 8244 TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader); 8245 8246 assert(!shader_data->gl_shaders.hs); 8247 new_size = 1; 8248 if (!(new_array = heap_alloc(sizeof(*new_array)))) 8249 { 8250 ERR("Failed to allocate GL shaders array.\n"); 8251 return 0; 8252 } 8253 shader_data->gl_shaders.hs = new_array; 8254 shader_data->shader_array_size = new_size; 8255 gl_shaders = new_array; 8256 8257 string_buffer_clear(&priv->shader_buffer); 8258 ret = shader_glsl_generate_hull_shader(context, priv, shader); 8259 gl_shaders[shader_data->num_gl_shaders++].id = ret; 8260 8261 return ret; 8262 } 8263 8264 static GLuint find_glsl_domain_shader(const struct wined3d_context *context, 8265 struct shader_glsl_priv *priv, struct wined3d_shader *shader, const struct ds_compile_args *args) 8266 { 8267 struct glsl_ds_compiled_shader *gl_shaders, *new_array; 8268 struct glsl_shader_private *shader_data; 8269 unsigned int i, new_size; 8270 GLuint ret; 8271 8272 if (!shader->backend_data) 8273 { 8274 if (!(shader->backend_data = heap_alloc_zero(sizeof(*shader_data)))) 8275 { 8276 ERR("Failed to allocate backend data.\n"); 8277 return 0; 8278 } 8279 } 8280 shader_data = shader->backend_data; 8281 gl_shaders = shader_data->gl_shaders.ds; 8282 8283 for (i = 0; i < shader_data->num_gl_shaders; ++i) 8284 { 8285 if (!memcmp(&gl_shaders[i].args, args, sizeof(*args))) 8286 return gl_shaders[i].id; 8287 } 8288 8289 TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader); 8290 8291 if (shader_data->num_gl_shaders) 8292 { 8293 new_size = shader_data->shader_array_size + 1; 8294 new_array = heap_realloc(shader_data->gl_shaders.ds, new_size * sizeof(*new_array)); 8295 } 8296 else 8297 { 8298 new_array = heap_alloc(sizeof(*new_array)); 8299 new_size = 1; 8300 } 8301 8302 if (!new_array) 8303 { 8304 ERR("Failed to allocate GL shaders array.\n"); 8305 return 0; 8306 } 8307 shader_data->gl_shaders.ds = new_array; 8308 shader_data->shader_array_size = new_size; 8309 gl_shaders = new_array; 8310 8311 string_buffer_clear(&priv->shader_buffer); 8312 ret = shader_glsl_generate_domain_shader(context, priv, shader, args); 8313 gl_shaders[shader_data->num_gl_shaders].args = *args; 8314 gl_shaders[shader_data->num_gl_shaders++].id = ret; 8315 8316 return ret; 8317 } 8318 8319 static GLuint find_glsl_geometry_shader(const struct wined3d_context *context, 8320 struct shader_glsl_priv *priv, struct wined3d_shader *shader, const struct gs_compile_args *args) 8321 { 8322 struct glsl_gs_compiled_shader *gl_shaders, *new_array; 8323 struct glsl_shader_private *shader_data; 8324 unsigned int i, new_size; 8325 GLuint ret; 8326 8327 if (!shader->backend_data) 8328 { 8329 if (!(shader->backend_data = heap_alloc_zero(sizeof(*shader_data)))) 8330 { 8331 ERR("Failed to allocate backend data.\n"); 8332 return 0; 8333 } 8334 } 8335 shader_data = shader->backend_data; 8336 gl_shaders = shader_data->gl_shaders.gs; 8337 8338 for (i = 0; i < shader_data->num_gl_shaders; ++i) 8339 { 8340 if (!memcmp(&gl_shaders[i].args, args, sizeof(*args))) 8341 return gl_shaders[i].id; 8342 } 8343 8344 TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader); 8345 8346 if (shader_data->num_gl_shaders) 8347 { 8348 new_size = shader_data->shader_array_size + 1; 8349 new_array = heap_realloc(shader_data->gl_shaders.gs, new_size * sizeof(*new_array)); 8350 } 8351 else 8352 { 8353 new_array = heap_alloc(sizeof(*new_array)); 8354 new_size = 1; 8355 } 8356 8357 if (!new_array) 8358 { 8359 ERR("Failed to allocate GL shaders array.\n"); 8360 return 0; 8361 } 8362 shader_data->gl_shaders.gs = new_array; 8363 shader_data->shader_array_size = new_size; 8364 gl_shaders = new_array; 8365 8366 string_buffer_clear(&priv->shader_buffer); 8367 ret = shader_glsl_generate_geometry_shader(context, priv, shader, args); 8368 gl_shaders[shader_data->num_gl_shaders].args = *args; 8369 gl_shaders[shader_data->num_gl_shaders++].id = ret; 8370 8371 return ret; 8372 } 8373 8374 static const char *shader_glsl_ffp_mcs(enum wined3d_material_color_source mcs, const char *material) 8375 { 8376 switch (mcs) 8377 { 8378 case WINED3D_MCS_MATERIAL: 8379 return material; 8380 case WINED3D_MCS_COLOR1: 8381 return "ffp_attrib_diffuse"; 8382 case WINED3D_MCS_COLOR2: 8383 return "ffp_attrib_specular"; 8384 default: 8385 ERR("Invalid material color source %#x.\n", mcs); 8386 return "<invalid>"; 8387 } 8388 } 8389 8390 static void shader_glsl_ffp_vertex_lighting_footer(struct wined3d_string_buffer *buffer, 8391 const struct wined3d_ffp_vs_settings *settings, unsigned int idx) 8392 { 8393 shader_addline(buffer, "diffuse += clamp(dot(dir, normal), 0.0, 1.0)" 8394 " * ffp_light[%u].diffuse.xyz * att;\n", idx); 8395 if (settings->localviewer) 8396 shader_addline(buffer, "t = dot(normal, normalize(dir - normalize(ec_pos.xyz)));\n"); 8397 else 8398 shader_addline(buffer, "t = dot(normal, normalize(dir + vec3(0.0, 0.0, -1.0)));\n"); 8399 shader_addline(buffer, "if (dot(dir, normal) > 0.0 && t > 0.0) specular +=" 8400 " pow(t, ffp_material.shininess) * ffp_light[%u].specular * att;\n", idx); 8401 } 8402 8403 static void shader_glsl_ffp_vertex_lighting(struct wined3d_string_buffer *buffer, 8404 const struct wined3d_ffp_vs_settings *settings, BOOL legacy_lighting) 8405 { 8406 const char *diffuse, *specular, *emissive, *ambient; 8407 unsigned int i, idx; 8408 8409 if (!settings->lighting) 8410 { 8411 shader_addline(buffer, "ffp_varying_diffuse = ffp_attrib_diffuse;\n"); 8412 shader_addline(buffer, "ffp_varying_specular = ffp_attrib_specular;\n"); 8413 return; 8414 } 8415 8416 shader_addline(buffer, "vec3 ambient = ffp_light_ambient;\n"); 8417 shader_addline(buffer, "vec3 diffuse = vec3(0.0);\n"); 8418 shader_addline(buffer, "vec4 specular = vec4(0.0);\n"); 8419 shader_addline(buffer, "vec3 dir, dst;\n"); 8420 shader_addline(buffer, "float att, t;\n"); 8421 8422 ambient = shader_glsl_ffp_mcs(settings->ambient_source, "ffp_material.ambient"); 8423 diffuse = shader_glsl_ffp_mcs(settings->diffuse_source, "ffp_material.diffuse"); 8424 specular = shader_glsl_ffp_mcs(settings->specular_source, "ffp_material.specular"); 8425 emissive = shader_glsl_ffp_mcs(settings->emissive_source, "ffp_material.emissive"); 8426 8427 idx = 0; 8428 for (i = 0; i < settings->point_light_count; ++i, ++idx) 8429 { 8430 shader_addline(buffer, "dir = ffp_light[%u].position.xyz - ec_pos.xyz;\n", idx); 8431 shader_addline(buffer, "dst.z = dot(dir, dir);\n"); 8432 shader_addline(buffer, "dst.y = sqrt(dst.z);\n"); 8433 shader_addline(buffer, "dst.x = 1.0;\n"); 8434 if (legacy_lighting) 8435 { 8436 shader_addline(buffer, "dst.y = (ffp_light[%u].range - dst.y) / ffp_light[%u].range;\n", idx, idx); 8437 shader_addline(buffer, "dst.z = dst.y * dst.y;\n"); 8438 shader_addline(buffer, "if (dst.y > 0.0)\n{\n"); 8439 } 8440 else 8441 { 8442 shader_addline(buffer, "if (dst.y <= ffp_light[%u].range)\n{\n", idx); 8443 } 8444 shader_addline(buffer, "att = dot(dst.xyz, vec3(ffp_light[%u].c_att," 8445 " ffp_light[%u].l_att, ffp_light[%u].q_att));\n", idx, idx, idx); 8446 if (!legacy_lighting) 8447 shader_addline(buffer, "att = 1.0 / att;\n"); 8448 shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz * att;\n", idx); 8449 if (!settings->normal) 8450 { 8451 shader_addline(buffer, "}\n"); 8452 continue; 8453 } 8454 shader_addline(buffer, "dir = normalize(dir);\n"); 8455 shader_glsl_ffp_vertex_lighting_footer(buffer, settings, idx); 8456 shader_addline(buffer, "}\n"); 8457 } 8458 8459 for (i = 0; i < settings->spot_light_count; ++i, ++idx) 8460 { 8461 shader_addline(buffer, "dir = ffp_light[%u].position.xyz - ec_pos.xyz;\n", idx); 8462 shader_addline(buffer, "dst.z = dot(dir, dir);\n"); 8463 shader_addline(buffer, "dst.y = sqrt(dst.z);\n"); 8464 shader_addline(buffer, "dst.x = 1.0;\n"); 8465 if (legacy_lighting) 8466 { 8467 shader_addline(buffer, "dst.y = (ffp_light[%u].range - dst.y) / ffp_light[%u].range;\n", idx, idx); 8468 shader_addline(buffer, "dst.z = dst.y * dst.y;\n"); 8469 shader_addline(buffer, "if (dst.y > 0.0)\n{\n"); 8470 } 8471 else 8472 { 8473 shader_addline(buffer, "if (dst.y <= ffp_light[%u].range)\n{\n", idx); 8474 } 8475 shader_addline(buffer, "dir = normalize(dir);\n"); 8476 shader_addline(buffer, "t = dot(-dir, normalize(ffp_light[%u].direction));\n", idx); 8477 shader_addline(buffer, "if (t > ffp_light[%u].cos_htheta) att = 1.0;\n", idx); 8478 shader_addline(buffer, "else if (t <= ffp_light[%u].cos_hphi) att = 0.0;\n", idx); 8479 shader_addline(buffer, "else att = pow((t - ffp_light[%u].cos_hphi)" 8480 " / (ffp_light[%u].cos_htheta - ffp_light[%u].cos_hphi), ffp_light[%u].falloff);\n", 8481 idx, idx, idx, idx); 8482 if (legacy_lighting) 8483 shader_addline(buffer, "att *= dot(dst.xyz, vec3(ffp_light[%u].c_att," 8484 " ffp_light[%u].l_att, ffp_light[%u].q_att));\n", 8485 idx, idx, idx); 8486 else 8487 shader_addline(buffer, "att /= dot(dst.xyz, vec3(ffp_light[%u].c_att," 8488 " ffp_light[%u].l_att, ffp_light[%u].q_att));\n", 8489 idx, idx, idx); 8490 shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz * att;\n", idx); 8491 if (!settings->normal) 8492 { 8493 shader_addline(buffer, "}\n"); 8494 continue; 8495 } 8496 shader_glsl_ffp_vertex_lighting_footer(buffer, settings, idx); 8497 shader_addline(buffer, "}\n"); 8498 } 8499 8500 for (i = 0; i < settings->directional_light_count; ++i, ++idx) 8501 { 8502 shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz;\n", idx); 8503 if (!settings->normal) 8504 continue; 8505 shader_addline(buffer, "att = 1.0;\n"); 8506 shader_addline(buffer, "dir = normalize(ffp_light[%u].direction.xyz);\n", idx); 8507 shader_glsl_ffp_vertex_lighting_footer(buffer, settings, idx); 8508 } 8509 8510 for (i = 0; i < settings->parallel_point_light_count; ++i, ++idx) 8511 { 8512 shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz;\n", idx); 8513 if (!settings->normal) 8514 continue; 8515 shader_addline(buffer, "att = 1.0;\n"); 8516 shader_addline(buffer, "dir = normalize(ffp_light[%u].position.xyz);\n", idx); 8517 shader_glsl_ffp_vertex_lighting_footer(buffer, settings, idx); 8518 } 8519 8520 shader_addline(buffer, "ffp_varying_diffuse.xyz = %s.xyz * ambient + %s.xyz * diffuse + %s.xyz;\n", 8521 ambient, diffuse, emissive); 8522 shader_addline(buffer, "ffp_varying_diffuse.w = %s.w;\n", diffuse); 8523 shader_addline(buffer, "ffp_varying_specular = %s * specular;\n", specular); 8524 } 8525 8526 /* Context activation is done by the caller. */ 8527 static GLuint shader_glsl_generate_ffp_vertex_shader(struct shader_glsl_priv *priv, 8528 const struct wined3d_ffp_vs_settings *settings, const struct wined3d_gl_info *gl_info) 8529 { 8530 static const struct attrib_info 8531 { 8532 const char type[6]; 8533 const char name[24]; 8534 } 8535 attrib_info[] = 8536 { 8537 {"vec4", "ffp_attrib_position"}, /* WINED3D_FFP_POSITION */ 8538 {"vec4", "ffp_attrib_blendweight"}, /* WINED3D_FFP_BLENDWEIGHT */ 8539 {"vec4", "ffp_attrib_blendindices"}, /* WINED3D_FFP_BLENDINDICES */ 8540 {"vec3", "ffp_attrib_normal"}, /* WINED3D_FFP_NORMAL */ 8541 {"float", "ffp_attrib_psize"}, /* WINED3D_FFP_PSIZE */ 8542 {"vec4", "ffp_attrib_diffuse"}, /* WINED3D_FFP_DIFFUSE */ 8543 {"vec4", "ffp_attrib_specular"}, /* WINED3D_FFP_SPECULAR */ 8544 }; 8545 const BOOL legacy_syntax = needs_legacy_glsl_syntax(gl_info); 8546 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 8547 BOOL output_legacy_fogcoord = legacy_syntax; 8548 BOOL legacy_lighting = priv->legacy_lighting; 8549 GLuint shader_obj; 8550 unsigned int i; 8551 char var[64]; 8552 8553 string_buffer_clear(buffer); 8554 8555 shader_glsl_add_version_declaration(buffer, gl_info); 8556 8557 if (shader_glsl_use_explicit_attrib_location(gl_info)) 8558 shader_addline(buffer, "#extension GL_ARB_explicit_attrib_location : enable\n"); 8559 8560 for (i = 0; i < WINED3D_FFP_ATTRIBS_COUNT; ++i) 8561 { 8562 const char *type = i < ARRAY_SIZE(attrib_info) ? attrib_info[i].type : "vec4"; 8563 8564 if (shader_glsl_use_explicit_attrib_location(gl_info)) 8565 shader_addline(buffer, "layout(location = %u) ", i); 8566 shader_addline(buffer, "%s %s vs_in%u;\n", get_attribute_keyword(gl_info), type, i); 8567 } 8568 shader_addline(buffer, "\n"); 8569 8570 shader_addline(buffer, "uniform mat4 ffp_modelview_matrix[%u];\n", MAX_VERTEX_INDEX_BLENDS); 8571 shader_addline(buffer, "uniform mat3 ffp_normal_matrix[%u];\n", MAX_VERTEX_INDEX_BLENDS); 8572 shader_addline(buffer, "uniform mat4 ffp_projection_matrix;\n"); 8573 shader_addline(buffer, "uniform mat4 ffp_texture_matrix[%u];\n", MAX_TEXTURES); 8574 8575 shader_addline(buffer, "uniform struct\n{\n"); 8576 shader_addline(buffer, " vec4 emissive;\n"); 8577 shader_addline(buffer, " vec4 ambient;\n"); 8578 shader_addline(buffer, " vec4 diffuse;\n"); 8579 shader_addline(buffer, " vec4 specular;\n"); 8580 shader_addline(buffer, " float shininess;\n"); 8581 shader_addline(buffer, "} ffp_material;\n"); 8582 8583 shader_addline(buffer, "uniform vec3 ffp_light_ambient;\n"); 8584 shader_addline(buffer, "uniform struct\n{\n"); 8585 shader_addline(buffer, " vec4 diffuse;\n"); 8586 shader_addline(buffer, " vec4 specular;\n"); 8587 shader_addline(buffer, " vec4 ambient;\n"); 8588 shader_addline(buffer, " vec4 position;\n"); 8589 shader_addline(buffer, " vec3 direction;\n"); 8590 shader_addline(buffer, " float range;\n"); 8591 shader_addline(buffer, " float falloff;\n"); 8592 shader_addline(buffer, " float c_att;\n"); 8593 shader_addline(buffer, " float l_att;\n"); 8594 shader_addline(buffer, " float q_att;\n"); 8595 shader_addline(buffer, " float cos_htheta;\n"); 8596 shader_addline(buffer, " float cos_hphi;\n"); 8597 shader_addline(buffer, "} ffp_light[%u];\n", MAX_ACTIVE_LIGHTS); 8598 8599 if (settings->point_size) 8600 { 8601 shader_addline(buffer, "uniform struct\n{\n"); 8602 shader_addline(buffer, " float size;\n"); 8603 shader_addline(buffer, " float size_min;\n"); 8604 shader_addline(buffer, " float size_max;\n"); 8605 shader_addline(buffer, " float c_att;\n"); 8606 shader_addline(buffer, " float l_att;\n"); 8607 shader_addline(buffer, " float q_att;\n"); 8608 shader_addline(buffer, "} ffp_point;\n"); 8609 } 8610 8611 if (legacy_syntax) 8612 { 8613 shader_addline(buffer, "vec4 ffp_varying_diffuse;\n"); 8614 shader_addline(buffer, "vec4 ffp_varying_specular;\n"); 8615 shader_addline(buffer, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES); 8616 shader_addline(buffer, "float ffp_varying_fogcoord;\n"); 8617 } 8618 else 8619 { 8620 if (settings->clipping) 8621 shader_addline(buffer, "uniform vec4 clip_planes[%u];\n", gl_info->limits.user_clip_distances); 8622 8623 declare_out_varying(gl_info, buffer, settings->flatshading, "vec4 ffp_varying_diffuse;\n"); 8624 declare_out_varying(gl_info, buffer, settings->flatshading, "vec4 ffp_varying_specular;\n"); 8625 declare_out_varying(gl_info, buffer, FALSE, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES); 8626 declare_out_varying(gl_info, buffer, FALSE, "float ffp_varying_fogcoord;\n"); 8627 } 8628 8629 shader_addline(buffer, "\nvoid main()\n{\n"); 8630 shader_addline(buffer, "float m;\n"); 8631 shader_addline(buffer, "vec3 r;\n"); 8632 8633 for (i = 0; i < ARRAY_SIZE(attrib_info); ++i) 8634 { 8635 if (attrib_info[i].name[0]) 8636 shader_addline(buffer, "%s %s = vs_in%u%s;\n", attrib_info[i].type, attrib_info[i].name, 8637 i, settings->swizzle_map & (1u << i) ? ".zyxw" : ""); 8638 } 8639 for (i = 0; i < MAX_TEXTURES; ++i) 8640 { 8641 unsigned int coord_idx = settings->texgen[i] & 0x0000ffff; 8642 if ((settings->texgen[i] & 0xffff0000) == WINED3DTSS_TCI_PASSTHRU 8643 && settings->texcoords & (1u << i)) 8644 shader_addline(buffer, "vec4 ffp_attrib_texcoord%u = vs_in%u;\n", i, coord_idx + WINED3D_FFP_TEXCOORD0); 8645 } 8646 8647 shader_addline(buffer, "ffp_attrib_blendweight[%u] = 1.0;\n", settings->vertexblends); 8648 8649 if (settings->transformed) 8650 { 8651 shader_addline(buffer, "vec4 ec_pos = vec4(ffp_attrib_position.xyz, 1.0);\n"); 8652 shader_addline(buffer, "gl_Position = ffp_projection_matrix * ec_pos;\n"); 8653 shader_addline(buffer, "if (ffp_attrib_position.w != 0.0) gl_Position /= ffp_attrib_position.w;\n"); 8654 } 8655 else 8656 { 8657 if (!settings->sw_blending) 8658 { 8659 for (i = 0; i < settings->vertexblends; ++i) 8660 shader_addline(buffer, "ffp_attrib_blendweight[%u] -= ffp_attrib_blendweight[%u];\n", settings->vertexblends, i); 8661 8662 shader_addline(buffer, "vec4 ec_pos = vec4(0.0);\n"); 8663 for (i = 0; i < settings->vertexblends + 1; ++i) 8664 { 8665 sprintf(var, settings->vb_indices ? "int(ffp_attrib_blendindices[%u] + 0.1)" : "%u", i); 8666 shader_addline(buffer, "ec_pos += ffp_attrib_blendweight[%u] * (ffp_modelview_matrix[%s] * ffp_attrib_position);\n", i, var); 8667 } 8668 } 8669 else 8670 { 8671 shader_addline(buffer, "vec4 ec_pos = ffp_attrib_position;\n"); 8672 } 8673 8674 shader_addline(buffer, "gl_Position = ffp_projection_matrix * ec_pos;\n"); 8675 if (settings->clipping) 8676 { 8677 if (legacy_syntax) 8678 shader_addline(buffer, "gl_ClipVertex = ec_pos;\n"); 8679 else 8680 for (i = 0; i < gl_info->limits.user_clip_distances; ++i) 8681 shader_addline(buffer, "gl_ClipDistance[%u] = dot(ec_pos, clip_planes[%u]);\n", i, i); 8682 } 8683 shader_addline(buffer, "ec_pos /= ec_pos.w;\n"); 8684 } 8685 8686 shader_addline(buffer, "vec3 normal = vec3(0.0);\n"); 8687 if (settings->normal) 8688 { 8689 if (!settings->sw_blending) 8690 { 8691 for (i = 0; i < settings->vertexblends + 1; ++i) 8692 { 8693 sprintf(var, settings->vb_indices ? "int(ffp_attrib_blendindices[%u] + 0.1)" : "%u", i); 8694 shader_addline(buffer, "normal += ffp_attrib_blendweight[%u] * (ffp_normal_matrix[%s] * ffp_attrib_normal);\n", i, var); 8695 } 8696 } 8697 else 8698 { 8699 shader_addline(buffer, "normal = ffp_attrib_normal;\n"); 8700 } 8701 8702 if (settings->normalize) 8703 shader_addline(buffer, "normal = normalize(normal);\n"); 8704 } 8705 8706 shader_glsl_ffp_vertex_lighting(buffer, settings, legacy_lighting); 8707 if (legacy_syntax) 8708 { 8709 shader_addline(buffer, "gl_FrontColor = ffp_varying_diffuse;\n"); 8710 shader_addline(buffer, "gl_FrontSecondaryColor = ffp_varying_specular;\n"); 8711 } 8712 else 8713 { 8714 shader_addline(buffer, "ffp_varying_diffuse = clamp(ffp_varying_diffuse, 0.0, 1.0);\n"); 8715 shader_addline(buffer, "ffp_varying_specular = clamp(ffp_varying_specular, 0.0, 1.0);\n"); 8716 } 8717 8718 for (i = 0; i < MAX_TEXTURES; ++i) 8719 { 8720 BOOL output_legacy_texcoord = legacy_syntax; 8721 8722 switch (settings->texgen[i] & 0xffff0000) 8723 { 8724 case WINED3DTSS_TCI_PASSTHRU: 8725 if (settings->texcoords & (1u << i)) 8726 shader_addline(buffer, "ffp_varying_texcoord[%u] = ffp_texture_matrix[%u] * ffp_attrib_texcoord%u;\n", 8727 i, i, i); 8728 else if (gl_info->limits.glsl_varyings >= wined3d_max_compat_varyings(gl_info)) 8729 shader_addline(buffer, "ffp_varying_texcoord[%u] = vec4(0.0);\n", i); 8730 else 8731 output_legacy_texcoord = FALSE; 8732 break; 8733 8734 case WINED3DTSS_TCI_CAMERASPACENORMAL: 8735 shader_addline(buffer, "ffp_varying_texcoord[%u] = ffp_texture_matrix[%u] * vec4(normal, 1.0);\n", i, i); 8736 break; 8737 8738 case WINED3DTSS_TCI_CAMERASPACEPOSITION: 8739 shader_addline(buffer, "ffp_varying_texcoord[%u] = ffp_texture_matrix[%u] * ec_pos;\n", i, i); 8740 break; 8741 8742 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR: 8743 shader_addline(buffer, "ffp_varying_texcoord[%u] = ffp_texture_matrix[%u]" 8744 " * vec4(reflect(normalize(ec_pos.xyz), normal), 1.0);\n", i, i); 8745 break; 8746 8747 case WINED3DTSS_TCI_SPHEREMAP: 8748 shader_addline(buffer, "r = reflect(normalize(ec_pos.xyz), normal);\n"); 8749 shader_addline(buffer, "m = 2.0 * length(vec3(r.x, r.y, r.z + 1.0));\n"); 8750 shader_addline(buffer, "ffp_varying_texcoord[%u] = ffp_texture_matrix[%u]" 8751 " * vec4(r.x / m + 0.5, r.y / m + 0.5, 0.0, 1.0);\n", i, i); 8752 break; 8753 8754 default: 8755 ERR("Unhandled texgen %#x.\n", settings->texgen[i]); 8756 break; 8757 } 8758 if (output_legacy_texcoord) 8759 shader_addline(buffer, "gl_TexCoord[%u] = ffp_varying_texcoord[%u];\n", i, i); 8760 } 8761 8762 switch (settings->fog_mode) 8763 { 8764 case WINED3D_FFP_VS_FOG_OFF: 8765 output_legacy_fogcoord = FALSE; 8766 break; 8767 8768 case WINED3D_FFP_VS_FOG_FOGCOORD: 8769 shader_addline(buffer, "ffp_varying_fogcoord = ffp_attrib_specular.w * 255.0;\n"); 8770 break; 8771 8772 case WINED3D_FFP_VS_FOG_RANGE: 8773 shader_addline(buffer, "ffp_varying_fogcoord = length(ec_pos.xyz);\n"); 8774 break; 8775 8776 case WINED3D_FFP_VS_FOG_DEPTH: 8777 if (settings->ortho_fog) 8778 { 8779 if (gl_info->supported[ARB_CLIP_CONTROL]) 8780 shader_addline(buffer, "ffp_varying_fogcoord = gl_Position.z;\n"); 8781 else 8782 /* Need to undo the [0.0 - 1.0] -> [-1.0 - 1.0] transformation from D3D to GL coordinates. */ 8783 shader_addline(buffer, "ffp_varying_fogcoord = gl_Position.z * 0.5 + 0.5;\n"); 8784 } 8785 else if (settings->transformed) 8786 { 8787 shader_addline(buffer, "ffp_varying_fogcoord = ec_pos.z;\n"); 8788 } 8789 else 8790 { 8791 shader_addline(buffer, "ffp_varying_fogcoord = abs(ec_pos.z);\n"); 8792 } 8793 break; 8794 8795 default: 8796 ERR("Unhandled fog mode %#x.\n", settings->fog_mode); 8797 break; 8798 } 8799 if (output_legacy_fogcoord) 8800 shader_addline(buffer, "gl_FogFragCoord = ffp_varying_fogcoord;\n"); 8801 8802 if (settings->point_size) 8803 { 8804 shader_addline(buffer, "gl_PointSize = %s / sqrt(ffp_point.c_att" 8805 " + ffp_point.l_att * length(ec_pos.xyz)" 8806 " + ffp_point.q_att * dot(ec_pos.xyz, ec_pos.xyz));\n", 8807 settings->per_vertex_point_size ? "ffp_attrib_psize" : "ffp_point.size"); 8808 shader_addline(buffer, "gl_PointSize = clamp(gl_PointSize, ffp_point.size_min, ffp_point.size_max);\n"); 8809 } 8810 8811 shader_addline(buffer, "}\n"); 8812 8813 shader_obj = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER)); 8814 shader_glsl_compile(gl_info, shader_obj, buffer->buffer); 8815 8816 return shader_obj; 8817 } 8818 8819 static const char *shader_glsl_get_ffp_fragment_op_arg(struct wined3d_string_buffer *buffer, 8820 DWORD argnum, unsigned int stage, DWORD arg) 8821 { 8822 const char *ret; 8823 8824 if (arg == ARG_UNUSED) 8825 return "<unused arg>"; 8826 8827 switch (arg & WINED3DTA_SELECTMASK) 8828 { 8829 case WINED3DTA_DIFFUSE: 8830 ret = "ffp_varying_diffuse"; 8831 break; 8832 8833 case WINED3DTA_CURRENT: 8834 ret = "ret"; 8835 break; 8836 8837 case WINED3DTA_TEXTURE: 8838 switch (stage) 8839 { 8840 case 0: ret = "tex0"; break; 8841 case 1: ret = "tex1"; break; 8842 case 2: ret = "tex2"; break; 8843 case 3: ret = "tex3"; break; 8844 case 4: ret = "tex4"; break; 8845 case 5: ret = "tex5"; break; 8846 case 6: ret = "tex6"; break; 8847 case 7: ret = "tex7"; break; 8848 default: 8849 ret = "<invalid texture>"; 8850 break; 8851 } 8852 break; 8853 8854 case WINED3DTA_TFACTOR: 8855 ret = "tex_factor"; 8856 break; 8857 8858 case WINED3DTA_SPECULAR: 8859 ret = "ffp_varying_specular"; 8860 break; 8861 8862 case WINED3DTA_TEMP: 8863 ret = "temp_reg"; 8864 break; 8865 8866 case WINED3DTA_CONSTANT: 8867 switch (stage) 8868 { 8869 case 0: ret = "tss_const0"; break; 8870 case 1: ret = "tss_const1"; break; 8871 case 2: ret = "tss_const2"; break; 8872 case 3: ret = "tss_const3"; break; 8873 case 4: ret = "tss_const4"; break; 8874 case 5: ret = "tss_const5"; break; 8875 case 6: ret = "tss_const6"; break; 8876 case 7: ret = "tss_const7"; break; 8877 default: 8878 ret = "<invalid constant>"; 8879 break; 8880 } 8881 break; 8882 8883 default: 8884 return "<unhandled arg>"; 8885 } 8886 8887 if (arg & WINED3DTA_COMPLEMENT) 8888 { 8889 shader_addline(buffer, "arg%u = vec4(1.0) - %s;\n", argnum, ret); 8890 if (argnum == 0) 8891 ret = "arg0"; 8892 else if (argnum == 1) 8893 ret = "arg1"; 8894 else if (argnum == 2) 8895 ret = "arg2"; 8896 } 8897 8898 if (arg & WINED3DTA_ALPHAREPLICATE) 8899 { 8900 shader_addline(buffer, "arg%u = vec4(%s.w);\n", argnum, ret); 8901 if (argnum == 0) 8902 ret = "arg0"; 8903 else if (argnum == 1) 8904 ret = "arg1"; 8905 else if (argnum == 2) 8906 ret = "arg2"; 8907 } 8908 8909 return ret; 8910 } 8911 8912 static void shader_glsl_ffp_fragment_op(struct wined3d_string_buffer *buffer, unsigned int stage, BOOL color, 8913 BOOL alpha, DWORD dst, DWORD op, DWORD dw_arg0, DWORD dw_arg1, DWORD dw_arg2) 8914 { 8915 const char *dstmask, *dstreg, *arg0, *arg1, *arg2; 8916 8917 if (color && alpha) 8918 dstmask = ""; 8919 else if (color) 8920 dstmask = ".xyz"; 8921 else 8922 dstmask = ".w"; 8923 8924 if (dst == tempreg) 8925 dstreg = "temp_reg"; 8926 else 8927 dstreg = "ret"; 8928 8929 arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, dw_arg0); 8930 arg1 = shader_glsl_get_ffp_fragment_op_arg(buffer, 1, stage, dw_arg1); 8931 arg2 = shader_glsl_get_ffp_fragment_op_arg(buffer, 2, stage, dw_arg2); 8932 8933 switch (op) 8934 { 8935 case WINED3D_TOP_DISABLE: 8936 break; 8937 8938 case WINED3D_TOP_SELECT_ARG1: 8939 shader_addline(buffer, "%s%s = %s%s;\n", dstreg, dstmask, arg1, dstmask); 8940 break; 8941 8942 case WINED3D_TOP_SELECT_ARG2: 8943 shader_addline(buffer, "%s%s = %s%s;\n", dstreg, dstmask, arg2, dstmask); 8944 break; 8945 8946 case WINED3D_TOP_MODULATE: 8947 shader_addline(buffer, "%s%s = %s%s * %s%s;\n", dstreg, dstmask, arg1, dstmask, arg2, dstmask); 8948 break; 8949 8950 case WINED3D_TOP_MODULATE_4X: 8951 shader_addline(buffer, "%s%s = clamp(%s%s * %s%s * 4.0, 0.0, 1.0);\n", 8952 dstreg, dstmask, arg1, dstmask, arg2, dstmask); 8953 break; 8954 8955 case WINED3D_TOP_MODULATE_2X: 8956 shader_addline(buffer, "%s%s = clamp(%s%s * %s%s * 2.0, 0.0, 1.0);\n", 8957 dstreg, dstmask, arg1, dstmask, arg2, dstmask); 8958 break; 8959 8960 case WINED3D_TOP_ADD: 8961 shader_addline(buffer, "%s%s = clamp(%s%s + %s%s, 0.0, 1.0);\n", 8962 dstreg, dstmask, arg1, dstmask, arg2, dstmask); 8963 break; 8964 8965 case WINED3D_TOP_ADD_SIGNED: 8966 shader_addline(buffer, "%s%s = clamp(%s%s + (%s - vec4(0.5))%s, 0.0, 1.0);\n", 8967 dstreg, dstmask, arg1, dstmask, arg2, dstmask); 8968 break; 8969 8970 case WINED3D_TOP_ADD_SIGNED_2X: 8971 shader_addline(buffer, "%s%s = clamp((%s%s + (%s - vec4(0.5))%s) * 2.0, 0.0, 1.0);\n", 8972 dstreg, dstmask, arg1, dstmask, arg2, dstmask); 8973 break; 8974 8975 case WINED3D_TOP_SUBTRACT: 8976 shader_addline(buffer, "%s%s = clamp(%s%s - %s%s, 0.0, 1.0);\n", 8977 dstreg, dstmask, arg1, dstmask, arg2, dstmask); 8978 break; 8979 8980 case WINED3D_TOP_ADD_SMOOTH: 8981 shader_addline(buffer, "%s%s = clamp((vec4(1.0) - %s)%s * %s%s + %s%s, 0.0, 1.0);\n", 8982 dstreg, dstmask, arg1, dstmask, arg2, dstmask, arg1, dstmask); 8983 break; 8984 8985 case WINED3D_TOP_BLEND_DIFFUSE_ALPHA: 8986 arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, WINED3DTA_DIFFUSE); 8987 shader_addline(buffer, "%s%s = mix(%s%s, %s%s, %s.w);\n", 8988 dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0); 8989 break; 8990 8991 case WINED3D_TOP_BLEND_TEXTURE_ALPHA: 8992 arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, WINED3DTA_TEXTURE); 8993 shader_addline(buffer, "%s%s = mix(%s%s, %s%s, %s.w);\n", 8994 dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0); 8995 break; 8996 8997 case WINED3D_TOP_BLEND_FACTOR_ALPHA: 8998 arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, WINED3DTA_TFACTOR); 8999 shader_addline(buffer, "%s%s = mix(%s%s, %s%s, %s.w);\n", 9000 dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0); 9001 break; 9002 9003 case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM: 9004 arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, WINED3DTA_TEXTURE); 9005 shader_addline(buffer, "%s%s = clamp(%s%s * (1.0 - %s.w) + %s%s, 0.0, 1.0);\n", 9006 dstreg, dstmask, arg2, dstmask, arg0, arg1, dstmask); 9007 break; 9008 9009 case WINED3D_TOP_BLEND_CURRENT_ALPHA: 9010 arg0 = shader_glsl_get_ffp_fragment_op_arg(buffer, 0, stage, WINED3DTA_CURRENT); 9011 shader_addline(buffer, "%s%s = mix(%s%s, %s%s, %s.w);\n", 9012 dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0); 9013 break; 9014 9015 case WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR: 9016 shader_addline(buffer, "%s%s = clamp(%s%s * %s.w + %s%s, 0.0, 1.0);\n", 9017 dstreg, dstmask, arg2, dstmask, arg1, arg1, dstmask); 9018 break; 9019 9020 case WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA: 9021 shader_addline(buffer, "%s%s = clamp(%s%s * %s%s + %s.w, 0.0, 1.0);\n", 9022 dstreg, dstmask, arg1, dstmask, arg2, dstmask, arg1); 9023 break; 9024 9025 case WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR: 9026 shader_addline(buffer, "%s%s = clamp(%s%s * (1.0 - %s.w) + %s%s, 0.0, 1.0);\n", 9027 dstreg, dstmask, arg2, dstmask, arg1, arg1, dstmask); 9028 break; 9029 case WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA: 9030 shader_addline(buffer, "%s%s = clamp((vec4(1.0) - %s)%s * %s%s + %s.w, 0.0, 1.0);\n", 9031 dstreg, dstmask, arg1, dstmask, arg2, dstmask, arg1); 9032 break; 9033 9034 case WINED3D_TOP_BUMPENVMAP: 9035 case WINED3D_TOP_BUMPENVMAP_LUMINANCE: 9036 /* These are handled in the first pass, nothing to do. */ 9037 break; 9038 9039 case WINED3D_TOP_DOTPRODUCT3: 9040 shader_addline(buffer, "%s%s = vec4(clamp(dot(%s.xyz - 0.5, %s.xyz - 0.5) * 4.0, 0.0, 1.0))%s;\n", 9041 dstreg, dstmask, arg1, arg2, dstmask); 9042 break; 9043 9044 case WINED3D_TOP_MULTIPLY_ADD: 9045 shader_addline(buffer, "%s%s = clamp(%s%s * %s%s + %s%s, 0.0, 1.0);\n", 9046 dstreg, dstmask, arg1, dstmask, arg2, dstmask, arg0, dstmask); 9047 break; 9048 9049 case WINED3D_TOP_LERP: 9050 /* MSDN isn't quite right here. */ 9051 shader_addline(buffer, "%s%s = mix(%s%s, %s%s, %s%s);\n", 9052 dstreg, dstmask, arg2, dstmask, arg1, dstmask, arg0, dstmask); 9053 break; 9054 9055 default: 9056 FIXME("Unhandled operation %#x.\n", op); 9057 break; 9058 } 9059 } 9060 9061 /* Context activation is done by the caller. */ 9062 static GLuint shader_glsl_generate_ffp_fragment_shader(struct shader_glsl_priv *priv, 9063 const struct ffp_frag_settings *settings, const struct wined3d_context *context) 9064 { 9065 const char *output = needs_legacy_glsl_syntax(context->gl_info) ? "gl_FragData[0]" : "ps_out0"; 9066 struct wined3d_string_buffer *tex_reg_name = string_buffer_get(&priv->string_buffers); 9067 enum wined3d_cmp_func alpha_test_func = settings->alpha_test_func + 1; 9068 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 9069 BYTE lum_map = 0, bump_map = 0, tex_map = 0, tss_const_map = 0; 9070 const struct wined3d_gl_info *gl_info = context->gl_info; 9071 const BOOL legacy_syntax = needs_legacy_glsl_syntax(gl_info); 9072 BOOL tempreg_used = FALSE, tfactor_used = FALSE; 9073 UINT lowest_disabled_stage; 9074 GLuint shader_id; 9075 DWORD arg0, arg1, arg2; 9076 unsigned int stage; 9077 9078 string_buffer_clear(buffer); 9079 9080 /* Find out which textures are read */ 9081 for (stage = 0; stage < MAX_TEXTURES; ++stage) 9082 { 9083 if (settings->op[stage].cop == WINED3D_TOP_DISABLE) 9084 break; 9085 9086 arg0 = settings->op[stage].carg0 & WINED3DTA_SELECTMASK; 9087 arg1 = settings->op[stage].carg1 & WINED3DTA_SELECTMASK; 9088 arg2 = settings->op[stage].carg2 & WINED3DTA_SELECTMASK; 9089 9090 if (arg0 == WINED3DTA_TEXTURE || arg1 == WINED3DTA_TEXTURE || arg2 == WINED3DTA_TEXTURE 9091 || (stage == 0 && settings->color_key_enabled)) 9092 tex_map |= 1u << stage; 9093 if (arg0 == WINED3DTA_TFACTOR || arg1 == WINED3DTA_TFACTOR || arg2 == WINED3DTA_TFACTOR) 9094 tfactor_used = TRUE; 9095 if (arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP) 9096 tempreg_used = TRUE; 9097 if (settings->op[stage].dst == tempreg) 9098 tempreg_used = TRUE; 9099 if (arg0 == WINED3DTA_CONSTANT || arg1 == WINED3DTA_CONSTANT || arg2 == WINED3DTA_CONSTANT) 9100 tss_const_map |= 1u << stage; 9101 9102 switch (settings->op[stage].cop) 9103 { 9104 case WINED3D_TOP_BUMPENVMAP_LUMINANCE: 9105 lum_map |= 1u << stage; 9106 /* fall through */ 9107 case WINED3D_TOP_BUMPENVMAP: 9108 bump_map |= 1u << stage; 9109 /* fall through */ 9110 case WINED3D_TOP_BLEND_TEXTURE_ALPHA: 9111 case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM: 9112 tex_map |= 1u << stage; 9113 break; 9114 9115 case WINED3D_TOP_BLEND_FACTOR_ALPHA: 9116 tfactor_used = TRUE; 9117 break; 9118 9119 default: 9120 break; 9121 } 9122 9123 if (settings->op[stage].aop == WINED3D_TOP_DISABLE) 9124 continue; 9125 9126 arg0 = settings->op[stage].aarg0 & WINED3DTA_SELECTMASK; 9127 arg1 = settings->op[stage].aarg1 & WINED3DTA_SELECTMASK; 9128 arg2 = settings->op[stage].aarg2 & WINED3DTA_SELECTMASK; 9129 9130 if (arg0 == WINED3DTA_TEXTURE || arg1 == WINED3DTA_TEXTURE || arg2 == WINED3DTA_TEXTURE) 9131 tex_map |= 1u << stage; 9132 if (arg0 == WINED3DTA_TFACTOR || arg1 == WINED3DTA_TFACTOR || arg2 == WINED3DTA_TFACTOR) 9133 tfactor_used = TRUE; 9134 if (arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP) 9135 tempreg_used = TRUE; 9136 if (arg0 == WINED3DTA_CONSTANT || arg1 == WINED3DTA_CONSTANT || arg2 == WINED3DTA_CONSTANT) 9137 tss_const_map |= 1u << stage; 9138 } 9139 lowest_disabled_stage = stage; 9140 9141 shader_glsl_add_version_declaration(buffer, gl_info); 9142 9143 if (shader_glsl_use_explicit_attrib_location(gl_info)) 9144 shader_addline(buffer, "#extension GL_ARB_explicit_attrib_location : enable\n"); 9145 if (gl_info->supported[ARB_SHADING_LANGUAGE_420PACK]) 9146 shader_addline(buffer, "#extension GL_ARB_shading_language_420pack : enable\n"); 9147 if (gl_info->supported[ARB_TEXTURE_RECTANGLE]) 9148 shader_addline(buffer, "#extension GL_ARB_texture_rectangle : enable\n"); 9149 9150 if (!needs_legacy_glsl_syntax(gl_info)) 9151 { 9152 if (shader_glsl_use_explicit_attrib_location(gl_info)) 9153 shader_addline(buffer, "layout(location = 0) "); 9154 shader_addline(buffer, "out vec4 ps_out0;\n"); 9155 } 9156 9157 shader_addline(buffer, "vec4 tmp0, tmp1;\n"); 9158 shader_addline(buffer, "vec4 ret;\n"); 9159 if (tempreg_used || settings->sRGB_write) 9160 shader_addline(buffer, "vec4 temp_reg = vec4(0.0);\n"); 9161 shader_addline(buffer, "vec4 arg0, arg1, arg2;\n"); 9162 9163 for (stage = 0; stage < MAX_TEXTURES; ++stage) 9164 { 9165 const char *sampler_type; 9166 9167 if (tss_const_map & (1u << stage)) 9168 shader_addline(buffer, "uniform vec4 tss_const%u;\n", stage); 9169 9170 if (!(tex_map & (1u << stage))) 9171 continue; 9172 9173 switch (settings->op[stage].tex_type) 9174 { 9175 case WINED3D_GL_RES_TYPE_TEX_1D: 9176 sampler_type = "1D"; 9177 break; 9178 case WINED3D_GL_RES_TYPE_TEX_2D: 9179 sampler_type = "2D"; 9180 break; 9181 case WINED3D_GL_RES_TYPE_TEX_3D: 9182 sampler_type = "3D"; 9183 break; 9184 case WINED3D_GL_RES_TYPE_TEX_CUBE: 9185 sampler_type = "Cube"; 9186 break; 9187 case WINED3D_GL_RES_TYPE_TEX_RECT: 9188 sampler_type = "2DRect"; 9189 break; 9190 default: 9191 FIXME("Unhandled sampler type %#x.\n", settings->op[stage].tex_type); 9192 sampler_type = NULL; 9193 break; 9194 } 9195 if (sampler_type) 9196 { 9197 if (shader_glsl_use_layout_binding_qualifier(gl_info)) 9198 shader_glsl_append_sampler_binding_qualifier(buffer, context, NULL, stage); 9199 shader_addline(buffer, "uniform sampler%s ps_sampler%u;\n", sampler_type, stage); 9200 } 9201 9202 shader_addline(buffer, "vec4 tex%u;\n", stage); 9203 9204 if (!(bump_map & (1u << stage))) 9205 continue; 9206 shader_addline(buffer, "uniform mat2 bumpenv_mat%u;\n", stage); 9207 9208 if (!(lum_map & (1u << stage))) 9209 continue; 9210 shader_addline(buffer, "uniform float bumpenv_lum_scale%u;\n", stage); 9211 shader_addline(buffer, "uniform float bumpenv_lum_offset%u;\n", stage); 9212 } 9213 if (tfactor_used) 9214 shader_addline(buffer, "uniform vec4 tex_factor;\n"); 9215 if (settings->color_key_enabled) 9216 shader_addline(buffer, "uniform vec4 color_key[2];\n"); 9217 shader_addline(buffer, "uniform vec4 specular_enable;\n"); 9218 9219 if (settings->sRGB_write) 9220 { 9221 shader_addline(buffer, "const vec4 srgb_const0 = "); 9222 shader_glsl_append_imm_vec4(buffer, wined3d_srgb_const0); 9223 shader_addline(buffer, ";\n"); 9224 shader_addline(buffer, "const vec4 srgb_const1 = "); 9225 shader_glsl_append_imm_vec4(buffer, wined3d_srgb_const1); 9226 shader_addline(buffer, ";\n"); 9227 } 9228 9229 shader_addline(buffer, "uniform struct\n{\n"); 9230 shader_addline(buffer, " vec4 color;\n"); 9231 shader_addline(buffer, " float density;\n"); 9232 shader_addline(buffer, " float end;\n"); 9233 shader_addline(buffer, " float scale;\n"); 9234 shader_addline(buffer, "} ffp_fog;\n"); 9235 9236 if (alpha_test_func != WINED3D_CMP_ALWAYS) 9237 shader_addline(buffer, "uniform float alpha_test_ref;\n"); 9238 9239 if (legacy_syntax) 9240 { 9241 shader_addline(buffer, "vec4 ffp_varying_diffuse;\n"); 9242 shader_addline(buffer, "vec4 ffp_varying_specular;\n"); 9243 shader_addline(buffer, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES); 9244 shader_addline(buffer, "vec4 ffp_texcoord[%u];\n", MAX_TEXTURES); 9245 shader_addline(buffer, "float ffp_varying_fogcoord;\n"); 9246 } 9247 else 9248 { 9249 declare_in_varying(gl_info, buffer, settings->flatshading, "vec4 ffp_varying_diffuse;\n"); 9250 declare_in_varying(gl_info, buffer, settings->flatshading, "vec4 ffp_varying_specular;\n"); 9251 declare_in_varying(gl_info, buffer, FALSE, "vec4 ffp_varying_texcoord[%u];\n", MAX_TEXTURES); 9252 shader_addline(buffer, "vec4 ffp_texcoord[%u];\n", MAX_TEXTURES); 9253 declare_in_varying(gl_info, buffer, FALSE, "float ffp_varying_fogcoord;\n"); 9254 } 9255 9256 shader_addline(buffer, "void main()\n{\n"); 9257 9258 if (legacy_syntax) 9259 { 9260 shader_addline(buffer, "ffp_varying_diffuse = gl_Color;\n"); 9261 shader_addline(buffer, "ffp_varying_specular = gl_SecondaryColor;\n"); 9262 } 9263 9264 for (stage = 0; stage < MAX_TEXTURES; ++stage) 9265 { 9266 if (tex_map & (1u << stage)) 9267 { 9268 if (settings->pointsprite) 9269 shader_addline(buffer, "ffp_texcoord[%u] = vec4(gl_PointCoord.xy, 0.0, 0.0);\n", stage); 9270 else if (settings->texcoords_initialized & (1u << stage)) 9271 shader_addline(buffer, "ffp_texcoord[%u] = %s[%u];\n", 9272 stage, legacy_syntax ? "gl_TexCoord" : "ffp_varying_texcoord", stage); 9273 else 9274 shader_addline(buffer, "ffp_texcoord[%u] = vec4(0.0);\n", stage); 9275 } 9276 } 9277 9278 if (legacy_syntax && settings->fog != WINED3D_FFP_PS_FOG_OFF) 9279 shader_addline(buffer, "ffp_varying_fogcoord = gl_FogFragCoord;\n"); 9280 9281 if (lowest_disabled_stage < 7 && settings->emul_clipplanes) 9282 shader_addline(buffer, "if (any(lessThan(ffp_texcoord[7], vec4(0.0)))) discard;\n"); 9283 9284 /* Generate texture sampling instructions */ 9285 for (stage = 0; stage < MAX_TEXTURES && settings->op[stage].cop != WINED3D_TOP_DISABLE; ++stage) 9286 { 9287 const char *texture_function, *coord_mask; 9288 BOOL proj; 9289 9290 if (!(tex_map & (1u << stage))) 9291 continue; 9292 9293 if (settings->op[stage].projected == proj_none) 9294 { 9295 proj = FALSE; 9296 } 9297 else if (settings->op[stage].projected == proj_count4 9298 || settings->op[stage].projected == proj_count3) 9299 { 9300 proj = TRUE; 9301 } 9302 else 9303 { 9304 FIXME("Unexpected projection mode %d\n", settings->op[stage].projected); 9305 proj = TRUE; 9306 } 9307 9308 if (settings->op[stage].tex_type == WINED3D_GL_RES_TYPE_TEX_CUBE) 9309 proj = FALSE; 9310 9311 switch (settings->op[stage].tex_type) 9312 { 9313 case WINED3D_GL_RES_TYPE_TEX_1D: 9314 if (proj) 9315 { 9316 texture_function = "texture1DProj"; 9317 coord_mask = "xw"; 9318 } 9319 else 9320 { 9321 texture_function = "texture1D"; 9322 coord_mask = "x"; 9323 } 9324 break; 9325 case WINED3D_GL_RES_TYPE_TEX_2D: 9326 if (proj) 9327 { 9328 texture_function = "texture2DProj"; 9329 coord_mask = "xyw"; 9330 } 9331 else 9332 { 9333 texture_function = "texture2D"; 9334 coord_mask = "xy"; 9335 } 9336 break; 9337 case WINED3D_GL_RES_TYPE_TEX_3D: 9338 if (proj) 9339 { 9340 texture_function = "texture3DProj"; 9341 coord_mask = "xyzw"; 9342 } 9343 else 9344 { 9345 texture_function = "texture3D"; 9346 coord_mask = "xyz"; 9347 } 9348 break; 9349 case WINED3D_GL_RES_TYPE_TEX_CUBE: 9350 texture_function = "textureCube"; 9351 coord_mask = "xyz"; 9352 break; 9353 case WINED3D_GL_RES_TYPE_TEX_RECT: 9354 if (proj) 9355 { 9356 texture_function = "texture2DRectProj"; 9357 coord_mask = "xyw"; 9358 } 9359 else 9360 { 9361 texture_function = "texture2DRect"; 9362 coord_mask = "xy"; 9363 } 9364 break; 9365 default: 9366 FIXME("Unhandled texture type %#x.\n", settings->op[stage].tex_type); 9367 texture_function = ""; 9368 coord_mask = "xyzw"; 9369 break; 9370 } 9371 if (!legacy_syntax) 9372 texture_function = proj ? "textureProj" : "texture"; 9373 9374 if (stage > 0 9375 && (settings->op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP 9376 || settings->op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE)) 9377 { 9378 shader_addline(buffer, "ret.xy = bumpenv_mat%u * tex%u.xy;\n", stage - 1, stage - 1); 9379 9380 /* With projective textures, texbem only divides the static 9381 * texture coord, not the displacement, so multiply the 9382 * displacement with the dividing parameter before passing it to 9383 * TXP. */ 9384 if (settings->op[stage].projected != proj_none) 9385 { 9386 if (settings->op[stage].projected == proj_count4) 9387 { 9388 shader_addline(buffer, "ret.xy = (ret.xy * ffp_texcoord[%u].w) + ffp_texcoord[%u].xy;\n", 9389 stage, stage); 9390 shader_addline(buffer, "ret.zw = ffp_texcoord[%u].ww;\n", stage); 9391 } 9392 else 9393 { 9394 shader_addline(buffer, "ret.xy = (ret.xy * ffp_texcoord[%u].z) + ffp_texcoord[%u].xy;\n", 9395 stage, stage); 9396 shader_addline(buffer, "ret.zw = ffp_texcoord[%u].zz;\n", stage); 9397 } 9398 } 9399 else 9400 { 9401 shader_addline(buffer, "ret = ffp_texcoord[%u] + ret.xyxy;\n", stage); 9402 } 9403 9404 shader_addline(buffer, "tex%u = %s(ps_sampler%u, ret.%s);\n", 9405 stage, texture_function, stage, coord_mask); 9406 9407 if (settings->op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE) 9408 shader_addline(buffer, "tex%u *= clamp(tex%u.z * bumpenv_lum_scale%u + bumpenv_lum_offset%u, 0.0, 1.0);\n", 9409 stage, stage - 1, stage - 1, stage - 1); 9410 } 9411 else if (settings->op[stage].projected == proj_count3) 9412 { 9413 shader_addline(buffer, "tex%u = %s(ps_sampler%u, ffp_texcoord[%u].xyz);\n", 9414 stage, texture_function, stage, stage); 9415 } 9416 else 9417 { 9418 shader_addline(buffer, "tex%u = %s(ps_sampler%u, ffp_texcoord[%u].%s);\n", 9419 stage, texture_function, stage, stage, coord_mask); 9420 } 9421 9422 string_buffer_sprintf(tex_reg_name, "tex%u", stage); 9423 shader_glsl_color_correction_ext(buffer, tex_reg_name->buffer, WINED3DSP_WRITEMASK_ALL, 9424 settings->op[stage].color_fixup); 9425 } 9426 9427 if (settings->color_key_enabled) 9428 { 9429 shader_addline(buffer, "if (all(greaterThanEqual(tex0, color_key[0])) && all(lessThan(tex0, color_key[1])))\n"); 9430 shader_addline(buffer, " discard;\n"); 9431 } 9432 9433 shader_addline(buffer, "ret = ffp_varying_diffuse;\n"); 9434 9435 /* Generate the main shader */ 9436 for (stage = 0; stage < MAX_TEXTURES; ++stage) 9437 { 9438 BOOL op_equal; 9439 9440 if (settings->op[stage].cop == WINED3D_TOP_DISABLE) 9441 break; 9442 9443 if (settings->op[stage].cop == WINED3D_TOP_SELECT_ARG1 9444 && settings->op[stage].aop == WINED3D_TOP_SELECT_ARG1) 9445 op_equal = settings->op[stage].carg1 == settings->op[stage].aarg1; 9446 else if (settings->op[stage].cop == WINED3D_TOP_SELECT_ARG1 9447 && settings->op[stage].aop == WINED3D_TOP_SELECT_ARG2) 9448 op_equal = settings->op[stage].carg1 == settings->op[stage].aarg2; 9449 else if (settings->op[stage].cop == WINED3D_TOP_SELECT_ARG2 9450 && settings->op[stage].aop == WINED3D_TOP_SELECT_ARG1) 9451 op_equal = settings->op[stage].carg2 == settings->op[stage].aarg1; 9452 else if (settings->op[stage].cop == WINED3D_TOP_SELECT_ARG2 9453 && settings->op[stage].aop == WINED3D_TOP_SELECT_ARG2) 9454 op_equal = settings->op[stage].carg2 == settings->op[stage].aarg2; 9455 else 9456 op_equal = settings->op[stage].aop == settings->op[stage].cop 9457 && settings->op[stage].carg0 == settings->op[stage].aarg0 9458 && settings->op[stage].carg1 == settings->op[stage].aarg1 9459 && settings->op[stage].carg2 == settings->op[stage].aarg2; 9460 9461 if (settings->op[stage].aop == WINED3D_TOP_DISABLE) 9462 { 9463 shader_glsl_ffp_fragment_op(buffer, stage, TRUE, FALSE, settings->op[stage].dst, 9464 settings->op[stage].cop, settings->op[stage].carg0, 9465 settings->op[stage].carg1, settings->op[stage].carg2); 9466 } 9467 else if (op_equal) 9468 { 9469 shader_glsl_ffp_fragment_op(buffer, stage, TRUE, TRUE, settings->op[stage].dst, 9470 settings->op[stage].cop, settings->op[stage].carg0, 9471 settings->op[stage].carg1, settings->op[stage].carg2); 9472 } 9473 else if (settings->op[stage].cop != WINED3D_TOP_BUMPENVMAP 9474 && settings->op[stage].cop != WINED3D_TOP_BUMPENVMAP_LUMINANCE) 9475 { 9476 shader_glsl_ffp_fragment_op(buffer, stage, TRUE, FALSE, settings->op[stage].dst, 9477 settings->op[stage].cop, settings->op[stage].carg0, 9478 settings->op[stage].carg1, settings->op[stage].carg2); 9479 shader_glsl_ffp_fragment_op(buffer, stage, FALSE, TRUE, settings->op[stage].dst, 9480 settings->op[stage].aop, settings->op[stage].aarg0, 9481 settings->op[stage].aarg1, settings->op[stage].aarg2); 9482 } 9483 } 9484 9485 shader_addline(buffer, "%s = ffp_varying_specular * specular_enable + ret;\n", output); 9486 9487 if (settings->sRGB_write) 9488 shader_glsl_generate_srgb_write_correction(buffer, gl_info); 9489 9490 shader_glsl_generate_fog_code(buffer, gl_info, settings->fog); 9491 9492 shader_glsl_generate_alpha_test(buffer, gl_info, alpha_test_func); 9493 9494 shader_addline(buffer, "}\n"); 9495 9496 shader_id = GL_EXTCALL(glCreateShader(GL_FRAGMENT_SHADER)); 9497 shader_glsl_compile(gl_info, shader_id, buffer->buffer); 9498 9499 string_buffer_release(&priv->string_buffers, tex_reg_name); 9500 return shader_id; 9501 } 9502 9503 static struct glsl_ffp_vertex_shader *shader_glsl_find_ffp_vertex_shader(struct shader_glsl_priv *priv, 9504 const struct wined3d_gl_info *gl_info, const struct wined3d_ffp_vs_settings *settings) 9505 { 9506 struct glsl_ffp_vertex_shader *shader; 9507 const struct wine_rb_entry *entry; 9508 9509 if ((entry = wine_rb_get(&priv->ffp_vertex_shaders, settings))) 9510 return WINE_RB_ENTRY_VALUE(entry, struct glsl_ffp_vertex_shader, desc.entry); 9511 9512 if (!(shader = heap_alloc(sizeof(*shader)))) 9513 return NULL; 9514 9515 shader->desc.settings = *settings; 9516 shader->id = shader_glsl_generate_ffp_vertex_shader(priv, settings, gl_info); 9517 list_init(&shader->linked_programs); 9518 if (wine_rb_put(&priv->ffp_vertex_shaders, &shader->desc.settings, &shader->desc.entry) == -1) 9519 ERR("Failed to insert ffp vertex shader.\n"); 9520 9521 return shader; 9522 } 9523 9524 static struct glsl_ffp_fragment_shader *shader_glsl_find_ffp_fragment_shader(struct shader_glsl_priv *priv, 9525 const struct ffp_frag_settings *args, const struct wined3d_context *context) 9526 { 9527 struct glsl_ffp_fragment_shader *glsl_desc; 9528 const struct ffp_frag_desc *desc; 9529 9530 if ((desc = find_ffp_frag_shader(&priv->ffp_fragment_shaders, args))) 9531 return CONTAINING_RECORD(desc, struct glsl_ffp_fragment_shader, entry); 9532 9533 if (!(glsl_desc = heap_alloc(sizeof(*glsl_desc)))) 9534 return NULL; 9535 9536 glsl_desc->entry.settings = *args; 9537 glsl_desc->id = shader_glsl_generate_ffp_fragment_shader(priv, args, context); 9538 list_init(&glsl_desc->linked_programs); 9539 add_ffp_frag_shader(&priv->ffp_fragment_shaders, &glsl_desc->entry); 9540 9541 return glsl_desc; 9542 } 9543 9544 9545 static void shader_glsl_init_vs_uniform_locations(const struct wined3d_gl_info *gl_info, 9546 struct shader_glsl_priv *priv, GLuint program_id, struct glsl_vs_program *vs, unsigned int vs_c_count) 9547 { 9548 unsigned int i; 9549 struct wined3d_string_buffer *name = string_buffer_get(&priv->string_buffers); 9550 9551 for (i = 0; i < vs_c_count; ++i) 9552 { 9553 string_buffer_sprintf(name, "vs_c[%u]", i); 9554 vs->uniform_f_locations[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9555 } 9556 memset(&vs->uniform_f_locations[vs_c_count], 0xff, (WINED3D_MAX_VS_CONSTS_F - vs_c_count) * sizeof(GLuint)); 9557 9558 for (i = 0; i < WINED3D_MAX_CONSTS_I; ++i) 9559 { 9560 string_buffer_sprintf(name, "vs_i[%u]", i); 9561 vs->uniform_i_locations[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9562 } 9563 9564 for (i = 0; i < WINED3D_MAX_CONSTS_B; ++i) 9565 { 9566 string_buffer_sprintf(name, "vs_b[%u]", i); 9567 vs->uniform_b_locations[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9568 } 9569 9570 vs->pos_fixup_location = GL_EXTCALL(glGetUniformLocation(program_id, "pos_fixup")); 9571 9572 for (i = 0; i < MAX_VERTEX_INDEX_BLENDS; ++i) 9573 { 9574 string_buffer_sprintf(name, "ffp_modelview_matrix[%u]", i); 9575 vs->modelview_matrix_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9576 } 9577 for (i = 0; i < MAX_VERTEX_INDEX_BLENDS; ++i) 9578 { 9579 string_buffer_sprintf(name, "ffp_normal_matrix[%u]", i); 9580 vs->normal_matrix_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9581 } 9582 vs->projection_matrix_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_projection_matrix")); 9583 for (i = 0; i < MAX_TEXTURES; ++i) 9584 { 9585 string_buffer_sprintf(name, "ffp_texture_matrix[%u]", i); 9586 vs->texture_matrix_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9587 } 9588 vs->material_ambient_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_material.ambient")); 9589 vs->material_diffuse_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_material.diffuse")); 9590 vs->material_specular_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_material.specular")); 9591 vs->material_emissive_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_material.emissive")); 9592 vs->material_shininess_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_material.shininess")); 9593 vs->light_ambient_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_light_ambient")); 9594 for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i) 9595 { 9596 string_buffer_sprintf(name, "ffp_light[%u].diffuse", i); 9597 vs->light_location[i].diffuse = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9598 string_buffer_sprintf(name, "ffp_light[%u].specular", i); 9599 vs->light_location[i].specular = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9600 string_buffer_sprintf(name, "ffp_light[%u].ambient", i); 9601 vs->light_location[i].ambient = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9602 string_buffer_sprintf(name, "ffp_light[%u].position", i); 9603 vs->light_location[i].position = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9604 string_buffer_sprintf(name, "ffp_light[%u].direction", i); 9605 vs->light_location[i].direction = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9606 string_buffer_sprintf(name, "ffp_light[%u].range", i); 9607 vs->light_location[i].range = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9608 string_buffer_sprintf(name, "ffp_light[%u].falloff", i); 9609 vs->light_location[i].falloff = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9610 string_buffer_sprintf(name, "ffp_light[%u].c_att", i); 9611 vs->light_location[i].c_att = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9612 string_buffer_sprintf(name, "ffp_light[%u].l_att", i); 9613 vs->light_location[i].l_att = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9614 string_buffer_sprintf(name, "ffp_light[%u].q_att", i); 9615 vs->light_location[i].q_att = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9616 string_buffer_sprintf(name, "ffp_light[%u].cos_htheta", i); 9617 vs->light_location[i].cos_htheta = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9618 string_buffer_sprintf(name, "ffp_light[%u].cos_hphi", i); 9619 vs->light_location[i].cos_hphi = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9620 } 9621 vs->pointsize_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_point.size")); 9622 vs->pointsize_min_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_point.size_min")); 9623 vs->pointsize_max_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_point.size_max")); 9624 vs->pointsize_c_att_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_point.c_att")); 9625 vs->pointsize_l_att_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_point.l_att")); 9626 vs->pointsize_q_att_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_point.q_att")); 9627 vs->clip_planes_location = GL_EXTCALL(glGetUniformLocation(program_id, "clip_planes")); 9628 9629 string_buffer_release(&priv->string_buffers, name); 9630 } 9631 9632 static void shader_glsl_init_ds_uniform_locations(const struct wined3d_gl_info *gl_info, 9633 struct shader_glsl_priv *priv, GLuint program_id, struct glsl_ds_program *ds) 9634 { 9635 ds->pos_fixup_location = GL_EXTCALL(glGetUniformLocation(program_id, "pos_fixup")); 9636 } 9637 9638 static void shader_glsl_init_gs_uniform_locations(const struct wined3d_gl_info *gl_info, 9639 struct shader_glsl_priv *priv, GLuint program_id, struct glsl_gs_program *gs) 9640 { 9641 gs->pos_fixup_location = GL_EXTCALL(glGetUniformLocation(program_id, "pos_fixup")); 9642 } 9643 9644 static void shader_glsl_init_ps_uniform_locations(const struct wined3d_gl_info *gl_info, 9645 struct shader_glsl_priv *priv, GLuint program_id, struct glsl_ps_program *ps, unsigned int ps_c_count) 9646 { 9647 unsigned int i; 9648 struct wined3d_string_buffer *name = string_buffer_get(&priv->string_buffers); 9649 9650 for (i = 0; i < ps_c_count; ++i) 9651 { 9652 string_buffer_sprintf(name, "ps_c[%u]", i); 9653 ps->uniform_f_locations[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9654 } 9655 memset(&ps->uniform_f_locations[ps_c_count], 0xff, (WINED3D_MAX_PS_CONSTS_F - ps_c_count) * sizeof(GLuint)); 9656 9657 for (i = 0; i < WINED3D_MAX_CONSTS_I; ++i) 9658 { 9659 string_buffer_sprintf(name, "ps_i[%u]", i); 9660 ps->uniform_i_locations[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9661 } 9662 9663 for (i = 0; i < WINED3D_MAX_CONSTS_B; ++i) 9664 { 9665 string_buffer_sprintf(name, "ps_b[%u]", i); 9666 ps->uniform_b_locations[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9667 } 9668 9669 for (i = 0; i < MAX_TEXTURES; ++i) 9670 { 9671 string_buffer_sprintf(name, "bumpenv_mat%u", i); 9672 ps->bumpenv_mat_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9673 string_buffer_sprintf(name, "bumpenv_lum_scale%u", i); 9674 ps->bumpenv_lum_scale_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9675 string_buffer_sprintf(name, "bumpenv_lum_offset%u", i); 9676 ps->bumpenv_lum_offset_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9677 string_buffer_sprintf(name, "tss_const%u", i); 9678 ps->tss_constant_location[i] = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer)); 9679 } 9680 9681 ps->tex_factor_location = GL_EXTCALL(glGetUniformLocation(program_id, "tex_factor")); 9682 ps->specular_enable_location = GL_EXTCALL(glGetUniformLocation(program_id, "specular_enable")); 9683 9684 ps->fog_color_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_fog.color")); 9685 ps->fog_density_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_fog.density")); 9686 ps->fog_end_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_fog.end")); 9687 ps->fog_scale_location = GL_EXTCALL(glGetUniformLocation(program_id, "ffp_fog.scale")); 9688 9689 ps->alpha_test_ref_location = GL_EXTCALL(glGetUniformLocation(program_id, "alpha_test_ref")); 9690 9691 ps->np2_fixup_location = GL_EXTCALL(glGetUniformLocation(program_id, "ps_samplerNP2Fixup")); 9692 ps->ycorrection_location = GL_EXTCALL(glGetUniformLocation(program_id, "ycorrection")); 9693 ps->color_key_location = GL_EXTCALL(glGetUniformLocation(program_id, "color_key")); 9694 9695 string_buffer_release(&priv->string_buffers, name); 9696 } 9697 9698 static HRESULT shader_glsl_compile_compute_shader(struct shader_glsl_priv *priv, 9699 const struct wined3d_context *context, struct wined3d_shader *shader) 9700 { 9701 struct glsl_context_data *ctx_data = context->shader_backend_data; 9702 struct wined3d_string_buffer *buffer = &priv->shader_buffer; 9703 const struct wined3d_gl_info *gl_info = context->gl_info; 9704 struct glsl_cs_compiled_shader *gl_shaders; 9705 struct glsl_shader_private *shader_data; 9706 struct glsl_shader_prog_link *entry; 9707 GLuint shader_id, program_id; 9708 9709 if (!(entry = heap_alloc(sizeof(*entry)))) 9710 { 9711 ERR("Out of memory.\n"); 9712 return E_OUTOFMEMORY; 9713 } 9714 9715 if (!(shader->backend_data = heap_alloc_zero(sizeof(*shader_data)))) 9716 { 9717 ERR("Failed to allocate backend data.\n"); 9718 heap_free(entry); 9719 return E_OUTOFMEMORY; 9720 } 9721 shader_data = shader->backend_data; 9722 gl_shaders = shader_data->gl_shaders.cs; 9723 9724 if (!(shader_data->gl_shaders.cs = heap_alloc(sizeof(*gl_shaders)))) 9725 { 9726 ERR("Failed to allocate GL shader array.\n"); 9727 heap_free(entry); 9728 heap_free(shader->backend_data); 9729 shader->backend_data = NULL; 9730 return E_OUTOFMEMORY; 9731 } 9732 shader_data->shader_array_size = 1; 9733 gl_shaders = shader_data->gl_shaders.cs; 9734 9735 TRACE("Compiling compute shader %p.\n", shader); 9736 9737 string_buffer_clear(buffer); 9738 shader_id = shader_glsl_generate_compute_shader(context, buffer, &priv->string_buffers, shader); 9739 gl_shaders[shader_data->num_gl_shaders++].id = shader_id; 9740 9741 program_id = GL_EXTCALL(glCreateProgram()); 9742 TRACE("Created new GLSL shader program %u.\n", program_id); 9743 9744 entry->id = program_id; 9745 entry->vs.id = 0; 9746 entry->hs.id = 0; 9747 entry->ds.id = 0; 9748 entry->gs.id = 0; 9749 entry->ps.id = 0; 9750 entry->cs.id = shader_id; 9751 entry->constant_version = 0; 9752 entry->shader_controlled_clip_distances = 0; 9753 entry->ps.np2_fixup_info = NULL; 9754 add_glsl_program_entry(priv, entry); 9755 9756 TRACE("Attaching GLSL shader object %u to program %u.\n", shader_id, program_id); 9757 GL_EXTCALL(glAttachShader(program_id, shader_id)); 9758 checkGLcall("glAttachShader"); 9759 9760 list_add_head(&shader->linked_programs, &entry->cs.shader_entry); 9761 9762 TRACE("Linking GLSL shader program %u.\n", program_id); 9763 GL_EXTCALL(glLinkProgram(program_id)); 9764 shader_glsl_validate_link(gl_info, program_id); 9765 9766 GL_EXTCALL(glUseProgram(program_id)); 9767 checkGLcall("glUseProgram"); 9768 shader_glsl_load_program_resources(context, priv, program_id, shader); 9769 shader_glsl_load_images(gl_info, priv, program_id, &shader->reg_maps); 9770 9771 entry->constant_update_mask = 0; 9772 9773 GL_EXTCALL(glUseProgram(ctx_data->glsl_program ? ctx_data->glsl_program->id : 0)); 9774 checkGLcall("glUseProgram"); 9775 return WINED3D_OK; 9776 } 9777 9778 static GLuint find_glsl_compute_shader(const struct wined3d_context *context, 9779 struct shader_glsl_priv *priv, struct wined3d_shader *shader) 9780 { 9781 struct glsl_shader_private *shader_data; 9782 9783 if (!shader->backend_data) 9784 { 9785 WARN("Failed to find GLSL program for compute shader %p.\n", shader); 9786 if (FAILED(shader_glsl_compile_compute_shader(priv, context, shader))) 9787 { 9788 ERR("Failed to compile compute shader %p.\n", shader); 9789 return 0; 9790 } 9791 } 9792 shader_data = shader->backend_data; 9793 return shader_data->gl_shaders.cs[0].id; 9794 } 9795 9796 /* Context activation is done by the caller. */ 9797 static void set_glsl_compute_shader_program(const struct wined3d_context *context, 9798 const struct wined3d_state *state, struct shader_glsl_priv *priv, struct glsl_context_data *ctx_data) 9799 { 9800 struct glsl_shader_prog_link *entry; 9801 struct wined3d_shader *shader; 9802 struct glsl_program_key key; 9803 GLuint cs_id; 9804 9805 if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_COMPUTE))) 9806 return; 9807 9808 if (!(shader = state->shader[WINED3D_SHADER_TYPE_COMPUTE])) 9809 { 9810 WARN("Compute shader is NULL.\n"); 9811 ctx_data->glsl_program = NULL; 9812 return; 9813 } 9814 9815 cs_id = find_glsl_compute_shader(context, priv, shader); 9816 memset(&key, 0, sizeof(key)); 9817 key.cs_id = cs_id; 9818 if (!(entry = get_glsl_program_entry(priv, &key))) 9819 ERR("Failed to find GLSL program for compute shader %p.\n", shader); 9820 ctx_data->glsl_program = entry; 9821 } 9822 9823 /* Context activation is done by the caller. */ 9824 static void set_glsl_shader_program(const struct wined3d_context *context, const struct wined3d_state *state, 9825 struct shader_glsl_priv *priv, struct glsl_context_data *ctx_data) 9826 { 9827 const struct wined3d_d3d_info *d3d_info = context->d3d_info; 9828 const struct wined3d_gl_info *gl_info = context->gl_info; 9829 const struct wined3d_shader *pre_rasterization_shader; 9830 const struct ps_np2fixup_info *np2fixup_info = NULL; 9831 struct wined3d_shader *hshader, *dshader, *gshader; 9832 struct glsl_shader_prog_link *entry = NULL; 9833 struct wined3d_shader *vshader = NULL; 9834 struct wined3d_shader *pshader = NULL; 9835 GLuint reorder_shader_id = 0; 9836 struct glsl_program_key key; 9837 GLuint program_id; 9838 unsigned int i; 9839 GLuint vs_id = 0; 9840 GLuint hs_id = 0; 9841 GLuint ds_id = 0; 9842 GLuint gs_id = 0; 9843 GLuint ps_id = 0; 9844 struct list *ps_list = NULL, *vs_list = NULL; 9845 WORD attribs_map; 9846 struct wined3d_string_buffer *tmp_name; 9847 9848 if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_VERTEX)) && ctx_data->glsl_program) 9849 { 9850 vs_id = ctx_data->glsl_program->vs.id; 9851 vs_list = &ctx_data->glsl_program->vs.shader_entry; 9852 9853 if (use_vs(state)) 9854 vshader = state->shader[WINED3D_SHADER_TYPE_VERTEX]; 9855 } 9856 else if (use_vs(state)) 9857 { 9858 struct vs_compile_args vs_compile_args; 9859 9860 vshader = state->shader[WINED3D_SHADER_TYPE_VERTEX]; 9861 9862 find_vs_compile_args(state, vshader, context->stream_info.swizzle_map, &vs_compile_args, context); 9863 vs_id = find_glsl_vshader(context, priv, vshader, &vs_compile_args); 9864 vs_list = &vshader->linked_programs; 9865 } 9866 else if (priv->vertex_pipe == &glsl_vertex_pipe) 9867 { 9868 struct glsl_ffp_vertex_shader *ffp_shader; 9869 struct wined3d_ffp_vs_settings settings; 9870 9871 wined3d_ffp_get_vs_settings(context, state, &settings); 9872 ffp_shader = shader_glsl_find_ffp_vertex_shader(priv, gl_info, &settings); 9873 vs_id = ffp_shader->id; 9874 vs_list = &ffp_shader->linked_programs; 9875 } 9876 9877 hshader = state->shader[WINED3D_SHADER_TYPE_HULL]; 9878 if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_HULL)) && ctx_data->glsl_program) 9879 hs_id = ctx_data->glsl_program->hs.id; 9880 else if (hshader) 9881 hs_id = find_glsl_hull_shader(context, priv, hshader); 9882 9883 dshader = state->shader[WINED3D_SHADER_TYPE_DOMAIN]; 9884 if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_DOMAIN)) && ctx_data->glsl_program) 9885 { 9886 ds_id = ctx_data->glsl_program->ds.id; 9887 } 9888 else if (dshader) 9889 { 9890 struct ds_compile_args args; 9891 9892 find_ds_compile_args(state, dshader, &args, context); 9893 ds_id = find_glsl_domain_shader(context, priv, dshader, &args); 9894 } 9895 9896 gshader = state->shader[WINED3D_SHADER_TYPE_GEOMETRY]; 9897 if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_GEOMETRY)) && ctx_data->glsl_program) 9898 { 9899 gs_id = ctx_data->glsl_program->gs.id; 9900 } 9901 else if (gshader) 9902 { 9903 struct gs_compile_args args; 9904 9905 find_gs_compile_args(state, gshader, &args, context); 9906 gs_id = find_glsl_geometry_shader(context, priv, gshader, &args); 9907 } 9908 9909 /* A pixel shader is not used when rasterization is disabled. */ 9910 if (is_rasterization_disabled(gshader)) 9911 { 9912 ps_id = 0; 9913 ps_list = NULL; 9914 } 9915 else if (!(context->shader_update_mask & (1u << WINED3D_SHADER_TYPE_PIXEL)) && ctx_data->glsl_program) 9916 { 9917 ps_id = ctx_data->glsl_program->ps.id; 9918 ps_list = &ctx_data->glsl_program->ps.shader_entry; 9919 9920 if (use_ps(state)) 9921 pshader = state->shader[WINED3D_SHADER_TYPE_PIXEL]; 9922 } 9923 else if (use_ps(state)) 9924 { 9925 struct ps_compile_args ps_compile_args; 9926 pshader = state->shader[WINED3D_SHADER_TYPE_PIXEL]; 9927 find_ps_compile_args(state, pshader, context->stream_info.position_transformed, &ps_compile_args, context); 9928 ps_id = find_glsl_pshader(context, &priv->shader_buffer, &priv->string_buffers, 9929 pshader, &ps_compile_args, &np2fixup_info); 9930 ps_list = &pshader->linked_programs; 9931 } 9932 else if (priv->fragment_pipe == &glsl_fragment_pipe 9933 && !(vshader && vshader->reg_maps.shader_version.major >= 4)) 9934 { 9935 struct glsl_ffp_fragment_shader *ffp_shader; 9936 struct ffp_frag_settings settings; 9937 9938 gen_ffp_frag_op(context, state, &settings, FALSE); 9939 ffp_shader = shader_glsl_find_ffp_fragment_shader(priv, &settings, context); 9940 ps_id = ffp_shader->id; 9941 ps_list = &ffp_shader->linked_programs; 9942 } 9943 9944 key.vs_id = vs_id; 9945 key.hs_id = hs_id; 9946 key.ds_id = ds_id; 9947 key.gs_id = gs_id; 9948 key.ps_id = ps_id; 9949 key.cs_id = 0; 9950 if ((!vs_id && !hs_id && !ds_id && !gs_id && !ps_id) || (entry = get_glsl_program_entry(priv, &key))) 9951 { 9952 ctx_data->glsl_program = entry; 9953 return; 9954 } 9955 9956 /* If we get to this point, then no matching program exists, so we create one */ 9957 program_id = GL_EXTCALL(glCreateProgram()); 9958 TRACE("Created new GLSL shader program %u.\n", program_id); 9959 9960 /* Create the entry */ 9961 entry = heap_alloc(sizeof(*entry)); 9962 entry->id = program_id; 9963 entry->vs.id = vs_id; 9964 entry->hs.id = hs_id; 9965 entry->ds.id = ds_id; 9966 entry->gs.id = gs_id; 9967 entry->ps.id = ps_id; 9968 entry->cs.id = 0; 9969 entry->constant_version = 0; 9970 entry->shader_controlled_clip_distances = 0; 9971 entry->ps.np2_fixup_info = np2fixup_info; 9972 /* Add the hash table entry */ 9973 add_glsl_program_entry(priv, entry); 9974 9975 /* Set the current program */ 9976 ctx_data->glsl_program = entry; 9977 9978 /* Attach GLSL vshader */ 9979 if (vs_id) 9980 { 9981 TRACE("Attaching GLSL shader object %u to program %u.\n", vs_id, program_id); 9982 GL_EXTCALL(glAttachShader(program_id, vs_id)); 9983 checkGLcall("glAttachShader"); 9984 9985 list_add_head(vs_list, &entry->vs.shader_entry); 9986 } 9987 9988 if (vshader) 9989 { 9990 attribs_map = vshader->reg_maps.input_registers; 9991 if (vshader->reg_maps.shader_version.major < 4) 9992 { 9993 reorder_shader_id = shader_glsl_generate_vs3_rasterizer_input_setup(priv, vshader, pshader, 9994 state->gl_primitive_type == GL_POINTS && vshader->reg_maps.point_size, 9995 d3d_info->emulated_flatshading 9996 && state->render_states[WINED3D_RS_SHADEMODE] == WINED3D_SHADE_FLAT, gl_info); 9997 TRACE("Attaching GLSL shader object %u to program %u.\n", reorder_shader_id, program_id); 9998 GL_EXTCALL(glAttachShader(program_id, reorder_shader_id)); 9999 checkGLcall("glAttachShader"); 10000 /* Flag the reorder function for deletion, it will be freed 10001 * automatically when the program is destroyed. */ 10002 GL_EXTCALL(glDeleteShader(reorder_shader_id)); 10003 } 10004 } 10005 else 10006 { 10007 attribs_map = (1u << WINED3D_FFP_ATTRIBS_COUNT) - 1; 10008 } 10009 10010 if (!shader_glsl_use_explicit_attrib_location(gl_info)) 10011 { 10012 /* Bind vertex attributes to a corresponding index number to match 10013 * the same index numbers as ARB_vertex_programs (makes loading 10014 * vertex attributes simpler). With this method, we can use the 10015 * exact same code to load the attributes later for both ARB and 10016 * GLSL shaders. 10017 * 10018 * We have to do this here because we need to know the Program ID 10019 * in order to make the bindings work, and it has to be done prior 10020 * to linking the GLSL program. */ 10021 tmp_name = string_buffer_get(&priv->string_buffers); 10022 for (i = 0; attribs_map; attribs_map >>= 1, ++i) 10023 { 10024 if (!(attribs_map & 1)) 10025 continue; 10026 10027 string_buffer_sprintf(tmp_name, "vs_in%u", i); 10028 GL_EXTCALL(glBindAttribLocation(program_id, i, tmp_name->buffer)); 10029 if (vshader && vshader->reg_maps.shader_version.major >= 4) 10030 { 10031 string_buffer_sprintf(tmp_name, "vs_in_uint%u", i); 10032 GL_EXTCALL(glBindAttribLocation(program_id, i, tmp_name->buffer)); 10033 string_buffer_sprintf(tmp_name, "vs_in_int%u", i); 10034 GL_EXTCALL(glBindAttribLocation(program_id, i, tmp_name->buffer)); 10035 } 10036 } 10037 checkGLcall("glBindAttribLocation"); 10038 string_buffer_release(&priv->string_buffers, tmp_name); 10039 10040 if (!needs_legacy_glsl_syntax(gl_info)) 10041 { 10042 char var[12]; 10043 10044 if (wined3d_dualblend_enabled(state, gl_info)) 10045 { 10046 for (i = 0; i < gl_info->limits.dual_buffers * 2; i++) 10047 { 10048 sprintf(var, "ps_out%u", i); 10049 GL_EXTCALL(glBindFragDataLocationIndexed(program_id, i / 2, i % 2, var)); 10050 checkGLcall("glBindFragDataLocationIndexed"); 10051 } 10052 } 10053 else 10054 { 10055 for (i = 0; i < gl_info->limits.buffers; i++) 10056 { 10057 sprintf(var, "ps_out%u", i); 10058 GL_EXTCALL(glBindFragDataLocation(program_id, i, var)); 10059 checkGLcall("glBindFragDataLocation"); 10060 } 10061 } 10062 } 10063 } 10064 10065 if (hshader) 10066 { 10067 TRACE("Attaching GLSL tessellation control shader object %u to program %u.\n", hs_id, program_id); 10068 GL_EXTCALL(glAttachShader(program_id, hs_id)); 10069 checkGLcall("glAttachShader"); 10070 10071 list_add_head(&hshader->linked_programs, &entry->hs.shader_entry); 10072 } 10073 10074 if (dshader) 10075 { 10076 TRACE("Attaching GLSL tessellation evaluation shader object %u to program %u.\n", ds_id, program_id); 10077 GL_EXTCALL(glAttachShader(program_id, ds_id)); 10078 checkGLcall("glAttachShader"); 10079 10080 list_add_head(&dshader->linked_programs, &entry->ds.shader_entry); 10081 } 10082 10083 if (gshader) 10084 { 10085 TRACE("Attaching GLSL geometry shader object %u to program %u.\n", gs_id, program_id); 10086 GL_EXTCALL(glAttachShader(program_id, gs_id)); 10087 checkGLcall("glAttachShader"); 10088 10089 shader_glsl_init_transform_feedback(context, priv, program_id, gshader); 10090 10091 list_add_head(&gshader->linked_programs, &entry->gs.shader_entry); 10092 } 10093 10094 /* Attach GLSL pshader */ 10095 if (ps_id) 10096 { 10097 TRACE("Attaching GLSL shader object %u to program %u.\n", ps_id, program_id); 10098 GL_EXTCALL(glAttachShader(program_id, ps_id)); 10099 checkGLcall("glAttachShader"); 10100 10101 list_add_head(ps_list, &entry->ps.shader_entry); 10102 } 10103 10104 /* Link the program */ 10105 TRACE("Linking GLSL shader program %u.\n", program_id); 10106 GL_EXTCALL(glLinkProgram(program_id)); 10107 shader_glsl_validate_link(gl_info, program_id); 10108 10109 shader_glsl_init_vs_uniform_locations(gl_info, priv, program_id, &entry->vs, 10110 vshader ? vshader->limits->constant_float : 0); 10111 shader_glsl_init_ds_uniform_locations(gl_info, priv, program_id, &entry->ds); 10112 shader_glsl_init_gs_uniform_locations(gl_info, priv, program_id, &entry->gs); 10113 shader_glsl_init_ps_uniform_locations(gl_info, priv, program_id, &entry->ps, 10114 pshader ? pshader->limits->constant_float : 0); 10115 checkGLcall("find glsl program uniform locations"); 10116 10117 pre_rasterization_shader = gshader ? gshader : dshader ? dshader : vshader; 10118 if (pre_rasterization_shader && pre_rasterization_shader->reg_maps.shader_version.major >= 4) 10119 { 10120 unsigned int clip_distance_count = wined3d_popcount(pre_rasterization_shader->reg_maps.clip_distance_mask); 10121 entry->shader_controlled_clip_distances = 1; 10122 entry->clip_distance_mask = (1u << clip_distance_count) - 1; 10123 } 10124 10125 if (needs_legacy_glsl_syntax(gl_info)) 10126 { 10127 if (pshader && pshader->reg_maps.shader_version.major >= 3 10128 && pshader->u.ps.declared_in_count > vec4_varyings(3, gl_info)) 10129 { 10130 TRACE("Shader %d needs vertex color clamping disabled.\n", program_id); 10131 entry->vs.vertex_color_clamp = GL_FALSE; 10132 } 10133 else 10134 { 10135 entry->vs.vertex_color_clamp = GL_FIXED_ONLY_ARB; 10136 } 10137 } 10138 else 10139 { 10140 /* With core profile we never change vertex_color_clamp from 10141 * GL_FIXED_ONLY_MODE (which is also the initial value) so we never call 10142 * glClampColorARB(). */ 10143 entry->vs.vertex_color_clamp = GL_FIXED_ONLY_ARB; 10144 } 10145 10146 /* Set the shader to allow uniform loading on it */ 10147 GL_EXTCALL(glUseProgram(program_id)); 10148 checkGLcall("glUseProgram"); 10149 10150 entry->constant_update_mask = 0; 10151 if (vshader) 10152 { 10153 entry->constant_update_mask |= WINED3D_SHADER_CONST_VS_F; 10154 if (vshader->reg_maps.integer_constants) 10155 entry->constant_update_mask |= WINED3D_SHADER_CONST_VS_I; 10156 if (vshader->reg_maps.boolean_constants) 10157 entry->constant_update_mask |= WINED3D_SHADER_CONST_VS_B; 10158 if (entry->vs.pos_fixup_location != -1) 10159 entry->constant_update_mask |= WINED3D_SHADER_CONST_POS_FIXUP; 10160 10161 shader_glsl_load_program_resources(context, priv, program_id, vshader); 10162 } 10163 else 10164 { 10165 entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_MODELVIEW 10166 | WINED3D_SHADER_CONST_FFP_PROJ; 10167 10168 for (i = 1; i < MAX_VERTEX_INDEX_BLENDS; ++i) 10169 { 10170 if (entry->vs.modelview_matrix_location[i] != -1) 10171 { 10172 entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_VERTEXBLEND; 10173 break; 10174 } 10175 } 10176 10177 for (i = 0; i < MAX_TEXTURES; ++i) 10178 { 10179 if (entry->vs.texture_matrix_location[i] != -1) 10180 { 10181 entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_TEXMATRIX; 10182 break; 10183 } 10184 } 10185 if (entry->vs.material_ambient_location != -1 || entry->vs.material_diffuse_location != -1 10186 || entry->vs.material_specular_location != -1 10187 || entry->vs.material_emissive_location != -1 10188 || entry->vs.material_shininess_location != -1) 10189 entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_MATERIAL; 10190 if (entry->vs.light_ambient_location != -1) 10191 entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_LIGHTS; 10192 } 10193 if (entry->vs.clip_planes_location != -1) 10194 entry->constant_update_mask |= WINED3D_SHADER_CONST_VS_CLIP_PLANES; 10195 if (entry->vs.pointsize_min_location != -1) 10196 entry->constant_update_mask |= WINED3D_SHADER_CONST_VS_POINTSIZE; 10197 10198 if (hshader) 10199 shader_glsl_load_program_resources(context, priv, program_id, hshader); 10200 10201 if (dshader) 10202 { 10203 if (entry->ds.pos_fixup_location != -1) 10204 entry->constant_update_mask |= WINED3D_SHADER_CONST_POS_FIXUP; 10205 10206 shader_glsl_load_program_resources(context, priv, program_id, dshader); 10207 } 10208 10209 if (gshader) 10210 { 10211 if (entry->gs.pos_fixup_location != -1) 10212 entry->constant_update_mask |= WINED3D_SHADER_CONST_POS_FIXUP; 10213 10214 shader_glsl_load_program_resources(context, priv, program_id, gshader); 10215 } 10216 10217 if (ps_id) 10218 { 10219 if (pshader) 10220 { 10221 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_F; 10222 if (pshader->reg_maps.integer_constants) 10223 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_I; 10224 if (pshader->reg_maps.boolean_constants) 10225 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_B; 10226 if (entry->ps.ycorrection_location != -1) 10227 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_Y_CORR; 10228 10229 shader_glsl_load_program_resources(context, priv, program_id, pshader); 10230 shader_glsl_load_images(gl_info, priv, program_id, &pshader->reg_maps); 10231 } 10232 else 10233 { 10234 entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_PS; 10235 10236 shader_glsl_load_samplers(context, priv, program_id, NULL); 10237 } 10238 10239 for (i = 0; i < MAX_TEXTURES; ++i) 10240 { 10241 if (entry->ps.bumpenv_mat_location[i] != -1) 10242 { 10243 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_BUMP_ENV; 10244 break; 10245 } 10246 } 10247 10248 if (entry->ps.fog_color_location != -1) 10249 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_FOG; 10250 if (entry->ps.alpha_test_ref_location != -1) 10251 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_ALPHA_TEST; 10252 if (entry->ps.np2_fixup_location != -1) 10253 entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_NP2_FIXUP; 10254 if (entry->ps.color_key_location != -1) 10255 entry->constant_update_mask |= WINED3D_SHADER_CONST_FFP_COLOR_KEY; 10256 } 10257 } 10258 10259 static void shader_glsl_precompile(void *shader_priv, struct wined3d_shader *shader) 10260 { 10261 struct wined3d_device *device = shader->device; 10262 struct wined3d_context *context; 10263 10264 if (shader->reg_maps.shader_version.type == WINED3D_SHADER_TYPE_COMPUTE) 10265 { 10266 context = context_acquire(device, NULL, 0); 10267 shader_glsl_compile_compute_shader(shader_priv, context, shader); 10268 context_release(context); 10269 } 10270 } 10271 10272 /* Context activation is done by the caller. */ 10273 static void shader_glsl_select(void *shader_priv, struct wined3d_context *context, 10274 const struct wined3d_state *state) 10275 { 10276 struct glsl_context_data *ctx_data = context->shader_backend_data; 10277 const struct wined3d_gl_info *gl_info = context->gl_info; 10278 struct shader_glsl_priv *priv = shader_priv; 10279 struct glsl_shader_prog_link *glsl_program; 10280 GLenum current_vertex_color_clamp; 10281 GLuint program_id, prev_id; 10282 10283 priv->vertex_pipe->vp_enable(gl_info, !use_vs(state)); 10284 priv->fragment_pipe->enable_extension(gl_info, !use_ps(state)); 10285 10286 prev_id = ctx_data->glsl_program ? ctx_data->glsl_program->id : 0; 10287 set_glsl_shader_program(context, state, priv, ctx_data); 10288 glsl_program = ctx_data->glsl_program; 10289 10290 if (glsl_program) 10291 { 10292 program_id = glsl_program->id; 10293 current_vertex_color_clamp = glsl_program->vs.vertex_color_clamp; 10294 if (glsl_program->shader_controlled_clip_distances) 10295 context_enable_clip_distances(context, glsl_program->clip_distance_mask); 10296 } 10297 else 10298 { 10299 program_id = 0; 10300 current_vertex_color_clamp = GL_FIXED_ONLY_ARB; 10301 } 10302 10303 if (ctx_data->vertex_color_clamp != current_vertex_color_clamp) 10304 { 10305 ctx_data->vertex_color_clamp = current_vertex_color_clamp; 10306 if (gl_info->supported[ARB_COLOR_BUFFER_FLOAT]) 10307 { 10308 GL_EXTCALL(glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, current_vertex_color_clamp)); 10309 checkGLcall("glClampColorARB"); 10310 } 10311 else 10312 { 10313 FIXME("Vertex color clamp needs to be changed, but extension not supported.\n"); 10314 } 10315 } 10316 10317 TRACE("Using GLSL program %u.\n", program_id); 10318 10319 if (prev_id != program_id) 10320 { 10321 GL_EXTCALL(glUseProgram(program_id)); 10322 checkGLcall("glUseProgram"); 10323 10324 if (glsl_program) 10325 context->constant_update_mask |= glsl_program->constant_update_mask; 10326 } 10327 10328 context->shader_update_mask |= (1u << WINED3D_SHADER_TYPE_COMPUTE); 10329 } 10330 10331 /* Context activation is done by the caller. */ 10332 static void shader_glsl_select_compute(void *shader_priv, struct wined3d_context *context, 10333 const struct wined3d_state *state) 10334 { 10335 struct glsl_context_data *ctx_data = context->shader_backend_data; 10336 const struct wined3d_gl_info *gl_info = context->gl_info; 10337 struct shader_glsl_priv *priv = shader_priv; 10338 GLuint program_id, prev_id; 10339 10340 prev_id = ctx_data->glsl_program ? ctx_data->glsl_program->id : 0; 10341 set_glsl_compute_shader_program(context, state, priv, ctx_data); 10342 program_id = ctx_data->glsl_program ? ctx_data->glsl_program->id : 0; 10343 10344 TRACE("Using GLSL program %u.\n", program_id); 10345 10346 if (prev_id != program_id) 10347 { 10348 GL_EXTCALL(glUseProgram(program_id)); 10349 checkGLcall("glUseProgram"); 10350 } 10351 10352 context->shader_update_mask |= (1u << WINED3D_SHADER_TYPE_PIXEL) 10353 | (1u << WINED3D_SHADER_TYPE_VERTEX) 10354 | (1u << WINED3D_SHADER_TYPE_GEOMETRY) 10355 | (1u << WINED3D_SHADER_TYPE_HULL) 10356 | (1u << WINED3D_SHADER_TYPE_DOMAIN); 10357 } 10358 10359 /* "context" is not necessarily the currently active context. */ 10360 static void shader_glsl_invalidate_current_program(struct wined3d_context *context) 10361 { 10362 struct glsl_context_data *ctx_data = context->shader_backend_data; 10363 10364 ctx_data->glsl_program = NULL; 10365 context->shader_update_mask = (1u << WINED3D_SHADER_TYPE_PIXEL) 10366 | (1u << WINED3D_SHADER_TYPE_VERTEX) 10367 | (1u << WINED3D_SHADER_TYPE_GEOMETRY) 10368 | (1u << WINED3D_SHADER_TYPE_HULL) 10369 | (1u << WINED3D_SHADER_TYPE_DOMAIN) 10370 | (1u << WINED3D_SHADER_TYPE_COMPUTE); 10371 } 10372 10373 /* Context activation is done by the caller. */ 10374 static void shader_glsl_disable(void *shader_priv, struct wined3d_context *context) 10375 { 10376 struct glsl_context_data *ctx_data = context->shader_backend_data; 10377 const struct wined3d_gl_info *gl_info = context->gl_info; 10378 struct shader_glsl_priv *priv = shader_priv; 10379 10380 shader_glsl_invalidate_current_program(context); 10381 GL_EXTCALL(glUseProgram(0)); 10382 checkGLcall("glUseProgram"); 10383 10384 priv->vertex_pipe->vp_enable(gl_info, FALSE); 10385 priv->fragment_pipe->enable_extension(gl_info, FALSE); 10386 10387 if (needs_legacy_glsl_syntax(gl_info) && gl_info->supported[ARB_COLOR_BUFFER_FLOAT]) 10388 { 10389 ctx_data->vertex_color_clamp = GL_FIXED_ONLY_ARB; 10390 GL_EXTCALL(glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, GL_FIXED_ONLY_ARB)); 10391 checkGLcall("glClampColorARB"); 10392 } 10393 } 10394 10395 static void shader_glsl_invalidate_contexts_program(struct wined3d_device *device, 10396 const struct glsl_shader_prog_link *program) 10397 { 10398 const struct glsl_context_data *ctx_data; 10399 struct wined3d_context *context; 10400 unsigned int i; 10401 10402 for (i = 0; i < device->context_count; ++i) 10403 { 10404 context = device->contexts[i]; 10405 ctx_data = context->shader_backend_data; 10406 10407 if (ctx_data->glsl_program == program) 10408 shader_glsl_invalidate_current_program(context); 10409 } 10410 } 10411 10412 static void shader_glsl_destroy(struct wined3d_shader *shader) 10413 { 10414 struct glsl_shader_private *shader_data = shader->backend_data; 10415 struct wined3d_device *device = shader->device; 10416 struct shader_glsl_priv *priv = device->shader_priv; 10417 const struct wined3d_gl_info *gl_info; 10418 const struct list *linked_programs; 10419 struct wined3d_context *context; 10420 10421 if (!shader_data || !shader_data->num_gl_shaders) 10422 { 10423 heap_free(shader_data); 10424 shader->backend_data = NULL; 10425 return; 10426 } 10427 10428 context = context_acquire(device, NULL, 0); 10429 gl_info = context->gl_info; 10430 10431 TRACE("Deleting linked programs.\n"); 10432 linked_programs = &shader->linked_programs; 10433 if (linked_programs->next) 10434 { 10435 struct glsl_shader_prog_link *entry, *entry2; 10436 UINT i; 10437 10438 switch (shader->reg_maps.shader_version.type) 10439 { 10440 case WINED3D_SHADER_TYPE_PIXEL: 10441 { 10442 struct glsl_ps_compiled_shader *gl_shaders = shader_data->gl_shaders.ps; 10443 10444 for (i = 0; i < shader_data->num_gl_shaders; ++i) 10445 { 10446 TRACE("Deleting pixel shader %u.\n", gl_shaders[i].id); 10447 GL_EXTCALL(glDeleteShader(gl_shaders[i].id)); 10448 checkGLcall("glDeleteShader"); 10449 } 10450 heap_free(shader_data->gl_shaders.ps); 10451 10452 LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, 10453 struct glsl_shader_prog_link, ps.shader_entry) 10454 { 10455 shader_glsl_invalidate_contexts_program(device, entry); 10456 delete_glsl_program_entry(priv, gl_info, entry); 10457 } 10458 10459 break; 10460 } 10461 10462 case WINED3D_SHADER_TYPE_VERTEX: 10463 { 10464 struct glsl_vs_compiled_shader *gl_shaders = shader_data->gl_shaders.vs; 10465 10466 for (i = 0; i < shader_data->num_gl_shaders; ++i) 10467 { 10468 TRACE("Deleting vertex shader %u.\n", gl_shaders[i].id); 10469 GL_EXTCALL(glDeleteShader(gl_shaders[i].id)); 10470 checkGLcall("glDeleteShader"); 10471 } 10472 heap_free(shader_data->gl_shaders.vs); 10473 10474 LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, 10475 struct glsl_shader_prog_link, vs.shader_entry) 10476 { 10477 shader_glsl_invalidate_contexts_program(device, entry); 10478 delete_glsl_program_entry(priv, gl_info, entry); 10479 } 10480 10481 break; 10482 } 10483 10484 case WINED3D_SHADER_TYPE_HULL: 10485 { 10486 struct glsl_hs_compiled_shader *gl_shaders = shader_data->gl_shaders.hs; 10487 10488 for (i = 0; i < shader_data->num_gl_shaders; ++i) 10489 { 10490 TRACE("Deleting hull shader %u.\n", gl_shaders[i].id); 10491 GL_EXTCALL(glDeleteShader(gl_shaders[i].id)); 10492 checkGLcall("glDeleteShader"); 10493 } 10494 heap_free(shader_data->gl_shaders.hs); 10495 10496 LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, 10497 struct glsl_shader_prog_link, hs.shader_entry) 10498 { 10499 shader_glsl_invalidate_contexts_program(device, entry); 10500 delete_glsl_program_entry(priv, gl_info, entry); 10501 } 10502 10503 break; 10504 } 10505 10506 case WINED3D_SHADER_TYPE_DOMAIN: 10507 { 10508 struct glsl_ds_compiled_shader *gl_shaders = shader_data->gl_shaders.ds; 10509 10510 for (i = 0; i < shader_data->num_gl_shaders; ++i) 10511 { 10512 TRACE("Deleting domain shader %u.\n", gl_shaders[i].id); 10513 GL_EXTCALL(glDeleteShader(gl_shaders[i].id)); 10514 checkGLcall("glDeleteShader"); 10515 } 10516 heap_free(shader_data->gl_shaders.ds); 10517 10518 LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, 10519 struct glsl_shader_prog_link, ds.shader_entry) 10520 { 10521 shader_glsl_invalidate_contexts_program(device, entry); 10522 delete_glsl_program_entry(priv, gl_info, entry); 10523 } 10524 10525 break; 10526 } 10527 10528 case WINED3D_SHADER_TYPE_GEOMETRY: 10529 { 10530 struct glsl_gs_compiled_shader *gl_shaders = shader_data->gl_shaders.gs; 10531 10532 for (i = 0; i < shader_data->num_gl_shaders; ++i) 10533 { 10534 TRACE("Deleting geometry shader %u.\n", gl_shaders[i].id); 10535 GL_EXTCALL(glDeleteShader(gl_shaders[i].id)); 10536 checkGLcall("glDeleteShader"); 10537 } 10538 heap_free(shader_data->gl_shaders.gs); 10539 10540 LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, 10541 struct glsl_shader_prog_link, gs.shader_entry) 10542 { 10543 shader_glsl_invalidate_contexts_program(device, entry); 10544 delete_glsl_program_entry(priv, gl_info, entry); 10545 } 10546 10547 break; 10548 } 10549 10550 case WINED3D_SHADER_TYPE_COMPUTE: 10551 { 10552 struct glsl_cs_compiled_shader *gl_shaders = shader_data->gl_shaders.cs; 10553 10554 for (i = 0; i < shader_data->num_gl_shaders; ++i) 10555 { 10556 TRACE("Deleting compute shader %u.\n", gl_shaders[i].id); 10557 GL_EXTCALL(glDeleteShader(gl_shaders[i].id)); 10558 checkGLcall("glDeleteShader"); 10559 } 10560 heap_free(shader_data->gl_shaders.cs); 10561 10562 LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, 10563 struct glsl_shader_prog_link, cs.shader_entry) 10564 { 10565 shader_glsl_invalidate_contexts_program(device, entry); 10566 delete_glsl_program_entry(priv, gl_info, entry); 10567 } 10568 10569 break; 10570 } 10571 10572 default: 10573 ERR("Unhandled shader type %#x.\n", shader->reg_maps.shader_version.type); 10574 break; 10575 } 10576 } 10577 10578 heap_free(shader->backend_data); 10579 shader->backend_data = NULL; 10580 10581 context_release(context); 10582 } 10583 10584 static int glsl_program_key_compare(const void *key, const struct wine_rb_entry *entry) 10585 { 10586 const struct glsl_program_key *k = key; 10587 const struct glsl_shader_prog_link *prog = WINE_RB_ENTRY_VALUE(entry, 10588 const struct glsl_shader_prog_link, program_lookup_entry); 10589 10590 if (k->vs_id > prog->vs.id) return 1; 10591 else if (k->vs_id < prog->vs.id) return -1; 10592 10593 if (k->gs_id > prog->gs.id) return 1; 10594 else if (k->gs_id < prog->gs.id) return -1; 10595 10596 if (k->ps_id > prog->ps.id) return 1; 10597 else if (k->ps_id < prog->ps.id) return -1; 10598 10599 if (k->hs_id > prog->hs.id) return 1; 10600 else if (k->hs_id < prog->hs.id) return -1; 10601 10602 if (k->ds_id > prog->ds.id) return 1; 10603 else if (k->ds_id < prog->ds.id) return -1; 10604 10605 if (k->cs_id > prog->cs.id) return 1; 10606 else if (k->cs_id < prog->cs.id) return -1; 10607 10608 return 0; 10609 } 10610 10611 static BOOL constant_heap_init(struct constant_heap *heap, unsigned int constant_count) 10612 { 10613 SIZE_T size = (constant_count + 1) * sizeof(*heap->entries) 10614 + constant_count * sizeof(*heap->contained) 10615 + constant_count * sizeof(*heap->positions); 10616 void *mem; 10617 10618 if (!(mem = heap_alloc(size))) 10619 { 10620 ERR("Failed to allocate memory\n"); 10621 return FALSE; 10622 } 10623 10624 heap->entries = mem; 10625 heap->entries[1].version = 0; 10626 heap->contained = (BOOL *)(heap->entries + constant_count + 1); 10627 memset(heap->contained, 0, constant_count * sizeof(*heap->contained)); 10628 heap->positions = (unsigned int *)(heap->contained + constant_count); 10629 heap->size = 1; 10630 10631 return TRUE; 10632 } 10633 10634 static void constant_heap_free(struct constant_heap *heap) 10635 { 10636 heap_free(heap->entries); 10637 } 10638 10639 static HRESULT shader_glsl_alloc(struct wined3d_device *device, const struct wined3d_vertex_pipe_ops *vertex_pipe, 10640 const struct fragment_pipeline *fragment_pipe) 10641 { 10642 SIZE_T stack_size = wined3d_log2i(max(WINED3D_MAX_VS_CONSTS_F, WINED3D_MAX_PS_CONSTS_F)) + 1; 10643 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; 10644 struct fragment_caps fragment_caps; 10645 void *vertex_priv, *fragment_priv; 10646 struct shader_glsl_priv *priv; 10647 10648 if (!(priv = heap_alloc_zero(sizeof(*priv)))) 10649 return E_OUTOFMEMORY; 10650 10651 string_buffer_list_init(&priv->string_buffers); 10652 10653 if (!(vertex_priv = vertex_pipe->vp_alloc(&glsl_shader_backend, priv))) 10654 { 10655 ERR("Failed to initialize vertex pipe.\n"); 10656 heap_free(priv); 10657 return E_FAIL; 10658 } 10659 10660 if (!(fragment_priv = fragment_pipe->alloc_private(&glsl_shader_backend, priv))) 10661 { 10662 ERR("Failed to initialize fragment pipe.\n"); 10663 vertex_pipe->vp_free(device); 10664 heap_free(priv); 10665 return E_FAIL; 10666 } 10667 10668 if (!string_buffer_init(&priv->shader_buffer)) 10669 { 10670 ERR("Failed to initialize shader buffer.\n"); 10671 goto fail; 10672 } 10673 10674 if (!(priv->stack = heap_calloc(stack_size, sizeof(*priv->stack)))) 10675 { 10676 ERR("Failed to allocate memory.\n"); 10677 goto fail; 10678 } 10679 10680 if (!constant_heap_init(&priv->vconst_heap, WINED3D_MAX_VS_CONSTS_F)) 10681 { 10682 ERR("Failed to initialize vertex shader constant heap\n"); 10683 goto fail; 10684 } 10685 10686 if (!constant_heap_init(&priv->pconst_heap, WINED3D_MAX_PS_CONSTS_F)) 10687 { 10688 ERR("Failed to initialize pixel shader constant heap\n"); 10689 goto fail; 10690 } 10691 10692 wine_rb_init(&priv->program_lookup, glsl_program_key_compare); 10693 10694 priv->next_constant_version = 1; 10695 priv->vertex_pipe = vertex_pipe; 10696 priv->fragment_pipe = fragment_pipe; 10697 fragment_pipe->get_caps(gl_info, &fragment_caps); 10698 priv->ffp_proj_control = fragment_caps.wined3d_caps & WINED3D_FRAGMENT_CAP_PROJ_CONTROL; 10699 priv->legacy_lighting = device->wined3d->flags & WINED3D_LEGACY_FFP_LIGHTING; 10700 10701 device->vertex_priv = vertex_priv; 10702 device->fragment_priv = fragment_priv; 10703 device->shader_priv = priv; 10704 10705 return WINED3D_OK; 10706 10707 fail: 10708 constant_heap_free(&priv->pconst_heap); 10709 constant_heap_free(&priv->vconst_heap); 10710 heap_free(priv->stack); 10711 string_buffer_free(&priv->shader_buffer); 10712 fragment_pipe->free_private(device); 10713 vertex_pipe->vp_free(device); 10714 heap_free(priv); 10715 return E_OUTOFMEMORY; 10716 } 10717 10718 /* Context activation is done by the caller. */ 10719 static void shader_glsl_free(struct wined3d_device *device) 10720 { 10721 struct shader_glsl_priv *priv = device->shader_priv; 10722 10723 wine_rb_destroy(&priv->program_lookup, NULL, NULL); 10724 constant_heap_free(&priv->pconst_heap); 10725 constant_heap_free(&priv->vconst_heap); 10726 heap_free(priv->stack); 10727 string_buffer_list_cleanup(&priv->string_buffers); 10728 string_buffer_free(&priv->shader_buffer); 10729 priv->fragment_pipe->free_private(device); 10730 priv->vertex_pipe->vp_free(device); 10731 10732 heap_free(device->shader_priv); 10733 device->shader_priv = NULL; 10734 } 10735 10736 static BOOL shader_glsl_allocate_context_data(struct wined3d_context *context) 10737 { 10738 struct glsl_context_data *ctx_data; 10739 10740 if (!(ctx_data = heap_alloc_zero(sizeof(*ctx_data)))) 10741 return FALSE; 10742 ctx_data->vertex_color_clamp = GL_FIXED_ONLY_ARB; 10743 context->shader_backend_data = ctx_data; 10744 return TRUE; 10745 } 10746 10747 static void shader_glsl_free_context_data(struct wined3d_context *context) 10748 { 10749 heap_free(context->shader_backend_data); 10750 } 10751 10752 static void shader_glsl_init_context_state(struct wined3d_context *context) 10753 { 10754 const struct wined3d_gl_info *gl_info = context->gl_info; 10755 10756 gl_info->gl_ops.gl.p_glEnable(GL_PROGRAM_POINT_SIZE); 10757 checkGLcall("GL_PROGRAM_POINT_SIZE"); 10758 } 10759 10760 static unsigned int shader_glsl_get_shader_model(const struct wined3d_gl_info *gl_info) 10761 { 10762 BOOL shader_model_4 = gl_info->glsl_version >= MAKEDWORD_VERSION(1, 50) 10763 && gl_info->supported[WINED3D_GL_VERSION_3_2] 10764 && gl_info->supported[ARB_SAMPLER_OBJECTS] 10765 && gl_info->supported[ARB_SHADER_BIT_ENCODING] 10766 && gl_info->supported[ARB_TEXTURE_SWIZZLE]; 10767 10768 if (shader_model_4 10769 && gl_info->supported[ARB_COMPUTE_SHADER] 10770 && gl_info->supported[ARB_CULL_DISTANCE] 10771 && gl_info->supported[ARB_DERIVATIVE_CONTROL] 10772 && gl_info->supported[ARB_DRAW_INDIRECT] 10773 && gl_info->supported[ARB_GPU_SHADER5] 10774 && gl_info->supported[ARB_SHADER_ATOMIC_COUNTERS] 10775 && gl_info->supported[ARB_SHADER_IMAGE_LOAD_STORE] 10776 && gl_info->supported[ARB_SHADER_IMAGE_SIZE] 10777 && gl_info->supported[ARB_SHADING_LANGUAGE_PACKING] 10778 && gl_info->supported[ARB_TESSELLATION_SHADER] 10779 && gl_info->supported[ARB_TEXTURE_GATHER] 10780 && gl_info->supported[ARB_TRANSFORM_FEEDBACK3]) 10781 return 5; 10782 10783 if (shader_model_4) 10784 return 4; 10785 10786 /* Support for texldd and texldl instructions in pixel shaders is required 10787 * for SM3. */ 10788 if (shader_glsl_has_core_grad(gl_info) || gl_info->supported[ARB_SHADER_TEXTURE_LOD]) 10789 return 3; 10790 10791 return 2; 10792 } 10793 10794 static void shader_glsl_get_caps(const struct wined3d_gl_info *gl_info, struct shader_caps *caps) 10795 { 10796 unsigned int shader_model = shader_glsl_get_shader_model(gl_info); 10797 10798 TRACE("Shader model %u.\n", shader_model); 10799 10800 caps->vs_version = min(wined3d_settings.max_sm_vs, shader_model); 10801 caps->hs_version = min(wined3d_settings.max_sm_hs, shader_model); 10802 caps->ds_version = min(wined3d_settings.max_sm_ds, shader_model); 10803 caps->gs_version = min(wined3d_settings.max_sm_gs, shader_model); 10804 caps->ps_version = min(wined3d_settings.max_sm_ps, shader_model); 10805 caps->cs_version = min(wined3d_settings.max_sm_cs, shader_model); 10806 10807 caps->vs_version = gl_info->supported[ARB_VERTEX_SHADER] ? caps->vs_version : 0; 10808 caps->ps_version = gl_info->supported[ARB_FRAGMENT_SHADER] ? caps->ps_version : 0; 10809 10810 caps->vs_uniform_count = min(WINED3D_MAX_VS_CONSTS_F, gl_info->limits.glsl_vs_float_constants); 10811 caps->ps_uniform_count = min(WINED3D_MAX_PS_CONSTS_F, gl_info->limits.glsl_ps_float_constants); 10812 caps->varying_count = gl_info->limits.glsl_varyings; 10813 10814 /* FIXME: The following line is card dependent. -8.0 to 8.0 is the 10815 * Direct3D minimum requirement. 10816 * 10817 * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude" 10818 * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here? 10819 * 10820 * The problem is that the refrast clamps temporary results in the shader to 10821 * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here, 10822 * then applications may miss the clamping behavior. On the other hand, if it is smaller, 10823 * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't 10824 * offer a way to query this. 10825 */ 10826 if (shader_model >= 4) 10827 caps->ps_1x_max_value = FLT_MAX; 10828 else 10829 caps->ps_1x_max_value = 1024.0f; 10830 10831 /* Ideally we'd only set caps like sRGB writes here if supported by both 10832 * the shader backend and the fragment pipe, but we can get called before 10833 * shader_glsl_alloc(). */ 10834 caps->wined3d_caps = WINED3D_SHADER_CAP_VS_CLIPPING 10835 | WINED3D_SHADER_CAP_SRGB_WRITE; 10836 } 10837 10838 static BOOL shader_glsl_color_fixup_supported(struct color_fixup_desc fixup) 10839 { 10840 /* We support everything except YUV conversions. */ 10841 return !is_complex_fixup(fixup); 10842 } 10843 10844 static const SHADER_HANDLER shader_glsl_instruction_handler_table[WINED3DSIH_TABLE_SIZE] = 10845 { 10846 /* WINED3DSIH_ABS */ shader_glsl_map2gl, 10847 /* WINED3DSIH_ADD */ shader_glsl_binop, 10848 /* WINED3DSIH_AND */ shader_glsl_binop, 10849 /* WINED3DSIH_ATOMIC_AND */ shader_glsl_atomic, 10850 /* WINED3DSIH_ATOMIC_CMP_STORE */ shader_glsl_atomic, 10851 /* WINED3DSIH_ATOMIC_IADD */ shader_glsl_atomic, 10852 /* WINED3DSIH_ATOMIC_IMAX */ shader_glsl_atomic, 10853 /* WINED3DSIH_ATOMIC_IMIN */ shader_glsl_atomic, 10854 /* WINED3DSIH_ATOMIC_OR */ shader_glsl_atomic, 10855 /* WINED3DSIH_ATOMIC_UMAX */ shader_glsl_atomic, 10856 /* WINED3DSIH_ATOMIC_UMIN */ shader_glsl_atomic, 10857 /* WINED3DSIH_ATOMIC_XOR */ shader_glsl_atomic, 10858 /* WINED3DSIH_BEM */ shader_glsl_bem, 10859 /* WINED3DSIH_BFI */ shader_glsl_bitwise_op, 10860 /* WINED3DSIH_BFREV */ shader_glsl_map2gl, 10861 /* WINED3DSIH_BREAK */ shader_glsl_break, 10862 /* WINED3DSIH_BREAKC */ shader_glsl_breakc, 10863 /* WINED3DSIH_BREAKP */ shader_glsl_conditional_op, 10864 /* WINED3DSIH_BUFINFO */ shader_glsl_bufinfo, 10865 /* WINED3DSIH_CALL */ shader_glsl_call, 10866 /* WINED3DSIH_CALLNZ */ shader_glsl_callnz, 10867 /* WINED3DSIH_CASE */ shader_glsl_case, 10868 /* WINED3DSIH_CMP */ shader_glsl_conditional_move, 10869 /* WINED3DSIH_CND */ shader_glsl_cnd, 10870 /* WINED3DSIH_CONTINUE */ shader_glsl_continue, 10871 /* WINED3DSIH_CONTINUEP */ shader_glsl_conditional_op, 10872 /* WINED3DSIH_COUNTBITS */ shader_glsl_map2gl, 10873 /* WINED3DSIH_CRS */ shader_glsl_cross, 10874 /* WINED3DSIH_CUT */ shader_glsl_cut, 10875 /* WINED3DSIH_CUT_STREAM */ shader_glsl_cut, 10876 /* WINED3DSIH_DCL */ shader_glsl_nop, 10877 /* WINED3DSIH_DCL_CONSTANT_BUFFER */ shader_glsl_nop, 10878 /* WINED3DSIH_DCL_FUNCTION_BODY */ NULL, 10879 /* WINED3DSIH_DCL_FUNCTION_TABLE */ NULL, 10880 /* WINED3DSIH_DCL_GLOBAL_FLAGS */ shader_glsl_nop, 10881 /* WINED3DSIH_DCL_GS_INSTANCES */ shader_glsl_nop, 10882 /* WINED3DSIH_DCL_HS_FORK_PHASE_INSTANCE_COUNT */ shader_glsl_nop, 10883 /* WINED3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT */ shader_glsl_nop, 10884 /* WINED3DSIH_DCL_HS_MAX_TESSFACTOR */ shader_glsl_nop, 10885 /* WINED3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER */ shader_glsl_nop, 10886 /* WINED3DSIH_DCL_INDEX_RANGE */ shader_glsl_nop, 10887 /* WINED3DSIH_DCL_INDEXABLE_TEMP */ shader_glsl_nop, 10888 /* WINED3DSIH_DCL_INPUT */ shader_glsl_nop, 10889 /* WINED3DSIH_DCL_INPUT_CONTROL_POINT_COUNT */ shader_glsl_nop, 10890 /* WINED3DSIH_DCL_INPUT_PRIMITIVE */ shader_glsl_nop, 10891 /* WINED3DSIH_DCL_INPUT_PS */ shader_glsl_nop, 10892 /* WINED3DSIH_DCL_INPUT_PS_SGV */ NULL, 10893 /* WINED3DSIH_DCL_INPUT_PS_SIV */ NULL, 10894 /* WINED3DSIH_DCL_INPUT_SGV */ shader_glsl_nop, 10895 /* WINED3DSIH_DCL_INPUT_SIV */ shader_glsl_nop, 10896 /* WINED3DSIH_DCL_INTERFACE */ NULL, 10897 /* WINED3DSIH_DCL_OUTPUT */ shader_glsl_nop, 10898 /* WINED3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT */ shader_glsl_nop, 10899 /* WINED3DSIH_DCL_OUTPUT_SIV */ shader_glsl_nop, 10900 /* WINED3DSIH_DCL_OUTPUT_TOPOLOGY */ shader_glsl_nop, 10901 /* WINED3DSIH_DCL_RESOURCE_RAW */ shader_glsl_nop, 10902 /* WINED3DSIH_DCL_RESOURCE_STRUCTURED */ shader_glsl_nop, 10903 /* WINED3DSIH_DCL_SAMPLER */ shader_glsl_nop, 10904 /* WINED3DSIH_DCL_STREAM */ NULL, 10905 /* WINED3DSIH_DCL_TEMPS */ shader_glsl_nop, 10906 /* WINED3DSIH_DCL_TESSELLATOR_DOMAIN */ shader_glsl_nop, 10907 /* WINED3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE */ shader_glsl_nop, 10908 /* WINED3DSIH_DCL_TESSELLATOR_PARTITIONING */ shader_glsl_nop, 10909 /* WINED3DSIH_DCL_TGSM_RAW */ shader_glsl_nop, 10910 /* WINED3DSIH_DCL_TGSM_STRUCTURED */ shader_glsl_nop, 10911 /* WINED3DSIH_DCL_THREAD_GROUP */ shader_glsl_nop, 10912 /* WINED3DSIH_DCL_UAV_RAW */ shader_glsl_nop, 10913 /* WINED3DSIH_DCL_UAV_STRUCTURED */ shader_glsl_nop, 10914 /* WINED3DSIH_DCL_UAV_TYPED */ shader_glsl_nop, 10915 /* WINED3DSIH_DCL_VERTICES_OUT */ shader_glsl_nop, 10916 /* WINED3DSIH_DEF */ shader_glsl_nop, 10917 /* WINED3DSIH_DEFAULT */ shader_glsl_default, 10918 /* WINED3DSIH_DEFB */ shader_glsl_nop, 10919 /* WINED3DSIH_DEFI */ shader_glsl_nop, 10920 /* WINED3DSIH_DIV */ shader_glsl_binop, 10921 /* WINED3DSIH_DP2 */ shader_glsl_dot, 10922 /* WINED3DSIH_DP2ADD */ shader_glsl_dp2add, 10923 /* WINED3DSIH_DP3 */ shader_glsl_dot, 10924 /* WINED3DSIH_DP4 */ shader_glsl_dot, 10925 /* WINED3DSIH_DST */ shader_glsl_dst, 10926 /* WINED3DSIH_DSX */ shader_glsl_map2gl, 10927 /* WINED3DSIH_DSX_COARSE */ shader_glsl_map2gl, 10928 /* WINED3DSIH_DSX_FINE */ shader_glsl_map2gl, 10929 /* WINED3DSIH_DSY */ shader_glsl_map2gl, 10930 /* WINED3DSIH_DSY_COARSE */ shader_glsl_map2gl, 10931 /* WINED3DSIH_DSY_FINE */ shader_glsl_map2gl, 10932 /* WINED3DSIH_EVAL_SAMPLE_INDEX */ NULL, 10933 /* WINED3DSIH_ELSE */ shader_glsl_else, 10934 /* WINED3DSIH_EMIT */ shader_glsl_emit, 10935 /* WINED3DSIH_EMIT_STREAM */ shader_glsl_emit, 10936 /* WINED3DSIH_ENDIF */ shader_glsl_end, 10937 /* WINED3DSIH_ENDLOOP */ shader_glsl_end, 10938 /* WINED3DSIH_ENDREP */ shader_glsl_end, 10939 /* WINED3DSIH_ENDSWITCH */ shader_glsl_end, 10940 /* WINED3DSIH_EQ */ shader_glsl_relop, 10941 /* WINED3DSIH_EXP */ shader_glsl_scalar_op, 10942 /* WINED3DSIH_EXPP */ shader_glsl_expp, 10943 /* WINED3DSIH_F16TOF32 */ shader_glsl_float16, 10944 /* WINED3DSIH_F32TOF16 */ shader_glsl_float16, 10945 /* WINED3DSIH_FCALL */ NULL, 10946 /* WINED3DSIH_FIRSTBIT_HI */ shader_glsl_map2gl, 10947 /* WINED3DSIH_FIRSTBIT_LO */ shader_glsl_map2gl, 10948 /* WINED3DSIH_FIRSTBIT_SHI */ shader_glsl_map2gl, 10949 /* WINED3DSIH_FRC */ shader_glsl_map2gl, 10950 /* WINED3DSIH_FTOI */ shader_glsl_to_int, 10951 /* WINED3DSIH_FTOU */ shader_glsl_to_uint, 10952 /* WINED3DSIH_GATHER4 */ shader_glsl_gather4, 10953 /* WINED3DSIH_GATHER4_C */ shader_glsl_gather4, 10954 /* WINED3DSIH_GATHER4_PO */ shader_glsl_gather4, 10955 /* WINED3DSIH_GATHER4_PO_C */ shader_glsl_gather4, 10956 /* WINED3DSIH_GE */ shader_glsl_relop, 10957 /* WINED3DSIH_HS_CONTROL_POINT_PHASE */ shader_glsl_nop, 10958 /* WINED3DSIH_HS_DECLS */ shader_glsl_nop, 10959 /* WINED3DSIH_HS_FORK_PHASE */ shader_glsl_nop, 10960 /* WINED3DSIH_HS_JOIN_PHASE */ shader_glsl_nop, 10961 /* WINED3DSIH_IADD */ shader_glsl_binop, 10962 /* WINED3DSIH_IBFE */ shader_glsl_bitwise_op, 10963 /* WINED3DSIH_IEQ */ shader_glsl_relop, 10964 /* WINED3DSIH_IF */ shader_glsl_if, 10965 /* WINED3DSIH_IFC */ shader_glsl_ifc, 10966 /* WINED3DSIH_IGE */ shader_glsl_relop, 10967 /* WINED3DSIH_ILT */ shader_glsl_relop, 10968 /* WINED3DSIH_IMAD */ shader_glsl_mad, 10969 /* WINED3DSIH_IMAX */ shader_glsl_map2gl, 10970 /* WINED3DSIH_IMIN */ shader_glsl_map2gl, 10971 /* WINED3DSIH_IMM_ATOMIC_ALLOC */ shader_glsl_uav_counter, 10972 /* WINED3DSIH_IMM_ATOMIC_AND */ shader_glsl_atomic, 10973 /* WINED3DSIH_IMM_ATOMIC_CMP_EXCH */ shader_glsl_atomic, 10974 /* WINED3DSIH_IMM_ATOMIC_CONSUME */ shader_glsl_uav_counter, 10975 /* WINED3DSIH_IMM_ATOMIC_EXCH */ shader_glsl_atomic, 10976 /* WINED3DSIH_IMM_ATOMIC_IADD */ shader_glsl_atomic, 10977 /* WINED3DSIH_IMM_ATOMIC_IMAX */ shader_glsl_atomic, 10978 /* WINED3DSIH_IMM_ATOMIC_IMIN */ shader_glsl_atomic, 10979 /* WINED3DSIH_IMM_ATOMIC_OR */ shader_glsl_atomic, 10980 /* WINED3DSIH_IMM_ATOMIC_UMAX */ shader_glsl_atomic, 10981 /* WINED3DSIH_IMM_ATOMIC_UMIN */ shader_glsl_atomic, 10982 /* WINED3DSIH_IMM_ATOMIC_XOR */ shader_glsl_atomic, 10983 /* WINED3DSIH_IMUL */ shader_glsl_mul_extended, 10984 /* WINED3DSIH_INE */ shader_glsl_relop, 10985 /* WINED3DSIH_INEG */ shader_glsl_unary_op, 10986 /* WINED3DSIH_ISHL */ shader_glsl_binop, 10987 /* WINED3DSIH_ISHR */ shader_glsl_binop, 10988 /* WINED3DSIH_ITOF */ shader_glsl_to_float, 10989 /* WINED3DSIH_LABEL */ shader_glsl_label, 10990 /* WINED3DSIH_LD */ shader_glsl_ld, 10991 /* WINED3DSIH_LD2DMS */ shader_glsl_ld, 10992 /* WINED3DSIH_LD_RAW */ shader_glsl_ld_raw_structured, 10993 /* WINED3DSIH_LD_STRUCTURED */ shader_glsl_ld_raw_structured, 10994 /* WINED3DSIH_LD_UAV_TYPED */ shader_glsl_ld_uav, 10995 /* WINED3DSIH_LIT */ shader_glsl_lit, 10996 /* WINED3DSIH_LOD */ NULL, 10997 /* WINED3DSIH_LOG */ shader_glsl_scalar_op, 10998 /* WINED3DSIH_LOGP */ shader_glsl_scalar_op, 10999 /* WINED3DSIH_LOOP */ shader_glsl_loop, 11000 /* WINED3DSIH_LRP */ shader_glsl_lrp, 11001 /* WINED3DSIH_LT */ shader_glsl_relop, 11002 /* WINED3DSIH_M3x2 */ shader_glsl_mnxn, 11003 /* WINED3DSIH_M3x3 */ shader_glsl_mnxn, 11004 /* WINED3DSIH_M3x4 */ shader_glsl_mnxn, 11005 /* WINED3DSIH_M4x3 */ shader_glsl_mnxn, 11006 /* WINED3DSIH_M4x4 */ shader_glsl_mnxn, 11007 /* WINED3DSIH_MAD */ shader_glsl_mad, 11008 /* WINED3DSIH_MAX */ shader_glsl_map2gl, 11009 /* WINED3DSIH_MIN */ shader_glsl_map2gl, 11010 /* WINED3DSIH_MOV */ shader_glsl_mov, 11011 /* WINED3DSIH_MOVA */ shader_glsl_mov, 11012 /* WINED3DSIH_MOVC */ shader_glsl_conditional_move, 11013 /* WINED3DSIH_MUL */ shader_glsl_binop, 11014 /* WINED3DSIH_NE */ shader_glsl_relop, 11015 /* WINED3DSIH_NOP */ shader_glsl_nop, 11016 /* WINED3DSIH_NOT */ shader_glsl_unary_op, 11017 /* WINED3DSIH_NRM */ shader_glsl_nrm, 11018 /* WINED3DSIH_OR */ shader_glsl_binop, 11019 /* WINED3DSIH_PHASE */ shader_glsl_nop, 11020 /* WINED3DSIH_POW */ shader_glsl_pow, 11021 /* WINED3DSIH_RCP */ shader_glsl_scalar_op, 11022 /* WINED3DSIH_REP */ shader_glsl_rep, 11023 /* WINED3DSIH_RESINFO */ shader_glsl_resinfo, 11024 /* WINED3DSIH_RET */ shader_glsl_ret, 11025 /* WINED3DSIH_RETP */ shader_glsl_conditional_op, 11026 /* WINED3DSIH_ROUND_NE */ shader_glsl_map2gl, 11027 /* WINED3DSIH_ROUND_NI */ shader_glsl_map2gl, 11028 /* WINED3DSIH_ROUND_PI */ shader_glsl_map2gl, 11029 /* WINED3DSIH_ROUND_Z */ shader_glsl_map2gl, 11030 /* WINED3DSIH_RSQ */ shader_glsl_scalar_op, 11031 /* WINED3DSIH_SAMPLE */ shader_glsl_sample, 11032 /* WINED3DSIH_SAMPLE_B */ shader_glsl_sample, 11033 /* WINED3DSIH_SAMPLE_C */ shader_glsl_sample_c, 11034 /* WINED3DSIH_SAMPLE_C_LZ */ shader_glsl_sample_c, 11035 /* WINED3DSIH_SAMPLE_GRAD */ shader_glsl_sample, 11036 /* WINED3DSIH_SAMPLE_INFO */ NULL, 11037 /* WINED3DSIH_SAMPLE_LOD */ shader_glsl_sample, 11038 /* WINED3DSIH_SAMPLE_POS */ NULL, 11039 /* WINED3DSIH_SETP */ NULL, 11040 /* WINED3DSIH_SGE */ shader_glsl_compare, 11041 /* WINED3DSIH_SGN */ shader_glsl_sgn, 11042 /* WINED3DSIH_SINCOS */ shader_glsl_sincos, 11043 /* WINED3DSIH_SLT */ shader_glsl_compare, 11044 /* WINED3DSIH_SQRT */ shader_glsl_map2gl, 11045 /* WINED3DSIH_STORE_RAW */ shader_glsl_store_raw_structured, 11046 /* WINED3DSIH_STORE_STRUCTURED */ shader_glsl_store_raw_structured, 11047 /* WINED3DSIH_STORE_UAV_TYPED */ shader_glsl_store_uav, 11048 /* WINED3DSIH_SUB */ shader_glsl_binop, 11049 /* WINED3DSIH_SWAPC */ shader_glsl_swapc, 11050 /* WINED3DSIH_SWITCH */ shader_glsl_switch, 11051 /* WINED3DSIH_SYNC */ shader_glsl_sync, 11052 /* WINED3DSIH_TEX */ shader_glsl_tex, 11053 /* WINED3DSIH_TEXBEM */ shader_glsl_texbem, 11054 /* WINED3DSIH_TEXBEML */ shader_glsl_texbem, 11055 /* WINED3DSIH_TEXCOORD */ shader_glsl_texcoord, 11056 /* WINED3DSIH_TEXDEPTH */ shader_glsl_texdepth, 11057 /* WINED3DSIH_TEXDP3 */ shader_glsl_texdp3, 11058 /* WINED3DSIH_TEXDP3TEX */ shader_glsl_texdp3tex, 11059 /* WINED3DSIH_TEXKILL */ shader_glsl_texkill, 11060 /* WINED3DSIH_TEXLDD */ shader_glsl_texldd, 11061 /* WINED3DSIH_TEXLDL */ shader_glsl_texldl, 11062 /* WINED3DSIH_TEXM3x2DEPTH */ shader_glsl_texm3x2depth, 11063 /* WINED3DSIH_TEXM3x2PAD */ shader_glsl_texm3x2pad, 11064 /* WINED3DSIH_TEXM3x2TEX */ shader_glsl_texm3x2tex, 11065 /* WINED3DSIH_TEXM3x3 */ shader_glsl_texm3x3, 11066 /* WINED3DSIH_TEXM3x3DIFF */ NULL, 11067 /* WINED3DSIH_TEXM3x3PAD */ shader_glsl_texm3x3pad, 11068 /* WINED3DSIH_TEXM3x3SPEC */ shader_glsl_texm3x3spec, 11069 /* WINED3DSIH_TEXM3x3TEX */ shader_glsl_texm3x3tex, 11070 /* WINED3DSIH_TEXM3x3VSPEC */ shader_glsl_texm3x3vspec, 11071 /* WINED3DSIH_TEXREG2AR */ shader_glsl_texreg2ar, 11072 /* WINED3DSIH_TEXREG2GB */ shader_glsl_texreg2gb, 11073 /* WINED3DSIH_TEXREG2RGB */ shader_glsl_texreg2rgb, 11074 /* WINED3DSIH_UBFE */ shader_glsl_bitwise_op, 11075 /* WINED3DSIH_UDIV */ shader_glsl_udiv, 11076 /* WINED3DSIH_UGE */ shader_glsl_relop, 11077 /* WINED3DSIH_ULT */ shader_glsl_relop, 11078 /* WINED3DSIH_UMAX */ shader_glsl_map2gl, 11079 /* WINED3DSIH_UMIN */ shader_glsl_map2gl, 11080 /* WINED3DSIH_UMUL */ shader_glsl_mul_extended, 11081 /* WINED3DSIH_USHR */ shader_glsl_binop, 11082 /* WINED3DSIH_UTOF */ shader_glsl_to_float, 11083 /* WINED3DSIH_XOR */ shader_glsl_binop, 11084 }; 11085 11086 static void shader_glsl_handle_instruction(const struct wined3d_shader_instruction *ins) { 11087 SHADER_HANDLER hw_fct; 11088 11089 /* Select handler */ 11090 hw_fct = shader_glsl_instruction_handler_table[ins->handler_idx]; 11091 11092 /* Unhandled opcode */ 11093 if (!hw_fct) 11094 { 11095 FIXME("Backend can't handle opcode %s.\n", debug_d3dshaderinstructionhandler(ins->handler_idx)); 11096 return; 11097 } 11098 hw_fct(ins); 11099 11100 shader_glsl_add_instruction_modifiers(ins); 11101 } 11102 11103 static BOOL shader_glsl_has_ffp_proj_control(void *shader_priv) 11104 { 11105 struct shader_glsl_priv *priv = shader_priv; 11106 11107 return priv->ffp_proj_control; 11108 } 11109 11110 const struct wined3d_shader_backend_ops glsl_shader_backend = 11111 { 11112 shader_glsl_handle_instruction, 11113 shader_glsl_precompile, 11114 shader_glsl_select, 11115 shader_glsl_select_compute, 11116 shader_glsl_disable, 11117 shader_glsl_update_float_vertex_constants, 11118 shader_glsl_update_float_pixel_constants, 11119 shader_glsl_load_constants, 11120 shader_glsl_destroy, 11121 shader_glsl_alloc, 11122 shader_glsl_free, 11123 shader_glsl_allocate_context_data, 11124 shader_glsl_free_context_data, 11125 shader_glsl_init_context_state, 11126 shader_glsl_get_caps, 11127 shader_glsl_color_fixup_supported, 11128 shader_glsl_has_ffp_proj_control, 11129 }; 11130 11131 static void glsl_vertex_pipe_vp_enable(const struct wined3d_gl_info *gl_info, BOOL enable) {} 11132 11133 static void glsl_vertex_pipe_vp_get_caps(const struct wined3d_gl_info *gl_info, struct wined3d_vertex_caps *caps) 11134 { 11135 caps->xyzrhw = TRUE; 11136 caps->emulated_flatshading = !needs_legacy_glsl_syntax(gl_info); 11137 caps->ffp_generic_attributes = TRUE; 11138 caps->max_active_lights = MAX_ACTIVE_LIGHTS; 11139 caps->max_vertex_blend_matrices = MAX_VERTEX_BLENDS; 11140 caps->max_vertex_blend_matrix_index = MAX_VERTEX_INDEX_BLENDS - 1; 11141 caps->vertex_processing_caps = WINED3DVTXPCAPS_TEXGEN 11142 | WINED3DVTXPCAPS_MATERIALSOURCE7 11143 | WINED3DVTXPCAPS_VERTEXFOG 11144 | WINED3DVTXPCAPS_DIRECTIONALLIGHTS 11145 | WINED3DVTXPCAPS_POSITIONALLIGHTS 11146 | WINED3DVTXPCAPS_LOCALVIEWER 11147 | WINED3DVTXPCAPS_TEXGEN_SPHEREMAP; 11148 caps->fvf_caps = WINED3DFVFCAPS_PSIZE | 8; /* 8 texture coordinates. */ 11149 caps->max_user_clip_planes = gl_info->limits.user_clip_distances; 11150 caps->raster_caps = WINED3DPRASTERCAPS_FOGRANGE; 11151 } 11152 11153 static DWORD glsl_vertex_pipe_vp_get_emul_mask(const struct wined3d_gl_info *gl_info) 11154 { 11155 if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]) 11156 return GL_EXT_EMUL_ARB_MULTITEXTURE; 11157 return 0; 11158 } 11159 11160 static void *glsl_vertex_pipe_vp_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv) 11161 { 11162 struct shader_glsl_priv *priv; 11163 11164 if (shader_backend == &glsl_shader_backend) 11165 { 11166 priv = shader_priv; 11167 wine_rb_init(&priv->ffp_vertex_shaders, wined3d_ffp_vertex_program_key_compare); 11168 return priv; 11169 } 11170 11171 FIXME("GLSL vertex pipe without GLSL shader backend not implemented.\n"); 11172 11173 return NULL; 11174 } 11175 11176 static void shader_glsl_free_ffp_vertex_shader(struct wine_rb_entry *entry, void *context) 11177 { 11178 struct glsl_ffp_vertex_shader *shader = WINE_RB_ENTRY_VALUE(entry, 11179 struct glsl_ffp_vertex_shader, desc.entry); 11180 struct glsl_shader_prog_link *program, *program2; 11181 struct glsl_ffp_destroy_ctx *ctx = context; 11182 11183 LIST_FOR_EACH_ENTRY_SAFE(program, program2, &shader->linked_programs, 11184 struct glsl_shader_prog_link, vs.shader_entry) 11185 { 11186 delete_glsl_program_entry(ctx->priv, ctx->gl_info, program); 11187 } 11188 ctx->gl_info->gl_ops.ext.p_glDeleteShader(shader->id); 11189 heap_free(shader); 11190 } 11191 11192 /* Context activation is done by the caller. */ 11193 static void glsl_vertex_pipe_vp_free(struct wined3d_device *device) 11194 { 11195 struct shader_glsl_priv *priv = device->vertex_priv; 11196 struct glsl_ffp_destroy_ctx ctx; 11197 11198 ctx.priv = priv; 11199 ctx.gl_info = &device->adapter->gl_info; 11200 wine_rb_destroy(&priv->ffp_vertex_shaders, shader_glsl_free_ffp_vertex_shader, &ctx); 11201 } 11202 11203 static void glsl_vertex_pipe_nop(struct wined3d_context *context, 11204 const struct wined3d_state *state, DWORD state_id) {} 11205 11206 static void glsl_vertex_pipe_shader(struct wined3d_context *context, 11207 const struct wined3d_state *state, DWORD state_id) 11208 { 11209 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX; 11210 } 11211 11212 static void glsl_vertex_pipe_vdecl(struct wined3d_context *context, 11213 const struct wined3d_state *state, DWORD state_id) 11214 { 11215 const struct wined3d_gl_info *gl_info = context->gl_info; 11216 BOOL normal = !!(context->stream_info.use_map & (1u << WINED3D_FFP_NORMAL)); 11217 const BOOL legacy_clip_planes = needs_legacy_glsl_syntax(gl_info); 11218 BOOL transformed = context->stream_info.position_transformed; 11219 BOOL wasrhw = context->last_was_rhw; 11220 unsigned int i; 11221 11222 context->last_was_rhw = transformed; 11223 11224 /* If the vertex declaration contains a transformed position attribute, 11225 * the draw uses the fixed function vertex pipeline regardless of any 11226 * vertex shader set by the application. */ 11227 if (transformed != wasrhw 11228 || context->stream_info.swizzle_map != context->last_swizzle_map) 11229 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX; 11230 11231 context->last_swizzle_map = context->stream_info.swizzle_map; 11232 11233 if (!use_vs(state)) 11234 { 11235 if (context->last_was_vshader) 11236 { 11237 if (legacy_clip_planes) 11238 for (i = 0; i < gl_info->limits.user_clip_distances; ++i) 11239 clipplane(context, state, STATE_CLIPPLANE(i)); 11240 else 11241 context->constant_update_mask |= WINED3D_SHADER_CONST_VS_CLIP_PLANES; 11242 } 11243 11244 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_TEXMATRIX; 11245 11246 /* Because of settings->texcoords, we have to regenerate the vertex 11247 * shader on a vdecl change if there aren't enough varyings to just 11248 * always output all the texture coordinates. */ 11249 if (gl_info->limits.glsl_varyings < wined3d_max_compat_varyings(gl_info) 11250 || normal != context->last_was_normal) 11251 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX; 11252 11253 if (use_ps(state) 11254 && state->shader[WINED3D_SHADER_TYPE_PIXEL]->reg_maps.shader_version.major == 1 11255 && state->shader[WINED3D_SHADER_TYPE_PIXEL]->reg_maps.shader_version.minor <= 3) 11256 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL; 11257 } 11258 else 11259 { 11260 if (!context->last_was_vshader) 11261 { 11262 /* Vertex shader clipping ignores the view matrix. Update all clip planes. */ 11263 if (legacy_clip_planes) 11264 for (i = 0; i < gl_info->limits.user_clip_distances; ++i) 11265 clipplane(context, state, STATE_CLIPPLANE(i)); 11266 else 11267 context->constant_update_mask |= WINED3D_SHADER_CONST_VS_CLIP_PLANES; 11268 } 11269 } 11270 11271 context->last_was_vshader = use_vs(state); 11272 context->last_was_normal = normal; 11273 } 11274 11275 static void glsl_vertex_pipe_vs(struct wined3d_context *context, 11276 const struct wined3d_state *state, DWORD state_id) 11277 { 11278 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX; 11279 /* Different vertex shaders potentially require a different vertex attributes setup. */ 11280 if (!isStateDirty(context, STATE_VDECL)) 11281 context_apply_state(context, state, STATE_VDECL); 11282 } 11283 11284 static void glsl_vertex_pipe_hs(struct wined3d_context *context, 11285 const struct wined3d_state *state, DWORD state_id) 11286 { 11287 /* In Direct3D tessellator options (e.g. output primitive type, primitive 11288 * winding) are defined in Hull Shaders, while in GLSL those are 11289 * specified in Tessellation Evaluation Shaders. */ 11290 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_DOMAIN; 11291 11292 if (state->shader[WINED3D_SHADER_TYPE_VERTEX]) 11293 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX; 11294 } 11295 11296 static void glsl_vertex_pipe_geometry_shader(struct wined3d_context *context, 11297 const struct wined3d_state *state, DWORD state_id) 11298 { 11299 struct glsl_context_data *ctx_data = context->shader_backend_data; 11300 BOOL rasterization_disabled; 11301 11302 rasterization_disabled = is_rasterization_disabled(state->shader[WINED3D_SHADER_TYPE_GEOMETRY]); 11303 if (ctx_data->rasterization_disabled != rasterization_disabled) 11304 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL; 11305 ctx_data->rasterization_disabled = rasterization_disabled; 11306 11307 if (state->shader[WINED3D_SHADER_TYPE_DOMAIN]) 11308 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_DOMAIN; 11309 else if (state->shader[WINED3D_SHADER_TYPE_VERTEX] 11310 && state->shader[WINED3D_SHADER_TYPE_VERTEX]->reg_maps.shader_version.major >= 4) 11311 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX; 11312 } 11313 11314 static void glsl_vertex_pipe_pixel_shader(struct wined3d_context *context, 11315 const struct wined3d_state *state, DWORD state_id) 11316 { 11317 if (state->shader[WINED3D_SHADER_TYPE_GEOMETRY]) 11318 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_GEOMETRY; 11319 else if (state->shader[WINED3D_SHADER_TYPE_DOMAIN]) 11320 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_DOMAIN; 11321 else if (state->shader[WINED3D_SHADER_TYPE_VERTEX] 11322 && state->shader[WINED3D_SHADER_TYPE_VERTEX]->reg_maps.shader_version.major >= 4) 11323 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX; 11324 } 11325 11326 static void glsl_vertex_pipe_world(struct wined3d_context *context, 11327 const struct wined3d_state *state, DWORD state_id) 11328 { 11329 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_MODELVIEW; 11330 } 11331 11332 static void glsl_vertex_pipe_vertexblend(struct wined3d_context *context, 11333 const struct wined3d_state *state, DWORD state_id) 11334 { 11335 int i = state_id - STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)); 11336 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_VERTEXBLEND_INDEX(i); 11337 } 11338 11339 static void glsl_vertex_pipe_view(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) 11340 { 11341 const struct wined3d_gl_info *gl_info = context->gl_info; 11342 unsigned int k; 11343 11344 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_MODELVIEW 11345 | WINED3D_SHADER_CONST_FFP_LIGHTS 11346 | WINED3D_SHADER_CONST_FFP_VERTEXBLEND; 11347 11348 if (needs_legacy_glsl_syntax(gl_info)) 11349 { 11350 for (k = 0; k < gl_info->limits.user_clip_distances; ++k) 11351 { 11352 if (!isStateDirty(context, STATE_CLIPPLANE(k))) 11353 clipplane(context, state, STATE_CLIPPLANE(k)); 11354 } 11355 } 11356 else 11357 { 11358 context->constant_update_mask |= WINED3D_SHADER_CONST_VS_CLIP_PLANES; 11359 } 11360 } 11361 11362 static void glsl_vertex_pipe_projection(struct wined3d_context *context, 11363 const struct wined3d_state *state, DWORD state_id) 11364 { 11365 /* Table fog behavior depends on the projection matrix. */ 11366 if (state->render_states[WINED3D_RS_FOGENABLE] 11367 && state->render_states[WINED3D_RS_FOGTABLEMODE] != WINED3D_FOG_NONE) 11368 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX; 11369 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_PROJ; 11370 } 11371 11372 static void glsl_vertex_pipe_viewport(struct wined3d_context *context, 11373 const struct wined3d_state *state, DWORD state_id) 11374 { 11375 if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION))) 11376 glsl_vertex_pipe_projection(context, state, STATE_TRANSFORM(WINED3D_TS_PROJECTION)); 11377 if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_POINTSCALEENABLE)) 11378 && state->render_states[WINED3D_RS_POINTSCALEENABLE]) 11379 context->constant_update_mask |= WINED3D_SHADER_CONST_VS_POINTSIZE; 11380 context->constant_update_mask |= WINED3D_SHADER_CONST_POS_FIXUP; 11381 } 11382 11383 static void glsl_vertex_pipe_texmatrix(struct wined3d_context *context, 11384 const struct wined3d_state *state, DWORD state_id) 11385 { 11386 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_TEXMATRIX; 11387 } 11388 11389 static void glsl_vertex_pipe_texmatrix_np2(struct wined3d_context *context, 11390 const struct wined3d_state *state, DWORD state_id) 11391 { 11392 DWORD sampler = state_id - STATE_SAMPLER(0); 11393 const struct wined3d_texture *texture = state->textures[sampler]; 11394 BOOL np2; 11395 11396 if (!texture) 11397 return; 11398 11399 if (sampler >= MAX_TEXTURES) 11400 return; 11401 11402 if ((np2 = !(texture->flags & WINED3D_TEXTURE_POW2_MAT_IDENT)) 11403 || context->lastWasPow2Texture & (1u << sampler)) 11404 { 11405 if (np2) 11406 context->lastWasPow2Texture |= 1u << sampler; 11407 else 11408 context->lastWasPow2Texture &= ~(1u << sampler); 11409 11410 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_TEXMATRIX; 11411 } 11412 } 11413 11414 static void glsl_vertex_pipe_material(struct wined3d_context *context, 11415 const struct wined3d_state *state, DWORD state_id) 11416 { 11417 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_MATERIAL; 11418 } 11419 11420 static void glsl_vertex_pipe_light(struct wined3d_context *context, 11421 const struct wined3d_state *state, DWORD state_id) 11422 { 11423 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_LIGHTS; 11424 } 11425 11426 static void glsl_vertex_pipe_pointsize(struct wined3d_context *context, 11427 const struct wined3d_state *state, DWORD state_id) 11428 { 11429 context->constant_update_mask |= WINED3D_SHADER_CONST_VS_POINTSIZE; 11430 } 11431 11432 static void glsl_vertex_pipe_pointscale(struct wined3d_context *context, 11433 const struct wined3d_state *state, DWORD state_id) 11434 { 11435 if (!use_vs(state)) 11436 context->constant_update_mask |= WINED3D_SHADER_CONST_VS_POINTSIZE; 11437 } 11438 11439 static void glsl_vertex_pointsprite_core(struct wined3d_context *context, 11440 const struct wined3d_state *state, DWORD state_id) 11441 { 11442 static unsigned int once; 11443 11444 if (state->gl_primitive_type == GL_POINTS && !state->render_states[WINED3D_RS_POINTSPRITEENABLE] && !once++) 11445 FIXME("Non-point sprite points not supported in core profile.\n"); 11446 } 11447 11448 static void glsl_vertex_pipe_shademode(struct wined3d_context *context, 11449 const struct wined3d_state *state, DWORD state_id) 11450 { 11451 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX; 11452 } 11453 11454 static void glsl_vertex_pipe_clip_plane(struct wined3d_context *context, 11455 const struct wined3d_state *state, DWORD state_id) 11456 { 11457 const struct wined3d_gl_info *gl_info = context->gl_info; 11458 UINT index = state_id - STATE_CLIPPLANE(0); 11459 11460 if (index >= gl_info->limits.user_clip_distances) 11461 return; 11462 11463 context->constant_update_mask |= WINED3D_SHADER_CONST_VS_CLIP_PLANES; 11464 } 11465 11466 static const struct StateEntryTemplate glsl_vertex_pipe_vp_states[] = 11467 { 11468 {STATE_VDECL, {STATE_VDECL, glsl_vertex_pipe_vdecl }, WINED3D_GL_EXT_NONE }, 11469 {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), glsl_vertex_pipe_vs }, WINED3D_GL_EXT_NONE }, 11470 {STATE_SHADER(WINED3D_SHADER_TYPE_HULL), {STATE_SHADER(WINED3D_SHADER_TYPE_HULL), glsl_vertex_pipe_hs }, WINED3D_GL_EXT_NONE }, 11471 {STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY), {STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY), glsl_vertex_pipe_geometry_shader}, WINED3D_GL_EXT_NONE }, 11472 {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), glsl_vertex_pipe_pixel_shader}, WINED3D_GL_EXT_NONE }, 11473 {STATE_MATERIAL, {STATE_RENDER(WINED3D_RS_SPECULARENABLE), NULL }, WINED3D_GL_EXT_NONE }, 11474 {STATE_RENDER(WINED3D_RS_SPECULARENABLE), {STATE_RENDER(WINED3D_RS_SPECULARENABLE), glsl_vertex_pipe_material}, WINED3D_GL_EXT_NONE }, 11475 /* Clip planes */ 11476 {STATE_CLIPPLANE(0), {STATE_CLIPPLANE(0), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 }, 11477 {STATE_CLIPPLANE(0), {STATE_CLIPPLANE(0), clipplane }, WINED3D_GL_EXT_NONE }, 11478 {STATE_CLIPPLANE(1), {STATE_CLIPPLANE(1), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 }, 11479 {STATE_CLIPPLANE(1), {STATE_CLIPPLANE(1), clipplane }, WINED3D_GL_EXT_NONE }, 11480 {STATE_CLIPPLANE(2), {STATE_CLIPPLANE(2), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 }, 11481 {STATE_CLIPPLANE(2), {STATE_CLIPPLANE(2), clipplane }, WINED3D_GL_EXT_NONE }, 11482 {STATE_CLIPPLANE(3), {STATE_CLIPPLANE(3), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 }, 11483 {STATE_CLIPPLANE(3), {STATE_CLIPPLANE(3), clipplane }, WINED3D_GL_EXT_NONE }, 11484 {STATE_CLIPPLANE(4), {STATE_CLIPPLANE(4), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 }, 11485 {STATE_CLIPPLANE(4), {STATE_CLIPPLANE(4), clipplane }, WINED3D_GL_EXT_NONE }, 11486 {STATE_CLIPPLANE(5), {STATE_CLIPPLANE(5), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 }, 11487 {STATE_CLIPPLANE(5), {STATE_CLIPPLANE(5), clipplane }, WINED3D_GL_EXT_NONE }, 11488 {STATE_CLIPPLANE(6), {STATE_CLIPPLANE(6), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 }, 11489 {STATE_CLIPPLANE(6), {STATE_CLIPPLANE(6), clipplane }, WINED3D_GL_EXT_NONE }, 11490 {STATE_CLIPPLANE(7), {STATE_CLIPPLANE(7), glsl_vertex_pipe_clip_plane}, WINED3D_GLSL_130 }, 11491 {STATE_CLIPPLANE(7), {STATE_CLIPPLANE(7), clipplane }, WINED3D_GL_EXT_NONE }, 11492 /* Lights */ 11493 {STATE_LIGHT_TYPE, {STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, 11494 {STATE_ACTIVELIGHT(0), {STATE_ACTIVELIGHT(0), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, 11495 {STATE_ACTIVELIGHT(1), {STATE_ACTIVELIGHT(1), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, 11496 {STATE_ACTIVELIGHT(2), {STATE_ACTIVELIGHT(2), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, 11497 {STATE_ACTIVELIGHT(3), {STATE_ACTIVELIGHT(3), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, 11498 {STATE_ACTIVELIGHT(4), {STATE_ACTIVELIGHT(4), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, 11499 {STATE_ACTIVELIGHT(5), {STATE_ACTIVELIGHT(5), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, 11500 {STATE_ACTIVELIGHT(6), {STATE_ACTIVELIGHT(6), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, 11501 {STATE_ACTIVELIGHT(7), {STATE_ACTIVELIGHT(7), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, 11502 /* Viewport */ 11503 {STATE_VIEWPORT, {STATE_VIEWPORT, glsl_vertex_pipe_viewport}, WINED3D_GL_EXT_NONE }, 11504 /* Transform states */ 11505 {STATE_TRANSFORM(WINED3D_TS_VIEW), {STATE_TRANSFORM(WINED3D_TS_VIEW), glsl_vertex_pipe_view }, WINED3D_GL_EXT_NONE }, 11506 {STATE_TRANSFORM(WINED3D_TS_PROJECTION), {STATE_TRANSFORM(WINED3D_TS_PROJECTION), glsl_vertex_pipe_projection}, WINED3D_GL_EXT_NONE }, 11507 {STATE_TRANSFORM(WINED3D_TS_TEXTURE0), {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, 11508 {STATE_TRANSFORM(WINED3D_TS_TEXTURE1), {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, 11509 {STATE_TRANSFORM(WINED3D_TS_TEXTURE2), {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, 11510 {STATE_TRANSFORM(WINED3D_TS_TEXTURE3), {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, 11511 {STATE_TRANSFORM(WINED3D_TS_TEXTURE4), {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, 11512 {STATE_TRANSFORM(WINED3D_TS_TEXTURE5), {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, 11513 {STATE_TRANSFORM(WINED3D_TS_TEXTURE6), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, 11514 {STATE_TRANSFORM(WINED3D_TS_TEXTURE7), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL }, WINED3D_GL_EXT_NONE }, 11515 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)), glsl_vertex_pipe_world }, WINED3D_GL_EXT_NONE }, 11516 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(1)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(1)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, 11517 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(2)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(2)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, 11518 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(3)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(3)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, 11519 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(4)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(4)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, 11520 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(5)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(5)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, 11521 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(6)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(6)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, 11522 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(7)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(7)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, 11523 {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(8)), {STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(8)), glsl_vertex_pipe_vertexblend }, WINED3D_GL_EXT_NONE }, 11524 {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE }, 11525 {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE }, 11526 {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE }, 11527 {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE }, 11528 {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE }, 11529 {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE }, 11530 {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE }, 11531 {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_vertex_pipe_texmatrix}, WINED3D_GL_EXT_NONE }, 11532 {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11533 {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11534 {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11535 {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11536 {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11537 {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11538 {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11539 {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXCOORD_INDEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11540 /* Fog */ 11541 {STATE_RENDER(WINED3D_RS_FOGENABLE), {STATE_RENDER(WINED3D_RS_FOGENABLE), glsl_vertex_pipe_shader}, WINED3D_GL_EXT_NONE }, 11542 {STATE_RENDER(WINED3D_RS_FOGTABLEMODE), {STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, 11543 {STATE_RENDER(WINED3D_RS_FOGVERTEXMODE), {STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, 11544 {STATE_RENDER(WINED3D_RS_RANGEFOGENABLE), {STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, 11545 {STATE_RENDER(WINED3D_RS_CLIPPING), {STATE_RENDER(WINED3D_RS_CLIPPING), state_clipping }, WINED3D_GL_EXT_NONE }, 11546 {STATE_RENDER(WINED3D_RS_CLIPPLANEENABLE), {STATE_RENDER(WINED3D_RS_CLIPPING), NULL }, WINED3D_GL_EXT_NONE }, 11547 {STATE_RENDER(WINED3D_RS_LIGHTING), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11548 {STATE_RENDER(WINED3D_RS_AMBIENT), {STATE_RENDER(WINED3D_RS_AMBIENT), glsl_vertex_pipe_light }, WINED3D_GL_EXT_NONE }, 11549 {STATE_RENDER(WINED3D_RS_COLORVERTEX), {STATE_RENDER(WINED3D_RS_COLORVERTEX), glsl_vertex_pipe_shader}, WINED3D_GL_EXT_NONE }, 11550 {STATE_RENDER(WINED3D_RS_LOCALVIEWER), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11551 {STATE_RENDER(WINED3D_RS_NORMALIZENORMALS), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11552 {STATE_RENDER(WINED3D_RS_DIFFUSEMATERIALSOURCE), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11553 {STATE_RENDER(WINED3D_RS_SPECULARMATERIALSOURCE), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11554 {STATE_RENDER(WINED3D_RS_AMBIENTMATERIALSOURCE), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11555 {STATE_RENDER(WINED3D_RS_EMISSIVEMATERIALSOURCE), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11556 {STATE_RENDER(WINED3D_RS_VERTEXBLEND), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11557 {STATE_RENDER(WINED3D_RS_POINTSIZE), {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), NULL }, WINED3D_GL_EXT_NONE }, 11558 {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), glsl_vertex_pipe_pointsize}, WINED3D_GL_EXT_NONE }, 11559 {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), state_pointsprite }, ARB_POINT_SPRITE }, 11560 {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), state_pointsprite_w }, WINED3D_GL_LEGACY_CONTEXT }, 11561 {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), glsl_vertex_pointsprite_core}, WINED3D_GL_EXT_NONE }, 11562 {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), glsl_vertex_pipe_pointscale}, WINED3D_GL_EXT_NONE }, 11563 {STATE_RENDER(WINED3D_RS_POINTSCALE_A), {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE }, 11564 {STATE_RENDER(WINED3D_RS_POINTSCALE_B), {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE }, 11565 {STATE_RENDER(WINED3D_RS_POINTSCALE_C), {STATE_RENDER(WINED3D_RS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE }, 11566 {STATE_RENDER(WINED3D_RS_POINTSIZE_MAX), {STATE_RENDER(WINED3D_RS_POINTSIZE_MIN), NULL }, WINED3D_GL_EXT_NONE }, 11567 {STATE_RENDER(WINED3D_RS_TWEENFACTOR), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11568 {STATE_RENDER(WINED3D_RS_INDEXEDVERTEXBLENDENABLE), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), NULL }, WINED3D_GL_EXT_NONE }, 11569 /* NP2 texture matrix fixups. They are not needed if 11570 * GL_ARB_texture_non_power_of_two is supported. Otherwise, register 11571 * glsl_vertex_pipe_texmatrix(), which takes care of updating the texture 11572 * matrix. */ 11573 {STATE_SAMPLER(0), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, 11574 {STATE_SAMPLER(0), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, 11575 {STATE_SAMPLER(0), {STATE_SAMPLER(0), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE }, 11576 {STATE_SAMPLER(1), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, 11577 {STATE_SAMPLER(1), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, 11578 {STATE_SAMPLER(1), {STATE_SAMPLER(1), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE }, 11579 {STATE_SAMPLER(2), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, 11580 {STATE_SAMPLER(2), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, 11581 {STATE_SAMPLER(2), {STATE_SAMPLER(2), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE }, 11582 {STATE_SAMPLER(3), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, 11583 {STATE_SAMPLER(3), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, 11584 {STATE_SAMPLER(3), {STATE_SAMPLER(3), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE }, 11585 {STATE_SAMPLER(4), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, 11586 {STATE_SAMPLER(4), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, 11587 {STATE_SAMPLER(4), {STATE_SAMPLER(4), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE }, 11588 {STATE_SAMPLER(5), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, 11589 {STATE_SAMPLER(5), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, 11590 {STATE_SAMPLER(5), {STATE_SAMPLER(5), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE }, 11591 {STATE_SAMPLER(6), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, 11592 {STATE_SAMPLER(6), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, 11593 {STATE_SAMPLER(6), {STATE_SAMPLER(6), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE }, 11594 {STATE_SAMPLER(7), {0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, 11595 {STATE_SAMPLER(7), {0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT}, 11596 {STATE_SAMPLER(7), {STATE_SAMPLER(7), glsl_vertex_pipe_texmatrix_np2}, WINED3D_GL_EXT_NONE }, 11597 {STATE_POINT_ENABLE, {STATE_POINT_ENABLE, glsl_vertex_pipe_shader}, WINED3D_GL_EXT_NONE }, 11598 {STATE_RENDER(WINED3D_RS_SHADEMODE), {STATE_RENDER(WINED3D_RS_SHADEMODE), glsl_vertex_pipe_shademode}, WINED3D_GLSL_130 }, 11599 {STATE_RENDER(WINED3D_RS_SHADEMODE), {STATE_RENDER(WINED3D_RS_SHADEMODE), glsl_vertex_pipe_nop }, WINED3D_GL_EXT_NONE }, 11600 {0 /* Terminate */, {0, NULL }, WINED3D_GL_EXT_NONE }, 11601 }; 11602 11603 /* TODO: 11604 * - Implement vertex tweening. */ 11605 const struct wined3d_vertex_pipe_ops glsl_vertex_pipe = 11606 { 11607 glsl_vertex_pipe_vp_enable, 11608 glsl_vertex_pipe_vp_get_caps, 11609 glsl_vertex_pipe_vp_get_emul_mask, 11610 glsl_vertex_pipe_vp_alloc, 11611 glsl_vertex_pipe_vp_free, 11612 glsl_vertex_pipe_vp_states, 11613 }; 11614 11615 static void glsl_fragment_pipe_enable(const struct wined3d_gl_info *gl_info, BOOL enable) 11616 { 11617 /* Nothing to do. */ 11618 } 11619 11620 static void glsl_fragment_pipe_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps) 11621 { 11622 caps->wined3d_caps = WINED3D_FRAGMENT_CAP_PROJ_CONTROL 11623 | WINED3D_FRAGMENT_CAP_SRGB_WRITE 11624 | WINED3D_FRAGMENT_CAP_COLOR_KEY; 11625 caps->PrimitiveMiscCaps = WINED3DPMISCCAPS_TSSARGTEMP 11626 | WINED3DPMISCCAPS_PERSTAGECONSTANT; 11627 caps->TextureOpCaps = WINED3DTEXOPCAPS_DISABLE 11628 | WINED3DTEXOPCAPS_SELECTARG1 11629 | WINED3DTEXOPCAPS_SELECTARG2 11630 | WINED3DTEXOPCAPS_MODULATE4X 11631 | WINED3DTEXOPCAPS_MODULATE2X 11632 | WINED3DTEXOPCAPS_MODULATE 11633 | WINED3DTEXOPCAPS_ADDSIGNED2X 11634 | WINED3DTEXOPCAPS_ADDSIGNED 11635 | WINED3DTEXOPCAPS_ADD 11636 | WINED3DTEXOPCAPS_SUBTRACT 11637 | WINED3DTEXOPCAPS_ADDSMOOTH 11638 | WINED3DTEXOPCAPS_BLENDCURRENTALPHA 11639 | WINED3DTEXOPCAPS_BLENDFACTORALPHA 11640 | WINED3DTEXOPCAPS_BLENDTEXTUREALPHA 11641 | WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA 11642 | WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM 11643 | WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR 11644 | WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA 11645 | WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA 11646 | WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR 11647 | WINED3DTEXOPCAPS_DOTPRODUCT3 11648 | WINED3DTEXOPCAPS_MULTIPLYADD 11649 | WINED3DTEXOPCAPS_LERP 11650 | WINED3DTEXOPCAPS_BUMPENVMAP 11651 | WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE; 11652 caps->MaxTextureBlendStages = MAX_TEXTURES; 11653 caps->MaxSimultaneousTextures = min(gl_info->limits.samplers[WINED3D_SHADER_TYPE_PIXEL], MAX_TEXTURES); 11654 } 11655 11656 static DWORD glsl_fragment_pipe_get_emul_mask(const struct wined3d_gl_info *gl_info) 11657 { 11658 if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]) 11659 return GL_EXT_EMUL_ARB_MULTITEXTURE; 11660 return 0; 11661 } 11662 11663 static void *glsl_fragment_pipe_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv) 11664 { 11665 struct shader_glsl_priv *priv; 11666 11667 if (shader_backend == &glsl_shader_backend) 11668 { 11669 priv = shader_priv; 11670 wine_rb_init(&priv->ffp_fragment_shaders, wined3d_ffp_frag_program_key_compare); 11671 return priv; 11672 } 11673 11674 FIXME("GLSL fragment pipe without GLSL shader backend not implemented.\n"); 11675 11676 return NULL; 11677 } 11678 11679 static void shader_glsl_free_ffp_fragment_shader(struct wine_rb_entry *entry, void *context) 11680 { 11681 struct glsl_ffp_fragment_shader *shader = WINE_RB_ENTRY_VALUE(entry, 11682 struct glsl_ffp_fragment_shader, entry.entry); 11683 struct glsl_shader_prog_link *program, *program2; 11684 struct glsl_ffp_destroy_ctx *ctx = context; 11685 11686 LIST_FOR_EACH_ENTRY_SAFE(program, program2, &shader->linked_programs, 11687 struct glsl_shader_prog_link, ps.shader_entry) 11688 { 11689 delete_glsl_program_entry(ctx->priv, ctx->gl_info, program); 11690 } 11691 ctx->gl_info->gl_ops.ext.p_glDeleteShader(shader->id); 11692 heap_free(shader); 11693 } 11694 11695 /* Context activation is done by the caller. */ 11696 static void glsl_fragment_pipe_free(struct wined3d_device *device) 11697 { 11698 struct shader_glsl_priv *priv = device->fragment_priv; 11699 struct glsl_ffp_destroy_ctx ctx; 11700 11701 ctx.priv = priv; 11702 ctx.gl_info = &device->adapter->gl_info; 11703 wine_rb_destroy(&priv->ffp_fragment_shaders, shader_glsl_free_ffp_fragment_shader, &ctx); 11704 } 11705 11706 static void glsl_fragment_pipe_shader(struct wined3d_context *context, 11707 const struct wined3d_state *state, DWORD state_id) 11708 { 11709 context->last_was_pshader = use_ps(state); 11710 11711 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL; 11712 } 11713 11714 static void glsl_fragment_pipe_fogparams(struct wined3d_context *context, 11715 const struct wined3d_state *state, DWORD state_id) 11716 { 11717 context->constant_update_mask |= WINED3D_SHADER_CONST_PS_FOG; 11718 } 11719 11720 static void glsl_fragment_pipe_fog(struct wined3d_context *context, 11721 const struct wined3d_state *state, DWORD state_id) 11722 { 11723 BOOL use_vshader = use_vs(state); 11724 enum fogsource new_source; 11725 DWORD fogstart = state->render_states[WINED3D_RS_FOGSTART]; 11726 DWORD fogend = state->render_states[WINED3D_RS_FOGEND]; 11727 11728 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL; 11729 11730 if (!state->render_states[WINED3D_RS_FOGENABLE]) 11731 return; 11732 11733 if (state->render_states[WINED3D_RS_FOGTABLEMODE] == WINED3D_FOG_NONE) 11734 { 11735 if (use_vshader) 11736 new_source = FOGSOURCE_VS; 11737 else if (state->render_states[WINED3D_RS_FOGVERTEXMODE] == WINED3D_FOG_NONE || context->stream_info.position_transformed) 11738 new_source = FOGSOURCE_COORD; 11739 else 11740 new_source = FOGSOURCE_FFP; 11741 } 11742 else 11743 { 11744 new_source = FOGSOURCE_FFP; 11745 } 11746 11747 if (new_source != context->fog_source || fogstart == fogend) 11748 { 11749 context->fog_source = new_source; 11750 context->constant_update_mask |= WINED3D_SHADER_CONST_PS_FOG; 11751 } 11752 } 11753 11754 static void glsl_fragment_pipe_vdecl(struct wined3d_context *context, 11755 const struct wined3d_state *state, DWORD state_id) 11756 { 11757 /* Because of settings->texcoords_initialized and args->texcoords_initialized. */ 11758 if (context->gl_info->limits.glsl_varyings < wined3d_max_compat_varyings(context->gl_info)) 11759 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL; 11760 11761 if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_FOGENABLE))) 11762 glsl_fragment_pipe_fog(context, state, state_id); 11763 } 11764 11765 static void glsl_fragment_pipe_vs(struct wined3d_context *context, 11766 const struct wined3d_state *state, DWORD state_id) 11767 { 11768 /* Because of settings->texcoords_initialized and args->texcoords_initialized. */ 11769 if (context->gl_info->limits.glsl_varyings < wined3d_max_compat_varyings(context->gl_info)) 11770 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL; 11771 } 11772 11773 static void glsl_fragment_pipe_tex_transform(struct wined3d_context *context, 11774 const struct wined3d_state *state, DWORD state_id) 11775 { 11776 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL; 11777 } 11778 11779 static void glsl_fragment_pipe_invalidate_constants(struct wined3d_context *context, 11780 const struct wined3d_state *state, DWORD state_id) 11781 { 11782 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_PS; 11783 } 11784 11785 static void glsl_fragment_pipe_alpha_test_func(struct wined3d_context *context, 11786 const struct wined3d_state *state, DWORD state_id) 11787 { 11788 const struct wined3d_gl_info *gl_info = context->gl_info; 11789 GLint func = wined3d_gl_compare_func(state->render_states[WINED3D_RS_ALPHAFUNC]); 11790 float ref = state->render_states[WINED3D_RS_ALPHAREF] / 255.0f; 11791 11792 if (func) 11793 { 11794 gl_info->gl_ops.gl.p_glAlphaFunc(func, ref); 11795 checkGLcall("glAlphaFunc"); 11796 } 11797 } 11798 11799 static void glsl_fragment_pipe_core_alpha_test(struct wined3d_context *context, 11800 const struct wined3d_state *state, DWORD state_id) 11801 { 11802 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL; 11803 } 11804 11805 static void glsl_fragment_pipe_alpha_test(struct wined3d_context *context, 11806 const struct wined3d_state *state, DWORD state_id) 11807 { 11808 const struct wined3d_gl_info *gl_info = context->gl_info; 11809 11810 if (state->render_states[WINED3D_RS_ALPHATESTENABLE]) 11811 { 11812 gl_info->gl_ops.gl.p_glEnable(GL_ALPHA_TEST); 11813 checkGLcall("glEnable(GL_ALPHA_TEST)"); 11814 } 11815 else 11816 { 11817 gl_info->gl_ops.gl.p_glDisable(GL_ALPHA_TEST); 11818 checkGLcall("glDisable(GL_ALPHA_TEST)"); 11819 } 11820 } 11821 11822 static void glsl_fragment_pipe_core_alpha_test_ref(struct wined3d_context *context, 11823 const struct wined3d_state *state, DWORD state_id) 11824 { 11825 context->constant_update_mask |= WINED3D_SHADER_CONST_PS_ALPHA_TEST; 11826 } 11827 11828 static void glsl_fragment_pipe_color_key(struct wined3d_context *context, 11829 const struct wined3d_state *state, DWORD state_id) 11830 { 11831 context->constant_update_mask |= WINED3D_SHADER_CONST_FFP_COLOR_KEY; 11832 } 11833 11834 static void glsl_fragment_pipe_shademode(struct wined3d_context *context, 11835 const struct wined3d_state *state, DWORD state_id) 11836 { 11837 context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL; 11838 } 11839 11840 static const struct StateEntryTemplate glsl_fragment_pipe_state_template[] = 11841 { 11842 {STATE_VDECL, {STATE_VDECL, glsl_fragment_pipe_vdecl }, WINED3D_GL_EXT_NONE }, 11843 {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), glsl_fragment_pipe_vs }, WINED3D_GL_EXT_NONE }, 11844 {STATE_RENDER(WINED3D_RS_TEXTUREFACTOR), {STATE_RENDER(WINED3D_RS_TEXTUREFACTOR), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE }, 11845 {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11846 {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11847 {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11848 {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11849 {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11850 {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11851 {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11852 {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11853 {STATE_TEXTURESTAGE(0, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11854 {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11855 {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11856 {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11857 {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11858 {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11859 {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11860 {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11861 {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11862 {STATE_TEXTURESTAGE(1, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11863 {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11864 {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11865 {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11866 {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11867 {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11868 {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11869 {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11870 {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11871 {STATE_TEXTURESTAGE(2, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11872 {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11873 {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11874 {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11875 {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11876 {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11877 {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11878 {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11879 {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11880 {STATE_TEXTURESTAGE(3, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11881 {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11882 {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11883 {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11884 {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11885 {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11886 {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11887 {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11888 {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11889 {STATE_TEXTURESTAGE(4, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11890 {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11891 {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11892 {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11893 {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11894 {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11895 {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11896 {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11897 {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11898 {STATE_TEXTURESTAGE(5, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11899 {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11900 {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11901 {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11902 {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11903 {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11904 {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11905 {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11906 {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11907 {STATE_TEXTURESTAGE(6, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11908 {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11909 {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11910 {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11911 {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11912 {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11913 {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG1), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11914 {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG2), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11915 {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG0), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11916 {STATE_TEXTURESTAGE(7, WINED3D_TSS_RESULT_ARG), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11917 {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), glsl_fragment_pipe_shader }, WINED3D_GL_EXT_NONE }, 11918 {STATE_RENDER(WINED3D_RS_ALPHAFUNC), {STATE_RENDER(WINED3D_RS_ALPHAFUNC), glsl_fragment_pipe_alpha_test_func }, WINED3D_GL_LEGACY_CONTEXT}, 11919 {STATE_RENDER(WINED3D_RS_ALPHAFUNC), {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), NULL }, WINED3D_GL_EXT_NONE }, 11920 {STATE_RENDER(WINED3D_RS_ALPHAREF), {STATE_RENDER(WINED3D_RS_ALPHAFUNC), NULL }, WINED3D_GL_LEGACY_CONTEXT}, 11921 {STATE_RENDER(WINED3D_RS_ALPHAREF), {STATE_RENDER(WINED3D_RS_ALPHAREF), glsl_fragment_pipe_core_alpha_test_ref }, WINED3D_GL_EXT_NONE }, 11922 {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), glsl_fragment_pipe_alpha_test }, WINED3D_GL_LEGACY_CONTEXT}, 11923 {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), {STATE_RENDER(WINED3D_RS_ALPHATESTENABLE), glsl_fragment_pipe_core_alpha_test }, WINED3D_GL_EXT_NONE }, 11924 {STATE_RENDER(WINED3D_RS_COLORKEYENABLE), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11925 {STATE_COLOR_KEY, { STATE_COLOR_KEY, glsl_fragment_pipe_color_key }, WINED3D_GL_EXT_NONE }, 11926 {STATE_RENDER(WINED3D_RS_FOGENABLE), {STATE_RENDER(WINED3D_RS_FOGENABLE), glsl_fragment_pipe_fog }, WINED3D_GL_EXT_NONE }, 11927 {STATE_RENDER(WINED3D_RS_FOGTABLEMODE), {STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, 11928 {STATE_RENDER(WINED3D_RS_FOGVERTEXMODE), {STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, 11929 {STATE_RENDER(WINED3D_RS_FOGSTART), {STATE_RENDER(WINED3D_RS_FOGSTART), glsl_fragment_pipe_fogparams }, WINED3D_GL_EXT_NONE }, 11930 {STATE_RENDER(WINED3D_RS_FOGEND), {STATE_RENDER(WINED3D_RS_FOGSTART), NULL }, WINED3D_GL_EXT_NONE }, 11931 {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE), {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE), state_srgbwrite }, ARB_FRAMEBUFFER_SRGB}, 11932 {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), NULL }, WINED3D_GL_EXT_NONE }, 11933 {STATE_RENDER(WINED3D_RS_FOGCOLOR), {STATE_RENDER(WINED3D_RS_FOGCOLOR), glsl_fragment_pipe_fogparams }, WINED3D_GL_EXT_NONE }, 11934 {STATE_RENDER(WINED3D_RS_FOGDENSITY), {STATE_RENDER(WINED3D_RS_FOGDENSITY), glsl_fragment_pipe_fogparams }, WINED3D_GL_EXT_NONE }, 11935 {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), glsl_fragment_pipe_shader }, ARB_POINT_SPRITE }, 11936 {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), {STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE), glsl_fragment_pipe_shader }, WINED3D_GL_VERSION_2_0}, 11937 {STATE_TEXTURESTAGE(0,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform }, WINED3D_GL_EXT_NONE }, 11938 {STATE_TEXTURESTAGE(1,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform }, WINED3D_GL_EXT_NONE }, 11939 {STATE_TEXTURESTAGE(2,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform }, WINED3D_GL_EXT_NONE }, 11940 {STATE_TEXTURESTAGE(3,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform }, WINED3D_GL_EXT_NONE }, 11941 {STATE_TEXTURESTAGE(4,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform }, WINED3D_GL_EXT_NONE }, 11942 {STATE_TEXTURESTAGE(5,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform }, WINED3D_GL_EXT_NONE }, 11943 {STATE_TEXTURESTAGE(6,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform }, WINED3D_GL_EXT_NONE }, 11944 {STATE_TEXTURESTAGE(7,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform }, WINED3D_GL_EXT_NONE }, 11945 {STATE_TEXTURESTAGE(0, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(0, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE }, 11946 {STATE_TEXTURESTAGE(1, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(1, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE }, 11947 {STATE_TEXTURESTAGE(2, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(2, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE }, 11948 {STATE_TEXTURESTAGE(3, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(3, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE }, 11949 {STATE_TEXTURESTAGE(4, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(4, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE }, 11950 {STATE_TEXTURESTAGE(5, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(5, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE }, 11951 {STATE_TEXTURESTAGE(6, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(6, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE }, 11952 {STATE_TEXTURESTAGE(7, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(7, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE }, 11953 {STATE_RENDER(WINED3D_RS_SPECULARENABLE), {STATE_RENDER(WINED3D_RS_SPECULARENABLE), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE }, 11954 {STATE_POINT_ENABLE, {STATE_POINT_ENABLE, glsl_fragment_pipe_shader }, WINED3D_GL_EXT_NONE }, 11955 {STATE_RENDER(WINED3D_RS_SHADEMODE), {STATE_RENDER(WINED3D_RS_SHADEMODE), glsl_fragment_pipe_shademode }, WINED3D_GLSL_130 }, 11956 {STATE_RENDER(WINED3D_RS_SHADEMODE), {STATE_RENDER(WINED3D_RS_SHADEMODE), state_shademode }, WINED3D_GL_EXT_NONE }, 11957 {0 /* Terminate */, {0, 0 }, WINED3D_GL_EXT_NONE }, 11958 }; 11959 11960 static BOOL glsl_fragment_pipe_alloc_context_data(struct wined3d_context *context) 11961 { 11962 return TRUE; 11963 } 11964 11965 static void glsl_fragment_pipe_free_context_data(struct wined3d_context *context) 11966 { 11967 } 11968 11969 const struct fragment_pipeline glsl_fragment_pipe = 11970 { 11971 glsl_fragment_pipe_enable, 11972 glsl_fragment_pipe_get_caps, 11973 glsl_fragment_pipe_get_emul_mask, 11974 glsl_fragment_pipe_alloc, 11975 glsl_fragment_pipe_free, 11976 glsl_fragment_pipe_alloc_context_data, 11977 glsl_fragment_pipe_free_context_data, 11978 shader_glsl_color_fixup_supported, 11979 glsl_fragment_pipe_state_template, 11980 }; 11981