aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2015-04-20 22:42:55 +0200
committermarha <marha@users.sourceforge.net>2015-04-20 22:42:55 +0200
commit934184bfecd402aae891b8740d788b486aa7269f (patch)
treec23fb0afd169dc6846ea23bda21260fcffd1e3e6 /mesalib/src
parent57dd848fb6dd7cf15820172e2abc9fb9de2b4268 (diff)
parent4ba9be2882d9f1567809edb0a31fcdf11320d41f (diff)
downloadvcxsrv-934184bfecd402aae891b8740d788b486aa7269f.tar.gz
vcxsrv-934184bfecd402aae891b8740d788b486aa7269f.tar.bz2
vcxsrv-934184bfecd402aae891b8740d788b486aa7269f.zip
Merge remote-tracking branch 'origin/released'
Conflicts: mesalib/src/mesa/main/.gitignore mesalib/src/mesa/main/dlopen.h xorg-server/hw/xwin/glx/gen_gl_wrappers.py xorg-server/hw/xwin/win.h xorg-server/hw/xwin/winengine.c xorg-server/hw/xwin/winglobals.c xorg-server/hw/xwin/winscrinit.c xorg-server/hw/xwin/winshaddd.c xorg-server/randr/rrxinerama.c
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
-rwxr-xr-xmesalib/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
-rwxr-xr-xmesalib/src/glsl/ir.cpp14
-rw-r--r--mesalib/src/glsl/ir.h102
-rwxr-xr-xmesalib/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
-rwxr-xr-xmesalib/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
-rwxr-xr-xmesalib/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
-rwxr-xr-xmesalib/src/mesa/drivers/dri/swrast/swrast.c2
-rw-r--r--mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h4
-rwxr-xr-xmesalib/src/mesa/main/.gitignore1
-rw-r--r--mesalib/src/mesa/main/atifragshader.c4
-rw-r--r--mesalib/src/mesa/main/attrib.c1
-rwxr-xr-xmesalib/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
-rwxr-xr-x[-rw-r--r--]mesalib/src/mesa/main/dlopen.h0
-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
-rwxr-xr-xmesalib/src/mesa/main/imports.h24
-rwxr-xr-xmesalib/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
-rwxr-xr-xmesalib/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, 7807 insertions, 2140 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 e46db8552..98d0b1887 100755
--- 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.0f)
@@ -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 c5670fdb1..5047049fb 100644
--- a/mesalib/src/glsl/glsl_parser_extras.h
+++ b/mesalib/src/glsl/glsl_parser_extras.h
@@ -109,8 +109,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,
@@ -230,6 +232,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 516a53499..68c37275c 100755
--- 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 d198276c6..bbf2b0ca8 100755
--- a/mesalib/src/glsl/ir_constant_expression.cpp
+++ b/mesalib/src/glsl/ir_constant_expression.cpp
@@ -774,7 +774,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]);
@@ -782,7 +781,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 972ba8100..51b939098 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 100755
--- 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 a640241e9..5fa2e14a1 100755
--- 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 a90a97fa9..7ae38d07a 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 e84059073..d07988a40 100755
--- a/mesalib/src/mesa/drivers/dri/swrast/swrast.c
+++ b/mesalib/src/mesa/drivers/dri/swrast/swrast.c
@@ -335,7 +335,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 8dccc2265..8182e7677 100644
--- a/mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h
+++ b/mesalib/src/mesa/drivers/dri/swrast/swrast_priv.h
@@ -48,13 +48,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 54885405f..58c73d333 100755
--- a/mesalib/src/mesa/main/.gitignore
+++ b/mesalib/src/mesa/main/.gitignore
@@ -8,5 +8,6 @@ get_hash.h
get_hash.h.tmp
format_info.h
glapitable.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 25110c33b..4a116acfe 100755
--- 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 93d1258cf..93d1258cf 100644..100755
--- a/mesalib/src/mesa/main/dlopen.h
+++ b/mesalib/src/mesa/main/dlopen.h
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 8877966ec..27f54d585 100755
--- a/mesalib/src/mesa/main/imports.h
+++ b/mesalib/src/mesa/main/imports.h
@@ -432,6 +432,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 b22510965..5680b2ee1 100755
--- 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 9ecc7d3b5..12363de7b 100755
--- 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 d8e22d438..5df5a2922 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) \