[Piglit] [RFC PATCH 2/5] add API-related tests for ARB_bindless_texture

Samuel Pitoiset samuel.pitoiset at gmail.com
Mon Mar 27 22:05:10 UTC 2017


Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
---
 tests/all.py                                      |  14 +
 tests/spec/CMakeLists.txt                         |   1 +
 tests/spec/arb_bindless_texture/CMakeLists.gl.txt |  21 +
 tests/spec/arb_bindless_texture/CMakeLists.txt    |   1 +
 tests/spec/arb_bindless_texture/border-color.c    | 209 ++++++++
 tests/spec/arb_bindless_texture/conversions.c     | 280 +++++++++++
 tests/spec/arb_bindless_texture/errors.c          | 514 +++++++++++++++++++
 tests/spec/arb_bindless_texture/handles.c         | 576 ++++++++++++++++++++++
 tests/spec/arb_bindless_texture/illegal.c         | 331 +++++++++++++
 tests/spec/arb_bindless_texture/legal.c           | 259 ++++++++++
 tests/spec/arb_bindless_texture/limit.c           | 302 ++++++++++++
 tests/spec/arb_bindless_texture/uint64_attribs.c  |  96 ++++
 tests/spec/arb_bindless_texture/uniform.c         | 371 ++++++++++++++
 13 files changed, 2975 insertions(+)
 create mode 100644 tests/spec/arb_bindless_texture/CMakeLists.gl.txt
 create mode 100644 tests/spec/arb_bindless_texture/CMakeLists.txt
 create mode 100644 tests/spec/arb_bindless_texture/border-color.c
 create mode 100644 tests/spec/arb_bindless_texture/conversions.c
 create mode 100644 tests/spec/arb_bindless_texture/errors.c
 create mode 100644 tests/spec/arb_bindless_texture/handles.c
 create mode 100644 tests/spec/arb_bindless_texture/illegal.c
 create mode 100644 tests/spec/arb_bindless_texture/legal.c
 create mode 100644 tests/spec/arb_bindless_texture/limit.c
 create mode 100644 tests/spec/arb_bindless_texture/uint64_attribs.c
 create mode 100644 tests/spec/arb_bindless_texture/uniform.c

diff --git a/tests/all.py b/tests/all.py
index ee7043118..58e9fc88c 100644
--- a/tests/all.py
+++ b/tests/all.py
@@ -4940,5 +4940,19 @@ with profile.test_list.group_manager(
     g(['intel_conservative_rasterization-innercoverage_gles3'])
     g(['intel_conservative_rasterization-tri_gles3'])
 
+# Group ARB_bindless_texture
+with profile.test_list.group_manager(
+	PiglitGLTest,
+	grouptools.join('spec', 'ARB_bindless_texture')) as g:
+    g(['arb_bindless_texture-border-color'], 'border-color')
+    g(['arb_bindless_texture-conversions'], 'conversions')
+    g(['arb_bindless_texture-errors'], 'errors')
+    g(['arb_bindless_texture-handles'], 'handles')
+    g(['arb_bindless_texture-illegal'], 'illegal')
+    g(['arb_bindless_texture-legal'], 'legal')
+    g(['arb_bindless_texture-limit'], 'limit')
+    g(['arb_bindless_texture-uint64_attribs'], 'uint64_attribs')
+    g(['arb_bindless_texture-uniform'], 'uniform')
+
 if platform.system() is 'Windows':
     profile.filters.append(lambda p, _: not p.startswith('glx'))
diff --git a/tests/spec/CMakeLists.txt b/tests/spec/CMakeLists.txt
index 01a7935c7..b3adcdcfd 100644
--- a/tests/spec/CMakeLists.txt
+++ b/tests/spec/CMakeLists.txt
@@ -2,6 +2,7 @@ add_subdirectory (amd_performance_monitor)
 add_subdirectory (amd_pinned_memory)
 add_subdirectory (arb_arrays_of_arrays)
 add_subdirectory (arb_base_instance)
+add_subdirectory (arb_bindless_texture)
 add_subdirectory (arb_buffer_storage)
 add_subdirectory (arb_clear_buffer_object)
 add_subdirectory (arb_clear_texture)
diff --git a/tests/spec/arb_bindless_texture/CMakeLists.gl.txt b/tests/spec/arb_bindless_texture/CMakeLists.gl.txt
new file mode 100644
index 000000000..2c83a296e
--- /dev/null
+++ b/tests/spec/arb_bindless_texture/CMakeLists.gl.txt
@@ -0,0 +1,21 @@
+include_directories(
+	${GLEXT_INCLUDE_DIR}
+	${OPENGL_INCLUDE_PATH}
+)
+
+link_libraries (
+	piglitutil_${piglit_target_api}
+	${OPENGL_gl_LIBRARY}
+)
+
+piglit_add_executable (arb_bindless_texture-border-color border-color.c)
+piglit_add_executable (arb_bindless_texture-conversions conversions.c)
+piglit_add_executable (arb_bindless_texture-errors errors.c)
+piglit_add_executable (arb_bindless_texture-handles handles.c)
+piglit_add_executable (arb_bindless_texture-illegal illegal.c)
+piglit_add_executable (arb_bindless_texture-legal legal.c)
+piglit_add_executable (arb_bindless_texture-limit limit.c)
+piglit_add_executable (arb_bindless_texture-uint64_attribs uint64_attribs.c)
+piglit_add_executable (arb_bindless_texture-uniform uniform.c)
+
+# vim: ft=cmake:
diff --git a/tests/spec/arb_bindless_texture/CMakeLists.txt b/tests/spec/arb_bindless_texture/CMakeLists.txt
new file mode 100644
index 000000000..144a306f4
--- /dev/null
+++ b/tests/spec/arb_bindless_texture/CMakeLists.txt
@@ -0,0 +1 @@
+piglit_include_target_api()
diff --git a/tests/spec/arb_bindless_texture/border-color.c b/tests/spec/arb_bindless_texture/border-color.c
new file mode 100644
index 000000000..76f3f9292
--- /dev/null
+++ b/tests/spec/arb_bindless_texture/border-color.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2017 Valve 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.
+ */
+
+/** \file
+ *
+ * Test cases which exercise different border color values with
+ * glGetTextureHandleARB() and glGetTextureSamplerARB().
+ */
+
+/* The ARB_bindless_texture spec says:
+ *
+ * "The error INVALID_OPERATION is generated if the border color (taken from
+ *  the embedded sampler for GetTextureHandleARB or from the <sampler> for
+ *  GetTextureSamplerHandleARB) is not one of the following allowed values.
+ *  If the texture's base internal format is signed or unsigned integer,
+ *  allowed values are (0,0,0,0), (0,0,0,1), (1,1,1,0), and (1,1,1,1). If the
+ *  base internal format is not integer, allowed values are
+ *  (0.0,0.0,0.0,0.0), (0.0,0.0,0.0,1.0), (1.0,1.0,1.0,0.0), and
+ *  (1.0,1.0,1.0,1.0)."
+ */
+
+#include "piglit-util-gl.h"
+
+static struct piglit_gl_test_config *piglit_config;
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+	piglit_config = &config;
+	config.supports_gl_compat_version = 33;
+	config.supports_gl_core_version = 33;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+static enum piglit_result
+check_valid_integer_border_colors(void *data)
+{
+	GLint border_colors[4][4] = {
+		{ 0, 0, 0, 0 },
+		{ 0, 0, 0, 1 },
+		{ 1, 1, 1, 0 },
+		{ 1, 1, 1, 1 },
+	};
+	GLuint tex, i;
+
+	for (i = 0; i < 4; i++) {
+		tex = piglit_integer_texture(GL_RGBA32I, 16, 16, 0, 0);
+		glTextureParameterIiv(tex, GL_TEXTURE_BORDER_COLOR,
+				      border_colors[i]);
+		glBindTexture(GL_TEXTURE_2D, 0);
+
+		glGetTextureHandleARB(tex);
+		if (!piglit_check_gl_error(GL_NO_ERROR))
+			return PIGLIT_FAIL;
+	}
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+check_invalid_integer_border_colors(void *data)
+{
+	GLint border_color[4] = { 42, 2, 7, 9 };
+	GLuint sampler, texture;
+
+	texture = piglit_integer_texture(GL_RGBA32I, 16, 16, 0, 0);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	/* Texture and sampler have to be consistent. */
+	glGenSamplers(1, &sampler);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+			GL_NEAREST);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+			GL_NEAREST);
+
+	glSamplerParameterIiv(sampler, GL_TEXTURE_BORDER_COLOR, border_color);
+
+	glGetTextureSamplerHandleARB(texture, sampler);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+check_valid_float_border_colors(void *data)
+{
+	GLfloat border_colors[4][4] = {
+		{ 0.0, 0.0, 0.0, 0.0 },
+		{ 0.0, 0.0, 0.0, 1.0 },
+		{ 1.0, 1.0, 1.0, 0.0 },
+		{ 1.0, 1.0, 1.0, 1.0 },
+	};
+	GLuint tex, i;
+
+	for (i = 0; i < 4; i++) {
+		tex = piglit_rgbw_texture(GL_RGBA32F, 16, 16, GL_FALSE,
+					  GL_FALSE, GL_UNSIGNED_NORMALIZED);
+		glTextureParameterfv(tex, GL_TEXTURE_BORDER_COLOR,
+				     border_colors[i]);
+		glBindTexture(GL_TEXTURE_2D, 0);
+
+		glGetTextureHandleARB(tex);
+		if (!piglit_check_gl_error(GL_NO_ERROR))
+			return PIGLIT_FAIL;
+	}
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+check_invalid_float_border_colors(void *data)
+{
+	GLfloat border_color[4] = { 0.3, 0.9, 0.7, 0.5 };
+	GLuint sampler, texture;
+
+	texture = piglit_rgbw_texture(GL_RGBA, 16, 16, GL_FALSE, GL_FALSE, 
+				      GL_UNSIGNED_NORMALIZED);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	/* Texture and sampler have to be consistent. */
+	glGenSamplers(1, &sampler);
+	glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+	glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+	glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+	/* Set an invalid border color */
+	glSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, border_color);
+
+	glGetTextureSamplerHandleARB(texture, sampler);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static const struct piglit_subtest subtests[] = {
+	{
+		"Check valid integer border color values",
+		"check_valid_integer_border_colors",
+		check_valid_integer_border_colors,
+		NULL
+	},
+	{
+		"Check invalid integer border color values",
+		"check_invalid_integer_border_colors",
+		check_invalid_integer_border_colors,
+		NULL
+	},
+	{
+		"Check valid float border color values",
+		"check_valid_float_border_colors",
+		check_valid_float_border_colors,
+		NULL
+	},
+	{
+		"Check invalid float border color values",
+		"check_invalid_float_border_colors",
+		check_invalid_float_border_colors,
+		NULL
+	},
+	{
+		NULL,
+		NULL,
+		NULL,
+		NULL
+	}
+};
+
+enum piglit_result
+piglit_display(void)
+{
+	return PIGLIT_FAIL;
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+	enum piglit_result result;
+
+	piglit_require_extension("GL_ARB_bindless_texture");
+	result = piglit_run_selected_subtests(subtests,
+					      piglit_config->selected_subtests,
+					      piglit_config->num_selected_subtests,
+					      PIGLIT_SKIP);
+	piglit_report_result(result);
+}
diff --git a/tests/spec/arb_bindless_texture/conversions.c b/tests/spec/arb_bindless_texture/conversions.c
new file mode 100644
index 000000000..809f908cb
--- /dev/null
+++ b/tests/spec/arb_bindless_texture/conversions.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2017 Valve 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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
+ * NON-INFRINGEMENT.  IN NO EVENT SHALL VMWARE AND/OR THEIR SUPPLIERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/** \file
+ *
+ * Test cases for conversions and explicit constructors.
+ */
+
+#include "piglit-util-gl.h"
+
+static struct piglit_gl_test_config *piglit_config;
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+	piglit_config = &config;
+	config.supports_gl_core_version = 33;
+	config.supports_gl_compat_version = 33;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+static const char *passthrough_vs_src =
+	"#version 330\n"
+	"\n"
+	"in vec4 piglit_vertex;\n"
+	"\n"
+	"void main()\n"
+	"{\n"
+	"	gl_Position = piglit_vertex;\n"
+	"}\n";
+
+GLuint vs;
+
+static enum piglit_result
+convert_sampler_to_uvec2(void *data)
+{
+	static const char *fs_src =
+		"#version 330\n"
+		"#extension GL_ARB_bindless_texture: require\n"
+		"\n"
+		"layout (bindless_sampler) uniform;\n"
+		"\n"
+		"uniform sampler2D given_tex;\n"
+		"uniform uvec2 expected_uval;\n"
+		"out vec4 color;\n"
+		"\n"
+		"void main()\n"
+		"{\n"
+		"	color = vec4(0.0, 1.0, 0.0, 1.0);\n"
+		"	uvec2 packval = uvec2(given_tex);\n"
+		"	if (packval != expected_uval)\n"
+		"		color.r = 1.0;\n"
+		"}\n";
+	float expected[4] = { 0.0, 1.0, 0.0, 1.0 };
+	GLuint expected_uval[2] = { 0x0040020, 0x1 };
+	GLuint64 handle = 0x100040020;
+	GLuint prog, fs;
+	GLint loc;
+	bool pass;
+
+	fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fs_src);
+	prog = piglit_link_simple_program(vs, fs);
+	glUseProgram(prog);
+
+	loc = glGetUniformLocation(prog, "expected_uval");
+	glUniform2uiv(loc, 1, expected_uval);
+
+	loc = glGetUniformLocation(prog, "given_tex");
+	glUniformHandleui64vARB(loc, 1, &handle);
+
+	piglit_draw_rect(-1, -1, 1, 1);
+	pass = piglit_probe_pixel_rgba(0, 0, expected);
+
+	piglit_present_results();
+
+	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+static enum piglit_result
+convert_uvec2_to_sampler(void *data)
+{
+	static const char *fs_src =
+		"#version 330\n"
+		"#extension GL_ARB_bindless_texture: require\n"
+		"\n"
+		"uniform uvec2 given_uval;\n"
+		"out vec4 color;\n"
+		"\n"
+		"void main()\n"
+		"{\n"
+		"	color = vec4(0.0, 1.0, 0.0, 1.0);\n"
+		"	sampler2D tex = sampler2D(given_uval);\n"
+		"	uvec2 pair = uvec2(tex);\n"
+		"	if (pair != given_uval)\n"
+		"		color.r = 1.0;\n"
+		"}\n";
+	float expected[4] = { 0.0, 1.0, 0.0, 1.0 };
+	GLuint given_uval[2] = { 0x0040020, 0x1 };
+	GLuint prog, fs;
+	GLint loc;
+	bool pass;
+
+	fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fs_src);
+	prog = piglit_link_simple_program(vs, fs);
+	glUseProgram(prog);
+
+	loc = glGetUniformLocation(prog, "given_uval");
+	glUniform2uiv(loc, 1, given_uval);
+
+	piglit_draw_rect(-1, -1, 1, 1);
+	pass = piglit_probe_pixel_rgba(0, 0, expected);
+
+	piglit_present_results();
+
+	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+static enum piglit_result
+convert_image_to_uvec2(void *data)
+{
+	static const char *fs_src =
+		"#version 330\n"
+		"#extension GL_ARB_bindless_texture: require\n"
+		"#extension GL_ARB_shader_image_load_store: enable\n"
+		"\n"
+		"layout (bindless_image) uniform;\n"
+		"\n"
+		"uniform writeonly image2D given_img;\n"
+		"uniform uvec2 expected_uval;\n"
+		"out vec4 color;\n"
+		"\n"
+		"void main()\n"
+		"{\n"
+		"	color = vec4(0.0, 1.0, 0.0, 1.0);\n"
+		"	uvec2 packval = uvec2(given_img);\n"
+		"	if (packval != expected_uval)\n"
+		"		color.r = 1.0;\n"
+		"}\n";
+	float expected[4] = { 0.0, 1.0, 0.0, 1.0 };
+	GLuint expected_val[2] = { 0x0040020, 0x1 };
+	GLuint64 handle = 0x100040020;
+	GLuint prog, fs;
+	GLint loc;
+	bool pass;
+
+	if (!piglit_is_extension_supported("GL_ARB_shader_image_load_store"))
+		return PIGLIT_SKIP;
+
+	fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fs_src);
+	prog = piglit_link_simple_program(vs, fs);
+	glUseProgram(prog);
+
+	loc = glGetUniformLocation(prog, "expected_uval");
+	glUniform2uiv(loc, 1, expected_val);
+
+	loc = glGetUniformLocation(prog, "given_img");
+	glUniformHandleui64vARB(loc, 1, &handle);
+
+	piglit_draw_rect(-1, -1, 1, 1);
+	pass = piglit_probe_pixel_rgba(0, 0, expected);
+
+	piglit_present_results();
+
+	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+static enum piglit_result
+convert_uvec2_to_image(void *data)
+{
+	static const char *fs_src =
+		"#version 330\n"
+		"#extension GL_ARB_bindless_texture: require\n"
+		"#extension GL_ARB_shader_image_load_store: enable\n"
+		"\n"
+		"uniform uvec2 given_uval;\n"
+		"out vec4 color;\n"
+		"\n"
+		"void main()\n"
+		"{\n"
+		"	color = vec4(0.0, 1.0, 0.0, 1.0);\n"
+		"	writeonly image2D img = sampler2D(given_uval);\n"
+		"	uvec2 pair = uvec2(img);\n"
+		"	if (pair != given_uval)\n"
+		"		color.r = 1.0;\n"
+		"}\n";
+	float expected[4] = { 0.0, 1.0, 0.0, 1.0 };
+	GLuint given_uval[2] = { 0x0040020, 0x1 };
+	GLuint prog, fs;
+	GLint loc;
+	bool pass;
+
+	if (!piglit_is_extension_supported("GL_ARB_shader_image_load_store"))
+		return PIGLIT_SKIP;
+
+	fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fs_src);
+	prog = piglit_link_simple_program(vs, fs);
+	glUseProgram(prog);
+
+	loc = glGetUniformLocation(prog, "given_uval");
+	glUniform2uiv(loc, 1, given_uval);
+
+	piglit_draw_rect(-1, -1, 1, 1);
+	pass = piglit_probe_pixel_rgba(0, 0, expected);
+
+	piglit_present_results();
+
+	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+static const struct piglit_subtest subtests[] = {
+	{
+		"Convert sampler to uvec2",
+		"convert_sampler_to_uvec2",
+		convert_sampler_to_uvec2,
+		NULL
+	},
+	{
+		"Convert uvec2 to sampler",
+		"convert_uvec2_to_sampler",
+		convert_uvec2_to_sampler,
+	},
+	{
+		"Convert image to uvec2",
+		"convert_image_to_uvec2",
+		convert_image_to_uvec2,
+		NULL
+	},
+	{
+		"Convert uvec2 to image",
+		"convert_uvec2_to_image",
+		convert_uvec2_to_image,
+	},
+	{
+		NULL,
+		NULL,
+		NULL,
+		NULL
+	}
+};
+
+enum piglit_result
+piglit_display(void)
+{
+	return PIGLIT_FAIL;
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+	enum piglit_result result;
+
+	vs = piglit_compile_shader_text(GL_VERTEX_SHADER, passthrough_vs_src);
+
+	piglit_require_extension("GL_ARB_bindless_texture");
+	result = piglit_run_selected_subtests(subtests,
+					      piglit_config->selected_subtests,
+					      piglit_config->num_selected_subtests,
+					      PIGLIT_SKIP);
+	piglit_report_result(result);
+}
diff --git a/tests/spec/arb_bindless_texture/errors.c b/tests/spec/arb_bindless_texture/errors.c
new file mode 100644
index 000000000..2f6607671
--- /dev/null
+++ b/tests/spec/arb_bindless_texture/errors.c
@@ -0,0 +1,514 @@
+/*
+ * Copyright (C) 2017 Valve 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.
+ */
+
+/** \file
+ *
+ * Test cases which exercice the new bindless API.
+ */
+
+#include "piglit-util-gl.h"
+
+static struct piglit_gl_test_config *piglit_config;
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+	piglit_config = &config;
+	config.supports_gl_compat_version = 33;
+	config.supports_gl_core_version = 33;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+static enum piglit_result
+check_GetTextureHandle_invalid_values(void *data)
+{
+	GLuint sampler, texture;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The error INVALID_VALUE is generated by GetTextureHandleARB or
+	 *  GetTextureSamplerHandleARB if <texture> is zero or not the name of
+	 *  an existing texture object."
+	 */
+
+	/* Invalid texture */
+	glGetTextureHandleARB(42);
+	if (!piglit_check_gl_error(GL_INVALID_VALUE))
+		return PIGLIT_FAIL;
+
+	/* Invalid texture */
+	glGenSamplers(1, &sampler);
+	glGetTextureSamplerHandleARB(42, sampler);
+	if (!piglit_check_gl_error(GL_INVALID_VALUE))
+		return PIGLIT_FAIL;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The error INVALID_VALUE is generated by GetTextureSamplerHandleARB
+	 *  if <sampler> is zero or is not the name of an existing sampler
+	 *  object."
+	 */
+
+	/* Invalid sampler */
+	glGenTextures(1, &texture);
+	glGetTextureSamplerHandleARB(texture, 42);
+	if (!piglit_check_gl_error(GL_INVALID_VALUE))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+check_GetTextureHandle_invalid_operations(void *data)
+{
+	GLuint sampler, texture;
+
+	glGenTextures(1, &texture);
+	glBindTexture(GL_TEXTURE_2D, texture);
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The error INVALID_OPERATION is generated by GetTextureHandleARB or
+	 *  GetTextureSamplerHandleARB if the texture object specified by
+	 *  <texture> is not complete."
+	 */
+
+	/* Incomplete texture */
+	glGetTextureHandleARB(texture);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	/* Incomplete texture */
+	glGenSamplers(1, &sampler);
+	glBindSampler(0, sampler);
+	glGetTextureSamplerHandleARB(texture, sampler);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+check_MakeTextureHandleResident_invalid_operations(void *data)
+{
+	GLuint64 handle;
+	GLuint texture;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The error INVALID_OPERATION is generated by
+	 *  MakeTextureHandleResidentARB if <handle> is not a valid texture
+	 *  handle, or if <handle> is already resident in the current GL
+	 *  context."
+	 */
+
+	/* Invalid handle */
+	glMakeTextureHandleResidentARB(42);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	texture = piglit_rgbw_texture(GL_RGBA, 16, 16, GL_FALSE, GL_FALSE,
+				      GL_UNSIGNED_NORMALIZED);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	handle = glGetTextureHandleARB(texture);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	glMakeTextureHandleResidentARB(handle);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	/* Already resident */
+	glMakeTextureHandleResidentARB(handle);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+check_MakeTextureHandleNonResident_invalid_operations(void *data)
+{
+	GLuint64 handle;
+	GLuint texture;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The error INVALID_OPERATION is generated by
+	 *  MakeTextureHandleNonResidentARB if <handle> is not a valid texture
+	 *  handle, or if <handle> is not resident in the current GL context."
+	 */
+
+	/* Invalid handle */
+	glMakeTextureHandleNonResidentARB(42);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	texture = piglit_rgbw_texture(GL_RGBA, 16, 16, GL_FALSE, GL_FALSE,
+				      GL_UNSIGNED_NORMALIZED);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	handle = glGetTextureHandleARB(texture);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	/* Not resident */
+	glMakeTextureHandleNonResidentARB(handle);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+check_IsTextureHandleResident_invalid_operations(void *data)
+{
+	GLboolean ret;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The error INVALID_OPERATION will be generated by
+	 *  IsTextureHandleResidentARB and IsImageHandleResidentARB if <handle>
+	 *  is not a valid texture or image handle, respectively."
+	 */
+	ret = glIsTextureHandleResidentARB(42);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	return ret == false ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+static enum piglit_result
+check_GetImageHandle_invalid_values(void *data)
+{
+	GLuint tex;
+
+	if (!piglit_is_extension_supported("GL_ARB_shader_image_load_store"))
+		return PIGLIT_SKIP;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The error INVALID_VALUE is generated by GetImageHandleARB if
+	 *  <texture> is zero or not the name of an existing texture object, if
+	 *  the image for <level> does not existing in <texture>, or if
+	 *  <layered> is FALSE and <layer> is greater than or equal to the
+	 *  number of layers in the image at <level>."
+	 *
+	 * NOTE: The spec says nothing about invalid formats, but I think it
+	 * makes sense to return INVALID_VALUE like BindImageTexture().
+	 */
+
+	/* Invalid texture */
+	glGetImageHandleARB(42, 0, GL_FALSE, 0, GL_RGBA32F);
+	if (!piglit_check_gl_error(GL_INVALID_VALUE))
+		return PIGLIT_FAIL;
+
+	tex = piglit_rgbw_texture(GL_RGBA32F, 16, 16, GL_TRUE, GL_FALSE,
+				  GL_UNSIGNED_NORMALIZED);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	/* Invalid level */
+	glGetImageHandleARB(tex, 42, GL_FALSE, 0, GL_RGBA32F);
+	if (!piglit_check_gl_error(GL_INVALID_VALUE))
+		return PIGLIT_FAIL;
+
+	/* Invalid layer */
+	glGetImageHandleARB(tex, 0, GL_FALSE, 42, GL_RGBA32F);
+	if (!piglit_check_gl_error(GL_INVALID_VALUE))
+		return PIGLIT_FAIL;
+
+	/* Invalid format */
+	glGetImageHandleARB(tex, 0, GL_FALSE, 0, GL_RGBA);
+	if (!piglit_check_gl_error(GL_INVALID_VALUE))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+check_GetImageHandle_invalid_operations(void *data)
+{
+	GLuint tex;
+
+	if (!piglit_is_extension_supported("GL_ARB_shader_image_load_store"))
+		return PIGLIT_SKIP;
+
+	glGenTextures(1, &tex);
+	glBindTexture(GL_TEXTURE_2D, tex);
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The error INVALID_OPERATION is generated by GetImageHandleARB if
+	 *  the texture object <texture> is not complete or if <layered> is
+	 *  TRUE and <texture> is not a three-dimensional, one-dimensional
+	 *  array, two dimensional array, cube map, or cube map array texture."
+	 */
+
+	/* Incomplete texture */
+	glGetImageHandleARB(tex, 0, GL_FALSE, 0, GL_RGBA32F);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	tex = piglit_rgbw_texture(GL_RGBA32F, 16, 16, GL_FALSE, GL_FALSE,
+				  GL_UNSIGNED_NORMALIZED);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	/* Not layered texture */
+	glGetImageHandleARB(tex, 0, GL_TRUE, 0, GL_RGBA32F);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+check_MakeImageHandleResident_invalid_enum(void *data)
+{
+	GLuint64 handle;
+	GLuint tex;
+
+	if (!piglit_is_extension_supported("GL_ARB_shader_image_load_store"))
+		return PIGLIT_SKIP;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "To make an image handle accessible to shaders for image loads,
+	 *  stores, and atomic operations, the handle must be made resident by
+	 *  calling:
+	 *
+	 *  void MakeImageHandleResidentARB(uint64 handle, enum access);
+	 *
+	 *  <access> specifies whether the texture bound to the image handle
+	 *  will be treated as READ_ONLY, WRITE_ONLY, or READ_WRITE."
+	 *
+	 * NOTE: The spec doesn't explicitely say that INVALID_ENUM should
+	 * be returned, but I think it makes sense (like NVIDIA).
+	 */
+	tex = piglit_rgbw_texture(GL_RGBA32F, 16, 16, GL_FALSE, GL_FALSE,
+				  GL_UNSIGNED_NORMALIZED);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	handle = glGetImageHandleARB(tex, 0, GL_FALSE, 0, GL_RGBA32F);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	/* Invalid access */
+	glMakeImageHandleResidentARB(handle, GL_DEPTH);
+	if (!piglit_check_gl_error(GL_INVALID_ENUM))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+check_MakeImageHandleResident_invalid_operations(void *data)
+{
+	GLuint64 handle;
+	GLuint tex;
+
+	if (!piglit_is_extension_supported("GL_ARB_shader_image_load_store"))
+		return PIGLIT_SKIP;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The error INVALID_OPERATION is generated by
+	 *  MakeImageHandleResidentARB if <handle> is not a valid image handle,
+	 *  or if <handle> is already resident in the current GL context."
+	 */
+
+	/* Invalid handle */
+	glMakeImageHandleResidentARB(42, GL_READ_WRITE);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	tex = piglit_rgbw_texture(GL_RGBA32F, 16, 16, GL_FALSE, GL_FALSE,
+				  GL_UNSIGNED_NORMALIZED);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	handle = glGetImageHandleARB(tex, 0, GL_FALSE, 0, GL_RGBA32F);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	glMakeImageHandleResidentARB(handle, GL_READ_WRITE);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	/* Handle already resident. */
+	glMakeImageHandleResidentARB(handle, GL_READ_WRITE);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+check_MakeImageHandleNonResident_invalid_operations(void *data)
+{
+	GLuint64 handle;
+	GLuint tex;
+
+	if (!piglit_is_extension_supported("GL_ARB_shader_image_load_store"))
+		return PIGLIT_SKIP;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The error INVALID_OPERATION is generated by
+	 *  MakeImageHandleNonResidentARB if <handle> is not a valid image
+	 *  handle, or if <handle> is not resident in the current GL context."
+	 */
+
+	/* Invalid handle */
+	glMakeImageHandleNonResidentARB(42);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	tex = piglit_rgbw_texture(GL_RGBA32F, 16, 16, GL_FALSE, GL_FALSE,
+				  GL_UNSIGNED_NORMALIZED);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	handle = glGetImageHandleARB(tex, 0, GL_FALSE, 0, GL_RGBA32F);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	/* Handle not resident. */
+	glMakeImageHandleNonResidentARB(handle);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+check_IsImageHandleResident_invalid_operations(void *data)
+{
+	GLboolean ret;
+
+	if (!piglit_is_extension_supported("GL_ARB_shader_image_load_store"))
+		return PIGLIT_SKIP;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The error INVALID_OPERATION will be generated by
+	 *  IsTextureHandleResidentARB and IsImageHandleResidentARB if <handle>
+	 *  is not a valid texture or image handle, respectively."
+	 */
+	ret = glIsImageHandleResidentARB(42);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	return ret == false ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+static const struct piglit_subtest subtests[] = {
+	{
+		"Check glGetTexture*HandleARB() invalid values",
+		"check_GetTextureHandle_invalid_values",
+		check_GetTextureHandle_invalid_values,
+		NULL
+	},
+	{
+		"Check glGetTexture*HandleARB() invalid operations",
+		"check_GetTextureHandle_invalid_operations",
+		check_GetTextureHandle_invalid_operations,
+		NULL
+	},
+	{
+		"Check glMakeTextureHandleResidentARB() invalid operations",
+		"check_MakeTextureHandleResident_invalid_operations",
+		check_MakeTextureHandleResident_invalid_operations,
+		NULL
+	},
+	{
+		"Check glMakeTextureHandleNonResidentARB() invalid operations",
+		"check_MakeTextureHandleNonResident_invalid_operations",
+		check_MakeTextureHandleNonResident_invalid_operations,
+		NULL
+	},
+	{
+		"Check glIsTextureHandleResidentARB() invalid operations",
+		"check_IsTextureHandleResident_invalid_operations",
+		check_IsTextureHandleResident_invalid_operations,
+		NULL
+	},
+	{
+		"Check glGetImageHandleARB() invalid values",
+		"check_GetImageHandle_invalid_values",
+		check_GetImageHandle_invalid_values,
+		NULL
+	},
+	{
+		"Check glGetImageHandleARB() invalid operations",
+		"check_GetImageHandle_invalid_operations",
+		check_GetImageHandle_invalid_operations,
+		NULL
+	},
+	{
+		"Check glMakeImageHandleResidentARB() invalid enum",
+		"check_MakeImageHandleResident_invalid_enum",
+		check_MakeImageHandleResident_invalid_enum,
+		NULL
+	},
+	{
+		"Check glMakeImageHandleResidentARB() invalid operations",
+		"check_MakeImageHandleResident_invalid_operations",
+		check_MakeImageHandleResident_invalid_operations,
+		NULL
+	},
+	{
+		"Check glMakeImageHandleNonResidentARB() invalid operations",
+		"check_MakeImageHandleNonResident_invalid_operations",
+		check_MakeImageHandleNonResident_invalid_operations,
+		NULL
+	},
+	{
+		"Check glIsImageHandleResidentARB() invalid operations",
+		"check_IsImageHandleResident_invalid_operations",
+		check_IsImageHandleResident_invalid_operations,
+		NULL
+	},
+	{
+		NULL,
+		NULL,
+		NULL,
+		NULL
+	}
+};
+
+enum piglit_result
+piglit_display(void)
+{
+	return PIGLIT_FAIL;
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+	enum piglit_result result;
+
+	piglit_require_extension("GL_ARB_bindless_texture");
+	result = piglit_run_selected_subtests(subtests,
+					      piglit_config->selected_subtests,
+					      piglit_config->num_selected_subtests,
+					      PIGLIT_SKIP);
+	piglit_report_result(result);
+}
diff --git a/tests/spec/arb_bindless_texture/handles.c b/tests/spec/arb_bindless_texture/handles.c
new file mode 100644
index 000000000..902a1c392
--- /dev/null
+++ b/tests/spec/arb_bindless_texture/handles.c
@@ -0,0 +1,576 @@
+/*
+ * Copyright (C) 2017 Valve 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.
+ */
+
+/** \file
+ *
+ * Test cases which exercice the texture handle API with
+ * glGetTextureHandleARB(), glMakeTextureHandleResidentARB(), etc.
+ */
+
+#include "piglit-util-gl.h"
+
+static struct piglit_gl_test_config *piglit_config;
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+	piglit_config = &config;
+	config.supports_gl_compat_version = 33;
+	config.supports_gl_core_version = 33;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+static enum piglit_result
+check_GetTextureHandle_zero_handle(void *data)
+{
+	bool pass = true;
+	GLuint64 handle;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "If an error occurs, a handle of zero is returned."
+	 */
+	handle = glGetTextureHandleARB(42);
+	if (!piglit_check_gl_error(GL_INVALID_VALUE))
+		return PIGLIT_FAIL;
+
+	pass &= handle == 0;
+
+	handle = glGetTextureSamplerHandleARB(42, 42);
+	if (!piglit_check_gl_error(GL_INVALID_VALUE))
+		return PIGLIT_FAIL;
+
+	pass &= handle == 0;
+
+	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+static enum piglit_result
+check_GetTextureHandle_reserved_zero_handle(void *data)
+{
+	GLuint texture, sampler;
+	bool pass = true;
+	GLuint64 handle;
+
+	texture = piglit_rgbw_texture(GL_RGBA32F, 16, 16, GL_FALSE, GL_FALSE,
+				      GL_UNSIGNED_NORMALIZED);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The handle zero is reserved and will never be assigned to a valid
+	 *  texture handle."
+	 */
+	handle = glGetTextureHandleARB(texture);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	pass &= handle > 0;
+
+	/* Texture and sampler have to be consistent. */
+	glGenSamplers(1, &sampler);
+	glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+	glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+	glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+	handle = glGetTextureSamplerHandleARB(texture, sampler);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	pass &= handle > 0;
+
+	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+static enum piglit_result
+check_GetTextureHandle_uniqueness(void *data)
+{
+	GLuint sampler, texture;
+	GLuint64 handles[4];
+	bool pass = true;
+
+	texture = piglit_rgbw_texture(GL_RGBA32F, 16, 16, GL_FALSE, GL_FALSE,
+				      GL_UNSIGNED_NORMALIZED);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The handle for each texture or texture/sampler pair is unique; the
+	 *  same handle will be returned if GetTextureHandleARB is called
+	 *  multiple times for the same texture or if GetTextureSamplerHandleARB
+	 *  is called multiple times for the same texture/sampler pair."
+	 */
+	handles[0] = glGetTextureHandleARB(texture);
+	handles[1] = glGetTextureHandleARB(texture);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	pass &= handles[0] == handles[1];
+
+	/* Texture and sampler have to be consistent. */
+	glGenSamplers(1, &sampler);
+	glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+	glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+	glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+	handles[2] = glGetTextureSamplerHandleARB(texture, sampler);
+	handles[3] = glGetTextureSamplerHandleARB(texture, sampler);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	pass &= handles[2] == handles[3];
+	pass &= handles[0] != handles[2];
+
+	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+static enum piglit_result
+check_IsTextureHandleResident_valid(void *data)
+{
+	bool pass = true;
+	GLuint64 handle;
+	GLboolean ret;
+	GLuint tex;
+
+	tex = piglit_rgbw_texture(GL_RGBA32F, 16, 16, GL_FALSE, GL_FALSE,
+				  GL_UNSIGNED_NORMALIZED);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	handle = glGetTextureHandleARB(tex);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	/* Resident */
+	glMakeTextureHandleResidentARB(handle);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	ret = glIsTextureHandleResidentARB(handle);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	pass &= ret;
+
+	/* Non resident */
+	glMakeTextureHandleNonResidentARB(handle);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	ret = glIsTextureHandleResidentARB(handle);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	pass &= !ret;
+
+	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+static enum piglit_result
+delete_texture_sampler_while_handle_is_allocated(void *data)
+{
+	GLuint texture, sampler;
+	GLuint64 handle;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "(5) Is there a way to release a texture or image handle after it
+	 *  is created?"
+	 *
+	 * "RESOLVED:  No API is provided to release or delete handles once
+	 *  they are created.  Texture and image handles are automatically
+	 *  reclaimed when the underlying texture or sampler objects are finally
+	 *  deleted.  This deletion will happen only when no handle using the
+	 *  texture or sampler object is resident on any context."
+	 */
+
+	/* Test #1: Create a texture handle and remove it. */
+	texture = piglit_rgbw_texture(GL_RGBA32F, 16, 16, GL_FALSE, GL_FALSE,
+				      GL_UNSIGNED_NORMALIZED);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	handle = glGetTextureHandleARB(texture);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	glDeleteTextures(1, &texture);
+
+	/* Texture handle should have been removed. */
+	glMakeTextureHandleResidentARB(handle);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	/* Test #2: Create a texture/sampler handle and remove the sampler. */
+	texture = piglit_rgbw_texture(GL_RGBA32F, 16, 16, GL_FALSE, GL_FALSE,
+				      GL_UNSIGNED_NORMALIZED);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	/* Texture and sampler have to be consistent. */
+	glGenSamplers(1, &sampler);
+	glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+	glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+	glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+	handle = glGetTextureSamplerHandleARB(texture, sampler);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	glDeleteSamplers(1, &sampler);
+
+	/* Texture handle should have been removed. */
+	glMakeTextureHandleResidentARB(handle);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+delete_texture_sampler_while_handle_is_resident(void *data)
+{
+	GLuint texture, sampler;
+	GLuint64 handle;
+	GLboolean ret;
+
+	/* The ARB_bindless_texture_spec says:
+	 *
+	 * "(7) What happens if you try to delete a texture or sampler object
+	 *  with a handle that is resident in another context?"
+	 *
+	 * "RESOLVED:  Deleting the texture will remove the texture from the
+	 *  name space and make all handles using the texture non-resident in
+	 *  the current context.  However, texture or image handles for a
+	 *  deleted texture are not deleted until the underlying texture or
+	 *  sampler object itself is deleted.  That deletion won't happen
+	 *  until the object is not bound anywhere and there are no handles
+	 *  using the object that are resident in any context."
+	 */
+
+	/* Test #1: Create a texture handle, make it resident and remove the
+	 * texture. */
+	texture = piglit_rgbw_texture(GL_RGBA, 16, 16, GL_FALSE, GL_FALSE,
+				      GL_UNSIGNED_NORMALIZED);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	handle = glGetTextureHandleARB(texture);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	glMakeTextureHandleResidentARB(handle);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	glDeleteTextures(1, &texture);
+
+	/* Texture handle should have been removed. */
+	glIsTextureHandleResidentARB(handle);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	/* Test #2: Create a texture/sampler handle, make it resident and
+	 * remove the sampler. */
+	texture = piglit_rgbw_texture(GL_RGBA32F, 16, 16, GL_FALSE, GL_FALSE,
+				      GL_UNSIGNED_NORMALIZED);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	/* Texture and sampler have to be consistent. */
+	glGenSamplers(1, &sampler);
+	glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+	glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+	glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+	handle = glGetTextureSamplerHandleARB(texture, sampler);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	glMakeTextureHandleResidentARB(handle);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	glDeleteSamplers(1, &sampler);
+
+	/* Texture handle should still be resident. */
+	ret = glIsTextureHandleResidentARB(handle);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	if (!ret)
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+check_GetImageHandle_zero_handle(void *data)
+{
+	GLuint64 handle;
+
+	if (!piglit_is_extension_supported("GL_ARB_shader_image_load_store"))
+		return PIGLIT_SKIP;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "A 64-bit unsigned integer handle is returned if the command
+	 *  succeeds; otherwise, zero is returned."
+	 */
+	handle = glGetImageHandleARB(42, 0, GL_FALSE, 0, GL_RGBA32F);
+	if (!piglit_check_gl_error(GL_INVALID_VALUE))
+		return PIGLIT_FAIL;
+
+	return handle == 0 ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+static enum piglit_result
+check_GetImageHandle_reserved_zero_handle(void *data)
+{
+	GLuint64 handle;
+	GLuint tex;
+
+	if (!piglit_is_extension_supported("GL_ARB_shader_image_load_store"))
+		return PIGLIT_SKIP;
+
+	tex = piglit_rgbw_texture(GL_RGBA32F, 16, 16, GL_FALSE, GL_FALSE,
+				  GL_UNSIGNED_NORMALIZED);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The handle zero is reserved and will never be assigned to a valid
+	 *  image handle."
+	 */
+	handle = glGetImageHandleARB(tex, 0, GL_FALSE, 0, GL_RGBA32F);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	return handle > 0 ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+static enum piglit_result
+check_GetImageHandle_uniqueness(void *data)
+{
+	GLuint64 handles[4];
+	bool pass = true;
+	GLuint tex;
+
+	if (!piglit_is_extension_supported("GL_ARB_shader_image_load_store"))
+		return PIGLIT_SKIP;
+
+	tex = piglit_rgbw_texture(GL_RGBA32F, 16, 16, GL_TRUE, GL_FALSE,
+				  GL_UNSIGNED_NORMALIZED);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The handle returned for each combination of <texture>, <level>,
+	 *  <layered>, <layer>, and <format> is unique; the same handle will
+	 *  be returned if GetImageHandleARB is called multiple times with
+	 *  the same parameters."
+	 */
+	handles[0] = glGetImageHandleARB(tex, 0, GL_FALSE, 0, GL_RGBA32F);
+	handles[1] = glGetImageHandleARB(tex, 0, GL_FALSE, 0, GL_RGBA32F);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	pass &= handles[0] == handles[1];
+
+	/* Use a different format. */
+	handles[2] = glGetImageHandleARB(tex, 0, GL_FALSE, 0, GL_RGBA32I);
+	handles[3] = glGetImageHandleARB(tex, 0, GL_FALSE, 0, GL_RGBA32I);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	pass &= handles[2] == handles[3];
+	pass &= handles[0] != handles[2];
+
+	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+static enum piglit_result
+check_IsImageHandleResident_valid(void *data)
+{
+	bool pass = true;
+	GLuint64 handle;
+	GLboolean ret;
+	GLuint tex;
+
+	if (!piglit_is_extension_supported("GL_ARB_shader_image_load_store"))
+		return PIGLIT_SKIP;
+
+	tex = piglit_rgbw_texture(GL_RGBA32F, 16, 16, GL_TRUE, GL_FALSE,
+				  GL_UNSIGNED_NORMALIZED);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	handle = glGetImageHandleARB(tex, 0, GL_FALSE, 0, GL_RGBA32F);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	/* Resident */
+	glMakeImageHandleResidentARB(handle, GL_READ_WRITE);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	ret = glIsImageHandleResidentARB(handle);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	pass &= ret;
+
+	/* Non resident */
+	glMakeImageHandleNonResidentARB(handle);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	ret = glIsImageHandleResidentARB(handle);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	pass &= !ret;
+
+	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+static enum piglit_result
+delete_texture_while_image_handle_resident(void *data)
+{
+	GLuint64 handle;
+	GLuint tex;
+
+	if (!piglit_is_extension_supported("GL_ARB_shader_image_load_store"))
+		return PIGLIT_SKIP;
+
+	tex = piglit_rgbw_texture(GL_RGBA32F, 16, 16, GL_TRUE, GL_FALSE,
+				  GL_UNSIGNED_NORMALIZED);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	handle = glGetImageHandleARB(tex, 0, GL_FALSE, 0, GL_RGBA32F);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	glMakeImageHandleResidentARB(handle, GL_READ_WRITE);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	glDeleteTextures(1, &tex);
+
+	/* Image handle should have been removed. */
+	glMakeImageHandleResidentARB(handle, GL_READ_WRITE);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static const struct piglit_subtest subtests[] = {
+	{
+		"Check glGetTexture*HandleARB() zero handle",
+		"check_GetTextureHandle_zero_handle",
+		check_GetTextureHandle_zero_handle,
+		NULL
+	},
+	{
+		"Check glGetTexture*HandleARB() reserved zero handle",
+		"check_GetTextureHandle_reserved_zero_handle",
+		check_GetTextureHandle_reserved_zero_handle,
+		NULL
+	},
+	{
+		"Check glGetTexture*HandleARB() uniqueness",
+		"check_GetTextureHandle_uniqueness",
+		check_GetTextureHandle_uniqueness,
+		NULL
+	},
+	{
+		"Check glIsTextureHandleResidentARB() valid",
+		"check_IsTextureHandleResident_valid",
+		check_IsTextureHandleResident_valid,
+		NULL
+	},
+	{
+		"Delete the texture/sampler while a handle is allocated",
+		"delete_texture_sampler_while_handle_is_allocated",
+		delete_texture_sampler_while_handle_is_allocated,
+		NULL
+	},
+	{
+		"Delete the texture/sampler while the handle is resident",
+		"delete_texture_sampler_while_handle_is_resident",
+		delete_texture_sampler_while_handle_is_resident,
+	},
+	{
+		"Check glGetImageHandleARB() zero handle",
+		"check_GetImageHandle_zero_handle",
+		check_GetImageHandle_zero_handle,
+		NULL
+	},
+	{
+		"Check glGetImageHandleARB() reserved zero handle",
+		"check_GetImageHandle_reserved_zero_handle",
+		check_GetImageHandle_reserved_zero_handle,
+		NULL
+	},
+	{
+		"Check glGetImageHandleARB() uniqueness",
+		"check_GetImageHandle_uniqueness",
+		check_GetImageHandle_uniqueness,
+		NULL
+	},
+	{
+		"Check glIsImageHandleResidentARB() valid",
+		"check_IsImageHandleResident_valid",
+		check_IsImageHandleResident_valid,
+		NULL
+	},
+	{
+		"Delete the texture while the image handle is resident",
+		"delete_texture_while_image_handle_resident",
+		delete_texture_while_image_handle_resident,
+		NULL
+	},
+	{
+		NULL,
+		NULL,
+		NULL,
+		NULL
+	}
+};
+
+enum piglit_result
+piglit_display(void)
+{
+	return PIGLIT_FAIL;
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+	enum piglit_result result;
+
+	piglit_require_extension("GL_ARB_bindless_texture");
+	result = piglit_run_selected_subtests(subtests,
+					      piglit_config->selected_subtests,
+					      piglit_config->num_selected_subtests,
+					      PIGLIT_SKIP);
+	piglit_report_result(result);
+}
diff --git a/tests/spec/arb_bindless_texture/illegal.c b/tests/spec/arb_bindless_texture/illegal.c
new file mode 100644
index 000000000..c2c713452
--- /dev/null
+++ b/tests/spec/arb_bindless_texture/illegal.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2017 Valve 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.
+ */
+
+/** \file
+ *
+ * Test cases which exercise illegal operations when a texture/sampler object
+ * has been referenced by one or more texture handles.
+ */
+
+#include "piglit-util-gl.h"
+
+static struct piglit_gl_test_config *piglit_config;
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+	piglit_config = &config;
+	config.supports_gl_compat_version = 33;
+	config.supports_gl_core_version = 33;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+static enum piglit_result
+call_TextureParameter_when_texture_is_referenced(void *data)
+{
+	GLuint tex;
+
+	tex = piglit_integer_texture(GL_RGBA32I, 16, 16, 0, 0);
+
+	glGetTextureHandleARB(tex);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	/* The ARB_bindless_texture_spec says:
+	 *
+	 * "The error INVALID_OPERATION is generated by TexImage*,
+	 *  CopyTexImage*, CompressedTexImage*, TexBuffer*, TexParameter*, as
+	 *  well as other functions defined in terms of these, if the texture
+	 *  object to be modified is referenced by one or more texture or image
+	 *  handles."
+	 */
+	glTextureParameteri(tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+call_TexImage_when_texture_is_referenced(void *data)
+{
+	GLuint tex;
+
+	tex = piglit_integer_texture(GL_RGBA32I, 16, 16, 0, 0);
+
+	glGetTextureHandleARB(tex);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	/* The ARB_bindless_texture_spec says:
+	 *
+	 * "The error INVALID_OPERATION is generated by TexImage*,
+	 *  CopyTexImage*, CompressedTexImage*, TexBuffer*, TexParameter*, as
+	 *  well as other functions defined in terms of these, if the texture
+	 *  object to be modified is referenced by one or more texture or image
+	 *  handles."
+	 */
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 16, 16, 0, GL_RGBA_INTEGER,
+		     GL_INT, NULL);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+call_CopyTexImage_when_texture_is_referenced(void *data)
+{
+	GLuint tex;
+
+	tex = piglit_integer_texture(GL_RGBA32I, 16, 16, 0, 0);
+
+	glGetTextureHandleARB(tex);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	/* The ARB_bindless_texture_spec says:
+	 *
+	 * "The error INVALID_OPERATION is generated by TexImage*,
+	 *  CopyTexImage*, CompressedTexImage*, TexBuffer*, TexParameter*, as
+	 *  well as other functions defined in terms of these, if the texture
+	 *  object to be modified is referenced by one or more texture or image
+	 *  handles."
+	 */
+	glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 16, 16, 0);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+call_CompressedTexImage_when_texture_is_referenced(void *data)
+{
+	void *compressed;
+	GLuint tex;
+	GLint size;
+
+	tex = piglit_rgbw_texture(GL_COMPRESSED_RGBA_BPTC_UNORM, 16, 16,
+				  GL_FALSE, GL_FALSE, GL_UNSIGNED_NORMALIZED);
+
+	glGetTextureHandleARB(tex);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	glGetTexLevelParameteriv(GL_TEXTURE_2D, 0,
+				 GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &size);
+
+	compressed = malloc(size);
+	glGetCompressedTexImage(GL_TEXTURE_2D, 0, compressed);
+
+	/* The ARB_bindless_texture_spec says:
+	 *
+	 * "The error INVALID_OPERATION is generated by TexImage*,
+	 *  CopyTexImage*, CompressedTexImage*, TexBuffer*, TexParameter*, as
+	 *  well as other functions defined in terms of these, if the texture
+	 *  object to be modified is referenced by one or more texture or
+	 *  image handles."
+	 */
+	glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_BPTC_UNORM,
+			       16, 16, 0, size, compressed);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	free(compressed);
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+call_TexBuffer_when_texture_is_referenced(void *data)
+{
+	static const float red[4] = {1, 0, 0, 0};
+	GLuint tex, tbo;
+
+	glGenBuffers(1, &tbo);
+	glBindBuffer(GL_TEXTURE_BUFFER, tbo);
+	glBufferData(GL_TEXTURE_BUFFER, sizeof(red), red, GL_STATIC_DRAW);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	glGenTextures(1, &tex);
+	glBindTexture(GL_TEXTURE_BUFFER, tex);
+	glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tbo);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	glGetTextureHandleARB(tex);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	/* The ARB_bindless_texture_spec says:
+	 *
+	 * "The error INVALID_OPERATION is generated by TexImage*,
+	 *  CopyTexImage*, CompressedTexImage*, TexBuffer*, TexParameter*, as
+	 *  well as other functions defined in terms of these, if the texture
+	 *  object to be modified is referenced by one or more texture or
+	 *  image handles."
+	 */
+	glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tbo);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+call_BufferData_when_texture_is_referenced(void *data)
+{
+	static const float red[4] = {1, 0, 0, 0};
+	GLuint tex, tbo;
+
+	glGenBuffers(1, &tbo);
+	glBindBuffer(GL_TEXTURE_BUFFER, tbo);
+	glBufferData(GL_TEXTURE_BUFFER, sizeof(red), red, GL_STATIC_DRAW);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	glGenTextures(1, &tex);
+	glBindTexture(GL_TEXTURE_BUFFER, tex);
+	glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tbo);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	glGetTextureHandleARB(tex);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The error INVALID_OPERATION is generated by BufferData if it is
+	 *  called to modify a buffer object bound to a buffer texture while
+	 *  that texture object is referenced by one or more texture handles."
+	 */
+	glBufferData(GL_TEXTURE_BUFFER, sizeof(red), red, GL_STATIC_DRAW);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+call_SamplerParameter_when_texture_is_referenced(void *data)
+{
+	GLuint sampler, texture;
+
+	texture = piglit_integer_texture(GL_RGBA32I, 16, 16, 0, 0);
+
+	/* Texture and sampler have to be consistent. */
+	glGenSamplers(1, &sampler);
+	glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+	glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+	glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+	glGetTextureSamplerHandleARB(texture, sampler);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "When a sampler object is referenced by one or more texture
+	 *  handles, the sampler parameters of the object may not be changed.
+	 *  The error INVALID_OPERATION is generated when calling
+	 *  SamplerParameter* functions to modify a sampler object referenced
+	 *  by one or more texture handles."
+	 */
+	glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static const struct piglit_subtest subtests[] = {
+	{
+		"Call glTextureParameter* when a texture handle is referenced",
+		"call_TextureParameter_when_texture_referenced",
+		call_TextureParameter_when_texture_is_referenced,
+		NULL
+	},
+	{
+		"Call glTexImage* when a texture handle is referenced",
+		"call_TexImage_when_texture_referenced",
+		call_TexImage_when_texture_is_referenced,
+		NULL
+	},
+	{
+		"Call glCopyTexImage* when a texture handle is referenced",
+		"call_CopyTexImage_when_texture_referenced",
+		call_CopyTexImage_when_texture_is_referenced,
+		NULL
+	},
+	{
+		"Call glCompressedTexImage* when a texture handle is referenced",
+		"call_CompressedTexImage_when_texture_referenced",
+		call_CompressedTexImage_when_texture_is_referenced,
+		NULL
+	},
+	{
+		"Call glTexBuffer* when a texture handle is referenced",
+		"call_TexBuffer_when_texture_referenced",
+		call_TexBuffer_when_texture_is_referenced,
+		NULL
+	},
+	{
+		"Call glBufferData when a texture handle is referenced",
+		"call_BufferData_when_texture_referenced",
+		call_BufferData_when_texture_is_referenced,
+		NULL
+	},
+	{
+		"Call glSamplerParameter* when a texture handle is referenced",
+		"call_SamplerParameter_when_texture_referenced",
+		call_SamplerParameter_when_texture_is_referenced,
+		NULL
+	},
+	{
+		NULL,
+		NULL,
+		NULL,
+		NULL
+	}
+};
+
+enum piglit_result
+piglit_display(void)
+{
+	return PIGLIT_FAIL;
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+	enum piglit_result result;
+
+	piglit_require_extension("GL_ARB_bindless_texture");
+	result = piglit_run_selected_subtests(subtests,
+					      piglit_config->selected_subtests,
+					      piglit_config->num_selected_subtests,
+					      PIGLIT_SKIP);
+	piglit_report_result(result);
+}
diff --git a/tests/spec/arb_bindless_texture/legal.c b/tests/spec/arb_bindless_texture/legal.c
new file mode 100644
index 000000000..0626eef0e
--- /dev/null
+++ b/tests/spec/arb_bindless_texture/legal.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2017 Valve 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.
+ */
+
+/** \file
+ *
+ * Test cases which exercise legal operations when a texture/sampler object
+ * has been referenced by one or more texture handles.
+ */
+
+#include "piglit-util-gl.h"
+
+static struct piglit_gl_test_config *piglit_config;
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+	piglit_config = &config;
+	config.supports_gl_compat_version = 33;
+	config.supports_gl_core_version = 33;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+static enum piglit_result
+call_TexSubImage_when_texture_is_referenced(void *data)
+{
+	int *img = malloc(16 * 16 * 4 * sizeof(unsigned));
+	GLuint tex;
+
+	tex = piglit_integer_texture(GL_RGBA32I, 16, 16, 0, 0);
+
+	glGetTextureHandleARB(tex);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The contents of the images in a texture object may still be
+	 *  updated via commands such as TexSubImage*, CopyTexSubImage*, and
+	 *  CompressedTexSubImage*, and by rendering to a framebuffer object,
+	 *  even if the texture object is referenced by one or more texture
+	 *  handles."
+	 */
+	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGBA_INTEGER,
+			GL_INT, img);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	free(img);
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+call_CopyTexSubImage_when_texture_is_referenced(void *data)
+{
+	GLuint tex;
+
+	tex = piglit_rgbw_texture(GL_RGBA8, 16, 16, GL_FALSE, GL_FALSE,
+				  GL_UNSIGNED_BYTE);
+
+	glGetTextureHandleARB(tex);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The contents of the images in a texture object may still be
+	 *  updated via commands such as TexSubImage*, CopyTexSubImage*, and
+	 *  CompressedTexSubImage*, and by rendering to a framebuffer object,
+	 *  even if the texture object is referenced by one or more texture
+	 *  handles."
+	 */
+	glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 16, 16);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+call_CompressedTexSubImage_when_texture_is_referenced(void *data)
+{
+	void *compressed;
+	GLuint tex;
+	GLint size;
+
+	tex = piglit_rgbw_texture(GL_COMPRESSED_RGBA_BPTC_UNORM, 16, 16,
+				  GL_FALSE, GL_FALSE, GL_UNSIGNED_NORMALIZED);
+
+	glGetTextureHandleARB(tex);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	glGetTexLevelParameteriv(GL_TEXTURE_2D, 0,
+				 GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &size);
+
+	compressed = malloc(size);
+	glGetCompressedTexImage(GL_TEXTURE_2D, 0, compressed);
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The contents of the images in a texture object may still be
+	 *  updated via commands such as TexSubImage*, CopyTexSubImage*, and
+	 *  CompressedTexSubImage*, and by rendering to a framebuffer object,
+	 *  even if the texture object is referenced by one or more texture
+	 *  handles."
+	 */
+	glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16,
+				  GL_COMPRESSED_RGBA_BPTC_UNORM, size,
+				  compressed);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	free(compressed);
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+call_BufferSubData_when_texture_is_referenced(void *data)
+{
+	static const float red[4] = {1, 0, 0, 0};
+	GLuint tex, tbo;
+
+	glGenBuffers(1, &tbo);
+	glBindBuffer(GL_TEXTURE_BUFFER, tbo);
+	glBufferData(GL_TEXTURE_BUFFER, sizeof(red), red, GL_STATIC_DRAW);
+
+	glGenTextures(1, &tex);
+	glBindTexture(GL_TEXTURE_BUFFER, tex);
+	glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tbo);
+
+	glGetTextureHandleARB(tex);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The contents of the buffer object may still be updated via buffer
+	 *  update commands such as BufferSubData and MapBuffer*, or via the
+	 *  texture update commands, even if the buffer is bound to a texture
+	 *  while that buffer texture object is referenced by one or more
+	 *  texture handles."
+	 */
+	glBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(red), red);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+call_MapBuffer_when_texture_is_referenced(void *data)
+{
+	static const float red[4] = {1, 0, 0, 0};
+	GLuint tex, tbo;
+
+	glGenBuffers(1, &tbo);
+	glBindBuffer(GL_TEXTURE_BUFFER, tbo);
+	glBufferData(GL_TEXTURE_BUFFER, sizeof(red), red, GL_STATIC_DRAW);
+
+	glGenTextures(1, &tex);
+	glBindTexture(GL_TEXTURE_BUFFER, tex);
+	glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tbo);
+
+	glGetTextureHandleARB(tex);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The contents of the buffer object may still be updated via buffer
+	 *  update commands such as BufferSubData and MapBuffer*, or via the
+	 *  texture update commands, even if the buffer is bound to a texture
+	 *  while that buffer texture object is referenced by one or more
+	 *  texture handles."
+	 */
+	glMapBuffer(GL_TEXTURE_BUFFER, GL_READ_ONLY);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+	glUnmapBuffer(GL_TEXTURE_BUFFER);
+
+	return PIGLIT_PASS;
+}
+
+static const struct piglit_subtest subtests[] = {
+	{
+		"Call glTexSubImage* when a texture handle is referenced",
+		"call_TexSubImage_when_texture_referenced",
+		call_TexSubImage_when_texture_is_referenced,
+		NULL
+	},
+	{
+		"Call glCopyTexSubImage* when a texture handle is referenced",
+		"call_CopyTexSubImage_when_texture_referenced",
+		call_CopyTexSubImage_when_texture_is_referenced,
+		NULL
+	},
+	{
+		"Call glCompressedTexSubImage* when a texture handle is referenced",
+		"call_CompressedTexSubImage_when_texture_referenced",
+		call_CompressedTexSubImage_when_texture_is_referenced,
+		NULL
+	},
+	{
+		"Call glBufferSubData when a texture handle is referenced",
+		"call_BufferSubData_when_texture_referenced",
+		call_BufferSubData_when_texture_is_referenced,
+		NULL
+	},
+	{
+		"Call glMapBuffer when a texture handle is referenced",
+		"call_MapBuffer_when_texture_referenced",
+		call_MapBuffer_when_texture_is_referenced,
+		NULL
+	},
+	{
+		NULL,
+		NULL,
+		NULL,
+		NULL
+	}
+};
+
+enum piglit_result
+piglit_display(void)
+{
+	return PIGLIT_FAIL;
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+	enum piglit_result result;
+
+	piglit_require_extension("GL_ARB_bindless_texture");
+	result = piglit_run_selected_subtests(subtests,
+					      piglit_config->selected_subtests,
+					      piglit_config->num_selected_subtests,
+					      PIGLIT_SKIP);
+	piglit_report_result(result);
+}
diff --git a/tests/spec/arb_bindless_texture/limit.c b/tests/spec/arb_bindless_texture/limit.c
new file mode 100644
index 000000000..960027597
--- /dev/null
+++ b/tests/spec/arb_bindless_texture/limit.c
@@ -0,0 +1,302 @@
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *  Marek Olšák <maraeo at gmail.com>
+ *  Samuel Pitoiset <samuel.pitoiset at gmail.com>
+ */
+
+/**
+ * Test that samplers accessed using texture handles are not counted against
+ * the texture limits.
+ * Derived from Marek's max-samplers test.
+ */
+
+#include "piglit-util-gl.h"
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+	config.supports_gl_compat_version = 33;
+	config.supports_gl_core_version = 33;
+
+	config.window_width = 300;
+	config.window_height = 300;
+	config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+static const char *vs_source =
+	"#version 330\n"
+	"#extension GL_ARB_bindless_texture: require\n"
+	"\n"
+	"#define NUM %i \n"
+	"layout (bindless_sampler) uniform;\n"
+	"\n"
+	"uniform sampler2D vertex_tex[NUM]; \n"
+	"uniform int vertex_index;"
+	"in vec4 piglit_vertex;\n"
+	"out vec3 vertex_tex_color; \n"
+	"\n"
+	"void main() \n"
+	"{ \n"
+	"	int i; \n"
+	"	gl_Position = piglit_vertex;\n"
+	"	vertex_tex_color = vec3(0.0); \n"
+	"	for (i = 0; i < NUM; i++) \n"
+	"		if (i == vertex_index) \n"
+	"			vertex_tex_color = textureLod(vertex_tex[i], vec2(%f), 0.0).xyz; \n"
+	"} \n";
+
+static const char *fs_source =
+	"#version 330\n"
+	"#extension GL_ARB_bindless_texture: require\n"
+	"\n"
+	"#define NUM %i \n"
+	"layout (bindless_sampler) uniform;\n"
+	"\n"
+	"uniform sampler2D fragment_tex[NUM]; \n"
+	"uniform int fragment_index;"
+	"in vec3 vertex_tex_color; \n"
+	"void main() \n"
+	"{ \n"
+	"	int i; \n"
+	"	vec3 fragment_tex_color = vec3(0.0); \n"
+	"	for (i = 0; i < NUM; i++) \n"
+	"		if (i == fragment_index) \n"
+	"			fragment_tex_color = texture2D(fragment_tex[i], vec2(%f), 0.0).xyz; \n"
+	"	gl_FragColor = vec4(fragment_tex_color + vertex_tex_color, 1.0); \n"
+	"} \n";
+
+GLuint prog;
+static int max_vs_textures, max_fs_textures;
+
+static void
+get_texture_color(int unit, float out[4])
+{
+	out[0] = (unit % 16) / 15.0;
+	out[1] = (unit / 16) / 15.0;
+	out[2] = 0;
+	out[3] = 1;
+}
+
+static void
+set_uniform(GLuint prog, const char *name, int value)
+{
+	GLuint loc = glGetUniformLocation(prog, name);
+	if (loc != -1)
+		glUniform1i(loc, value);
+}
+
+static GLvoid
+draw_rect_core(int ix, int iy, int iw, int ih)
+{
+	float x = -1 + 2.0*ix/piglit_width;
+	float y = -1 + 2.0*iy/piglit_height;
+	float w = 2.0*iw/piglit_width;
+	float h = 2.0*ih/piglit_height;
+	float verts[4][4];
+	GLuint vbo;
+
+	verts[0][0] = x;
+	verts[0][1] = y;
+	verts[0][2] = 0.0;
+	verts[0][3] = 1.0;
+	verts[1][0] = x + w;
+	verts[1][1] = y;
+	verts[1][2] = 0.0;
+	verts[1][3] = 1.0;
+	verts[2][0] = x + w;
+	verts[2][1] = y + h;
+	verts[2][2] = 0.0;
+	verts[2][3] = 1.0;
+	verts[3][0] = x;
+	verts[3][1] = y + h;
+	verts[3][2] = 0.0;
+	verts[3][3] = 1.0;
+
+	glGenBuffers(1, &vbo);
+	glBindBuffer(GL_ARRAY_BUFFER, vbo);
+	glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
+
+	glEnableVertexAttribArray(0);
+	glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
+
+	glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+	glDisableVertexAttribArray(0);
+	glDeleteBuffers(1, &vbo);
+}
+
+static GLboolean
+probe_pixel(int num, int x, int y)
+{
+	float expected[4];
+
+	get_texture_color(num, expected);
+
+	if (piglit_probe_pixel_rgb(x, y, expected))
+		return GL_TRUE;
+
+	printf("  When testing texture num %i\n", num);
+	return GL_FALSE;
+}
+
+enum piglit_result
+piglit_display(void)
+{
+	GLboolean pass = GL_TRUE;
+	int i, num, x, y;
+
+	glClear(GL_COLOR_BUFFER_BIT);
+
+	x = 0;
+	y = 0;
+	num = 0;
+
+	set_uniform(prog, "fragment_index", max_fs_textures);
+	for (i = 0; i < max_vs_textures; i++) {
+		set_uniform(prog, "vertex_index", i);
+		draw_rect_core(x, y, 20, 20);
+		pass = probe_pixel(num, x+10, y+10) && pass;
+
+		num++;
+		x += 20;
+		if (x+20 > piglit_width) {
+			x = 0;
+			y += 20;
+		}
+	}
+
+	set_uniform(prog, "vertex_index", max_vs_textures);
+	for (i = 0; i < max_fs_textures; i++) {
+		set_uniform(prog, "fragment_index", i);
+		draw_rect_core(x, y, 20, 20);
+		pass = probe_pixel(num, x+10, y+10) && pass;
+
+		num++;
+		x += 20;
+		if (x+20 > piglit_width) {
+			x = 0;
+			y += 20;
+		}
+	}
+
+	piglit_check_gl_error(GL_NO_ERROR);
+	piglit_present_results();
+
+	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+static void
+set_texture_handle(GLuint prog, const char *name, GLuint64 handle)
+{
+	GLint loc;
+
+	loc = glGetUniformLocation(prog, name);
+	if (loc != -1)
+		glUniformHandleui64vARB(loc, 1, &handle);
+}
+
+static GLuint64
+new_bindless_texture(int idx)
+{
+	GLuint64 handle;
+	float color[4];
+	GLuint tex;
+
+	get_texture_color(idx, color);
+
+	glGenTextures(1, &tex);
+	glBindTexture(GL_TEXTURE_2D, tex);
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0,
+		     GL_RGBA, GL_FLOAT, color);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	handle = glGetTextureHandleARB(tex);
+	glMakeTextureHandleResidentARB(handle);
+
+	return handle;
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+	GLuint vs, fs, vao;
+	int max_combined_textures, i, num;
+	char str[2048];
+	float texcoord = 0.5;
+	GLuint64 handle;
+
+	piglit_require_extension("GL_ARB_bindless_texture");
+
+	/* get limits */
+	glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_fs_textures);
+	glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &max_vs_textures);
+	glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_combined_textures);
+	printf("GL_MAX_TEXTURE_IMAGE_UNITS = %d\n", max_fs_textures);
+	printf("GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS = %d\n", max_vs_textures);
+	printf("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS = %d\n", max_combined_textures);
+
+	assert(max_fs_textures <= max_combined_textures);
+
+	/* use max_combined_textures + max_vs_textures */
+	max_vs_textures = MIN2(max_vs_textures, max_combined_textures - max_fs_textures);
+	max_fs_textures = max_combined_textures;
+
+	/* compile shaders */
+	sprintf(str, vs_source, max_vs_textures, texcoord);
+	vs = piglit_compile_shader_text(GL_VERTEX_SHADER, str);
+	sprintf(str, fs_source, max_fs_textures, texcoord);
+	fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, str);
+
+	prog = piglit_link_simple_program(vs, fs);
+	glUseProgram(prog);
+
+	/* initialize resident textures */
+	num = 0;
+	for (i = 0; i < max_vs_textures; i++) {
+		char name[64];
+		sprintf(name, "vertex_tex[%i]", i);
+		handle = new_bindless_texture(num);
+		set_texture_handle(prog, name, handle);
+		num++;
+	}
+
+	for (i = 0; i < max_fs_textures; i++) {
+		char name[64];
+		sprintf(name, "fragment_tex[%i]", i);
+		handle = new_bindless_texture(num);
+		set_texture_handle(prog, name, handle);
+		num++;
+	}
+
+	piglit_check_gl_error(GL_NO_ERROR);
+
+	glClearColor(0.0, 0.0, 1.0, 1.0);
+
+	glGenVertexArrays(1, &vao);
+	glBindVertexArray(vao);
+
+	piglit_check_gl_error(GL_NO_ERROR);
+}
diff --git a/tests/spec/arb_bindless_texture/uint64_attribs.c b/tests/spec/arb_bindless_texture/uint64_attribs.c
new file mode 100644
index 000000000..b6d085b6d
--- /dev/null
+++ b/tests/spec/arb_bindless_texture/uint64_attribs.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2010 VMware, Inc.
+ * Copyright (c) 2015 Red Hat Inc.
+ * Copyright (C) 2017 Valve 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.
+ */
+
+/** \file
+ *
+ * Test inherited vertex attributes from NV_vertex_attrib_integer_64bit.
+ * Derived from Brian's gpu_shader4 tests and Dave's vertex_attrib_64bit tests.
+ */
+
+#include <inttypes.h>
+
+#include "piglit-util-gl.h"
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+	config.supports_gl_core_version = 33;
+
+	config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+static const char *TestName = "uint64_attribs";
+static const GLuint Index = 3;
+
+static GLboolean
+check_uint64_attrib(const GLuint64EXT expected, const char *func)
+{
+	GLuint64EXT vals[4];
+
+	glGetVertexAttribLui64vARB(Index, GL_CURRENT_VERTEX_ATTRIB_ARB, vals);
+
+	if (expected != vals[0]) {
+		fprintf(stderr, "%s: %s failed\n", TestName, func);
+		fprintf(stderr, "  Expected: %"PRIu64"  Found: %"PRIu64"\n",
+			expected, vals[0]);
+		return GL_FALSE;
+	}
+	return GL_TRUE;
+}
+
+enum piglit_result
+piglit_display(void)
+{
+	return PIGLIT_FAIL;
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+	GLuint64EXT val = 1844674407370955165;
+
+	piglit_require_extension("GL_ARB_bindless_texture");
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "Interactions with NV_vertex_attrib_integer_64bit"
+	 *
+	 * "If NV_vertex_attrib_integer_64bit is not supported, this
+	 *  extension inherits the {Get}VertexAttribL1ui64{v}ARB entry points
+	 *  and UNSIGNED_INT64_ARB enum, as well as the functional edits
+	 *  describing them. However, references to the uint64_t type in the
+	 *  shader and providing 64-bit unsigned integer data to the shader
+	 *  are removed."
+	 */
+	glVertexAttribL1ui64ARB(Index, val);
+	if (!check_uint64_attrib(val, "glVertexAttribL1ui64ARB"))
+		piglit_report_result(PIGLIT_FAIL);
+
+	glVertexAttribL1ui64vARB(Index, &val);
+	if (!check_uint64_attrib(val, "glVertexAttribL1ui64vARB"))
+		piglit_report_result(PIGLIT_FAIL);
+
+	piglit_report_result(PIGLIT_PASS);
+}
diff --git a/tests/spec/arb_bindless_texture/uniform.c b/tests/spec/arb_bindless_texture/uniform.c
new file mode 100644
index 000000000..5e4c6ba84
--- /dev/null
+++ b/tests/spec/arb_bindless_texture/uniform.c
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2017 Valve 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.
+ */
+
+/** \file
+ *
+ * Test cases which exercice the uniform handle API with
+ * glUniformHandleui*64ARB(), glGetActiveUniform(), etc.
+ */
+
+#include "piglit-util-gl.h"
+
+static struct piglit_gl_test_config *piglit_config;
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+	piglit_config = &config;
+	config.supports_gl_compat_version = 33;
+	config.supports_gl_core_version = 33;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+static const char *passthrough_vs_src =
+	"#version 330\n"
+	"\n"
+	"in vec4 piglit_vertex;\n"
+	"\n"
+	"void main()\n"
+	"{\n"
+	"	gl_Position = piglit_vertex;\n"
+	"}\n";
+
+static const char *fs_explicit_bound_sampler =
+	"#version 330\n"
+	"#extension GL_ARB_bindless_texture: require\n"
+	"\n"
+	"layout (bound_sampler) uniform sampler2D tex;\n"
+	"out vec4 color;\n"
+	"\n"
+	"void main()\n"
+	"{\n"
+	"	color = texture(tex, vec2(0, 0));\n"
+	"}\n";
+
+static const char *fs_implicit_bound_sampler =
+	"#version 330\n"
+	"#extension GL_ARB_bindless_texture: require\n"
+	"\n"
+	"uniform sampler2D tex;\n"
+	"out vec4 color;\n"
+	"\n"
+	"void main()\n"
+	"{\n"
+	"	color = texture(tex, vec2(0, 0));\n"
+	"}\n";
+
+static const char *fs_explicit_bound_image =
+	"#version 330\n"
+	"#extension GL_ARB_bindless_texture: require\n"
+	"#extension GL_ARB_shader_image_load_store: enable\n"
+	"\n"
+	"layout (bound_image) writeonly uniform image2D img;\n"
+	"out vec4 color;\n"
+	"\n"
+	"void main()\n"
+	"{\n"
+	"	imageStore(img, ivec2(0, 0), color);\n"
+	"}\n";
+
+static const char *fs_implicit_bound_image =
+	"#version 330\n"
+	"#extension GL_ARB_bindless_texture: require\n"
+	"#extension GL_ARB_shader_image_load_store: enable\n"
+	"\n"
+	"writeonly uniform image2D img;\n"
+	"out vec4 color;\n"
+	"\n"
+	"void main()\n"
+	"{\n"
+	"	imageStore(img, ivec2(0, 0), color);\n"
+	"}\n";
+
+static enum piglit_result
+check_UniformHandleui64_with_explicit_bound_sampler(void *data)
+{
+	GLuint vs, fs, prog;
+	GLuint64 handle = 0;
+	GLint loc;
+
+	vs = piglit_compile_shader_text(GL_VERTEX_SHADER, passthrough_vs_src);
+	fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER,
+					fs_explicit_bound_sampler);
+	prog = piglit_link_simple_program(vs, fs);
+	glUseProgram(prog);
+
+	loc = glGetUniformLocation(prog, "tex");
+	if (loc == -1)
+		return PIGLIT_FAIL;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The error INVALID_OPERATION is generated by UniformHandleui64{v}ARB
+	 *  if the sampler or image uniform being updated has the
+	 *  "bound_sampler" or "bound_image" layout qualifier."
+	 */
+	glUniformHandleui64ARB(loc, handle);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	glProgramUniformHandleui64vARB(prog, loc, 1, &handle);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+check_UniformHandleui64_with_implicit_bound_sampler(void *data)
+{
+	GLuint vs, fs, prog;
+	GLuint64 handle = 0;
+	GLint loc;
+
+	vs = piglit_compile_shader_text(GL_VERTEX_SHADER, passthrough_vs_src);
+	fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER,
+					fs_implicit_bound_sampler);
+	prog = piglit_link_simple_program(vs, fs);
+	glUseProgram(prog);
+
+	loc = glGetUniformLocation(prog, "tex");
+	if (loc == -1)
+		return PIGLIT_FAIL;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "When used as uniforms in the default block, the value of sampler
+	 *  variables may be specified with either Uniform1i{v} or
+	 *  UniformHandleui64{v}ARB."
+	 */
+	glUniformHandleui64ARB(loc, handle);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	glProgramUniformHandleui64vARB(prog, loc, 1, &handle);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+check_UniformHandleui64_with_explicit_bound_image(void *data)
+{
+	GLuint vs, fs, prog;
+	GLuint64 handle = 0;
+	GLint loc;
+
+	vs = piglit_compile_shader_text(GL_VERTEX_SHADER, passthrough_vs_src);
+	fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER,
+					fs_explicit_bound_image);
+	prog = piglit_link_simple_program(vs, fs);
+	glUseProgram(prog);
+
+	loc = glGetUniformLocation(prog, "img");
+	if (loc == -1)
+		return PIGLIT_FAIL;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "The error INVALID_OPERATION is generated by UniformHandleui64{v}ARB
+	 *  if the sampler or image uniform being updated has the
+	 *  "bound_sampler" or "bound_image" layout qualifier."
+	 */
+	glUniformHandleui64ARB(loc, handle);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	glProgramUniformHandleui64vARB(prog, loc, 1, &handle);
+	if (!piglit_check_gl_error(GL_INVALID_OPERATION))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+check_UniformHandleui64_with_implicit_bound_image(void *data)
+{
+	GLuint vs, fs, prog;
+	GLuint64 handle = 0;
+	GLint loc;
+
+	vs = piglit_compile_shader_text(GL_VERTEX_SHADER, passthrough_vs_src);
+	fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER,
+					fs_implicit_bound_image);
+	prog = piglit_link_simple_program(vs, fs);
+	glUseProgram(prog);
+
+	loc = glGetUniformLocation(prog, "img");
+	if (loc == -1)
+		return PIGLIT_FAIL;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "When used as uniforms in the default block, the value of sampler
+	 *  variables may be specified with either Uniform1i{v} or
+	 *  UniformHandleui64{v}ARB."
+	 */
+	glUniformHandleui64ARB(loc, handle);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	glProgramUniformHandleui64vARB(prog, loc, 1, &handle);
+	if (!piglit_check_gl_error(GL_NO_ERROR))
+		return PIGLIT_FAIL;
+
+	return PIGLIT_PASS;
+}
+
+static enum piglit_result
+use_glGetActiveUniform_with_sampler(void *data)
+{
+	GLuint vs, fs, prog;
+	GLint num_uniforms, size;
+	char name[128];
+	GLsizei len;
+	GLenum type;
+
+	vs = piglit_compile_shader_text(GL_VERTEX_SHADER, passthrough_vs_src);
+	fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER,
+					fs_explicit_bound_sampler);
+	prog = piglit_link_simple_program(vs, fs);
+	glUseProgram(prog);
+
+	glGetProgramiv(prog, GL_ACTIVE_UNIFORMS, &num_uniforms);
+	if (num_uniforms != 1)
+		return PIGLIT_FAIL;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "Modify Section 2.14.4, Uniform Variables, p. 97"
+	 *
+	 * "(Edit Table 2.15, "OpenGL Shading Language type tokens returned
+	 *  by GetActiveUniform and GetActiveUniformsiv...", pp. 104-106.  In
+	 *  particular, add dots to the "Attrib" and "Xfb" columns for all
+	 *  SAMPLER and IMAGE types.)"
+	 */
+	glGetActiveUniform(prog, 0, sizeof(name), &len, &size, &type, name);
+
+	/* Minimal test which only checks one sampler type. */
+	return type == GL_SAMPLER_2D ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+static enum piglit_result
+use_glGetActiveUniform_with_image(void *data)
+{
+	GLuint vs, fs, prog;
+	GLint num_uniforms, size;
+	char name[128];
+	GLsizei len;
+	GLenum type;
+
+	if (!piglit_is_extension_supported("GL_ARB_shader_image_load_store"))
+		return PIGLIT_SKIP;
+
+	vs = piglit_compile_shader_text(GL_VERTEX_SHADER, passthrough_vs_src);
+	fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER,
+					fs_explicit_bound_image);
+	prog = piglit_link_simple_program(vs, fs);
+	glUseProgram(prog);
+
+	glGetProgramiv(prog, GL_ACTIVE_UNIFORMS, &num_uniforms);
+	if (num_uniforms != 1)
+		return PIGLIT_FAIL;
+
+	/* The ARB_bindless_texture spec says:
+	 *
+	 * "Modify Section 2.14.4, Uniform Variables, p. 97"
+	 *
+	 * "(Edit Table 2.15, "OpenGL Shading Language type tokens returned
+	 *  by GetActiveUniform and GetActiveUniformsiv...", pp. 104-106.  In
+	 *  particular, add dots to the "Attrib" and "Xfb" columns for all
+	 *  SAMPLER and IMAGE types.)"
+	 */
+	glGetActiveUniform(prog, 0, sizeof(name), &len, &size, &type, name);
+
+	/* Minimal test which only checks one image type. */
+	return type == GL_IMAGE_2D ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+static const struct piglit_subtest subtests[] = {
+	{
+		"Check glUniformHandleui64*ARB() with explicit bound_sampler",
+		"check_UniformHandleui64_with_explicit_bound_sampler",
+		check_UniformHandleui64_with_explicit_bound_sampler,
+		NULL
+	},
+	{
+		"Check glUniformHandleui64*ARB() with implicit bound_sampler",
+		"check_UniformHandleui64_with_implicit_bound_sampler",
+		check_UniformHandleui64_with_implicit_bound_sampler,
+		NULL
+	},
+	{
+		"Check glUniformHandleui64*ARB() with explicit bound_image",
+		"check_UniformHandleui64_with_explicit_bound_image",
+		check_UniformHandleui64_with_explicit_bound_image,
+		NULL
+	},
+	{
+		"Check glUniformHandleui64*ARB() with implicit bound_image",
+		"check_UniformHandleui64_with_implicit_bound_image",
+		check_UniformHandleui64_with_implicit_bound_image,
+		NULL
+	},
+	{
+		"Use glGetActiveUniform with a sampler type",
+		"use_glGetActiveUniform_with_sampler",
+		use_glGetActiveUniform_with_sampler,
+		NULL
+	},
+	{
+		"Use glGetActiveUniform with an image type",
+		"use_glGetActiveUniform_with_image",
+		use_glGetActiveUniform_with_image,
+		NULL
+	},
+	{
+		NULL,
+		NULL,
+		NULL,
+		NULL
+	}
+};
+
+enum piglit_result
+piglit_display(void)
+{
+	return PIGLIT_FAIL;
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+	enum piglit_result result;
+
+	piglit_require_extension("GL_ARB_bindless_texture");
+	result = piglit_run_selected_subtests(subtests,
+					      piglit_config->selected_subtests,
+					      piglit_config->num_selected_subtests,
+					      PIGLIT_SKIP);
+	piglit_report_result(result);
+}
-- 
2.12.1



More information about the Piglit mailing list