summaryrefslogtreecommitdiff
path: root/generated_tests
diff options
context:
space:
mode:
authorFrancisco Jerez <currojerez@riseup.net>2016-06-29 16:15:06 -0700
committerFrancisco Jerez <currojerez@riseup.net>2016-11-07 14:07:06 -0800
commitd81536a3c5989b66c593d0cd13ed29c1cad093c1 (patch)
treecd8128c25584ab86827f30fb7242bee116f8ac07 /generated_tests
parent2fc3f588b4914e8f262014a40adedb63426c0430 (diff)
Add test generator for EXT_shader_framebuffer_fetch.
Reviewed-by: Dylan Baker <dylan@pnwbakers.com>
Diffstat (limited to 'generated_tests')
-rw-r--r--generated_tests/CMakeLists.txt4
-rw-r--r--generated_tests/gen_shader_framebuffer_fetch_tests.py799
2 files changed, 803 insertions, 0 deletions
diff --git a/generated_tests/CMakeLists.txt b/generated_tests/CMakeLists.txt
index ff43af5cb..60595699f 100644
--- a/generated_tests/CMakeLists.txt
+++ b/generated_tests/CMakeLists.txt
@@ -193,6 +193,9 @@ piglit_make_generated_tests(
gen_vs_in_fp64.py
templates/gen_vs_in_fp64/columns.shader_test.mako
templates/gen_vs_in_fp64/regular.shader_test.mako)
+piglit_make_generated_tests(
+ shader_framebuffer_fetch_tests.list
+ gen_shader_framebuffer_fetch_tests.py)
# OpenCL Test generators
piglit_make_generated_tests(
@@ -241,6 +244,7 @@ add_custom_target(gen-gl-tests
flat_interpolation_qualifier.list
conversion_fp64.list
shader_precision_tests.list
+ shader_framebuffer_fetch_tests.list
shader_image_load_store_tests.list
variable_index_read_tests.list
gen_extensions_defined.list
diff --git a/generated_tests/gen_shader_framebuffer_fetch_tests.py b/generated_tests/gen_shader_framebuffer_fetch_tests.py
new file mode 100644
index 000000000..a7c54ed55
--- /dev/null
+++ b/generated_tests/gen_shader_framebuffer_fetch_tests.py
@@ -0,0 +1,799 @@
+# coding=utf-8
+#
+# Copyright © 2014-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"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+from __future__ import print_function, division, absolute_import
+
+import os.path
+from textwrap import dedent
+
+from mako.template import Template
+
+from modules import utils
+
+
+def product(ps, *qss):
+ """
+ Generate the cartesian product of a number of lists of dictionaries.
+
+ Generate a sequence with every possible combination of elements of
+ the specified lists of dictionaries. Each element of the result
+ will be the union of some combination of dictionaries from the
+ lists given as argument. The 'name' attribute of each dictionary
+ given as input is concatenated with the names of other
+ dictionaries part of the same combination to give the 'name'
+ attribute of the result.
+ """
+ for q in (product(*qss) if qss else [{}]):
+ for p in ps:
+ r = dict(p, **q)
+ r['name'] = ''.join(s['name'] for s in (p, q) if s.get('name'))
+ yield r
+
+
+def gen(src, tests):
+ """
+ Expand a source template for the provided list of test definitions.
+
+ Generate a test script for each element of the 'tests' iterable,
+ each of them should be a dictionary of definitions that will be
+ used as environment to render the source template.
+
+ The 'path' attribute of each dictionary gives the filename each
+ test will be written to.
+ """
+ template = Template(dedent(src))
+
+ for t in tests:
+ print(t['path'])
+ utils.safe_makedirs(os.path.dirname(t['path']))
+ with open(t['path'], 'w') as f:
+ f.write(template.render(**t))
+
+
+def gen_execution(src, tests):
+ """
+ Generate a shader runner test for each element of the 'tests'
+ iterable.
+ """
+ return gen(src,
+ (dict(t, path = os.path.join(
+ 'spec', t['extension'], 'execution',
+ t['name'] + '.shader_test')) for t in tests))
+
+
+def gen_compiler(src, tests):
+ """
+ Generate a GLSL parser test for each element of the 'tests'
+ iterable.
+ """
+ return gen(src,
+ (dict(t, path = os.path.join(
+ 'spec', t['extension'], 'compiler',
+ t['name'] + '.' + t['shader_stage'])) for t in tests))
+
+
+#
+# Common definitions for framebuffer fetch tests.
+#
+common_defs = [{'extension': 'EXT_shader_framebuffer_fetch',
+
+ # Allocate and bind a framebuffer object of the given
+ # format and number of samples.
+ 'bind_fb': lambda fmt, samples = 0:
+ 'fb ms {0} 250 250 {1}'.format(fmt, samples) if samples > 0 else
+ ('texture storage 0 2D {0} (1 250 250)\n'
+ 'fb tex 2d 0').format(fmt) if fmt[-1] == 'I' else
+ ('texture rgbw 0 (250, 250) {0}\n'
+ 'fb tex 2d 0').format(fmt),
+
+ # Resolve the contents of a framebuffer previously
+ # allocated with 'bind_fb' of the given format and
+ # samples into a newly allocated single-sample
+ # framebuffer.
+ 'resolve_fb': lambda fmt, samples:
+ '' if samples == 0 else
+ ('texture storage 0 2D {0} (1 250 250)\n'
+ 'fb draw tex 2d 0\n'
+ 'blit color nearest\n'
+ 'fb read tex 2d 0\n').format(fmt) if fmt[-1] == 'I' else
+ ('texture rgbw 0 (250, 250) {0}\n'
+ 'fb draw tex 2d 0\n'
+ 'blit color linear\n'
+ 'fb read tex 2d 0').format(fmt),
+
+ # Blit the contents of the current read framebuffer
+ # into the window system framebuffer. XXX - Requires
+ # GL(ES) 3.0+ since glBlitFramebuffer doesn't exist on
+ # earlier API versions.
+ 'display_fb': lambda api_version:
+ '' if api_version < 3.0 else
+ ('fb draw winsys\n'
+ 'blit color linear'),
+
+ # Declare a fragment color array set up for
+ # framebuffer fetch with the specified number of
+ # elements (n=0 indicates a single scalar output).
+ #
+ # The fragment color array can be accessed using the
+ # 'frag_data' and 'last_frag_data' macros defined
+ # below to make sure the generated test is valid
+ # irrespective of the GLSL version.
+ 'decl_frag_data': lambda api_version, n = 0:
+ '' if api_version < 3.0 else
+ 'inout highp vec4 fcolor;' if n == 0 else
+ 'inout highp vec4 fcolor[{0}];'.format(n),
+
+ 'frag_data': lambda api_version, i = -1:
+ 'gl_FragData[{0}]'.format(max(0, i)) if api_version < 3.0 else
+ 'fcolor[{0}]'.format(i) if i >= 0 else
+ 'fcolor',
+
+ 'last_frag_data': lambda api_version, i = -1:
+ 'gl_LastFragData[{0}]'.format(max(0, i)) if api_version < 3.0 else
+ 'fcolor[{0}]'.format(i) if i >= 0 else
+ 'fcolor'}]
+
+
+def main():
+ """Main function."""
+
+ #
+ # Test that the GL(ES) 2 gl_LastFragData built-in is not defined
+ # in more recent GLSL versions.
+ #
+ gen_compiler("""\
+ /*
+ * [config]
+ * expect_result: fail
+ * glsl_version: 3.0 es
+ * require_extensions: GL_${extension}
+ * [end config]
+ */
+ #version 300 es
+ #extension GL_${extension} : enable
+
+ out highp vec4 color;
+
+ void main()
+ {
+ color = gl_LastFragData[0];
+ }
+ """, product(common_defs,
+ [{'name': 'negative-gl_LastFragData-gles3',
+ 'shader_stage': 'frag'}]))
+
+ #
+ # Test that the GL(ES) 2 gl_LastFragData built-in is read-only.
+ # From the EXT_shader_framebuffer_fetch extension: "[...] fragment
+ # shaders should use the read-only input array gl_LastFragData."
+ #
+ gen_compiler("""\
+ /*
+ * [config]
+ * expect_result: fail
+ * glsl_version: 1.0 es
+ * require_extensions: GL_${extension}
+ * [end config]
+ */
+ #version 100
+ #extension GL_${extension} : enable
+
+ void main()
+ {
+ gl_LastFragData[0] = vec4(1.0);
+ }
+ """, product(common_defs,
+ [{'name': 'negative-gl_LastFragData-write-gles2',
+ 'shader_stage': 'frag'}]))
+
+ #
+ # Test that GL(ES) 3+ user-defined inout arrays are not accepted
+ # in earlier GLSL versions.
+ #
+ gen_compiler("""\
+ /*
+ * [config]
+ * expect_result: fail
+ * glsl_version: 1.0 es
+ * require_extensions: GL_${extension}
+ * [end config]
+ */
+ #version 100
+ #extension GL_${extension} : enable
+
+ inout highp vec4 color;
+
+ void main()
+ {
+ color += vec4(0.5);
+ }
+ """, product(common_defs,
+ [{'name': 'negative-inout-fragment-output-gles2',
+ 'shader_stage': 'frag'}]))
+
+ #
+ # Test that redeclaring an existing built-in fragment output as
+ # 'inout' leads to an error.
+ #
+ gen_compiler("""\
+ /*
+ * [config]
+ * expect_result: fail
+ * glsl_version: 3.0 es
+ * require_extensions: GL_${extension}
+ * [end config]
+ */
+ #version 300 es
+ #extension GL_${extension} : enable
+
+ inout highp float gl_FragDepth;
+
+ void main()
+ {
+ gl_FragDepth += 0.5;
+ }
+ """, product(common_defs,
+ [{'name': 'negative-inout-gl_FragDepth-gles3',
+ 'shader_stage': 'frag'}]))
+
+ #
+ # Test that vertex shader interface variables cannot be declared
+ # 'inout'.
+ #
+ gen_compiler("""\
+ /*
+ * [config]
+ * expect_result: fail
+ * glsl_version: 3.0 es
+ * require_extensions: GL_${extension}
+ * [end config]
+ */
+ #version 300 es
+ #extension GL_${extension} : enable
+
+ inout highp vec4 vcolor;
+
+ void main()
+ {
+ }
+ """, product(common_defs,
+ [{'name': 'negative-inout-vertex-output-gles3',
+ 'shader_stage': 'vert'}]))
+
+ #
+ # Test basic framebuffer fetch functionality.
+ #
+ gen_execution("""\
+ [require]
+ GL ES >= ${api_version}
+ GLSL ES >= ${3.0 if api_version >= 3.0 else 1.0}
+ %if samples > 0:
+ INT GL_MAX_SAMPLES >= ${samples}
+ %endif
+ GL_${extension}
+
+ [vertex shader passthrough]
+
+ [fragment shader]
+ #version ${'300 es' if api_version >= 3.0 else '100'}
+ #extension GL_${extension} : enable
+
+ ${decl_frag_data(api_version)}
+
+ void main()
+ {
+ ${frag_data(api_version)} = ${last_frag_data(api_version)} +
+ vec4(0.5, 0.0, 0.0, 0.0);
+ }
+
+ [test]
+ ${bind_fb('GL_RGBA8', samples)}
+
+ clear color 0.0 0.0 1.0 0.0
+ clear
+ draw rect -1 -1 2 2
+ draw rect -1 -1 2 2
+
+ ${resolve_fb('GL_RGBA8', samples)}
+
+ relative probe rect rgb (0, 0.0, 1.0, 1.0) (1.0, 0.0, 1.0)
+
+ ${display_fb(api_version)}
+ """, product(common_defs,
+ [{'name': 'simple-'}],
+ [{'name': 'ss-gles2', 'api_version': 2.0, 'samples': 0},
+ {'name': 'ss-gles3', 'api_version': 3.0, 'samples': 0},
+ {'name': 'ms2-gles3', 'api_version': 3.0, 'samples': 2},
+ {'name': 'ms8-gles3', 'api_version': 3.0, 'samples': 8},
+ {'name': 'ms16-gles3', 'api_version': 3.0, 'samples': 16}]))
+
+ #
+ # Test read-back from a framebuffer with non-uniform contents
+ # rendered during a previous draw call.
+ #
+ gen_execution("""\
+ [require]
+ GL ES >= ${api_version}
+ GLSL ES >= ${3.0 if api_version >= 3.0 else 1.0}
+ %if samples > 0:
+ INT GL_MAX_SAMPLES >= ${samples}
+ %endif
+ GL_${extension}
+
+ [vertex shader]
+ #version ${'300 es' if api_version >= 3.0 else '100'}
+
+ ${'in' if api_version >= 3.0 else 'attribute'} highp vec4 vertex;
+ ${'out' if api_version >= 3.0 else 'varying'} highp vec4 vcolor;
+
+ void main()
+ {
+ gl_Position = vertex;
+ // Transform the vertex coordinates so that the R and G
+ // components of the vertex color range between 0.0 and 1.0.
+ vcolor = vec4((1.0 + vertex.x) / 2.0,
+ (1.0 + vertex.y) / 2.0, 0.0, 1.0);
+ }
+
+ [fragment shader]
+ #version ${'300 es' if api_version >= 3.0 else '100'}
+ #extension GL_${extension} : enable
+
+ ${'in' if api_version >= 3.0 else 'varying'} highp vec4 vcolor;
+ ${decl_frag_data(api_version)}
+
+ %if api_version < 3.0 and precision:
+ ${precision} vec4 gl_LastFragData[gl_MaxDrawBuffers];
+ %endif
+
+ void main()
+ {
+ // The condition makes sure that the else branch is
+ // taken for the top and right quadrants during the second
+ // overdraw.
+ if (${last_frag_data(api_version)}.x <= 0.5 &&
+ ${last_frag_data(api_version)}.y <= 0.5) {
+ ${frag_data(api_version)} = ${last_frag_data(api_version)} +
+ vcolor;
+ } else {
+ // Will give a solid color as result different for
+ // each quadrant, assuming that the first branch was
+ // taken during the first pass.
+ ${frag_data(api_version)} = ${last_frag_data(api_version)} +
+ vec4((vcolor.x >= 0.5 ? 1.0 : 0.0) - vcolor.x,
+ (vcolor.y >= 0.5 ? 1.0 : 0.0) - vcolor.y,
+ 0, 0);
+ }
+ }
+
+ [test]
+ ${bind_fb('GL_RGBA8', samples)}
+
+ clear color 0.0 0.0 1.0 0.0
+ clear
+ draw rect -1 -1 2 2
+ draw rect -1 -1 2 2
+
+ ${resolve_fb('GL_RGBA8', samples)}
+
+ 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)
+
+ ${display_fb(api_version)}
+ """, product(common_defs,
+ [{'name': 'nonuniform-'}],
+ [{'name': 'ss-gles2', 'api_version': 2.0,
+ 'samples': 0, 'precision': ''},
+ {'name': 'ss-gles2-redecl-highp', 'api_version': 2.0,
+ 'samples': 0, 'precision': 'highp'},
+ {'name': 'ss-gles2-redecl-mediump', 'api_version': 2.0,
+ 'samples': 0, 'precision': 'mediump'},
+ {'name': 'ss-gles2-redecl-lowp', 'api_version': 2.0,
+ 'samples': 0, 'precision': 'lowp'},
+ {'name': 'ss-gles3', 'api_version': 3.0,
+ 'samples': 0, 'precision': ''},
+ {'name': 'ms2-gles3', 'api_version': 3.0,
+ 'samples': 2, 'precision': ''},
+ {'name': 'ms8-gles3', 'api_version': 3.0,
+ 'samples': 8, 'precision': ''},
+ {'name': 'ms16-gles3', 'api_version': 3.0,
+ 'samples': 16, 'precision': ''}]))
+
+ #
+ # Test basic framebuffer fetch functionality in combination with
+ # texturing.
+ #
+ gen_execution("""\
+ [require]
+ GL ES >= 3.0
+ GLSL ES >= 3.00
+ GL_${extension}
+
+ [vertex shader passthrough]
+
+ [fragment shader]
+ #version 300 es
+ #extension GL_${extension} : enable
+
+ uniform sampler2D s;
+ inout highp vec4 fcolor;
+
+ void main()
+ {
+ fcolor += texelFetch(s, ivec2(gl_FragCoord), 0) / 4.0;
+ }
+
+ [test]
+ ${bind_fb('GL_RGBA8')}
+
+ 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)
+
+ ${display_fb(3.0)}
+ """, product(common_defs,
+ [{'name': 'texture-gles3'}]))
+
+ #
+ # Test non-uniform fragment discard dependent on the result read
+ # back from the framebuffer. The EXT_shader_framebuffer_fetch
+ # multisample test will be skipped if the implementation doesn't
+ # claim to support per-sample discard.
+ #
+ gen_execution("""\
+ [require]
+ GL ES >= 3.0
+ GLSL ES >= 3.00
+ GL_${extension}
+ %if samples > 0:
+ INT GL_MAX_SAMPLES >= ${samples}
+ %endif
+ INT GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT >= ${1 if samples else 0}
+
+ [vertex shader]
+ #version 300 es
+
+ in highp vec4 vertex;
+ out highp vec4 vcolor;
+
+ void main()
+ {
+ gl_Position = vertex;
+ // Transform the vertex coordinates so that the R and G
+ // components of the vertex color range between 0.0 and 1.0.
+ 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_${extension} : enable
+
+ in highp vec4 vcolor;
+ inout highp vec4 fcolor;
+
+ void main()
+ {
+ // The condition makes sure that the discard branch is
+ // taken for the top and right quadrants during the second
+ // overdraw.
+ 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]
+ ${bind_fb('GL_RGBA8', samples)}
+
+ clear color 0.0 0.0 1.0 0.0
+ clear
+ draw rect -1 -1 2 2
+ draw rect -1 -1 2 2
+
+ ${resolve_fb('GL_RGBA8', samples)}
+
+ 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)
+
+ ${display_fb(3.0)}
+ """, product(common_defs,
+ [{'name': 'discard-gles3-'}],
+ [{'name': 'ss', 'samples': 0},
+ {'name': 'ms8', 'samples': 8}]))
+
+ #
+ # Test read-back from an integer framebuffer with non-uniform
+ # contents rendered during a previous draw call. Similar to the
+ # "nonuniform" test above but using an integer framebuffer.
+ #
+ gen_execution("""\
+ [require]
+ GL ES >= ${api_version}
+ GLSL ES >= 3.00
+ GL_${extension}
+ %if samples > 0:
+ INT GL_MAX_SAMPLES >= ${samples}
+ %endif
+
+ [vertex shader]
+ #version 300 es
+
+ in highp vec4 vertex;
+ out highp vec4 vcolor;
+
+ void main()
+ {
+ gl_Position = vertex;
+ // Transform the vertex coordinates so that the R and G
+ // components of the vertex color range between 0.0 and 1.0.
+ 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_${extension} : 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]
+ ${bind_fb('GL_RGBA8I', samples)}
+
+ clear color 0 0 1 0
+ clear
+ draw rect -1 -1 2 2
+ draw rect -1 -1 2 2
+
+ ${resolve_fb('GL_RGBA8I', samples)}
+
+ 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)
+ """, product(common_defs,
+ [{'name': 'integer-gles3-'}],
+ [{'name': 'ss', 'samples': 0, 'api_version': 3.0},
+ {'name': 'ms2', 'samples': 2, 'api_version': 3.1},
+ {'name': 'ms8', 'samples': 8, 'api_version': 3.1}]))
+
+ #
+ # Test framebuffer fetch functionality in combination with
+ # multiple render targets.
+ #
+ gen_execution("""\
+ [require]
+ GL ES >= ${api_version}
+ GLSL ES >= ${3.0 if api_version >= 3.0 else 1.0}
+ GL_${extension}
+
+ [vertex shader passthrough]
+
+ [fragment shader]
+ #version ${'300 es' if api_version >= 3.0 else '100'}
+ #extension GL_${extension} : enable
+
+ ${decl_frag_data(api_version, 4)}
+
+ void main()
+ {
+ ${frag_data(api_version, 0)} = ${last_frag_data(api_version, 0)} +
+ vec4(0.5, 0.0, 0.0, 0.0);
+ ${frag_data(api_version, 1)} = ${last_frag_data(api_version, 1)} +
+ vec4(0.0, 0.5, 0.0, 0.0);
+ ${frag_data(api_version, 2)} = ${last_frag_data(api_version, 2)} +
+ vec4(0.5, 0.5, 0.0, 0.0);
+ ${frag_data(api_version, 3)} = ${last_frag_data(api_version, 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 2d 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)
+
+ ${display_fb(api_version)}
+ """, product(common_defs,
+ [{'name': 'mrt-'}],
+ [{'name': 'gles2', 'api_version': 2.0},
+ {'name': 'gles3', 'api_version': 3.0}]))
+
+ #
+ # Test framebuffer fetch functionality with multiple assignments
+ # of the fragment color input-output.
+ #
+ gen_execution("""\
+ [require]
+ GL ES >= 3.0
+ GLSL ES >= 3.00
+ GL_${extension}
+
+ [vertex shader]
+ #version 300 es
+
+ in vec4 vertex;
+ out vec4 vcolor;
+
+ void main()
+ {
+ gl_Position = vertex;
+ // Transform the vertex coordinates so that the R and G
+ // components of the vertex color range between 0.0 and 1.0.
+ 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_${extension} : enable
+
+ in highp vec4 vcolor;
+ inout highp vec4 fcolor;
+
+ void main()
+ {
+ // The conditional assignment will be executed for the top
+ // and right quadrants.
+ 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]
+ ${bind_fb('GL_RGBA8')}
+
+ 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)
+
+ ${display_fb(3.0)}
+ """, product(common_defs,
+ [{'name': 'overwrite-gles3'}]))
+
+ #
+ # Test framebuffer fetch functionality on individual slices of a
+ # texture render target with multiple layers or mipmap levels.
+ #
+ gen_execution("""\
+ [require]
+ GL ES >= 3.0
+ GLSL ES >= 3.00
+ GL_${extension}
+
+ [vertex shader passthrough]
+
+ [fragment shader]
+ #version 300 es
+ #extension GL_${extension} : enable
+
+ inout highp vec4 fcolor;
+ uniform highp vec4 ucolor;
+
+ void main()
+ {
+ fcolor += ucolor;
+ }
+
+ [test]
+ %if target == 'Cube':
+ texture storage 0 ${target} GL_RGBA8 (${levels} 250 250)
+ %else:
+ texture storage 0 ${target} GL_RGBA8 (${levels} 250 250 ${layers})
+ %endif
+
+ <%! blend_colors = ['0.5 0.0 0.0 0.0',
+ '0.0 0.5 0.0 0.0',
+ '0.5 0.5 0.0 0.0',
+ '0.0 0.0 0.5 0.0'] %>
+
+ %for l in range(0, levels):
+ %for z in range(0, layers):
+ fb tex slice ${target} 0 ${l} ${z}
+ uniform vec4 ucolor ${blend_colors[(l + z) % 4]}
+ clear color 0.0 0.0 0.5 0.0
+ clear
+ draw rect -1 -1 2 2
+ draw rect -1 -1 2 2
+
+ %endfor
+ %endfor
+
+ <%! expected_colors = ['(1.0, 0.0, 0.5)',
+ '(0.0, 1.0, 0.5)',
+ '(1.0, 1.0, 0.5)',
+ '(0.0, 0.0, 1.0)'] %>
+
+ %for l in range(0, levels):
+ %for z in range(0, layers):
+ fb tex slice ${target} 0 ${l} ${z}
+ relative probe rect rgb (0.0, 0.0, 1.0, 1.0) ${expected_colors[(l + z) % 4]}
+
+ %endfor
+ %endfor
+
+ ${display_fb(3.0)}
+ """, product(common_defs,
+ [{'name': 'single-slice-'}],
+ [{'name': '2darray-gles3', 'target': '2DArray',
+ 'levels': 1, 'layers': 4},
+ {'name': '2darray-mipmap-gles3', 'target': '2DArray',
+ 'levels': 4, 'layers': 1},
+ {'name': '3d-gles3', 'target': '3D',
+ 'levels': 1, 'layers': 4},
+ {'name': 'cubemap-gles3', 'target': 'Cube',
+ 'levels': 1, 'layers': 6}]))
+
+if __name__ == '__main__':
+ main()