aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2015-04-20 21:25:25 +0200
committermarha <marha@users.sourceforge.net>2015-04-20 21:25:25 +0200
commit4ba9be2882d9f1567809edb0a31fcdf11320d41f (patch)
treef796ab7a5044f9dd99aac7cb9a7c836857987635 /mesalib/src
parent82c8df11062f72a7d467e26cedbbd8b322ff7a70 (diff)
downloadvcxsrv-4ba9be2882d9f1567809edb0a31fcdf11320d41f.tar.gz
vcxsrv-4ba9be2882d9f1567809edb0a31fcdf11320d41f.tar.bz2
vcxsrv-4ba9be2882d9f1567809edb0a31fcdf11320d41f.zip
randrproto xkeyboard-config fontconfig libX11 libXdmcp libXmu pixman xkbcomp xserver mesa git update 20 Apr 2015
xserver commit b1029716e41e252f149b82124a149da180607c96 xkeyboard-config commit 7d00bcc2d9c3944bbdfcbe472ee3299729dc7687 libX11 commit 748d47e69f5c12d8557d56a8a8ec166588da7b93 libXdmcp commit b10f382e3aa2e86cd5a2bc27d6758da55f0ab1f6 xkbcomp commit 1ae525b3d236b59e6437b2b5433d460e18370973 pixman commit 58e21d3e45c5227c2ca9ac00cf044f22a7975180 randrproto commit 98da0d6e48b7d124d6788ea568e9f9e3dc204322 libXmu commit 4459e6940fe3fdf26a8d5d4c71989498bc400a62 fontconfig commit 07be485a0a84995ce69bf60e3b1bb22cb35f6b0e mesa commit c1485f4b7d044724b3dbc1011f3c3a8a53132010
Diffstat (limited to 'mesalib/src')
-rw-r--r--mesalib/src/Makefile.am8
-rw-r--r--mesalib/src/SConscript5
-rw-r--r--mesalib/src/gallium/auxiliary/Makefile.am2
-rw-r--r--mesalib/src/gallium/auxiliary/Makefile.sources6
-rw-r--r--mesalib/src/gallium/auxiliary/hud/hud_driver_query.c3
-rw-r--r--mesalib/src/gallium/auxiliary/nir/tgsi_to_nir.c1750
-rw-r--r--mesalib/src/gallium/auxiliary/nir/tgsi_to_nir.h30
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_debug_symbol.c12
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_linkage.c149
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_linkage.h67
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_math.h18
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_tile.c12
-rw-r--r--mesalib/src/glsl/Makefile.am11
-rw-r--r--mesalib/src/glsl/Makefile.sources10
-rw-r--r--mesalib/src/glsl/ast_function.cpp112
-rw-r--r--mesalib/src/glsl/ast_to_hir.cpp68
-rw-r--r--mesalib/src/glsl/builtin_functions.cpp4
-rw-r--r--mesalib/src/glsl/glsl_lexer.ll20
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.cpp11
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.h5
-rw-r--r--mesalib/src/glsl/glsl_types.cpp76
-rw-r--r--mesalib/src/glsl/glsl_types.h6
-rw-r--r--mesalib/src/glsl/ir.cpp14
-rw-r--r--mesalib/src/glsl/ir.h102
-rw-r--r--mesalib/src/glsl/ir_constant_expression.cpp2
-rw-r--r--mesalib/src/glsl/ir_equals.cpp20
-rw-r--r--mesalib/src/glsl/ir_validate.cpp8
-rw-r--r--mesalib/src/glsl/link_uniforms.cpp4
-rw-r--r--mesalib/src/glsl/link_varyings.cpp13
-rw-r--r--mesalib/src/glsl/linker.cpp236
-rw-r--r--mesalib/src/glsl/loop_controls.cpp2
-rw-r--r--mesalib/src/glsl/lower_const_arrays_to_uniforms.cpp4
-rw-r--r--mesalib/src/glsl/nir/glsl_to_nir.cpp92
-rw-r--r--mesalib/src/glsl/nir/nir.c64
-rw-r--r--mesalib/src/glsl/nir/nir.h51
-rw-r--r--mesalib/src/glsl/nir/nir_algebraic.py17
-rw-r--r--mesalib/src/glsl/nir/nir_builder.h135
-rw-r--r--mesalib/src/glsl/nir/nir_from_ssa.c9
-rw-r--r--mesalib/src/glsl/nir/nir_lower_idiv.c155
-rw-r--r--mesalib/src/glsl/nir/nir_lower_phis_to_scalar.c2
-rw-r--r--mesalib/src/glsl/nir/nir_lower_samplers.cpp45
-rw-r--r--mesalib/src/glsl/nir/nir_lower_tex_projector.c143
-rw-r--r--mesalib/src/glsl/nir/nir_lower_var_copies.c8
-rw-r--r--mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c2
-rw-r--r--mesalib/src/glsl/nir/nir_normalize_cubemap_coords.c110
-rw-r--r--mesalib/src/glsl/nir/nir_opcodes.py8
-rw-r--r--mesalib/src/glsl/nir/nir_opt_algebraic.py63
-rw-r--r--mesalib/src/glsl/nir/nir_opt_cse.c32
-rw-r--r--mesalib/src/glsl/nir/nir_opt_peephole_ffma.c261
-rw-r--r--mesalib/src/glsl/nir/nir_opt_peephole_select.c4
-rw-r--r--mesalib/src/glsl/nir/nir_print.c36
-rw-r--r--mesalib/src/glsl/nir/nir_remove_dead_variables.c22
-rw-r--r--mesalib/src/glsl/nir/nir_search.c4
-rw-r--r--mesalib/src/glsl/nir/nir_split_var_copies.c4
-rw-r--r--mesalib/src/glsl/nir/nir_sweep.c172
-rw-r--r--mesalib/src/glsl/nir/nir_to_ssa.c2
-rw-r--r--mesalib/src/glsl/nir/nir_types.cpp6
-rw-r--r--mesalib/src/glsl/nir/nir_types.h1
-rw-r--r--mesalib/src/glsl/nir/nir_validate.c16
-rw-r--r--mesalib/src/glsl/opt_algebraic.cpp32
-rw-r--r--mesalib/src/glsl/opt_cse.cpp63
-rw-r--r--mesalib/src/glsl/s_expression.cpp4
-rw-r--r--mesalib/src/glsl/shader_enums.h187
-rw-r--r--mesalib/src/loader/Makefile.am1
-rw-r--r--mesalib/src/mapi/glapi/gen/ARB_direct_state_access.xml118
-rw-r--r--mesalib/src/mapi/glapi/gen/ARB_program_interface_query.xml109
-rw-r--r--mesalib/src/mapi/glapi/gen/gl_API.xml4
-rw-r--r--mesalib/src/mapi/glapi/gen/gl_genexec.py1
-rw-r--r--mesalib/src/mapi/stub.c2
-rw-r--r--mesalib/src/mesa/Makefile.am2
-rw-r--r--mesalib/src/mesa/Makefile.sources7
-rw-r--r--mesalib/src/mesa/SConscript7
-rw-r--r--mesalib/src/mesa/drivers/SConscript2
-rw-r--r--mesalib/src/mesa/drivers/dri/common/utils.c2
-rw-r--r--mesalib/src/mesa/drivers/dri/common/xmlconfig.c2
-rw-r--r--mesalib/src/mesa/drivers/dri/common/xmlpool/Makefile.am19
-rw-r--r--mesalib/src/mesa/drivers/dri/swrast/swrast.c2
-rw-r--r--mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h4
-rw-r--r--mesalib/src/mesa/main/.gitignore1
-rw-r--r--mesalib/src/mesa/main/atifragshader.c4
-rw-r--r--mesalib/src/mesa/main/attrib.c1
-rw-r--r--mesalib/src/mesa/main/bufferobj.c11
-rw-r--r--mesalib/src/mesa/main/colormac.h45
-rw-r--r--mesalib/src/mesa/main/context.c12
-rw-r--r--mesalib/src/mesa/main/debug.c2
-rw-r--r--mesalib/src/mesa/main/dlopen.h6
-rw-r--r--mesalib/src/mesa/main/errors.c43
-rw-r--r--mesalib/src/mesa/main/errors.h7
-rw-r--r--mesalib/src/mesa/main/extensions.c1
-rw-r--r--mesalib/src/mesa/main/fbobject.c439
-rw-r--r--mesalib/src/mesa/main/fbobject.h16
-rw-r--r--mesalib/src/mesa/main/ffvertex_prog.c6
-rw-r--r--mesalib/src/mesa/main/format_pack.py1
-rw-r--r--mesalib/src/mesa/main/format_unpack.h2
-rw-r--r--mesalib/src/mesa/main/format_unpack.py5
-rw-r--r--mesalib/src/mesa/main/glformats.c2
-rw-r--r--mesalib/src/mesa/main/imports.h24
-rw-r--r--mesalib/src/mesa/main/macros.h7
-rw-r--r--mesalib/src/mesa/main/mtypes.h184
-rw-r--r--mesalib/src/mesa/main/multisample.c9
-rw-r--r--mesalib/src/mesa/main/pipelineobj.c35
-rw-r--r--mesalib/src/mesa/main/pipelineobj.h3
-rw-r--r--mesalib/src/mesa/main/pixel.c1
-rw-r--r--mesalib/src/mesa/main/pixeltransfer.c2
-rw-r--r--mesalib/src/mesa/main/program_resource.c417
-rw-r--r--mesalib/src/mesa/main/program_resource.h58
-rw-r--r--mesalib/src/mesa/main/queryobj.c131
-rw-r--r--mesalib/src/mesa/main/queryobj.h14
-rw-r--r--mesalib/src/mesa/main/samplerobj.c25
-rw-r--r--mesalib/src/mesa/main/samplerobj.h5
-rw-r--r--mesalib/src/mesa/main/shader_query.cpp764
-rw-r--r--mesalib/src/mesa/main/shaderapi.c25
-rw-r--r--mesalib/src/mesa/main/shaderapi.h45
-rw-r--r--mesalib/src/mesa/main/shaderobj.c6
-rw-r--r--mesalib/src/mesa/main/state.c27
-rw-r--r--mesalib/src/mesa/main/texcompress.c1
-rw-r--r--mesalib/src/mesa/main/texcompress_fxt1.c1
-rw-r--r--mesalib/src/mesa/main/texcompress_rgtc.c1
-rw-r--r--mesalib/src/mesa/main/texcompress_s3tc.c9
-rw-r--r--mesalib/src/mesa/main/texparam.c1
-rw-r--r--mesalib/src/mesa/main/texstate.c2
-rw-r--r--mesalib/src/mesa/main/texstore.c1
-rw-r--r--mesalib/src/mesa/main/transformfeedback.c386
-rw-r--r--mesalib/src/mesa/main/transformfeedback.h30
-rw-r--r--mesalib/src/mesa/main/uniform_query.cpp138
-rw-r--r--mesalib/src/mesa/main/uniforms.c294
-rw-r--r--mesalib/src/mesa/main/uniforms.h5
-rw-r--r--mesalib/src/mesa/main/version.c1
-rw-r--r--mesalib/src/mesa/main/viewport.c48
-rw-r--r--mesalib/src/mesa/main/viewport.h3
-rw-r--r--mesalib/src/mesa/program/ir_to_mesa.cpp104
-rw-r--r--mesalib/src/mesa/program/prog_execute.c1
-rw-r--r--mesalib/src/mesa/program/prog_instruction.h2
-rw-r--r--mesalib/src/mesa/program/prog_parameter.c72
-rw-r--r--mesalib/src/mesa/program/prog_parameter.h9
-rw-r--r--mesalib/src/mesa/program/prog_to_nir.c1096
-rw-r--r--mesalib/src/mesa/program/prog_to_nir.h37
-rw-r--r--mesalib/src/mesa/program/program.c5
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom.c2
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom_array.c2
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom_constbuf.c2
-rw-r--r--mesalib/src/mesa/state_tracker/st_atom_shader.c3
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_clear.c2
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_program.c4
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_texture.c23
-rw-r--r--mesalib/src/mesa/state_tracker/st_debug.c1
-rw-r--r--mesalib/src/mesa/state_tracker/st_debug.h1
-rw-r--r--mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp237
-rw-r--r--mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.h7
-rw-r--r--mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c2
-rw-r--r--mesalib/src/mesa/state_tracker/st_program.c49
-rw-r--r--mesalib/src/mesa/state_tracker/st_program.h3
-rw-r--r--mesalib/src/mesa/state_tracker/st_texture.c8
-rw-r--r--mesalib/src/mesa/swrast/s_aatriangle.c1
-rw-r--r--mesalib/src/mesa/swrast/s_alpha.c1
-rw-r--r--mesalib/src/mesa/swrast/s_atifragshader.c1
-rw-r--r--mesalib/src/mesa/swrast/s_context.c1
-rw-r--r--mesalib/src/mesa/swrast/s_copypix.c1
-rw-r--r--mesalib/src/mesa/swrast/s_feedback.c1
-rw-r--r--mesalib/src/mesa/swrast/s_fog.c1
-rw-r--r--mesalib/src/mesa/swrast/s_fragprog.c2
-rw-r--r--mesalib/src/mesa/swrast/s_lines.c1
-rw-r--r--mesalib/src/mesa/swrast/s_linetemp.h4
-rw-r--r--mesalib/src/mesa/swrast/s_points.c1
-rw-r--r--mesalib/src/mesa/swrast/s_span.c3
-rw-r--r--mesalib/src/mesa/swrast/s_texcombine.c2
-rw-r--r--mesalib/src/mesa/swrast/s_texfetch.c1
-rw-r--r--mesalib/src/mesa/swrast/s_texfilter.c2
-rw-r--r--mesalib/src/mesa/swrast/s_texrender.c1
-rw-r--r--mesalib/src/mesa/swrast/s_triangle.c1
-rw-r--r--mesalib/src/mesa/swrast/s_tritemp.h4
-rw-r--r--mesalib/src/mesa/swrast/s_zoom.c1
-rw-r--r--mesalib/src/mesa/swrast_setup/ss_context.c7
-rw-r--r--mesalib/src/mesa/swrast_setup/ss_triangle.c1
-rw-r--r--mesalib/src/mesa/tnl/t_context.c12
-rw-r--r--mesalib/src/mesa/tnl/t_context.h1
-rw-r--r--mesalib/src/mesa/tnl/t_draw.c2
-rw-r--r--mesalib/src/mesa/tnl/t_rasterpos.c14
-rw-r--r--mesalib/src/mesa/tnl/t_vb_fog.c1
-rw-r--r--mesalib/src/mesa/tnl/t_vb_light.c1
-rw-r--r--mesalib/src/mesa/tnl/t_vb_lighttmp.h8
-rw-r--r--mesalib/src/mesa/tnl/t_vb_normals.c1
-rw-r--r--mesalib/src/mesa/tnl/t_vb_program.c1
-rw-r--r--mesalib/src/mesa/tnl/t_vb_texgen.c1
-rw-r--r--mesalib/src/mesa/tnl/t_vb_texmat.c1
-rw-r--r--mesalib/src/mesa/tnl/t_vb_vertex.c1
-rw-r--r--mesalib/src/mesa/tnl/t_vertex.c1
-rw-r--r--mesalib/src/mesa/tnl/t_vertex_generic.c4
-rw-r--r--mesalib/src/mesa/tnl/t_vertex_sse.c1
-rw-r--r--mesalib/src/mesa/vbo/vbo_exec_api.c2
-rw-r--r--mesalib/src/mesa/vbo/vbo_exec_draw.c4
-rw-r--r--mesalib/src/mesa/vbo/vbo_primitive_restart.c6
-rw-r--r--mesalib/src/mesa/vbo/vbo_rebase.c2
-rw-r--r--mesalib/src/mesa/vbo/vbo_save_api.c2
-rw-r--r--mesalib/src/mesa/x86/common_x86.c2
-rw-r--r--mesalib/src/util/ralloc.c26
-rw-r--r--mesalib/src/util/ralloc.h15
-rw-r--r--mesalib/src/util/u_atomic_test.c5
198 files changed, 7810 insertions, 2143 deletions
diff --git a/mesalib/src/Makefile.am b/mesalib/src/Makefile.am
index 8edf33373..18cb4ce76 100644
--- a/mesalib/src/Makefile.am
+++ b/mesalib/src/Makefile.am
@@ -53,7 +53,13 @@ if HAVE_GALLIUM
SUBDIRS += gallium
endif
-EXTRA_DIST = egl/docs getopt hgl SConscript
+EXTRA_DIST = \
+ egl/drivers/haiku \
+ egl/docs \
+ getopt hgl SConscript
+
+AM_CFLAGS = $(VISIBILITY_CFLAGS)
+AM_CXXFLAGS = $(VISIBILITY_CXXFLAGS)
AM_CPPFLAGS = \
-I$(top_srcdir)/include/ \
diff --git a/mesalib/src/SConscript b/mesalib/src/SConscript
index 188ab08b6..b0578e892 100644
--- a/mesalib/src/SConscript
+++ b/mesalib/src/SConscript
@@ -12,7 +12,8 @@ if env['hostonly']:
# compilation
Return()
-SConscript('loader/SConscript')
+if env['platform'] != 'windows':
+ SConscript('loader/SConscript')
# When env['gles'] is set, the targets defined in mapi/glapi/SConscript are not
# used. libgl-xlib and libgl-gdi adapt themselves to use the targets defined
@@ -30,7 +31,7 @@ SConscript('mesa/SConscript')
if not env['embedded']:
if env['platform'] not in ('cygwin', 'darwin', 'freebsd', 'haiku', 'windows'):
SConscript('glx/SConscript')
- if env['platform'] not in ['darwin', 'haiku', 'sunos']:
+ if env['platform'] not in ['darwin', 'haiku', 'sunos', 'windows']:
if env['dri']:
SConscript('egl/drivers/dri2/SConscript')
SConscript('egl/main/SConscript')
diff --git a/mesalib/src/gallium/auxiliary/Makefile.am b/mesalib/src/gallium/auxiliary/Makefile.am
index 27a8b3fe4..89c7a13e9 100644
--- a/mesalib/src/gallium/auxiliary/Makefile.am
+++ b/mesalib/src/gallium/auxiliary/Makefile.am
@@ -10,6 +10,7 @@ include $(top_srcdir)/src/gallium/Automake.inc
noinst_LTLIBRARIES = libgallium.la
AM_CFLAGS = \
+ -I$(top_builddir)/src/glsl/nir \
-I$(top_srcdir)/src/gallium/auxiliary/util \
$(GALLIUM_CFLAGS) \
$(VISIBILITY_CFLAGS) \
@@ -21,6 +22,7 @@ AM_CXXFLAGS = \
libgallium_la_SOURCES = \
$(C_SOURCES) \
+ $(NIR_SOURCES) \
$(GENERATED_SOURCES)
if HAVE_MESA_LLVM
diff --git a/mesalib/src/gallium/auxiliary/Makefile.sources b/mesalib/src/gallium/auxiliary/Makefile.sources
index b7174d6e7..ec7547cad 100644
--- a/mesalib/src/gallium/auxiliary/Makefile.sources
+++ b/mesalib/src/gallium/auxiliary/Makefile.sources
@@ -251,8 +251,6 @@ C_SOURCES := \
util/u_keymap.h \
util/u_linear.c \
util/u_linear.h \
- util/u_linkage.c \
- util/u_linkage.h \
util/u_math.c \
util/u_math.h \
util/u_memory.h \
@@ -304,6 +302,10 @@ C_SOURCES := \
util/u_vbuf.h \
util/u_video.h
+NIR_SOURCES := \
+ nir/tgsi_to_nir.c \
+ nir/tgsi_to_nir.h
+
VL_SOURCES := \
vl/vl_compositor.c \
vl/vl_compositor.h \
diff --git a/mesalib/src/gallium/auxiliary/hud/hud_driver_query.c b/mesalib/src/gallium/auxiliary/hud/hud_driver_query.c
index b48708c2f..53771fcae 100644
--- a/mesalib/src/gallium/auxiliary/hud/hud_driver_query.c
+++ b/mesalib/src/gallium/auxiliary/hud/hud_driver_query.c
@@ -157,7 +157,8 @@ hud_pipe_query_install(struct hud_pane *pane, struct pipe_context *pipe,
if (!gr)
return;
- strcpy(gr->name, name);
+ strncpy(gr->name, name, sizeof(gr->name));
+ gr->name[sizeof(gr->name) - 1] = '\0';
gr->query_data = CALLOC_STRUCT(query_info);
if (!gr->query_data) {
FREE(gr);
diff --git a/mesalib/src/gallium/auxiliary/nir/tgsi_to_nir.c b/mesalib/src/gallium/auxiliary/nir/tgsi_to_nir.c
new file mode 100644
index 000000000..59aaf6778
--- /dev/null
+++ b/mesalib/src/gallium/auxiliary/nir/tgsi_to_nir.c
@@ -0,0 +1,1750 @@
+/*
+ * Copyright © 2014-2015 Broadcom
+ * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "util/ralloc.h"
+#include "glsl/nir/nir.h"
+#include "glsl/nir/nir_builder.h"
+#include "glsl/list.h"
+#include "glsl/shader_enums.h"
+
+#include "nir/tgsi_to_nir.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_info.h"
+#include "tgsi/tgsi_scan.h"
+
+#define SWIZ(X, Y, Z, W) (unsigned[4]){ \
+ TGSI_SWIZZLE_##X, \
+ TGSI_SWIZZLE_##Y, \
+ TGSI_SWIZZLE_##Z, \
+ TGSI_SWIZZLE_##W, \
+ }
+
+struct ttn_reg_info {
+ /** nir register containing this TGSI index. */
+ nir_register *reg;
+ nir_variable *var;
+ /** Offset (in vec4s) from the start of var for this TGSI index. */
+ int offset;
+};
+
+struct ttn_compile {
+ union tgsi_full_token *token;
+ nir_builder build;
+ struct tgsi_shader_info *scan;
+
+ struct ttn_reg_info *output_regs;
+ struct ttn_reg_info *temp_regs;
+ nir_ssa_def **imm_defs;
+
+ nir_register *addr_reg;
+
+ /**
+ * Stack of cf_node_lists where instructions should be pushed as we pop
+ * back out of the control flow stack.
+ *
+ * For each IF/ELSE/ENDIF block, if_stack[if_stack_pos] has where the else
+ * instructions should be placed, and if_stack[if_stack_pos - 1] has where
+ * the next instructions outside of the if/then/else block go.
+ */
+ struct exec_list **if_stack;
+ unsigned if_stack_pos;
+
+ /**
+ * Stack of cf_node_lists where instructions should be pushed as we pop
+ * back out of the control flow stack.
+ *
+ * loop_stack[loop_stack_pos - 1] contains the cf_node_list for the outside
+ * of the loop.
+ */
+ struct exec_list **loop_stack;
+ unsigned loop_stack_pos;
+
+ /* How many TGSI_FILE_IMMEDIATE vec4s have been parsed so far. */
+ unsigned next_imm;
+};
+
+#define ttn_swizzle(b, src, x, y, z, w) \
+ nir_swizzle(b, src, SWIZ(x, y, z, w), 4, false)
+#define ttn_channel(b, src, swiz) \
+ nir_swizzle(b, src, SWIZ(swiz, swiz, swiz, swiz), 1, false)
+
+static nir_ssa_def *
+ttn_src_for_dest(nir_builder *b, nir_alu_dest *dest)
+{
+ nir_alu_src src;
+ memset(&src, 0, sizeof(src));
+
+ if (dest->dest.is_ssa)
+ src.src = nir_src_for_ssa(&dest->dest.ssa);
+ else {
+ assert(!dest->dest.reg.indirect);
+ src.src = nir_src_for_reg(dest->dest.reg.reg);
+ src.src.reg.base_offset = dest->dest.reg.base_offset;
+ }
+
+ for (int i = 0; i < 4; i++)
+ src.swizzle[i] = i;
+
+ return nir_fmov_alu(b, src, 4);
+}
+
+static void
+ttn_emit_declaration(struct ttn_compile *c)
+{
+ nir_builder *b = &c->build;
+ struct tgsi_full_declaration *decl = &c->token->FullDeclaration;
+ unsigned array_size = decl->Range.Last - decl->Range.First + 1;
+ unsigned file = decl->Declaration.File;
+ unsigned i;
+
+ if (file == TGSI_FILE_TEMPORARY) {
+ if (decl->Declaration.Array) {
+ /* for arrays, we create variables instead of registers: */
+ nir_variable *var = rzalloc(b->shader, nir_variable);
+
+ var->type = glsl_array_type(glsl_vec4_type(), array_size);
+ var->data.mode = nir_var_global;
+ var->name = ralloc_asprintf(var, "arr_%d", decl->Array.ArrayID);
+
+ exec_list_push_tail(&b->shader->globals, &var->node);
+
+ for (i = 0; i < array_size; i++) {
+ /* point all the matching slots to the same var,
+ * with appropriate offset set, mostly just so
+ * we know what to do when tgsi does a non-indirect
+ * access
+ */
+ c->temp_regs[decl->Range.First + i].reg = NULL;
+ c->temp_regs[decl->Range.First + i].var = var;
+ c->temp_regs[decl->Range.First + i].offset = i;
+ }
+ } else {
+ for (i = 0; i < array_size; i++) {
+ nir_register *reg = nir_local_reg_create(b->impl);
+ reg->num_components = 4;
+ c->temp_regs[decl->Range.First + i].reg = reg;
+ c->temp_regs[decl->Range.First + i].var = NULL;
+ c->temp_regs[decl->Range.First + i].offset = 0;
+ }
+ }
+ } else if (file == TGSI_FILE_ADDRESS) {
+ c->addr_reg = nir_local_reg_create(b->impl);
+ c->addr_reg->num_components = 4;
+ } else if (file == TGSI_FILE_SYSTEM_VALUE) {
+ /* Nothing to record for system values. */
+ } else if (file == TGSI_FILE_SAMPLER) {
+ /* Nothing to record for samplers. */
+ } else {
+ nir_variable *var;
+ assert(file == TGSI_FILE_INPUT ||
+ file == TGSI_FILE_OUTPUT ||
+ file == TGSI_FILE_CONSTANT);
+
+ /* nothing to do for UBOs: */
+ if ((file == TGSI_FILE_CONSTANT) && decl->Declaration.Dimension)
+ return;
+
+ var = rzalloc(b->shader, nir_variable);
+ var->data.driver_location = decl->Range.First;
+
+ var->type = glsl_vec4_type();
+ if (array_size > 1)
+ var->type = glsl_array_type(var->type, array_size);
+
+ switch (file) {
+ case TGSI_FILE_INPUT:
+ var->data.read_only = true;
+ var->data.mode = nir_var_shader_in;
+ var->name = ralloc_asprintf(var, "in_%d", decl->Range.First);
+
+ /* We should probably translate to a VERT_ATTRIB_* or VARYING_SLOT_*
+ * instead, but nothing in NIR core is looking at the value
+ * currently, and this is less change to drivers.
+ */
+ var->data.location = decl->Semantic.Name;
+ var->data.index = decl->Semantic.Index;
+
+ /* We definitely need to translate the interpolation field, because
+ * nir_print will decode it.
+ */
+ switch (decl->Interp.Interpolate) {
+ case TGSI_INTERPOLATE_CONSTANT:
+ var->data.interpolation = INTERP_QUALIFIER_FLAT;
+ break;
+ case TGSI_INTERPOLATE_LINEAR:
+ var->data.interpolation = INTERP_QUALIFIER_NOPERSPECTIVE;
+ break;
+ case TGSI_INTERPOLATE_PERSPECTIVE:
+ var->data.interpolation = INTERP_QUALIFIER_SMOOTH;
+ break;
+ }
+
+ exec_list_push_tail(&b->shader->inputs, &var->node);
+ break;
+ case TGSI_FILE_OUTPUT: {
+ /* Since we can't load from outputs in the IR, we make temporaries
+ * for the outputs and emit stores to the real outputs at the end of
+ * the shader.
+ */
+ nir_register *reg = nir_local_reg_create(b->impl);
+ reg->num_components = 4;
+ if (array_size > 1)
+ reg->num_array_elems = array_size;
+
+ var->data.mode = nir_var_shader_out;
+ var->name = ralloc_asprintf(var, "out_%d", decl->Range.First);
+
+ var->data.location = decl->Semantic.Name;
+ var->data.index = decl->Semantic.Index;
+
+ for (i = 0; i < array_size; i++) {
+ c->output_regs[decl->Range.First + i].offset = i;
+ c->output_regs[decl->Range.First + i].reg = reg;
+ }
+
+ exec_list_push_tail(&b->shader->outputs, &var->node);
+ }
+ break;
+ case TGSI_FILE_CONSTANT:
+ var->data.mode = nir_var_uniform;
+ var->name = ralloc_asprintf(var, "uniform_%d", decl->Range.First);
+
+ exec_list_push_tail(&b->shader->uniforms, &var->node);
+ break;
+ default:
+ unreachable("bad declaration file");
+ return;
+ }
+
+ }
+}
+
+static void
+ttn_emit_immediate(struct ttn_compile *c)
+{
+ nir_builder *b = &c->build;
+ struct tgsi_full_immediate *tgsi_imm = &c->token->FullImmediate;
+ nir_load_const_instr *load_const;
+ int i;
+
+ load_const = nir_load_const_instr_create(b->shader, 4);
+ c->imm_defs[c->next_imm] = &load_const->def;
+ c->next_imm++;
+
+ for (i = 0; i < 4; i++)
+ load_const->value.u[i] = tgsi_imm->u[i].Uint;
+
+ nir_instr_insert_after_cf_list(b->cf_node_list, &load_const->instr);
+}
+
+static nir_src
+ttn_src_for_indirect(struct ttn_compile *c, struct tgsi_ind_register *indirect);
+
+/* generate either a constant or indirect deref chain for accessing an
+ * array variable.
+ */
+static nir_deref_var *
+ttn_array_deref(struct ttn_compile *c, nir_intrinsic_instr *instr,
+ nir_variable *var, unsigned offset,
+ struct tgsi_ind_register *indirect)
+{
+ nir_deref_var *deref = nir_deref_var_create(instr, var);
+ nir_deref_array *arr = nir_deref_array_create(deref);
+
+ arr->base_offset = offset;
+ arr->deref.type = glsl_get_array_element(var->type);
+
+ if (indirect) {
+ arr->deref_array_type = nir_deref_array_type_indirect;
+ arr->indirect = ttn_src_for_indirect(c, indirect);
+ } else {
+ arr->deref_array_type = nir_deref_array_type_direct;
+ }
+
+ deref->deref.child = &arr->deref;
+
+ return deref;
+}
+
+static nir_src
+ttn_src_for_file_and_index(struct ttn_compile *c, unsigned file, unsigned index,
+ struct tgsi_ind_register *indirect,
+ struct tgsi_dimension *dim,
+ struct tgsi_ind_register *dimind)
+{
+ nir_builder *b = &c->build;
+ nir_src src;
+
+ memset(&src, 0, sizeof(src));
+
+ switch (file) {
+ case TGSI_FILE_TEMPORARY:
+ if (c->temp_regs[index].var) {
+ unsigned offset = c->temp_regs[index].offset;
+ nir_variable *var = c->temp_regs[index].var;
+ nir_intrinsic_instr *load;
+
+ load = nir_intrinsic_instr_create(b->shader,
+ nir_intrinsic_load_var);
+ load->num_components = 4;
+ load->variables[0] = ttn_array_deref(c, load, var, offset, indirect);
+
+ nir_ssa_dest_init(&load->instr, &load->dest, 4, NULL);
+ nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr);
+
+ src = nir_src_for_ssa(&load->dest.ssa);
+
+ } else {
+ assert(!indirect);
+ src.reg.reg = c->temp_regs[index].reg;
+ }
+ assert(!dim);
+ break;
+
+ case TGSI_FILE_ADDRESS:
+ src.reg.reg = c->addr_reg;
+ assert(!dim);
+ break;
+
+ case TGSI_FILE_IMMEDIATE:
+ src = nir_src_for_ssa(c->imm_defs[index]);
+ assert(!indirect);
+ assert(!dim);
+ break;
+
+ case TGSI_FILE_SYSTEM_VALUE: {
+ nir_intrinsic_instr *load;
+ nir_intrinsic_op op;
+ unsigned ncomp = 1;
+
+ assert(!indirect);
+ assert(!dim);
+
+ switch (c->scan->system_value_semantic_name[index]) {
+ case TGSI_SEMANTIC_VERTEXID_NOBASE:
+ op = nir_intrinsic_load_vertex_id_zero_base;
+ break;
+ case TGSI_SEMANTIC_VERTEXID:
+ op = nir_intrinsic_load_vertex_id;
+ break;
+ case TGSI_SEMANTIC_BASEVERTEX:
+ op = nir_intrinsic_load_base_vertex;
+ break;
+ case TGSI_SEMANTIC_INSTANCEID:
+ op = nir_intrinsic_load_instance_id;
+ break;
+ default:
+ unreachable("bad system value");
+ }
+
+ load = nir_intrinsic_instr_create(b->shader, op);
+ load->num_components = ncomp;
+
+ nir_ssa_dest_init(&load->instr, &load->dest, ncomp, NULL);
+ nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr);
+
+ src = nir_src_for_ssa(&load->dest.ssa);
+ break;
+ }
+
+ case TGSI_FILE_INPUT:
+ case TGSI_FILE_CONSTANT: {
+ nir_intrinsic_instr *load;
+ nir_intrinsic_op op;
+ unsigned srcn = 0;
+
+ switch (file) {
+ case TGSI_FILE_INPUT:
+ op = indirect ? nir_intrinsic_load_input_indirect :
+ nir_intrinsic_load_input;
+ assert(!dim);
+ break;
+ case TGSI_FILE_CONSTANT:
+ if (dim) {
+ op = indirect ? nir_intrinsic_load_ubo_indirect :
+ nir_intrinsic_load_ubo;
+ /* convert index from vec4 to byte: */
+ index *= 16;
+ } else {
+ op = indirect ? nir_intrinsic_load_uniform_indirect :
+ nir_intrinsic_load_uniform;
+ }
+ break;
+ default:
+ unreachable("No other load files supported");
+ break;
+ }
+
+ load = nir_intrinsic_instr_create(b->shader, op);
+
+ load->num_components = 4;
+ load->const_index[0] = index;
+ load->const_index[1] = 1;
+ if (dim) {
+ if (dimind) {
+ load->src[srcn] =
+ ttn_src_for_file_and_index(c, dimind->File, dimind->Index,
+ NULL, NULL, NULL);
+ } else {
+ /* UBOs start at index 1 in TGSI: */
+ load->src[srcn] =
+ nir_src_for_ssa(nir_imm_int(b, dim->Index - 1));
+ }
+ srcn++;
+ }
+ if (indirect) {
+ load->src[srcn] = ttn_src_for_indirect(c, indirect);
+ if (dim) {
+ assert(load->src[srcn].is_ssa);
+ /* we also need to covert vec4 to byte here too: */
+ load->src[srcn] =
+ nir_src_for_ssa(nir_ishl(b, load->src[srcn].ssa,
+ nir_imm_int(b, 4)));
+ }
+ srcn++;
+ }
+ nir_ssa_dest_init(&load->instr, &load->dest, 4, NULL);
+ nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr);
+
+ src = nir_src_for_ssa(&load->dest.ssa);
+ break;
+ }
+
+ default:
+ unreachable("bad src file");
+ }
+
+
+ return src;
+}
+
+static nir_src
+ttn_src_for_indirect(struct ttn_compile *c, struct tgsi_ind_register *indirect)
+{
+ nir_builder *b = &c->build;
+ nir_alu_src src;
+ memset(&src, 0, sizeof(src));
+ for (int i = 0; i < 4; i++)
+ src.swizzle[i] = indirect->Swizzle;
+ src.src = ttn_src_for_file_and_index(c,
+ indirect->File,
+ indirect->Index,
+ NULL, NULL, NULL);
+ return nir_src_for_ssa(nir_imov_alu(b, src, 1));
+}
+
+static nir_alu_dest
+ttn_get_dest(struct ttn_compile *c, struct tgsi_full_dst_register *tgsi_fdst)
+{
+ struct tgsi_dst_register *tgsi_dst = &tgsi_fdst->Register;
+ nir_alu_dest dest;
+ unsigned index = tgsi_dst->Index;
+
+ memset(&dest, 0, sizeof(dest));
+
+ if (tgsi_dst->File == TGSI_FILE_TEMPORARY) {
+ if (c->temp_regs[index].var) {
+ nir_builder *b = &c->build;
+ nir_intrinsic_instr *load;
+ struct tgsi_ind_register *indirect =
+ tgsi_dst->Indirect ? &tgsi_fdst->Indirect : NULL;
+ nir_register *reg;
+
+ /* this works, because TGSI will give us a base offset
+ * (in case of indirect index) that points back into
+ * the array. Access can be direct or indirect, we
+ * don't really care. Just create a one-shot dst reg
+ * that will get store_var'd back into the array var
+ * at the end of ttn_emit_instruction()
+ */
+ reg = nir_local_reg_create(c->build.impl);
+ reg->num_components = 4;
+ dest.dest.reg.reg = reg;
+ dest.dest.reg.base_offset = 0;
+
+ /* since the alu op might not write to all components
+ * of the temporary, we must first do a load_var to
+ * get the previous array elements into the register.
+ * This is one area that NIR could use a bit of
+ * improvement (or opt pass to clean up the mess
+ * once things are scalarized)
+ */
+
+ load = nir_intrinsic_instr_create(c->build.shader,
+ nir_intrinsic_load_var);
+ load->num_components = 4;
+ load->variables[0] =
+ ttn_array_deref(c, load, c->temp_regs[index].var,
+ c->temp_regs[index].offset,
+ indirect);
+
+ load->dest = nir_dest_for_reg(reg);
+
+ nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr);
+ } else {
+ assert(!tgsi_dst->Indirect);
+ dest.dest.reg.reg = c->temp_regs[index].reg;
+ dest.dest.reg.base_offset = c->temp_regs[index].offset;
+ }
+ } else if (tgsi_dst->File == TGSI_FILE_OUTPUT) {
+ dest.dest.reg.reg = c->output_regs[index].reg;
+ dest.dest.reg.base_offset = c->output_regs[index].offset;
+ } else if (tgsi_dst->File == TGSI_FILE_ADDRESS) {
+ assert(index == 0);
+ dest.dest.reg.reg = c->addr_reg;
+ }
+
+ dest.write_mask = tgsi_dst->WriteMask;
+ dest.saturate = false;
+
+ if (tgsi_dst->Indirect && (tgsi_dst->File != TGSI_FILE_TEMPORARY)) {
+ nir_src *indirect = ralloc(c->build.shader, nir_src);
+ *indirect = ttn_src_for_indirect(c, &tgsi_fdst->Indirect);
+ dest.dest.reg.indirect = indirect;
+ }
+
+ return dest;
+}
+
+static nir_variable *
+ttn_get_var(struct ttn_compile *c, struct tgsi_full_dst_register *tgsi_fdst)
+{
+ struct tgsi_dst_register *tgsi_dst = &tgsi_fdst->Register;
+ unsigned index = tgsi_dst->Index;
+
+ if (tgsi_dst->File == TGSI_FILE_TEMPORARY) {
+ /* we should not have an indirect when there is no var! */
+ if (!c->temp_regs[index].var)
+ assert(!tgsi_dst->Indirect);
+ return c->temp_regs[index].var;
+ }
+
+ return NULL;
+}
+
+static nir_ssa_def *
+ttn_get_src(struct ttn_compile *c, struct tgsi_full_src_register *tgsi_fsrc)
+{
+ nir_builder *b = &c->build;
+ struct tgsi_src_register *tgsi_src = &tgsi_fsrc->Register;
+ unsigned tgsi_opcode = c->token->FullInstruction.Instruction.Opcode;
+ unsigned tgsi_src_type = tgsi_opcode_infer_src_type(tgsi_opcode);
+ bool src_is_float = !(tgsi_src_type == TGSI_TYPE_SIGNED ||
+ tgsi_src_type == TGSI_TYPE_UNSIGNED);
+ nir_alu_src src;
+
+ memset(&src, 0, sizeof(src));
+
+ if (tgsi_src->File == TGSI_FILE_NULL) {
+ return nir_imm_float(b, 0.0);
+ } else if (tgsi_src->File == TGSI_FILE_SAMPLER) {
+ /* Only the index of the sampler gets used in texturing, and it will
+ * handle looking that up on its own instead of using the nir_alu_src.
+ */
+ assert(!tgsi_src->Indirect);
+ return NULL;
+ } else {
+ struct tgsi_ind_register *ind = NULL;
+ struct tgsi_dimension *dim = NULL;
+ struct tgsi_ind_register *dimind = NULL;
+ if (tgsi_src->Indirect)
+ ind = &tgsi_fsrc->Indirect;
+ if (tgsi_src->Dimension) {
+ dim = &tgsi_fsrc->Dimension;
+ if (dim->Indirect)
+ dimind = &tgsi_fsrc->DimIndirect;
+ }
+ src.src = ttn_src_for_file_and_index(c,
+ tgsi_src->File,
+ tgsi_src->Index,
+ ind, dim, dimind);
+ }
+
+ src.swizzle[0] = tgsi_src->SwizzleX;
+ src.swizzle[1] = tgsi_src->SwizzleY;
+ src.swizzle[2] = tgsi_src->SwizzleZ;
+ src.swizzle[3] = tgsi_src->SwizzleW;
+
+ nir_ssa_def *def = nir_fmov_alu(b, src, 4);
+
+ if (tgsi_src->Absolute) {
+ if (src_is_float)
+ def = nir_fabs(b, def);
+ else
+ def = nir_iabs(b, def);
+ }
+
+ if (tgsi_src->Negate) {
+ if (src_is_float)
+ def = nir_fneg(b, def);
+ else
+ def = nir_ineg(b, def);
+ }
+
+ return def;
+}
+
+static void
+ttn_alu(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ unsigned num_srcs = nir_op_infos[op].num_inputs;
+ nir_alu_instr *instr = nir_alu_instr_create(b->shader, op);
+ unsigned i;
+
+ for (i = 0; i < num_srcs; i++)
+ instr->src[i].src = nir_src_for_ssa(src[i]);
+
+ instr->dest = dest;
+ nir_instr_insert_after_cf_list(b->cf_node_list, &instr->instr);
+}
+
+static void
+ttn_move_dest_masked(nir_builder *b, nir_alu_dest dest,
+ nir_ssa_def *def, unsigned write_mask)
+{
+ if (!(dest.write_mask & write_mask))
+ return;
+
+ nir_alu_instr *mov = nir_alu_instr_create(b->shader, nir_op_imov);
+ mov->dest = dest;
+ mov->dest.write_mask &= write_mask;
+ mov->src[0].src = nir_src_for_ssa(def);
+ for (unsigned i = def->num_components; i < 4; i++)
+ mov->src[0].swizzle[i] = def->num_components - 1;
+ nir_instr_insert_after_cf_list(b->cf_node_list, &mov->instr);
+}
+
+static void
+ttn_move_dest(nir_builder *b, nir_alu_dest dest, nir_ssa_def *def)
+{
+ ttn_move_dest_masked(b, dest, def, TGSI_WRITEMASK_XYZW);
+}
+
+static void
+ttn_arl(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ttn_move_dest(b, dest, nir_f2i(b, nir_ffloor(b, src[0])));
+}
+
+/* EXP - Approximate Exponential Base 2
+ * dst.x = 2^{\lfloor src.x\rfloor}
+ * dst.y = src.x - \lfloor src.x\rfloor
+ * dst.z = 2^{src.x}
+ * dst.w = 1.0
+ */
+static void
+ttn_exp(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ nir_ssa_def *srcx = ttn_channel(b, src[0], X);
+
+ ttn_move_dest_masked(b, dest, nir_fexp2(b, nir_ffloor(b, srcx)),
+ TGSI_WRITEMASK_X);
+ ttn_move_dest_masked(b, dest, nir_fsub(b, srcx, nir_ffloor(b, srcx)),
+ TGSI_WRITEMASK_Y);
+ ttn_move_dest_masked(b, dest, nir_fexp2(b, srcx), TGSI_WRITEMASK_Z);
+ ttn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), TGSI_WRITEMASK_W);
+}
+
+/* LOG - Approximate Logarithm Base 2
+ * dst.x = \lfloor\log_2{|src.x|}\rfloor
+ * dst.y = \frac{|src.x|}{2^{\lfloor\log_2{|src.x|}\rfloor}}
+ * dst.z = \log_2{|src.x|}
+ * dst.w = 1.0
+ */
+static void
+ttn_log(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ nir_ssa_def *abs_srcx = nir_fabs(b, ttn_channel(b, src[0], X));
+ nir_ssa_def *log2 = nir_flog2(b, abs_srcx);
+
+ ttn_move_dest_masked(b, dest, nir_ffloor(b, log2), TGSI_WRITEMASK_X);
+ ttn_move_dest_masked(b, dest,
+ nir_fdiv(b, abs_srcx, nir_fexp2(b, nir_ffloor(b, log2))),
+ TGSI_WRITEMASK_Y);
+ ttn_move_dest_masked(b, dest, nir_flog2(b, abs_srcx), TGSI_WRITEMASK_Z);
+ ttn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), TGSI_WRITEMASK_W);
+}
+
+/* DST - Distance Vector
+ * dst.x = 1.0
+ * dst.y = src0.y \times src1.y
+ * dst.z = src0.z
+ * dst.w = src1.w
+ */
+static void
+ttn_dst(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ttn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), TGSI_WRITEMASK_X);
+ ttn_move_dest_masked(b, dest, nir_fmul(b, src[0], src[1]), TGSI_WRITEMASK_Y);
+ ttn_move_dest_masked(b, dest, nir_fmov(b, src[0]), TGSI_WRITEMASK_Z);
+ ttn_move_dest_masked(b, dest, nir_fmov(b, src[1]), TGSI_WRITEMASK_W);
+}
+
+/* LIT - Light Coefficients
+ * dst.x = 1.0
+ * dst.y = max(src.x, 0.0)
+ * dst.z = (src.x > 0.0) ? max(src.y, 0.0)^{clamp(src.w, -128.0, 128.0))} : 0
+ * dst.w = 1.0
+ */
+static void
+ttn_lit(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ttn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), TGSI_WRITEMASK_XW);
+
+ ttn_move_dest_masked(b, dest, nir_fmax(b, ttn_channel(b, src[0], X),
+ nir_imm_float(b, 0.0)), TGSI_WRITEMASK_Y);
+
+ if (dest.write_mask & TGSI_WRITEMASK_Z) {
+ nir_ssa_def *src0_y = ttn_channel(b, src[0], Y);
+ nir_ssa_def *wclamp = nir_fmax(b, nir_fmin(b, ttn_channel(b, src[0], W),
+ nir_imm_float(b, 128.0)),
+ nir_imm_float(b, -128.0));
+ nir_ssa_def *pow = nir_fpow(b, nir_fmax(b, src0_y, nir_imm_float(b, 0.0)),
+ wclamp);
+
+ ttn_move_dest_masked(b, dest,
+ nir_bcsel(b,
+ nir_fge(b,
+ nir_imm_float(b, 0.0),
+ ttn_channel(b, src[0], X)),
+ nir_imm_float(b, 0.0),
+ pow),
+ TGSI_WRITEMASK_Z);
+ }
+}
+
+/* SCS - Sine Cosine
+ * dst.x = \cos{src.x}
+ * dst.y = \sin{src.x}
+ * dst.z = 0.0
+ * dst.w = 1.0
+ */
+static void
+ttn_scs(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ttn_move_dest_masked(b, dest, nir_fcos(b, ttn_channel(b, src[0], X)),
+ TGSI_WRITEMASK_X);
+ ttn_move_dest_masked(b, dest, nir_fsin(b, ttn_channel(b, src[0], X)),
+ TGSI_WRITEMASK_Y);
+ ttn_move_dest_masked(b, dest, nir_imm_float(b, 0.0), TGSI_WRITEMASK_Z);
+ ttn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), TGSI_WRITEMASK_W);
+}
+
+static void
+ttn_sle(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ttn_move_dest(b, dest, nir_sge(b, src[1], src[0]));
+}
+
+static void
+ttn_sgt(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ttn_move_dest(b, dest, nir_slt(b, src[1], src[0]));
+}
+
+static void
+ttn_clamp(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ttn_move_dest(b, dest, nir_fmin(b, nir_fmax(b, src[0], src[1]), src[2]));
+}
+
+static void
+ttn_xpd(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ttn_move_dest_masked(b, dest,
+ nir_fsub(b,
+ nir_fmul(b,
+ ttn_swizzle(b, src[0], Y, Z, X, X),
+ ttn_swizzle(b, src[1], Z, X, Y, X)),
+ nir_fmul(b,
+ ttn_swizzle(b, src[1], Y, Z, X, X),
+ ttn_swizzle(b, src[0], Z, X, Y, X))),
+ TGSI_WRITEMASK_XYZ);
+ ttn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), TGSI_WRITEMASK_W);
+}
+
+static void
+ttn_dp2a(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ttn_move_dest(b, dest,
+ ttn_channel(b, nir_fadd(b, nir_fdot2(b, src[0], src[1]),
+ src[2]),
+ X));
+}
+
+static void
+ttn_dp2(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ttn_move_dest(b, dest, nir_fdot2(b, src[0], src[1]));
+}
+
+static void
+ttn_dp3(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ttn_move_dest(b, dest, nir_fdot3(b, src[0], src[1]));
+}
+
+static void
+ttn_dp4(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ttn_move_dest(b, dest, nir_fdot4(b, src[0], src[1]));
+}
+
+static void
+ttn_dph(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ttn_move_dest(b, dest, nir_fadd(b, nir_fdot3(b, src[0], src[1]),
+ ttn_channel(b, src[1], W)));
+}
+
+static void
+ttn_umad(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ttn_move_dest(b, dest, nir_iadd(b, nir_imul(b, src[0], src[1]), src[2]));
+}
+
+static void
+ttn_arr(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ttn_move_dest(b, dest, nir_ffloor(b, nir_fadd(b, src[0], nir_imm_float(b, 0.5))));
+}
+
+static void
+ttn_cmp(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ttn_move_dest(b, dest, nir_bcsel(b,
+ nir_flt(b, src[0], nir_imm_float(b, 0.0)),
+ src[1], src[2]));
+}
+
+static void
+ttn_ucmp(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ttn_move_dest(b, dest, nir_bcsel(b,
+ nir_ine(b, src[0], nir_imm_int(b, 0)),
+ src[1], src[2]));
+}
+
+static void
+ttn_kill(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ nir_intrinsic_instr *discard =
+ nir_intrinsic_instr_create(b->shader, nir_intrinsic_discard);
+ nir_instr_insert_after_cf_list(b->cf_node_list, &discard->instr);
+}
+
+static void
+ttn_kill_if(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ nir_ssa_def *cmp = nir_bany4(b, nir_flt(b, src[0], nir_imm_float(b, 0.0)));
+ nir_intrinsic_instr *discard =
+ nir_intrinsic_instr_create(b->shader, nir_intrinsic_discard_if);
+ discard->src[0] = nir_src_for_ssa(cmp);
+ nir_instr_insert_after_cf_list(b->cf_node_list, &discard->instr);
+}
+
+static void
+ttn_if(struct ttn_compile *c, nir_ssa_def *src, bool is_uint)
+{
+ nir_builder *b = &c->build;
+
+ /* Save the outside-of-the-if-statement node list. */
+ c->if_stack[c->if_stack_pos] = b->cf_node_list;
+ c->if_stack_pos++;
+
+ src = ttn_channel(b, src, X);
+
+ nir_if *if_stmt = nir_if_create(b->shader);
+ if (is_uint) {
+ if_stmt->condition = nir_src_for_ssa(nir_ine(b, src, nir_imm_int(b, 0)));
+ } else {
+ if_stmt->condition = nir_src_for_ssa(nir_fne(b, src, nir_imm_int(b, 0)));
+ }
+ nir_cf_node_insert_end(b->cf_node_list, &if_stmt->cf_node);
+
+ nir_builder_insert_after_cf_list(b, &if_stmt->then_list);
+
+ c->if_stack[c->if_stack_pos] = &if_stmt->else_list;
+ c->if_stack_pos++;
+}
+
+static void
+ttn_else(struct ttn_compile *c)
+{
+ nir_builder *b = &c->build;
+
+ nir_builder_insert_after_cf_list(b, c->if_stack[c->if_stack_pos - 1]);
+}
+
+static void
+ttn_endif(struct ttn_compile *c)
+{
+ nir_builder *b = &c->build;
+
+ c->if_stack_pos -= 2;
+ nir_builder_insert_after_cf_list(b, c->if_stack[c->if_stack_pos]);
+}
+
+static void
+ttn_bgnloop(struct ttn_compile *c)
+{
+ nir_builder *b = &c->build;
+
+ /* Save the outside-of-the-loop node list. */
+ c->loop_stack[c->loop_stack_pos] = b->cf_node_list;
+ c->loop_stack_pos++;
+
+ nir_loop *loop = nir_loop_create(b->shader);
+ nir_cf_node_insert_end(b->cf_node_list, &loop->cf_node);
+
+ nir_builder_insert_after_cf_list(b, &loop->body);
+}
+
+static void
+ttn_cont(nir_builder *b)
+{
+ nir_jump_instr *instr = nir_jump_instr_create(b->shader, nir_jump_continue);
+ nir_instr_insert_after_cf_list(b->cf_node_list, &instr->instr);
+}
+
+static void
+ttn_brk(nir_builder *b)
+{
+ nir_jump_instr *instr = nir_jump_instr_create(b->shader, nir_jump_break);
+ nir_instr_insert_after_cf_list(b->cf_node_list, &instr->instr);
+}
+
+static void
+ttn_endloop(struct ttn_compile *c)
+{
+ nir_builder *b = &c->build;
+
+ c->loop_stack_pos--;
+ nir_builder_insert_after_cf_list(b, c->loop_stack[c->loop_stack_pos]);
+}
+
+static void
+setup_texture_info(nir_tex_instr *instr, unsigned texture)
+{
+ switch (texture) {
+ case TGSI_TEXTURE_1D:
+ instr->sampler_dim = GLSL_SAMPLER_DIM_1D;
+ break;
+ case TGSI_TEXTURE_1D_ARRAY:
+ instr->sampler_dim = GLSL_SAMPLER_DIM_1D;
+ instr->is_array = true;
+ break;
+ case TGSI_TEXTURE_SHADOW1D:
+ instr->sampler_dim = GLSL_SAMPLER_DIM_1D;
+ instr->is_shadow = true;
+ break;
+ case TGSI_TEXTURE_SHADOW1D_ARRAY:
+ instr->sampler_dim = GLSL_SAMPLER_DIM_1D;
+ instr->is_shadow = true;
+ instr->is_array = true;
+ break;
+ case TGSI_TEXTURE_2D:
+ instr->sampler_dim = GLSL_SAMPLER_DIM_2D;
+ break;
+ case TGSI_TEXTURE_2D_ARRAY:
+ instr->sampler_dim = GLSL_SAMPLER_DIM_2D;
+ instr->is_array = true;
+ break;
+ case TGSI_TEXTURE_2D_MSAA:
+ instr->sampler_dim = GLSL_SAMPLER_DIM_MS;
+ break;
+ case TGSI_TEXTURE_2D_ARRAY_MSAA:
+ instr->sampler_dim = GLSL_SAMPLER_DIM_MS;
+ instr->is_array = true;
+ break;
+ case TGSI_TEXTURE_SHADOW2D:
+ instr->sampler_dim = GLSL_SAMPLER_DIM_2D;
+ instr->is_shadow = true;
+ break;
+ case TGSI_TEXTURE_SHADOW2D_ARRAY:
+ instr->sampler_dim = GLSL_SAMPLER_DIM_2D;
+ instr->is_shadow = true;
+ instr->is_array = true;
+ break;
+ case TGSI_TEXTURE_3D:
+ instr->sampler_dim = GLSL_SAMPLER_DIM_3D;
+ break;
+ case TGSI_TEXTURE_CUBE:
+ instr->sampler_dim = GLSL_SAMPLER_DIM_CUBE;
+ break;
+ case TGSI_TEXTURE_CUBE_ARRAY:
+ instr->sampler_dim = GLSL_SAMPLER_DIM_CUBE;
+ instr->is_array = true;
+ break;
+ case TGSI_TEXTURE_SHADOWCUBE:
+ instr->sampler_dim = GLSL_SAMPLER_DIM_CUBE;
+ instr->is_shadow = true;
+ break;
+ case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
+ instr->sampler_dim = GLSL_SAMPLER_DIM_CUBE;
+ instr->is_shadow = true;
+ instr->is_array = true;
+ break;
+ case TGSI_TEXTURE_RECT:
+ instr->sampler_dim = GLSL_SAMPLER_DIM_RECT;
+ break;
+ case TGSI_TEXTURE_SHADOWRECT:
+ instr->sampler_dim = GLSL_SAMPLER_DIM_RECT;
+ instr->is_shadow = true;
+ break;
+ default:
+ fprintf(stderr, "Unknown TGSI texture target %d\n", texture);
+ abort();
+ }
+}
+
+static void
+ttn_tex(struct ttn_compile *c, nir_alu_dest dest, nir_ssa_def **src)
+{
+ nir_builder *b = &c->build;
+ struct tgsi_full_instruction *tgsi_inst = &c->token->FullInstruction;
+ nir_tex_instr *instr;
+ nir_texop op;
+ unsigned num_srcs, samp = 1, i;
+
+ switch (tgsi_inst->Instruction.Opcode) {
+ case TGSI_OPCODE_TEX:
+ op = nir_texop_tex;
+ num_srcs = 1;
+ break;
+ case TGSI_OPCODE_TXP:
+ op = nir_texop_tex;
+ num_srcs = 2;
+ break;
+ case TGSI_OPCODE_TXB:
+ op = nir_texop_txb;
+ num_srcs = 2;
+ break;
+ case TGSI_OPCODE_TXL:
+ op = nir_texop_txl;
+ num_srcs = 2;
+ break;
+ case TGSI_OPCODE_TXL2:
+ op = nir_texop_txl;
+ num_srcs = 2;
+ samp = 2;
+ break;
+ case TGSI_OPCODE_TXF:
+ op = nir_texop_txf;
+ num_srcs = 2;
+ break;
+ case TGSI_OPCODE_TXD:
+ op = nir_texop_txd;
+ num_srcs = 3;
+ samp = 3;
+ break;
+
+ default:
+ fprintf(stderr, "unknown TGSI tex op %d\n", tgsi_inst->Instruction.Opcode);
+ abort();
+ }
+
+ if (tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOW1D ||
+ tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOW1D_ARRAY ||
+ tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOW2D ||
+ tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOW2D_ARRAY ||
+ tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOWRECT ||
+ tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOWCUBE ||
+ tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOWCUBE_ARRAY) {
+ num_srcs++;
+ }
+
+ num_srcs += tgsi_inst->Texture.NumOffsets;
+
+ instr = nir_tex_instr_create(b->shader, num_srcs);
+ instr->op = op;
+
+ setup_texture_info(instr, tgsi_inst->Texture.Texture);
+
+ switch (instr->sampler_dim) {
+ case GLSL_SAMPLER_DIM_1D:
+ case GLSL_SAMPLER_DIM_BUF:
+ instr->coord_components = 1;
+ break;
+ case GLSL_SAMPLER_DIM_2D:
+ case GLSL_SAMPLER_DIM_RECT:
+ case GLSL_SAMPLER_DIM_EXTERNAL:
+ case GLSL_SAMPLER_DIM_MS:
+ instr->coord_components = 2;
+ break;
+ case GLSL_SAMPLER_DIM_3D:
+ case GLSL_SAMPLER_DIM_CUBE:
+ instr->coord_components = 3;
+ break;
+ }
+
+ if (instr->is_array)
+ instr->coord_components++;
+
+ assert(tgsi_inst->Src[samp].Register.File == TGSI_FILE_SAMPLER);
+ instr->sampler_index = tgsi_inst->Src[samp].Register.Index;
+
+ unsigned src_number = 0;
+
+ instr->src[src_number].src =
+ nir_src_for_ssa(nir_swizzle(b, src[0], SWIZ(X, Y, Z, W),
+ instr->coord_components, false));
+ instr->src[src_number].src_type = nir_tex_src_coord;
+ src_number++;
+
+ if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXP) {
+ instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[0], W));
+ instr->src[src_number].src_type = nir_tex_src_projector;
+ src_number++;
+ }
+
+ if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXB) {
+ instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[0], W));
+ instr->src[src_number].src_type = nir_tex_src_bias;
+ src_number++;
+ }
+
+ if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXL) {
+ instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[0], W));
+ instr->src[src_number].src_type = nir_tex_src_lod;
+ src_number++;
+ }
+
+ if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXL2) {
+ instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[1], X));
+ instr->src[src_number].src_type = nir_tex_src_lod;
+ src_number++;
+ }
+
+ if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXF) {
+ instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[0], W));
+ instr->src[src_number].src_type = nir_tex_src_lod;
+ src_number++;
+ }
+
+ if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXD) {
+ instr->src[src_number].src =
+ nir_src_for_ssa(nir_swizzle(b, src[1], SWIZ(X, Y, Z, W),
+ instr->coord_components, false));
+ instr->src[src_number].src_type = nir_tex_src_ddx;
+ src_number++;
+ instr->src[src_number].src =
+ nir_src_for_ssa(nir_swizzle(b, src[2], SWIZ(X, Y, Z, W),
+ instr->coord_components, false));
+ instr->src[src_number].src_type = nir_tex_src_ddy;
+ src_number++;
+ }
+
+ if (instr->is_shadow) {
+ if (instr->coord_components < 3)
+ instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[0], Z));
+ else
+ instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[0], W));
+
+ instr->src[src_number].src_type = nir_tex_src_comparitor;
+ src_number++;
+ }
+
+ for (i = 0; i < tgsi_inst->Texture.NumOffsets; i++) {
+ struct tgsi_texture_offset *tex_offset = &tgsi_inst->TexOffsets[i];
+ /* since TexOffset ins't using tgsi_full_src_register we get to
+ * do some extra gymnastics:
+ */
+ nir_alu_src src;
+
+ memset(&src, 0, sizeof(src));
+
+ src.src = ttn_src_for_file_and_index(c,
+ tex_offset->File,
+ tex_offset->Index,
+ NULL, NULL, NULL);
+
+ src.swizzle[0] = tex_offset->SwizzleX;
+ src.swizzle[1] = tex_offset->SwizzleY;
+ src.swizzle[2] = tex_offset->SwizzleZ;
+ src.swizzle[3] = TGSI_SWIZZLE_W;
+
+ instr->src[src_number].src_type = nir_tex_src_offset;
+ instr->src[src_number].src = nir_src_for_ssa(
+ nir_fmov_alu(b, src, nir_tex_instr_src_size(instr, src_number)));
+ src_number++;
+ }
+
+ assert(src_number == num_srcs);
+
+ nir_ssa_dest_init(&instr->instr, &instr->dest, 4, NULL);
+ nir_instr_insert_after_cf_list(b->cf_node_list, &instr->instr);
+
+ /* Resolve the writemask on the texture op. */
+ ttn_move_dest(b, dest, &instr->dest.ssa);
+}
+
+/* TGSI_OPCODE_TXQ is actually two distinct operations:
+ *
+ * dst.x = texture\_width(unit, lod)
+ * dst.y = texture\_height(unit, lod)
+ * dst.z = texture\_depth(unit, lod)
+ * dst.w = texture\_levels(unit)
+ *
+ * dst.xyz map to NIR txs opcode, and dst.w maps to query_levels
+ */
+static void
+ttn_txq(struct ttn_compile *c, nir_alu_dest dest, nir_ssa_def **src)
+{
+ nir_builder *b = &c->build;
+ struct tgsi_full_instruction *tgsi_inst = &c->token->FullInstruction;
+ nir_tex_instr *txs, *qlv;
+
+ txs = nir_tex_instr_create(b->shader, 1);
+ txs->op = nir_texop_txs;
+ setup_texture_info(txs, tgsi_inst->Texture.Texture);
+
+ qlv = nir_tex_instr_create(b->shader, 0);
+ qlv->op = nir_texop_query_levels;
+ setup_texture_info(qlv, tgsi_inst->Texture.Texture);
+
+ assert(tgsi_inst->Src[1].Register.File == TGSI_FILE_SAMPLER);
+ txs->sampler_index = tgsi_inst->Src[1].Register.Index;
+ qlv->sampler_index = tgsi_inst->Src[1].Register.Index;
+
+ /* only single src, the lod: */
+ txs->src[0].src = nir_src_for_ssa(ttn_channel(b, src[0], X));
+ txs->src[0].src_type = nir_tex_src_lod;
+
+ nir_ssa_dest_init(&txs->instr, &txs->dest, 3, NULL);
+ nir_instr_insert_after_cf_list(b->cf_node_list, &txs->instr);
+
+ nir_ssa_dest_init(&qlv->instr, &qlv->dest, 1, NULL);
+ nir_instr_insert_after_cf_list(b->cf_node_list, &qlv->instr);
+
+ ttn_move_dest_masked(b, dest, &txs->dest.ssa, TGSI_WRITEMASK_XYZ);
+ ttn_move_dest_masked(b, dest, &qlv->dest.ssa, TGSI_WRITEMASK_W);
+}
+
+static const nir_op op_trans[TGSI_OPCODE_LAST] = {
+ [TGSI_OPCODE_ARL] = 0,
+ [TGSI_OPCODE_MOV] = nir_op_fmov,
+ [TGSI_OPCODE_LIT] = 0,
+ [TGSI_OPCODE_RCP] = nir_op_frcp,
+ [TGSI_OPCODE_RSQ] = nir_op_frsq,
+ [TGSI_OPCODE_EXP] = 0,
+ [TGSI_OPCODE_LOG] = 0,
+ [TGSI_OPCODE_MUL] = nir_op_fmul,
+ [TGSI_OPCODE_ADD] = nir_op_fadd,
+ [TGSI_OPCODE_DP3] = 0,
+ [TGSI_OPCODE_DP4] = 0,
+ [TGSI_OPCODE_DST] = 0,
+ [TGSI_OPCODE_MIN] = nir_op_fmin,
+ [TGSI_OPCODE_MAX] = nir_op_fmax,
+ [TGSI_OPCODE_SLT] = nir_op_slt,
+ [TGSI_OPCODE_SGE] = nir_op_sge,
+ [TGSI_OPCODE_MAD] = nir_op_ffma,
+ [TGSI_OPCODE_SUB] = nir_op_fsub,
+ [TGSI_OPCODE_LRP] = 0,
+ [TGSI_OPCODE_SQRT] = nir_op_fsqrt,
+ [TGSI_OPCODE_DP2A] = 0,
+ [TGSI_OPCODE_FRC] = nir_op_ffract,
+ [TGSI_OPCODE_CLAMP] = 0,
+ [TGSI_OPCODE_FLR] = nir_op_ffloor,
+ [TGSI_OPCODE_ROUND] = nir_op_fround_even,
+ [TGSI_OPCODE_EX2] = nir_op_fexp2,
+ [TGSI_OPCODE_LG2] = nir_op_flog2,
+ [TGSI_OPCODE_POW] = nir_op_fpow,
+ [TGSI_OPCODE_XPD] = 0,
+ [TGSI_OPCODE_ABS] = nir_op_fabs,
+ [TGSI_OPCODE_DPH] = 0,
+ [TGSI_OPCODE_COS] = nir_op_fcos,
+ [TGSI_OPCODE_DDX] = nir_op_fddx,
+ [TGSI_OPCODE_DDY] = nir_op_fddy,
+ [TGSI_OPCODE_KILL] = 0,
+ [TGSI_OPCODE_PK2H] = 0, /* XXX */
+ [TGSI_OPCODE_PK2US] = 0, /* XXX */
+ [TGSI_OPCODE_PK4B] = 0, /* XXX */
+ [TGSI_OPCODE_PK4UB] = 0, /* XXX */
+ [TGSI_OPCODE_SEQ] = nir_op_seq,
+ [TGSI_OPCODE_SGT] = 0,
+ [TGSI_OPCODE_SIN] = nir_op_fsin,
+ [TGSI_OPCODE_SLE] = 0,
+ [TGSI_OPCODE_TEX] = 0,
+ [TGSI_OPCODE_TXD] = 0,
+ [TGSI_OPCODE_TXP] = 0,
+ [TGSI_OPCODE_UP2H] = 0, /* XXX */
+ [TGSI_OPCODE_UP2US] = 0, /* XXX */
+ [TGSI_OPCODE_UP4B] = 0, /* XXX */
+ [TGSI_OPCODE_UP4UB] = 0, /* XXX */
+ [TGSI_OPCODE_ARR] = 0,
+
+ /* No function calls, yet. */
+ [TGSI_OPCODE_CAL] = 0, /* XXX */
+ [TGSI_OPCODE_RET] = 0, /* XXX */
+
+ [TGSI_OPCODE_SSG] = nir_op_fsign,
+ [TGSI_OPCODE_CMP] = 0,
+ [TGSI_OPCODE_SCS] = 0,
+ [TGSI_OPCODE_TXB] = 0,
+ [TGSI_OPCODE_DIV] = nir_op_fdiv,
+ [TGSI_OPCODE_DP2] = 0,
+ [TGSI_OPCODE_DP2A] = 0,
+ [TGSI_OPCODE_TXL] = 0,
+
+ [TGSI_OPCODE_BRK] = 0,
+ [TGSI_OPCODE_IF] = 0,
+ [TGSI_OPCODE_UIF] = 0,
+ [TGSI_OPCODE_ELSE] = 0,
+ [TGSI_OPCODE_ENDIF] = 0,
+
+ [TGSI_OPCODE_DDX_FINE] = nir_op_fddx_fine,
+ [TGSI_OPCODE_DDY_FINE] = nir_op_fddy_fine,
+
+ [TGSI_OPCODE_PUSHA] = 0, /* XXX */
+ [TGSI_OPCODE_POPA] = 0, /* XXX */
+
+ [TGSI_OPCODE_CEIL] = nir_op_fceil,
+ [TGSI_OPCODE_I2F] = nir_op_i2f,
+ [TGSI_OPCODE_NOT] = nir_op_inot,
+ [TGSI_OPCODE_TRUNC] = nir_op_ftrunc,
+ [TGSI_OPCODE_SHL] = nir_op_ishl,
+ [TGSI_OPCODE_AND] = nir_op_iand,
+ [TGSI_OPCODE_OR] = nir_op_ior,
+ [TGSI_OPCODE_MOD] = nir_op_umod,
+ [TGSI_OPCODE_XOR] = nir_op_ixor,
+ [TGSI_OPCODE_SAD] = 0, /* XXX */
+ [TGSI_OPCODE_TXF] = 0,
+ [TGSI_OPCODE_TXQ] = 0,
+
+ [TGSI_OPCODE_CONT] = 0,
+
+ [TGSI_OPCODE_EMIT] = 0, /* XXX */
+ [TGSI_OPCODE_ENDPRIM] = 0, /* XXX */
+
+ [TGSI_OPCODE_BGNLOOP] = 0,
+ [TGSI_OPCODE_BGNSUB] = 0, /* XXX: no function calls */
+ [TGSI_OPCODE_ENDLOOP] = 0,
+ [TGSI_OPCODE_ENDSUB] = 0, /* XXX: no function calls */
+
+ [TGSI_OPCODE_TXQ_LZ] = 0,
+ [TGSI_OPCODE_NOP] = 0,
+ [TGSI_OPCODE_FSEQ] = nir_op_feq,
+ [TGSI_OPCODE_FSGE] = nir_op_fge,
+ [TGSI_OPCODE_FSLT] = nir_op_flt,
+ [TGSI_OPCODE_FSNE] = nir_op_fne,
+
+ /* No control flow yet */
+ [TGSI_OPCODE_CALLNZ] = 0, /* XXX */
+ [TGSI_OPCODE_BREAKC] = 0, /* not emitted by glsl_to_tgsi.cpp */
+
+ [TGSI_OPCODE_KILL_IF] = 0,
+
+ [TGSI_OPCODE_END] = 0,
+
+ [TGSI_OPCODE_F2I] = nir_op_f2i,
+ [TGSI_OPCODE_IDIV] = nir_op_idiv,
+ [TGSI_OPCODE_IMAX] = nir_op_imax,
+ [TGSI_OPCODE_IMIN] = nir_op_imin,
+ [TGSI_OPCODE_INEG] = nir_op_ineg,
+ [TGSI_OPCODE_ISGE] = nir_op_ige,
+ [TGSI_OPCODE_ISHR] = nir_op_ishr,
+ [TGSI_OPCODE_ISLT] = nir_op_ilt,
+ [TGSI_OPCODE_F2U] = nir_op_f2u,
+ [TGSI_OPCODE_U2F] = nir_op_u2f,
+ [TGSI_OPCODE_UADD] = nir_op_iadd,
+ [TGSI_OPCODE_UDIV] = nir_op_udiv,
+ [TGSI_OPCODE_UMAD] = 0,
+ [TGSI_OPCODE_UMAX] = nir_op_umax,
+ [TGSI_OPCODE_UMIN] = nir_op_umin,
+ [TGSI_OPCODE_UMOD] = nir_op_umod,
+ [TGSI_OPCODE_UMUL] = nir_op_imul,
+ [TGSI_OPCODE_USEQ] = nir_op_ieq,
+ [TGSI_OPCODE_USGE] = nir_op_uge,
+ [TGSI_OPCODE_USHR] = nir_op_ushr,
+ [TGSI_OPCODE_USLT] = nir_op_ult,
+ [TGSI_OPCODE_USNE] = nir_op_ine,
+
+ [TGSI_OPCODE_SWITCH] = 0, /* not emitted by glsl_to_tgsi.cpp */
+ [TGSI_OPCODE_CASE] = 0, /* not emitted by glsl_to_tgsi.cpp */
+ [TGSI_OPCODE_DEFAULT] = 0, /* not emitted by glsl_to_tgsi.cpp */
+ [TGSI_OPCODE_ENDSWITCH] = 0, /* not emitted by glsl_to_tgsi.cpp */
+
+ /* XXX: SAMPLE opcodes */
+
+ [TGSI_OPCODE_UARL] = nir_op_imov,
+ [TGSI_OPCODE_UCMP] = 0,
+ [TGSI_OPCODE_IABS] = nir_op_iabs,
+ [TGSI_OPCODE_ISSG] = nir_op_isign,
+
+ /* XXX: atomics */
+
+ [TGSI_OPCODE_TEX2] = 0,
+ [TGSI_OPCODE_TXB2] = 0,
+ [TGSI_OPCODE_TXL2] = 0,
+
+ [TGSI_OPCODE_IMUL_HI] = nir_op_imul_high,
+ [TGSI_OPCODE_UMUL_HI] = nir_op_umul_high,
+
+ [TGSI_OPCODE_TG4] = 0,
+ [TGSI_OPCODE_LODQ] = 0, /* XXX */
+
+ [TGSI_OPCODE_IBFE] = nir_op_ibitfield_extract,
+ [TGSI_OPCODE_UBFE] = nir_op_ubitfield_extract,
+ [TGSI_OPCODE_BFI] = nir_op_bitfield_insert,
+ [TGSI_OPCODE_BREV] = nir_op_bitfield_reverse,
+ [TGSI_OPCODE_POPC] = nir_op_bit_count,
+ [TGSI_OPCODE_LSB] = nir_op_find_lsb,
+ [TGSI_OPCODE_IMSB] = nir_op_ifind_msb,
+ [TGSI_OPCODE_UMSB] = nir_op_ifind_msb, /* XXX: signed vs unsigned */
+
+ [TGSI_OPCODE_INTERP_CENTROID] = 0, /* XXX */
+ [TGSI_OPCODE_INTERP_SAMPLE] = 0, /* XXX */
+ [TGSI_OPCODE_INTERP_OFFSET] = 0, /* XXX */
+};
+
+static void
+ttn_emit_instruction(struct ttn_compile *c)
+{
+ nir_builder *b = &c->build;
+ struct tgsi_full_instruction *tgsi_inst = &c->token->FullInstruction;
+ unsigned i;
+ unsigned tgsi_op = tgsi_inst->Instruction.Opcode;
+ struct tgsi_full_dst_register *tgsi_dst = &tgsi_inst->Dst[0];
+
+ if (tgsi_op == TGSI_OPCODE_END)
+ return;
+
+ nir_ssa_def *src[TGSI_FULL_MAX_SRC_REGISTERS];
+ for (i = 0; i < TGSI_FULL_MAX_SRC_REGISTERS; i++) {
+ src[i] = ttn_get_src(c, &tgsi_inst->Src[i]);
+ }
+ nir_alu_dest dest = ttn_get_dest(c, tgsi_dst);
+
+ switch (tgsi_op) {
+ case TGSI_OPCODE_RSQ:
+ ttn_move_dest(b, dest, nir_frsq(b, ttn_channel(b, src[0], X)));
+ break;
+
+ case TGSI_OPCODE_SQRT:
+ ttn_move_dest(b, dest, nir_fsqrt(b, ttn_channel(b, src[0], X)));
+ break;
+
+ case TGSI_OPCODE_RCP:
+ ttn_move_dest(b, dest, nir_frcp(b, ttn_channel(b, src[0], X)));
+ break;
+
+ case TGSI_OPCODE_EX2:
+ ttn_move_dest(b, dest, nir_fexp2(b, ttn_channel(b, src[0], X)));
+ break;
+
+ case TGSI_OPCODE_LG2:
+ ttn_move_dest(b, dest, nir_flog2(b, ttn_channel(b, src[0], X)));
+ break;
+
+ case TGSI_OPCODE_POW:
+ ttn_move_dest(b, dest, nir_fpow(b,
+ ttn_channel(b, src[0], X),
+ ttn_channel(b, src[1], X)));
+ break;
+
+ case TGSI_OPCODE_COS:
+ ttn_move_dest(b, dest, nir_fcos(b, ttn_channel(b, src[0], X)));
+ break;
+
+ case TGSI_OPCODE_SIN:
+ ttn_move_dest(b, dest, nir_fsin(b, ttn_channel(b, src[0], X)));
+ break;
+
+ case TGSI_OPCODE_ARL:
+ ttn_arl(b, op_trans[tgsi_op], dest, src);
+ break;
+
+ case TGSI_OPCODE_EXP:
+ ttn_exp(b, op_trans[tgsi_op], dest, src);
+ break;
+
+ case TGSI_OPCODE_LOG:
+ ttn_log(b, op_trans[tgsi_op], dest, src);
+ break;
+
+ case TGSI_OPCODE_DST:
+ ttn_dst(b, op_trans[tgsi_op], dest, src);
+ break;
+
+ case TGSI_OPCODE_LIT:
+ ttn_lit(b, op_trans[tgsi_op], dest, src);
+ break;
+
+ case TGSI_OPCODE_CLAMP:
+ ttn_clamp(b, op_trans[tgsi_op], dest, src);
+ break;
+
+ case TGSI_OPCODE_XPD:
+ ttn_xpd(b, op_trans[tgsi_op], dest, src);
+ break;
+
+ case TGSI_OPCODE_DP2:
+ ttn_dp2(b, op_trans[tgsi_op], dest, src);
+ break;
+
+ case TGSI_OPCODE_DP3:
+ ttn_dp3(b, op_trans[tgsi_op], dest, src);
+ break;
+
+ case TGSI_OPCODE_DP4:
+ ttn_dp4(b, op_trans[tgsi_op], dest, src);
+ break;
+
+ case TGSI_OPCODE_DP2A:
+ ttn_dp2a(b, op_trans[tgsi_op], dest, src);
+ break;
+
+ case TGSI_OPCODE_DPH:
+ ttn_dph(b, op_trans[tgsi_op], dest, src);
+ break;
+
+ case TGSI_OPCODE_UMAD:
+ ttn_umad(b, op_trans[tgsi_op], dest, src);
+ break;
+
+ case TGSI_OPCODE_LRP:
+ ttn_move_dest(b, dest, nir_flrp(b, src[2], src[1], src[0]));
+ break;
+
+ case TGSI_OPCODE_KILL:
+ ttn_kill(b, op_trans[tgsi_op], dest, src);
+ break;
+
+ case TGSI_OPCODE_ARR:
+ ttn_arr(b, op_trans[tgsi_op], dest, src);
+ break;
+
+ case TGSI_OPCODE_CMP:
+ ttn_cmp(b, op_trans[tgsi_op], dest, src);
+ break;
+
+ case TGSI_OPCODE_UCMP:
+ ttn_ucmp(b, op_trans[tgsi_op], dest, src);
+ break;
+
+ case TGSI_OPCODE_SCS:
+ ttn_scs(b, op_trans[tgsi_op], dest, src);
+ break;
+
+ case TGSI_OPCODE_SGT:
+ ttn_sgt(b, op_trans[tgsi_op], dest, src);
+ break;
+
+ case TGSI_OPCODE_SLE:
+ ttn_sle(b, op_trans[tgsi_op], dest, src);
+ break;
+
+ case TGSI_OPCODE_KILL_IF:
+ ttn_kill_if(b, op_trans[tgsi_op], dest, src);
+ break;
+
+ case TGSI_OPCODE_TEX:
+ case TGSI_OPCODE_TXP:
+ case TGSI_OPCODE_TXL:
+ case TGSI_OPCODE_TXB:
+ case TGSI_OPCODE_TXD:
+ case TGSI_OPCODE_TXL2:
+ case TGSI_OPCODE_TXB2:
+ case TGSI_OPCODE_TXQ_LZ:
+ case TGSI_OPCODE_TXF:
+ case TGSI_OPCODE_TG4:
+ ttn_tex(c, dest, src);
+ break;
+
+ case TGSI_OPCODE_TXQ:
+ ttn_txq(c, dest, src);
+ break;
+
+ case TGSI_OPCODE_NOP:
+ break;
+
+ case TGSI_OPCODE_IF:
+ ttn_if(c, src[0], false);
+ break;
+
+ case TGSI_OPCODE_UIF:
+ ttn_if(c, src[0], true);
+ break;
+
+ case TGSI_OPCODE_ELSE:
+ ttn_else(c);
+ break;
+
+ case TGSI_OPCODE_ENDIF:
+ ttn_endif(c);
+ break;
+
+ case TGSI_OPCODE_BGNLOOP:
+ ttn_bgnloop(c);
+ break;
+
+ case TGSI_OPCODE_BRK:
+ ttn_brk(b);
+ break;
+
+ case TGSI_OPCODE_CONT:
+ ttn_cont(b);
+ break;
+
+ case TGSI_OPCODE_ENDLOOP:
+ ttn_endloop(c);
+ break;
+
+ default:
+ if (op_trans[tgsi_op] != 0 || tgsi_op == TGSI_OPCODE_MOV) {
+ ttn_alu(b, op_trans[tgsi_op], dest, src);
+ } else {
+ fprintf(stderr, "unknown TGSI opcode: %s\n",
+ tgsi_get_opcode_name(tgsi_op));
+ abort();
+ }
+ break;
+ }
+
+ if (tgsi_inst->Instruction.Saturate) {
+ assert(tgsi_inst->Instruction.Saturate == TGSI_SAT_ZERO_ONE);
+ assert(!dest.dest.is_ssa);
+ ttn_move_dest(b, dest, nir_fsat(b, ttn_src_for_dest(b, &dest)));
+ }
+
+ /* if the dst has a matching var, append store_global to move
+ * output from reg to var
+ */
+ nir_variable *var = ttn_get_var(c, tgsi_dst);
+ if (var) {
+ unsigned index = tgsi_dst->Register.Index;
+ unsigned offset = c->temp_regs[index].offset;
+ nir_intrinsic_instr *store =
+ nir_intrinsic_instr_create(b->shader, nir_intrinsic_store_var);
+ struct tgsi_ind_register *indirect = tgsi_dst->Register.Indirect ?
+ &tgsi_dst->Indirect : NULL;
+
+ store->num_components = 4;
+ store->variables[0] = ttn_array_deref(c, store, var, offset, indirect);
+ store->src[0] = nir_src_for_reg(dest.dest.reg.reg);
+
+ nir_instr_insert_after_cf_list(b->cf_node_list, &store->instr);
+ }
+}
+
+/**
+ * Puts a NIR intrinsic to store of each TGSI_FILE_OUTPUT value to the output
+ * variables at the end of the shader.
+ *
+ * We don't generate these incrementally as the TGSI_FILE_OUTPUT values are
+ * written, because there's no output load intrinsic, which means we couldn't
+ * handle writemasks.
+ */
+static void
+ttn_add_output_stores(struct ttn_compile *c)
+{
+ nir_builder *b = &c->build;
+
+ foreach_list_typed(nir_variable, var, node, &b->shader->outputs) {
+ unsigned array_len = MAX2(glsl_get_length(var->type), 1);
+ unsigned i;
+
+ for (i = 0; i < array_len; i++) {
+ nir_intrinsic_instr *store =
+ nir_intrinsic_instr_create(b->shader, nir_intrinsic_store_output);
+ store->num_components = 4;
+ store->const_index[0] = var->data.driver_location + i;
+ store->const_index[1] = 1;
+ store->src[0].reg.reg = c->output_regs[var->data.driver_location].reg;
+ nir_instr_insert_after_cf_list(b->cf_node_list, &store->instr);
+ }
+ }
+}
+
+struct nir_shader *
+tgsi_to_nir(const void *tgsi_tokens,
+ const nir_shader_compiler_options *options)
+{
+ struct tgsi_parse_context parser;
+ struct tgsi_shader_info scan;
+ struct ttn_compile *c;
+ struct nir_shader *s;
+ int ret;
+
+ c = rzalloc(NULL, struct ttn_compile);
+ s = nir_shader_create(NULL, options);
+
+ nir_function *func = nir_function_create(s, "main");
+ nir_function_overload *overload = nir_function_overload_create(func);
+ nir_function_impl *impl = nir_function_impl_create(overload);
+
+ nir_builder_init(&c->build, impl);
+ nir_builder_insert_after_cf_list(&c->build, &impl->body);
+
+ tgsi_scan_shader(tgsi_tokens, &scan);
+ c->scan = &scan;
+
+ s->num_inputs = scan.file_max[TGSI_FILE_INPUT] + 1;
+ s->num_uniforms = scan.const_file_max[0] + 1;
+ s->num_outputs = scan.file_max[TGSI_FILE_OUTPUT] + 1;
+
+ c->output_regs = rzalloc_array(c, struct ttn_reg_info,
+ scan.file_max[TGSI_FILE_OUTPUT] + 1);
+ c->temp_regs = rzalloc_array(c, struct ttn_reg_info,
+ scan.file_max[TGSI_FILE_TEMPORARY] + 1);
+ c->imm_defs = rzalloc_array(c, nir_ssa_def *,
+ scan.file_max[TGSI_FILE_IMMEDIATE] + 1);
+
+ c->if_stack = rzalloc_array(c, struct exec_list *,
+ (scan.opcode_count[TGSI_OPCODE_IF] +
+ scan.opcode_count[TGSI_OPCODE_UIF]) * 2);
+ c->loop_stack = rzalloc_array(c, struct exec_list *,
+ scan.opcode_count[TGSI_OPCODE_BGNLOOP]);
+
+ ret = tgsi_parse_init(&parser, tgsi_tokens);
+ assert(ret == TGSI_PARSE_OK);
+
+ while (!tgsi_parse_end_of_tokens(&parser)) {
+ tgsi_parse_token(&parser);
+ c->token = &parser.FullToken;
+
+ switch (parser.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ ttn_emit_declaration(c);
+ break;
+
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ ttn_emit_instruction(c);
+ break;
+
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ ttn_emit_immediate(c);
+ break;
+ }
+ }
+
+ tgsi_parse_free(&parser);
+
+ ttn_add_output_stores(c);
+
+ ralloc_free(c);
+ return s;
+}
diff --git a/mesalib/src/gallium/auxiliary/nir/tgsi_to_nir.h b/mesalib/src/gallium/auxiliary/nir/tgsi_to_nir.h
new file mode 100644
index 000000000..687348a80
--- /dev/null
+++ b/mesalib/src/gallium/auxiliary/nir/tgsi_to_nir.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright © 2014 Broadcom
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "glsl/nir/nir.h"
+
+struct nir_shader_compiler_options *options;
+
+struct nir_shader *
+tgsi_to_nir(const void *tgsi_tokens,
+ const struct nir_shader_compiler_options *options);
diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_symbol.c b/mesalib/src/gallium/auxiliary/util/u_debug_symbol.c
index bba9122e7..542493252 100644
--- a/mesalib/src/gallium/auxiliary/util/u_debug_symbol.c
+++ b/mesalib/src/gallium/auxiliary/util/u_debug_symbol.c
@@ -82,18 +82,10 @@ getDbgHelpProcAddress(LPCSTR lpProcName)
hModule = LoadLibraryA("mgwhelp.dll");
if (!hModule) {
_debug_printf("warning: mgwhelp.dll not found: symbol names will not be resolved\n"
- "warning: download it from http://code.google.com/p/jrfonseca/wiki/DrMingw#MgwHelp\n");
+ "warning: download it from https://github.com/jrfonseca/drmingw/#mgwhelp\n");
}
}
-
- /*
- * bfdhelp.dll was the predecessor of mgwhelp.dll. It is available from
- * http://people.freedesktop.org/~jrfonseca/bfdhelp/ for now.
- */
- if (!hModule) {
- hModule = LoadLibraryA("bfdhelp.dll");
- }
- #endif
+#endif
/*
* Fallback to the real DbgHelp.
diff --git a/mesalib/src/gallium/auxiliary/util/u_linkage.c b/mesalib/src/gallium/auxiliary/util/u_linkage.c
deleted file mode 100644
index 245d941dc..000000000
--- a/mesalib/src/gallium/auxiliary/util/u_linkage.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2010 Luca Barbieri
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#include "util/u_debug.h"
-#include "pipe/p_shader_tokens.h"
-#include "tgsi/tgsi_parse.h"
-#include "tgsi/tgsi_scan.h"
-#include "util/u_linkage.h"
-
-/* we must only record the registers that are actually used, not just declared */
-static INLINE boolean
-util_semantic_set_test_and_set(struct util_semantic_set *set, unsigned value)
-{
- unsigned mask = 1 << (value % (sizeof(long) * 8));
- unsigned long *p = &set->masks[value / (sizeof(long) * 8)];
- unsigned long v = *p & mask;
- *p |= mask;
- return !!v;
-}
-
-unsigned
-util_semantic_set_from_program_file(struct util_semantic_set *set, const struct tgsi_token *tokens, enum tgsi_file_type file)
-{
- struct tgsi_shader_info info;
- struct tgsi_parse_context parse;
- unsigned count = 0;
- ubyte *semantic_name;
- ubyte *semantic_index;
-
- tgsi_scan_shader(tokens, &info);
-
- if(file == TGSI_FILE_INPUT)
- {
- semantic_name = info.input_semantic_name;
- semantic_index = info.input_semantic_index;
- }
- else if(file == TGSI_FILE_OUTPUT)
- {
- semantic_name = info.output_semantic_name;
- semantic_index = info.output_semantic_index;
- }
- else
- {
- assert(0);
- semantic_name = NULL;
- semantic_index = NULL;
- }
-
- tgsi_parse_init(&parse, tokens);
-
- memset(set->masks, 0, sizeof(set->masks));
- while(!tgsi_parse_end_of_tokens(&parse))
- {
- tgsi_parse_token(&parse);
-
- if(parse.FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION)
- {
- const struct tgsi_full_instruction *finst = &parse.FullToken.FullInstruction;
- unsigned i;
- for(i = 0; i < finst->Instruction.NumDstRegs; ++i)
- {
- if(finst->Dst[i].Register.File == file)
- {
- unsigned idx = finst->Dst[i].Register.Index;
- if(semantic_name[idx] == TGSI_SEMANTIC_GENERIC)
- {
- if(!util_semantic_set_test_and_set(set, semantic_index[idx]))
- ++count;
- }
- }
- }
-
- for(i = 0; i < finst->Instruction.NumSrcRegs; ++i)
- {
- if(finst->Src[i].Register.File == file)
- {
- unsigned idx = finst->Src[i].Register.Index;
- if(semantic_name[idx] == TGSI_SEMANTIC_GENERIC)
- {
- if(!util_semantic_set_test_and_set(set, semantic_index[idx]))
- ++count;
- }
- }
- }
- }
- }
- tgsi_parse_free(&parse);
-
- return count;
-}
-
-#define UTIL_SEMANTIC_SET_FOR_EACH(i, set) for(i = 0; i < 256; ++i) if(set->masks[i / (sizeof(long) * 8)] & (1 << (i % (sizeof(long) * 8))))
-
-void
-util_semantic_layout_from_set(unsigned char *layout, const struct util_semantic_set *set, unsigned efficient_slots, unsigned num_slots)
-{
- int first = -1;
- int last = -1;
- unsigned i;
-
- memset(layout, 0xff, num_slots);
-
- UTIL_SEMANTIC_SET_FOR_EACH(i, set)
- {
- if(first < 0)
- first = i;
- last = i;
- }
-
- if (last < (int) efficient_slots)
- {
- UTIL_SEMANTIC_SET_FOR_EACH(i, set)
- layout[i] = i;
- }
- else if ((last - first) < (int) efficient_slots)
- {
- UTIL_SEMANTIC_SET_FOR_EACH(i, set)
- layout[i - first] = i;
- }
- else
- {
- unsigned idx = 0;
- UTIL_SEMANTIC_SET_FOR_EACH(i, set)
- layout[idx++] = i;
- }
-}
diff --git a/mesalib/src/gallium/auxiliary/util/u_linkage.h b/mesalib/src/gallium/auxiliary/util/u_linkage.h
deleted file mode 100644
index 7b23123d3..000000000
--- a/mesalib/src/gallium/auxiliary/util/u_linkage.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2010 Luca Barbieri
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#ifndef U_LINKAGE_H_
-#define U_LINKAGE_H_
-
-#include "pipe/p_compiler.h"
-#include "pipe/p_shader_tokens.h"
-
-struct util_semantic_set
-{
- unsigned long masks[256 / 8 / sizeof(unsigned long)];
-};
-
-static INLINE boolean
-util_semantic_set_contains(struct util_semantic_set *set, unsigned char value)
-{
- return !!(set->masks[value / (sizeof(long) * 8)] & (1 << (value / (sizeof(long) * 8))));
-}
-
-unsigned util_semantic_set_from_program_file(struct util_semantic_set *set, const struct tgsi_token *tokens, enum tgsi_file_type file);
-
-/* efficient_slots is the number of slots such that hardware performance is
- * the same for using that amount, with holes, or less slots but with less
- * holes.
- *
- * num_slots is the size of the layout array and hardware limit instead.
- *
- * efficient_slots == 0 or efficient_slots == num_slots are typical settings.
- */
-void util_semantic_layout_from_set(unsigned char *layout, const struct util_semantic_set *set, unsigned efficient_slots, unsigned num_slots);
-
-static INLINE void
-util_semantic_table_from_layout(unsigned char *table, size_t table_size, unsigned char *layout,
- unsigned char first_slot_value, unsigned char num_slots)
-{
- unsigned char i;
- memset(table, 0xff, table_size);
-
- for(i = 0; i < num_slots; ++i)
- table[layout[i]] = first_slot_value + i;
-}
-
-#endif /* U_LINKAGE_H_ */
diff --git a/mesalib/src/gallium/auxiliary/util/u_math.h b/mesalib/src/gallium/auxiliary/util/u_math.h
index 8f62cac66..3d27a59e8 100644
--- a/mesalib/src/gallium/auxiliary/util/u_math.h
+++ b/mesalib/src/gallium/auxiliary/util/u_math.h
@@ -383,14 +383,28 @@ unsigned ffs( unsigned u )
return i;
}
-#elif defined(__MINGW32__) || defined(PIPE_OS_ANDROID)
+#elif defined(__MINGW32__) || defined(PIPE_OS_ANDROID) || \
+ defined(HAVE___BUILTIN_FFS)
#define ffs __builtin_ffs
-#define ffsll __builtin_ffsll
#endif
#endif /* FFS_DEFINED */
/**
+ * Find first bit set in long long. Least significant bit is 1.
+ * Return 0 if no bits set.
+ */
+#ifndef FFSLL_DEFINED
+#define FFSLL_DEFINED 1
+
+#if defined(__MINGW32__) || defined(PIPE_OS_ANDROID) || \
+ defined(HAVE___BUILTIN_FFSLL)
+#define ffsll __builtin_ffsll
+#endif
+
+#endif /* FFSLL_DEFINED */
+
+/**
* Find last bit set in a word. The least significant bit is 1.
* Return 0 if no bits are set.
*/
diff --git a/mesalib/src/gallium/auxiliary/util/u_tile.c b/mesalib/src/gallium/auxiliary/util/u_tile.c
index 6252e5dcf..8e199200f 100644
--- a/mesalib/src/gallium/auxiliary/util/u_tile.c
+++ b/mesalib/src/gallium/auxiliary/util/u_tile.c
@@ -214,13 +214,13 @@ s8x24_get_tile_rgba(const unsigned *src,
unsigned i, j;
for (i = 0; i < h; i++) {
- float *pRow = p;
+ uint32_t *pRow = (uint32_t *)p;
for (j = 0; j < w; j++, pRow += 4) {
pRow[0] =
pRow[1] =
pRow[2] =
- pRow[3] = (float)((*src++ >> 24) & 0xff);
+ pRow[3] = ((*src++ >> 24) & 0xff);
}
p += dst_stride;
@@ -241,12 +241,12 @@ x24s8_get_tile_rgba(const unsigned *src,
unsigned i, j;
for (i = 0; i < h; i++) {
- float *pRow = p;
+ uint32_t *pRow = (uint32_t *)p;
for (j = 0; j < w; j++, pRow += 4) {
pRow[0] =
pRow[1] =
pRow[2] =
- pRow[3] = (float)(*src++ & 0xff);
+ pRow[3] = (*src++ & 0xff);
}
p += dst_stride;
}
@@ -265,12 +265,12 @@ s8_get_tile_rgba(const unsigned char *src,
unsigned i, j;
for (i = 0; i < h; i++) {
- float *pRow = p;
+ uint32_t *pRow = (uint32_t *)p;
for (j = 0; j < w; j++, pRow += 4) {
pRow[0] =
pRow[1] =
pRow[2] =
- pRow[3] = (float)(*src++ & 0xff);
+ pRow[3] = (*src++ & 0xff);
}
p += dst_stride;
}
diff --git a/mesalib/src/glsl/Makefile.am b/mesalib/src/glsl/Makefile.am
index b466a3b5c..23c6fe8bb 100644
--- a/mesalib/src/glsl/Makefile.am
+++ b/mesalib/src/glsl/Makefile.am
@@ -46,6 +46,7 @@ EXTRA_DIST = tests glcpp/tests README TODO glcpp/README \
glcpp/glcpp-lex.l \
glcpp/glcpp-parse.y \
nir/nir_algebraic.py \
+ nir/nir_builder_opcodes_h.py \
nir/nir_constant_expressions.py \
nir/nir_opcodes.py \
nir/nir_opcodes_c.py \
@@ -67,7 +68,7 @@ TESTS_ENVIRONMENT= \
export PYTHON2=$(PYTHON2); \
export PYTHON_FLAGS=$(PYTHON_FLAGS);
-noinst_LTLIBRARIES = libglsl.la libglcpp.la
+noinst_LTLIBRARIES = libnir.la libglsl.la libglcpp.la
check_PROGRAMS = \
glcpp/glcpp \
glsl_test \
@@ -147,6 +148,12 @@ libglsl_la_SOURCES = \
$(LIBGLSL_FILES) \
$(NIR_FILES)
+libnir_la_SOURCES = \
+ glsl_types.cpp \
+ builtin_types.cpp \
+ glsl_symbol_table.cpp \
+ $(NIR_FILES)
+
glsl_compiler_SOURCES = \
$(GLSL_COMPILER_CXX_FILES)
@@ -251,8 +258,6 @@ nir/nir_opcodes.h: nir/nir_opcodes.py nir/nir_opcodes_h.py
$(MKDIR_P) nir; \
$(PYTHON2) $(PYTHON_FLAGS) $(srcdir)/nir/nir_opcodes_h.py > $@
-nir/nir.h: nir/nir_opcodes.h
-
nir/nir_opcodes.c: nir/nir_opcodes.py nir/nir_opcodes_c.py
$(MKDIR_P) nir; \
$(PYTHON2) $(PYTHON_FLAGS) $(srcdir)/nir/nir_opcodes_c.py > $@
diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources
index b876642e8..c471eca23 100644
--- a/mesalib/src/glsl/Makefile.sources
+++ b/mesalib/src/glsl/Makefile.sources
@@ -22,6 +22,7 @@ NIR_FILES = \
nir/glsl_to_nir.h \
nir/nir.c \
nir/nir.h \
+ nir/nir_builder.h \
nir/nir_constant_expressions.h \
nir/nir_dominance.c \
nir/nir_from_ssa.c \
@@ -32,21 +33,25 @@ NIR_FILES = \
nir/nir_lower_atomics.c \
nir/nir_lower_global_vars_to_local.c \
nir/nir_lower_locals_to_regs.c \
+ nir/nir_lower_idiv.c \
nir/nir_lower_io.c \
nir/nir_lower_phis_to_scalar.c \
nir/nir_lower_samplers.cpp \
nir/nir_lower_system_values.c \
+ nir/nir_lower_tex_projector.c \
nir/nir_lower_to_source_mods.c \
nir/nir_lower_vars_to_ssa.c \
nir/nir_lower_var_copies.c \
nir/nir_lower_vec_to_movs.c \
nir/nir_metadata.c \
+ nir/nir_normalize_cubemap_coords.c \
nir/nir_opt_constant_folding.c \
nir/nir_opt_copy_propagate.c \
nir/nir_opt_cse.c \
nir/nir_opt_dce.c \
nir/nir_opt_gcm.c \
nir/nir_opt_global_to_local.c \
+ nir/nir_opt_peephole_ffma.c \
nir/nir_opt_peephole_select.c \
nir/nir_opt_remove_phis.c \
nir/nir_print.c \
@@ -54,9 +59,11 @@ NIR_FILES = \
nir/nir_search.c \
nir/nir_search.h \
nir/nir_split_var_copies.c \
+ nir/nir_sweep.c \
nir/nir_to_ssa.c \
nir/nir_types.h \
nir/nir_validate.c \
+ nir/nir_vla.h \
nir/nir_worklist.c \
nir/nir_worklist.h \
nir/nir_types.cpp \
@@ -183,7 +190,8 @@ LIBGLSL_FILES = \
opt_vectorize.cpp \
program.h \
s_expression.cpp \
- s_expression.h
+ s_expression.h \
+ shader_enums.h
# glsl_compiler
diff --git a/mesalib/src/glsl/ast_function.cpp b/mesalib/src/glsl/ast_function.cpp
index 918be6966..87df93e68 100644
--- a/mesalib/src/glsl/ast_function.cpp
+++ b/mesalib/src/glsl/ast_function.cpp
@@ -1370,71 +1370,59 @@ emit_inline_matrix_constructor(const glsl_type *type,
} else {
const unsigned cols = type->matrix_columns;
const unsigned rows = type->vector_elements;
+ unsigned remaining_slots = rows * cols;
unsigned col_idx = 0;
unsigned row_idx = 0;
foreach_in_list(ir_rvalue, rhs, parameters) {
- const unsigned components_remaining_this_column = rows - row_idx;
- unsigned rhs_components = rhs->type->components();
- unsigned rhs_base = 0;
-
- /* Since the parameter might be used in the RHS of two assignments,
- * generate a temporary and copy the paramter there.
- */
- ir_variable *rhs_var =
- new(ctx) ir_variable(rhs->type, "mat_ctor_vec", ir_var_temporary);
- instructions->push_tail(rhs_var);
-
- ir_dereference *rhs_var_ref =
- new(ctx) ir_dereference_variable(rhs_var);
- ir_instruction *inst = new(ctx) ir_assignment(rhs_var_ref, rhs, NULL);
- instructions->push_tail(inst);
-
- /* Assign the current parameter to as many components of the matrix
- * as it will fill.
- *
- * NOTE: A single vector parameter can span two matrix columns. A
- * single vec4, for example, can completely fill a mat2.
- */
- if (rhs_components >= components_remaining_this_column) {
- const unsigned count = MIN2(rhs_components,
- components_remaining_this_column);
-
- rhs_var_ref = new(ctx) ir_dereference_variable(rhs_var);
-
- ir_instruction *inst = assign_to_matrix_column(var, col_idx,
- row_idx,
- rhs_var_ref, 0,
- count, ctx);
- instructions->push_tail(inst);
-
- rhs_base = count;
-
- col_idx++;
- row_idx = 0;
- }
-
- /* If there is data left in the parameter and components left to be
- * set in the destination, emit another assignment. It is possible
- * that the assignment could be of a vec4 to the last element of the
- * matrix. In this case col_idx==cols, but there is still data
- * left in the source parameter. Obviously, don't emit an assignment
- * to data outside the destination matrix.
- */
- if ((col_idx < cols) && (rhs_base < rhs_components)) {
- const unsigned count = rhs_components - rhs_base;
-
- rhs_var_ref = new(ctx) ir_dereference_variable(rhs_var);
-
- ir_instruction *inst = assign_to_matrix_column(var, col_idx,
- row_idx,
- rhs_var_ref,
- rhs_base,
- count, ctx);
- instructions->push_tail(inst);
-
- row_idx += count;
- }
+ unsigned rhs_components = rhs->type->components();
+ unsigned rhs_base = 0;
+
+ if (remaining_slots == 0)
+ break;
+
+ /* Since the parameter might be used in the RHS of two assignments,
+ * generate a temporary and copy the paramter there.
+ */
+ ir_variable *rhs_var =
+ new(ctx) ir_variable(rhs->type, "mat_ctor_vec", ir_var_temporary);
+ instructions->push_tail(rhs_var);
+
+ ir_dereference *rhs_var_ref =
+ new(ctx) ir_dereference_variable(rhs_var);
+ ir_instruction *inst = new(ctx) ir_assignment(rhs_var_ref, rhs, NULL);
+ instructions->push_tail(inst);
+
+ do {
+ /* Assign the current parameter to as many components of the matrix
+ * as it will fill.
+ *
+ * NOTE: A single vector parameter can span two matrix columns. A
+ * single vec4, for example, can completely fill a mat2.
+ */
+ unsigned count = MIN2(rows - row_idx,
+ rhs_components - rhs_base);
+
+ rhs_var_ref = new(ctx) ir_dereference_variable(rhs_var);
+ ir_instruction *inst = assign_to_matrix_column(var, col_idx,
+ row_idx,
+ rhs_var_ref,
+ rhs_base,
+ count, ctx);
+ instructions->push_tail(inst);
+ rhs_base += count;
+ row_idx += count;
+ remaining_slots -= count;
+
+ /* Sometimes, there is still data left in the parameters and
+ * components left to be set in the destination but in other
+ * column.
+ */
+ if (row_idx >= rows) {
+ row_idx = 0;
+ col_idx++;
+ }
+ } while(remaining_slots > 0 && rhs_base < rhs_components);
}
}
@@ -1791,7 +1779,7 @@ ast_function_expression::hir(exec_list *instructions,
return value;
}
- return ir_rvalue::error_value(ctx);
+ unreachable("not reached");
}
ir_rvalue *
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp
index d387b2e35..78369360f 100644
--- a/mesalib/src/glsl/ast_to_hir.cpp
+++ b/mesalib/src/glsl/ast_to_hir.cpp
@@ -375,66 +375,14 @@ arithmetic_result_type(ir_rvalue * &value_a, ir_rvalue * &value_b,
if (type_a == type_b)
return type_a;
} else {
- if (type_a->is_matrix() && type_b->is_matrix()) {
- /* Matrix multiply. The columns of A must match the rows of B. Given
- * the other previously tested constraints, this means the vector type
- * of a row from A must be the same as the vector type of a column from
- * B.
- */
- if (type_a->row_type() == type_b->column_type()) {
- /* The resulting matrix has the number of columns of matrix B and
- * the number of rows of matrix A. We get the row count of A by
- * looking at the size of a vector that makes up a column. The
- * transpose (size of a row) is done for B.
- */
- const glsl_type *const type =
- glsl_type::get_instance(type_a->base_type,
- type_a->column_type()->vector_elements,
- type_b->row_type()->vector_elements);
- assert(type != glsl_type::error_type);
-
- return type;
- }
- } else if (type_a->is_matrix()) {
- /* A is a matrix and B is a column vector. Columns of A must match
- * rows of B. Given the other previously tested constraints, this
- * means the vector type of a row from A must be the same as the
- * vector the type of B.
- */
- if (type_a->row_type() == type_b) {
- /* The resulting vector has a number of elements equal to
- * the number of rows of matrix A. */
- const glsl_type *const type =
- glsl_type::get_instance(type_a->base_type,
- type_a->column_type()->vector_elements,
- 1);
- assert(type != glsl_type::error_type);
-
- return type;
- }
- } else {
- assert(type_b->is_matrix());
+ const glsl_type *type = glsl_type::get_mul_type(type_a, type_b);
- /* A is a row vector and B is a matrix. Columns of A must match rows
- * of B. Given the other previously tested constraints, this means
- * the type of A must be the same as the vector type of a column from
- * B.
- */
- if (type_a == type_b->column_type()) {
- /* The resulting vector has a number of elements equal to
- * the number of columns of matrix B. */
- const glsl_type *const type =
- glsl_type::get_instance(type_a->base_type,
- type_b->row_type()->vector_elements,
- 1);
- assert(type != glsl_type::error_type);
-
- return type;
- }
+ if (type == glsl_type::error_type) {
+ _mesa_glsl_error(loc, state,
+ "size mismatch for matrix multiplication");
}
- _mesa_glsl_error(loc, state, "size mismatch for matrix multiplication");
- return glsl_type::error_type;
+ return type;
}
@@ -5776,6 +5724,9 @@ ast_interface_block::hir(exec_list *instructions,
var->data.matrix_layout = matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED
? GLSL_MATRIX_LAYOUT_COLUMN_MAJOR : matrix_layout;
+ if (var_mode == ir_var_shader_in || var_mode == ir_var_uniform)
+ var->data.read_only = true;
+
if (state->stage == MESA_SHADER_GEOMETRY && var_mode == ir_var_shader_in)
handle_geometry_shader_input_decl(state, loc, var);
@@ -5816,6 +5767,9 @@ ast_interface_block::hir(exec_list *instructions,
var->data.sample = fields[i].sample;
var->init_interface_type(block_type);
+ if (var_mode == ir_var_shader_in || var_mode == ir_var_uniform)
+ var->data.read_only = true;
+
if (fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED) {
var->data.matrix_layout = matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED
? GLSL_MATRIX_LAYOUT_COLUMN_MAJOR : matrix_layout;
diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp
index c6075722c..524b8d6e8 100644
--- a/mesalib/src/glsl/builtin_functions.cpp
+++ b/mesalib/src/glsl/builtin_functions.cpp
@@ -60,7 +60,7 @@
#include "ir_builder.h"
#include "glsl_parser_extras.h"
#include "program/prog_instruction.h"
-#include <limits>
+#include <math.h>
#define M_PIf ((float) M_PI)
#define M_PI_2f ((float) M_PI_2)
@@ -3215,7 +3215,7 @@ builtin_builder::_isinf(builtin_available_predicate avail, const glsl_type *type
ir_constant_data infinities;
for (int i = 0; i < type->vector_elements; i++) {
- infinities.f[i] = std::numeric_limits<float>::infinity();
+ infinities.f[i] = INFINITY;
}
body.emit(ret(equal(abs(x), imm(type, infinities))));
diff --git a/mesalib/src/glsl/glsl_lexer.ll b/mesalib/src/glsl/glsl_lexer.ll
index 8dc3d106b..2785ed168 100644
--- a/mesalib/src/glsl/glsl_lexer.ll
+++ b/mesalib/src/glsl/glsl_lexer.ll
@@ -36,14 +36,13 @@ static int classify_identifier(struct _mesa_glsl_parse_state *, const char *);
#define YY_USER_ACTION \
do { \
- yylloc->source = 0; \
yylloc->first_column = yycolumn + 1; \
yylloc->first_line = yylloc->last_line = yylineno + 1; \
yycolumn += yyleng; \
yylloc->last_column = yycolumn + 1; \
} while(0);
-#define YY_USER_INIT yylineno = 0; yycolumn = 0;
+#define YY_USER_INIT yylineno = 0; yycolumn = 0; yylloc->source = 0;
/* A macro for handling reserved words and keywords across language versions.
*
@@ -188,6 +187,15 @@ HASH ^{SPC}#{SPC}
* one-based.
*/
yylineno = strtol(ptr, &ptr, 0) - 1;
+
+ /* From GLSL 3.30 and GLSL ES on, after processing the
+ * line directive (including its new-line), the implementation
+ * will behave as if it is compiling at the line number passed
+ * as argument. It was line number + 1 in older specifications.
+ */
+ if (yyextra->is_version(330, 100))
+ yylineno--;
+
yylloc->source = strtol(ptr, NULL, 0);
}
{HASH}line{SPCP}{INT}{SPC}$ {
@@ -203,6 +211,14 @@ HASH ^{SPC}#{SPC}
* one-based.
*/
yylineno = strtol(ptr, &ptr, 0) - 1;
+
+ /* From GLSL 3.30 and GLSL ES on, after processing the
+ * line directive (including its new-line), the implementation
+ * will behave as if it is compiling at the line number passed
+ * as argument. It was line number + 1 in older specifications.
+ */
+ if (yyextra->is_version(330, 100))
+ yylineno--;
}
^{SPC}#{SPC}pragma{SPCP}debug{SPC}\({SPC}on{SPC}\) {
BEGIN PP;
diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp
index 79624bc26..0aa3c54fc 100644
--- a/mesalib/src/glsl/glsl_parser_extras.cpp
+++ b/mesalib/src/glsl/glsl_parser_extras.cpp
@@ -73,8 +73,8 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
this->uses_builtin_functions = false;
/* Set default language version and extensions */
- this->language_version = ctx->Const.ForceGLSLVersion ?
- ctx->Const.ForceGLSLVersion : 110;
+ this->language_version = 110;
+ this->forced_language_version = ctx->Const.ForceGLSLVersion;
this->es_shader = false;
this->ARB_texture_rectangle_enable = true;
@@ -320,11 +320,14 @@ _mesa_glsl_parse_state::process_version_directive(YYLTYPE *locp, int version,
this->ARB_texture_rectangle_enable = false;
}
- this->language_version = version;
+ if (this->forced_language_version)
+ this->language_version = this->forced_language_version;
+ else
+ this->language_version = version;
bool supported = false;
for (unsigned i = 0; i < this->num_supported_versions; i++) {
- if (this->supported_versions[i].ver == (unsigned) version
+ if (this->supported_versions[i].ver == this->language_version
&& this->supported_versions[i].es == this->es_shader) {
supported = true;
break;
diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h
index 0975c86ed..dae7864fd 100644
--- a/mesalib/src/glsl/glsl_parser_extras.h
+++ b/mesalib/src/glsl/glsl_parser_extras.h
@@ -105,8 +105,10 @@ struct _mesa_glsl_parse_state {
{
unsigned required_version = this->es_shader ?
required_glsl_es_version : required_glsl_version;
+ unsigned this_version = this->forced_language_version
+ ? this->forced_language_version : this->language_version;
return required_version != 0
- && this->language_version >= required_version;
+ && this_version >= required_version;
}
bool check_version(unsigned required_glsl_version,
@@ -226,6 +228,7 @@ struct _mesa_glsl_parse_state {
bool es_shader;
unsigned language_version;
+ unsigned forced_language_version;
gl_shader_stage stage;
/**
diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp
index 38b37a6a9..4aa36a794 100644
--- a/mesalib/src/glsl/glsl_types.cpp
+++ b/mesalib/src/glsl/glsl_types.cpp
@@ -825,6 +825,73 @@ glsl_type::get_interface_instance(const glsl_struct_field *fields,
const glsl_type *
+glsl_type::get_mul_type(const glsl_type *type_a, const glsl_type *type_b)
+{
+ if (type_a == type_b) {
+ return type_a;
+ } else if (type_a->is_matrix() && type_b->is_matrix()) {
+ /* Matrix multiply. The columns of A must match the rows of B. Given
+ * the other previously tested constraints, this means the vector type
+ * of a row from A must be the same as the vector type of a column from
+ * B.
+ */
+ if (type_a->row_type() == type_b->column_type()) {
+ /* The resulting matrix has the number of columns of matrix B and
+ * the number of rows of matrix A. We get the row count of A by
+ * looking at the size of a vector that makes up a column. The
+ * transpose (size of a row) is done for B.
+ */
+ const glsl_type *const type =
+ get_instance(type_a->base_type,
+ type_a->column_type()->vector_elements,
+ type_b->row_type()->vector_elements);
+ assert(type != error_type);
+
+ return type;
+ }
+ } else if (type_a->is_matrix()) {
+ /* A is a matrix and B is a column vector. Columns of A must match
+ * rows of B. Given the other previously tested constraints, this
+ * means the vector type of a row from A must be the same as the
+ * vector the type of B.
+ */
+ if (type_a->row_type() == type_b) {
+ /* The resulting vector has a number of elements equal to
+ * the number of rows of matrix A. */
+ const glsl_type *const type =
+ get_instance(type_a->base_type,
+ type_a->column_type()->vector_elements,
+ 1);
+ assert(type != error_type);
+
+ return type;
+ }
+ } else {
+ assert(type_b->is_matrix());
+
+ /* A is a row vector and B is a matrix. Columns of A must match rows
+ * of B. Given the other previously tested constraints, this means
+ * the type of A must be the same as the vector type of a column from
+ * B.
+ */
+ if (type_a == type_b->column_type()) {
+ /* The resulting vector has a number of elements equal to
+ * the number of columns of matrix B. */
+ const glsl_type *const type =
+ get_instance(type_a->base_type,
+ type_b->row_type()->vector_elements,
+ 1);
+ assert(type != error_type);
+
+ return type;
+ }
+ }
+
+ return error_type;
+}
+
+
+const glsl_type *
glsl_type::field_type(const char *name) const
{
if (this->base_type != GLSL_TYPE_STRUCT
@@ -1077,15 +1144,6 @@ glsl_type::std140_base_alignment(bool row_major) const
return base_alignment;
}
- /* A sampler may never occur in a UBO (without bindless of some sort),
- * however it is convenient to use this alignment function even with
- * regular uniforms. This allows use of this function on uniform structs
- * that contain samplers.
- */
- if (this->is_sampler()) {
- return 0;
- }
-
assert(!"not reached");
return -1;
}
diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h
index 7359e9476..d383dd5be 100644
--- a/mesalib/src/glsl/glsl_types.h
+++ b/mesalib/src/glsl/glsl_types.h
@@ -276,6 +276,12 @@ struct glsl_type {
const char *block_name);
/**
+ * Get the type resulting from a multiplication of \p type_a * \p type_b
+ */
+ static const glsl_type *get_mul_type(const glsl_type *type_a,
+ const glsl_type *type_b);
+
+ /**
* Query the total number of scalars that make up a scalar, vector or matrix
*/
unsigned components() const
diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp
index 54656f899..9e3238552 100644
--- a/mesalib/src/glsl/ir.cpp
+++ b/mesalib/src/glsl/ir.cpp
@@ -240,8 +240,6 @@ ir_expression::ir_expression(int op, ir_rvalue *op0)
case ir_unop_round_even:
case ir_unop_sin:
case ir_unop_cos:
- case ir_unop_sin_reduced:
- case ir_unop_cos_reduced:
case ir_unop_dFdx:
case ir_unop_dFdx_coarse:
case ir_unop_dFdx_fine:
@@ -380,10 +378,12 @@ ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1)
} else if (op1->type->is_scalar()) {
this->type = op0->type;
} else {
- /* FINISHME: matrix types */
- assert(!op0->type->is_matrix() && !op1->type->is_matrix());
- assert(op0->type == op1->type);
- this->type = op0->type;
+ if (this->operation == ir_binop_mul) {
+ this->type = glsl_type::get_mul_type(op0->type, op1->type);
+ } else {
+ assert(op0->type == op1->type);
+ this->type = op0->type;
+ }
}
break;
@@ -540,8 +540,6 @@ static const char *const operator_strs[] = {
"round_even",
"sin",
"cos",
- "sin_reduced",
- "cos_reduced",
"dFdx",
"dFdxCoarse",
"dFdxFine",
diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h
index fdc22edf1..fab1cd2d2 100644
--- a/mesalib/src/glsl/ir.h
+++ b/mesalib/src/glsl/ir.h
@@ -109,6 +109,31 @@ public:
virtual ir_instruction *clone(void *mem_ctx,
struct hash_table *ht) const = 0;
+ bool is_rvalue() const
+ {
+ return ir_type == ir_type_dereference_array ||
+ ir_type == ir_type_dereference_record ||
+ ir_type == ir_type_dereference_variable ||
+ ir_type == ir_type_constant ||
+ ir_type == ir_type_expression ||
+ ir_type == ir_type_swizzle ||
+ ir_type == ir_type_texture;
+ }
+
+ bool is_dereference() const
+ {
+ return ir_type == ir_type_dereference_array ||
+ ir_type == ir_type_dereference_record ||
+ ir_type == ir_type_dereference_variable;
+ }
+
+ bool is_jump() const
+ {
+ return ir_type == ir_type_loop_jump ||
+ ir_type == ir_type_return ||
+ ir_type == ir_type_discard;
+ }
+
/**
* \name IR instruction downcast functions
*
@@ -117,45 +142,33 @@ public:
* Additional downcast functions will be added as needed.
*/
/*@{*/
- class ir_rvalue *as_rvalue()
- {
- assume(this != NULL);
- if (ir_type == ir_type_dereference_array ||
- ir_type == ir_type_dereference_record ||
- ir_type == ir_type_dereference_variable ||
- ir_type == ir_type_constant ||
- ir_type == ir_type_expression ||
- ir_type == ir_type_swizzle ||
- ir_type == ir_type_texture)
- return (class ir_rvalue *) this;
- return NULL;
- }
-
- class ir_dereference *as_dereference()
- {
- assume(this != NULL);
- if (ir_type == ir_type_dereference_array ||
- ir_type == ir_type_dereference_record ||
- ir_type == ir_type_dereference_variable)
- return (class ir_dereference *) this;
- return NULL;
- }
-
- class ir_jump *as_jump()
- {
- assume(this != NULL);
- if (ir_type == ir_type_loop_jump ||
- ir_type == ir_type_return ||
- ir_type == ir_type_discard)
- return (class ir_jump *) this;
- return NULL;
- }
+ #define AS_BASE(TYPE) \
+ class ir_##TYPE *as_##TYPE() \
+ { \
+ assume(this != NULL); \
+ return is_##TYPE() ? (ir_##TYPE *) this : NULL; \
+ } \
+ const class ir_##TYPE *as_##TYPE() const \
+ { \
+ assume(this != NULL); \
+ return is_##TYPE() ? (ir_##TYPE *) this : NULL; \
+ }
+
+ AS_BASE(rvalue)
+ AS_BASE(dereference)
+ AS_BASE(jump)
+ #undef AS_BASE
#define AS_CHILD(TYPE) \
class ir_##TYPE * as_##TYPE() \
{ \
assume(this != NULL); \
return ir_type == ir_type_##TYPE ? (ir_##TYPE *) this : NULL; \
+ } \
+ const class ir_##TYPE * as_##TYPE() const \
+ { \
+ assume(this != NULL); \
+ return ir_type == ir_type_##TYPE ? (const ir_##TYPE *) this : NULL; \
}
AS_CHILD(variable)
AS_CHILD(function)
@@ -183,7 +196,8 @@ public:
* in particular. No support for other instruction types (assignments,
* jumps, calls, etc.) is planned.
*/
- virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
+ virtual bool equals(const ir_instruction *ir,
+ enum ir_node_type ignore = ir_type_unset) const;
protected:
ir_instruction(enum ir_node_type t)
@@ -1300,8 +1314,6 @@ enum ir_expression_operation {
/*@{*/
ir_unop_sin,
ir_unop_cos,
- ir_unop_sin_reduced, /**< Reduced range sin. [-pi, pi] */
- ir_unop_cos_reduced, /**< Reduced range cos. [-pi, pi] */
/*@}*/
/**
@@ -1598,7 +1610,8 @@ public:
*/
ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1, ir_rvalue *op2);
- virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
+ virtual bool equals(const ir_instruction *ir,
+ enum ir_node_type ignore = ir_type_unset) const;
virtual ir_expression *clone(void *mem_ctx, struct hash_table *ht) const;
@@ -1909,7 +1922,8 @@ public:
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
- virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
+ virtual bool equals(const ir_instruction *ir,
+ enum ir_node_type ignore = ir_type_unset) const;
/**
* Return a string representing the ir_texture_opcode.
@@ -2010,7 +2024,8 @@ public:
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
- virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
+ virtual bool equals(const ir_instruction *ir,
+ enum ir_node_type ignore = ir_type_unset) const;
bool is_lvalue() const
{
@@ -2063,7 +2078,8 @@ public:
virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
- virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
+ virtual bool equals(const ir_instruction *ir,
+ enum ir_node_type ignore = ir_type_unset) const;
/**
* Get the variable that is ultimately referenced by an r-value
@@ -2109,7 +2125,8 @@ public:
virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
- virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
+ virtual bool equals(const ir_instruction *ir,
+ enum ir_node_type ignore = ir_type_unset) const;
/**
* Get the variable that is ultimately referenced by an r-value
@@ -2219,7 +2236,8 @@ public:
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
- virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
+ virtual bool equals(const ir_instruction *ir,
+ enum ir_node_type ignore = ir_type_unset) const;
/**
* Get a particular component of a constant as a specific type
diff --git a/mesalib/src/glsl/ir_constant_expression.cpp b/mesalib/src/glsl/ir_constant_expression.cpp
index ecebc3cdc..171b8e954 100644
--- a/mesalib/src/glsl/ir_constant_expression.cpp
+++ b/mesalib/src/glsl/ir_constant_expression.cpp
@@ -781,7 +781,6 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
break;
case ir_unop_sin:
- case ir_unop_sin_reduced:
assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
for (unsigned c = 0; c < op[0]->type->components(); c++) {
data.f[c] = sinf(op[0]->value.f[c]);
@@ -789,7 +788,6 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
break;
case ir_unop_cos:
- case ir_unop_cos_reduced:
assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
for (unsigned c = 0; c < op[0]->type->components(); c++) {
data.f[c] = cosf(op[0]->value.f[c]);
diff --git a/mesalib/src/glsl/ir_equals.cpp b/mesalib/src/glsl/ir_equals.cpp
index 65376cd94..cc1964eef 100644
--- a/mesalib/src/glsl/ir_equals.cpp
+++ b/mesalib/src/glsl/ir_equals.cpp
@@ -28,7 +28,8 @@
* can't access a's vtable in that case.
*/
static bool
-possibly_null_equals(ir_instruction *a, ir_instruction *b, enum ir_node_type ignore)
+possibly_null_equals(const ir_instruction *a, const ir_instruction *b,
+ enum ir_node_type ignore)
{
if (!a || !b)
return !a && !b;
@@ -41,13 +42,13 @@ possibly_null_equals(ir_instruction *a, ir_instruction *b, enum ir_node_type ign
* about.
*/
bool
-ir_instruction::equals(ir_instruction *, enum ir_node_type)
+ir_instruction::equals(const ir_instruction *, enum ir_node_type) const
{
return false;
}
bool
-ir_constant::equals(ir_instruction *ir, enum ir_node_type)
+ir_constant::equals(const ir_instruction *ir, enum ir_node_type) const
{
const ir_constant *other = ir->as_constant();
if (!other)
@@ -65,7 +66,8 @@ ir_constant::equals(ir_instruction *ir, enum ir_node_type)
}
bool
-ir_dereference_variable::equals(ir_instruction *ir, enum ir_node_type)
+ir_dereference_variable::equals(const ir_instruction *ir,
+ enum ir_node_type) const
{
const ir_dereference_variable *other = ir->as_dereference_variable();
if (!other)
@@ -75,7 +77,8 @@ ir_dereference_variable::equals(ir_instruction *ir, enum ir_node_type)
}
bool
-ir_dereference_array::equals(ir_instruction *ir, enum ir_node_type ignore)
+ir_dereference_array::equals(const ir_instruction *ir,
+ enum ir_node_type ignore) const
{
const ir_dereference_array *other = ir->as_dereference_array();
if (!other)
@@ -94,7 +97,8 @@ ir_dereference_array::equals(ir_instruction *ir, enum ir_node_type ignore)
}
bool
-ir_swizzle::equals(ir_instruction *ir, enum ir_node_type ignore)
+ir_swizzle::equals(const ir_instruction *ir,
+ enum ir_node_type ignore) const
{
const ir_swizzle *other = ir->as_swizzle();
if (!other)
@@ -116,7 +120,7 @@ ir_swizzle::equals(ir_instruction *ir, enum ir_node_type ignore)
}
bool
-ir_texture::equals(ir_instruction *ir, enum ir_node_type ignore)
+ir_texture::equals(const ir_instruction *ir, enum ir_node_type ignore) const
{
const ir_texture *other = ir->as_texture();
if (!other)
@@ -179,7 +183,7 @@ ir_texture::equals(ir_instruction *ir, enum ir_node_type ignore)
}
bool
-ir_expression::equals(ir_instruction *ir, enum ir_node_type ignore)
+ir_expression::equals(const ir_instruction *ir, enum ir_node_type ignore) const
{
const ir_expression *other = ir->as_expression();
if (!other)
diff --git a/mesalib/src/glsl/ir_validate.cpp b/mesalib/src/glsl/ir_validate.cpp
index 7a7688cb2..cfe0df3dc 100644
--- a/mesalib/src/glsl/ir_validate.cpp
+++ b/mesalib/src/glsl/ir_validate.cpp
@@ -334,8 +334,6 @@ ir_validate::visit_leave(ir_expression *ir)
break;
case ir_unop_sin:
case ir_unop_cos:
- case ir_unop_sin_reduced:
- case ir_unop_cos_reduced:
case ir_unop_dFdx:
case ir_unop_dFdx_coarse:
case ir_unop_dFdx_fine:
@@ -543,9 +541,9 @@ ir_validate::visit_leave(ir_expression *ir)
case ir_binop_logic_and:
case ir_binop_logic_xor:
case ir_binop_logic_or:
- assert(ir->type == glsl_type::bool_type);
- assert(ir->operands[0]->type == glsl_type::bool_type);
- assert(ir->operands[1]->type == glsl_type::bool_type);
+ assert(ir->type->base_type == GLSL_TYPE_BOOL);
+ assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
+ assert(ir->operands[1]->type->base_type == GLSL_TYPE_BOOL);
break;
case ir_binop_dot:
diff --git a/mesalib/src/glsl/link_uniforms.cpp b/mesalib/src/glsl/link_uniforms.cpp
index 799c74bb9..59adc298b 100644
--- a/mesalib/src/glsl/link_uniforms.cpp
+++ b/mesalib/src/glsl/link_uniforms.cpp
@@ -547,6 +547,8 @@ private:
virtual void enter_record(const glsl_type *type, const char *name,
bool row_major) {
assert(type->is_record());
+ if (this->ubo_block_index == -1)
+ return;
this->ubo_byte_offset = glsl_align(
this->ubo_byte_offset, type->std140_base_alignment(row_major));
}
@@ -554,6 +556,8 @@ private:
virtual void leave_record(const glsl_type *type, const char *name,
bool row_major) {
assert(type->is_record());
+ if (this->ubo_block_index == -1)
+ return;
this->ubo_byte_offset = glsl_align(
this->ubo_byte_offset, type->std140_base_alignment(row_major));
}
diff --git a/mesalib/src/glsl/link_varyings.cpp b/mesalib/src/glsl/link_varyings.cpp
index 22617990f..605748a9c 100644
--- a/mesalib/src/glsl/link_varyings.cpp
+++ b/mesalib/src/glsl/link_varyings.cpp
@@ -263,6 +263,19 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
if (output != NULL) {
cross_validate_types_and_qualifiers(prog, input, output,
consumer->Stage, producer->Stage);
+ } else {
+ /* Check for input vars with unmatched output vars in prev stage
+ * taking into account that interface blocks could have a matching
+ * output but with different name, so we ignore them.
+ */
+ assert(!input->data.assigned);
+ if (input->data.used && !input->get_interface_type() &&
+ !input->data.explicit_location && !prog->SeparateShader)
+ linker_error(prog,
+ "%s shader input `%s' "
+ "has no matching output in the previous stage\n",
+ _mesa_shader_stage_to_string(consumer->Stage),
+ input->name);
}
}
}
diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp
index 4349f0973..b6baa5d36 100644
--- a/mesalib/src/glsl/linker.cpp
+++ b/mesalib/src/glsl/linker.cpp
@@ -1377,24 +1377,13 @@ link_fs_input_layout_qualifiers(struct gl_shader_program *prog,
* "If gl_FragCoord is redeclared in any fragment shader in a program,
* it must be redeclared in all the fragment shaders in that program
* that have a static use gl_FragCoord."
- *
- * Exclude the case when one of the 'linked_shader' or 'shader' redeclares
- * gl_FragCoord with no layout qualifiers but the other one doesn't
- * redeclare it. If we strictly follow GLSL 1.50 spec's language, it
- * should be a link error. But, generating link error for this case will
- * be a wrong behaviour which spec didn't intend to do and it could also
- * break some applications.
*/
if ((linked_shader->redeclares_gl_fragcoord
&& !shader->redeclares_gl_fragcoord
- && shader->uses_gl_fragcoord
- && (linked_shader->origin_upper_left
- || linked_shader->pixel_center_integer))
+ && shader->uses_gl_fragcoord)
|| (shader->redeclares_gl_fragcoord
&& !linked_shader->redeclares_gl_fragcoord
- && linked_shader->uses_gl_fragcoord
- && (shader->origin_upper_left
- || shader->pixel_center_integer))) {
+ && linked_shader->uses_gl_fragcoord)) {
linker_error(prog, "fragment shader defined with conflicting "
"layout qualifiers for gl_FragCoord\n");
}
@@ -2503,6 +2492,194 @@ check_explicit_uniform_locations(struct gl_context *ctx,
delete uniform_map;
}
+static bool
+add_program_resource(struct gl_shader_program *prog, GLenum type,
+ const void *data, uint8_t stages)
+{
+ assert(data);
+
+ /* If resource already exists, do not add it again. */
+ for (unsigned i = 0; i < prog->NumProgramResourceList; i++)
+ if (prog->ProgramResourceList[i].Data == data)
+ return true;
+
+ prog->ProgramResourceList =
+ reralloc(prog,
+ prog->ProgramResourceList,
+ gl_program_resource,
+ prog->NumProgramResourceList + 1);
+
+ if (!prog->ProgramResourceList) {
+ linker_error(prog, "Out of memory during linking.\n");
+ return false;
+ }
+
+ struct gl_program_resource *res =
+ &prog->ProgramResourceList[prog->NumProgramResourceList];
+
+ res->Type = type;
+ res->Data = data;
+ res->StageReferences = stages;
+
+ prog->NumProgramResourceList++;
+
+ return true;
+}
+
+/**
+ * Function builds a stage reference bitmask from variable name.
+ */
+static uint8_t
+build_stageref(struct gl_shader_program *shProg, const char *name)
+{
+ uint8_t stages = 0;
+
+ /* Note, that we assume MAX 8 stages, if there will be more stages, type
+ * used for reference mask in gl_program_resource will need to be changed.
+ */
+ assert(MESA_SHADER_STAGES < 8);
+
+ for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+ struct gl_shader *sh = shProg->_LinkedShaders[i];
+ if (!sh)
+ continue;
+ ir_variable *var = sh->symbols->get_variable(name);
+ if (var)
+ stages |= (1 << i);
+ }
+ return stages;
+}
+
+static bool
+add_interface_variables(struct gl_shader_program *shProg,
+ struct gl_shader *sh, GLenum programInterface)
+{
+ foreach_in_list(ir_instruction, node, sh->ir) {
+ ir_variable *var = node->as_variable();
+
+ if (!var)
+ continue;
+
+ switch (var->data.mode) {
+ /* From GL 4.3 core spec, section 11.1.1 (Vertex Attributes):
+ * "For GetActiveAttrib, all active vertex shader input variables
+ * are enumerated, including the special built-in inputs gl_VertexID
+ * and gl_InstanceID."
+ */
+ case ir_var_system_value:
+ if (var->data.location != SYSTEM_VALUE_VERTEX_ID &&
+ var->data.location != SYSTEM_VALUE_VERTEX_ID_ZERO_BASE &&
+ var->data.location != SYSTEM_VALUE_INSTANCE_ID)
+ continue;
+ case ir_var_shader_in:
+ if (programInterface != GL_PROGRAM_INPUT)
+ continue;
+ break;
+ case ir_var_shader_out:
+ if (programInterface != GL_PROGRAM_OUTPUT)
+ continue;
+ break;
+ default:
+ continue;
+ };
+
+ if (!add_program_resource(shProg, programInterface, var,
+ build_stageref(shProg, var->name)))
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Builds up a list of program resources that point to existing
+ * resource data.
+ */
+static void
+build_program_resource_list(struct gl_context *ctx,
+ struct gl_shader_program *shProg)
+{
+ /* Rebuild resource list. */
+ if (shProg->ProgramResourceList) {
+ ralloc_free(shProg->ProgramResourceList);
+ shProg->ProgramResourceList = NULL;
+ shProg->NumProgramResourceList = 0;
+ }
+
+ int input_stage = MESA_SHADER_STAGES, output_stage = 0;
+
+ /* Determine first input and final output stage. These are used to
+ * detect which variables should be enumerated in the resource list
+ * for GL_PROGRAM_INPUT and GL_PROGRAM_OUTPUT.
+ */
+ for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+ if (!shProg->_LinkedShaders[i])
+ continue;
+ if (input_stage == MESA_SHADER_STAGES)
+ input_stage = i;
+ output_stage = i;
+ }
+
+ /* Empty shader, no resources. */
+ if (input_stage == MESA_SHADER_STAGES && output_stage == 0)
+ return;
+
+ /* Add inputs and outputs to the resource list. */
+ if (!add_interface_variables(shProg, shProg->_LinkedShaders[input_stage],
+ GL_PROGRAM_INPUT))
+ return;
+
+ if (!add_interface_variables(shProg, shProg->_LinkedShaders[output_stage],
+ GL_PROGRAM_OUTPUT))
+ return;
+
+ /* Add transform feedback varyings. */
+ if (shProg->LinkedTransformFeedback.NumVarying > 0) {
+ for (int i = 0; i < shProg->LinkedTransformFeedback.NumVarying; i++) {
+ uint8_t stageref =
+ build_stageref(shProg,
+ shProg->LinkedTransformFeedback.Varyings[i].Name);
+ if (!add_program_resource(shProg, GL_TRANSFORM_FEEDBACK_VARYING,
+ &shProg->LinkedTransformFeedback.Varyings[i],
+ stageref))
+ return;
+ }
+ }
+
+ /* Add uniforms from uniform storage. */
+ for (unsigned i = 0; i < shProg->NumUserUniformStorage; i++) {
+ /* Do not add uniforms internally used by Mesa. */
+ if (shProg->UniformStorage[i].hidden)
+ continue;
+
+ uint8_t stageref =
+ build_stageref(shProg, shProg->UniformStorage[i].name);
+ if (!add_program_resource(shProg, GL_UNIFORM,
+ &shProg->UniformStorage[i], stageref))
+ return;
+ }
+
+ /* Add program uniform blocks. */
+ for (unsigned i = 0; i < shProg->NumUniformBlocks; i++) {
+ if (!add_program_resource(shProg, GL_UNIFORM_BLOCK,
+ &shProg->UniformBlocks[i], 0))
+ return;
+ }
+
+ /* Add atomic counter buffers. */
+ for (unsigned i = 0; i < shProg->NumAtomicBuffers; i++) {
+ if (!add_program_resource(shProg, GL_ATOMIC_COUNTER_BUFFER,
+ &shProg->AtomicBuffers[i], 0))
+ return;
+ }
+
+ /* TODO - following extensions will require more resource types:
+ *
+ * GL_ARB_shader_storage_buffer_object
+ * GL_ARB_shader_subroutine
+ */
+}
+
+
void
link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
{
@@ -2737,10 +2914,18 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
goto done;
}
- unsigned first;
- for (first = 0; first <= MESA_SHADER_FRAGMENT; first++) {
- if (prog->_LinkedShaders[first] != NULL)
- break;
+ unsigned first, last;
+
+ first = MESA_SHADER_STAGES;
+ last = 0;
+
+ /* Determine first and last stage. */
+ for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+ if (!prog->_LinkedShaders[i])
+ continue;
+ if (first == MESA_SHADER_STAGES)
+ first = i;
+ last = i;
}
if (num_tfeedback_decls != 0) {
@@ -2769,13 +2954,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
* ensures that inter-shader outputs written to in an earlier stage are
* eliminated if they are (transitively) not used in a later stage.
*/
- int last, next;
- for (last = MESA_SHADER_FRAGMENT; last >= 0; last--) {
- if (prog->_LinkedShaders[last] != NULL)
- break;
- }
+ int next;
- if (last >= 0 && last < MESA_SHADER_FRAGMENT) {
+ if (first < MESA_SHADER_FRAGMENT) {
gl_shader *const sh = prog->_LinkedShaders[last];
if (first == MESA_SHADER_GEOMETRY) {
@@ -2787,13 +2968,14 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
* MESA_SHADER_GEOMETRY.
*/
if (!assign_varying_locations(ctx, mem_ctx, prog,
- NULL, sh,
+ NULL, prog->_LinkedShaders[first],
num_tfeedback_decls, tfeedback_decls,
prog->Geom.VerticesIn))
goto done;
}
- if (num_tfeedback_decls != 0 || prog->SeparateShader) {
+ if (last != MESA_SHADER_FRAGMENT &&
+ (num_tfeedback_decls != 0 || prog->SeparateShader)) {
/* There was no fragment shader, but we still have to assign varying
* locations for use by transform feedback.
*/
@@ -2905,6 +3087,10 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
}
}
+ build_program_resource_list(ctx, prog);
+ if (!prog->LinkStatus)
+ goto done;
+
/* FINISHME: Assign fragment shader output locations. */
done:
diff --git a/mesalib/src/glsl/loop_controls.cpp b/mesalib/src/glsl/loop_controls.cpp
index d7f0b2809..51804bb5f 100644
--- a/mesalib/src/glsl/loop_controls.cpp
+++ b/mesalib/src/glsl/loop_controls.cpp
@@ -139,7 +139,7 @@ calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment,
iter = new(mem_ctx) ir_constant(double(iter_value + bias[i]));
break;
default:
- unreachable(!"Unsupported type for loop iterator.");
+ unreachable("Unsupported type for loop iterator.");
}
ir_expression *const mul =
diff --git a/mesalib/src/glsl/lower_const_arrays_to_uniforms.cpp b/mesalib/src/glsl/lower_const_arrays_to_uniforms.cpp
index 2243f479a..44967dcdb 100644
--- a/mesalib/src/glsl/lower_const_arrays_to_uniforms.cpp
+++ b/mesalib/src/glsl/lower_const_arrays_to_uniforms.cpp
@@ -49,7 +49,6 @@ public:
{
instructions = insts;
progress = false;
- index = 0;
}
bool run()
@@ -63,7 +62,6 @@ public:
private:
exec_list *instructions;
bool progress;
- unsigned index;
};
void
@@ -82,7 +80,7 @@ lower_const_array_visitor::handle_rvalue(ir_rvalue **rvalue)
void *mem_ctx = ralloc_parent(con);
- char *uniform_name = ralloc_asprintf(mem_ctx, "constarray__%d", index++);
+ char *uniform_name = ralloc_asprintf(mem_ctx, "constarray__%p", dra);
ir_variable *uni =
new(mem_ctx) ir_variable(con->type, uniform_name, ir_var_uniform);
diff --git a/mesalib/src/glsl/nir/glsl_to_nir.cpp b/mesalib/src/glsl/nir/glsl_to_nir.cpp
index 357944da6..f6b8331d4 100644
--- a/mesalib/src/glsl/nir/glsl_to_nir.cpp
+++ b/mesalib/src/glsl/nir/glsl_to_nir.cpp
@@ -88,6 +88,8 @@ private:
exec_list *cf_node_list;
nir_instr *result; /* result of the expression tree last visited */
+ nir_deref_var *evaluate_deref(nir_instr *mem_ctx, ir_instruction *ir);
+
/* the head of the dereference chain we're creating */
nir_deref_var *deref_head;
/* the tail of the dereference chain we're creating */
@@ -156,6 +158,14 @@ nir_visitor::~nir_visitor()
_mesa_hash_table_destroy(this->overload_table, NULL);
}
+nir_deref_var *
+nir_visitor::evaluate_deref(nir_instr *mem_ctx, ir_instruction *ir)
+{
+ ir->accept(this);
+ ralloc_steal(mem_ctx, this->deref_head);
+ return this->deref_head;
+}
+
static nir_constant *
constant_copy(ir_constant *ir, void *mem_ctx)
{
@@ -582,13 +592,11 @@ void
nir_visitor::visit(ir_return *ir)
{
if (ir->value != NULL) {
- ir->value->accept(this);
nir_intrinsic_instr *copy =
nir_intrinsic_instr_create(this->shader, nir_intrinsic_copy_var);
- copy->variables[0] = nir_deref_var_create(this->shader,
- this->impl->return_var);
- copy->variables[1] = this->deref_head;
+ copy->variables[0] = nir_deref_var_create(copy, this->impl->return_var);
+ copy->variables[1] = evaluate_deref(&copy->instr, ir->value);
}
nir_jump_instr *instr = nir_jump_instr_create(this->shader, nir_jump_return);
@@ -613,8 +621,7 @@ nir_visitor::visit(ir_call *ir)
nir_intrinsic_instr *instr = nir_intrinsic_instr_create(shader, op);
ir_dereference *param =
(ir_dereference *) ir->actual_parameters.get_head();
- param->accept(this);
- instr->variables[0] = this->deref_head;
+ instr->variables[0] = evaluate_deref(&instr->instr, param);
nir_ssa_dest_init(&instr->instr, &instr->dest, 1, NULL);
nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr);
@@ -623,8 +630,7 @@ nir_visitor::visit(ir_call *ir)
nir_intrinsic_instr_create(shader, nir_intrinsic_store_var);
store_instr->num_components = 1;
- ir->return_deref->accept(this);
- store_instr->variables[0] = this->deref_head;
+ store_instr->variables[0] = evaluate_deref(&store_instr->instr, ir->return_deref);
store_instr->src[0].is_ssa = true;
store_instr->src[0].ssa = &instr->dest.ssa;
@@ -642,13 +648,11 @@ nir_visitor::visit(ir_call *ir)
unsigned i = 0;
foreach_in_list(ir_dereference, param, &ir->actual_parameters) {
- param->accept(this);
- instr->params[i] = this->deref_head;
+ instr->params[i] = evaluate_deref(&instr->instr, param);
i++;
}
- ir->return_deref->accept(this);
- instr->return_deref = this->deref_head;
+ instr->return_deref = evaluate_deref(&instr->instr, ir->return_deref);
nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr);
}
@@ -663,12 +667,8 @@ nir_visitor::visit(ir_assignment *ir)
nir_intrinsic_instr *copy =
nir_intrinsic_instr_create(this->shader, nir_intrinsic_copy_var);
- ir->lhs->accept(this);
- copy->variables[0] = this->deref_head;
-
- ir->rhs->accept(this);
- copy->variables[1] = this->deref_head;
-
+ copy->variables[0] = evaluate_deref(&copy->instr, ir->lhs);
+ copy->variables[1] = evaluate_deref(&copy->instr, ir->rhs);
if (ir->condition) {
nir_if *if_stmt = nir_if_create(this->shader);
@@ -700,6 +700,7 @@ nir_visitor::visit(ir_assignment *ir)
load->num_components = ir->lhs->type->vector_elements;
nir_ssa_dest_init(&load->instr, &load->dest, num_components, NULL);
load->variables[0] = lhs_deref;
+ ralloc_steal(load, load->variables[0]);
nir_instr_insert_after_cf_list(this->cf_node_list, &load->instr);
nir_op vec_op;
@@ -741,7 +742,7 @@ nir_visitor::visit(ir_assignment *ir)
nir_intrinsic_instr *store =
nir_intrinsic_instr_create(this->shader, nir_intrinsic_store_var);
store->num_components = ir->lhs->type->vector_elements;
- nir_deref *store_deref = nir_copy_deref(this->shader, &lhs_deref->deref);
+ nir_deref *store_deref = nir_copy_deref(store, &lhs_deref->deref);
store->variables[0] = nir_deref_as_var(store_deref);
store->src[0] = src;
@@ -816,6 +817,7 @@ nir_visitor::evaluate_rvalue(ir_rvalue* ir)
nir_intrinsic_instr_create(this->shader, nir_intrinsic_load_var);
load_instr->num_components = ir->type->vector_elements;
load_instr->variables[0] = this->deref_head;
+ ralloc_steal(load_instr, load_instr->variables[0]);
add_instr(&load_instr->instr, ir->type->vector_elements);
}
@@ -959,6 +961,7 @@ nir_visitor::visit(ir_expression *ir)
nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(shader, op);
intrin->num_components = deref->type->vector_elements;
intrin->variables[0] = this->deref_head;
+ ralloc_steal(intrin, intrin->variables[0]);
if (intrin->intrinsic == nir_intrinsic_interp_var_at_offset ||
intrin->intrinsic == nir_intrinsic_interp_var_at_sample)
@@ -1087,12 +1090,6 @@ nir_visitor::visit(ir_expression *ir)
case ir_unop_round_even: emit(nir_op_fround_even, dest_size, srcs); break;
case ir_unop_sin: emit(nir_op_fsin, dest_size, srcs); break;
case ir_unop_cos: emit(nir_op_fcos, dest_size, srcs); break;
- case ir_unop_sin_reduced:
- emit(nir_op_fsin_reduced, dest_size, srcs);
- break;
- case ir_unop_cos_reduced:
- emit(nir_op_fcos_reduced, dest_size, srcs);
- break;
case ir_unop_dFdx: emit(nir_op_fddx, dest_size, srcs); break;
case ir_unop_dFdy: emit(nir_op_fddy, dest_size, srcs); break;
case ir_unop_dFdx_fine: emit(nir_op_fddx_fine, dest_size, srcs); break;
@@ -1210,6 +1207,9 @@ nir_visitor::visit(ir_expression *ir)
case ir_binop_bit_and:
case ir_binop_bit_or:
case ir_binop_bit_xor:
+ case ir_binop_logic_and:
+ case ir_binop_logic_or:
+ case ir_binop_logic_xor:
case ir_binop_lshift:
case ir_binop_rshift:
switch (ir->operation) {
@@ -1270,6 +1270,24 @@ nir_visitor::visit(ir_expression *ir)
case ir_binop_bit_xor:
op = nir_op_ixor;
break;
+ case ir_binop_logic_and:
+ if (supports_ints)
+ op = nir_op_iand;
+ else
+ op = nir_op_fand;
+ break;
+ case ir_binop_logic_or:
+ if (supports_ints)
+ op = nir_op_ior;
+ else
+ op = nir_op_for;
+ break;
+ case ir_binop_logic_xor:
+ if (supports_ints)
+ op = nir_op_ixor;
+ else
+ op = nir_op_fxor;
+ break;
case ir_binop_lshift:
op = nir_op_ishl;
break;
@@ -1444,24 +1462,6 @@ nir_visitor::visit(ir_expression *ir)
}
}
break;
- case ir_binop_logic_and:
- if (supports_ints)
- emit(nir_op_iand, dest_size, srcs);
- else
- emit(nir_op_fand, dest_size, srcs);
- break;
- case ir_binop_logic_or:
- if (supports_ints)
- emit(nir_op_ior, dest_size, srcs);
- else
- emit(nir_op_for, dest_size, srcs);
- break;
- case ir_binop_logic_xor:
- if (supports_ints)
- emit(nir_op_ixor, dest_size, srcs);
- else
- emit(nir_op_fxor, dest_size, srcs);
- break;
case ir_binop_dot:
switch (ir->operands[0]->type->vector_elements) {
case 2: emit(nir_op_fdot2, dest_size, srcs); break;
@@ -1633,8 +1633,7 @@ nir_visitor::visit(ir_texture *ir)
unreachable("not reached");
}
- ir->sampler->accept(this);
- instr->sampler = this->deref_head;
+ instr->sampler = evaluate_deref(&instr->instr, ir->sampler);
unsigned src_number = 0;
@@ -1759,7 +1758,7 @@ nir_visitor::visit(ir_dereference_record *ir)
int field_index = this->deref_tail->type->field_index(ir->field);
assert(field_index >= 0);
- nir_deref_struct *deref = nir_deref_struct_create(this->shader, field_index);
+ nir_deref_struct *deref = nir_deref_struct_create(this->deref_tail, field_index);
deref->deref.type = ir->type;
this->deref_tail->child = &deref->deref;
this->deref_tail = &deref->deref;
@@ -1783,5 +1782,6 @@ nir_visitor::visit(ir_dereference_array *ir)
ir->array->accept(this);
this->deref_tail->child = &deref->deref;
+ ralloc_steal(this->deref_tail, deref);
this->deref_tail = &deref->deref;
}
diff --git a/mesalib/src/glsl/nir/nir.c b/mesalib/src/glsl/nir/nir.c
index 6459d5108..c6e53612b 100644
--- a/mesalib/src/glsl/nir/nir.c
+++ b/mesalib/src/glsl/nir/nir.c
@@ -58,11 +58,11 @@ reg_create(void *mem_ctx, struct exec_list *list)
nir_register *reg = ralloc(mem_ctx, nir_register);
reg->parent_instr = NULL;
- reg->uses = _mesa_set_create(mem_ctx, _mesa_hash_pointer,
+ reg->uses = _mesa_set_create(reg, _mesa_hash_pointer,
_mesa_key_pointer_equal);
- reg->defs = _mesa_set_create(mem_ctx, _mesa_hash_pointer,
+ reg->defs = _mesa_set_create(reg, _mesa_hash_pointer,
_mesa_key_pointer_equal);
- reg->if_uses = _mesa_set_create(mem_ctx, _mesa_hash_pointer,
+ reg->if_uses = _mesa_set_create(reg, _mesa_hash_pointer,
_mesa_key_pointer_equal);
reg->num_components = 0;
@@ -108,7 +108,7 @@ nir_function_create(nir_shader *shader, const char *name)
exec_list_push_tail(&shader->functions, &func->node);
exec_list_make_empty(&func->overload_list);
- func->name = name;
+ func->name = ralloc_strdup(func, name);
func->shader = shader;
return func;
@@ -285,10 +285,10 @@ nir_block_create(void *mem_ctx)
cf_init(&block->cf_node, nir_cf_node_block);
block->successors[0] = block->successors[1] = NULL;
- block->predecessors = _mesa_set_create(mem_ctx, _mesa_hash_pointer,
+ block->predecessors = _mesa_set_create(block, _mesa_hash_pointer,
_mesa_key_pointer_equal);
block->imm_dom = NULL;
- block->dom_frontier = _mesa_set_create(mem_ctx, _mesa_hash_pointer,
+ block->dom_frontier = _mesa_set_create(block, _mesa_hash_pointer,
_mesa_key_pointer_equal);
exec_list_make_empty(&block->instr_list);
@@ -381,11 +381,11 @@ alu_src_init(nir_alu_src *src)
}
nir_alu_instr *
-nir_alu_instr_create(void *mem_ctx, nir_op op)
+nir_alu_instr_create(nir_shader *shader, nir_op op)
{
unsigned num_srcs = nir_op_infos[op].num_inputs;
nir_alu_instr *instr =
- ralloc_size(mem_ctx,
+ ralloc_size(shader,
sizeof(nir_alu_instr) + num_srcs * sizeof(nir_alu_src));
instr_init(&instr->instr, nir_instr_type_alu);
@@ -398,18 +398,18 @@ nir_alu_instr_create(void *mem_ctx, nir_op op)
}
nir_jump_instr *
-nir_jump_instr_create(void *mem_ctx, nir_jump_type type)
+nir_jump_instr_create(nir_shader *shader, nir_jump_type type)
{
- nir_jump_instr *instr = ralloc(mem_ctx, nir_jump_instr);
+ nir_jump_instr *instr = ralloc(shader, nir_jump_instr);
instr_init(&instr->instr, nir_instr_type_jump);
instr->type = type;
return instr;
}
nir_load_const_instr *
-nir_load_const_instr_create(void *mem_ctx, unsigned num_components)
+nir_load_const_instr_create(nir_shader *shader, unsigned num_components)
{
- nir_load_const_instr *instr = ralloc(mem_ctx, nir_load_const_instr);
+ nir_load_const_instr *instr = ralloc(shader, nir_load_const_instr);
instr_init(&instr->instr, nir_instr_type_load_const);
nir_ssa_def_init(&instr->instr, &instr->def, num_components, NULL);
@@ -418,11 +418,11 @@ nir_load_const_instr_create(void *mem_ctx, unsigned num_components)
}
nir_intrinsic_instr *
-nir_intrinsic_instr_create(void *mem_ctx, nir_intrinsic_op op)
+nir_intrinsic_instr_create(nir_shader *shader, nir_intrinsic_op op)
{
unsigned num_srcs = nir_intrinsic_infos[op].num_srcs;
nir_intrinsic_instr *instr =
- ralloc_size(mem_ctx,
+ ralloc_size(shader,
sizeof(nir_intrinsic_instr) + num_srcs * sizeof(nir_src));
instr_init(&instr->instr, nir_instr_type_intrinsic);
@@ -438,29 +438,29 @@ nir_intrinsic_instr_create(void *mem_ctx, nir_intrinsic_op op)
}
nir_call_instr *
-nir_call_instr_create(void *mem_ctx, nir_function_overload *callee)
+nir_call_instr_create(nir_shader *shader, nir_function_overload *callee)
{
- nir_call_instr *instr = ralloc(mem_ctx, nir_call_instr);
+ nir_call_instr *instr = ralloc(shader, nir_call_instr);
instr_init(&instr->instr, nir_instr_type_call);
instr->callee = callee;
instr->num_params = callee->num_params;
- instr->params = ralloc_array(mem_ctx, nir_deref_var *, instr->num_params);
+ instr->params = ralloc_array(instr, nir_deref_var *, instr->num_params);
instr->return_deref = NULL;
return instr;
}
nir_tex_instr *
-nir_tex_instr_create(void *mem_ctx, unsigned num_srcs)
+nir_tex_instr_create(nir_shader *shader, unsigned num_srcs)
{
- nir_tex_instr *instr = ralloc(mem_ctx, nir_tex_instr);
+ nir_tex_instr *instr = ralloc(shader, nir_tex_instr);
instr_init(&instr->instr, nir_instr_type_tex);
dest_init(&instr->dest);
instr->num_srcs = num_srcs;
- instr->src = ralloc_array(mem_ctx, nir_tex_src, num_srcs);
+ instr->src = ralloc_array(instr, nir_tex_src, num_srcs);
for (unsigned i = 0; i < num_srcs; i++)
src_init(&instr->src[i].src);
@@ -472,9 +472,9 @@ nir_tex_instr_create(void *mem_ctx, unsigned num_srcs)
}
nir_phi_instr *
-nir_phi_instr_create(void *mem_ctx)
+nir_phi_instr_create(nir_shader *shader)
{
- nir_phi_instr *instr = ralloc(mem_ctx, nir_phi_instr);
+ nir_phi_instr *instr = ralloc(shader, nir_phi_instr);
instr_init(&instr->instr, nir_instr_type_phi);
dest_init(&instr->dest);
@@ -483,9 +483,9 @@ nir_phi_instr_create(void *mem_ctx)
}
nir_parallel_copy_instr *
-nir_parallel_copy_instr_create(void *mem_ctx)
+nir_parallel_copy_instr_create(nir_shader *shader)
{
- nir_parallel_copy_instr *instr = ralloc(mem_ctx, nir_parallel_copy_instr);
+ nir_parallel_copy_instr *instr = ralloc(shader, nir_parallel_copy_instr);
instr_init(&instr->instr, nir_instr_type_parallel_copy);
exec_list_make_empty(&instr->entries);
@@ -494,9 +494,9 @@ nir_parallel_copy_instr_create(void *mem_ctx)
}
nir_ssa_undef_instr *
-nir_ssa_undef_instr_create(void *mem_ctx, unsigned num_components)
+nir_ssa_undef_instr_create(nir_shader *shader, unsigned num_components)
{
- nir_ssa_undef_instr *instr = ralloc(mem_ctx, nir_ssa_undef_instr);
+ nir_ssa_undef_instr *instr = ralloc(shader, nir_ssa_undef_instr);
instr_init(&instr->instr, nir_instr_type_ssa_undef);
nir_ssa_def_init(&instr->instr, &instr->def, num_components, NULL);
@@ -543,7 +543,7 @@ copy_deref_var(void *mem_ctx, nir_deref_var *deref)
nir_deref_var *ret = nir_deref_var_create(mem_ctx, deref->var);
ret->deref.type = deref->deref.type;
if (deref->deref.child)
- ret->deref.child = nir_copy_deref(mem_ctx, deref->deref.child);
+ ret->deref.child = nir_copy_deref(ret, deref->deref.child);
return ret;
}
@@ -558,7 +558,7 @@ copy_deref_array(void *mem_ctx, nir_deref_array *deref)
}
ret->deref.type = deref->deref.type;
if (deref->deref.child)
- ret->deref.child = nir_copy_deref(mem_ctx, deref->deref.child);
+ ret->deref.child = nir_copy_deref(ret, deref->deref.child);
return ret;
}
@@ -568,7 +568,7 @@ copy_deref_struct(void *mem_ctx, nir_deref_struct *deref)
nir_deref_struct *ret = nir_deref_struct_create(mem_ctx, deref->index);
ret->deref.type = deref->deref.type;
if (deref->deref.child)
- ret->deref.child = nir_copy_deref(mem_ctx, deref->deref.child);
+ ret->deref.child = nir_copy_deref(ret, deref->deref.child);
return ret;
}
@@ -1834,13 +1834,11 @@ void
nir_ssa_def_init(nir_instr *instr, nir_ssa_def *def,
unsigned num_components, const char *name)
{
- void *mem_ctx = ralloc_parent(instr);
-
def->name = name;
def->parent_instr = instr;
- def->uses = _mesa_set_create(mem_ctx, _mesa_hash_pointer,
+ def->uses = _mesa_set_create(instr, _mesa_hash_pointer,
_mesa_key_pointer_equal);
- def->if_uses = _mesa_set_create(mem_ctx, _mesa_hash_pointer,
+ def->if_uses = _mesa_set_create(instr, _mesa_hash_pointer,
_mesa_key_pointer_equal);
def->num_components = num_components;
diff --git a/mesalib/src/glsl/nir/nir.h b/mesalib/src/glsl/nir/nir.h
index 29fe94243..74772c798 100644
--- a/mesalib/src/glsl/nir/nir.h
+++ b/mesalib/src/glsl/nir/nir.h
@@ -34,6 +34,7 @@
#include "util/set.h"
#include "util/bitset.h"
#include "nir_types.h"
+#include "glsl/shader_enums.h"
#include <stdio.h>
#include "nir_opcodes.h"
@@ -529,6 +530,16 @@ nir_src_for_reg(nir_register *reg)
return src;
}
+static inline nir_instr *
+nir_src_get_parent_instr(const nir_src *src)
+{
+ if (src->is_ssa) {
+ return src->ssa->parent_instr;
+ } else {
+ return src->reg.reg->parent_instr;
+ }
+}
+
static inline nir_dest
nir_dest_for_reg(nir_register *reg)
{
@@ -1365,11 +1376,17 @@ typedef struct nir_function {
typedef struct nir_shader_compiler_options {
bool lower_ffma;
+ bool lower_flrp;
bool lower_fpow;
bool lower_fsat;
bool lower_fsqrt;
/** lowers fneg and ineg to fsub and isub. */
bool lower_negate;
+ /** lowers fsub and isub to fadd+fneg and iadd+ineg. */
+ bool lower_sub;
+
+ /* lower {slt,sge,seq,sne} to {flt,fge,feq,fne} + b2f: */
+ bool lower_scmp;
/**
* Does the driver support real 32-bit integers? (Otherwise, integers
@@ -1414,6 +1431,9 @@ typedef struct nir_shader {
* access plus one
*/
unsigned num_inputs, num_uniforms, num_outputs;
+
+ /** the number of uniforms that are only accessed directly */
+ unsigned num_direct_uniforms;
} nir_shader;
#define nir_foreach_overload(shader, overload) \
@@ -1466,26 +1486,26 @@ void nir_metadata_require(nir_function_impl *impl, nir_metadata required);
void nir_metadata_preserve(nir_function_impl *impl, nir_metadata preserved);
/** creates an instruction with default swizzle/writemask/etc. with NULL registers */
-nir_alu_instr *nir_alu_instr_create(void *mem_ctx, nir_op op);
+nir_alu_instr *nir_alu_instr_create(nir_shader *shader, nir_op op);
-nir_jump_instr *nir_jump_instr_create(void *mem_ctx, nir_jump_type type);
+nir_jump_instr *nir_jump_instr_create(nir_shader *shader, nir_jump_type type);
-nir_load_const_instr *nir_load_const_instr_create(void *mem_ctx,
+nir_load_const_instr *nir_load_const_instr_create(nir_shader *shader,
unsigned num_components);
-nir_intrinsic_instr *nir_intrinsic_instr_create(void *mem_ctx,
+nir_intrinsic_instr *nir_intrinsic_instr_create(nir_shader *shader,
nir_intrinsic_op op);
-nir_call_instr *nir_call_instr_create(void *mem_ctx,
+nir_call_instr *nir_call_instr_create(nir_shader *shader,
nir_function_overload *callee);
-nir_tex_instr *nir_tex_instr_create(void *mem_ctx, unsigned num_srcs);
+nir_tex_instr *nir_tex_instr_create(nir_shader *shader, unsigned num_srcs);
-nir_phi_instr *nir_phi_instr_create(void *mem_ctx);
+nir_phi_instr *nir_phi_instr_create(nir_shader *shader);
-nir_parallel_copy_instr *nir_parallel_copy_instr_create(void *mem_ctx);
+nir_parallel_copy_instr *nir_parallel_copy_instr_create(nir_shader *shader);
-nir_ssa_undef_instr *nir_ssa_undef_instr_create(void *mem_ctx,
+nir_ssa_undef_instr *nir_ssa_undef_instr_create(nir_shader *shader,
unsigned num_components);
nir_deref_var *nir_deref_var_create(void *mem_ctx, nir_variable *var);
@@ -1550,7 +1570,7 @@ void nir_print_instr(const nir_instr *instr, FILE *fp);
#ifdef DEBUG
void nir_validate_shader(nir_shader *shader);
#else
-static inline void nir_validate_shader(nir_shader *shader) { }
+static inline void nir_validate_shader(nir_shader *shader) { (void) shader; }
#endif /* DEBUG */
void nir_calc_dominance_impl(nir_function_impl *impl);
@@ -1596,14 +1616,18 @@ void nir_lower_alu_to_scalar(nir_shader *shader);
void nir_lower_phis_to_scalar(nir_shader *shader);
void nir_lower_samplers(nir_shader *shader,
- struct gl_shader_program *shader_program,
- struct gl_program *prog);
+ const struct gl_shader_program *shader_program,
+ gl_shader_stage stage);
void nir_lower_system_values(nir_shader *shader);
+void nir_lower_tex_projector(nir_shader *shader);
+void nir_lower_idiv(nir_shader *shader);
void nir_lower_atomics(nir_shader *shader);
void nir_lower_to_source_mods(nir_shader *shader);
+void nir_normalize_cubemap_coords(nir_shader *shader);
+
void nir_live_variables_impl(nir_function_impl *impl);
bool nir_ssa_defs_interfere(nir_ssa_def *a, nir_ssa_def *b);
@@ -1612,6 +1636,7 @@ void nir_convert_to_ssa(nir_shader *shader);
void nir_convert_from_ssa(nir_shader *shader);
bool nir_opt_algebraic(nir_shader *shader);
+bool nir_opt_algebraic_late(nir_shader *shader);
bool nir_opt_constant_folding(nir_shader *shader);
bool nir_opt_global_to_local(nir_shader *shader);
@@ -1631,6 +1656,8 @@ bool nir_opt_peephole_ffma(nir_shader *shader);
bool nir_opt_remove_phis(nir_shader *shader);
+void nir_sweep(nir_shader *shader);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/mesalib/src/glsl/nir/nir_algebraic.py b/mesalib/src/glsl/nir/nir_algebraic.py
index afab1a008..bbf4f08ef 100644
--- a/mesalib/src/glsl/nir/nir_algebraic.py
+++ b/mesalib/src/glsl/nir/nir_algebraic.py
@@ -181,12 +181,23 @@ _algebraic_pass_template = mako.template.Template("""
#include "nir.h"
#include "nir_search.h"
+#ifndef NIR_OPT_ALGEBRAIC_STRUCT_DEFS
+#define NIR_OPT_ALGEBRAIC_STRUCT_DEFS
+
struct transform {
const nir_search_expression *search;
const nir_search_value *replace;
unsigned condition_offset;
};
+struct opt_state {
+ void *mem_ctx;
+ bool progress;
+ const bool *condition_flags;
+};
+
+#endif
+
% for (opcode, xform_list) in xform_dict.iteritems():
% for xform in xform_list:
${xform.search.render()}
@@ -200,12 +211,6 @@ static const struct transform ${pass_name}_${opcode}_xforms[] = {
};
% endfor
-struct opt_state {
- void *mem_ctx;
- bool progress;
- const bool *condition_flags;
-};
-
static bool
${pass_name}_block(nir_block *block, void *void_state)
{
diff --git a/mesalib/src/glsl/nir/nir_builder.h b/mesalib/src/glsl/nir/nir_builder.h
index 7c4f7fd96..d1419ee21 100644
--- a/mesalib/src/glsl/nir/nir_builder.h
+++ b/mesalib/src/glsl/nir/nir_builder.h
@@ -28,6 +28,9 @@ struct exec_list;
typedef struct nir_builder {
struct exec_list *cf_node_list;
+ nir_instr *before_instr;
+ nir_instr *after_instr;
+
nir_shader *shader;
nir_function_impl *impl;
} nir_builder;
@@ -45,8 +48,75 @@ nir_builder_insert_after_cf_list(nir_builder *build,
struct exec_list *cf_node_list)
{
build->cf_node_list = cf_node_list;
+ build->before_instr = NULL;
+ build->after_instr = NULL;
+}
+
+static inline void
+nir_builder_insert_before_instr(nir_builder *build, nir_instr *before_instr)
+{
+ build->cf_node_list = NULL;
+ build->before_instr = before_instr;
+ build->after_instr = NULL;
}
+static inline void
+nir_builder_insert_after_instr(nir_builder *build, nir_instr *after_instr)
+{
+ build->cf_node_list = NULL;
+ build->before_instr = NULL;
+ build->after_instr = after_instr;
+}
+
+static inline void
+nir_builder_instr_insert(nir_builder *build, nir_instr *instr)
+{
+ if (build->cf_node_list) {
+ nir_instr_insert_after_cf_list(build->cf_node_list, instr);
+ } else if (build->before_instr) {
+ nir_instr_insert_before(build->before_instr, instr);
+ } else {
+ assert(build->after_instr);
+ nir_instr_insert_after(build->after_instr, instr);
+ build->after_instr = instr;
+ }
+}
+
+static inline nir_ssa_def *
+nir_build_imm(nir_builder *build, unsigned num_components, nir_const_value value)
+{
+ nir_load_const_instr *load_const =
+ nir_load_const_instr_create(build->shader, num_components);
+ if (!load_const)
+ return NULL;
+
+ load_const->value = value;
+
+ nir_builder_instr_insert(build, &load_const->instr);
+
+ return &load_const->def;
+}
+
+static inline nir_ssa_def *
+nir_imm_float(nir_builder *build, float x)
+{
+ nir_const_value v = { { .f = {x, 0, 0, 0} } };
+ return nir_build_imm(build, 1, v);
+}
+
+static inline nir_ssa_def *
+nir_imm_vec4(nir_builder *build, float x, float y, float z, float w)
+{
+ nir_const_value v = { { .f = {x, y, z, w} } };
+ return nir_build_imm(build, 4, v);
+}
+
+static inline nir_ssa_def *
+nir_imm_int(nir_builder *build, int x)
+{
+ nir_const_value v = { { .i = {x, 0, 0, 0} } };
+ return nir_build_imm(build, 1, v);
+}
static inline nir_ssa_def *
nir_build_alu(nir_builder *build, nir_op op, nir_ssa_def *src0,
@@ -90,7 +160,7 @@ nir_build_alu(nir_builder *build, nir_op op, nir_ssa_def *src0,
nir_ssa_dest_init(&instr->instr, &instr->dest.dest, num_components, NULL);
instr->dest.write_mask = (1 << num_components) - 1;
- nir_instr_insert_after_cf_list(build->cf_node_list, &instr->instr);
+ nir_builder_instr_insert(build, &instr->instr);
return &instr->dest.dest.ssa;
}
@@ -127,4 +197,67 @@ nir_##op(nir_builder *build, nir_ssa_def *src0, \
#include "nir_builder_opcodes.h"
+/**
+ * Similar to nir_fmov, but takes a nir_alu_src instead of a nir_ssa_def.
+ */
+static inline nir_ssa_def *
+nir_fmov_alu(nir_builder *build, nir_alu_src src, unsigned num_components)
+{
+ nir_alu_instr *mov = nir_alu_instr_create(build->shader, nir_op_fmov);
+ nir_ssa_dest_init(&mov->instr, &mov->dest.dest, num_components, NULL);
+ mov->dest.write_mask = (1 << num_components) - 1;
+ mov->src[0] = src;
+ nir_builder_instr_insert(build, &mov->instr);
+
+ return &mov->dest.dest.ssa;
+}
+
+static inline nir_ssa_def *
+nir_imov_alu(nir_builder *build, nir_alu_src src, unsigned num_components)
+{
+ nir_alu_instr *mov = nir_alu_instr_create(build->shader, nir_op_imov);
+ nir_ssa_dest_init(&mov->instr, &mov->dest.dest, num_components, NULL);
+ mov->dest.write_mask = (1 << num_components) - 1;
+ mov->src[0] = src;
+ nir_builder_instr_insert(build, &mov->instr);
+
+ return &mov->dest.dest.ssa;
+}
+
+/**
+ * Construct an fmov or imov that reswizzles the source's components.
+ */
+static inline nir_ssa_def *
+nir_swizzle(nir_builder *build, nir_ssa_def *src, unsigned swiz[4],
+ unsigned num_components, bool use_fmov)
+{
+ nir_alu_src alu_src;
+ memset(&alu_src, 0, sizeof(alu_src));
+ alu_src.src = nir_src_for_ssa(src);
+ for (int i = 0; i < 4; i++)
+ alu_src.swizzle[i] = swiz[i];
+
+ return use_fmov ? nir_fmov_alu(build, alu_src, num_components) :
+ nir_imov_alu(build, alu_src, num_components);
+}
+
+/**
+ * Turns a nir_src into a nir_ssa_def * so it can be passed to
+ * nir_build_alu()-based builder calls.
+ */
+static inline nir_ssa_def *
+nir_ssa_for_src(nir_builder *build, nir_src src, int num_components)
+{
+ if (src.is_ssa && src.ssa->num_components == num_components)
+ return src.ssa;
+
+ nir_alu_src alu;
+ memset(&alu, 0, sizeof(alu));
+ alu.src = src;
+ for (int j = 0; j < 4; j++)
+ alu.swizzle[j] = j;
+
+ return nir_imov_alu(build, alu, num_components);
+}
+
#endif /* NIR_BUILDER_H */
diff --git a/mesalib/src/glsl/nir/nir_from_ssa.c b/mesalib/src/glsl/nir/nir_from_ssa.c
index c3090fb06..184698abd 100644
--- a/mesalib/src/glsl/nir/nir_from_ssa.c
+++ b/mesalib/src/glsl/nir/nir_from_ssa.c
@@ -509,12 +509,13 @@ get_register_for_ssa_def(nir_ssa_def *def, struct from_ssa_state *state)
reg->num_components = def->num_components;
reg->num_array_elems = 0;
- /* This register comes from an SSA definition that was not part of a
- * phi-web. Therefore, we know it has a single unique definition
- * that dominates all of its uses. Therefore, we can copy the
+ /* This register comes from an SSA definition that is defined and not
+ * part of a phi-web. Therefore, we know it has a single unique
+ * definition that dominates all of its uses; we can copy the
* parent_instr from the SSA def safely.
*/
- reg->parent_instr = def->parent_instr;
+ if (def->parent_instr->type != nir_instr_type_ssa_undef)
+ reg->parent_instr = def->parent_instr;
_mesa_hash_table_insert(state->ssa_table, def, reg);
return reg;
diff --git a/mesalib/src/glsl/nir/nir_lower_idiv.c b/mesalib/src/glsl/nir/nir_lower_idiv.c
new file mode 100644
index 000000000..7b6803207
--- /dev/null
+++ b/mesalib/src/glsl/nir/nir_lower_idiv.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright © 2015 Red Hat
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Rob Clark <robclark@freedesktop.org>
+ */
+
+#include "nir.h"
+#include "nir_builder.h"
+
+/* Lowers idiv/udiv/umod
+ * Based on NV50LegalizeSSA::handleDIV()
+ *
+ * Note that this is probably not enough precision for compute shaders.
+ * Perhaps we want a second higher precision (looping) version of this?
+ * Or perhaps we assume if you can do compute shaders you can also
+ * branch out to a pre-optimized shader library routine..
+ */
+
+static void
+convert_instr(nir_builder *bld, nir_alu_instr *alu)
+{
+ nir_ssa_def *numer, *denom, *af, *bf, *a, *b, *q, *r;
+ nir_op op = alu->op;
+ bool is_signed;
+
+ if ((op != nir_op_idiv) &&
+ (op != nir_op_udiv) &&
+ (op != nir_op_umod))
+ return;
+
+ is_signed = (op == nir_op_idiv);
+
+ nir_builder_insert_before_instr(bld, &alu->instr);
+
+ numer = nir_ssa_for_src(bld, alu->src[0].src,
+ nir_ssa_alu_instr_src_components(alu, 0));
+ denom = nir_ssa_for_src(bld, alu->src[1].src,
+ nir_ssa_alu_instr_src_components(alu, 1));
+
+ if (is_signed) {
+ af = nir_i2f(bld, numer);
+ bf = nir_i2f(bld, denom);
+ af = nir_fabs(bld, af);
+ bf = nir_fabs(bld, bf);
+ a = nir_iabs(bld, numer);
+ b = nir_iabs(bld, denom);
+ } else {
+ af = nir_u2f(bld, numer);
+ bf = nir_u2f(bld, denom);
+ a = numer;
+ b = denom;
+ }
+
+ /* get first result: */
+ bf = nir_frcp(bld, bf);
+ bf = nir_isub(bld, bf, nir_imm_int(bld, 2)); /* yes, really */
+ q = nir_fmul(bld, af, bf);
+
+ if (is_signed) {
+ q = nir_f2i(bld, q);
+ } else {
+ q = nir_f2u(bld, q);
+ }
+
+ /* get error of first result: */
+ r = nir_imul(bld, q, b);
+ r = nir_isub(bld, a, r);
+ r = nir_u2f(bld, r);
+ r = nir_fmul(bld, r, bf);
+ r = nir_f2u(bld, r);
+
+ /* add quotients: */
+ q = nir_iadd(bld, q, r);
+
+ /* correction: if modulus >= divisor, add 1 */
+ r = nir_imul(bld, q, b);
+ r = nir_isub(bld, a, r);
+
+ r = nir_ige(bld, r, b);
+ r = nir_b2i(bld, r);
+
+ q = nir_iadd(bld, q, r);
+ if (is_signed) {
+ /* fix the sign: */
+ r = nir_ixor(bld, numer, denom);
+ r = nir_ushr(bld, r, nir_imm_int(bld, 31));
+ r = nir_i2b(bld, r);
+ b = nir_ineg(bld, q);
+ q = nir_bcsel(bld, r, b, q);
+ }
+
+ if (op == nir_op_umod) {
+ /* division result in q */
+ r = nir_imul(bld, q, b);
+ q = nir_isub(bld, a, r);
+ }
+
+ assert(alu->dest.dest.is_ssa);
+ nir_ssa_def_rewrite_uses(&alu->dest.dest.ssa,
+ nir_src_for_ssa(q),
+ ralloc_parent(alu));
+}
+
+static bool
+convert_block(nir_block *block, void *state)
+{
+ nir_builder *b = state;
+
+ nir_foreach_instr_safe(block, instr) {
+ if (instr->type == nir_instr_type_alu)
+ convert_instr(b, nir_instr_as_alu(instr));
+ }
+
+ return true;
+}
+
+static void
+convert_impl(nir_function_impl *impl)
+{
+ nir_builder b;
+ nir_builder_init(&b, impl);
+
+ nir_foreach_block(impl, convert_block, &b);
+ nir_metadata_preserve(impl, nir_metadata_block_index |
+ nir_metadata_dominance);
+}
+
+void
+nir_lower_idiv(nir_shader *shader)
+{
+ nir_foreach_overload(shader, overload) {
+ if (overload->impl)
+ convert_impl(overload->impl);
+ }
+}
diff --git a/mesalib/src/glsl/nir/nir_lower_phis_to_scalar.c b/mesalib/src/glsl/nir/nir_lower_phis_to_scalar.c
index 7cd93ea0a..4bdb80072 100644
--- a/mesalib/src/glsl/nir/nir_lower_phis_to_scalar.c
+++ b/mesalib/src/glsl/nir/nir_lower_phis_to_scalar.c
@@ -223,7 +223,7 @@ lower_phis_to_scalar_block(nir_block *block, void *void_state)
else
nir_instr_insert_after_block(src->pred, &mov->instr);
- nir_phi_src *new_src = ralloc(state->mem_ctx, nir_phi_src);
+ nir_phi_src *new_src = ralloc(new_phi, nir_phi_src);
new_src->pred = src->pred;
new_src->src = nir_src_for_ssa(&mov->dest.dest.ssa);
diff --git a/mesalib/src/glsl/nir/nir_lower_samplers.cpp b/mesalib/src/glsl/nir/nir_lower_samplers.cpp
index 3015dbd09..cf8ab8325 100644
--- a/mesalib/src/glsl/nir/nir_lower_samplers.cpp
+++ b/mesalib/src/glsl/nir/nir_lower_samplers.cpp
@@ -36,33 +36,26 @@ extern "C" {
}
static unsigned
-get_sampler_index(struct gl_shader_program *shader_program, const char *name,
- const struct gl_program *prog)
+get_sampler_index(const struct gl_shader_program *shader_program,
+ gl_shader_stage stage, const char *name)
{
- GLuint shader = _mesa_program_enum_to_shader_stage(prog->Target);
-
unsigned location;
if (!shader_program->UniformHash->get(location, name)) {
- linker_error(shader_program,
- "failed to find sampler named %s.\n", name);
+ assert(!"failed to find sampler");
return 0;
}
- if (!shader_program->UniformStorage[location].sampler[shader].active) {
- assert(0 && "cannot return a sampler");
- linker_error(shader_program,
- "cannot return a sampler named %s, because it is not "
- "used in this shader stage. This is a driver bug.\n",
- name);
+ if (!shader_program->UniformStorage[location].sampler[stage].active) {
+ assert(!"cannot return a sampler");
return 0;
}
- return shader_program->UniformStorage[location].sampler[shader].index;
+ return shader_program->UniformStorage[location].sampler[stage].index;
}
static void
-lower_sampler(nir_tex_instr *instr, struct gl_shader_program *shader_program,
- const struct gl_program *prog, void *mem_ctx)
+lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_program,
+ gl_shader_stage stage, void *mem_ctx)
{
if (instr->sampler == NULL)
return;
@@ -90,7 +83,7 @@ lower_sampler(nir_tex_instr *instr, struct gl_shader_program *shader_program,
ralloc_asprintf_append(&name, "[%u]", deref_array->base_offset);
break;
case nir_deref_array_type_indirect: {
- instr->src = reralloc(mem_ctx, instr->src, nir_tex_src,
+ instr->src = reralloc(instr, instr->src, nir_tex_src,
instr->num_srcs + 1);
memset(&instr->src[instr->num_srcs], 0, sizeof *instr->src);
instr->src[instr->num_srcs].src_type = nir_tex_src_sampler_offset;
@@ -133,15 +126,15 @@ lower_sampler(nir_tex_instr *instr, struct gl_shader_program *shader_program,
}
}
- instr->sampler_index += get_sampler_index(shader_program, name, prog);
+ instr->sampler_index += get_sampler_index(shader_program, stage, name);
instr->sampler = NULL;
}
typedef struct {
void *mem_ctx;
- struct gl_shader_program *shader_program;
- struct gl_program *prog;
+ const struct gl_shader_program *shader_program;
+ gl_shader_stage stage;
} lower_state;
static bool
@@ -152,7 +145,7 @@ lower_block_cb(nir_block *block, void *_state)
nir_foreach_instr(block, instr) {
if (instr->type == nir_instr_type_tex) {
nir_tex_instr *tex_instr = nir_instr_as_tex(instr);
- lower_sampler(tex_instr, state->shader_program, state->prog,
+ lower_sampler(tex_instr, state->shader_program, state->stage,
state->mem_ctx);
}
}
@@ -161,24 +154,24 @@ lower_block_cb(nir_block *block, void *_state)
}
static void
-lower_impl(nir_function_impl *impl, struct gl_shader_program *shader_program,
- struct gl_program *prog)
+lower_impl(nir_function_impl *impl, const struct gl_shader_program *shader_program,
+ gl_shader_stage stage)
{
lower_state state;
state.mem_ctx = ralloc_parent(impl);
state.shader_program = shader_program;
- state.prog = prog;
+ state.stage = stage;
nir_foreach_block(impl, lower_block_cb, &state);
}
extern "C" void
-nir_lower_samplers(nir_shader *shader, struct gl_shader_program *shader_program,
- struct gl_program *prog)
+nir_lower_samplers(nir_shader *shader, const struct gl_shader_program *shader_program,
+ gl_shader_stage stage)
{
nir_foreach_overload(shader, overload) {
if (overload->impl)
- lower_impl(overload->impl, shader_program, prog);
+ lower_impl(overload->impl, shader_program, stage);
}
}
diff --git a/mesalib/src/glsl/nir/nir_lower_tex_projector.c b/mesalib/src/glsl/nir/nir_lower_tex_projector.c
new file mode 100644
index 000000000..6b0e9c340
--- /dev/null
+++ b/mesalib/src/glsl/nir/nir_lower_tex_projector.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright © 2015 Broadcom
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/*
+ * This lowering pass converts the coordinate division for texture projection
+ * to be done in ALU instructions instead of asking the texture operation to
+ * do so.
+ */
+
+#include "nir.h"
+#include "nir_builder.h"
+
+static nir_ssa_def *
+channel(nir_builder *b, nir_ssa_def *def, int c)
+{
+ return nir_swizzle(b, def, (unsigned[4]){c, c, c, c}, 1, false);
+}
+
+static bool
+nir_lower_tex_projector_block(nir_block *block, void *void_state)
+{
+ nir_builder *b = void_state;
+
+ nir_foreach_instr_safe(block, instr) {
+ if (instr->type != nir_instr_type_tex)
+ continue;
+
+ nir_tex_instr *tex = nir_instr_as_tex(instr);
+ nir_builder_insert_before_instr(b, &tex->instr);
+
+ /* Find the projector in the srcs list, if present. */
+ int proj_index;
+ for (proj_index = 0; proj_index < tex->num_srcs; proj_index++) {
+ if (tex->src[proj_index].src_type == nir_tex_src_projector)
+ break;
+ }
+ if (proj_index == tex->num_srcs)
+ continue;
+ nir_ssa_def *inv_proj =
+ nir_frcp(b, nir_ssa_for_src(b, tex->src[proj_index].src, 1));
+
+ /* Walk through the sources projecting the arguments. */
+ for (int i = 0; i < tex->num_srcs; i++) {
+ switch (tex->src[i].src_type) {
+ case nir_tex_src_coord:
+ case nir_tex_src_comparitor:
+ break;
+ default:
+ continue;
+ }
+ nir_ssa_def *unprojected =
+ nir_ssa_for_src(b, tex->src[i].src, nir_tex_instr_src_size(tex, i));
+ nir_ssa_def *projected = nir_fmul(b, unprojected, inv_proj);
+
+ /* Array indices don't get projected, so make an new vector with the
+ * coordinate's array index untouched.
+ */
+ if (tex->is_array && tex->src[i].src_type == nir_tex_src_coord) {
+ switch (tex->coord_components) {
+ case 4:
+ projected = nir_vec4(b,
+ channel(b, projected, 0),
+ channel(b, projected, 1),
+ channel(b, projected, 2),
+ channel(b, unprojected, 3));
+ break;
+ case 3:
+ projected = nir_vec3(b,
+ channel(b, projected, 0),
+ channel(b, projected, 1),
+ channel(b, unprojected, 2));
+ break;
+ case 2:
+ projected = nir_vec2(b,
+ channel(b, projected, 0),
+ channel(b, unprojected, 1));
+ break;
+ default:
+ unreachable("bad texture coord count for array");
+ break;
+ }
+ }
+
+ nir_instr_rewrite_src(&tex->instr,
+ &tex->src[i].src,
+ nir_src_for_ssa(projected));
+ }
+
+ /* Now move the later tex sources down the array so that the projector
+ * disappears.
+ */
+ nir_src dead;
+ memset(&dead, 0, sizeof dead);
+ nir_instr_rewrite_src(&tex->instr, &tex->src[proj_index].src, dead);
+ memmove(&tex->src[proj_index],
+ &tex->src[proj_index + 1],
+ (tex->num_srcs - proj_index) * sizeof(*tex->src));
+ tex->num_srcs--;
+ }
+
+ return true;
+}
+
+static void
+nir_lower_tex_projector_impl(nir_function_impl *impl)
+{
+ nir_builder b;
+ nir_builder_init(&b, impl);
+
+ nir_foreach_block(impl, nir_lower_tex_projector_block, &b);
+
+ nir_metadata_preserve(impl, nir_metadata_block_index |
+ nir_metadata_dominance);
+}
+
+void
+nir_lower_tex_projector(nir_shader *shader)
+{
+ nir_foreach_overload(shader, overload) {
+ if (overload->impl)
+ nir_lower_tex_projector_impl(overload->impl);
+ }
+}
diff --git a/mesalib/src/glsl/nir/nir_lower_var_copies.c b/mesalib/src/glsl/nir/nir_lower_var_copies.c
index 85ebb281c..58389a7c7 100644
--- a/mesalib/src/glsl/nir/nir_lower_var_copies.c
+++ b/mesalib/src/glsl/nir/nir_lower_var_copies.c
@@ -148,13 +148,10 @@ emit_copy_load_store(nir_intrinsic_instr *copy_instr,
unsigned num_components = glsl_get_vector_elements(src_tail->type);
- nir_deref *src_deref = nir_copy_deref(mem_ctx, &src_head->deref);
- nir_deref *dest_deref = nir_copy_deref(mem_ctx, &dest_head->deref);
-
nir_intrinsic_instr *load =
nir_intrinsic_instr_create(mem_ctx, nir_intrinsic_load_var);
load->num_components = num_components;
- load->variables[0] = nir_deref_as_var(src_deref);
+ load->variables[0] = nir_deref_as_var(nir_copy_deref(load, &src_head->deref));
nir_ssa_dest_init(&load->instr, &load->dest, num_components, NULL);
nir_instr_insert_before(&copy_instr->instr, &load->instr);
@@ -162,7 +159,8 @@ emit_copy_load_store(nir_intrinsic_instr *copy_instr,
nir_intrinsic_instr *store =
nir_intrinsic_instr_create(mem_ctx, nir_intrinsic_store_var);
store->num_components = num_components;
- store->variables[0] = nir_deref_as_var(dest_deref);
+ store->variables[0] = nir_deref_as_var(nir_copy_deref(store, &dest_head->deref));
+
store->src[0].is_ssa = true;
store->src[0].ssa = &load->dest.ssa;
diff --git a/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c b/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c
index 86e6ab416..2ca74d71b 100644
--- a/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c
+++ b/mesalib/src/glsl/nir/nir_lower_vars_to_ssa.c
@@ -642,7 +642,7 @@ add_phi_sources(nir_block *block, nir_block *pred,
struct deref_node *node = entry->data;
- nir_phi_src *src = ralloc(state->mem_ctx, nir_phi_src);
+ nir_phi_src *src = ralloc(phi, nir_phi_src);
src->pred = pred;
src->src.is_ssa = true;
src->src.ssa = get_ssa_def_for_block(node, pred, state);
diff --git a/mesalib/src/glsl/nir/nir_normalize_cubemap_coords.c b/mesalib/src/glsl/nir/nir_normalize_cubemap_coords.c
new file mode 100644
index 000000000..0da8447ac
--- /dev/null
+++ b/mesalib/src/glsl/nir/nir_normalize_cubemap_coords.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright © 2015 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Jason Ekstrand <jason@jlekstrand.net>
+ */
+
+#include "nir.h"
+#include "nir_builder.h"
+
+/**
+ * This file implements a NIR lowering pass to perform the normalization of
+ * the cubemap coordinates to have the largest magnitude component be -1.0
+ * or 1.0. This is based on the old GLSL IR based pass by Eric.
+ */
+
+static nir_ssa_def *
+channel(nir_builder *b, nir_ssa_def *def, int c)
+{
+ return nir_swizzle(b, def, (unsigned[4]){c, c, c, c}, 1, false);
+}
+
+static bool
+normalize_cubemap_coords_block(nir_block *block, void *void_state)
+{
+ nir_builder *b = void_state;
+
+ nir_foreach_instr(block, instr) {
+ if (instr->type != nir_instr_type_tex)
+ continue;
+
+ nir_tex_instr *tex = nir_instr_as_tex(instr);
+ if (tex->sampler_dim != GLSL_SAMPLER_DIM_CUBE)
+ continue;
+
+ nir_builder_insert_before_instr(b, &tex->instr);
+
+ for (unsigned i = 0; i < tex->num_srcs; i++) {
+ if (tex->src[i].src_type != nir_tex_src_coord)
+ continue;
+
+ nir_ssa_def *orig_coord =
+ nir_ssa_for_src(b, tex->src[i].src, nir_tex_instr_src_size(tex, i));
+ assert(orig_coord->num_components >= 3);
+
+ nir_ssa_def *abs = nir_fabs(b, orig_coord);
+ nir_ssa_def *norm = nir_fmax(b, channel(b, abs, 0),
+ nir_fmax(b, channel(b, abs, 1),
+ channel(b, abs, 2)));
+
+ nir_ssa_def *normalized = nir_fmul(b, orig_coord, nir_frcp(b, norm));
+
+ /* Array indices don't have to be normalized, so make a new vector
+ * with the coordinate's array index untouched.
+ */
+ if (tex->coord_components == 4) {
+ normalized = nir_vec4(b,
+ channel(b, normalized, 0),
+ channel(b, normalized, 1),
+ channel(b, normalized, 2),
+ channel(b, orig_coord, 3));
+ }
+
+ nir_instr_rewrite_src(&tex->instr,
+ &tex->src[i].src,
+ nir_src_for_ssa(normalized));
+ }
+ }
+
+ return true;
+}
+
+static void
+normalize_cubemap_coords_impl(nir_function_impl *impl)
+{
+ nir_builder b;
+ nir_builder_init(&b, impl);
+
+ nir_foreach_block(impl, normalize_cubemap_coords_block, &b);
+
+ nir_metadata_preserve(impl, nir_metadata_block_index |
+ nir_metadata_dominance);
+}
+
+void
+nir_normalize_cubemap_coords(nir_shader *shader)
+{
+ nir_foreach_overload(shader, overload)
+ if (overload->impl)
+ normalize_cubemap_coords_impl(overload->impl);
+}
diff --git a/mesalib/src/glsl/nir/nir_opcodes.py b/mesalib/src/glsl/nir/nir_opcodes.py
index 062cd628b..264806f5d 100644
--- a/mesalib/src/glsl/nir/nir_opcodes.py
+++ b/mesalib/src/glsl/nir/nir_opcodes.py
@@ -161,12 +161,12 @@ unop_convert("f2i", tfloat, tint, "src0") # Float-to-integer conversion.
unop_convert("f2u", tfloat, tunsigned, "src0") # Float-to-unsigned conversion
unop_convert("i2f", tint, tfloat, "src0") # Integer-to-float conversion.
# Float-to-boolean conversion
-unop_convert("f2b", tfloat, tbool, "src0 == 0.0f")
+unop_convert("f2b", tfloat, tbool, "src0 != 0.0f")
# Boolean-to-float conversion
unop_convert("b2f", tbool, tfloat, "src0 ? 1.0f : 0.0f")
# Int-to-boolean conversion
-unop_convert("i2b", tint, tbool, "src0 == 0")
-unop_convert("b2i", tbool, tint, "src0 ? 0 : -1") # Boolean-to-int conversion
+unop_convert("i2b", tint, tbool, "src0 != 0")
+unop_convert("b2i", tbool, tint, "src0 ? 1 : 0") # Boolean-to-int conversion
unop_convert("u2f", tunsigned, tfloat, "src0") #Unsigned-to-float conversion.
unop_reduce("bany", 1, tbool, tbool, "{src}", "{src0} || {src1}", "{src}")
@@ -191,8 +191,6 @@ unop("fround_even", tfloat, "_mesa_roundevenf(src0)")
unop("fsin", tfloat, "sinf(src0)")
unop("fcos", tfloat, "cosf(src0)")
-unop("fsin_reduced", tfloat, "sinf(src0)")
-unop("fcos_reduced", tfloat, "cosf(src0)")
# Partial derivatives.
diff --git a/mesalib/src/glsl/nir/nir_opt_algebraic.py b/mesalib/src/glsl/nir/nir_opt_algebraic.py
index ef855aa77..cdb19241c 100644
--- a/mesalib/src/glsl/nir/nir_opt_algebraic.py
+++ b/mesalib/src/glsl/nir/nir_opt_algebraic.py
@@ -75,6 +75,9 @@ optimizations = [
(('flrp', a, b, 1.0), b),
(('flrp', a, a, b), a),
(('flrp', 0.0, a, b), ('fmul', a, b)),
+ (('flrp', a, b, c), ('fadd', ('fmul', c, ('fsub', b, a)), a), 'options->lower_flrp'),
+ (('fadd', ('fmul', a, ('fadd', 1.0, ('fneg', c))), ('fmul', b, c)), ('flrp', a, b, c), '!options->lower_flrp'),
+ (('fadd', a, ('fmul', c, ('fadd', b, ('fneg', a)))), ('flrp', a, b, c), '!options->lower_flrp'),
(('ffma', a, b, c), ('fadd', ('fmul', a, b), c), 'options->lower_ffma'),
(('fadd', ('fmul', a, b), c), ('ffma', a, b, c), '!options->lower_ffma'),
# Comparison simplifications
@@ -82,10 +85,6 @@ optimizations = [
(('inot', ('fge', a, b)), ('flt', a, b)),
(('inot', ('ilt', a, b)), ('ige', a, b)),
(('inot', ('ige', a, b)), ('ilt', a, b)),
- (('flt', ('fadd', a, b), 0.0), ('flt', a, ('fneg', b))),
- (('fge', ('fadd', a, b), 0.0), ('fge', a, ('fneg', b))),
- (('feq', ('fadd', a, b), 0.0), ('feq', a, ('fneg', b))),
- (('fne', ('fadd', a, b), 0.0), ('fne', a, ('fneg', b))),
(('fge', ('fneg', ('fabs', a)), 0.0), ('feq', a, 0.0)),
(('bcsel', ('flt', a, b), a, b), ('fmin', a, b)),
(('bcsel', ('flt', a, b), b, a), ('fmax', a, b)),
@@ -95,6 +94,18 @@ optimizations = [
(('fsat', a), ('fmin', ('fmax', a, 0.0), 1.0), 'options->lower_fsat'),
(('fsat', ('fsat', a)), ('fsat', a)),
(('fmin', ('fmax', ('fmin', ('fmax', a, 0.0), 1.0), 0.0), 1.0), ('fmin', ('fmax', a, 0.0), 1.0)),
+ (('ior', ('flt', a, b), ('flt', a, c)), ('flt', a, ('fmax', b, c))),
+ (('ior', ('fge', a, b), ('fge', a, c)), ('fge', a, ('fmin', b, c))),
+ (('slt', a, b), ('b2f', ('flt', a, b)), 'options->lower_scmp'),
+ (('sge', a, b), ('b2f', ('fge', a, b)), 'options->lower_scmp'),
+ (('seq', a, b), ('b2f', ('feq', a, b)), 'options->lower_scmp'),
+ (('sne', a, b), ('b2f', ('fne', a, b)), 'options->lower_scmp'),
+ # Emulating booleans
+ (('fmul', ('b2f', a), ('b2f', b)), ('b2f', ('iand', a, b))),
+ (('fsat', ('fadd', ('b2f', a), ('b2f', b))), ('b2f', ('ior', a, b))),
+ (('iand', 'a@bool', 1.0), ('b2f', a)),
+ (('flt', ('fneg', ('b2f', a)), 0), a), # Generated by TGSI KILL_IF.
+ (('flt', ('fsub', 0.0, ('b2f', a)), 0), a), # Generated by TGSI KILL_IF.
# Comparison with the same args. Note that these are not done for
# the float versions because NaN always returns false on float
# inequalities.
@@ -122,7 +133,7 @@ optimizations = [
(('ishr', 0, a), 0),
(('ishr', a, 0), a),
(('ushr', 0, a), 0),
- (('ushr', a, 0), 0),
+ (('ushr', a, 0), a),
# Exponential/logarithmic identities
(('fexp2', ('flog2', a)), a), # 2^lg2(a) = a
(('fexp', ('flog', a)), a), # e^ln(a) = a
@@ -134,6 +145,26 @@ optimizations = [
(('fpow', a, 1.0), a),
(('fpow', a, 2.0), ('fmul', a, a)),
(('fpow', 2.0, a), ('fexp2', a)),
+ (('fsqrt', ('fexp2', a)), ('fexp2', ('fmul', 0.5, a))),
+ (('fsqrt', ('fexp', a)), ('fexp', ('fmul', 0.5, a))),
+ (('frcp', ('fexp2', a)), ('fexp2', ('fneg', a))),
+ (('frcp', ('fexp', a)), ('fexp', ('fneg', a))),
+ (('frsq', ('fexp2', a)), ('fexp2', ('fmul', -0.5, a))),
+ (('frsq', ('fexp', a)), ('fexp', ('fmul', -0.5, a))),
+ (('flog2', ('fsqrt', a)), ('fmul', 0.5, ('flog2', a))),
+ (('flog', ('fsqrt', a)), ('fmul', 0.5, ('flog', a))),
+ (('flog2', ('frcp', a)), ('fneg', ('flog2', a))),
+ (('flog', ('frcp', a)), ('fneg', ('flog', a))),
+ (('flog2', ('frsq', a)), ('fmul', -0.5, ('flog2', a))),
+ (('flog', ('frsq', a)), ('fmul', -0.5, ('flog', a))),
+ (('flog2', ('fpow', a, b)), ('fmul', b, ('flog2', a))),
+ (('flog', ('fpow', a, b)), ('fmul', b, ('flog', a))),
+ (('fadd', ('flog2', a), ('flog2', b)), ('flog2', ('fmul', a, b))),
+ (('fadd', ('flog', a), ('flog', b)), ('flog', ('fmul', a, b))),
+ (('fadd', ('flog2', a), ('fneg', ('flog2', b))), ('flog2', ('fdiv', a, b))),
+ (('fadd', ('flog', a), ('fneg', ('flog', b))), ('flog', ('fdiv', a, b))),
+ (('fmul', ('fexp2', a), ('fexp2', b)), ('fexp2', ('fadd', a, b))),
+ (('fmul', ('fexp', a), ('fexp', b)), ('fexp', ('fadd', a, b))),
# Division and reciprocal
(('fdiv', 1.0, a), ('frcp', a)),
(('frcp', ('frcp', a)), a),
@@ -154,18 +185,21 @@ optimizations = [
(('bcsel', a, b, b), b),
(('fcsel', a, b, b), b),
+ # Conversions
+ (('f2i', ('ftrunc', a)), ('f2i', a)),
+ (('f2u', ('ftrunc', a)), ('f2u', a)),
+
# Subtracts
(('fsub', a, ('fsub', 0.0, b)), ('fadd', a, b)),
(('isub', a, ('isub', 0, b)), ('iadd', a, b)),
+ (('fsub', a, b), ('fadd', a, ('fneg', b)), 'options->lower_sub'),
+ (('isub', a, b), ('iadd', a, ('ineg', b)), 'options->lower_sub'),
(('fneg', a), ('fsub', 0.0, a), 'options->lower_negate'),
(('ineg', a), ('isub', 0, a), 'options->lower_negate'),
(('fadd', a, ('fsub', 0.0, b)), ('fsub', a, b)),
(('iadd', a, ('isub', 0, b)), ('isub', a, b)),
(('fabs', ('fsub', 0.0, a)), ('fabs', a)),
(('iabs', ('isub', 0, a)), ('iabs', a)),
-
-# This one may not be exact
- (('feq', ('fadd', a, b), 0.0), ('feq', a, ('fneg', b))),
]
# Add optimizations to handle the case where the result of a ternary is
@@ -189,4 +223,17 @@ for op in ['flt', 'fge', 'feq', 'fne',
('bcsel', 'a', (op, 'd', 'b'), (op, 'd', 'c'))),
]
+# This section contains "late" optimizations that should be run after the
+# regular optimizations have finished. Optimizations should go here if
+# they help code generation but do not necessarily produce code that is
+# more easily optimizable.
+late_optimizations = [
+ (('flt', ('fadd', a, b), 0.0), ('flt', a, ('fneg', b))),
+ (('fge', ('fadd', a, b), 0.0), ('fge', a, ('fneg', b))),
+ (('feq', ('fadd', a, b), 0.0), ('feq', a, ('fneg', b))),
+ (('fne', ('fadd', a, b), 0.0), ('fne', a, ('fneg', b))),
+]
+
print nir_algebraic.AlgebraicPass("nir_opt_algebraic", optimizations).render()
+print nir_algebraic.AlgebraicPass("nir_opt_algebraic_late",
+ late_optimizations).render()
diff --git a/mesalib/src/glsl/nir/nir_opt_cse.c b/mesalib/src/glsl/nir/nir_opt_cse.c
index 9b383202d..553906e12 100644
--- a/mesalib/src/glsl/nir/nir_opt_cse.c
+++ b/mesalib/src/glsl/nir/nir_opt_cse.c
@@ -37,20 +37,19 @@ struct cse_state {
};
static bool
-nir_alu_srcs_equal(nir_alu_src src1, nir_alu_src src2, uint8_t read_mask)
+nir_alu_srcs_equal(nir_alu_instr *alu1, nir_alu_instr *alu2, unsigned src1,
+ unsigned src2)
{
- if (src1.abs != src2.abs || src1.negate != src2.negate)
+ if (alu1->src[src1].abs != alu2->src[src2].abs ||
+ alu1->src[src1].negate != alu2->src[src2].negate)
return false;
- for (int i = 0; i < 4; ++i) {
- if (!(read_mask & (1 << i)))
- continue;
-
- if (src1.swizzle[i] != src2.swizzle[i])
+ for (unsigned i = 0; i < nir_ssa_alu_instr_src_components(alu1, src1); i++) {
+ if (alu1->src[src1].swizzle[i] != alu2->src[src2].swizzle[i])
return false;
}
- return nir_srcs_equal(src1.src, src2.src);
+ return nir_srcs_equal(alu1->src[src1].src, alu2->src[src2].src);
}
static bool
@@ -73,10 +72,17 @@ nir_instrs_equal(nir_instr *instr1, nir_instr *instr2)
if (alu1->dest.dest.ssa.num_components != alu2->dest.dest.ssa.num_components)
return false;
- for (unsigned i = 0; i < nir_op_infos[alu1->op].num_inputs; i++) {
- if (!nir_alu_srcs_equal(alu1->src[i], alu2->src[i],
- (1 << alu1->dest.dest.ssa.num_components) - 1))
- return false;
+ if (nir_op_infos[alu1->op].algebraic_properties & NIR_OP_IS_COMMUTATIVE) {
+ assert(nir_op_infos[alu1->op].num_inputs == 2);
+ return (nir_alu_srcs_equal(alu1, alu2, 0, 0) &&
+ nir_alu_srcs_equal(alu1, alu2, 1, 1)) ||
+ (nir_alu_srcs_equal(alu1, alu2, 0, 1) &&
+ nir_alu_srcs_equal(alu1, alu2, 1, 0));
+ } else {
+ for (unsigned i = 0; i < nir_op_infos[alu1->op].num_inputs; i++) {
+ if (!nir_alu_srcs_equal(alu1, alu2, i, i))
+ return false;
+ }
}
return true;
}
@@ -154,12 +160,14 @@ nir_instrs_equal(nir_instr *instr1, nir_instr *instr2)
static bool
src_is_ssa(nir_src *src, void *data)
{
+ (void) data;
return src->is_ssa;
}
static bool
dest_is_ssa(nir_dest *dest, void *data)
{
+ (void) data;
return dest->is_ssa;
}
diff --git a/mesalib/src/glsl/nir/nir_opt_peephole_ffma.c b/mesalib/src/glsl/nir/nir_opt_peephole_ffma.c
new file mode 100644
index 000000000..9d5646fe6
--- /dev/null
+++ b/mesalib/src/glsl/nir/nir_opt_peephole_ffma.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Jason Ekstrand (jason@jlekstrand.net)
+ *
+ */
+
+#include "nir.h"
+
+/*
+ * Implements a small peephole optimization that looks for a multiply that
+ * is only ever used in an add and replaces both with an fma.
+ */
+
+struct peephole_ffma_state {
+ void *mem_ctx;
+ nir_function_impl *impl;
+ bool progress;
+};
+
+static inline bool
+are_all_uses_fadd(nir_ssa_def *def)
+{
+ if (def->if_uses->entries > 0)
+ return false;
+
+ struct set_entry *use_iter;
+ set_foreach(def->uses, use_iter) {
+ nir_instr *use_instr = (nir_instr *)use_iter->key;
+
+ if (use_instr->type != nir_instr_type_alu)
+ return false;
+
+ nir_alu_instr *use_alu = nir_instr_as_alu(use_instr);
+ switch (use_alu->op) {
+ case nir_op_fadd:
+ break; /* This one's ok */
+
+ case nir_op_imov:
+ case nir_op_fmov:
+ case nir_op_fneg:
+ case nir_op_fabs:
+ assert(use_alu->dest.dest.is_ssa);
+ if (!are_all_uses_fadd(&use_alu->dest.dest.ssa))
+ return false;
+ break;
+
+ default:
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static nir_alu_instr *
+get_mul_for_src(nir_alu_src *src, uint8_t swizzle[4], bool *negate, bool *abs)
+{
+ assert(src->src.is_ssa && !src->abs && !src->negate);
+
+ nir_instr *instr = src->src.ssa->parent_instr;
+ if (instr->type != nir_instr_type_alu)
+ return NULL;
+
+ nir_alu_instr *alu = nir_instr_as_alu(instr);
+ switch (alu->op) {
+ case nir_op_imov:
+ case nir_op_fmov:
+ alu = get_mul_for_src(&alu->src[0], swizzle, negate, abs);
+ break;
+
+ case nir_op_fneg:
+ alu = get_mul_for_src(&alu->src[0], swizzle, negate, abs);
+ *negate = !*negate;
+ break;
+
+ case nir_op_fabs:
+ alu = get_mul_for_src(&alu->src[0], swizzle, negate, abs);
+ *negate = false;
+ *abs = true;
+ break;
+
+ case nir_op_fmul:
+ /* Only absorb a fmul into a ffma if the fmul is is only used in fadd
+ * operations. This prevents us from being too aggressive with our
+ * fusing which can actually lead to more instructions.
+ */
+ if (!are_all_uses_fadd(&alu->dest.dest.ssa))
+ return NULL;
+ break;
+
+ default:
+ return NULL;
+ }
+
+ if (!alu)
+ return NULL;
+
+ for (unsigned i = 0; i < 4; i++) {
+ if (!(alu->dest.write_mask & (1 << i)))
+ break;
+
+ swizzle[i] = swizzle[src->swizzle[i]];
+ }
+
+ return alu;
+}
+
+static bool
+nir_opt_peephole_ffma_block(nir_block *block, void *void_state)
+{
+ struct peephole_ffma_state *state = void_state;
+
+ nir_foreach_instr_safe(block, instr) {
+ if (instr->type != nir_instr_type_alu)
+ continue;
+
+ nir_alu_instr *add = nir_instr_as_alu(instr);
+ if (add->op != nir_op_fadd)
+ continue;
+
+ /* TODO: Maybe bail if this expression is considered "precise"? */
+
+ assert(add->src[0].src.is_ssa && add->src[1].src.is_ssa);
+
+ /* This, is the case a + a. We would rather handle this with an
+ * algebraic reduction than fuse it. Also, we want to only fuse
+ * things where the multiply is used only once and, in this case,
+ * it would be used twice by the same instruction.
+ */
+ if (add->src[0].src.ssa == add->src[1].src.ssa)
+ continue;
+
+ nir_alu_instr *mul;
+ uint8_t add_mul_src, swizzle[4];
+ bool negate, abs;
+ for (add_mul_src = 0; add_mul_src < 2; add_mul_src++) {
+ for (unsigned i = 0; i < 4; i++)
+ swizzle[i] = i;
+
+ negate = false;
+ abs = false;
+
+ mul = get_mul_for_src(&add->src[add_mul_src], swizzle, &negate, &abs);
+
+ if (mul != NULL)
+ break;
+ }
+
+ if (mul == NULL)
+ continue;
+
+ nir_ssa_def *mul_src[2];
+ mul_src[0] = mul->src[0].src.ssa;
+ mul_src[1] = mul->src[1].src.ssa;
+
+ if (abs) {
+ for (unsigned i = 0; i < 2; i++) {
+ nir_alu_instr *abs = nir_alu_instr_create(state->mem_ctx,
+ nir_op_fabs);
+ abs->src[0].src = nir_src_for_ssa(mul_src[i]);
+ nir_ssa_dest_init(&abs->instr, &abs->dest.dest,
+ mul_src[i]->num_components, NULL);
+ abs->dest.write_mask = (1 << mul_src[i]->num_components) - 1;
+ nir_instr_insert_before(&add->instr, &abs->instr);
+ mul_src[i] = &abs->dest.dest.ssa;
+ }
+ }
+
+ if (negate) {
+ nir_alu_instr *neg = nir_alu_instr_create(state->mem_ctx,
+ nir_op_fneg);
+ neg->src[0].src = nir_src_for_ssa(mul_src[0]);
+ nir_ssa_dest_init(&neg->instr, &neg->dest.dest,
+ mul_src[0]->num_components, NULL);
+ neg->dest.write_mask = (1 << mul_src[0]->num_components) - 1;
+ nir_instr_insert_before(&add->instr, &neg->instr);
+ mul_src[0] = &neg->dest.dest.ssa;
+ }
+
+ nir_alu_instr *ffma = nir_alu_instr_create(state->mem_ctx, nir_op_ffma);
+ ffma->dest.saturate = add->dest.saturate;
+ ffma->dest.write_mask = add->dest.write_mask;
+
+ for (unsigned i = 0; i < 2; i++) {
+ ffma->src[i].src = nir_src_for_ssa(mul_src[i]);
+ for (unsigned j = 0; j < add->dest.dest.ssa.num_components; j++)
+ ffma->src[i].swizzle[j] = mul->src[i].swizzle[swizzle[j]];
+ }
+ nir_alu_src_copy(&ffma->src[2], &add->src[1 - add_mul_src],
+ state->mem_ctx);
+
+ assert(add->dest.dest.is_ssa);
+
+ nir_ssa_dest_init(&ffma->instr, &ffma->dest.dest,
+ add->dest.dest.ssa.num_components,
+ add->dest.dest.ssa.name);
+ nir_ssa_def_rewrite_uses(&add->dest.dest.ssa,
+ nir_src_for_ssa(&ffma->dest.dest.ssa),
+ state->mem_ctx);
+
+ nir_instr_insert_before(&add->instr, &ffma->instr);
+ assert(add->dest.dest.ssa.uses->entries == 0);
+ nir_instr_remove(&add->instr);
+
+ state->progress = true;
+ }
+
+ return true;
+}
+
+static bool
+nir_opt_peephole_ffma_impl(nir_function_impl *impl)
+{
+ struct peephole_ffma_state state;
+
+ state.mem_ctx = ralloc_parent(impl);
+ state.impl = impl;
+ state.progress = false;
+
+ nir_foreach_block(impl, nir_opt_peephole_ffma_block, &state);
+
+ if (state.progress)
+ nir_metadata_preserve(impl, nir_metadata_block_index |
+ nir_metadata_dominance);
+
+ return state.progress;
+}
+
+bool
+nir_opt_peephole_ffma(nir_shader *shader)
+{
+ bool progress = false;
+
+ nir_foreach_overload(shader, overload) {
+ if (overload->impl)
+ progress |= nir_opt_peephole_ffma_impl(overload->impl);
+ }
+
+ return progress;
+}
diff --git a/mesalib/src/glsl/nir/nir_opt_peephole_select.c b/mesalib/src/glsl/nir/nir_opt_peephole_select.c
index b89451b09..f400cfd66 100644
--- a/mesalib/src/glsl/nir/nir_opt_peephole_select.c
+++ b/mesalib/src/glsl/nir/nir_opt_peephole_select.c
@@ -84,7 +84,9 @@ block_check_for_allowed_instrs(nir_block *block)
case nir_instr_type_alu: {
/* It must be a move operation */
nir_alu_instr *mov = nir_instr_as_alu(instr);
- if (mov->op != nir_op_fmov && mov->op != nir_op_imov)
+ if (mov->op != nir_op_fmov && mov->op != nir_op_imov &&
+ mov->op != nir_op_fneg && mov->op != nir_op_ineg &&
+ mov->op != nir_op_fabs && mov->op != nir_op_iabs)
return false;
/* Can't handle saturate */
diff --git a/mesalib/src/glsl/nir/nir_print.c b/mesalib/src/glsl/nir/nir_print.c
index fa11a312e..fb8c9344c 100644
--- a/mesalib/src/glsl/nir/nir_print.c
+++ b/mesalib/src/glsl/nir/nir_print.c
@@ -137,25 +137,37 @@ print_dest(nir_dest *dest, FILE *fp)
}
static void
-print_alu_src(nir_alu_src *src, FILE *fp)
+print_alu_src(nir_alu_instr *instr, unsigned src, FILE *fp)
{
- if (src->negate)
+ if (instr->src[src].negate)
fprintf(fp, "-");
- if (src->abs)
+ if (instr->src[src].abs)
fprintf(fp, "abs(");
- print_src(&src->src, fp);
+ print_src(&instr->src[src].src, fp);
- if (src->swizzle[0] != 0 ||
- src->swizzle[1] != 1 ||
- src->swizzle[2] != 2 ||
- src->swizzle[3] != 3) {
+ bool print_swizzle = false;
+ for (unsigned i = 0; i < 4; i++) {
+ if (!nir_alu_instr_channel_used(instr, src, i))
+ continue;
+
+ if (instr->src[src].swizzle[i] != i) {
+ print_swizzle = true;
+ break;
+ }
+ }
+
+ if (print_swizzle) {
fprintf(fp, ".");
- for (unsigned i = 0; i < 4; i++)
- fprintf(fp, "%c", "xyzw"[src->swizzle[i]]);
+ for (unsigned i = 0; i < 4; i++) {
+ if (!nir_alu_instr_channel_used(instr, src, i))
+ continue;
+
+ fprintf(fp, "%c", "xyzw"[instr->src[src].swizzle[i]]);
+ }
}
- if (src->abs)
+ if (instr->src[src].abs)
fprintf(fp, ")");
}
@@ -189,7 +201,7 @@ print_alu_instr(nir_alu_instr *instr, FILE *fp)
if (i != 0)
fprintf(fp, ", ");
- print_alu_src(&instr->src[i], fp);
+ print_alu_src(instr, i, fp);
}
}
diff --git a/mesalib/src/glsl/nir/nir_remove_dead_variables.c b/mesalib/src/glsl/nir/nir_remove_dead_variables.c
index e7f8aeacb..4417e2a48 100644
--- a/mesalib/src/glsl/nir/nir_remove_dead_variables.c
+++ b/mesalib/src/glsl/nir/nir_remove_dead_variables.c
@@ -98,22 +98,14 @@ add_var_use_shader(nir_shader *shader, struct set *live)
}
static void
-remove_dead_local_vars(nir_function_impl *impl, struct set *live)
+remove_dead_vars(struct exec_list *var_list, struct set *live)
{
- foreach_list_typed_safe(nir_variable, var, node, &impl->locals) {
+ foreach_list_typed_safe(nir_variable, var, node, var_list) {
struct set_entry *entry = _mesa_set_search(live, var);
- if (entry == NULL)
- exec_node_remove(&var->node);
- }
-}
-
-static void
-remove_dead_global_vars(nir_shader *shader, struct set *live)
-{
- foreach_list_typed_safe(nir_variable, var, node, &shader->globals) {
- struct set_entry *entry = _mesa_set_search(live, var);
- if (entry == NULL)
+ if (entry == NULL) {
exec_node_remove(&var->node);
+ ralloc_free(var);
+ }
}
}
@@ -125,11 +117,11 @@ nir_remove_dead_variables(nir_shader *shader)
add_var_use_shader(shader, live);
- remove_dead_global_vars(shader, live);
+ remove_dead_vars(&shader->globals, live);
nir_foreach_overload(shader, overload) {
if (overload->impl)
- remove_dead_local_vars(overload->impl, live);
+ remove_dead_vars(&overload->impl->locals, live);
}
_mesa_set_destroy(live, NULL);
diff --git a/mesalib/src/glsl/nir/nir_search.c b/mesalib/src/glsl/nir/nir_search.c
index 73a802be7..5ba016085 100644
--- a/mesalib/src/glsl/nir/nir_search.c
+++ b/mesalib/src/glsl/nir/nir_search.c
@@ -218,8 +218,8 @@ match_expression(const nir_search_expression *expr, nir_alu_instr *instr,
if (matched)
return true;
- if (nir_op_infos[instr->op].num_inputs == 2 &&
- (nir_op_infos[instr->op].algebraic_properties & NIR_OP_IS_COMMUTATIVE)) {
+ if (nir_op_infos[instr->op].algebraic_properties & NIR_OP_IS_COMMUTATIVE) {
+ assert(nir_op_infos[instr->op].num_inputs == 2);
if (!match_value(expr->srcs[0], instr, 1, num_components,
swizzle, state))
return false;
diff --git a/mesalib/src/glsl/nir/nir_split_var_copies.c b/mesalib/src/glsl/nir/nir_split_var_copies.c
index 4d663b51b..fc72c078c 100644
--- a/mesalib/src/glsl/nir/nir_split_var_copies.c
+++ b/mesalib/src/glsl/nir/nir_split_var_copies.c
@@ -188,8 +188,8 @@ split_var_copy_instr(nir_intrinsic_instr *old_copy,
* belongs to the copy instruction and b) the deref chains may
* have some of the same links due to the way we constructed them
*/
- nir_deref *src = nir_copy_deref(state->mem_ctx, src_head);
- nir_deref *dest = nir_copy_deref(state->mem_ctx, dest_head);
+ nir_deref *src = nir_copy_deref(new_copy, src_head);
+ nir_deref *dest = nir_copy_deref(new_copy, dest_head);
new_copy->variables[0] = nir_deref_as_var(dest);
new_copy->variables[1] = nir_deref_as_var(src);
diff --git a/mesalib/src/glsl/nir/nir_sweep.c b/mesalib/src/glsl/nir/nir_sweep.c
new file mode 100644
index 000000000..d3549756a
--- /dev/null
+++ b/mesalib/src/glsl/nir/nir_sweep.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright © 2015 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "nir.h"
+
+/**
+ * \file nir_sweep.c
+ *
+ * The nir_sweep() pass performs a mark and sweep pass over a nir_shader's associated
+ * memory - anything still connected to the program will be kept, and any dead memory
+ * we dropped on the floor will be freed.
+ *
+ * The expectation is that drivers should call this when finished compiling the shader
+ * (after any optimization, lowering, and so on). However, it's also fine to call it
+ * earlier, and even many times, trading CPU cycles for memory savings.
+ */
+
+#define steal_list(mem_ctx, type, list) \
+ foreach_list_typed(type, obj, node, list) { ralloc_steal(mem_ctx, obj); }
+
+static void sweep_cf_node(nir_shader *nir, nir_cf_node *cf_node);
+
+static bool
+sweep_src_indirect(nir_src *src, void *nir)
+{
+ if (!src->is_ssa && src->reg.indirect)
+ ralloc_steal(nir, src->reg.indirect);
+
+ return true;
+}
+
+static bool
+sweep_dest_indirect(nir_dest *dest, void *nir)
+{
+ if (!dest->is_ssa && dest->reg.indirect)
+ ralloc_steal(nir, dest->reg.indirect);
+
+ return true;
+}
+
+static void
+sweep_block(nir_shader *nir, nir_block *block)
+{
+ ralloc_steal(nir, block);
+
+ nir_foreach_instr(block, instr) {
+ ralloc_steal(nir, instr);
+
+ nir_foreach_src(instr, sweep_src_indirect, nir);
+ nir_foreach_dest(instr, sweep_dest_indirect, nir);
+ }
+}
+
+static void
+sweep_if(nir_shader *nir, nir_if *iff)
+{
+ ralloc_steal(nir, iff);
+
+ foreach_list_typed(nir_cf_node, cf_node, node, &iff->then_list) {
+ sweep_cf_node(nir, cf_node);
+ }
+
+ foreach_list_typed(nir_cf_node, cf_node, node, &iff->else_list) {
+ sweep_cf_node(nir, cf_node);
+ }
+}
+
+static void
+sweep_loop(nir_shader *nir, nir_loop *loop)
+{
+ ralloc_steal(nir, loop);
+
+ foreach_list_typed(nir_cf_node, cf_node, node, &loop->body) {
+ sweep_cf_node(nir, cf_node);
+ }
+}
+
+static void
+sweep_cf_node(nir_shader *nir, nir_cf_node *cf_node)
+{
+ switch (cf_node->type) {
+ case nir_cf_node_block:
+ sweep_block(nir, nir_cf_node_as_block(cf_node));
+ break;
+ case nir_cf_node_if:
+ sweep_if(nir, nir_cf_node_as_if(cf_node));
+ break;
+ case nir_cf_node_loop:
+ sweep_loop(nir, nir_cf_node_as_loop(cf_node));
+ break;
+ default:
+ unreachable("Invalid CF node type");
+ }
+}
+
+static void
+sweep_impl(nir_shader *nir, nir_function_impl *impl)
+{
+ ralloc_steal(nir, impl);
+
+ ralloc_steal(nir, impl->params);
+ ralloc_steal(nir, impl->return_var);
+ steal_list(nir, nir_variable, &impl->locals);
+ steal_list(nir, nir_register, &impl->registers);
+
+ foreach_list_typed(nir_cf_node, cf_node, node, &impl->body) {
+ sweep_cf_node(nir, cf_node);
+ }
+
+ sweep_block(nir, impl->end_block);
+
+ /* Wipe out all the metadata, if any. */
+ nir_metadata_preserve(impl, nir_metadata_none);
+}
+
+static void
+sweep_function(nir_shader *nir, nir_function *f)
+{
+ ralloc_steal(nir, f);
+
+ foreach_list_typed(nir_function_overload, overload, node, &f->overload_list) {
+ ralloc_steal(nir, overload);
+ ralloc_steal(nir, overload->params);
+ if (overload->impl)
+ sweep_impl(nir, overload->impl);
+ }
+}
+
+void
+nir_sweep(nir_shader *nir)
+{
+ void *rubbish = ralloc_context(NULL);
+
+ /* First, move ownership of all the memory to a temporary context; assume dead. */
+ ralloc_adopt(rubbish, nir);
+
+ /* Variables and registers are not dead. Steal them back. */
+ steal_list(nir, nir_variable, &nir->uniforms);
+ steal_list(nir, nir_variable, &nir->inputs);
+ steal_list(nir, nir_variable, &nir->outputs);
+ steal_list(nir, nir_variable, &nir->globals);
+ steal_list(nir, nir_variable, &nir->system_values);
+ steal_list(nir, nir_register, &nir->registers);
+
+ /* Recurse into functions, stealing their contents back. */
+ foreach_list_typed(nir_function, func, node, &nir->functions) {
+ sweep_function(nir, func);
+ }
+
+ /* Free everything we didn't steal back. */
+ ralloc_free(rubbish);
+}
diff --git a/mesalib/src/glsl/nir/nir_to_ssa.c b/mesalib/src/glsl/nir/nir_to_ssa.c
index 47cf45393..53ff54766 100644
--- a/mesalib/src/glsl/nir/nir_to_ssa.c
+++ b/mesalib/src/glsl/nir/nir_to_ssa.c
@@ -47,7 +47,7 @@ insert_trivial_phi(nir_register *reg, nir_block *block, void *mem_ctx)
set_foreach(block->predecessors, entry) {
nir_block *pred = (nir_block *) entry->key;
- nir_phi_src *src = ralloc(mem_ctx, nir_phi_src);
+ nir_phi_src *src = ralloc(instr, nir_phi_src);
src->pred = pred;
src->src.is_ssa = false;
src->src.reg.base_offset = 0;
diff --git a/mesalib/src/glsl/nir/nir_types.cpp b/mesalib/src/glsl/nir/nir_types.cpp
index a13c3e12a..f0d0b46d2 100644
--- a/mesalib/src/glsl/nir/nir_types.cpp
+++ b/mesalib/src/glsl/nir/nir_types.cpp
@@ -143,6 +143,12 @@ glsl_void_type(void)
}
const glsl_type *
+glsl_float_type(void)
+{
+ return glsl_type::float_type;
+}
+
+const glsl_type *
glsl_vec4_type(void)
{
return glsl_type::vec4_type;
diff --git a/mesalib/src/glsl/nir/nir_types.h b/mesalib/src/glsl/nir/nir_types.h
index 494051a67..276d4ad62 100644
--- a/mesalib/src/glsl/nir/nir_types.h
+++ b/mesalib/src/glsl/nir/nir_types.h
@@ -69,6 +69,7 @@ bool glsl_type_is_scalar(const struct glsl_type *type);
bool glsl_type_is_matrix(const struct glsl_type *type);
const struct glsl_type *glsl_void_type(void);
+const struct glsl_type *glsl_float_type(void);
const struct glsl_type *glsl_vec4_type(void);
const struct glsl_type *glsl_array_type(const struct glsl_type *base,
unsigned elements);
diff --git a/mesalib/src/glsl/nir/nir_validate.c b/mesalib/src/glsl/nir/nir_validate.c
index f247ae069..a7aa79837 100644
--- a/mesalib/src/glsl/nir/nir_validate.c
+++ b/mesalib/src/glsl/nir/nir_validate.c
@@ -295,6 +295,8 @@ validate_alu_instr(nir_alu_instr *instr, validate_state *state)
static void
validate_deref_chain(nir_deref *deref, validate_state *state)
{
+ assert(deref->child == NULL || ralloc_parent(deref->child) == deref);
+
nir_deref *parent = NULL;
while (deref != NULL) {
switch (deref->deref_type) {
@@ -336,9 +338,10 @@ validate_var_use(nir_variable *var, validate_state *state)
}
static void
-validate_deref_var(nir_deref_var *deref, validate_state *state)
+validate_deref_var(void *parent_mem_ctx, nir_deref_var *deref, validate_state *state)
{
assert(deref != NULL);
+ assert(ralloc_parent(deref) == parent_mem_ctx);
assert(deref->deref.type == deref->var->type);
validate_var_use(deref->var, state);
@@ -386,7 +389,7 @@ validate_intrinsic_instr(nir_intrinsic_instr *instr, validate_state *state)
unsigned num_vars = nir_intrinsic_infos[instr->intrinsic].num_variables;
for (unsigned i = 0; i < num_vars; i++) {
- validate_deref_var(instr->variables[i], state);
+ validate_deref_var(instr, instr->variables[i], state);
}
switch (instr->intrinsic) {
@@ -423,7 +426,7 @@ validate_tex_instr(nir_tex_instr *instr, validate_state *state)
}
if (instr->sampler != NULL)
- validate_deref_var(instr->sampler, state);
+ validate_deref_var(instr, instr->sampler, state);
}
static void
@@ -438,10 +441,10 @@ validate_call_instr(nir_call_instr *instr, validate_state *state)
for (unsigned i = 0; i < instr->num_params; i++) {
assert(instr->callee->params[i].type == instr->params[i]->deref.type);
- validate_deref_var(instr->params[i], state);
+ validate_deref_var(instr, instr->params[i], state);
}
- validate_deref_var(instr->return_deref, state);
+ validate_deref_var(instr, instr->return_deref, state);
}
static void
@@ -680,8 +683,7 @@ validate_cf_node(nir_cf_node *node, validate_state *state)
break;
default:
- assert(!"Invalid ALU instruction type");
- break;
+ unreachable("Invalid CF node type");
}
}
diff --git a/mesalib/src/glsl/opt_algebraic.cpp b/mesalib/src/glsl/opt_algebraic.cpp
index 69c03ea8b..3d2f2ca0b 100644
--- a/mesalib/src/glsl/opt_algebraic.cpp
+++ b/mesalib/src/glsl/opt_algebraic.cpp
@@ -290,6 +290,20 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
ir_expression *op_expr[4] = {NULL, NULL, NULL, NULL};
unsigned int i;
+ if (ir->operation == ir_binop_mul &&
+ ir->operands[0]->type->is_matrix() &&
+ ir->operands[1]->type->is_vector()) {
+ ir_expression *matrix_mul = ir->operands[0]->as_expression();
+
+ if (matrix_mul && matrix_mul->operation == ir_binop_mul &&
+ matrix_mul->operands[0]->type->is_matrix() &&
+ matrix_mul->operands[1]->type->is_matrix()) {
+
+ return mul(matrix_mul->operands[0],
+ mul(matrix_mul->operands[1], ir->operands[1]));
+ }
+ }
+
assert(ir->get_num_operands() <= 4);
for (i = 0; i < ir->get_num_operands(); i++) {
if (ir->operands[i]->type->is_matrix())
@@ -421,6 +435,18 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
break;
}
+ case ir_unop_saturate:
+ if (op_expr[0] && op_expr[0]->operation == ir_binop_add) {
+ ir_expression *b2f_0 = op_expr[0]->operands[0]->as_expression();
+ ir_expression *b2f_1 = op_expr[0]->operands[1]->as_expression();
+
+ if (b2f_0 && b2f_0->operation == ir_unop_b2f &&
+ b2f_1 && b2f_1->operation == ir_unop_b2f) {
+ return b2f(logic_or(b2f_0->operands[0], b2f_1->operands[0]));
+ }
+ }
+ break;
+
case ir_binop_add:
if (is_vec_zero(op_const[0]))
return ir->operands[1];
@@ -518,6 +544,10 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
if (is_vec_negative_one(op_const[1]))
return neg(ir->operands[0]);
+ if (op_expr[0] && op_expr[0]->operation == ir_unop_b2f &&
+ op_expr[1] && op_expr[1]->operation == ir_unop_b2f) {
+ return b2f(logic_and(op_expr[0]->operands[0], op_expr[1]->operands[0]));
+ }
/* Reassociate multiplication of constants so that we can do
* constant folding.
@@ -544,6 +574,8 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
continue;
ir_expression *add_expr = floor_expr->operands[0]->as_expression();
+ if (!add_expr)
+ continue;
for (int j = 0; j < 2; j++) {
ir_expression *abs_expr = add_expr->operands[j]->as_expression();
diff --git a/mesalib/src/glsl/opt_cse.cpp b/mesalib/src/glsl/opt_cse.cpp
index b0b67f496..4b8e9a07b 100644
--- a/mesalib/src/glsl/opt_cse.cpp
+++ b/mesalib/src/glsl/opt_cse.cpp
@@ -63,6 +63,17 @@ public:
var = NULL;
}
+ void init(ir_instruction *base_ir, ir_rvalue **val)
+ {
+ this->val = val;
+ this->base_ir = base_ir;
+ this->var = NULL;
+
+ assert(val);
+ assert(*val);
+ assert(base_ir);
+ }
+
/**
* The pointer to the expression that we might be able to reuse
*
@@ -116,6 +127,18 @@ private:
ir_rvalue *try_cse(ir_rvalue *rvalue);
void add_to_ae(ir_rvalue **rvalue);
+ /**
+ * Move all nodes from the ae list to the free list
+ */
+ void empty_ae_list();
+
+ /**
+ * Get and initialize a new ae_entry
+ *
+ * This will either come from the free list or be freshly allocated.
+ */
+ ae_entry *get_ae_entry(ir_rvalue **rvalue);
+
/** List of ae_entry: The available expressions to reuse */
exec_list *ae;
@@ -126,6 +149,11 @@ private:
* right.
*/
exec_list *validate_instructions;
+
+ /**
+ * List of available-for-use ae_entry objects.
+ */
+ exec_list free_ae_entries;
};
/**
@@ -322,6 +350,25 @@ cse_visitor::try_cse(ir_rvalue *rvalue)
return NULL;
}
+void
+cse_visitor::empty_ae_list()
+{
+ free_ae_entries.append_list(ae);
+}
+
+ae_entry *
+cse_visitor::get_ae_entry(ir_rvalue **rvalue)
+{
+ ae_entry *entry = (ae_entry *) free_ae_entries.pop_head();
+ if (entry) {
+ entry->init(base_ir, rvalue);
+ } else {
+ entry = new(mem_ctx) ae_entry(base_ir, rvalue);
+ }
+
+ return entry;
+}
+
/** Add the rvalue to the list of available expressions for CSE. */
void
cse_visitor::add_to_ae(ir_rvalue **rvalue)
@@ -332,7 +379,7 @@ cse_visitor::add_to_ae(ir_rvalue **rvalue)
printf("\n");
}
- ae->push_tail(new(mem_ctx) ae_entry(base_ir, rvalue));
+ ae->push_tail(get_ae_entry(rvalue));
if (debug)
dump_ae(ae);
@@ -370,33 +417,33 @@ cse_visitor::visit_enter(ir_if *ir)
{
handle_rvalue(&ir->condition);
- ae->make_empty();
+ empty_ae_list();
visit_list_elements(this, &ir->then_instructions);
- ae->make_empty();
+ empty_ae_list();
visit_list_elements(this, &ir->else_instructions);
- ae->make_empty();
+ empty_ae_list();
return visit_continue_with_parent;
}
ir_visitor_status
cse_visitor::visit_enter(ir_function_signature *ir)
{
- ae->make_empty();
+ empty_ae_list();
visit_list_elements(this, &ir->body);
- ae->make_empty();
+ empty_ae_list();
return visit_continue_with_parent;
}
ir_visitor_status
cse_visitor::visit_enter(ir_loop *ir)
{
- ae->make_empty();
+ empty_ae_list();
visit_list_elements(this, &ir->body_instructions);
- ae->make_empty();
+ empty_ae_list();
return visit_continue_with_parent;
}
diff --git a/mesalib/src/glsl/s_expression.cpp b/mesalib/src/glsl/s_expression.cpp
index 7eaa491e2..f82e155a6 100644
--- a/mesalib/src/glsl/s_expression.cpp
+++ b/mesalib/src/glsl/s_expression.cpp
@@ -23,8 +23,8 @@
*/
#include <assert.h>
-#include <limits>
#include <stdio.h>
+#include <math.h>
#include "s_expression.h"
s_symbol::s_symbol(const char *str, size_t n)
@@ -70,7 +70,7 @@ read_atom(void *ctx, const char *&src, char *&symbol_buffer)
// requires strtof to parse '+INF' as +Infinity, but we still support some
// non-C99-compliant compilers (e.g. MSVC).
if (n == 4 && strncmp(src, "+INF", 4) == 0) {
- expr = new(ctx) s_float(std::numeric_limits<float>::infinity());
+ expr = new(ctx) s_float(INFINITY);
} else {
// Check if the atom is a number.
char *float_end = NULL;
diff --git a/mesalib/src/glsl/shader_enums.h b/mesalib/src/glsl/shader_enums.h
new file mode 100644
index 000000000..79e0f6b5f
--- /dev/null
+++ b/mesalib/src/glsl/shader_enums.h
@@ -0,0 +1,187 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SHADER_ENUMS_H
+#define SHADER_ENUMS_H
+
+/**
+ * Shader stages. Note that these will become 5 with tessellation.
+ *
+ * The order must match how shaders are ordered in the pipeline.
+ * The GLSL linker assumes that if i<j, then the j-th shader is
+ * executed later than the i-th shader.
+ */
+typedef enum
+{
+ MESA_SHADER_VERTEX = 0,
+ MESA_SHADER_GEOMETRY = 1,
+ MESA_SHADER_FRAGMENT = 2,
+ MESA_SHADER_COMPUTE = 3,
+} gl_shader_stage;
+
+#define MESA_SHADER_STAGES (MESA_SHADER_COMPUTE + 1)
+
+/**
+ * Bitflags for system values.
+ */
+#define SYSTEM_BIT_SAMPLE_ID ((uint64_t)1 << SYSTEM_VALUE_SAMPLE_ID)
+#define SYSTEM_BIT_SAMPLE_POS ((uint64_t)1 << SYSTEM_VALUE_SAMPLE_POS)
+#define SYSTEM_BIT_SAMPLE_MASK_IN ((uint64_t)1 << SYSTEM_VALUE_SAMPLE_MASK_IN)
+/**
+ * If the gl_register_file is PROGRAM_SYSTEM_VALUE, the register index will be
+ * one of these values. If a NIR variable's mode is nir_var_system_value, it
+ * will be one of these values.
+ */
+typedef enum
+{
+ /**
+ * \name Vertex shader system values
+ */
+ /*@{*/
+ /**
+ * OpenGL-style vertex ID.
+ *
+ * Section 2.11.7 (Shader Execution), subsection Shader Inputs, of the
+ * OpenGL 3.3 core profile spec says:
+ *
+ * "gl_VertexID holds the integer index i implicitly passed by
+ * DrawArrays or one of the other drawing commands defined in section
+ * 2.8.3."
+ *
+ * Section 2.8.3 (Drawing Commands) of the same spec says:
+ *
+ * "The commands....are equivalent to the commands with the same base
+ * name (without the BaseVertex suffix), except that the ith element
+ * transferred by the corresponding draw call will be taken from
+ * element indices[i] + basevertex of each enabled array."
+ *
+ * Additionally, the overview in the GL_ARB_shader_draw_parameters spec
+ * says:
+ *
+ * "In unextended GL, vertex shaders have inputs named gl_VertexID and
+ * gl_InstanceID, which contain, respectively the index of the vertex
+ * and instance. The value of gl_VertexID is the implicitly passed
+ * index of the vertex being processed, which includes the value of
+ * baseVertex, for those commands that accept it."
+ *
+ * gl_VertexID gets basevertex added in. This differs from DirectX where
+ * SV_VertexID does \b not get basevertex added in.
+ *
+ * \note
+ * If all system values are available, \c SYSTEM_VALUE_VERTEX_ID will be
+ * equal to \c SYSTEM_VALUE_VERTEX_ID_ZERO_BASE plus
+ * \c SYSTEM_VALUE_BASE_VERTEX.
+ *
+ * \sa SYSTEM_VALUE_VERTEX_ID_ZERO_BASE, SYSTEM_VALUE_BASE_VERTEX
+ */
+ SYSTEM_VALUE_VERTEX_ID,
+
+ /**
+ * Instanced ID as supplied to gl_InstanceID
+ *
+ * Values assigned to gl_InstanceID always begin with zero, regardless of
+ * the value of baseinstance.
+ *
+ * Section 11.1.3.9 (Shader Inputs) of the OpenGL 4.4 core profile spec
+ * says:
+ *
+ * "gl_InstanceID holds the integer instance number of the current
+ * primitive in an instanced draw call (see section 10.5)."
+ *
+ * Through a big chain of pseudocode, section 10.5 describes that
+ * baseinstance is not counted by gl_InstanceID. In that section, notice
+ *
+ * "If an enabled vertex attribute array is instanced (it has a
+ * non-zero divisor as specified by VertexAttribDivisor), the element
+ * index that is transferred to the GL, for all vertices, is given by
+ *
+ * floor(instance/divisor) + baseinstance
+ *
+ * If an array corresponding to an attribute required by a vertex
+ * shader is not enabled, then the corresponding element is taken from
+ * the current attribute state (see section 10.2)."
+ *
+ * Note that baseinstance is \b not included in the value of instance.
+ */
+ SYSTEM_VALUE_INSTANCE_ID,
+
+ /**
+ * DirectX-style vertex ID.
+ *
+ * Unlike \c SYSTEM_VALUE_VERTEX_ID, this system value does \b not include
+ * the value of basevertex.
+ *
+ * \sa SYSTEM_VALUE_VERTEX_ID, SYSTEM_VALUE_BASE_VERTEX
+ */
+ SYSTEM_VALUE_VERTEX_ID_ZERO_BASE,
+
+ /**
+ * Value of \c basevertex passed to \c glDrawElementsBaseVertex and similar
+ * functions.
+ *
+ * \sa SYSTEM_VALUE_VERTEX_ID, SYSTEM_VALUE_VERTEX_ID_ZERO_BASE
+ */
+ SYSTEM_VALUE_BASE_VERTEX,
+ /*@}*/
+
+ /**
+ * \name Geometry shader system values
+ */
+ /*@{*/
+ SYSTEM_VALUE_INVOCATION_ID,
+ /*@}*/
+
+ /**
+ * \name Fragment shader system values
+ */
+ /*@{*/
+ SYSTEM_VALUE_FRONT_FACE, /**< (not done yet) */
+ SYSTEM_VALUE_SAMPLE_ID,
+ SYSTEM_VALUE_SAMPLE_POS,
+ SYSTEM_VALUE_SAMPLE_MASK_IN,
+ /*@}*/
+
+ SYSTEM_VALUE_MAX /**< Number of values */
+} gl_system_value;
+
+
+/**
+ * The possible interpolation qualifiers that can be applied to a fragment
+ * shader input in GLSL.
+ *
+ * Note: INTERP_QUALIFIER_NONE must be 0 so that memsetting the
+ * gl_fragment_program data structure to 0 causes the default behavior.
+ */
+enum glsl_interp_qualifier
+{
+ INTERP_QUALIFIER_NONE = 0,
+ INTERP_QUALIFIER_SMOOTH,
+ INTERP_QUALIFIER_FLAT,
+ INTERP_QUALIFIER_NOPERSPECTIVE,
+ INTERP_QUALIFIER_COUNT /**< Number of interpolation qualifiers */
+};
+
+
+#endif /* SHADER_ENUMS_H */
diff --git a/mesalib/src/loader/Makefile.am b/mesalib/src/loader/Makefile.am
index 3d32279ea..36ddba82b 100644
--- a/mesalib/src/loader/Makefile.am
+++ b/mesalib/src/loader/Makefile.am
@@ -30,7 +30,6 @@ libloader_la_CPPFLAGS = \
-I$(top_srcdir)/include \
-I$(top_srcdir)/src \
$(VISIBILITY_CFLAGS) \
- $(MSVC2013_COMPAT_CFLAGS) \
$(LIBUDEV_CFLAGS)
libloader_la_SOURCES = $(LOADER_C_FILES)
diff --git a/mesalib/src/mapi/glapi/gen/ARB_direct_state_access.xml b/mesalib/src/mapi/glapi/gen/ARB_direct_state_access.xml
index 641e68f71..8a092d697 100644
--- a/mesalib/src/mapi/glapi/gen/ARB_direct_state_access.xml
+++ b/mesalib/src/mapi/glapi/gen/ARB_direct_state_access.xml
@@ -7,6 +7,47 @@
<enum name="QUERY_TARGET" value="0x82EA"/>
<enum name="TEXTURE_BINDING" value="0x82EB"/>
+ <!-- Transform Feedback object functions -->
+
+ <function name="CreateTransformFeedbacks" offset="assign">
+ <param name="n" type="GLsizei" />
+ <param name="ids" type="GLuint *" />
+ </function>
+
+ <function name="TransformFeedbackBufferBase" offset="assign">
+ <param name="xfb" type="GLuint" />
+ <param name="index" type="GLuint" />
+ <param name="buffer" type="GLuint" />
+ </function>
+
+ <function name="TransformFeedbackBufferRange" offset="assign">
+ <param name="xfb" type="GLuint" />
+ <param name="index" type="GLuint" />
+ <param name="buffer" type="GLuint" />
+ <param name="offset" type="GLintptr" />
+ <param name="size" type="GLsizeiptr" />
+ </function>
+
+ <function name="GetTransformFeedbackiv" offset="assign">
+ <param name="xfb" type="GLuint" />
+ <param name="pname" type="GLenum" />
+ <param name="param" type="GLint *" />
+ </function>
+
+ <function name="GetTransformFeedbacki_v" offset="assign">
+ <param name="xfb" type="GLuint" />
+ <param name="pname" type="GLenum" />
+ <param name="index" type="GLuint" />
+ <param name="param" type="GLint *" />
+ </function>
+
+ <function name="GetTransformFeedbacki64_v" offset="assign">
+ <param name="xfb" type="GLuint" />
+ <param name="pname" type="GLenum" />
+ <param name="index" type="GLuint" />
+ <param name="param" type="GLint64 *" />
+ </function>
+
<!-- Buffer object functions -->
<function name="CreateBuffers" offset="assign">
@@ -111,6 +152,34 @@
<param name="data" type="GLvoid *" />
</function>
+ <!-- Renderbuffer object functions -->
+
+ <function name="CreateRenderbuffers" offset="assign">
+ <param name="n" type="GLsizei" />
+ <param name="renderbuffers" type="GLuint *" />
+ </function>
+
+ <function name="NamedRenderbufferStorage" offset="assign">
+ <param name="renderbuffer" type="GLuint" />
+ <param name="internalformat" type="GLenum" />
+ <param name="width" type="GLsizei" />
+ <param name="height" type="GLsizei" />
+ </function>
+
+ <function name="NamedRenderbufferStorageMultisample" offset="assign">
+ <param name="renderbuffer" type="GLuint" />
+ <param name="samples" type="GLsizei" />
+ <param name="internalformat" type="GLenum" />
+ <param name="width" type="GLsizei" />
+ <param name="height" type="GLsizei" />
+ </function>
+
+ <function name="GetNamedRenderbufferParameteriv" offset="assign">
+ <param name="renderbuffer" type="GLuint" />
+ <param name="pname" type="GLenum" />
+ <param name="params" type="GLint *" />
+ </function>
+
<!-- Texture object functions -->
<function name="CreateTextures" offset="assign">
@@ -379,5 +448,54 @@
<param name="params" type="GLint *" />
</function>
+ <!-- Sampler object functions -->
+
+ <function name="CreateSamplers" offset="assign">
+ <param name="n" type="GLsizei" />
+ <param name="samplers" type="GLuint *" />
+ </function>
+
+ <!-- Program Pipeline object functions -->
+
+ <function name="CreateProgramPipelines" offset="assign">
+ <param name="n" type="GLsizei" />
+ <param name="pipelines" type="GLuint *" />
+ </function>
+
+ <!-- Query object functions -->
+
+ <function name="CreateQueries" offset="assign">
+ <param name="target" type="GLenum" />
+ <param name="n" type="GLsizei" />
+ <param name="ids" type="GLuint *" />
+ </function>
+
+ <function name="GetQueryBufferObjectiv" offset="assign">
+ <param name="id" type="GLuint" />
+ <param name="buffer" type="GLuint" />
+ <param name="pname" type="GLenum" />
+ <param name="offset" type="GLintptr" />
+ </function>
+
+ <function name="GetQueryBufferObjectuiv" offset="assign">
+ <param name="id" type="GLuint" />
+ <param name="buffer" type="GLuint" />
+ <param name="pname" type="GLenum" />
+ <param name="offset" type="GLintptr" />
+ </function>
+
+ <function name="GetQueryBufferObjecti64v" offset="assign">
+ <param name="id" type="GLuint" />
+ <param name="buffer" type="GLuint" />
+ <param name="pname" type="GLenum" />
+ <param name="offset" type="GLintptr" />
+ </function>
+
+ <function name="GetQueryBufferObjectui64v" offset="assign">
+ <param name="id" type="GLuint" />
+ <param name="buffer" type="GLuint" />
+ <param name="pname" type="GLenum" />
+ <param name="offset" type="GLintptr" />
+ </function>
</category>
</OpenGLAPI>
diff --git a/mesalib/src/mapi/glapi/gen/ARB_program_interface_query.xml b/mesalib/src/mapi/glapi/gen/ARB_program_interface_query.xml
new file mode 100644
index 000000000..59eb59c64
--- /dev/null
+++ b/mesalib/src/mapi/glapi/gen/ARB_program_interface_query.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<OpenGLAPI>
+
+<category name="GL_ARB_program_interface_query" number="134">
+
+ <enum name="UNIFORM" value="0x92E1"/>
+ <enum name="UNIFORM_BLOCK" value="0x92E2"/>
+ <enum name="PROGRAM_INPUT" value="0x92E3"/>
+ <enum name="PROGRAM_OUTPUT" value="0x92E4"/>
+ <enum name="BUFFER_VARIABLE" value="0x92E5"/>
+ <enum name="SHADER_STORAGE_BLOCK" value="0x92E6"/>
+ <enum name="ATOMIC_COUNTER_BUFFER" value="0x92C0"/>
+ <enum name="VERTEX_SUBROUTINE" value="0x92E8"/>
+ <enum name="TESS_CONTROL_SUBROUTINE" value="0x92E9"/>
+ <enum name="TESS_EVALUATION_SUBROUTINE" value="0x92EA"/>
+ <enum name="GEOMETRY_SUBROUTINE" value="0x92EB"/>
+ <enum name="FRAGMENT_SUBROUTINE" value="0x92EC"/>
+ <enum name="COMPUTE_SUBROUTINE" value="0x92ED"/>
+ <enum name="VERTEX_SUBROUTINE_UNIFORM" value="0x92EE"/>
+ <enum name="TESS_CONTROL_SUBROUTINE_UNIFORM" value="0x92EF"/>
+ <enum name="TESS_EVALUATION_SUBROUTINE_UNIFORM" value="0x92F0"/>
+ <enum name="GEOMETRY_SUBROUTINE_UNIFORM" value="0x92F1"/>
+ <enum name="FRAGMENT_SUBROUTINE_UNIFORM" value="0x92F2"/>
+ <enum name="COMPUTE_SUBROUTINE_UNIFORM" value="0x92F3"/>
+ <enum name="TRANSFORM_FEEDBACK_VARYING" value="0x92F4"/>
+ <enum name="ACTIVE_RESOURCES" value="0x92F5"/>
+ <enum name="MAX_NAME_LENGTH" value="0x92F6"/>
+ <enum name="MAX_NUM_ACTIVE_VARIABLES" value="0x92F7"/>
+ <enum name="MAX_NUM_COMPATIBLE_SUBROUTINES" value="0x92F8"/>
+ <enum name="NAME_LENGTH" value="0x92F9"/>
+ <enum name="TYPE" value="0x92FA"/>
+ <enum name="ARRAY_SIZE" value="0x92FB"/>
+ <enum name="OFFSET" value="0x92FC"/>
+ <enum name="BLOCK_INDEX" value="0x92FD"/>
+ <enum name="ARRAY_STRIDE" value="0x92FE"/>
+ <enum name="MATRIX_STRIDE" value="0x92FF"/>
+ <enum name="IS_ROW_MAJOR" value="0x9300"/>
+ <enum name="ATOMIC_COUNTER_BUFFER_INDEX" value="0x9301"/>
+ <enum name="BUFFER_BINDING" value="0x9302"/>
+ <enum name="BUFFER_DATA_SIZE" value="0x9303"/>
+ <enum name="NUM_ACTIVE_VARIABLES" value="0x9304"/>
+ <enum name="ACTIVE_VARIABLES" value="0x9305"/>
+ <enum name="REFERENCED_BY_VERTEX_SHADER" value="0x9306"/>
+ <enum name="REFERENCED_BY_TESS_CONTROL_SHADER" value="0x9307"/>
+ <enum name="REFERENCED_BY_TESS_EVALUATION_SHADER" value="0x9308"/>
+ <enum name="REFERENCED_BY_GEOMETRY_SHADER" value="0x9309"/>
+ <enum name="REFERENCED_BY_FRAGMENT_SHADER" value="0x930A"/>
+ <enum name="REFERENCED_BY_COMPUTE_SHADER" value="0x930B"/>
+ <enum name="TOP_LEVEL_ARRAY_SIZE" value="0x930C"/>
+ <enum name="TOP_LEVEL_ARRAY_STRIDE" value="0x930D"/>
+ <enum name="LOCATION" value="0x930E"/>
+ <enum name="LOCATION_INDEX" value="0x930F"/>
+ <enum name="IS_PER_PATCH" value="0x92E7"/>
+ <enum name="NUM_COMPATIBLE_SUBROUTINES" value="0x8E4A"/>
+ <enum name="COMPATIBLE_SUBROUTINES" value="0x8E4B"/>
+
+ <function name="GetProgramInterfaceiv" offset="assign">
+ <param name="program" type="GLuint"/>
+ <param name="programInterface" type="GLenum"/>
+ <param name="pname" type="GLenum"/>
+ <param name="params" type="GLint *" output="true"/>
+ </function>
+
+ <function name="GetProgramResourceIndex" offset="assign">
+ <param name="program" type="GLuint"/>
+ <param name="programInterface" type="GLenum"/>
+ <param name="name" type="const GLchar *"/>
+ <return type="GLuint"/>
+ </function>
+
+ <function name="GetProgramResourceName" offset="assign">
+ <param name="program" type="GLuint"/>
+ <param name="programInterface" type="GLenum"/>
+ <param name="index" type="GLuint"/>
+ <param name="bufSize" type="GLsizei "/>
+ <param name="length" type="GLsizei *" output="true"/>
+ <param name="name" type="GLchar *" output="true"/>
+ </function>
+
+ <function name="GetProgramResourceiv" offset="assign">
+ <param name="program" type="GLuint"/>
+ <param name="programInterface" type="GLenum"/>
+ <param name="index" type="GLuint"/>
+ <param name="propCount" type="GLsizei "/>
+ <param name="props" type="const GLenum *" output="true"/>
+ <param name="bufSize" type="GLsizei "/>
+ <param name="length" type="GLsizei *" output="true"/>
+ <param name="params" type="GLint *" output="true"/>
+ </function>
+
+ <function name="GetProgramResourceLocation" offset="assign">
+ <param name="program" type="GLuint"/>
+ <param name="programInterface" type="GLenum"/>
+ <param name="name" type="const GLchar *"/>
+ <return type="GLint"/>
+ </function>
+
+ <function name="GetProgramResourceLocationIndex" offset="assign">
+ <param name="program" type="GLuint"/>
+ <param name="programInterface" type="GLenum"/>
+ <param name="name" type="const GLchar *"/>
+ <return type="GLint"/>
+ </function>
+
+</category>
+
+</OpenGLAPI>
diff --git a/mesalib/src/mapi/glapi/gen/gl_API.xml b/mesalib/src/mapi/glapi/gen/gl_API.xml
index 1ceb60a0f..a8a6db683 100644
--- a/mesalib/src/mapi/glapi/gen/gl_API.xml
+++ b/mesalib/src/mapi/glapi/gen/gl_API.xml
@@ -8337,7 +8337,9 @@
<!-- ARB extension #133 is ARB_multi_draw_indirect, defined in the same
file as ARB_draw_indirect -->
-<!-- ARB extensions #134...#138 -->
+<xi:include href="ARB_program_interface_query.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
+<!-- ARB extensions #135...#138 -->
<xi:include href="ARB_texture_buffer_range.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
diff --git a/mesalib/src/mapi/glapi/gen/gl_genexec.py b/mesalib/src/mapi/glapi/gen/gl_genexec.py
index d479e66da..7151f0de1 100644
--- a/mesalib/src/mapi/glapi/gen/gl_genexec.py
+++ b/mesalib/src/mapi/glapi/gen/gl_genexec.py
@@ -92,6 +92,7 @@ header = """/**
#include "main/pixelstore.h"
#include "main/points.h"
#include "main/polygon.h"
+#include "main/program_resource.h"
#include "main/querymatrix.h"
#include "main/queryobj.h"
#include "main/readpix.h"
diff --git a/mesalib/src/mapi/stub.c b/mesalib/src/mapi/stub.c
index 05436bab6..45e4f7dc6 100644
--- a/mesalib/src/mapi/stub.c
+++ b/mesalib/src/mapi/stub.c
@@ -102,7 +102,7 @@ stub_add_dynamic(const char *name)
if (!stub->addr)
return NULL;
- stub->name = (const void *) name;
+ stub->name = (const void *) strdup(name);
/* to be fixed later */
stub->slot = -1;
diff --git a/mesalib/src/mesa/Makefile.am b/mesalib/src/mesa/Makefile.am
index 3dab8f03f..60114e4f6 100644
--- a/mesalib/src/mesa/Makefile.am
+++ b/mesalib/src/mesa/Makefile.am
@@ -174,6 +174,7 @@ endif
libmesa_la_SOURCES = \
$(MESA_FILES) \
$(PROGRAM_FILES) \
+ $(PROGRAM_NIR_FILES) \
$(MESA_ASM_FILES_FOR_ARCH)
libmesa_la_LIBADD = \
@@ -183,6 +184,7 @@ libmesa_la_LIBADD = \
libmesagallium_la_SOURCES = \
$(MESA_GALLIUM_FILES) \
$(PROGRAM_FILES) \
+ $(PROGRAM_NIR_FILES) \
$(MESA_ASM_FILES_FOR_ARCH)
libmesagallium_la_LIBADD = \
diff --git a/mesalib/src/mesa/Makefile.sources b/mesalib/src/mesa/Makefile.sources
index 217be9ab3..1293d4135 100644
--- a/mesalib/src/mesa/Makefile.sources
+++ b/mesalib/src/mesa/Makefile.sources
@@ -152,6 +152,8 @@ MAIN_FILES = \
main/points.h \
main/polygon.c \
main/polygon.h \
+ main/program_resource.c \
+ main/program_resource.h \
main/querymatrix.c \
main/querymatrix.h \
main/queryobj.c \
@@ -520,6 +522,10 @@ PROGRAM_FILES = \
program/symbol_table.c \
program/symbol_table.h
+PROGRAM_NIR_FILES = \
+ program/prog_to_nir.c \
+ program/prog_to_nir.h
+
ASM_C_FILES = \
x86/common_x86.c \
x86/x86_xform.c \
@@ -608,6 +614,7 @@ INCLUDE_DIRS = \
-I$(top_srcdir)/src \
-I$(top_srcdir)/src/glsl \
-I$(top_builddir)/src/glsl \
+ -I$(top_builddir)/src/glsl/nir \
-I$(top_srcdir)/src/glsl/glcpp \
-I$(top_srcdir)/src/mesa \
-I$(top_builddir)/src/mesa \
diff --git a/mesalib/src/mesa/SConscript b/mesalib/src/mesa/SConscript
index a563fd2ff..5b80a216f 100644
--- a/mesalib/src/mesa/SConscript
+++ b/mesalib/src/mesa/SConscript
@@ -130,9 +130,10 @@ def write_git_sha1_h_file(filename):
(commit, foo) = subprocess.Popen(args, stdout=subprocess.PIPE).communicate()
except:
# git log command didn't work
- dirname = os.path.dirname(filename)
- if not os.path.exists(dirname):
- os.makedirs(dirname)
+ if not os.path.exists(filename):
+ dirname = os.path.dirname(filename)
+ if not os.path.exists(dirname):
+ os.makedirs(dirname)
# create an empty file if none already exists
f = open(filename, "w")
f.close()
diff --git a/mesalib/src/mesa/drivers/SConscript b/mesalib/src/mesa/drivers/SConscript
index 17813da96..db656780c 100644
--- a/mesalib/src/mesa/drivers/SConscript
+++ b/mesalib/src/mesa/drivers/SConscript
@@ -1,7 +1,5 @@
Import('*')
-SConscript('osmesa/SConscript')
-
if env['x11']:
SConscript('x11/SConscript')
diff --git a/mesalib/src/mesa/drivers/dri/common/utils.c b/mesalib/src/mesa/drivers/dri/common/utils.c
index bb22107e9..70d34e8ce 100644
--- a/mesalib/src/mesa/drivers/dri/common/utils.c
+++ b/mesalib/src/mesa/drivers/dri/common/utils.c
@@ -227,7 +227,7 @@ driCreateConfigs(mesa_format format,
break;
default:
fprintf(stderr, "[%s:%u] Unknown framebuffer type %s (%d).\n",
- __FUNCTION__, __LINE__,
+ __func__, __LINE__,
_mesa_get_format_name(format), format);
return NULL;
}
diff --git a/mesalib/src/mesa/drivers/dri/common/xmlconfig.c b/mesalib/src/mesa/drivers/dri/common/xmlconfig.c
index 2b284ccf2..f17693e73 100644
--- a/mesalib/src/mesa/drivers/dri/common/xmlconfig.c
+++ b/mesalib/src/mesa/drivers/dri/common/xmlconfig.c
@@ -56,7 +56,7 @@ extern char *program_invocation_name, *program_invocation_short_name;
# include <stdlib.h>
# define GET_PROGRAM_NAME() getprogname()
# endif
-#elif defined(__NetBSD__) && defined(__NetBSD_Version) && (__NetBSD_Version >= 106000100)
+#elif defined(__NetBSD__) && defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 106000100)
# include <stdlib.h>
# define GET_PROGRAM_NAME() getprogname()
#elif defined(__APPLE__)
diff --git a/mesalib/src/mesa/drivers/dri/common/xmlpool/Makefile.am b/mesalib/src/mesa/drivers/dri/common/xmlpool/Makefile.am
index 555771685..a6f1652d1 100644
--- a/mesalib/src/mesa/drivers/dri/common/xmlpool/Makefile.am
+++ b/mesalib/src/mesa/drivers/dri/common/xmlpool/Makefile.am
@@ -52,14 +52,19 @@ POT=xmlpool.pot
.PHONY: all clean pot po mo
-EXTRA_DIST = gen_xmlpool.py options.h t_options.h $(POS) SConscript
-BUILT_SOURCES = options.h
-CLEANFILES = $(MOS) options.h
+EXTRA_DIST = \
+ gen_xmlpool.py \
+ options.h \
+ t_options.h \
+ $(POS) \
+ $(MOS) \
+ SConscript
-# All generated files are cleaned up.
-clean:
- -rm -f $(POT) options.h *~
- -rm -rf $(LANGS)
+BUILT_SOURCES = options.h
+CLEANFILES = \
+ options.h
+ $(POS) \
+ $(MOS)
# Default target options.h
options.h: LOCALEDIR := .
diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast.c b/mesalib/src/mesa/drivers/dri/swrast/swrast.c
index fb29078b6..d1bb72139 100644
--- a/mesalib/src/mesa/drivers/dri/swrast/swrast.c
+++ b/mesalib/src/mesa/drivers/dri/swrast/swrast.c
@@ -326,7 +326,7 @@ choose_pixel_format(const struct gl_config *v)
&& v->blueMask == 0xc0)
return PF_R3G3B2;
- _mesa_problem( NULL, "unexpected format in %s", __FUNCTION__ );
+ _mesa_problem( NULL, "unexpected format in %s", __func__ );
return 0;
}
diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h b/mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h
index 1f3a48f38..a6ab53529 100644
--- a/mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h
+++ b/mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h
@@ -41,13 +41,13 @@
#define DEBUG_SPAN 0
#if DEBUG_CORE
-#define TRACE printf("--> %s\n", __FUNCTION__)
+#define TRACE printf("--> %s\n", __func__)
#else
#define TRACE
#endif
#if DEBUG_SPAN
-#define TRACE_SPAN printf("--> %s\n", __FUNCTION__)
+#define TRACE_SPAN printf("--> %s\n", __func__)
#else
#define TRACE_SPAN
#endif
diff --git a/mesalib/src/mesa/main/.gitignore b/mesalib/src/mesa/main/.gitignore
index 8256ad792..355b426e2 100644
--- a/mesalib/src/mesa/main/.gitignore
+++ b/mesalib/src/mesa/main/.gitignore
@@ -7,5 +7,6 @@ remap_helper.h
get_hash.h
get_hash.h.tmp
format_info.h
+format_info.c
format_pack.c
format_unpack.c
diff --git a/mesalib/src/mesa/main/atifragshader.c b/mesalib/src/mesa/main/atifragshader.c
index 9d967b9e6..9fc35520a 100644
--- a/mesalib/src/mesa/main/atifragshader.c
+++ b/mesalib/src/mesa/main/atifragshader.c
@@ -476,7 +476,7 @@ _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
curI->swizzle = swizzle;
#if MESA_DEBUG_ATI_FS
- _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
+ _mesa_debug(ctx, "%s(%s, %s, %s)\n", __func__,
_mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(coord),
_mesa_lookup_enum_by_nr(swizzle));
#endif
@@ -549,7 +549,7 @@ _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
curI->swizzle = swizzle;
#if MESA_DEBUG_ATI_FS
- _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
+ _mesa_debug(ctx, "%s(%s, %s, %s)\n", __func__,
_mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(interp),
_mesa_lookup_enum_by_nr(swizzle));
#endif
diff --git a/mesalib/src/mesa/main/attrib.c b/mesalib/src/mesa/main/attrib.c
index 20216a87d..b163c0aa6 100644
--- a/mesalib/src/mesa/main/attrib.c
+++ b/mesalib/src/mesa/main/attrib.c
@@ -32,7 +32,6 @@
#include "buffers.h"
#include "bufferobj.h"
#include "clear.h"
-#include "colormac.h"
#include "context.h"
#include "depth.h"
#include "enable.h"
diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c
index 965877084..66dee6802 100644
--- a/mesalib/src/mesa/main/bufferobj.c
+++ b/mesalib/src/mesa/main/bufferobj.c
@@ -1333,6 +1333,7 @@ create_buffers(GLsizei n, GLuint *buffers, bool dsa)
buf = ctx->Driver.NewBufferObject(ctx, buffers[i]);
if (!buf) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
+ mtx_unlock(&ctx->Shared->Mutex);
return;
}
}
@@ -3885,8 +3886,10 @@ _mesa_BindBufferRange(GLenum target, GLuint index,
switch (target) {
case GL_TRANSFORM_FEEDBACK_BUFFER:
- _mesa_bind_buffer_range_transform_feedback(ctx, index, bufObj,
- offset, size);
+ _mesa_bind_buffer_range_transform_feedback(ctx,
+ ctx->TransformFeedback.CurrentObject,
+ index, bufObj, offset, size,
+ false);
return;
case GL_UNIFORM_BUFFER:
bind_buffer_range_uniform_buffer(ctx, index, bufObj, offset, size);
@@ -3950,7 +3953,9 @@ _mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer)
switch (target) {
case GL_TRANSFORM_FEEDBACK_BUFFER:
- _mesa_bind_buffer_base_transform_feedback(ctx, index, bufObj);
+ _mesa_bind_buffer_base_transform_feedback(ctx,
+ ctx->TransformFeedback.CurrentObject,
+ index, bufObj, false);
return;
case GL_UNIFORM_BUFFER:
bind_buffer_base_uniform_buffer(ctx, index, bufObj);
diff --git a/mesalib/src/mesa/main/colormac.h b/mesalib/src/mesa/main/colormac.h
index bc69f4673..33ca5af07 100644
--- a/mesalib/src/mesa/main/colormac.h
+++ b/mesalib/src/mesa/main/colormac.h
@@ -52,70 +52,25 @@ _mesa_unclamped_float_rgba_to_ubyte(GLubyte dst[4], const GLfloat src[4])
/**
* \name Generic color packing macros. All inputs should be GLubytes.
- *
- * \todo We may move these into texstore.h at some point.
*/
/*@{*/
#define PACK_COLOR_8888( X, Y, Z, W ) \
(((X) << 24) | ((Y) << 16) | ((Z) << 8) | (W))
-#define PACK_COLOR_8888_REV( X, Y, Z, W ) \
- (((W) << 24) | ((Z) << 16) | ((Y) << 8) | (X))
-
-#define PACK_COLOR_888( X, Y, Z ) \
- (((X) << 16) | ((Y) << 8) | (Z))
-
#define PACK_COLOR_565( X, Y, Z ) \
((((X) & 0xf8) << 8) | (((Y) & 0xfc) << 3) | (((Z) & 0xf8) >> 3))
-#define PACK_COLOR_5551( R, G, B, A ) \
- ((((R) & 0xf8) << 8) | (((G) & 0xf8) << 3) | (((B) & 0xf8) >> 2) | \
- ((A) >> 7))
-
#define PACK_COLOR_1555( A, B, G, R ) \
((((B) & 0xf8) << 7) | (((G) & 0xf8) << 2) | (((R) & 0xf8) >> 3) | \
(((A) & 0x80) << 8))
-#define PACK_COLOR_1555_REV( A, B, G, R ) \
- ((((B) & 0xf8) >> 1) | (((G) & 0xc0) >> 6) | (((G) & 0x38) << 10) | (((R) & 0xf8) << 5) | \
- ((A) ? 0x80 : 0))
-
-#define PACK_COLOR_2101010_UB( A, B, G, R ) \
- (((B) << 22) | ((G) << 12) | ((R) << 2) | \
- (((A) & 0xc0) << 24))
-
-#define PACK_COLOR_2101010_US( A, B, G, R ) \
- ((((B) >> 6) << 20) | (((G) >> 6) << 10) | ((R) >> 6) | \
- (((A) >> 14) << 30))
-
#define PACK_COLOR_4444( R, G, B, A ) \
((((R) & 0xf0) << 8) | (((G) & 0xf0) << 4) | ((B) & 0xf0) | ((A) >> 4))
-#define PACK_COLOR_4444_REV( R, G, B, A ) \
- ((((B) & 0xf0) << 8) | (((A) & 0xf0) << 4) | ((R) & 0xf0) | ((G) >> 4))
-
-#define PACK_COLOR_44( L, A ) \
- (((L) & 0xf0) | (((A) & 0xf0) >> 4))
-
#define PACK_COLOR_88( L, A ) \
(((L) << 8) | (A))
-#define PACK_COLOR_88_REV( L, A ) \
- (((A) << 8) | (L))
-
-#define PACK_COLOR_1616( L, A ) \
- (((L) << 16) | (A))
-
-#define PACK_COLOR_1616_REV( L, A ) \
- (((A) << 16) | (L))
-
-#define PACK_COLOR_332( R, G, B ) \
- (((R) & 0xe0) | (((G) & 0xe0) >> 3) | (((B) & 0xc0) >> 6))
-
-#define PACK_COLOR_233( B, G, R ) \
- (((B) & 0xc0) | (((G) & 0xe0) >> 2) | (((R) & 0xe0) >> 5))
-
/*@}*/
diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c
index c1acda980..adf64976e 100644
--- a/mesalib/src/mesa/main/context.c
+++ b/mesalib/src/mesa/main/context.c
@@ -1288,7 +1288,6 @@ _mesa_free_context_data( struct gl_context *ctx )
_mesa_free_eval_data( ctx );
_mesa_free_texture_data( ctx );
_mesa_free_matrix_data( ctx );
- _mesa_free_viewport_data( ctx );
_mesa_free_pipeline_data(ctx);
_mesa_free_program_data(ctx);
_mesa_free_shader_state(ctx);
@@ -1449,17 +1448,10 @@ _mesa_copy_context( const struct gl_context *src, struct gl_context *dst,
dst->Transform = src->Transform;
}
if (mask & GL_VIEWPORT_BIT) {
- /* Cannot use memcpy, because of pointers in GLmatrix _WindowMap */
unsigned i;
for (i = 0; i < src->Const.MaxViewports; i++) {
- dst->ViewportArray[i].X = src->ViewportArray[i].X;
- dst->ViewportArray[i].Y = src->ViewportArray[i].Y;
- dst->ViewportArray[i].Width = src->ViewportArray[i].Width;
- dst->ViewportArray[i].Height = src->ViewportArray[i].Height;
- dst->ViewportArray[i].Near = src->ViewportArray[i].Near;
- dst->ViewportArray[i].Far = src->ViewportArray[i].Far;
- _math_matrix_copy(&dst->ViewportArray[i]._WindowMap,
- &src->ViewportArray[i]._WindowMap);
+ /* OK to memcpy */
+ dst->ViewportArray[i] = src->ViewportArray[i];
}
}
diff --git a/mesalib/src/mesa/main/debug.c b/mesalib/src/mesa/main/debug.c
index b50d79e0c..c93e84a04 100644
--- a/mesalib/src/mesa/main/debug.c
+++ b/mesalib/src/mesa/main/debug.c
@@ -26,11 +26,11 @@
#include <stdio.h>
#include "mtypes.h"
#include "attrib.h"
-#include "colormac.h"
#include "enums.h"
#include "formats.h"
#include "hash.h"
#include "imports.h"
+#include "macros.h"
#include "debug.h"
#include "get.h"
#include "pixelstore.h"
diff --git a/mesalib/src/mesa/main/dlopen.h b/mesalib/src/mesa/main/dlopen.h
index 1e7784914..4d20ff2c7 100644
--- a/mesalib/src/mesa/main/dlopen.h
+++ b/mesalib/src/mesa/main/dlopen.h
@@ -50,7 +50,7 @@ _mesa_dlopen(const char *libname, int flags)
#if defined(HAVE_DLOPEN)
flags = RTLD_LAZY | RTLD_GLOBAL; /* Overriding flags at this time */
return dlopen(libname, flags);
-#elif defined(__MINGW32__)
+#elif defined(_WIN32)
return LoadLibraryA(libname);
#else
return NULL;
@@ -71,7 +71,7 @@ _mesa_dlsym(void *handle, const char *fname)
} u;
#if defined(HAVE_DLOPEN)
u.v = dlsym(handle, fname);
-#elif defined(__MINGW32__)
+#elif defined(_WIN32)
u.v = (void *) GetProcAddress(handle, fname);
#else
u.v = NULL;
@@ -87,7 +87,7 @@ _mesa_dlclose(void *handle)
{
#if defined(HAVE_DLOPEN)
dlclose(handle);
-#elif defined(__MINGW32__)
+#elif defined(_WIN32)
FreeLibrary(handle);
#else
(void) handle;
diff --git a/mesalib/src/mesa/main/errors.c b/mesalib/src/mesa/main/errors.c
index 8ffbf413c..2aa1deb63 100644
--- a/mesalib/src/mesa/main/errors.c
+++ b/mesalib/src/mesa/main/errors.c
@@ -1232,12 +1232,14 @@ _mesa_free_errors_data(struct gl_context *ctx)
/** \name Diagnostics */
/*@{*/
+static FILE *LogFile = NULL;
+
+
static void
output_if_debug(const char *prefixString, const char *outputString,
GLboolean newline)
{
static int debug = -1;
- static FILE *fout = NULL;
/* Init the local 'debug' var once.
* Note: the _mesa_init_debug() function should have been called
@@ -1249,9 +1251,9 @@ output_if_debug(const char *prefixString, const char *outputString,
*/
const char *logFile = getenv("MESA_LOG_FILE");
if (logFile)
- fout = fopen(logFile, "w");
- if (!fout)
- fout = stderr;
+ LogFile = fopen(logFile, "w");
+ if (!LogFile)
+ LogFile = stderr;
#ifdef DEBUG
/* in debug builds, print messages unless MESA_DEBUG="silent" */
if (MESA_DEBUG_FLAGS & DEBUG_SILENT)
@@ -1266,10 +1268,13 @@ output_if_debug(const char *prefixString, const char *outputString,
/* Now only print the string if we're required to do so. */
if (debug) {
- fprintf(fout, "%s: %s", prefixString, outputString);
+ if (prefixString)
+ fprintf(LogFile, "%s: %s", prefixString, outputString);
+ else
+ fprintf(LogFile, "%s", outputString);
if (newline)
- fprintf(fout, "\n");
- fflush(fout);
+ fprintf(LogFile, "\n");
+ fflush(LogFile);
#if defined(_WIN32)
/* stderr from windows applications without console is not usually
@@ -1285,6 +1290,18 @@ output_if_debug(const char *prefixString, const char *outputString,
/**
+ * Return the file handle to use for debug/logging. Defaults to stderr
+ * unless MESA_LOG_FILE is defined.
+ */
+FILE *
+_mesa_get_log_file(void)
+{
+ assert(LogFile);
+ return LogFile;
+}
+
+
+/**
* When a new type of error is recorded, print a message describing
* previous errors which were accumulated.
*/
@@ -1525,6 +1542,18 @@ _mesa_debug( const struct gl_context *ctx, const char *fmtString, ... )
}
+void
+_mesa_log(const char *fmtString, ...)
+{
+ char s[MAX_DEBUG_MESSAGE_LENGTH];
+ va_list args;
+ va_start(args, fmtString);
+ _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
+ va_end(args);
+ output_if_debug("", s, GL_FALSE);
+}
+
+
/**
* Report debug information from the shader compiler via GL_ARB_debug_output.
*
diff --git a/mesalib/src/mesa/main/errors.h b/mesalib/src/mesa/main/errors.h
index 0c521c0d0..e6dc9b5f1 100644
--- a/mesalib/src/mesa/main/errors.h
+++ b/mesalib/src/mesa/main/errors.h
@@ -36,6 +36,7 @@
#define ERRORS_H
+#include <stdio.h>
#include "compiler.h"
#include "glheader.h"
#include "mtypes.h"
@@ -69,6 +70,12 @@ extern void
_mesa_debug( const struct gl_context *ctx, const char *fmtString, ... ) PRINTFLIKE(2, 3);
extern void
+_mesa_log(const char *fmtString, ...) PRINTFLIKE(1, 2);
+
+extern FILE *
+_mesa_get_log_file(void);
+
+extern void
_mesa_gl_debug(struct gl_context *ctx,
GLuint *id,
enum mesa_debug_source source,
diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c
index f21201538..861b15006 100644
--- a/mesalib/src/mesa/main/extensions.c
+++ b/mesalib/src/mesa/main/extensions.c
@@ -139,6 +139,7 @@ static const struct extension extension_table[] = {
{ "GL_ARB_pixel_buffer_object", o(EXT_pixel_buffer_object), GL, 2004 },
{ "GL_ARB_point_parameters", o(EXT_point_parameters), GLL, 1997 },
{ "GL_ARB_point_sprite", o(ARB_point_sprite), GL, 2003 },
+ { "GL_ARB_program_interface_query", o(dummy_true), GL, 2012 },
{ "GL_ARB_provoking_vertex", o(EXT_provoking_vertex), GL, 2009 },
{ "GL_ARB_robustness", o(dummy_true), GL, 2010 },
{ "GL_ARB_sample_shading", o(ARB_sample_shading), GL, 2009 },
diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c
index f8d0d92bf..8032585ab 100644
--- a/mesalib/src/mesa/main/fbobject.c
+++ b/mesalib/src/mesa/main/fbobject.c
@@ -212,13 +212,13 @@ get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
*/
i = attachment - GL_COLOR_ATTACHMENT0_EXT;
if (i >= ctx->Const.MaxColorAttachments
- || (i > 0 && ctx->API == API_OPENGLES)) {
- return NULL;
+ || (i > 0 && ctx->API == API_OPENGLES)) {
+ return NULL;
}
return &fb->Attachment[BUFFER_COLOR0 + i];
case GL_DEPTH_STENCIL_ATTACHMENT:
if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
- return NULL;
+ return NULL;
/* fall-through */
case GL_DEPTH_ATTACHMENT_EXT:
return &fb->Attachment[BUFFER_DEPTH];
@@ -1122,28 +1122,28 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx,
if (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_ES2_compatibility) {
/* Check that all DrawBuffers are present */
for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) {
- if (fb->ColorDrawBuffer[j] != GL_NONE) {
- const struct gl_renderbuffer_attachment *att
- = get_attachment(ctx, fb, fb->ColorDrawBuffer[j]);
- assert(att);
- if (att->Type == GL_NONE) {
- fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
- fbo_incomplete(ctx, "missing drawbuffer", j);
- return;
- }
- }
+ if (fb->ColorDrawBuffer[j] != GL_NONE) {
+ const struct gl_renderbuffer_attachment *att
+ = get_attachment(ctx, fb, fb->ColorDrawBuffer[j]);
+ assert(att);
+ if (att->Type == GL_NONE) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
+ fbo_incomplete(ctx, "missing drawbuffer", j);
+ return;
+ }
+ }
}
/* Check that the ReadBuffer is present */
if (fb->ColorReadBuffer != GL_NONE) {
- const struct gl_renderbuffer_attachment *att
- = get_attachment(ctx, fb, fb->ColorReadBuffer);
- assert(att);
- if (att->Type == GL_NONE) {
- fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
+ const struct gl_renderbuffer_attachment *att
+ = get_attachment(ctx, fb, fb->ColorReadBuffer);
+ assert(att);
+ if (att->Type == GL_NONE) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
fbo_incomplete(ctx, "missing readbuffer", -1);
- return;
- }
+ return;
+ }
}
}
@@ -1205,6 +1205,28 @@ _mesa_IsRenderbuffer(GLuint renderbuffer)
}
+static struct gl_renderbuffer *
+allocate_renderbuffer(struct gl_context *ctx, GLuint renderbuffer,
+ const char *func)
+{
+ struct gl_renderbuffer *newRb;
+
+ /* create new renderbuffer object */
+ newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
+ if (!newRb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
+ return NULL;
+ }
+ assert(newRb->AllocStorage);
+ mtx_lock(&ctx->Shared->Mutex);
+ _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb);
+ newRb->RefCount = 1; /* referenced by hash table */
+ mtx_unlock(&ctx->Shared->Mutex);
+
+ return newRb;
+}
+
+
static void
bind_renderbuffer(GLenum target, GLuint renderbuffer, bool allow_user_names)
{
@@ -1233,15 +1255,7 @@ bind_renderbuffer(GLenum target, GLuint renderbuffer, bool allow_user_names)
}
if (!newRb) {
- /* create new renderbuffer object */
- newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
- if (!newRb) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT");
- return;
- }
- assert(newRb->AllocStorage);
- _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb);
- newRb->RefCount = 1; /* referenced by hash table */
+ newRb = allocate_renderbuffer(ctx, renderbuffer, "glBindRenderbufferEXT");
}
}
else {
@@ -1333,9 +1347,9 @@ _mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
for (i = 0; i < n; i++) {
if (renderbuffers[i] > 0) {
- struct gl_renderbuffer *rb;
- rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
- if (rb) {
+ struct gl_renderbuffer *rb;
+ rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
+ if (rb) {
/* check if deleting currently bound renderbuffer object */
if (rb == ctx->CurrentRenderbuffer) {
/* bind default */
@@ -1368,31 +1382,31 @@ _mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
_mesa_detach_renderbuffer(ctx, ctx->ReadBuffer, rb);
}
- /* Remove from hash table immediately, to free the ID.
+ /* Remove from hash table immediately, to free the ID.
* But the object will not be freed until it's no longer
* referenced anywhere else.
*/
- _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);
+ _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);
if (rb != &DummyRenderbuffer) {
/* no longer referenced by hash table */
_mesa_reference_renderbuffer(&rb, NULL);
- }
- }
+ }
+ }
}
}
}
-
-void GLAPIENTRY
-_mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
+static void
+create_render_buffers(struct gl_context *ctx, GLsizei n, GLuint *renderbuffers,
+ bool dsa)
{
- GET_CURRENT_CONTEXT(ctx);
+ const char *func = dsa ? "glCreateRenderbuffers" : "glGenRenderbuffers";
GLuint first;
GLint i;
if (n < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGenRenderbuffersEXT(n)");
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", func);
return;
}
@@ -1404,14 +1418,35 @@ _mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
for (i = 0; i < n; i++) {
GLuint name = first + i;
renderbuffers[i] = name;
- /* insert dummy placeholder into hash table */
- mtx_lock(&ctx->Shared->Mutex);
- _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer);
- mtx_unlock(&ctx->Shared->Mutex);
+
+ if (dsa) {
+ allocate_renderbuffer(ctx, name, func);
+ } else {
+ /* insert a dummy renderbuffer into the hash table */
+ mtx_lock(&ctx->Shared->Mutex);
+ _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer);
+ mtx_unlock(&ctx->Shared->Mutex);
+ }
}
}
+void GLAPIENTRY
+_mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ create_render_buffers(ctx, n, renderbuffers, false);
+}
+
+
+void GLAPIENTRY
+_mesa_CreateRenderbuffers(GLsizei n, GLuint *renderbuffers)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ create_render_buffers(ctx, n, renderbuffers, true);
+}
+
+
/**
* Given an internal format token for a render buffer, return the
* corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX,
@@ -1749,40 +1784,17 @@ invalidate_rb(GLuint key, void *data, void *userData)
/**
- * Helper function used by _mesa_RenderbufferStorage() and
- * _mesa_RenderbufferStorageMultisample().
- * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorage().
+ * Helper function used by renderbuffer_storage_direct() and
+ * renderbuffer_storage_target().
+ * samples will be NO_SAMPLES if called by a non-multisample function.
*/
static void
-renderbuffer_storage(GLenum target, GLenum internalFormat,
- GLsizei width, GLsizei height, GLsizei samples)
+renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
+ GLenum internalFormat, GLsizei width,
+ GLsizei height, GLsizei samples, const char *func)
{
- const char *func = samples == NO_SAMPLES ?
- "glRenderbufferStorage" : "glRenderbufferStorageMultisample";
- struct gl_renderbuffer *rb;
GLenum baseFormat;
GLenum sample_count_error;
- GET_CURRENT_CONTEXT(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API) {
- if (samples == NO_SAMPLES)
- _mesa_debug(ctx, "%s(%s, %s, %d, %d)\n",
- func,
- _mesa_lookup_enum_by_nr(target),
- _mesa_lookup_enum_by_nr(internalFormat),
- width, height);
- else
- _mesa_debug(ctx, "%s(%s, %s, %d, %d, %d)\n",
- func,
- _mesa_lookup_enum_by_nr(target),
- _mesa_lookup_enum_by_nr(internalFormat),
- width, height, samples);
- }
-
- if (target != GL_RENDERBUFFER_EXT) {
- _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
- return;
- }
baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
if (baseFormat == 0) {
@@ -1792,12 +1804,14 @@ renderbuffer_storage(GLenum target, GLenum internalFormat,
}
if (width < 0 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) {
- _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func);
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid width %d)", func,
+ width);
return;
}
if (height < 0 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) {
- _mesa_error(ctx, GL_INVALID_VALUE, "%s(height)", func);
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid height %d)", func,
+ height);
return;
}
@@ -1809,7 +1823,7 @@ renderbuffer_storage(GLenum target, GLenum internalFormat,
/* check the sample count;
* note: driver may choose to use more samples than what's requested
*/
- sample_count_error = _mesa_check_sample_count(ctx, target,
+ sample_count_error = _mesa_check_sample_count(ctx, GL_RENDERBUFFER,
internalFormat, samples);
if (sample_count_error != GL_NO_ERROR) {
_mesa_error(ctx, sample_count_error, "%s(samples)", func);
@@ -1817,12 +1831,6 @@ renderbuffer_storage(GLenum target, GLenum internalFormat,
}
}
- rb = ctx->CurrentRenderbuffer;
- if (!rb) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
- return;
- }
-
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
if (rb->InternalFormat == internalFormat &&
@@ -1864,6 +1872,83 @@ renderbuffer_storage(GLenum target, GLenum internalFormat,
}
}
+/**
+ * Helper function used by _mesa_NamedRenderbufferStorage*().
+ * samples will be NO_SAMPLES if called by a non-multisample function.
+ */
+static void
+renderbuffer_storage_named(GLuint renderbuffer, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLsizei samples,
+ const char *func)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API) {
+ if (samples == NO_SAMPLES)
+ _mesa_debug(ctx, "%s(%u, %s, %d, %d)\n",
+ func, renderbuffer,
+ _mesa_lookup_enum_by_nr(internalFormat),
+ width, height);
+ else
+ _mesa_debug(ctx, "%s(%u, %s, %d, %d, %d)\n",
+ func, renderbuffer,
+ _mesa_lookup_enum_by_nr(internalFormat),
+ width, height, samples);
+ }
+
+ struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
+ if (!rb || rb == &DummyRenderbuffer) {
+ /* ID was reserved, but no real renderbuffer object made yet */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid renderbuffer %u)",
+ func, renderbuffer);
+ return;
+ }
+
+ renderbuffer_storage(ctx, rb, internalFormat, width, height, samples, func);
+}
+
+/**
+ * Helper function used by _mesa_RenderbufferStorage() and
+ * _mesa_RenderbufferStorageMultisample().
+ * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorage().
+ */
+static void
+renderbuffer_storage_target(GLenum target, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLsizei samples,
+ const char *func)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API) {
+ if (samples == NO_SAMPLES)
+ _mesa_debug(ctx, "%s(%s, %s, %d, %d)\n",
+ func,
+ _mesa_lookup_enum_by_nr(target),
+ _mesa_lookup_enum_by_nr(internalFormat),
+ width, height);
+ else
+ _mesa_debug(ctx, "%s(%s, %s, %d, %d, %d)\n",
+ func,
+ _mesa_lookup_enum_by_nr(target),
+ _mesa_lookup_enum_by_nr(internalFormat),
+ width, height, samples);
+ }
+
+ if (target != GL_RENDERBUFFER_EXT) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
+ return;
+ }
+
+ if (!ctx->CurrentRenderbuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no renderbuffer bound)",
+ func);
+ return;
+ }
+
+ renderbuffer_storage(ctx, ctx->CurrentRenderbuffer, internalFormat, width,
+ height, samples, func);
+}
+
void GLAPIENTRY
_mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
@@ -1923,7 +2008,8 @@ _mesa_RenderbufferStorage(GLenum target, GLenum internalFormat,
* glRenderbufferStorageMultisample() with samples=0. We pass in
* a token value here just for error reporting purposes.
*/
- renderbuffer_storage(target, internalFormat, width, height, NO_SAMPLES);
+ renderbuffer_storage_target(target, internalFormat, width, height,
+ NO_SAMPLES, "glRenderbufferStorage");
}
@@ -1932,7 +2018,8 @@ _mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
GLenum internalFormat,
GLsizei width, GLsizei height)
{
- renderbuffer_storage(target, internalFormat, width, height, samples);
+ renderbuffer_storage_target(target, internalFormat, width, height,
+ samples, "glRenderbufferStorageMultisample");
}
@@ -1941,7 +2028,7 @@ _mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
*/
void GLAPIENTRY
_es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
- GLsizei width, GLsizei height)
+ GLsizei width, GLsizei height)
{
switch (internalFormat) {
case GL_RGB565:
@@ -1953,29 +2040,38 @@ _es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
break;
}
- renderbuffer_storage(target, internalFormat, width, height, 0);
+ renderbuffer_storage_target(target, internalFormat, width, height, 0,
+ "glRenderbufferStorageEXT");
}
-
void GLAPIENTRY
-_mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
+_mesa_NamedRenderbufferStorage(GLuint renderbuffer, GLenum internalformat,
+ GLsizei width, GLsizei height)
{
- struct gl_renderbuffer *rb;
- GET_CURRENT_CONTEXT(ctx);
+ /* GL_ARB_fbo says calling this function is equivalent to calling
+ * glRenderbufferStorageMultisample() with samples=0. We pass in
+ * a token value here just for error reporting purposes.
+ */
+ renderbuffer_storage_named(renderbuffer, internalformat, width, height,
+ NO_SAMPLES, "glNamedRenderbufferStorage");
+}
- if (target != GL_RENDERBUFFER_EXT) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetRenderbufferParameterivEXT(target)");
- return;
- }
+void GLAPIENTRY
+_mesa_NamedRenderbufferStorageMultisample(GLuint renderbuffer, GLsizei samples,
+ GLenum internalformat,
+ GLsizei width, GLsizei height)
+{
+ renderbuffer_storage_named(renderbuffer, internalformat, width, height,
+ samples,
+ "glNamedRenderbufferStorageMultisample");
+}
- rb = ctx->CurrentRenderbuffer;
- if (!rb) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetRenderbufferParameterivEXT");
- return;
- }
+static void
+get_render_buffer_parameteriv(struct gl_context *ctx,
+ struct gl_renderbuffer *rb, GLenum pname,
+ GLint *params, const char *func)
+{
/* No need to flush here since we're just quering state which is
* not effected by rendering.
*/
@@ -2006,10 +2102,51 @@ _mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
}
/* fallthrough */
default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname=%s)", func,
+ _mesa_lookup_enum_by_nr(pname));
+ return;
+ }
+}
+
+
+void GLAPIENTRY
+_mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (target != GL_RENDERBUFFER_EXT) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glGetRenderbufferParameterivEXT(target)");
return;
}
+
+ if (!ctx->CurrentRenderbuffer) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetRenderbufferParameterivEXT"
+ "(no renderbuffer bound)");
+ return;
+ }
+
+ get_render_buffer_parameteriv(ctx, ctx->CurrentRenderbuffer, pname,
+ params, "glGetRenderbufferParameteriv");
+}
+
+
+void GLAPIENTRY
+_mesa_GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname,
+ GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
+ if (!rb || rb == &DummyRenderbuffer) {
+ /* ID was reserved, but no real renderbuffer object made yet */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetNamedRenderbufferParameteriv"
+ "(invalid renderbuffer %i)", renderbuffer);
+ return;
+ }
+
+ get_render_buffer_parameteriv(ctx, rb, pname, params,
+ "glGetNamedRenderbufferParameteriv");
}
@@ -2116,12 +2253,12 @@ bind_framebuffer(GLenum target, GLuint framebuffer, bool allow_user_names)
}
if (!newDrawFb) {
- /* create new framebuffer object */
- newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
- if (!newDrawFb) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
- return;
- }
+ /* create new framebuffer object */
+ newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
+ if (!newDrawFb) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
+ return;
+ }
_mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb);
}
newReadFb = newDrawFb;
@@ -2224,9 +2361,9 @@ _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
for (i = 0; i < n; i++) {
if (framebuffers[i] > 0) {
- struct gl_framebuffer *fb;
- fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
- if (fb) {
+ struct gl_framebuffer *fb;
+ fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
+ if (fb) {
assert(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
/* check if deleting currently bound framebuffer object */
@@ -2241,16 +2378,16 @@ _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
_mesa_BindFramebuffer(GL_READ_FRAMEBUFFER, 0);
}
- /* remove from hash table immediately, to free the ID */
- _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
+ /* remove from hash table immediately, to free the ID */
+ _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
if (fb != &DummyFramebuffer) {
/* But the object will not be freed until it's no longer
* bound in any context.
*/
_mesa_reference_framebuffer(&fb, NULL);
- }
- }
+ }
+ }
}
}
}
@@ -2498,34 +2635,34 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
_mesa_tex_target_to_face(textarget) ==
fb->Attachment[BUFFER_STENCIL].CubeMapFace &&
zoffset == fb->Attachment[BUFFER_STENCIL].Zoffset) {
- /* The texture object is already attached to the stencil attachment
- * point. Don't create a new renderbuffer; just reuse the stencil
- * attachment's. This is required to prevent a GL error in
- * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL).
- */
- reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH,
- BUFFER_STENCIL);
+ /* The texture object is already attached to the stencil attachment
+ * point. Don't create a new renderbuffer; just reuse the stencil
+ * attachment's. This is required to prevent a GL error in
+ * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL).
+ */
+ reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH,
+ BUFFER_STENCIL);
} else if (attachment == GL_STENCIL_ATTACHMENT &&
- texObj == fb->Attachment[BUFFER_DEPTH].Texture &&
+ texObj == fb->Attachment[BUFFER_DEPTH].Texture &&
level == fb->Attachment[BUFFER_DEPTH].TextureLevel &&
_mesa_tex_target_to_face(textarget) ==
fb->Attachment[BUFFER_DEPTH].CubeMapFace &&
zoffset == fb->Attachment[BUFFER_DEPTH].Zoffset) {
- /* As above, but with depth and stencil transposed. */
- reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL,
- BUFFER_DEPTH);
+ /* As above, but with depth and stencil transposed. */
+ reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL,
+ BUFFER_DEPTH);
} else {
- set_texture_attachment(ctx, fb, att, texObj, textarget,
- level, zoffset, layered);
- if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
- /* Above we created a new renderbuffer and attached it to the
- * depth attachment point. Now attach it to the stencil attachment
- * point too.
- */
- assert(att == &fb->Attachment[BUFFER_DEPTH]);
- reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL,
- BUFFER_DEPTH);
- }
+ set_texture_attachment(ctx, fb, att, texObj, textarget,
+ level, zoffset, layered);
+ if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
+ /* Above we created a new renderbuffer and attached it to the
+ * depth attachment point. Now attach it to the stencil attachment
+ * point too.
+ */
+ assert(att == &fb->Attachment[BUFFER_DEPTH]);
+ reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL,
+ BUFFER_DEPTH);
+ }
}
/* Set the render-to-texture flag. We'll check this flag in
@@ -2541,8 +2678,8 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
else {
remove_attachment(ctx, att);
if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
- assert(att == &fb->Attachment[BUFFER_DEPTH]);
- remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]);
+ assert(att == &fb->Attachment[BUFFER_DEPTH]);
+ remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]);
}
}
@@ -2721,16 +2858,16 @@ _mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
if (renderbuffer) {
rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
if (!rb) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferRenderbuffer(non-existant"
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFramebufferRenderbuffer(non-existant"
" renderbuffer %u)", renderbuffer);
- return;
+ return;
}
else if (rb == &DummyRenderbuffer) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glFramebufferRenderbuffer(renderbuffer %u)",
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glFramebufferRenderbuffer(renderbuffer %u)",
renderbuffer);
- return;
+ return;
}
}
else {
@@ -2795,9 +2932,9 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
if ((!_mesa_is_desktop_gl(ctx) ||
!ctx->Extensions.ARB_framebuffer_object)
&& !_mesa_is_gles3(ctx)) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glGetFramebufferAttachmentParameteriv(bound FBO = 0)");
- return;
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetFramebufferAttachmentParameteriv(bound FBO = 0)");
+ return;
}
if (_mesa_is_gles3(ctx) && attachment != GL_BACK &&
@@ -2855,10 +2992,10 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
return;
case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
if (att->Type == GL_RENDERBUFFER_EXT) {
- *params = att->Renderbuffer->Name;
+ *params = att->Renderbuffer->Name;
}
else if (att->Type == GL_TEXTURE) {
- *params = att->Texture->Name;
+ *params = att->Texture->Name;
}
else {
assert(att->Type == GL_NONE);
@@ -2871,7 +3008,7 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
return;
case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
if (att->Type == GL_TEXTURE) {
- *params = att->TextureLevel;
+ *params = att->TextureLevel;
}
else if (att->Type == GL_NONE) {
_mesa_error(ctx, err,
diff --git a/mesalib/src/mesa/main/fbobject.h b/mesalib/src/mesa/main/fbobject.h
index 77fdef415..61aa1f503 100644
--- a/mesalib/src/mesa/main/fbobject.h
+++ b/mesalib/src/mesa/main/fbobject.h
@@ -115,6 +115,9 @@ extern void GLAPIENTRY
_mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers);
extern void GLAPIENTRY
+_mesa_CreateRenderbuffers(GLsizei n, GLuint *renderbuffers);
+
+extern void GLAPIENTRY
_mesa_RenderbufferStorage(GLenum target, GLenum internalformat,
GLsizei width, GLsizei height);
@@ -128,12 +131,25 @@ _es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
GLsizei width, GLsizei height);
extern void GLAPIENTRY
+_mesa_NamedRenderbufferStorage(GLuint renderbuffer, GLenum internalformat,
+ GLsizei width, GLsizei height);
+
+extern void GLAPIENTRY
+_mesa_NamedRenderbufferStorageMultisample(GLuint renderbuffer, GLsizei samples,
+ GLenum internalformat,
+ GLsizei width, GLsizei height);
+
+extern void GLAPIENTRY
_mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image);
extern void GLAPIENTRY
_mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname,
GLint *params);
+void GLAPIENTRY
+_mesa_GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname,
+ GLint *params);
+
extern GLboolean GLAPIENTRY
_mesa_IsFramebuffer(GLuint framebuffer);
diff --git a/mesalib/src/mesa/main/ffvertex_prog.c b/mesalib/src/mesa/main/ffvertex_prog.c
index 395b00e15..edf7e3390 100644
--- a/mesalib/src/mesa/main/ffvertex_prog.c
+++ b/mesalib/src/mesa/main/ffvertex_prog.c
@@ -619,13 +619,13 @@ static void emit_op3fn(struct tnl_program *p,
#define emit_op3(p, op, dst, mask, src0, src1, src2) \
- emit_op3fn(p, op, dst, mask, src0, src1, src2, __FUNCTION__, __LINE__)
+ emit_op3fn(p, op, dst, mask, src0, src1, src2, __func__, __LINE__)
#define emit_op2(p, op, dst, mask, src0, src1) \
- emit_op3fn(p, op, dst, mask, src0, src1, undef, __FUNCTION__, __LINE__)
+ emit_op3fn(p, op, dst, mask, src0, src1, undef, __func__, __LINE__)
#define emit_op1(p, op, dst, mask, src0) \
- emit_op3fn(p, op, dst, mask, src0, undef, undef, __FUNCTION__, __LINE__)
+ emit_op3fn(p, op, dst, mask, src0, undef, undef, __func__, __LINE__)
static struct ureg make_temp( struct tnl_program *p, struct ureg reg )
diff --git a/mesalib/src/mesa/main/format_pack.py b/mesalib/src/mesa/main/format_pack.py
index f141da83c..2f43a30dd 100644
--- a/mesalib/src/mesa/main/format_pack.py
+++ b/mesalib/src/mesa/main/format_pack.py
@@ -43,7 +43,6 @@ string = """/*
#include <stdint.h>
-#include "colormac.h"
#include "format_pack.h"
#include "format_utils.h"
#include "macros.h"
diff --git a/mesalib/src/mesa/main/format_unpack.h b/mesalib/src/mesa/main/format_unpack.h
index eba3c6650..964c6077a 100644
--- a/mesalib/src/mesa/main/format_unpack.h
+++ b/mesalib/src/mesa/main/format_unpack.h
@@ -25,6 +25,8 @@
#ifndef FORMAT_UNPACK_H
#define FORMAT_UNPACK_H
+#include "formats.h"
+
extern void
_mesa_unpack_rgba_row(mesa_format format, GLuint n,
const void *src, GLfloat dst[][4]);
diff --git a/mesalib/src/mesa/main/format_unpack.py b/mesalib/src/mesa/main/format_unpack.py
index 53bdf641d..0ae73b897 100644
--- a/mesalib/src/mesa/main/format_unpack.py
+++ b/mesalib/src/mesa/main/format_unpack.py
@@ -43,7 +43,6 @@ string = """/*
#include <stdint.h>
-#include "colormac.h"
#include "format_unpack.h"
#include "format_utils.h"
#include "macros.h"
@@ -333,7 +332,7 @@ _mesa_unpack_rgba_row(mesa_format format, GLuint n,
unpack_float_ycbcr_rev(src, dst, n);
break;
default:
- _mesa_problem(NULL, "%s: bad format %s", __FUNCTION__,
+ _mesa_problem(NULL, "%s: bad format %s", __func__,
_mesa_get_format_name(format));
return;
}
@@ -402,7 +401,7 @@ _mesa_unpack_uint_rgba_row(mesa_format format, GLuint n,
break;
%endfor
default:
- _mesa_problem(NULL, "%s: bad format %s", __FUNCTION__,
+ _mesa_problem(NULL, "%s: bad format %s", __func__,
_mesa_get_format_name(format));
return;
}
diff --git a/mesalib/src/mesa/main/glformats.c b/mesalib/src/mesa/main/glformats.c
index 4e05229cf..8ced57949 100644
--- a/mesalib/src/mesa/main/glformats.c
+++ b/mesalib/src/mesa/main/glformats.c
@@ -1393,7 +1393,7 @@ _mesa_base_format_has_channel(GLenum base_format, GLenum pname)
return GL_FALSE;
default:
_mesa_warning(NULL, "%s: Unexpected channel token 0x%x\n",
- __FUNCTION__, pname);
+ __func__, pname);
return GL_FALSE;
}
diff --git a/mesalib/src/mesa/main/imports.h b/mesalib/src/mesa/main/imports.h
index 29f249980..c4d917ebb 100644
--- a/mesalib/src/mesa/main/imports.h
+++ b/mesalib/src/mesa/main/imports.h
@@ -433,6 +433,30 @@ _mesa_fls(unsigned int n)
#endif
}
+/**
+ * Find the last (most significant) bit set in a uint64_t value.
+ *
+ * Essentially ffsll() in the reverse direction.
+ */
+static inline unsigned int
+_mesa_flsll(uint64_t n)
+{
+#ifdef HAVE___BUILTIN_CLZLL
+ return n == 0 ? 0 : 64 - __builtin_clzll(n);
+#else
+ unsigned int v = 1;
+
+ if (n == 0)
+ return 0;
+
+ while (n >>= 1)
+ v++;
+
+ return v;
+#endif
+}
+
+
extern GLhalfARB
_mesa_float_to_half(float f);
diff --git a/mesalib/src/mesa/main/macros.h b/mesalib/src/mesa/main/macros.h
index 2d7a6a107..3344ec841 100644
--- a/mesalib/src/mesa/main/macros.h
+++ b/mesalib/src/mesa/main/macros.h
@@ -789,7 +789,14 @@ NORMALIZE_3FV(GLfloat v[3])
static inline GLboolean
DIFFERENT_SIGNS(GLfloat x, GLfloat y)
{
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 6334 ) /* sizeof operator applied to an expression with an operator may yield unexpected results */
+#endif
return signbit(x) != signbit(y);
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
}
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index 8e1dba6f0..1c751cfff 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -42,6 +42,7 @@
#include "main/config.h"
#include "glapi/glapi.h"
#include "math/m_matrix.h" /* GLmatrix */
+#include "glsl/shader_enums.h"
#include "util/simple_list.h" /* struct simple_node */
#include "main/formats.h" /* MESA_FORMAT_COUNT */
@@ -280,13 +281,6 @@ typedef enum
/*@}*/
/**
- * Bitflags for system values.
- */
-#define SYSTEM_BIT_SAMPLE_ID BITFIELD64_BIT(SYSTEM_VALUE_SAMPLE_ID)
-#define SYSTEM_BIT_SAMPLE_POS BITFIELD64_BIT(SYSTEM_VALUE_SAMPLE_POS)
-#define SYSTEM_BIT_SAMPLE_MASK_IN BITFIELD64_BIT(SYSTEM_VALUE_SAMPLE_MASK_IN)
-
-/**
* Determine if the given gl_varying_slot appears in the fragment shader.
*/
static inline GLboolean
@@ -395,25 +389,6 @@ typedef enum
BUFFER_BIT_COLOR6 | \
BUFFER_BIT_COLOR7)
-
-/**
- * Shader stages. Note that these will become 5 with tessellation.
- *
- * The order must match how shaders are ordered in the pipeline.
- * The GLSL linker assumes that if i<j, then the j-th shader is
- * executed later than the i-th shader.
- */
-typedef enum
-{
- MESA_SHADER_VERTEX = 0,
- MESA_SHADER_GEOMETRY = 1,
- MESA_SHADER_FRAGMENT = 2,
- MESA_SHADER_COMPUTE = 3,
-} gl_shader_stage;
-
-#define MESA_SHADER_STAGES (MESA_SHADER_COMPUTE + 1)
-
-
/**
* Framebuffer configuration (aka visual / pixelformat)
* Note: some of these fields should be boolean, but it appears that
@@ -1456,7 +1431,6 @@ struct gl_viewport_attrib
GLfloat X, Y; /**< position */
GLfloat Width, Height; /**< size */
GLdouble Near, Far; /**< Depth buffer range */
- GLmatrix _WindowMap; /**< Mapping transformation as a matrix. */
};
@@ -2082,140 +2056,6 @@ typedef enum
/**
- * If the register file is PROGRAM_SYSTEM_VALUE, the register index will be
- * one of these values.
- */
-typedef enum
-{
- /**
- * \name Vertex shader system values
- */
- /*@{*/
- /**
- * OpenGL-style vertex ID.
- *
- * Section 2.11.7 (Shader Execution), subsection Shader Inputs, of the
- * OpenGL 3.3 core profile spec says:
- *
- * "gl_VertexID holds the integer index i implicitly passed by
- * DrawArrays or one of the other drawing commands defined in section
- * 2.8.3."
- *
- * Section 2.8.3 (Drawing Commands) of the same spec says:
- *
- * "The commands....are equivalent to the commands with the same base
- * name (without the BaseVertex suffix), except that the ith element
- * transferred by the corresponding draw call will be taken from
- * element indices[i] + basevertex of each enabled array."
- *
- * Additionally, the overview in the GL_ARB_shader_draw_parameters spec
- * says:
- *
- * "In unextended GL, vertex shaders have inputs named gl_VertexID and
- * gl_InstanceID, which contain, respectively the index of the vertex
- * and instance. The value of gl_VertexID is the implicitly passed
- * index of the vertex being processed, which includes the value of
- * baseVertex, for those commands that accept it."
- *
- * gl_VertexID gets basevertex added in. This differs from DirectX where
- * SV_VertexID does \b not get basevertex added in.
- *
- * \note
- * If all system values are available, \c SYSTEM_VALUE_VERTEX_ID will be
- * equal to \c SYSTEM_VALUE_VERTEX_ID_ZERO_BASE plus
- * \c SYSTEM_VALUE_BASE_VERTEX.
- *
- * \sa SYSTEM_VALUE_VERTEX_ID_ZERO_BASE, SYSTEM_VALUE_BASE_VERTEX
- */
- SYSTEM_VALUE_VERTEX_ID,
-
- /**
- * Instanced ID as supplied to gl_InstanceID
- *
- * Values assigned to gl_InstanceID always begin with zero, regardless of
- * the value of baseinstance.
- *
- * Section 11.1.3.9 (Shader Inputs) of the OpenGL 4.4 core profile spec
- * says:
- *
- * "gl_InstanceID holds the integer instance number of the current
- * primitive in an instanced draw call (see section 10.5)."
- *
- * Through a big chain of pseudocode, section 10.5 describes that
- * baseinstance is not counted by gl_InstanceID. In that section, notice
- *
- * "If an enabled vertex attribute array is instanced (it has a
- * non-zero divisor as specified by VertexAttribDivisor), the element
- * index that is transferred to the GL, for all vertices, is given by
- *
- * floor(instance/divisor) + baseinstance
- *
- * If an array corresponding to an attribute required by a vertex
- * shader is not enabled, then the corresponding element is taken from
- * the current attribute state (see section 10.2)."
- *
- * Note that baseinstance is \b not included in the value of instance.
- */
- SYSTEM_VALUE_INSTANCE_ID,
-
- /**
- * DirectX-style vertex ID.
- *
- * Unlike \c SYSTEM_VALUE_VERTEX_ID, this system value does \b not include
- * the value of basevertex.
- *
- * \sa SYSTEM_VALUE_VERTEX_ID, SYSTEM_VALUE_BASE_VERTEX
- */
- SYSTEM_VALUE_VERTEX_ID_ZERO_BASE,
-
- /**
- * Value of \c basevertex passed to \c glDrawElementsBaseVertex and similar
- * functions.
- *
- * \sa SYSTEM_VALUE_VERTEX_ID, SYSTEM_VALUE_VERTEX_ID_ZERO_BASE
- */
- SYSTEM_VALUE_BASE_VERTEX,
- /*@}*/
-
- /**
- * \name Geometry shader system values
- */
- /*@{*/
- SYSTEM_VALUE_INVOCATION_ID,
- /*@}*/
-
- /**
- * \name Fragment shader system values
- */
- /*@{*/
- SYSTEM_VALUE_FRONT_FACE, /**< (not done yet) */
- SYSTEM_VALUE_SAMPLE_ID,
- SYSTEM_VALUE_SAMPLE_POS,
- SYSTEM_VALUE_SAMPLE_MASK_IN,
- /*@}*/
-
- SYSTEM_VALUE_MAX /**< Number of values */
-} gl_system_value;
-
-
-/**
- * The possible interpolation qualifiers that can be applied to a fragment
- * shader input in GLSL.
- *
- * Note: INTERP_QUALIFIER_NONE must be 0 so that memsetting the
- * gl_fragment_program data structure to 0 causes the default behavior.
- */
-enum glsl_interp_qualifier
-{
- INTERP_QUALIFIER_NONE = 0,
- INTERP_QUALIFIER_SMOOTH,
- INTERP_QUALIFIER_FLAT,
- INTERP_QUALIFIER_NOPERSPECTIVE,
- INTERP_QUALIFIER_COUNT /**< Number of interpolation qualifiers */
-};
-
-
-/**
* \brief Layout qualifiers for gl_FragDepth.
*
* Extension AMD_conservative_depth allows gl_FragDepth to be redeclared with
@@ -2247,6 +2087,8 @@ struct gl_program
struct prog_instruction *Instructions;
+ struct nir_shader *nir;
+
GLbitfield64 InputsRead; /**< Bitmask of which input regs are read */
GLbitfield64 OutputsWritten; /**< Bitmask of which output regs are written */
GLbitfield SystemValuesRead; /**< Bitmask of SYSTEM_VALUE_x inputs used */
@@ -2762,6 +2604,16 @@ struct gl_active_atomic_buffer
};
/**
+ * Active resource in a gl_shader_program
+ */
+struct gl_program_resource
+{
+ GLenum Type; /** Program interface type. */
+ const void *Data; /** Pointer to resource associated data structure. */
+ uint8_t StageReferences; /** Bitmask of shader stage references. */
+};
+
+/**
* A GLSL program object.
* Basically a linked collection of vertex and fragment shaders.
*/
@@ -2935,6 +2787,10 @@ struct gl_shader_program
*/
struct gl_shader *_LinkedShaders[MESA_SHADER_STAGES];
+ /** List of all active resources after linking. */
+ struct gl_program_resource *ProgramResourceList;
+ unsigned NumProgramResourceList;
+
/* True if any of the fragment shaders attached to this program use:
* #extension ARB_fragment_coord_conventions: enable
*/
@@ -3527,8 +3383,8 @@ struct gl_constants
GLboolean ForceGLSLExtensionsWarn;
/**
- * If non-zero, forces GLSL shaders without the #version directive to behave
- * as if they began with "#version ForceGLSLVersion".
+ * If non-zero, forces GLSL shaders to behave as if they began
+ * with "#version ForceGLSLVersion".
*/
GLuint ForceGLSLVersion;
@@ -4523,7 +4379,7 @@ struct gl_context
#ifdef DEBUG
extern int MESA_VERBOSE;
extern int MESA_DEBUG_FLAGS;
-# define MESA_FUNCTION __FUNCTION__
+# define MESA_FUNCTION __func__
#else
# define MESA_VERBOSE 0
# define MESA_DEBUG_FLAGS 0
diff --git a/mesalib/src/mesa/main/multisample.c b/mesalib/src/mesa/main/multisample.c
index 0e9207bc1..816837b95 100644
--- a/mesalib/src/mesa/main/multisample.c
+++ b/mesalib/src/mesa/main/multisample.c
@@ -150,6 +150,15 @@ GLenum
_mesa_check_sample_count(struct gl_context *ctx, GLenum target,
GLenum internalFormat, GLsizei samples)
{
+ /* Section 2.5 (GL Errors) of OpenGL 3.0 specification, page 16:
+ *
+ * "If a negative number is provided where an argument of type sizei or
+ * sizeiptr is specified, the error INVALID VALUE is generated."
+ */
+ if (samples < 0) {
+ return GL_INVALID_VALUE;
+ }
+
/* Section 4.4 (Framebuffer objects), page 198 of the OpenGL ES 3.0.0
* specification says:
*
diff --git a/mesalib/src/mesa/main/pipelineobj.c b/mesalib/src/mesa/main/pipelineobj.c
index fb241af1e..0fefa7d56 100644
--- a/mesalib/src/mesa/main/pipelineobj.c
+++ b/mesalib/src/mesa/main/pipelineobj.c
@@ -498,16 +498,18 @@ _mesa_DeleteProgramPipelines(GLsizei n, const GLuint *pipelines)
* \param n Number of IDs to generate.
* \param pipelines pipeline of \c n locations to store the IDs.
*/
-void GLAPIENTRY
-_mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines)
+static void
+create_program_pipelines(struct gl_context *ctx, GLsizei n, GLuint *pipelines,
+ bool dsa)
{
- GET_CURRENT_CONTEXT(ctx);
-
+ const char *func;
GLuint first;
GLint i;
+ func = dsa ? "glCreateProgramPipelines" : "glGenProgramPipelines";
+
if (n < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGenProgramPipelines(n<0)");
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s (n < 0)", func);
return;
}
@@ -523,16 +525,37 @@ _mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines)
obj = _mesa_new_pipeline_object(ctx, name);
if (!obj) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenProgramPipelines");
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
return;
}
+ if (dsa) {
+ /* make dsa-allocated objects behave like program objects */
+ obj->EverBound = GL_TRUE;
+ }
+
save_pipeline_object(ctx, obj);
pipelines[i] = first + i;
}
}
+void GLAPIENTRY
+_mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ create_program_pipelines(ctx, n, pipelines, false);
+}
+
+void GLAPIENTRY
+_mesa_CreateProgramPipelines(GLsizei n, GLuint *pipelines)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ create_program_pipelines(ctx, n, pipelines, true);
+}
+
/**
* Determine if ID is the name of an pipeline object.
*
diff --git a/mesalib/src/mesa/main/pipelineobj.h b/mesalib/src/mesa/main/pipelineobj.h
index 7285a78f1..b57bcb99e 100644
--- a/mesalib/src/mesa/main/pipelineobj.h
+++ b/mesalib/src/mesa/main/pipelineobj.h
@@ -82,6 +82,9 @@ _mesa_DeleteProgramPipelines(GLsizei n, const GLuint *pipelines);
extern void GLAPIENTRY
_mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines);
+void GLAPIENTRY
+_mesa_CreateProgramPipelines(GLsizei n, GLuint *pipelines);
+
extern GLboolean GLAPIENTRY
_mesa_IsProgramPipeline(GLuint pipeline);
diff --git a/mesalib/src/mesa/main/pixel.c b/mesalib/src/mesa/main/pixel.c
index 7162c6fef..ecda2694f 100644
--- a/mesalib/src/mesa/main/pixel.c
+++ b/mesalib/src/mesa/main/pixel.c
@@ -30,7 +30,6 @@
#include "glheader.h"
#include "bufferobj.h"
-#include "colormac.h"
#include "context.h"
#include "macros.h"
#include "pixel.h"
diff --git a/mesalib/src/mesa/main/pixeltransfer.c b/mesalib/src/mesa/main/pixeltransfer.c
index 8bbeeb853..94464ea67 100644
--- a/mesalib/src/mesa/main/pixeltransfer.c
+++ b/mesalib/src/mesa/main/pixeltransfer.c
@@ -31,7 +31,7 @@
#include "glheader.h"
-#include "colormac.h"
+#include "macros.h"
#include "pixeltransfer.h"
#include "imports.h"
#include "mtypes.h"
diff --git a/mesalib/src/mesa/main/program_resource.c b/mesalib/src/mesa/main/program_resource.c
new file mode 100644
index 000000000..b15a13210
--- /dev/null
+++ b/mesalib/src/mesa/main/program_resource.c
@@ -0,0 +1,417 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2015 Intel Corporation. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "main/enums.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
+#include "main/shaderapi.h"
+#include "main/shaderobj.h"
+#include "program_resource.h"
+
+static bool
+supported_interface_enum(GLenum iface)
+{
+ switch (iface) {
+ case GL_UNIFORM:
+ case GL_UNIFORM_BLOCK:
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ case GL_ATOMIC_COUNTER_BUFFER:
+ return true;
+ case GL_VERTEX_SUBROUTINE:
+ case GL_TESS_CONTROL_SUBROUTINE:
+ case GL_TESS_EVALUATION_SUBROUTINE:
+ case GL_GEOMETRY_SUBROUTINE:
+ case GL_FRAGMENT_SUBROUTINE:
+ case GL_COMPUTE_SUBROUTINE:
+ case GL_VERTEX_SUBROUTINE_UNIFORM:
+ case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
+ case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
+ case GL_GEOMETRY_SUBROUTINE_UNIFORM:
+ case GL_FRAGMENT_SUBROUTINE_UNIFORM:
+ case GL_COMPUTE_SUBROUTINE_UNIFORM:
+ case GL_BUFFER_VARIABLE:
+ case GL_SHADER_STORAGE_BLOCK:
+ default:
+ return false;
+ }
+}
+
+void GLAPIENTRY
+_mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface,
+ GLenum pname, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ unsigned i;
+ struct gl_shader_program *shProg =
+ _mesa_lookup_shader_program_err(ctx, program,
+ "glGetProgramInterfaceiv");
+ if (!shProg)
+ return;
+
+ if (!params) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetProgramInterfaceiv(params NULL)");
+ return;
+ }
+
+ /* Validate interface. */
+ if (!supported_interface_enum(programInterface)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramInterfaceiv(%s)",
+ _mesa_lookup_enum_by_nr(programInterface));
+ return;
+ }
+
+ /* Validate pname against interface. */
+ switch(pname) {
+ case GL_ACTIVE_RESOURCES:
+ for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++)
+ if (shProg->ProgramResourceList[i].Type == programInterface)
+ (*params)++;
+ break;
+ case GL_MAX_NAME_LENGTH:
+ if (programInterface == GL_ATOMIC_COUNTER_BUFFER) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetProgramInterfaceiv(%s pname %s)",
+ _mesa_lookup_enum_by_nr(programInterface),
+ _mesa_lookup_enum_by_nr(pname));
+ return;
+ }
+ /* Name length consists of base name, 3 additional chars '[0]' if
+ * resource is an array and finally 1 char for string terminator.
+ */
+ for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
+ if (shProg->ProgramResourceList[i].Type != programInterface)
+ continue;
+ const char *name =
+ _mesa_program_resource_name(&shProg->ProgramResourceList[i]);
+ unsigned array_size =
+ _mesa_program_resource_array_size(&shProg->ProgramResourceList[i]);
+ *params = MAX2(*params, strlen(name) + (array_size ? 3 : 0) + 1);
+ }
+ break;
+ case GL_MAX_NUM_ACTIVE_VARIABLES:
+ switch (programInterface) {
+ case GL_UNIFORM_BLOCK:
+ for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
+ if (shProg->ProgramResourceList[i].Type == programInterface) {
+ struct gl_uniform_block *block =
+ (struct gl_uniform_block *)
+ shProg->ProgramResourceList[i].Data;
+ *params = MAX2(*params, block->NumUniforms);
+ }
+ }
+ break;
+ case GL_ATOMIC_COUNTER_BUFFER:
+ for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
+ if (shProg->ProgramResourceList[i].Type == programInterface) {
+ struct gl_active_atomic_buffer *buffer =
+ (struct gl_active_atomic_buffer *)
+ shProg->ProgramResourceList[i].Data;
+ *params = MAX2(*params, buffer->NumUniforms);
+ }
+ }
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetProgramInterfaceiv(%s pname %s)",
+ _mesa_lookup_enum_by_nr(programInterface),
+ _mesa_lookup_enum_by_nr(pname));
+ };
+ break;
+ case GL_MAX_NUM_COMPATIBLE_SUBROUTINES:
+ default:
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetProgramInterfaceiv(pname %s)",
+ _mesa_lookup_enum_by_nr(pname));
+ }
+}
+
+static bool
+is_xfb_marker(const char *str)
+{
+ static const char *markers[] = {
+ "gl_NextBuffer",
+ "gl_SkipComponents1",
+ "gl_SkipComponents2",
+ "gl_SkipComponents3",
+ "gl_SkipComponents4",
+ NULL
+ };
+ const char **m = markers;
+
+ if (strncmp(str, "gl_", 3) != 0)
+ return false;
+
+ for (; *m; m++)
+ if (strcmp(*m, str) == 0)
+ return true;
+
+ return false;
+}
+
+/**
+ * Checks if given name index is legal for GetProgramResourceIndex,
+ * check is written to be compatible with GL_ARB_array_of_arrays.
+ */
+static bool
+valid_program_resource_index_name(const GLchar *name)
+{
+ const char *array = strstr(name, "[");
+ const char *close = strrchr(name, ']');
+
+ /* Not array, no need for the check. */
+ if (!array)
+ return true;
+
+ /* Last array index has to be zero. */
+ if (!close || *--close != '0')
+ return false;
+
+ return true;
+}
+
+GLuint GLAPIENTRY
+_mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface,
+ const GLchar *name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_program_resource *res;
+ struct gl_shader_program *shProg =
+ _mesa_lookup_shader_program_err(ctx, program,
+ "glGetProgramResourceIndex");
+ if (!shProg || !name)
+ return GL_INVALID_INDEX;
+
+ /*
+ * For the interface TRANSFORM_FEEDBACK_VARYING, the value INVALID_INDEX
+ * should be returned when querying the index assigned to the special names
+ * "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2",
+ * "gl_SkipComponents3", and "gl_SkipComponents4".
+ */
+ if (programInterface == GL_TRANSFORM_FEEDBACK_VARYING &&
+ is_xfb_marker(name))
+ return GL_INVALID_INDEX;
+
+ switch (programInterface) {
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ case GL_UNIFORM:
+ case GL_UNIFORM_BLOCK:
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ /* Validate name syntax for arrays. */
+ if (!valid_program_resource_index_name(name))
+ return GL_INVALID_INDEX;
+
+ res = _mesa_program_resource_find_name(shProg, programInterface, name);
+ if (!res)
+ return GL_INVALID_INDEX;
+
+ return _mesa_program_resource_index(shProg, res);
+ case GL_ATOMIC_COUNTER_BUFFER:
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)",
+ _mesa_lookup_enum_by_nr(programInterface));
+ }
+
+ return GL_INVALID_INDEX;
+}
+
+void GLAPIENTRY
+_mesa_GetProgramResourceName(GLuint program, GLenum programInterface,
+ GLuint index, GLsizei bufSize, GLsizei *length,
+ GLchar *name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg =
+ _mesa_lookup_shader_program_err(ctx, program,
+ "glGetProgramResourceName");
+
+ /* Set user friendly return values in case of errors. */
+ if (name)
+ *name = '\0';
+ if (length)
+ *length = 0;
+
+ if (!shProg || !name)
+ return;
+
+ if (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
+ !supported_interface_enum(programInterface)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceName(%s)",
+ _mesa_lookup_enum_by_nr(programInterface));
+ return;
+ }
+
+ _mesa_get_program_resource_name(shProg, programInterface, index, bufSize,
+ length, name, "glGetProgramResourceName");
+}
+
+void GLAPIENTRY
+_mesa_GetProgramResourceiv(GLuint program, GLenum programInterface,
+ GLuint index, GLsizei propCount,
+ const GLenum *props, GLsizei bufSize,
+ GLsizei *length, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg =
+ _mesa_lookup_shader_program_err(ctx, program, "glGetProgramResourceiv");
+
+ if (!shProg || !params)
+ return;
+
+ /* The error INVALID_VALUE is generated if <propCount> is zero.
+ * Note that we check < 0 here because it makes sense to bail early.
+ */
+ if (propCount <= 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetProgramResourceiv(propCount <= 0)");
+ return;
+ }
+
+ /* No need to write any properties, user requested none. */
+ if (bufSize == 0)
+ return;
+
+ _mesa_get_program_resourceiv(shProg, programInterface, index,
+ propCount, props, bufSize, length, params);
+}
+
+/**
+ * Function verifies syntax of given name for GetProgramResourceLocation
+ * and GetProgramResourceLocationIndex for the following cases:
+ *
+ * "array element portion of a string passed to GetProgramResourceLocation
+ * or GetProgramResourceLocationIndex must not have, a "+" sign, extra
+ * leading zeroes, or whitespace".
+ *
+ * Check is written to be compatible with GL_ARB_array_of_arrays.
+ */
+static bool
+invalid_array_element_syntax(const GLchar *name)
+{
+ char *first = strchr(name, '[');
+ char *last = strrchr(name, '[');
+
+ if (!first)
+ return false;
+
+ /* No '+' or ' ' allowed anywhere. */
+ if (strchr(first, '+') || strchr(first, ' '))
+ return true;
+
+ /* Check that last array index is 0. */
+ if (last[1] == '0' && last[2] != ']')
+ return true;
+
+ return false;
+}
+
+static struct gl_shader_program *
+lookup_linked_program(GLuint program, const char *caller)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *prog =
+ _mesa_lookup_shader_program_err(ctx, program, caller);
+
+ if (!prog)
+ return NULL;
+
+ if (prog->LinkStatus == GL_FALSE) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
+ caller);
+ return NULL;
+ }
+ return prog;
+}
+
+GLint GLAPIENTRY
+_mesa_GetProgramResourceLocation(GLuint program, GLenum programInterface,
+ const GLchar *name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg =
+ lookup_linked_program(program, "glGetProgramResourceLocation");
+
+ if (!shProg || !name || invalid_array_element_syntax(name))
+ return -1;
+
+ /* Validate programInterface. */
+ switch (programInterface) {
+ case GL_UNIFORM:
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ break;
+
+ /* For reference valid cases requiring additional extension support:
+ * GL_ARB_shader_subroutine
+ * GL_ARB_tessellation_shader
+ * GL_ARB_compute_shader
+ */
+ case GL_VERTEX_SUBROUTINE_UNIFORM:
+ case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
+ case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
+ case GL_GEOMETRY_SUBROUTINE_UNIFORM:
+ case GL_FRAGMENT_SUBROUTINE_UNIFORM:
+ case GL_COMPUTE_SUBROUTINE_UNIFORM:
+
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceLocation(%s %s)",
+ _mesa_lookup_enum_by_nr(programInterface), name);
+ }
+
+ return _mesa_program_resource_location(shProg, programInterface, name);
+}
+
+/**
+ * Returns output index for dual source blending.
+ */
+GLint GLAPIENTRY
+_mesa_GetProgramResourceLocationIndex(GLuint program, GLenum programInterface,
+ const GLchar *name)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg =
+ lookup_linked_program(program, "glGetProgramResourceLocationIndex");
+
+ if (!shProg || !name || invalid_array_element_syntax(name))
+ return -1;
+
+ /* From the GL_ARB_program_interface_query spec:
+ *
+ * "For GetProgramResourceLocationIndex, <programInterface> must be
+ * PROGRAM_OUTPUT."
+ */
+ if (programInterface != GL_PROGRAM_OUTPUT) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetProgramResourceLocationIndex(%s)",
+ _mesa_lookup_enum_by_nr(programInterface));
+ return -1;
+ }
+
+ return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT,
+ name);
+}
diff --git a/mesalib/src/mesa/main/program_resource.h b/mesalib/src/mesa/main/program_resource.h
new file mode 100644
index 000000000..326ae1f93
--- /dev/null
+++ b/mesalib/src/mesa/main/program_resource.h
@@ -0,0 +1,58 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 2015 Intel Corporation. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef PROGRAM_RESOURCE_H
+#define PROGRAM_RESOURCE_H
+
+#include "glheader.h"
+
+extern void GLAPIENTRY
+_mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface,
+ GLenum pname, GLint *params);
+
+extern GLuint GLAPIENTRY
+_mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface,
+ const GLchar *name);
+
+extern void GLAPIENTRY
+_mesa_GetProgramResourceName(GLuint program, GLenum programInterface,
+ GLuint index, GLsizei bufSize, GLsizei *length,
+ GLchar *name);
+
+extern void GLAPIENTRY
+_mesa_GetProgramResourceiv(GLuint program, GLenum programInterface,
+ GLuint index, GLsizei propCount,
+ const GLenum *props, GLsizei bufSize,
+ GLsizei *length, GLint *params);
+
+extern GLint GLAPIENTRY
+_mesa_GetProgramResourceLocation(GLuint program, GLenum programInterface,
+ const GLchar *name);
+
+extern GLint GLAPIENTRY
+_mesa_GetProgramResourceLocationIndex(GLuint program, GLenum programInterface,
+ const GLchar *name);
+
+#endif
diff --git a/mesalib/src/mesa/main/queryobj.c b/mesalib/src/mesa/main/queryobj.c
index 0842b540d..fbccf3fe6 100644
--- a/mesalib/src/mesa/main/queryobj.c
+++ b/mesalib/src/mesa/main/queryobj.c
@@ -233,18 +233,22 @@ get_query_binding_point(struct gl_context *ctx, GLenum target, GLuint index)
}
}
-
-void GLAPIENTRY
-_mesa_GenQueries(GLsizei n, GLuint *ids)
+/**
+ * Create $n query objects and store them in *ids. Make them of type $target
+ * if dsa is set. Called from _mesa_GenQueries() and _mesa_CreateQueries().
+ */
+static void
+create_queries(struct gl_context *ctx, GLenum target, GLsizei n, GLuint *ids,
+ bool dsa)
{
+ const char *func = dsa ? "glGenQueries" : "glCreateQueries";
GLuint first;
- GET_CURRENT_CONTEXT(ctx);
if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glGenQueries(%d)\n", n);
+ _mesa_debug(ctx, "%s(%d)\n", func, n);
if (n < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGenQueriesARB(n < 0)");
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
return;
}
@@ -255,8 +259,12 @@ _mesa_GenQueries(GLsizei n, GLuint *ids)
struct gl_query_object *q
= ctx->Driver.NewQueryObject(ctx, first + i);
if (!q) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenQueriesARB");
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
return;
+ } else if (dsa) {
+ /* Do the equivalent of binding the buffer with a target */
+ q->Target = target;
+ q->EverBound = GL_TRUE;
}
ids[i] = first + i;
_mesa_HashInsert(ctx->Query.QueryObjects, first + i, q);
@@ -264,6 +272,36 @@ _mesa_GenQueries(GLsizei n, GLuint *ids)
}
}
+void GLAPIENTRY
+_mesa_GenQueries(GLsizei n, GLuint *ids)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ create_queries(ctx, 0, n, ids, false);
+}
+
+void GLAPIENTRY
+_mesa_CreateQueries(GLenum target, GLsizei n, GLuint *ids)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ switch (target) {
+ case GL_SAMPLES_PASSED:
+ case GL_ANY_SAMPLES_PASSED:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+ case GL_TIME_ELAPSED:
+ case GL_TIMESTAMP:
+ case GL_PRIMITIVES_GENERATED:
+ case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCreateQueries(invalid target = %s)",
+ _mesa_lookup_enum_by_nr(target));
+ return;
+ }
+
+ create_queries(ctx, target, n, ids, true);
+}
+
void GLAPIENTRY
_mesa_DeleteQueries(GLsizei n, const GLuint *ids)
@@ -424,6 +462,18 @@ _mesa_BeginQueryIndexed(GLenum target, GLuint index, GLuint id)
}
}
+ /* This possibly changes the target of a buffer allocated by
+ * CreateQueries. Issue 39) in the ARB_direct_state_access extension states
+ * the following:
+ *
+ * "CreateQueries adds a <target>, so strictly speaking the <target>
+ * command isn't needed for BeginQuery/EndQuery, but in the end, this also
+ * isn't a selector, so we decided not to change it."
+ *
+ * Updating the target of the query object should be acceptable, so let's
+ * do that.
+ */
+
q->Target = target;
q->Active = GL_TRUE;
q->Result = 0;
@@ -541,6 +591,18 @@ _mesa_QueryCounter(GLuint id, GLenum target)
return;
}
+ /* This possibly changes the target of a buffer allocated by
+ * CreateQueries. Issue 39) in the ARB_direct_state_access extension states
+ * the following:
+ *
+ * "CreateQueries adds a <target>, so strictly speaking the <target>
+ * command isn't needed for BeginQuery/EndQuery, but in the end, this also
+ * isn't a selector, so we decided not to change it."
+ *
+ * Updating the target of the query object should be acceptable, so let's
+ * do that.
+ */
+
q->Target = target;
q->Result = 0;
q->Ready = GL_FALSE;
@@ -710,8 +772,8 @@ _mesa_GetQueryObjectiv(GLuint id, GLenum pname, GLint *params)
}
break;
case GL_QUERY_RESULT_AVAILABLE_ARB:
- if (!q->Ready)
- ctx->Driver.CheckQuery( ctx, q );
+ if (!q->Ready)
+ ctx->Driver.CheckQuery( ctx, q );
*params = q->Ready;
break;
default:
@@ -761,8 +823,8 @@ _mesa_GetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)
}
break;
case GL_QUERY_RESULT_AVAILABLE_ARB:
- if (!q->Ready)
- ctx->Driver.CheckQuery( ctx, q );
+ if (!q->Ready)
+ ctx->Driver.CheckQuery( ctx, q );
*params = q->Ready;
break;
default:
@@ -801,8 +863,8 @@ _mesa_GetQueryObjecti64v(GLuint id, GLenum pname, GLint64EXT *params)
*params = q->Result;
break;
case GL_QUERY_RESULT_AVAILABLE_ARB:
- if (!q->Ready)
- ctx->Driver.CheckQuery( ctx, q );
+ if (!q->Ready)
+ ctx->Driver.CheckQuery( ctx, q );
*params = q->Ready;
break;
default:
@@ -841,8 +903,8 @@ _mesa_GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64EXT *params)
*params = q->Result;
break;
case GL_QUERY_RESULT_AVAILABLE_ARB:
- if (!q->Ready)
- ctx->Driver.CheckQuery( ctx, q );
+ if (!q->Ready)
+ ctx->Driver.CheckQuery( ctx, q );
*params = q->Ready;
break;
default:
@@ -852,6 +914,45 @@ _mesa_GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64EXT *params)
}
/**
+ * New with GL_ARB_query_buffer_object
+ */
+void GLAPIENTRY
+_mesa_GetQueryBufferObjectiv(GLuint id, GLuint buffer, GLenum pname,
+ GLintptr offset)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryBufferObjectiv");
+}
+
+
+void GLAPIENTRY
+_mesa_GetQueryBufferObjectuiv(GLuint id, GLuint buffer, GLenum pname,
+ GLintptr offset)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryBufferObjectuiv");
+}
+
+
+void GLAPIENTRY
+_mesa_GetQueryBufferObjecti64v(GLuint id, GLuint buffer, GLenum pname,
+ GLintptr offset)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryBufferObjecti64v");
+}
+
+
+void GLAPIENTRY
+_mesa_GetQueryBufferObjectui64v(GLuint id, GLuint buffer, GLenum pname,
+ GLintptr offset)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryBufferObjectui64v");
+}
+
+
+/**
* Allocate/init the context state related to query objects.
*/
void
diff --git a/mesalib/src/mesa/main/queryobj.h b/mesalib/src/mesa/main/queryobj.h
index 6cbcabd46..d1036fcce 100644
--- a/mesalib/src/mesa/main/queryobj.h
+++ b/mesalib/src/mesa/main/queryobj.h
@@ -51,6 +51,8 @@ _mesa_free_queryobj_data(struct gl_context *ctx);
void GLAPIENTRY
_mesa_GenQueries(GLsizei n, GLuint *ids);
void GLAPIENTRY
+_mesa_CreateQueries(GLenum target, GLsizei n, GLuint *ids);
+void GLAPIENTRY
_mesa_DeleteQueries(GLsizei n, const GLuint *ids);
GLboolean GLAPIENTRY
_mesa_IsQuery(GLuint id);
@@ -77,5 +79,17 @@ void GLAPIENTRY
_mesa_GetQueryObjecti64v(GLuint id, GLenum pname, GLint64EXT *params);
void GLAPIENTRY
_mesa_GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64EXT *params);
+void GLAPIENTRY
+_mesa_GetQueryBufferObjectiv(GLuint id, GLuint buffer, GLenum pname,
+ GLintptr offset);
+void GLAPIENTRY
+_mesa_GetQueryBufferObjectuiv(GLuint id, GLuint buffer, GLenum pname,
+ GLintptr offset);
+void GLAPIENTRY
+_mesa_GetQueryBufferObjecti64v(GLuint id, GLuint buffer, GLenum pname,
+ GLintptr offset);
+void GLAPIENTRY
+_mesa_GetQueryBufferObjectui64v(GLuint id, GLuint buffer, GLenum pname,
+ GLintptr offset);
#endif /* QUERYOBJ_H */
diff --git a/mesalib/src/mesa/main/samplerobj.c b/mesalib/src/mesa/main/samplerobj.c
index d66b0b5e8..a3aacc66a 100644
--- a/mesalib/src/mesa/main/samplerobj.c
+++ b/mesalib/src/mesa/main/samplerobj.c
@@ -181,19 +181,18 @@ _mesa_delete_sampler_object(struct gl_context *ctx,
free(sampObj);
}
-
-void GLAPIENTRY
-_mesa_GenSamplers(GLsizei count, GLuint *samplers)
+static void
+create_samplers(struct gl_context *ctx, GLsizei count, GLuint *samplers,
+ const char *caller)
{
- GET_CURRENT_CONTEXT(ctx);
GLuint first;
GLint i;
if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glGenSamplers(%d)\n", count);
+ _mesa_debug(ctx, "%s(%d)\n", caller, count);
if (count < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGenSamplers");
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", caller);
return;
}
@@ -211,6 +210,20 @@ _mesa_GenSamplers(GLsizei count, GLuint *samplers)
}
}
+void GLAPIENTRY
+_mesa_GenSamplers(GLsizei count, GLuint *samplers)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ create_samplers(ctx, count, samplers, "glGenSamplers");
+}
+
+void GLAPIENTRY
+_mesa_CreateSamplers(GLsizei count, GLuint *samplers)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ create_samplers(ctx, count, samplers, "glCreateSamplers");
+}
+
void GLAPIENTRY
_mesa_DeleteSamplers(GLsizei count, const GLuint *samplers)
diff --git a/mesalib/src/mesa/main/samplerobj.h b/mesalib/src/mesa/main/samplerobj.h
index 1bb3193e4..7bea91114 100644
--- a/mesalib/src/mesa/main/samplerobj.h
+++ b/mesalib/src/mesa/main/samplerobj.h
@@ -32,6 +32,9 @@ extern "C" {
#endif
+#include "mtypes.h"
+
+
struct dd_function_table;
static inline struct gl_sampler_object *
@@ -80,6 +83,8 @@ _mesa_init_sampler_object_functions(struct dd_function_table *driver);
void GLAPIENTRY
_mesa_GenSamplers(GLsizei count, GLuint *samplers);
void GLAPIENTRY
+_mesa_CreateSamplers(GLsizei count, GLuint *samplers);
+void GLAPIENTRY
_mesa_DeleteSamplers(GLsizei count, const GLuint *samplers);
GLboolean GLAPIENTRY
_mesa_IsSampler(GLuint sampler);
diff --git a/mesalib/src/mesa/main/shader_query.cpp b/mesalib/src/mesa/main/shader_query.cpp
index df9081b73..b5f1d082c 100644
--- a/mesalib/src/mesa/main/shader_query.cpp
+++ b/mesalib/src/mesa/main/shader_query.cpp
@@ -34,11 +34,33 @@
#include "shaderobj.h"
#include "program/hash_table.h"
#include "../glsl/program.h"
+#include "uniforms.h"
+#include "main/enums.h"
extern "C" {
#include "shaderapi.h"
}
+static GLint
+program_resource_location(struct gl_shader_program *shProg,
+ struct gl_program_resource *res, const char *name);
+
+/**
+ * Declare convenience functions to return resource data in a given type.
+ * Warning! this is not type safe so be *very* careful when using these.
+ */
+#define DECL_RESOURCE_FUNC(name, type) \
+const type * RESOURCE_ ## name (gl_program_resource *res) { \
+ assert(res->Data); \
+ return (type *) res->Data; \
+}
+
+DECL_RESOURCE_FUNC(VAR, ir_variable);
+DECL_RESOURCE_FUNC(UBO, gl_uniform_block);
+DECL_RESOURCE_FUNC(UNI, gl_uniform_storage);
+DECL_RESOURCE_FUNC(ATC, gl_active_atomic_buffer);
+DECL_RESOURCE_FUNC(XFB, gl_transform_feedback_varying_info);
+
void GLAPIENTRY
_mesa_BindAttribLocation(GLhandleARB program, GLuint index,
const GLcharARB *name)
@@ -129,45 +151,41 @@ _mesa_GetActiveAttrib(GLhandleARB program, GLuint desired_index,
return;
}
- exec_list *const ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir;
- unsigned current_index = 0;
-
- foreach_in_list(ir_instruction, node, ir) {
- const ir_variable *const var = node->as_variable();
-
- if (!is_active_attrib(var))
- continue;
+ struct gl_program_resource *res =
+ _mesa_program_resource_find_index(shProg, GL_PROGRAM_INPUT,
+ desired_index);
- if (current_index == desired_index) {
- const char *var_name = var->name;
+ /* User asked for index that does not exist. */
+ if (!res) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
+ return;
+ }
- /* Since gl_VertexID may be lowered to gl_VertexIDMESA, we need to
- * consider gl_VertexIDMESA as gl_VertexID for purposes of checking
- * active attributes.
- */
- if (var->data.mode == ir_var_system_value &&
- var->data.location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) {
- var_name = "gl_VertexID";
- }
+ const ir_variable *const var = RESOURCE_VAR(res);
- _mesa_copy_string(name, maxLength, length, var_name);
+ if (!is_active_attrib(var))
+ return;
- if (size)
- *size = (var->type->is_array()) ? var->type->length : 1;
+ const char *var_name = var->name;
- if (type)
- *type = var->type->gl_type;
+ /* Since gl_VertexID may be lowered to gl_VertexIDMESA, we need to
+ * consider gl_VertexIDMESA as gl_VertexID for purposes of checking
+ * active attributes.
+ */
+ if (var->data.mode == ir_var_system_value &&
+ var->data.location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) {
+ var_name = "gl_VertexID";
+ }
- return;
- }
+ _mesa_copy_string(name, maxLength, length, var_name);
- current_index++;
- }
+ if (size)
+ _mesa_program_resource_prop(shProg, res, desired_index, GL_ARRAY_SIZE,
+ size, "glGetActiveAttrib");
- /* If the loop did not return early, the caller must have asked for
- * an index that did not exit. Set an error.
- */
- _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
+ if (type)
+ _mesa_program_resource_prop(shProg, res, desired_index, GL_TYPE,
+ (GLint *) type, "glGetActiveAttrib");
}
/* Locations associated with shader variables (array or non-array) can be
@@ -252,31 +270,25 @@ _mesa_GetAttribLocation(GLhandleARB program, const GLcharARB * name)
if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL)
return -1;
- exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir;
- foreach_in_list(ir_instruction, node, ir) {
- const ir_variable *const var = node->as_variable();
-
- /* The extra check against VERT_ATTRIB_GENERIC0 is because
- * glGetAttribLocation cannot be used on "conventional" attributes.
- *
- * From page 95 of the OpenGL 3.0 spec:
- *
- * "If name is not an active attribute, if name is a conventional
- * attribute, or if an error occurs, -1 will be returned."
- */
- if (var == NULL
- || var->data.mode != ir_var_shader_in
- || var->data.location == -1
- || var->data.location < VERT_ATTRIB_GENERIC0)
- continue;
-
- int index = get_matching_index(var, (const char *) name);
+ struct gl_program_resource *res =
+ _mesa_program_resource_find_name(shProg, GL_PROGRAM_INPUT, name);
- if (index >= 0)
- return var->data.location + index - VERT_ATTRIB_GENERIC0;
- }
+ if (!res)
+ return -1;
- return -1;
+ GLint loc = program_resource_location(shProg, res, name);
+
+ /* The extra check against against 0 is made because of builtin-attribute
+ * locations that have offset applied. Function program_resource_location
+ * can return built-in attribute locations < 0 and glGetAttribLocation
+ * cannot be used on "conventional" attributes.
+ *
+ * From page 95 of the OpenGL 3.0 spec:
+ *
+ * "If name is not an active attribute, if name is a conventional
+ * attribute, or if an error occurs, -1 will be returned."
+ */
+ return (loc >= 0) ? loc : -1;
}
@@ -416,29 +428,8 @@ _mesa_GetFragDataIndex(GLuint program, const GLchar *name)
if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
return -1;
- exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir;
- foreach_in_list(ir_instruction, node, ir) {
- const ir_variable *const var = node->as_variable();
-
- /* The extra check against FRAG_RESULT_DATA0 is because
- * glGetFragDataLocation cannot be used on "conventional" attributes.
- *
- * From page 95 of the OpenGL 3.0 spec:
- *
- * "If name is not an active attribute, if name is a conventional
- * attribute, or if an error occurs, -1 will be returned."
- */
- if (var == NULL
- || var->data.mode != ir_var_shader_out
- || var->data.location == -1
- || var->data.location < FRAG_RESULT_DATA0)
- continue;
-
- if (get_matching_index(var, (const char *) name) >= 0)
- return var->data.index;
- }
-
- return -1;
+ return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT,
+ name);
}
GLint GLAPIENTRY
@@ -472,29 +463,612 @@ _mesa_GetFragDataLocation(GLuint program, const GLchar *name)
if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
return -1;
- exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir;
- foreach_in_list(ir_instruction, node, ir) {
- const ir_variable *const var = node->as_variable();
+ struct gl_program_resource *res =
+ _mesa_program_resource_find_name(shProg, GL_PROGRAM_OUTPUT, name);
- /* The extra check against FRAG_RESULT_DATA0 is because
- * glGetFragDataLocation cannot be used on "conventional" attributes.
- *
- * From page 95 of the OpenGL 3.0 spec:
+ if (!res)
+ return -1;
+
+ GLint loc = program_resource_location(shProg, res, name);
+
+ /* The extra check against against 0 is made because of builtin-attribute
+ * locations that have offset applied. Function program_resource_location
+ * can return built-in attribute locations < 0 and glGetFragDataLocation
+ * cannot be used on "conventional" attributes.
+ *
+ * From page 95 of the OpenGL 3.0 spec:
+ *
+ * "If name is not an active attribute, if name is a conventional
+ * attribute, or if an error occurs, -1 will be returned."
+ */
+ return (loc >= 0) ? loc : -1;
+}
+
+const char*
+_mesa_program_resource_name(struct gl_program_resource *res)
+{
+ switch (res->Type) {
+ case GL_UNIFORM_BLOCK:
+ return RESOURCE_UBO(res)->Name;
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ return RESOURCE_XFB(res)->Name;
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ return RESOURCE_VAR(res)->name;
+ case GL_UNIFORM:
+ return RESOURCE_UNI(res)->name;
+ default:
+ assert(!"support for resource type not implemented");
+ }
+ return NULL;
+}
+
+
+unsigned
+_mesa_program_resource_array_size(struct gl_program_resource *res)
+{
+ switch (res->Type) {
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ return RESOURCE_XFB(res)->Size > 1 ?
+ RESOURCE_XFB(res)->Size : 0;
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ return RESOURCE_VAR(res)->data.max_array_access;
+ case GL_UNIFORM:
+ return RESOURCE_UNI(res)->array_elements;
+ case GL_ATOMIC_COUNTER_BUFFER:
+ case GL_UNIFORM_BLOCK:
+ return 0;
+ default:
+ assert(!"support for resource type not implemented");
+ }
+ return 0;
+}
+
+static int
+array_index_of_resource(struct gl_program_resource *res,
+ const char *name)
+{
+ assert(res->Data);
+
+ switch (res->Type) {
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ return get_matching_index(RESOURCE_VAR(res), name);
+ default:
+ assert(!"support for resource type not implemented");
+ }
+}
+
+/* Find a program resource with specific name in given interface.
+ */
+struct gl_program_resource *
+_mesa_program_resource_find_name(struct gl_shader_program *shProg,
+ GLenum programInterface, const char *name)
+{
+ struct gl_program_resource *res = shProg->ProgramResourceList;
+ for (unsigned i = 0; i < shProg->NumProgramResourceList; i++, res++) {
+ if (res->Type != programInterface)
+ continue;
+
+ /* Resource basename. */
+ const char *rname = _mesa_program_resource_name(res);
+ unsigned baselen = strlen(rname);
+
+ switch (programInterface) {
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ case GL_UNIFORM_BLOCK:
+ case GL_UNIFORM:
+ if (strncmp(rname, name, baselen) == 0) {
+ /* Basename match, check if array or struct. */
+ if (name[baselen] == '\0' ||
+ name[baselen] == '[' ||
+ name[baselen] == '.') {
+ return res;
+ }
+ }
+ break;
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ if (array_index_of_resource(res, name) >= 0)
+ return res;
+ break;
+ default:
+ assert(!"not implemented for given interface");
+ }
+ }
+ return NULL;
+}
+
+static GLuint
+calc_resource_index(struct gl_shader_program *shProg,
+ struct gl_program_resource *res)
+{
+ unsigned i;
+ GLuint index = 0;
+ for (i = 0; i < shProg->NumProgramResourceList; i++) {
+ if (&shProg->ProgramResourceList[i] == res)
+ return index;
+ if (shProg->ProgramResourceList[i].Type == res->Type)
+ index++;
+ }
+ return GL_INVALID_INDEX;
+}
+
+/**
+ * Calculate index for the given resource.
+ */
+GLuint
+_mesa_program_resource_index(struct gl_shader_program *shProg,
+ struct gl_program_resource *res)
+{
+ if (!res)
+ return GL_INVALID_INDEX;
+
+ switch (res->Type) {
+ case GL_UNIFORM_BLOCK:
+ return RESOURCE_UBO(res)- shProg->UniformBlocks;
+ case GL_ATOMIC_COUNTER_BUFFER:
+ return RESOURCE_ATC(res) - shProg->AtomicBuffers;
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ default:
+ return calc_resource_index(shProg, res);
+ }
+}
+
+/* Find a program resource with specific index in given interface.
+ */
+struct gl_program_resource *
+_mesa_program_resource_find_index(struct gl_shader_program *shProg,
+ GLenum programInterface, GLuint index)
+{
+ struct gl_program_resource *res = shProg->ProgramResourceList;
+ int idx = -1;
+
+ for (unsigned i = 0; i < shProg->NumProgramResourceList; i++, res++) {
+ if (res->Type != programInterface)
+ continue;
+
+ switch (res->Type) {
+ case GL_UNIFORM_BLOCK:
+ case GL_ATOMIC_COUNTER_BUFFER:
+ if (_mesa_program_resource_index(shProg, res) == index)
+ return res;
+
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ case GL_UNIFORM:
+ if (++idx == (int) index)
+ return res;
+ break;
+ default:
+ assert(!"not implemented for given interface");
+ }
+ }
+ return NULL;
+}
+
+/* Get full name of a program resource.
+ */
+bool
+_mesa_get_program_resource_name(struct gl_shader_program *shProg,
+ GLenum programInterface, GLuint index,
+ GLsizei bufSize, GLsizei *length,
+ GLchar *name, const char *caller)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ /* Find resource with given interface and index. */
+ struct gl_program_resource *res =
+ _mesa_program_resource_find_index(shProg, programInterface, index);
+
+ /* The error INVALID_VALUE is generated if <index> is greater than
+ * or equal to the number of entries in the active resource list for
+ * <programInterface>.
+ */
+ if (!res) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(index %u)", caller, index);
+ return false;
+ }
+
+ if (bufSize < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(bufSize %d)", caller, bufSize);
+ return false;
+ }
+
+ GLsizei localLength;
+
+ if (length == NULL)
+ length = &localLength;
+
+ _mesa_copy_string(name, bufSize, length, _mesa_program_resource_name(res));
+
+ /* Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0
+ * spec says:
+ *
+ * "If the active uniform is an array, the uniform name returned in
+ * name will always be the name of the uniform array appended with
+ * "[0]"."
+ *
+ * The same text also appears in the OpenGL 4.2 spec. It does not,
+ * however, appear in any previous spec. Previous specifications are
+ * ambiguous in this regard. However, either name can later be passed
+ * to glGetUniformLocation (and related APIs), so there shouldn't be any
+ * harm in always appending "[0]" to uniform array names.
+ *
+ * Geometry shader stage has different naming convention where the 'normal'
+ * condition is an array, therefore for variables referenced in geometry
+ * stage we do not add '[0]'.
+ *
+ * Note, that TCS outputs and TES inputs should not have index appended
+ * either.
+ */
+ bool add_index = !(((programInterface == GL_PROGRAM_INPUT) &&
+ res->StageReferences & (1 << MESA_SHADER_GEOMETRY)));
+
+ if (add_index && _mesa_program_resource_array_size(res)) {
+ int i;
+
+ /* The comparison is strange because *length does *NOT* include the
+ * terminating NUL, but maxLength does.
+ */
+ for (i = 0; i < 3 && (*length + i + 1) < bufSize; i++)
+ name[*length + i] = "[0]"[i];
+
+ name[*length + i] = '\0';
+ *length += i;
+ }
+ return true;
+}
+
+static GLint
+program_resource_location(struct gl_shader_program *shProg,
+ struct gl_program_resource *res, const char *name)
+{
+ unsigned index, offset;
+ int array_index = -1;
+
+ if (res->Type == GL_PROGRAM_INPUT || res->Type == GL_PROGRAM_OUTPUT) {
+ array_index = array_index_of_resource(res, name);
+ if (array_index < 0)
+ return -1;
+ }
+
+ /* VERT_ATTRIB_GENERIC0 and FRAG_RESULT_DATA0 are decremented as these
+ * offsets are used internally to differentiate between built-in attributes
+ * and user-defined attributes.
+ */
+ switch (res->Type) {
+ case GL_PROGRAM_INPUT:
+ return RESOURCE_VAR(res)->data.location + array_index - VERT_ATTRIB_GENERIC0;
+ case GL_PROGRAM_OUTPUT:
+ return RESOURCE_VAR(res)->data.location + array_index - FRAG_RESULT_DATA0;
+ case GL_UNIFORM:
+ index = _mesa_get_uniform_location(shProg, name, &offset);
+
+ if (index == GL_INVALID_INDEX)
+ return -1;
+
+ /* From the GL_ARB_uniform_buffer_object spec:
*
- * "If name is not an active attribute, if name is a conventional
- * attribute, or if an error occurs, -1 will be returned."
+ * "The value -1 will be returned if <name> does not correspond to an
+ * active uniform variable name in <program>, if <name> is associated
+ * with a named uniform block, or if <name> starts with the reserved
+ * prefix "gl_"."
*/
- if (var == NULL
- || var->data.mode != ir_var_shader_out
- || var->data.location == -1
- || var->data.location < FRAG_RESULT_DATA0)
- continue;
+ if (RESOURCE_UNI(res)->block_index != -1 ||
+ RESOURCE_UNI(res)->atomic_buffer_index != -1)
+ return -1;
- int index = get_matching_index(var, (const char *) name);
+ /* location in remap table + array element offset */
+ return RESOURCE_UNI(res)->remap_location + offset;
- if (index >= 0)
- return var->data.location + index - FRAG_RESULT_DATA0;
+ default:
+ return -1;
}
+}
- return -1;
+/**
+ * Function implements following location queries:
+ * glGetAttribLocation
+ * glGetFragDataLocation
+ * glGetUniformLocation
+ */
+GLint
+_mesa_program_resource_location(struct gl_shader_program *shProg,
+ GLenum programInterface, const char *name)
+{
+ struct gl_program_resource *res =
+ _mesa_program_resource_find_name(shProg, programInterface, name);
+
+ /* Resource not found. */
+ if (!res)
+ return -1;
+
+ return program_resource_location(shProg, res, name);
+}
+
+/**
+ * Function implements following index queries:
+ * glGetFragDataIndex
+ */
+GLint
+_mesa_program_resource_location_index(struct gl_shader_program *shProg,
+ GLenum programInterface, const char *name)
+{
+ struct gl_program_resource *res =
+ _mesa_program_resource_find_name(shProg, programInterface, name);
+
+ /* Non-existent variable or resource is not referenced by fragment stage. */
+ if (!res || !(res->StageReferences & (1 << MESA_SHADER_FRAGMENT)))
+ return -1;
+
+ return RESOURCE_VAR(res)->data.index;
+}
+
+static uint8_t
+stage_from_enum(GLenum ref)
+{
+ switch (ref) {
+ case GL_REFERENCED_BY_VERTEX_SHADER:
+ return MESA_SHADER_VERTEX;
+ case GL_REFERENCED_BY_GEOMETRY_SHADER:
+ return MESA_SHADER_GEOMETRY;
+ case GL_REFERENCED_BY_FRAGMENT_SHADER:
+ return MESA_SHADER_FRAGMENT;
+ default:
+ assert(!"shader stage not supported");
+ return MESA_SHADER_STAGES;
+ }
+}
+
+/**
+ * Check if resource is referenced by given 'referenced by' stage enum.
+ * ATC and UBO resources hold stage references of their own.
+ */
+static bool
+is_resource_referenced(struct gl_shader_program *shProg,
+ struct gl_program_resource *res,
+ GLuint index, uint8_t stage)
+{
+ if (res->Type == GL_ATOMIC_COUNTER_BUFFER)
+ return RESOURCE_ATC(res)->StageReferences[stage];
+
+ if (res->Type == GL_UNIFORM_BLOCK)
+ return shProg->UniformBlockStageIndex[stage][index] != -1;
+
+ return res->StageReferences & (1 << stage);
+}
+
+static unsigned
+get_buffer_property(struct gl_shader_program *shProg,
+ struct gl_program_resource *res, const GLenum prop,
+ GLint *val, const char *caller)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (res->Type != GL_UNIFORM_BLOCK &&
+ res->Type != GL_ATOMIC_COUNTER_BUFFER)
+ goto invalid_operation;
+
+ if (res->Type == GL_UNIFORM_BLOCK) {
+ switch (prop) {
+ case GL_BUFFER_BINDING:
+ *val = RESOURCE_UBO(res)->Binding;
+ return 1;
+ case GL_BUFFER_DATA_SIZE:
+ *val = RESOURCE_UBO(res)->UniformBufferSize;
+ return 1;
+ case GL_NUM_ACTIVE_VARIABLES:
+ *val = RESOURCE_UBO(res)->NumUniforms;
+ return 1;
+ case GL_ACTIVE_VARIABLES:
+ for (unsigned i = 0; i < RESOURCE_UBO(res)->NumUniforms; i++) {
+ const char *iname = RESOURCE_UBO(res)->Uniforms[i].IndexName;
+ struct gl_program_resource *uni =
+ _mesa_program_resource_find_name(shProg, GL_UNIFORM, iname);
+ *val++ =
+ _mesa_program_resource_index(shProg, uni);
+ }
+ return RESOURCE_UBO(res)->NumUniforms;
+ }
+ } else if (res->Type == GL_ATOMIC_COUNTER_BUFFER) {
+ switch (prop) {
+ case GL_BUFFER_BINDING:
+ *val = RESOURCE_ATC(res)->Binding;
+ return 1;
+ case GL_BUFFER_DATA_SIZE:
+ *val = RESOURCE_ATC(res)->MinimumSize;
+ return 1;
+ case GL_NUM_ACTIVE_VARIABLES:
+ *val = RESOURCE_ATC(res)->NumUniforms;
+ return 1;
+ case GL_ACTIVE_VARIABLES:
+ for (unsigned i = 0; i < RESOURCE_ATC(res)->NumUniforms; i++)
+ *val++ = RESOURCE_ATC(res)->Uniforms[i];
+ return RESOURCE_ATC(res)->NumUniforms;
+ }
+ }
+ assert(!"support for property type not implemented");
+
+invalid_operation:
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller,
+ _mesa_lookup_enum_by_nr(res->Type),
+ _mesa_lookup_enum_by_nr(prop));
+
+ return 0;
+}
+
+unsigned
+_mesa_program_resource_prop(struct gl_shader_program *shProg,
+ struct gl_program_resource *res, GLuint index,
+ const GLenum prop, GLint *val, const char *caller)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+#define VALIDATE_TYPE(type)\
+ if (res->Type != type)\
+ goto invalid_operation;
+
+ switch(prop) {
+ case GL_NAME_LENGTH:
+ if (res->Type == GL_ATOMIC_COUNTER_BUFFER)
+ goto invalid_operation;
+ /* Base name +3 if array '[0]' + terminator. */
+ *val = strlen(_mesa_program_resource_name(res)) +
+ (_mesa_program_resource_array_size(res) > 0 ? 3 : 0) + 1;
+ return 1;
+ case GL_TYPE:
+ switch (res->Type) {
+ case GL_UNIFORM:
+ *val = RESOURCE_UNI(res)->type->gl_type;
+ return 1;
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ *val = RESOURCE_VAR(res)->type->gl_type;
+ return 1;
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ *val = RESOURCE_XFB(res)->Type;
+ return 1;
+ default:
+ goto invalid_operation;
+ }
+ case GL_ARRAY_SIZE:
+ switch (res->Type) {
+ case GL_UNIFORM:
+ *val = MAX2(RESOURCE_UNI(res)->array_elements, 1);
+ return 1;
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ *val = MAX2(RESOURCE_VAR(res)->type->length, 1);
+ return 1;
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ *val = MAX2(RESOURCE_XFB(res)->Size, 1);
+ return 1;
+ default:
+ goto invalid_operation;
+ }
+ case GL_OFFSET:
+ VALIDATE_TYPE(GL_UNIFORM);
+ *val = RESOURCE_UNI(res)->offset;
+ return 1;
+ case GL_BLOCK_INDEX:
+ VALIDATE_TYPE(GL_UNIFORM);
+ *val = RESOURCE_UNI(res)->block_index;
+ return 1;
+ case GL_ARRAY_STRIDE:
+ VALIDATE_TYPE(GL_UNIFORM);
+ *val = RESOURCE_UNI(res)->array_stride;
+ return 1;
+ case GL_MATRIX_STRIDE:
+ VALIDATE_TYPE(GL_UNIFORM);
+ *val = RESOURCE_UNI(res)->matrix_stride;
+ return 1;
+ case GL_IS_ROW_MAJOR:
+ VALIDATE_TYPE(GL_UNIFORM);
+ *val = RESOURCE_UNI(res)->row_major;
+ return 1;
+ case GL_ATOMIC_COUNTER_BUFFER_INDEX:
+ VALIDATE_TYPE(GL_UNIFORM);
+ *val = RESOURCE_UNI(res)->atomic_buffer_index;
+ return 1;
+ case GL_BUFFER_BINDING:
+ case GL_BUFFER_DATA_SIZE:
+ case GL_NUM_ACTIVE_VARIABLES:
+ case GL_ACTIVE_VARIABLES:
+ return get_buffer_property(shProg, res, prop, val, caller);
+ case GL_REFERENCED_BY_VERTEX_SHADER:
+ case GL_REFERENCED_BY_GEOMETRY_SHADER:
+ case GL_REFERENCED_BY_FRAGMENT_SHADER:
+ switch (res->Type) {
+ case GL_UNIFORM:
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ case GL_UNIFORM_BLOCK:
+ case GL_ATOMIC_COUNTER_BUFFER:
+ *val = is_resource_referenced(shProg, res, index,
+ stage_from_enum(prop));
+ return 1;
+ default:
+ goto invalid_operation;
+ }
+ case GL_LOCATION:
+ switch (res->Type) {
+ case GL_UNIFORM:
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ *val = program_resource_location(shProg, res,
+ _mesa_program_resource_name(res));
+ return 1;
+ default:
+ goto invalid_operation;
+ }
+ case GL_LOCATION_INDEX:
+ if (res->Type != GL_PROGRAM_OUTPUT)
+ goto invalid_operation;
+ *val = RESOURCE_VAR(res)->data.index;
+ return 1;
+
+ /* GL_ARB_tessellation_shader */
+ case GL_IS_PER_PATCH:
+ case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
+ case GL_REFERENCED_BY_TESS_EVALUATION_SHADER:
+ /* GL_ARB_compute_shader */
+ case GL_REFERENCED_BY_COMPUTE_SHADER:
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s prop %s)", caller,
+ _mesa_lookup_enum_by_nr(res->Type),
+ _mesa_lookup_enum_by_nr(prop));
+ return 0;
+ }
+
+#undef VALIDATE_TYPE
+
+invalid_operation:
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller,
+ _mesa_lookup_enum_by_nr(res->Type),
+ _mesa_lookup_enum_by_nr(prop));
+ return 0;
+}
+
+extern void
+_mesa_get_program_resourceiv(struct gl_shader_program *shProg,
+ GLenum programInterface, GLuint index, GLsizei propCount,
+ const GLenum *props, GLsizei bufSize,
+ GLsizei *length, GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint *val = (GLint *) params;
+ const GLenum *prop = props;
+ GLsizei amount = 0;
+
+ struct gl_program_resource *res =
+ _mesa_program_resource_find_index(shProg, programInterface, index);
+
+ /* No such resource found or bufSize negative. */
+ if (!res || bufSize < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetProgramResourceiv(%s index %d bufSize %d)",
+ _mesa_lookup_enum_by_nr(programInterface), index, bufSize);
+ return;
+ }
+
+ /* Write propCount values until error occurs or bufSize reached. */
+ for (int i = 0; i < propCount && i < bufSize; i++, val++, prop++) {
+ int props_written =
+ _mesa_program_resource_prop(shProg, res, index, *prop, val,
+ "glGetProgramResourceiv");
+
+ /* Error happened. */
+ if (props_written == 0)
+ return;
+
+ amount += props_written;
+ }
+
+ /* If <length> is not NULL, the actual number of integer values
+ * written to <params> will be written to <length>.
+ */
+ if (length)
+ *length = amount;
}
diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c
index 30716f5e3..77e2b8745 100644
--- a/mesalib/src/mesa/main/shaderapi.c
+++ b/mesalib/src/mesa/main/shaderapi.c
@@ -882,10 +882,9 @@ compile_shader(struct gl_context *ctx, GLuint shaderObj)
sh->CompileStatus = GL_FALSE;
} else {
if (ctx->_Shader->Flags & GLSL_DUMP) {
- fprintf(stderr, "GLSL source for %s shader %d:\n",
+ _mesa_log("GLSL source for %s shader %d:\n",
_mesa_shader_stage_to_string(sh->Stage), sh->Name);
- fprintf(stderr, "%s\n", sh->Source);
- fflush(stderr);
+ _mesa_log("%s\n", sh->Source);
}
/* this call will set the shader->CompileStatus field to indicate if
@@ -899,27 +898,25 @@ compile_shader(struct gl_context *ctx, GLuint shaderObj)
if (ctx->_Shader->Flags & GLSL_DUMP) {
if (sh->CompileStatus) {
- fprintf(stderr, "GLSL IR for shader %d:\n", sh->Name);
- _mesa_print_ir(stderr, sh->ir, NULL);
- fprintf(stderr, "\n\n");
+ _mesa_log("GLSL IR for shader %d:\n", sh->Name);
+ _mesa_print_ir(_mesa_get_log_file(), sh->ir, NULL);
+ _mesa_log("\n\n");
} else {
- fprintf(stderr, "GLSL shader %d failed to compile.\n", sh->Name);
+ _mesa_log("GLSL shader %d failed to compile.\n", sh->Name);
}
if (sh->InfoLog && sh->InfoLog[0] != 0) {
- fprintf(stderr, "GLSL shader %d info log:\n", sh->Name);
- fprintf(stderr, "%s\n", sh->InfoLog);
+ _mesa_log("GLSL shader %d info log:\n", sh->Name);
+ _mesa_log("%s\n", sh->InfoLog);
}
- fflush(stderr);
}
}
if (!sh->CompileStatus) {
if (ctx->_Shader->Flags & GLSL_DUMP_ON_ERROR) {
- fprintf(stderr, "GLSL source for %s shader %d:\n",
+ _mesa_log("GLSL source for %s shader %d:\n",
_mesa_shader_stage_to_string(sh->Stage), sh->Name);
- fprintf(stderr, "%s\n", sh->Source);
- fprintf(stderr, "Info Log:\n%s\n", sh->InfoLog);
- fflush(stderr);
+ _mesa_log("%s\n", sh->Source);
+ _mesa_log("Info Log:\n%s\n", sh->InfoLog);
}
if (ctx->_Shader->Flags & GLSL_REPORT_ERRORS) {
diff --git a/mesalib/src/mesa/main/shaderapi.h b/mesalib/src/mesa/main/shaderapi.h
index 047d2562d..aba6d5d83 100644
--- a/mesalib/src/mesa/main/shaderapi.h
+++ b/mesalib/src/mesa/main/shaderapi.h
@@ -219,6 +219,51 @@ extern GLuint GLAPIENTRY
_mesa_CreateShaderProgramv(GLenum type, GLsizei count,
const GLchar* const *strings);
+/* GL_ARB_program_resource_query */
+extern const char*
+_mesa_program_resource_name(struct gl_program_resource *res);
+
+extern unsigned
+_mesa_program_resource_array_size(struct gl_program_resource *res);
+
+extern GLuint
+_mesa_program_resource_index(struct gl_shader_program *shProg,
+ struct gl_program_resource *res);
+
+extern struct gl_program_resource *
+_mesa_program_resource_find_name(struct gl_shader_program *shProg,
+ GLenum programInterface, const char *name);
+
+extern struct gl_program_resource *
+_mesa_program_resource_find_index(struct gl_shader_program *shProg,
+ GLenum programInterface, GLuint index);
+
+extern bool
+_mesa_get_program_resource_name(struct gl_shader_program *shProg,
+ GLenum programInterface, GLuint index,
+ GLsizei bufSize, GLsizei *length,
+ GLchar *name, const char *caller);
+
+extern GLint
+_mesa_program_resource_location(struct gl_shader_program *shProg,
+ GLenum programInterface, const char *name);
+
+extern GLint
+_mesa_program_resource_location_index(struct gl_shader_program *shProg,
+ GLenum programInterface, const char *name);
+
+extern unsigned
+_mesa_program_resource_prop(struct gl_shader_program *shProg,
+ struct gl_program_resource *res, GLuint index,
+ const GLenum prop, GLint *val, const char *caller);
+
+extern void
+_mesa_get_program_resourceiv(struct gl_shader_program *shProg,
+ GLenum programInterface, GLuint index,
+ GLsizei propCount, const GLenum *props,
+ GLsizei bufSize, GLsizei *length,
+ GLint *params);
+
#ifdef __cplusplus
}
#endif
diff --git a/mesalib/src/mesa/main/shaderobj.c b/mesalib/src/mesa/main/shaderobj.c
index d7620c8ef..e42896036 100644
--- a/mesalib/src/mesa/main/shaderobj.c
+++ b/mesalib/src/mesa/main/shaderobj.c
@@ -315,6 +315,12 @@ _mesa_clear_shader_program_data(struct gl_shader_program *shProg)
ralloc_free(shProg->AtomicBuffers);
shProg->AtomicBuffers = NULL;
shProg->NumAtomicBuffers = 0;
+
+ if (shProg->ProgramResourceList) {
+ ralloc_free(shProg->ProgramResourceList);
+ shProg->ProgramResourceList = NULL;
+ shProg->NumProgramResourceList = 0;
+ }
}
diff --git a/mesalib/src/mesa/main/state.c b/mesalib/src/mesa/main/state.c
index dadfb3c8c..cc84c6148 100644
--- a/mesalib/src/mesa/main/state.c
+++ b/mesalib/src/mesa/main/state.c
@@ -269,28 +269,6 @@ update_program_constants(struct gl_context *ctx)
-static void
-update_viewport_matrix(struct gl_context *ctx)
-{
- const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF;
- unsigned i;
-
- assert(depthMax > 0);
-
- /* Compute scale and bias values. This is really driver-specific
- * and should be maintained elsewhere if at all.
- * NOTE: RasterPos uses this.
- */
- for (i = 0; i < ctx->Const.MaxViewports; i++) {
- double scale[3], translate[3];
-
- _mesa_get_viewport_xform(ctx, i, scale, translate);
- _math_matrix_viewport(&ctx->ViewportArray[i]._WindowMap,
- scale, translate, depthMax);
- }
-}
-
-
/**
* Update the ctx->Polygon._FrontBit flag.
*/
@@ -407,9 +385,6 @@ _mesa_update_state_locked( struct gl_context *ctx )
if (new_state & _NEW_PIXEL)
_mesa_update_pixel( ctx, new_state );
- if (new_state & (_NEW_BUFFERS | _NEW_VIEWPORT))
- update_viewport_matrix(ctx);
-
if (new_state & (_NEW_MULTISAMPLE | _NEW_BUFFERS))
update_multisample( ctx );
@@ -507,7 +482,7 @@ _mesa_set_varying_vp_inputs( struct gl_context *ctx,
ctx->FragmentProgram._TexEnvProgram) {
ctx->NewState |= _NEW_VARYING_VP_INPUTS;
}
- /*printf("%s %x\n", __FUNCTION__, varying_inputs);*/
+ /*printf("%s %x\n", __func__, varying_inputs);*/
}
}
diff --git a/mesalib/src/mesa/main/texcompress.c b/mesalib/src/mesa/main/texcompress.c
index 00234d4cc..0fd1a3683 100644
--- a/mesalib/src/mesa/main/texcompress.c
+++ b/mesalib/src/mesa/main/texcompress.c
@@ -32,7 +32,6 @@
#include "glheader.h"
#include "imports.h"
-#include "colormac.h"
#include "context.h"
#include "formats.h"
#include "mtypes.h"
diff --git a/mesalib/src/mesa/main/texcompress_fxt1.c b/mesalib/src/mesa/main/texcompress_fxt1.c
index 562359410..f06f04882 100644
--- a/mesalib/src/mesa/main/texcompress_fxt1.c
+++ b/mesalib/src/mesa/main/texcompress_fxt1.c
@@ -31,7 +31,6 @@
#include "glheader.h"
#include "imports.h"
-#include "colormac.h"
#include "image.h"
#include "macros.h"
#include "mipmap.h"
diff --git a/mesalib/src/mesa/main/texcompress_rgtc.c b/mesalib/src/mesa/main/texcompress_rgtc.c
index f40e4e6c0..66de1f17d 100644
--- a/mesalib/src/mesa/main/texcompress_rgtc.c
+++ b/mesalib/src/mesa/main/texcompress_rgtc.c
@@ -35,7 +35,6 @@
#include "glheader.h"
#include "imports.h"
-#include "colormac.h"
#include "image.h"
#include "macros.h"
#include "mipmap.h"
diff --git a/mesalib/src/mesa/main/texcompress_s3tc.c b/mesalib/src/mesa/main/texcompress_s3tc.c
index 41d00d4e9..7ce3cb88e 100644
--- a/mesalib/src/mesa/main/texcompress_s3tc.c
+++ b/mesalib/src/mesa/main/texcompress_s3tc.c
@@ -29,13 +29,8 @@
* GL_EXT_texture_compression_s3tc support.
*/
-#ifndef USE_EXTERNAL_DXTN_LIB
-#define USE_EXTERNAL_DXTN_LIB 1
-#endif
-
#include "glheader.h"
#include "imports.h"
-#include "colormac.h"
#include "dlopen.h"
#include "image.h"
#include "macros.h"
@@ -77,7 +72,6 @@ _mesa_init_texture_s3tc( struct gl_context *ctx )
{
/* called during context initialization */
ctx->Mesa_DXTn = GL_FALSE;
-#if USE_EXTERNAL_DXTN_LIB
if (!dxtlibhandle) {
dxtlibhandle = _mesa_dlopen(DXTN_LIBNAME, 0);
if (!dxtlibhandle) {
@@ -118,9 +112,6 @@ _mesa_init_texture_s3tc( struct gl_context *ctx )
if (dxtlibhandle) {
ctx->Mesa_DXTn = GL_TRUE;
}
-#else
- (void) ctx;
-#endif
}
/**
diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c
index 1ef728660..b5d42d304 100644
--- a/mesalib/src/mesa/main/texparam.c
+++ b/mesalib/src/mesa/main/texparam.c
@@ -32,7 +32,6 @@
#include <stdbool.h>
#include "main/glheader.h"
#include "main/blend.h"
-#include "main/colormac.h"
#include "main/context.h"
#include "main/enums.h"
#include "main/formats.h"
diff --git a/mesalib/src/mesa/main/texstate.c b/mesalib/src/mesa/main/texstate.c
index 0a7f983fb..1af9d47f0 100644
--- a/mesalib/src/mesa/main/texstate.c
+++ b/mesalib/src/mesa/main/texstate.c
@@ -31,8 +31,6 @@
#include <stdio.h>
#include "glheader.h"
#include "bufferobj.h"
-#include "colormac.h"
-#include "colortab.h"
#include "context.h"
#include "enums.h"
#include "macros.h"
diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c
index 7ad9d2b68..152520598 100644
--- a/mesalib/src/mesa/main/texstore.c
+++ b/mesalib/src/mesa/main/texstore.c
@@ -53,7 +53,6 @@
#include "glheader.h"
#include "bufferobj.h"
-#include "colormac.h"
#include "format_pack.h"
#include "format_utils.h"
#include "image.h"
diff --git a/mesalib/src/mesa/main/transformfeedback.c b/mesalib/src/mesa/main/transformfeedback.c
index ce678c864..103011ce5 100644
--- a/mesalib/src/mesa/main/transformfeedback.c
+++ b/mesalib/src/mesa/main/transformfeedback.c
@@ -514,22 +514,24 @@ _mesa_EndTransformFeedback(void)
* Helper used by BindBufferRange() and BindBufferBase().
*/
static void
-bind_buffer_range(struct gl_context *ctx, GLuint index,
+bind_buffer_range(struct gl_context *ctx,
+ struct gl_transform_feedback_object *obj,
+ GLuint index,
struct gl_buffer_object *bufObj,
- GLintptr offset, GLsizeiptr size)
+ GLintptr offset, GLsizeiptr size,
+ bool dsa)
{
- struct gl_transform_feedback_object *obj =
- ctx->TransformFeedback.CurrentObject;
-
/* Note: no need to FLUSH_VERTICES or flag NewTransformFeedback, because
* transform feedback buffers can't be changed while transform feedback is
* active.
*/
- /* The general binding point */
- _mesa_reference_buffer_object(ctx,
- &ctx->TransformFeedback.CurrentBuffer,
- bufObj);
+ if (!dsa) {
+ /* The general binding point */
+ _mesa_reference_buffer_object(ctx,
+ &ctx->TransformFeedback.CurrentBuffer,
+ bufObj);
+ }
/* The per-attribute binding point */
_mesa_set_transform_feedback_binding(ctx, obj, index, bufObj, offset, size);
@@ -539,75 +541,209 @@ bind_buffer_range(struct gl_context *ctx, GLuint index,
/**
* Specify a buffer object to receive transform feedback results. Plus,
* specify the starting offset to place the results, and max size.
- * Called from the glBindBufferRange() function.
+ * Called from the glBindBufferRange() and glTransformFeedbackBufferRange
+ * functions.
*/
void
_mesa_bind_buffer_range_transform_feedback(struct gl_context *ctx,
- GLuint index,
- struct gl_buffer_object *bufObj,
- GLintptr offset,
- GLsizeiptr size)
+ struct gl_transform_feedback_object *obj,
+ GLuint index,
+ struct gl_buffer_object *bufObj,
+ GLintptr offset,
+ GLsizeiptr size,
+ bool dsa)
{
- struct gl_transform_feedback_object *obj;
+ const char *gl_methd_name;
+ if (dsa)
+ gl_methd_name = "glTransformFeedbackBufferRange";
+ else
+ gl_methd_name = "glBindBufferRange";
- obj = ctx->TransformFeedback.CurrentObject;
if (obj->Active) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBindBufferRange(transform feedback active)");
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(transform feedback active)",
+ gl_methd_name);
return;
}
if (index >= ctx->Const.MaxTransformFeedbackBuffers) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index);
+ /* OpenGL 4.5 core profile, 6.1, pdf page 82: "An INVALID_VALUE error is
+ * generated if index is greater than or equal to the number of binding
+ * points for transform feedback, as described in section 6.7.1."
+ */
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%d out of bounds)",
+ gl_methd_name, index);
return;
}
if (size & 0x3) {
- /* must a multiple of four */
- _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size=%d)", (int) size);
+ /* OpenGL 4.5 core profile, 6.7, pdf page 103: multiple of 4 */
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d must be a multiple of "
+ "four)", gl_methd_name, (int) size);
return;
}
if (offset & 0x3) {
- /* must be multiple of four */
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glBindBufferRange(offset=%d)", (int) offset);
+ /* OpenGL 4.5 core profile, 6.7, pdf page 103: multiple of 4 */
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset=%d must be a multiple "
+ "of four)", gl_methd_name, (int) offset);
return;
- }
+ }
+
+ if (offset < 0) {
+ /* OpenGL 4.5 core profile, 6.1, pdf page 82: "An INVALID_VALUE error is
+ * generated by BindBufferRange if offset is negative."
+ *
+ * OpenGL 4.5 core profile, 13.2, pdf page 445: "An INVALID_VALUE error
+ * is generated by TransformFeedbackBufferRange if offset is negative."
+ */
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset=%d must be >= 0)",
+ gl_methd_name,
+ (int) offset);
+ return;
+ }
- bind_buffer_range(ctx, index, bufObj, offset, size);
+ if (size <= 0 && (dsa || bufObj != ctx->Shared->NullBufferObj)) {
+ /* OpenGL 4.5 core profile, 6.1, pdf page 82: "An INVALID_VALUE error is
+ * generated by BindBufferRange if buffer is non-zero and size is less
+ * than or equal to zero."
+ *
+ * OpenGL 4.5 core profile, 13.2, pdf page 445: "An INVALID_VALUE error
+ * is generated by TransformFeedbackBufferRange if size is less than or
+ * equal to zero."
+ */
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d must be > 0)",
+ gl_methd_name, (int) size);
+ return;
+ }
+
+ bind_buffer_range(ctx, obj, index, bufObj, offset, size, dsa);
}
/**
* Specify a buffer object to receive transform feedback results.
* As above, but start at offset = 0.
- * Called from the glBindBufferBase() function.
+ * Called from the glBindBufferBase() and glTransformFeedbackBufferBase()
+ * functions.
*/
void
_mesa_bind_buffer_base_transform_feedback(struct gl_context *ctx,
- GLuint index,
- struct gl_buffer_object *bufObj)
+ struct gl_transform_feedback_object *obj,
+ GLuint index,
+ struct gl_buffer_object *bufObj,
+ bool dsa)
{
- struct gl_transform_feedback_object *obj;
-
- obj = ctx->TransformFeedback.CurrentObject;
-
if (obj->Active) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glBindBufferBase(transform feedback active)");
+ "%s(transform feedback active)",
+ dsa ? "glTransformFeedbackBufferBase" : "glBindBufferBase");
return;
}
if (index >= ctx->Const.MaxTransformFeedbackBuffers) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index);
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%d out of bounds)",
+ dsa ? "glTransformFeedbackBufferBase" : "glBindBufferBase",
+ index);
+ return;
+ }
+
+ bind_buffer_range(ctx, obj, index, bufObj, 0, 0, dsa);
+}
+
+/**
+ * Wrapper around lookup_transform_feedback_object that throws
+ * GL_INVALID_OPERATION if id is not in the hash table. After calling
+ * _mesa_error, it returns NULL.
+ */
+static struct gl_transform_feedback_object *
+lookup_transform_feedback_object_err(struct gl_context *ctx,
+ GLuint xfb, const char* func)
+{
+ struct gl_transform_feedback_object *obj;
+
+ obj = _mesa_lookup_transform_feedback_object(ctx, xfb);
+ if (!obj) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "%s(xfb=%u: non-generated object name)", func, xfb);
+ }
+
+ return obj;
+}
+
+/**
+ * Wrapper around _mesa_lookup_bufferobj that throws GL_INVALID_VALUE if id
+ * is not in the hash table. Specialised version for the
+ * transform-feedback-related functions. After calling _mesa_error, it
+ * returns NULL.
+ */
+static struct gl_buffer_object *
+lookup_transform_feedback_bufferobj_err(struct gl_context *ctx,
+ GLuint buffer, const char* func)
+{
+ struct gl_buffer_object *bufObj;
+
+ /* OpenGL 4.5 core profile, 13.2, pdf page 444: buffer must be zero or the
+ * name of an existing buffer object.
+ */
+ if (buffer == 0) {
+ bufObj = ctx->Shared->NullBufferObj;
+ } else {
+ bufObj = _mesa_lookup_bufferobj(ctx, buffer);
+ if (!bufObj) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid buffer=%u)", func,
+ buffer);
+ }
+ }
+
+ return bufObj;
+}
+
+void GLAPIENTRY
+_mesa_TransformFeedbackBufferBase(GLuint xfb, GLuint index, GLuint buffer)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_transform_feedback_object *obj;
+ struct gl_buffer_object *bufObj;
+
+ obj = lookup_transform_feedback_object_err(ctx, xfb,
+ "glTransformFeedbackBufferBase");
+ if(!obj) {
+ return;
+ }
+
+ bufObj = lookup_transform_feedback_bufferobj_err(ctx, buffer,
+ "glTransformFeedbackBufferBase");
+ if(!bufObj) {
return;
}
- bind_buffer_range(ctx, index, bufObj, 0, 0);
+ _mesa_bind_buffer_base_transform_feedback(ctx, obj, index, bufObj, true);
}
+void GLAPIENTRY
+_mesa_TransformFeedbackBufferRange(GLuint xfb, GLuint index, GLuint buffer,
+ GLintptr offset, GLsizeiptr size)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_transform_feedback_object *obj;
+ struct gl_buffer_object *bufObj;
+
+ obj = lookup_transform_feedback_object_err(ctx, xfb,
+ "glTransformFeedbackBufferRange");
+ if(!obj) {
+ return;
+ }
+
+ bufObj = lookup_transform_feedback_bufferobj_err(ctx, buffer,
+ "glTransformFeedbackBufferRange");
+ if(!bufObj) {
+ return;
+ }
+
+ _mesa_bind_buffer_range_transform_feedback(ctx, obj, index, bufObj, offset,
+ size, true);
+}
/**
* Specify a buffer object to receive transform feedback results, plus the
@@ -660,7 +796,7 @@ _mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer,
return;
}
- bind_buffer_range(ctx, index, bufObj, offset, 0);
+ bind_buffer_range(ctx, obj, index, bufObj, offset, 0, false);
}
@@ -784,7 +920,7 @@ _mesa_GetTransformFeedbackVarying(GLuint program, GLuint index,
GLsizei *size, GLenum *type, GLchar *name)
{
const struct gl_shader_program *shProg;
- const struct gl_transform_feedback_info *linked_xfb_info;
+ struct gl_program_resource *res;
GET_CURRENT_CONTEXT(ctx);
shProg = _mesa_lookup_shader_program(ctx, program);
@@ -794,22 +930,27 @@ _mesa_GetTransformFeedbackVarying(GLuint program, GLuint index,
return;
}
- linked_xfb_info = &shProg->LinkedTransformFeedback;
- if (index >= (GLuint) linked_xfb_info->NumVarying) {
+ res = _mesa_program_resource_find_index((struct gl_shader_program *) shProg,
+ GL_TRANSFORM_FEEDBACK_VARYING,
+ index);
+ if (!res) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glGetTransformFeedbackVarying(index=%u)", index);
return;
}
/* return the varying's name and length */
- _mesa_copy_string(name, bufSize, length,
- linked_xfb_info->Varyings[index].Name);
+ _mesa_copy_string(name, bufSize, length, _mesa_program_resource_name(res));
/* return the datatype and value's size (in datatype units) */
if (type)
- *type = linked_xfb_info->Varyings[index].Type;
+ _mesa_program_resource_prop((struct gl_shader_program *) shProg,
+ res, index, GL_TYPE, (GLint*) type,
+ "glGetTransformFeedbackVarying");
if (size)
- *size = linked_xfb_info->Varyings[index].Size;
+ _mesa_program_resource_prop((struct gl_shader_program *) shProg,
+ res, index, GL_ARRAY_SIZE, (GLint*) size,
+ "glGetTransformFeedbackVarying");
}
@@ -817,6 +958,10 @@ _mesa_GetTransformFeedbackVarying(GLuint program, GLuint index,
struct gl_transform_feedback_object *
_mesa_lookup_transform_feedback_object(struct gl_context *ctx, GLuint name)
{
+ /* OpenGL 4.5 core profile, 13.2 pdf page 444: "xfb must be zero, indicating
+ * the default transform feedback object, or the name of an existing
+ * transform feedback object."
+ */
if (name == 0) {
return ctx->TransformFeedback.DefaultObject;
}
@@ -825,25 +970,24 @@ _mesa_lookup_transform_feedback_object(struct gl_context *ctx, GLuint name)
_mesa_HashLookup(ctx->TransformFeedback.Objects, name);
}
-
-/**
- * Create new transform feedback objects. Transform feedback objects
- * encapsulate the state related to transform feedback to allow quickly
- * switching state (and drawing the results, below).
- * Part of GL_ARB_transform_feedback2.
- */
-void GLAPIENTRY
-_mesa_GenTransformFeedbacks(GLsizei n, GLuint *names)
+static void
+create_transform_feedbacks(struct gl_context *ctx, GLsizei n, GLuint *ids,
+ bool dsa)
{
GLuint first;
- GET_CURRENT_CONTEXT(ctx);
+ const char* func;
+
+ if (dsa)
+ func = "glCreateTransformFeedbacks";
+ else
+ func = "glGenTransformFeedbacks";
if (n < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGenTransformFeedbacks(n < 0)");
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
return;
}
- if (!names)
+ if (!ids)
return;
/* we don't need contiguous IDs, but this might be faster */
@@ -854,18 +998,56 @@ _mesa_GenTransformFeedbacks(GLsizei n, GLuint *names)
struct gl_transform_feedback_object *obj
= ctx->Driver.NewTransformFeedback(ctx, first + i);
if (!obj) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTransformFeedbacks");
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
return;
}
- names[i] = first + i;
+ ids[i] = first + i;
_mesa_HashInsert(ctx->TransformFeedback.Objects, first + i, obj);
+ if (dsa) {
+ /* this is normally done at bind time in the non-dsa case */
+ obj->EverBound = GL_TRUE;
+ }
}
}
else {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTransformFeedbacks");
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
}
}
+/**
+ * Create new transform feedback objects. Transform feedback objects
+ * encapsulate the state related to transform feedback to allow quickly
+ * switching state (and drawing the results, below).
+ * Part of GL_ARB_transform_feedback2.
+ */
+void GLAPIENTRY
+_mesa_GenTransformFeedbacks(GLsizei n, GLuint *names)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ /* GenTransformFeedbacks should just reserve the object names that a
+ * subsequent call to BindTransformFeedback should actively create. For
+ * the sake of simplicity, we reserve the names and create the objects
+ * straight away.
+ */
+
+ create_transform_feedbacks(ctx, n, names, false);
+}
+
+/**
+ * Create new transform feedback objects. Transform feedback objects
+ * encapsulate the state related to transform feedback to allow quickly
+ * switching state (and drawing the results, below).
+ * Part of GL_ARB_direct_state_access.
+ */
+void GLAPIENTRY
+_mesa_CreateTransformFeedbacks(GLsizei n, GLuint *names)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ create_transform_feedbacks(ctx, n, names, true);
+}
+
/**
* Is the given ID a transform feedback object?
@@ -1026,3 +1208,89 @@ _mesa_ResumeTransformFeedback(void)
assert(ctx->Driver.ResumeTransformFeedback);
ctx->Driver.ResumeTransformFeedback(ctx, obj);
}
+
+extern void GLAPIENTRY
+_mesa_GetTransformFeedbackiv(GLuint xfb, GLenum pname, GLint *param)
+{
+ struct gl_transform_feedback_object *obj;
+ GET_CURRENT_CONTEXT(ctx);
+
+ obj = lookup_transform_feedback_object_err(ctx, xfb,
+ "glGetTransformFeedbackiv");
+ if(!obj) {
+ return;
+ }
+
+ switch(pname) {
+ case GL_TRANSFORM_FEEDBACK_PAUSED:
+ *param = obj->Paused;
+ break;
+ case GL_TRANSFORM_FEEDBACK_ACTIVE:
+ *param = obj->Active;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetTransformFeedbackiv(pname=%i)", pname);
+ }
+}
+
+extern void GLAPIENTRY
+_mesa_GetTransformFeedbacki_v(GLuint xfb, GLenum pname, GLuint index,
+ GLint *param)
+{
+ struct gl_transform_feedback_object *obj;
+ GET_CURRENT_CONTEXT(ctx);
+
+ obj = lookup_transform_feedback_object_err(ctx, xfb,
+ "glGetTransformFeedbacki_v");
+ if(!obj) {
+ return;
+ }
+
+ if (index >= ctx->Const.MaxTransformFeedbackBuffers) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetTransformFeedbacki_v(index=%i)", index);
+ return;
+ }
+
+ switch(pname) {
+ case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ *param = obj->BufferNames[index];
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetTransformFeedbacki_v(pname=%i)", pname);
+ }
+}
+
+extern void GLAPIENTRY
+_mesa_GetTransformFeedbacki64_v(GLuint xfb, GLenum pname, GLuint index,
+ GLint64 *param)
+{
+ struct gl_transform_feedback_object *obj;
+ GET_CURRENT_CONTEXT(ctx);
+
+ obj = lookup_transform_feedback_object_err(ctx, xfb,
+ "glGetTransformFeedbacki64_v");
+ if(!obj) {
+ return;
+ }
+
+ if (index >= ctx->Const.MaxTransformFeedbackBuffers) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetTransformFeedbacki64_v(index=%i)", index);
+ return;
+ }
+
+ switch(pname) {
+ case GL_TRANSFORM_FEEDBACK_BUFFER_START:
+ *param = obj->Offset[index];
+ break;
+ case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
+ *param = obj->RequestedSize[index];
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetTransformFeedbacki64_v(pname=%i)", pname);
+ }
+}
diff --git a/mesalib/src/mesa/main/transformfeedback.h b/mesalib/src/mesa/main/transformfeedback.h
index 87f4080e0..bb9729cdb 100644
--- a/mesalib/src/mesa/main/transformfeedback.h
+++ b/mesalib/src/mesa/main/transformfeedback.h
@@ -65,15 +65,18 @@ _mesa_EndTransformFeedback(void);
extern void
_mesa_bind_buffer_range_transform_feedback(struct gl_context *ctx,
+ struct gl_transform_feedback_object *obj,
GLuint index,
struct gl_buffer_object *bufObj,
GLintptr offset,
- GLsizeiptr size);
+ GLsizeiptr size, bool dsa);
extern void
_mesa_bind_buffer_base_transform_feedback(struct gl_context *ctx,
+ struct gl_transform_feedback_object *obj,
GLuint index,
- struct gl_buffer_object *bufObj);
+ struct gl_buffer_object *bufObj,
+ bool dsa);
extern void GLAPIENTRY
_mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer,
@@ -102,6 +105,9 @@ _mesa_lookup_transform_feedback_object(struct gl_context *ctx, GLuint name);
extern void GLAPIENTRY
_mesa_GenTransformFeedbacks(GLsizei n, GLuint *names);
+extern void GLAPIENTRY
+_mesa_CreateTransformFeedbacks(GLsizei n, GLuint *names);
+
extern GLboolean GLAPIENTRY
_mesa_IsTransformFeedback(GLuint name);
@@ -141,4 +147,24 @@ _mesa_set_transform_feedback_binding(struct gl_context *ctx,
tfObj->RequestedSize[index] = size;
}
+/*** GL_ARB_direct_state_access ***/
+
+extern void GLAPIENTRY
+_mesa_TransformFeedbackBufferBase(GLuint xfb, GLuint index, GLuint buffer);
+
+extern void GLAPIENTRY
+_mesa_TransformFeedbackBufferRange(GLuint xfb, GLuint index, GLuint buffer,
+ GLintptr offset, GLsizeiptr size);
+
+extern void GLAPIENTRY
+_mesa_GetTransformFeedbackiv(GLuint xfb, GLenum pname, GLint *param);
+
+extern void GLAPIENTRY
+_mesa_GetTransformFeedbacki_v(GLuint xfb, GLenum pname, GLuint index,
+ GLint *param);
+
+extern void GLAPIENTRY
+_mesa_GetTransformFeedbacki64_v(GLuint xfb, GLenum pname, GLuint index,
+ GLint64 *param);
+
#endif /* TRANSFORM_FEEDBACK_H */
diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp
index 2ab5528c3..4e77b3284 100644
--- a/mesalib/src/mesa/main/uniform_query.cpp
+++ b/mesalib/src/mesa/main/uniform_query.cpp
@@ -46,6 +46,7 @@ _mesa_GetActiveUniform(GLuint program, GLuint index,
{
GET_CURRENT_CONTEXT(ctx);
struct gl_shader_program *shProg;
+ struct gl_program_resource *res;
if (maxLength < 0) {
_mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(maxLength < 0)");
@@ -56,26 +57,51 @@ _mesa_GetActiveUniform(GLuint program, GLuint index,
if (!shProg)
return;
- if (index >= shProg->NumUserUniformStorage) {
+ res = _mesa_program_resource_find_index((struct gl_shader_program *) shProg,
+ GL_UNIFORM, index);
+
+ if (!res) {
_mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
return;
}
- const struct gl_uniform_storage *const uni = &shProg->UniformStorage[index];
-
- if (nameOut) {
- _mesa_get_uniform_name(uni, maxLength, length, nameOut);
- }
-
- if (size) {
- /* array_elements is zero for non-arrays, but the API requires that 1 be
- * returned.
- */
- *size = MAX2(1, uni->array_elements);
- }
+ if (nameOut)
+ _mesa_get_program_resource_name(shProg, GL_UNIFORM, index, maxLength,
+ length, nameOut, "glGetActiveUniform");
+ if (type)
+ _mesa_program_resource_prop((struct gl_shader_program *) shProg,
+ res, index, GL_TYPE, (GLint*) type,
+ "glGetActiveUniform");
+ if (size)
+ _mesa_program_resource_prop((struct gl_shader_program *) shProg,
+ res, index, GL_ARRAY_SIZE, (GLint*) size,
+ "glGetActiveUniform");
+}
- if (type) {
- *type = uni->type->gl_type;
+static GLenum
+resource_prop_from_uniform_prop(GLenum uni_prop)
+{
+ switch (uni_prop) {
+ case GL_UNIFORM_TYPE:
+ return GL_TYPE;
+ case GL_UNIFORM_SIZE:
+ return GL_ARRAY_SIZE;
+ case GL_UNIFORM_NAME_LENGTH:
+ return GL_NAME_LENGTH;
+ case GL_UNIFORM_BLOCK_INDEX:
+ return GL_BLOCK_INDEX;
+ case GL_UNIFORM_OFFSET:
+ return GL_OFFSET;
+ case GL_UNIFORM_ARRAY_STRIDE:
+ return GL_ARRAY_STRIDE;
+ case GL_UNIFORM_MATRIX_STRIDE:
+ return GL_MATRIX_STRIDE;
+ case GL_UNIFORM_IS_ROW_MAJOR:
+ return GL_IS_ROW_MAJOR;
+ case GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX:
+ return GL_ATOMIC_COUNTER_BUFFER_INDEX;
+ default:
+ return 0;
}
}
@@ -88,7 +114,8 @@ _mesa_GetActiveUniformsiv(GLuint program,
{
GET_CURRENT_CONTEXT(ctx);
struct gl_shader_program *shProg;
- GLsizei i;
+ struct gl_program_resource *res;
+ GLenum res_prop;
if (uniformCount < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
@@ -100,80 +127,21 @@ _mesa_GetActiveUniformsiv(GLuint program,
if (!shProg)
return;
- for (i = 0; i < uniformCount; i++) {
- GLuint index = uniformIndices[i];
+ res_prop = resource_prop_from_uniform_prop(pname);
- if (index >= shProg->NumUserUniformStorage) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniformsiv(index)");
- return;
+ for (int i = 0; i < uniformCount; i++) {
+ res = _mesa_program_resource_find_index(shProg, GL_UNIFORM,
+ uniformIndices[i]);
+ if (!res) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniformsiv(index)");
+ break;
}
- }
-
- for (i = 0; i < uniformCount; i++) {
- GLuint index = uniformIndices[i];
- const struct gl_uniform_storage *uni = &shProg->UniformStorage[index];
-
- switch (pname) {
- case GL_UNIFORM_TYPE:
- params[i] = uni->type->gl_type;
- break;
-
- case GL_UNIFORM_SIZE:
- /* array_elements is zero for non-arrays, but the API requires that 1 be
- * returned.
- */
- params[i] = MAX2(1, uni->array_elements);
- break;
- case GL_UNIFORM_NAME_LENGTH:
- params[i] = strlen(uni->name) + 1;
-
- /* Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0
- * spec says:
- *
- * "If the active uniform is an array, the uniform name returned
- * in name will always be the name of the uniform array appended
- * with "[0]"."
- */
- if (uni->array_elements != 0)
- params[i] += 3;
- break;
-
- case GL_UNIFORM_BLOCK_INDEX:
- params[i] = uni->block_index;
- break;
-
- case GL_UNIFORM_OFFSET:
- params[i] = uni->offset;
- break;
-
- case GL_UNIFORM_ARRAY_STRIDE:
- params[i] = uni->array_stride;
- break;
-
- case GL_UNIFORM_MATRIX_STRIDE:
- params[i] = uni->matrix_stride;
- break;
-
- case GL_UNIFORM_IS_ROW_MAJOR:
- params[i] = uni->row_major;
- break;
-
- case GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX:
- if (!ctx->Extensions.ARB_shader_atomic_counters)
- goto invalid_enum;
- params[i] = uni->atomic_buffer_index;
+ if (!_mesa_program_resource_prop(shProg, res, uniformIndices[i],
+ res_prop, &params[i],
+ "glGetActiveUniformsiv"))
break;
-
- default:
- goto invalid_enum;
- }
}
-
- return;
-
- invalid_enum:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetActiveUniformsiv(pname)");
}
static struct gl_uniform_storage *
diff --git a/mesalib/src/mesa/main/uniforms.c b/mesalib/src/mesa/main/uniforms.c
index fb1482f9c..5548d1d02 100644
--- a/mesalib/src/mesa/main/uniforms.c
+++ b/mesalib/src/mesa/main/uniforms.c
@@ -911,7 +911,6 @@ GLint GLAPIENTRY
_mesa_GetUniformLocation(GLuint programObj, const GLcharARB *name)
{
struct gl_shader_program *shProg;
- GLuint index, offset;
GET_CURRENT_CONTEXT(ctx);
@@ -931,23 +930,7 @@ _mesa_GetUniformLocation(GLuint programObj, const GLcharARB *name)
return -1;
}
- index = _mesa_get_uniform_location(shProg, name, &offset);
- if (index == GL_INVALID_INDEX)
- return -1;
-
- /* From the GL_ARB_uniform_buffer_object spec:
- *
- * "The value -1 will be returned if <name> does not correspond to an
- * active uniform variable name in <program>, if <name> is associated
- * with a named uniform block, or if <name> starts with the reserved
- * prefix "gl_"."
- */
- if (shProg->UniformStorage[index].block_index != -1 ||
- shProg->UniformStorage[index].atomic_buffer_index != -1)
- return -1;
-
- /* location in remap table + array element offset */
- return shProg->UniformStorage[index].remap_location + offset;
+ return _mesa_program_resource_location(shProg, GL_UNIFORM, name);
}
GLuint GLAPIENTRY
@@ -955,7 +938,6 @@ _mesa_GetUniformBlockIndex(GLuint program,
const GLchar *uniformBlockName)
{
GET_CURRENT_CONTEXT(ctx);
- GLuint i;
struct gl_shader_program *shProg;
if (!ctx->Extensions.ARB_uniform_buffer_object) {
@@ -968,12 +950,13 @@ _mesa_GetUniformBlockIndex(GLuint program,
if (!shProg)
return GL_INVALID_INDEX;
- for (i = 0; i < shProg->NumUniformBlocks; i++) {
- if (!strcmp(shProg->UniformBlocks[i].Name, uniformBlockName))
- return i;
- }
+ struct gl_program_resource *res =
+ _mesa_program_resource_find_name(shProg, GL_UNIFORM_BLOCK,
+ uniformBlockName);
+ if (!res)
+ return GL_INVALID_INDEX;
- return GL_INVALID_INDEX;
+ return _mesa_program_resource_index(shProg, res);
}
void GLAPIENTRY
@@ -1003,9 +986,9 @@ _mesa_GetUniformIndices(GLuint program,
}
for (i = 0; i < uniformCount; i++) {
- unsigned offset;
- uniformIndices[i] = _mesa_get_uniform_location(shProg,
- uniformNames[i], &offset);
+ struct gl_program_resource *res =
+ _mesa_program_resource_find_name(shProg, GL_UNIFORM, uniformNames[i]);
+ uniformIndices[i] = _mesa_program_resource_index(shProg, res);
}
}
@@ -1061,104 +1044,104 @@ _mesa_UniformBlockBinding(GLuint program,
}
}
-void GLAPIENTRY
-_mesa_GetActiveUniformBlockiv(GLuint program,
- GLuint uniformBlockIndex,
- GLenum pname,
- GLint *params)
+
+/**
+ * Generic program resource property query.
+ */
+static void
+mesa_bufferiv(struct gl_shader_program *shProg, GLenum type,
+ GLuint index, GLenum pname, GLint *params, const char *caller)
{
GET_CURRENT_CONTEXT(ctx);
- struct gl_shader_program *shProg;
- struct gl_uniform_block *block;
- unsigned i;
+ struct gl_program_resource *res =
+ _mesa_program_resource_find_index(shProg, type, index);
- if (!ctx->Extensions.ARB_uniform_buffer_object) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv");
+ if (!res) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(bufferindex %d)", caller, index);
return;
}
- shProg = _mesa_lookup_shader_program_err(ctx, program,
- "glGetActiveUniformBlockiv");
- if (!shProg)
- return;
-
- if (uniformBlockIndex >= shProg->NumUniformBlocks) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glGetActiveUniformBlockiv(block index %u >= %u)",
- uniformBlockIndex, shProg->NumUniformBlocks);
- return;
- }
-
- block = &shProg->UniformBlocks[uniformBlockIndex];
-
switch (pname) {
case GL_UNIFORM_BLOCK_BINDING:
- params[0] = block->Binding;
+ case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+ _mesa_program_resource_prop(shProg, res, index, GL_BUFFER_BINDING,
+ params, caller);
return;
-
case GL_UNIFORM_BLOCK_DATA_SIZE:
- params[0] = block->UniformBufferSize;
+ case GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE:
+ _mesa_program_resource_prop(shProg, res, index, GL_BUFFER_DATA_SIZE,
+ params, caller);
return;
-
case GL_UNIFORM_BLOCK_NAME_LENGTH:
- params[0] = strlen(block->Name) + 1;
+ _mesa_program_resource_prop(shProg, res, index, GL_NAME_LENGTH,
+ params, caller);
return;
-
- case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: {
- unsigned count = 0;
-
- for (i = 0; i < block->NumUniforms; i++) {
- unsigned offset;
- const int idx =
- _mesa_get_uniform_location(shProg,
- block->Uniforms[i].IndexName,
- &offset);
- if (idx != -1)
- count++;
- }
-
- params[0] = count;
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
+ case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS:
+ _mesa_program_resource_prop(shProg, res, index, GL_NUM_ACTIVE_VARIABLES,
+ params, caller);
return;
- }
-
- case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: {
- unsigned count = 0;
-
- for (i = 0; i < block->NumUniforms; i++) {
- unsigned offset;
- const int idx =
- _mesa_get_uniform_location(shProg,
- block->Uniforms[i].IndexName,
- &offset);
-
- if (idx != -1)
- params[count++] = idx;
- }
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
+ case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES:
+ _mesa_program_resource_prop(shProg, res, index, GL_ACTIVE_VARIABLES,
+ params, caller);
return;
- }
-
case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
- params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_VERTEX][uniformBlockIndex] != -1;
+ case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER:
+ _mesa_program_resource_prop(shProg, res, index,
+ GL_REFERENCED_BY_VERTEX_SHADER, params,
+ caller);
return;
-
case GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER:
- if (!_mesa_has_geometry_shaders(ctx))
- break;
- params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_GEOMETRY][uniformBlockIndex] != -1;
+ case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER:
+ _mesa_program_resource_prop(shProg, res, index,
+ GL_REFERENCED_BY_GEOMETRY_SHADER, params,
+ caller);
return;
-
case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
- params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_FRAGMENT][uniformBlockIndex] != -1;
+ case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER:
+ _mesa_program_resource_prop(shProg, res, index,
+ GL_REFERENCED_BY_FRAGMENT_SHADER, params,
+ caller);
+ return;
+ case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER:
+ params[0] = GL_FALSE;
+ return;
+ case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER:
+ params[0] = GL_FALSE;
return;
-
default:
_mesa_error(ctx, GL_INVALID_ENUM,
- "glGetActiveUniformBlockiv(pname 0x%x (%s))",
- pname, _mesa_lookup_enum_by_nr(pname));
+ "%s(pname 0x%x (%s))", caller, pname,
+ _mesa_lookup_enum_by_nr(pname));
return;
}
}
+
+void GLAPIENTRY
+_mesa_GetActiveUniformBlockiv(GLuint program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg;
+
+ if (!ctx->Extensions.ARB_uniform_buffer_object) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv");
+ return;
+ }
+
+ shProg = _mesa_lookup_shader_program_err(ctx, program,
+ "glGetActiveUniformBlockiv");
+ if (!shProg)
+ return;
+
+ mesa_bufferiv(shProg, GL_UNIFORM_BLOCK, uniformBlockIndex, pname, params,
+ "glGetActiveUniformBlockiv");
+}
+
void GLAPIENTRY
_mesa_GetActiveUniformBlockName(GLuint program,
GLuint uniformBlockIndex,
@@ -1168,7 +1151,6 @@ _mesa_GetActiveUniformBlockName(GLuint program,
{
GET_CURRENT_CONTEXT(ctx);
struct gl_shader_program *shProg;
- struct gl_uniform_block *block;
if (!ctx->Extensions.ARB_uniform_buffer_object) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv");
@@ -1187,18 +1169,11 @@ _mesa_GetActiveUniformBlockName(GLuint program,
if (!shProg)
return;
- if (uniformBlockIndex >= shProg->NumUniformBlocks) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glGetActiveUniformBlockiv(block index %u >= %u)",
- uniformBlockIndex, shProg->NumUniformBlocks);
- return;
- }
-
- block = &shProg->UniformBlocks[uniformBlockIndex];
-
- if (uniformBlockName) {
- _mesa_copy_string(uniformBlockName, bufSize, length, block->Name);
- }
+ if (uniformBlockName)
+ _mesa_get_program_resource_name(shProg, GL_UNIFORM_BLOCK,
+ uniformBlockIndex, bufSize, length,
+ uniformBlockName,
+ "glGetActiveUniformBlockName");
}
void GLAPIENTRY
@@ -1226,54 +1201,8 @@ _mesa_GetActiveUniformName(GLuint program, GLuint uniformIndex,
if (!shProg)
return;
- if (uniformIndex >= shProg->NumUserUniformStorage) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
- return;
- }
-
- if (uniformName) {
- _mesa_get_uniform_name(& shProg->UniformStorage[uniformIndex],
- bufSize, length, uniformName);
- }
-}
-
-void
-_mesa_get_uniform_name(const struct gl_uniform_storage *uni,
- GLsizei maxLength, GLsizei *length,
- GLchar *nameOut)
-{
- GLsizei localLength;
-
- if (length == NULL)
- length = &localLength;
-
- _mesa_copy_string(nameOut, maxLength, length, uni->name);
-
- /* Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0
- * spec says:
- *
- * "If the active uniform is an array, the uniform name returned in
- * name will always be the name of the uniform array appended with
- * "[0]"."
- *
- * The same text also appears in the OpenGL 4.2 spec. It does not,
- * however, appear in any previous spec. Previous specifications are
- * ambiguous in this regard. However, either name can later be passed
- * to glGetUniformLocation (and related APIs), so there shouldn't be any
- * harm in always appending "[0]" to uniform array names.
- */
- if (uni->array_elements != 0) {
- int i;
-
- /* The comparison is strange because *length does *NOT* include the
- * terminating NUL, but maxLength does.
- */
- for (i = 0; i < 3 && (*length + i + 1) < maxLength; i++)
- nameOut[*length + i] = "[0]"[i];
-
- nameOut[*length + i] = '\0';
- *length += i;
- }
+ _mesa_get_program_resource_name(shProg, GL_UNIFORM, uniformIndex, bufSize,
+ length, uniformName, "glGetActiveUniformName");
}
void GLAPIENTRY
@@ -1282,8 +1211,6 @@ _mesa_GetActiveAtomicCounterBufferiv(GLuint program, GLuint bufferIndex,
{
GET_CURRENT_CONTEXT(ctx);
struct gl_shader_program *shProg;
- struct gl_active_atomic_buffer *ab;
- GLuint i;
if (!ctx->Extensions.ARB_shader_atomic_counters) {
_mesa_error(ctx, GL_INVALID_OPERATION,
@@ -1296,49 +1223,8 @@ _mesa_GetActiveAtomicCounterBufferiv(GLuint program, GLuint bufferIndex,
if (!shProg)
return;
- if (bufferIndex >= shProg->NumAtomicBuffers) {
- _mesa_error(ctx, GL_INVALID_VALUE,
- "glGetActiveAtomicCounterBufferiv(bufferIndex)");
- return;
- }
-
- ab = &shProg->AtomicBuffers[bufferIndex];
-
- switch (pname) {
- case GL_ATOMIC_COUNTER_BUFFER_BINDING:
- params[0] = ab->Binding;
- return;
- case GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE:
- params[0] = ab->MinimumSize;
- return;
- case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS:
- params[0] = ab->NumUniforms;
- return;
- case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES:
- for (i = 0; i < ab->NumUniforms; ++i)
- params[i] = ab->Uniforms[i];
- return;
- case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER:
- params[0] = ab->StageReferences[MESA_SHADER_VERTEX];
- return;
- case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER:
- params[0] = ab->StageReferences[MESA_SHADER_GEOMETRY];
- return;
- case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER:
- params[0] = ab->StageReferences[MESA_SHADER_FRAGMENT];
- return;
- case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER:
- params[0] = GL_FALSE;
- return;
- case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER:
- params[0] = GL_FALSE;
- return;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetActiveAtomicCounterBufferiv(pname 0x%x (%s))",
- pname, _mesa_lookup_enum_by_nr(pname));
- return;
- }
+ mesa_bufferiv(shProg, GL_ATOMIC_COUNTER_BUFFER, bufferIndex, pname, params,
+ "glGetActiveAtomicCounterBufferiv");
}
void GLAPIENTRY
diff --git a/mesalib/src/mesa/main/uniforms.h b/mesalib/src/mesa/main/uniforms.h
index 0e6113fe9..55fa2357e 100644
--- a/mesalib/src/mesa/main/uniforms.h
+++ b/mesalib/src/mesa/main/uniforms.h
@@ -398,11 +398,6 @@ _mesa_sampler_uniforms_pipeline_are_valid(struct gl_pipeline_object *);
extern const struct gl_program_parameter *
get_uniform_parameter(struct gl_shader_program *shProg, GLint index);
-extern void
-_mesa_get_uniform_name(const struct gl_uniform_storage *uni,
- GLsizei maxLength, GLsizei *length,
- GLchar *nameOut);
-
struct gl_builtin_uniform_element {
const char *field;
int tokens[STATE_LENGTH];
diff --git a/mesalib/src/mesa/main/version.c b/mesalib/src/mesa/main/version.c
index 8e0c3ef5b..7c6d99418 100644
--- a/mesalib/src/mesa/main/version.c
+++ b/mesalib/src/mesa/main/version.c
@@ -382,6 +382,7 @@ compute_version_es2(const struct gl_extensions *extensions)
extensions->ARB_shader_texture_lod &&
extensions->ARB_texture_float &&
extensions->ARB_texture_rg &&
+ extensions->ARB_depth_buffer_float &&
extensions->EXT_draw_buffers2 &&
/* extensions->ARB_framebuffer_object && */
extensions->EXT_framebuffer_sRGB &&
diff --git a/mesalib/src/mesa/main/viewport.c b/mesalib/src/mesa/main/viewport.c
index 0adce9c78..b27063031 100644
--- a/mesalib/src/mesa/main/viewport.c
+++ b/mesalib/src/mesa/main/viewport.c
@@ -40,8 +40,6 @@ set_viewport_no_notify(struct gl_context *ctx, unsigned idx,
GLfloat x, GLfloat y,
GLfloat width, GLfloat height)
{
- double scale[3], translate[3];
-
/* clamp width and height to the implementation dependent range */
width = MIN2(width, (GLfloat) ctx->Const.MaxViewportWidth);
height = MIN2(height, (GLfloat) ctx->Const.MaxViewportHeight);
@@ -72,16 +70,6 @@ set_viewport_no_notify(struct gl_context *ctx, unsigned idx,
ctx->ViewportArray[idx].Y = y;
ctx->ViewportArray[idx].Height = height;
ctx->NewState |= _NEW_VIEWPORT;
-
-#if 1
- /* XXX remove this someday. Currently the DRI drivers rely on
- * the WindowMap matrix being up to date in the driver's Viewport
- * and DepthRange functions.
- */
- _mesa_get_viewport_xform(ctx, idx, scale, translate);
- _math_matrix_viewport(&ctx->ViewportArray[idx]._WindowMap,
- scale, translate, ctx->DrawBuffer->_DepthMaxF);
-#endif
}
struct gl_viewport_inputs {
@@ -140,8 +128,8 @@ _mesa_Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
/**
- * Set new viewport parameters and update derived state (the _WindowMap
- * matrix). Usually called from _mesa_Viewport().
+ * Set new viewport parameters and update derived state.
+ * Usually called from _mesa_Viewport().
*
* \param ctx GL context.
* \param idx Index of the viewport to be updated.
@@ -246,8 +234,6 @@ static void
set_depth_range_no_notify(struct gl_context *ctx, unsigned idx,
GLclampd nearval, GLclampd farval)
{
- double scale[3], translate[3];
-
if (ctx->ViewportArray[idx].Near == nearval &&
ctx->ViewportArray[idx].Far == farval)
return;
@@ -255,16 +241,6 @@ set_depth_range_no_notify(struct gl_context *ctx, unsigned idx,
ctx->ViewportArray[idx].Near = CLAMP(nearval, 0.0, 1.0);
ctx->ViewportArray[idx].Far = CLAMP(farval, 0.0, 1.0);
ctx->NewState |= _NEW_VIEWPORT;
-
-#if 1
- /* XXX remove this someday. Currently the DRI drivers rely on
- * the WindowMap matrix being up to date in the driver's Viewport
- * and DepthRange functions.
- */
- _mesa_get_viewport_xform(ctx, idx, scale, translate);
- _math_matrix_viewport(&ctx->ViewportArray[idx]._WindowMap,
- scale, translate, ctx->DrawBuffer->_DepthMaxF);
-#endif
}
void
@@ -388,7 +364,6 @@ _mesa_DepthRangeIndexed(GLuint index, GLclampd nearval, GLclampd farval)
*/
void _mesa_init_viewport(struct gl_context *ctx)
{
- GLfloat depthMax = 65535.0F; /* sorf of arbitrary */
unsigned i;
ctx->Transform.ClipOrigin = GL_LOWER_LEFT;
@@ -398,8 +373,6 @@ void _mesa_init_viewport(struct gl_context *ctx)
* so just initialize all of them.
*/
for (i = 0; i < MAX_VIEWPORTS; i++) {
- double scale[3], translate[3];
-
/* Viewport group */
ctx->ViewportArray[i].X = 0;
ctx->ViewportArray[i].Y = 0;
@@ -407,27 +380,10 @@ void _mesa_init_viewport(struct gl_context *ctx)
ctx->ViewportArray[i].Height = 0;
ctx->ViewportArray[i].Near = 0.0;
ctx->ViewportArray[i].Far = 1.0;
- _math_matrix_ctr(&ctx->ViewportArray[i]._WindowMap);
-
- _mesa_get_viewport_xform(ctx, i, scale, translate);
- _math_matrix_viewport(&ctx->ViewportArray[i]._WindowMap,
- scale, translate, depthMax);
}
}
-/**
- * Free the context viewport attribute group data.
- * \param ctx the GL context.
- */
-void _mesa_free_viewport_data(struct gl_context *ctx)
-{
- unsigned i;
-
- for (i = 0; i < MAX_VIEWPORTS; i++)
- _math_matrix_dtr(&ctx->ViewportArray[i]._WindowMap);
-}
-
extern void GLAPIENTRY
_mesa_ClipControl(GLenum origin, GLenum depth)
{
diff --git a/mesalib/src/mesa/main/viewport.h b/mesalib/src/mesa/main/viewport.h
index 426e194bd..899dc2d0b 100644
--- a/mesalib/src/mesa/main/viewport.h
+++ b/mesalib/src/mesa/main/viewport.h
@@ -68,9 +68,6 @@ extern void
_mesa_init_viewport(struct gl_context *ctx);
-extern void
-_mesa_free_viewport_data(struct gl_context *ctx);
-
extern void GLAPIENTRY
_mesa_ClipControl(GLenum origin, GLenum depth);
diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp
index 39790ec8e..3dcb53702 100644
--- a/mesalib/src/mesa/program/ir_to_mesa.cpp
+++ b/mesalib/src/mesa/program/ir_to_mesa.cpp
@@ -303,9 +303,6 @@ public:
void emit_scalar(ir_instruction *ir, enum prog_opcode op,
dst_reg dst, src_reg src0, src_reg src1);
- void emit_scs(ir_instruction *ir, enum prog_opcode op,
- dst_reg dst, const src_reg &src);
-
bool try_emit_mad(ir_expression *ir,
int mul_operand);
bool try_emit_mad_for_and_not(ir_expression *ir,
@@ -479,101 +476,6 @@ ir_to_mesa_visitor::emit_scalar(ir_instruction *ir, enum prog_opcode op,
emit_scalar(ir, op, dst, src0, undef);
}
-/**
- * Emit an OPCODE_SCS instruction
- *
- * The \c SCS opcode functions a bit differently than the other Mesa (or
- * ARB_fragment_program) opcodes. Instead of splatting its result across all
- * four components of the destination, it writes one value to the \c x
- * component and another value to the \c y component.
- *
- * \param ir IR instruction being processed
- * \param op Either \c OPCODE_SIN or \c OPCODE_COS depending on which
- * value is desired.
- * \param dst Destination register
- * \param src Source register
- */
-void
-ir_to_mesa_visitor::emit_scs(ir_instruction *ir, enum prog_opcode op,
- dst_reg dst,
- const src_reg &src)
-{
- /* Vertex programs cannot use the SCS opcode.
- */
- if (this->prog->Target == GL_VERTEX_PROGRAM_ARB) {
- emit_scalar(ir, op, dst, src);
- return;
- }
-
- const unsigned component = (op == OPCODE_SIN) ? 0 : 1;
- const unsigned scs_mask = (1U << component);
- int done_mask = ~dst.writemask;
- src_reg tmp;
-
- assert(op == OPCODE_SIN || op == OPCODE_COS);
-
- /* If there are compnents in the destination that differ from the component
- * that will be written by the SCS instrution, we'll need a temporary.
- */
- if (scs_mask != unsigned(dst.writemask)) {
- tmp = get_temp(glsl_type::vec4_type);
- }
-
- for (unsigned i = 0; i < 4; i++) {
- unsigned this_mask = (1U << i);
- src_reg src0 = src;
-
- if ((done_mask & this_mask) != 0)
- continue;
-
- /* The source swizzle specified which component of the source generates
- * sine / cosine for the current component in the destination. The SCS
- * instruction requires that this value be swizzle to the X component.
- * Replace the current swizzle with a swizzle that puts the source in
- * the X component.
- */
- unsigned src0_swiz = GET_SWZ(src.swizzle, i);
-
- src0.swizzle = MAKE_SWIZZLE4(src0_swiz, src0_swiz,
- src0_swiz, src0_swiz);
- for (unsigned j = i + 1; j < 4; j++) {
- /* If there is another enabled component in the destination that is
- * derived from the same inputs, generate its value on this pass as
- * well.
- */
- if (!(done_mask & (1 << j)) &&
- GET_SWZ(src0.swizzle, j) == src0_swiz) {
- this_mask |= (1 << j);
- }
- }
-
- if (this_mask != scs_mask) {
- ir_to_mesa_instruction *inst;
- dst_reg tmp_dst = dst_reg(tmp);
-
- /* Emit the SCS instruction.
- */
- inst = emit(ir, OPCODE_SCS, tmp_dst, src0);
- inst->dst.writemask = scs_mask;
-
- /* Move the result of the SCS instruction to the desired location in
- * the destination.
- */
- tmp.swizzle = MAKE_SWIZZLE4(component, component,
- component, component);
- inst = emit(ir, OPCODE_SCS, dst, tmp);
- inst->dst.writemask = this_mask;
- } else {
- /* Emit the SCS instruction to write directly to the destination.
- */
- ir_to_mesa_instruction *inst = emit(ir, OPCODE_SCS, dst, src0);
- inst->dst.writemask = scs_mask;
- }
-
- done_mask |= this_mask;
- }
-}
-
src_reg
ir_to_mesa_visitor::src_reg_for_float(float val)
{
@@ -1122,12 +1024,6 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
case ir_unop_cos:
emit_scalar(ir, OPCODE_COS, result_dst, op[0]);
break;
- case ir_unop_sin_reduced:
- emit_scs(ir, OPCODE_SIN, result_dst, op[0]);
- break;
- case ir_unop_cos_reduced:
- emit_scs(ir, OPCODE_COS, result_dst, op[0]);
- break;
case ir_unop_dFdx:
emit(ir, OPCODE_DDX, result_dst, op[0]);
diff --git a/mesalib/src/mesa/program/prog_execute.c b/mesalib/src/mesa/program/prog_execute.c
index dc4919ae8..16e8e340d 100644
--- a/mesalib/src/mesa/program/prog_execute.c
+++ b/mesalib/src/mesa/program/prog_execute.c
@@ -37,7 +37,6 @@
#include "c99_math.h"
#include "main/glheader.h"
-#include "main/colormac.h"
#include "main/macros.h"
#include "prog_execute.h"
#include "prog_instruction.h"
diff --git a/mesalib/src/mesa/program/prog_instruction.h b/mesalib/src/mesa/program/prog_instruction.h
index ab3acbc02..96da198f8 100644
--- a/mesalib/src/mesa/program/prog_instruction.h
+++ b/mesalib/src/mesa/program/prog_instruction.h
@@ -59,6 +59,8 @@
#define SWIZZLE_NOOP MAKE_SWIZZLE4(0,1,2,3)
#define GET_SWZ(swz, idx) (((swz) >> ((idx)*3)) & 0x7)
#define GET_BIT(msk, idx) (((msk) >> (idx)) & 0x1)
+/** Determine if swz contains SWIZZLE_ZERO/ONE/NIL for any components. */
+#define HAS_EXTENDED_SWIZZLE(swz) (swz & 0x924)
#define SWIZZLE_XYZW MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W)
#define SWIZZLE_XXXX MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X)
diff --git a/mesalib/src/mesa/program/prog_parameter.c b/mesalib/src/mesa/program/prog_parameter.c
index cdfe25145..53e9813e6 100644
--- a/mesalib/src/mesa/program/prog_parameter.c
+++ b/mesalib/src/mesa/program/prog_parameter.c
@@ -190,40 +190,6 @@ _mesa_add_parameter(struct gl_program_parameter_list *paramList,
/**
- * Add a new named constant to the parameter list.
- * This will be used when the program contains something like this:
- * PARAM myVals = { 0, 1, 2, 3 };
- *
- * \param paramList the parameter list
- * \param name the name for the constant
- * \param values four float values
- * \return index/position of the new parameter in the parameter list
- */
-GLint
-_mesa_add_named_constant(struct gl_program_parameter_list *paramList,
- const char *name, const gl_constant_value values[4],
- GLuint size)
-{
- /* first check if this is a duplicate constant */
- GLint pos;
- for (pos = 0; pos < (GLint)paramList->NumParameters; pos++) {
- const gl_constant_value *pvals = paramList->ParameterValues[pos];
- if (pvals[0].u == values[0].u &&
- pvals[1].u == values[1].u &&
- pvals[2].u == values[2].u &&
- pvals[3].u == values[3].u &&
- strcmp(paramList->Parameters[pos].Name, name) == 0) {
- /* Same name and value is already in the param list - reuse it */
- return pos;
- }
- }
- /* not found, add new parameter */
- return _mesa_add_parameter(paramList, PROGRAM_CONSTANT, name,
- size, GL_NONE, values, NULL);
-}
-
-
-/**
* Add a new unnamed constant to the parameter list. This will be used
* when a fragment/vertex program contains something like this:
* MOV r, { 0, 1, 2, 3 };
@@ -303,28 +269,6 @@ _mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList,
swizzleOut);
}
-#if 0 /* not used yet */
-/**
- * Returns the number of 4-component registers needed to store a piece
- * of GL state. For matrices this may be as many as 4 registers,
- * everything else needs
- * just 1 register.
- */
-static GLuint
-sizeof_state_reference(const GLint *stateTokens)
-{
- if (stateTokens[0] == STATE_MATRIX) {
- GLuint rows = stateTokens[4] - stateTokens[3] + 1;
- assert(rows >= 1);
- assert(rows <= 4);
- return rows;
- }
- else {
- return 1;
- }
-}
-#endif
-
/**
* Add a new state reference to the parameter list.
@@ -365,22 +309,6 @@ _mesa_add_state_reference(struct gl_program_parameter_list *paramList,
/**
- * Lookup a parameter value by name in the given parameter list.
- * \return pointer to the float[4] values.
- */
-gl_constant_value *
-_mesa_lookup_parameter_value(const struct gl_program_parameter_list *paramList,
- GLsizei nameLen, const char *name)
-{
- GLint i = _mesa_lookup_parameter_index(paramList, nameLen, name);
- if (i < 0)
- return NULL;
- else
- return paramList->ParameterValues[i];
-}
-
-
-/**
* Given a program parameter name, find its position in the list of parameters.
* \param paramList the parameter list to search
* \param nameLen length of name (in chars).
diff --git a/mesalib/src/mesa/program/prog_parameter.h b/mesalib/src/mesa/program/prog_parameter.h
index 6b3b3c262..74a5fd918 100644
--- a/mesalib/src/mesa/program/prog_parameter.h
+++ b/mesalib/src/mesa/program/prog_parameter.h
@@ -120,11 +120,6 @@ _mesa_add_parameter(struct gl_program_parameter_list *paramList,
const gl_state_index state[STATE_LENGTH]);
extern GLint
-_mesa_add_named_constant(struct gl_program_parameter_list *paramList,
- const char *name, const gl_constant_value values[4],
- GLuint size);
-
-extern GLint
_mesa_add_typed_unnamed_constant(struct gl_program_parameter_list *paramList,
const gl_constant_value values[4], GLuint size,
GLenum datatype, GLuint *swizzleOut);
@@ -138,10 +133,6 @@ extern GLint
_mesa_add_state_reference(struct gl_program_parameter_list *paramList,
const gl_state_index stateTokens[STATE_LENGTH]);
-extern gl_constant_value *
-_mesa_lookup_parameter_value(const struct gl_program_parameter_list *paramList,
- GLsizei nameLen, const char *name);
-
extern GLint
_mesa_lookup_parameter_index(const struct gl_program_parameter_list *paramList,
GLsizei nameLen, const char *name);
diff --git a/mesalib/src/mesa/program/prog_to_nir.c b/mesalib/src/mesa/program/prog_to_nir.c
new file mode 100644
index 000000000..c738f5073
--- /dev/null
+++ b/mesalib/src/mesa/program/prog_to_nir.c
@@ -0,0 +1,1096 @@
+/*
+ * Copyright © 2015 Intel Corporation
+ * Copyright © 2014-2015 Broadcom
+ * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "nir/nir.h"
+#include "nir/nir_builder.h"
+#include "glsl/list.h"
+#include "main/imports.h"
+#include "util/ralloc.h"
+
+#include "prog_to_nir.h"
+#include "prog_instruction.h"
+#include "prog_parameter.h"
+#include "prog_print.h"
+
+/**
+ * \file prog_to_nir.c
+ *
+ * A translator from Mesa IR (prog_instruction.h) to NIR. This is primarily
+ * intended to support ARB_vertex_program, ARB_fragment_program, and fixed-function
+ * vertex processing. Full GLSL support should use glsl_to_nir instead.
+ */
+
+struct ptn_compile {
+ const struct gl_program *prog;
+ nir_builder build;
+ bool error;
+
+ nir_variable *input_vars[VARYING_SLOT_MAX];
+ nir_variable *output_vars[VARYING_SLOT_MAX];
+ nir_register **output_regs;
+ nir_register **temp_regs;
+
+ nir_register *addr_reg;
+};
+
+#define SWIZ(X, Y, Z, W) \
+ (unsigned[4]){ SWIZZLE_##X, SWIZZLE_##Y, SWIZZLE_##Z, SWIZZLE_##W }
+#define ptn_swizzle(b, src, x, y, z, w) nir_swizzle(b, src, SWIZ(x, y, z, w), 4, true)
+#define ptn_channel(b, src, ch) nir_swizzle(b, src, SWIZ(ch, ch, ch, ch), 1, true)
+
+static nir_ssa_def *
+ptn_src_for_dest(struct ptn_compile *c, nir_alu_dest *dest)
+{
+ nir_builder *b = &c->build;
+
+ nir_alu_src src;
+ memset(&src, 0, sizeof(src));
+
+ if (dest->dest.is_ssa)
+ src.src = nir_src_for_ssa(&dest->dest.ssa);
+ else {
+ assert(!dest->dest.reg.indirect);
+ src.src = nir_src_for_reg(dest->dest.reg.reg);
+ src.src.reg.base_offset = dest->dest.reg.base_offset;
+ }
+
+ for (int i = 0; i < 4; i++)
+ src.swizzle[i] = i;
+
+ return nir_fmov_alu(b, src, 4);
+}
+
+static nir_alu_dest
+ptn_get_dest(struct ptn_compile *c, const struct prog_dst_register *prog_dst)
+{
+ nir_alu_dest dest;
+
+ memset(&dest, 0, sizeof(dest));
+
+ switch (prog_dst->File) {
+ case PROGRAM_TEMPORARY:
+ dest.dest.reg.reg = c->temp_regs[prog_dst->Index];
+ break;
+ case PROGRAM_OUTPUT:
+ dest.dest.reg.reg = c->output_regs[prog_dst->Index];
+ break;
+ case PROGRAM_ADDRESS:
+ assert(prog_dst->Index == 0);
+ dest.dest.reg.reg = c->addr_reg;
+ break;
+ case PROGRAM_UNDEFINED:
+ break;
+ }
+
+ dest.write_mask = prog_dst->WriteMask;
+ dest.saturate = false;
+
+ assert(!prog_dst->RelAddr);
+
+ return dest;
+}
+
+/**
+ * Multiply the contents of the ADDR register by 4 to convert from the number
+ * of vec4s to the number of floating point components.
+ */
+static nir_ssa_def *
+ptn_addr_reg_value(struct ptn_compile *c)
+{
+ nir_builder *b = &c->build;
+ nir_alu_src src;
+ memset(&src, 0, sizeof(src));
+ src.src = nir_src_for_reg(c->addr_reg);
+
+ return nir_imul(b, nir_fmov_alu(b, src, 1), nir_imm_int(b, 4));
+}
+
+static nir_ssa_def *
+ptn_get_src(struct ptn_compile *c, const struct prog_src_register *prog_src)
+{
+ nir_builder *b = &c->build;
+ nir_alu_src src;
+
+ memset(&src, 0, sizeof(src));
+
+ switch (prog_src->File) {
+ case PROGRAM_UNDEFINED:
+ return nir_imm_float(b, 0.0);
+ case PROGRAM_TEMPORARY:
+ assert(!prog_src->RelAddr && prog_src->Index >= 0);
+ src.src.reg.reg = c->temp_regs[prog_src->Index];
+ break;
+ case PROGRAM_INPUT: {
+ /* ARB_vertex_program doesn't allow relative addressing on vertex
+ * attributes; ARB_fragment_program has no relative addressing at all.
+ */
+ assert(!prog_src->RelAddr);
+
+ assert(prog_src->Index >= 0 && prog_src->Index < VARYING_SLOT_MAX);
+
+ nir_intrinsic_instr *load =
+ nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_var);
+ load->num_components = 4;
+ load->variables[0] = nir_deref_var_create(load, c->input_vars[prog_src->Index]);
+
+ nir_ssa_dest_init(&load->instr, &load->dest, 4, NULL);
+ nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr);
+
+ src.src = nir_src_for_ssa(&load->dest.ssa);
+ break;
+ }
+ case PROGRAM_STATE_VAR:
+ case PROGRAM_CONSTANT: {
+ /* We actually want to look at the type in the Parameters list for this,
+ * because it lets us upload constant builtin uniforms as actual
+ * constants.
+ */
+ struct gl_program_parameter_list *plist = c->prog->Parameters;
+ gl_register_file file = prog_src->RelAddr ? prog_src->File :
+ plist->Parameters[prog_src->Index].Type;
+
+ switch (file) {
+ case PROGRAM_CONSTANT:
+ if ((c->prog->IndirectRegisterFiles & (1 << PROGRAM_CONSTANT)) == 0) {
+ float *v = (float *) plist->ParameterValues[prog_src->Index];
+ src.src = nir_src_for_ssa(nir_imm_vec4(b, v[0], v[1], v[2], v[3]));
+ break;
+ }
+ /* FALLTHROUGH */
+ case PROGRAM_STATE_VAR: {
+ nir_intrinsic_op load_op =
+ prog_src->RelAddr ? nir_intrinsic_load_uniform_indirect :
+ nir_intrinsic_load_uniform;
+ nir_intrinsic_instr *load = nir_intrinsic_instr_create(b->shader, load_op);
+ nir_ssa_dest_init(&load->instr, &load->dest, 4, NULL);
+ load->num_components = 4;
+
+ /* Multiply src->Index by 4 to scale from # of vec4s to components. */
+ load->const_index[0] = 4 * prog_src->Index;
+ load->const_index[1] = 1;
+
+ if (prog_src->RelAddr) {
+ nir_ssa_def *reladdr = ptn_addr_reg_value(c);
+ if (prog_src->Index < 0) {
+ /* This is a negative offset which should be added to the address
+ * register's value.
+ */
+ reladdr = nir_iadd(b, reladdr, nir_imm_int(b, load->const_index[0]));
+ load->const_index[0] = 0;
+ }
+ load->src[0] = nir_src_for_ssa(reladdr);
+ }
+
+ nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr);
+
+ src.src = nir_src_for_ssa(&load->dest.ssa);
+ break;
+ }
+ default:
+ fprintf(stderr, "bad uniform src register file: %s (%d)\n",
+ _mesa_register_file_name(file), file);
+ abort();
+ }
+ break;
+ }
+ default:
+ fprintf(stderr, "unknown src register file: %s (%d)\n",
+ _mesa_register_file_name(prog_src->File), prog_src->File);
+ abort();
+ }
+
+ nir_ssa_def *def;
+ if (!HAS_EXTENDED_SWIZZLE(prog_src->Swizzle)) {
+ for (int i = 0; i < 4; i++)
+ src.swizzle[i] = GET_SWZ(prog_src->Swizzle, i);
+
+ def = nir_fmov_alu(b, src, 4);
+ } else {
+ nir_ssa_def *chans[4];
+ for (int i = 0; i < 4; i++) {
+ int swizzle = GET_SWZ(prog_src->Swizzle, i);
+ if (swizzle == SWIZZLE_ZERO) {
+ chans[i] = nir_imm_float(b, 0.0);
+ } else if (swizzle == SWIZZLE_ONE) {
+ chans[i] = nir_imm_float(b, 1.0);
+ } else {
+ assert(swizzle != SWIZZLE_NIL);
+ nir_alu_instr *mov = nir_alu_instr_create(b->shader, nir_op_fmov);
+ nir_ssa_dest_init(&mov->instr, &mov->dest.dest, 1, NULL);
+ mov->dest.write_mask = 0x1;
+ mov->src[0] = src;
+ mov->src[0].swizzle[0] = swizzle;
+ nir_instr_insert_after_cf_list(b->cf_node_list, &mov->instr);
+
+ chans[i] = &mov->dest.dest.ssa;
+ }
+ }
+ def = nir_vec4(b, chans[0], chans[1], chans[2], chans[3]);
+ }
+
+ if (prog_src->Abs)
+ def = nir_fabs(b, def);
+
+ if (prog_src->Negate)
+ def = nir_fneg(b, def);
+
+ return def;
+}
+
+static void
+ptn_alu(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
+{
+ unsigned num_srcs = nir_op_infos[op].num_inputs;
+ nir_alu_instr *instr = nir_alu_instr_create(b->shader, op);
+ unsigned i;
+
+ for (i = 0; i < num_srcs; i++)
+ instr->src[i].src = nir_src_for_ssa(src[i]);
+
+ instr->dest = dest;
+ nir_instr_insert_after_cf_list(b->cf_node_list, &instr->instr);
+}
+
+static void
+ptn_move_dest_masked(nir_builder *b, nir_alu_dest dest,
+ nir_ssa_def *def, unsigned write_mask)
+{
+ if (!(dest.write_mask & write_mask))
+ return;
+
+ nir_alu_instr *mov = nir_alu_instr_create(b->shader, nir_op_fmov);
+ if (!mov)
+ return;
+
+ mov->dest = dest;
+ mov->dest.write_mask &= write_mask;
+ mov->src[0].src = nir_src_for_ssa(def);
+ for (unsigned i = def->num_components; i < 4; i++)
+ mov->src[0].swizzle[i] = def->num_components - 1;
+ nir_instr_insert_after_cf_list(b->cf_node_list, &mov->instr);
+}
+
+static void
+ptn_move_dest(nir_builder *b, nir_alu_dest dest, nir_ssa_def *def)
+{
+ ptn_move_dest_masked(b, dest, def, WRITEMASK_XYZW);
+}
+
+static void
+ptn_arl(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ptn_move_dest(b, dest, nir_f2i(b, nir_ffloor(b, src[0])));
+}
+
+/* EXP - Approximate Exponential Base 2
+ * dst.x = 2^{\lfloor src.x\rfloor}
+ * dst.y = src.x - \lfloor src.x\rfloor
+ * dst.z = 2^{src.x}
+ * dst.w = 1.0
+ */
+static void
+ptn_exp(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
+{
+ nir_ssa_def *srcx = ptn_channel(b, src[0], X);
+
+ ptn_move_dest_masked(b, dest, nir_fexp2(b, nir_ffloor(b, srcx)), WRITEMASK_X);
+ ptn_move_dest_masked(b, dest, nir_fsub(b, srcx, nir_ffloor(b, srcx)), WRITEMASK_Y);
+ ptn_move_dest_masked(b, dest, nir_fexp2(b, srcx), WRITEMASK_Z);
+ ptn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), WRITEMASK_W);
+}
+
+/* LOG - Approximate Logarithm Base 2
+ * dst.x = \lfloor\log_2{|src.x|}\rfloor
+ * dst.y = |src.x| * 2^{-\lfloor\log_2{|src.x|}\rfloor}}
+ * dst.z = \log_2{|src.x|}
+ * dst.w = 1.0
+ */
+static void
+ptn_log(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
+{
+ nir_ssa_def *abs_srcx = nir_fabs(b, ptn_channel(b, src[0], X));
+ nir_ssa_def *log2 = nir_flog2(b, abs_srcx);
+ nir_ssa_def *floor_log2 = nir_ffloor(b, log2);
+
+ ptn_move_dest_masked(b, dest, floor_log2, WRITEMASK_X);
+ ptn_move_dest_masked(b, dest,
+ nir_fmul(b, abs_srcx,
+ nir_fexp2(b, nir_fneg(b, floor_log2))),
+ WRITEMASK_Y);
+ ptn_move_dest_masked(b, dest, log2, WRITEMASK_Z);
+ ptn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), WRITEMASK_W);
+}
+
+/* DST - Distance Vector
+ * dst.x = 1.0
+ * dst.y = src0.y \times src1.y
+ * dst.z = src0.z
+ * dst.w = src1.w
+ */
+static void
+ptn_dst(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ptn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), WRITEMASK_X);
+ ptn_move_dest_masked(b, dest, nir_fmul(b, src[0], src[1]), WRITEMASK_Y);
+ ptn_move_dest_masked(b, dest, nir_fmov(b, src[0]), WRITEMASK_Z);
+ ptn_move_dest_masked(b, dest, nir_fmov(b, src[1]), WRITEMASK_W);
+}
+
+/* LIT - Light Coefficients
+ * dst.x = 1.0
+ * dst.y = max(src.x, 0.0)
+ * dst.z = (src.x > 0.0) ? max(src.y, 0.0)^{clamp(src.w, -128.0, 128.0))} : 0
+ * dst.w = 1.0
+ */
+static void
+ptn_lit(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ptn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), WRITEMASK_XW);
+
+ ptn_move_dest_masked(b, dest, nir_fmax(b, ptn_channel(b, src[0], X),
+ nir_imm_float(b, 0.0)), WRITEMASK_Y);
+
+ if (dest.write_mask & WRITEMASK_Z) {
+ nir_ssa_def *src0_y = ptn_channel(b, src[0], Y);
+ nir_ssa_def *wclamp = nir_fmax(b, nir_fmin(b, ptn_channel(b, src[0], W),
+ nir_imm_float(b, 128.0)),
+ nir_imm_float(b, -128.0));
+ nir_ssa_def *pow = nir_fpow(b, nir_fmax(b, src0_y, nir_imm_float(b, 0.0)),
+ wclamp);
+
+ nir_ssa_def *z;
+ if (b->shader->options->native_integers) {
+ z = nir_bcsel(b,
+ nir_fge(b, nir_imm_float(b, 0.0), ptn_channel(b, src[0], X)),
+ nir_imm_float(b, 0.0),
+ pow);
+ } else {
+ z = nir_fcsel(b,
+ nir_sge(b, nir_imm_float(b, 0.0), ptn_channel(b, src[0], X)),
+ nir_imm_float(b, 0.0),
+ pow);
+ }
+
+ ptn_move_dest_masked(b, dest, z, WRITEMASK_Z);
+ }
+}
+
+/* SCS - Sine Cosine
+ * dst.x = \cos{src.x}
+ * dst.y = \sin{src.x}
+ * dst.z = 0.0
+ * dst.w = 1.0
+ */
+static void
+ptn_scs(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ptn_move_dest_masked(b, dest, nir_fcos(b, ptn_channel(b, src[0], X)),
+ WRITEMASK_X);
+ ptn_move_dest_masked(b, dest, nir_fsin(b, ptn_channel(b, src[0], X)),
+ WRITEMASK_Y);
+ ptn_move_dest_masked(b, dest, nir_imm_float(b, 0.0), WRITEMASK_Z);
+ ptn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), WRITEMASK_W);
+}
+
+/**
+ * Emit SLT. For platforms with integers, prefer b2f(flt(...)).
+ */
+static void
+ptn_slt(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
+{
+ if (b->shader->options->native_integers) {
+ ptn_move_dest(b, dest, nir_b2f(b, nir_flt(b, src[0], src[1])));
+ } else {
+ ptn_move_dest(b, dest, nir_slt(b, src[0], src[1]));
+ }
+}
+
+/**
+ * Emit SGE. For platforms with integers, prefer b2f(fge(...)).
+ */
+static void
+ptn_sge(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
+{
+ if (b->shader->options->native_integers) {
+ ptn_move_dest(b, dest, nir_b2f(b, nir_fge(b, src[0], src[1])));
+ } else {
+ ptn_move_dest(b, dest, nir_sge(b, src[0], src[1]));
+ }
+}
+
+static void
+ptn_sle(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
+{
+ nir_ssa_def *commuted[] = { src[1], src[0] };
+ ptn_sge(b, dest, commuted);
+}
+
+static void
+ptn_sgt(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
+{
+ nir_ssa_def *commuted[] = { src[1], src[0] };
+ ptn_slt(b, dest, commuted);
+}
+
+/**
+ * Emit SEQ. For platforms with integers, prefer b2f(feq(...)).
+ */
+static void
+ptn_seq(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
+{
+ if (b->shader->options->native_integers) {
+ ptn_move_dest(b, dest, nir_b2f(b, nir_feq(b, src[0], src[1])));
+ } else {
+ ptn_move_dest(b, dest, nir_seq(b, src[0], src[1]));
+ }
+}
+
+/**
+ * Emit SNE. For platforms with integers, prefer b2f(fne(...)).
+ */
+static void
+ptn_sne(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
+{
+ if (b->shader->options->native_integers) {
+ ptn_move_dest(b, dest, nir_b2f(b, nir_fne(b, src[0], src[1])));
+ } else {
+ ptn_move_dest(b, dest, nir_sne(b, src[0], src[1]));
+ }
+}
+
+static void
+ptn_xpd(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ptn_move_dest_masked(b, dest,
+ nir_fsub(b,
+ nir_fmul(b,
+ ptn_swizzle(b, src[0], Y, Z, X, X),
+ ptn_swizzle(b, src[1], Z, X, Y, X)),
+ nir_fmul(b,
+ ptn_swizzle(b, src[1], Y, Z, X, X),
+ ptn_swizzle(b, src[0], Z, X, Y, X))),
+ WRITEMASK_XYZ);
+ ptn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), WRITEMASK_W);
+}
+
+static void
+ptn_dp2(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ptn_move_dest(b, dest, nir_fdot2(b, src[0], src[1]));
+}
+
+static void
+ptn_dp3(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ptn_move_dest(b, dest, nir_fdot3(b, src[0], src[1]));
+}
+
+static void
+ptn_dp4(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ptn_move_dest(b, dest, nir_fdot4(b, src[0], src[1]));
+}
+
+static void
+ptn_dph(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
+{
+ nir_ssa_def *dp3 = nir_fdot3(b, src[0], src[1]);
+ ptn_move_dest(b, dest, nir_fadd(b, dp3, ptn_channel(b, src[1], W)));
+}
+
+static void
+ptn_cmp(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
+{
+ if (b->shader->options->native_integers) {
+ ptn_move_dest(b, dest, nir_bcsel(b,
+ nir_flt(b, src[0], nir_imm_float(b, 0.0)),
+ src[1], src[2]));
+ } else {
+ ptn_move_dest(b, dest, nir_fcsel(b,
+ nir_slt(b, src[0], nir_imm_float(b, 0.0)),
+ src[1], src[2]));
+ }
+}
+
+static void
+ptn_lrp(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
+{
+ ptn_move_dest(b, dest, nir_flrp(b, src[2], src[1], src[0]));
+}
+
+static void
+ptn_kil(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
+{
+ nir_ssa_def *cmp = b->shader->options->native_integers ?
+ nir_bany4(b, nir_flt(b, src[0], nir_imm_float(b, 0.0))) :
+ nir_fany4(b, nir_slt(b, src[0], nir_imm_float(b, 0.0)));
+
+ nir_intrinsic_instr *discard =
+ nir_intrinsic_instr_create(b->shader, nir_intrinsic_discard_if);
+ discard->src[0] = nir_src_for_ssa(cmp);
+ nir_instr_insert_after_cf_list(b->cf_node_list, &discard->instr);
+}
+
+static void
+ptn_tex(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src,
+ struct prog_instruction *prog_inst)
+{
+ nir_tex_instr *instr;
+ nir_texop op;
+ unsigned num_srcs;
+
+ switch (prog_inst->Opcode) {
+ case OPCODE_TEX:
+ op = nir_texop_tex;
+ num_srcs = 1;
+ break;
+ case OPCODE_TXB:
+ op = nir_texop_txb;
+ num_srcs = 2;
+ break;
+ case OPCODE_TXD:
+ op = nir_texop_txd;
+ num_srcs = 3;
+ break;
+ case OPCODE_TXL:
+ op = nir_texop_txl;
+ num_srcs = 2;
+ break;
+ case OPCODE_TXP:
+ op = nir_texop_tex;
+ num_srcs = 2;
+ break;
+ case OPCODE_TXP_NV:
+ assert(!"not handled");
+ op = nir_texop_tex;
+ num_srcs = 2;
+ break;
+ default:
+ fprintf(stderr, "unknown tex op %d\n", prog_inst->Opcode);
+ abort();
+ }
+
+ if (prog_inst->TexShadow)
+ num_srcs++;
+
+ instr = nir_tex_instr_create(b->shader, num_srcs);
+ instr->op = op;
+ instr->dest_type = nir_type_float;
+ instr->is_shadow = prog_inst->TexShadow;
+ instr->sampler_index = prog_inst->TexSrcUnit;
+
+ switch (prog_inst->TexSrcTarget) {
+ case TEXTURE_1D_INDEX:
+ instr->sampler_dim = GLSL_SAMPLER_DIM_1D;
+ break;
+ case TEXTURE_2D_INDEX:
+ instr->sampler_dim = GLSL_SAMPLER_DIM_2D;
+ break;
+ case TEXTURE_3D_INDEX:
+ instr->sampler_dim = GLSL_SAMPLER_DIM_3D;
+ break;
+ case TEXTURE_CUBE_INDEX:
+ instr->sampler_dim = GLSL_SAMPLER_DIM_CUBE;
+ break;
+ case TEXTURE_RECT_INDEX:
+ instr->sampler_dim = GLSL_SAMPLER_DIM_RECT;
+ break;
+ default:
+ fprintf(stderr, "Unknown texture target %d\n", prog_inst->TexSrcTarget);
+ abort();
+ }
+
+ switch (instr->sampler_dim) {
+ case GLSL_SAMPLER_DIM_1D:
+ case GLSL_SAMPLER_DIM_BUF:
+ instr->coord_components = 1;
+ break;
+ case GLSL_SAMPLER_DIM_2D:
+ case GLSL_SAMPLER_DIM_RECT:
+ case GLSL_SAMPLER_DIM_EXTERNAL:
+ case GLSL_SAMPLER_DIM_MS:
+ instr->coord_components = 2;
+ break;
+ case GLSL_SAMPLER_DIM_3D:
+ case GLSL_SAMPLER_DIM_CUBE:
+ instr->coord_components = 3;
+ break;
+ }
+
+ unsigned src_number = 0;
+
+ instr->src[src_number].src =
+ nir_src_for_ssa(ptn_swizzle(b, src[0], X, Y, Z, W));
+ instr->src[src_number].src_type = nir_tex_src_coord;
+ src_number++;
+
+ if (prog_inst->Opcode == OPCODE_TXP) {
+ instr->src[src_number].src = nir_src_for_ssa(ptn_channel(b, src[0], W));
+ instr->src[src_number].src_type = nir_tex_src_projector;
+ src_number++;
+ }
+
+ if (prog_inst->Opcode == OPCODE_TXB) {
+ instr->src[src_number].src = nir_src_for_ssa(ptn_channel(b, src[0], W));
+ instr->src[src_number].src_type = nir_tex_src_bias;
+ src_number++;
+ }
+
+ if (prog_inst->Opcode == OPCODE_TXL) {
+ instr->src[src_number].src = nir_src_for_ssa(ptn_channel(b, src[0], W));
+ instr->src[src_number].src_type = nir_tex_src_lod;
+ src_number++;
+ }
+
+ if (instr->is_shadow) {
+ if (instr->coord_components < 3)
+ instr->src[src_number].src = nir_src_for_ssa(ptn_channel(b, src[0], Z));
+ else
+ instr->src[src_number].src = nir_src_for_ssa(ptn_channel(b, src[0], W));
+
+ instr->src[src_number].src_type = nir_tex_src_comparitor;
+ src_number++;
+ }
+
+ assert(src_number == num_srcs);
+
+ nir_ssa_dest_init(&instr->instr, &instr->dest, 4, NULL);
+ nir_instr_insert_after_cf_list(b->cf_node_list, &instr->instr);
+
+ /* Resolve the writemask on the texture op. */
+ ptn_move_dest(b, dest, &instr->dest.ssa);
+}
+
+static const nir_op op_trans[MAX_OPCODE] = {
+ [OPCODE_NOP] = 0,
+ [OPCODE_ABS] = nir_op_fabs,
+ [OPCODE_ADD] = nir_op_fadd,
+ [OPCODE_ARL] = 0,
+ [OPCODE_CMP] = 0,
+ [OPCODE_COS] = nir_op_fcos,
+ [OPCODE_DDX] = nir_op_fddx,
+ [OPCODE_DDY] = nir_op_fddy,
+ [OPCODE_DP2] = 0,
+ [OPCODE_DP3] = 0,
+ [OPCODE_DP4] = 0,
+ [OPCODE_DPH] = 0,
+ [OPCODE_DST] = 0,
+ [OPCODE_END] = 0,
+ [OPCODE_EX2] = nir_op_fexp2,
+ [OPCODE_EXP] = nir_op_fexp,
+ [OPCODE_FLR] = nir_op_ffloor,
+ [OPCODE_FRC] = nir_op_ffract,
+ [OPCODE_LG2] = nir_op_flog2,
+ [OPCODE_LIT] = 0,
+ [OPCODE_LOG] = 0,
+ [OPCODE_LRP] = 0,
+ [OPCODE_MAD] = nir_op_ffma,
+ [OPCODE_MAX] = nir_op_fmax,
+ [OPCODE_MIN] = nir_op_fmin,
+ [OPCODE_MOV] = nir_op_fmov,
+ [OPCODE_MUL] = nir_op_fmul,
+ [OPCODE_POW] = nir_op_fpow,
+ [OPCODE_RCP] = nir_op_frcp,
+
+ [OPCODE_RSQ] = nir_op_frsq,
+ [OPCODE_SCS] = 0,
+ [OPCODE_SEQ] = 0,
+ [OPCODE_SGE] = 0,
+ [OPCODE_SGT] = 0,
+ [OPCODE_SIN] = nir_op_fsin,
+ [OPCODE_SLE] = 0,
+ [OPCODE_SLT] = 0,
+ [OPCODE_SNE] = 0,
+ [OPCODE_SSG] = nir_op_fsign,
+ [OPCODE_SUB] = nir_op_fsub,
+ [OPCODE_SWZ] = 0,
+ [OPCODE_TEX] = 0,
+ [OPCODE_TRUNC] = nir_op_ftrunc,
+ [OPCODE_TXB] = 0,
+ [OPCODE_TXD] = 0,
+ [OPCODE_TXL] = 0,
+ [OPCODE_TXP] = 0,
+ [OPCODE_TXP_NV] = 0,
+ [OPCODE_XPD] = 0,
+};
+
+static void
+ptn_emit_instruction(struct ptn_compile *c, struct prog_instruction *prog_inst)
+{
+ nir_builder *b = &c->build;
+ unsigned i;
+ const unsigned op = prog_inst->Opcode;
+
+ if (op == OPCODE_END)
+ return;
+
+ nir_ssa_def *src[3];
+ for (i = 0; i < 3; i++) {
+ src[i] = ptn_get_src(c, &prog_inst->SrcReg[i]);
+ }
+ nir_alu_dest dest = ptn_get_dest(c, &prog_inst->DstReg);
+ if (c->error)
+ return;
+
+ switch (op) {
+ case OPCODE_RSQ:
+ ptn_move_dest(b, dest, nir_frsq(b, ptn_channel(b, src[0], X)));
+ break;
+
+ case OPCODE_RCP:
+ ptn_move_dest(b, dest, nir_frcp(b, ptn_channel(b, src[0], X)));
+ break;
+
+ case OPCODE_EX2:
+ ptn_move_dest(b, dest, nir_fexp2(b, ptn_channel(b, src[0], X)));
+ break;
+
+ case OPCODE_LG2:
+ ptn_move_dest(b, dest, nir_flog2(b, ptn_channel(b, src[0], X)));
+ break;
+
+ case OPCODE_POW:
+ ptn_move_dest(b, dest, nir_fpow(b,
+ ptn_channel(b, src[0], X),
+ ptn_channel(b, src[1], X)));
+ break;
+
+ case OPCODE_COS:
+ ptn_move_dest(b, dest, nir_fcos(b, ptn_channel(b, src[0], X)));
+ break;
+
+ case OPCODE_SIN:
+ ptn_move_dest(b, dest, nir_fsin(b, ptn_channel(b, src[0], X)));
+ break;
+
+ case OPCODE_ARL:
+ ptn_arl(b, dest, src);
+ break;
+
+ case OPCODE_EXP:
+ ptn_exp(b, dest, src);
+ break;
+
+ case OPCODE_LOG:
+ ptn_log(b, dest, src);
+ break;
+
+ case OPCODE_LRP:
+ ptn_lrp(b, dest, src);
+ break;
+
+ case OPCODE_DST:
+ ptn_dst(b, dest, src);
+ break;
+
+ case OPCODE_LIT:
+ ptn_lit(b, dest, src);
+ break;
+
+ case OPCODE_XPD:
+ ptn_xpd(b, dest, src);
+ break;
+
+ case OPCODE_DP2:
+ ptn_dp2(b, dest, src);
+ break;
+
+ case OPCODE_DP3:
+ ptn_dp3(b, dest, src);
+ break;
+
+ case OPCODE_DP4:
+ ptn_dp4(b, dest, src);
+ break;
+
+ case OPCODE_DPH:
+ ptn_dph(b, dest, src);
+ break;
+
+ case OPCODE_KIL:
+ ptn_kil(b, dest, src);
+ break;
+
+ case OPCODE_CMP:
+ ptn_cmp(b, dest, src);
+ break;
+
+ case OPCODE_SCS:
+ ptn_scs(b, dest, src);
+ break;
+
+ case OPCODE_SLT:
+ ptn_slt(b, dest, src);
+ break;
+
+ case OPCODE_SGT:
+ ptn_sgt(b, dest, src);
+ break;
+
+ case OPCODE_SLE:
+ ptn_sle(b, dest, src);
+ break;
+
+ case OPCODE_SGE:
+ ptn_sge(b, dest, src);
+ break;
+
+ case OPCODE_SEQ:
+ ptn_seq(b, dest, src);
+ break;
+
+ case OPCODE_SNE:
+ ptn_sne(b, dest, src);
+ break;
+
+ case OPCODE_TEX:
+ case OPCODE_TXB:
+ case OPCODE_TXD:
+ case OPCODE_TXL:
+ case OPCODE_TXP:
+ case OPCODE_TXP_NV:
+ ptn_tex(b, dest, src, prog_inst);
+ break;
+
+ case OPCODE_SWZ:
+ /* Extended swizzles were already handled in ptn_get_src(). */
+ ptn_alu(b, nir_op_fmov, dest, src);
+ break;
+
+ case OPCODE_NOP:
+ break;
+
+ default:
+ if (op_trans[op] != 0 || op == OPCODE_MOV) {
+ ptn_alu(b, op_trans[op], dest, src);
+ } else {
+ fprintf(stderr, "unknown opcode: %s\n", _mesa_opcode_string(op));
+ abort();
+ }
+ break;
+ }
+
+ if (prog_inst->SaturateMode) {
+ assert(prog_inst->SaturateMode == SATURATE_ZERO_ONE);
+ assert(!dest.dest.is_ssa);
+ ptn_move_dest(b, dest, nir_fsat(b, ptn_src_for_dest(c, &dest)));
+ }
+}
+
+/**
+ * Puts a NIR intrinsic to store of each PROGRAM_OUTPUT value to the output
+ * variables at the end of the shader.
+ *
+ * We don't generate these incrementally as the PROGRAM_OUTPUT values are
+ * written, because there's no output load intrinsic, which means we couldn't
+ * handle writemasks.
+ */
+static void
+ptn_add_output_stores(struct ptn_compile *c)
+{
+ nir_builder *b = &c->build;
+
+ foreach_list_typed(nir_variable, var, node, &b->shader->outputs) {
+ nir_intrinsic_instr *store =
+ nir_intrinsic_instr_create(b->shader, nir_intrinsic_store_var);
+ store->num_components = 4;
+ store->variables[0] =
+ nir_deref_var_create(store, c->output_vars[var->data.location]);
+ store->src[0].reg.reg = c->output_regs[var->data.location];
+ nir_instr_insert_after_cf_list(c->build.cf_node_list, &store->instr);
+ }
+}
+
+static void
+setup_registers_and_variables(struct ptn_compile *c)
+{
+ nir_builder *b = &c->build;
+ struct nir_shader *shader = b->shader;
+
+ /* Create input variables. */
+ const int num_inputs = _mesa_flsll(c->prog->InputsRead);
+ for (int i = 0; i < num_inputs; i++) {
+ if (!(c->prog->InputsRead & BITFIELD64_BIT(i)))
+ continue;
+ nir_variable *var = rzalloc(shader, nir_variable);
+ var->type = glsl_vec4_type();
+ var->data.read_only = true;
+ var->data.mode = nir_var_shader_in;
+ var->name = ralloc_asprintf(var, "in_%d", i);
+ var->data.location = i;
+ var->data.index = 0;
+
+ if (c->prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
+ struct gl_fragment_program *fp =
+ (struct gl_fragment_program *) c->prog;
+
+ var->data.interpolation = fp->InterpQualifier[i];
+
+ if (i == VARYING_SLOT_POS) {
+ var->data.origin_upper_left = fp->OriginUpperLeft;
+ var->data.pixel_center_integer = fp->PixelCenterInteger;
+ } else if (i == VARYING_SLOT_FOGC) {
+ /* fogcoord is defined as <f, 0.0, 0.0, 1.0>. Make the actual
+ * input variable a float, and create a local containing the
+ * full vec4 value.
+ */
+ var->type = glsl_float_type();
+
+ nir_intrinsic_instr *load_x =
+ nir_intrinsic_instr_create(shader, nir_intrinsic_load_var);
+ load_x->num_components = 1;
+ load_x->variables[0] = nir_deref_var_create(load_x, var);
+ nir_ssa_dest_init(&load_x->instr, &load_x->dest, 1, NULL);
+ nir_instr_insert_after_cf_list(b->cf_node_list, &load_x->instr);
+
+ nir_ssa_def *f001 = nir_vec4(b, &load_x->dest.ssa, nir_imm_float(b, 0.0),
+ nir_imm_float(b, 0.0), nir_imm_float(b, 1.0));
+
+ nir_variable *fullvar = rzalloc(shader, nir_variable);
+ fullvar->type = glsl_vec4_type();
+ fullvar->data.mode = nir_var_local;
+ fullvar->name = "fogcoord_tmp";
+ exec_list_push_tail(&b->impl->locals, &fullvar->node);
+
+ nir_intrinsic_instr *store =
+ nir_intrinsic_instr_create(shader, nir_intrinsic_store_var);
+ store->num_components = 4;
+ store->variables[0] = nir_deref_var_create(store, fullvar);
+ store->src[0] = nir_src_for_ssa(f001);
+ nir_instr_insert_after_cf_list(b->cf_node_list, &store->instr);
+
+ /* Insert the real input into the list so the driver has real
+ * inputs, but set c->input_vars[i] to the temporary so we use
+ * the splatted value.
+ */
+ exec_list_push_tail(&shader->inputs, &var->node);
+ c->input_vars[i] = fullvar;
+ continue;
+ }
+ }
+
+ exec_list_push_tail(&shader->inputs, &var->node);
+ c->input_vars[i] = var;
+ }
+
+ /* Create output registers and variables. */
+ int max_outputs = _mesa_fls(c->prog->OutputsWritten);
+ c->output_regs = rzalloc_array(c, nir_register *, max_outputs);
+
+ for (int i = 0; i < max_outputs; i++) {
+ if (!(c->prog->OutputsWritten & BITFIELD64_BIT(i)))
+ continue;
+
+ /* Since we can't load from outputs in the IR, we make temporaries
+ * for the outputs and emit stores to the real outputs at the end of
+ * the shader.
+ */
+ nir_register *reg = nir_local_reg_create(b->impl);
+ reg->num_components = 4;
+
+ nir_variable *var = rzalloc(shader, nir_variable);
+ var->type = glsl_vec4_type();
+ var->data.mode = nir_var_shader_out;
+ var->name = ralloc_asprintf(var, "out_%d", i);
+
+ var->data.location = i;
+ var->data.index = 0;
+
+ c->output_regs[i] = reg;
+
+ exec_list_push_tail(&shader->outputs, &var->node);
+ c->output_vars[i] = var;
+ }
+
+ /* Create temporary registers. */
+ c->temp_regs = rzalloc_array(c, nir_register *, c->prog->NumTemporaries);
+
+ nir_register *reg;
+ for (int i = 0; i < c->prog->NumTemporaries; i++) {
+ reg = nir_local_reg_create(b->impl);
+ if (!reg) {
+ c->error = true;
+ return;
+ }
+ reg->num_components = 4;
+ c->temp_regs[i] = reg;
+ }
+
+ /* Create the address register (for ARB_vertex_program). */
+ reg = nir_local_reg_create(b->impl);
+ if (!reg) {
+ c->error = true;
+ return;
+ }
+ reg->num_components = 1;
+ c->addr_reg = reg;
+
+ /* Set the number of uniforms */
+ shader->num_uniforms = 4 * c->prog->Parameters->NumParameters;
+}
+
+struct nir_shader *
+prog_to_nir(const struct gl_program *prog, const nir_shader_compiler_options *options)
+{
+ struct ptn_compile *c;
+ struct nir_shader *s;
+
+ c = rzalloc(NULL, struct ptn_compile);
+ if (!c)
+ return NULL;
+ s = nir_shader_create(NULL, options);
+ if (!s)
+ goto fail;
+ c->prog = prog;
+
+ nir_function *func = nir_function_create(s, "main");
+ nir_function_overload *overload = nir_function_overload_create(func);
+ nir_function_impl *impl = nir_function_impl_create(overload);
+
+ c->build.shader = s;
+ c->build.impl = impl;
+ c->build.cf_node_list = &impl->body;
+
+ setup_registers_and_variables(c);
+ if (unlikely(c->error))
+ goto fail;
+
+ for (unsigned int i = 0; i < prog->NumInstructions; i++) {
+ ptn_emit_instruction(c, &prog->Instructions[i]);
+
+ if (unlikely(c->error))
+ break;
+ }
+
+ ptn_add_output_stores(c);
+
+fail:
+ if (c->error) {
+ ralloc_free(s);
+ s = NULL;
+ }
+ ralloc_free(c);
+ return s;
+}
diff --git a/mesalib/src/mesa/program/prog_to_nir.h b/mesalib/src/mesa/program/prog_to_nir.h
new file mode 100644
index 000000000..34e4cd104
--- /dev/null
+++ b/mesalib/src/mesa/program/prog_to_nir.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2015 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#pragma once
+#ifndef PROG_TO_NIR_H
+#define PROG_TO_NIR_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct nir_shader *prog_to_nir(const struct gl_program *prog,
+ const nir_shader_compiler_options *options);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/mesalib/src/mesa/program/program.c b/mesalib/src/mesa/program/program.c
index 3c214d5e3..4f28e2a3b 100644
--- a/mesalib/src/mesa/program/program.c
+++ b/mesalib/src/mesa/program/program.c
@@ -37,6 +37,7 @@
#include "prog_cache.h"
#include "prog_parameter.h"
#include "prog_instruction.h"
+#include "util/ralloc.h"
/**
@@ -380,6 +381,10 @@ _mesa_delete_program(struct gl_context *ctx, struct gl_program *prog)
_mesa_free_parameter_list(prog->Parameters);
}
+ if (prog->nir) {
+ ralloc_free(prog->nir);
+ }
+
free(prog);
}
diff --git a/mesalib/src/mesa/state_tracker/st_atom.c b/mesalib/src/mesa/state_tracker/st_atom.c
index f0fe11ffa..428f2d9d7 100644
--- a/mesalib/src/mesa/state_tracker/st_atom.c
+++ b/mesalib/src/mesa/state_tracker/st_atom.c
@@ -183,7 +183,7 @@ void st_validate_state( struct st_context *st )
if (state->st == 0)
return;
- /*printf("%s %x/%x\n", __FUNCTION__, state->mesa, state->st);*/
+ /*printf("%s %x/%x\n", __func__, state->mesa, state->st);*/
#ifdef DEBUG
if (1) {
diff --git a/mesalib/src/mesa/state_tracker/st_atom_array.c b/mesalib/src/mesa/state_tracker/st_atom_array.c
index 9b52f9779..d4fb8b862 100644
--- a/mesalib/src/mesa/state_tracker/st_atom_array.c
+++ b/mesalib/src/mesa/state_tracker/st_atom_array.c
@@ -598,7 +598,7 @@ static void update_array(struct st_context *st)
const struct st_tracked_state st_update_array = {
"st_update_array", /* name */
{ /* dirty */
- 0, /* mesa */
+ _NEW_CURRENT_ATTRIB, /* mesa */
ST_NEW_VERTEX_ARRAYS | ST_NEW_VERTEX_PROGRAM, /* st */
},
update_array /* update */
diff --git a/mesalib/src/mesa/state_tracker/st_atom_constbuf.c b/mesalib/src/mesa/state_tracker/st_atom_constbuf.c
index 7984bf742..a54e0d9db 100644
--- a/mesalib/src/mesa/state_tracker/st_atom_constbuf.c
+++ b/mesalib/src/mesa/state_tracker/st_atom_constbuf.c
@@ -92,7 +92,7 @@ void st_upload_constants( struct st_context *st,
if (ST_DEBUG & DEBUG_CONSTANTS) {
debug_printf("%s(shader=%d, numParams=%d, stateFlags=0x%x)\n",
- __FUNCTION__, shader_type, params->NumParameters,
+ __func__, shader_type, params->NumParameters,
params->StateFlags);
_mesa_print_parameter_list(params);
}
diff --git a/mesalib/src/mesa/state_tracker/st_atom_shader.c b/mesalib/src/mesa/state_tracker/st_atom_shader.c
index 73768ed12..629f54f25 100644
--- a/mesalib/src/mesa/state_tracker/st_atom_shader.c
+++ b/mesalib/src/mesa/state_tracker/st_atom_shader.c
@@ -40,9 +40,8 @@
#include "program/program.h"
#include "pipe/p_context.h"
-
+#include "pipe/p_shader_tokens.h"
#include "util/u_simple_shaders.h"
-
#include "cso_cache/cso_context.h"
#include "st_context.h"
diff --git a/mesalib/src/mesa/state_tracker/st_cb_clear.c b/mesalib/src/mesa/state_tracker/st_cb_clear.c
index dd81a6273..f10e9063a 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_clear.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_clear.c
@@ -247,7 +247,7 @@ clear_with_quad(struct gl_context *ctx, unsigned clear_buffers)
util_framebuffer_get_num_layers(&st->state.framebuffer);
/*
- printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__,
+ printf("%s %s%s%s %f,%f %f,%f\n", __func__,
color ? "color, " : "",
depth ? "depth, " : "",
stencil ? "stencil" : "",
diff --git a/mesalib/src/mesa/state_tracker/st_cb_program.c b/mesalib/src/mesa/state_tracker/st_cb_program.c
index aa301d830..c382d7d2c 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_program.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_program.c
@@ -41,6 +41,7 @@
#include "draw/draw_context.h"
#include "st_context.h"
+#include "st_debug.h"
#include "st_program.h"
#include "st_mesa_to_tgsi.h"
#include "st_cb_program.h"
@@ -214,6 +215,9 @@ st_program_string_notify( struct gl_context *ctx,
st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
}
+ if (ST_DEBUG & DEBUG_PRECOMPILE)
+ st_precompile_shader_variant(st, prog);
+
/* XXX check if program is legal, within limits */
return GL_TRUE;
}
diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c
index 5c520b44f..bdf236e82 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_texture.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c
@@ -123,7 +123,7 @@ gl_target_to_pipe(GLenum target)
static struct gl_texture_image *
st_NewTextureImage(struct gl_context * ctx)
{
- DBG("%s\n", __FUNCTION__);
+ DBG("%s\n", __func__);
(void) ctx;
return (struct gl_texture_image *) ST_CALLOC_STRUCT(st_texture_image);
}
@@ -144,7 +144,7 @@ st_NewTextureObject(struct gl_context * ctx, GLuint name, GLenum target)
{
struct st_texture_object *obj = ST_CALLOC_STRUCT(st_texture_object);
- DBG("%s\n", __FUNCTION__);
+ DBG("%s\n", __func__);
_mesa_initialize_texture_object(ctx, &obj->base, name, target);
return &obj->base;
@@ -172,7 +172,7 @@ st_FreeTextureImageBuffer(struct gl_context *ctx,
{
struct st_texture_image *stImage = st_texture_image(texImage);
- DBG("%s\n", __FUNCTION__);
+ DBG("%s\n", __func__);
if (stImage->pt) {
pipe_resource_reference(&stImage->pt, NULL);
@@ -405,7 +405,7 @@ guess_and_alloc_texture(struct st_context *st,
GLuint ptWidth, ptHeight, ptDepth, ptLayers;
enum pipe_format fmt;
- DBG("%s\n", __FUNCTION__);
+ DBG("%s\n", __func__);
assert(!stObj->pt);
@@ -473,7 +473,7 @@ guess_and_alloc_texture(struct st_context *st,
stObj->lastLevel = lastLevel;
- DBG("%s returning %d\n", __FUNCTION__, (stObj->pt != NULL));
+ DBG("%s returning %d\n", __func__, (stObj->pt != NULL));
return stObj->pt != NULL;
}
@@ -496,7 +496,7 @@ st_AllocTextureImageBuffer(struct gl_context *ctx,
GLuint height = texImage->Height;
GLuint depth = texImage->Depth;
- DBG("%s\n", __FUNCTION__);
+ DBG("%s\n", __func__);
assert(!stImage->pt); /* xxx this might be wrong */
@@ -738,6 +738,11 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims,
if (gl_target == GL_TEXTURE_CUBE_MAP) {
gl_target = GL_TEXTURE_2D;
}
+ /* TexSubImage can specify subsets of cube map array faces
+ * so we need to upload via 2D array instead */
+ if (gl_target == GL_TEXTURE_CUBE_MAP_ARRAY) {
+ gl_target = GL_TEXTURE_2D_ARRAY;
+ }
/* Initialize the source texture description. */
memset(&src_templ, 0, sizeof(src_templ));
@@ -1148,7 +1153,7 @@ st_GetTexImage(struct gl_context * ctx,
}
if (ST_DEBUG & DEBUG_FALLBACK)
- debug_printf("%s: fallback format translation\n", __FUNCTION__);
+ debug_printf("%s: fallback format translation\n", __func__);
dstMesaFormat = _mesa_format_from_format_and_type(format, type);
dstStride = _mesa_image_row_stride(&ctx->Pack, width, format, type);
@@ -1234,7 +1239,7 @@ fallback_copy_texsubimage(struct gl_context *ctx,
struct pipe_transfer *transfer;
if (ST_DEBUG & DEBUG_FALLBACK)
- debug_printf("%s: fallback processing\n", __FUNCTION__);
+ debug_printf("%s: fallback processing\n", __func__);
if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
srcY = strb->Base.Height - srcY - height;
@@ -1389,7 +1394,7 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
texImage->TexFormat != MESA_FORMAT_ETC1_RGB8);
if (!strb || !strb->surface || !stImage->pt) {
- debug_printf("%s: null strb or stImage\n", __FUNCTION__);
+ debug_printf("%s: null strb or stImage\n", __func__);
return;
}
diff --git a/mesalib/src/mesa/state_tracker/st_debug.c b/mesalib/src/mesa/state_tracker/st_debug.c
index de3e3a9cd..50891c112 100644
--- a/mesalib/src/mesa/state_tracker/st_debug.c
+++ b/mesalib/src/mesa/state_tracker/st_debug.c
@@ -56,6 +56,7 @@ static const struct debug_named_value st_debug_flags[] = {
{ "draw", DEBUG_DRAW, NULL },
{ "buffer", DEBUG_BUFFER, NULL },
{ "wf", DEBUG_WIREFRAME, NULL },
+ { "precompile", DEBUG_PRECOMPILE, NULL },
DEBUG_NAMED_VALUE_END
};
diff --git a/mesalib/src/mesa/state_tracker/st_debug.h b/mesalib/src/mesa/state_tracker/st_debug.h
index cc8197836..288eccf9f 100644
--- a/mesalib/src/mesa/state_tracker/st_debug.h
+++ b/mesalib/src/mesa/state_tracker/st_debug.h
@@ -47,6 +47,7 @@ st_print_current(void);
#define DEBUG_DRAW 0x100
#define DEBUG_BUFFER 0x200
#define DEBUG_WIREFRAME 0x400
+#define DEBUG_PRECOMPILE 0x800
#ifdef DEBUG
extern int ST_DEBUG;
diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index efee4b258..93671ba9c 100644
--- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -30,40 +30,25 @@
* Translate GLSL IR to TGSI.
*/
-#include <stdio.h>
-#include "main/compiler.h"
-#include "ir.h"
-#include "ir_visitor.h"
-#include "ir_expression_flattening.h"
-#include "glsl_types.h"
+#include "st_glsl_to_tgsi.h"
+
#include "glsl_parser_extras.h"
-#include "../glsl/program.h"
#include "ir_optimization.h"
-#include "ast.h"
-#include "main/mtypes.h"
+#include "main/errors.h"
#include "main/shaderobj.h"
#include "main/uniforms.h"
#include "main/shaderapi.h"
-#include "program/hash_table.h"
#include "program/prog_instruction.h"
-#include "program/prog_optimize.h"
-#include "program/prog_print.h"
-#include "program/program.h"
-#include "program/prog_parameter.h"
#include "program/sampler.h"
-#include "pipe/p_compiler.h"
#include "pipe/p_context.h"
#include "pipe/p_screen.h"
-#include "pipe/p_shader_tokens.h"
-#include "pipe/p_state.h"
-#include "util/u_math.h"
#include "tgsi/tgsi_ureg.h"
#include "tgsi/tgsi_info.h"
-#include "st_context.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
#include "st_program.h"
-#include "st_glsl_to_tgsi.h"
#include "st_mesa_to_tgsi.h"
@@ -328,6 +313,7 @@ public:
int num_address_regs;
int samplers_used;
bool indirect_addr_consts;
+ int wpos_transform_const;
int glsl_version;
bool native_integers;
@@ -441,9 +427,6 @@ public:
void emit_arl(ir_instruction *ir, st_dst_reg dst, st_src_reg src0);
- void emit_scs(ir_instruction *ir, unsigned op,
- st_dst_reg dst, const st_src_reg &src);
-
bool try_emit_mad(ir_expression *ir,
int mul_operand);
bool try_emit_mad_for_and_not(ir_expression *ir,
@@ -966,101 +949,6 @@ glsl_to_tgsi_visitor::emit_arl(ir_instruction *ir,
emit(NULL, op, dst, src0);
}
-/**
- * Emit an TGSI_OPCODE_SCS instruction
- *
- * The \c SCS opcode functions a bit differently than the other TGSI opcodes.
- * Instead of splatting its result across all four components of the
- * destination, it writes one value to the \c x component and another value to
- * the \c y component.
- *
- * \param ir IR instruction being processed
- * \param op Either \c TGSI_OPCODE_SIN or \c TGSI_OPCODE_COS depending
- * on which value is desired.
- * \param dst Destination register
- * \param src Source register
- */
-void
-glsl_to_tgsi_visitor::emit_scs(ir_instruction *ir, unsigned op,
- st_dst_reg dst,
- const st_src_reg &src)
-{
- /* Vertex programs cannot use the SCS opcode.
- */
- if (this->prog->Target == GL_VERTEX_PROGRAM_ARB) {
- emit_scalar(ir, op, dst, src);
- return;
- }
-
- const unsigned component = (op == TGSI_OPCODE_SIN) ? 0 : 1;
- const unsigned scs_mask = (1U << component);
- int done_mask = ~dst.writemask;
- st_src_reg tmp;
-
- assert(op == TGSI_OPCODE_SIN || op == TGSI_OPCODE_COS);
-
- /* If there are compnents in the destination that differ from the component
- * that will be written by the SCS instrution, we'll need a temporary.
- */
- if (scs_mask != unsigned(dst.writemask)) {
- tmp = get_temp(glsl_type::vec4_type);
- }
-
- for (unsigned i = 0; i < 4; i++) {
- unsigned this_mask = (1U << i);
- st_src_reg src0 = src;
-
- if ((done_mask & this_mask) != 0)
- continue;
-
- /* The source swizzle specified which component of the source generates
- * sine / cosine for the current component in the destination. The SCS
- * instruction requires that this value be swizzle to the X component.
- * Replace the current swizzle with a swizzle that puts the source in
- * the X component.
- */
- unsigned src0_swiz = GET_SWZ(src.swizzle, i);
-
- src0.swizzle = MAKE_SWIZZLE4(src0_swiz, src0_swiz,
- src0_swiz, src0_swiz);
- for (unsigned j = i + 1; j < 4; j++) {
- /* If there is another enabled component in the destination that is
- * derived from the same inputs, generate its value on this pass as
- * well.
- */
- if (!(done_mask & (1 << j)) &&
- GET_SWZ(src0.swizzle, j) == src0_swiz) {
- this_mask |= (1 << j);
- }
- }
-
- if (this_mask != scs_mask) {
- glsl_to_tgsi_instruction *inst;
- st_dst_reg tmp_dst = st_dst_reg(tmp);
-
- /* Emit the SCS instruction.
- */
- inst = emit(ir, TGSI_OPCODE_SCS, tmp_dst, src0);
- inst->dst[0].writemask = scs_mask;
-
- /* Move the result of the SCS instruction to the desired location in
- * the destination.
- */
- tmp.swizzle = MAKE_SWIZZLE4(component, component,
- component, component);
- inst = emit(ir, TGSI_OPCODE_SCS, dst, tmp);
- inst->dst[0].writemask = this_mask;
- } else {
- /* Emit the SCS instruction to write directly to the destination.
- */
- glsl_to_tgsi_instruction *inst = emit(ir, TGSI_OPCODE_SCS, dst, src0);
- inst->dst[0].writemask = scs_mask;
- }
-
- done_mask |= this_mask;
- }
-}
-
int
glsl_to_tgsi_visitor::add_constant(gl_register_file file,
gl_constant_value values[8], int size, int datatype,
@@ -1611,12 +1499,6 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
case ir_unop_cos:
emit_scalar(ir, TGSI_OPCODE_COS, result_dst, op[0]);
break;
- case ir_unop_sin_reduced:
- emit_scs(ir, TGSI_OPCODE_SIN, result_dst, op[0]);
- break;
- case ir_unop_cos_reduced:
- emit_scs(ir, TGSI_OPCODE_COS, result_dst, op[0]);
- break;
case ir_unop_saturate: {
glsl_to_tgsi_instruction *inst;
inst = emit(ir, TGSI_OPCODE_MOV, result_dst, op[0]);
@@ -3134,7 +3016,7 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir)
break;
case ir_query_levels:
opcode = TGSI_OPCODE_TXQ;
- lod_info = st_src_reg(PROGRAM_IMMEDIATE, 0, GLSL_TYPE_INT);
+ lod_info = undef_src;
levels_src = get_temp(ir->type);
break;
case ir_txf:
@@ -3456,6 +3338,7 @@ glsl_to_tgsi_visitor::glsl_to_tgsi_visitor()
num_address_regs = 0;
samplers_used = 0;
indirect_addr_consts = false;
+ wpos_transform_const = -1;
glsl_version = 0;
native_integers = false;
mem_ctx = ralloc_context(NULL);
@@ -3465,6 +3348,7 @@ glsl_to_tgsi_visitor::glsl_to_tgsi_visitor()
shader = NULL;
options = NULL;
have_sqrt = false;
+ have_fma = false;
}
glsl_to_tgsi_visitor::~glsl_to_tgsi_visitor()
@@ -3937,6 +3821,7 @@ glsl_to_tgsi_visitor::copy_propagate(void)
inst->dst[0].index == inst->src[0].index) &&
!inst->dst[0].reladdr &&
!inst->saturate &&
+ inst->src[0].file != PROGRAM_ARRAY &&
!inst->src[0].reladdr &&
!inst->src[0].reladdr2 &&
!inst->src[0].negate) {
@@ -4464,7 +4349,9 @@ struct st_translate {
struct ureg_dst arrays[MAX_ARRAYS];
struct ureg_src *constants;
+ int num_constants;
struct ureg_src *immediates;
+ int num_immediates;
struct ureg_dst outputs[PIPE_MAX_SHADER_OUTPUTS];
struct ureg_src inputs[PIPE_MAX_SHADER_INPUTS];
struct ureg_dst address[3];
@@ -4666,7 +4553,7 @@ src_register(struct st_translate *t, const st_src_reg *reg)
{
switch(reg->file) {
case PROGRAM_UNDEFINED:
- return ureg_src_undef();
+ return ureg_imm4f(t->ureg, 0, 0, 0, 0);
case PROGRAM_TEMPORARY:
case PROGRAM_ARRAY:
@@ -4674,17 +4561,18 @@ src_register(struct st_translate *t, const st_src_reg *reg)
case PROGRAM_UNIFORM:
assert(reg->index >= 0);
- return t->constants[reg->index];
+ return reg->index < t->num_constants ?
+ t->constants[reg->index] : ureg_imm4f(t->ureg, 0, 0, 0, 0);
case PROGRAM_STATE_VAR:
case PROGRAM_CONSTANT: /* ie, immediate */
if (reg->has_index2)
return ureg_src_register(TGSI_FILE_CONSTANT, reg->index);
- else if (reg->index < 0)
- return ureg_DECL_constant(t->ureg, 0);
else
- return t->constants[reg->index];
+ return reg->index >= 0 && reg->index < t->num_constants ?
+ t->constants[reg->index] : ureg_imm4f(t->ureg, 0, 0, 0, 0);
case PROGRAM_IMMEDIATE:
+ assert(reg->index >= 0 && reg->index < t->num_immediates);
return t->immediates[reg->index];
case PROGRAM_INPUT:
@@ -4805,6 +4693,7 @@ translate_tex_offset(struct st_translate *t,
switch (in_offset->file) {
case PROGRAM_IMMEDIATE:
+ assert(in_offset->index >= 0 && in_offset->index < t->num_immediates);
imm_src = t->immediates[in_offset->index];
offset.File = imm_src.File;
@@ -4867,10 +4756,8 @@ compile_tgsi_instruction(struct st_translate *t,
inst->saturate,
clamp_dst_color_output);
- for (i = 0; i < num_src; i++) {
- assert(inst->src[i].file != PROGRAM_UNDEFINED);
+ for (i = 0; i < num_src; i++)
src[i] = translate_src(t, &inst->src[i]);
- }
switch(inst->op) {
case TGSI_OPCODE_BGNLOOP:
@@ -4939,28 +4826,19 @@ compile_tgsi_instruction(struct st_translate *t,
*/
static void
emit_wpos_adjustment( struct st_translate *t,
- const struct gl_program *program,
+ int wpos_transform_const,
boolean invert,
GLfloat adjX, GLfloat adjY[2])
{
struct ureg_program *ureg = t->ureg;
+ assert(wpos_transform_const >= 0);
+
/* Fragment program uses fragment position input.
* Need to replace instances of INPUT[WPOS] with temp T
- * where T = INPUT[WPOS] by y is inverted.
+ * where T = INPUT[WPOS] is inverted by Y.
*/
- static const gl_state_index wposTransformState[STATE_LENGTH]
- = { STATE_INTERNAL, STATE_FB_WPOS_Y_TRANSFORM,
- (gl_state_index)0, (gl_state_index)0, (gl_state_index)0 };
-
- /* XXX: note we are modifying the incoming shader here! Need to
- * do this before emitting the constant decls below, or this
- * will be missed:
- */
- unsigned wposTransConst = _mesa_add_state_reference(program->Parameters,
- wposTransformState);
-
- struct ureg_src wpostrans = ureg_DECL_constant( ureg, wposTransConst );
+ struct ureg_src wpostrans = ureg_DECL_constant(ureg, wpos_transform_const);
struct ureg_dst wpos_temp = ureg_DECL_temporary( ureg );
struct ureg_src wpos_input = t->inputs[t->inputMapping[VARYING_SLOT_POS]];
@@ -5024,7 +4902,8 @@ static void
emit_wpos(struct st_context *st,
struct st_translate *t,
const struct gl_program *program,
- struct ureg_program *ureg)
+ struct ureg_program *ureg,
+ int wpos_transform_const)
{
const struct gl_fragment_program *fp =
(const struct gl_fragment_program *) program;
@@ -5121,7 +5000,7 @@ emit_wpos(struct st_context *st,
/* we invert after adjustment so that we avoid the MOV to temporary,
* and reuse the adjustment ADD instead */
- emit_wpos_adjustment(t, program, invert, adjX, adjY);
+ emit_wpos_adjustment(t, wpos_transform_const, invert, adjX, adjY);
}
/**
@@ -5238,15 +5117,6 @@ st_translate_program(
t->outputMapping = outputMapping;
t->ureg = ureg;
- if (program->shader_program) {
- for (i = 0; i < program->shader_program->NumUserUniformStorage; i++) {
- struct gl_uniform_storage *const storage =
- &program->shader_program->UniformStorage[i];
-
- _mesa_uniform_detach_all_driver_storage(storage);
- }
- }
-
/*
* Declare input attributes.
*/
@@ -5260,10 +5130,9 @@ st_translate_program(
}
if (proginfo->InputsRead & VARYING_BIT_POS) {
- /* Must do this after setting up t->inputs, and before
- * emitting constant references, below:
- */
- emit_wpos(st_context(ctx), t, proginfo, ureg);
+ /* Must do this after setting up t->inputs. */
+ emit_wpos(st_context(ctx), t, proginfo, ureg,
+ program->wpos_transform_const);
}
if (proginfo->InputsRead & VARYING_BIT_FACE)
@@ -5400,6 +5269,7 @@ st_translate_program(
ret = PIPE_ERROR_OUT_OF_MEMORY;
goto out;
}
+ t->num_constants = proginfo->Parameters->NumParameters;
for (i = 0; i < proginfo->Parameters->NumParameters; i++) {
switch (proginfo->Parameters->Parameters[i].Type) {
@@ -5451,6 +5321,8 @@ st_translate_program(
ret = PIPE_ERROR_OUT_OF_MEMORY;
goto out;
}
+ t->num_immediates = program->num_immediates;
+
i = 0;
foreach_in_list(immediate_storage, imm, &program->immediates) {
assert(i < program->num_immediates);
@@ -5479,33 +5351,21 @@ st_translate_program(
t->insn[t->labels[i].branch_target]);
}
- if (program->shader_program) {
- /* This has to be done last. Any operation the can cause
- * prog->ParameterValues to get reallocated (e.g., anything that adds a
- * program constant) has to happen before creating this linkage.
- */
- for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
- if (program->shader_program->_LinkedShaders[i] == NULL)
- continue;
-
- _mesa_associate_uniform_storage(ctx, program->shader_program,
- program->shader_program->_LinkedShaders[i]->Program->Parameters);
- }
- }
-
out:
if (t) {
free(t->temps);
free(t->insn);
free(t->labels);
free(t->constants);
+ t->num_constants = 0;
free(t->immediates);
+ t->num_immediates = 0;
if (t->error) {
- debug_printf("%s: translate error flag set\n", __FUNCTION__);
+ debug_printf("%s: translate error flag set\n", __func__);
}
- free(t);
+ FREE(t);
}
return ret;
@@ -5634,14 +5494,12 @@ get_mesa_program(struct gl_context *ctx,
v->emit(NULL, TGSI_OPCODE_END);
if (ctx->_Shader->Flags & GLSL_DUMP) {
- printf("\n");
- printf("GLSL IR for linked %s program %d:\n",
+ _mesa_log("\n");
+ _mesa_log("GLSL IR for linked %s program %d:\n",
_mesa_shader_stage_to_string(shader->Stage),
shader_program->Name);
- _mesa_print_ir(stdout, shader->ir, NULL);
- printf("\n");
- printf("\n");
- fflush(stdout);
+ _mesa_print_ir(_mesa_get_log_file(), shader->ir, NULL);
+ _mesa_log("\n\n");
}
prog->Instructions = NULL;
@@ -5650,6 +5508,17 @@ get_mesa_program(struct gl_context *ctx,
do_set_program_inouts(shader->ir, prog, shader->Stage);
count_resources(v, prog);
+ /* This must be done before the uniform storage is associated. */
+ if (shader->Type == GL_FRAGMENT_SHADER &&
+ prog->InputsRead & VARYING_BIT_POS){
+ static const gl_state_index wposTransformState[STATE_LENGTH] = {
+ STATE_INTERNAL, STATE_FB_WPOS_Y_TRANSFORM
+ };
+
+ v->wpos_transform_const = _mesa_add_state_reference(prog->Parameters,
+ wposTransformState);
+ }
+
_mesa_reference_program(ctx, &shader->Program, prog);
/* This has to be done last. Any operation the can cause
diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.h b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.h
index 5ed640747..2cb80bcf9 100644
--- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.h
+++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.h
@@ -22,17 +22,18 @@
* DEALINGS IN THE SOFTWARE.
*/
+#include "pipe/p_defines.h"
+#include "main/mtypes.h"
+
#ifdef __cplusplus
extern "C" {
#endif
-#include "main/glheader.h"
-#include "tgsi/tgsi_ureg.h"
-
struct gl_context;
struct gl_shader;
struct gl_shader_program;
struct glsl_to_tgsi_visitor;
+struct ureg_program;
enum pipe_error st_translate_program(
struct gl_context *ctx,
diff --git a/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c b/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c
index 2f1016110..98d525c86 100644
--- a/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c
+++ b/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c
@@ -1249,7 +1249,7 @@ out:
free(t->constants);
if (t->error) {
- debug_printf("%s: translate error flag set\n", __FUNCTION__);
+ debug_printf("%s: translate error flag set\n", __func__);
}
return ret;
diff --git a/mesalib/src/mesa/state_tracker/st_program.c b/mesalib/src/mesa/state_tracker/st_program.c
index 4cfd817ce..d93b3c7bc 100644
--- a/mesalib/src/mesa/state_tracker/st_program.c
+++ b/mesalib/src/mesa/state_tracker/st_program.c
@@ -185,9 +185,6 @@ st_prepare_vertex_program(struct gl_context *ctx,
if (stvp->Base.IsPositionInvariant)
_mesa_insert_mvp_code(ctx, &stvp->Base);
- if (!stvp->glsl_to_tgsi)
- assert(stvp->Base.Base.NumInstructions > 1);
-
/*
* Determine number of inputs, the mappings between VERT_ATTRIB_x
* and TGSI generic input indexes, plus input attrib semantic info.
@@ -403,7 +400,7 @@ st_translate_vertex_program(struct st_context *st,
return vpv;
fail:
- debug_printf("%s: failed to translate Mesa program:\n", __FUNCTION__);
+ debug_printf("%s: failed to translate Mesa program:\n", __func__);
_mesa_print_program(&stvp->Base.Base);
debug_assert(0);
@@ -1318,3 +1315,47 @@ st_print_current_vertex_program(void)
}
}
}
+
+
+/**
+ * Compile one shader variant.
+ */
+void
+st_precompile_shader_variant(struct st_context *st,
+ struct gl_program *prog)
+{
+ switch (prog->Target) {
+ case GL_VERTEX_PROGRAM_ARB: {
+ struct st_vertex_program *p = (struct st_vertex_program *)prog;
+ struct st_vp_variant_key key;
+
+ memset(&key, 0, sizeof(key));
+ key.st = st;
+ st_get_vp_variant(st, p, &key);
+ break;
+ }
+
+ case GL_GEOMETRY_PROGRAM_NV: {
+ struct st_geometry_program *p = (struct st_geometry_program *)prog;
+ struct st_gp_variant_key key;
+
+ memset(&key, 0, sizeof(key));
+ key.st = st;
+ st_get_gp_variant(st, p, &key);
+ break;
+ }
+
+ case GL_FRAGMENT_PROGRAM_ARB: {
+ struct st_fragment_program *p = (struct st_fragment_program *)prog;
+ struct st_fp_variant_key key;
+
+ memset(&key, 0, sizeof(key));
+ key.st = st;
+ st_get_fp_variant(st, p, &key);
+ break;
+ }
+
+ default:
+ assert(0);
+ }
+}
diff --git a/mesalib/src/mesa/state_tracker/st_program.h b/mesalib/src/mesa/state_tracker/st_program.h
index 451d7bb6a..b2c86faec 100644
--- a/mesalib/src/mesa/state_tracker/st_program.h
+++ b/mesalib/src/mesa/state_tracker/st_program.h
@@ -329,6 +329,9 @@ st_destroy_program_variants(struct st_context *st);
extern void
st_print_current_vertex_program(void);
+extern void
+st_precompile_shader_variant(struct st_context *st,
+ struct gl_program *prog);
#ifdef __cplusplus
}
diff --git a/mesalib/src/mesa/state_tracker/st_texture.c b/mesalib/src/mesa/state_tracker/st_texture.c
index ca7c83c21..6beb21e33 100644
--- a/mesalib/src/mesa/state_tracker/st_texture.c
+++ b/mesalib/src/mesa/state_tracker/st_texture.c
@@ -74,7 +74,7 @@ st_texture_create(struct st_context *st,
if (target == PIPE_TEXTURE_CUBE)
assert(layers == 6);
- DBG("%s target %d format %s last_level %d\n", __FUNCTION__,
+ DBG("%s target %d format %s last_level %d\n", __func__,
(int) target, util_format_name(format), last_level);
assert(format);
@@ -177,7 +177,7 @@ st_gl_texture_dims_to_pipe_dims(GLenum texture,
*widthOut = widthIn;
*heightOut = heightIn;
*depthOut = 1;
- *layersOut = depthIn;
+ *layersOut = util_align_npot(depthIn, 6);
break;
default:
assert(0 && "Unexpected texture in st_gl_texture_dims_to_pipe_dims()");
@@ -250,7 +250,7 @@ st_texture_image_map(struct st_context *st, struct st_texture_image *stImage,
GLuint level;
void *map;
- DBG("%s \n", __FUNCTION__);
+ DBG("%s \n", __func__);
if (!stImage->pt)
return NULL;
@@ -304,7 +304,7 @@ st_texture_image_unmap(struct st_context *st,
slice += stObj->base.MinLayer;
transfer = &stImage->transfer[slice + stImage->base.Face].transfer;
- DBG("%s\n", __FUNCTION__);
+ DBG("%s\n", __func__);
pipe_transfer_unmap(pipe, *transfer);
*transfer = NULL;
diff --git a/mesalib/src/mesa/swrast/s_aatriangle.c b/mesalib/src/mesa/swrast/s_aatriangle.c
index 1d076cc7d..b51098704 100644
--- a/mesalib/src/mesa/swrast/s_aatriangle.c
+++ b/mesalib/src/mesa/swrast/s_aatriangle.c
@@ -30,7 +30,6 @@
#include "main/glheader.h"
#include "main/context.h"
-#include "main/colormac.h"
#include "main/macros.h"
#include "main/imports.h"
#include "main/state.h"
diff --git a/mesalib/src/mesa/swrast/s_alpha.c b/mesalib/src/mesa/swrast/s_alpha.c
index b1a7ff132..841642fa9 100644
--- a/mesalib/src/mesa/swrast/s_alpha.c
+++ b/mesalib/src/mesa/swrast/s_alpha.c
@@ -29,7 +29,6 @@
#include "main/glheader.h"
#include "main/context.h"
-#include "main/colormac.h"
#include "main/macros.h"
#include "s_alpha.h"
diff --git a/mesalib/src/mesa/swrast/s_atifragshader.c b/mesalib/src/mesa/swrast/s_atifragshader.c
index 0bf03771f..9e029db25 100644
--- a/mesalib/src/mesa/swrast/s_atifragshader.c
+++ b/mesalib/src/mesa/swrast/s_atifragshader.c
@@ -20,7 +20,6 @@
*/
#include "main/glheader.h"
-#include "main/colormac.h"
#include "main/macros.h"
#include "main/atifragshader.h"
#include "main/samplerobj.h"
diff --git a/mesalib/src/mesa/swrast/s_context.c b/mesalib/src/mesa/swrast/s_context.c
index ecde292e3..af24207e5 100644
--- a/mesalib/src/mesa/swrast/s_context.c
+++ b/mesalib/src/mesa/swrast/s_context.c
@@ -27,7 +27,6 @@
#include "main/imports.h"
#include "main/bufferobj.h"
-#include "main/colormac.h"
#include "main/mtypes.h"
#include "main/samplerobj.h"
#include "main/teximage.h"
diff --git a/mesalib/src/mesa/swrast/s_copypix.c b/mesalib/src/mesa/swrast/s_copypix.c
index 17140ad2d..68c83e44e 100644
--- a/mesalib/src/mesa/swrast/s_copypix.c
+++ b/mesalib/src/mesa/swrast/s_copypix.c
@@ -25,7 +25,6 @@
#include "main/glheader.h"
#include "main/context.h"
-#include "main/colormac.h"
#include "main/condrender.h"
#include "main/macros.h"
#include "main/pixeltransfer.h"
diff --git a/mesalib/src/mesa/swrast/s_feedback.c b/mesalib/src/mesa/swrast/s_feedback.c
index f25b89735..71f48ce92 100644
--- a/mesalib/src/mesa/swrast/s_feedback.c
+++ b/mesalib/src/mesa/swrast/s_feedback.c
@@ -23,7 +23,6 @@
*/
#include "main/glheader.h"
-#include "main/colormac.h"
#include "main/feedback.h"
#include "main/macros.h"
diff --git a/mesalib/src/mesa/swrast/s_fog.c b/mesalib/src/mesa/swrast/s_fog.c
index e270b7e24..8b0bdf8fa 100644
--- a/mesalib/src/mesa/swrast/s_fog.c
+++ b/mesalib/src/mesa/swrast/s_fog.c
@@ -25,7 +25,6 @@
#include "c99_math.h"
#include "main/glheader.h"
-#include "main/colormac.h"
#include "main/macros.h"
#include "s_context.h"
diff --git a/mesalib/src/mesa/swrast/s_fragprog.c b/mesalib/src/mesa/swrast/s_fragprog.c
index 12bcda311..175915a5a 100644
--- a/mesalib/src/mesa/swrast/s_fragprog.c
+++ b/mesalib/src/mesa/swrast/s_fragprog.c
@@ -23,7 +23,7 @@
*/
#include "main/glheader.h"
-#include "main/colormac.h"
+#include "main/macros.h"
#include "main/samplerobj.h"
#include "main/teximage.h"
#include "program/prog_instruction.h"
diff --git a/mesalib/src/mesa/swrast/s_lines.c b/mesalib/src/mesa/swrast/s_lines.c
index 3e626b9e0..58bd2fc72 100644
--- a/mesalib/src/mesa/swrast/s_lines.c
+++ b/mesalib/src/mesa/swrast/s_lines.c
@@ -25,7 +25,6 @@
#include "main/glheader.h"
#include "main/context.h"
-#include "main/colormac.h"
#include "main/macros.h"
#include "s_aaline.h"
#include "s_context.h"
diff --git a/mesalib/src/mesa/swrast/s_linetemp.h b/mesalib/src/mesa/swrast/s_linetemp.h
index 352c88428..035a1e640 100644
--- a/mesalib/src/mesa/swrast/s_linetemp.h
+++ b/mesalib/src/mesa/swrast/s_linetemp.h
@@ -106,7 +106,7 @@ NAME( struct gl_context *ctx, const SWvertex *vert0, const SWvertex *vert1 )
}
/*
- printf("%s():\n", __FUNCTION__);
+ printf("%s():\n", __func__);
printf(" (%f, %f, %f) -> (%f, %f, %f)\n",
vert0->attrib[VARYING_SLOT_POS][0],
vert0->attrib[VARYING_SLOT_POS][1],
@@ -154,7 +154,7 @@ NAME( struct gl_context *ctx, const SWvertex *vert0, const SWvertex *vert1 )
return;
/*
- printf("%s %d,%d %g %g %g %g %g %g %g %g\n", __FUNCTION__, dx, dy,
+ printf("%s %d,%d %g %g %g %g %g %g %g %g\n", __func__, dx, dy,
vert0->attrib[VARYING_SLOT_COL1][0],
vert0->attrib[VARYING_SLOT_COL1][1],
vert0->attrib[VARYING_SLOT_COL1][2],
diff --git a/mesalib/src/mesa/swrast/s_points.c b/mesalib/src/mesa/swrast/s_points.c
index 8180483ba..2212c95fa 100644
--- a/mesalib/src/mesa/swrast/s_points.c
+++ b/mesalib/src/mesa/swrast/s_points.c
@@ -24,7 +24,6 @@
#include "main/glheader.h"
-#include "main/colormac.h"
#include "main/macros.h"
#include "s_context.h"
#include "s_feedback.h"
diff --git a/mesalib/src/mesa/swrast/s_span.c b/mesalib/src/mesa/swrast/s_span.c
index e304b6b5a..3db10e163 100644
--- a/mesalib/src/mesa/swrast/s_span.c
+++ b/mesalib/src/mesa/swrast/s_span.c
@@ -33,7 +33,6 @@
#include "c99_math.h"
#include "main/glheader.h"
-#include "main/colormac.h"
#include "main/format_pack.h"
#include "main/format_unpack.h"
#include "main/macros.h"
@@ -1144,7 +1143,7 @@ _swrast_write_rgba_span( struct gl_context *ctx, SWspan *span)
struct gl_framebuffer *fb = ctx->DrawBuffer;
/*
- printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__,
+ printf("%s() interp 0x%x array 0x%x\n", __func__,
span->interpMask, span->arrayMask);
*/
diff --git a/mesalib/src/mesa/swrast/s_texcombine.c b/mesalib/src/mesa/swrast/s_texcombine.c
index 58ff16465..0adb8e5ba 100644
--- a/mesalib/src/mesa/swrast/s_texcombine.c
+++ b/mesalib/src/mesa/swrast/s_texcombine.c
@@ -26,8 +26,8 @@
#include "main/glheader.h"
#include "main/context.h"
-#include "main/colormac.h"
#include "main/imports.h"
+#include "main/macros.h"
#include "main/pixeltransfer.h"
#include "main/samplerobj.h"
#include "program/prog_instruction.h"
diff --git a/mesalib/src/mesa/swrast/s_texfetch.c b/mesalib/src/mesa/swrast/s_texfetch.c
index 3c4ee15ba..1fe21c0b4 100644
--- a/mesalib/src/mesa/swrast/s_texfetch.c
+++ b/mesalib/src/mesa/swrast/s_texfetch.c
@@ -33,7 +33,6 @@
*/
-#include "main/colormac.h"
#include "main/macros.h"
#include "main/texcompress.h"
#include "main/texcompress_fxt1.h"
diff --git a/mesalib/src/mesa/swrast/s_texfilter.c b/mesalib/src/mesa/swrast/s_texfilter.c
index 3ade99519..abc1727cf 100644
--- a/mesalib/src/mesa/swrast/s_texfilter.c
+++ b/mesalib/src/mesa/swrast/s_texfilter.c
@@ -26,8 +26,8 @@
#include "c99_math.h"
#include "main/glheader.h"
#include "main/context.h"
-#include "main/colormac.h"
#include "main/imports.h"
+#include "main/macros.h"
#include "main/samplerobj.h"
#include "main/teximage.h"
#include "main/texobj.h"
diff --git a/mesalib/src/mesa/swrast/s_texrender.c b/mesalib/src/mesa/swrast/s_texrender.c
index 29bb270d6..fa853c919 100644
--- a/mesalib/src/mesa/swrast/s_texrender.c
+++ b/mesalib/src/mesa/swrast/s_texrender.c
@@ -1,6 +1,5 @@
#include "main/context.h"
-#include "main/colormac.h"
#include "main/fbobject.h"
#include "main/macros.h"
#include "main/teximage.h"
diff --git a/mesalib/src/mesa/swrast/s_triangle.c b/mesalib/src/mesa/swrast/s_triangle.c
index af039c359..876a74b08 100644
--- a/mesalib/src/mesa/swrast/s_triangle.c
+++ b/mesalib/src/mesa/swrast/s_triangle.c
@@ -31,7 +31,6 @@
#include "main/glheader.h"
#include "main/context.h"
-#include "main/colormac.h"
#include "main/imports.h"
#include "main/macros.h"
#include "main/mtypes.h"
diff --git a/mesalib/src/mesa/swrast/s_tritemp.h b/mesalib/src/mesa/swrast/s_tritemp.h
index fb73b2d59..fddbbfd99 100644
--- a/mesalib/src/mesa/swrast/s_tritemp.h
+++ b/mesalib/src/mesa/swrast/s_tritemp.h
@@ -92,7 +92,7 @@
#ifndef MAX_GLUINT
-#define MAX_GLUINT 0xffffffff
+#define MAX_GLUINT 0xffffffffu
#endif
@@ -156,7 +156,7 @@ static void NAME(struct gl_context *ctx, const SWvertex *v0,
#endif
/*
- printf("%s()\n", __FUNCTION__);
+ printf("%s()\n", __func__);
printf(" %g, %g, %g\n",
v0->attrib[VARYING_SLOT_POS][0],
v0->attrib[VARYING_SLOT_POS][1],
diff --git a/mesalib/src/mesa/swrast/s_zoom.c b/mesalib/src/mesa/swrast/s_zoom.c
index ab22652c7..9879e2a5f 100644
--- a/mesalib/src/mesa/swrast/s_zoom.c
+++ b/mesalib/src/mesa/swrast/s_zoom.c
@@ -26,7 +26,6 @@
#include "main/macros.h"
#include "main/imports.h"
#include "main/format_pack.h"
-#include "main/colormac.h"
#include "s_context.h"
#include "s_span.h"
diff --git a/mesalib/src/mesa/swrast_setup/ss_context.c b/mesalib/src/mesa/swrast_setup/ss_context.c
index 0b3b9e4df..74b1da342 100644
--- a/mesalib/src/mesa/swrast_setup/ss_context.c
+++ b/mesalib/src/mesa/swrast_setup/ss_context.c
@@ -27,7 +27,7 @@
#include "main/glheader.h"
#include "main/imports.h"
-#include "main/colormac.h"
+#include "main/macros.h"
#include "tnl/tnl.h"
#include "tnl/t_context.h"
#include "tnl/t_pipeline.h"
@@ -167,7 +167,7 @@ setup_vertex_format(struct gl_context *ctx)
EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, pointSize );
_tnl_install_attrs( ctx, map, e,
- ctx->ViewportArray[0]._WindowMap.m,
+ tnl->_WindowMap.m,
sizeof(SWvertex) );
swsetup->last_index_bitset = index_bitset;
@@ -265,7 +265,8 @@ _swsetup_Wakeup( struct gl_context *ctx )
void
_swsetup_Translate( struct gl_context *ctx, const void *vertex, SWvertex *dest )
{
- const GLfloat *m = ctx->ViewportArray[0]._WindowMap.m;
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ const GLfloat *m = tnl->_WindowMap.m;
GLfloat tmp[4];
GLuint i;
diff --git a/mesalib/src/mesa/swrast_setup/ss_triangle.c b/mesalib/src/mesa/swrast_setup/ss_triangle.c
index 483c41592..b92c20be2 100644
--- a/mesalib/src/mesa/swrast_setup/ss_triangle.c
+++ b/mesalib/src/mesa/swrast_setup/ss_triangle.c
@@ -27,7 +27,6 @@
#include "c99_math.h"
#include "main/glheader.h"
-#include "main/colormac.h"
#include "main/macros.h"
#include "main/mtypes.h"
diff --git a/mesalib/src/mesa/tnl/t_context.c b/mesalib/src/mesa/tnl/t_context.c
index bc705d7a3..5b9dd54d7 100644
--- a/mesalib/src/mesa/tnl/t_context.c
+++ b/mesalib/src/mesa/tnl/t_context.c
@@ -35,6 +35,7 @@
#include "math/m_translate.h"
#include "math/m_xform.h"
#include "main/state.h"
+#include "main/viewport.h"
#include "tnl.h"
#include "t_context.h"
@@ -69,6 +70,8 @@ _tnl_CreateContext( struct gl_context *ctx )
_tnl_install_pipeline( ctx, _tnl_default_pipeline );
}
+ _math_matrix_ctr(&tnl->_WindowMap);
+
tnl->NeedNdcCoords = GL_TRUE;
tnl->AllowVertexFog = GL_TRUE;
tnl->AllowPixelFog = GL_TRUE;
@@ -108,6 +111,8 @@ _tnl_DestroyContext( struct gl_context *ctx )
struct tnl_shine_tab *s, *tmps;
TNLcontext *tnl = TNL_CONTEXT(ctx);
+ _math_matrix_dtr(&tnl->_WindowMap);
+
/* Free lighting shininess exponentiation table */
foreach_s( s, tmps, tnl->_ShineTabList ) {
free( s );
@@ -182,6 +187,13 @@ _tnl_InvalidateState( struct gl_context *ctx, GLuint new_state )
}
}
}
+
+ if (new_state & (_NEW_VIEWPORT | _NEW_BUFFERS)) {
+ double scale[3], translate[3];
+ _mesa_get_viewport_xform(ctx, 0, scale, translate);
+ _math_matrix_viewport(&tnl->_WindowMap, scale, translate,
+ ctx->DrawBuffer->_DepthMaxF);
+ }
}
diff --git a/mesalib/src/mesa/tnl/t_context.h b/mesalib/src/mesa/tnl/t_context.h
index e89a7f836..e7adb5f53 100644
--- a/mesalib/src/mesa/tnl/t_context.h
+++ b/mesalib/src/mesa/tnl/t_context.h
@@ -514,6 +514,7 @@ typedef struct
/* Clipspace/ndc/window vertex managment:
*/
struct tnl_clipspace clipspace;
+ GLmatrix _WindowMap;
/* Probably need a better configuration mechanism:
*/
diff --git a/mesalib/src/mesa/tnl/t_draw.c b/mesalib/src/mesa/tnl/t_draw.c
index 60265d60b..6adf1dce6 100644
--- a/mesalib/src/mesa/tnl/t_draw.c
+++ b/mesalib/src/mesa/tnl/t_draw.c
@@ -448,7 +448,7 @@ void _tnl_draw_prims(struct gl_context *ctx,
if (0)
{
- printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
+ printf("%s %d..%d\n", __func__, min_index, max_index);
for (i = 0; i < nr_prims; i++)
printf("prim %d: %s start %d count %d\n", i,
_mesa_lookup_enum_by_nr(prim[i].mode),
diff --git a/mesalib/src/mesa/tnl/t_rasterpos.c b/mesalib/src/mesa/tnl/t_rasterpos.c
index 9ecf947df..d4b45bac9 100644
--- a/mesalib/src/mesa/tnl/t_rasterpos.c
+++ b/mesalib/src/mesa/tnl/t_rasterpos.c
@@ -25,12 +25,12 @@
#include "c99_math.h"
#include "main/glheader.h"
-#include "main/colormac.h"
#include "main/feedback.h"
#include "main/light.h"
#include "main/macros.h"
#include "util/simple_list.h"
#include "main/mtypes.h"
+#include "main/viewport.h"
#include "math/m_matrix.h"
#include "tnl/tnl.h"
@@ -378,6 +378,7 @@ _tnl_RasterPos(struct gl_context *ctx, const GLfloat vObj[4])
GLfloat eye[4], clip[4], ndc[3], d;
GLfloat *norm, eyenorm[3];
GLfloat *objnorm = ctx->Current.Attrib[VERT_ATTRIB_NORMAL];
+ double scale[3], translate[3];
/* apply modelview matrix: eye = MV * obj */
TRANSFORM_POINT( eye, ctx->ModelviewMatrixStack.Top->m, vObj );
@@ -410,13 +411,10 @@ _tnl_RasterPos(struct gl_context *ctx, const GLfloat vObj[4])
ndc[1] = clip[1] * d;
ndc[2] = clip[2] * d;
/* wincoord = viewport_mapping(ndc) */
- ctx->Current.RasterPos[0] = (ndc[0] * ctx->ViewportArray[0]._WindowMap.m[MAT_SX]
- + ctx->ViewportArray[0]._WindowMap.m[MAT_TX]);
- ctx->Current.RasterPos[1] = (ndc[1] * ctx->ViewportArray[0]._WindowMap.m[MAT_SY]
- + ctx->ViewportArray[0]._WindowMap.m[MAT_TY]);
- ctx->Current.RasterPos[2] = (ndc[2] * ctx->ViewportArray[0]._WindowMap.m[MAT_SZ]
- + ctx->ViewportArray[0]._WindowMap.m[MAT_TZ])
- / ctx->DrawBuffer->_DepthMaxF;
+ _mesa_get_viewport_xform(ctx, 0, scale, translate);
+ ctx->Current.RasterPos[0] = ndc[0] * scale[0] + translate[0];
+ ctx->Current.RasterPos[1] = ndc[1] * scale[1] + translate[1];
+ ctx->Current.RasterPos[2] = ndc[2] * scale[2] + translate[2];
ctx->Current.RasterPos[3] = clip[3];
if (ctx->Transform.DepthClamp) {
diff --git a/mesalib/src/mesa/tnl/t_vb_fog.c b/mesalib/src/mesa/tnl/t_vb_fog.c
index 3626f1da3..1ca72f866 100644
--- a/mesalib/src/mesa/tnl/t_vb_fog.c
+++ b/mesalib/src/mesa/tnl/t_vb_fog.c
@@ -28,7 +28,6 @@
#include "c99_math.h"
#include "main/glheader.h"
-#include "main/colormac.h"
#include "main/macros.h"
#include "main/imports.h"
#include "main/mtypes.h"
diff --git a/mesalib/src/mesa/tnl/t_vb_light.c b/mesalib/src/mesa/tnl/t_vb_light.c
index 7781b6a6c..dbd57fa6b 100644
--- a/mesalib/src/mesa/tnl/t_vb_light.c
+++ b/mesalib/src/mesa/tnl/t_vb_light.c
@@ -25,7 +25,6 @@
#include "c99_math.h"
#include "main/glheader.h"
-#include "main/colormac.h"
#include "main/light.h"
#include "main/macros.h"
#include "main/imports.h"
diff --git a/mesalib/src/mesa/tnl/t_vb_lighttmp.h b/mesalib/src/mesa/tnl/t_vb_lighttmp.h
index 57f569bd7..f8786accb 100644
--- a/mesalib/src/mesa/tnl/t_vb_lighttmp.h
+++ b/mesalib/src/mesa/tnl/t_vb_lighttmp.h
@@ -68,7 +68,7 @@ static void TAG(light_rgba_spec)( struct gl_context *ctx,
const GLuint nr = VB->Count;
#ifdef TRACE
- fprintf(stderr, "%s\n", __FUNCTION__ );
+ fprintf(stderr, "%s\n", __func__ );
#endif
VB->AttribPtr[_TNL_ATTRIB_COLOR0] = &store->LitColor[0];
@@ -249,7 +249,7 @@ static void TAG(light_rgba)( struct gl_context *ctx,
const GLuint nr = VB->Count;
#ifdef TRACE
- fprintf(stderr, "%s\n", __FUNCTION__ );
+ fprintf(stderr, "%s\n", __func__ );
#endif
VB->AttribPtr[_TNL_ATTRIB_COLOR0] = &store->LitColor[0];
@@ -429,7 +429,7 @@ static void TAG(light_fast_rgba_single)( struct gl_context *ctx,
#endif
#ifdef TRACE
- fprintf(stderr, "%s\n", __FUNCTION__ );
+ fprintf(stderr, "%s\n", __func__ );
#endif
(void) input; /* doesn't refer to Eye or Obj */
@@ -533,7 +533,7 @@ static void TAG(light_fast_rgba)( struct gl_context *ctx,
const struct gl_light *light;
#ifdef TRACE
- fprintf(stderr, "%s %d\n", __FUNCTION__, nr );
+ fprintf(stderr, "%s %d\n", __func__, nr );
#endif
(void) input;
diff --git a/mesalib/src/mesa/tnl/t_vb_normals.c b/mesalib/src/mesa/tnl/t_vb_normals.c
index b67789e42..9aee1a2fb 100644
--- a/mesalib/src/mesa/tnl/t_vb_normals.c
+++ b/mesalib/src/mesa/tnl/t_vb_normals.c
@@ -27,7 +27,6 @@
#include "main/glheader.h"
-#include "main/colormac.h"
#include "main/macros.h"
#include "main/imports.h"
#include "main/mtypes.h"
diff --git a/mesalib/src/mesa/tnl/t_vb_program.c b/mesalib/src/mesa/tnl/t_vb_program.c
index 464a4cddd..149434971 100644
--- a/mesalib/src/mesa/tnl/t_vb_program.c
+++ b/mesalib/src/mesa/tnl/t_vb_program.c
@@ -32,7 +32,6 @@
#include "main/glheader.h"
-#include "main/colormac.h"
#include "main/macros.h"
#include "main/imports.h"
#include "main/samplerobj.h"
diff --git a/mesalib/src/mesa/tnl/t_vb_texgen.c b/mesalib/src/mesa/tnl/t_vb_texgen.c
index 9a61ef2fe..94066f4f6 100644
--- a/mesalib/src/mesa/tnl/t_vb_texgen.c
+++ b/mesalib/src/mesa/tnl/t_vb_texgen.c
@@ -35,7 +35,6 @@
*/
#include "main/glheader.h"
-#include "main/colormac.h"
#include "main/macros.h"
#include "main/imports.h"
#include "main/mtypes.h"
diff --git a/mesalib/src/mesa/tnl/t_vb_texmat.c b/mesalib/src/mesa/tnl/t_vb_texmat.c
index 1cc2c8116..ef034d643 100644
--- a/mesalib/src/mesa/tnl/t_vb_texmat.c
+++ b/mesalib/src/mesa/tnl/t_vb_texmat.c
@@ -27,7 +27,6 @@
#include "main/glheader.h"
-#include "main/colormac.h"
#include "main/macros.h"
#include "main/imports.h"
#include "main/mtypes.h"
diff --git a/mesalib/src/mesa/tnl/t_vb_vertex.c b/mesalib/src/mesa/tnl/t_vb_vertex.c
index ea3a56cd1..b56d6803c 100644
--- a/mesalib/src/mesa/tnl/t_vb_vertex.c
+++ b/mesalib/src/mesa/tnl/t_vb_vertex.c
@@ -27,7 +27,6 @@
#include "main/glheader.h"
-#include "main/colormac.h"
#include "main/macros.h"
#include "main/imports.h"
#include "main/mtypes.h"
diff --git a/mesalib/src/mesa/tnl/t_vertex.c b/mesalib/src/mesa/tnl/t_vertex.c
index 369d6d945..c3294b007 100644
--- a/mesalib/src/mesa/tnl/t_vertex.c
+++ b/mesalib/src/mesa/tnl/t_vertex.c
@@ -28,7 +28,6 @@
#include <stdio.h>
#include "main/glheader.h"
#include "main/context.h"
-#include "main/colormac.h"
#include "swrast/s_chan.h"
#include "t_context.h"
#include "t_vertex.h"
diff --git a/mesalib/src/mesa/tnl/t_vertex_generic.c b/mesalib/src/mesa/tnl/t_vertex_generic.c
index 079d473fc..2a25a9692 100644
--- a/mesalib/src/mesa/tnl/t_vertex_generic.c
+++ b/mesalib/src/mesa/tnl/t_vertex_generic.c
@@ -28,7 +28,7 @@
#include "main/glheader.h"
#include "main/context.h"
-#include "main/colormac.h"
+#include "main/macros.h"
#include "util/simple_list.h"
#include "swrast/s_chan.h"
#include "t_context.h"
@@ -36,7 +36,7 @@
#if 0
-#define DEBUG_INSERT printf("%s\n", __FUNCTION__)
+#define DEBUG_INSERT printf("%s\n", __func__)
#else
#define DEBUG_INSERT
#endif
diff --git a/mesalib/src/mesa/tnl/t_vertex_sse.c b/mesalib/src/mesa/tnl/t_vertex_sse.c
index 963432c48..30dc1a720 100644
--- a/mesalib/src/mesa/tnl/t_vertex_sse.c
+++ b/mesalib/src/mesa/tnl/t_vertex_sse.c
@@ -29,7 +29,6 @@
#include "main/glheader.h"
#include "main/context.h"
-#include "main/colormac.h"
#include "util/simple_list.h"
#include "main/enums.h"
#include "swrast/s_chan.h"
diff --git a/mesalib/src/mesa/vbo/vbo_exec_api.c b/mesalib/src/mesa/vbo/vbo_exec_api.c
index 02741c2bc..859078f12 100644
--- a/mesalib/src/mesa/vbo/vbo_exec_api.c
+++ b/mesalib/src/mesa/vbo/vbo_exec_api.c
@@ -439,7 +439,7 @@ do { \
} while (0)
-#define ERROR(err) _mesa_error( ctx, err, __FUNCTION__ )
+#define ERROR(err) _mesa_error( ctx, err, __func__ )
#define TAG(x) vbo_##x
#include "vbo_attrib_tmp.h"
diff --git a/mesalib/src/mesa/vbo/vbo_exec_draw.c b/mesalib/src/mesa/vbo/vbo_exec_draw.c
index 91f2ca43a..37b53a830 100644
--- a/mesalib/src/mesa/vbo/vbo_exec_draw.c
+++ b/mesalib/src/mesa/vbo/vbo_exec_draw.c
@@ -45,7 +45,7 @@ vbo_exec_debug_verts( struct vbo_exec_context *exec )
GLuint i;
printf("%s: %u vertices %d primitives, %d vertsize\n",
- __FUNCTION__,
+ __func__,
count,
exec->vtx.prim_count,
exec->vtx.vertex_size);
@@ -402,7 +402,7 @@ vbo_exec_vtx_flush(struct vbo_exec_context *exec, GLboolean keepUnmapped)
}
if (0)
- printf("%s %d %d\n", __FUNCTION__, exec->vtx.prim_count,
+ printf("%s %d %d\n", __func__, exec->vtx.prim_count,
exec->vtx.vert_count);
vbo_context(ctx)->draw_prims( ctx,
diff --git a/mesalib/src/mesa/vbo/vbo_primitive_restart.c b/mesalib/src/mesa/vbo/vbo_primitive_restart.c
index 562dedcd5..dafc4fd2a 100644
--- a/mesalib/src/mesa/vbo/vbo_primitive_restart.c
+++ b/mesalib/src/mesa/vbo/vbo_primitive_restart.c
@@ -167,6 +167,8 @@ vbo_sw_primitive_restart(struct gl_context *ctx,
struct gl_buffer_object *indirect)
{
GLuint prim_num;
+ struct _mesa_prim new_prim;
+ struct _mesa_index_buffer new_ib;
struct sub_primitive *sub_prims;
struct sub_primitive *sub_prim;
GLuint num_sub_prims;
@@ -182,8 +184,6 @@ vbo_sw_primitive_restart(struct gl_context *ctx,
/* If there is an indirect buffer, map it and extract the draw params */
if (indirect && prims[0].is_indirect) {
- struct _mesa_prim new_prim = *prims;
- struct _mesa_index_buffer new_ib = *ib;
const uint32_t *indirect_params;
if (!ctx->Driver.MapBufferRange(ctx, 0, indirect->Size, GL_MAP_READ_BIT,
indirect, MAP_INTERNAL)) {
@@ -195,6 +195,7 @@ vbo_sw_primitive_restart(struct gl_context *ctx,
}
assert(nr_prims == 1);
+ new_prim = prims[0];
indirect_params = (const uint32_t *)
ADD_POINTERS(indirect->Mappings[MAP_INTERNAL].Pointer,
new_prim.indirect_offset);
@@ -206,6 +207,7 @@ vbo_sw_primitive_restart(struct gl_context *ctx,
new_prim.basevertex = indirect_params[3];
new_prim.base_instance = indirect_params[4];
+ new_ib = *ib;
new_ib.count = new_prim.count;
prims = &new_prim;
diff --git a/mesalib/src/mesa/vbo/vbo_rebase.c b/mesalib/src/mesa/vbo/vbo_rebase.c
index b06df4ab2..c3c4b64e6 100644
--- a/mesalib/src/mesa/vbo/vbo_rebase.c
+++ b/mesalib/src/mesa/vbo/vbo_rebase.c
@@ -142,7 +142,7 @@ void vbo_rebase_prims( struct gl_context *ctx,
assert(min_index != 0);
if (0)
- printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
+ printf("%s %d..%d\n", __func__, min_index, max_index);
/* XXX this path is disabled for now.
diff --git a/mesalib/src/mesa/vbo/vbo_save_api.c b/mesalib/src/mesa/vbo/vbo_save_api.c
index fd9a5de3d..5927beeb3 100644
--- a/mesalib/src/mesa/vbo/vbo_save_api.c
+++ b/mesalib/src/mesa/vbo/vbo_save_api.c
@@ -763,7 +763,7 @@ _save_reset_vertex(struct gl_context *ctx)
-#define ERROR(err) _mesa_compile_error(ctx, err, __FUNCTION__);
+#define ERROR(err) _mesa_compile_error(ctx, err, __func__);
/* Only one size for each attribute may be active at once. Eg. if
diff --git a/mesalib/src/mesa/x86/common_x86.c b/mesalib/src/mesa/x86/common_x86.c
index 86fbca91e..1c8640514 100644
--- a/mesalib/src/mesa/x86/common_x86.c
+++ b/mesalib/src/mesa/x86/common_x86.c
@@ -42,7 +42,7 @@
#include <sys/types.h>
#include <sys/sysctl.h>
#endif
-#if defined(USE_SSE_ASM) && defined(__OpenBSD__)
+#if defined(USE_SSE_ASM) && (defined(__OpenBSD__) || defined(__NetBSD__))
#include <sys/param.h>
#include <sys/sysctl.h>
#include <machine/cpu.h>
diff --git a/mesalib/src/util/ralloc.c b/mesalib/src/util/ralloc.c
index 36bc61fd0..01719c888 100644
--- a/mesalib/src/util/ralloc.c
+++ b/mesalib/src/util/ralloc.c
@@ -271,6 +271,32 @@ ralloc_steal(const void *new_ctx, void *ptr)
add_child(parent, info);
}
+void
+ralloc_adopt(const void *new_ctx, void *old_ctx)
+{
+ ralloc_header *new_info, *old_info, *child;
+
+ if (unlikely(old_ctx == NULL))
+ return;
+
+ old_info = get_header(old_ctx);
+ new_info = get_header(new_ctx);
+
+ /* If there are no children, bail. */
+ if (unlikely(old_info->child == NULL))
+ return;
+
+ /* Set all the children's parent to new_ctx; get a pointer to the last child. */
+ for (child = old_info->child; child->next != NULL; child = child->next) {
+ child->parent = new_info;
+ }
+
+ /* Connect the two lists together; parent them to new_ctx; make old_ctx empty. */
+ child->next = new_info->child;
+ new_info->child = old_info->child;
+ old_info->child = NULL;
+}
+
void *
ralloc_parent(const void *ptr)
{
diff --git a/mesalib/src/util/ralloc.h b/mesalib/src/util/ralloc.h
index f088a3627..7587e1190 100644
--- a/mesalib/src/util/ralloc.h
+++ b/mesalib/src/util/ralloc.h
@@ -46,16 +46,16 @@
#ifndef RALLOC_H
#define RALLOC_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include <stddef.h>
#include <stdarg.h>
#include <stdbool.h>
#include "macros.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/**
* \def ralloc(ctx, type)
* Allocate a new object chained off of the given context.
@@ -235,6 +235,13 @@ void ralloc_free(void *ptr);
void ralloc_steal(const void *new_ctx, void *ptr);
/**
+ * Reparent all children from one context to another.
+ *
+ * This effectively calls ralloc_steal(new_ctx, child) for all children of \p old_ctx.
+ */
+void ralloc_adopt(const void *new_ctx, void *old_ctx);
+
+/**
* Return the given pointer's ralloc context.
*/
void *ralloc_parent(const void *ptr);
diff --git a/mesalib/src/util/u_atomic_test.c b/mesalib/src/util/u_atomic_test.c
index 939cfe445..7844f6162 100644
--- a/mesalib/src/util/u_atomic_test.c
+++ b/mesalib/src/util/u_atomic_test.c
@@ -36,6 +36,11 @@
#include "u_atomic.h"
+#ifdef _MSC_VER
+#pragma warning( disable : 28112 ) /* Accessing a local variable via an Interlocked function */
+#pragma warning( disable : 28113 ) /* A variable which is accessed via an Interlocked function must always be accessed via an Interlocked function */
+#endif
+
/* Test only assignment-like operations, which are supported on all types */
#define test_atomic_assign(type, ones) \