ReactOS  0.4.12-dev-90-g2e2e63e
glsl_shader.c
Go to the documentation of this file.
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);
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 }
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 
75 {
76  char reg_name[150];
77  char mask_str[6];
78 };
79 
81 {
82  char reg_name[150];
83  char param_str[200];
84 };
85 
87 {
89  unsigned int coord_mask;
90  unsigned int deriv_mask;
91  enum wined3d_data_type data_type;
93  unsigned int offset_size;
94 };
95 
97 {
101 };
102 
104 {
105  unsigned int idx;
106  unsigned int version;
107 };
108 
110 {
113  unsigned int *positions;
114  unsigned int size;
115 };
116 
117 /* GLSL shader private data */
119 {
120  struct wined3d_string_buffer shader_buffer;
121  struct wined3d_string_buffer_list string_buffers;
122  struct wine_rb_tree program_lookup;
123  struct constant_heap vconst_heap;
124  struct constant_heap pconst_heap;
125  unsigned char *stack;
127 
130  struct wine_rb_tree ffp_vertex_shaders;
131  struct wine_rb_tree ffp_fragment_shaders;
134 };
135 
137 {
138  struct list shader_entry;
141  GLint uniform_f_locations[WINED3D_MAX_VS_CONSTS_F];
142  GLint uniform_i_locations[WINED3D_MAX_CONSTS_I];
143  GLint uniform_b_locations[WINED3D_MAX_CONSTS_B];
145 
146  GLint modelview_matrix_location[MAX_VERTEX_INDEX_BLENDS];
147  GLint normal_matrix_location[MAX_VERTEX_INDEX_BLENDS];
149  GLint texture_matrix_location[MAX_TEXTURES];
156  struct
157  {
170  } light_location[MAX_ACTIVE_LIGHTS];
178 };
179 
181 {
182  struct list shader_entry;
184 };
185 
187 {
188  struct list shader_entry;
190 
192 };
193 
195 {
196  struct list shader_entry;
198 
200 };
201 
203 {
204  struct list shader_entry;
206  GLint uniform_f_locations[WINED3D_MAX_PS_CONSTS_F];
207  GLint uniform_i_locations[WINED3D_MAX_CONSTS_I];
208  GLint uniform_b_locations[WINED3D_MAX_CONSTS_B];
209  GLint bumpenv_mat_location[MAX_TEXTURES];
210  GLint bumpenv_lum_scale_location[MAX_TEXTURES];
211  GLint bumpenv_lum_offset_location[MAX_TEXTURES];
212  GLint tss_constant_location[MAX_TEXTURES];
224 };
225 
227 {
228  struct list shader_entry;
230 };
231 
232 /* Struct to maintain data about a linked GLSL program */
234 {
235  struct wine_rb_entry program_lookup_entry;
236  struct glsl_vs_program vs;
237  struct glsl_hs_program hs;
240  struct glsl_ps_program ps;
244  unsigned int constant_version;
246  DWORD clip_distance_mask : 8; /* MAX_CLIP_DISTANCES, 8 */
248 };
249 
251 {
258 };
259 
266 };
267 
269 {
273 };
274 
276 {
278  struct ps_np2fixup_info np2fixup;
280 };
281 
283 {
286 };
287 
289 {
291 };
292 
294 {
297 };
298 
300 {
303 };
304 
306 {
308 };
309 
311 {
312  union
313  {
320  } gl_shaders;
321  unsigned int num_gl_shaders, shader_array_size;
322 };
323 
325 {
328  struct list linked_programs;
329 };
330 
332 {
335  struct list linked_programs;
336 };
337 
339 {
341  const struct wined3d_gl_info *gl_info;
342 };
343 
344 static void shader_glsl_generate_shader_epilogue(const struct wined3d_shader_context *ctx);
345 
346 static const char *debug_gl_shader_type(GLenum type)
347 {
348  switch (type)
349  {
350 #define WINED3D_TO_STR(u) case u: return #u
357 #undef WINED3D_TO_STR
358  default:
359  return wine_dbg_sprintf("UNKNOWN(%#x)", type);
360  }
361 }
362 
364 {
365  switch (type)
366  {
368  return "vs";
369 
371  return "hs";
372 
374  return "ds";
375 
377  return "gs";
378 
380  return "ps";
381 
383  return "cs";
384 
385  default:
386  FIXME("Unhandled shader type %#x.\n", type);
387  return "unknown";
388  }
389 }
390 
391 static unsigned int shader_glsl_get_version(const struct wined3d_gl_info *gl_info)
392 {
393  if (gl_info->glsl_version >= MAKEDWORD_VERSION(4, 40))
394  return 440;
395  else if (gl_info->glsl_version >= MAKEDWORD_VERSION(1, 50))
396  return 150;
397  else if (gl_info->glsl_version >= MAKEDWORD_VERSION(1, 30))
398  return 130;
399  else
400  return 120;
401 }
402 
404  const struct wined3d_gl_info *gl_info)
405 {
406  shader_addline(buffer, "#version %u\n", shader_glsl_get_version(gl_info));
407 }
408 
410 {
411  char str[4][17];
412 
413  wined3d_ftoa(values[0], str[0]);
414  wined3d_ftoa(values[1], str[1]);
415  wined3d_ftoa(values[2], str[2]);
416  wined3d_ftoa(values[3], str[3]);
417  shader_addline(buffer, "vec4(%s, %s, %s, %s)", str[0], str[1], str[2], str[3]);
418 }
419 
421  const int *values, unsigned int size)
422 {
423  int i;
424 
425  if (!size || size > 4)
426  {
427  ERR("Invalid vector size %u.\n", size);
428  return;
429  }
430 
431  if (size > 1)
432  shader_addline(buffer, "ivec%u(", size);
433 
434  for (i = 0; i < size; ++i)
435  shader_addline(buffer, i ? ", %#x" : "%#x", values[i]);
436 
437  if (size > 1)
438  shader_addline(buffer, ")");
439 }
440 
441 static const char *get_info_log_line(const char **ptr)
442 {
443  const char *p, *q;
444 
445  p = *ptr;
446  if (!(q = strstr(p, "\n")))
447  {
448  if (!*p) return NULL;
449  *ptr += strlen(p);
450  return p;
451  }
452  *ptr = q + 1;
453 
454  return p;
455 }
456 
457 /* Context activation is done by the caller. */
458 void print_glsl_info_log(const struct wined3d_gl_info *gl_info, GLuint id, BOOL program)
459 {
460  int length = 0;
461  char *log;
462 
463  if (!WARN_ON(d3d_shader) && !FIXME_ON(d3d_shader))
464  return;
465 
466  if (program)
467  GL_EXTCALL(glGetProgramiv(id, GL_INFO_LOG_LENGTH, &length));
468  else
469  GL_EXTCALL(glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length));
470 
471  /* A size of 1 is just a null-terminated string, so the log should be bigger than
472  * that if there are errors. */
473  if (length > 1)
474  {
475  const char *ptr, *line;
476 
477  log = heap_alloc(length);
478  /* The info log is supposed to be zero-terminated, but at least some
479  * versions of fglrx don't terminate the string properly. The reported
480  * length does include the terminator, so explicitly set it to zero
481  * here. */
482  log[length - 1] = 0;
483  if (program)
484  GL_EXTCALL(glGetProgramInfoLog(id, length, NULL, log));
485  else
486  GL_EXTCALL(glGetShaderInfoLog(id, length, NULL, log));
487 
488  ptr = log;
489  if (gl_info->quirks & WINED3D_QUIRK_INFO_LOG_SPAM)
490  {
491  WARN("Info log received from GLSL shader #%u:\n", id);
492  while ((line = get_info_log_line(&ptr))) WARN(" %.*s", (int)(ptr - line), line);
493  }
494  else
495  {
496  FIXME("Info log received from GLSL shader #%u:\n", id);
497  while ((line = get_info_log_line(&ptr))) FIXME(" %.*s", (int)(ptr - line), line);
498  }
499  heap_free(log);
500  }
501 }
502 
503 /* Context activation is done by the caller. */
504 static void shader_glsl_compile(const struct wined3d_gl_info *gl_info, GLuint shader, const char *src)
505 {
506  const char *ptr, *line;
507 
508  TRACE("Compiling shader object %u.\n", shader);
509 
510  if (TRACE_ON(d3d_shader))
511  {
512  ptr = src;
513  while ((line = get_info_log_line(&ptr))) TRACE_(d3d_shader)(" %.*s", (int)(ptr - line), line);
514  }
515 
516  GL_EXTCALL(glShaderSource(shader, 1, &src, NULL));
517  checkGLcall("glShaderSource");
518  GL_EXTCALL(glCompileShader(shader));
519  checkGLcall("glCompileShader");
520  print_glsl_info_log(gl_info, shader, FALSE);
521 }
522 
523 /* Context activation is done by the caller. */
525 {
526  GLint i, shader_count, source_size = -1;
527  GLuint *shaders;
528  char *source = NULL;
529 
530  GL_EXTCALL(glGetProgramiv(program, GL_ATTACHED_SHADERS, &shader_count));
531  if (!(shaders = heap_calloc(shader_count, sizeof(*shaders))))
532  {
533  ERR("Failed to allocate shader array memory.\n");
534  return;
535  }
536 
537  GL_EXTCALL(glGetAttachedShaders(program, shader_count, NULL, shaders));
538  for (i = 0; i < shader_count; ++i)
539  {
540  const char *ptr, *line;
541  GLint tmp;
542 
543  GL_EXTCALL(glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &tmp));
544 
545  if (source_size < tmp)
546  {
547  heap_free(source);
548 
549  if (!(source = heap_alloc_zero(tmp)))
550  {
551  ERR("Failed to allocate %d bytes for shader source.\n", tmp);
552  heap_free(shaders);
553  return;
554  }
555  source_size = tmp;
556  }
557 
558  FIXME("Shader %u:\n", shaders[i]);
559  GL_EXTCALL(glGetShaderiv(shaders[i], GL_SHADER_TYPE, &tmp));
560  FIXME(" GL_SHADER_TYPE: %s.\n", debug_gl_shader_type(tmp));
561  GL_EXTCALL(glGetShaderiv(shaders[i], GL_COMPILE_STATUS, &tmp));
562  FIXME(" GL_COMPILE_STATUS: %d.\n", tmp);
563  FIXME("\n");
564 
565  ptr = source;
566  GL_EXTCALL(glGetShaderSource(shaders[i], source_size, NULL, source));
567  while ((line = get_info_log_line(&ptr))) FIXME(" %.*s", (int)(ptr - line), line);
568  FIXME("\n");
569  }
570 
571  heap_free(source);
572  heap_free(shaders);
573 }
574 
575 /* Context activation is done by the caller. */
577 {
578  GLint tmp;
579 
580  if (!TRACE_ON(d3d_shader) && !FIXME_ON(d3d_shader))
581  return;
582 
583  GL_EXTCALL(glGetProgramiv(program, GL_LINK_STATUS, &tmp));
584  if (!tmp)
585  {
586  FIXME("Program %u link status invalid.\n", program);
587  shader_glsl_dump_program_source(gl_info, program);
588  }
589 
590  print_glsl_info_log(gl_info, program, TRUE);
591 }
592 
594 {
595  /* Layout qualifiers were introduced in GLSL 1.40. The Nvidia Legacy GPU
596  * driver (series 340.xx) doesn't parse layout qualifiers in older GLSL
597  * versions. */
598  return shader_glsl_get_version(gl_info) >= 140;
599 }
600 
602 {
604 }
605 
607  struct shader_glsl_priv *priv, GLuint program_id,
608  const struct wined3d_shader_reg_maps *reg_maps)
609 {
610  const char *prefix = shader_glsl_get_prefix(reg_maps->shader_version.type);
611  struct wined3d_string_buffer *name;
612  unsigned int i, base, count;
613  GLuint block_idx;
614 
616  return;
617 
618  name = string_buffer_get(&priv->string_buffers);
619  wined3d_gl_limits_get_uniform_block_range(&gl_info->limits, reg_maps->shader_version.type, &base, &count);
620  for (i = 0; i < count; ++i)
621  {
622  if (!reg_maps->cb_sizes[i])
623  continue;
624 
625  string_buffer_sprintf(name, "block_%s_cb%u", prefix, i);
626  block_idx = GL_EXTCALL(glGetUniformBlockIndex(program_id, name->buffer));
627  GL_EXTCALL(glUniformBlockBinding(program_id, block_idx, base + i));
628  }
629  checkGLcall("glUniformBlockBinding");
631 }
632 
633 /* Context activation is done by the caller. */
634 static void shader_glsl_load_samplers_range(const struct wined3d_gl_info *gl_info,
635  struct shader_glsl_priv *priv, GLuint program_id, const char *prefix,
636  unsigned int base, unsigned int count, const DWORD *tex_unit_map)
637 {
638  struct wined3d_string_buffer *sampler_name = string_buffer_get(&priv->string_buffers);
639  unsigned int i, mapped_unit;
640  GLint name_loc;
641 
642  for (i = 0; i < count; ++i)
643  {
644  string_buffer_sprintf(sampler_name, "%s_sampler%u", prefix, i);
645  name_loc = GL_EXTCALL(glGetUniformLocation(program_id, sampler_name->buffer));
646  if (name_loc == -1)
647  continue;
648 
649  mapped_unit = tex_unit_map ? tex_unit_map[base + i] : base + i;
650  if (mapped_unit == WINED3D_UNMAPPED_STAGE || mapped_unit >= gl_info->limits.combined_samplers)
651  {
652  ERR("Trying to load sampler %s on unsupported unit %u.\n", sampler_name->buffer, mapped_unit);
653  continue;
654  }
655 
656  TRACE("Loading sampler %s on unit %u.\n", sampler_name->buffer, mapped_unit);
657  GL_EXTCALL(glUniform1i(name_loc, mapped_unit));
658  }
659  checkGLcall("Load sampler bindings");
660  string_buffer_release(&priv->string_buffers, sampler_name);
661 }
662 
663 static unsigned int shader_glsl_map_tex_unit(const struct wined3d_context *context,
664  const struct wined3d_shader_version *shader_version, unsigned int sampler_idx)
665 {
666  const DWORD *tex_unit_map;
667  unsigned int base, count;
668 
669  tex_unit_map = context_get_tex_unit_mapping(context, shader_version, &base, &count);
670  if (sampler_idx >= count)
671  return WINED3D_UNMAPPED_STAGE;
672  if (!tex_unit_map)
673  return base + sampler_idx;
674  return tex_unit_map[base + sampler_idx];
675 }
676 
678  const struct wined3d_context *context, const struct wined3d_shader_version *shader_version,
679  unsigned int sampler_idx)
680 {
681  unsigned int mapped_unit = shader_glsl_map_tex_unit(context, shader_version, sampler_idx);
682  if (mapped_unit != WINED3D_UNMAPPED_STAGE)
683  shader_addline(buffer, "layout(binding = %u)\n", mapped_unit);
684  else
685  ERR("Unmapped sampler %u.\n", sampler_idx);
686 }
687 
688 /* Context activation is done by the caller. */
690  struct shader_glsl_priv *priv, GLuint program_id, const struct wined3d_shader_reg_maps *reg_maps)
691 {
692  const struct wined3d_gl_info *gl_info = context->gl_info;
693  const struct wined3d_shader_version *shader_version;
694  const DWORD *tex_unit_map;
695  unsigned int base, count;
696  const char *prefix;
697 
699  return;
700 
701  shader_version = reg_maps ? &reg_maps->shader_version : NULL;
702  prefix = shader_glsl_get_prefix(shader_version ? shader_version->type : WINED3D_SHADER_TYPE_PIXEL);
703  tex_unit_map = context_get_tex_unit_mapping(context, shader_version, &base, &count);
704  shader_glsl_load_samplers_range(gl_info, priv, program_id, prefix, base, count, tex_unit_map);
705 }
706 
707 static void shader_glsl_load_icb(const struct wined3d_gl_info *gl_info, struct shader_glsl_priv *priv,
708  GLuint program_id, const struct wined3d_shader_reg_maps *reg_maps)
709 {
710  const struct wined3d_shader_immediate_constant_buffer *icb = reg_maps->icb;
711 
712  if (icb)
713  {
714  struct wined3d_string_buffer *icb_name = string_buffer_get(&priv->string_buffers);
715  const char *prefix = shader_glsl_get_prefix(reg_maps->shader_version.type);
716  GLint icb_location;
717 
718  string_buffer_sprintf(icb_name, "%s_icb", prefix);
719  icb_location = GL_EXTCALL(glGetUniformLocation(program_id, icb_name->buffer));
720  GL_EXTCALL(glUniform4fv(icb_location, icb->vec4_count, (const GLfloat *)icb->data));
721  checkGLcall("Load immediate constant buffer");
722 
723  string_buffer_release(&priv->string_buffers, icb_name);
724  }
725 }
726 
727 /* Context activation is done by the caller. */
728 static void shader_glsl_load_images(const struct wined3d_gl_info *gl_info, struct shader_glsl_priv *priv,
729  GLuint program_id, const struct wined3d_shader_reg_maps *reg_maps)
730 {
731  const char *prefix = shader_glsl_get_prefix(reg_maps->shader_version.type);
732  struct wined3d_string_buffer *name;
733  GLint location;
734  unsigned int i;
735 
737  return;
738 
739  name = string_buffer_get(&priv->string_buffers);
740  for (i = 0; i < MAX_UNORDERED_ACCESS_VIEWS; ++i)
741  {
742  if (!reg_maps->uav_resource_info[i].type)
743  continue;
744 
745  string_buffer_sprintf(name, "%s_image%u", prefix, i);
746  location = GL_EXTCALL(glGetUniformLocation(program_id, name->buffer));
747  if (location == -1)
748  continue;
749 
750  TRACE("Loading image %s on unit %u.\n", name->buffer, i);
751  GL_EXTCALL(glUniform1i(location, i));
752  }
753  checkGLcall("Load image bindings");
755 }
756 
757 /* Context activation is done by the caller. */
759  struct shader_glsl_priv *priv, GLuint program_id, const struct wined3d_shader *shader)
760 {
761  const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
762 
763  shader_glsl_init_uniform_block_bindings(context->gl_info, priv, program_id, reg_maps);
764  shader_glsl_load_icb(context->gl_info, priv, program_id, reg_maps);
765  /* Texture unit mapping is set up to be the same each time the shader
766  * program is used so we can hardcode the sampler uniform values. */
767  shader_glsl_load_samplers(context, priv, program_id, reg_maps);
768 }
769 
770 static void append_transform_feedback_varying(const char **varyings, unsigned int *varying_count,
771  char **strings, unsigned int *strings_length, struct wined3d_string_buffer *buffer)
772 {
773  if (varyings && *strings)
774  {
775  char *ptr = *strings;
776 
777  varyings[*varying_count] = ptr;
778 
779  memcpy(ptr, buffer->buffer, buffer->content_size + 1);
780  ptr += buffer->content_size + 1;
781 
782  *strings = ptr;
783  }
784 
785  *strings_length += buffer->content_size + 1;
786  ++(*varying_count);
787 }
788 
790  unsigned int *varying_count, char **strings, unsigned int *strings_length,
791  struct wined3d_string_buffer *buffer, unsigned int component_count)
792 {
793  unsigned int j;
794 
795  for (j = 0; j < component_count / 4; ++j)
796  {
797  string_buffer_sprintf(buffer, "gl_SkipComponents4");
798  append_transform_feedback_varying(varyings, varying_count, strings, strings_length, buffer);
799  }
800  if (component_count % 4)
801  {
802  string_buffer_sprintf(buffer, "gl_SkipComponents%u", component_count % 4);
803  append_transform_feedback_varying(varyings, varying_count, strings, strings_length, buffer);
804  }
805 }
806 
808  struct wined3d_string_buffer *buffer, const char **varyings, unsigned int *varying_count,
809  char *strings, unsigned int *strings_length, GLenum buffer_mode)
810 {
811  unsigned int i, buffer_idx, count, length, highest_output_slot, stride;
812  BOOL have_varyings_to_record = FALSE;
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 
837  {
839  &strings, &length, buffer, e->component_count);
840  continue;
841  }
842 
843  if (e->component_idx || e->component_count != 4)
844  {
846  {
847  FIXME("Unsupported component range %u-%u.\n", e->component_idx, e->component_count);
849  &strings, &length, buffer, e->component_count);
850  continue;
851  }
852 
853  string_buffer_sprintf(buffer, "shader_in_out.reg%u_%u_%u",
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  have_varyings_to_record = TRUE;
864  }
865 
866  if (buffer_idx < so_desc->buffer_stride_count
867  && stride < so_desc->buffer_strides[buffer_idx] / 4)
868  {
869  unsigned int component_count = so_desc->buffer_strides[buffer_idx] / 4 - stride;
871  &strings, &length, buffer, component_count);
872  }
873 
874  if (highest_output_slot <= buffer_idx)
875  break;
876 
877  if (buffer_mode == GL_INTERLEAVED_ATTRIBS)
878  {
879  string_buffer_sprintf(buffer, "gl_NextBuffer");
880  append_transform_feedback_varying(varyings, &count, &strings, &length, buffer);
881  }
882  }
883 
884  if (varying_count)
885  *varying_count = count;
886  if (strings_length)
887  *strings_length = length;
888 
889  return have_varyings_to_record;
890 }
891 
893  struct shader_glsl_priv *priv, GLuint program_id, struct wined3d_shader *shader)
894 {
895  const struct wined3d_stream_output_desc *so_desc = &shader->u.gs.so_desc;
896  const struct wined3d_gl_info *gl_info = context->gl_info;
898  unsigned int i, count, length;
899  const char **varyings;
900  char *strings;
901  GLenum mode;
902 
903  if (!so_desc->element_count)
904  return;
905 
906  if (gl_info->supported[ARB_TRANSFORM_FEEDBACK3])
907  {
908  mode = GL_INTERLEAVED_ATTRIBS;
909  }
910  else
911  {
912  unsigned int element_count[WINED3D_MAX_STREAM_OUTPUT_BUFFERS] = {0};
913 
914  for (i = 0; i < so_desc->element_count; ++i)
915  {
916  if (so_desc->elements[i].register_idx == WINED3D_STREAM_OUTPUT_GAP)
917  {
918  FIXME("ARB_transform_feedback3 is needed for stream output gaps.\n");
919  return;
920  }
921  ++element_count[so_desc->elements[i].output_slot];
922  }
923 
924  if (element_count[0] == so_desc->element_count)
925  {
926  mode = GL_INTERLEAVED_ATTRIBS;
927  }
928  else
929  {
930  mode = GL_SEPARATE_ATTRIBS;
931  for (i = 0; i < ARRAY_SIZE(element_count); ++i)
932  {
933  if (element_count[i] != 1)
934  break;
935  }
936  for (; i < ARRAY_SIZE(element_count); ++i)
937  {
938  if (element_count[i])
939  {
940  FIXME("Only single element per buffer is allowed in separate mode.\n");
941  return;
942  }
943  }
944  }
945  }
946 
947  buffer = string_buffer_get(&priv->string_buffers);
948 
949  if (!shader_glsl_generate_transform_feedback_varyings(so_desc, buffer, NULL, &count, NULL, &length, mode))
950  {
951  FIXME("No varyings to record, disabling transform feedback.\n");
952  shader->u.gs.so_desc.element_count = 0;
953  string_buffer_release(&priv->string_buffers, buffer);
954  return;
955  }
956 
957  if (!(varyings = heap_calloc(count, sizeof(*varyings))))
958  {
959  ERR("Out of memory.\n");
960  string_buffer_release(&priv->string_buffers, buffer);
961  return;
962  }
963  if (!(strings = heap_calloc(length, sizeof(*strings))))
964  {
965  ERR("Out of memory.\n");
966  heap_free(varyings);
967  string_buffer_release(&priv->string_buffers, buffer);
968  return;
969  }
970 
971  shader_glsl_generate_transform_feedback_varyings(so_desc, buffer, varyings, NULL, strings, NULL, mode);
972  GL_EXTCALL(glTransformFeedbackVaryings(program_id, count, varyings, mode));
973  checkGLcall("glTransformFeedbackVaryings");
974 
975  heap_free(varyings);
976  heap_free(strings);
977  string_buffer_release(&priv->string_buffers, buffer);
978 }
979 
980 /* Context activation is done by the caller. */
981 static inline void walk_constant_heap(const struct wined3d_gl_info *gl_info, const struct wined3d_vec4 *constants,
982  const GLint *constant_locations, const struct constant_heap *heap, unsigned char *stack, DWORD version)
983 {
984  unsigned int start = ~0U, end = 0;
985  int stack_idx = 0;
986  unsigned int heap_idx = 1;
987  unsigned int idx;
988 
989  if (heap->entries[heap_idx].version <= version) return;
990 
991  idx = heap->entries[heap_idx].idx;
992  if (constant_locations[idx] != -1)
993  start = end = idx;
994  stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
995 
996  while (stack_idx >= 0)
997  {
998  /* Note that we fall through to the next case statement. */
999  switch(stack[stack_idx])
1000  {
1002  {
1003  unsigned int left_idx = heap_idx << 1;
1004  if (left_idx < heap->size && heap->entries[left_idx].version > version)
1005  {
1006  heap_idx = left_idx;
1007  idx = heap->entries[heap_idx].idx;
1008  if (constant_locations[idx] != -1)
1009  {
1010  if (start > idx)
1011  start = idx;
1012  if (end < idx)
1013  end = idx;
1014  }
1015 
1016  stack[stack_idx++] = HEAP_NODE_TRAVERSE_RIGHT;
1017  stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
1018  break;
1019  }
1020  }
1021 
1023  {
1024  unsigned int right_idx = (heap_idx << 1) + 1;
1025  if (right_idx < heap->size && heap->entries[right_idx].version > version)
1026  {
1027  heap_idx = right_idx;
1028  idx = heap->entries[heap_idx].idx;
1029  if (constant_locations[idx] != -1)
1030  {
1031  if (start > idx)
1032  start = idx;
1033  if (end < idx)
1034  end = idx;
1035  }
1036 
1037  stack[stack_idx++] = HEAP_NODE_POP;
1038  stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
1039  break;
1040  }
1041  }
1042 
1043  case HEAP_NODE_POP:
1044  heap_idx >>= 1;
1045  --stack_idx;
1046  break;
1047  }
1048  }
1049  if (start <= end)
1050  GL_EXTCALL(glUniform4fv(constant_locations[start], end - start + 1, &constants[start].x));
1051  checkGLcall("walk_constant_heap()");
1052 }
1053 
1054 /* Context activation is done by the caller. */
1055 static inline void apply_clamped_constant(const struct wined3d_gl_info *gl_info,
1056  GLint location, const struct wined3d_vec4 *data)
1057 {
1058  GLfloat clamped_constant[4];
1059 
1060  if (location == -1) return;
1061 
1062  clamped_constant[0] = data->x < -1.0f ? -1.0f : data->x > 1.0f ? 1.0f : data->x;
1063  clamped_constant[1] = data->y < -1.0f ? -1.0f : data->y > 1.0f ? 1.0f : data->y;
1064  clamped_constant[2] = data->z < -1.0f ? -1.0f : data->z > 1.0f ? 1.0f : data->z;
1065  clamped_constant[3] = data->w < -1.0f ? -1.0f : data->w > 1.0f ? 1.0f : data->w;
1066 
1067  GL_EXTCALL(glUniform4fv(location, 1, clamped_constant));
1068 }
1069 
1070 /* Context activation is done by the caller. */
1071 static inline void walk_constant_heap_clamped(const struct wined3d_gl_info *gl_info,
1072  const struct wined3d_vec4 *constants, const GLint *constant_locations,
1073  const struct constant_heap *heap, unsigned char *stack, DWORD version)
1074 {
1075  int stack_idx = 0;
1076  unsigned int heap_idx = 1;
1077  unsigned int idx;
1078 
1079  if (heap->entries[heap_idx].version <= version) return;
1080 
1081  idx = heap->entries[heap_idx].idx;
1082  apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx]);
1083  stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
1084 
1085  while (stack_idx >= 0)
1086  {
1087  /* Note that we fall through to the next case statement. */
1088  switch(stack[stack_idx])
1089  {
1091  {
1092  unsigned int left_idx = heap_idx << 1;
1093  if (left_idx < heap->size && heap->entries[left_idx].version > version)
1094  {
1095  heap_idx = left_idx;
1096  idx = heap->entries[heap_idx].idx;
1097  apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx]);
1098 
1099  stack[stack_idx++] = HEAP_NODE_TRAVERSE_RIGHT;
1100  stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
1101  break;
1102  }
1103  }
1104 
1106  {
1107  unsigned int right_idx = (heap_idx << 1) + 1;
1108  if (right_idx < heap->size && heap->entries[right_idx].version > version)
1109  {
1110  heap_idx = right_idx;
1111  idx = heap->entries[heap_idx].idx;
1112  apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx]);
1113 
1114  stack[stack_idx++] = HEAP_NODE_POP;
1115  stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
1116  break;
1117  }
1118  }
1119 
1120  case HEAP_NODE_POP:
1121  heap_idx >>= 1;
1122  --stack_idx;
1123  break;
1124  }
1125  }
1126  checkGLcall("walk_constant_heap_clamped()");
1127 }
1128 
1129 /* Context activation is done by the caller. */
1130 static void shader_glsl_load_constants_f(const struct wined3d_shader *shader, const struct wined3d_gl_info *gl_info,
1131  const struct wined3d_vec4 *constants, const GLint *constant_locations, const struct constant_heap *heap,
1132  unsigned char *stack, unsigned int version)
1133 {
1134  const struct wined3d_shader_lconst *lconst;
1135 
1136  /* 1.X pshaders have the constants clamped to [-1;1] implicitly. */
1137  if (shader->reg_maps.shader_version.major == 1
1138  && shader->reg_maps.shader_version.type == WINED3D_SHADER_TYPE_PIXEL)
1139  walk_constant_heap_clamped(gl_info, constants, constant_locations, heap, stack, version);
1140  else
1141  walk_constant_heap(gl_info, constants, constant_locations, heap, stack, version);
1142 
1143  if (!shader->load_local_constsF)
1144  {
1145  TRACE("No need to load local float constants for this shader.\n");
1146  return;
1147  }
1148 
1149  /* Immediate constants are clamped to [-1;1] at shader creation time if needed */
1150  LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry)
1151  {
1152  GL_EXTCALL(glUniform4fv(constant_locations[lconst->idx], 1, (const GLfloat *)lconst->value));
1153  }
1154  checkGLcall("glUniform4fv()");
1155 }
1156 
1157 /* Context activation is done by the caller. */
1158 static void shader_glsl_load_constants_i(const struct wined3d_shader *shader, const struct wined3d_gl_info *gl_info,
1159  const struct wined3d_ivec4 *constants, const GLint locations[WINED3D_MAX_CONSTS_I], WORD constants_set)
1160 {
1161  unsigned int i;
1162  struct list* ptr;
1163 
1164  for (i = 0; constants_set; constants_set >>= 1, ++i)
1165  {
1166  if (!(constants_set & 1)) continue;
1167 
1168  /* We found this uniform name in the program - go ahead and send the data */
1169  GL_EXTCALL(glUniform4iv(locations[i], 1, &constants[i].x));
1170  }
1171 
1172  /* Load immediate constants */
1173  ptr = list_head(&shader->constantsI);
1174  while (ptr)
1175  {
1176  const struct wined3d_shader_lconst *lconst = LIST_ENTRY(ptr, const struct wined3d_shader_lconst, entry);
1177  unsigned int idx = lconst->idx;
1178  const GLint *values = (const GLint *)lconst->value;
1179 
1180  /* We found this uniform name in the program - go ahead and send the data */
1181  GL_EXTCALL(glUniform4iv(locations[idx], 1, values));
1182  ptr = list_next(&shader->constantsI, ptr);
1183  }
1184  checkGLcall("glUniform4iv()");
1185 }
1186 
1187 /* Context activation is done by the caller. */
1188 static void shader_glsl_load_constantsB(const struct wined3d_shader *shader, const struct wined3d_gl_info *gl_info,
1189  const GLint locations[WINED3D_MAX_CONSTS_B], const BOOL *constants, WORD constants_set)
1190 {
1191  unsigned int i;
1192  struct list* ptr;
1193 
1194  for (i = 0; constants_set; constants_set >>= 1, ++i)
1195  {
1196  if (!(constants_set & 1)) continue;
1197 
1198  GL_EXTCALL(glUniform1iv(locations[i], 1, &constants[i]));
1199  }
1200 
1201  /* Load immediate constants */
1202  ptr = list_head(&shader->constantsB);
1203  while (ptr)
1204  {
1205  const struct wined3d_shader_lconst *lconst = LIST_ENTRY(ptr, const struct wined3d_shader_lconst, entry);
1206  unsigned int idx = lconst->idx;
1207  const GLint *values = (const GLint *)lconst->value;
1208 
1209  GL_EXTCALL(glUniform1iv(locations[idx], 1, values));
1210  ptr = list_next(&shader->constantsB, ptr);
1211  }
1212  checkGLcall("glUniform1iv()");
1213 }
1214 
1216 {
1217  WINE_RB_ENTRY_VALUE(entry, struct glsl_shader_prog_link, program_lookup_entry)->constant_version = 0;
1218 }
1219 
1220 /* Context activation is done by the caller (state handler). */
1222  const struct wined3d_gl_info *gl_info, const struct wined3d_state *state)
1223 {
1224  struct
1225  {
1226  float sx, sy;
1227  }
1228  np2fixup_constants[MAX_FRAGMENT_SAMPLERS];
1229  UINT fixup = ps->np2_fixup_info->active;
1230  UINT i;
1231 
1232  for (i = 0; fixup; fixup >>= 1, ++i)
1233  {
1234  const struct wined3d_texture *tex = state->textures[i];
1235  unsigned char idx = ps->np2_fixup_info->idx[i];
1236 
1237  if (!tex)
1238  {
1239  ERR("Nonexistent texture is flagged for NP2 texcoord fixup.\n");
1240  continue;
1241  }
1242 
1243  np2fixup_constants[idx].sx = tex->pow2_matrix[0];
1244  np2fixup_constants[idx].sy = tex->pow2_matrix[5];
1245  }
1246 
1247  GL_EXTCALL(glUniform4fv(ps->np2_fixup_location, ps->np2_fixup_info->num_consts, &np2fixup_constants[0].sx));
1248 }
1249 
1251  const struct wined3d_state *state, unsigned int tex, struct glsl_shader_prog_link *prog)
1252 {
1253  const struct wined3d_gl_info *gl_info = context->gl_info;
1254  struct wined3d_matrix mat;
1255 
1256  if (tex >= MAX_TEXTURES)
1257  return;
1258  if (prog->vs.texture_matrix_location[tex] == -1)
1259  return;
1260 
1261  get_texture_matrix(context, state, tex, &mat);
1262  GL_EXTCALL(glUniformMatrix4fv(prog->vs.texture_matrix_location[tex], 1, FALSE, &mat._11));
1263  checkGLcall("glUniformMatrix4fv");
1264 }
1265 
1267  const struct wined3d_state *state, struct glsl_shader_prog_link *prog)
1268 {
1269  const struct wined3d_gl_info *gl_info = context->gl_info;
1270 
1272  {
1273  GL_EXTCALL(glUniform4fv(prog->vs.material_specular_location, 1, &state->material.specular.r));
1274  GL_EXTCALL(glUniform1f(prog->vs.material_shininess_location, state->material.power));
1275  }
1276  else
1277  {
1278  static const float black[] = {0.0f, 0.0f, 0.0f, 0.0f};
1279 
1280  GL_EXTCALL(glUniform4fv(prog->vs.material_specular_location, 1, black));
1281  }
1282  GL_EXTCALL(glUniform4fv(prog->vs.material_ambient_location, 1, &state->material.ambient.r));
1283  GL_EXTCALL(glUniform4fv(prog->vs.material_diffuse_location, 1, &state->material.diffuse.r));
1284  GL_EXTCALL(glUniform4fv(prog->vs.material_emissive_location, 1, &state->material.emissive.r));
1285  checkGLcall("setting FFP material uniforms");
1286 }
1287 
1289  const struct wined3d_state *state, struct glsl_shader_prog_link *prog)
1290 {
1291  const struct wined3d_gl_info *gl_info = context->gl_info;
1292  struct wined3d_color color;
1293 
1295  GL_EXTCALL(glUniform3fv(prog->vs.light_ambient_location, 1, &color.r));
1296  checkGLcall("glUniform3fv");
1297 }
1298 
1299 static void multiply_vector_matrix(struct wined3d_vec4 *dest, const struct wined3d_vec4 *src1,
1300  const struct wined3d_matrix *src2)
1301 {
1302  struct wined3d_vec4 temp;
1303 
1304  temp.x = (src1->x * src2->_11) + (src1->y * src2->_21) + (src1->z * src2->_31) + (src1->w * src2->_41);
1305  temp.y = (src1->x * src2->_12) + (src1->y * src2->_22) + (src1->z * src2->_32) + (src1->w * src2->_42);
1306  temp.z = (src1->x * src2->_13) + (src1->y * src2->_23) + (src1->z * src2->_33) + (src1->w * src2->_43);
1307  temp.w = (src1->x * src2->_14) + (src1->y * src2->_24) + (src1->z * src2->_34) + (src1->w * src2->_44);
1308 
1309  *dest = temp;
1310 }
1311 
1313  const struct wined3d_state *state, unsigned int light, const struct wined3d_light_info *light_info,
1314  struct glsl_shader_prog_link *prog)
1315 {
1316  const struct wined3d_matrix *view = &state->transforms[WINED3D_TS_VIEW];
1317  const struct wined3d_gl_info *gl_info = context->gl_info;
1318  struct wined3d_vec4 vec4;
1319 
1320  GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].diffuse, 1, &light_info->OriginalParms.diffuse.r));
1321  GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].specular, 1, &light_info->OriginalParms.specular.r));
1322  GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].ambient, 1, &light_info->OriginalParms.ambient.r));
1323 
1324  switch (light_info->OriginalParms.type)
1325  {
1326  case WINED3D_LIGHT_POINT:
1327  multiply_vector_matrix(&vec4, &light_info->position, view);
1328  GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].position, 1, &vec4.x));
1329  GL_EXTCALL(glUniform1f(prog->vs.light_location[light].range, light_info->OriginalParms.range));
1330  GL_EXTCALL(glUniform1f(prog->vs.light_location[light].c_att, light_info->OriginalParms.attenuation0));
1331  GL_EXTCALL(glUniform1f(prog->vs.light_location[light].l_att, light_info->OriginalParms.attenuation1));
1332  GL_EXTCALL(glUniform1f(prog->vs.light_location[light].q_att, light_info->OriginalParms.attenuation2));
1333  break;
1334 
1335  case WINED3D_LIGHT_SPOT:
1336  multiply_vector_matrix(&vec4, &light_info->position, view);
1337  GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].position, 1, &vec4.x));
1338 
1339  multiply_vector_matrix(&vec4, &light_info->direction, view);
1340  GL_EXTCALL(glUniform3fv(prog->vs.light_location[light].direction, 1, &vec4.x));
1341 
1342  GL_EXTCALL(glUniform1f(prog->vs.light_location[light].range, light_info->OriginalParms.range));
1343  GL_EXTCALL(glUniform1f(prog->vs.light_location[light].falloff, light_info->OriginalParms.falloff));
1344  GL_EXTCALL(glUniform1f(prog->vs.light_location[light].c_att, light_info->OriginalParms.attenuation0));
1345  GL_EXTCALL(glUniform1f(prog->vs.light_location[light].l_att, light_info->OriginalParms.attenuation1));
1346  GL_EXTCALL(glUniform1f(prog->vs.light_location[light].q_att, light_info->OriginalParms.attenuation2));
1347  GL_EXTCALL(glUniform1f(prog->vs.light_location[light].cos_htheta, cosf(light_info->OriginalParms.theta / 2.0f)));
1348  GL_EXTCALL(glUniform1f(prog->vs.light_location[light].cos_hphi, cosf(light_info->OriginalParms.phi / 2.0f)));
1349  break;
1350 
1352  multiply_vector_matrix(&vec4, &light_info->direction, view);
1353  GL_EXTCALL(glUniform3fv(prog->vs.light_location[light].direction, 1, &vec4.x));
1354  break;
1355 
1357  multiply_vector_matrix(&vec4, &light_info->position, view);
1358  GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].position, 1, &vec4.x));
1359  break;
1360 
1361  default:
1362  FIXME("Unrecognized light type %#x.\n", light_info->OriginalParms.type);
1363  }
1364  checkGLcall("setting FFP lights uniforms");
1365 }
1366 
1368  const struct wined3d_state *state, struct glsl_shader_prog_link *prog)
1369 {
1370  const struct wined3d_gl_info *gl_info = context->gl_info;
1371  float min, max;
1372  float size, att[3];
1373 
1374  get_pointsize_minmax(context, state, &min, &max);
1375 
1376  GL_EXTCALL(glUniform1f(prog->vs.pointsize_min_location, min));
1377  checkGLcall("glUniform1f");
1378  GL_EXTCALL(glUniform1f(prog->vs.pointsize_max_location, max));
1379  checkGLcall("glUniform1f");
1380 
1381  get_pointsize(context, state, &size, att);
1382 
1383  GL_EXTCALL(glUniform1f(prog->vs.pointsize_location, size));
1384  checkGLcall("glUniform1f");
1385  GL_EXTCALL(glUniform1f(prog->vs.pointsize_c_att_location, att[0]));
1386  checkGLcall("glUniform1f");
1387  GL_EXTCALL(glUniform1f(prog->vs.pointsize_l_att_location, att[1]));
1388  checkGLcall("glUniform1f");
1389  GL_EXTCALL(glUniform1f(prog->vs.pointsize_q_att_location, att[2]));
1390  checkGLcall("glUniform1f");
1391 }
1392 
1394  const struct wined3d_state *state, struct glsl_shader_prog_link *prog)
1395 {
1396  const struct wined3d_gl_info *gl_info = context->gl_info;
1397  struct wined3d_color color;
1398  float start, end, scale;
1399  union
1400  {
1401  DWORD d;
1402  float f;
1403  } tmpvalue;
1404 
1406  GL_EXTCALL(glUniform4fv(prog->ps.fog_color_location, 1, &color.r));
1407  tmpvalue.d = state->render_states[WINED3D_RS_FOGDENSITY];
1408  GL_EXTCALL(glUniform1f(prog->ps.fog_density_location, tmpvalue.f));
1409  get_fog_start_end(context, state, &start, &end);
1410  scale = 1.0f / (end - start);
1411  GL_EXTCALL(glUniform1f(prog->ps.fog_end_location, end));
1412  GL_EXTCALL(glUniform1f(prog->ps.fog_scale_location, scale));
1413  checkGLcall("fog emulation uniforms");
1414 }
1415 
1417  const struct wined3d_state *state, unsigned int index, struct glsl_shader_prog_link *prog)
1418 {
1419  const struct wined3d_gl_info *gl_info = context->gl_info;
1420  struct wined3d_matrix matrix;
1421  struct wined3d_vec4 plane;
1422 
1423  plane = state->clip_planes[index];
1424 
1425  /* Clip planes are affected by the view transform in d3d for FFP draws. */
1426  if (!use_vs(state))
1427  {
1428  invert_matrix(&matrix, &state->transforms[WINED3D_TS_VIEW]);
1429  transpose_matrix(&matrix, &matrix);
1430  multiply_vector_matrix(&plane, &plane, &matrix);
1431  }
1432 
1433  GL_EXTCALL(glUniform4fv(prog->vs.clip_planes_location + index, 1, &plane.x));
1434 }
1435 
1436 /* Context activation is done by the caller (state handler). */
1438  const struct wined3d_gl_info *gl_info, const struct wined3d_state *state)
1439 {
1440  struct wined3d_color float_key[2];
1441  const struct wined3d_texture *texture = state->textures[0];
1442 
1443  wined3d_format_get_float_color_key(texture->resource.format, &texture->async.src_blt_color_key, float_key);
1444  GL_EXTCALL(glUniform4fv(ps->color_key_location, 2, &float_key[0].r));
1445 }
1446 
1447 /* Context activation is done by the caller. */
1448 static void get_normal_matrix(struct wined3d_context *context, struct wined3d_matrix *mat, float *normal)
1449 {
1450  int i, j;
1451 
1452  if (context->d3d_info->wined3d_creation_flags & WINED3D_LEGACY_FFP_LIGHTING)
1453  invert_matrix_3d(mat, mat);
1454  else
1455  invert_matrix(mat, mat);
1456  /* Tests show that singular modelview matrices are used unchanged as normal
1457  * matrices on D3D3 and older. There seems to be no clearly consistent
1458  * behavior on newer D3D versions so always follow older ddraw behavior. */
1459  for (i = 0; i < 3; ++i)
1460  for (j = 0; j < 3; ++j)
1461  normal[i * 3 + j] = (&mat->_11)[j * 4 + i];
1462 }
1463 
1464 /* Context activation is done by the caller (state handler). */
1465 static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context *context,
1466  const struct wined3d_state *state)
1467 {
1468  const struct glsl_context_data *ctx_data = context->shader_backend_data;
1469  const struct wined3d_shader *vshader = state->shader[WINED3D_SHADER_TYPE_VERTEX];
1470  const struct wined3d_shader *pshader = state->shader[WINED3D_SHADER_TYPE_PIXEL];
1471  const struct wined3d_gl_info *gl_info = context->gl_info;
1472  struct shader_glsl_priv *priv = shader_priv;
1473  float position_fixup[4 * WINED3D_MAX_VIEWPORTS];
1474  float normal[3 * 3];
1475  DWORD update_mask;
1476 
1477  struct glsl_shader_prog_link *prog = ctx_data->glsl_program;
1479  int i;
1480 
1481  if (!prog) {
1482  /* No GLSL program set - nothing to do. */
1483  return;
1484  }
1485  constant_version = prog->constant_version;
1486  update_mask = context->constant_update_mask & prog->constant_update_mask;
1487 
1488  if (update_mask & WINED3D_SHADER_CONST_VS_F)
1489  shader_glsl_load_constants_f(vshader, gl_info, state->vs_consts_f,
1490  prog->vs.uniform_f_locations, &priv->vconst_heap, priv->stack, constant_version);
1491 
1492  if (update_mask & WINED3D_SHADER_CONST_VS_I)
1493  shader_glsl_load_constants_i(vshader, gl_info, state->vs_consts_i,
1494  prog->vs.uniform_i_locations, vshader->reg_maps.integer_constants);
1495 
1496  if (update_mask & WINED3D_SHADER_CONST_VS_B)
1497  shader_glsl_load_constantsB(vshader, gl_info, prog->vs.uniform_b_locations, state->vs_consts_b,
1498  vshader->reg_maps.boolean_constants);
1499 
1500  if (update_mask & WINED3D_SHADER_CONST_VS_CLIP_PLANES)
1501  {
1502  for (i = 0; i < gl_info->limits.user_clip_distances; ++i)
1503  shader_glsl_clip_plane_uniform(context, state, i, prog);
1504  }
1505 
1506  if (update_mask & WINED3D_SHADER_CONST_VS_POINTSIZE)
1507  shader_glsl_pointsize_uniform(context, state, prog);
1508 
1509  if (update_mask & WINED3D_SHADER_CONST_POS_FIXUP)
1510  {
1511  unsigned int fixup_count = state->shader[WINED3D_SHADER_TYPE_GEOMETRY] ?
1512  max(state->viewport_count, 1) : 1;
1513  shader_get_position_fixup(context, state, fixup_count, position_fixup);
1515  GL_EXTCALL(glUniform4fv(prog->gs.pos_fixup_location, fixup_count, position_fixup));
1516  else if (state->shader[WINED3D_SHADER_TYPE_DOMAIN])
1517  GL_EXTCALL(glUniform4fv(prog->ds.pos_fixup_location, 1, position_fixup));
1518  else
1519  GL_EXTCALL(glUniform4fv(prog->vs.pos_fixup_location, 1, position_fixup));
1520  checkGLcall("glUniform4fv");
1521  }
1522 
1523  if (update_mask & WINED3D_SHADER_CONST_FFP_MODELVIEW)
1524  {
1525  struct wined3d_matrix mat;
1526 
1527  get_modelview_matrix(context, state, 0, &mat);
1528  GL_EXTCALL(glUniformMatrix4fv(prog->vs.modelview_matrix_location[0], 1, FALSE, &mat._11));
1529  checkGLcall("glUniformMatrix4fv");
1530 
1531  get_normal_matrix(context, &mat, normal);
1532  GL_EXTCALL(glUniformMatrix3fv(prog->vs.normal_matrix_location[0], 1, FALSE, normal));
1533  checkGLcall("glUniformMatrix3fv");
1534  }
1535 
1536  if (update_mask & WINED3D_SHADER_CONST_FFP_VERTEXBLEND)
1537  {
1538  struct wined3d_matrix mat;
1539 
1540  for (i = 1; i < MAX_VERTEX_INDEX_BLENDS; ++i)
1541  {
1542  if (prog->vs.modelview_matrix_location[i] == -1)
1543  break;
1544  if (!(update_mask & WINED3D_SHADER_CONST_FFP_VERTEXBLEND_INDEX(i)))
1545  continue;
1546 
1547  get_modelview_matrix(context, state, i, &mat);
1548  GL_EXTCALL(glUniformMatrix4fv(prog->vs.modelview_matrix_location[i], 1, FALSE, &mat._11));
1549  checkGLcall("glUniformMatrix4fv");
1550 
1551  get_normal_matrix(context, &mat, normal);
1552  GL_EXTCALL(glUniformMatrix3fv(prog->vs.normal_matrix_location[i], 1, FALSE, normal));
1553  checkGLcall("glUniformMatrix3fv");
1554  }
1555  }
1556 
1557  if (update_mask & WINED3D_SHADER_CONST_FFP_PROJ)
1558  {
1559  struct wined3d_matrix projection;
1560 
1561  get_projection_matrix(context, state, &projection);
1562  GL_EXTCALL(glUniformMatrix4fv(prog->vs.projection_matrix_location, 1, FALSE, &projection._11));
1563  checkGLcall("glUniformMatrix4fv");
1564  }
1565 
1566  if (update_mask & WINED3D_SHADER_CONST_FFP_TEXMATRIX)
1567  {
1568  for (i = 0; i < MAX_TEXTURES; ++i)
1569  shader_glsl_ffp_vertex_texmatrix_uniform(context, state, i, prog);
1570  }
1571 
1572  if (update_mask & WINED3D_SHADER_CONST_FFP_MATERIAL)
1573  shader_glsl_ffp_vertex_material_uniform(context, state, prog);
1574 
1575  if (update_mask & WINED3D_SHADER_CONST_FFP_LIGHTS)
1576  {
1577  unsigned int point_idx, spot_idx, directional_idx, parallel_point_idx;
1578  DWORD point_count = 0;
1579  DWORD spot_count = 0;
1580  DWORD directional_count = 0;
1581  DWORD parallel_point_count = 0;
1582 
1583  for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i)
1584  {
1585  if (!state->lights[i])
1586  continue;
1587 
1588  switch (state->lights[i]->OriginalParms.type)
1589  {
1590  case WINED3D_LIGHT_POINT:
1591  ++point_count;
1592  break;
1593  case WINED3D_LIGHT_SPOT:
1594  ++spot_count;
1595  break;
1597  ++directional_count;
1598  break;
1600  ++parallel_point_count;
1601  break;
1602  default:
1603  FIXME("Unhandled light type %#x.\n", state->lights[i]->OriginalParms.type);
1604  break;
1605  }
1606  }
1607  point_idx = 0;
1608  spot_idx = point_idx + point_count;
1609  directional_idx = spot_idx + spot_count;
1610  parallel_point_idx = directional_idx + directional_count;
1611 
1612  shader_glsl_ffp_vertex_lightambient_uniform(context, state, prog);
1613  for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i)
1614  {
1615  const struct wined3d_light_info *light_info = state->lights[i];
1616  unsigned int idx;
1617 
1618  if (!light_info)
1619  continue;
1620 
1621  switch (light_info->OriginalParms.type)
1622  {
1623  case WINED3D_LIGHT_POINT:
1624  idx = point_idx++;
1625  break;
1626  case WINED3D_LIGHT_SPOT:
1627  idx = spot_idx++;
1628  break;
1630  idx = directional_idx++;
1631  break;
1633  idx = parallel_point_idx++;
1634  break;
1635  default:
1636  FIXME("Unhandled light type %#x.\n", light_info->OriginalParms.type);
1637  continue;
1638  }
1639  shader_glsl_ffp_vertex_light_uniform(context, state, idx, light_info, prog);
1640  }
1641  }
1642 
1643  if (update_mask & WINED3D_SHADER_CONST_PS_F)
1644  shader_glsl_load_constants_f(pshader, gl_info, state->ps_consts_f,
1645  prog->ps.uniform_f_locations, &priv->pconst_heap, priv->stack, constant_version);
1646 
1647  if (update_mask & WINED3D_SHADER_CONST_PS_I)
1648  shader_glsl_load_constants_i(pshader, gl_info, state->ps_consts_i,
1649  prog->ps.uniform_i_locations, pshader->reg_maps.integer_constants);
1650 
1651  if (update_mask & WINED3D_SHADER_CONST_PS_B)
1652  shader_glsl_load_constantsB(pshader, gl_info, prog->ps.uniform_b_locations, state->ps_consts_b,
1653  pshader->reg_maps.boolean_constants);
1654 
1655  if (update_mask & WINED3D_SHADER_CONST_PS_BUMP_ENV)
1656  {
1657  for (i = 0; i < MAX_TEXTURES; ++i)
1658  {
1659  if (prog->ps.bumpenv_mat_location[i] == -1)
1660  continue;
1661 
1662  GL_EXTCALL(glUniformMatrix2fv(prog->ps.bumpenv_mat_location[i], 1, 0,
1663  (const GLfloat *)&state->texture_states[i][WINED3D_TSS_BUMPENV_MAT00]));
1664 
1665  if (prog->ps.bumpenv_lum_scale_location[i] != -1)
1666  {
1667  GL_EXTCALL(glUniform1fv(prog->ps.bumpenv_lum_scale_location[i], 1,
1668  (const GLfloat *)&state->texture_states[i][WINED3D_TSS_BUMPENV_LSCALE]));
1669  GL_EXTCALL(glUniform1fv(prog->ps.bumpenv_lum_offset_location[i], 1,
1670  (const GLfloat *)&state->texture_states[i][WINED3D_TSS_BUMPENV_LOFFSET]));
1671  }
1672  }
1673 
1674  checkGLcall("bump env uniforms");
1675  }
1676 
1677  if (update_mask & WINED3D_SHADER_CONST_PS_Y_CORR)
1678  {
1679  const struct wined3d_vec4 correction_params =
1680  {
1681  /* Position is relative to the framebuffer, not the viewport. */
1682  context->render_offscreen ? 0.0f : (float)state->fb->render_targets[0]->height,
1683  context->render_offscreen ? 1.0f : -1.0f,
1684  0.0f,
1685  0.0f,
1686  };
1687 
1688  GL_EXTCALL(glUniform4fv(prog->ps.ycorrection_location, 1, &correction_params.x));
1689  }
1690 
1691  if (update_mask & WINED3D_SHADER_CONST_PS_NP2_FIXUP)
1692  shader_glsl_load_np2fixup_constants(&prog->ps, gl_info, state);
1693  if (update_mask & WINED3D_SHADER_CONST_FFP_COLOR_KEY)
1694  shader_glsl_load_color_key_constant(&prog->ps, gl_info, state);
1695 
1696  if (update_mask & WINED3D_SHADER_CONST_FFP_PS)
1697  {
1698  struct wined3d_color color;
1699 
1700  if (prog->ps.tex_factor_location != -1)
1701  {
1703  GL_EXTCALL(glUniform4fv(prog->ps.tex_factor_location, 1, &color.r));
1704  }
1705 
1707  GL_EXTCALL(glUniform4f(prog->ps.specular_enable_location, 1.0f, 1.0f, 1.0f, 0.0f));
1708  else
1709  GL_EXTCALL(glUniform4f(prog->ps.specular_enable_location, 0.0f, 0.0f, 0.0f, 0.0f));
1710 
1711  for (i = 0; i < MAX_TEXTURES; ++i)
1712  {
1713  if (prog->ps.tss_constant_location[i] == -1)
1714  continue;
1715 
1717  GL_EXTCALL(glUniform4fv(prog->ps.tss_constant_location[i], 1, &color.r));
1718  }
1719 
1720  checkGLcall("fixed function uniforms");
1721  }
1722 
1723  if (update_mask & WINED3D_SHADER_CONST_PS_FOG)
1724  shader_glsl_load_fog_uniform(context, state, prog);
1725 
1726  if (update_mask & WINED3D_SHADER_CONST_PS_ALPHA_TEST)
1727  {
1728  float ref = state->render_states[WINED3D_RS_ALPHAREF] / 255.0f;
1729 
1730  GL_EXTCALL(glUniform1f(prog->ps.alpha_test_ref_location, ref));
1731  checkGLcall("alpha test emulation uniform");
1732  }
1733 
1734  if (priv->next_constant_version == UINT_MAX)
1735  {
1736  TRACE("Max constant version reached, resetting to 0.\n");
1738  priv->next_constant_version = 1;
1739  }
1740  else
1741  {
1742  prog->constant_version = priv->next_constant_version++;
1743  }
1744 }
1745 
1746 static void update_heap_entry(struct constant_heap *heap, unsigned int idx, DWORD new_version)
1747 {
1748  struct constant_entry *entries = heap->entries;
1749  unsigned int *positions = heap->positions;
1750  unsigned int heap_idx, parent_idx;
1751 
1752  if (!heap->contained[idx])
1753  {
1754  heap_idx = heap->size++;
1755  heap->contained[idx] = TRUE;
1756  }
1757  else
1758  {
1759  heap_idx = positions[idx];
1760  }
1761 
1762  while (heap_idx > 1)
1763  {
1764  parent_idx = heap_idx >> 1;
1765 
1766  if (new_version <= entries[parent_idx].version) break;
1767 
1768  entries[heap_idx] = entries[parent_idx];
1769  positions[entries[parent_idx].idx] = heap_idx;
1770  heap_idx = parent_idx;
1771  }
1772 
1773  entries[heap_idx].version = new_version;
1774  entries[heap_idx].idx = idx;
1775  positions[idx] = heap_idx;
1776 }
1777 
1779 {
1780  struct shader_glsl_priv *priv = device->shader_priv;
1781  struct constant_heap *heap = &priv->vconst_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 
1791 {
1792  struct shader_glsl_priv *priv = device->shader_priv;
1793  struct constant_heap *heap = &priv->pconst_heap;
1794  UINT i;
1795 
1796  for (i = start; i < count + start; ++i)
1797  {
1798  update_heap_entry(heap, i, priv->next_constant_version);
1799  }
1800 }
1801 
1802 static unsigned int vec4_varyings(DWORD shader_major, const struct wined3d_gl_info *gl_info)
1803 {
1804  unsigned int ret = gl_info->limits.glsl_varyings / 4;
1805  /* 4.0 shaders do not write clip coords because d3d10 does not support user clipplanes */
1806  if(shader_major > 3) return ret;
1807 
1808  /* 3.0 shaders may need an extra varying for the clip coord on some cards(mostly dx10 ones) */
1809  if (gl_info->quirks & WINED3D_QUIRK_GLSL_CLIP_VARYING) ret -= 1;
1810  return ret;
1811 }
1812 
1813 static BOOL needs_legacy_glsl_syntax(const struct wined3d_gl_info *gl_info)
1814 {
1815  return gl_info->glsl_version < MAKEDWORD_VERSION(1, 30);
1816 }
1817 
1819 {
1820  return gl_info->supported[ARB_EXPLICIT_ATTRIB_LOCATION]
1822 }
1823 
1825 {
1826  return shader_glsl_get_version(gl_info) >= 150;
1827 }
1828 
1829 static const char *get_attribute_keyword(const struct wined3d_gl_info *gl_info)
1830 {
1831  return needs_legacy_glsl_syntax(gl_info) ? "attribute" : "in";
1832 }
1833 
1834 static void PRINTF_ATTR(4, 5) declare_in_varying(const struct wined3d_gl_info *gl_info,
1835  struct wined3d_string_buffer *buffer, BOOL flat, const char *format, ...)
1836 {
1837  va_list args;
1838  int ret;
1839 
1840  shader_addline(buffer, "%s%s ", flat ? "flat " : "",
1841  needs_legacy_glsl_syntax(gl_info) ? "varying" : "in");
1842  for (;;)
1843  {
1844  va_start(args, format);
1845  ret = shader_vaddline(buffer, format, args);
1846  va_end(args);
1847  if (!ret)
1848  return;
1849  if (!string_buffer_resize(buffer, ret))
1850  return;
1851  }
1852 }
1853 
1854 static void PRINTF_ATTR(4, 5) declare_out_varying(const struct wined3d_gl_info *gl_info,
1855  struct wined3d_string_buffer *buffer, BOOL flat, const char *format, ...)
1856 {
1857  va_list args;
1858  int ret;
1859 
1860  shader_addline(buffer, "%s%s ", flat ? "flat " : "",
1861  needs_legacy_glsl_syntax(gl_info) ? "varying" : "out");
1862  for (;;)
1863  {
1864  va_start(args, format);
1865  ret = shader_vaddline(buffer, format, args);
1866  va_end(args);
1867  if (!ret)
1868  return;
1869  if (!string_buffer_resize(buffer, ret))
1870  return;
1871  }
1872 }
1873 
1874 static const char *shader_glsl_shader_input_name(const struct wined3d_gl_info *gl_info)
1875 {
1876  return shader_glsl_use_interface_blocks(gl_info) ? "shader_in.reg" : "ps_link";
1877 }
1878 
1879 static const char *shader_glsl_shader_output_name(const struct wined3d_gl_info *gl_info)
1880 {
1881  return shader_glsl_use_interface_blocks(gl_info) ? "shader_out.reg" : "ps_link";
1882 }
1883 
1885 {
1886  switch (mode)
1887  {
1888  case WINED3DSIM_CONSTANT:
1889  return "flat";
1891  return "noperspective";
1892  default:
1893  FIXME("Unhandled interpolation mode %#x.\n", mode);
1894  case WINED3DSIM_NONE:
1895  case WINED3DSIM_LINEAR:
1896  return "";
1897  }
1898 }
1899 
1901  const DWORD *packed_interpolation_mode, unsigned int register_idx)
1902 {
1903  return wined3d_extract_bits(packed_interpolation_mode,
1904  register_idx * WINED3D_PACKED_INTERPOLATION_BIT_COUNT, WINED3D_PACKED_INTERPOLATION_BIT_COUNT);
1905 }
1906 
1907 static void shader_glsl_declare_shader_inputs(const struct wined3d_gl_info *gl_info,
1908  struct wined3d_string_buffer *buffer, unsigned int element_count,
1909  const DWORD *interpolation_mode, BOOL unroll)
1910 {
1912  unsigned int i;
1913 
1914  if (shader_glsl_use_interface_blocks(gl_info))
1915  {
1916  if (unroll)
1917  {
1918  shader_addline(buffer, "in shader_in_out {\n");
1919  for (i = 0; i < element_count; ++i)
1920  {
1921  mode = wined3d_extract_interpolation_mode(interpolation_mode, i);
1922  shader_addline(buffer, "%s vec4 reg%u;\n", shader_glsl_interpolation_qualifiers(mode), i);
1923  }
1924  shader_addline(buffer, "} shader_in;\n");
1925  }
1926  else
1927  {
1928  shader_addline(buffer, "in shader_in_out { vec4 reg[%u]; } shader_in;\n", element_count);
1929  }
1930  }
1931  else
1932  {
1933  declare_in_varying(gl_info, buffer, FALSE, "vec4 ps_link[%u];\n", element_count);
1934  }
1935 }
1936 
1937 static void shader_glsl_declare_shader_outputs(const struct wined3d_gl_info *gl_info,
1938  struct wined3d_string_buffer *buffer, unsigned int element_count, BOOL rasterizer_setup,
1939  const DWORD *interpolation_mode)
1940 {
1942  unsigned int i;
1943 
1944  if (shader_glsl_use_interface_blocks(gl_info))
1945  {
1946  if (rasterizer_setup)
1947  {
1948  shader_addline(buffer, "out shader_in_out {\n");
1949  for (i = 0; i < element_count; ++i)
1950  {
1951  const char *interpolation_qualifiers = "";
1953  {
1954  mode = wined3d_extract_interpolation_mode(interpolation_mode, i);
1955  interpolation_qualifiers = shader_glsl_interpolation_qualifiers(mode);
1956  }
1957  shader_addline(buffer, "%s vec4 reg%u;\n", interpolation_qualifiers, i);
1958  }
1959  shader_addline(buffer, "} shader_out;\n");
1960  }
1961  else
1962  {
1963  shader_addline(buffer, "out shader_in_out { vec4 reg[%u]; } shader_out;\n", element_count);
1964  }
1965  }
1966  else
1967  {
1968  declare_out_varying(gl_info, buffer, FALSE, "vec4 ps_link[%u];\n", element_count);
1969  }
1970 }
1971 
1972 static const char *get_fragment_output(const struct wined3d_gl_info *gl_info)
1973 {
1974  return needs_legacy_glsl_syntax(gl_info) ? "gl_FragData" : "ps_out";
1975 }
1976 
1977 static const char *glsl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type)
1978 {
1979  switch (primitive_type)
1980  {
1981  case WINED3D_PT_POINTLIST:
1982  return "points";
1983 
1984  case WINED3D_PT_LINELIST:
1985  return "lines";
1986 
1987  case WINED3D_PT_LINESTRIP:
1988  return "line_strip";
1989 
1991  return "triangles";
1992 
1994  return "triangle_strip";
1995 
1997  return "lines_adjacency";
1998 
2000  return "triangles_adjacency";
2001 
2002  default:
2003  FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(primitive_type));
2004  return "";
2005  }
2006 }
2007 
2008 static BOOL glsl_is_color_reg_read(const struct wined3d_shader *shader, unsigned int idx)
2009 {
2010  const struct wined3d_shader_signature *input_signature = &shader->input_signature;
2011  const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
2012  DWORD input_reg_used = shader->u.ps.input_reg_used;
2013  unsigned int i;
2014 
2015  if (reg_maps->shader_version.major < 3)
2016  return input_reg_used & (1u << idx);
2017 
2018  for (i = 0; i < input_signature->element_count; ++i)
2019  {
2020  const struct wined3d_shader_signature_element *input = &input_signature->elements[i];
2021 
2022  if (!(reg_maps->input_registers & (1u << input->register_idx)))
2023  continue;
2024 
2026  && input->semantic_idx == idx)
2027  return input_reg_used & (1u << input->register_idx);
2028  }
2029  return FALSE;
2030 }
2031 
2033  const struct ps_compile_args *ps_args, unsigned int resource_idx, unsigned int sampler_idx)
2034 {
2035  const struct wined3d_shader_version *version = &shader->reg_maps.shader_version;
2036 
2037  if (version->major >= 4)
2038  return shader->reg_maps.sampler_comparison_mode & (1u << sampler_idx);
2039  else
2040  return version->type == WINED3D_SHADER_TYPE_PIXEL && (ps_args->shadow & (1u << resource_idx));
2041 }
2042 
2044  const struct wined3d_gl_info *gl_info, const char *vector_type, const char *scalar_type,
2045  unsigned int index)
2046 {
2047  shader_addline(buffer, "%s %s4 vs_in_%s%u;\n",
2048  get_attribute_keyword(gl_info), vector_type, scalar_type, index);
2049  shader_addline(buffer, "vec4 vs_in%u = %sBitsToFloat(vs_in_%s%u);\n",
2050  index, scalar_type, scalar_type, index);
2051 }
2052 
2054  const struct wined3d_gl_info *gl_info, const struct wined3d_shader_signature_element *e)
2055 {
2056  unsigned int index = e->register_idx;
2057 
2059  {
2060  shader_addline(buffer, "vec4 vs_in%u = vec4(intBitsToFloat(gl_VertexID), 0.0, 0.0, 0.0);\n",
2061  index);
2062  return;
2063  }
2065  {
2066  shader_addline(buffer, "vec4 vs_in%u = vec4(intBitsToFloat(gl_InstanceID), 0.0, 0.0, 0.0);\n",
2067  index);
2068  return;
2069  }
2071  FIXME("Unhandled sysval semantic %#x.\n", e->sysval_semantic);
2072 
2074  shader_addline(buffer, "layout(location = %u) ", index);
2075 
2076  switch (e->component_type)
2077  {
2078  case WINED3D_TYPE_UINT:
2079  shader_glsl_declare_typed_vertex_attribute(buffer, gl_info, "uvec", "uint", index);
2080  break;
2081  case WINED3D_TYPE_INT:
2082  shader_glsl_declare_typed_vertex_attribute(buffer, gl_info, "ivec", "int", index);
2083  break;
2084 
2085  default:
2086  FIXME("Unhandled type %#x.\n", e->component_type);
2087  /* Fall through. */
2088  case WINED3D_TYPE_UNKNOWN:
2089  case WINED3D_TYPE_FLOAT:
2090  shader_addline(buffer, "%s vec4 vs_in%u;\n", get_attribute_keyword(gl_info), index);
2091  break;
2092  }
2093 }
2094 
2097  struct wined3d_string_buffer *buffer, const struct wined3d_shader *shader,
2098  const struct wined3d_shader_reg_maps *reg_maps, const struct shader_glsl_ctx_priv *ctx_priv)
2099 {
2100  const struct wined3d_shader_version *version = &reg_maps->shader_version;
2101  const struct vs_compile_args *vs_args = ctx_priv->cur_vs_args;
2102  const struct ps_compile_args *ps_args = ctx_priv->cur_ps_args;
2103  const struct wined3d_gl_info *gl_info = context->gl_info;
2104  const struct wined3d_shader_indexable_temp *idx_temp_reg;
2105  unsigned int uniform_block_base, uniform_block_count;
2106  const struct wined3d_shader_lconst *lconst;
2107  const char *prefix;
2108  unsigned int i;
2109  DWORD map;
2110 
2111  prefix = shader_glsl_get_prefix(version->type);
2112 
2113  /* Prototype the subroutines */
2114  for (i = 0, map = reg_maps->labels; map; map >>= 1, ++i)
2115  {
2116  if (map & 1) shader_addline(buffer, "void subroutine%u();\n", i);
2117  }
2118 
2119  /* Declare the constants (aka uniforms) */
2120  if (shader->limits->constant_float > 0)
2121  {
2122  unsigned max_constantsF;
2123 
2124  /* Unless the shader uses indirect addressing, always declare the
2125  * maximum array size and ignore that we need some uniforms privately.
2126  * E.g. if GL supports 256 uniforms, and we need 2 for the pos fixup
2127  * and immediate values, still declare VC[256]. If the shader needs
2128  * more uniforms than we have it won't work in any case. If it uses
2129  * less, the compiler will figure out which uniforms are really used
2130  * and strip them out. This allows a shader to use c255 on a dx9 card,
2131  * as long as it doesn't also use all the other constants.
2132  *
2133  * If the shader uses indirect addressing the compiler must assume
2134  * that all declared uniforms are used. In this case, declare only the
2135  * amount that we're assured to have.
2136  *
2137  * Thus we run into problems in these two cases:
2138  * 1) The shader really uses more uniforms than supported.
2139  * 2) The shader uses indirect addressing, less constants than
2140  * supported, but uses a constant index > #supported consts. */
2141  if (version->type == WINED3D_SHADER_TYPE_PIXEL)
2142  {
2143  /* No indirect addressing here. */
2144  max_constantsF = gl_info->limits.glsl_ps_float_constants;
2145  }
2146  else
2147  {
2148  if (reg_maps->usesrelconstF)
2149  {
2150  /* Subtract the other potential uniforms from the max
2151  * available (bools, ints, and 1 row of projection matrix).
2152  * Subtract another uniform for immediate values, which have
2153  * to be loaded via uniform by the driver as well. The shader
2154  * code only uses 0.5, 2.0, 1.0, 128 and -128 in vertex
2155  * shader code, so one vec4 should be enough. (Unfortunately
2156  * the Nvidia driver doesn't store 128 and -128 in one float).
2157  *
2158  * Writing gl_ClipVertex requires one uniform for each
2159  * clipplane as well. */
2160  max_constantsF = gl_info->limits.glsl_vs_float_constants - 3;
2161  if (vs_args->clip_enabled)
2162  max_constantsF -= gl_info->limits.user_clip_distances;
2163  max_constantsF -= wined3d_popcount(reg_maps->integer_constants);
2164  /* Strictly speaking a bool only uses one scalar, but the nvidia(Linux) compiler doesn't pack them properly,
2165  * so each scalar requires a full vec4. We could work around this by packing the booleans ourselves, but
2166  * for now take this into account when calculating the number of available constants
2167  */
2168  max_constantsF -= wined3d_popcount(reg_maps->boolean_constants);
2169  /* Set by driver quirks in directx.c */
2170  max_constantsF -= gl_info->reserved_glsl_constants;
2171 
2172  if (max_constantsF < shader->limits->constant_float)
2173  {
2174  static unsigned int once;
2175 
2176  if (!once++)
2177  ERR_(winediag)("The hardware does not support enough uniform components to run this shader,"
2178  " it may not render correctly.\n");
2179  else
2180  WARN("The hardware does not support enough uniform components to run this shader.\n");
2181  }
2182  }
2183  else
2184  {
2185  max_constantsF = gl_info->limits.glsl_vs_float_constants;
2186  }
2187  }
2188  max_constantsF = min(shader->limits->constant_float, max_constantsF);
2189  shader_addline(buffer, "uniform vec4 %s_c[%u];\n", prefix, max_constantsF);
2190  }
2191 
2192  /* Always declare the full set of constants, the compiler can remove the
2193  * unused ones because d3d doesn't (yet) support indirect int and bool
2194  * constant addressing. This avoids problems if the app uses e.g. i0 and i9. */
2195  if (shader->limits->constant_int > 0 && reg_maps->integer_constants)
2196  shader_addline(buffer, "uniform ivec4 %s_i[%u];\n", prefix, shader->limits->constant_int);
2197 
2198  if (shader->limits->constant_bool > 0 && reg_maps->boolean_constants)
2199  shader_addline(buffer, "uniform bool %s_b[%u];\n", prefix, shader->limits->constant_bool);
2200 
2201  /* Declare immediate constant buffer */
2202  if (reg_maps->icb)
2203  shader_addline(buffer, "uniform vec4 %s_icb[%u];\n", prefix, reg_maps->icb->vec4_count);
2204 
2205  /* Declare constant buffers */
2207  &uniform_block_base, &uniform_block_count);
2208  for (i = 0; i < min(uniform_block_count, WINED3D_MAX_CBS); ++i)
2209  {
2210  if (reg_maps->cb_sizes[i])
2211  {
2212  shader_addline(buffer, "layout(std140");
2214  shader_addline(buffer, ", binding = %u", uniform_block_base + i);
2215  shader_addline(buffer, ") uniform block_%s_cb%u { vec4 %s_cb%u[%u]; };\n",
2216  prefix, i, prefix, i, reg_maps->cb_sizes[i]);
2217  }
2218  }
2219 
2220  /* Declare texture samplers */
2221  for (i = 0; i < reg_maps->sampler_map.count; ++i)
2222  {
2224  const char *sampler_type_prefix, *sampler_type;
2225  BOOL shadow_sampler, tex_rect;
2226 
2227  entry = &reg_maps->sampler_map.entries[i];
2228 
2229  if (entry->resource_idx >= ARRAY_SIZE(reg_maps->resource_info))
2230  {
2231  ERR("Invalid resource index %u.\n", entry->resource_idx);
2232  continue;
2233  }
2234 
2235  switch (reg_maps->resource_info[entry->resource_idx].data_type)
2236  {
2237  case WINED3D_DATA_FLOAT:
2238  case WINED3D_DATA_UNORM:
2239  case WINED3D_DATA_SNORM:
2240  sampler_type_prefix = "";
2241  break;
2242 
2243  case WINED3D_DATA_INT:
2244  sampler_type_prefix = "i";
2245  break;
2246 
2247  case WINED3D_DATA_UINT:
2248  sampler_type_prefix = "u";
2249  break;
2250 
2251  default:
2252  sampler_type_prefix = "";
2253  ERR("Unhandled resource data type %#x.\n", reg_maps->resource_info[i].data_type);
2254  break;
2255  }
2256 
2257  shadow_sampler = glsl_is_shadow_sampler(shader, ps_args, entry->resource_idx, entry->sampler_idx);
2258  switch (reg_maps->resource_info[entry->resource_idx].type)
2259  {
2261  sampler_type = "samplerBuffer";
2262  break;
2263 
2265  if (shadow_sampler)
2266  sampler_type = "sampler1DShadow";
2267  else
2268  sampler_type = "sampler1D";
2269  break;
2270 
2272  tex_rect = version->type == WINED3D_SHADER_TYPE_PIXEL
2273  && (ps_args->np2_fixup & (1u << entry->resource_idx))
2274  && gl_info->supported[ARB_TEXTURE_RECTANGLE];
2275  if (shadow_sampler)
2276  {
2277  if (tex_rect)
2278  sampler_type = "sampler2DRectShadow";
2279  else
2280  sampler_type = "sampler2DShadow";
2281  }
2282  else
2283  {
2284  if (tex_rect)
2285  sampler_type = "sampler2DRect";
2286  else
2287  sampler_type = "sampler2D";
2288  }
2289  break;
2290 
2292  if (shadow_sampler)
2293  FIXME("Unsupported 3D shadow sampler.\n");
2294  sampler_type = "sampler3D";
2295  break;
2296 
2298  if (shadow_sampler)
2299  sampler_type = "samplerCubeShadow";
2300  else
2301  sampler_type = "samplerCube";
2302  break;
2303 
2305  if (shadow_sampler)
2306  sampler_type = "sampler1DArrayShadow";
2307  else
2308  sampler_type = "sampler1DArray";
2309  break;
2310 
2312  if (shadow_sampler)
2313  sampler_type = "sampler2DArrayShadow";
2314  else
2315  sampler_type = "sampler2DArray";
2316  break;
2317 
2319  if (shadow_sampler)
2320  sampler_type = "samplerCubeArrayShadow";
2321  else
2322  sampler_type = "samplerCubeArray";
2323  break;
2324 
2326  sampler_type = "sampler2DMS";
2327  break;
2328 
2330  sampler_type = "sampler2DMSArray";
2331  break;
2332 
2333  default:
2334  sampler_type = "unsupported_sampler";
2335  FIXME("Unhandled resource type %#x.\n", reg_maps->resource_info[entry->resource_idx].type);
2336  break;
2337  }
2338 
2340  shader_glsl_append_sampler_binding_qualifier(buffer, context, version, entry->bind_idx);
2341  shader_addline(buffer, "uniform %s%s %s_sampler%u;\n",
2342  sampler_type_prefix, sampler_type, prefix, entry->bind_idx);
2343  }
2344 
2345  /* Declare images */
2346  for (i = 0; i < ARRAY_SIZE(reg_maps->uav_resource_info); ++i)
2347  {
2348  const char *image_type_prefix, *image_type, *read_format;
2349 
2350  if (!reg_maps->uav_resource_info[i].type)
2351  continue;
2352 
2353  switch (reg_maps->uav_resource_info[i].data_type)
2354  {
2355  case WINED3D_DATA_FLOAT:
2356  case WINED3D_DATA_UNORM:
2357  case WINED3D_DATA_SNORM:
2358  image_type_prefix = "";
2359  read_format = "r32f";
2360  break;
2361 
2362  case WINED3D_DATA_INT:
2363  image_type_prefix = "i";
2364  read_format = "r32i";
2365  break;
2366 
2367  case WINED3D_DATA_UINT:
2368  image_type_prefix = "u";
2369  read_format = "r32ui";
2370  break;
2371 
2372  default:
2373  image_type_prefix = "";
2374  read_format = "";
2375  ERR("Unhandled resource data type %#x.\n", reg_maps->uav_resource_info[i].data_type);
2376  break;
2377  }
2378 
2379  switch (reg_maps->uav_resource_info[i].type)
2380  {
2382  image_type = "imageBuffer";
2383  break;
2384 
2386  image_type = "image2D";
2387  break;
2388 
2390  image_type = "image3D";
2391  break;
2392 
2394  image_type = "image2DArray";
2395  break;
2396 
2397  default:
2398  image_type = "unsupported_image";
2399  FIXME("Unhandled resource type %#x.\n", reg_maps->uav_resource_info[i].type);
2400  break;
2401  }
2402 
2404  shader_addline(buffer, "layout(binding = %u)\n", i);
2405  if (reg_maps->uav_read_mask & (1u << i))
2406  shader_addline(buffer, "layout(%s) uniform %s%s %s_image%u;\n",
2407  read_format, image_type_prefix, image_type, prefix, i);
2408  else
2409  shader_addline(buffer, "writeonly uniform %s%s %s_image%u;\n",
2410  image_type_prefix, image_type, prefix, i);
2411 
2412  if (reg_maps->uav_counter_mask & (1u << i))
2413  shader_addline(buffer, "layout(binding = %u) uniform atomic_uint %s_counter%u;\n",
2414  i, prefix, i);
2415  }
2416 
2417  /* Declare address variables */
2418  for (i = 0, map = reg_maps->address; map; map >>= 1, ++i)
2419  {
2420  if (map & 1) shader_addline(buffer, "ivec4 A%u;\n", i);
2421  }
2422 
2423  /* Declare output register temporaries */
2424  if (shader->limits->packed_output)
2425  shader_addline(buffer, "vec4 %s_out[%u];\n", prefix, shader->limits->packed_output);
2426 
2427  /* Declare temporary variables */
2428  if (reg_maps->temporary_count)
2429  {
2430  for (i = 0; i < reg_maps->temporary_count; ++i)
2431  shader_addline(buffer, "vec4 R%u;\n", i);
2432  }
2433  else if (version->major < 4)
2434  {
2435  for (i = 0, map = reg_maps->temporary; map; map >>= 1, ++i)
2436  {
2437  if (map & 1)
2438  shader_addline(buffer, "vec4 R%u;\n", i);
2439  }
2440  }
2441 
2442  /* Declare indexable temporary variables */
2443  LIST_FOR_EACH_ENTRY(idx_temp_reg, &reg_maps->indexable_temps, struct wined3d_shader_indexable_temp, entry)
2444  {
2445  if (idx_temp_reg->component_count != 4)
2446  FIXME("Ignoring component count %u.\n", idx_temp_reg->component_count);
2447  shader_addline(buffer, "vec4 X%u[%u];\n", idx_temp_reg->register_idx, idx_temp_reg->register_size);
2448  }
2449 
2450  /* Declare loop registers aLx */
2451  if (version->major < 4)
2452  {
2453  for (i = 0; i < reg_maps->loop_depth; ++i)
2454  {
2455  shader_addline(buffer, "int aL%u;\n", i);
2456  shader_addline(buffer, "int tmpInt%u;\n", i);
2457  }
2458  }
2459 
2460  /* Temporary variables for matrix operations */
2461  shader_addline(buffer, "vec4 tmp0;\n");
2462  shader_addline(buffer, "vec4 tmp1;\n");
2463 
2464  if (!shader->load_local_constsF)
2465  {
2466  LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, struct wined3d_shader_lconst, entry)
2467  {
2468  shader_addline(buffer, "const vec4 %s_lc%u = ", prefix, lconst->idx);
2469  shader_glsl_append_imm_vec4(buffer, (const float *)lconst->value);
2470  shader_addline(buffer, ";\n");
2471  }
2472  }
2473 }
2474 
2475 /* Prototypes */
2476 static void shader_glsl_add_src_param(const struct wined3d_shader_instruction *ins,
2477  const struct wined3d_shader_src_param *wined3d_src, DWORD mask, struct glsl_src_param *glsl_src);
2478 
2480 static const char * const shift_glsl_tab[] = {
2481  "", /* 0 (none) */
2482  "2.0 * ", /* 1 (x2) */
2483  "4.0 * ", /* 2 (x4) */
2484  "8.0 * ", /* 3 (x8) */
2485  "16.0 * ", /* 4 (x16) */
2486  "32.0 * ", /* 5 (x32) */
2487  "", /* 6 (x64) */
2488  "", /* 7 (x128) */
2489  "", /* 8 (d256) */
2490  "", /* 9 (d128) */
2491  "", /* 10 (d64) */
2492  "", /* 11 (d32) */
2493  "0.0625 * ", /* 12 (d16) */
2494  "0.125 * ", /* 13 (d8) */
2495  "0.25 * ", /* 14 (d4) */
2496  "0.5 * " /* 15 (d2) */
2497 };
2498 
2499 /* Generate a GLSL parameter that does the input modifier computation and return the input register/mask to use */
2501  const char *in_reg, const char *in_regswizzle, char *out_str)
2502 {
2503  switch (src_modifier)
2504  {
2505  case WINED3DSPSM_DZ: /* Need to handle this in the instructions itself (texld & texcrd). */
2506  case WINED3DSPSM_DW:
2507  case WINED3DSPSM_NONE:
2508  sprintf(out_str, "%s%s", in_reg, in_regswizzle);
2509  break;
2510  case WINED3DSPSM_NEG:
2511  sprintf(out_str, "-%s%s", in_reg, in_regswizzle);
2512  break;
2513  case WINED3DSPSM_NOT:
2514  sprintf(out_str, "!%s%s", in_reg, in_regswizzle);
2515  break;
2516  case WINED3DSPSM_BIAS:
2517  sprintf(out_str, "(%s%s - vec4(0.5)%s)", in_reg, in_regswizzle, in_regswizzle);
2518  break;
2519  case WINED3DSPSM_BIASNEG:
2520  sprintf(out_str, "-(%s%s - vec4(0.5)%s)", in_reg, in_regswizzle, in_regswizzle);
2521  break;
2522  case WINED3DSPSM_SIGN:
2523  sprintf(out_str, "(2.0 * (%s%s - 0.5))", in_reg, in_regswizzle);
2524  break;
2525  case WINED3DSPSM_SIGNNEG:
2526  sprintf(out_str, "-(2.0 * (%s%s - 0.5))", in_reg, in_regswizzle);
2527  break;
2528  case WINED3DSPSM_COMP:
2529  sprintf(out_str, "(1.0 - %s%s)", in_reg, in_regswizzle);
2530  break;
2531  case WINED3DSPSM_X2:
2532  sprintf(out_str, "(2.0 * %s%s)", in_reg, in_regswizzle);
2533  break;
2534  case WINED3DSPSM_X2NEG:
2535  sprintf(out_str, "-(2.0 * %s%s)", in_reg, in_regswizzle);
2536  break;
2537  case WINED3DSPSM_ABS:
2538  sprintf(out_str, "abs(%s%s)", in_reg, in_regswizzle);
2539  break;
2540  case WINED3DSPSM_ABSNEG:
2541  sprintf(out_str, "-abs(%s%s)", in_reg, in_regswizzle);
2542  break;
2543  default:
2544  FIXME("Unhandled modifier %u\n", src_modifier);
2545  sprintf(out_str, "%s%s", in_reg, in_regswizzle);
2546  }
2547 }
2548 
2549 static void shader_glsl_fixup_scalar_register_variable(char *register_name,
2550  const char *glsl_variable, const struct wined3d_gl_info *gl_info)
2551 {
2552  /* The ARB_shading_language_420pack extension allows swizzle operations on
2553  * scalars. */
2555  sprintf(register_name, "%s", glsl_variable);
2556  else
2557  sprintf(register_name, "ivec2(%s, 0)", glsl_variable);
2558 }
2559 
2563  enum wined3d_data_type data_type, char *register_name, BOOL *is_color,
2564  const struct wined3d_shader_instruction *ins)
2565 {
2566  /* oPos, oFog and oPts in D3D */
2567  static const char * const hwrastout_reg_names[] = {"vs_out[10]", "vs_out[11].x", "vs_out[11].y"};
2568 
2569  const struct wined3d_shader *shader = ins->ctx->shader;
2570  const struct wined3d_shader_reg_maps *reg_maps = ins->ctx->reg_maps;
2571  const struct wined3d_shader_version *version = &reg_maps->shader_version;
2572  const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
2573  const char *prefix = shader_glsl_get_prefix(version->type);
2574  struct glsl_src_param rel_param0, rel_param1;
2575  char imm_str[4][17];
2576 
2577  if (reg->idx[0].offset != ~0U && reg->idx[0].rel_addr)
2578  shader_glsl_add_src_param(ins, reg->idx[0].rel_addr, WINED3DSP_WRITEMASK_0, &rel_param0);
2579  if (reg->idx[1].offset != ~0U && reg->idx[1].rel_addr)
2580  shader_glsl_add_src_param(ins, reg->idx[1].rel_addr, WINED3DSP_WRITEMASK_0, &rel_param1);
2581  *is_color = FALSE;
2582 
2583  switch (reg->type)
2584  {
2585  case WINED3DSPR_TEMP:
2586  sprintf(register_name, "R%u", reg->idx[0].offset);
2587  break;
2588 
2589  case WINED3DSPR_INPUT:
2591  if (version->type == WINED3D_SHADER_TYPE_VERTEX)
2592  {
2593  struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
2594 
2595  if (reg->idx[0].rel_addr)
2596  FIXME("VS3 input registers relative addressing.\n");
2597  if (priv->cur_vs_args->swizzle_map & (1u << reg->idx[0].offset))
2598  *is_color = TRUE;
2599  if (reg->idx[0].rel_addr)
2600  {
2601  sprintf(register_name, "%s_in[%s + %u]",
2602  prefix, rel_param0.param_str, reg->idx[0].offset);
2603  }
2604  else
2605  {
2606  sprintf(register_name, "%s_in%u", prefix, reg->idx[0].offset);
2607  }
2608  break;
2609  }
2610 
2611  if (version->type == WINED3D_SHADER_TYPE_HULL
2612  || version->type == WINED3D_SHADER_TYPE_DOMAIN
2613  || version->type == WINED3D_SHADER_TYPE_GEOMETRY)
2614  {
2615  if (reg->idx[0].rel_addr)
2616  {
2617  if (reg->idx[1].rel_addr)
2618  sprintf(register_name, "shader_in[%s + %u].reg[%s + %u]",
2619  rel_param0.param_str, reg->idx[0].offset,
2620  rel_param1.param_str, reg->idx[1].offset);
2621  else
2622  sprintf(register_name, "shader_in[%s + %u].reg[%u]",
2623  rel_param0.param_str, reg->idx[0].offset,
2624  reg->idx[1].offset);
2625  }
2626  else if (reg->idx[1].rel_addr)
2627  sprintf(register_name, "shader_in[%u].reg[%s + %u]", reg->idx[0].offset,
2628  rel_param1.param_str, reg->idx[1].offset);
2629  else
2630  sprintf(register_name, "shader_in[%u].reg[%u]",
2631  reg->idx[0].offset, reg->idx[1].offset);
2632  break;
2633  }
2634 
2635  /* pixel shaders >= 3.0 */
2636  if (version->major >= 3)
2637  {
2638  DWORD idx = shader->u.ps.input_reg_map[reg->idx[0].offset];
2639  unsigned int in_count = vec4_varyings(version->major, gl_info);
2640 
2641  if (reg->idx[0].rel_addr)
2642  {
2643  /* Removing a + 0 would be an obvious optimization, but
2644  * OS X doesn't see the NOP operation there. */
2645  if (idx)
2646  {
2647  if (needs_legacy_glsl_syntax(gl_info)
2648  && shader->u.ps.declared_in_count > in_count)
2649  {
2650  sprintf(register_name,
2651  "((%s + %u) > %u ? (%s + %u) > %u ? gl_SecondaryColor : gl_Color : %s_in[%s + %u])",
2652  rel_param0.param_str, idx, in_count - 1, rel_param0.param_str, idx, in_count,
2653  prefix, rel_param0.param_str, idx);
2654  }
2655  else
2656  {
2657  sprintf(register_name, "%s_in[%s + %u]", prefix, rel_param0.param_str, idx);
2658  }
2659  }
2660  else
2661  {
2662  if (needs_legacy_glsl_syntax(gl_info)
2663  && shader->u.ps.declared_in_count > in_count)
2664  {
2665  sprintf(register_name, "((%s) > %u ? (%s) > %u ? gl_SecondaryColor : gl_Color : %s_in[%s])",
2666  rel_param0.param_str, in_count - 1, rel_param0.param_str, in_count,
2667  prefix, rel_param0.param_str);
2668  }
2669  else
2670  {
2671  sprintf(register_name, "%s_in[%s]", prefix, rel_param0.param_str);
2672  }
2673  }
2674  }
2675  else
2676  {
2677  if (idx == in_count) sprintf(register_name, "gl_Color");
2678  else if (idx == in_count + 1) sprintf(register_name, "gl_SecondaryColor");
2679  else sprintf(register_name, "%s_in[%u]", prefix, idx);
2680  }
2681  }
2682  else
2683  {
2684  if (!reg->idx[0].offset)
2685  strcpy(register_name, "ffp_varying_diffuse");
2686  else
2687  strcpy(register_name, "ffp_varying_specular");
2688  break;
2689  }
2690  break;
2691 
2692  case WINED3DSPR_CONST:
2693  {
2694  /* Relative addressing */
2695  if (reg->idx[0].rel_addr)
2696  {
2698  sprintf(register_name, "(%s + %u >= 0 && %s + %u < %u ? %s_c[%s + %u] : vec4(0.0))",
2699  rel_param0.param_str, reg->idx[0].offset,
2700  rel_param0.param_str, reg->idx[0].offset, shader->limits->constant_float,
2701  prefix, rel_param0.param_str, reg->idx[0].offset);
2702  else if (reg->idx[0].offset)
2703  sprintf(register_name, "%s_c[%s + %u]", prefix, rel_param0.param_str, reg->idx[0].offset);
2704  else
2705  sprintf(register_name, "%s_c[%s]", prefix, rel_param0.param_str);
2706  }
2707  else
2708  {
2709  if (shader_constant_is_local(shader, reg->idx[0].offset))
2710  sprintf(register_name, "%s_lc%u", prefix, reg->idx[0].offset);
2711  else
2712  sprintf(register_name, "%s_c[%u]", prefix, reg->idx[0].offset);
2713  }
2714  }
2715  break;
2716 
2717  case WINED3DSPR_CONSTINT:
2718  sprintf(register_name, "%s_i[%u]", prefix, reg->idx[0].offset);
2719  break;
2720 
2721  case WINED3DSPR_CONSTBOOL:
2722  sprintf(register_name, "%s_b[%u]", prefix, reg->idx[0].offset);
2723  break;
2724 
2725  case WINED3DSPR_TEXTURE: /* case WINED3DSPR_ADDR: */
2726  if (version->type == WINED3D_SHADER_TYPE_PIXEL)
2727  sprintf(register_name, "T%u", reg->idx[0].offset);
2728  else
2729  sprintf(register_name, "A%u", reg->idx[0].offset);
2730  break;
2731 
2732  case WINED3DSPR_LOOP:
2733  sprintf(register_name, "aL%u", ins->ctx->state->current_loop_reg - 1);
2734  break;
2735 
2736  case WINED3DSPR_SAMPLER:
2737  sprintf(register_name, "%s_sampler%u", prefix, reg->idx[0].offset);
2738  break;
2739 
2740  case WINED3DSPR_COLOROUT:
2741  /* FIXME: should check dual_buffers when dual blending is enabled */
2742  if (reg->idx[0].offset >= gl_info->limits.buffers)
2743  WARN("Write to render target %u, only %d supported.\n",
2744  reg->idx[0].offset, gl_info->limits.buffers);
2745 
2746  sprintf(register_name, needs_legacy_glsl_syntax(gl_info) ? "gl_FragData[%u]" : "ps_out%u",
2747  reg->idx[0].offset);
2748  break;
2749 
2750  case WINED3DSPR_RASTOUT:
2751  sprintf(register_name, "%s", hwrastout_reg_names[reg->idx[0].offset]);
2752  break;
2753 
2754  case WINED3DSPR_DEPTHOUT:
2755  case WINED3DSPR_DEPTHOUTGE:
2756  case WINED3DSPR_DEPTHOUTLE:
2757  sprintf(register_name, "gl_FragDepth");
2758  break;
2759 
2760  case WINED3DSPR_ATTROUT:
2761  if (!reg->idx[0].offset)
2762  sprintf(register_name, "%s_out[8]", prefix);
2763  else
2764  sprintf(register_name, "%s_out[9]", prefix);
2765  break;
2766 
2767  case WINED3DSPR_TEXCRDOUT:
2768  /* Vertex shaders >= 3.0: WINED3DSPR_OUTPUT */
2769  if (reg->idx[0].rel_addr)
2770  sprintf(register_name, "%s_out[%s + %u]",
2771  prefix, rel_param0.param_str, reg->idx[0].offset);
2772  else
2773  sprintf(register_name, "%s_out[%u]", prefix, reg->idx[0].offset);
2774  break;
2775 
2776  case WINED3DSPR_MISCTYPE:
2777  if (!reg->idx[0].offset)
2778  {
2779  /* vPos */
2780  sprintf(register_name, "vpos");
2781  }
2782  else if (reg->idx[0].offset == 1)
2783  {
2784  /* Note that gl_FrontFacing is a bool, while vFace is
2785  * a float for which the sign determines front/back */
2786  sprintf(register_name, "(gl_FrontFacing ? 1.0 : -1.0)");
2787  }
2788  else
2789  {
2790  FIXME("Unhandled misctype register %u.\n", reg->idx[0].offset);
2791  sprintf(register_name, "unrecognized_register");
2792  }
2793  break;
2794 
2795  case WINED3DSPR_IMMCONST:
2796  switch (reg->immconst_type)
2797  {
2799  switch (data_type)
2800  {
2801  case WINED3D_DATA_FLOAT:
2802  if (gl_info->supported[ARB_SHADER_BIT_ENCODING])
2803  sprintf(register_name, "uintBitsToFloat(%#xu)", reg->u.immconst_data[0]);
2804  else
2805  wined3d_ftoa(*(const float *)reg->u.immconst_data, register_name);
2806  break;
2807  case WINED3D_DATA_INT:
2808  sprintf(register_name, "%#x", reg->u.immconst_data[0]);
2809  break;
2810  case WINED3D_DATA_RESOURCE:
2811  case WINED3D_DATA_SAMPLER:
2812  case WINED3D_DATA_UINT:
2813  sprintf(register_name, "%#xu", reg->u.immconst_data[0]);
2814  break;
2815  default:
2816  sprintf(register_name, "<unhandled data type %#x>", data_type);
2817  break;
2818  }
2819  break;
2820 
2821  case WINED3D_IMMCONST_VEC4:
2822  switch (data_type)
2823  {
2824  case WINED3D_DATA_FLOAT:
2825  if (gl_info->supported[ARB_SHADER_BIT_ENCODING])
2826  {
2827  sprintf(register_name, "uintBitsToFloat(uvec4(%#xu, %#xu, %#xu, %#xu))",
2828  reg->u.immconst_data[0], reg->u.immconst_data[1],
2829  reg->u.immconst_data[2], reg->u.immconst_data[3]);
2830  }
2831  else
2832  {
2833  wined3d_ftoa(*(const float *)&reg->u.immconst_data[0], imm_str[0]);
2834  wined3d_ftoa(*(const float *)&reg->u.immconst_data[1], imm_str[1]);
2835  wined3d_ftoa(*(const float *)&reg->u.immconst_data[2], imm_str[2]);
2836  wined3d_ftoa(*(const float *)&reg->u.immconst_data[3], imm_str[3]);
2837  sprintf(register_name, "vec4(%s, %s, %s, %s)",
2838  imm_str[0], imm_str[1], imm_str[2], imm_str[3]);
2839  }
2840  break;
2841  case WINED3D_DATA_INT:
2842  sprintf(register_name, "ivec4(%#x, %#x, %#x, %#x)",
2843  reg->u.immconst_data[0], reg->u.immconst_data[1],
2844  reg->u.immconst_data[2], reg->u.immconst_data[3]);
2845  break;
2846  case WINED3D_DATA_RESOURCE:
2847  case WINED3D_DATA_SAMPLER:
2848  case WINED3D_DATA_UINT:
2849  sprintf(register_name, "uvec4(%#xu, %#xu, %#xu, %#xu)",
2850  reg->u.immconst_data[0], reg->u.immconst_data[1],
2851  reg->u.immconst_data[2], reg->u.immconst_data[3]);
2852  break;
2853  default:
2854  sprintf(register_name, "<unhandled data type %#x>", data_type);
2855  break;
2856  }
2857  break;
2858 
2859  default:
2860  FIXME("Unhandled immconst type %#x\n", reg->immconst_type);
2861  sprintf(register_name, "<unhandled_immconst_type %#x>", reg->immconst_type);
2862  }
2863  break;
2864 
2866  if (reg->idx[1].rel_addr)
2867  sprintf(register_name, "%s_cb%u[%s + %u]",
2868  prefix, reg->idx[0].offset, rel_param1.param_str, reg->idx[1].offset);
2869  else
2870  sprintf(register_name, "%s_cb%u[%u]", prefix, reg->idx[0].offset, reg->idx[1].offset);
2871  break;
2872 
2874  if (reg->idx[0].rel_addr)
2875  sprintf(register_name, "%s_icb[%s + %u]", prefix, rel_param0.param_str, reg->idx[0].offset);
2876  else
2877  sprintf(register_name, "%s_icb[%u]", prefix, reg->idx[0].offset);
2878  break;
2879 
2880  case WINED3DSPR_PRIMID:
2881  if (version->type == WINED3D_SHADER_TYPE_GEOMETRY)
2882  sprintf(register_name, "gl_PrimitiveIDIn");
2883  else
2884  sprintf(register_name, "gl_PrimitiveID");
2885  break;
2886 
2887  case WINED3DSPR_IDXTEMP:
2888  if (reg->idx[1].rel_addr)
2889  sprintf(register_name, "X%u[%s + %u]", reg->idx[0].offset, rel_param1.param_str, reg->idx[1].offset);
2890  else
2891  sprintf(register_name, "X%u[%u]", reg->idx[0].offset, reg->idx[1].offset);
2892  break;
2893 
2896  "int(gl_LocalInvocationIndex)", gl_info);
2897  break;
2898 
2899  case WINED3DSPR_GSINSTID:
2900  case WINED3DSPR_OUTPOINTID:
2902  "gl_InvocationID", gl_info);
2903  break;
2904 
2905  case WINED3DSPR_THREADID:
2906  sprintf(register_name, "ivec3(gl_GlobalInvocationID)");
2907  break;
2908 
2910  sprintf(register_name, "ivec3(gl_WorkGroupID)");
2911  break;
2912 
2914  sprintf(register_name, "ivec3(gl_LocalInvocationID)");
2915  break;
2916 
2917  case WINED3DSPR_FORKINSTID:
2918  case WINED3DSPR_JOININSTID:
2920  "phase_instance_id", gl_info);
2921  break;
2922 
2923  case WINED3DSPR_TESSCOORD:
2924  sprintf(register_name, "gl_TessCoord");
2925  break;
2926 
2928  if (reg->idx[0].rel_addr)
2929  {
2930  if (reg->idx[1].rel_addr)
2931  sprintf(register_name, "shader_out[%s + %u].reg[%s + %u]",
2932  rel_param0.param_str, reg->idx[0].offset,
2933  rel_param1.param_str, reg->idx[1].offset);
2934  else
2935  sprintf(register_name, "shader_out[%s + %u].reg[%u]",
2936  rel_param0.param_str, reg->idx[0].offset,
2937  reg->idx[1].offset);
2938  }
2939  else if (reg->idx[1].rel_addr)
2940  {
2941  sprintf(register_name, "shader_out[%u].reg[%s + %u]",
2942  reg->idx[0].offset, rel_param1.param_str,
2943  reg->idx[1].offset);
2944  }
2945  else
2946  {
2947  sprintf(register_name, "shader_out[%u].reg[%u]",
2948  reg->idx[0].offset, reg->idx[1].offset);
2949  }
2950  break;
2951 
2952  case WINED3DSPR_PATCHCONST:
2953  if (version->type == WINED3D_SHADER_TYPE_HULL)
2954  sprintf(register_name, "hs_out[%u]", reg->idx[0].offset);
2955  else
2956  sprintf(register_name, "vpc[%u]", reg->idx[0].offset);
2957  break;
2958 
2959  case WINED3DSPR_SAMPLEMASK:
2960  sprintf(register_name, "sample_mask");
2961  break;
2962 
2963  default:
2964  FIXME("Unhandled register type %#x.\n", reg->type);
2965  sprintf(register_name, "unrecognized_register");
2966  break;
2967  }
2968 }
2969 
2970 static void shader_glsl_write_mask_to_str(DWORD write_mask, char *str)
2971 {
2972  *str++ = '.';
2973  if (write_mask & WINED3DSP_WRITEMASK_0) *str++ = 'x';
2974  if (write_mask & WINED3DSP_WRITEMASK_1) *str++ = 'y';
2975  if (write_mask & WINED3DSP_WRITEMASK_2) *str++ = 'z';
2976  if (write_mask & WINED3DSP_WRITEMASK_3) *str++ = 'w';
2977  *str = '\0';
2978 }
2979 
2980 /* Get the GLSL write mask for the destination register */
2981 static DWORD shader_glsl_get_write_mask(const struct wined3d_shader_dst_param *param, char *write_mask)
2982 {
2983  DWORD mask = param->write_mask;
2984 
2985  if (shader_is_scalar(&param->reg))
2986  {
2987  mask = WINED3DSP_WRITEMASK_0;
2988  *write_mask = '\0';
2989  }
2990  else
2991  {
2992  shader_glsl_write_mask_to_str(mask, write_mask);
2993  }
2994 
2995  return mask;
2996 }
2997 
2998 static unsigned int shader_glsl_get_write_mask_size(DWORD write_mask)
2999 {
3000  unsigned int size = 0;
3001 
3002  if (write_mask & WINED3DSP_WRITEMASK_0) ++size;
3003  if (write_mask & WINED3DSP_WRITEMASK_1) ++size;
3004  if (write_mask & WINED3DSP_WRITEMASK_2) ++size;
3005  if (write_mask & WINED3DSP_WRITEMASK_3) ++size;
3006 
3007  return size;
3008 }
3009 
3011  unsigned int component_idx)
3012 {
3013  /* swizzle bits fields: wwzzyyxx */
3014  return (swizzle >> (2 * component_idx)) & 0x3;
3015 }
3016 
3018 {
3019  /* For registers of type WINED3DDECLTYPE_D3DCOLOR, data is stored as "bgra",
3020  * but addressed as "rgba". To fix this we need to swap the register's x
3021  * and z components. */
3022  const char *swizzle_chars = fixup ? "zyxw" : "xyzw";
3023  unsigned int i;
3024 
3025  *str++ = '.';
3026  for (i = 0; i < 4; ++i)
3027  {
3028  if (mask & (WINED3DSP_WRITEMASK_0 << i))
3029  *str++ = swizzle_chars[shader_glsl_swizzle_get_component(swizzle, i)];
3030  }
3031  *str = '\0';
3032 }
3033 
3035  BOOL fixup, DWORD mask, char *swizzle_str)
3036 {
3037  if (shader_is_scalar(&param->reg))
3038  *swizzle_str = '\0';
3039  else
3040  shader_glsl_swizzle_to_str(param->swizzle, fixup, mask, swizzle_str);
3041 }
3042 
3043 static void shader_glsl_sprintf_cast(struct wined3d_string_buffer *dst_param, const char *src_param,
3044  enum wined3d_data_type dst_data_type, enum wined3d_data_type src_data_type)
3045 {
3046  if (dst_data_type == src_data_type)
3047  {
3048  string_buffer_sprintf(dst_param, "%s", src_param);
3049  return;
3050  }
3051 
3052  if (src_data_type == WINED3D_DATA_FLOAT)
3053  {
3054  switch (dst_data_type)
3055  {
3056  case WINED3D_DATA_INT:
3057  string_buffer_sprintf(dst_param, "floatBitsToInt(%s)", src_param);
3058  return;
3059  case WINED3D_DATA_RESOURCE:
3060  case WINED3D_DATA_SAMPLER:
3061  case WINED3D_DATA_UINT:
3062  string_buffer_sprintf(dst_param, "floatBitsToUint(%s)", src_param);
3063  return;
3064  default:
3065  break;
3066  }
3067  }
3068 
3069  if (src_data_type == WINED3D_DATA_UINT && dst_data_type == WINED3D_DATA_FLOAT)
3070  {
3071  string_buffer_sprintf(dst_param, "uintBitsToFloat(%s)", src_param);
3072  return;
3073  }
3074 
3075  if (src_data_type == WINED3D_DATA_INT && dst_data_type == WINED3D_DATA_FLOAT)
3076  {
3077  string_buffer_sprintf(dst_param, "intBitsToFloat(%s)", src_param);
3078  return;
3079  }
3080 
3081  FIXME("Unhandled cast from %#x to %#x.\n", src_data_type, dst_data_type);
3082  string_buffer_sprintf(dst_param, "%s", src_param);
3083 }
3084 
3085 /* From a given parameter token, generate the corresponding GLSL string.
3086  * Also, return the actual register name and swizzle in case the
3087  * caller needs this information as well. */
3089  const struct wined3d_shader_src_param *wined3d_src, DWORD mask, struct glsl_src_param *glsl_src,
3090  enum wined3d_data_type data_type)
3091 {
3092  struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
3094  enum wined3d_data_type param_data_type;
3095  BOOL is_color = FALSE;
3096  char swizzle_str[6];
3097 
3098  glsl_src->reg_name[0] = '\0';
3099  glsl_src->param_str[0] = '\0';
3100  swizzle_str[0] = '\0';
3101 
3102  shader_glsl_get_register_name(&wined3d_src->reg, data_type, glsl_src->reg_name, &is_color, ins);
3103  shader_glsl_get_swizzle(wined3d_src, is_color, mask, swizzle_str);
3104 
3105  switch (wined3d_src->reg.type)
3106  {
3107  case WINED3DSPR_IMMCONST:
3108  param_data_type = data_type;
3109  break;
3110  case WINED3DSPR_FORKINSTID:
3111  case WINED3DSPR_GSINSTID:
3112  case WINED3DSPR_JOININSTID:
3115  case WINED3DSPR_OUTPOINTID:
3116  case WINED3DSPR_PRIMID:
3118  case WINED3DSPR_THREADID:
3119  param_data_type = WINED3D_DATA_INT;
3120  break;
3121  default:
3122  param_data_type = WINED3D_DATA_FLOAT;
3123  break;
3124  }
3125 
3126  shader_glsl_sprintf_cast(reg_name, glsl_src->reg_name, data_type, param_data_type);
3127  shader_glsl_gen_modifier(wined3d_src->modifiers, reg_name->buffer, swizzle_str, glsl_src->param_str);
3128 
3129  string_buffer_release(priv->string_buffers, reg_name);
3130 }
3131 
3133  const struct wined3d_shader_src_param *wined3d_src, DWORD mask, struct glsl_src_param *glsl_src)
3134 {
3135  shader_glsl_add_src_param_ext(ins, wined3d_src, mask, glsl_src, wined3d_src->reg.data_type);
3136 }
3137 
3138 /* From a given parameter token, generate the corresponding GLSL string.
3139  * Also, return the actual register name and swizzle in case the
3140  * caller needs this information as well. */
3142  const struct wined3d_shader_dst_param *wined3d_dst, struct glsl_dst_param *glsl_dst)
3143 {
3144  BOOL is_color = FALSE;
3145 
3146  glsl_dst->mask_str[0] = '\0';
3147  glsl_dst->reg_name[0] = '\0';
3148 
3149  shader_glsl_get_register_name(&wined3d_dst->reg, wined3d_dst->reg.data_type,
3150  glsl_dst->reg_name, &is_color, ins);
3151  return shader_glsl_get_write_mask(wined3d_dst, glsl_dst->mask_str);
3152 }
3153 
3154 /* Append the destination part of the instruction to the buffer, return the effective write mask */
3156  const struct wined3d_shader_instruction *ins, const struct wined3d_shader_dst_param *dst,
3157  enum wined3d_data_type data_type)
3158 {
3159  struct glsl_dst_param glsl_dst;
3160  DWORD mask;
3161 
3162  if ((mask = shader_glsl_add_dst_param(ins, dst, &glsl_dst)))
3163  {
3164  switch (data_type)
3165  {
3166  case WINED3D_DATA_FLOAT:
3167  shader_addline(buffer, "%s%s = %s(",
3168  glsl_dst.reg_name, glsl_dst.mask_str, shift_glsl_tab[dst->shift]);
3169  break;
3170  case WINED3D_DATA_INT:
3171  shader_addline(buffer, "%s%s = %sintBitsToFloat(",
3172  glsl_dst.reg_name, glsl_dst.mask_str, shift_glsl_tab[dst->shift]);
3173  break;
3174  case WINED3D_DATA_RESOURCE:
3175  case WINED3D_DATA_SAMPLER:
3176  case WINED3D_DATA_UINT:
3177  shader_addline(buffer, "%s%s = %suintBitsToFloat(",
3178  glsl_dst.reg_name, glsl_dst.mask_str, shift_glsl_tab[dst->shift]);
3179  break;
3180  default:
3181  FIXME("Unhandled data type %#x.\n", data_type);
3182  shader_addline(buffer, "%s%s = %s(",
3183  glsl_dst.reg_name, glsl_dst.mask_str, shift_glsl_tab[dst->shift]);
3184  break;
3185  }
3186  }
3187 
3188  return mask;
3189 }
3190 
3191 /* Append the destination part of the instruction to the buffer, return the effective write mask */
3193 {
3194  return shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], ins->dst[0].reg.data_type);
3195 }
3196 
3199 {
3200  struct glsl_dst_param dst_param;
3201  DWORD modifiers;
3202 
3203  if (!ins->dst_count) return;
3204 
3205  modifiers = ins->dst[0].modifiers;
3206  if (!modifiers) return;
3207 
3208  shader_glsl_add_dst_param(ins, &ins->dst[0], &dst_param);
3209 
3210  if (modifiers & WINED3DSPDM_SATURATE)
3211  {
3212  /* _SAT means to clamp the value of the register to between 0 and 1 */
3213  shader_addline(ins->ctx->buffer, "%s%s = clamp(%s%s, 0.0, 1.0);\n", dst_param.reg_name,
3214  dst_param.mask_str, dst_param.reg_name, dst_param.mask_str);
3215  }
3216 
3217  if (modifiers & WINED3DSPDM_MSAMPCENTROID)
3218  {
3219  FIXME("_centroid modifier not handled\n");
3220  }
3221 
3222  if (modifiers & WINED3DSPDM_PARTIALPRECISION)
3223  {
3224  /* MSDN says this modifier can be safely ignored, so that's what we'll do. */
3225  }
3226 }
3227 
3229 {
3230  switch (op)
3231  {
3232  case WINED3D_SHADER_REL_OP_GT: return ">";
3233  case WINED3D_SHADER_REL_OP_EQ: return "==";
3234  case WINED3D_SHADER_REL_OP_GE: return ">=";
3235  case WINED3D_SHADER_REL_OP_LT: return "<";
3236  case WINED3D_SHADER_REL_OP_NE: return "!=";
3237  case WINED3D_SHADER_REL_OP_LE: return "<=";
3238  default:
3239  FIXME("Unrecognized operator %#x.\n", op);
3240  return "(\?\?)";
3241  }
3242 }
3243 
3244 static BOOL shader_glsl_has_core_grad(const struct wined3d_gl_info *gl_info)
3245 {
3246  return shader_glsl_get_version(gl_info) >= 130 || gl_info->supported[EXT_GPU_SHADER4];
3247 }
3248 
3250  unsigned int *coord_size, unsigned int *deriv_size)
3251 {
3252  const BOOL is_array = resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_1DARRAY
3253  || resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY;
3254 
3255  *coord_size = resource_type_info[resource_type].coord_size;
3256  *deriv_size = *coord_size;
3257  if (is_array)
3258  --(*deriv_size);
3259 }
3260 
3262  DWORD resource_idx, DWORD sampler_idx, DWORD flags, struct glsl_sample_function *sample_function)
3263 {
3264  enum wined3d_shader_resource_type resource_type = ctx->reg_maps->resource_info[resource_idx].type;
3265  struct shader_glsl_ctx_priv *priv = ctx->backend_data;
3266  const struct wined3d_gl_info *gl_info = ctx->gl_info;
3267  BOOL shadow = glsl_is_shadow_sampler(ctx->shader, priv->cur_ps_args, resource_idx, sampler_idx);
3268  BOOL projected = flags & WINED3D_GLSL_SAMPLE_PROJECTED;
3269  BOOL texrect = ctx->reg_maps->shader_version.type == WINED3D_SHADER_TYPE_PIXEL
3270  && priv->cur_ps_args->np2_fixup & (1u << resource_idx)
3271  && gl_info->supported[ARB_TEXTURE_RECTANGLE];
3272  BOOL lod = flags & WINED3D_GLSL_SAMPLE_LOD;
3273  BOOL grad = flags & WINED3D_GLSL_SAMPLE_GRAD;
3275  const char *base = "texture", *type_part = "", *suffix = "";
3276  unsigned int coord_size, deriv_size;
3277 
3278  sample_function->data_type = ctx->reg_maps->resource_info[resource_idx].data_type;
3279 
3280  if (resource_type >= ARRAY_SIZE(resource_type_info))
3281  {
3282  ERR("Unexpected resource type %#x.\n", resource_type);
3283  resource_type = WINED3D_SHADER_RESOURCE_TEXTURE_2D;
3284  }
3285 
3286  /* Note that there's no such thing as a projected cube texture. */
3287  if (resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_CUBE)
3288  projected = FALSE;
3289 
3290  if (needs_legacy_glsl_syntax(gl_info))
3291  {
3292  if (shadow)
3293  base = "shadow";
3294 
3295  type_part = resource_type_info[resource_type].type_part;
3296  if (resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_2D && texrect)
3297  type_part = "2DRect";
3298  if (!type_part[0] && resource_type != WINED3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY)
3299  FIXME("Unhandled resource type %#x.\n", resource_type);
3300 
3301  if (!lod && grad && !shader_glsl_has_core_grad(gl_info))
3302  {
3303  if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
3304  suffix = "ARB";
3305  else
3306  FIXME("Unsupported grad function.\n");
3307  }
3308  }
3309 
3310  if (flags & WINED3D_GLSL_SAMPLE_LOAD)
3311  {
3312  static const DWORD texel_fetch_flags = WINED3D_GLSL_SAMPLE_LOAD | WINED3D_GLSL_SAMPLE_OFFSET;
3313  if (flags & ~texel_fetch_flags)
3314  ERR("Unexpected flags %#x for texelFetch.\n", flags & ~texel_fetch_flags);
3315 
3316  base = "texelFetch";
3317  type_part = "";
3318  }
3319 
3320  sample_function->name = string_buffer_get(priv->string_buffers);
3321  string_buffer_sprintf(sample_function->name, "%s%s%s%s%s%s", base, type_part, projected ? "Proj" : "",
3322  lod ? "Lod" : grad ? "Grad" : "", offset ? "Offset" : "", suffix);
3323 
3324  shader_glsl_get_coord_size(resource_type, &coord_size, &deriv_size);
3325  if (shadow)
3326  ++coord_size;
3327  sample_function->offset_size = offset ? deriv_size : 0;
3328  sample_function->coord_mask = (1u << coord_size) - 1;
3329  sample_function->deriv_mask = (1u << deriv_size) - 1;
3330  sample_function->output_single_component = shadow && !needs_legacy_glsl_syntax(gl_info);
3331 }
3332 
3334  struct glsl_sample_function *sample_function)
3335 {
3336  const struct shader_glsl_ctx_priv *priv = ctx->backend_data;
3337 
3338  string_buffer_release(priv->string_buffers, sample_function->name);
3339 }
3340 
3341 static void shader_glsl_append_fixup_arg(char *arguments, const char *reg_name,
3342  BOOL sign_fixup, enum fixup_channel_source channel_source)
3343 {
3344  switch(channel_source)
3345  {
3346  case CHANNEL_SOURCE_ZERO:
3347  strcat(arguments, "0.0");
3348  break;
3349 
3350  case CHANNEL_SOURCE_ONE:
3351  strcat(arguments, "1.0");
3352  break;
3353 
3354  case CHANNEL_SOURCE_X:
3355  strcat(arguments, reg_name);
3356  strcat(arguments, ".x");
3357  break;
3358 
3359  case CHANNEL_SOURCE_Y:
3360  strcat(arguments, reg_name);
3361  strcat(arguments, ".y");
3362  break;
3363 
3364  case CHANNEL_SOURCE_Z:
3365  strcat(arguments, reg_name);
3366  strcat(arguments, ".z");
3367  break;
3368 
3369  case CHANNEL_SOURCE_W:
3370  strcat(arguments, reg_name);
3371  strcat(arguments, ".w");
3372  break;
3373 
3374  default:
3375  FIXME("Unhandled channel source %#x\n", channel_source);
3376  strcat(arguments, "undefined");
3377  break;
3378  }
3379 
3380  if (sign_fixup) strcat(arguments, " * 2.0 - 1.0");
3381 }
3382 
3384  const char *reg_name, DWORD mask, struct color_fixup_desc fixup)
3385 {
3386  unsigned int mask_size, remaining;
3387  DWORD fixup_mask = 0;
3388  char arguments[256];
3389  char mask_str[6];
3390 
3391  if (fixup.x_sign_fixup || fixup.x_source != CHANNEL_SOURCE_X) fixup_mask |= WINED3DSP_WRITEMASK_0;
3392  if (fixup.y_sign_fixup || fixup.y_source != CHANNEL_SOURCE_Y) fixup_mask |= WINED3DSP_WRITEMASK_1;
3393  if (fixup.z_sign_fixup || fixup.z_source != CHANNEL_SOURCE_Z) fixup_mask |= WINED3DSP_WRITEMASK_2;
3394  if (fixup.w_sign_fixup || fixup.w_source != CHANNEL_SOURCE_W) fixup_mask |= WINED3DSP_WRITEMASK_3;
3395  if (!(mask &= fixup_mask))
3396  return;
3397 
3398  if (is_complex_fixup(fixup))
3399  {
3401  FIXME("Complex fixup (%#x) not supported\n",complex_fixup);
3402  return;
3403  }
3404 
3405  shader_glsl_write_mask_to_str(mask, mask_str);
3406  mask_size = shader_glsl_get_write_mask_size(mask);
3407 
3408  arguments[0] = '\0';
3409  remaining = mask_size;
3410  if (mask & WINED3DSP_WRITEMASK_0)
3411  {
3412  shader_glsl_append_fixup_arg(arguments, reg_name, fixup.x_sign_fixup, fixup.x_source);
3413  if (--remaining) strcat(arguments, ", ");
3414  }
3415  if (mask & WINED3DSP_WRITEMASK_1)
3416  {
3417  shader_glsl_append_fixup_arg(arguments, reg_name, fixup.y_sign_fixup, fixup.y_source);
3418  if (--remaining) strcat(arguments, ", ");
3419  }
3420  if (mask & WINED3DSP_WRITEMASK_2)
3421  {
3422  shader_glsl_append_fixup_arg(arguments, reg_name, fixup.z_sign_fixup, fixup.z_source);
3423  if (--remaining) strcat(arguments, ", ");
3424  }
3425  if (mask & WINED3DSP_WRITEMASK_3)
3426  {
3427  shader_glsl_append_fixup_arg(arguments, reg_name, fixup.w_sign_fixup, fixup.w_source);
3428  if (--remaining) strcat(arguments, ", ");
3429  }
3430 
3431  if (mask_size > 1)
3432  shader_addline(buffer, "%s%s = vec%u(%s);\n", reg_name, mask_str, mask_size, arguments);
3433  else
3434  shader_addline(buffer, "%s%s = %s;\n", reg_name, mask_str, arguments);
3435 }
3436 
3438 {
3439  char reg_name[256];
3440  BOOL is_color;
3441 
3442  shader_glsl_get_register_name(&ins->dst[0].reg, ins->dst[0].reg.data_type, reg_name, &is_color, ins);
3443  shader_glsl_color_correction_ext(ins->ctx->buffer, reg_name, ins->dst[0].write_mask, fixup);
3444 }
3445 
3446 static void PRINTF_ATTR(9, 10) shader_glsl_gen_sample_code(const struct wined3d_shader_instruction *ins,
3447  unsigned int sampler_bind_idx, const struct glsl_sample_function *sample_function, DWORD swizzle,
3449  const char *coord_reg_fmt, ...)
3450 {
3451  const struct wined3d_shader_version *version = &ins->ctx->reg_maps->shader_version;
3452  char dst_swizzle[6];
3453  struct color_fixup_desc fixup;
3454  BOOL np2_fixup = FALSE;
3455  va_list args;
3456  int ret;
3457 
3458  shader_glsl_swizzle_to_str(swizzle, FALSE, ins->dst[0].write_mask, dst_swizzle);
3459 
3460  /* If ARB_texture_swizzle is supported we don't need to do anything here.
3461  * We actually rely on it for vertex shaders and SM4+. */
3462  if (version->type == WINED3D_SHADER_TYPE_PIXEL && version->major < 4)
3463  {
3464  const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
3465  fixup = priv->cur_ps_args->color_fixup[sampler_bind_idx];
3466 
3467  if (priv->cur_ps_args->np2_fixup & (1u << sampler_bind_idx))
3468  np2_fixup = TRUE;
3469  }
3470  else
3471  {
3472  fixup = COLOR_FIXUP_IDENTITY;
3473  }
3474 
3475  shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &ins->dst[0], sample_function->data_type);
3476 
3477  if (sample_function->output_single_component)
3478  shader_addline(ins->ctx->buffer, "vec4(");
3479 
3480  shader_addline(ins->ctx->buffer, "%s(%s_sampler%u, ",
3481  sample_function->name->buffer, shader_glsl_get_prefix(version->type), sampler_bind_idx);
3482 
3483  for (;;)
3484  {
3485  va_start(args, coord_reg_fmt);
3486  ret = shader_vaddline(ins->ctx->buffer, coord_reg_fmt, args);
3487  va_end(args);
3488  if (!ret)
3489  break;
3490  if (!string_buffer_resize(ins->ctx->buffer, ret))
3491  break;
3492  }
3493 
3494  if (np2_fixup)
3495  {
3496  const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data;
3497  const unsigned char idx = priv->cur_np2fixup_info->idx[sampler_bind_idx];
3498 
3499  switch (shader_glsl_get_write_mask_size(sample_function->coord_mask))
3500  {
3501  case 1:
3502  shader_addline(ins->ctx->buffer, " * ps_samplerNP2Fixup[%u].%s",
3503  idx >> 1, (idx % 2) ? "z" : "x");
3504  break;
3505  case 2:
3506  shader_addline(ins->ctx->buffer, " * ps_samplerNP2Fixup[%u].%s",
3507  idx >> 1, (idx % 2) ? "zw" : "xy");
3508  break;
3509  case 3:
3510  shader_addline(ins->ctx->buffer, " * vec3(ps_samplerNP2Fixup[%u].%s, 1.0)",
3511  idx >> 1, (idx % 2) ? "zw" : "xy");
3512  break;
3513  case 4:
3514  shader_addline(ins->ctx->buffer, " * vec4(ps_samplerNP2Fixup[%u].%s, 1.0, 1.0)",
3515  idx >> 1, (idx % 2) ? "zw" : "xy");
3516  break;
3517  }
3518  }
3519  if (dx && dy)
3520  shader_addline(ins->ctx->buffer, ", %s, %s", dx, dy);
3521  else if (bias)
3522  shader_addline(ins->ctx->buffer, ", %s", bias);
3523  if (sample_function->offset_size)
3524  {
3525  int offset_immdata[4] = {offset->u, offset->v, offset->w};
3526  shader_addline(ins->ctx->buffer, ", ");
3527  shader_glsl_append_imm_ivec(ins->ctx->buffer, offset_immdata, sample_function->offset_size);
3528  }
3529  shader_addline(ins->ctx->buffer, ")");
3530 
3531  if (sample_function->output_single_component)
3532  shader_addline(ins->ctx->buffer, ")");
3533 
3534  shader_addline(ins->ctx->buffer, "%s);\n", dst_swizzle);
3535 
3536  if (!is_identity_fixup(fixup))
3537  shader_glsl_color_correction(ins, fixup);
3538 }
3539 
3540 static void shader_glsl_fixup_position(struct wined3d_string_buffer *buffer, BOOL use_viewport_index)
3541 {
3542  /* Write the final position.
3543  *
3544  * OpenGL coordinates specify the center of the pixel while D3D coords
3545  * specify the corner. The offsets are stored in z and w in
3546  * pos_fixup. pos_fixup.y contains 1.0 or -1.0 to turn the rendering
3547  * upside down for offscreen rendering. pos_fixup.x contains 1.0 to allow
3548  * a MAD. */
3549  if (use_viewport_index)
3550  {
3551  shader_addline(buffer, "gl_Position.y = gl_Position.y * pos_fixup[gl_ViewportIndex].y;\n");
3552  shader_addline(buffer, "gl_Position.xy += pos_fixup[gl_ViewportIndex].zw * gl_Position.ww;\n");
3553  }
3554  else
3555  {
3556  shader_addline(buffer, "gl_Position.y = gl_Position.y * pos_fixup.y;\n");
3557  shader_addline(buffer, "gl_Position.xy += pos_fixup.zw * gl_Position.ww;\n");
3558  }
3559 
3560  /* Z coord [0;1]->[-1;1] mapping, see comment in get_projection_matrix()
3561  * in utils.c
3562  *
3563  * Basically we want (in homogeneous coordinates) z = z * 2 - 1. However,
3564  * shaders are run before the homogeneous divide, so we have to take the w
3565  * into account: z = ((z / w) * 2 - 1) * w, which is the same as
3566  * z = z * 2 - w. */
3567  shader_addline(buffer, "gl_Position.z = gl_Position.z * 2.0 - gl_Position.w;\n");
3568 }
3569 
3570 /*****************************************************************************
3571  * Begin processing individual instruction opcodes
3572  ****************************************************************************/
3573 
3574 static void shader_glsl_binop(const struct wined3d_shader_instruction *ins)
3575 {
3576  struct wined3d_string_buffer *buffer = ins->ctx->buffer;
3577  struct glsl_src_param src0_param;
3578  struct glsl_src_param src1_param;
3579  DWORD write_mask;
3580  const char *op;
3581 
3582  /* Determine the GLSL operator to use based on the opcode */
3583  switch (ins->handler_idx)
3584  {
3585  case WINED3DSIH_ADD: op = "+"; break;
3586  case WINED3DSIH_AND: op = "&"; break;
3587  case WINED3DSIH_DIV: op = "/"; break;
3588  case WINED3DSIH_IADD: op = "+"; break;
3589  case WINED3DSIH_ISHL: op = "<<"; break;
3590  case WINED3DSIH_ISHR: op = ">>"; break;
3591  case WINED3DSIH_MUL: op = "*"; break;
3592  case WINED3DSIH_OR: op = "|"; break;
3593  case WINED3DSIH_SUB: op = "-"; break;
3594  case WINED3DSIH_USHR: op = ">>"; break;
3595  case WINED3DSIH_XOR: op = "^"; break;
3596  default:
3597  op = "<unhandled operator>";
3598  FIXME("Opcode %s not yet handled in GLSL.\n", debug_d3dshaderinstructionhandler(ins->handler_idx));
3599  break;
3600  }
3601 
3602  write_mask = shader_glsl_append_dst(buffer, ins);
3603  shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
3604  shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
3605  shader_addline(buffer, "%s %s %s);\n", src0_param.param_str, op, src1_param.param_str);
3606 }
3607 
3608 static void shader_glsl_relop(const struct wined3d_shader_instruction *ins)
3609 {
3610  struct wined3d_string_buffer *buffer = ins->ctx->buffer;
3611  struct glsl_src_param src0_param;
3612  struct glsl_src_param src1_param;
3613  unsigned int mask_size;
3614  DWORD write_mask;
3615  const char *op;
3616 
3617  write_mask = shader_glsl_append_dst(buffer, ins);
3618  mask_size = shader_glsl_get_write_mask_size(write_mask);
3619  shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
3620  shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
3621 
3622  if (mask_size > 1)
3623  {
3624  switch (ins->handler_idx)
3625  {
3626  case WINED3DSIH_EQ: op = "equal"; break;
3627  case WINED3DSIH_IEQ: op = "equal"; break;
3628  case WINED3DSIH_GE: op = "greaterThanEqual"; break;
3629  case WINED3DSIH_IGE: op = "greaterThanEqual"; break;
3630  case WINED3DSIH_UGE: op = "greaterThanEqual"; break;
3631  case WINED3DSIH_LT: op = "lessThan"; break;
3632  case WINED3DSIH_ILT: op = "lessThan"; break;
3633  case WINED3DSIH_ULT: op = "lessThan"; break;
3634  case WINED3DSIH_NE: op = "notEqual"; break;
3635  case WINED3DSIH_INE: op = "notEqual"; break;
3636  default:
3637  op = "<unhandled operator>";
3638  ERR("Unhandled opcode %#x.\n", ins->handler_idx);
3639  break;
3640  }
3641 
3642  shader_addline(buffer, "uvec%u(%s(%s, %s)) * 0xffffffffu);\n",
3643  mask_size, op, src0_param.param_str, src1_param.param_str);
3644  }
3645  else
3646  {
3647  switch (ins->handler_idx)
3648  {
3649  case WINED3DSIH_EQ: op = "=="; break;
3650  case WINED3DSIH_IEQ: op = "=="; break;
3651  case WINED3DSIH_GE: op = ">="; break;
3652  case WINED3DSIH_IGE: op = ">="; break;
3653  case WINED3DSIH_UGE: op = ">="; break;
3654  case WINED3DSIH_LT: op = "<"; break;
3655  case WINED3DSIH_ILT: op = "<"; break;
3656  case WINED3DSIH_ULT: op = "<"; break;
3657  case WINED3DSIH_NE: op = "!="; break;
3658  case WINED3DSIH_INE: op = "!="; break;
3659  default:
3660  op = "<unhandled operator>";
3661  ERR("Unhandled opcode %#x.\n", ins->handler_idx);
3662  break;
3663  }
3664 
3665  shader_addline(buffer, "%s %s %s ? 0xffffffffu : 0u);\n",
3666  src0_param.param_str, op, src1_param.param_str);
3667  }
3668 }
3669 
3670 static void shader_glsl_unary_op(const struct wined3d_shader_instruction *ins)
3671 {
3672  struct glsl_src_param src_param;
3673  DWORD write_mask;
3674  const char *op;
3675 
3676  switch (ins->handler_idx)
3677  {
3678  case WINED3DSIH_INEG: op = "-"; break;
3679  case WINED3DSIH_NOT: op = "~"; break;
3680  default:
3681  op = "<unhandled operator>";
3682  ERR("Unhandled opcode %s.\n",
3684  break;
3685  }
3686 
3687  write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
3688  shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param);
3689  shader_addline(ins->ctx->buffer, "%s%s);\n", op, src_param.param_str);
3690 }
3691 
3693 {
3694  struct wined3d_string_buffer *buffer = ins->ctx->buffer;
3695  struct glsl_src_param src0_param;
3696  struct glsl_src_param src1_param;
3697  DWORD write_mask;
3698 
3699  /* If we have ARB_gpu_shader5, we can use imulExtended() / umulExtended().
3700  * If not, we can emulate it. */
3701  if (ins->dst[0].reg.type != WINED3DSPR_NULL)
3702  FIXME("64-bit integer multiplies not implemented.\n");
3703 
3704  if (ins->dst[1].reg.type != WINED3DSPR_NULL)
3705  {
3706  write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1], ins->dst[1].reg.data_type);
3707  shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
3708  shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
3709 
3710  shader_addline(ins->ctx->buffer, "%s * %s);\n",
3711  src0_param.param_str, src1_param.param_str);
3712  }
3713 }
3714 
3715 static void shader_glsl_udiv(const struct wined3d_shader_instruction *ins)
3716 {
3717  struct wined3d_string_buffer *buffer = ins->ctx->buffer;
3718  struct glsl_src_param src0_param, src1_param;
3719  DWORD write_mask;
3720 
3721  if (ins->dst[0].reg.type != WINED3DSPR_NULL)
3722  {
3723  if (ins->dst[1].reg.type != WINED3DSPR_NULL)
3724  {
3725  char dst_mask[6];
3726 
3727  write_mask = shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
3728  shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
3729  shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
3730  shader_addline(buffer, "tmp0%s = uintBitsToFloat(%s / %s);\n",
3731  dst_mask, src0_param.param_str, src1_param.param_str);
3732 
3733  write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1], ins->dst[1].reg.data_type);
3734  shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
3735  shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
3736  shader_addline(buffer, "%s %% %s);\n", src0_param.param_str, src1_param.param_str);
3737 
3738  shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], WINED3D_DATA_FLOAT);
3739  shader_addline(buffer, "tmp0%s);\n", dst_mask);
3740  }
3741  else
3742  {
3743  write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], ins->dst[0].reg.data_type);
3744  shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
3745  shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
3746  shader_addline(buffer, "%s / %s);\n", src0_param.param_str, src1_param.param_str);
3747  }
3748  }
3749  else if (ins->dst[1].reg.type != WINED3DSPR_NULL)
3750  {
3751  write_mask = shader_glsl_append_dst_ext(buffer, ins, &ins->dst[1], ins->dst[1].reg.data_type);
3752  shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
3753  shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
3754  shader_addline(buffer, "%s %% %s);\n", src0_param.param_str, src1_param.param_str);
3755  }
3756 }
3757 
3758 /* Process the WINED3DSIO_MOV opcode using GLSL (dst = src) */
3759 static void shader_glsl_mov(const struct wined3d_shader_instruction *ins)
3760 {
3761  const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
3762  struct wined3d_string_buffer *buffer = ins->ctx->buffer;
3763  struct glsl_src_param src0_param;
3764  DWORD write_mask;
3765 
3766  write_mask = shader_glsl_append_dst(buffer, ins);
3767  shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
3768 
3769  /* In vs_1_1 WINED3DSIO_MOV can write to the address register. In later
3770  * shader versions WINED3DSIO_MOVA is used for this. */
3771  if (ins->ctx->reg_maps->shader_version.major == 1
3772  && ins->ctx->reg_maps->shader_version.type == WINED3D_SHADER_TYPE_VERTEX
3773  && ins->dst[0].reg.type == WINED3DSPR_ADDR)
3774  {
3775  /* This is a simple floor() */
3776  unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask);
3777  if (mask_size > 1) {
3778  shader_addline(buffer, "ivec%d(floor(%s)));\n", mask_size, src0_param.param_str);
3779  } else {
3780  shader_addline(buffer, "int(floor(%s)));\n", src0_param.param_str);
3781  }
3782  }
3783  else if (ins->handler_idx == WINED3DSIH_MOVA)
3784  {
3785  unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask);
3786 
3787  if (shader_glsl_get_version(gl_info) >= 130 || gl_info->supported[EXT_GPU_SHADER4])
3788  {
3789  if (mask_size > 1)
3790  shader_addline(buffer, "ivec%d(round(%s)));\n", mask_size, src0_param.param_str);
3791  else
3792  shader_addline(buffer, "int(round(%s)));\n", src0_param.param_str);
3793  }
3794  else
3795  {
3796  if (mask_size > 1)
3797  shader_addline(buffer, "ivec%d(floor(abs(%s) + vec%d(0.5)) * sign(%s)));\n",
3798  mask_size, src0_param.param_str, mask_size, src0_param.param_str);
3799  else
3800  shader_addline(buffer, "int(floor(abs(%s) + 0.5) * sign(%s)));\n",
3801  src0_param.param_str, src0_param.param_str);
3802  }
3803  }
3804  else
3805  {
3806  shader_addline(buffer, "%s);\n", src0_param.param_str);
3807  }
3808 }
3809 
3810 /* Process the dot product operators DP3 and DP4 in GLSL (dst = dot(src0, src1)) */
3811 static void shader_glsl_dot(const struct wined3d_shader_instruction *ins)
3812 {
3813  struct wined3d_string_buffer *buffer = ins->ctx->buffer;
3814  struct glsl_src_param src0_param;
3815  struct glsl_src_param src1_param;
3816  DWORD dst_write_mask, src_write_mask;
3817  unsigned int dst_size;
3818 
3819  dst_write_mask = shader_glsl_append_dst(buffer, ins);
3820  dst_size = shader_glsl_get_write_mask_size(dst_write_mask);
3821 
3822  /* dp4 works on vec4, dp3 on vec3, etc. */
3823  if (ins->handler_idx == WINED3DSIH_DP4)
3824  src_write_mask = WINED3DSP_WRITEMASK_ALL;
3825  else if (ins->handler_idx == WINED3DSIH_DP3)
3827  else
3828  src_write_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1;
3829 
3830  shader_glsl_add_src_param(ins, &ins->src[0], src_write_mask, &src0_param);
3831  shader_glsl_add_src_param(ins, &ins->src[1], src_write_mask, &src1_param);
3832 
3833  if (dst_size > 1) {
3834  shader_addline(buffer, "vec%d(dot(%s, %s)));\n", dst_size, src0_param.param_str, src1_param.param_str);
3835  } else {
3836  shader_addline(buffer, "dot(%s, %s));\n", src0_param.param_str, src1_param.param_str);
3837  }
3838 }
3839 
3840 /* Note that this instruction has some restrictions. The destination write mask
3841  * can't contain the w component, and the source swizzles have to be .xyzw */
3842 static void shader_glsl_cross(const struct wined3d_shader_instruction *ins)
3843 {
3845  struct glsl_src_param src0_param;
3846  struct glsl_src_param src1_param;
3847  char dst_mask[6];
3848 
3849  shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
3850  shader_glsl_append_dst(ins->ctx->buffer, ins);
3851  shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
3852  shader_glsl_add_src_param(ins, &ins->src[1], src_mask, &src1_param);
3853  shader_addline(ins->ctx->buffer, "cross(%s, %s)%s);\n", src0_param.param_str, src1_param.param_str, dst_mask);
3854 }
3855 
3856 static void shader_glsl_cut(const struct wined3d_shader_instruction *ins)
3857 {
3858  unsigned int stream = ins->handler_idx == WINED3DSIH_CUT ? 0 : ins->src[0].reg.idx[0].offset;
3859 
3860  if (!stream)
3861  shader_addline(ins->ctx->buffer, "EndPrimitive();\n");
3862  else
3863  FIXME("Unhandled primitive stream %u.\n", stream);
3864 }
3865 
3866 /* Process the WINED3DSIO_POW instruction in GLSL (dst = |src0|^src1)
3867  * Src0 and src1 are scalars. Note that D3D uses the absolute of src0, while
3868  * GLSL uses the value as-is. */
3869 static void shader_glsl_pow(const struct wined3d_shader_instruction *ins)
3870 {
3871  struct wined3d_string_buffer *buffer = ins->ctx->buffer;
3872  struct glsl_src_param src0_param;
3873  struct glsl_src_param src1_param;
3874  DWORD dst_write_mask;
3875  unsigned int dst_size;
3876 
3877  dst_write_mask = shader_glsl_append_dst(buffer, ins);
3878  dst_size = shader_glsl_get_write_mask_size(dst_write_mask);
3879 
3880  shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
3881  shader_glsl_add_src_param(ins, &ins->src[1], WINED3DSP_WRITEMASK_0, &src1_param);
3882 
3883  if (dst_size > 1)
3884  {
3885  shader_addline(buffer, "vec%u(%s == 0.0 ? 1.0 : pow(abs(%s), %s)));\n",
3886  dst_size, src1_param.param_str, src0_param.param_str, src1_param.param_str);
3887  }
3888  else
3889  {
3890  shader_addline(buffer, "%s == 0.0 ? 1.0 : pow(abs(%s), %s));\n",
3891  src1_param.param_str, src0_param.param_str, src1_param.param_str);
3892  }
3893 }
3894 
3895 /* Map the opcode 1-to-1 to the GL code (arg->dst = instruction(src0, src1, ...) */
3896 static void shader_glsl_map2gl(const struct wined3d_shader_instruction *ins)
3897 {
3898  struct wined3d_string_buffer *buffer = ins->ctx->buffer;
3899  struct glsl_src_param src_param;
3900  const char *instruction;
3901  DWORD write_mask;
3902  unsigned i;
3903 
3904  /* Determine the GLSL function to use based on the opcode */
3905  /* TODO: Possibly make this a table for faster lookups */
3906  switch (ins->handler_idx)
3907  {
3908  case WINED3DSIH_ABS: instruction = "abs"; break;
3909  case WINED3DSIH_BFREV: instruction = "bitfieldReverse"; break;
3910  case WINED3DSIH_COUNTBITS: instruction = "bitCount"; break;
3911  case WINED3DSIH_DSX: instruction = "dFdx"; break;
3912  case WINED3DSIH_DSX_COARSE: instruction = "dFdxCoarse"; break;
3913  case WINED3DSIH_DSX_FINE: instruction = "dFdxFine"; break;
3914  case WINED3DSIH_DSY: instruction = "ycorrection.y * dFdy"; break;
3915  case WINED3DSIH_DSY_COARSE: instruction = "ycorrection.y * dFdyCoarse"; break;
3916  case WINED3DSIH_DSY_FINE: instruction = "ycorrection.y * dFdyFine"; break;
3917  case WINED3DSIH_FIRSTBIT_HI: instruction = "findMSB"; break;
3918  case WINED3DSIH_FIRSTBIT_LO: instruction = "findLSB"; break;
3919  case WINED3DSIH_FIRSTBIT_SHI: instruction = "findMSB"; break;
3920  case WINED3DSIH_FRC: instruction = "fract"; break;
3921  case WINED3DSIH_IMAX: instruction = "max"; break;
3922  case WINED3DSIH_IMIN: instruction = "min"; break;
3923  case WINED3DSIH_MAX: instruction = "max"; break;
3924  case WINED3DSIH_MIN: instruction = "min"; break;
3925  case WINED3DSIH_ROUND_NE: instruction = "roundEven"; break;
3926  case WINED3DSIH_ROUND_NI: instruction = "floor"; break;
3927  case WINED3DSIH_ROUND_PI: instruction = "ceil"; break;
3928  case WINED3DSIH_ROUND_Z: instruction = "trunc"; break;
3929  case WINED3DSIH_SQRT: instruction = "sqrt"; break;
3930  case WINED3DSIH_UMAX: instruction = "max"; break;
3931  case WINED3DSIH_UMIN: instruction = "min"; break;
3932  default: instruction = "";
3933  ERR("Opcode %s not yet handled in GLSL.\n", debug_d3dshaderinstructionhandler(ins->handler_idx));
3934  break;
3935  }
3936 
3937  write_mask = shader_glsl_append_dst(buffer, ins);
3938 
3939  /* In D3D bits are numbered from the most significant bit. */
3941  shader_addline(buffer, "31 - ");
3942  shader_addline(buffer, "%s(", instruction);
3943 
3944  if (ins->src_count)
3945  {
3946  shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param);
3947  shader_addline(buffer, "%s", src_param.param_str);
3948  for (i = 1; i < ins->src_count; ++i)
3949  {
3950  shader_glsl_add_src_param(ins, &ins->src[i], write_mask, &src_param);
3951  shader_addline(buffer, ", %s", src_param.param_str);
3952  }
3953  }
3954 
3955  shader_addline(buffer, "));\n");
3956 }
3957 
3958 static void shader_glsl_float16(const struct wined3d_shader_instruction *ins)
3959 {
3960  struct wined3d_shader_dst_param dst;
3961  struct glsl_src_param src;
3962  DWORD write_mask;
3963  const char *fmt;
3964  unsigned int i;
3965 
3966  fmt = ins->handler_idx == WINED3DSIH_F16TOF32
3967  ? "unpackHalf2x16(%s).x);\n" : "packHalf2x16(vec2(%s, 0.0)));\n";
3968 
3969  dst = ins->dst[0];
3970  for (i = 0; i < 4; ++i)
3971  {
3972  dst.write_mask = ins->dst[0].write_mask & (WINED3DSP_WRITEMASK_0 << i);
3973  if (!(write_mask = shader_glsl_append_dst_ext(ins->ctx->buffer, ins,
3974  &dst, dst.reg.data_type)))
3975  continue;
3976 
3977  shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src);
3978  shader_addline(ins->ctx->buffer, fmt, src.param_str);
3979  }
3980 }
3981 
3983 {
3984  struct wined3d_string_buffer *buffer = ins->ctx->buffer;
3985  struct wined3d_shader_dst_param dst;
3986  struct glsl_src_param src[4];
3987  const char *instruction;
3988  BOOL tmp_dst = FALSE;
3989  char mask_char[6];
3990  unsigned int i, j;
3991  DWORD write_mask;
3992 
3993  switch (ins->handler_idx)
3994  {
3995  case WINED3DSIH_BFI: instruction = "bitfieldInsert"; break;
3996  case WINED3DSIH_IBFE: instruction = "bitfieldExtract"; break;
3997  case WINED3DSIH_UBFE: instruction = "bitfieldExtract"; break;
3998  default:
3999  ERR("Unhandled opcode %#x.\n", ins->handler_idx);
4000  return;
4001  }
4002 
4003  for (i = 0; i < ins->src_count; ++i)
4004  {
4005  if (ins->dst[0].reg.idx[0].offset == ins->src[i].reg.idx[0].offset
4006  && ins->dst[0].reg.type == ins->src[i].reg.type)
4007  tmp_dst = TRUE;
4008  }
4009 
4010  dst = ins->dst[0];
4011  for (i = 0; i < 4; ++i)
4012  {
4013  dst.write_mask = ins->dst[0].write_mask & (WINED3DSP_WRITEMASK_0 << i);
4014  if (tmp_dst && (write_mask = shader_glsl_get_write_mask(&dst, mask_char)))
4015  shader_addline(buffer, "tmp0%s = %sBitsToFloat(", mask_char,
4016  dst.reg.data_type == WINED3D_DATA_INT ? "int" : "uint");
4017  else if (!(write_mask = shader_glsl_append_dst_ext(buffer, ins, &dst, dst.reg.data_type)))
4018  continue;
4019 
4020  for (j = 0; j < ins->src_count; ++j)
4021  shader_glsl_add_src_param(ins, &ins->src[j], write_mask, &src[j]);
4022  shader_addline(buffer, "%s(", instruction);
4023  for (j = 0; j < ins->src_count - 2; ++j)
4024  shader_addline(buffer, "%s, ", src[ins->src_count - j - 1].param_str);
4025  shader_addline(buffer, "%s & 0x1f, %s & 0x1f));\n", src[1].param_str, src[0].param_str);
4026  }
4027 
4028  if (tmp_dst)
4029  {
4030  shader_glsl_append_dst_ext(buffer, ins, &ins->dst[0], WINED3D_DATA_FLOAT);
4031  shader_glsl_get_write_mask(&ins->dst[0], mask_char);
4032  shader_addline(buffer, "tmp0%s);\n", mask_char);
4033  }
4034 }
4035 
4036 static void shader_glsl_nop(const struct wined3d_shader_instruction *ins) {}
4037 
4038 static void shader_glsl_nrm(const struct wined3d_shader_instruction *ins)
4039 {
4040  struct wined3d_string_buffer *buffer = ins->ctx->buffer;
4041  struct glsl_src_param src_param;
4042  unsigned int mask_size;
4043  DWORD write_mask;
4044  char dst_mask[6];
4045 
4046  write_mask = shader_glsl_get_write_mask(ins->dst, dst_mask);
4047  mask_size = shader_glsl_get_write_mask_size(write_mask);
4048  shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param);
4049 
4050  shader_addline(buffer, "tmp0.x = dot(%s, %s);\n",
4051  src_param.param_str, src_param.param_str);
4052  shader_glsl_append_dst(buffer, ins);
4053 
4054  if (mask_size > 1)
4055  {
4056  shader_addline(buffer, "tmp0.x == 0.0 ? vec%u(0.0) : (%s * inversesqrt(tmp0.x)));\n",
4057  mask_size, src_param.param_str);
4058  }
4059  else
4060  {
4061  shader_addline(buffer, "tmp0.x == 0.0 ? 0.0 : (%s * inversesqrt(tmp0.x)));\n",
4062  src_param.param_str);
4063  }
4064 }
4065 
4067 {
4068  DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major,
4069  ins->ctx->reg_maps->shader_version.minor);
4070  struct wined3d_string_buffer *buffer = ins->ctx->buffer;
4071  struct glsl_src_param src0_param;
4072  const char *prefix, *suffix;
4073  unsigned int dst_size;
4074  DWORD dst_write_mask;
4075 
4076  dst_write_mask = shader_glsl_append_dst(buffer, ins);
4077  dst_size = shader_glsl_get_write_mask_size(dst_write_mask);
4078 
4079  if (shader_version < WINED3D_SHADER_VERSION(4, 0))
4080  dst_write_mask = WINED3DSP_WRITEMASK_3;
4081 
4082  shader_glsl_add_src_param(ins, &ins->src[0], dst_write_mask, &src0_param);
4083 
4084  switch (ins->handler_idx)
4085  {
4086  case WINED3DSIH_EXP:
4087  case WINED3DSIH_EXPP:
4088  prefix = "exp2(";
4089  suffix = ")";
4090  break;
4091 
4092  case WINED3DSIH_LOG:
4093  case WINED3DSIH_LOGP:
4094  prefix = "log2(abs(";
4095  suffix = "))";
4096  break;
4097 
4098  case WINED3DSIH_RCP:
4099  prefix = "1.0 / ";
4100  suffix = "";
4101  break;
4102 
4103  case WINED3DSIH_RSQ:
4104  prefix = "inversesqrt(abs(";
4105  suffix = "))";
4106  break;
4107 
4108  default:
4109  prefix = "";
4110  suffix = "";
4111  FIXME("Unhandled instruction %#x.\n", ins->handler_idx);
4112  break;
4113  }
4114 
4115  if (dst_size > 1 && shader_version < WINED3D_SHADER_VERSION(4, 0))
4116  shader_addline(buffer, "vec%u(%s%s%s));\n", dst_size, prefix, src0_param.param_str, suffix);
4117  else
4118  shader_addline(buffer, "%s%s%s);\n", prefix, src0_param.param_str, suffix);
4119 }
4120 
4130 static void shader_glsl_expp(const struct wined3d_shader_instruction *ins)
4131 {
4132  if (ins->ctx->reg_maps->shader_version.major < 2)
4133  {
4134  struct glsl_src_param src_param;
4135  char dst_mask[6];
4136 
4137  shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &src_param);
4138 
4139  shader_addline(ins->ctx->buffer, "tmp0.x = exp2(floor(%s));\n", src_param.param_str);
4140  shader_addline(ins->ctx->buffer, "tmp0.y = %s - floor(%s);\n", src_param.param_str, src_param.param_str);
4141  shader_addline(ins->ctx->buffer, "tmp0.z = exp2(%s);\n", src_param.param_str);
4142  shader_addline(ins->ctx->buffer, "tmp0.w = 1.0;\n");
4143 
4144  shader_glsl_append_dst(ins->ctx->buffer, ins);
4145  shader_glsl_get_write_mask(&ins->dst[0], dst_mask);
4146  shader_addline(ins->ctx->buffer, "tmp0%s);\n", dst_mask);
4147  return;
4148  }
4149 
4150  shader_glsl_scalar_op(ins);
4151 }
4152 
4153 static void shader_glsl_cast(const struct wined3d_shader_instruction *ins,
4154  const char *vector_constructor, const char *scalar_constructor)
4155 {
4156  struct wined3d_string_buffer *buffer = ins->ctx->buffer;
4157  struct glsl_src_param src_param;
4158  unsigned int mask_size;
4159  DWORD write_mask;
4160 
4161  write_mask = shader_glsl_append_dst(buffer, ins);
4162  mask_size = shader_glsl_get_write_mask_size(write_mask);
4163  shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param);
4164 
4165  if (mask_size > 1)
4166  shader_addline(buffer, "%s%u(%s));\n", vector_constructor, mask_size, src_param.param_str);
4167  else
4168  shader_addline(buffer, "%s(%s));\n", scalar_constructor, src_param.param_str);
4169 }
4170 
4171 static void shader_glsl_to_int(const struct wined3d_shader_instruction *ins)
4172 {
4173  shader_glsl_cast(ins, "ivec", "int");
4174 }
4175 
4176 static void shader_glsl_to_uint(const struct wined3d_shader_instruction *ins)
4177 {
4178  shader_glsl_cast(ins, "uvec", "uint");
4179 }
4180 
4181 static void shader_glsl_to_float(const struct wined3d_shader_instruction *ins)
4182 {
4183  shader_glsl_cast(ins, "vec", "float");
4184 }
4185 
4187 static void shader_glsl_compare(const struct wined3d_shader_instruction *ins)
4188 {
4189  struct glsl_src_param src0_param;
4190  struct glsl_src_param src1_param;
4191  DWORD write_mask;
4192  unsigned int mask_size;
4193 
4194  write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
4195  mask_size = shader_glsl_get_write_mask_size(write_mask);
4196  shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
4197  shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
4198 
4199  if (mask_size > 1) {
4200  const char *compare;
4201 
4202  switch(ins->handler_idx)
4203  {
4204  case WINED3DSIH_SLT: compare = "lessThan"; break;
4205  case WINED3DSIH_SGE: compare = "greaterThanEqual"; break;
4206  default: compare = "";
4207  FIXME("Can't handle opcode %s.\n", debug_d3dshaderinstructionhandler(ins->handler_idx));
4208  }
4209 
4210  shader_addline(ins->ctx->buffer, "vec%d(%s(%s, %s)));\n", mask_size, compare,
4211  src0_param.param_str, src1_param.param_str);
4212  } else {
4213  switch(ins->handler_idx)
4214  {
4215  case WINED3DSIH_SLT:
4216  /* Step(src0, src1) is not suitable here because if src0 == src1 SLT is supposed,
4217  * to return 0.0 but step returns 1.0 because step is not < x
4218  * An alternative is a bvec compare padded with an unused second component.
4219  * step(src1 * -1.0, src0 * -1.0) is not an option because it suffers from the same
4220  * issue. Playing with not() is not possible either because not() does not accept
4221  * a scalar.
4222  */
4223  shader_addline(ins->ctx->buffer, "(%s < %s) ? 1.0 : 0.0);\n",
4224  src0_param.param_str, src1_param.param_str);
4225  break;
4226  case WINED3DSIH_SGE:
4227  /* Here we can use the step() function and safe a conditional */
4228  shader_addline(ins->ctx->buffer, "step(%s, %s));\n", src1_param.param_str, src0_param.param_str);
4229  break;
4230  default:
4231  FIXME("Can't handle opcode %s.\n", debug_d3dshaderinstructionhandler(ins->handler_idx));
4232  }
4233 
4234  }
4235 }
4236 
4237 static void shader_glsl_swapc(const struct wined3d_shader_instruction *ins)
4238 {
4239  struct wined3d_string_buffer *buffer = ins->ctx->buffer;
4240  struct wined3d_shader_dst_param dst[2];
4241  struct glsl_src_param src[3];
4242  unsigned int i, j, k;
4243  char mask_char[6];
4244  DWORD write_mask;
4245  BOOL tmp_dst[2];
4246 
4247  for (i = 0; i < ins->dst_count; ++i)
4248  {
4249  tmp_dst[i] = FALSE;
4250  for (j = 0; j < ins->src_count; ++j)
4251  {
4252  if (ins->dst[i].reg.idx[0].offset == ins->src[j].reg.idx[0].offset
4253  && ins->dst[i].reg.type == ins->src[j].reg.type)
4254  tmp_dst[i] = TRUE;
4255  }
4256  }
4257 
4258  dst[0] = ins->dst[0];
4259  dst[1] = ins->dst[1];
4260  for (i = 0; i < 4; ++i)
4261  {
4262  for (j = 0; j < ARRAY_SIZE(dst); ++j)
4263  {
4264  dst[j].write_mask = ins->dst[j].write_mask & (WINED3DSP_WRITEMASK_0 << i);
4265  if (tmp_dst[j] && (write_mask = shader_glsl_get_write_mask(&dst[j], mask_char)))
4266  shader_addline(buffer, "tmp%u%s = (", j, mask_char);
4267  else if (!(write_mask = shader_glsl_append_dst_ext(buffer, ins, &dst[j], dst[j].reg.data_type)))
4268  continue;
4269 
4270  for (k = 0; k < ARRAY_SIZE(src); ++k)
4271  shader_glsl_add_src_param(ins, &ins->src[k], write_mask, &src[k]);
4272 
4273  shader_addline(buffer, "%sbool(%s) ? %s : %s);\n", !j ? "!" : "",
4274  src[0].param_str, src[1].param_str, src[2].param_str);
4275  }
4276  }
4277 
4278  for (i = 0; i < ARRAY_SIZE(tmp_dst); ++i)
4279  {
4280  if (tmp_dst[i])
4281  {
4282  shader_glsl_get_write_mask(&ins->dst[i], mask_char);
4283  shader_glsl_append_dst_ext(buffer, ins, &ins->dst[i], ins->dst[i].reg.data_type);
4284  shader_addline(buffer, "tmp%u%s);\n", i, mask_char);
4285  }
4286  }
4287 }
4288 
4290 {
4291  const char *condition_prefix, *condition_suffix;
4292  struct wined3d_shader_dst_param dst;
4293  struct glsl_src_param src0_param;
4294  struct glsl_src_param src1_param;
4295  struct glsl_src_param src2_param;
4296  BOOL temp_destination = FALSE;
4297  DWORD cmp_channel = 0;
4298  unsigned int i, j;
4299  char mask_char[6];
4300  DWORD write_mask;
4301 
4302  switch (ins->handler_idx)
4303  {
4304  case WINED3DSIH_CMP:
4305  condition_prefix = "";
4306  condition_suffix = " >= 0.0";
4307  break;
4308 
4309  case WINED3DSIH_CND:
4310  condition_prefix = "";
4311  condition_suffix = " > 0.5";
4312  break;
4313 
4314  case WINED3DSIH_MOVC:
4315  condition_prefix = "bool(";
4316  condition_suffix = ")";
4317  break;
4318 
4319  default:
4320  FIXME("Unhandled instruction %#x.\n", ins->handler_idx);
4321  condition_prefix = "<unhandled prefix>";
4322  condition_suffix = "<unhandled suffix>";
4323  break;
4324  }
4325 
4326  if (shader_is_scalar(&ins->dst[0].reg) || shader_is_scalar(&ins->src[0].reg))
4327  {
4328  write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
4329  shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src0_param);
4330  shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
4331  shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param);
4332 
4333  shader_addline(ins->ctx->buffer, "%s%s%s ? %s : %s);\n",
4334  condition_prefix, src0_param.param_str, condition_suffix,
4335  src1_param.param_str, src2_param.param_str);
4336  return;
4337  }
4338 
4339  dst = ins->dst[0];
4340 
4341  /* Splitting the instruction up in multiple lines imposes a problem:
4342  * The first lines may overwrite source parameters of the following lines.
4343  * Deal with that by using a temporary destination register if needed. */
4344  if ((ins->src[0].reg.idx[0].offset == dst.reg.idx[0].offset
4345  && ins->src[0].reg.type == dst.reg.type)
4346  || (ins->src[1].reg.idx[0].offset == dst.reg.idx[0].offset
4347  && ins->src[1].reg.type == dst.reg.type)
4348  || (ins->src[2].reg.idx[0].offset == dst.reg.idx[0].offset
4349  && ins->src[2].reg.type == dst.reg.type))
4350  temp_destination = TRUE;
4351 
4352  /* Cycle through all source0 channels. */
4353  for (i = 0; i < 4; ++i)
4354  {
4355  write_mask = 0;
4356  /* Find the destination channels which use the current source0 channel. */
4357  for (j = 0; j < 4; ++j)
4358  {
4359  if (shader_glsl_swizzle_get_component(ins->src[0].swizzle, j) == i)
4360  {
4361  write_mask |= WINED3DSP_WRITEMASK_0 << j;
4362  cmp_channel = WINED3DSP_WRITEMASK_0 << j;
4363  }
4364  }
4365  dst.write_mask = ins->dst[0].write_mask & write_mask;
4366 
4367  if (temp_destination)
4368  {
4369  if (!(write_mask = shader_glsl_get_write_mask(&dst, mask_char)))
4370  continue;
4371  shader_addline(ins->ctx->buffer, "tmp0%s = (", mask_char);
4372  }
4373  else if (!(write_mask = shader_glsl_append_dst_ext(ins->ctx->buffer, ins, &dst, dst.reg.data_type)))
4374  continue;
4375 
4376  shader_glsl_add_src_param(ins, &ins->src[0], cmp_channel, &src0_param);
4377  shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
4378  shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param);
4379 
4380  shader_addline(ins->ctx->buffer, "%s%s%s ? %s : %s);\n",
4381  condition_prefix, src0_param.param_str, condition_suffix,
4382  src1_param.param_str, src2_param.param_str);
4383  }
4384 
4385  if (temp_destination)
4386  {
4387  shader_glsl_get_write_mask(&ins->dst[0], mask_char);
4388  shader_glsl_append_dst(ins->ctx->buffer, ins);
4389  shader_addline(ins->ctx->buffer, "tmp0%s);\n", mask_char);
4390  }
4391 }
4392 
4394 /* For ps 1.1-1.3, only a single component of src0 is used. For ps 1.4
4395  * the compare is done per component of src0. */
4396 static void shader_glsl_cnd(const struct wined3d_shader_instruction *ins)
4397 {
4398  struct glsl_src_param src0_param;
4399  struct glsl_src_param src1_param;
4400  struct glsl_src_param src2_param;
4401  DWORD write_mask;
4402  DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major,
4403  ins->ctx->reg_maps->shader_version.minor);
4404 
4405  if (shader_version < WINED3D_SHADER_VERSION(1, 4))
4406  {
4407  write_mask = shader_glsl_append_dst(ins->ctx->buffer, ins);
4408  shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_0, &src0_param);
4409  shader_glsl_add_src_param(ins, &ins->src[1], write_mask, &src1_param);
4410  shader_glsl_add_src_param(ins, &ins->src[2], write_mask, &src2_param);
4411 
4412  if (ins->coissue && ins->dst->write_mask != WINED3DSP_WRITEMASK_3)
4413  shader_addline(ins->ctx->buffer, "%s /* COISSUE! */);\n", src1_param.param_str);
4414  else
4415  shader_addline(ins->ctx->buffer, "%s > 0.5 ? %s : %s);\n",
4416  src0_param.param_str, src1_param.param_str, src2_param.param_str);
4417  return;
4418  }
4419 
4421 }
4422 
4424 static void shader_glsl_mad(const struct wined3d_shader_instruction *ins)
4425 {
4426  struct glsl_src_param src0_param;
4427