summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancisco Jerez <currojerez@riseup.net>2016-07-18 18:56:21 -0700
committerFrancisco Jerez <currojerez@riseup.net>2016-07-19 14:41:37 -0700
commitc2f81b59eb5b416d6050ddd6c1896180a1763ec5 (patch)
tree801b017d4d8aa909e806d405714ef2b925669a88
parent3529e325ff989d4b825f551184d1542060e21420 (diff)
-rw-r--r--framework/test/shader_test.py9
-rw-r--r--registry/gl.xml9
-rw-r--r--tests/shaders/built-in-constants.c34
-rw-r--r--tests/shaders/parser_utils.c214
-rw-r--r--tests/shaders/parser_utils.h173
-rw-r--r--tests/shaders/shader_runner.c1120
-rw-r--r--tests/spec/arb_fragment_layer_viewport/layer-gs-writes-in-range.shader_test2
-rw-r--r--tests/spec/arb_fragment_layer_viewport/layer-gs-writes-out-of-range.shader_test2
-rw-r--r--tests/spec/arb_fragment_layer_viewport/viewport-gs-writes-in-range.shader_test2
-rw-r--r--tests/spec/arb_fragment_layer_viewport/viewport-gs-writes-out-of-range.shader_test2
-rw-r--r--tests/spec/arb_shader_image_load_store/shader-mem-barrier.c2
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/compiler/negative-gl_LastFragData-gles3.frag15
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/compiler/negative-gl_LastFragData-write-gles2.frag13
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/compiler/negative-inout-fragment-output-gles2.frag15
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/compiler/negative-inout-gl_FragDepth-gles3.frag15
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/compiler/negative-inout-vertex-output-gles3.vert14
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/execution/discard-gles3.shader_test50
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/execution/discard-ms8-gles3.shader_test55
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/execution/integer-gles3.shader_test47
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/execution/mrt-gles2.shader_test42
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/execution/mrt-gles3.shader_test47
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/execution/ms16-gles3.shader_test53
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/execution/ms2-gles3.shader_test53
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/execution/ms2-integer-gles3.shader_test52
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/execution/ms8-gles3.shader_test53
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/execution/ms8-integer-gles3.shader_test52
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/execution/nonuniform-gles2.shader_test45
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/execution/nonuniform-gles3.shader_test48
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/execution/overwrite-gles3.shader_test48
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/execution/redeclared-highp-gles2.shader_test46
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/execution/redeclared-lowp-gles2.shader_test46
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/execution/redeclared-mediump-gles2.shader_test46
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/execution/simple-gles3.shader_test31
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/execution/single-2d-level-gles3.shader_test63
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/execution/single-2darray-layer-gles3.shader_test63
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/execution/single-3d-layer-gles3.shader_test63
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/execution/single-cubemap-layer-gles3.shader_test63
-rw-r--r--tests/spec/ext_shader_framebuffer_fetch/execution/texture-gles3.shader_test38
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/coherent-1d-gl32.shader_test48
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/coherent-layered-1darray-gl32.shader_test65
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/coherent-layered-2darray-gl32.shader_test65
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/coherent-layered-cubemap-gl32.shader_test73
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-1d-gl32.shader_test50
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-discard-gles3.shader_test51
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-discard-ms2-gles3.shader_test56
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-discard-ms8-gles3.shader_test56
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-integer-gles3.shader_test49
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-layered-1darray-gl32.shader_test67
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-layered-2darray-gl32.shader_test67
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-layered-cubemap-gl32.shader_test75
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-mrt-gles2.shader_test44
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-mrt-gles3.shader_test49
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-ms16-gles3.shader_test55
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-ms2-gles3.shader_test55
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-ms2-integer-gles3.shader_test54
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-ms8-gles3.shader_test55
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-ms8-integer-gles3.shader_test54
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-nonuniform-gles2.shader_test47
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-nonuniform-gles3.shader_test50
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-overwrite-gles3.shader_test50
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-redeclared-highp-gles2.shader_test48
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-redeclared-lowp-gles2.shader_test48
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-redeclared-mediump-gles2.shader_test48
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-simple-gles3.shader_test33
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-single-2d-level-gles3.shader_test71
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-single-2darray-layer-gles3.shader_test71
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-single-3d-layer-gles3.shader_test71
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-single-cubemap-layer-gles3.shader_test71
-rw-r--r--tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-texture-gles3.shader_test40
69 files changed, 3919 insertions, 562 deletions
diff --git a/framework/test/shader_test.py b/framework/test/shader_test.py
index 4fb33a081..26a1d93ff 100644
--- a/framework/test/shader_test.py
+++ b/framework/test/shader_test.py
@@ -95,15 +95,10 @@ class ShaderTest(FastSkipMixin, PiglitBaseTest):
for line in lines:
line = line.strip()
if line.startswith('GL ES'):
- if line.endswith('3.0'):
- prog = 'shader_runner_gles3'
- elif line.endswith('2.0'):
+ if line.endswith('2.0'):
prog = 'shader_runner_gles2'
- # If we don't set gles2 or gles3 continue the loop,
- # probably htting the exception in the for/else
else:
- raise exceptions.PiglitFatalError(
- "In File {}: No GL ES version set".format(filename))
+ prog = 'shader_runner_gles3'
break
elif line.startswith('[') or self._is_gl.match(line):
# In the event that we reach the end of the config black
diff --git a/registry/gl.xml b/registry/gl.xml
index c754ec463..cf198ad23 100644
--- a/registry/gl.xml
+++ b/registry/gl.xml
@@ -9300,6 +9300,10 @@ typedef unsigned int GLhandleARB;
<alias name="glBlendBarrier"/>
</command>
<command>
+ <proto>void <name>glBlendBarrierMESA</name></proto>
+ <alias name="glBlendBarrier"/>
+ </command>
+ <command>
<proto>void <name>glBlendColor</name></proto>
<param group="ColorF"><ptype>GLfloat</ptype> <name>red</name></param>
<param group="ColorF"><ptype>GLfloat</ptype> <name>green</name></param>
@@ -43219,6 +43223,11 @@ typedef unsigned int GLhandleARB;
<command name="glResizeBuffersMESA"/>
</require>
</extension>
+ <extension name="GL_MESA_shader_framebuffer_fetch_non_coherent" supported="glcore|gles2">
+ <require>
+ <command name="glBlendBarrierMESA"/>
+ </require>
+ </extension>
<extension name="GL_MESA_window_pos" supported="gl">
<require>
<command name="glWindowPos2dMESA"/>
diff --git a/tests/shaders/built-in-constants.c b/tests/shaders/built-in-constants.c
index b1951fb0b..e3c7bac81 100644
--- a/tests/shaders/built-in-constants.c
+++ b/tests/shaders/built-in-constants.c
@@ -230,7 +230,7 @@ parse_file(const char *filename)
required_glsl_version_string[len] = '\0';
required_glsl_version = strtol(line, &endptr, 10);
- line = (char *) eat_whitespace(endptr);
+ parse_whitespace(endptr, (const char **)&line);
es_shader = strncmp("es\n", line, 3) == 0;
if (required_glsl_version <= 0 ||
@@ -289,13 +289,13 @@ parse_file(const char *filename)
}
while (line[0] != '\0') {
- line = (char *) eat_whitespace(line);
+ if (!(parse_word(line, (const char **)&line,
+ (const char **)&endptr) &&
+ (parse_str(line, "gl_Max", NULL) ||
+ parse_str(line, "gl_Min", NULL)))) {
+ char bad_name[80] = "";
+ parse_word_copy(line, bad_name, sizeof(bad_name), NULL);
- if (string_match("gl_Max", line) != 0
- && string_match("gl_Min", line) != 0) {
- char bad_name[80];
-
- strcpy_to_space(bad_name, line);
fprintf(stderr,
"Invalid built-in constant name \"%s\".\n",
bad_name);
@@ -303,18 +303,14 @@ parse_file(const char *filename)
}
tests[num_tests].name = line;
+ *endptr = 0;
+ line = endptr + 1;
- line = (char *) eat_text(line);
- line[0] = '\0';
- line++;
-
- line = (char *) eat_whitespace(line);
-
- tests[num_tests].minimum = strtol(line, &endptr, 0);
- if (endptr == line) {
- char bad_number[80];
-
- strcpy_to_space(bad_number, line);
+ if (!parse_int(line, &tests[num_tests].minimum,
+ (const char **)&endptr)) {
+ char bad_number[80] = "";
+ parse_word_copy(line, bad_number, sizeof(bad_number),
+ NULL);
fprintf(stderr,
"Invalid built-in constant value \"%s\".\n",
@@ -519,7 +515,7 @@ piglit_init(int argc, char **argv)
for (i = 0; i < num_tests; i++) {
bool subtest_pass = true;
const char *comparitor =
- string_match("gl_Min", tests[i].name) ? "<=" : ">=";
+ parse_str(tests[i].name, "gl_Min", NULL) ? "<=" : ">=";
/* Generate the uniform declaration for the test. This will
* be shared by all shader stages.
diff --git a/tests/shaders/parser_utils.c b/tests/shaders/parser_utils.c
index e534a4c44..f75a8db0b 100644
--- a/tests/shaders/parser_utils.c
+++ b/tests/shaders/parser_utils.c
@@ -1,5 +1,5 @@
/*
- * Copyright © 2010 Intel Corporation
+ * Copyright © 2016 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -24,48 +24,206 @@
#include <ctype.h>
#include "parser_utils.h"
-/**
- * Skip over whitespace upto the end of line
- */
-const char *
-eat_whitespace(const char *src)
+bool
+parse_whitespace(const char *s, const char **rest)
{
- while (isspace((int) *src) && (*src != '\n'))
- src++;
+ const char *end = s;
+ for (; *end && *end != '\n' && isspace(*end); end++);
- return src;
+ if (rest)
+ *rest = end;
+
+ return end != s;
}
+bool
+parse_str(const char *s, const char *lit, const char **rest)
+{
+ const char *t;
+ parse_whitespace(s, &t);
+ const bool ret = strncmp(t, lit, strlen(lit)) == 0;
-/**
- * Skip over non-whitespace upto the end of line
- */
-const char *
-eat_text(const char *src)
+ if (rest)
+ *rest = (ret ? t + strlen(lit) : s);
+
+ return ret;
+}
+
+unsigned
+parse_ints(const char *s, int *i, unsigned n, const char **rest)
{
- while (!isspace((int) *src) && (*src != '\0'))
- src++;
+ const char *end = s;
+ unsigned j;
+
+ for (j = 0; j < n; j++) {
+ i[j] = strtoll(s = end, (char **)&end, 0);
+ if (s == end)
+ break;
+ }
+
+ if (rest)
+ *rest = end;
- return src;
+ return j;
}
+unsigned
+parse_uints(const char *s, unsigned *u, unsigned n, const char **rest)
+{
+ const char *end = s;
+ unsigned j;
+
+ for (j = 0; j < n; j++) {
+ u[j] = strtoul(s = end, (char **)&end, 0);
+ if (s == end)
+ break;
+ }
+
+ if (rest)
+ *rest = end;
+
+ return j;
+}
+
+unsigned
+parse_floats(const char *s, float *f, unsigned n, const char **rest)
+{
+ const char *end = s;
+ unsigned j;
+
+ for (j = 0; j < n; j++) {
+ f[j] = strtof_hex(s = end, (char **)&end);
+ if (s == end)
+ break;
+ }
+
+ if (rest)
+ *rest = end;
+
+ return j;
+}
+
+unsigned
+parse_doubles(const char *s, double *d, unsigned n, const char **rest)
+{
+ const char *end = s;
+ unsigned j;
+
+ for (j = 0; j < n; j++) {
+ d[j] = strtod_hex(s = end, (char **)&end);
+ if (s == end)
+ break;
+ }
+
+ if (rest)
+ *rest = end;
+
+ return j;
+}
bool
-string_match(const char *string, const char *line)
+parse_word(const char *s, const char **t, const char **rest)
{
- return (strncmp(string, line, strlen(string)) == 0);
+ parse_whitespace(s, t);
+
+ const char *end = *t;
+ for (; *end && !isspace(*end); end++);
+
+ if (rest)
+ *rest = (*t != end ? end : s);
+
+ return *t != end;
}
+bool
+parse_word_copy(const char *s, char *t, unsigned n, const char **rest)
+{
+ const char *start, *end;
+ const bool ret = parse_word(s, &start, &end) && end - start < n;
-/**
- * Copy a string until either whitespace or the end of the string
- */
-const char *
-strcpy_to_space(char *dst, const char *src)
+ if (ret) {
+ memcpy(t, start, end - start);
+ t[end - start] = 0;
+ }
+ if (rest)
+ *rest = (ret ? end : s);
+
+ return ret;
+}
+
+bool
+parse_enum_gl(const char *s, GLenum *e, const char **rest)
+{
+ char name[512];
+ const bool ret = parse_word_copy(s, name, sizeof(name), rest);
+ *e = (ret ? piglit_get_gl_enum_from_name(name) : GL_NONE);
+ return ret;
+}
+
+bool
+parse_enum_tab(const struct string_to_enum *tab,
+ const char *s, unsigned *e, const char **rest)
{
- while (!isspace((int) *src) && (*src != '\0'))
- *(dst++) = *(src++);
+ const char *end = s;
+ bool ret = parse_word(s, &s, &end);
+ unsigned i = 0;
+
+ if (ret) {
+ for (i = 0; tab[i].name; i++) {
+ if (!strncmp(tab[i].name, s, end - s) &&
+ !tab[i].name[end - s])
+ break;
+ }
+
+ *e = tab[i].value;
+ ret = tab[i].name;
+ }
+
+ if (rest)
+ *rest = (ret ? end : s);
+
+ return ret;
+}
- *dst = '\0';
- return src;
+bool
+parse_tex_target(const char *s, unsigned *t, const char **rest)
+{
+ static const struct string_to_enum tab[] = {
+ { "1D", GL_TEXTURE_1D },
+ { "2D", GL_TEXTURE_2D },
+ { "3D", GL_TEXTURE_3D },
+ { "Rect", GL_TEXTURE_RECTANGLE },
+ { "Cube", GL_TEXTURE_CUBE_MAP },
+ { "1DArray", GL_TEXTURE_1D_ARRAY },
+ { "2DArray", GL_TEXTURE_2D_ARRAY },
+ { "CubeArray", GL_TEXTURE_CUBE_MAP_ARRAY },
+ { NULL, 0 }
+ };
+ return parse_enum_tab(tab, s, t, rest);
+}
+
+bool
+parse_comparison_op(const char *s, GLenum *t, const char **rest)
+{
+ if (parse_str(s, "==", rest)) {
+ *t = equal;
+ return true;
+ } else if (parse_str(s, "!=", rest)) {
+ *t = greater;
+ return true;
+ } else if (parse_str(s, "<=", rest)) {
+ *t = less_equal;
+ return true;
+ } else if (parse_str(s, "<", rest)) {
+ *t = less;
+ return true;
+ } else if (parse_str(s, ">=", rest)) {
+ *t = greater_equal;
+ return true;
+ } else if (parse_str(s, ">", rest)) {
+ *t = greater;
+ return true;
+ } else {
+ return false;
+ }
}
diff --git a/tests/shaders/parser_utils.h b/tests/shaders/parser_utils.h
index 538fa6b66..b9e8556ab 100644
--- a/tests/shaders/parser_utils.h
+++ b/tests/shaders/parser_utils.h
@@ -1,5 +1,5 @@
/*
- * Copyright © 2010 Intel Corporation
+ * Copyright © 2016 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -21,9 +21,172 @@
* DEALINGS IN THE SOFTWARE.
*/
+/**
+ * \file parser_utils.h
+ *
+ * These are a bunch of plain-text parsing utilities, most of them
+ * have the form:
+ * boolean-like parse_foo(input-string, output-foo, output-string)
+ *
+ * If the input is a well-formed string representation of a "foo"
+ * value, as many characters will be read from the string as they are
+ * needed to initialize the "foo" object returned via the first output
+ * argument, and the boolean return value will evaluate to true. If
+ * the output string argument is not NULL, a pointer one past the last
+ * character consumed to parse a "foo" value will be returned to the
+ * caller so that the rest of the document can be processed (e.g. by
+ * passing the output string as input string of another parse
+ * function).
+ *
+ * If the input cannot be parsed as a "foo" object, the boolean return
+ * value will evaluate to false and the input string will be returned
+ * as output string as-is (which mimicks the behavior of the C
+ * standard library strto* functions). The "foo" output argument will
+ * be left in an undefined state in that case.
+ */
+#ifndef PIGLIT_PARSER_UTILS_H
+#define PIGLIT_PARSER_UTILS_H
+
#include <stdbool.h>
+#include "piglit-util-gl.h"
+
+/**
+ * Parse one or more whitespace characters (other than newline) from
+ * the input string.
+ */
+bool
+parse_whitespace(const char *s, const char **rest);
+
+/**
+ * Parse an exact match of string \p lit, optionally preceded by
+ * whitespace.
+ */
+bool
+parse_str(const char *s, const char *lit, const char **rest);
+
+/**
+ * Parse up to \p n whitespace-separated signed integer values. The
+ * number of values actually parsed is returned as result.
+ */
+unsigned
+parse_ints(const char *s, int *i, unsigned n, const char **rest);
+
+static inline bool
+parse_int(const char *s, int *i, const char **rest)
+{
+ return parse_ints(s, i, 1, rest);
+}
+
+/**
+ * Parse up to \p n whitespace-separated unsigned integer values. The
+ * number of values actually parsed is returned as result.
+ */
+unsigned
+parse_uints(const char *s, unsigned *u, unsigned n, const char **rest);
+
+static inline bool
+parse_uint(const char *s, unsigned *u, const char **rest)
+{
+ return parse_uints(s, u, 1, rest);
+}
+
+/**
+ * Parse up to \p n whitespace-separated floating point values. The
+ * number of values actually parsed is returned as result.
+ */
+unsigned
+parse_floats(const char *s, float *f, unsigned n, const char **rest);
+
+static inline bool
+parse_float(const char *s, float *f, const char **rest)
+{
+ return parse_floats(s, f, 1, rest);
+}
+
+/**
+ * Parse up to \p n whitespace-separated double-precision floating
+ * point values. The number of values actually parsed is returned as
+ * result.
+ */
+unsigned
+parse_doubles(const char *s, double *d, unsigned n, const char **rest);
+
+static inline bool
+parse_double(const char *s, double *d, const char **rest)
+{
+ return parse_doubles(s, d, 1, rest);
+}
+
+/**
+ * Parse a single non-empty whitespace-separated token. On success \p
+ * t and \p rest will respectively point at the first and one past the
+ * last character of the result.
+ */
+bool
+parse_word(const char *s, const char **t, const char **rest);
+
+/**
+ * Like parse_word(), but the result is copied into the fixed-size
+ * buffer pointed to by \p t and null-terminated.
+ *
+ * The parse is considered to fail if the size of the result
+ * (including the terminating null character) would have exceded the
+ * number of characters allocated for it in the buffer as given by the
+ * \p n argument.
+ */
+bool
+parse_word_copy(const char *s, char *t, unsigned n, const char **rest);
+
+/**
+ * Parse any GL_* symbolic constant.
+ */
+bool
+parse_enum_gl(const char *s, GLenum *e, const char **rest);
+
+struct string_to_enum {
+ const char *name;
+ unsigned value;
+};
+
+/**
+ * Parse a whitespace-delimited symbolic constant from the set
+ * specified in the \p tab argument pointing to a zero-terminated
+ * array of string-value pairs.
+ */
+bool
+parse_enum_tab(const struct string_to_enum *tab,
+ const char *s, unsigned *e, const char **rest);
+
+/**
+ * Parse a texture target symbolic constant.
+ */
+bool
+parse_tex_target(const char *s, GLenum *t, const char **rest);
+
+enum comparison {
+ equal = 0,
+ not_equal,
+ less,
+ greater_equal,
+ greater,
+ less_equal
+};
+
+/**
+ * Parse a binary comparison operator.
+ */
+bool parse_comparison_op(const char *s, enum comparison *t, const char **rest);
+
+/**
+ * Abort the Piglit test with failure status if the boolean expression
+ * (typically the result of a chain of parse function calls) evaluates
+ * to false.
+ */
+#define REQUIRE(b, ...) do { \
+ if (!(b)) { \
+ fprintf(stderr, __VA_ARGS__); \
+ piglit_report_result(PIGLIT_FAIL); \
+ } \
+ } while (0)
-const char *eat_whitespace(const char *src);
-const char *eat_text(const char *src);
-bool string_match(const char *string, const char *line);
-const char *strcpy_to_space(char *dst, const char *src);
+#endif
diff --git a/tests/shaders/shader_runner.c b/tests/shaders/shader_runner.c
index 2f90fee7b..78dc9b4da 100644
--- a/tests/shaders/shader_runner.c
+++ b/tests/shaders/shader_runner.c
@@ -38,9 +38,6 @@ get_required_config(const char *script_name,
static GLenum
decode_drawing_mode(const char *mode_str);
-static void
-get_uints(const char *line, unsigned *uints, unsigned count);
-
PIGLIT_GL_TEST_CONFIG_BEGIN
config.window_width = 250;
@@ -77,11 +74,6 @@ struct component_version {
#define ENUM_STRING(e) { #e, e }
-struct string_to_enum {
- const char *name;
- GLenum token;
-};
-
extern float piglit_tolerance[4];
static struct component_version gl_version;
@@ -138,8 +130,38 @@ static bool prog_in_use = false;
static bool sso_in_use = false;
static GLchar *prog_err_info = NULL;
static GLuint vao = 0;
-static GLuint fbo = 0;
static GLint render_width, render_height;
+static GLint read_width, read_height;
+
+struct texture_binding {
+ GLuint obj;
+ unsigned width;
+ unsigned height;
+ unsigned layers;
+} texture_bindings[32];
+
+GLuint draw_fbo_binding, read_fbo_binding;
+
+static void
+set_texture_binding(unsigned idx, GLuint obj, unsigned w, unsigned h, unsigned l)
+{
+ REQUIRE(idx < ARRAY_SIZE(texture_bindings),
+ "Invalid texture index %d\n", idx);
+ texture_bindings[idx].obj = obj;
+ texture_bindings[idx].width = w;
+ texture_bindings[idx].height = h;
+ texture_bindings[idx].layers = l;
+}
+
+static const struct texture_binding *
+get_texture_binding(unsigned idx)
+{
+ REQUIRE(idx < ARRAY_SIZE(texture_bindings),
+ "Invalid texture index %d\n", idx);
+ REQUIRE(texture_bindings[idx].obj,
+ "No texture bound at %d\n", idx);
+ return &texture_bindings[idx];
+}
enum states {
none = 0,
@@ -158,16 +180,6 @@ enum states {
test,
};
-
-enum comparison {
- equal = 0,
- not_equal,
- less,
- greater_equal,
- greater,
- less_equal
-};
-
static const struct string_to_enum all_types[] = {
ENUM_STRING(GL_FLOAT),
ENUM_STRING(GL_FLOAT_VEC2),
@@ -246,25 +258,6 @@ static const struct string_to_enum all_types[] = {
{ NULL, 0 }
};
-static GLenum
-lookup_enum_string(const struct string_to_enum *table, const char **line,
- const char *error_desc)
-{
- int i;
- *line = eat_whitespace(*line);
- for (i = 0; table[i].name; i++) {
- size_t len = strlen(table[i].name);
- if (strncmp(table[i].name, *line, len) == 0 &&
- ((*line)[len] == '\0' || isspace((*line)[len]))) {
- *line = eat_whitespace(*line + len);
- return table[i].token;
- }
- }
- fprintf(stderr, "Bad %s at: %s\n", error_desc, *line);
- piglit_report_result(PIGLIT_FAIL);
- return 0;
-}
-
static bool
compare(float ref, float value, enum comparison cmp);
@@ -599,56 +592,6 @@ comparison_string(enum comparison cmp)
return false;
}
-
-/**
- * Parse a binary comparison operator and return the matching token
- */
-static const char *
-process_comparison(const char *src, enum comparison *cmp)
-{
- char buf[32];
-
- switch (src[0]) {
- case '=':
- if (src[1] == '=') {
- *cmp = equal;
- return src + 2;
- }
- break;
- case '<':
- if (src[1] == '=') {
- *cmp = less_equal;
- return src + 2;
- } else {
- *cmp = less;
- return src + 1;
- }
- case '>':
- if (src[1] == '=') {
- *cmp = greater_equal;
- return src + 2;
- } else {
- *cmp = greater;
- return src + 1;
- }
- case '!':
- if (src[1] == '=') {
- *cmp = not_equal;
- return src + 2;
- }
- break;
- }
-
- strncpy(buf, src, sizeof(buf));
- buf[sizeof(buf) - 1] = '\0';
- printf("invalid comparison in test script:\n%s\n", buf);
- piglit_report_result(PIGLIT_FAIL);
-
- /* Won't get here. */
- return NULL;
-}
-
-
/**
* " ES" before the comparison operator indicates the version
* pertains to GL ES.
@@ -660,25 +603,18 @@ parse_version_comparison(const char *line, enum comparison *cmp,
unsigned major;
unsigned minor;
unsigned full_num;
- bool es = false;
- bool core = false;
+ const bool core = parse_str(line, "CORE", &line);
+ const bool es = parse_str(line, "ES", &line);
- if (string_match(" CORE", line)) {
- core = true;
- line += 5;
- }
- if (string_match(" ES", line)) {
- es = true;
- line += 3;
- }
- line = eat_whitespace(line);
- line = process_comparison(line, cmp);
+ REQUIRE(parse_comparison_op(line, cmp, &line),
+ "Invalid comparison at: %s\n", line);
- line = eat_whitespace(line);
- sscanf(line, "%u.%u", &major, &minor);
- line = eat_text(line);
+ REQUIRE(parse_uint(line, &major, &line) &&
+ parse_str(line, ".", &line) &&
+ parse_uint(line, &minor, &line),
+ "Invalid version string: %s\n", line);
- line = eat_whitespace(line);
+ parse_whitespace(line, &line);
if (*line != '\n') {
printf("Unexpected characters following version comparison\n");
piglit_report_result(PIGLIT_FAIL);
@@ -742,30 +678,29 @@ process_requirement(const char *line)
* shader_runner to read the specified integer value and
* processes the given requirement.
*/
- if (string_match("INT ", line)) {
+ if (parse_str(line, "INT ", &line)) {
enum comparison cmp;
- const char *enum_name = eat_whitespace(line+3);
- const char *int_string;
int comparison_value, gl_int_value;
- GLenum int_enum;
-
- strcpy_to_space(buffer, enum_name);
-
- int_enum = piglit_get_gl_enum_from_name(buffer);
+ unsigned int_enum;
- int_string = process_comparison(eat_whitespace(enum_name + strlen(buffer)), &cmp);
- comparison_value = atoi(int_string);
+ REQUIRE(parse_enum_gl(line, &int_enum, &line),
+ "Invalid comparison enum at: %s\n", line);
+ REQUIRE(parse_comparison_op(line, &cmp, &line),
+ "Invalid comparison operation at: %s\n", line);
+ REQUIRE(parse_int(line, &comparison_value, &line),
+ "Invalid comparison value at: %s\n", line);
glGetIntegerv(int_enum, &gl_int_value);
if (!piglit_check_gl_error(GL_NO_ERROR)) {
- fprintf(stderr, "Error reading %s\n", buffer);
+ fprintf(stderr, "Error reading %s\n",
+ piglit_get_gl_enum_name(int_enum));
piglit_report_result(PIGLIT_FAIL);
}
if (!compare(comparison_value, gl_int_value, cmp)) {
printf("Test requires %s %s %i. "
"The driver supports %i.\n",
- buffer,
+ piglit_get_gl_enum_name(int_enum),
comparison_string(cmp),
comparison_value,
gl_int_value);
@@ -793,12 +728,11 @@ process_requirement(const char *line)
enum comparison cmp;
int maxcomp;
- if (!string_match(getint_limits[i].name, line))
+ if (!parse_str(line, getint_limits[i].name, &line))
continue;
- line = eat_whitespace(line + strlen(getint_limits[i].name));
-
- line = process_comparison(line, &cmp);
+ REQUIRE(parse_comparison_op(line, &cmp, &line),
+ "Invalid comparison operation at: %s\n", line);
maxcomp = atoi(line);
if (!compare(maxcomp, *getint_limits[i].val, cmp)) {
@@ -813,21 +747,17 @@ process_requirement(const char *line)
return;
}
- /* Consume any leading whitespace before requirements. This is
- * important for generated test files that may have odd whitespace
- */
- line = eat_whitespace(line);
-
- if (string_match("GL_", line)) {
- strcpy_to_space(buffer, line);
+ if (parse_str(line, "GL_", NULL) &&
+ parse_word_copy(line, buffer, sizeof(buffer), &line)) {
piglit_require_extension(buffer);
- } else if (string_match("!GL_", line)) {
- strcpy_to_space(buffer, line + 1);
+ } else if (parse_str(line, "!", &line) &&
+ parse_str(line, "GL_", NULL) &&
+ parse_word_copy(line, buffer, sizeof(buffer), &line)) {
piglit_require_not_extension(buffer);
- } else if (string_match("GLSL", line)) {
+ } else if (parse_str(line, "GLSL", &line)) {
enum comparison cmp;
- parse_version_comparison(line + 4, &cmp, &glsl_req_version,
+ parse_version_comparison(line, &cmp, &glsl_req_version,
VERSION_GLSL);
/* We only allow >= because we potentially use the
@@ -845,11 +775,11 @@ process_requirement(const char *line)
version_string(&glsl_version));
piglit_report_result(PIGLIT_SKIP);
}
- } else if (string_match("GL", line)) {
+ } else if (parse_str(line, "GL", &line)) {
enum comparison cmp;
struct component_version gl_req_version;
- parse_version_comparison(line + 2, &cmp, &gl_req_version,
+ parse_version_comparison(line, &cmp, &gl_req_version,
VERSION_GL);
if (!version_compare(&gl_req_version, &gl_version, cmp)) {
@@ -860,25 +790,17 @@ process_requirement(const char *line)
version_string(&gl_version));
piglit_report_result(PIGLIT_SKIP);
}
- } else if (string_match("rlimit", line)) {
- unsigned long lim;
- char *ptr;
+ } else if (parse_str(line, "rlimit", &line)) {
+ unsigned lim;
- line = eat_whitespace(line + 6);
-
- lim = strtoul(line, &ptr, 0);
- if (ptr == line) {
- printf("rlimit requires numeric argument\n");
- piglit_report_result(PIGLIT_FAIL);
- }
+ REQUIRE(parse_uint(line, &lim, &line),
+ "Invalid rlimit argument at: %s\n", line);
piglit_set_rlimit(lim);
- } else if (string_match("SSO", line)) {
- line = eat_whitespace(line + 3);
- if (string_match("ENABLED", line)) {
- piglit_require_extension("GL_ARB_separate_shader_objects");
- sso_in_use = true;
- }
+ } else if (parse_str(line, "SSO", &line) &&
+ parse_str(line, "ENABLED", NULL)) {
+ piglit_require_extension("GL_ARB_separate_shader_objects");
+ sso_in_use = true;
}
}
@@ -892,7 +814,7 @@ process_geometry_layout(const char *line)
char s[32];
int x;
- line = eat_whitespace(line);
+ parse_whitespace(line, &line);
if (line[0] == '\0' || line[0] == '\n') {
return;
@@ -1125,44 +1047,44 @@ process_test_script(const char *script_name)
if (line[0] == '[') {
leave_state(state, line);
- if (string_match("[require]", line)) {
+ if (parse_str(line, "[require]", NULL)) {
state = requirements;
- } else if (string_match("[vertex shader]", line)) {
+ } else if (parse_str(line, "[vertex shader]", NULL)) {
state = vertex_shader;
shader_string = NULL;
- } else if (string_match("[vertex program]", line)) {
+ } else if (parse_str(line, "[vertex program]", NULL)) {
state = vertex_program;
shader_string = NULL;
- } else if (string_match("[vertex shader passthrough]", line)) {
+ } else if (parse_str(line, "[vertex shader passthrough]", NULL)) {
state = vertex_shader_passthrough;
shader_string =
(char *) passthrough_vertex_shader_source;
shader_string_size = strlen(shader_string);
- } else if (string_match("[tessellation control shader]", line)) {
+ } else if (parse_str(line, "[tessellation control shader]", NULL)) {
state = tess_ctrl_shader;
shader_string = NULL;
- } else if (string_match("[tessellation evaluation shader]", line)) {
+ } else if (parse_str(line, "[tessellation evaluation shader]", NULL)) {
state = tess_eval_shader;
shader_string = NULL;
- } else if (string_match("[geometry shader]", line)) {
+ } else if (parse_str(line, "[geometry shader]", NULL)) {
state = geometry_shader;
shader_string = NULL;
- } else if (string_match("[geometry layout]", line)) {
+ } else if (parse_str(line, "[geometry layout]", NULL)) {
state = geometry_layout;
shader_string = NULL;
- } else if (string_match("[fragment shader]", line)) {
+ } else if (parse_str(line, "[fragment shader]", NULL)) {
state = fragment_shader;
shader_string = NULL;
- } else if (string_match("[fragment program]", line)) {
+ } else if (parse_str(line, "[fragment program]", NULL)) {
state = fragment_program;
shader_string = NULL;
- } else if (string_match("[compute shader]", line)) {
+ } else if (parse_str(line, "[compute shader]", NULL)) {
state = compute_shader;
shader_string = NULL;
- } else if (string_match("[vertex data]", line)) {
+ } else if (parse_str(line, "[vertex data]", NULL)) {
state = vertex_data;
vertex_data_start = NULL;
- } else if (string_match("[test]", line)) {
+ } else if (parse_str(line, "[test]", NULL)) {
test_start = strchrnul(line, '\n');
if (test_start[0] != '\0')
test_start++;
@@ -1255,28 +1177,28 @@ parse_required_config(struct requirement_parse_results *results,
}
if (!in_requirement_section) {
- if (string_match("[require]", line)) {
+ if (parse_str(line, "[require]", NULL)) {
in_requirement_section = true;
}
} else {
- if (string_match("GL_", line)
- || string_match("!GL_", line)) {
+ if (parse_str(line, "GL_", NULL)
+ || parse_str(line, "!GL_", NULL)) {
/* empty */
- } else if (string_match("GLSL", line)) {
+ } else if (parse_str(line, "GLSL", &line)) {
enum comparison cmp;
struct component_version version;
- parse_version_comparison(line + 4, &cmp,
+ parse_version_comparison(line, &cmp,
&version, VERSION_GLSL);
if (cmp == greater_equal) {
results->found_glsl = true;
version_copy(&results->glsl_version, &version);
}
- } else if (string_match("GL", line)) {
+ } else if (parse_str(line, "GL", &line)) {
enum comparison cmp;
struct component_version version;
- parse_version_comparison(line + 2, &cmp,
+ parse_version_comparison(line, &cmp,
&version, VERSION_GL);
if (cmp == greater_equal
|| cmp == greater
@@ -1284,10 +1206,10 @@ parse_required_config(struct requirement_parse_results *results,
results->found_gl = true;
version_copy(&results->gl_version, &version);
}
- } else if (string_match("SIZE", line)) {
+ } else if (parse_str(line, "SIZE", &line)) {
results->found_size = true;
- get_uints(line+4, results->size, 2);
- } else if (string_match("depthbuffer", line)) {
+ parse_uints(line, results->size, 2, NULL);
+ } else if (parse_str(line, "depthbuffer", NULL)) {
results->found_depthbuffer = true;
}
}
@@ -1378,45 +1300,6 @@ get_required_config(const char *script_name,
}
}
-static void
-get_floats(const char *line, float *f, unsigned count)
-{
- unsigned i;
-
- for (i = 0; i < count; i++)
- f[i] = strtof_hex(line, (char **) &line);
-}
-
-static void
-get_doubles(const char *line, double *d, unsigned count)
-{
- unsigned i;
-
- for (i = 0; i < count; i++)
- d[i] = strtod_hex(line, (char **) &line);
-}
-
-
-static void
-get_ints(const char *line, int *ints, unsigned count)
-{
- unsigned i;
-
- for (i = 0; i < count; i++)
- ints[i] = strtoll(line, (char **) &line, 0);
-}
-
-
-static void
-get_uints(const char *line, unsigned *uints, unsigned count)
-{
- unsigned i;
-
- for (i = 0; i < count; i++)
- uints[i] = strtoul(line, (char **) &line, 0);
-}
-
-
/**
* Check that the GL implementation supports unsigned uniforms
* (e.g. through glUniform1ui). If not, terminate the test with a
@@ -1529,35 +1412,35 @@ set_ubo_uniform(char *name, const char *type, const char *line, int ubo_array_in
data = glMapBuffer(GL_UNIFORM_BUFFER, GL_WRITE_ONLY);
data += offset;
- if (string_match("float", type)) {
- get_floats(line, f, 1);
+ if (parse_str(type, "float", NULL)) {
+ parse_floats(line, f, 1, NULL);
memcpy(data, f, sizeof(float));
- } else if (string_match("int", type)) {
- get_ints(line, ints, 1);
+ } else if (parse_str(type, "int", NULL)) {
+ parse_ints(line, ints, 1, NULL);
memcpy(data, ints, sizeof(int));
- } else if (string_match("uint", type)) {
- get_uints(line, uints, 1);
+ } else if (parse_str(type, "uint", NULL)) {
+ parse_uints(line, uints, 1, NULL);
memcpy(data, uints, sizeof(int));
- } else if (string_match("double", type)) {
- get_doubles(line, d, 1);
+ } else if (parse_str(type, "double", NULL)) {
+ parse_doubles(line, d, 1, NULL);
memcpy(data, d, sizeof(double));
- } else if (string_match("vec", type)) {
+ } else if (parse_str(type, "vec", NULL)) {
int elements = type[3] - '0';
- get_floats(line, f, elements);
+ parse_floats(line, f, elements, NULL);
memcpy(data, f, elements * sizeof(float));
- } else if (string_match("ivec", type)) {
+ } else if (parse_str(type, "ivec", NULL)) {
int elements = type[4] - '0';
- get_ints(line, ints, elements);
+ parse_ints(line, ints, elements, NULL);
memcpy(data, ints, elements * sizeof(int));
- } else if (string_match("uvec", type)) {
+ } else if (parse_str(type, "uvec", NULL)) {
int elements = type[4] - '0';
- get_uints(line, uints, elements);
+ parse_uints(line, uints, elements, NULL);
memcpy(data, uints, elements * sizeof(unsigned));
- } else if (string_match("dvec", type)) {
+ } else if (parse_str(type, "dvec", NULL)) {
int elements = type[4] - '0';
- get_doubles(line, d, elements);
+ parse_doubles(line, d, elements, NULL);
memcpy(data, d, elements * sizeof(double));
- } else if (string_match("mat", type)) {
+ } else if (parse_str(type, "mat", NULL)) {
GLint matrix_stride, row_major;
int cols = type[3] - '0';
int rows = type[4] == 'x' ? type[5] - '0' : cols;
@@ -1567,7 +1450,7 @@ set_ubo_uniform(char *name, const char *type, const char *line, int ubo_array_in
assert(cols >= 2 && cols <= 4);
assert(rows >= 2 && rows <= 4);
- get_floats(line, f, rows * cols);
+ parse_floats(line, f, rows * cols, NULL);
glGetActiveUniformsiv(prog, 1, &uniform_index,
GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
@@ -1591,7 +1474,7 @@ set_ubo_uniform(char *name, const char *type, const char *line, int ubo_array_in
}
}
}
- } else if (string_match("dmat", type)) {
+ } else if (parse_str(type, "dmat", NULL)) {
GLint matrix_stride, row_major;
int cols = type[4] - '0';
int rows = type[5] == 'x' ? type[6] - '0' : cols;
@@ -1601,7 +1484,7 @@ set_ubo_uniform(char *name, const char *type, const char *line, int ubo_array_in
assert(cols >= 2 && cols <= 4);
assert(rows >= 2 && rows <= 4);
- get_doubles(line, d, rows * cols);
+ parse_doubles(line, d, rows * cols, NULL);
glGetActiveUniformsiv(prog, 1, &uniform_index,
GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
@@ -1638,18 +1521,16 @@ set_ubo_uniform(char *name, const char *type, const char *line, int ubo_array_in
static void
set_uniform(const char *line, int ubo_array_index)
{
- char name[512];
+ char name[512], type[512];
float f[16];
double d[16];
int ints[16];
unsigned uints[16];
GLint loc;
- const char *type;
- type = eat_whitespace(line);
- line = eat_text(type);
-
- line = strcpy_to_space(name, eat_whitespace(line));
+ REQUIRE(parse_word_copy(line, type, sizeof(type), &line) &&
+ parse_word_copy(line, name, sizeof(name), &line),
+ "Invalid set uniform command at: %s\n", line);
if (isdigit(name[0])) {
loc = strtol(name, NULL, 0);
@@ -1668,190 +1549,189 @@ set_uniform(const char *line, int ubo_array_index)
}
}
- if (string_match("float", type)) {
- get_floats(line, f, 1);
+ if (parse_str(type, "float", NULL)) {
+ parse_floats(line, f, 1, NULL);
glUniform1fv(loc, 1, f);
return;
- } else if (string_match("int", type)) {
- get_ints(line, ints, 1);
+ } else if (parse_str(type, "int", NULL)) {
+ parse_ints(line, ints, 1, NULL);
glUniform1iv(loc, 1, ints);
return;
- } else if (string_match("uint", type)) {
+ } else if (parse_str(type, "uint", NULL)) {
check_unsigned_support();
- get_uints(line, uints, 1);
+ parse_uints(line, uints, 1, NULL);
glUniform1uiv(loc, 1, uints);
return;
- } else if (string_match("double", type)) {
+ } else if (parse_str(type, "double", NULL)) {
check_double_support();
- get_doubles(line, d, 1);
+ parse_doubles(line, d, 1, NULL);
glUniform1dv(loc, 1, d);
return;
- } else if (string_match("vec", type)) {
+ } else if (parse_str(type, "vec", NULL)) {
switch (type[3]) {
case '2':
- get_floats(line, f, 2);
+ parse_floats(line, f, 2, NULL);
glUniform2fv(loc, 1, f);
return;
case '3':
- get_floats(line, f, 3);
+ parse_floats(line, f, 3, NULL);
glUniform3fv(loc, 1, f);
return;
case '4':
- get_floats(line, f, 4);
+ parse_floats(line, f, 4, NULL);
glUniform4fv(loc, 1, f);
return;
}
- } else if (string_match("ivec", type)) {
+ } else if (parse_str(type, "ivec", NULL)) {
switch (type[4]) {
case '2':
- get_ints(line, ints, 2);
+ parse_ints(line, ints, 2, NULL);
glUniform2iv(loc, 1, ints);
return;
case '3':
- get_ints(line, ints, 3);
+ parse_ints(line, ints, 3, NULL);
glUniform3iv(loc, 1, ints);
return;
case '4':
- get_ints(line, ints, 4);
+ parse_ints(line, ints, 4, NULL);
glUniform4iv(loc, 1, ints);
return;
}
- } else if (string_match("uvec", type)) {
+ } else if (parse_str(type, "uvec", NULL)) {
check_unsigned_support();
switch (type[4]) {
case '2':
- get_uints(line, uints, 2);
+ parse_uints(line, uints, 2, NULL);
glUniform2uiv(loc, 1, uints);
return;
case '3':
- get_uints(line, uints, 3);
+ parse_uints(line, uints, 3, NULL);
glUniform3uiv(loc, 1, uints);
return;
case '4':
- get_uints(line, uints, 4);
+ parse_uints(line, uints, 4, NULL);
glUniform4uiv(loc, 1, uints);
return;
}
- } else if (string_match("dvec", type)) {
+ } else if (parse_str(type, "dvec", NULL)) {
check_double_support();
switch (type[4]) {
case '2':
- get_doubles(line, d, 2);
+ parse_doubles(line, d, 2, NULL);
glUniform2dv(loc, 1, d);
return;
case '3':
- get_doubles(line, d, 3);
+ parse_doubles(line, d, 3, NULL);
glUniform3dv(loc, 1, d);
return;
case '4':
- get_doubles(line, d, 4);
+ parse_doubles(line, d, 4, NULL);
glUniform4dv(loc, 1, d);
return;
}
- } else if (string_match("mat", type) && type[3] != '\0') {
+ } else if (parse_str(type, "mat", NULL) && type[3] != '\0') {
char cols = type[3];
char rows = type[4] == 'x' ? type[5] : cols;
switch (cols) {
case '2':
switch (rows) {
case '2':
- get_floats(line, f, 4);
+ parse_floats(line, f, 4, NULL);
glUniformMatrix2fv(loc, 1, GL_FALSE, f);
return;
case '3':
- get_floats(line, f, 6);
+ parse_floats(line, f, 6, NULL);
glUniformMatrix2x3fv(loc, 1, GL_FALSE, f);
return;
case '4':
- get_floats(line, f, 8);
+ parse_floats(line, f, 8, NULL);
glUniformMatrix2x4fv(loc, 1, GL_FALSE, f);
return;
}
case '3':
switch (rows) {
case '2':
- get_floats(line, f, 6);
+ parse_floats(line, f, 6, NULL);
glUniformMatrix3x2fv(loc, 1, GL_FALSE, f);
return;
case '3':
- get_floats(line, f, 9);
+ parse_floats(line, f, 9, NULL);
glUniformMatrix3fv(loc, 1, GL_FALSE, f);
return;
case '4':
- get_floats(line, f, 12);
+ parse_floats(line, f, 12, NULL);
glUniformMatrix3x4fv(loc, 1, GL_FALSE, f);
return;
}
case '4':
switch (rows) {
case '2':
- get_floats(line, f, 8);
+ parse_floats(line, f, 8, NULL);
glUniformMatrix4x2fv(loc, 1, GL_FALSE, f);
return;
case '3':
- get_floats(line, f, 12);
+ parse_floats(line, f, 12, NULL);
glUniformMatrix4x3fv(loc, 1, GL_FALSE, f);
return;
case '4':
- get_floats(line, f, 16);
+ parse_floats(line, f, 16, NULL);
glUniformMatrix4fv(loc, 1, GL_FALSE, f);
return;
}
}
- } else if (string_match("dmat", type) && type[4] != '\0') {
+ } else if (parse_str(type, "dmat", NULL) && type[4] != '\0') {
char cols = type[4];
char rows = type[5] == 'x' ? type[6] : cols;
switch (cols) {
case '2':
switch (rows) {
case '2':
- get_doubles(line, d, 4);
+ parse_doubles(line, d, 4, NULL);
glUniformMatrix2dv(loc, 1, GL_FALSE, d);
return;
case '3':
- get_doubles(line, d, 6);
+ parse_doubles(line, d, 6, NULL);
glUniformMatrix2x3dv(loc, 1, GL_FALSE, d);
return;
case '4':
- get_doubles(line, d, 8);
+ parse_doubles(line, d, 8, NULL);
glUniformMatrix2x4dv(loc, 1, GL_FALSE, d);
return;
}
case '3':
switch (rows) {
case '2':
- get_doubles(line, d, 6);
+ parse_doubles(line, d, 6, NULL);
glUniformMatrix3x2dv(loc, 1, GL_FALSE, d);
return;
case '3':
- get_doubles(line, d, 9);
+ parse_doubles(line, d, 9, NULL);
glUniformMatrix3dv(loc, 1, GL_FALSE, d);
return;
case '4':
- get_doubles(line, d, 12);
+ parse_doubles(line, d, 12, NULL);
glUniformMatrix3x4dv(loc, 1, GL_FALSE, d);
return;
}
case '4':
switch (rows) {
case '2':
- get_doubles(line, d, 8);
+ parse_doubles(line, d, 8, NULL);
glUniformMatrix4x2dv(loc, 1, GL_FALSE, d);
return;
case '3':
- get_doubles(line, d, 12);
+ parse_doubles(line, d, 12, NULL);
glUniformMatrix4x3dv(loc, 1, GL_FALSE, d);
return;
case '4':
- get_doubles(line, d, 16);
+ parse_doubles(line, d, 16, NULL);
glUniformMatrix4dv(loc, 1, GL_FALSE, d);
return;
}
}
}
- strcpy_to_space(name, type);
- printf("unknown uniform type \"%s\"\n", name);
+ printf("unknown uniform type \"%s\"\n", type);
piglit_report_result(PIGLIT_FAIL);
return;
@@ -1879,27 +1759,27 @@ static GLenum lookup_shader_type(GLuint idx)
static GLenum get_shader_from_string(const char *name, int *idx)
{
- if (string_match("GL_VERTEX_SHADER", name)) {
+ if (parse_str(name, "GL_VERTEX_SHADER", NULL)) {
*idx = 0;
return GL_VERTEX_SHADER;
}
- if (string_match("GL_FRAGMENT_SHADER", name)) {
+ if (parse_str(name, "GL_FRAGMENT_SHADER", NULL)) {
*idx = 1;
return GL_FRAGMENT_SHADER;
}
- if (string_match("GL_GEOMETRY_SHADER", name)) {
+ if (parse_str(name, "GL_GEOMETRY_SHADER", NULL)) {
*idx = 2;
return GL_GEOMETRY_SHADER;
}
- if (string_match("GL_TESS_CONTROL_SHADER", name)) {
+ if (parse_str(name, "GL_TESS_CONTROL_SHADER", NULL)) {
*idx = 3;
return GL_TESS_CONTROL_SHADER;
}
- if (string_match("GL_TESS_EVALUATION_SHADER", name)) {
+ if (parse_str(name, "GL_TESS_EVALUATION_SHADER", NULL)) {
*idx = 4;
return GL_TESS_EVALUATION_SHADER;
}
- if (string_match("GL_COMPUTE_SHADER", name)) {
+ if (parse_str(name, "GL_COMPUTE_SHADER", NULL)) {
*idx = 5;
return GL_COMPUTE_SHADER;
}
@@ -1937,19 +1817,18 @@ static void
set_subroutine_uniform(const char *line)
{
GLuint prog;
+ char type[512];
char name[512];
char subname[512];
- const char *type;
GLint loc;
GLuint idx;
GLenum ptype = 0;
int sidx = 0;
- type = eat_whitespace(line);
- line = eat_text(type);
-
- line = strcpy_to_space(name, eat_whitespace(line));
- line = strcpy_to_space(subname, eat_whitespace(line));
+ REQUIRE(parse_word_copy(line, type, sizeof(type), &line) &&
+ parse_word_copy(line, name, sizeof(name), &line) &&
+ parse_word_copy(line, subname, sizeof(subname), &line),
+ "Invalid set subroutine uniform command at: %s\n", line);
ptype = get_shader_from_string(type, &sidx);
if (ptype == 0) {
@@ -2018,25 +1897,22 @@ active_uniform(const char *line)
{ NULL, 0 }
};
+ const char *rest = line;
char name[512];
- char name_buf[512];
- char pname_string[512];
- GLenum pname;
- GLint expected;
+ unsigned pname;
+ int expected;
int i;
int num_active_uniforms;
- line = strcpy_to_space(name, eat_whitespace(line));
+ REQUIRE(parse_word_copy(rest, name, sizeof(name), &rest),
+ "Bad uniform name at: %s\n", line);
- strcpy_to_space(pname_string, eat_whitespace(line));
- pname = lookup_enum_string(all_pnames, &line, "glGetUniformsiv pname");
+ REQUIRE(parse_enum_tab(all_pnames, rest, &pname, &rest),
+ "Bad glGetUniformsiv pname at: %s\n", line);
- line = eat_whitespace(line);
- if (isdigit(line[0])) {
- expected = strtol(line, NULL, 0);
- } else {
- expected = lookup_enum_string(all_types, &line, "type enum");
- }
+ REQUIRE(parse_enum_tab(all_types, rest, (unsigned *)&expected, &rest) ||
+ parse_int(rest, &expected, &rest),
+ "Bad expected value at: %s\n", line);
glGetProgramiv(prog, GL_ACTIVE_UNIFORMS, &num_active_uniforms);
for (i = 0; i < num_active_uniforms; i++) {
@@ -2044,6 +1920,7 @@ active_uniform(const char *line)
GLint size;
GLenum type;
GLsizei name_len;
+ char name_buf[512];
bool pass = true;
glGetActiveUniform(prog, i, sizeof(name_buf), &name_len,
@@ -2087,7 +1964,7 @@ active_uniform(const char *line)
fprintf(stderr,
"glGetActiveUniform(%s, %s): "
"expected %d (0x%04x), got %d (0x%04x)\n",
- name, pname_string,
+ name, piglit_get_gl_enum_name(pname),
expected, expected, got, got);
pass = false;
}
@@ -2109,7 +1986,7 @@ active_uniform(const char *line)
fprintf(stderr,
"glGetActiveUniformsiv(%s, %s): "
"expected %d, got %d\n",
- name, pname_string,
+ name, piglit_get_gl_enum_name(pname),
expected, got);
pass = false;
}
@@ -2120,7 +1997,6 @@ active_uniform(const char *line)
return;
}
-
fprintf(stderr, "No active uniform named \"%s\"\n", name);
piglit_report_result(PIGLIT_FAIL);
return;
@@ -2196,10 +2072,8 @@ active_program_interface(const char *line)
char name[512];
char name_buf[512];
- char prop_string[512];
- char interface_type_string[512];
- GLenum prop, interface_type;
- GLint expected;
+ unsigned prop, interface_type;
+ int expected;
int i;
int num_active_buffers;
@@ -2211,22 +2085,16 @@ active_program_interface(const char *line)
return;
}
- strcpy_to_space(interface_type_string, eat_whitespace(line));
- interface_type = lookup_enum_string(all_program_interface, &line,
- "glGetProgramResourceiv "
- "programInterface");
- line = strcpy_to_space(name, eat_whitespace(line));
-
- strcpy_to_space(prop_string, eat_whitespace(line));
- prop = lookup_enum_string(all_props, &line,
- "glGetProgramResourceiv pname");
-
- line = eat_whitespace(line);
- if (isdigit(line[0])) {
- expected = strtol(line, NULL, 0);
- } else {
- expected = lookup_enum_string(all_types, &line, "type enum");
- }
+ REQUIRE(parse_enum_tab(all_program_interface, line,
+ &interface_type, &line),
+ "Bad program interface at: %s\n", line);
+ REQUIRE(parse_word_copy(line, name, sizeof(name), &line),
+ "Bad program resource name at: %s\n", line);
+ REQUIRE(parse_enum_tab(all_props, line, &prop, &line),
+ "Bad glGetProgramResourceiv pname at: %s\n", line);
+ REQUIRE(parse_enum_tab(all_types, line, (unsigned *)&expected, &line) ||
+ parse_int(line, &expected, &line),
+ "Bad expected value at: %s\n", line);
glGetProgramInterfaceiv(prog, interface_type,
GL_ACTIVE_RESOURCES, &num_active_buffers);
@@ -2251,7 +2119,7 @@ active_program_interface(const char *line)
fprintf(stderr,
"glGetProgramResourceName(%s, %s): "
"expected %d (0x%04x), got %d (0x%04x)\n",
- name, prop_string,
+ name, piglit_get_gl_enum_name(prop),
expected, expected, name_len, name_len);
pass = false;
}
@@ -2275,7 +2143,7 @@ active_program_interface(const char *line)
fprintf(stderr,
"glGetProgramResourceiv(%s, %s): "
"expected %d, got %d\n",
- name, prop_string,
+ name, piglit_get_gl_enum_name(prop),
expected, got);
pass = false;
}
@@ -2305,13 +2173,13 @@ set_parameter(const char *line)
piglit_report_result(PIGLIT_FAIL);
}
- if (string_match("env_vp", type)) {
+ if (parse_str(type, "env_vp", NULL)) {
glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, index, f);
- } else if (string_match("local_vp", type)) {
+ } else if (parse_str(type, "local_vp", NULL)) {
glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, index, f);
- } else if (string_match("env_fp", type)) {
+ } else if (parse_str(type, "env_fp", NULL)) {
glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, index, f);
- } else if (string_match("local_fp", type)) {
+ } else if (parse_str(type, "local_fp", NULL)) {
glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, index, f);
} else {
fprintf(stderr, "Unknown parameter type `%s'\n", type);
@@ -2330,24 +2198,21 @@ set_patch_parameter(const char *line)
if (gl_version.num < 40)
piglit_require_extension("GL_ARB_tessellation_shader");
- if (string_match("vertices ", line)) {
- line += strlen("vertices ");
+ if (parse_str(line, "vertices ", &line)) {
count = sscanf(line, "%d", &i);
if (count != 1) {
fprintf(stderr, "Couldn't parse patch parameter command:\n%s\n", line0);
piglit_report_result(PIGLIT_FAIL);
}
glPatchParameteri(GL_PATCH_VERTICES, i);
- } else if (string_match("default level outer ", line)) {
- line += strlen("default level outer ");
+ } else if (parse_str(line, "default level outer ", &line)) {
count = sscanf(line, "%f %f %f %f", &f[0], &f[1], &f[2], &f[3]);
if (count != 4) {
fprintf(stderr, "Couldn't parse patch parameter command:\n%s\n", line0);
piglit_report_result(PIGLIT_FAIL);
}
glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, f);
- } else if (string_match("default level inner ", line)) {
- line += strlen("default level inner ");
+ } else if (parse_str(line, "default level inner ", &line)) {
count = sscanf(line, "%f %f", &f[0], &f[1]);
if (count != 2) {
fprintf(stderr, "Couldn't parse patch parameter command:\n%s\n", line0);
@@ -2367,9 +2232,9 @@ set_patch_parameter(const char *line)
static void
set_provoking_vertex(const char *line)
{
- if (string_match("first", line)) {
+ if (parse_str(line, "first", NULL)) {
glProvokingVertexEXT(GL_FIRST_VERTEX_CONVENTION_EXT);
- } else if (string_match("last", line)) {
+ } else if (parse_str(line, "last", NULL)) {
glProvokingVertexEXT(GL_LAST_VERTEX_CONVENTION_EXT);
} else {
fprintf(stderr, "Unknown provoking vertex parameter `%s'\n", line);
@@ -2395,8 +2260,10 @@ static const struct string_to_enum enable_table[] = {
static void
do_enable_disable(const char *line, bool enable_flag)
{
- GLenum value = lookup_enum_string(enable_table, &line,
- "enable/disable enum");
+ GLenum value;
+ REQUIRE(parse_enum_tab(enable_table, line, &value, NULL),
+ "Bad enable/disable enum at: %s\n", line);
+
if (enable_flag)
glEnable(value);
else
@@ -2420,10 +2287,12 @@ static const struct string_to_enum hint_param_table[] = {
static void do_hint(const char *line)
{
- GLenum target = lookup_enum_string(hint_target_table, &line,
- "hint target");
- GLenum param = lookup_enum_string(hint_param_table, &line,
- "hint param");
+ unsigned target, param;
+ REQUIRE(parse_enum_tab(hint_target_table, line, &target, &line),
+ "Bad hint target at: %s\n", line);
+ REQUIRE(parse_enum_tab(hint_param_table, line, &param, &line),
+ "Bad hint param at: %s\n", line);
+
glHint(target, param);
}
@@ -2481,18 +2350,6 @@ decode_drawing_mode(const char *mode_str)
static void
handle_texparameter(const char *line)
{
- static const struct string_to_enum texture_target[] = {
- { "1D", GL_TEXTURE_1D },
- { "2D", GL_TEXTURE_2D },
- { "3D", GL_TEXTURE_3D },
- { "Rect", GL_TEXTURE_RECTANGLE },
- { "Cube", GL_TEXTURE_CUBE_MAP },
- { "1DArray", GL_TEXTURE_1D_ARRAY },
- { "2DArray", GL_TEXTURE_2D_ARRAY },
- { "CubeArray", GL_TEXTURE_CUBE_MAP_ARRAY },
- { NULL, 0 }
- };
-
static const struct string_to_enum compare_funcs[] = {
{ "greater", GL_GREATER },
{ "gequal", GL_GEQUAL },
@@ -2532,37 +2389,33 @@ handle_texparameter(const char *line)
{ "alpha", GL_ALPHA },
{ NULL, 0 }
};
- GLenum target = 0;
+ unsigned target = 0;
GLenum parameter = GL_NONE;
const char *parameter_name = NULL;
const struct string_to_enum *strings = NULL;
- GLenum value;
+ unsigned value;
- target = lookup_enum_string(texture_target, &line, "texture target");
+ REQUIRE(parse_tex_target(line, &target, &line),
+ "Bad texture target at: %s\n", line);
- if (string_match("compare_func ", line)) {
+ if (parse_str(line, "compare_func ", &line)) {
parameter = GL_TEXTURE_COMPARE_FUNC;
parameter_name = "compare_func";
- line += strlen("compare_func ");
strings = compare_funcs;
- } else if (string_match("depth_mode ", line)) {
+ } else if (parse_str(line, "depth_mode ", &line)) {
parameter = GL_DEPTH_TEXTURE_MODE;
parameter_name = "depth_mode";
- line += strlen("depth_mode ");
strings = depth_modes;
- } else if (string_match("min ", line)) {
+ } else if (parse_str(line, "min ", &line)) {
parameter = GL_TEXTURE_MIN_FILTER;
parameter_name = "min";
- line += strlen("min ");
strings = min_filter_modes;
- } else if (string_match("mag ", line)) {
+ } else if (parse_str(line, "mag ", &line)) {
parameter = GL_TEXTURE_MAG_FILTER;
parameter_name = "mag";
- line += strlen("mag ");
strings = mag_filter_modes;
- } else if (string_match("lod_bias ", line)) {
+ } else if (parse_str(line, "lod_bias ", &line)) {
#ifdef PIGLIT_USE_OPENGL
- line += strlen("lod_bias ");
glTexParameterf(target, GL_TEXTURE_LOD_BIAS,
strtod(line, NULL));
return;
@@ -2570,27 +2423,26 @@ handle_texparameter(const char *line)
printf("lod_bias feature is only available in desktop GL\n");
piglit_report_result(PIGLIT_SKIP);
#endif
- } else if (string_match("max_level ", line)) {
- line += strlen("max_level ");
+ } else if (parse_str(line, "max_level ", &line)) {
glTexParameteri(target, GL_TEXTURE_MAX_LEVEL,
strtol(line, NULL, 10));
return;
- } else if (string_match("base_level ", line)) {
- line += strlen("base_level ");
+ } else if (parse_str(line, "base_level ", &line)) {
glTexParameteri(target, GL_TEXTURE_BASE_LEVEL,
strtol(line, NULL, 10));
return;
- } else if (string_match("swizzle_r ", line)) {
+ } else if (parse_str(line, "swizzle_r ", &line)) {
parameter = GL_TEXTURE_SWIZZLE_R;
parameter_name = "swizzle_r";
- line += strlen("swizzle_r ");
strings = swizzle_modes;
} else {
fprintf(stderr, "unknown texture parameter in `%s'\n", line);
piglit_report_result(PIGLIT_FAIL);
}
- value = lookup_enum_string(strings, &line, parameter_name);
+ REQUIRE(parse_enum_tab(strings, line, &value, &line),
+ "Bad %s at: %s\n", parameter_name, line);
+
glTexParameteri(target, parameter, value);
}
@@ -2660,7 +2512,8 @@ probe_atomic_counter(GLint counter_num, const char *op, uint32_t value)
enum comparison cmp;
bool result;
- process_comparison(op, &cmp);
+ REQUIRE(parse_comparison_op(op, &cmp, NULL),
+ "Invalid comparison operation at: %s\n", op);
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomics_bo);
p = glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, counter_num * sizeof(uint32_t),
@@ -2695,7 +2548,8 @@ probe_ssbo_uint(GLint ssbo_index, GLint ssbo_offset, const char *op, uint32_t va
enum comparison cmp;
bool result;
- process_comparison(op, &cmp);
+ REQUIRE(parse_comparison_op(op, &cmp, NULL),
+ "Invalid comparison operation at: %s\n", op);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo[ssbo_index]);
p = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, ssbo_offset,
@@ -2725,7 +2579,7 @@ probe_ssbo_uint(GLint ssbo_index, GLint ssbo_offset, const char *op, uint32_t va
enum piglit_result
piglit_display(void)
{
- const char *line, *next_line;
+ const char *line, *next_line, *rest;
bool pass = true;
GLbitfield clear_bits = 0;
bool link_error_expected = false;
@@ -2741,9 +2595,9 @@ piglit_display(void)
int x, y, z, w, h, l, tex, level;
unsigned ux, uy;
char s[32];
+ GLuint obj;
-
- line = eat_whitespace(next_line);
+ parse_whitespace(next_line, &line);
next_line = strchrnul(next_line, '\n');
@@ -2784,15 +2638,15 @@ piglit_display(void)
sizeof(GLuint) * x,
atomics_buf, GL_STATIC_DRAW);
free(atomics_buf);
- } else if (string_match("clear color", line)) {
- get_floats(line + 11, c, 4);
+ } else if (parse_str(line, "clear color ", &rest)) {
+ parse_floats(rest, c, 4, NULL);
glClearColor(c[0], c[1], c[2], c[3]);
clear_bits |= GL_COLOR_BUFFER_BIT;
- } else if (string_match("clear depth", line)) {
- get_floats(line + 11, c, 1);
+ } else if (parse_str(line, "clear depth ", &rest)) {
+ parse_floats(rest, c, 1, NULL);
glClearDepth(c[0]);
clear_bits |= GL_DEPTH_BUFFER_BIT;
- } else if (string_match("clear", line)) {
+ } else if (parse_str(line, "clear", NULL)) {
glClear(clear_bits);
} else if (sscanf(line,
"clip plane %d %lf %lf %lf %lf",
@@ -2809,44 +2663,44 @@ piglit_display(void)
glMemoryBarrier(GL_ALL_BARRIER_BITS);
glDispatchCompute(x, y, z);
glMemoryBarrier(GL_ALL_BARRIER_BITS);
- } else if (string_match("draw rect tex", line)) {
+ } else if (parse_str(line, "draw rect tex ", &rest)) {
program_must_be_in_use();
program_subroutine_uniforms();
- get_floats(line + 13, c, 8);
+ parse_floats(rest, c, 8, NULL);
piglit_draw_rect_tex(c[0], c[1], c[2], c[3],
c[4], c[5], c[6], c[7]);
- } else if (string_match("draw rect ortho patch", line)) {
+ } else if (parse_str(line, "draw rect ortho patch ", &rest)) {
program_must_be_in_use();
program_subroutine_uniforms();
- get_floats(line + 21, c, 4);
+ parse_floats(rest, c, 4, NULL);
piglit_draw_rect_custom(-1.0 + 2.0 * (c[0] / piglit_width),
-1.0 + 2.0 * (c[1] / piglit_height),
2.0 * (c[2] / piglit_width),
2.0 * (c[3] / piglit_height), true);
- } else if (string_match("draw rect ortho", line)) {
+ } else if (parse_str(line, "draw rect ortho ", &rest)) {
program_must_be_in_use();
program_subroutine_uniforms();
- get_floats(line + 15, c, 4);
+ parse_floats(rest, c, 4, NULL);
piglit_draw_rect(-1.0 + 2.0 * (c[0] / piglit_width),
-1.0 + 2.0 * (c[1] / piglit_height),
2.0 * (c[2] / piglit_width),
2.0 * (c[3] / piglit_height));
- } else if (string_match("draw rect patch", line)) {
+ } else if (parse_str(line, "draw rect patch ", &rest)) {
program_must_be_in_use();
- get_floats(line + 15, c, 4);
+ parse_floats(rest, c, 4, NULL);
piglit_draw_rect_custom(c[0], c[1], c[2], c[3], true);
- } else if (string_match("draw rect", line)) {
+ } else if (parse_str(line, "draw rect ", &rest)) {
program_must_be_in_use();
program_subroutine_uniforms();
- get_floats(line + 9, c, 4);
+ parse_floats(rest, c, 4, NULL);
piglit_draw_rect(c[0], c[1], c[2], c[3]);
- } else if (string_match("draw instanced rect", line)) {
+ } else if (parse_str(line, "draw instanced rect ", &rest)) {
int primcount;
program_must_be_in_use();
- sscanf(line + 19, "%d %f %f %f %f",
+ sscanf(rest, "%d %f %f %f %f",
&primcount,
c + 0, c + 1, c + 2, c + 3);
draw_instanced_rect(primcount, c[0], c[1], c[2], c[3]);
@@ -2875,101 +2729,275 @@ piglit_display(void)
}
bind_vao_if_supported();
glDrawArrays(mode, first, count);
- } else if (string_match("disable", line)) {
- do_enable_disable(line + 7, false);
- } else if (string_match("enable", line)) {
- do_enable_disable(line + 6, true);
+ } else if (parse_str(line, "disable ", &rest)) {
+ do_enable_disable(rest, false);
+ } else if (parse_str(line, "enable ", &rest)) {
+ do_enable_disable(rest, true);
} else if (sscanf(line, "depthfunc %31s", s) == 1) {
glDepthFunc(piglit_get_gl_enum_from_name(s));
- } else if (sscanf(line, "fb tex 2d %d", &tex) == 1) {
- GLenum status;
- GLint tex_num;
+ } else if (parse_str(line, "fb ", &rest)) {
+ const GLenum target =
+ parse_str(rest, "draw ", &rest) ? GL_DRAW_FRAMEBUFFER :
+ parse_str(rest, "read ", &rest) ? GL_READ_FRAMEBUFFER :
+ GL_FRAMEBUFFER;
+ GLuint fbo = 0;
+
+ if (parse_str(rest, "tex multi ", &rest) ||
+ parse_str(rest, "tex 2d ", &rest)) {
+ GLenum attachments[32];
+ unsigned num_attachments = 0;
- glActiveTexture(GL_TEXTURE0 + tex);
- glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex_num);
+ glGenFramebuffers(1, &fbo);
+ glBindFramebuffer(target, fbo);
+
+ while (parse_int(rest, &tex, &rest)) {
+ attachments[num_attachments] =
+ GL_COLOR_ATTACHMENT0 + num_attachments;
+ glFramebufferTexture2D(
+ target, attachments[num_attachments],
+ GL_TEXTURE_2D,
+ get_texture_binding(tex)->obj, 0);
+
+ if (!piglit_check_gl_error(GL_NO_ERROR)) {
+ fprintf(stderr, "glFramebufferTexture2D error\n");
+ piglit_report_result(PIGLIT_FAIL);
+ }
+
+ num_attachments++;
+ }
+
+ if (target != GL_READ_FRAMEBUFFER)
+ glDrawBuffers(num_attachments, attachments);
+
+ w = get_texture_binding(tex)->width;
+ h = get_texture_binding(tex)->height;
+
+ } else if (parse_str(rest, "tex slice ", &rest)) {
+ GLenum tex_target;
+
+ REQUIRE(parse_tex_target(rest, &tex_target, &rest) &&
+ parse_int(rest, &tex, &rest) &&
+ parse_int(rest, &l, &rest) &&
+ parse_int(rest, &z, &rest),
+ "Framebuffer binding command not "
+ "understood at: %s\n", rest);
+
+ const GLuint tex_obj = get_texture_binding(tex)->obj;
- if (fbo == 0) {
glGenFramebuffers(1, &fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, fbo);
- }
+ glBindFramebuffer(target, fbo);
+
+ if (tex_target == GL_TEXTURE_1D) {
+ REQUIRE(z == 0,
+ "Invalid layer index provided "
+ "in command: %s\n", line);
+ glFramebufferTexture1D(
+ target, GL_COLOR_ATTACHMENT0,
+ tex_target, tex_obj, l);
+
+ } else if (tex_target == GL_TEXTURE_2D ||
+ tex_target == GL_TEXTURE_RECTANGLE ||
+ tex_target == GL_TEXTURE_2D_MULTISAMPLE) {
+ REQUIRE(z == 0,
+ "Invalid layer index provided "
+ "in command: %s\n", line);
+ glFramebufferTexture2D(
+ target, GL_COLOR_ATTACHMENT0,
+ tex_target, tex_obj, l);
+
+ } else if (tex_target == GL_TEXTURE_CUBE_MAP) {
+ static const GLenum cubemap_targets[] = {
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+ };
+ REQUIRE(z < ARRAY_SIZE(cubemap_targets),
+ "Invalid layer index provided "
+ "in command: %s\n", line);
+ tex_target = cubemap_targets[z];
+
+ glFramebufferTexture2D(
+ target, GL_COLOR_ATTACHMENT0,
+ tex_target, tex_obj, l);
- glFramebufferTexture2D(GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, tex_num, 0);
- if (!piglit_check_gl_error(GL_NO_ERROR)) {
- fprintf(stderr, "glFramebufferTexture2D error\n");
+ } else {
+ glFramebufferTextureLayer(
+ target, GL_COLOR_ATTACHMENT0,
+ tex_obj, l, z);
+ }
+
+ if (!piglit_check_gl_error(GL_NO_ERROR)) {
+ fprintf(stderr, "Error binding texture "
+ "attachment for command: %s\n",
+ line);
+ piglit_report_result(PIGLIT_FAIL);
+ }
+
+ w = MAX2(1, get_texture_binding(tex)->width >> l);
+ h = MAX2(1, get_texture_binding(tex)->height >> l);
+
+ } else if (sscanf(rest, "tex layered %d", &tex) == 1) {
+ glGenFramebuffers(1, &fbo);
+ glBindFramebuffer(target, fbo);
+
+ glFramebufferTexture(target,
+ GL_COLOR_ATTACHMENT0,
+ get_texture_binding(tex)->obj, 0);
+ if (!piglit_check_gl_error(GL_NO_ERROR)) {
+ fprintf(stderr, "glFramebufferTexture error\n");
+ piglit_report_result(PIGLIT_FAIL);
+ }
+
+ w = get_texture_binding(tex)->width;
+ h = get_texture_binding(tex)->height;
+
+ } else if (parse_str(rest, "ms ", &rest)) {
+ GLuint rb;
+ GLenum format;
+ int samples;
+
+ REQUIRE(parse_enum_gl(rest, &format, &rest) &&
+ parse_int(rest, &w, &rest) &&
+ parse_int(rest, &h, &rest) &&
+ parse_int(rest, &samples, &rest),
+ "Framebuffer binding command not "
+ "understood at: %s\n", rest);
+
+ glGenFramebuffers(1, &fbo);
+ glBindFramebuffer(target, fbo);
+
+ glGenRenderbuffers(1, &rb);
+ glBindRenderbuffer(GL_RENDERBUFFER, rb);
+
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
+ format, w, h);
+
+ glFramebufferRenderbuffer(target,
+ GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER, rb);
+
+ if (!piglit_check_gl_error(GL_NO_ERROR)) {
+ fprintf(stderr, "glFramebufferRenderbuffer error\n");
+ piglit_report_result(PIGLIT_FAIL);
+ }
+
+ } else if (parse_str(rest, "winsys", &rest)) {
+ fbo = piglit_winsys_fbo;
+ glBindFramebuffer(target, fbo);
+ if (!piglit_check_gl_error(GL_NO_ERROR)) {
+ fprintf(stderr, "glBindFramebuffer error\n");
+ piglit_report_result(PIGLIT_FAIL);
+ }
+
+ w = piglit_width;
+ h = piglit_height;
+
+ } else {
+ fprintf(stderr, "Unknown fb bind subcommand "
+ "\"%s\"\n", rest);
piglit_report_result(PIGLIT_FAIL);
}
- status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ const GLenum status = glCheckFramebufferStatus(target);
if (status != GL_FRAMEBUFFER_COMPLETE) {
fprintf(stderr, "incomplete fbo (status 0x%x)\n", status);
piglit_report_result(PIGLIT_FAIL);
}
- glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &render_width);
- glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &render_height);
- } else if (sscanf(line, "fb tex layered 2DArray %d", &tex) == 1) {
- GLenum status;
- GLint tex_num;
+ if (target != GL_READ_FRAMEBUFFER) {
+ render_width = w;
+ render_height = h;
- glActiveTexture(GL_TEXTURE0 + tex);
- glGetIntegerv(GL_TEXTURE_BINDING_2D_ARRAY, &tex_num);
+ /* Delete the previous draw FB in case
+ * it's no longer reachable.
+ */
+ if (draw_fbo_binding != 0 &&
+ draw_fbo_binding != piglit_winsys_fbo &&
+ draw_fbo_binding != (target == GL_DRAW_FRAMEBUFFER ?
+ read_fbo_binding : 0))
+ glDeleteFramebuffers(1, &draw_fbo_binding);
- if (fbo == 0) {
- glGenFramebuffers(1, &fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ draw_fbo_binding = fbo;
}
- glFramebufferTexture(GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- tex_num, 0);
- if (!piglit_check_gl_error(GL_NO_ERROR)) {
- fprintf(stderr, "glFramebufferTexture error\n");
- piglit_report_result(PIGLIT_FAIL);
+ if (target != GL_DRAW_FRAMEBUFFER) {
+ read_width = w;
+ read_height = h;
+
+ /* Delete the previous read FB in case
+ * it's no longer reachable.
+ */
+ if (read_fbo_binding != 0 &&
+ read_fbo_binding != piglit_winsys_fbo &&
+ read_fbo_binding != (target == GL_READ_FRAMEBUFFER ?
+ draw_fbo_binding : 0))
+ glDeleteFramebuffers(1, &read_fbo_binding);
+
+ read_fbo_binding = fbo;
}
- status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- fprintf(stderr, "incomplete fbo (status 0x%x)\n", status);
+ } else if (parse_str(line, "blit ", &rest)) {
+ static const struct string_to_enum buffers[] = {
+ { "color", GL_COLOR_BUFFER_BIT },
+ { "depth", GL_DEPTH_BUFFER_BIT },
+ { "stencil", GL_STENCIL_BUFFER_BIT },
+ { NULL }
+ };
+ static const struct string_to_enum filters[] = {
+ { "linear", GL_LINEAR },
+ { "nearest", GL_NEAREST },
+ { NULL }
+ };
+ unsigned buffer, filter;
+
+ REQUIRE(parse_enum_tab(buffers, rest, &buffer, &rest) &&
+ parse_enum_tab(filters, rest, &filter, &rest),
+ "FB blit command not understood at: %s\n",
+ rest);
+
+ glBlitFramebuffer(0, 0, read_width, read_height,
+ 0, 0, render_width, render_height,
+ buffer, filter);
+
+ if (!piglit_check_gl_error(GL_NO_ERROR)) {
+ fprintf(stderr, "glBlitFramebuffer error\n");
piglit_report_result(PIGLIT_FAIL);
}
- glGetTexLevelParameteriv(GL_TEXTURE_2D_ARRAY, 0, GL_TEXTURE_WIDTH, &render_width);
- glGetTexLevelParameteriv(GL_TEXTURE_2D_ARRAY, 0, GL_TEXTURE_HEIGHT, &render_height);
- } else if (string_match("frustum", line)) {
- get_floats(line + 7, c, 6);
+ } else if (parse_str(line, "frustum", &rest)) {
+ parse_floats(rest, c, 6, NULL);
piglit_frustum_projection(false, c[0], c[1], c[2],
c[3], c[4], c[5]);
- } else if (string_match("hint", line)) {
- do_hint(line + 4);
+ } else if (parse_str(line, "hint", &rest)) {
+ do_hint(rest);
} else if (sscanf(line,
"image texture %d %31s",
&tex, s) == 2) {
const GLenum img_fmt = piglit_get_gl_enum_from_name(s);
- GLint tex_num;
-
- glActiveTexture(GL_TEXTURE0 + tex);
- glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex_num);
- glBindImageTexture(tex, tex_num, 0, GL_FALSE, 0,
- GL_READ_WRITE, img_fmt);
+ glBindImageTexture(tex, get_texture_binding(tex)->obj, 0,
+ GL_FALSE, 0, GL_READ_WRITE, img_fmt);
} else if (sscanf(line, "memory barrier %s", s) == 1) {
glMemoryBarrier(piglit_get_gl_memory_barrier_enum_from_name(s));
+ } else if (parse_str(line, "blend barrier", NULL)) {
+ glBlendBarrier();
} else if (sscanf(line, "ortho %f %f %f %f",
c + 0, c + 1, c + 2, c + 3) == 4) {
piglit_gen_ortho_projection(c[0], c[1], c[2], c[3],
-1, 1, GL_FALSE);
- } else if (string_match("ortho", line)) {
+ } else if (parse_str(line, "ortho", NULL)) {
piglit_ortho_projection(render_width, render_height,
GL_FALSE);
- } else if (string_match("probe rgba", line)) {
- get_floats(line + 10, c, 6);
+ } else if (parse_str(line, "probe rgba ", &rest)) {
+ parse_floats(rest, c, 6, NULL);
if (!piglit_probe_pixel_rgba((int) c[0], (int) c[1],
& c[2])) {
pass = false;
}
- } else if (string_match("probe depth", line)) {
- get_floats(line + 11, c, 3);
+ } else if (parse_str(line, "probe depth ", &rest)) {
+ parse_floats(rest, c, 3, NULL);
if (!piglit_probe_pixel_depth((int) c[0], (int) c[1],
c[2])) {
pass = false;
@@ -3003,8 +3031,8 @@ piglit_display(void)
if (!piglit_probe_pixel_rgba(x, y, &c[2])) {
pass = false;
}
- } else if (string_match("probe rgb", line)) {
- get_floats(line + 9, c, 5);
+ } else if (parse_str(line, "probe rgb ", &rest)) {
+ parse_floats(rest, c, 5, NULL);
if (!piglit_probe_pixel_rgb((int) c[0], (int) c[1],
& c[2])) {
pass = false;
@@ -3045,21 +3073,35 @@ piglit_display(void)
if (!piglit_probe_rect_rgb(x, y, w, h, &c[4])) {
pass = false;
}
- } else if (string_match("probe all rgba", line)) {
- get_floats(line + 14, c, 4);
+
+ } else if (sscanf(line, "relative probe rect rgba int "
+ "( %f , %f , %f , %f ) "
+ "( %d , %d , %d , %d )",
+ c + 0, c + 1, c + 2, c + 3,
+ &x, &y, &z, &w) == 8) {
+ const int expected[] = { x, y, z, w };
+ pass = pass && piglit_probe_rect_rgba_int(
+ c[0] * render_width,
+ c[1] * render_height,
+ c[2] * render_width,
+ c[3] * render_height,
+ expected);
+
+ } else if (parse_str(line, "probe all rgba ", &rest)) {
+ parse_floats(rest, c, 4, NULL);
pass = pass &&
piglit_probe_rect_rgba(0, 0, render_width,
render_height, c);
- } else if (string_match("probe all rgb", line)) {
- get_floats(line + 13, c, 3);
+ } else if (parse_str(line, "probe all rgb ", &rest)) {
+ parse_floats(rest, c, 3, NULL);
pass = pass &&
piglit_probe_rect_rgb(0, 0, render_width,
render_height, c);
- } else if (string_match("tolerance", line)) {
- get_floats(line + strlen("tolerance"), piglit_tolerance, 4);
- } else if (string_match("shade model smooth", line)) {
+ } else if (parse_str(line, "tolerance ", &rest)) {
+ parse_floats(rest, piglit_tolerance, 4, NULL);
+ } else if (parse_str(line, "shade model smooth", NULL)) {
glShadeModel(GL_SMOOTH);
- } else if (string_match("shade model flat", line)) {
+ } else if (parse_str(line, "shade model flat", NULL)) {
glShadeModel(GL_FLAT);
} else if (sscanf(line, "ssbo %d %d", &x, &y) == 2) {
GLuint *ssbo_init = calloc(y, 1);
@@ -3089,15 +3131,21 @@ piglit_display(void)
glActiveTexture(GL_TEXTURE0 + tex);
piglit_rgbw_texture(int_fmt, w, h, GL_FALSE, GL_FALSE,
- GL_UNSIGNED_NORMALIZED);
- if (!piglit_is_core_profile)
+ (piglit_is_gles() ? GL_UNSIGNED_BYTE :
+ GL_UNSIGNED_NORMALIZED));
+
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *)&obj);
+ set_texture_binding(tex, obj, w, h, 1);
+
+ if (!piglit_is_core_profile &&
+ !(piglit_is_gles() && piglit_get_gl_version() >= 20))
glEnable(GL_TEXTURE_2D);
- } else if (sscanf(line, "texture integer %d ( %d", &tex, &w) == 2) {
+
+ } else if (parse_str(line, "texture integer ", &rest)) {
GLenum int_fmt;
int b, a;
int num_scanned =
- sscanf(line,
- "texture integer %d ( %d , %d ) ( %d, %d ) %31s",
+ sscanf(rest, "%d ( %d , %d ) ( %d, %d ) %31s",
&tex, &w, &h, &b, &a, s);
if (num_scanned < 6) {
fprintf(stderr,
@@ -3109,11 +3157,21 @@ piglit_display(void)
glActiveTexture(GL_TEXTURE0 + tex);
(void)piglit_integer_texture(int_fmt, w, h, b, a);
+
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *)&obj);
+ set_texture_binding(tex, obj, w, h, 1);
+
} else if (sscanf(line, "texture miptree %d", &tex) == 1) {
glActiveTexture(GL_TEXTURE0 + tex);
piglit_miptree_texture();
- if (!piglit_is_core_profile)
+
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *)&obj);
+ set_texture_binding(tex, obj, 8, 8, 1);
+
+ if (!piglit_is_core_profile &&
+ !(piglit_is_gles() && piglit_get_gl_version() >= 20))
glEnable(GL_TEXTURE_2D);
+
} else if (sscanf(line,
"texture checkerboard %d %d ( %d , %d ) "
"( %f , %f , %f , %f ) "
@@ -3126,8 +3184,14 @@ piglit_display(void)
w, h,
w / 2, h / 2,
c + 0, c + 4);
- if (!piglit_is_core_profile)
+
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *)&obj);
+ set_texture_binding(tex, obj, w, h, 1);
+
+ if (!piglit_is_core_profile &&
+ !(piglit_is_gles() && piglit_get_gl_version() >= 20))
glEnable(GL_TEXTURE_2D);
+
} else if (sscanf(line,
"texture junk 2DArray %d ( %d , %d , %d )",
&tex, &w, &h, &l) == 4) {
@@ -3137,12 +3201,53 @@ piglit_display(void)
glBindTexture(GL_TEXTURE_2D_ARRAY, texobj);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA,
w, h, l, 0, GL_RGBA, GL_FLOAT, 0);
+
+ set_texture_binding(tex, texobj, w, h, l);
+
+ } else if (parse_str(line, "texture storage ", &rest)) {
+ GLenum target, format;
+ GLuint tex_obj;
+ int d = h = w = 1;
+
+ REQUIRE(parse_int(rest, &tex, &rest) &&
+ parse_tex_target(rest, &target, &rest) &&
+ parse_enum_gl(rest, &format, &rest) &&
+ parse_str(rest, "(", &rest) &&
+ parse_int(rest, &l, &rest) &&
+ parse_int(rest, &w, &rest),
+ "Texture storage command not understood "
+ "at: %s\n", rest);
+
+ glActiveTexture(GL_TEXTURE0 + tex);
+ glGenTextures(1, &tex_obj);
+ glBindTexture(target, tex_obj);
+
+ if (!parse_int(rest, &h, &rest))
+ glTexStorage1D(target, l, format, w);
+ else if (!parse_int(rest, &d, &rest))
+ glTexStorage2D(target, l, format, w, h);
+ else
+ glTexStorage3D(target, l, format, w, h, d);
+
+ if (!piglit_check_gl_error(GL_NO_ERROR)) {
+ fprintf(stderr, "glTexStorage error\n");
+ piglit_report_result(PIGLIT_FAIL);
+ }
+
+ if (target == GL_TEXTURE_1D_ARRAY)
+ set_texture_binding(tex, tex_obj, w, 1, h);
+ else
+ set_texture_binding(tex, tex_obj, w, h, d);
+
} else if (sscanf(line,
"texture rgbw 2DArray %d ( %d , %d , %d )",
&tex, &w, &h, &l) == 4) {
glActiveTexture(GL_TEXTURE0 + tex);
piglit_array_texture(GL_TEXTURE_2D_ARRAY, GL_RGBA,
w, h, l, GL_FALSE);
+ glGetIntegerv(GL_TEXTURE_BINDING_2D_ARRAY, (GLint *)&obj);
+ set_texture_binding(tex, obj, w, h, l);
+
} else if (sscanf(line,
"texture rgbw 1DArray %d ( %d , %d )",
&tex, &w, &l) == 3) {
@@ -3150,6 +3255,9 @@ piglit_display(void)
h = 1;
piglit_array_texture(GL_TEXTURE_1D_ARRAY, GL_RGBA,
w, h, l, GL_FALSE);
+ glGetIntegerv(GL_TEXTURE_BINDING_1D_ARRAY, (GLint *)&obj);
+ set_texture_binding(tex, obj, w, 1, l);
+
} else if (sscanf(line,
"texture shadow2D %d ( %d , %d )",
&tex, &w, &h) == 3) {
@@ -3163,7 +3271,11 @@ piglit_display(void)
GL_TEXTURE_COMPARE_FUNC,
GL_GREATER);
- if (!piglit_is_core_profile)
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *)&obj);
+ set_texture_binding(tex, obj, w, h, 1);
+
+ if (!piglit_is_core_profile &&
+ !(piglit_is_gles() && piglit_get_gl_version() >= 20))
glEnable(GL_TEXTURE_2D);
} else if (sscanf(line,
"texture shadowRect %d ( %d , %d )",
@@ -3177,6 +3289,9 @@ piglit_display(void)
glTexParameteri(GL_TEXTURE_RECTANGLE,
GL_TEXTURE_COMPARE_FUNC,
GL_GREATER);
+
+ glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE, (GLint *)&obj);
+ set_texture_binding(tex, obj, w, h, 1);
} else if (sscanf(line,
"texture shadow1D %d ( %d )",
&tex, &w) == 2) {
@@ -3189,6 +3304,9 @@ piglit_display(void)
glTexParameteri(GL_TEXTURE_1D,
GL_TEXTURE_COMPARE_FUNC,
GL_GREATER);
+
+ glGetIntegerv(GL_TEXTURE_BINDING_1D, (GLint *)&obj);
+ set_texture_binding(tex, obj, w, 1, 1);
} else if (sscanf(line,
"texture shadow1DArray %d ( %d , %d )",
&tex, &w, &l) == 3) {
@@ -3201,6 +3319,9 @@ piglit_display(void)
glTexParameteri(GL_TEXTURE_1D_ARRAY,
GL_TEXTURE_COMPARE_FUNC,
GL_GREATER);
+
+ glGetIntegerv(GL_TEXTURE_BINDING_1D_ARRAY, (GLint *)&obj);
+ set_texture_binding(tex, obj, w, 1, l);
} else if (sscanf(line,
"texture shadow2DArray %d ( %d , %d , %d )",
&tex, &w, &h, &l) == 4) {
@@ -3213,25 +3334,28 @@ piglit_display(void)
glTexParameteri(GL_TEXTURE_2D_ARRAY,
GL_TEXTURE_COMPARE_FUNC,
GL_GREATER);
+
+ glGetIntegerv(GL_TEXTURE_BINDING_2D_ARRAY, (GLint *)&obj);
+ set_texture_binding(tex, obj, w, h, l);
} else if (sscanf(line, "texcoord %d ( %f , %f , %f , %f )",
&x, c + 0, c + 1, c + 2, c + 3) == 5) {
glMultiTexCoord4fv(GL_TEXTURE0 + x, c);
- } else if (string_match("texparameter ", line)) {
- handle_texparameter(line + strlen("texparameter "));
- } else if (string_match("uniform", line)) {
+ } else if (parse_str(line, "texparameter ", &rest)) {
+ handle_texparameter(rest);
+ } else if (parse_str(line, "uniform ", &rest)) {
program_must_be_in_use();
- set_uniform(line + 7, ubo_array_index);
- } else if (string_match("subuniform", line)) {
+ set_uniform(rest, ubo_array_index);
+ } else if (parse_str(line, "subuniform ", &rest)) {
program_must_be_in_use();
check_shader_subroutine_support();
- set_subroutine_uniform(line + 10);
- } else if (string_match("parameter ", line)) {
- set_parameter(line + strlen("parameter "));
- } else if (string_match("patch parameter ", line)) {
- set_patch_parameter(line + strlen("patch parameter "));
- } else if (string_match("provoking vertex ", line)) {
- set_provoking_vertex(line + strlen("provoking vertex "));
- } else if (string_match("link error", line)) {
+ set_subroutine_uniform(rest);
+ } else if (parse_str(line, "parameter ", &rest)) {
+ set_parameter(rest);
+ } else if (parse_str(line, "patch parameter ", &rest)) {
+ set_patch_parameter(rest);
+ } else if (parse_str(line, "provoking vertex ", &rest)) {
+ set_provoking_vertex(rest);
+ } else if (parse_str(line, "link error", &rest)) {
link_error_expected = true;
if (link_ok) {
printf("shader link error expected, but it was successful!\n");
@@ -3239,14 +3363,14 @@ piglit_display(void)
} else {
fprintf(stderr, "Failed to link:\n%s\n", prog_err_info);
}
- } else if (string_match("link success", line)) {
+ } else if (parse_str(line, "link success", &rest)) {
program_must_be_in_use();
- } else if (string_match("ubo array index ", line)) {
- get_ints(line + strlen("ubo array index "), &ubo_array_index, 1);
- } else if (string_match("active uniform ", line)) {
- active_uniform(line + strlen("active uniform "));
- } else if (string_match("verify program_interface_query ", line)) {
- active_program_interface(line + strlen("verify program_interface_query "));
+ } else if (parse_str(line, "ubo array index ", &rest)) {
+ parse_ints(rest, &ubo_array_index, 1, NULL);
+ } else if (parse_str(line, "active uniform ", &rest)) {
+ active_uniform(rest);
+ } else if (parse_str(line, "verify program_interface_query ", &rest)) {
+ active_program_interface(rest);
} else if ((line[0] != '\n') && (line[0] != '\0')
&& (line[0] != '#')) {
printf("unknown command \"%s\"\n", line);
diff --git a/tests/spec/arb_fragment_layer_viewport/layer-gs-writes-in-range.shader_test b/tests/spec/arb_fragment_layer_viewport/layer-gs-writes-in-range.shader_test
index 0e899bb8f..1c20f767c 100644
--- a/tests/spec/arb_fragment_layer_viewport/layer-gs-writes-in-range.shader_test
+++ b/tests/spec/arb_fragment_layer_viewport/layer-gs-writes-in-range.shader_test
@@ -64,7 +64,7 @@ void main()
[test]
texture junk 2DArray 0 ( 64 , 64 , 4 )
-fb tex layered 2DArray 0
+fb tex layered 0
atomic counters 2
diff --git a/tests/spec/arb_fragment_layer_viewport/layer-gs-writes-out-of-range.shader_test b/tests/spec/arb_fragment_layer_viewport/layer-gs-writes-out-of-range.shader_test
index ad1bfa84f..06a859b64 100644
--- a/tests/spec/arb_fragment_layer_viewport/layer-gs-writes-out-of-range.shader_test
+++ b/tests/spec/arb_fragment_layer_viewport/layer-gs-writes-out-of-range.shader_test
@@ -62,7 +62,7 @@ void main()
[test]
texture junk 2DArray 0 ( 64 , 64 , 4 )
-fb tex layered 2DArray 0
+fb tex layered 0
atomic counters 1
diff --git a/tests/spec/arb_fragment_layer_viewport/viewport-gs-writes-in-range.shader_test b/tests/spec/arb_fragment_layer_viewport/viewport-gs-writes-in-range.shader_test
index fdac3e3c8..3d3c7dfe8 100644
--- a/tests/spec/arb_fragment_layer_viewport/viewport-gs-writes-in-range.shader_test
+++ b/tests/spec/arb_fragment_layer_viewport/viewport-gs-writes-in-range.shader_test
@@ -65,7 +65,7 @@ void main()
[test]
texture junk 2DArray 0 ( 64 , 64 , 1 )
-fb tex layered 2DArray 0
+fb tex layered 0
atomic counters 2
diff --git a/tests/spec/arb_fragment_layer_viewport/viewport-gs-writes-out-of-range.shader_test b/tests/spec/arb_fragment_layer_viewport/viewport-gs-writes-out-of-range.shader_test
index ca852f6e0..9418e161b 100644
--- a/tests/spec/arb_fragment_layer_viewport/viewport-gs-writes-out-of-range.shader_test
+++ b/tests/spec/arb_fragment_layer_viewport/viewport-gs-writes-out-of-range.shader_test
@@ -63,7 +63,7 @@ void main()
[test]
texture junk 2DArray 0 ( 64 , 64 , 1 )
-fb tex layered 2DArray 0
+fb tex layered 0
atomic counters 1
diff --git a/tests/spec/arb_shader_image_load_store/shader-mem-barrier.c b/tests/spec/arb_shader_image_load_store/shader-mem-barrier.c
index ed086403b..553d537b7 100644
--- a/tests/spec/arb_shader_image_load_store/shader-mem-barrier.c
+++ b/tests/spec/arb_shader_image_load_store/shader-mem-barrier.c
@@ -84,7 +84,7 @@ struct image_test_info {
const struct image_test_info image_tests[] = {
{ "control", "", "", true },
{ "'coherent' qualifier", "coherent", "memoryBarrier()", false },
- { "'volatile' qualifier", "volatile", "", false },
+ { "'volatile' qualifier", "volatile", "memoryBarrier()", false },
{ 0 }
};
diff --git a/tests/spec/ext_shader_framebuffer_fetch/compiler/negative-gl_LastFragData-gles3.frag b/tests/spec/ext_shader_framebuffer_fetch/compiler/negative-gl_LastFragData-gles3.frag
new file mode 100644
index 000000000..3cae8ae4f
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/compiler/negative-gl_LastFragData-gles3.frag
@@ -0,0 +1,15 @@
+// [config]
+// expect_result: fail
+// glsl_version: 3.0 es
+// require_extensions: GL_EXT_shader_framebuffer_fetch
+// [end config]
+
+#version 300 es
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+out highp vec4 color;
+
+void main()
+{
+ color = gl_LastFragData[0];
+}
diff --git a/tests/spec/ext_shader_framebuffer_fetch/compiler/negative-gl_LastFragData-write-gles2.frag b/tests/spec/ext_shader_framebuffer_fetch/compiler/negative-gl_LastFragData-write-gles2.frag
new file mode 100644
index 000000000..4b5baec4f
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/compiler/negative-gl_LastFragData-write-gles2.frag
@@ -0,0 +1,13 @@
+// [config]
+// expect_result: fail
+// glsl_version: 1.0 es
+// require_extensions: GL_EXT_shader_framebuffer_fetch
+// [end config]
+
+#version 100
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+void main()
+{
+ gl_LastFragData[0] = vec4(1.0);
+}
diff --git a/tests/spec/ext_shader_framebuffer_fetch/compiler/negative-inout-fragment-output-gles2.frag b/tests/spec/ext_shader_framebuffer_fetch/compiler/negative-inout-fragment-output-gles2.frag
new file mode 100644
index 000000000..ae8fe5c46
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/compiler/negative-inout-fragment-output-gles2.frag
@@ -0,0 +1,15 @@
+// [config]
+// expect_result: fail
+// glsl_version: 1.0 es
+// require_extensions: GL_EXT_shader_framebuffer_fetch
+// [end config]
+
+#version 100
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+inout highp vec4 color;
+
+void main()
+{
+ color += vec4(0.5);
+}
diff --git a/tests/spec/ext_shader_framebuffer_fetch/compiler/negative-inout-gl_FragDepth-gles3.frag b/tests/spec/ext_shader_framebuffer_fetch/compiler/negative-inout-gl_FragDepth-gles3.frag
new file mode 100644
index 000000000..8b0d3d435
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/compiler/negative-inout-gl_FragDepth-gles3.frag
@@ -0,0 +1,15 @@
+// [config]
+// expect_result: fail
+// glsl_version: 3.0 es
+// require_extensions: GL_EXT_shader_framebuffer_fetch
+// [end config]
+
+#version 300 es
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+inout highp float gl_FragDepth;
+
+void main()
+{
+ gl_FragDepth += 0.5;
+}
diff --git a/tests/spec/ext_shader_framebuffer_fetch/compiler/negative-inout-vertex-output-gles3.vert b/tests/spec/ext_shader_framebuffer_fetch/compiler/negative-inout-vertex-output-gles3.vert
new file mode 100644
index 000000000..067211d7f
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/compiler/negative-inout-vertex-output-gles3.vert
@@ -0,0 +1,14 @@
+// [config]
+// expect_result: fail
+// glsl_version: 3.0 es
+// require_extensions: GL_EXT_shader_framebuffer_fetch
+// [end config]
+
+#version 300 es
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+inout highp vec4 vcolor;
+
+void main()
+{
+}
diff --git a/tests/spec/ext_shader_framebuffer_fetch/execution/discard-gles3.shader_test b/tests/spec/ext_shader_framebuffer_fetch/execution/discard-gles3.shader_test
new file mode 100644
index 000000000..197f8d976
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/execution/discard-gles3.shader_test
@@ -0,0 +1,50 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_EXT_shader_framebuffer_fetch
+INT GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT >= 0
+
+[vertex shader]
+#version 300 es
+
+in vec4 vertex;
+out vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 300 es
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+in highp vec4 vcolor;
+inout highp vec4 fcolor;
+
+void main()
+{
+ if (fcolor.x <= 0.45 && fcolor.y < 0.45)
+ fcolor += vec4(vcolor.x >= 0.5 ? 0.5 : 0.1,
+ vcolor.y >= 0.5 ? 0.5 : 0.1, 0.0, 0.0);
+ else
+ discard;
+}
+
+[test]
+texture rgbw 0 (250, 250) GL_RGBA8
+fb tex 2d 0
+
+clear color 0.0 0.0 1.0 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+relative probe rect rgb (0.0, 0.0, 0.45, 0.45) (0.2, 0.2, 1.0)
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (0.5, 0.1, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.1, 0.5, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (0.5, 0.5, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/ext_shader_framebuffer_fetch/execution/discard-ms8-gles3.shader_test b/tests/spec/ext_shader_framebuffer_fetch/execution/discard-ms8-gles3.shader_test
new file mode 100644
index 000000000..949c64660
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/execution/discard-ms8-gles3.shader_test
@@ -0,0 +1,55 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_EXT_shader_framebuffer_fetch
+INT GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT != 0
+INT GL_MAX_SAMPLES >= 8
+
+[vertex shader]
+#version 300 es
+
+in vec4 vertex;
+out vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 300 es
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+in highp vec4 vcolor;
+inout highp vec4 fcolor;
+
+void main()
+{
+ if (fcolor.x <= 0.45 && fcolor.y < 0.45)
+ fcolor += vec4(vcolor.x >= 0.5 ? 0.5 : 0.1,
+ vcolor.y >= 0.5 ? 0.5 : 0.1, 0.0, 0.0);
+ else
+ discard;
+}
+
+[test]
+fb ms GL_RGBA8 250 250 8
+
+clear color 0.0 0.0 1.0 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+texture rgbw 0 (250, 250) GL_RGBA8
+fb draw tex 2d 0
+blit color linear
+fb read tex 2d 0
+
+relative probe rect rgb (0.0, 0.0, 0.45, 0.45) (0.2, 0.2, 1.0)
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (0.5, 0.1, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.1, 0.5, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (0.5, 0.5, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/ext_shader_framebuffer_fetch/execution/integer-gles3.shader_test b/tests/spec/ext_shader_framebuffer_fetch/execution/integer-gles3.shader_test
new file mode 100644
index 000000000..4ce8d798b
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/execution/integer-gles3.shader_test
@@ -0,0 +1,47 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_EXT_shader_framebuffer_fetch
+
+[vertex shader]
+#version 300 es
+
+in vec4 vertex;
+out vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 300 es
+#extension GL_EXT_shader_framebuffer_fetch : enable
+#define SCALE 100
+
+in highp vec4 vcolor;
+inout highp ivec4 fcolor;
+
+void main()
+{
+ if (fcolor.x <= SCALE / 2 && fcolor.y <= SCALE / 2)
+ fcolor += ivec4(vcolor * float(SCALE));
+ else
+ fcolor += ivec4((vcolor.x >= 0.5 ? SCALE : 0) - int(vcolor.x * float(SCALE)),
+ (vcolor.y >= 0.5 ? SCALE : 0) - int(vcolor.y * float(SCALE)),
+ 0, 0);
+}
+
+[test]
+texture storage 0 2D GL_RGBA8I (1 250 250)
+fb tex 2d 0
+
+clear color 0 0 1 0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+relative probe rect rgba int (0.55, 0.0, 0.45, 0.45) (100, 0, 127, 100)
+relative probe rect rgba int (0.0, 0.55, 0.45, 0.45) (0, 100, 127, 100)
+relative probe rect rgba int (0.55, 0.55, 0.45, 0.45) (100, 100, 127, 100)
diff --git a/tests/spec/ext_shader_framebuffer_fetch/execution/mrt-gles2.shader_test b/tests/spec/ext_shader_framebuffer_fetch/execution/mrt-gles2.shader_test
new file mode 100644
index 000000000..fb39d0cdf
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/execution/mrt-gles2.shader_test
@@ -0,0 +1,42 @@
+[require]
+GL ES >= 2.0
+GLSL ES >= 1.00
+GL_EXT_shader_framebuffer_fetch
+
+[vertex shader passthrough]
+
+[fragment shader]
+#version 100
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+void main()
+{
+ gl_FragData[0] = gl_LastFragData[0] + vec4(0.5, 0.0, 0.0, 0.0);
+ gl_FragData[1] = gl_LastFragData[1] + vec4(0.0, 0.5, 0.0, 0.0);
+ gl_FragData[2] = gl_LastFragData[2] + vec4(0.5, 0.5, 0.0, 0.0);
+ gl_FragData[3] = gl_LastFragData[3] + vec4(0.0, 0.0, 0.5, 0.0);
+}
+
+[test]
+texture rgbw 0 (250, 250) GL_RGBA8
+texture rgbw 1 (250, 250) GL_RGBA8
+texture rgbw 2 (250, 250) GL_RGBA8
+texture rgbw 3 (250, 250) GL_RGBA8
+fb tex multi 0 1 2 3
+
+clear color 0.0 0.0 0.5 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+fb tex 2d 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0.0, 0.5)
+
+fb tex 2d 1
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 1.0, 0.5)
+
+fb tex 2d 2
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 1.0, 0.5)
+
+fb tex 2d 3
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 0.0, 1.0)
diff --git a/tests/spec/ext_shader_framebuffer_fetch/execution/mrt-gles3.shader_test b/tests/spec/ext_shader_framebuffer_fetch/execution/mrt-gles3.shader_test
new file mode 100644
index 000000000..dcba251c5
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/execution/mrt-gles3.shader_test
@@ -0,0 +1,47 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_EXT_shader_framebuffer_fetch
+
+[vertex shader passthrough]
+
+[fragment shader]
+#version 300 es
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+inout highp vec4 fcolor[4];
+
+void main()
+{
+ fcolor[0] += vec4(0.5, 0.0, 0.0, 0.0);
+ fcolor[1] += vec4(0.0, 0.5, 0.0, 0.0);
+ fcolor[2] += vec4(0.5, 0.5, 0.0, 0.0);
+ fcolor[3] += vec4(0.0, 0.0, 0.5, 0.0);
+}
+
+[test]
+texture rgbw 0 (250, 250) GL_RGBA8
+texture rgbw 1 (250, 250) GL_RGBA8
+texture rgbw 2 (250, 250) GL_RGBA8
+texture rgbw 3 (250, 250) GL_RGBA8
+fb tex multi 0 1 2 3
+
+clear color 0.0 0.0 0.5 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+fb tex 2d 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0.0, 0.5)
+
+fb tex 2d 1
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 1.0, 0.5)
+
+fb tex 2d 2
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 1.0, 0.5)
+
+fb tex 2d 3
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 0.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/ext_shader_framebuffer_fetch/execution/ms16-gles3.shader_test b/tests/spec/ext_shader_framebuffer_fetch/execution/ms16-gles3.shader_test
new file mode 100644
index 000000000..0d5def12c
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/execution/ms16-gles3.shader_test
@@ -0,0 +1,53 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_EXT_shader_framebuffer_fetch
+INT GL_MAX_SAMPLES >= 16
+
+[vertex shader]
+#version 300 es
+
+in highp vec4 vertex;
+out highp vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 300 es
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+in highp vec4 vcolor;
+inout highp vec4 fcolor;
+
+void main()
+{
+ if (fcolor.x <= 0.5 && fcolor.y <= 0.5)
+ fcolor += vcolor;
+ else
+ fcolor += vec4((vcolor.x >= 0.5 ? 1.0 : 0.0) - vcolor.x,
+ (vcolor.y >= 0.5 ? 1.0 : 0.0) - vcolor.y, 0, 0);
+}
+
+[test]
+fb ms GL_RGBA8 250 250 16
+
+clear color 0.0 0.0 1.0 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+texture rgbw 0 (250, 250) GL_RGBA8
+fb draw tex 2d 0
+blit color linear
+fb read tex 2d 0
+
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (1.0, 0.0, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.0, 1.0, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (1.0, 1.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/ext_shader_framebuffer_fetch/execution/ms2-gles3.shader_test b/tests/spec/ext_shader_framebuffer_fetch/execution/ms2-gles3.shader_test
new file mode 100644
index 000000000..9a3168aca
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/execution/ms2-gles3.shader_test
@@ -0,0 +1,53 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_EXT_shader_framebuffer_fetch
+INT GL_MAX_SAMPLES >= 2
+
+[vertex shader]
+#version 300 es
+
+in vec4 vertex;
+out vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 300 es
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+in highp vec4 vcolor;
+inout highp vec4 fcolor;
+
+void main()
+{
+ if (fcolor.x <= 0.5 && fcolor.y <= 0.5)
+ fcolor += vcolor;
+ else
+ fcolor += vec4((vcolor.x >= 0.5 ? 1.0 : 0.0) - vcolor.x,
+ (vcolor.y >= 0.5 ? 1.0 : 0.0) - vcolor.y, 0, 0);
+}
+
+[test]
+fb ms GL_RGBA8 250 250 2
+
+clear color 0.0 0.0 1.0 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+texture rgbw 0 (250, 250) GL_RGBA8
+fb draw tex 2d 0
+blit color linear
+fb read tex 2d 0
+
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (1.0, 0.0, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.0, 1.0, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (1.0, 1.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/ext_shader_framebuffer_fetch/execution/ms2-integer-gles3.shader_test b/tests/spec/ext_shader_framebuffer_fetch/execution/ms2-integer-gles3.shader_test
new file mode 100644
index 000000000..c3f7a12f0
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/execution/ms2-integer-gles3.shader_test
@@ -0,0 +1,52 @@
+[require]
+GL ES >= 3.1
+GLSL ES >= 3.00
+GL_EXT_shader_framebuffer_fetch
+INT GL_MAX_SAMPLES >= 2
+
+[vertex shader]
+#version 300 es
+
+in vec4 vertex;
+out vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 300 es
+#extension GL_EXT_shader_framebuffer_fetch : enable
+#define SCALE 100
+
+in highp vec4 vcolor;
+inout highp ivec4 fcolor;
+
+void main()
+{
+ if (fcolor.x <= SCALE / 2 && fcolor.y <= SCALE / 2)
+ fcolor += ivec4(vcolor * float(SCALE));
+ else
+ fcolor += ivec4((vcolor.x >= 0.5 ? SCALE : 0) - int(vcolor.x * float(SCALE)),
+ (vcolor.y >= 0.5 ? SCALE : 0) - int(vcolor.y * float(SCALE)),
+ 0, 0);
+}
+
+[test]
+fb ms GL_RGBA8I 250 250 2
+
+clear color 0 0 1 0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+texture storage 0 2D GL_RGBA8I (1 250 250)
+fb draw tex 2d 0
+blit color nearest
+fb read tex 2d 0
+
+relative probe rect rgba int (0.55, 0.0, 0.45, 0.45) (100, 0, 127, 100)
+relative probe rect rgba int (0.0, 0.55, 0.45, 0.45) (0, 100, 127, 100)
+relative probe rect rgba int (0.55, 0.55, 0.45, 0.45) (100, 100, 127, 100)
diff --git a/tests/spec/ext_shader_framebuffer_fetch/execution/ms8-gles3.shader_test b/tests/spec/ext_shader_framebuffer_fetch/execution/ms8-gles3.shader_test
new file mode 100644
index 000000000..cabbd68c4
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/execution/ms8-gles3.shader_test
@@ -0,0 +1,53 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_EXT_shader_framebuffer_fetch
+INT GL_MAX_SAMPLES >= 8
+
+[vertex shader]
+#version 300 es
+
+in vec4 vertex;
+out vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 300 es
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+in highp vec4 vcolor;
+inout highp vec4 fcolor;
+
+void main()
+{
+ if (fcolor.x <= 0.5 && fcolor.y <= 0.5)
+ fcolor += vcolor;
+ else
+ fcolor += vec4((vcolor.x >= 0.5 ? 1.0 : 0.0) - vcolor.x,
+ (vcolor.y >= 0.5 ? 1.0 : 0.0) - vcolor.y, 0, 0);
+}
+
+[test]
+fb ms GL_RGBA8 250 250 8
+
+clear color 0.0 0.0 1.0 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+texture rgbw 0 (250, 250) GL_RGBA8
+fb draw tex 2d 0
+blit color linear
+fb read tex 2d 0
+
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (1.0, 0.0, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.0, 1.0, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (1.0, 1.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/ext_shader_framebuffer_fetch/execution/ms8-integer-gles3.shader_test b/tests/spec/ext_shader_framebuffer_fetch/execution/ms8-integer-gles3.shader_test
new file mode 100644
index 000000000..2988d657e
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/execution/ms8-integer-gles3.shader_test
@@ -0,0 +1,52 @@
+[require]
+GL ES >= 3.1
+GLSL ES >= 3.00
+GL_EXT_shader_framebuffer_fetch
+INT GL_MAX_SAMPLES >= 8
+
+[vertex shader]
+#version 300 es
+
+in vec4 vertex;
+out vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 300 es
+#extension GL_EXT_shader_framebuffer_fetch : enable
+#define SCALE 100
+
+in highp vec4 vcolor;
+inout highp ivec4 fcolor;
+
+void main()
+{
+ if (fcolor.x <= SCALE / 2 && fcolor.y <= SCALE / 2)
+ fcolor += ivec4(vcolor * float(SCALE));
+ else
+ fcolor += ivec4((vcolor.x >= 0.5 ? SCALE : 0) - int(vcolor.x * float(SCALE)),
+ (vcolor.y >= 0.5 ? SCALE : 0) - int(vcolor.y * float(SCALE)),
+ 0, 0);
+}
+
+[test]
+fb ms GL_RGBA8I 250 250 8
+
+clear color 0 0 1 0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+texture storage 0 2D GL_RGBA8I (1 250 250)
+fb draw tex 2d 0
+blit color nearest
+fb read tex 2d 0
+
+relative probe rect rgba int (0.55, 0.0, 0.45, 0.45) (100, 0, 127, 100)
+relative probe rect rgba int (0.0, 0.55, 0.45, 0.45) (0, 100, 127, 100)
+relative probe rect rgba int (0.55, 0.55, 0.45, 0.45) (100, 100, 127, 100)
diff --git a/tests/spec/ext_shader_framebuffer_fetch/execution/nonuniform-gles2.shader_test b/tests/spec/ext_shader_framebuffer_fetch/execution/nonuniform-gles2.shader_test
new file mode 100644
index 000000000..db9f216d9
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/execution/nonuniform-gles2.shader_test
@@ -0,0 +1,45 @@
+[require]
+GL ES >= 2.0
+GLSL ES >= 1.00
+GL_EXT_shader_framebuffer_fetch
+
+[vertex shader]
+#version 100
+
+attribute highp vec4 vertex;
+varying highp vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 100
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+varying highp vec4 vcolor;
+
+void main()
+{
+ if (gl_LastFragData[0].x <= 0.5 && gl_LastFragData[0].y <= 0.5)
+ gl_FragData[0] = gl_LastFragData[0] + vcolor;
+ else
+ gl_FragData[0] = gl_LastFragData[0] +
+ vec4((vcolor.x >= 0.5 ? 1.0 : 0.0) - vcolor.x,
+ (vcolor.y >= 0.5 ? 1.0 : 0.0) - vcolor.y, 0, 0);
+}
+
+[test]
+texture rgbw 0 (250, 250) GL_RGBA8
+fb tex 2d 0
+
+clear color 0.0 0.0 1.0 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (1.0, 0.0, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.0, 1.0, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (1.0, 1.0, 1.0)
diff --git a/tests/spec/ext_shader_framebuffer_fetch/execution/nonuniform-gles3.shader_test b/tests/spec/ext_shader_framebuffer_fetch/execution/nonuniform-gles3.shader_test
new file mode 100644
index 000000000..a75da2766
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/execution/nonuniform-gles3.shader_test
@@ -0,0 +1,48 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_EXT_shader_framebuffer_fetch
+
+[vertex shader]
+#version 300 es
+
+in vec4 vertex;
+out vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 300 es
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+in highp vec4 vcolor;
+inout highp vec4 fcolor;
+
+void main()
+{
+ if (fcolor.x <= 0.5 && fcolor.y <= 0.5)
+ fcolor += vcolor;
+ else
+ fcolor += vec4((vcolor.x >= 0.5 ? 1.0 : 0.0) - vcolor.x,
+ (vcolor.y >= 0.5 ? 1.0 : 0.0) - vcolor.y, 0, 0);
+}
+
+[test]
+texture rgbw 0 (250, 250) GL_RGBA8
+fb tex 2d 0
+
+clear color 0.0 0.0 1.0 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (1.0, 0.0, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.0, 1.0, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (1.0, 1.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/ext_shader_framebuffer_fetch/execution/overwrite-gles3.shader_test b/tests/spec/ext_shader_framebuffer_fetch/execution/overwrite-gles3.shader_test
new file mode 100644
index 000000000..35d5208a0
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/execution/overwrite-gles3.shader_test
@@ -0,0 +1,48 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_EXT_shader_framebuffer_fetch
+
+[vertex shader]
+#version 300 es
+
+in vec4 vertex;
+out vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 300 es
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+in highp vec4 vcolor;
+inout highp vec4 fcolor;
+
+void main()
+{
+ if (vcolor.x >= 0.5 || vcolor.y >= 0.5)
+ fcolor += vec4(0.5, 0, 0, 0);
+
+ fcolor += vec4(0.0, 0.5, 0, 0);
+}
+
+[test]
+texture rgbw 0 (250, 250) GL_RGBA8
+fb tex 2d 0
+
+clear color 0.0 0.0 1.0 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+relative probe rect rgb (0.0, 0.0, 0.45, 0.45) (0.0, 1.0, 1.0)
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (1.0, 1.0, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (1.0, 1.0, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (1.0, 1.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/ext_shader_framebuffer_fetch/execution/redeclared-highp-gles2.shader_test b/tests/spec/ext_shader_framebuffer_fetch/execution/redeclared-highp-gles2.shader_test
new file mode 100644
index 000000000..f41fcf2b0
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/execution/redeclared-highp-gles2.shader_test
@@ -0,0 +1,46 @@
+[require]
+GL ES >= 2.0
+GLSL ES >= 1.00
+GL_EXT_shader_framebuffer_fetch
+
+[vertex shader]
+#version 100
+
+attribute highp vec4 vertex;
+varying highp vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 100
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+highp vec4 gl_LastFragData[gl_MaxDrawBuffers];
+varying highp vec4 vcolor;
+
+void main()
+{
+ if (gl_LastFragData[0].x <= 0.5 && gl_LastFragData[0].y <= 0.5)
+ gl_FragData[0] = gl_LastFragData[0] + vcolor;
+ else
+ gl_FragData[0] = gl_LastFragData[0] +
+ vec4((vcolor.x >= 0.5 ? 1.0 : 0.0) - vcolor.x,
+ (vcolor.y >= 0.5 ? 1.0 : 0.0) - vcolor.y, 0, 0);
+}
+
+[test]
+texture rgbw 0 (250, 250) GL_RGBA8
+fb tex 2d 0
+
+clear color 0.0 0.0 1.0 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (1.0, 0.0, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.0, 1.0, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (1.0, 1.0, 1.0)
diff --git a/tests/spec/ext_shader_framebuffer_fetch/execution/redeclared-lowp-gles2.shader_test b/tests/spec/ext_shader_framebuffer_fetch/execution/redeclared-lowp-gles2.shader_test
new file mode 100644
index 000000000..c9ecf2605
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/execution/redeclared-lowp-gles2.shader_test
@@ -0,0 +1,46 @@
+[require]
+GL ES >= 2.0
+GLSL ES >= 1.00
+GL_EXT_shader_framebuffer_fetch
+
+[vertex shader]
+#version 100
+
+attribute highp vec4 vertex;
+varying highp vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 100
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+lowp vec4 gl_LastFragData[gl_MaxDrawBuffers];
+varying highp vec4 vcolor;
+
+void main()
+{
+ if (gl_LastFragData[0].x <= 0.5 && gl_LastFragData[0].y <= 0.5)
+ gl_FragData[0] = gl_LastFragData[0] + vcolor;
+ else
+ gl_FragData[0] = gl_LastFragData[0] +
+ vec4((vcolor.x >= 0.5 ? 1.0 : 0.0) - vcolor.x,
+ (vcolor.y >= 0.5 ? 1.0 : 0.0) - vcolor.y, 0, 0);
+}
+
+[test]
+texture rgbw 0 (250, 250) GL_RGBA8
+fb tex 2d 0
+
+clear color 0.0 0.0 1.0 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (1.0, 0.0, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.0, 1.0, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (1.0, 1.0, 1.0)
diff --git a/tests/spec/ext_shader_framebuffer_fetch/execution/redeclared-mediump-gles2.shader_test b/tests/spec/ext_shader_framebuffer_fetch/execution/redeclared-mediump-gles2.shader_test
new file mode 100644
index 000000000..9484f35d0
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/execution/redeclared-mediump-gles2.shader_test
@@ -0,0 +1,46 @@
+[require]
+GL ES >= 2.0
+GLSL ES >= 1.00
+GL_EXT_shader_framebuffer_fetch
+
+[vertex shader]
+#version 100
+
+attribute highp vec4 vertex;
+varying highp vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 100
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+mediump vec4 gl_LastFragData[gl_MaxDrawBuffers];
+varying highp vec4 vcolor;
+
+void main()
+{
+ if (gl_LastFragData[0].x <= 0.5 && gl_LastFragData[0].y <= 0.5)
+ gl_FragData[0] = gl_LastFragData[0] + vcolor;
+ else
+ gl_FragData[0] = gl_LastFragData[0] +
+ vec4((vcolor.x >= 0.5 ? 1.0 : 0.0) - vcolor.x,
+ (vcolor.y >= 0.5 ? 1.0 : 0.0) - vcolor.y, 0, 0);
+}
+
+[test]
+texture rgbw 0 (250, 250) GL_RGBA8
+fb tex 2d 0
+
+clear color 0.0 0.0 1.0 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (1.0, 0.0, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.0, 1.0, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (1.0, 1.0, 1.0)
diff --git a/tests/spec/ext_shader_framebuffer_fetch/execution/simple-gles3.shader_test b/tests/spec/ext_shader_framebuffer_fetch/execution/simple-gles3.shader_test
new file mode 100644
index 000000000..83c71e4ff
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/execution/simple-gles3.shader_test
@@ -0,0 +1,31 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_EXT_shader_framebuffer_fetch
+
+[vertex shader passthrough]
+
+[fragment shader]
+#version 300 es
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+inout highp vec4 fcolor;
+
+void main()
+{
+ fcolor += vec4(0.5, 0.0, 0.0, 0.0);
+}
+
+[test]
+texture rgbw 0 (250, 250) GL_RGBA8
+fb tex 2d 0
+
+clear color 0.0 0.0 1.0 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+relative probe rect rgb (0, 0.0, 1.0, 1.0) (1.0, 0.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/ext_shader_framebuffer_fetch/execution/single-2d-level-gles3.shader_test b/tests/spec/ext_shader_framebuffer_fetch/execution/single-2d-level-gles3.shader_test
new file mode 100644
index 000000000..9f721db07
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/execution/single-2d-level-gles3.shader_test
@@ -0,0 +1,63 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_EXT_shader_framebuffer_fetch
+
+[vertex shader passthrough]
+[fragment shader]
+#version 300 es
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+inout highp vec4 fcolor;
+uniform highp vec4 ucolor;
+
+void main()
+{
+ fcolor += ucolor;
+}
+
+[test]
+texture storage 0 2DArray GL_RGBA8 (4 250 250 1)
+
+fb tex slice 2DArray 0 0 0
+uniform vec4 ucolor 0.5 0.0 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+fb tex slice 2DArray 0 1 0
+uniform vec4 ucolor 0.0 0.5 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+fb tex slice 2DArray 0 2 0
+uniform vec4 ucolor 0.5 0.5 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+fb tex slice 2DArray 0 3 0
+uniform vec4 ucolor 0.0 0.0 0.5 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+fb tex slice 2DArray 0 0 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0.0, 0.5)
+
+fb tex slice 2DArray 0 1 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 1.0, 0.5)
+
+fb tex slice 2DArray 0 2 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 1.0, 0.5)
+
+fb tex slice 2DArray 0 3 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 0.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/ext_shader_framebuffer_fetch/execution/single-2darray-layer-gles3.shader_test b/tests/spec/ext_shader_framebuffer_fetch/execution/single-2darray-layer-gles3.shader_test
new file mode 100644
index 000000000..20d071226
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/execution/single-2darray-layer-gles3.shader_test
@@ -0,0 +1,63 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_EXT_shader_framebuffer_fetch
+
+[vertex shader passthrough]
+[fragment shader]
+#version 300 es
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+inout highp vec4 fcolor;
+uniform highp vec4 ucolor;
+
+void main()
+{
+ fcolor += ucolor;
+}
+
+[test]
+texture storage 0 2DArray GL_RGBA8 (1 250 250 4)
+
+fb tex slice 2DArray 0 0 0
+uniform vec4 ucolor 0.5 0.0 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+fb tex slice 2DArray 0 0 1
+uniform vec4 ucolor 0.0 0.5 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+fb tex slice 2DArray 0 0 2
+uniform vec4 ucolor 0.5 0.5 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+fb tex slice 2DArray 0 0 3
+uniform vec4 ucolor 0.0 0.0 0.5 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+fb tex slice 2DArray 0 0 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0.0, 0.5)
+
+fb tex slice 2DArray 0 0 1
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 1.0, 0.5)
+
+fb tex slice 2DArray 0 0 2
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 1.0, 0.5)
+
+fb tex slice 2DArray 0 0 3
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 0.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/ext_shader_framebuffer_fetch/execution/single-3d-layer-gles3.shader_test b/tests/spec/ext_shader_framebuffer_fetch/execution/single-3d-layer-gles3.shader_test
new file mode 100644
index 000000000..42e0e4655
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/execution/single-3d-layer-gles3.shader_test
@@ -0,0 +1,63 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_EXT_shader_framebuffer_fetch
+
+[vertex shader passthrough]
+[fragment shader]
+#version 300 es
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+inout highp vec4 fcolor;
+uniform highp vec4 ucolor;
+
+void main()
+{
+ fcolor += ucolor;
+}
+
+[test]
+texture storage 0 3D GL_RGBA8 (1 250 250 4)
+
+fb tex slice 3D 0 0 0
+uniform vec4 ucolor 0.5 0.0 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+fb tex slice 3D 0 0 1
+uniform vec4 ucolor 0.0 0.5 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+fb tex slice 3D 0 0 2
+uniform vec4 ucolor 0.5 0.5 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+fb tex slice 3D 0 0 3
+uniform vec4 ucolor 0.0 0.0 0.5 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+fb tex slice 3D 0 0 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0.0, 0.5)
+
+fb tex slice 3D 0 0 1
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 1.0, 0.5)
+
+fb tex slice 3D 0 0 2
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 1.0, 0.5)
+
+fb tex slice 3D 0 0 3
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 0.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/ext_shader_framebuffer_fetch/execution/single-cubemap-layer-gles3.shader_test b/tests/spec/ext_shader_framebuffer_fetch/execution/single-cubemap-layer-gles3.shader_test
new file mode 100644
index 000000000..6a488f3d4
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/execution/single-cubemap-layer-gles3.shader_test
@@ -0,0 +1,63 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_EXT_shader_framebuffer_fetch
+
+[vertex shader passthrough]
+[fragment shader]
+#version 300 es
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+inout highp vec4 fcolor;
+uniform highp vec4 ucolor;
+
+void main()
+{
+ fcolor += ucolor;
+}
+
+[test]
+texture storage 0 Cube GL_RGBA8 (1 250 250)
+
+fb tex slice Cube 0 0 0
+uniform vec4 ucolor 0.5 0.0 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+fb tex slice Cube 0 0 1
+uniform vec4 ucolor 0.0 0.5 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+fb tex slice Cube 0 0 2
+uniform vec4 ucolor 0.5 0.5 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+fb tex slice Cube 0 0 3
+uniform vec4 ucolor 0.0 0.0 0.5 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+fb tex slice Cube 0 0 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0.0, 0.5)
+
+fb tex slice Cube 0 0 1
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 1.0, 0.5)
+
+fb tex slice Cube 0 0 2
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 1.0, 0.5)
+
+fb tex slice Cube 0 0 3
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 0.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/ext_shader_framebuffer_fetch/execution/texture-gles3.shader_test b/tests/spec/ext_shader_framebuffer_fetch/execution/texture-gles3.shader_test
new file mode 100644
index 000000000..807e12f42
--- /dev/null
+++ b/tests/spec/ext_shader_framebuffer_fetch/execution/texture-gles3.shader_test
@@ -0,0 +1,38 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_EXT_shader_framebuffer_fetch
+
+[vertex shader passthrough]
+
+[fragment shader]
+#version 300 es
+#extension GL_EXT_shader_framebuffer_fetch : enable
+
+uniform sampler2D s;
+inout highp vec4 fcolor;
+
+void main()
+{
+ fcolor += texelFetch(s, ivec2(gl_FragCoord), 0) / 4.0;
+}
+
+[test]
+texture rgbw 0 (250, 250) GL_RGBA8
+fb tex 2d 0
+
+texture rgbw 1 (250, 250) GL_RGBA8
+uniform int s 1
+
+clear color 0.5 0.0 0.0 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+relative probe rect rgb (0.0, 0.0, 0.45, 0.45) (1.0, 0.0, 0.0)
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (0.5, 0.5, 0.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.5, 0.0, 0.5)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (1.0, 0.5, 0.5)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/coherent-1d-gl32.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/coherent-1d-gl32.shader_test
new file mode 100644
index 000000000..9cd8fa743
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/coherent-1d-gl32.shader_test
@@ -0,0 +1,48 @@
+[require]
+GL >= 3.2
+GLSL >= 1.50
+GL_MESA_shader_framebuffer_fetch
+GL_ARB_texture_storage
+
+[vertex shader]
+#version 150
+
+in vec4 vertex;
+out vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, 0.7, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 150
+#extension GL_MESA_shader_framebuffer_fetch : enable
+
+in highp vec4 vcolor;
+inout highp vec4 fcolor;
+
+void main()
+{
+ if (fcolor.x <= 0.5 && fcolor.y <= 0.5)
+ fcolor += vcolor;
+ else
+ fcolor += vec4((vcolor.x >= 0.5 ? 1.0 : 0.0) - vcolor.x,
+ (vcolor.y >= 0.5 ? 1.0 : 0.0) - vcolor.y, 0, 0);
+}
+
+[test]
+texture storage 0 1D GL_RGBA8 (1 250)
+fb tex slice 1D 0 0 0
+
+clear color 0.0 0.0 1.0 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+relative probe rect rgb (0.0, 0.0, 0.45, 1.0) (0.0, 1.0, 1.0)
+relative probe rect rgb (0.55, 0.0, 0.45, 1.0) (1.0, 1.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/coherent-layered-1darray-gl32.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/coherent-layered-1darray-gl32.shader_test
new file mode 100644
index 000000000..22464c000
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/coherent-layered-1darray-gl32.shader_test
@@ -0,0 +1,65 @@
+[require]
+GL >= 3.2
+GLSL >= 1.50
+GL_MESA_shader_framebuffer_fetch
+GL_ARB_texture_storage
+
+[vertex shader passthrough]
+[geometry shader]
+#version 150
+
+layout(triangles) in;
+layout(triangle_strip, max_vertices=12) out;
+
+flat out int glayer;
+
+void main()
+{
+ for (int layer = 0; layer < 4; layer++) {
+ for (int i = 0; i < 3; i++) {
+ gl_Position = gl_in[i].gl_Position;
+ gl_Layer = glayer = layer;
+ EmitVertex();
+ }
+ EndPrimitive();
+ }
+}
+
+[fragment shader]
+#version 150
+#extension GL_MESA_shader_framebuffer_fetch : enable
+
+flat in int glayer;
+inout highp vec4 fcolor;
+
+void main()
+{
+ fcolor += (glayer == 3 ? vec4(0.0, 0.0, 0.5, 0.0) :
+ glayer == 2 ? vec4(0.5, 0.5, 0.0, 0.0) :
+ glayer == 1 ? vec4(0.0, 0.5, 0.0, 0.0) :
+ vec4(0.5, 0.0, 0.0, 0.0));
+}
+
+[test]
+texture storage 0 1DArray GL_RGBA8 (1 250 4)
+fb tex layered 0
+
+clear color 0.0 0.0 0.5 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+fb tex slice 1DArray 0 0 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0.0, 0.5)
+
+fb tex slice 1DArray 0 0 1
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 1.0, 0.5)
+
+fb tex slice 1DArray 0 0 2
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 1.0, 0.5)
+
+fb tex slice 1DArray 0 0 3
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 0.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/coherent-layered-2darray-gl32.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/coherent-layered-2darray-gl32.shader_test
new file mode 100644
index 000000000..e762bee75
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/coherent-layered-2darray-gl32.shader_test
@@ -0,0 +1,65 @@
+[require]
+GL >= 3.2
+GLSL >= 1.50
+GL_MESA_shader_framebuffer_fetch
+GL_ARB_texture_storage
+
+[vertex shader passthrough]
+[geometry shader]
+#version 150
+
+layout(triangles) in;
+layout(triangle_strip, max_vertices=12) out;
+
+flat out int glayer;
+
+void main()
+{
+ for (int layer = 0; layer < 4; layer++) {
+ for (int i = 0; i < 3; i++) {
+ gl_Position = gl_in[i].gl_Position;
+ gl_Layer = glayer = layer;
+ EmitVertex();
+ }
+ EndPrimitive();
+ }
+}
+
+[fragment shader]
+#version 150
+#extension GL_MESA_shader_framebuffer_fetch : enable
+
+flat in int glayer;
+inout highp vec4 fcolor;
+
+void main()
+{
+ fcolor += (glayer == 3 ? vec4(0.0, 0.0, 0.5, 0.0) :
+ glayer == 2 ? vec4(0.5, 0.5, 0.0, 0.0) :
+ glayer == 1 ? vec4(0.0, 0.5, 0.0, 0.0) :
+ vec4(0.5, 0.0, 0.0, 0.0));
+}
+
+[test]
+texture storage 0 2DArray GL_RGBA8 (1 250 250 4)
+fb tex layered 0
+
+clear color 0.0 0.0 0.5 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+fb tex slice 2DArray 0 0 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0.0, 0.5)
+
+fb tex slice 2DArray 0 0 1
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 1.0, 0.5)
+
+fb tex slice 2DArray 0 0 2
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 1.0, 0.5)
+
+fb tex slice 2DArray 0 0 3
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 0.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/coherent-layered-cubemap-gl32.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/coherent-layered-cubemap-gl32.shader_test
new file mode 100644
index 000000000..eba5376cf
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/coherent-layered-cubemap-gl32.shader_test
@@ -0,0 +1,73 @@
+[require]
+GL >= 3.2
+GLSL >= 1.50
+GL_MESA_shader_framebuffer_fetch
+GL_ARB_texture_storage
+
+[vertex shader passthrough]
+[geometry shader]
+#version 150
+
+layout(triangles) in;
+layout(triangle_strip, max_vertices=18) out;
+
+flat out int glayer;
+
+void main()
+{
+ for (int layer = 0; layer < 6; layer++) {
+ for (int i = 0; i < 3; i++) {
+ gl_Position = gl_in[i].gl_Position;
+ gl_Layer = glayer = layer;
+ EmitVertex();
+ }
+ EndPrimitive();
+ }
+}
+
+[fragment shader]
+#version 150
+#extension GL_MESA_shader_framebuffer_fetch : enable
+
+flat in int glayer;
+inout highp vec4 fcolor;
+
+void main()
+{
+ fcolor += (glayer == 5 ? vec4(0.0, 0.5, 0.5, 0.0) :
+ glayer == 4 ? vec4(0.5, 0.0, 0.5, 0.0) :
+ glayer == 3 ? vec4(0.0, 0.0, 0.5, 0.0) :
+ glayer == 2 ? vec4(0.5, 0.5, 0.0, 0.0) :
+ glayer == 1 ? vec4(0.0, 0.5, 0.0, 0.0) :
+ vec4(0.5, 0.0, 0.0, 0.0));
+}
+
+[test]
+texture storage 0 Cube GL_RGBA8 (1 250 250)
+fb tex layered 0
+
+clear color 0.0 0.0 0.5 0.0
+clear
+draw rect -1 -1 2 2
+draw rect -1 -1 2 2
+
+fb tex slice Cube 0 0 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0.0, 0.5)
+
+fb tex slice Cube 0 0 1
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 1.0, 0.5)
+
+fb tex slice Cube 0 0 2
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 1.0, 0.5)
+
+fb tex slice Cube 0 0 3
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 0.0, 1.0)
+
+fb tex slice Cube 0 0 4
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0.0, 1.0)
+
+fb tex slice Cube 0 0 5
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 1.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-1d-gl32.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-1d-gl32.shader_test
new file mode 100644
index 000000000..2539d4c16
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-1d-gl32.shader_test
@@ -0,0 +1,50 @@
+[require]
+GL >= 3.2
+GLSL >= 1.50
+GL_MESA_shader_framebuffer_fetch_non_coherent
+GL_ARB_texture_storage
+
+[vertex shader]
+#version 150
+
+in vec4 vertex;
+out vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, 0.7, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 150
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+in highp vec4 vcolor;
+inout highp vec4 fcolor;
+
+void main()
+{
+ if (fcolor.x <= 0.5 && fcolor.y <= 0.5)
+ fcolor += vcolor;
+ else
+ fcolor += vec4((vcolor.x >= 0.5 ? 1.0 : 0.0) - vcolor.x,
+ (vcolor.y >= 0.5 ? 1.0 : 0.0) - vcolor.y, 0, 0);
+}
+
+[test]
+texture storage 0 1D GL_RGBA8 (1 250)
+fb tex slice 1D 0 0 0
+
+clear color 0.0 0.0 1.0 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+relative probe rect rgb (0.0, 0.0, 0.45, 1.0) (0.0, 1.0, 1.0)
+relative probe rect rgb (0.55, 0.0, 0.45, 1.0) (1.0, 1.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-discard-gles3.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-discard-gles3.shader_test
new file mode 100644
index 000000000..fc4ad1fe5
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-discard-gles3.shader_test
@@ -0,0 +1,51 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+
+[vertex shader]
+#version 300 es
+
+in vec4 vertex;
+out vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 300 es
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+in highp vec4 vcolor;
+inout highp vec4 fcolor;
+
+void main()
+{
+ if (fcolor.x <= 0.45 && fcolor.y < 0.45)
+ fcolor += vec4(vcolor.x >= 0.5 ? 0.5 : 0.1,
+ vcolor.y >= 0.5 ? 0.5 : 0.1, 0.0, 0.0);
+ else
+ discard;
+}
+
+[test]
+texture rgbw 0 (250, 250) GL_RGBA8
+fb tex 2d 0
+
+clear color 0.0 0.0 1.0 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+relative probe rect rgb (0.0, 0.0, 0.45, 0.45) (0.2, 0.2, 1.0)
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (0.5, 0.1, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.1, 0.5, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (0.5, 0.5, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-discard-ms2-gles3.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-discard-ms2-gles3.shader_test
new file mode 100644
index 000000000..0705acd55
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-discard-ms2-gles3.shader_test
@@ -0,0 +1,56 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+INT GL_MAX_SAMPLES >= 2
+
+[vertex shader]
+#version 300 es
+
+in vec4 vertex;
+out vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 300 es
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+in highp vec4 vcolor;
+inout highp vec4 fcolor;
+
+void main()
+{
+ if (fcolor.x <= 0.45 && fcolor.y < 0.45)
+ fcolor += vec4(vcolor.x >= 0.5 ? 0.5 : 0.1,
+ vcolor.y >= 0.5 ? 0.5 : 0.1, 0.0, 0.0);
+ else
+ discard;
+}
+
+[test]
+fb ms GL_RGBA8 250 250 2
+
+clear color 0.0 0.0 1.0 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+texture rgbw 0 (250, 250) GL_RGBA8
+fb draw tex 2d 0
+blit color linear
+fb read tex 2d 0
+
+relative probe rect rgb (0.0, 0.0, 0.45, 0.45) (0.2, 0.2, 1.0)
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (0.5, 0.1, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.1, 0.5, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (0.5, 0.5, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-discard-ms8-gles3.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-discard-ms8-gles3.shader_test
new file mode 100644
index 000000000..7310ef07d
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-discard-ms8-gles3.shader_test
@@ -0,0 +1,56 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+INT GL_MAX_SAMPLES >= 8
+
+[vertex shader]
+#version 300 es
+
+in vec4 vertex;
+out vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 300 es
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+in highp vec4 vcolor;
+inout highp vec4 fcolor;
+
+void main()
+{
+ if (fcolor.x <= 0.45 && fcolor.y < 0.45)
+ fcolor += vec4(vcolor.x >= 0.5 ? 0.5 : 0.1,
+ vcolor.y >= 0.5 ? 0.5 : 0.1, 0.0, 0.0);
+ else
+ discard;
+}
+
+[test]
+fb ms GL_RGBA8 250 250 8
+
+clear color 0.0 0.0 1.0 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+texture rgbw 0 (250, 250) GL_RGBA8
+fb draw tex 2d 0
+blit color linear
+fb read tex 2d 0
+
+relative probe rect rgb (0.0, 0.0, 0.45, 0.45) (0.2, 0.2, 1.0)
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (0.5, 0.1, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.1, 0.5, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (0.5, 0.5, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-integer-gles3.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-integer-gles3.shader_test
new file mode 100644
index 000000000..18e4974bc
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-integer-gles3.shader_test
@@ -0,0 +1,49 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+
+[vertex shader]
+#version 300 es
+
+in vec4 vertex;
+out vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 300 es
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+#define SCALE 100
+
+in highp vec4 vcolor;
+inout highp ivec4 fcolor;
+
+void main()
+{
+ if (fcolor.x <= SCALE / 2 && fcolor.y <= SCALE / 2)
+ fcolor += ivec4(vcolor * float(SCALE));
+ else
+ fcolor += ivec4((vcolor.x >= 0.5 ? SCALE : 0) - int(vcolor.x * float(SCALE)),
+ (vcolor.y >= 0.5 ? SCALE : 0) - int(vcolor.y * float(SCALE)),
+ 0, 0);
+}
+
+[test]
+texture storage 0 2D GL_RGBA8I (1 250 250)
+fb tex 2d 0
+
+clear color 0 0 1 0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+relative probe rect rgba int (0.55, 0.0, 0.45, 0.45) (100, 0, 127, 100)
+relative probe rect rgba int (0.0, 0.55, 0.45, 0.45) (0, 100, 127, 100)
+relative probe rect rgba int (0.55, 0.55, 0.45, 0.45) (100, 100, 127, 100)
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-layered-1darray-gl32.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-layered-1darray-gl32.shader_test
new file mode 100644
index 000000000..c978397b2
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-layered-1darray-gl32.shader_test
@@ -0,0 +1,67 @@
+[require]
+GL >= 3.2
+GLSL >= 1.50
+GL_MESA_shader_framebuffer_fetch_non_coherent
+GL_ARB_texture_storage
+
+[vertex shader passthrough]
+[geometry shader]
+#version 150
+
+layout(triangles) in;
+layout(triangle_strip, max_vertices=12) out;
+
+flat out int glayer;
+
+void main()
+{
+ for (int layer = 0; layer < 4; layer++) {
+ for (int i = 0; i < 3; i++) {
+ gl_Position = gl_in[i].gl_Position;
+ gl_Layer = glayer = layer;
+ EmitVertex();
+ }
+ EndPrimitive();
+ }
+}
+
+[fragment shader]
+#version 150
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+flat in int glayer;
+inout highp vec4 fcolor;
+
+void main()
+{
+ fcolor += (glayer == 3 ? vec4(0.0, 0.0, 0.5, 0.0) :
+ glayer == 2 ? vec4(0.5, 0.5, 0.0, 0.0) :
+ glayer == 1 ? vec4(0.0, 0.5, 0.0, 0.0) :
+ vec4(0.5, 0.0, 0.0, 0.0));
+}
+
+[test]
+texture storage 0 1DArray GL_RGBA8 (1 250 4)
+fb tex layered 0
+
+clear color 0.0 0.0 0.5 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+fb tex slice 1DArray 0 0 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0.0, 0.5)
+
+fb tex slice 1DArray 0 0 1
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 1.0, 0.5)
+
+fb tex slice 1DArray 0 0 2
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 1.0, 0.5)
+
+fb tex slice 1DArray 0 0 3
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 0.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-layered-2darray-gl32.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-layered-2darray-gl32.shader_test
new file mode 100644
index 000000000..06f7fa652
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-layered-2darray-gl32.shader_test
@@ -0,0 +1,67 @@
+[require]
+GL >= 3.2
+GLSL >= 1.50
+GL_MESA_shader_framebuffer_fetch_non_coherent
+GL_ARB_texture_storage
+
+[vertex shader passthrough]
+[geometry shader]
+#version 150
+
+layout(triangles) in;
+layout(triangle_strip, max_vertices=12) out;
+
+flat out int glayer;
+
+void main()
+{
+ for (int layer = 0; layer < 4; layer++) {
+ for (int i = 0; i < 3; i++) {
+ gl_Position = gl_in[i].gl_Position;
+ gl_Layer = glayer = layer;
+ EmitVertex();
+ }
+ EndPrimitive();
+ }
+}
+
+[fragment shader]
+#version 150
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+flat in int glayer;
+inout highp vec4 fcolor;
+
+void main()
+{
+ fcolor += (glayer == 3 ? vec4(0.0, 0.0, 0.5, 0.0) :
+ glayer == 2 ? vec4(0.5, 0.5, 0.0, 0.0) :
+ glayer == 1 ? vec4(0.0, 0.5, 0.0, 0.0) :
+ vec4(0.5, 0.0, 0.0, 0.0));
+}
+
+[test]
+texture storage 0 2DArray GL_RGBA8 (1 250 250 4)
+fb tex layered 0
+
+clear color 0.0 0.0 0.5 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+fb tex slice 2DArray 0 0 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0.0, 0.5)
+
+fb tex slice 2DArray 0 0 1
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 1.0, 0.5)
+
+fb tex slice 2DArray 0 0 2
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 1.0, 0.5)
+
+fb tex slice 2DArray 0 0 3
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 0.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-layered-cubemap-gl32.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-layered-cubemap-gl32.shader_test
new file mode 100644
index 000000000..8c45ed69e
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-layered-cubemap-gl32.shader_test
@@ -0,0 +1,75 @@
+[require]
+GL >= 3.2
+GLSL >= 1.50
+GL_MESA_shader_framebuffer_fetch_non_coherent
+GL_ARB_texture_storage
+
+[vertex shader passthrough]
+[geometry shader]
+#version 150
+
+layout(triangles) in;
+layout(triangle_strip, max_vertices=18) out;
+
+flat out int glayer;
+
+void main()
+{
+ for (int layer = 0; layer < 6; layer++) {
+ for (int i = 0; i < 3; i++) {
+ gl_Position = gl_in[i].gl_Position;
+ gl_Layer = glayer = layer;
+ EmitVertex();
+ }
+ EndPrimitive();
+ }
+}
+
+[fragment shader]
+#version 150
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+flat in int glayer;
+inout highp vec4 fcolor;
+
+void main()
+{
+ fcolor += (glayer == 5 ? vec4(0.0, 0.5, 0.5, 0.0) :
+ glayer == 4 ? vec4(0.5, 0.0, 0.5, 0.0) :
+ glayer == 3 ? vec4(0.0, 0.0, 0.5, 0.0) :
+ glayer == 2 ? vec4(0.5, 0.5, 0.0, 0.0) :
+ glayer == 1 ? vec4(0.0, 0.5, 0.0, 0.0) :
+ vec4(0.5, 0.0, 0.0, 0.0));
+}
+
+[test]
+texture storage 0 Cube GL_RGBA8 (1 250 250)
+fb tex layered 0
+
+clear color 0.0 0.0 0.5 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+fb tex slice Cube 0 0 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0.0, 0.5)
+
+fb tex slice Cube 0 0 1
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 1.0, 0.5)
+
+fb tex slice Cube 0 0 2
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 1.0, 0.5)
+
+fb tex slice Cube 0 0 3
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 0.0, 1.0)
+
+fb tex slice Cube 0 0 4
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0.0, 1.0)
+
+fb tex slice Cube 0 0 5
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 1.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-mrt-gles2.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-mrt-gles2.shader_test
new file mode 100644
index 000000000..95f2cb73c
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-mrt-gles2.shader_test
@@ -0,0 +1,44 @@
+[require]
+GL ES >= 2.0
+GLSL ES >= 1.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+
+[vertex shader passthrough]
+
+[fragment shader]
+#version 100
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+void main()
+{
+ gl_FragData[0] = gl_LastFragData[0] + vec4(0.5, 0.0, 0.0, 0.0);
+ gl_FragData[1] = gl_LastFragData[1] + vec4(0.0, 0.5, 0.0, 0.0);
+ gl_FragData[2] = gl_LastFragData[2] + vec4(0.5, 0.5, 0.0, 0.0);
+ gl_FragData[3] = gl_LastFragData[3] + vec4(0.0, 0.0, 0.5, 0.0);
+}
+
+[test]
+texture rgbw 0 (250, 250) GL_RGBA8
+texture rgbw 1 (250, 250) GL_RGBA8
+texture rgbw 2 (250, 250) GL_RGBA8
+texture rgbw 3 (250, 250) GL_RGBA8
+fb tex multi 0 1 2 3
+
+clear color 0.0 0.0 0.5 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+fb tex 2d 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0.0, 0.5)
+
+fb tex 2d 1
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 1.0, 0.5)
+
+fb tex 2d 2
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 1.0, 0.5)
+
+fb tex 2d 3
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 0.0, 1.0)
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-mrt-gles3.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-mrt-gles3.shader_test
new file mode 100644
index 000000000..b9a88781d
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-mrt-gles3.shader_test
@@ -0,0 +1,49 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+
+[vertex shader passthrough]
+
+[fragment shader]
+#version 300 es
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+inout highp vec4 fcolor[4];
+
+void main()
+{
+ fcolor[0] += vec4(0.5, 0.0, 0.0, 0.0);
+ fcolor[1] += vec4(0.0, 0.5, 0.0, 0.0);
+ fcolor[2] += vec4(0.5, 0.5, 0.0, 0.0);
+ fcolor[3] += vec4(0.0, 0.0, 0.5, 0.0);
+}
+
+[test]
+texture rgbw 0 (250, 250) GL_RGBA8
+texture rgbw 1 (250, 250) GL_RGBA8
+texture rgbw 2 (250, 250) GL_RGBA8
+texture rgbw 3 (250, 250) GL_RGBA8
+fb tex multi 0 1 2 3
+
+clear color 0.0 0.0 0.5 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+fb tex 2d 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0.0, 0.5)
+
+fb tex 2d 1
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 1.0, 0.5)
+
+fb tex 2d 2
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 1.0, 0.5)
+
+fb tex 2d 3
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 0.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-ms16-gles3.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-ms16-gles3.shader_test
new file mode 100644
index 000000000..9b0ba3e29
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-ms16-gles3.shader_test
@@ -0,0 +1,55 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+INT GL_MAX_SAMPLES >= 16
+
+[vertex shader]
+#version 300 es
+
+in highp vec4 vertex;
+out highp vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 300 es
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+in highp vec4 vcolor;
+inout highp vec4 fcolor;
+
+void main()
+{
+ if (fcolor.x <= 0.5 && fcolor.y <= 0.5)
+ fcolor += vcolor;
+ else
+ fcolor += vec4((vcolor.x >= 0.5 ? 1.0 : 0.0) - vcolor.x,
+ (vcolor.y >= 0.5 ? 1.0 : 0.0) - vcolor.y, 0, 0);
+}
+
+[test]
+fb ms GL_RGBA8 250 250 16
+
+clear color 0.0 0.0 1.0 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+texture rgbw 0 (250, 250) GL_RGBA8
+fb draw tex 2d 0
+blit color linear
+fb read tex 2d 0
+
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (1.0, 0.0, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.0, 1.0, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (1.0, 1.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-ms2-gles3.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-ms2-gles3.shader_test
new file mode 100644
index 000000000..dd9181aa6
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-ms2-gles3.shader_test
@@ -0,0 +1,55 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+INT GL_MAX_SAMPLES >= 2
+
+[vertex shader]
+#version 300 es
+
+in vec4 vertex;
+out vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 300 es
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+in highp vec4 vcolor;
+inout highp vec4 fcolor;
+
+void main()
+{
+ if (fcolor.x <= 0.5 && fcolor.y <= 0.5)
+ fcolor += vcolor;
+ else
+ fcolor += vec4((vcolor.x >= 0.5 ? 1.0 : 0.0) - vcolor.x,
+ (vcolor.y >= 0.5 ? 1.0 : 0.0) - vcolor.y, 0, 0);
+}
+
+[test]
+fb ms GL_RGBA8 250 250 2
+
+clear color 0.0 0.0 1.0 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+texture rgbw 0 (250, 250) GL_RGBA8
+fb draw tex 2d 0
+blit color linear
+fb read tex 2d 0
+
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (1.0, 0.0, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.0, 1.0, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (1.0, 1.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-ms2-integer-gles3.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-ms2-integer-gles3.shader_test
new file mode 100644
index 000000000..9040d0f8a
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-ms2-integer-gles3.shader_test
@@ -0,0 +1,54 @@
+[require]
+GL ES >= 3.1
+GLSL ES >= 3.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+INT GL_MAX_SAMPLES >= 2
+
+[vertex shader]
+#version 300 es
+
+in vec4 vertex;
+out vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 300 es
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+#define SCALE 100
+
+in highp vec4 vcolor;
+inout highp ivec4 fcolor;
+
+void main()
+{
+ if (fcolor.x <= SCALE / 2 && fcolor.y <= SCALE / 2)
+ fcolor += ivec4(vcolor * float(SCALE));
+ else
+ fcolor += ivec4((vcolor.x >= 0.5 ? SCALE : 0) - int(vcolor.x * float(SCALE)),
+ (vcolor.y >= 0.5 ? SCALE : 0) - int(vcolor.y * float(SCALE)),
+ 0, 0);
+}
+
+[test]
+fb ms GL_RGBA8I 250 250 2
+
+clear color 0 0 1 0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+texture storage 0 2D GL_RGBA8I (1 250 250)
+fb draw tex 2d 0
+blit color nearest
+fb read tex 2d 0
+
+relative probe rect rgba int (0.55, 0.0, 0.45, 0.45) (100, 0, 127, 100)
+relative probe rect rgba int (0.0, 0.55, 0.45, 0.45) (0, 100, 127, 100)
+relative probe rect rgba int (0.55, 0.55, 0.45, 0.45) (100, 100, 127, 100)
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-ms8-gles3.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-ms8-gles3.shader_test
new file mode 100644
index 000000000..58788c416
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-ms8-gles3.shader_test
@@ -0,0 +1,55 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+INT GL_MAX_SAMPLES >= 8
+
+[vertex shader]
+#version 300 es
+
+in vec4 vertex;
+out vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 300 es
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+in highp vec4 vcolor;
+inout highp vec4 fcolor;
+
+void main()
+{
+ if (fcolor.x <= 0.5 && fcolor.y <= 0.5)
+ fcolor += vcolor;
+ else
+ fcolor += vec4((vcolor.x >= 0.5 ? 1.0 : 0.0) - vcolor.x,
+ (vcolor.y >= 0.5 ? 1.0 : 0.0) - vcolor.y, 0, 0);
+}
+
+[test]
+fb ms GL_RGBA8 250 250 8
+
+clear color 0.0 0.0 1.0 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+texture rgbw 0 (250, 250) GL_RGBA8
+fb draw tex 2d 0
+blit color linear
+fb read tex 2d 0
+
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (1.0, 0.0, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.0, 1.0, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (1.0, 1.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-ms8-integer-gles3.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-ms8-integer-gles3.shader_test
new file mode 100644
index 000000000..01599332d
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-ms8-integer-gles3.shader_test
@@ -0,0 +1,54 @@
+[require]
+GL ES >= 3.1
+GLSL ES >= 3.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+INT GL_MAX_SAMPLES >= 8
+
+[vertex shader]
+#version 300 es
+
+in vec4 vertex;
+out vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 300 es
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+#define SCALE 100
+
+in highp vec4 vcolor;
+inout highp ivec4 fcolor;
+
+void main()
+{
+ if (fcolor.x <= SCALE / 2 && fcolor.y <= SCALE / 2)
+ fcolor += ivec4(vcolor * float(SCALE));
+ else
+ fcolor += ivec4((vcolor.x >= 0.5 ? SCALE : 0) - int(vcolor.x * float(SCALE)),
+ (vcolor.y >= 0.5 ? SCALE : 0) - int(vcolor.y * float(SCALE)),
+ 0, 0);
+}
+
+[test]
+fb ms GL_RGBA8I 250 250 8
+
+clear color 0 0 1 0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+texture storage 0 2D GL_RGBA8I (1 250 250)
+fb draw tex 2d 0
+blit color nearest
+fb read tex 2d 0
+
+relative probe rect rgba int (0.55, 0.0, 0.45, 0.45) (100, 0, 127, 100)
+relative probe rect rgba int (0.0, 0.55, 0.45, 0.45) (0, 100, 127, 100)
+relative probe rect rgba int (0.55, 0.55, 0.45, 0.45) (100, 100, 127, 100)
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-nonuniform-gles2.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-nonuniform-gles2.shader_test
new file mode 100644
index 000000000..0652c1e2b
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-nonuniform-gles2.shader_test
@@ -0,0 +1,47 @@
+[require]
+GL ES >= 2.0
+GLSL ES >= 1.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+
+[vertex shader]
+#version 100
+
+attribute highp vec4 vertex;
+varying highp vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 100
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+varying highp vec4 vcolor;
+
+void main()
+{
+ if (gl_LastFragData[0].x <= 0.5 && gl_LastFragData[0].y <= 0.5)
+ gl_FragData[0] = gl_LastFragData[0] + vcolor;
+ else
+ gl_FragData[0] = gl_LastFragData[0] +
+ vec4((vcolor.x >= 0.5 ? 1.0 : 0.0) - vcolor.x,
+ (vcolor.y >= 0.5 ? 1.0 : 0.0) - vcolor.y, 0, 0);
+}
+
+[test]
+texture rgbw 0 (250, 250) GL_RGBA8
+fb tex 2d 0
+
+clear color 0.0 0.0 1.0 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (1.0, 0.0, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.0, 1.0, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (1.0, 1.0, 1.0)
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-nonuniform-gles3.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-nonuniform-gles3.shader_test
new file mode 100644
index 000000000..dab381753
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-nonuniform-gles3.shader_test
@@ -0,0 +1,50 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+
+[vertex shader]
+#version 300 es
+
+in vec4 vertex;
+out vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 300 es
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+in highp vec4 vcolor;
+inout highp vec4 fcolor;
+
+void main()
+{
+ if (fcolor.x <= 0.5 && fcolor.y <= 0.5)
+ fcolor += vcolor;
+ else
+ fcolor += vec4((vcolor.x >= 0.5 ? 1.0 : 0.0) - vcolor.x,
+ (vcolor.y >= 0.5 ? 1.0 : 0.0) - vcolor.y, 0, 0);
+}
+
+[test]
+texture rgbw 0 (250, 250) GL_RGBA8
+fb tex 2d 0
+
+clear color 0.0 0.0 1.0 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (1.0, 0.0, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.0, 1.0, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (1.0, 1.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-overwrite-gles3.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-overwrite-gles3.shader_test
new file mode 100644
index 000000000..d877eaa8e
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-overwrite-gles3.shader_test
@@ -0,0 +1,50 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+
+[vertex shader]
+#version 300 es
+
+in vec4 vertex;
+out vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 300 es
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+in highp vec4 vcolor;
+inout highp vec4 fcolor;
+
+void main()
+{
+ if (vcolor.x >= 0.5 || vcolor.y >= 0.5)
+ fcolor += vec4(0.5, 0, 0, 0);
+
+ fcolor += vec4(0.0, 0.5, 0, 0);
+}
+
+[test]
+texture rgbw 0 (250, 250) GL_RGBA8
+fb tex 2d 0
+
+clear color 0.0 0.0 1.0 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+relative probe rect rgb (0.0, 0.0, 0.45, 0.45) (0.0, 1.0, 1.0)
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (1.0, 1.0, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (1.0, 1.0, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (1.0, 1.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-redeclared-highp-gles2.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-redeclared-highp-gles2.shader_test
new file mode 100644
index 000000000..8fa0c2a65
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-redeclared-highp-gles2.shader_test
@@ -0,0 +1,48 @@
+[require]
+GL ES >= 2.0
+GLSL ES >= 1.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+
+[vertex shader]
+#version 100
+
+attribute highp vec4 vertex;
+varying highp vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 100
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+highp vec4 gl_LastFragData[gl_MaxDrawBuffers];
+varying highp vec4 vcolor;
+
+void main()
+{
+ if (gl_LastFragData[0].x <= 0.5 && gl_LastFragData[0].y <= 0.5)
+ gl_FragData[0] = gl_LastFragData[0] + vcolor;
+ else
+ gl_FragData[0] = gl_LastFragData[0] +
+ vec4((vcolor.x >= 0.5 ? 1.0 : 0.0) - vcolor.x,
+ (vcolor.y >= 0.5 ? 1.0 : 0.0) - vcolor.y, 0, 0);
+}
+
+[test]
+texture rgbw 0 (250, 250) GL_RGBA8
+fb tex 2d 0
+
+clear color 0.0 0.0 1.0 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (1.0, 0.0, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.0, 1.0, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (1.0, 1.0, 1.0)
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-redeclared-lowp-gles2.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-redeclared-lowp-gles2.shader_test
new file mode 100644
index 000000000..b37d2680a
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-redeclared-lowp-gles2.shader_test
@@ -0,0 +1,48 @@
+[require]
+GL ES >= 2.0
+GLSL ES >= 1.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+
+[vertex shader]
+#version 100
+
+attribute highp vec4 vertex;
+varying highp vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 100
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+lowp vec4 gl_LastFragData[gl_MaxDrawBuffers];
+varying highp vec4 vcolor;
+
+void main()
+{
+ if (gl_LastFragData[0].x <= 0.5 && gl_LastFragData[0].y <= 0.5)
+ gl_FragData[0] = gl_LastFragData[0] + vcolor;
+ else
+ gl_FragData[0] = gl_LastFragData[0] +
+ vec4((vcolor.x >= 0.5 ? 1.0 : 0.0) - vcolor.x,
+ (vcolor.y >= 0.5 ? 1.0 : 0.0) - vcolor.y, 0, 0);
+}
+
+[test]
+texture rgbw 0 (250, 250) GL_RGBA8
+fb tex 2d 0
+
+clear color 0.0 0.0 1.0 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (1.0, 0.0, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.0, 1.0, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (1.0, 1.0, 1.0)
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-redeclared-mediump-gles2.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-redeclared-mediump-gles2.shader_test
new file mode 100644
index 000000000..d2d92a73e
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-redeclared-mediump-gles2.shader_test
@@ -0,0 +1,48 @@
+[require]
+GL ES >= 2.0
+GLSL ES >= 1.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+
+[vertex shader]
+#version 100
+
+attribute highp vec4 vertex;
+varying highp vec4 vcolor;
+
+void main()
+{
+ gl_Position = vertex;
+ vcolor = vec4((1.0 + vertex.x) / 2.0, (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+}
+
+[fragment shader]
+#version 100
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+mediump vec4 gl_LastFragData[gl_MaxDrawBuffers];
+varying highp vec4 vcolor;
+
+void main()
+{
+ if (gl_LastFragData[0].x <= 0.5 && gl_LastFragData[0].y <= 0.5)
+ gl_FragData[0] = gl_LastFragData[0] + vcolor;
+ else
+ gl_FragData[0] = gl_LastFragData[0] +
+ vec4((vcolor.x >= 0.5 ? 1.0 : 0.0) - vcolor.x,
+ (vcolor.y >= 0.5 ? 1.0 : 0.0) - vcolor.y, 0, 0);
+}
+
+[test]
+texture rgbw 0 (250, 250) GL_RGBA8
+fb tex 2d 0
+
+clear color 0.0 0.0 1.0 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (1.0, 0.0, 1.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.0, 1.0, 1.0)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (1.0, 1.0, 1.0)
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-simple-gles3.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-simple-gles3.shader_test
new file mode 100644
index 000000000..956e3b1b9
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-simple-gles3.shader_test
@@ -0,0 +1,33 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+
+[vertex shader passthrough]
+
+[fragment shader]
+#version 300 es
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+inout highp vec4 fcolor;
+
+void main()
+{
+ fcolor += vec4(0.5, 0.0, 0.0, 0.0);
+}
+
+[test]
+texture rgbw 0 (250, 250) GL_RGBA8
+fb tex 2d 0
+
+clear color 0.0 0.0 1.0 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+relative probe rect rgb (0, 0.0, 1.0, 1.0) (1.0, 0.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-single-2d-level-gles3.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-single-2d-level-gles3.shader_test
new file mode 100644
index 000000000..73f3b76ad
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-single-2d-level-gles3.shader_test
@@ -0,0 +1,71 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+
+[vertex shader passthrough]
+[fragment shader]
+#version 300 es
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+inout highp vec4 fcolor;
+uniform highp vec4 ucolor;
+
+void main()
+{
+ fcolor += ucolor;
+}
+
+[test]
+texture storage 0 2DArray GL_RGBA8 (4 250 250 1)
+
+fb tex slice 2DArray 0 0 0
+uniform vec4 ucolor 0.5 0.0 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+fb tex slice 2DArray 0 1 0
+uniform vec4 ucolor 0.0 0.5 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+fb tex slice 2DArray 0 2 0
+uniform vec4 ucolor 0.5 0.5 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+fb tex slice 2DArray 0 3 0
+uniform vec4 ucolor 0.0 0.0 0.5 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+fb tex slice 2DArray 0 0 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0.0, 0.5)
+
+fb tex slice 2DArray 0 1 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 1.0, 0.5)
+
+fb tex slice 2DArray 0 2 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 1.0, 0.5)
+
+fb tex slice 2DArray 0 3 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 0.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-single-2darray-layer-gles3.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-single-2darray-layer-gles3.shader_test
new file mode 100644
index 000000000..52a912424
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-single-2darray-layer-gles3.shader_test
@@ -0,0 +1,71 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+
+[vertex shader passthrough]
+[fragment shader]
+#version 300 es
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+inout highp vec4 fcolor;
+uniform highp vec4 ucolor;
+
+void main()
+{
+ fcolor += ucolor;
+}
+
+[test]
+texture storage 0 2DArray GL_RGBA8 (1 250 250 4)
+
+fb tex slice 2DArray 0 0 0
+uniform vec4 ucolor 0.5 0.0 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+fb tex slice 2DArray 0 0 1
+uniform vec4 ucolor 0.0 0.5 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+fb tex slice 2DArray 0 0 2
+uniform vec4 ucolor 0.5 0.5 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+fb tex slice 2DArray 0 0 3
+uniform vec4 ucolor 0.0 0.0 0.5 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+fb tex slice 2DArray 0 0 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0.0, 0.5)
+
+fb tex slice 2DArray 0 0 1
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 1.0, 0.5)
+
+fb tex slice 2DArray 0 0 2
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 1.0, 0.5)
+
+fb tex slice 2DArray 0 0 3
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 0.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-single-3d-layer-gles3.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-single-3d-layer-gles3.shader_test
new file mode 100644
index 000000000..700833db8
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-single-3d-layer-gles3.shader_test
@@ -0,0 +1,71 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+
+[vertex shader passthrough]
+[fragment shader]
+#version 300 es
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+inout highp vec4 fcolor;
+uniform highp vec4 ucolor;
+
+void main()
+{
+ fcolor += ucolor;
+}
+
+[test]
+texture storage 0 3D GL_RGBA8 (1 250 250 4)
+
+fb tex slice 3D 0 0 0
+uniform vec4 ucolor 0.5 0.0 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+fb tex slice 3D 0 0 1
+uniform vec4 ucolor 0.0 0.5 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+fb tex slice 3D 0 0 2
+uniform vec4 ucolor 0.5 0.5 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+fb tex slice 3D 0 0 3
+uniform vec4 ucolor 0.0 0.0 0.5 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+fb tex slice 3D 0 0 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0.0, 0.5)
+
+fb tex slice 3D 0 0 1
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 1.0, 0.5)
+
+fb tex slice 3D 0 0 2
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 1.0, 0.5)
+
+fb tex slice 3D 0 0 3
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 0.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-single-cubemap-layer-gles3.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-single-cubemap-layer-gles3.shader_test
new file mode 100644
index 000000000..4270ccfd6
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-single-cubemap-layer-gles3.shader_test
@@ -0,0 +1,71 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+
+[vertex shader passthrough]
+[fragment shader]
+#version 300 es
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+inout highp vec4 fcolor;
+uniform highp vec4 ucolor;
+
+void main()
+{
+ fcolor += ucolor;
+}
+
+[test]
+texture storage 0 Cube GL_RGBA8 (1 250 250)
+
+fb tex slice Cube 0 0 0
+uniform vec4 ucolor 0.5 0.0 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+fb tex slice Cube 0 0 1
+uniform vec4 ucolor 0.0 0.5 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+fb tex slice Cube 0 0 2
+uniform vec4 ucolor 0.5 0.5 0.0 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+fb tex slice Cube 0 0 3
+uniform vec4 ucolor 0.0 0.0 0.5 0.0
+clear color 0.0 0.0 0.5 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+fb tex slice Cube 0 0 0
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 0.0, 0.5)
+
+fb tex slice Cube 0 0 1
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 1.0, 0.5)
+
+fb tex slice Cube 0 0 2
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (1.0, 1.0, 0.5)
+
+fb tex slice Cube 0 0 3
+relative probe rect rgb (0.0, 0.0, 1.0, 1.0) (0.0, 0.0, 1.0)
+
+fb draw winsys
+blit color linear
diff --git a/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-texture-gles3.shader_test b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-texture-gles3.shader_test
new file mode 100644
index 000000000..8354d80f2
--- /dev/null
+++ b/tests/spec/mesa_shader_framebuffer_fetch/execution/non_coherent-texture-gles3.shader_test
@@ -0,0 +1,40 @@
+[require]
+GL ES >= 3.0
+GLSL ES >= 3.00
+GL_MESA_shader_framebuffer_fetch_non_coherent
+
+[vertex shader passthrough]
+
+[fragment shader]
+#version 300 es
+#extension GL_MESA_shader_framebuffer_fetch_non_coherent : enable
+
+uniform sampler2D s;
+inout highp vec4 fcolor;
+
+void main()
+{
+ fcolor += texelFetch(s, ivec2(gl_FragCoord), 0) / 4.0;
+}
+
+[test]
+texture rgbw 0 (250, 250) GL_RGBA8
+fb tex 2d 0
+
+texture rgbw 1 (250, 250) GL_RGBA8
+uniform int s 1
+
+clear color 0.5 0.0 0.0 0.0
+clear
+blend barrier
+draw rect -1 -1 2 2
+blend barrier
+draw rect -1 -1 2 2
+
+relative probe rect rgb (0.0, 0.0, 0.45, 0.45) (1.0, 0.0, 0.0)
+relative probe rect rgb (0.55, 0.0, 0.45, 0.45) (0.5, 0.5, 0.0)
+relative probe rect rgb (0.0, 0.55, 0.45, 0.45) (0.5, 0.0, 0.5)
+relative probe rect rgb (0.55, 0.55, 0.45, 0.45) (1.0, 0.5, 0.5)
+
+fb draw winsys
+blit color linear