aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2014-05-08 00:18:25 +0200
committermarha <marha@users.sourceforge.net>2014-05-08 00:18:25 +0200
commit683155917770af9e63a938bc450df25d1904d567 (patch)
tree5eb9d2d0bba27ed4e8afe58c195d1918282c343b /mesalib/src/glsl
parentea0cd87ecbe9fc3c5503ccad7f87a895a458d6d4 (diff)
downloadvcxsrv-683155917770af9e63a938bc450df25d1904d567.tar.gz
vcxsrv-683155917770af9e63a938bc450df25d1904d567.tar.bz2
vcxsrv-683155917770af9e63a938bc450df25d1904d567.zip
xserver xcb-proto mesa pixman xkeyboard-config git update 7 May 2014
xserver commit a5b9757142a2ab471ca26651dce9cc5f5e351f3d libxcb commit d978a4f69b30b630f28d07f1003cf290284d24d8 libxcb/xcb-proto commit 389889e2f95af19e7fc7ac89e7faeb2f28652415 xkeyboard-config commit 3e54f31b1f118f00c240f59d72d7ddb685c6db79 libX11 commit 8be4610939b833587954957f5963eb4191b43d19 libXdmcp commit 089081dca4ba3598c6f9bf401c029378943b5854 libXext commit 11aad96bd689d54156064d2e81213dc827a689d1 libfontenc commit 0037a42107b952c9d903719615747e760e4e7247 libXinerama commit edd95182b26eb5d576d4878c559e0f17dddaa909 libXau commit 1e4635be11154dd8262f37b379511bd627defa2a xkbcomp commit d4e02a09258063c6d024c3ccd42d6b22212e6e18 pixman commit 91f32ce961bc85f98b3372b95681ad8918d24b18 xextproto commit 66afec3f49e8eb0d4c2e9af7088fc3116d4bafd7 randrproto commit a4a6694c059d74247c16527eef4a0ec9f56bbef6 glproto commit f84853d97d5749308992412a215fa518b6536eb3 mkfontscale commit 399db42a151687f1181ae23d28a76d31125a2853 xwininfo commit ba0d1b0da21d2dbdd81098ed5778f3792b472e13 libXft commit 4acfdaf95adb0a05c2a25550bdde036c865902f4 libXmu commit 22d9c590901e121936f50dee97dc60c4f7defb63 libxtrans commit a57a7f62242e1ea972b81414741729bf3dbae0a4 fontconfig commit 81664fe54f117e4781fda5a30429b51858302e91 mesa commit 9ced3fc649ec04710a5f5c855bfb582b898cff83
Diffstat (limited to 'mesalib/src/glsl')
-rw-r--r--mesalib/src/glsl/Makefile.am11
-rw-r--r--mesalib/src/glsl/ast_to_hir.cpp80
-rw-r--r--mesalib/src/glsl/builtin_types.cpp2
-rw-r--r--mesalib/src/glsl/builtin_variables.cpp63
-rw-r--r--mesalib/src/glsl/glcpp/glcpp-parse.y5
-rw-r--r--mesalib/src/glsl/glsl_parser.yy15
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.cpp82
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.h116
-rw-r--r--mesalib/src/glsl/ir.cpp2
-rw-r--r--mesalib/src/glsl/ir_optimization.h4
-rw-r--r--mesalib/src/glsl/link_varyings.cpp368
-rw-r--r--mesalib/src/glsl/linker.cpp190
-rw-r--r--mesalib/src/glsl/lower_instructions.cpp58
-rw-r--r--mesalib/src/glsl/lower_packed_varyings.cpp39
-rw-r--r--mesalib/src/glsl/main.cpp6
-rw-r--r--mesalib/src/glsl/opt_dead_builtin_varyings.cpp7
16 files changed, 810 insertions, 238 deletions
diff --git a/mesalib/src/glsl/Makefile.am b/mesalib/src/glsl/Makefile.am
index 534eaa385..fd0e837d1 100644
--- a/mesalib/src/glsl/Makefile.am
+++ b/mesalib/src/glsl/Makefile.am
@@ -61,7 +61,9 @@ tests_general_ir_test_SOURCES = \
$(GLSL_SRCDIR)/standalone_scaffolding.cpp \
tests/builtin_variable_test.cpp \
tests/invalidate_locations_test.cpp \
- tests/general_ir_test.cpp
+ tests/general_ir_test.cpp \
+ tests/varyings_test.cpp \
+ tests/common.c
tests_general_ir_test_CFLAGS = \
$(PTHREAD_CFLAGS)
tests_general_ir_test_LDADD = \
@@ -76,7 +78,8 @@ tests_uniform_initializer_test_SOURCES = \
$(top_srcdir)/src/mesa/program/symbol_table.c \
tests/copy_constant_to_storage_tests.cpp \
tests/set_uniform_initializer_tests.cpp \
- tests/uniform_initializer_utils.cpp
+ tests/uniform_initializer_utils.cpp \
+ tests/common.c
tests_uniform_initializer_test_CFLAGS = \
$(PTHREAD_CFLAGS)
tests_uniform_initializer_test_LDADD = \
@@ -95,7 +98,8 @@ tests_ralloc_test_LDADD = \
tests_sampler_types_test_SOURCES = \
$(top_srcdir)/src/mesa/program/prog_hash_table.c\
$(top_srcdir)/src/mesa/program/symbol_table.c \
- tests/sampler_types_test.cpp
+ tests/sampler_types_test.cpp \
+ tests/common.c
tests_sampler_types_test_CFLAGS = \
$(PTHREAD_CFLAGS)
tests_sampler_types_test_LDADD = \
@@ -138,6 +142,7 @@ glsl_test_SOURCES = \
$(top_srcdir)/src/mesa/program/prog_hash_table.c \
$(top_srcdir)/src/mesa/program/symbol_table.c \
$(GLSL_SRCDIR)/standalone_scaffolding.cpp \
+ tests/common.c \
test.cpp \
test_optpass.cpp
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp
index 0411befa9..7516c33e1 100644
--- a/mesalib/src/glsl/ast_to_hir.cpp
+++ b/mesalib/src/glsl/ast_to_hir.cpp
@@ -123,6 +123,11 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state)
instructions->push_head(var);
}
+ /* Figure out if gl_FragCoord is actually used in fragment shader */
+ ir_variable *const var = state->symbols->get_variable("gl_FragCoord");
+ if (var != NULL)
+ state->fs_uses_gl_fragcoord = var->data.used;
+
/* From section 7.1 (Built-In Language Variables) of the GLSL 4.10 spec:
*
* If multiple shaders using members of a built-in block belonging to
@@ -2341,6 +2346,34 @@ apply_image_qualifier_to_variable(const struct ast_type_qualifier *qual,
}
}
+static inline const char*
+get_layout_qualifier_string(bool origin_upper_left, bool pixel_center_integer)
+{
+ if (origin_upper_left && pixel_center_integer)
+ return "origin_upper_left, pixel_center_integer";
+ else if (origin_upper_left)
+ return "origin_upper_left";
+ else if (pixel_center_integer)
+ return "pixel_center_integer";
+ else
+ return " ";
+}
+
+static inline bool
+is_conflicting_fragcoord_redeclaration(struct _mesa_glsl_parse_state *state,
+ const struct ast_type_qualifier *qual)
+{
+ /* If gl_FragCoord was previously declared, and the qualifiers were
+ * different in any way, return true.
+ */
+ if (state->fs_redeclares_gl_fragcoord) {
+ return (state->fs_pixel_center_integer != qual->flags.q.pixel_center_integer
+ || state->fs_origin_upper_left != qual->flags.q.origin_upper_left);
+ }
+
+ return false;
+}
+
static void
apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
ir_variable *var,
@@ -2505,6 +2538,53 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
qual_string);
}
+ if (var->name != NULL && strcmp(var->name, "gl_FragCoord") == 0) {
+
+ /* Section 4.3.8.1, page 39 of GLSL 1.50 spec says:
+ *
+ * "Within any shader, the first redeclarations of gl_FragCoord
+ * must appear before any use of gl_FragCoord."
+ *
+ * Generate a compiler error if above condition is not met by the
+ * fragment shader.
+ */
+ ir_variable *earlier = state->symbols->get_variable("gl_FragCoord");
+ if (earlier != NULL &&
+ earlier->data.used &&
+ !state->fs_redeclares_gl_fragcoord) {
+ _mesa_glsl_error(loc, state,
+ "gl_FragCoord used before its first redeclaration "
+ "in fragment shader");
+ }
+
+ /* Make sure all gl_FragCoord redeclarations specify the same layout
+ * qualifiers.
+ */
+ if (is_conflicting_fragcoord_redeclaration(state, qual)) {
+ const char *const qual_string =
+ get_layout_qualifier_string(qual->flags.q.origin_upper_left,
+ qual->flags.q.pixel_center_integer);
+
+ const char *const state_string =
+ get_layout_qualifier_string(state->fs_origin_upper_left,
+ state->fs_pixel_center_integer);
+
+ _mesa_glsl_error(loc, state,
+ "gl_FragCoord redeclared with different layout "
+ "qualifiers (%s) and (%s) ",
+ state_string,
+ qual_string);
+ }
+ state->fs_origin_upper_left = qual->flags.q.origin_upper_left;
+ state->fs_pixel_center_integer = qual->flags.q.pixel_center_integer;
+ state->fs_redeclares_gl_fragcoord_with_no_layout_qualifiers =
+ !qual->flags.q.origin_upper_left && !qual->flags.q.pixel_center_integer;
+ state->fs_redeclares_gl_fragcoord =
+ state->fs_origin_upper_left ||
+ state->fs_pixel_center_integer ||
+ state->fs_redeclares_gl_fragcoord_with_no_layout_qualifiers;
+ }
+
if (qual->flags.q.explicit_location) {
validate_explicit_location(qual, var, state, loc);
} else if (qual->flags.q.explicit_index) {
diff --git a/mesalib/src/glsl/builtin_types.cpp b/mesalib/src/glsl/builtin_types.cpp
index dd42ecb05..0a0fa8cd3 100644
--- a/mesalib/src/glsl/builtin_types.cpp
+++ b/mesalib/src/glsl/builtin_types.cpp
@@ -241,7 +241,7 @@ const static struct builtin_type_versions {
T(atomic_uint, 420, 999)
};
-const glsl_type *const deprecated_types[] = {
+static const glsl_type *const deprecated_types[] = {
glsl_type::struct_gl_PointParameters_type,
glsl_type::struct_gl_MaterialParameters_type,
glsl_type::struct_gl_LightSourceParameters_type,
diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp
index 4176ae6e6..9b35850ee 100644
--- a/mesalib/src/glsl/builtin_variables.cpp
+++ b/mesalib/src/glsl/builtin_variables.cpp
@@ -30,21 +30,21 @@
#include "program/prog_statevars.h"
#include "program/prog_instruction.h"
-static struct gl_builtin_uniform_element gl_NumSamples_elements[] = {
+static const struct gl_builtin_uniform_element gl_NumSamples_elements[] = {
{NULL, {STATE_NUM_SAMPLES, 0, 0}, SWIZZLE_XXXX}
};
-static struct gl_builtin_uniform_element gl_DepthRange_elements[] = {
+static const struct gl_builtin_uniform_element gl_DepthRange_elements[] = {
{"near", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_XXXX},
{"far", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_YYYY},
{"diff", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_ZZZZ},
};
-static struct gl_builtin_uniform_element gl_ClipPlane_elements[] = {
+static const struct gl_builtin_uniform_element gl_ClipPlane_elements[] = {
{NULL, {STATE_CLIPPLANE, 0, 0}, SWIZZLE_XYZW}
};
-static struct gl_builtin_uniform_element gl_Point_elements[] = {
+static const struct gl_builtin_uniform_element gl_Point_elements[] = {
{"size", {STATE_POINT_SIZE}, SWIZZLE_XXXX},
{"sizeMin", {STATE_POINT_SIZE}, SWIZZLE_YYYY},
{"sizeMax", {STATE_POINT_SIZE}, SWIZZLE_ZZZZ},
@@ -54,7 +54,7 @@ static struct gl_builtin_uniform_element gl_Point_elements[] = {
{"distanceQuadraticAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_ZZZZ},
};
-static struct gl_builtin_uniform_element gl_FrontMaterial_elements[] = {
+static const struct gl_builtin_uniform_element gl_FrontMaterial_elements[] = {
{"emission", {STATE_MATERIAL, 0, STATE_EMISSION}, SWIZZLE_XYZW},
{"ambient", {STATE_MATERIAL, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
{"diffuse", {STATE_MATERIAL, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
@@ -62,7 +62,7 @@ static struct gl_builtin_uniform_element gl_FrontMaterial_elements[] = {
{"shininess", {STATE_MATERIAL, 0, STATE_SHININESS}, SWIZZLE_XXXX},
};
-static struct gl_builtin_uniform_element gl_BackMaterial_elements[] = {
+static const struct gl_builtin_uniform_element gl_BackMaterial_elements[] = {
{"emission", {STATE_MATERIAL, 1, STATE_EMISSION}, SWIZZLE_XYZW},
{"ambient", {STATE_MATERIAL, 1, STATE_AMBIENT}, SWIZZLE_XYZW},
{"diffuse", {STATE_MATERIAL, 1, STATE_DIFFUSE}, SWIZZLE_XYZW},
@@ -70,7 +70,7 @@ static struct gl_builtin_uniform_element gl_BackMaterial_elements[] = {
{"shininess", {STATE_MATERIAL, 1, STATE_SHININESS}, SWIZZLE_XXXX},
};
-static struct gl_builtin_uniform_element gl_LightSource_elements[] = {
+static const struct gl_builtin_uniform_element gl_LightSource_elements[] = {
{"ambient", {STATE_LIGHT, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
{"diffuse", {STATE_LIGHT, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
{"specular", {STATE_LIGHT, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
@@ -89,67 +89,67 @@ static struct gl_builtin_uniform_element gl_LightSource_elements[] = {
{"quadraticAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_ZZZZ},
};
-static struct gl_builtin_uniform_element gl_LightModel_elements[] = {
+static const struct gl_builtin_uniform_element gl_LightModel_elements[] = {
{"ambient", {STATE_LIGHTMODEL_AMBIENT, 0}, SWIZZLE_XYZW},
};
-static struct gl_builtin_uniform_element gl_FrontLightModelProduct_elements[] = {
+static const struct gl_builtin_uniform_element gl_FrontLightModelProduct_elements[] = {
{"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 0}, SWIZZLE_XYZW},
};
-static struct gl_builtin_uniform_element gl_BackLightModelProduct_elements[] = {
+static const struct gl_builtin_uniform_element gl_BackLightModelProduct_elements[] = {
{"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 1}, SWIZZLE_XYZW},
};
-static struct gl_builtin_uniform_element gl_FrontLightProduct_elements[] = {
+static const struct gl_builtin_uniform_element gl_FrontLightProduct_elements[] = {
{"ambient", {STATE_LIGHTPROD, 0, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
{"diffuse", {STATE_LIGHTPROD, 0, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
{"specular", {STATE_LIGHTPROD, 0, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
};
-static struct gl_builtin_uniform_element gl_BackLightProduct_elements[] = {
+static const struct gl_builtin_uniform_element gl_BackLightProduct_elements[] = {
{"ambient", {STATE_LIGHTPROD, 0, 1, STATE_AMBIENT}, SWIZZLE_XYZW},
{"diffuse", {STATE_LIGHTPROD, 0, 1, STATE_DIFFUSE}, SWIZZLE_XYZW},
{"specular", {STATE_LIGHTPROD, 0, 1, STATE_SPECULAR}, SWIZZLE_XYZW},
};
-static struct gl_builtin_uniform_element gl_TextureEnvColor_elements[] = {
+static const struct gl_builtin_uniform_element gl_TextureEnvColor_elements[] = {
{NULL, {STATE_TEXENV_COLOR, 0}, SWIZZLE_XYZW},
};
-static struct gl_builtin_uniform_element gl_EyePlaneS_elements[] = {
+static const struct gl_builtin_uniform_element gl_EyePlaneS_elements[] = {
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_S}, SWIZZLE_XYZW},
};
-static struct gl_builtin_uniform_element gl_EyePlaneT_elements[] = {
+static const struct gl_builtin_uniform_element gl_EyePlaneT_elements[] = {
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_T}, SWIZZLE_XYZW},
};
-static struct gl_builtin_uniform_element gl_EyePlaneR_elements[] = {
+static const struct gl_builtin_uniform_element gl_EyePlaneR_elements[] = {
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_R}, SWIZZLE_XYZW},
};
-static struct gl_builtin_uniform_element gl_EyePlaneQ_elements[] = {
+static const struct gl_builtin_uniform_element gl_EyePlaneQ_elements[] = {
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_Q}, SWIZZLE_XYZW},
};
-static struct gl_builtin_uniform_element gl_ObjectPlaneS_elements[] = {
+static const struct gl_builtin_uniform_element gl_ObjectPlaneS_elements[] = {
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_S}, SWIZZLE_XYZW},
};
-static struct gl_builtin_uniform_element gl_ObjectPlaneT_elements[] = {
+static const struct gl_builtin_uniform_element gl_ObjectPlaneT_elements[] = {
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_T}, SWIZZLE_XYZW},
};
-static struct gl_builtin_uniform_element gl_ObjectPlaneR_elements[] = {
+static const struct gl_builtin_uniform_element gl_ObjectPlaneR_elements[] = {
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_R}, SWIZZLE_XYZW},
};
-static struct gl_builtin_uniform_element gl_ObjectPlaneQ_elements[] = {
+static const struct gl_builtin_uniform_element gl_ObjectPlaneQ_elements[] = {
{NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_Q}, SWIZZLE_XYZW},
};
-static struct gl_builtin_uniform_element gl_Fog_elements[] = {
+static const struct gl_builtin_uniform_element gl_Fog_elements[] = {
{"color", {STATE_FOG_COLOR}, SWIZZLE_XYZW},
{"density", {STATE_FOG_PARAMS}, SWIZZLE_XXXX},
{"start", {STATE_FOG_PARAMS}, SWIZZLE_YYYY},
@@ -157,32 +157,32 @@ static struct gl_builtin_uniform_element gl_Fog_elements[] = {
{"scale", {STATE_FOG_PARAMS}, SWIZZLE_WWWW},
};
-static struct gl_builtin_uniform_element gl_NormalScale_elements[] = {
+static const struct gl_builtin_uniform_element gl_NormalScale_elements[] = {
{NULL, {STATE_NORMAL_SCALE}, SWIZZLE_XXXX},
};
-static struct gl_builtin_uniform_element gl_BumpRotMatrix0MESA_elements[] = {
+static const struct gl_builtin_uniform_element gl_BumpRotMatrix0MESA_elements[] = {
{NULL, {STATE_INTERNAL, STATE_ROT_MATRIX_0}, SWIZZLE_XYZW},
};
-static struct gl_builtin_uniform_element gl_BumpRotMatrix1MESA_elements[] = {
+static const struct gl_builtin_uniform_element gl_BumpRotMatrix1MESA_elements[] = {
{NULL, {STATE_INTERNAL, STATE_ROT_MATRIX_1}, SWIZZLE_XYZW},
};
-static struct gl_builtin_uniform_element gl_FogParamsOptimizedMESA_elements[] = {
+static const struct gl_builtin_uniform_element gl_FogParamsOptimizedMESA_elements[] = {
{NULL, {STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED}, SWIZZLE_XYZW},
};
-static struct gl_builtin_uniform_element gl_CurrentAttribVertMESA_elements[] = {
+static const struct gl_builtin_uniform_element gl_CurrentAttribVertMESA_elements[] = {
{NULL, {STATE_INTERNAL, STATE_CURRENT_ATTRIB, 0}, SWIZZLE_XYZW},
};
-static struct gl_builtin_uniform_element gl_CurrentAttribFragMESA_elements[] = {
+static const struct gl_builtin_uniform_element gl_CurrentAttribFragMESA_elements[] = {
{NULL, {STATE_INTERNAL, STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED, 0}, SWIZZLE_XYZW},
};
#define MATRIX(name, statevar, modifier) \
- static struct gl_builtin_uniform_element name ## _elements[] = { \
+ static const struct gl_builtin_uniform_element name ## _elements[] = { \
{ NULL, { statevar, 0, 0, 0, modifier}, SWIZZLE_XYZW }, \
{ NULL, { statevar, 0, 1, 1, modifier}, SWIZZLE_XYZW }, \
{ NULL, { statevar, 0, 2, 2, modifier}, SWIZZLE_XYZW }, \
@@ -225,7 +225,7 @@ MATRIX(gl_TextureMatrixTranspose,
MATRIX(gl_TextureMatrixInverseTranspose,
STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE);
-static struct gl_builtin_uniform_element gl_NormalMatrix_elements[] = {
+static const struct gl_builtin_uniform_element gl_NormalMatrix_elements[] = {
{ NULL, { STATE_MODELVIEW_MATRIX, 0, 0, 0, STATE_MATRIX_INVERSE},
MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z) },
{ NULL, { STATE_MODELVIEW_MATRIX, 0, 1, 1, STATE_MATRIX_INVERSE},
@@ -498,7 +498,8 @@ builtin_variable_generator::add_uniform(const glsl_type *type,
for (unsigned a = 0; a < array_count; a++) {
for (unsigned j = 0; j < statevar->num_elements; j++) {
- struct gl_builtin_uniform_element *element = &statevar->elements[j];
+ const struct gl_builtin_uniform_element *element =
+ &statevar->elements[j];
memcpy(slots->tokens, element->tokens, sizeof(element->tokens));
if (type->is_array()) {
diff --git a/mesalib/src/glsl/glcpp/glcpp-parse.y b/mesalib/src/glsl/glcpp/glcpp-parse.y
index f28d8531e..98875837c 100644
--- a/mesalib/src/glsl/glcpp/glcpp-parse.y
+++ b/mesalib/src/glsl/glcpp/glcpp-parse.y
@@ -2062,6 +2062,7 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio
/* Add pre-defined macros. */
if (parser->is_gles) {
add_builtin_define(parser, "GL_ES", 1);
+ add_builtin_define(parser, "GL_EXT_separate_shader_objects", 1);
if (extensions != NULL) {
if (extensions->OES_EGL_image_external)
@@ -2069,6 +2070,7 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio
}
} else {
add_builtin_define(parser, "GL_ARB_draw_buffers", 1);
+ add_builtin_define(parser, "GL_ARB_separate_shader_objects", 1);
add_builtin_define(parser, "GL_ARB_texture_rectangle", 1);
add_builtin_define(parser, "GL_AMD_shader_trinary_minmax", 1);
@@ -2134,9 +2136,6 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio
if (extensions->ARB_texture_gather)
add_builtin_define(parser, "GL_ARB_texture_gather", 1);
- if (extensions->ARB_separate_shader_objects)
- add_builtin_define(parser, "GL_ARB_separate_shader_objects", 1);
-
if (extensions->ARB_shader_atomic_counters)
add_builtin_define(parser, "GL_ARB_shader_atomic_counters", 1);
diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy
index 2d0e7be54..b09d6e536 100644
--- a/mesalib/src/glsl/glsl_parser.yy
+++ b/mesalib/src/glsl/glsl_parser.yy
@@ -1214,7 +1214,7 @@ layout_qualifier_id:
/* Layout qualifiers for GLSL 1.50 geometry shaders. */
if (!$$.flags.i) {
- struct {
+ static const struct {
const char *s;
GLenum e;
} map[] = {
@@ -1319,6 +1319,13 @@ layout_qualifier_id:
if (match_layout_qualifier("location", $1, state) == 0) {
$$.flags.q.explicit_location = 1;
+ if ($$.flags.q.attribute == 1 &&
+ state->ARB_explicit_attrib_location_warn) {
+ _mesa_glsl_warning(& @1, state,
+ "GL_ARB_explicit_attrib_location layout "
+ "identifier `%s' used", $1);
+ }
+
if ($3 >= 0) {
$$.location = $3;
} else {
@@ -1368,7 +1375,7 @@ layout_qualifier_id:
}
}
- static const char *local_size_qualifiers[3] = {
+ static const char * const local_size_qualifiers[3] = {
"local_size_x",
"local_size_y",
"local_size_z",
@@ -1426,10 +1433,6 @@ layout_qualifier_id:
_mesa_glsl_error(& @1, state, "unrecognized layout identifier "
"`%s'", $1);
YYERROR;
- } else if (state->ARB_explicit_attrib_location_warn) {
- _mesa_glsl_warning(& @1, state,
- "GL_ARB_explicit_attrib_location layout "
- "identifier `%s' used", $1);
}
}
| interface_block_layout_qualifier
diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp
index 03c2a972a..d3339e779 100644
--- a/mesalib/src/glsl/glsl_parser_extras.cpp
+++ b/mesalib/src/glsl/glsl_parser_extras.cpp
@@ -49,7 +49,7 @@ glsl_compute_version_string(void *mem_ctx, bool is_es, unsigned version)
}
-static unsigned known_desktop_glsl_versions[] =
+static const unsigned known_desktop_glsl_versions[] =
{ 110, 120, 130, 140, 150, 330, 400, 410, 420, 430, 440 };
@@ -197,6 +197,12 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
this->default_uniform_qualifier->flags.q.shared = 1;
this->default_uniform_qualifier->flags.q.column_major = 1;
+ this->fs_uses_gl_fragcoord = false;
+ this->fs_redeclares_gl_fragcoord = false;
+ this->fs_origin_upper_left = false;
+ this->fs_pixel_center_integer = false;
+ this->fs_redeclares_gl_fragcoord_with_no_layout_qualifiers = false;
+
this->gs_input_prim_type_specified = false;
this->gs_input_size = 0;
this->in_qualifier = new(this) ast_type_qualifier();
@@ -500,40 +506,53 @@ struct _mesa_glsl_extension {
static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = {
/* API availability */
/* name GL ES supported flag */
+
+ /* ARB extensions go here, sorted alphabetically.
+ */
EXT(ARB_arrays_of_arrays, true, false, ARB_arrays_of_arrays),
+ EXT(ARB_compute_shader, true, false, ARB_compute_shader),
EXT(ARB_conservative_depth, true, false, ARB_conservative_depth),
EXT(ARB_draw_buffers, true, false, dummy_true),
EXT(ARB_draw_instanced, true, false, ARB_draw_instanced),
EXT(ARB_explicit_attrib_location, true, false, ARB_explicit_attrib_location),
EXT(ARB_fragment_coord_conventions, true, false, ARB_fragment_coord_conventions),
- EXT(ARB_texture_rectangle, true, false, dummy_true),
- EXT(EXT_texture_array, true, false, EXT_texture_array),
- EXT(ARB_separate_shader_objects, true, false, ARB_separate_shader_objects),
- EXT(ARB_shader_texture_lod, true, false, ARB_shader_texture_lod),
- EXT(ARB_shader_stencil_export, true, false, ARB_shader_stencil_export),
- EXT(AMD_conservative_depth, true, false, ARB_conservative_depth),
- EXT(AMD_shader_stencil_export, true, false, ARB_shader_stencil_export),
- EXT(OES_texture_3D, false, true, EXT_texture3D),
- EXT(OES_EGL_image_external, false, true, OES_EGL_image_external),
+ EXT(ARB_gpu_shader5, true, false, ARB_gpu_shader5),
+ EXT(ARB_sample_shading, true, false, ARB_sample_shading),
+ EXT(ARB_separate_shader_objects, true, false, dummy_true),
+ EXT(ARB_shader_atomic_counters, true, false, ARB_shader_atomic_counters),
EXT(ARB_shader_bit_encoding, true, false, ARB_shader_bit_encoding),
- EXT(ARB_uniform_buffer_object, true, false, ARB_uniform_buffer_object),
- EXT(OES_standard_derivatives, false, true, OES_standard_derivatives),
- EXT(ARB_texture_cube_map_array, true, false, ARB_texture_cube_map_array),
- EXT(ARB_shading_language_packing, true, false, ARB_shading_language_packing),
+ EXT(ARB_shader_image_load_store, true, false, ARB_shader_image_load_store),
+ EXT(ARB_shader_stencil_export, true, false, ARB_shader_stencil_export),
+ EXT(ARB_shader_texture_lod, true, false, ARB_shader_texture_lod),
EXT(ARB_shading_language_420pack, true, false, ARB_shading_language_420pack),
+ EXT(ARB_shading_language_packing, true, false, ARB_shading_language_packing),
+ EXT(ARB_texture_cube_map_array, true, false, ARB_texture_cube_map_array),
+ EXT(ARB_texture_gather, true, false, ARB_texture_gather),
EXT(ARB_texture_multisample, true, false, ARB_texture_multisample),
EXT(ARB_texture_query_levels, true, false, ARB_texture_query_levels),
EXT(ARB_texture_query_lod, true, false, ARB_texture_query_lod),
- EXT(ARB_gpu_shader5, true, false, ARB_gpu_shader5),
+ EXT(ARB_texture_rectangle, true, false, dummy_true),
+ EXT(ARB_uniform_buffer_object, true, false, ARB_uniform_buffer_object),
+ EXT(ARB_viewport_array, true, false, ARB_viewport_array),
+
+ /* KHR extensions go here, sorted alphabetically.
+ */
+
+ /* OES extensions go here, sorted alphabetically.
+ */
+ EXT(OES_EGL_image_external, false, true, OES_EGL_image_external),
+ EXT(OES_standard_derivatives, false, true, OES_standard_derivatives),
+ EXT(OES_texture_3D, false, true, EXT_texture3D),
+
+ /* All other extensions go here, sorted alphabetically.
+ */
+ EXT(AMD_conservative_depth, true, false, ARB_conservative_depth),
+ EXT(AMD_shader_stencil_export, true, false, ARB_shader_stencil_export),
+ EXT(AMD_shader_trinary_minmax, true, false, dummy_true),
EXT(AMD_vertex_shader_layer, true, false, AMD_vertex_shader_layer),
+ EXT(EXT_separate_shader_objects, false, true, dummy_true),
EXT(EXT_shader_integer_mix, true, true, EXT_shader_integer_mix),
- EXT(ARB_texture_gather, true, false, ARB_texture_gather),
- EXT(ARB_shader_atomic_counters, true, false, ARB_shader_atomic_counters),
- EXT(ARB_sample_shading, true, false, ARB_sample_shading),
- EXT(AMD_shader_trinary_minmax, true, false, dummy_true),
- EXT(ARB_viewport_array, true, false, ARB_viewport_array),
- EXT(ARB_compute_shader, true, false, ARB_compute_shader),
- EXT(ARB_shader_image_load_store, true, false, ARB_shader_image_load_store),
+ EXT(EXT_texture_array, true, false, EXT_texture_array),
};
#undef EXT
@@ -637,7 +656,7 @@ _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp,
if (extension && extension->compatible_with_state(state)) {
extension->set_flags(state, behavior);
} else {
- static const char *const fmt = "extension `%s' unsupported in %s shader";
+ static const char fmt[] = "extension `%s' unsupported in %s shader";
if (behavior == extension_require) {
_mesa_glsl_error(name_locp, state, fmt,
@@ -1356,6 +1375,14 @@ set_shader_inout_layout(struct gl_shader *shader,
assert(!state->cs_input_local_size_specified);
}
+ if (shader->Stage != MESA_SHADER_FRAGMENT) {
+ /* Should have been prevented by the parser. */
+ assert(!state->fs_uses_gl_fragcoord);
+ assert(!state->fs_redeclares_gl_fragcoord);
+ assert(!state->fs_pixel_center_integer);
+ assert(!state->fs_origin_upper_left);
+ }
+
switch (shader->Stage) {
case MESA_SHADER_GEOMETRY:
shader->Geom.VerticesOut = 0;
@@ -1389,6 +1416,15 @@ set_shader_inout_layout(struct gl_shader *shader,
}
break;
+ case MESA_SHADER_FRAGMENT:
+ shader->redeclares_gl_fragcoord = state->fs_redeclares_gl_fragcoord;
+ shader->uses_gl_fragcoord = state->fs_uses_gl_fragcoord;
+ shader->pixel_center_integer = state->fs_pixel_center_integer;
+ shader->origin_upper_left = state->fs_origin_upper_left;
+ shader->ARB_fragment_coord_conventions_enable =
+ state->ARB_fragment_coord_conventions_enable;
+ break;
+
default:
/* Nothing to do. */
break;
diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h
index 3ad205c07..0416a9c72 100644
--- a/mesalib/src/glsl/glsl_parser_extras.h
+++ b/mesalib/src/glsl/glsl_parser_extras.h
@@ -140,8 +140,7 @@ struct _mesa_glsl_parse_state {
{
if (!this->has_separate_shader_objects()) {
const char *const requirement = this->es_shader
- ? "GL_EXT_separate_shader_objects (not supported by this "
- "implementation)"
+ ? "GL_EXT_separate_shader_objects extension"
: "GL_ARB_separate_shader_objects extension or GLSL 420";
_mesa_glsl_error(locp, this, "%s explicit location requires %s",
@@ -164,7 +163,8 @@ struct _mesa_glsl_parse_state {
bool has_separate_shader_objects() const
{
- return ARB_separate_shader_objects_enable || is_version(410, 0);
+ return ARB_separate_shader_objects_enable || is_version(410, 0)
+ || EXT_separate_shader_objects_enable;
}
void process_version_directive(YYLTYPE *locp, int version,
@@ -200,6 +200,18 @@ struct _mesa_glsl_parse_state {
struct ast_type_qualifier *default_uniform_qualifier;
/**
+ * Variables to track different cases if a fragment shader redeclares
+ * built-in variable gl_FragCoord.
+ *
+ * Note: These values are computed at ast_to_hir time rather than at parse
+ * time.
+ */
+ bool fs_redeclares_gl_fragcoord;
+ bool fs_origin_upper_left;
+ bool fs_pixel_center_integer;
+ bool fs_redeclares_gl_fragcoord_with_no_layout_qualifiers;
+
+ /**
* True if a geometry shader input primitive type was specified using a
* layout directive.
*
@@ -337,8 +349,14 @@ struct _mesa_glsl_parse_state {
* \name Enable bits for GLSL extensions
*/
/*@{*/
+ /* ARB extensions go here, sorted alphabetically.
+ */
bool ARB_arrays_of_arrays_enable;
bool ARB_arrays_of_arrays_warn;
+ bool ARB_compute_shader_enable;
+ bool ARB_compute_shader_warn;
+ bool ARB_conservative_depth_enable;
+ bool ARB_conservative_depth_warn;
bool ARB_draw_buffers_enable;
bool ARB_draw_buffers_warn;
bool ARB_draw_instanced_enable;
@@ -347,70 +365,78 @@ struct _mesa_glsl_parse_state {
bool ARB_explicit_attrib_location_warn;
bool ARB_fragment_coord_conventions_enable;
bool ARB_fragment_coord_conventions_warn;
- bool ARB_texture_rectangle_enable;
- bool ARB_texture_rectangle_warn;
- bool ARB_texture_gather_enable;
- bool ARB_texture_gather_warn;
- bool EXT_texture_array_enable;
- bool EXT_texture_array_warn;
+ bool ARB_gpu_shader5_enable;
+ bool ARB_gpu_shader5_warn;
+ bool ARB_sample_shading_enable;
+ bool ARB_sample_shading_warn;
bool ARB_separate_shader_objects_enable;
bool ARB_separate_shader_objects_warn;
- bool ARB_shader_texture_lod_enable;
- bool ARB_shader_texture_lod_warn;
- bool ARB_shader_stencil_export_enable;
- bool ARB_shader_stencil_export_warn;
- bool AMD_conservative_depth_enable;
- bool AMD_conservative_depth_warn;
- bool ARB_conservative_depth_enable;
- bool ARB_conservative_depth_warn;
- bool AMD_shader_stencil_export_enable;
- bool AMD_shader_stencil_export_warn;
- bool OES_texture_3D_enable;
- bool OES_texture_3D_warn;
- bool OES_EGL_image_external_enable;
- bool OES_EGL_image_external_warn;
+ bool ARB_shader_atomic_counters_enable;
+ bool ARB_shader_atomic_counters_warn;
bool ARB_shader_bit_encoding_enable;
bool ARB_shader_bit_encoding_warn;
- bool ARB_uniform_buffer_object_enable;
- bool ARB_uniform_buffer_object_warn;
- bool OES_standard_derivatives_enable;
- bool OES_standard_derivatives_warn;
- bool ARB_texture_cube_map_array_enable;
- bool ARB_texture_cube_map_array_warn;
+ bool ARB_shader_image_load_store_enable;
+ bool ARB_shader_image_load_store_warn;
+ bool ARB_shader_stencil_export_enable;
+ bool ARB_shader_stencil_export_warn;
+ bool ARB_shader_texture_lod_enable;
+ bool ARB_shader_texture_lod_warn;
+ bool ARB_shading_language_420pack_enable;
+ bool ARB_shading_language_420pack_warn;
bool ARB_shading_language_packing_enable;
bool ARB_shading_language_packing_warn;
+ bool ARB_texture_cube_map_array_enable;
+ bool ARB_texture_cube_map_array_warn;
+ bool ARB_texture_gather_enable;
+ bool ARB_texture_gather_warn;
bool ARB_texture_multisample_enable;
bool ARB_texture_multisample_warn;
bool ARB_texture_query_levels_enable;
bool ARB_texture_query_levels_warn;
bool ARB_texture_query_lod_enable;
bool ARB_texture_query_lod_warn;
- bool ARB_gpu_shader5_enable;
- bool ARB_gpu_shader5_warn;
+ bool ARB_texture_rectangle_enable;
+ bool ARB_texture_rectangle_warn;
+ bool ARB_uniform_buffer_object_enable;
+ bool ARB_uniform_buffer_object_warn;
+ bool ARB_viewport_array_enable;
+ bool ARB_viewport_array_warn;
+
+ /* KHR extensions go here, sorted alphabetically.
+ */
+
+ /* OES extensions go here, sorted alphabetically.
+ */
+ bool OES_EGL_image_external_enable;
+ bool OES_EGL_image_external_warn;
+ bool OES_standard_derivatives_enable;
+ bool OES_standard_derivatives_warn;
+ bool OES_texture_3D_enable;
+ bool OES_texture_3D_warn;
+
+ /* All other extensions go here, sorted alphabetically.
+ */
+ bool AMD_conservative_depth_enable;
+ bool AMD_conservative_depth_warn;
+ bool AMD_shader_stencil_export_enable;
+ bool AMD_shader_stencil_export_warn;
+ bool AMD_shader_trinary_minmax_enable;
+ bool AMD_shader_trinary_minmax_warn;
bool AMD_vertex_shader_layer_enable;
bool AMD_vertex_shader_layer_warn;
- bool ARB_shading_language_420pack_enable;
- bool ARB_shading_language_420pack_warn;
- bool ARB_sample_shading_enable;
- bool ARB_sample_shading_warn;
+ bool EXT_separate_shader_objects_enable;
+ bool EXT_separate_shader_objects_warn;
bool EXT_shader_integer_mix_enable;
bool EXT_shader_integer_mix_warn;
- bool ARB_shader_atomic_counters_enable;
- bool ARB_shader_atomic_counters_warn;
- bool AMD_shader_trinary_minmax_enable;
- bool AMD_shader_trinary_minmax_warn;
- bool ARB_viewport_array_enable;
- bool ARB_viewport_array_warn;
- bool ARB_compute_shader_enable;
- bool ARB_compute_shader_warn;
- bool ARB_shader_image_load_store_enable;
- bool ARB_shader_image_load_store_warn;
+ bool EXT_texture_array_enable;
+ bool EXT_texture_array_warn;
/*@}*/
/** Extensions supported by the OpenGL implementation. */
const struct gl_extensions *extensions;
bool uses_builtin_functions;
+ bool fs_uses_gl_fragcoord;
/**
* For geometry shaders, size of the most recently seen input declaration
diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp
index 1a18b47f7..ba8a8394f 100644
--- a/mesalib/src/glsl/ir.cpp
+++ b/mesalib/src/glsl/ir.cpp
@@ -1333,7 +1333,7 @@ ir_dereference::is_lvalue() const
}
-static const char *tex_opcode_strs[] = { "tex", "txb", "txl", "txd", "txf", "txf_ms", "txs", "lod", "tg4", "query_levels" };
+static const char * const tex_opcode_strs[] = { "tex", "txb", "txl", "txd", "txf", "txf_ms", "txs", "lod", "tg4", "query_levels" };
const char *ir_texture::opcode_string()
{
diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h
index 40bb61392..c63921c26 100644
--- a/mesalib/src/glsl/ir_optimization.h
+++ b/mesalib/src/glsl/ir_optimization.h
@@ -38,6 +38,8 @@
#define INT_DIV_TO_MUL_RCP 0x40
#define BITFIELD_INSERT_TO_BFM_BFI 0x80
#define LDEXP_TO_ARITH 0x100
+#define CARRY_TO_ARITH 0x200
+#define BORROW_TO_ARITH 0x400
/**
* \see class lower_packing_builtins_visitor
@@ -112,7 +114,7 @@ bool lower_clip_distance(gl_shader *shader);
void lower_output_reads(exec_list *instructions);
bool lower_packing_builtins(exec_list *instructions, int op_mask);
void lower_ubo_reference(struct gl_shader *shader, exec_list *instructions);
-void lower_packed_varyings(void *mem_ctx, unsigned location_base,
+void lower_packed_varyings(void *mem_ctx,
unsigned locations_used, ir_variable_mode mode,
unsigned gs_input_vertices, gl_shader *shader);
bool lower_vector_insert(exec_list *instructions, bool lower_nonconstant_index);
diff --git a/mesalib/src/glsl/link_varyings.cpp b/mesalib/src/glsl/link_varyings.cpp
index c925c00e3..ac38a2f31 100644
--- a/mesalib/src/glsl/link_varyings.cpp
+++ b/mesalib/src/glsl/link_varyings.cpp
@@ -172,6 +172,7 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
gl_shader *producer, gl_shader *consumer)
{
glsl_symbol_table parameters;
+ ir_variable *explicit_locations[MAX_VARYING] = { NULL, };
/* Find all shader outputs in the "producer" stage.
*/
@@ -181,7 +182,26 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
if ((var == NULL) || (var->data.mode != ir_var_shader_out))
continue;
- parameters.add_variable(var);
+ if (!var->data.explicit_location
+ || var->data.location < VARYING_SLOT_VAR0)
+ parameters.add_variable(var);
+ else {
+ /* User-defined varyings with explicit locations are handled
+ * differently because they do not need to have matching names.
+ */
+ const unsigned idx = var->data.location - VARYING_SLOT_VAR0;
+
+ if (explicit_locations[idx] != NULL) {
+ linker_error(prog,
+ "%s shader has multiple outputs explicitly "
+ "assigned to location %d\n",
+ _mesa_shader_stage_to_string(producer->Stage),
+ idx);
+ return;
+ }
+
+ explicit_locations[idx] = var;
+ }
}
@@ -220,7 +240,27 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
front_color, back_color,
consumer->Stage, producer->Stage);
} else {
- ir_variable *const output = parameters.get_variable(input->name);
+ /* The rules for connecting inputs and outputs change in the presence
+ * of explicit locations. In this case, we no longer care about the
+ * names of the variables. Instead, we care only about the
+ * explicitly assigned location.
+ */
+ ir_variable *output = NULL;
+ if (input->data.explicit_location
+ && input->data.location >= VARYING_SLOT_VAR0) {
+ output = explicit_locations[input->data.location - VARYING_SLOT_VAR0];
+
+ if (output == NULL) {
+ linker_error(prog,
+ "%s shader input `%s' with explicit location "
+ "has no matching output\n",
+ _mesa_shader_stage_to_string(consumer->Stage),
+ input->name);
+ }
+ } else {
+ output = parameters.get_variable(input->name);
+ }
+
if (output != NULL) {
cross_validate_types_and_qualifiers(prog, input, output,
consumer->Stage, producer->Stage);
@@ -622,7 +662,7 @@ public:
~varying_matches();
void record(ir_variable *producer_var, ir_variable *consumer_var);
unsigned assign_locations();
- void store_locations(unsigned producer_base, unsigned consumer_base) const;
+ void store_locations() const;
private:
/**
@@ -648,8 +688,8 @@ private:
PACKING_ORDER_VEC3,
};
- static unsigned compute_packing_class(ir_variable *var);
- static packing_order_enum compute_packing_order(ir_variable *var);
+ static unsigned compute_packing_class(const ir_variable *var);
+ static packing_order_enum compute_packing_order(const ir_variable *var);
static int match_comparator(const void *x_generic, const void *y_generic);
/**
@@ -746,7 +786,10 @@ varying_matches::~varying_matches()
void
varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var)
{
- if (!producer_var->data.is_unmatched_generic_inout) {
+ assert(producer_var != NULL || consumer_var != NULL);
+
+ if ((producer_var && !producer_var->data.is_unmatched_generic_inout)
+ || (consumer_var && !consumer_var->data.is_unmatched_generic_inout)) {
/* Either a location already exists for this variable (since it is part
* of fixed functionality), or it has already been recorded as part of a
* previous match.
@@ -781,24 +824,28 @@ varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var)
realloc(this->matches,
sizeof(*this->matches) * this->matches_capacity);
}
+
+ const ir_variable *const var = (producer_var != NULL)
+ ? producer_var : consumer_var;
+
this->matches[this->num_matches].packing_class
- = this->compute_packing_class(producer_var);
+ = this->compute_packing_class(var);
this->matches[this->num_matches].packing_order
- = this->compute_packing_order(producer_var);
+ = this->compute_packing_order(var);
if (this->disable_varying_packing) {
- unsigned slots = producer_var->type->is_array()
- ? (producer_var->type->length
- * producer_var->type->fields.array->matrix_columns)
- : producer_var->type->matrix_columns;
+ unsigned slots = var->type->is_array()
+ ? (var->type->length * var->type->fields.array->matrix_columns)
+ : var->type->matrix_columns;
this->matches[this->num_matches].num_components = 4 * slots;
} else {
this->matches[this->num_matches].num_components
- = producer_var->type->component_slots();
+ = var->type->component_slots();
}
this->matches[this->num_matches].producer_var = producer_var;
this->matches[this->num_matches].consumer_var = consumer_var;
this->num_matches++;
- producer_var->data.is_unmatched_generic_inout = 0;
+ if (producer_var)
+ producer_var->data.is_unmatched_generic_inout = 0;
if (consumer_var)
consumer_var->data.is_unmatched_generic_inout = 0;
}
@@ -842,8 +889,7 @@ varying_matches::assign_locations()
* assignments that were made by varying_matches::assign_locations().
*/
void
-varying_matches::store_locations(unsigned producer_base,
- unsigned consumer_base) const
+varying_matches::store_locations() const
{
for (unsigned i = 0; i < this->num_matches; i++) {
ir_variable *producer_var = this->matches[i].producer_var;
@@ -852,11 +898,14 @@ varying_matches::store_locations(unsigned producer_base,
unsigned slot = generic_location / 4;
unsigned offset = generic_location % 4;
- producer_var->data.location = producer_base + slot;
- producer_var->data.location_frac = offset;
+ if (producer_var) {
+ producer_var->data.location = VARYING_SLOT_VAR0 + slot;
+ producer_var->data.location_frac = offset;
+ }
+
if (consumer_var) {
assert(consumer_var->data.location == -1);
- consumer_var->data.location = consumer_base + slot;
+ consumer_var->data.location = VARYING_SLOT_VAR0 + slot;
consumer_var->data.location_frac = offset;
}
}
@@ -869,7 +918,7 @@ varying_matches::store_locations(unsigned producer_base,
* be safely backed into the same vec4.
*/
unsigned
-varying_matches::compute_packing_class(ir_variable *var)
+varying_matches::compute_packing_class(const ir_variable *var)
{
/* Without help from the back-end, there is no way to pack together
* variables with different interpolation types, because
@@ -900,7 +949,7 @@ varying_matches::compute_packing_class(ir_variable *var)
* other varyings in the same packing class.
*/
varying_matches::packing_order_enum
-varying_matches::compute_packing_order(ir_variable *var)
+varying_matches::compute_packing_order(const ir_variable *var)
{
const glsl_type *element_type = var->type;
@@ -1037,6 +1086,157 @@ private:
};
+namespace linker {
+
+bool
+populate_consumer_input_sets(void *mem_ctx, exec_list *ir,
+ hash_table *consumer_inputs,
+ hash_table *consumer_interface_inputs,
+ ir_variable *consumer_inputs_with_locations[VARYING_SLOT_MAX])
+{
+ memset(consumer_inputs_with_locations,
+ 0,
+ sizeof(consumer_inputs_with_locations[0]) * VARYING_SLOT_MAX);
+
+ foreach_list(node, ir) {
+ ir_variable *const input_var = ((ir_instruction *) node)->as_variable();
+
+ if ((input_var != NULL) && (input_var->data.mode == ir_var_shader_in)) {
+ if (input_var->type->is_interface())
+ return false;
+
+ if (input_var->data.explicit_location) {
+ /* assign_varying_locations only cares about finding the
+ * ir_variable at the start of a contiguous location block.
+ *
+ * - For !producer, consumer_inputs_with_locations isn't used.
+ *
+ * - For !consumer, consumer_inputs_with_locations is empty.
+ *
+ * For consumer && producer, if you were trying to set some
+ * ir_variable to the middle of a location block on the other side
+ * of producer/consumer, cross_validate_outputs_to_inputs() should
+ * be link-erroring due to either type mismatch or location
+ * overlaps. If the variables do match up, then they've got a
+ * matching data.location and you only looked at
+ * consumer_inputs_with_locations[var->data.location], not any
+ * following entries for the array/structure.
+ */
+ consumer_inputs_with_locations[input_var->data.location] =
+ input_var;
+ } else if (input_var->get_interface_type() != NULL) {
+ char *const iface_field_name =
+ ralloc_asprintf(mem_ctx, "%s.%s",
+ input_var->get_interface_type()->name,
+ input_var->name);
+ hash_table_insert(consumer_interface_inputs, input_var,
+ iface_field_name);
+ } else {
+ hash_table_insert(consumer_inputs, input_var,
+ ralloc_strdup(mem_ctx, input_var->name));
+ }
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Find a variable from the consumer that "matches" the specified variable
+ *
+ * This function only finds inputs with names that match. There is no
+ * validation (here) that the types, etc. are compatible.
+ */
+ir_variable *
+get_matching_input(void *mem_ctx,
+ const ir_variable *output_var,
+ hash_table *consumer_inputs,
+ hash_table *consumer_interface_inputs,
+ ir_variable *consumer_inputs_with_locations[VARYING_SLOT_MAX])
+{
+ ir_variable *input_var;
+
+ if (output_var->data.explicit_location) {
+ input_var = consumer_inputs_with_locations[output_var->data.location];
+ } else if (output_var->get_interface_type() != NULL) {
+ char *const iface_field_name =
+ ralloc_asprintf(mem_ctx, "%s.%s",
+ output_var->get_interface_type()->name,
+ output_var->name);
+ input_var =
+ (ir_variable *) hash_table_find(consumer_interface_inputs,
+ iface_field_name);
+ } else {
+ input_var =
+ (ir_variable *) hash_table_find(consumer_inputs, output_var->name);
+ }
+
+ return (input_var == NULL || input_var->data.mode != ir_var_shader_in)
+ ? NULL : input_var;
+}
+
+}
+
+static int
+io_variable_cmp(const void *_a, const void *_b)
+{
+ const ir_variable *const a = *(const ir_variable **) _a;
+ const ir_variable *const b = *(const ir_variable **) _b;
+
+ if (a->data.explicit_location && b->data.explicit_location)
+ return b->data.location - a->data.location;
+
+ if (a->data.explicit_location && !b->data.explicit_location)
+ return 1;
+
+ if (!a->data.explicit_location && b->data.explicit_location)
+ return -1;
+
+ return -strcmp(a->name, b->name);
+}
+
+/**
+ * Sort the shader IO variables into canonical order
+ */
+static void
+canonicalize_shader_io(exec_list *ir, enum ir_variable_mode io_mode)
+{
+ ir_variable *var_table[MAX_PROGRAM_OUTPUTS * 4];
+ unsigned num_variables = 0;
+
+ foreach_list(node, ir) {
+ ir_variable *const var = ((ir_instruction *) node)->as_variable();
+
+ if (var == NULL || var->data.mode != io_mode)
+ continue;
+
+ /* If we have already encountered more I/O variables that could
+ * successfully link, bail.
+ */
+ if (num_variables == ARRAY_SIZE(var_table))
+ return;
+
+ var_table[num_variables++] = var;
+ }
+
+ if (num_variables == 0)
+ return;
+
+ /* Sort the list in reverse order (io_variable_cmp handles this). Later
+ * we're going to push the variables on to the IR list as a stack, so we
+ * want the last variable (in canonical order) to be first in the list.
+ */
+ qsort(var_table, num_variables, sizeof(var_table[0]), io_variable_cmp);
+
+ /* Remove the variable from it's current location in the IR, and put it at
+ * the front.
+ */
+ for (unsigned i = 0; i < num_variables; i++) {
+ var_table[i]->remove();
+ ir->push_head(var_table[i]);
+ }
+}
+
/**
* Assign locations for all variables that are produced in one pipeline stage
* (the "producer") and consumed in the next stage (the "consumer").
@@ -1069,8 +1269,6 @@ assign_varying_locations(struct gl_context *ctx,
tfeedback_decl *tfeedback_decls,
unsigned gs_input_vertices)
{
- const unsigned producer_base = VARYING_SLOT_VAR0;
- const unsigned consumer_base = VARYING_SLOT_VAR0;
varying_matches matches(ctx->Const.DisableVaryingPacking,
consumer && consumer->Stage == MESA_SHADER_FRAGMENT);
hash_table *tfeedback_candidates
@@ -1079,67 +1277,85 @@ assign_varying_locations(struct gl_context *ctx,
= hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare);
hash_table *consumer_interface_inputs
= hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare);
+ ir_variable *consumer_inputs_with_locations[VARYING_SLOT_MAX] = {
+ NULL,
+ };
- /* Operate in a total of three passes.
+ /* Operate in a total of four passes.
+ *
+ * 1. Sort inputs / outputs into a canonical order. This is necessary so
+ * that inputs / outputs of separable shaders will be assigned
+ * predictable locations regardless of the order in which declarations
+ * appeared in the shader source.
*
- * 1. Assign locations for any matching inputs and outputs.
+ * 2. Assign locations for any matching inputs and outputs.
*
- * 2. Mark output variables in the producer that do not have locations as
+ * 3. Mark output variables in the producer that do not have locations as
* not being outputs. This lets the optimizer eliminate them.
*
- * 3. Mark input variables in the consumer that do not have locations as
+ * 4. Mark input variables in the consumer that do not have locations as
* not being inputs. This lets the optimizer eliminate them.
*/
+ if (consumer)
+ canonicalize_shader_io(consumer->ir, ir_var_shader_in);
+
+ if (producer)
+ canonicalize_shader_io(producer->ir, ir_var_shader_out);
+
+ if (consumer
+ && !linker::populate_consumer_input_sets(mem_ctx,
+ consumer->ir,
+ consumer_inputs,
+ consumer_interface_inputs,
+ consumer_inputs_with_locations)) {
+ assert(!"populate_consumer_input_sets failed");
+ hash_table_dtor(tfeedback_candidates);
+ hash_table_dtor(consumer_inputs);
+ hash_table_dtor(consumer_interface_inputs);
+ return false;
+ }
- if (consumer) {
- foreach_list(node, consumer->ir) {
- ir_variable *const input_var =
+ if (producer) {
+ foreach_list(node, producer->ir) {
+ ir_variable *const output_var =
((ir_instruction *) node)->as_variable();
- if ((input_var != NULL) && (input_var->data.mode == ir_var_shader_in)) {
- if (input_var->get_interface_type() != NULL) {
- char *const iface_field_name =
- ralloc_asprintf(mem_ctx, "%s.%s",
- input_var->get_interface_type()->name,
- input_var->name);
- hash_table_insert(consumer_interface_inputs, input_var,
- iface_field_name);
- } else {
- hash_table_insert(consumer_inputs, input_var,
- ralloc_strdup(mem_ctx, input_var->name));
- }
- }
- }
- }
-
- foreach_list(node, producer->ir) {
- ir_variable *const output_var = ((ir_instruction *) node)->as_variable();
+ if ((output_var == NULL) ||
+ (output_var->data.mode != ir_var_shader_out))
+ continue;
- if ((output_var == NULL) || (output_var->data.mode != ir_var_shader_out))
- continue;
+ tfeedback_candidate_generator g(mem_ctx, tfeedback_candidates);
+ g.process(output_var);
- tfeedback_candidate_generator g(mem_ctx, tfeedback_candidates);
- g.process(output_var);
-
- ir_variable *input_var;
- if (output_var->get_interface_type() != NULL) {
- char *const iface_field_name =
- ralloc_asprintf(mem_ctx, "%s.%s",
- output_var->get_interface_type()->name,
- output_var->name);
- input_var =
- (ir_variable *) hash_table_find(consumer_interface_inputs,
- iface_field_name);
- } else {
- input_var =
- (ir_variable *) hash_table_find(consumer_inputs, output_var->name);
+ ir_variable *const input_var =
+ linker::get_matching_input(mem_ctx, output_var, consumer_inputs,
+ consumer_interface_inputs,
+ consumer_inputs_with_locations);
+
+ /* If a matching input variable was found, add this ouptut (and the
+ * input) to the set. If this is a separable program and there is no
+ * consumer stage, add the output.
+ */
+ if (input_var || (prog->SeparateShader && consumer == NULL)) {
+ matches.record(output_var, input_var);
+ }
}
+ } else {
+ /* If there's no producer stage, then this must be a separable program.
+ * For example, we may have a program that has just a fragment shader.
+ * Later this program will be used with some arbitrary vertex (or
+ * geometry) shader program. This means that locations must be assigned
+ * for all the inputs.
+ */
+ foreach_list(node, consumer->ir) {
+ ir_variable *const input_var =
+ ((ir_instruction *) node)->as_variable();
- if (input_var && input_var->data.mode != ir_var_shader_in)
- input_var = NULL;
+ if ((input_var == NULL) ||
+ (input_var->data.mode != ir_var_shader_in))
+ continue;
- if (input_var) {
- matches.record(output_var, input_var);
+ matches.record(NULL, input_var);
}
}
@@ -1162,7 +1378,7 @@ assign_varying_locations(struct gl_context *ctx,
}
const unsigned slots_used = matches.assign_locations();
- matches.store_locations(producer_base, consumer_base);
+ matches.store_locations();
for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
if (!tfeedback_decls[i].is_varying())
@@ -1187,15 +1403,17 @@ assign_varying_locations(struct gl_context *ctx,
*/
assert(!ctx->Extensions.EXT_transform_feedback);
} else {
- lower_packed_varyings(mem_ctx, producer_base, slots_used,
- ir_var_shader_out, 0, producer);
+ if (producer) {
+ lower_packed_varyings(mem_ctx, slots_used, ir_var_shader_out,
+ 0, producer);
+ }
if (consumer) {
- lower_packed_varyings(mem_ctx, consumer_base, slots_used,
- ir_var_shader_in, gs_input_vertices, consumer);
+ lower_packed_varyings(mem_ctx, slots_used, ir_var_shader_in,
+ gs_input_vertices, consumer);
}
}
- if (consumer) {
+ if (consumer && producer) {
foreach_list(node, consumer->ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp
index c2f7f4863..a43d23082 100644
--- a/mesalib/src/glsl/linker.cpp
+++ b/mesalib/src/glsl/linker.cpp
@@ -1195,6 +1195,83 @@ private:
};
/**
+ * Performs the cross-validation of layout qualifiers specified in
+ * redeclaration of gl_FragCoord for the attached fragment shaders,
+ * and propagates them to the linked FS and linked shader program.
+ */
+static void
+link_fs_input_layout_qualifiers(struct gl_shader_program *prog,
+ struct gl_shader *linked_shader,
+ struct gl_shader **shader_list,
+ unsigned num_shaders)
+{
+ linked_shader->redeclares_gl_fragcoord = false;
+ linked_shader->uses_gl_fragcoord = false;
+ linked_shader->origin_upper_left = false;
+ linked_shader->pixel_center_integer = false;
+
+ if (linked_shader->Stage != MESA_SHADER_FRAGMENT ||
+ (prog->Version < 150 && !prog->ARB_fragment_coord_conventions_enable))
+ return;
+
+ for (unsigned i = 0; i < num_shaders; i++) {
+ struct gl_shader *shader = shader_list[i];
+ /* From the GLSL 1.50 spec, page 39:
+ *
+ * "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->redeclares_gl_fragcoord
+ && !linked_shader->redeclares_gl_fragcoord
+ && linked_shader->uses_gl_fragcoord
+ && (shader->origin_upper_left
+ || shader->pixel_center_integer))) {
+ linker_error(prog, "fragment shader defined with conflicting "
+ "layout qualifiers for gl_FragCoord\n");
+ }
+
+ /* From the GLSL 1.50 spec, page 39:
+ *
+ * "All redeclarations of gl_FragCoord in all fragment shaders in a
+ * single program must have the same set of qualifiers."
+ */
+ if (linked_shader->redeclares_gl_fragcoord && shader->redeclares_gl_fragcoord
+ && (shader->origin_upper_left != linked_shader->origin_upper_left
+ || shader->pixel_center_integer != linked_shader->pixel_center_integer)) {
+ linker_error(prog, "fragment shader defined with conflicting "
+ "layout qualifiers for gl_FragCoord\n");
+ }
+
+ /* Update the linked shader state.  Note that uses_gl_fragcoord should
+ * accumulate the results.  The other values should replace.  If there
+ * are multiple redeclarations, all the fields except uses_gl_fragcoord
+ * are already known to be the same.
+ */
+ if (shader->redeclares_gl_fragcoord || shader->uses_gl_fragcoord) {
+ linked_shader->redeclares_gl_fragcoord =
+ shader->redeclares_gl_fragcoord;
+ linked_shader->uses_gl_fragcoord = linked_shader->uses_gl_fragcoord
+ || shader->uses_gl_fragcoord;
+ linked_shader->origin_upper_left = shader->origin_upper_left;
+ linked_shader->pixel_center_integer = shader->pixel_center_integer;
+ }
+ }
+}
+
+/**
* Performs the cross-validation of geometry shader max_vertices and
* primitive type layout qualifiers for the attached geometry shaders,
* and propagates them to the linked GS and linked shader program.
@@ -1471,6 +1548,7 @@ link_intrastage_shaders(void *mem_ctx,
linked->NumUniformBlocks = num_uniform_blocks;
ralloc_steal(linked, linked->UniformBlocks);
+ link_fs_input_layout_qualifiers(prog, linked, shader_list, num_shaders);
link_gs_inout_layout_qualifiers(prog, linked, shader_list, num_shaders);
link_cs_input_layout_qualifiers(prog, linked, shader_list, num_shaders);
@@ -1798,10 +1876,12 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
* active attribute array, both of which require multiple
* contiguous generic attributes."
*
- * Previous versions of the spec contain similar language but omit
- * the bit about attribute arrays.
+ * I think above text prohibits the aliasing of explicit and
+ * automatic assignments. But, aliasing is allowed in manual
+ * assignments of attribute locations. See below comments for
+ * the details.
*
- * Page 61 of the OpenGL 4.0 spec also says:
+ * From OpenGL 4.0 spec, page 61:
*
* "It is possible for an application to bind more than one
* attribute name to the same location. This is referred to as
@@ -1814,29 +1894,84 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
* but implementations are not required to generate an error
* in this case."
*
- * These two paragraphs are either somewhat contradictory, or I
- * don't fully understand one or both of them.
- */
- /* FINISHME: The code as currently written does not support
- * FINISHME: attribute location aliasing (see comment above).
+ * From GLSL 4.30 spec, page 54:
+ *
+ * "A program will fail to link if any two non-vertex shader
+ * input variables are assigned to the same location. For
+ * vertex shaders, multiple input variables may be assigned
+ * to the same location using either layout qualifiers or via
+ * the OpenGL API. However, such aliasing is intended only to
+ * support vertex shaders where each execution path accesses
+ * at most one input per each location. Implementations are
+ * permitted, but not required, to generate link-time errors
+ * if they detect that every path through the vertex shader
+ * executable accesses multiple inputs assigned to any single
+ * location. For all shader types, a program will fail to link
+ * if explicit location assignments leave the linker unable
+ * to find space for other variables without explicit
+ * assignments."
+ *
+ * From OpenGL ES 3.0 spec, page 56:
+ *
+ * "Binding more than one attribute name to the same location
+ * is referred to as aliasing, and is not permitted in OpenGL
+ * ES Shading Language 3.00 vertex shaders. LinkProgram will
+ * fail when this condition exists. However, aliasing is
+ * possible in OpenGL ES Shading Language 1.00 vertex shaders.
+ * This will only work if only one of the aliased attributes
+ * is active in the executable program, or if no path through
+ * the shader consumes more than one attribute of a set of
+ * attributes aliased to the same location. A link error can
+ * occur if the linker determines that every path through the
+ * shader consumes multiple aliased attributes, but implemen-
+ * tations are not required to generate an error in this case."
+ *
+ * After looking at above references from OpenGL, OpenGL ES and
+ * GLSL specifications, we allow aliasing of vertex input variables
+ * in: OpenGL 2.0 (and above) and OpenGL ES 2.0.
+ *
+ * NOTE: This is not required by the spec but its worth mentioning
+ * here that we're not doing anything to make sure that no path
+ * through the vertex shader executable accesses multiple inputs
+ * assigned to any single location.
*/
+
/* Mask representing the contiguous slots that will be used by
* this attribute.
*/
const unsigned attr = var->data.location - generic_base;
const unsigned use_mask = (1 << slots) - 1;
+ const char *const string = (target_index == MESA_SHADER_VERTEX)
+ ? "vertex shader input" : "fragment shader output";
+
+ /* Generate a link error if the requested locations for this
+ * attribute exceed the maximum allowed attribute location.
+ */
+ if (attr + slots > max_index) {
+ linker_error(prog,
+ "insufficient contiguous locations "
+ "available for %s `%s' %d %d %d", string,
+ var->name, used_locations, use_mask, attr);
+ return false;
+ }
/* Generate a link error if the set of bits requested for this
* attribute overlaps any previously allocated bits.
*/
if ((~(use_mask << attr) & used_locations) != used_locations) {
- const char *const string = (target_index == MESA_SHADER_VERTEX)
- ? "vertex shader input" : "fragment shader output";
- linker_error(prog,
- "insufficient contiguous locations "
- "available for %s `%s' %d %d %d", string,
- var->name, used_locations, use_mask, attr);
- return false;
+ if (target_index == MESA_SHADER_FRAGMENT ||
+ (prog->IsES && prog->Version >= 300)) {
+ linker_error(prog,
+ "overlapping location is assigned "
+ "to %s `%s' %d %d %d\n", string,
+ var->name, used_locations, use_mask, attr);
+ return false;
+ } else {
+ linker_warning(prog,
+ "overlapping location is assigned "
+ "to %s `%s' %d %d %d\n", string,
+ var->name, used_locations, use_mask, attr);
+ }
}
used_locations |= (use_mask << attr);
@@ -2115,6 +2250,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
ralloc_free(prog->AtomicBuffers);
prog->AtomicBuffers = NULL;
prog->NumAtomicBuffers = 0;
+ prog->ARB_fragment_coord_conventions_enable = false;
/* Separate the shaders into groups based on their type.
*/
@@ -2141,6 +2277,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
goto done;
}
+ prog->ARB_fragment_coord_conventions_enable |=
+ prog->Shaders[i]->ARB_fragment_coord_conventions_enable;
+
gl_shader_stage shader_type = prog->Shaders[i]->Stage;
shader_list[shader_type][num_shaders[shader_type]] = prog->Shaders[i];
num_shaders[shader_type]++;
@@ -2161,7 +2300,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
/* Geometry shaders have to be linked with vertex shaders.
*/
if (num_shaders[MESA_SHADER_GEOMETRY] > 0 &&
- num_shaders[MESA_SHADER_VERTEX] == 0) {
+ num_shaders[MESA_SHADER_VERTEX] == 0 &&
+ !prog->SeparateShader) {
linker_error(prog, "Geometry shader must be linked with "
"vertex shader\n");
goto done;
@@ -2363,7 +2503,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
if (last >= 0 && last < MESA_SHADER_FRAGMENT) {
gl_shader *const sh = prog->_LinkedShaders[last];
- if (num_tfeedback_decls != 0) {
+ if (num_tfeedback_decls != 0 || prog->SeparateShader) {
/* There was no fragment shader, but we still have to assign varying
* locations for use by transform feedback.
*/
@@ -2377,7 +2517,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
do_dead_builtin_varyings(ctx, sh, NULL,
num_tfeedback_decls, tfeedback_decls);
- demote_shader_inputs_and_outputs(sh, ir_var_shader_out);
+ if (!prog->SeparateShader)
+ demote_shader_inputs_and_outputs(sh, ir_var_shader_out);
/* Eliminate code that is now dead due to unused outputs being demoted.
*/
@@ -2392,7 +2533,16 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
do_dead_builtin_varyings(ctx, NULL, sh,
num_tfeedback_decls, tfeedback_decls);
- demote_shader_inputs_and_outputs(sh, ir_var_shader_in);
+ if (prog->SeparateShader) {
+ if (!assign_varying_locations(ctx, mem_ctx, prog,
+ NULL /* producer */,
+ sh /* consumer */,
+ 0 /* num_tfeedback_decls */,
+ NULL /* tfeedback_decls */,
+ 0 /* gs_input_vertices */))
+ goto done;
+ } else
+ demote_shader_inputs_and_outputs(sh, ir_var_shader_in);
while (do_dead_code(sh->ir, false))
;
@@ -2457,7 +2607,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
* fragment shader) is absent. So, the extension shouldn't change the
* behavior specified in GLSL specification.
*/
- if (!prog->InternalSeparateShader && ctx->API == API_OPENGLES2) {
+ if (!prog->SeparateShader && ctx->API == API_OPENGLES2) {
if (prog->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
linker_error(prog, "program lacks a vertex shader\n");
} else if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) {
diff --git a/mesalib/src/glsl/lower_instructions.cpp b/mesalib/src/glsl/lower_instructions.cpp
index 49316d002..176070c87 100644
--- a/mesalib/src/glsl/lower_instructions.cpp
+++ b/mesalib/src/glsl/lower_instructions.cpp
@@ -39,6 +39,8 @@
* - MOD_TO_FRACT
* - LDEXP_TO_ARITH
* - BITFIELD_INSERT_TO_BFM_BFI
+ * - CARRY_TO_ARITH
+ * - BORROW_TO_ARITH
*
* SUB_TO_ADD_NEG:
* ---------------
@@ -94,6 +96,14 @@
* Many GPUs implement the bitfieldInsert() built-in from ARB_gpu_shader_5
* with a pair of instructions.
*
+ * CARRY_TO_ARITH:
+ * ---------------
+ * Converts ir_carry into (x + y) < x.
+ *
+ * BORROW_TO_ARITH:
+ * ----------------
+ * Converts ir_borrow into (x < y).
+ *
*/
#include "main/core.h" /* for M_LOG2E */
@@ -127,6 +137,8 @@ private:
void log_to_log2(ir_expression *);
void bitfield_insert_to_bfm_bfi(ir_expression *);
void ldexp_to_arith(ir_expression *);
+ void carry_to_arith(ir_expression *);
+ void borrow_to_arith(ir_expression *);
};
} /* anonymous namespace */
@@ -436,6 +448,42 @@ lower_instructions_visitor::ldexp_to_arith(ir_expression *ir)
this->progress = true;
}
+void
+lower_instructions_visitor::carry_to_arith(ir_expression *ir)
+{
+ /* Translates
+ * ir_binop_carry x y
+ * into
+ * sum = ir_binop_add x y
+ * bcarry = ir_binop_less sum x
+ * carry = ir_unop_b2i bcarry
+ */
+
+ ir_rvalue *x_clone = ir->operands[0]->clone(ir, NULL);
+ ir->operation = ir_unop_i2u;
+ ir->operands[0] = b2i(less(add(ir->operands[0], ir->operands[1]), x_clone));
+ ir->operands[1] = NULL;
+
+ this->progress = true;
+}
+
+void
+lower_instructions_visitor::borrow_to_arith(ir_expression *ir)
+{
+ /* Translates
+ * ir_binop_borrow x y
+ * into
+ * bcarry = ir_binop_less x y
+ * carry = ir_unop_b2i bcarry
+ */
+
+ ir->operation = ir_unop_i2u;
+ ir->operands[0] = b2i(less(ir->operands[0], ir->operands[1]));
+ ir->operands[1] = NULL;
+
+ this->progress = true;
+}
+
ir_visitor_status
lower_instructions_visitor::visit_leave(ir_expression *ir)
{
@@ -482,6 +530,16 @@ lower_instructions_visitor::visit_leave(ir_expression *ir)
ldexp_to_arith(ir);
break;
+ case ir_binop_carry:
+ if (lowering(CARRY_TO_ARITH))
+ carry_to_arith(ir);
+ break;
+
+ case ir_binop_borrow:
+ if (lowering(BORROW_TO_ARITH))
+ borrow_to_arith(ir);
+ break;
+
default:
return visit_continue;
}
diff --git a/mesalib/src/glsl/lower_packed_varyings.cpp b/mesalib/src/glsl/lower_packed_varyings.cpp
index 8c1b8850b..e8654748f 100644
--- a/mesalib/src/glsl/lower_packed_varyings.cpp
+++ b/mesalib/src/glsl/lower_packed_varyings.cpp
@@ -160,8 +160,7 @@ namespace {
class lower_packed_varyings_visitor
{
public:
- lower_packed_varyings_visitor(void *mem_ctx, unsigned location_base,
- unsigned locations_used,
+ lower_packed_varyings_visitor(void *mem_ctx, unsigned locations_used,
ir_variable_mode mode,
unsigned gs_input_vertices,
exec_list *out_instructions);
@@ -190,18 +189,10 @@ private:
void * const mem_ctx;
/**
- * Location representing the first generic varying slot for this shader
- * stage (e.g. VARYING_SLOT_VAR0 if we are packing vertex shader outputs).
- * Varyings whose location is less than this value are assumed to
- * correspond to special fixed function hardware, so they are not lowered.
- */
- const unsigned location_base;
-
- /**
* Number of generic varying slots which are used by this shader. This is
* used to allocate temporary intermediate data structures. If any varying
* used by this shader has a location greater than or equal to
- * location_base + locations_used, an assertion will fire.
+ * VARYING_SLOT_VAR0 + locations_used, an assertion will fire.
*/
const unsigned locations_used;
@@ -235,11 +226,9 @@ private:
} /* anonymous namespace */
lower_packed_varyings_visitor::lower_packed_varyings_visitor(
- void *mem_ctx, unsigned location_base, unsigned locations_used,
- ir_variable_mode mode, unsigned gs_input_vertices,
- exec_list *out_instructions)
+ void *mem_ctx, unsigned locations_used, ir_variable_mode mode,
+ unsigned gs_input_vertices, exec_list *out_instructions)
: mem_ctx(mem_ctx),
- location_base(location_base),
locations_used(locations_used),
packed_varyings((ir_variable **)
rzalloc_array_size(mem_ctx, sizeof(*packed_varyings),
@@ -259,7 +248,7 @@ lower_packed_varyings_visitor::run(exec_list *instructions)
continue;
if (var->data.mode != this->mode ||
- var->data.location < (int) this->location_base ||
+ var->data.location < VARYING_SLOT_VAR0 ||
!this->needs_lowering(var))
continue;
@@ -542,7 +531,7 @@ lower_packed_varyings_visitor::get_packed_varying_deref(
unsigned location, ir_variable *unpacked_var, const char *name,
unsigned vertex_index)
{
- unsigned slot = location - this->location_base;
+ unsigned slot = location - VARYING_SLOT_VAR0;
assert(slot < locations_used);
if (this->packed_varyings[slot] == NULL) {
char *packed_name = ralloc_asprintf(this->mem_ctx, "packed:%s", name);
@@ -595,7 +584,12 @@ lower_packed_varyings_visitor::get_packed_varying_deref(
bool
lower_packed_varyings_visitor::needs_lowering(ir_variable *var)
{
- /* Things composed of vec4's don't need lowering. Everything else does. */
+ /* Things composed of vec4's and varyings with explicitly assigned
+ * locations don't need lowering. Everything else does.
+ */
+ if (var->data.explicit_location)
+ return false;
+
const glsl_type *type = var->type;
if (this->gs_input_vertices != 0) {
assert(type->is_array());
@@ -654,9 +648,9 @@ lower_packed_varyings_gs_splicer::visit(ir_emit_vertex *ev)
void
-lower_packed_varyings(void *mem_ctx, unsigned location_base,
- unsigned locations_used, ir_variable_mode mode,
- unsigned gs_input_vertices, gl_shader *shader)
+lower_packed_varyings(void *mem_ctx, unsigned locations_used,
+ ir_variable_mode mode, unsigned gs_input_vertices,
+ gl_shader *shader)
{
exec_list *instructions = shader->ir;
ir_function *main_func = shader->symbols->get_function("main");
@@ -664,8 +658,7 @@ lower_packed_varyings(void *mem_ctx, unsigned location_base,
ir_function_signature *main_func_sig
= main_func->matching_signature(NULL, &void_parameters);
exec_list new_instructions;
- lower_packed_varyings_visitor visitor(mem_ctx, location_base,
- locations_used, mode,
+ lower_packed_varyings_visitor visitor(mem_ctx, locations_used, mode,
gs_input_vertices, &new_instructions);
visitor.run(instructions);
if (mode == ir_var_shader_out) {
diff --git a/mesalib/src/glsl/main.cpp b/mesalib/src/glsl/main.cpp
index 4ae8f0987..a4452e023 100644
--- a/mesalib/src/glsl/main.cpp
+++ b/mesalib/src/glsl/main.cpp
@@ -40,6 +40,12 @@
static int glsl_version = 330;
+extern "C" void
+_mesa_error_no_memory(const char *caller)
+{
+ fprintf(stderr, "Mesa error: out of memory in %s", caller);
+}
+
static void
initialize_context(struct gl_context *ctx, gl_api api)
{
diff --git a/mesalib/src/glsl/opt_dead_builtin_varyings.cpp b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp
index c2a306e7b..6612592aa 100644
--- a/mesalib/src/glsl/opt_dead_builtin_varyings.cpp
+++ b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp
@@ -518,14 +518,9 @@ do_dead_builtin_varyings(struct gl_context *ctx,
/* Lowering of built-in varyings has no effect with the core context and
* GLES2, because they are not available there.
- *
- * EXT_separate_shader_objects doesn't allow this optimization,
- * because a program object can be bound partially (e.g. only one
- * stage of a program object can be bound).
*/
if (ctx->API == API_OPENGL_CORE ||
- ctx->API == API_OPENGLES2 ||
- ctx->Extensions.EXT_separate_shader_objects) {
+ ctx->API == API_OPENGLES2) {
return;
}