Add query tests for ES31 states.

* Queries and pretty-printing for GLES31 core states.
* Move sample_mask_value from integer.* to indexed.*.
* Add image state reset.
* Move tcu::Array to a separate file

Bug: 18925583
Change-Id: Icce01201ca3c2c7daeb2daeb0fed04d373a15eb6
diff --git a/Android.mk b/Android.mk
index 9a69f89..21aefcc 100644
--- a/Android.mk
+++ b/Android.mk
@@ -32,18 +32,21 @@
 	executor/xeXMLParser.cpp \
 	executor/xeXMLWriter.cpp \
 	framework/common/tcuApp.cpp \
+	framework/common/tcuArray.cpp \
 	framework/common/tcuBilinearImageCompare.cpp \
 	framework/common/tcuCommandLine.cpp \
 	framework/common/tcuCompressedTexture.cpp \
 	framework/common/tcuCPUWarmup.cpp \
 	framework/common/tcuDefs.cpp \
 	framework/common/tcuFactoryRegistry.cpp \
+	framework/common/tcuFloat.cpp \
 	framework/common/tcuFloatFormat.cpp \
 	framework/common/tcuFunctionLibrary.cpp \
 	framework/common/tcuFuzzyImageCompare.cpp \
 	framework/common/tcuImageCompare.cpp \
 	framework/common/tcuImageIO.cpp \
 	framework/common/tcuInterval.cpp \
+	framework/common/tcuMatrix.cpp \
 	framework/common/tcuPlatform.cpp \
 	framework/common/tcuRandomValueIterator.cpp \
 	framework/common/tcuRenderTarget.cpp \
@@ -250,7 +253,13 @@
 	modules/gles31/functional/es31fGeometryShaderTests.cpp \
 	modules/gles31/functional/es31fIndirectComputeDispatchTests.cpp \
 	modules/gles31/functional/es31fIntegerStateQueryTests.cpp \
+	modules/gles31/functional/es31fBooleanStateQueryTests.cpp \
+	modules/gles31/functional/es31fIndexedStateQueryTests.cpp \
 	modules/gles31/functional/es31fInternalFormatQueryTests.cpp \
+	modules/gles31/functional/es31fTextureStateQueryTests.cpp \
+	modules/gles31/functional/es31fFramebufferDefaultStateQueryTests.cpp \
+	modules/gles31/functional/es31fProgramPipelineStateQueryTests.cpp \
+	modules/gles31/functional/es31fProgramStateQueryTests.cpp \
 	modules/gles31/functional/es31fLayoutBindingTests.cpp \
 	modules/gles31/functional/es31fMultisampleShaderRenderCase.cpp \
 	modules/gles31/functional/es31fMultisampleTests.cpp \
@@ -477,6 +486,7 @@
 	modules/glshared/glsShaderPerformanceCase.cpp \
 	modules/glshared/glsShaderPerformanceMeasurer.cpp \
 	modules/glshared/glsShaderRenderCase.cpp \
+	modules/glshared/glsStateQueryUtil.cpp \
 	modules/glshared/glsStateChangePerfTestCases.cpp \
 	modules/glshared/glsTextureBufferCase.cpp \
 	modules/glshared/glsTextureTestUtil.cpp \
diff --git a/android/cts/com.drawelements.deqp.gles31.xml b/android/cts/com.drawelements.deqp.gles31.xml
index a96e4da..5ecb518 100644
--- a/android/cts/com.drawelements.deqp.gles31.xml
+++ b/android/cts/com.drawelements.deqp.gles31.xml
@@ -13425,7 +13425,6 @@
 </TestSuite>
 <TestSuite name="state_query">
 <TestCase name="integer">
-<Test name="sample_mask_value" />
 <Test name="max_color_texture_samples_getboolean" />
 <Test name="max_color_texture_samples_getinteger" />
 <Test name="max_color_texture_samples_getinteger64" />
@@ -13463,6 +13462,9 @@
 <Test name="shader_storage_buffer_offset_alignment_getinteger64" />
 <Test name="shader_storage_buffer_offset_alignment_getfloat" />
 </TestCase>
+<TestCase name="indexed">
+<Test name="sample_mask_value_getintegeri_v" />
+</TestCase>
 <TestSuite name="texture_level">
 <TestCase name="integer">
 <Test name="texture_samples" />
diff --git a/android/cts/es31-lmp-mr1.txt b/android/cts/es31-lmp-mr1.txt
index 020e4ae..d084b66 100644
--- a/android/cts/es31-lmp-mr1.txt
+++ b/android/cts/es31-lmp-mr1.txt
@@ -11212,7 +11212,6 @@
 dEQP-GLES31.functional.texture.texture_buffer.render_modify.as_vertex_array_as_index_array_as_vertex_texture_as_fragment_texture.buffersubdata
 dEQP-GLES31.functional.texture.texture_buffer.render_modify.as_vertex_array_as_index_array_as_vertex_texture_as_fragment_texture.mapbuffer_write
 dEQP-GLES31.functional.texture.texture_buffer.render_modify.as_vertex_array_as_index_array_as_vertex_texture_as_fragment_texture.mapbuffer_readwrite
-dEQP-GLES31.functional.state_query.integer.sample_mask_value
 dEQP-GLES31.functional.state_query.integer.max_color_texture_samples_getboolean
 dEQP-GLES31.functional.state_query.integer.max_color_texture_samples_getinteger
 dEQP-GLES31.functional.state_query.integer.max_color_texture_samples_getinteger64
@@ -11249,6 +11248,7 @@
 dEQP-GLES31.functional.state_query.integer.shader_storage_buffer_offset_alignment_getinteger
 dEQP-GLES31.functional.state_query.integer.shader_storage_buffer_offset_alignment_getinteger64
 dEQP-GLES31.functional.state_query.integer.shader_storage_buffer_offset_alignment_getfloat
+dEQP-GLES31.functional.state_query.indexed.sample_mask_value_getintegeri_v
 dEQP-GLES31.functional.state_query.texture_level.integer.texture_samples
 dEQP-GLES31.functional.state_query.texture_level.integer.texture_fixed_sample_locations
 dEQP-GLES31.functional.state_query.texture_level.integer.texture_width
diff --git a/framework/common/CMakeLists.txt b/framework/common/CMakeLists.txt
index 4396797..4861de6 100644
--- a/framework/common/CMakeLists.txt
+++ b/framework/common/CMakeLists.txt
@@ -3,6 +3,8 @@
 set(TCUTIL_SRCS
 	tcuApp.cpp
 	tcuApp.hpp
+	tcuArray.hpp
+	tcuArray.cpp
 	tcuBilinearImageCompare.cpp
 	tcuBilinearImageCompare.hpp
 	tcuCommandLine.cpp
@@ -12,6 +14,7 @@
 	tcuDefs.cpp
 	tcuDefs.hpp
 	tcuFloat.hpp
+	tcuFloat.cpp
 	tcuFloatFormat.hpp
 	tcuFloatFormat.cpp
 	tcuFormatUtil.hpp
@@ -24,6 +27,7 @@
 	tcuInterval.cpp
 	tcuInterval.hpp
 	tcuMatrix.hpp
+	tcuMatrix.cpp
 	tcuMatrixUtil.hpp
 	tcuPixelFormat.hpp
 	tcuPlatform.cpp
diff --git a/framework/common/tcuArray.cpp b/framework/common/tcuArray.cpp
new file mode 100644
index 0000000..f8a3359
--- /dev/null
+++ b/framework/common/tcuArray.cpp
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Templatized array class.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuArray.hpp"
+
+DE_EMPTY_CPP_FILE
diff --git a/framework/common/tcuArray.hpp b/framework/common/tcuArray.hpp
new file mode 100644
index 0000000..26b1cf9
--- /dev/null
+++ b/framework/common/tcuArray.hpp
@@ -0,0 +1,60 @@
+#ifndef _TCUARRAY_HPP
+#define _TCUARRAY_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Templatized array class.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuFormatUtil.hpp"
+
+#include <ostream>
+
+namespace tcu
+{
+
+template <typename T, int Size>
+class Array
+{
+public:
+					Array			(void) {}
+					~Array			(void) {}
+
+	inline T		operator[]		(int ndx) const		{ return m_data[ndx]; }
+	inline T&		operator[]		(int ndx)			{ return m_data[ndx]; }
+
+	inline const T*	getPtr			(void) const		{ return m_data; }
+	inline T*		getPtr			(void)				{ return m_data; }
+
+private:
+	T				m_data[Size];
+};
+
+
+template <typename T, int Size>
+std::ostream& operator<< (std::ostream& stream, const Array<T, Size>& arr)
+{
+	return stream << Format::Array<T*>(arr.getPtr(), arr.getPtr() + Size);
+}
+
+} // tcu
+
+#endif // _TCUARRAY_HPP
diff --git a/framework/common/tcuFloat.cpp b/framework/common/tcuFloat.cpp
new file mode 100644
index 0000000..ddff239
--- /dev/null
+++ b/framework/common/tcuFloat.cpp
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Reconfigurable floating-point value template.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuFloat.hpp"
+
+DE_EMPTY_CPP_FILE
diff --git a/framework/common/tcuMatrix.cpp b/framework/common/tcuMatrix.cpp
new file mode 100644
index 0000000..77204d4
--- /dev/null
+++ b/framework/common/tcuMatrix.cpp
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief 	Templatized matrix class.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuMatrix.hpp"
+
+DE_EMPTY_CPP_FILE
diff --git a/framework/common/tcuMatrix.hpp b/framework/common/tcuMatrix.hpp
index 446e070..ee55784 100644
--- a/framework/common/tcuMatrix.hpp
+++ b/framework/common/tcuMatrix.hpp
@@ -25,27 +25,11 @@
 
 #include "tcuDefs.hpp"
 #include "tcuVector.hpp"
+#include "tcuArray.hpp"
 
 namespace tcu
 {
 
-template <typename T, int Size>
-class Array
-{
-public:
-					Array			(void) {}
-					~Array			(void) {}
-
-	inline T		operator[]		(int ndx) const		{ return m_data[ndx]; }
-	inline T&		operator[]		(int ndx)			{ return m_data[ndx]; }
-
-	inline const T*	getPtr			(void) const		{ return m_data; }
-	inline T*		getPtr			(void)				{ return m_data; }
-
-private:
-	T				m_data[Size];
-};
-
 // Templated matrix class.
 template <typename T, int Rows, int Cols>
 class Matrix
@@ -589,6 +573,6 @@
 	return res;
 }
 
-} // namespace tcu
+} // tcu
 
 #endif // _TCUMATRIX_HPP
diff --git a/framework/opengl/gluCallLogWrapper.inl b/framework/opengl/gluCallLogWrapper.inl
index 9f46b49..9b97d6f 100644
--- a/framework/opengl/gluCallLogWrapper.inl
+++ b/framework/opengl/gluCallLogWrapper.inl
@@ -795,7 +795,7 @@
 void CallLogWrapper::glDeleteProgramPipelines (glw::GLsizei n, const glw::GLuint *pipelines)
 {
 	if (m_enableLog)
-		m_log << TestLog::Message << "glDeleteProgramPipelines(" << n << ", " << pipelines << ");" << TestLog::EndMessage;
+		m_log << TestLog::Message << "glDeleteProgramPipelines(" << n << ", " << getPointerStr(pipelines, n) << ");" << TestLog::EndMessage;
 	m_gl.deleteProgramPipelines(n, pipelines);
 }
 
@@ -1249,9 +1249,7 @@
 		m_log << TestLog::Message << "glGenBuffers(" << n << ", " << buffers << ");" << TestLog::EndMessage;
 	m_gl.genBuffers(n, buffers);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// buffers = " << getPointerStr(buffers, n) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGenFramebuffers (glw::GLsizei n, glw::GLuint *framebuffers)
@@ -1260,9 +1258,7 @@
 		m_log << TestLog::Message << "glGenFramebuffers(" << n << ", " << framebuffers << ");" << TestLog::EndMessage;
 	m_gl.genFramebuffers(n, framebuffers);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// framebuffers = " << getPointerStr(framebuffers, n) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGenProgramPipelines (glw::GLsizei n, glw::GLuint *pipelines)
@@ -1270,6 +1266,8 @@
 	if (m_enableLog)
 		m_log << TestLog::Message << "glGenProgramPipelines(" << n << ", " << pipelines << ");" << TestLog::EndMessage;
 	m_gl.genProgramPipelines(n, pipelines);
+	if (m_enableLog)
+		m_log << TestLog::Message << "// pipelines = " << getPointerStr(pipelines, n) << TestLog::EndMessage;
 }
 
 void CallLogWrapper::glGenQueries (glw::GLsizei n, glw::GLuint *ids)
@@ -1278,9 +1276,7 @@
 		m_log << TestLog::Message << "glGenQueries(" << n << ", " << ids << ");" << TestLog::EndMessage;
 	m_gl.genQueries(n, ids);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// ids = " << getPointerStr(ids, n) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGenRenderbuffers (glw::GLsizei n, glw::GLuint *renderbuffers)
@@ -1289,9 +1285,7 @@
 		m_log << TestLog::Message << "glGenRenderbuffers(" << n << ", " << renderbuffers << ");" << TestLog::EndMessage;
 	m_gl.genRenderbuffers(n, renderbuffers);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// renderbuffers = " << getPointerStr(renderbuffers, n) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGenSamplers (glw::GLsizei count, glw::GLuint *samplers)
@@ -1307,9 +1301,7 @@
 		m_log << TestLog::Message << "glGenTextures(" << n << ", " << textures << ");" << TestLog::EndMessage;
 	m_gl.genTextures(n, textures);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// textures = " << getPointerStr(textures, n) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGenTransformFeedbacks (glw::GLsizei n, glw::GLuint *ids)
@@ -1318,9 +1310,7 @@
 		m_log << TestLog::Message << "glGenTransformFeedbacks(" << n << ", " << ids << ");" << TestLog::EndMessage;
 	m_gl.genTransformFeedbacks(n, ids);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// ids = " << getPointerStr(ids, n) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGenVertexArrays (glw::GLsizei n, glw::GLuint *arrays)
@@ -1329,9 +1319,7 @@
 		m_log << TestLog::Message << "glGenVertexArrays(" << n << ", " << arrays << ");" << TestLog::EndMessage;
 	m_gl.genVertexArrays(n, arrays);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// arrays = " << getPointerStr(arrays, n) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGenerateMipmap (glw::GLenum target)
@@ -1424,9 +1412,7 @@
 		m_log << TestLog::Message << "glGetActiveUniformsiv(" << program << ", " << uniformCount << ", " << getPointerStr(uniformIndices, uniformCount) << ", " << getUniformParamStr(pname) << ", " << params << ");" << TestLog::EndMessage;
 	m_gl.getActiveUniformsiv(program, uniformCount, uniformIndices, pname, params);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// params = " << getPointerStr(params, uniformCount) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGetAttachedShaders (glw::GLuint program, glw::GLsizei maxCount, glw::GLsizei *count, glw::GLuint *shaders)
@@ -1449,8 +1435,10 @@
 void CallLogWrapper::glGetBooleani_v (glw::GLenum target, glw::GLuint index, glw::GLboolean *data)
 {
 	if (m_enableLog)
-		m_log << TestLog::Message << "glGetBooleani_v(" << toHex(target) << ", " << index << ", " << data << ");" << TestLog::EndMessage;
+		m_log << TestLog::Message << "glGetBooleani_v(" << getGettableIndexedStateStr(target) << ", " << index << ", " << static_cast<const void*>(data) << ");" << TestLog::EndMessage;
 	m_gl.getBooleani_v(target, index, data);
+	if (m_enableLog)
+		m_log << TestLog::Message << "// data = " << getBooleanPointerStr(data, 1) << TestLog::EndMessage;
 }
 
 void CallLogWrapper::glGetBooleanv (glw::GLenum pname, glw::GLboolean *data)
@@ -1459,9 +1447,7 @@
 		m_log << TestLog::Message << "glGetBooleanv(" << getGettableStateStr(pname) << ", " << static_cast<const void*>(data) << ");" << TestLog::EndMessage;
 	m_gl.getBooleanv(pname, data);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// data = " << getBooleanPointerStr(data, getBasicQueryNumArgsOut(pname)) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGetBufferParameteri64v (glw::GLenum target, glw::GLenum pname, glw::GLint64 *params)
@@ -1560,9 +1546,7 @@
 		m_log << TestLog::Message << "glGetFloatv(" << getGettableStateStr(pname) << ", " << data << ");" << TestLog::EndMessage;
 	m_gl.getFloatv(pname, data);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// data = " << getPointerStr(data, getBasicQueryNumArgsOut(pname)) << TestLog::EndMessage;
-	}
 }
 
 glw::GLint CallLogWrapper::glGetFragDataIndex (glw::GLuint program, const glw::GLchar *name)
@@ -1591,9 +1575,7 @@
 		m_log << TestLog::Message << "glGetFramebufferAttachmentParameteriv(" << getFramebufferTargetStr(target) << ", " << getFramebufferAttachmentStr(attachment) << ", " << getFramebufferAttachmentParameterStr(pname) << ", " << params << ");" << TestLog::EndMessage;
 	m_gl.getFramebufferAttachmentParameteriv(target, attachment, pname, params);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// params = " << getFramebufferAttachmentParameterValueStr(pname, params) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGetFramebufferParameteriv (glw::GLenum target, glw::GLenum pname, glw::GLint *params)
@@ -1601,6 +1583,8 @@
 	if (m_enableLog)
 		m_log << TestLog::Message << "glGetFramebufferParameteriv(" << getFramebufferTargetStr(target) << ", " << getFramebufferParameterStr(pname) << ", " << params << ");" << TestLog::EndMessage;
 	m_gl.getFramebufferParameteriv(target, pname, params);
+	if (m_enableLog)
+		m_log << TestLog::Message << "// params = " << getPointerStr(params, 1) << TestLog::EndMessage;
 }
 
 glw::GLenum CallLogWrapper::glGetGraphicsResetStatus (void)
@@ -1618,6 +1602,8 @@
 	if (m_enableLog)
 		m_log << TestLog::Message << "glGetInteger64i_v(" << getGettableIndexedStateStr(target) << ", " << index << ", " << data << ");" << TestLog::EndMessage;
 	m_gl.getInteger64i_v(target, index, data);
+	if (m_enableLog)
+		m_log << TestLog::Message << "// data = " << getPointerStr(data, 1) << TestLog::EndMessage;
 }
 
 void CallLogWrapper::glGetInteger64v (glw::GLenum pname, glw::GLint64 *data)
@@ -1626,9 +1612,7 @@
 		m_log << TestLog::Message << "glGetInteger64v(" << getGettableStateStr(pname) << ", " << data << ");" << TestLog::EndMessage;
 	m_gl.getInteger64v(pname, data);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// data = " << getPointerStr(data, getBasicQueryNumArgsOut(pname)) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGetIntegeri_v (glw::GLenum target, glw::GLuint index, glw::GLint *data)
@@ -1636,6 +1620,8 @@
 	if (m_enableLog)
 		m_log << TestLog::Message << "glGetIntegeri_v(" << getGettableIndexedStateStr(target) << ", " << index << ", " << data << ");" << TestLog::EndMessage;
 	m_gl.getIntegeri_v(target, index, data);
+	if (m_enableLog)
+		m_log << TestLog::Message << "// data = " << getPointerStr(data, 1) << TestLog::EndMessage;
 }
 
 void CallLogWrapper::glGetIntegerv (glw::GLenum pname, glw::GLint *data)
@@ -1644,9 +1630,7 @@
 		m_log << TestLog::Message << "glGetIntegerv(" << getGettableStateStr(pname) << ", " << data << ");" << TestLog::EndMessage;
 	m_gl.getIntegerv(pname, data);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// data = " << getPointerStr(data, getBasicQueryNumArgsOut(pname)) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGetInternalformati64v (glw::GLenum target, glw::GLenum internalformat, glw::GLenum pname, glw::GLsizei bufSize, glw::GLint64 *params)
@@ -1662,9 +1646,7 @@
 		m_log << TestLog::Message << "glGetInternalformativ(" << getInternalFormatTargetStr(target) << ", " << getPixelFormatStr(internalformat) << ", " << getInternalFormatParameterStr(pname) << ", " << bufSize << ", " << params << ");" << TestLog::EndMessage;
 	m_gl.getInternalformativ(target, internalformat, pname, bufSize, params);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// params = " << getPointerStr(params, bufSize) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGetMultisamplefv (glw::GLenum pname, glw::GLuint index, glw::GLfloat *val)
@@ -1673,9 +1655,7 @@
 		m_log << TestLog::Message << "glGetMultisamplefv(" << getMultisampleParameterStr(pname) << ", " << index << ", " << val << ");" << TestLog::EndMessage;
 	m_gl.getMultisamplefv(pname, index, val);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// val = " << getPointerStr(val, 2) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGetNamedBufferParameteri64v (glw::GLuint buffer, glw::GLenum pname, glw::GLint64 *params)
@@ -1772,8 +1752,10 @@
 void CallLogWrapper::glGetProgramPipelineInfoLog (glw::GLuint pipeline, glw::GLsizei bufSize, glw::GLsizei *length, glw::GLchar *infoLog)
 {
 	if (m_enableLog)
-		m_log << TestLog::Message << "glGetProgramPipelineInfoLog(" << pipeline << ", " << bufSize << ", " << length << ", " << infoLog << ");" << TestLog::EndMessage;
+		m_log << TestLog::Message << "glGetProgramPipelineInfoLog(" << pipeline << ", " << bufSize << ", " << length << ", " << static_cast<const void*>(infoLog) << ");" << TestLog::EndMessage;
 	m_gl.getProgramPipelineInfoLog(pipeline, bufSize, length, infoLog);
+	if (m_enableLog)
+		m_log << TestLog::Message << "// length = " << getPointerStr(length, 1) << TestLog::EndMessage;
 }
 
 void CallLogWrapper::glGetProgramPipelineiv (glw::GLuint pipeline, glw::GLenum pname, glw::GLint *params)
@@ -1782,9 +1764,7 @@
 		m_log << TestLog::Message << "glGetProgramPipelineiv(" << pipeline << ", " << getPipelineParamStr(pname) << ", " << params << ");" << TestLog::EndMessage;
 	m_gl.getProgramPipelineiv(pipeline, pname, params);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// params = " << getPointerStr(params, 1) << TestLog::EndMessage;
-	}
 }
 
 glw::GLuint CallLogWrapper::glGetProgramResourceIndex (glw::GLuint program, glw::GLenum programInterface, const glw::GLchar *name)
@@ -1844,9 +1824,7 @@
 		m_log << TestLog::Message << "glGetProgramiv(" << program << ", " << getProgramParamStr(pname) << ", " << params << ");" << TestLog::EndMessage;
 	m_gl.getProgramiv(program, pname, params);
 	if (m_enableLog)
-	{
-		m_log << TestLog::Message << "// params = " << getPointerStr(params, 1) << TestLog::EndMessage;
-	}
+		m_log << TestLog::Message << "// params = " << getPointerStr(params, getProgramQueryNumArgsOut(pname)) << TestLog::EndMessage;
 }
 
 void CallLogWrapper::glGetQueryBufferObjecti64v (glw::GLuint id, glw::GLuint buffer, glw::GLenum pname, glw::GLintptr offset)
@@ -1890,9 +1868,7 @@
 		m_log << TestLog::Message << "glGetQueryObjecti64v(" << id << ", " << getQueryObjectParamStr(pname) << ", " << params << ");" << TestLog::EndMessage;
 	m_gl.getQueryObjecti64v(id, pname, params);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// params = " << getPointerStr(params, 1) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGetQueryObjectiv (glw::GLuint id, glw::GLenum pname, glw::GLint *params)
@@ -1901,9 +1877,7 @@
 		m_log << TestLog::Message << "glGetQueryObjectiv(" << id << ", " << getQueryObjectParamStr(pname) << ", " << params << ");" << TestLog::EndMessage;
 	m_gl.getQueryObjectiv(id, pname, params);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// params = " << getPointerStr(params, 1) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGetQueryObjectui64v (glw::GLuint id, glw::GLenum pname, glw::GLuint64 *params)
@@ -1912,9 +1886,7 @@
 		m_log << TestLog::Message << "glGetQueryObjectui64v(" << id << ", " << getQueryObjectParamStr(pname) << ", " << params << ");" << TestLog::EndMessage;
 	m_gl.getQueryObjectui64v(id, pname, params);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// params = " << getPointerStr(params, 1) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGetQueryObjectuiv (glw::GLuint id, glw::GLenum pname, glw::GLuint *params)
@@ -1923,9 +1895,7 @@
 		m_log << TestLog::Message << "glGetQueryObjectuiv(" << id << ", " << getQueryObjectParamStr(pname) << ", " << params << ");" << TestLog::EndMessage;
 	m_gl.getQueryObjectuiv(id, pname, params);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// params = " << getPointerStr(params, 1) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGetQueryiv (glw::GLenum target, glw::GLenum pname, glw::GLint *params)
@@ -1934,9 +1904,7 @@
 		m_log << TestLog::Message << "glGetQueryiv(" << getQueryTargetStr(target) << ", " << getQueryParamStr(pname) << ", " << params << ");" << TestLog::EndMessage;
 	m_gl.getQueryiv(target, pname, params);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// params = " << getPointerStr(params, 1) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGetRenderbufferParameteriv (glw::GLenum target, glw::GLenum pname, glw::GLint *params)
@@ -2001,9 +1969,7 @@
 		m_log << TestLog::Message << "glGetShaderiv(" << shader << ", " << getShaderParamStr(pname) << ", " << params << ");" << TestLog::EndMessage;
 	m_gl.getShaderiv(shader, pname, params);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// params = " << getPointerStr(params, 1) << TestLog::EndMessage;
-	}
 }
 
 const glw::GLubyte * CallLogWrapper::glGetString (glw::GLenum name)
@@ -2065,6 +2031,8 @@
 	if (m_enableLog)
 		m_log << TestLog::Message << "glGetTexLevelParameterfv(" << getTextureTargetStr(target) << ", " << level << ", " << getTextureLevelParameterStr(pname) << ", " << params << ");" << TestLog::EndMessage;
 	m_gl.getTexLevelParameterfv(target, level, pname, params);
+	if (m_enableLog)
+		m_log << TestLog::Message << "// params = " << getPointerStr(params, 1) << TestLog::EndMessage;
 }
 
 void CallLogWrapper::glGetTexLevelParameteriv (glw::GLenum target, glw::GLint level, glw::GLenum pname, glw::GLint *params)
@@ -2072,6 +2040,8 @@
 	if (m_enableLog)
 		m_log << TestLog::Message << "glGetTexLevelParameteriv(" << getTextureTargetStr(target) << ", " << level << ", " << getTextureLevelParameterStr(pname) << ", " << params << ");" << TestLog::EndMessage;
 	m_gl.getTexLevelParameteriv(target, level, pname, params);
+	if (m_enableLog)
+		m_log << TestLog::Message << "// params = " << getPointerStr(params, 1) << TestLog::EndMessage;
 }
 
 void CallLogWrapper::glGetTexParameterIiv (glw::GLenum target, glw::GLenum pname, glw::GLint *params)
@@ -2093,6 +2063,8 @@
 	if (m_enableLog)
 		m_log << TestLog::Message << "glGetTexParameterfv(" << getTextureTargetStr(target) << ", " << getTextureParameterStr(pname) << ", " << params << ");" << TestLog::EndMessage;
 	m_gl.getTexParameterfv(target, pname, params);
+	if (m_enableLog)
+		m_log << TestLog::Message << "// params = " << getPointerStr(params, 1) << TestLog::EndMessage;
 }
 
 void CallLogWrapper::glGetTexParameteriv (glw::GLenum target, glw::GLenum pname, glw::GLint *params)
@@ -2100,6 +2072,8 @@
 	if (m_enableLog)
 		m_log << TestLog::Message << "glGetTexParameteriv(" << getTextureTargetStr(target) << ", " << getTextureParameterStr(pname) << ", " << params << ");" << TestLog::EndMessage;
 	m_gl.getTexParameteriv(target, pname, params);
+	if (m_enableLog)
+		m_log << TestLog::Message << "// params = " << getPointerStr(params, 1) << TestLog::EndMessage;
 }
 
 void CallLogWrapper::glGetTextureImage (glw::GLuint texture, glw::GLint level, glw::GLenum format, glw::GLenum type, glw::GLsizei bufSize, void *pixels)
@@ -2202,9 +2176,7 @@
 		m_log << TestLog::Message << "glGetUniformIndices(" << program << ", " << uniformCount << ", " << getPointerStr(uniformNames, uniformCount) << ", " << uniformIndices << ");" << TestLog::EndMessage;
 	m_gl.getUniformIndices(program, uniformCount, uniformNames, uniformIndices);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// uniformIndices = " << getPointerStr(uniformIndices, uniformCount) << TestLog::EndMessage;
-	}
 }
 
 glw::GLint CallLogWrapper::glGetUniformLocation (glw::GLuint program, const glw::GLchar *name)
@@ -2279,9 +2251,7 @@
 		m_log << TestLog::Message << "glGetVertexAttribIiv(" << index << ", " << getVertexAttribParameterNameStr(pname) << ", " << params << ");" << TestLog::EndMessage;
 	m_gl.getVertexAttribIiv(index, pname, params);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// params = " << getPointerStr(params, getAttributeQueryNumArgsOut(pname)) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGetVertexAttribIuiv (glw::GLuint index, glw::GLenum pname, glw::GLuint *params)
@@ -2290,9 +2260,7 @@
 		m_log << TestLog::Message << "glGetVertexAttribIuiv(" << index << ", " << getVertexAttribParameterNameStr(pname) << ", " << params << ");" << TestLog::EndMessage;
 	m_gl.getVertexAttribIuiv(index, pname, params);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// params = " << getPointerStr(params, getAttributeQueryNumArgsOut(pname)) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGetVertexAttribLdv (glw::GLuint index, glw::GLenum pname, glw::GLdouble *params)
@@ -2322,9 +2290,7 @@
 		m_log << TestLog::Message << "glGetVertexAttribfv(" << index << ", " << getVertexAttribParameterNameStr(pname) << ", " << params << ");" << TestLog::EndMessage;
 	m_gl.getVertexAttribfv(index, pname, params);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// params = " << getPointerStr(params, getAttributeQueryNumArgsOut(pname)) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGetVertexAttribiv (glw::GLuint index, glw::GLenum pname, glw::GLint *params)
@@ -2333,9 +2299,7 @@
 		m_log << TestLog::Message << "glGetVertexAttribiv(" << index << ", " << getVertexAttribParameterNameStr(pname) << ", " << params << ");" << TestLog::EndMessage;
 	m_gl.getVertexAttribiv(index, pname, params);
 	if (m_enableLog)
-	{
 		m_log << TestLog::Message << "// params = " << getPointerStr(params, getAttributeQueryNumArgsOut(pname)) << TestLog::EndMessage;
-	}
 }
 
 void CallLogWrapper::glGetnCompressedTexImage (glw::GLenum target, glw::GLint lod, glw::GLsizei bufSize, void *pixels)
@@ -2913,7 +2877,7 @@
 void CallLogWrapper::glProgramParameteri (glw::GLuint program, glw::GLenum pname, glw::GLint value)
 {
 	if (m_enableLog)
-		m_log << TestLog::Message << "glProgramParameteri(" << program << ", " << toHex(pname) << ", " << value << ");" << TestLog::EndMessage;
+		m_log << TestLog::Message << "glProgramParameteri(" << program << ", " << getProgramParamStr(pname) << ", " << value << ");" << TestLog::EndMessage;
 	m_gl.programParameteri(program, pname, value);
 }
 
@@ -3557,7 +3521,7 @@
 void CallLogWrapper::glTexParameterfv (glw::GLenum target, glw::GLenum pname, const glw::GLfloat *params)
 {
 	if (m_enableLog)
-		m_log << TestLog::Message << "glTexParameterfv(" << getTextureTargetStr(target) << ", " << getTextureParameterStr(pname) << ", " << params << ");" << TestLog::EndMessage;
+		m_log << TestLog::Message << "glTexParameterfv(" << getTextureTargetStr(target) << ", " << getTextureParameterStr(pname) << ", " << getPointerStr(params, 1) << ");" << TestLog::EndMessage;
 	m_gl.texParameterfv(target, pname, params);
 }
 
@@ -3571,7 +3535,7 @@
 void CallLogWrapper::glTexParameteriv (glw::GLenum target, glw::GLenum pname, const glw::GLint *params)
 {
 	if (m_enableLog)
-		m_log << TestLog::Message << "glTexParameteriv(" << getTextureTargetStr(target) << ", " << getTextureParameterStr(pname) << ", " << params << ");" << TestLog::EndMessage;
+		m_log << TestLog::Message << "glTexParameteriv(" << getTextureTargetStr(target) << ", " << getTextureParameterStr(pname) << ", " << getPointerStr(params, 1) << ");" << TestLog::EndMessage;
 	m_gl.texParameteriv(target, pname, params);
 }
 
@@ -4172,7 +4136,7 @@
 void CallLogWrapper::glUseProgramStages (glw::GLuint pipeline, glw::GLbitfield stages, glw::GLuint program)
 {
 	if (m_enableLog)
-		m_log << TestLog::Message << "glUseProgramStages(" << pipeline << ", " << toHex(stages) << ", " << program << ");" << TestLog::EndMessage;
+		m_log << TestLog::Message << "glUseProgramStages(" << pipeline << ", " << getShaderTypeMaskStr(stages) << ", " << program << ");" << TestLog::EndMessage;
 	m_gl.useProgramStages(pipeline, stages, program);
 }
 
diff --git a/framework/opengl/gluQueryUtil.inl b/framework/opengl/gluQueryUtil.inl
index 9b9ec17..c5ca454 100644
--- a/framework/opengl/gluQueryUtil.inl
+++ b/framework/opengl/gluQueryUtil.inl
@@ -30,3 +30,12 @@
 		default:						return 1;
 	}
 }
+
+int getProgramQueryNumArgsOut (int pname)
+{
+	switch(pname)
+	{
+		case GL_COMPUTE_WORK_GROUP_SIZE:	return 3;
+		default:							return 1;
+	}
+}
diff --git a/framework/opengl/gluStateReset.cpp b/framework/opengl/gluStateReset.cpp
index 9429670..26cf894 100644
--- a/framework/opengl/gluStateReset.cpp
+++ b/framework/opengl/gluStateReset.cpp
@@ -452,6 +452,18 @@
 		GLU_EXPECT_NO_ERROR(gl.getError(), "Buffer copy state reset failed");
 	}
 
+	// Images.
+	if (contextSupports(type, ApiType::es(3,1)))
+	{
+		int numImageUnits = 0;
+		gl.getIntegerv(GL_MAX_IMAGE_UNITS, &numImageUnits);
+
+		for (int ndx = 0; ndx < numImageUnits; ndx++)
+			gl.bindImageTexture(ndx, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
+
+		GLU_EXPECT_NO_ERROR(gl.getError(), "Image state reset failed");
+	}
+
 	// Sample shading state.
 	if (contextSupports(type, ApiType::es(3,1)) && ctxInfo->isExtensionSupported("GL_OES_sample_shading"))
 	{
diff --git a/framework/opengl/gluStrUtil.cpp b/framework/opengl/gluStrUtil.cpp
index d83bc68..3560e04 100644
--- a/framework/opengl/gluStrUtil.cpp
+++ b/framework/opengl/gluStrUtil.cpp
@@ -108,6 +108,9 @@
 		case GL_TEXTURE_MAG_FILTER:
 			return str << getTextureFilterStr(valueStr.value);
 
+		case GL_DEPTH_STENCIL_TEXTURE_MODE:
+			return str << getTextureDepthStencilModeStr(valueStr.value);
+
 		default:
 			return str << tcu::toHex(valueStr.value);
 	}
diff --git a/framework/opengl/gluStrUtil.inl b/framework/opengl/gluStrUtil.inl
index c220932..8b82a3f 100644
--- a/framework/opengl/gluStrUtil.inl
+++ b/framework/opengl/gluStrUtil.inl
@@ -135,6 +135,9 @@
 		case GL_GEOMETRY_OUTPUT_TYPE:					return "GL_GEOMETRY_OUTPUT_TYPE";
 		case GL_GEOMETRY_VERTICES_OUT:					return "GL_GEOMETRY_VERTICES_OUT";
 		case GL_GEOMETRY_SHADER_INVOCATIONS:			return "GL_GEOMETRY_SHADER_INVOCATIONS";
+		case GL_PROGRAM_SEPARABLE:						return "GL_PROGRAM_SEPARABLE";
+		case GL_COMPUTE_WORK_GROUP_SIZE:				return "GL_COMPUTE_WORK_GROUP_SIZE";
+		case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:			return "GL_ACTIVE_ATOMIC_COUNTER_BUFFERS";
 		default:										return DE_NULL;
 	}
 }
@@ -365,6 +368,8 @@
 		case GL_DRAW_INDIRECT_BUFFER:		return "GL_DRAW_INDIRECT_BUFFER";
 		case GL_SHADER_STORAGE_BUFFER:		return "GL_SHADER_STORAGE_BUFFER";
 		case GL_TEXTURE_BUFFER:				return "GL_TEXTURE_BUFFER";
+		case GL_DISPATCH_INDIRECT_BUFFER:	return "GL_DISPATCH_INDIRECT_BUFFER";
+		case GL_ATOMIC_COUNTER_BUFFER:		return "GL_ATOMIC_COUNTER_BUFFER";
 		default:							return DE_NULL;
 	}
 }
@@ -457,6 +462,7 @@
 		case GL_SAMPLE_SHADING:					return "GL_SAMPLE_SHADING";
 		case GL_DEPTH_CLAMP:					return "GL_DEPTH_CLAMP";
 		case GL_PRIMITIVE_RESTART:				return "GL_PRIMITIVE_RESTART";
+		case GL_SAMPLE_MASK:					return "GL_SAMPLE_MASK";
 		default:								return DE_NULL;
 	}
 }
@@ -617,6 +623,7 @@
 		case GL_TEXTURE_SWIZZLE_A:			return "GL_TEXTURE_SWIZZLE_A";
 		case GL_TEXTURE_MIN_FILTER:			return "GL_TEXTURE_MIN_FILTER";
 		case GL_TEXTURE_MAG_FILTER:			return "GL_TEXTURE_MAG_FILTER";
+		case GL_DEPTH_STENCIL_TEXTURE_MODE:	return "GL_DEPTH_STENCIL_TEXTURE_MODE";
 		case GL_TEXTURE_IMMUTABLE_LEVELS:	return "GL_TEXTURE_IMMUTABLE_LEVELS";
 		case GL_TEXTURE_IMMUTABLE_FORMAT:	return "GL_TEXTURE_IMMUTABLE_FORMAT";
 		default:							return DE_NULL;
@@ -724,6 +731,16 @@
 	}
 }
 
+const char* getTextureDepthStencilModeName (int value)
+{
+	switch (value)
+	{
+		case GL_DEPTH_COMPONENT:	return "GL_DEPTH_COMPONENT";
+		case GL_STENCIL_INDEX:		return "GL_STENCIL_INDEX";
+		default:					return DE_NULL;
+	}
+}
+
 const char* getPixelStoreParameterName (int value)
 {
 	switch (value)
@@ -1201,6 +1218,20 @@
 		case GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS:				return "GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS";
 		case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:			return "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT";
 		case GL_PRIMITIVE_BOUNDING_BOX_EXT:						return "GL_PRIMITIVE_BOUNDING_BOX_EXT";
+		case GL_DRAW_INDIRECT_BUFFER_BINDING:					return "GL_DRAW_INDIRECT_BUFFER_BINDING";
+		case GL_MAX_SAMPLE_MASK_WORDS:							return "GL_MAX_SAMPLE_MASK_WORDS";
+		case GL_PROGRAM_PIPELINE_BINDING:						return "GL_PROGRAM_PIPELINE_BINDING";
+		case GL_ATOMIC_COUNTER_BUFFER_BINDING:					return "GL_ATOMIC_COUNTER_BUFFER_BINDING";
+		case GL_SHADER_STORAGE_BUFFER_BINDING:					return "GL_SHADER_STORAGE_BUFFER_BINDING";
+		case GL_DISPATCH_INDIRECT_BUFFER_BINDING:				return "GL_DISPATCH_INDIRECT_BUFFER_BINDING";
+		case GL_MAX_FRAMEBUFFER_WIDTH:							return "GL_MAX_FRAMEBUFFER_WIDTH";
+		case GL_MAX_FRAMEBUFFER_HEIGHT:							return "GL_MAX_FRAMEBUFFER_HEIGHT";
+		case GL_MAX_FRAMEBUFFER_SAMPLES:						return "GL_MAX_FRAMEBUFFER_SAMPLES";
+		case GL_MAX_COMPUTE_SHARED_MEMORY_SIZE:					return "GL_MAX_COMPUTE_SHARED_MEMORY_SIZE";
+		case GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET:				return "GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET";
+		case GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET:				return "GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET";
+		case GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS:				return "GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS";
+		case GL_MAX_UNIFORM_LOCATIONS:							return "GL_MAX_UNIFORM_LOCATIONS";
 		case GL_TEXTURE_2D:										return "GL_TEXTURE_2D";
 		case GL_CULL_FACE:										return "GL_CULL_FACE";
 		case GL_BLEND:											return "GL_BLEND";
@@ -1217,6 +1248,7 @@
 		case GL_SAMPLE_SHADING:									return "GL_SAMPLE_SHADING";
 		case GL_DEPTH_CLAMP:									return "GL_DEPTH_CLAMP";
 		case GL_PRIMITIVE_RESTART:								return "GL_PRIMITIVE_RESTART";
+		case GL_SAMPLE_MASK:									return "GL_SAMPLE_MASK";
 		default:												return DE_NULL;
 	}
 }
@@ -1236,6 +1268,20 @@
 		case GL_VERTEX_BINDING_STRIDE:				return "GL_VERTEX_BINDING_STRIDE";
 		case GL_VERTEX_BINDING_DIVISOR:				return "GL_VERTEX_BINDING_DIVISOR";
 		case GL_VERTEX_BINDING_BUFFER:				return "GL_VERTEX_BINDING_BUFFER";
+		case GL_MAX_COMPUTE_WORK_GROUP_COUNT:		return "GL_MAX_COMPUTE_WORK_GROUP_COUNT";
+		case GL_MAX_COMPUTE_WORK_GROUP_SIZE:		return "GL_MAX_COMPUTE_WORK_GROUP_SIZE";
+		case GL_ATOMIC_COUNTER_BUFFER_BINDING:		return "GL_ATOMIC_COUNTER_BUFFER_BINDING";
+		case GL_ATOMIC_COUNTER_BUFFER_START:		return "GL_ATOMIC_COUNTER_BUFFER_START";
+		case GL_ATOMIC_COUNTER_BUFFER_SIZE:			return "GL_ATOMIC_COUNTER_BUFFER_SIZE";
+		case GL_SHADER_STORAGE_BUFFER_BINDING:		return "GL_SHADER_STORAGE_BUFFER_BINDING";
+		case GL_SHADER_STORAGE_BUFFER_START:		return "GL_SHADER_STORAGE_BUFFER_START";
+		case GL_SHADER_STORAGE_BUFFER_SIZE:			return "GL_SHADER_STORAGE_BUFFER_SIZE";
+		case GL_IMAGE_BINDING_NAME:					return "GL_IMAGE_BINDING_NAME";
+		case GL_IMAGE_BINDING_LEVEL:				return "GL_IMAGE_BINDING_LEVEL";
+		case GL_IMAGE_BINDING_LAYERED:				return "GL_IMAGE_BINDING_LAYERED";
+		case GL_IMAGE_BINDING_LAYER:				return "GL_IMAGE_BINDING_LAYER";
+		case GL_IMAGE_BINDING_ACCESS:				return "GL_IMAGE_BINDING_ACCESS";
+		case GL_IMAGE_BINDING_FORMAT:				return "GL_IMAGE_BINDING_FORMAT";
 		default:									return DE_NULL;
 	}
 }
@@ -1519,3 +1565,17 @@
 	};
 	return tcu::Format::Bitfield<16>(value, &s_desc[0], &s_desc[DE_LENGTH_OF_ARRAY(s_desc)]);
 }
+
+tcu::Format::Bitfield<16> getShaderTypeMaskStr (int value)
+{
+	static const tcu::Format::BitDesc s_desc[] =
+	{
+		tcu::Format::BitDesc(GL_VERTEX_SHADER_BIT,			"GL_VERTEX_SHADER_BIT"),
+		tcu::Format::BitDesc(GL_FRAGMENT_SHADER_BIT,		"GL_FRAGMENT_SHADER_BIT"),
+		tcu::Format::BitDesc(GL_COMPUTE_SHADER_BIT,			"GL_COMPUTE_SHADER_BIT"),
+		tcu::Format::BitDesc(GL_GEOMETRY_SHADER_BIT,		"GL_GEOMETRY_SHADER_BIT"),
+		tcu::Format::BitDesc(GL_TESS_CONTROL_SHADER_BIT,	"GL_TESS_CONTROL_SHADER_BIT"),
+		tcu::Format::BitDesc(GL_TESS_EVALUATION_SHADER_BIT,	"GL_TESS_EVALUATION_SHADER_BIT"),
+	};
+	return tcu::Format::Bitfield<16>(value, &s_desc[0], &s_desc[DE_LENGTH_OF_ARRAY(s_desc)]);
+}
diff --git a/framework/opengl/gluStrUtilPrototypes.inl b/framework/opengl/gluStrUtilPrototypes.inl
index fed402e..ef1f822 100644
--- a/framework/opengl/gluStrUtilPrototypes.inl
+++ b/framework/opengl/gluStrUtilPrototypes.inl
@@ -43,6 +43,7 @@
 const char*							getTextureSwizzleName					(int value);
 const char*							getTextureCompareModeName				(int value);
 const char*							getCubeMapFaceName						(int value);
+const char*							getTextureDepthStencilModeName			(int value);
 const char*							getPixelStoreParameterName				(int value);
 const char*							getPixelFormatName						(int value);
 const char*							getCompressedTexFormatName				(int value);
@@ -72,6 +73,7 @@
 tcu::Format::Bitfield<16>			getBufferMaskStr						(int value);
 tcu::Format::Bitfield<16>			getBufferMapFlagsStr					(int value);
 tcu::Format::Bitfield<16>			getMemoryBarrierFlagsStr				(int value);
+tcu::Format::Bitfield<16>			getShaderTypeMaskStr					(int value);
 inline tcu::Format::Enum<int, 2>	getErrorStr								(int value)		{ return tcu::Format::Enum<int, 2>(getErrorName, value); }
 inline tcu::Format::Enum<int, 2>	getTypeStr								(int value)		{ return tcu::Format::Enum<int, 2>(getTypeName, value); }
 inline tcu::Format::Enum<int, 2>	getParamQueryStr						(int value)		{ return tcu::Format::Enum<int, 2>(getParamQueryName, value); }
@@ -112,6 +114,7 @@
 inline tcu::Format::Enum<int, 2>	getTextureSwizzleStr					(int value)		{ return tcu::Format::Enum<int, 2>(getTextureSwizzleName, value); }
 inline tcu::Format::Enum<int, 2>	getTextureCompareModeStr				(int value)		{ return tcu::Format::Enum<int, 2>(getTextureCompareModeName, value); }
 inline tcu::Format::Enum<int, 2>	getCubeMapFaceStr						(int value)		{ return tcu::Format::Enum<int, 2>(getCubeMapFaceName, value); }
+inline tcu::Format::Enum<int, 2>	getTextureDepthStencilModeStr			(int value)		{ return tcu::Format::Enum<int, 2>(getTextureDepthStencilModeName, value); }
 inline tcu::Format::Enum<int, 2>	getPixelStoreParameterStr				(int value)		{ return tcu::Format::Enum<int, 2>(getPixelStoreParameterName, value); }
 inline tcu::Format::Enum<int, 2>	getPixelFormatStr						(int value)		{ return tcu::Format::Enum<int, 2>(getPixelFormatName, value); }
 inline tcu::Format::Enum<int, 2>	getCompressedTexFormatStr				(int value)		{ return tcu::Format::Enum<int, 2>(getCompressedTexFormatName, value); }
diff --git a/modules/gles31/functional/CMakeLists.txt b/modules/gles31/functional/CMakeLists.txt
index f3ca374..3746735 100644
--- a/modules/gles31/functional/CMakeLists.txt
+++ b/modules/gles31/functional/CMakeLists.txt
@@ -73,8 +73,20 @@
 	es31fTextureSpecificationTests.cpp
 	es31fIntegerStateQueryTests.cpp
 	es31fIntegerStateQueryTests.hpp
+	es31fBooleanStateQueryTests.cpp
+	es31fBooleanStateQueryTests.hpp
+	es31fIndexedStateQueryTests.cpp
+	es31fIndexedStateQueryTests.hpp
 	es31fInternalFormatQueryTests.cpp
 	es31fInternalFormatQueryTests.hpp
+	es31fTextureStateQueryTests.cpp
+	es31fTextureStateQueryTests.hpp
+	es31fFramebufferDefaultStateQueryTests.cpp
+	es31fFramebufferDefaultStateQueryTests.hpp
+	es31fProgramPipelineStateQueryTests.cpp
+	es31fProgramPipelineStateQueryTests.hpp
+	es31fProgramStateQueryTests.cpp
+	es31fProgramStateQueryTests.hpp
 	es31fTextureMultisampleTests.cpp
 	es31fTextureMultisampleTests.hpp
 	es31fUniformLocationTests.cpp
diff --git a/modules/gles31/functional/es31fBooleanStateQueryTests.cpp b/modules/gles31/functional/es31fBooleanStateQueryTests.cpp
new file mode 100644
index 0000000..6a18fce
--- /dev/null
+++ b/modules/gles31/functional/es31fBooleanStateQueryTests.cpp
@@ -0,0 +1,150 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Boolean State Query tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "es31fBooleanStateQueryTests.hpp"
+#include "glsStateQueryUtil.hpp"
+#include "gluRenderContext.hpp"
+#include "gluCallLogWrapper.hpp"
+#include "tcuRenderTarget.hpp"
+#include "glwFunctions.hpp"
+#include "glwEnums.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace
+{
+
+using namespace gls::StateQueryUtil;
+
+static const char* getVerifierSuffix (QueryType type)
+{
+	switch (type)
+	{
+		case QUERY_ISENABLED:	return "isenabled";
+		case QUERY_BOOLEAN:		return "getboolean";
+		case QUERY_INTEGER:		return "getinteger";
+		case QUERY_INTEGER64:	return "getinteger64";
+		case QUERY_FLOAT:		return "getfloat";
+		default:
+			DE_ASSERT(DE_FALSE);
+			return DE_NULL;
+	}
+}
+
+class IsEnabledStateTestCase : public TestCase, private glu::CallLogWrapper
+{
+public:
+	IsEnabledStateTestCase (Context& context, QueryType verifier, const char* name, const char* description, glw::GLenum targetName, bool initial)
+		: TestCase				(context, name, description)
+		, glu::CallLogWrapper	(context.getRenderContext().getFunctions(), context.getTestContext().getLog())
+		, m_targetName			(targetName)
+		, m_initial				(initial)
+		, m_verifier			(verifier)
+	{
+	}
+
+	IterateResult iterate (void)
+	{
+		tcu::ResultCollector result(m_testCtx.getLog(), " // ERROR: ");
+		enableLogging(true);
+
+		// check inital value
+		verifyStateBoolean(result, *this, m_targetName, m_initial, m_verifier);
+
+		// check toggle
+
+		GLU_CHECK_CALL(glEnable(m_targetName));
+
+		verifyStateBoolean(result, *this, m_targetName, true, m_verifier);
+
+		GLU_CHECK_CALL(glDisable(m_targetName));
+
+		verifyStateBoolean(result, *this, m_targetName, false, m_verifier);
+
+		result.setTestContextResult(m_testCtx);
+		return STOP;
+	}
+
+private:
+	const glw::GLenum		m_targetName;
+	const bool				m_initial;
+	const QueryType			m_verifier;
+};
+
+} // anonymous
+
+BooleanStateQueryTests::BooleanStateQueryTests (Context& context)
+	: TestCaseGroup(context, "boolean", "Boolean State Query tests")
+{
+}
+
+BooleanStateQueryTests::~BooleanStateQueryTests (void)
+{
+}
+
+void BooleanStateQueryTests::init (void)
+{
+	static const QueryType isEnabledVerifiers[] =
+	{
+		QUERY_ISENABLED,
+		QUERY_BOOLEAN,
+		QUERY_INTEGER,
+		QUERY_INTEGER64,
+		QUERY_FLOAT
+	};
+
+#define FOR_EACH_VERIFIER(VERIFIERS, X) \
+	for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(VERIFIERS); ++verifierNdx)	\
+	{																						\
+		const char* verifierSuffix = getVerifierSuffix(VERIFIERS[verifierNdx]);				\
+		const QueryType verifier = VERIFIERS[verifierNdx];									\
+		this->addChild(X);																	\
+	}
+
+	struct StateBoolean
+	{
+		const char*		name;
+		const char*		description;
+		glw::GLenum		targetName;
+		bool			value;
+	};
+	const StateBoolean isEnableds[] =
+	{
+		{ "sample_mask",	"SAMPLE_MASK",	GL_SAMPLE_MASK,	false},
+	};
+
+	for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(isEnableds); testNdx++)
+	{
+		FOR_EACH_VERIFIER(isEnabledVerifiers, new IsEnabledStateTestCase(m_context, verifier, (std::string(isEnableds[testNdx].name) + "_" + verifierSuffix).c_str(), isEnableds[testNdx].description, isEnableds[testNdx].targetName, isEnableds[testNdx].value));
+	}
+
+#undef FOR_EACH_VERIFIER
+}
+
+} // Functional
+} // gles31
+} // deqp
diff --git a/modules/gles31/functional/es31fBooleanStateQueryTests.hpp b/modules/gles31/functional/es31fBooleanStateQueryTests.hpp
new file mode 100644
index 0000000..05d4b81
--- /dev/null
+++ b/modules/gles31/functional/es31fBooleanStateQueryTests.hpp
@@ -0,0 +1,53 @@
+#ifndef _ES31FBOOLEANSTATEQUERYTESTS_HPP
+#define _ES31FBOOLEANSTATEQUERYTESTS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Boolean State Query tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tes31TestCase.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+
+class BooleanStateQueryTests : public TestCaseGroup
+{
+public:
+							BooleanStateQueryTests	(Context& context);
+							~BooleanStateQueryTests	(void);
+
+	void					init					(void);
+
+private:
+							BooleanStateQueryTests	(const BooleanStateQueryTests& other);
+	BooleanStateQueryTests&	operator=				(const BooleanStateQueryTests& other);
+};
+
+} // Functional
+} // gles31
+} // deqp
+
+#endif // _ES31FBOOLEANSTATEQUERYTESTS_HPP
diff --git a/modules/gles31/functional/es31fFramebufferDefaultStateQueryTests.cpp b/modules/gles31/functional/es31fFramebufferDefaultStateQueryTests.cpp
new file mode 100644
index 0000000..67a17aa
--- /dev/null
+++ b/modules/gles31/functional/es31fFramebufferDefaultStateQueryTests.cpp
@@ -0,0 +1,230 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Framebuffer Default State Query tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "es31fFramebufferDefaultStateQueryTests.hpp"
+#include "glsStateQueryUtil.hpp"
+#include "gluRenderContext.hpp"
+#include "gluCallLogWrapper.hpp"
+#include "gluObjectWrapper.hpp"
+#include "glwFunctions.hpp"
+#include "glwEnums.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace
+{
+
+using namespace gls::StateQueryUtil;
+
+static const char* getVerifierSuffix (QueryType type)
+{
+	switch (type)
+	{
+		case QUERY_FRAMEBUFFER_INTEGER:	return "get_framebuffer_parameteriv";
+		default:
+			DE_ASSERT(DE_FALSE);
+			return DE_NULL;
+	}
+}
+
+class FramebufferTest : public TestCase
+{
+public:
+						FramebufferTest		(Context& context, QueryType verifier, const char* name, const char* desc);
+	IterateResult		iterate				(void);
+
+protected:
+	virtual void		checkInitial		(tcu::ResultCollector& result, glu::CallLogWrapper& gl) = 0;
+	virtual void		checkSet			(tcu::ResultCollector& result, glu::CallLogWrapper& gl) = 0;
+
+	const QueryType		m_verifier;
+};
+
+FramebufferTest::FramebufferTest (Context& context, QueryType verifier, const char* name, const char* desc)
+	: TestCase		(context, name, desc)
+	, m_verifier	(verifier)
+{
+}
+
+FramebufferTest::IterateResult FramebufferTest::iterate (void)
+{
+	glu::Framebuffer		fbo		(m_context.getRenderContext());
+	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
+
+	gl.enableLogging(true);
+
+	gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, *fbo);
+	GLU_EXPECT_NO_ERROR(gl.glGetError(), "bind");
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial");
+		checkInitial(result, gl);
+	}
+
+	{
+		const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Set", "Set");
+		checkSet(result, gl);
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class FramebufferDimensionTest : public FramebufferTest
+{
+public:
+	enum DimensionType
+	{
+		DIMENSION_WIDTH = 0,
+		DIMENSION_HEIGHT,
+
+		DIMENSION_LAST
+	};
+
+						FramebufferDimensionTest	(Context& context, QueryType verifier, DimensionType dimension, const char* name, const char* desc);
+	void				checkInitial				(tcu::ResultCollector& result, glu::CallLogWrapper& gl);
+	void				checkSet					(tcu::ResultCollector& result, glu::CallLogWrapper& gl);
+
+private:
+	const DimensionType	m_dimension;
+};
+
+FramebufferDimensionTest::FramebufferDimensionTest (Context& context, QueryType verifier, DimensionType dimension, const char* name, const char* desc)
+	: FramebufferTest	(context, verifier, name, desc)
+	, m_dimension		(dimension)
+{
+	DE_ASSERT(dimension < DIMENSION_LAST);
+}
+
+void FramebufferDimensionTest::checkInitial (tcu::ResultCollector& result, glu::CallLogWrapper& gl)
+{
+	const glw::GLenum pname = (m_dimension == DIMENSION_WIDTH) ? (GL_FRAMEBUFFER_DEFAULT_WIDTH) : (GL_FRAMEBUFFER_DEFAULT_HEIGHT);
+	verifyStateFramebufferInteger(result, gl, GL_DRAW_FRAMEBUFFER, pname, 0, m_verifier);
+}
+
+void FramebufferDimensionTest::checkSet (tcu::ResultCollector& result, glu::CallLogWrapper& gl)
+{
+	const glw::GLenum pname = (m_dimension == DIMENSION_WIDTH) ? (GL_FRAMEBUFFER_DEFAULT_WIDTH) : (GL_FRAMEBUFFER_DEFAULT_HEIGHT);
+	
+	gl.glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, pname, 32);
+	GLU_EXPECT_NO_ERROR(gl.glGetError(), "set state");
+
+	verifyStateFramebufferInteger(result, gl, GL_DRAW_FRAMEBUFFER, pname, 32, m_verifier);
+}
+
+class FramebufferSamplesTest : public FramebufferTest
+{
+public:
+						FramebufferSamplesTest	(Context& context, QueryType verifier, const char* name, const char* desc);
+	void				checkInitial				(tcu::ResultCollector& result, glu::CallLogWrapper& gl);
+	void				checkSet					(tcu::ResultCollector& result, glu::CallLogWrapper& gl);
+};
+
+FramebufferSamplesTest::FramebufferSamplesTest (Context& context, QueryType verifier, const char* name, const char* desc)
+	: FramebufferTest(context, verifier, name, desc)
+{
+}
+
+void FramebufferSamplesTest::checkInitial (tcu::ResultCollector& result, glu::CallLogWrapper& gl)
+{
+	verifyStateFramebufferInteger(result, gl, GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES, 0, m_verifier);
+}
+
+void FramebufferSamplesTest::checkSet (tcu::ResultCollector& result, glu::CallLogWrapper& gl)
+{
+	gl.glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES, 1);
+	GLU_EXPECT_NO_ERROR(gl.glGetError(), "set state");
+	verifyStateFramebufferIntegerMin(result, gl, GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES, 1, m_verifier);
+
+	gl.glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES, 0);
+	GLU_EXPECT_NO_ERROR(gl.glGetError(), "set state");
+	verifyStateFramebufferInteger(result, gl, GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES, 0, m_verifier);
+}
+
+class FramebufferFixedSampleLocationsTest : public FramebufferTest
+{
+public:
+						FramebufferFixedSampleLocationsTest	(Context& context, QueryType verifier, const char* name, const char* desc);
+	void				checkInitial				(tcu::ResultCollector& result, glu::CallLogWrapper& gl);
+	void				checkSet					(tcu::ResultCollector& result, glu::CallLogWrapper& gl);
+};
+
+FramebufferFixedSampleLocationsTest::FramebufferFixedSampleLocationsTest (Context& context, QueryType verifier, const char* name, const char* desc)
+	: FramebufferTest(context, verifier, name, desc)
+{
+}
+
+void FramebufferFixedSampleLocationsTest::checkInitial (tcu::ResultCollector& result, glu::CallLogWrapper& gl)
+{
+	verifyStateFramebufferInteger(result, gl, GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS, 0, m_verifier);
+}
+
+void FramebufferFixedSampleLocationsTest::checkSet (tcu::ResultCollector& result, glu::CallLogWrapper& gl)
+{
+	gl.glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS, GL_TRUE);
+	GLU_EXPECT_NO_ERROR(gl.glGetError(), "set state");
+	verifyStateFramebufferInteger(result, gl, GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS, GL_TRUE, m_verifier);
+}
+
+} // anonymous
+
+FramebufferDefaultStateQueryTests::FramebufferDefaultStateQueryTests (Context& context)
+	: TestCaseGroup(context, "framebuffer_default", "Framebuffer Default State Query tests")
+{
+}
+
+FramebufferDefaultStateQueryTests::~FramebufferDefaultStateQueryTests (void)
+{
+}
+
+void FramebufferDefaultStateQueryTests::init (void)
+{
+	static const QueryType verifiers[] =
+	{
+		QUERY_FRAMEBUFFER_INTEGER,
+	};
+
+#define FOR_EACH_VERIFIER(X) \
+	for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(verifiers); ++verifierNdx)	\
+	{																						\
+		const char* verifierSuffix = getVerifierSuffix(verifiers[verifierNdx]);				\
+		const QueryType verifier = verifiers[verifierNdx];								\
+		this->addChild(X);																	\
+	}
+
+	FOR_EACH_VERIFIER(new FramebufferDimensionTest				(m_context, verifier, FramebufferDimensionTest::DIMENSION_WIDTH,	(std::string("framebuffer_default_width_") + verifierSuffix).c_str(),					"Test FRAMEBUFFER_DEFAULT_WIDTH"));
+	FOR_EACH_VERIFIER(new FramebufferDimensionTest				(m_context, verifier, FramebufferDimensionTest::DIMENSION_HEIGHT,	(std::string("framebuffer_default_height_") + verifierSuffix).c_str(),					"Test FRAMEBUFFER_DEFAULT_HEIGHT"));
+	FOR_EACH_VERIFIER(new FramebufferSamplesTest				(m_context, verifier, 												(std::string("framebuffer_default_samples_") + verifierSuffix).c_str(),					"Test FRAMEBUFFER_DEFAULT_SAMPLES"));
+	FOR_EACH_VERIFIER(new FramebufferFixedSampleLocationsTest	(m_context, verifier,												(std::string("framebuffer_default_fixed_sample_locations_") + verifierSuffix).c_str(),	"Test FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS"));
+
+#undef FOR_EACH_VERIFIER
+}
+
+} // Functional
+} // gles31
+} // deqp
diff --git a/modules/gles31/functional/es31fFramebufferDefaultStateQueryTests.hpp b/modules/gles31/functional/es31fFramebufferDefaultStateQueryTests.hpp
new file mode 100644
index 0000000..bd4c1f9
--- /dev/null
+++ b/modules/gles31/functional/es31fFramebufferDefaultStateQueryTests.hpp
@@ -0,0 +1,53 @@
+#ifndef _ES31FFRAMEBUFFERDEFAULTSTATEQUERYTESTS_HPP
+#define _ES31FFRAMEBUFFERDEFAULTSTATEQUERYTESTS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Framebuffer Default State Query tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tes31TestCase.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+
+class FramebufferDefaultStateQueryTests : public TestCaseGroup
+{
+public:
+										FramebufferDefaultStateQueryTests	(Context& context);
+										~FramebufferDefaultStateQueryTests	(void);
+
+	void								init								(void);
+
+private:
+										FramebufferDefaultStateQueryTests	(const FramebufferDefaultStateQueryTests& other);
+	FramebufferDefaultStateQueryTests&	operator=							(const FramebufferDefaultStateQueryTests& other);
+};
+
+} // Functional
+} // gles31
+} // deqp
+
+#endif // _ES31FFRAMEBUFFERDEFAULTSTATEQUERYTESTS_HPP
diff --git a/modules/gles31/functional/es31fFunctionalTests.cpp b/modules/gles31/functional/es31fFunctionalTests.cpp
index 214222c..e7bb871 100644
--- a/modules/gles31/functional/es31fFunctionalTests.cpp
+++ b/modules/gles31/functional/es31fFunctionalTests.cpp
@@ -44,6 +44,12 @@
 #include "es31fTextureLevelStateQueryTests.hpp"
 #include "es31fIntegerStateQueryTests.hpp"
 #include "es31fInternalFormatQueryTests.hpp"
+#include "es31fBooleanStateQueryTests.hpp"
+#include "es31fIndexedStateQueryTests.hpp"
+#include "es31fTextureStateQueryTests.hpp"
+#include "es31fFramebufferDefaultStateQueryTests.hpp"
+#include "es31fProgramPipelineStateQueryTests.hpp"
+#include "es31fProgramStateQueryTests.hpp"
 #include "es31fTextureFilteringTests.hpp"
 #include "es31fTextureFormatTests.hpp"
 #include "es31fTextureSpecificationTests.hpp"
@@ -249,12 +255,18 @@
 
 	void init (void)
 	{
+		addChild(new BooleanStateQueryTests							(m_context));
 		addChild(new IntegerStateQueryTests							(m_context));
+		addChild(new IndexedStateQueryTests							(m_context));
+		addChild(new TextureStateQueryTests							(m_context));
 		addChild(new TextureLevelStateQueryTests					(m_context));
 		addChild(new ShaderStateQueryTests							(m_context));
 		addChild(new InternalFormatQueryTests						(m_context));
 		addChild(new VertexAttributeBindingStateQueryTests			(m_context));
 		addChild(new ShaderMultisampleInterpolationStateQueryTests	(m_context));
+		addChild(new FramebufferDefaultStateQueryTests				(m_context));
+		addChild(new ProgramStateQueryTests							(m_context));
+		addChild(new ProgramPipelineStateQueryTests					(m_context));
 	}
 };
 
diff --git a/modules/gles31/functional/es31fIndexedStateQueryTests.cpp b/modules/gles31/functional/es31fIndexedStateQueryTests.cpp
new file mode 100644
index 0000000..877e367
--- /dev/null
+++ b/modules/gles31/functional/es31fIndexedStateQueryTests.cpp
@@ -0,0 +1,886 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Indexed state query tests
+ *//*--------------------------------------------------------------------*/
+
+#include "es31fIndexedStateQueryTests.hpp"
+#include "tcuTestLog.hpp"
+#include "tcuFormatUtil.hpp"
+#include "gluRenderContext.hpp"
+#include "gluCallLogWrapper.hpp"
+#include "gluStrUtil.hpp"
+#include "gluObjectWrapper.hpp"
+#include "glwFunctions.hpp"
+#include "glwEnums.hpp"
+#include "glsStateQueryUtil.hpp"
+#include "deRandom.hpp"
+#include "deStringUtil.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace
+{
+
+using namespace gls::StateQueryUtil;
+
+static const char* getVerifierSuffix (QueryType type)
+{
+	switch (type)
+	{
+		case QUERY_INDEXED_BOOLEAN:		return "getbooleani_v";
+		case QUERY_INDEXED_INTEGER:		return "getintegeri_v";
+		case QUERY_INDEXED_INTEGER64:	return "getinteger64i_v";
+		default:
+			DE_ASSERT(DE_FALSE);
+			return DE_NULL;
+	}
+}
+
+class SampleMaskCase : public TestCase
+{
+public:
+						SampleMaskCase	(Context& context, const char* name, const char* desc, QueryType verifierType);
+
+private:
+	void				init			(void);
+	IterateResult		iterate			(void);
+
+	const QueryType		m_verifierType;
+	int					m_maxSampleMaskWords;
+};
+
+SampleMaskCase::SampleMaskCase (Context& context, const char* name, const char* desc, QueryType verifierType)
+	: TestCase				(context, name, desc)
+	, m_verifierType		(verifierType)
+	, m_maxSampleMaskWords	(-1)
+{
+}
+
+void SampleMaskCase::init (void)
+{
+	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+
+	gl.getIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &m_maxSampleMaskWords);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "query sample mask words");
+
+	// mask word count ok?
+	if (m_maxSampleMaskWords <= 0)
+		throw tcu::TestError("Minimum value of GL_MAX_SAMPLE_MASK_WORDS is 1. Got " + de::toString(m_maxSampleMaskWords));
+
+	m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_SAMPLE_MASK_WORDS = " << m_maxSampleMaskWords << tcu::TestLog::EndMessage;
+}
+
+SampleMaskCase::IterateResult SampleMaskCase::iterate (void)
+{
+	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
+
+	gl.enableLogging(true);
+
+	// initial values
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "initial", "Initial values");
+
+		for (int ndx = 0; ndx < m_maxSampleMaskWords; ++ndx)
+			verifyStateIndexedInteger(result, gl, GL_SAMPLE_MASK_VALUE, ndx, -1, m_verifierType);
+	}
+
+	// fixed values
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "fixed", "Fixed values");
+
+		for (int ndx = 0; ndx < m_maxSampleMaskWords; ++ndx)
+		{
+			gl.glSampleMaski(ndx, 0);
+			GLU_EXPECT_NO_ERROR(gl.glGetError(), "glSampleMaski");
+
+			verifyStateIndexedInteger(result, gl, GL_SAMPLE_MASK_VALUE, ndx, 0, m_verifierType);
+		}
+	}
+
+	// random masks
+	{
+		const int					numRandomTest	= 20;
+		const tcu::ScopedLogSection section			(m_testCtx.getLog(), "random", "Random values");
+		de::Random					rnd				(0x4312);
+
+		for (int testNdx = 0; testNdx < numRandomTest; ++testNdx)
+		{
+			const glw::GLint	maskIndex		= (glw::GLint)(rnd.getUint32() % m_maxSampleMaskWords);
+			glw::GLint			mask			= (glw::GLint)(rnd.getUint32());
+
+			gl.glSampleMaski(maskIndex, mask);
+			GLU_EXPECT_NO_ERROR(gl.glGetError(), "glSampleMaski");
+
+			verifyStateIndexedInteger(result, gl, GL_SAMPLE_MASK_VALUE, maskIndex, mask, m_verifierType);
+		}
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class MinValueIndexed3Case : public TestCase
+{
+public:
+						MinValueIndexed3Case	(Context& context, const char* name, const char* desc, glw::GLenum target, const tcu::IVec3& ref, QueryType verifierType);
+
+private:
+	IterateResult		iterate					(void);
+
+	const glw::GLenum	m_target;
+	const tcu::IVec3	m_ref;
+	const QueryType		m_verifierType;
+};
+
+MinValueIndexed3Case::MinValueIndexed3Case (Context& context, const char* name, const char* desc, glw::GLenum target, const tcu::IVec3& ref, QueryType verifierType)
+	: TestCase				(context, name, desc)
+	, m_target				(target)
+	, m_ref					(ref)
+	, m_verifierType		(verifierType)
+{
+}
+
+MinValueIndexed3Case::IterateResult MinValueIndexed3Case::iterate (void)
+{
+	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
+
+	gl.enableLogging(true);
+
+	for (int ndx = 0; ndx < 3; ++ndx)
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Element", "Element " + de::toString(ndx));
+
+		verifyStateIndexedIntegerMin(result, gl, m_target, ndx, m_ref[ndx], m_verifierType);
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class BufferBindingCase : public TestCase
+{
+public:
+						BufferBindingCase	(Context& context, const char* name, const char* desc, glw::GLenum queryTarget, glw::GLenum bufferTarget, glw::GLenum numBindingsTarget, QueryType verifierType);
+
+private:
+	IterateResult		iterate				(void);
+
+	const glw::GLenum	m_queryTarget;
+	const glw::GLenum	m_bufferTarget;
+	const glw::GLenum	m_numBindingsTarget;
+	const QueryType		m_verifierType;
+};
+
+BufferBindingCase::BufferBindingCase (Context& context, const char* name, const char* desc, glw::GLenum queryTarget, glw::GLenum bufferTarget, glw::GLenum numBindingsTarget, QueryType verifierType)
+	: TestCase				(context, name, desc)
+	, m_queryTarget			(queryTarget)
+	, m_bufferTarget		(bufferTarget)
+	, m_numBindingsTarget	(numBindingsTarget)
+	, m_verifierType		(verifierType)
+{
+}
+
+BufferBindingCase::IterateResult BufferBindingCase::iterate (void)
+{
+	glu::CallLogWrapper 	gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result		(m_testCtx.getLog(), " // ERROR: ");
+	int						maxBindings	= -1;
+
+	gl.enableLogging(true);
+
+	gl.glGetIntegerv(m_numBindingsTarget, &maxBindings);
+	GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetIntegerv");
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial value");
+
+		for (int ndx = 0; ndx < maxBindings; ++ndx)
+			verifyStateIndexedInteger(result, gl, m_queryTarget, ndx, 0, m_verifierType);
+	}
+
+	{
+		const tcu::ScopedLogSection	superSection	(m_testCtx.getLog(), "AfterSetting", "After setting");
+		glu::Buffer					bufferA			(m_context.getRenderContext());
+		glu::Buffer					bufferB			(m_context.getRenderContext());
+		const int					ndxA			= 0;
+		const int					ndxB			= maxBindings / 2;
+
+		{
+			const tcu::ScopedLogSection section(m_testCtx.getLog(), "Generic", "After setting generic binding point");
+
+			gl.glBindBuffer(m_bufferTarget, *bufferA);
+			GLU_EXPECT_NO_ERROR(gl.glGetError(), "glBindBuffer");
+
+			verifyStateIndexedInteger(result, gl, m_queryTarget, 0, 0, m_verifierType);
+		}
+		{
+			const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Indexed", "After setting with glBindBufferBase");
+
+			gl.glBindBufferBase(m_bufferTarget, ndxA, *bufferA);
+			GLU_EXPECT_NO_ERROR(gl.glGetError(), "glBindBufferBase");
+
+			verifyStateIndexedInteger(result, gl, m_queryTarget, ndxA, *bufferA, m_verifierType);
+		}
+		{
+			const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Indexed", "After setting with glBindBufferRange");
+
+			gl.glBindBufferRange(m_bufferTarget, ndxB, *bufferB, 0, 8);
+			GLU_EXPECT_NO_ERROR(gl.glGetError(), "glBindBufferRange");
+
+			verifyStateIndexedInteger(result, gl, m_queryTarget, ndxB, *bufferB, m_verifierType);
+		}
+		if (ndxA != ndxB)
+		{
+			const tcu::ScopedLogSection	section(m_testCtx.getLog(), "DifferentStates", "Original state did not change");
+
+			verifyStateIndexedInteger(result, gl, m_queryTarget, ndxA, *bufferA, m_verifierType);
+		}
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class BufferStartCase : public TestCase
+{
+public:
+						BufferStartCase		(Context& context, const char* name, const char* desc, glw::GLenum queryTarget, glw::GLenum bufferTarget, glw::GLenum numBindingsTarget, QueryType verifierType);
+
+private:
+	IterateResult		iterate				(void);
+
+	const glw::GLenum	m_queryTarget;
+	const glw::GLenum	m_bufferTarget;
+	const glw::GLenum	m_numBindingsTarget;
+	const QueryType		m_verifierType;
+};
+
+BufferStartCase::BufferStartCase (Context& context, const char* name, const char* desc, glw::GLenum queryTarget, glw::GLenum bufferTarget, glw::GLenum numBindingsTarget, QueryType verifierType)
+	: TestCase				(context, name, desc)
+	, m_queryTarget			(queryTarget)
+	, m_bufferTarget		(bufferTarget)
+	, m_numBindingsTarget	(numBindingsTarget)
+	, m_verifierType		(verifierType)
+{
+}
+
+BufferStartCase::IterateResult BufferStartCase::iterate (void)
+{
+	glu::CallLogWrapper		gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result		(m_testCtx.getLog(), " // ERROR: ");
+	int						maxBindings	= -1;
+
+	gl.enableLogging(true);
+
+	gl.glGetIntegerv(m_numBindingsTarget, &maxBindings);
+	GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetIntegerv");
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial value");
+
+		for (int ndx = 0; ndx < maxBindings; ++ndx)
+			verifyStateIndexedInteger(result, gl, m_queryTarget, ndx, 0, m_verifierType);
+	}
+
+
+	{
+		const tcu::ScopedLogSection	superSection	(m_testCtx.getLog(), "AfterSetting", "After setting");
+		glu::Buffer					bufferA			(m_context.getRenderContext());
+		glu::Buffer					bufferB			(m_context.getRenderContext());
+		const int					ndxA			= 0;
+		const int					ndxB			= maxBindings / 2;
+		int							offset			= -1;
+
+		if (m_bufferTarget == GL_ATOMIC_COUNTER_BUFFER)
+			offset = 4;
+		else if (m_bufferTarget == GL_SHADER_STORAGE_BUFFER)
+		{
+			gl.glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &offset);
+			GLU_EXPECT_NO_ERROR(gl.glGetError(), "get align");
+		}
+
+		DE_ASSERT(offset != -1);
+
+		{
+			const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Generic", "After setting generic binding point");
+
+			gl.glBindBuffer(m_bufferTarget, *bufferA);
+			gl.glBufferData(m_bufferTarget, 16, DE_NULL, GL_DYNAMIC_READ);
+			gl.glBindBuffer(m_bufferTarget, *bufferB);
+			gl.glBufferData(m_bufferTarget, 32, DE_NULL, GL_DYNAMIC_READ);
+			GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen bufs");
+
+			verifyStateIndexedInteger(result, gl, m_queryTarget, 0, 0, m_verifierType);
+		}
+		{
+			const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Indexed", "After setting with glBindBufferBase");
+
+			gl.glBindBufferBase(m_bufferTarget, ndxA, *bufferA);
+			GLU_EXPECT_NO_ERROR(gl.glGetError(), "bind buf");
+
+			verifyStateIndexedInteger(result, gl, m_queryTarget, ndxA, 0, m_verifierType);
+		}
+		{
+			const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Indexed", "After setting with glBindBufferRange");
+
+			gl.glBindBufferRange(m_bufferTarget, ndxB, *bufferB, offset, 8);
+			GLU_EXPECT_NO_ERROR(gl.glGetError(), "bind buf");
+
+			verifyStateIndexedInteger(result, gl, m_queryTarget, ndxB, offset, m_verifierType);
+		}
+		if (ndxA != ndxB)
+		{
+			const tcu::ScopedLogSection	section(m_testCtx.getLog(), "DifferentStates", "Original state did not change");
+
+			verifyStateIndexedInteger(result, gl, m_queryTarget, ndxA, 0, m_verifierType);
+		}
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class BufferSizeCase : public TestCase
+{
+public:
+						BufferSizeCase	(Context& context, const char* name, const char* desc, glw::GLenum queryTarget, glw::GLenum bufferTarget, glw::GLenum numBindingsTarget, QueryType verifierType);
+
+private:
+	IterateResult		iterate			(void);
+
+	const glw::GLenum	m_queryTarget;
+	const glw::GLenum	m_bufferTarget;
+	const glw::GLenum	m_numBindingsTarget;
+	const QueryType		m_verifierType;
+};
+
+BufferSizeCase::BufferSizeCase (Context& context, const char* name, const char* desc, glw::GLenum queryTarget, glw::GLenum bufferTarget, glw::GLenum numBindingsTarget, QueryType verifierType)
+	: TestCase				(context, name, desc)
+	, m_queryTarget			(queryTarget)
+	, m_bufferTarget		(bufferTarget)
+	, m_numBindingsTarget	(numBindingsTarget)
+	, m_verifierType		(verifierType)
+{
+}
+
+BufferSizeCase::IterateResult BufferSizeCase::iterate (void)
+{
+	glu::CallLogWrapper		gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result		(m_testCtx.getLog(), " // ERROR: ");
+	int						maxBindings	= -1;
+
+	gl.enableLogging(true);
+
+	gl.glGetIntegerv(m_numBindingsTarget, &maxBindings);
+	GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetIntegerv");
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial value");
+
+		for (int ndx = 0; ndx < maxBindings; ++ndx)
+			verifyStateIndexedInteger(result, gl, m_queryTarget, ndx, 0, m_verifierType);
+	}
+
+	{
+		const tcu::ScopedLogSection	superSection	(m_testCtx.getLog(), "AfterSetting", "After setting");
+		glu::Buffer					bufferA			(m_context.getRenderContext());
+		glu::Buffer					bufferB			(m_context.getRenderContext());
+		const int					ndxA			= 0;
+		const int					ndxB			= maxBindings / 2;
+
+		{
+			const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Generic", "After setting generic binding point");
+
+			gl.glBindBuffer(m_bufferTarget, *bufferA);
+			gl.glBufferData(m_bufferTarget, 16, DE_NULL, GL_DYNAMIC_READ);
+			gl.glBindBuffer(m_bufferTarget, *bufferB);
+			gl.glBufferData(m_bufferTarget, 32, DE_NULL, GL_DYNAMIC_READ);
+			GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen bufs");
+
+			verifyStateIndexedInteger(result, gl, m_queryTarget, 0, 0, m_verifierType);
+		}
+		{
+			const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Indexed", "After setting with glBindBufferBase");
+
+			gl.glBindBufferBase(m_bufferTarget, ndxA, *bufferA);
+			GLU_EXPECT_NO_ERROR(gl.glGetError(), "bind buf");
+
+			verifyStateIndexedInteger(result, gl, m_queryTarget, ndxA, 0, m_verifierType);
+		}
+		{
+			const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Indexed", "After setting with glBindBufferRange");
+
+			gl.glBindBufferRange(m_bufferTarget, ndxB, *bufferB, 0, 8);
+			GLU_EXPECT_NO_ERROR(gl.glGetError(), "bind buf");
+
+			verifyStateIndexedInteger(result, gl, m_queryTarget, ndxB, 8, m_verifierType);
+		}
+		if (ndxA != ndxB)
+		{
+			const tcu::ScopedLogSection	section(m_testCtx.getLog(), "DifferentStates", "Original state did not change");
+
+			verifyStateIndexedInteger(result, gl, m_queryTarget, ndxA, 0, m_verifierType);
+		}
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class ImageBindingNameCase : public TestCase
+{
+public:
+						ImageBindingNameCase	(Context& context, const char* name, const char* desc, QueryType verifierType);
+
+private:
+	IterateResult		iterate					(void);
+
+	const QueryType		m_verifierType;
+};
+
+ImageBindingNameCase::ImageBindingNameCase (Context& context, const char* name, const char* desc, QueryType verifierType)
+	: TestCase			(context, name, desc)
+	, m_verifierType	(verifierType)
+{
+}
+
+ImageBindingNameCase::IterateResult ImageBindingNameCase::iterate (void)
+{
+	glu::CallLogWrapper		gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result		(m_testCtx.getLog(), " // ERROR: ");
+	int						maxImages	= -1;
+
+	gl.enableLogging(true);
+
+	gl.glGetIntegerv(GL_MAX_IMAGE_UNITS, &maxImages);
+	GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetIntegerv");
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial value");
+
+		for (int ndx = 0; ndx < maxImages; ++ndx)
+			verifyStateIndexedInteger(result, gl, GL_IMAGE_BINDING_NAME, ndx, 0, m_verifierType);
+	}
+
+	{
+		const tcu::ScopedLogSection	superSection	(m_testCtx.getLog(), "AfterSetting", "After setting");
+		glu::Texture				textureA		(m_context.getRenderContext());
+		glu::Texture				textureB		(m_context.getRenderContext());
+		const int					ndxA			= 0;
+		const int					ndxB			= maxImages / 2;
+
+		gl.glBindTexture(GL_TEXTURE_2D, *textureA);
+		gl.glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 32, 32);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen tex");
+
+		gl.glBindImageTexture(ndxA, *textureA, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8UI);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "bind unit");
+
+		gl.glBindTexture(GL_TEXTURE_2D_ARRAY, *textureB);
+		gl.glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 32, 32, 4);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen tex");
+
+		gl.glBindImageTexture(ndxB, *textureB, 0, GL_FALSE, 2, GL_READ_ONLY, GL_RGBA8UI);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "bind unit");
+
+		verifyStateIndexedInteger(result, gl, GL_IMAGE_BINDING_NAME, ndxA, *textureA, m_verifierType);
+		verifyStateIndexedInteger(result, gl, GL_IMAGE_BINDING_NAME, ndxB, *textureB, m_verifierType);
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class ImageBindingLevelCase : public TestCase
+{
+public:
+						ImageBindingLevelCase	(Context& context, const char* name, const char* desc, QueryType verifierType);
+
+private:
+	IterateResult		iterate					(void);
+
+	const QueryType		m_verifierType;
+};
+
+ImageBindingLevelCase::ImageBindingLevelCase (Context& context, const char* name, const char* desc, QueryType verifierType)
+	: TestCase			(context, name, desc)
+	, m_verifierType	(verifierType)
+{
+}
+
+ImageBindingLevelCase::IterateResult ImageBindingLevelCase::iterate (void)
+{
+	glu::CallLogWrapper		gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result		(m_testCtx.getLog(), " // ERROR: ");
+	int						maxImages	= -1;
+
+	gl.enableLogging(true);
+
+	gl.glGetIntegerv(GL_MAX_IMAGE_UNITS, &maxImages);
+	GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetIntegerv");
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial value");
+
+		for (int ndx = 0; ndx < maxImages; ++ndx)
+			verifyStateIndexedInteger(result, gl, GL_IMAGE_BINDING_LEVEL, ndx, 0, m_verifierType);
+	}
+
+	{
+		const tcu::ScopedLogSection	superSection	(m_testCtx.getLog(), "AfterSetting", "After setting");
+		glu::Texture				textureA		(m_context.getRenderContext());
+		glu::Texture				textureB		(m_context.getRenderContext());
+		const int					ndxA			= 0;
+		const int					ndxB			= maxImages / 2;
+
+		gl.glBindTexture(GL_TEXTURE_2D, *textureA);
+		gl.glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 32, 32);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen tex");
+
+		gl.glBindImageTexture(ndxA, *textureA, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8UI);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "bind unit");
+
+		gl.glBindTexture(GL_TEXTURE_2D, *textureB);
+		gl.glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 32, 32);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen tex");
+
+		gl.glBindImageTexture(ndxB, *textureB, 2, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8UI);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "bind unit");
+
+		verifyStateIndexedInteger(result, gl, GL_IMAGE_BINDING_LEVEL, ndxA, 0, m_verifierType);
+		verifyStateIndexedInteger(result, gl, GL_IMAGE_BINDING_LEVEL, ndxB, 2, m_verifierType);
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class ImageBindingLayeredCase : public TestCase
+{
+public:
+						ImageBindingLayeredCase	(Context& context, const char* name, const char* desc, QueryType verifierType);
+
+private:
+	IterateResult		iterate					(void);
+
+	const QueryType		m_verifierType;
+};
+
+ImageBindingLayeredCase::ImageBindingLayeredCase (Context& context, const char* name, const char* desc, QueryType verifierType)
+	: TestCase			(context, name, desc)
+	, m_verifierType	(verifierType)
+{
+}
+
+ImageBindingLayeredCase::IterateResult ImageBindingLayeredCase::iterate (void)
+{
+	glu::CallLogWrapper		gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result		(m_testCtx.getLog(), " // ERROR: ");
+	int						maxImages	= -1;
+
+	gl.enableLogging(true);
+
+	gl.glGetIntegerv(GL_MAX_IMAGE_UNITS, &maxImages);
+	GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetIntegerv");
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial value");
+
+		for (int ndx = 0; ndx < maxImages; ++ndx)
+			verifyStateIndexedBoolean(result, gl, GL_IMAGE_BINDING_LAYERED, ndx, false, m_verifierType);
+	}
+
+	{
+		const tcu::ScopedLogSection	superSection	(m_testCtx.getLog(), "AfterSetting", "After setting");
+		glu::Texture				textureA		(m_context.getRenderContext());
+		glu::Texture				textureB		(m_context.getRenderContext());
+		const int					ndxA			= 0;
+		const int					ndxB			= maxImages / 2;
+
+		gl.glBindTexture(GL_TEXTURE_2D, *textureA);
+		gl.glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 32, 32);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen tex");
+
+		gl.glBindImageTexture(ndxA, *textureA, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8UI);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "bind unit");
+
+		gl.glBindTexture(GL_TEXTURE_2D_ARRAY, *textureB);
+		gl.glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 32, 32, 4);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen tex");
+
+		gl.glBindImageTexture(ndxB, *textureB, 0, GL_TRUE, 2, GL_READ_ONLY, GL_RGBA8UI);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "bind unit");
+
+		verifyStateIndexedBoolean(result, gl, GL_IMAGE_BINDING_LAYERED, ndxA, false, m_verifierType);
+		verifyStateIndexedBoolean(result, gl, GL_IMAGE_BINDING_LAYERED, ndxB, true, m_verifierType);
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class ImageBindingLayerCase : public TestCase
+{
+public:
+						ImageBindingLayerCase	(Context& context, const char* name, const char* desc, QueryType verifierType);
+
+private:
+	IterateResult		iterate					(void);
+
+	const QueryType		m_verifierType;
+};
+
+ImageBindingLayerCase::ImageBindingLayerCase (Context& context, const char* name, const char* desc, QueryType verifierType)
+	: TestCase			(context, name, desc)
+	, m_verifierType	(verifierType)
+{
+}
+
+ImageBindingLayerCase::IterateResult ImageBindingLayerCase::iterate (void)
+{
+	glu::CallLogWrapper		gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result		(m_testCtx.getLog(), " // ERROR: ");
+	int						maxImages	= -1;
+
+	gl.enableLogging(true);
+
+	gl.glGetIntegerv(GL_MAX_IMAGE_UNITS, &maxImages);
+	GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetIntegerv");
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial value");
+
+		for (int ndx = 0; ndx < maxImages; ++ndx)
+			verifyStateIndexedInteger(result, gl, GL_IMAGE_BINDING_LAYER, ndx, 0, m_verifierType);
+	}
+
+	{
+		const tcu::ScopedLogSection	superSection	(m_testCtx.getLog(), "AfterSetting", "After setting");
+		glu::Texture				textureA		(m_context.getRenderContext());
+		glu::Texture				textureB		(m_context.getRenderContext());
+		const int					ndxA			= 0;
+		const int					ndxB			= maxImages / 2;
+
+		gl.glBindTexture(GL_TEXTURE_2D, *textureA);
+		gl.glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 32, 32);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen tex");
+
+		gl.glBindImageTexture(ndxA, *textureA, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8UI);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "bind unit");
+
+		gl.glBindTexture(GL_TEXTURE_2D_ARRAY, *textureB);
+		gl.glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 32, 32, 4);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen tex");
+
+		gl.glBindImageTexture(ndxB, *textureB, 0, GL_TRUE, 2, GL_READ_ONLY, GL_RGBA8UI);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "bind unit");
+
+		verifyStateIndexedInteger(result, gl, GL_IMAGE_BINDING_LAYER, ndxA, 0, m_verifierType);
+		verifyStateIndexedInteger(result, gl, GL_IMAGE_BINDING_LAYER, ndxB, 2, m_verifierType);
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class ImageBindingAccessCase : public TestCase
+{
+public:
+						ImageBindingAccessCase	(Context& context, const char* name, const char* desc, QueryType verifierType);
+
+private:
+	IterateResult		iterate					(void);
+
+	const QueryType		m_verifierType;
+};
+
+ImageBindingAccessCase::ImageBindingAccessCase (Context& context, const char* name, const char* desc, QueryType verifierType)
+	: TestCase			(context, name, desc)
+	, m_verifierType	(verifierType)
+{
+}
+
+ImageBindingAccessCase::IterateResult ImageBindingAccessCase::iterate (void)
+{
+	glu::CallLogWrapper		gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result		(m_testCtx.getLog(), " // ERROR: ");
+	int						maxImages	= -1;
+
+	gl.enableLogging(true);
+
+	gl.glGetIntegerv(GL_MAX_IMAGE_UNITS, &maxImages);
+	GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetIntegerv");
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial value");
+
+		for (int ndx = 0; ndx < maxImages; ++ndx)
+			verifyStateIndexedInteger(result, gl, GL_IMAGE_BINDING_ACCESS, ndx, GL_READ_ONLY, m_verifierType);
+	}
+
+	{
+		const tcu::ScopedLogSection	superSection	(m_testCtx.getLog(), "AfterSetting", "After setting");
+		glu::Texture				textureA		(m_context.getRenderContext());
+		glu::Texture				textureB		(m_context.getRenderContext());
+		const int					ndxA			= 0;
+		const int					ndxB			= maxImages / 2;
+
+		gl.glBindTexture(GL_TEXTURE_2D, *textureA);
+		gl.glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 32, 32);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen tex");
+
+		gl.glBindImageTexture(ndxA, *textureA, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8UI);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "bind unit");
+
+		gl.glBindTexture(GL_TEXTURE_2D_ARRAY, *textureB);
+		gl.glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 32, 32, 4);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen tex");
+
+		gl.glBindImageTexture(ndxB, *textureB, 0, GL_TRUE, 2, GL_READ_WRITE, GL_RGBA8UI);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "bind unit");
+
+		verifyStateIndexedInteger(result, gl, GL_IMAGE_BINDING_ACCESS, ndxA, GL_READ_ONLY, m_verifierType);
+		verifyStateIndexedInteger(result, gl, GL_IMAGE_BINDING_ACCESS, ndxB, GL_READ_WRITE, m_verifierType);
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class ImageBindingFormatCase : public TestCase
+{
+public:
+						ImageBindingFormatCase	(Context& context, const char* name, const char* desc, QueryType verifierType);
+
+private:
+	IterateResult		iterate					(void);
+
+	const QueryType		m_verifierType;
+};
+
+ImageBindingFormatCase::ImageBindingFormatCase (Context& context, const char* name, const char* desc, QueryType verifierType)
+	: TestCase			(context, name, desc)
+	, m_verifierType	(verifierType)
+{
+}
+
+ImageBindingFormatCase::IterateResult ImageBindingFormatCase::iterate (void)
+{
+	glu::CallLogWrapper		gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result		(m_testCtx.getLog(), " // ERROR: ");
+	int						maxImages	= -1;
+
+	gl.enableLogging(true);
+
+	gl.glGetIntegerv(GL_MAX_IMAGE_UNITS, &maxImages);
+	GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetIntegerv");
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial value");
+
+		for (int ndx = 0; ndx < maxImages; ++ndx)
+			verifyStateIndexedInteger(result, gl, GL_IMAGE_BINDING_FORMAT, ndx, GL_R32UI, m_verifierType);
+	}
+
+	{
+		const tcu::ScopedLogSection	superSection	(m_testCtx.getLog(), "AfterSetting", "After setting");
+		glu::Texture				textureA		(m_context.getRenderContext());
+		glu::Texture				textureB		(m_context.getRenderContext());
+		const int					ndxA			= 0;
+		const int					ndxB			= maxImages / 2;
+
+		gl.glBindTexture(GL_TEXTURE_2D, *textureA);
+		gl.glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 32, 32);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen tex");
+
+		gl.glBindImageTexture(ndxA, *textureA, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8UI);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "bind unit");
+
+		gl.glBindTexture(GL_TEXTURE_2D_ARRAY, *textureB);
+		gl.glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, 32, 32, 4);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen tex");
+
+		gl.glBindImageTexture(ndxB, *textureB, 0, GL_TRUE, 2, GL_READ_WRITE, GL_R32F);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "bind unit");
+
+		verifyStateIndexedInteger(result, gl, GL_IMAGE_BINDING_FORMAT, ndxA, GL_RGBA8UI, m_verifierType);
+		verifyStateIndexedInteger(result, gl, GL_IMAGE_BINDING_FORMAT, ndxB, GL_R32F, m_verifierType);
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+} // anonymous
+
+IndexedStateQueryTests::IndexedStateQueryTests (Context& context)
+	: TestCaseGroup(context, "indexed", "Indexed state queries")
+{
+}
+
+IndexedStateQueryTests::~IndexedStateQueryTests (void)
+{
+}
+
+void IndexedStateQueryTests::init (void)
+{
+	static const QueryType verifiers[] = { QUERY_INDEXED_BOOLEAN, QUERY_INDEXED_INTEGER, QUERY_INDEXED_INTEGER64 };
+
+#define FOR_EACH_VERIFIER(X) \
+	for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(verifiers); ++verifierNdx)	\
+	{																						\
+		const char* verifierSuffix = getVerifierSuffix(verifiers[verifierNdx]);				\
+		const QueryType verifier = verifiers[verifierNdx];									\
+		this->addChild(X);																	\
+	}
+
+	FOR_EACH_VERIFIER(new SampleMaskCase			(m_context, (std::string() + "sample_mask_value_" + verifierSuffix).c_str(), 				"Test SAMPLE_MASK_VALUE", verifier))
+
+	FOR_EACH_VERIFIER(new MinValueIndexed3Case		(m_context, (std::string() + "max_compute_work_group_count_" + verifierSuffix).c_str(),		"Test MAX_COMPUTE_WORK_GROUP_COUNT",	GL_MAX_COMPUTE_WORK_GROUP_COUNT,	tcu::IVec3(65535,65535,65535),	verifier))
+	FOR_EACH_VERIFIER(new MinValueIndexed3Case		(m_context, (std::string() + "max_compute_work_group_size_" + verifierSuffix).c_str(),		"Test MAX_COMPUTE_WORK_GROUP_SIZE",		GL_MAX_COMPUTE_WORK_GROUP_SIZE,		tcu::IVec3(128, 128, 64),		verifier))
+
+	FOR_EACH_VERIFIER(new BufferBindingCase			(m_context, (std::string() + "atomic_counter_buffer_binding_" + verifierSuffix).c_str(),	"Test ATOMIC_COUNTER_BUFFER_BINDING",	GL_ATOMIC_COUNTER_BUFFER_BINDING,	GL_ATOMIC_COUNTER_BUFFER,	GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, verifier))
+	FOR_EACH_VERIFIER(new BufferStartCase			(m_context, (std::string() + "atomic_counter_buffer_start_" + verifierSuffix).c_str(),		"Test ATOMIC_COUNTER_BUFFER_START",		GL_ATOMIC_COUNTER_BUFFER_START,		GL_ATOMIC_COUNTER_BUFFER,	GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS,	verifier))
+	FOR_EACH_VERIFIER(new BufferSizeCase			(m_context, (std::string() + "atomic_counter_buffer_size_" + verifierSuffix).c_str(),		"Test ATOMIC_COUNTER_BUFFER_SIZE",		GL_ATOMIC_COUNTER_BUFFER_SIZE,		GL_ATOMIC_COUNTER_BUFFER,	GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS,	verifier))
+
+	FOR_EACH_VERIFIER(new BufferBindingCase			(m_context, (std::string() + "shader_storager_buffer_binding_" + verifierSuffix).c_str(),	"Test SHADER_STORAGE_BUFFER_BINDING",	GL_SHADER_STORAGE_BUFFER_BINDING,	GL_SHADER_STORAGE_BUFFER,	GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS,	verifier))
+	FOR_EACH_VERIFIER(new BufferStartCase			(m_context, (std::string() + "shader_storager_buffer_start_" + verifierSuffix).c_str(),		"Test SHADER_STORAGE_BUFFER_START",		GL_SHADER_STORAGE_BUFFER_START,		GL_SHADER_STORAGE_BUFFER,	GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS,	verifier))
+	FOR_EACH_VERIFIER(new BufferSizeCase			(m_context, (std::string() + "shader_storager_buffer_size_" + verifierSuffix).c_str(),		"Test SHADER_STORAGE_BUFFER_SIZE",		GL_SHADER_STORAGE_BUFFER_SIZE,		GL_SHADER_STORAGE_BUFFER,	GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS,	verifier))
+
+	FOR_EACH_VERIFIER(new ImageBindingNameCase		(m_context, (std::string() + "image_binding_name_" + verifierSuffix).c_str(),				"Test IMAGE_BINDING_NAME",				verifier))
+	FOR_EACH_VERIFIER(new ImageBindingLevelCase		(m_context, (std::string() + "image_binding_level_" + verifierSuffix).c_str(),				"Test IMAGE_BINDING_LEVEL",				verifier))
+	FOR_EACH_VERIFIER(new ImageBindingLayeredCase	(m_context, (std::string() + "image_binding_layered_" + verifierSuffix).c_str(),			"Test IMAGE_BINDING_LAYERED",			verifier))
+	FOR_EACH_VERIFIER(new ImageBindingLayerCase		(m_context, (std::string() + "image_binding_layer_" + verifierSuffix).c_str(),				"Test IMAGE_BINDING_LAYER",				verifier))
+	FOR_EACH_VERIFIER(new ImageBindingAccessCase	(m_context, (std::string() + "image_binding_access_" + verifierSuffix).c_str(),				"Test IMAGE_BINDING_ACCESS",			verifier))
+	FOR_EACH_VERIFIER(new ImageBindingFormatCase	(m_context, (std::string() + "image_binding_format_" + verifierSuffix).c_str(),				"Test IMAGE_BINDING_FORMAT",			verifier))
+
+#undef FOR_EACH_VERIFIER
+}
+
+} // Functional
+} // gles31
+} // deqp
diff --git a/modules/gles31/functional/es31fIndexedStateQueryTests.hpp b/modules/gles31/functional/es31fIndexedStateQueryTests.hpp
new file mode 100644
index 0000000..63ec49e
--- /dev/null
+++ b/modules/gles31/functional/es31fIndexedStateQueryTests.hpp
@@ -0,0 +1,53 @@
+#ifndef _ES31FINDEXEDSTATEQUERYTESTS_HPP
+#define _ES31FINDEXEDSTATEQUERYTESTS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Indexed state query tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tes31TestCase.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+
+class IndexedStateQueryTests : public TestCaseGroup
+{
+public:
+							IndexedStateQueryTests	(Context& context);
+							~IndexedStateQueryTests	(void);
+
+	void					init					(void);
+
+private:
+							IndexedStateQueryTests	(const IndexedStateQueryTests& other);
+	IndexedStateQueryTests&	operator=				(const IndexedStateQueryTests& other);
+};
+
+} // Functional
+} // gles31
+} // deqp
+
+#endif // _ES31FINDEXEDSTATEQUERYTESTS_HPP
diff --git a/modules/gles31/functional/es31fIntegerStateQueryTests.cpp b/modules/gles31/functional/es31fIntegerStateQueryTests.cpp
index 47b8b3a..182b42f 100644
--- a/modules/gles31/functional/es31fIntegerStateQueryTests.cpp
+++ b/modules/gles31/functional/es31fIntegerStateQueryTests.cpp
@@ -26,10 +26,14 @@
 #include "gluRenderContext.hpp"
 #include "gluCallLogWrapper.hpp"
 #include "gluContextInfo.hpp"
+#include "gluObjectWrapper.hpp"
+#include "gluShaderProgram.hpp"
+#include "gluStrUtil.hpp"
 #include "glwFunctions.hpp"
 #include "glwEnums.hpp"
-#include "deRandom.hpp"
 #include "glsStateQueryUtil.hpp"
+#include "deRandom.hpp"
+#include "deStringUtil.hpp"
 
 namespace deqp
 {
@@ -40,414 +44,35 @@
 namespace
 {
 
-using gls::StateQueryUtil::StateQueryMemoryWriteGuard;
+using namespace gls::StateQueryUtil;
 
-enum VerifierType
-{
-	VERIFIER_GETBOOLEAN = 0,
-	VERIFIER_GETINTEGER,
-	VERIFIER_GETINTEGER64,
-	VERIFIER_GETFLOAT
-};
-
-static const char* getVerifierSuffix (VerifierType type)
+static const char* getVerifierSuffix (QueryType type)
 {
 	switch (type)
 	{
-		case VERIFIER_GETBOOLEAN:	return "getboolean";
-		case VERIFIER_GETINTEGER:	return "getinteger";
-		case VERIFIER_GETINTEGER64:	return "getinteger64";
-		case VERIFIER_GETFLOAT:		return "getfloat";
+		case QUERY_BOOLEAN:		return "getboolean";
+		case QUERY_INTEGER:		return "getinteger";
+		case QUERY_INTEGER64:	return "getinteger64";
+		case QUERY_FLOAT:		return "getfloat";
 		default:
 			DE_ASSERT(DE_FALSE);
 			return DE_NULL;
 	}
 }
 
-static bool verifyValue (glu::CallLogWrapper& gl, glw::GLenum target, int refValue, VerifierType type)
-{
-	switch (type)
-	{
-		case VERIFIER_GETBOOLEAN:
-		{
-			StateQueryMemoryWriteGuard<glw::GLboolean> value;
-			gl.glGetBooleanv(target, &value);
-
-			GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetBooleanv");
-
-			if (value.isUndefined())
-			{
-				gl.getLog() << tcu::TestLog::Message << "Get* did not return a value." << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else if (value != ((refValue == 0) ? (GL_FALSE) : (GL_TRUE)))
-			{
-				gl.getLog() << tcu::TestLog::Message << "Expected " << ((refValue == 0) ? (GL_FALSE) : (GL_TRUE)) << ", got " << ((value == 0) ? (GL_FALSE) : (GL_TRUE)) << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else
-				return true;
-		}
-
-		case VERIFIER_GETINTEGER:
-		{
-			StateQueryMemoryWriteGuard<glw::GLint> value;
-			gl.glGetIntegerv(target, &value);
-
-			GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetIntegerv");
-
-			if (value.isUndefined())
-			{
-				gl.getLog() << tcu::TestLog::Message << "Get* did not return a value." << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else if (value != refValue)
-			{
-				gl.getLog() << tcu::TestLog::Message << "Expected " << refValue << ", got " << value << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else
-				return true;
-		}
-
-		case VERIFIER_GETINTEGER64:
-		{
-			StateQueryMemoryWriteGuard<glw::GLint64> value;
-			gl.glGetInteger64v(target, &value);
-
-			GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetInteger64v");
-
-			if (value.isUndefined())
-			{
-				gl.getLog() << tcu::TestLog::Message << "Get* did not return a value." << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else if (value != (glw::GLint64)refValue)
-			{
-				gl.getLog() << tcu::TestLog::Message << "Expected " << refValue << ", got " << value << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else
-				return true;
-		}
-
-		case VERIFIER_GETFLOAT:
-		{
-			StateQueryMemoryWriteGuard<glw::GLfloat> value;
-			gl.glGetFloatv(target, &value);
-
-			GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetFloatv");
-
-			if (value.isUndefined())
-			{
-				gl.getLog() << tcu::TestLog::Message << "Get* did not return a value." << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else if (value != (glw::GLfloat)refValue)
-			{
-				gl.getLog() << tcu::TestLog::Message << "Expected " << refValue << ", got " << value << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else
-				return true;
-		}
-
-		default:
-			DE_ASSERT(DE_FALSE);
-			return DE_NULL;
-	}
-}
-
-static bool verifyMinValue (glu::CallLogWrapper& gl, glw::GLenum target, int minValue, VerifierType type)
-{
-	switch (type)
-	{
-		case VERIFIER_GETBOOLEAN:
-		{
-			StateQueryMemoryWriteGuard<glw::GLboolean> value;
-			gl.glGetBooleanv(target, &value);
-
-			GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetBooleanv");
-
-			if (value.isUndefined())
-			{
-				gl.getLog() << tcu::TestLog::Message << "Get* did not return a value." << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else if (minValue > 0 && value == GL_FALSE)
-			{
-				gl.getLog() << tcu::TestLog::Message << "Expected GL_TRUE, got GL_FALSE" << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else
-				return true;
-		}
-
-		case VERIFIER_GETINTEGER:
-		{
-			StateQueryMemoryWriteGuard<glw::GLint> value;
-			gl.glGetIntegerv(target, &value);
-
-			GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetIntegerv");
-
-			if (value.isUndefined())
-			{
-				gl.getLog() << tcu::TestLog::Message << "Get* did not return a value." << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else if (value < minValue)
-			{
-				gl.getLog() << tcu::TestLog::Message << "Expected greater or equal to " << minValue << ", got " << value << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else
-				return true;
-		}
-
-		case VERIFIER_GETINTEGER64:
-		{
-			StateQueryMemoryWriteGuard<glw::GLint64> value;
-			gl.glGetInteger64v(target, &value);
-
-			GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetInteger64v");
-
-			if (value.isUndefined())
-			{
-				gl.getLog() << tcu::TestLog::Message << "Get* did not return a value." << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else if (value < minValue)
-			{
-				gl.getLog() << tcu::TestLog::Message << "Expected greater or equal to " << minValue << ", got " << value << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else
-				return true;
-		}
-
-		case VERIFIER_GETFLOAT:
-		{
-			StateQueryMemoryWriteGuard<glw::GLfloat> value;
-			gl.glGetFloatv(target, &value);
-
-			GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetFloatv");
-
-			if (value.isUndefined())
-			{
-				gl.getLog() << tcu::TestLog::Message << "Get* did not return a value." << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else if (value < minValue)
-			{
-				gl.getLog() << tcu::TestLog::Message << "Expected greater or equal to " << minValue << ", got " << value << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else
-				return true;
-		}
-
-		default:
-			DE_ASSERT(DE_FALSE);
-			return DE_NULL;
-	}
-}
-
-static bool verifyMaxValue (glu::CallLogWrapper& gl, glw::GLenum target, int maxValue, VerifierType type)
-{
-	switch (type)
-	{
-		case VERIFIER_GETBOOLEAN:
-		{
-			StateQueryMemoryWriteGuard<glw::GLboolean> value;
-			gl.glGetBooleanv(target, &value);
-
-			GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetBooleanv");
-
-			if (value.isUndefined())
-			{
-				gl.getLog() << tcu::TestLog::Message << "Get* did not return a value." << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else if (maxValue < 0 && value == GL_FALSE)
-			{
-				gl.getLog() << tcu::TestLog::Message << "Expected GL_TRUE, got GL_FALSE" << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else
-				return true;
-		}
-
-		case VERIFIER_GETINTEGER:
-		{
-			StateQueryMemoryWriteGuard<glw::GLint> value;
-			gl.glGetIntegerv(target, &value);
-
-			GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetIntegerv");
-
-			if (value.isUndefined())
-			{
-				gl.getLog() << tcu::TestLog::Message << "Get* did not return a value." << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else if (value > maxValue)
-			{
-				gl.getLog() << tcu::TestLog::Message << "Expected less or equal to " << maxValue << ", got " << value << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else
-				return true;
-		}
-
-		case VERIFIER_GETINTEGER64:
-		{
-			StateQueryMemoryWriteGuard<glw::GLint64> value;
-			gl.glGetInteger64v(target, &value);
-
-			GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetInteger64v");
-
-			if (value.isUndefined())
-			{
-				gl.getLog() << tcu::TestLog::Message << "Get* did not return a value." << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else if (value > maxValue)
-			{
-				gl.getLog() << tcu::TestLog::Message << "Expected less or equal to " << maxValue << ", got " << value << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else
-				return true;
-		}
-
-		case VERIFIER_GETFLOAT:
-		{
-			StateQueryMemoryWriteGuard<glw::GLfloat> value;
-			gl.glGetFloatv(target, &value);
-
-			GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetFloatv");
-
-			if (value.isUndefined())
-			{
-				gl.getLog() << tcu::TestLog::Message << "Get* did not return a value." << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else if (value > maxValue)
-			{
-				gl.getLog() << tcu::TestLog::Message << "Expected less or equal to " << maxValue << ", got " << value << tcu::TestLog::EndMessage;
-				return false;
-			}
-			else
-				return true;
-		}
-
-		default:
-			DE_ASSERT(DE_FALSE);
-			return DE_NULL;
-	}
-}
-
-class SampleMaskCase : public TestCase
-{
-public:
-					SampleMaskCase	(Context& context, const char* name, const char* desc);
-
-private:
-	void			init			(void);
-	IterateResult	iterate			(void);
-
-	int				m_maxSampleMaskWords;
-};
-
-SampleMaskCase::SampleMaskCase (Context& context, const char* name, const char* desc)
-	: TestCase				(context, name, desc)
-	, m_maxSampleMaskWords	(-1)
-{
-}
-
-void SampleMaskCase::init (void)
-{
-	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
-
-	gl.getIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &m_maxSampleMaskWords);
-	m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_SAMPLE_MASK_WORDS = " << m_maxSampleMaskWords << tcu::TestLog::EndMessage;
-}
-
-SampleMaskCase::IterateResult SampleMaskCase::iterate (void)
-{
-	glu::CallLogWrapper gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
-	bool				error	= false;
-
-	gl.enableLogging(true);
-
-	// mask word count ok?
-	if (m_maxSampleMaskWords <= 0)
-	{
-		m_testCtx.getLog() << tcu::TestLog::Message << "Minimum value of GL_MAX_SAMPLE_MASK_WORDS is 1. Got " << m_maxSampleMaskWords << tcu::TestLog::EndMessage;
-		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid limit value");
-		return STOP;
-	}
-
-	// initial values
-	{
-		const tcu::ScopedLogSection section(m_testCtx.getLog(), "initial", "Initial values");
-
-		for (int ndx = 0; ndx < m_maxSampleMaskWords; ++ndx)
-		{
-			glw::GLint word = 0;
-			gl.glGetIntegeri_v(GL_SAMPLE_MASK_VALUE, ndx, &word);
-
-			if (word != -1)
-			{
-				m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Expected all bits set (-1), got " << word << tcu::TestLog::EndMessage;
-				error = true;
-			}
-		}
-	}
-
-	// random masks
-	{
-		const int					numRandomTest	= 20;
-		const tcu::ScopedLogSection section			(m_testCtx.getLog(), "random", "Random values");
-		de::Random					rnd				(0x4312);
-
-		for (int testNdx = 0; testNdx < numRandomTest; ++testNdx)
-		{
-			const glw::GLint	maskIndex		= (glw::GLint)(rnd.getUint32() % m_maxSampleMaskWords);
-			glw::GLint			mask			= (glw::GLint)(rnd.getUint32());
-			glw::GLint			queriedMask		= 0;
-
-			gl.glSampleMaski(maskIndex, mask);
-			gl.glGetIntegeri_v(GL_SAMPLE_MASK_VALUE, maskIndex, &queriedMask);
-
-			if (mask != queriedMask)
-			{
-				m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Expected " << mask << ", got " << queriedMask << tcu::TestLog::EndMessage;
-				error = true;
-			}
-		}
-	}
-
-	if (!error)
-		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
-	else
-		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid mask value");
-
-	return STOP;
-}
-
 class MaxSamplesCase : public TestCase
 {
 public:
-						MaxSamplesCase	(Context& context, const char* name, const char* desc, glw::GLenum target, int minValue, VerifierType verifierType);
+						MaxSamplesCase	(Context& context, const char* name, const char* desc, glw::GLenum target, int minValue, QueryType verifierType);
 private:
 	IterateResult		iterate			(void);
 
 	const glw::GLenum	m_target;
 	const int			m_minValue;
-	const VerifierType	m_verifierType;
+	const QueryType		m_verifierType;
 };
 
-MaxSamplesCase::MaxSamplesCase (Context& context, const char* name, const char* desc, glw::GLenum target, int minValue, VerifierType verifierType)
+MaxSamplesCase::MaxSamplesCase (Context& context, const char* name, const char* desc, glw::GLenum target, int minValue, QueryType verifierType)
 	: TestCase			(context, name, desc)
 	, m_target			(target)
 	, m_minValue		(minValue)
@@ -457,31 +82,30 @@
 
 MaxSamplesCase::IterateResult MaxSamplesCase::iterate (void)
 {
-	glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	glu::CallLogWrapper 	gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
 
 	gl.enableLogging(true);
+	verifyStateIntegerMin(result, gl, m_target, m_minValue, m_verifierType);
 
-	if (verifyMinValue(gl, m_target, m_minValue, m_verifierType))
-		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
-	else
-		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Value not in legal range");
+	result.setTestContextResult(m_testCtx);
 	return STOP;
 }
 
 class TexBindingCase : public TestCase
 {
 public:
-						TexBindingCase	(Context& context, const char* name, const char* desc, glw::GLenum texTarget, glw::GLenum bindTarget, VerifierType verifierType);
+						TexBindingCase	(Context& context, const char* name, const char* desc, glw::GLenum texTarget, glw::GLenum bindTarget, QueryType verifierType);
 private:
 	void				init			(void);
 	IterateResult		iterate			(void);
 
 	const glw::GLenum	m_texTarget;
 	const glw::GLenum	m_bindTarget;
-	const VerifierType	m_verifierType;
+	const QueryType		m_verifierType;
 };
 
-TexBindingCase::TexBindingCase (Context& context, const char* name, const char* desc, glw::GLenum texTarget, glw::GLenum bindTarget, VerifierType verifierType)
+TexBindingCase::TexBindingCase (Context& context, const char* name, const char* desc, glw::GLenum texTarget, glw::GLenum bindTarget, QueryType verifierType)
 	: TestCase			(context, name, desc)
 	, m_texTarget		(texTarget)
 	, m_bindTarget		(bindTarget)
@@ -497,8 +121,8 @@
 
 TexBindingCase::IterateResult TexBindingCase::iterate (void)
 {
-	glu::CallLogWrapper gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
-	bool				allOk	= true;
+	glu::CallLogWrapper 	gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
 
 	gl.enableLogging(true);
 
@@ -506,7 +130,7 @@
 	{
 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "initial", "Initial value");
 
-		allOk &= verifyValue(gl, m_bindTarget, 0, m_verifierType);
+		verifyStateInteger(result, gl, m_bindTarget, 0, m_verifierType);
 	}
 
 	// bind
@@ -519,7 +143,7 @@
 		gl.glBindTexture(m_texTarget, texture);
 		GLU_EXPECT_NO_ERROR(gl.glGetError(), "bind texture");
 
-		allOk &= verifyValue(gl, m_bindTarget, texture, m_verifierType);
+		verifyStateInteger(result, gl, m_bindTarget, texture, m_verifierType);
 
 		gl.glDeleteTextures(1, &texture);
 	}
@@ -528,29 +152,26 @@
 	{
 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "bind", "After delete");
 
-		allOk &= verifyValue(gl, m_bindTarget, 0, m_verifierType);
+		verifyStateInteger(result, gl, m_bindTarget, 0, m_verifierType);
 	}
 
-	if (allOk)
-		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
-	else
-		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid value");
+	result.setTestContextResult(m_testCtx);
 	return STOP;
 }
 
 class MinimumValueCase : public TestCase
 {
 public:
-						MinimumValueCase	(Context& context, const char* name, const char* desc, glw::GLenum target, int minValue, VerifierType verifierType);
+						MinimumValueCase	(Context& context, const char* name, const char* desc, glw::GLenum target, int minValue, QueryType verifierType);
 private:
 	IterateResult		iterate				(void);
 
 	const glw::GLenum	m_target;
 	const int			m_minValue;
-	const VerifierType	m_verifierType;
+	const QueryType		m_verifierType;
 };
 
-MinimumValueCase::MinimumValueCase (Context& context, const char* name, const char* desc, glw::GLenum target, int minValue, VerifierType verifierType)
+MinimumValueCase::MinimumValueCase (Context& context, const char* name, const char* desc, glw::GLenum target, int minValue, QueryType verifierType)
 	: TestCase			(context, name, desc)
 	, m_target			(target)
 	, m_minValue		(minValue)
@@ -560,30 +181,29 @@
 
 MinimumValueCase::IterateResult MinimumValueCase::iterate (void)
 {
-	glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
 
 	gl.enableLogging(true);
+	verifyStateIntegerMin(result, gl, m_target, m_minValue, m_verifierType);
 
-	if (verifyMinValue(gl, m_target, m_minValue, m_verifierType))
-		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
-	else
-		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid value");
+	result.setTestContextResult(m_testCtx);
 	return STOP;
 }
 
 class AlignmentCase : public TestCase
 {
 public:
-						AlignmentCase	(Context& context, const char* name, const char* desc, glw::GLenum target, int minValue, VerifierType verifierType);
+						AlignmentCase	(Context& context, const char* name, const char* desc, glw::GLenum target, int minValue, QueryType verifierType);
 private:
 	IterateResult		iterate			(void);
 
 	const glw::GLenum	m_target;
 	const int			m_minValue;
-	const VerifierType	m_verifierType;
+	const QueryType		m_verifierType;
 };
 
-AlignmentCase::AlignmentCase (Context& context, const char* name, const char* desc, glw::GLenum target, int minValue, VerifierType verifierType)
+AlignmentCase::AlignmentCase (Context& context, const char* name, const char* desc, glw::GLenum target, int minValue, QueryType verifierType)
 	: TestCase			(context, name, desc)
 	, m_target			(target)
 	, m_minValue		(minValue)
@@ -593,14 +213,302 @@
 
 AlignmentCase::IterateResult AlignmentCase::iterate (void)
 {
-	glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
+
+	gl.enableLogging(true);
+	verifyStateIntegerMax(result, gl, m_target, m_minValue, m_verifierType);
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class BufferBindingCase : public TestCase
+{
+public:
+						BufferBindingCase	(Context& context, const char* name, const char* desc, glw::GLenum queryTarget, glw::GLenum bindingPoint, QueryType verifierType);
+private:
+	IterateResult		iterate				(void);
+
+	const glw::GLenum	m_queryTarget;
+	const glw::GLenum	m_bindingPoint;
+	const QueryType		m_verifierType;
+};
+
+BufferBindingCase::BufferBindingCase (Context& context, const char* name, const char* desc, glw::GLenum queryTarget, glw::GLenum bindingPoint, QueryType verifierType)
+	: TestCase			(context, name, desc)
+	, m_queryTarget		(queryTarget)
+	, m_bindingPoint	(bindingPoint)
+	, m_verifierType	(verifierType)
+{
+}
+
+BufferBindingCase::IterateResult BufferBindingCase::iterate (void)
+{
+	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
 
 	gl.enableLogging(true);
 
-	if (verifyMaxValue(gl, m_target, m_minValue, m_verifierType))
-		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+	{
+		const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Initial", "Initial value");
+
+		verifyStateInteger(result, gl, m_queryTarget, 0, m_verifierType);
+	}
+
+	{
+		const tcu::ScopedLogSection	section	(m_testCtx.getLog(), "AfterBinding", "After binding");
+		glu::Buffer					buf		(m_context.getRenderContext());
+
+		gl.glBindBuffer(m_bindingPoint, *buf);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup");
+
+		verifyStateInteger(result, gl, m_queryTarget, *buf, m_verifierType);
+	}
+
+	{
+		const tcu::ScopedLogSection	section	(m_testCtx.getLog(), "AfterDelete", "After deleting");
+		glw::GLuint					buf		= 0;
+
+		gl.glGenBuffers(1, &buf);
+		gl.glBindBuffer(m_bindingPoint, buf);
+		gl.glDeleteBuffers(1, &buf);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup");
+
+		verifyStateInteger(result, gl, m_queryTarget, 0, m_verifierType);
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class ProgramPipelineBindingCase : public TestCase
+{
+public:
+						ProgramPipelineBindingCase	(Context& context, const char* name, const char* desc, QueryType verifierType);
+private:
+	IterateResult		iterate						(void);
+
+	const QueryType		m_verifierType;
+};
+
+ProgramPipelineBindingCase::ProgramPipelineBindingCase (Context& context, const char* name, const char* desc, QueryType verifierType)
+	: TestCase			(context, name, desc)
+	, m_verifierType	(verifierType)
+{
+}
+
+ProgramPipelineBindingCase::IterateResult ProgramPipelineBindingCase::iterate (void)
+{
+	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
+
+	gl.enableLogging(true);
+
+	{
+		const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Initial", "Initial value");
+
+		verifyStateInteger(result, gl, GL_PROGRAM_PIPELINE_BINDING, 0, m_verifierType);
+	}
+
+	{
+		const tcu::ScopedLogSection	section		(m_testCtx.getLog(), "AfterBinding", "After binding");
+		glu::ProgramPipeline		pipeline	(m_context.getRenderContext());
+
+		gl.glBindProgramPipeline(pipeline.getPipeline());
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup");
+
+		verifyStateInteger(result, gl, GL_PROGRAM_PIPELINE_BINDING, pipeline.getPipeline(), m_verifierType);
+	}
+
+	{
+		const tcu::ScopedLogSection	section		(m_testCtx.getLog(), "AfterDelete", "After deleting");
+		glw::GLuint					pipeline	= 0;
+
+		gl.glGenProgramPipelines(1, &pipeline);
+		gl.glBindProgramPipeline(pipeline);
+		gl.glDeleteProgramPipelines(1, &pipeline);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup");
+
+		verifyStateInteger(result, gl, GL_PROGRAM_PIPELINE_BINDING, 0, m_verifierType);
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class FramebufferMinimumValueCase : public TestCase
+{
+public:
+						FramebufferMinimumValueCase	(Context& context, const char* name, const char* desc, glw::GLenum target, int minValue, glw::GLenum tiedTo, QueryType verifierType);
+private:
+	IterateResult		iterate						(void);
+
+	const glw::GLenum	m_target;
+	const glw::GLenum	m_tiedTo;
+	const int			m_minValue;
+	const QueryType		m_verifierType;
+};
+
+FramebufferMinimumValueCase::FramebufferMinimumValueCase (Context& context, const char* name, const char* desc, glw::GLenum target, int minValue, glw::GLenum tiedTo, QueryType verifierType)
+	: TestCase			(context, name, desc)
+	, m_target			(target)
+	, m_tiedTo			(tiedTo)
+	, m_minValue		(minValue)
+	, m_verifierType	(verifierType)
+{
+}
+
+FramebufferMinimumValueCase::IterateResult FramebufferMinimumValueCase::iterate (void)
+{
+	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
+
+	gl.enableLogging(true);
+
+	{
+		const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Minimum", "Minimum is " + de::toString(m_minValue));
+
+		verifyStateIntegerMin(result, gl, m_target, m_minValue, m_verifierType);
+	}
+	{
+		const tcu::ScopedLogSection	section(m_testCtx.getLog(), "Ties", "Tied to " + de::toString(glu::getGettableStateStr(m_tiedTo)));
+
+		verifyStateIntegerEqualToOther(result, gl, m_target, m_tiedTo, m_verifierType);
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class LegacyVectorLimitCase : public TestCase
+{
+public:
+						LegacyVectorLimitCase	(Context& context, const char* name, const char* desc, glw::GLenum legacyTarget, glw::GLenum componentTarget, QueryType verifierType);
+private:
+	IterateResult		iterate					(void);
+
+	const glw::GLenum	m_legacyTarget;
+	const glw::GLenum	m_componentTarget;
+	const QueryType		m_verifierType;
+};
+
+LegacyVectorLimitCase::LegacyVectorLimitCase (Context& context, const char* name, const char* desc, glw::GLenum legacyTarget, glw::GLenum componentTarget, QueryType verifierType)
+	: TestCase			(context, name, desc)
+	, m_legacyTarget	(legacyTarget)
+	, m_componentTarget	(componentTarget)
+	, m_verifierType	(verifierType)
+{
+}
+
+LegacyVectorLimitCase::IterateResult LegacyVectorLimitCase::iterate (void)
+{
+	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
+
+	gl.enableLogging(true);
+
+	{
+		const tcu::ScopedLogSection	section(m_testCtx.getLog(), "TiedTo", de::toString(glu::getGettableStateStr(m_legacyTarget)) +
+																			" is " +
+																			de::toString(glu::getGettableStateStr(m_componentTarget)) +
+																			" divided by four");
+
+		StateQueryMemoryWriteGuard<glw::GLint> value;
+		gl.glGetIntegerv(m_componentTarget, &value);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetIntegerv");
+
+		if (value.verifyValidity(result))
+			verifyStateInteger(result, gl, m_legacyTarget, ((int)value) / 4, m_verifierType);
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class CombinedComputeUniformComponentsCase : public TestCase
+{
+public:
+						CombinedComputeUniformComponentsCase	(Context& context, const char* name, const char* desc, QueryType verifierType);
+private:
+	IterateResult		iterate									(void);
+
+	const QueryType		m_verifierType;
+};
+
+CombinedComputeUniformComponentsCase::CombinedComputeUniformComponentsCase (Context& context, const char* name, const char* desc, QueryType verifierType)
+	: TestCase			(context, name, desc)
+	, m_verifierType	(verifierType)
+{
+}
+
+CombinedComputeUniformComponentsCase::IterateResult CombinedComputeUniformComponentsCase::iterate (void)
+{
+	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
+
+	gl.enableLogging(true);
+
+	m_testCtx.getLog()	<< tcu::TestLog::Message
+						<< "The minimum value of MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS is MAX_COMPUTE_UNIFORM_BLOCKS x MAX_UNIFORM_BLOCK_SIZE / 4 + MAX_COMPUTE_UNIFORM_COMPONENTS"
+						<< tcu::TestLog::EndMessage;
+
+	StateQueryMemoryWriteGuard<glw::GLint> maxUniformBlocks;
+	gl.glGetIntegerv(GL_MAX_COMPUTE_UNIFORM_BLOCKS, &maxUniformBlocks);
+	GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetIntegerv");
+
+	StateQueryMemoryWriteGuard<glw::GLint> maxUniformBlockSize;
+	gl.glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
+	GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetIntegerv");
+
+	StateQueryMemoryWriteGuard<glw::GLint> maxUniformComponents;
+	gl.glGetIntegerv(GL_MAX_COMPUTE_UNIFORM_COMPONENTS, &maxUniformComponents);
+	GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetIntegerv");
+
+	if (maxUniformBlocks.verifyValidity(result) && maxUniformBlockSize.verifyValidity(result) && maxUniformComponents.verifyValidity(result))
+		verifyStateIntegerMin(result, gl, GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS, ((int)maxUniformBlocks) * ((int)maxUniformBlockSize) / 4 + (int)maxUniformComponents, m_verifierType);
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class TextureGatherLimitCase : public TestCase
+{
+public:
+						TextureGatherLimitCase	(Context& context, const char* name, const char* desc, bool isMaxCase, QueryType verifierType);
+private:
+	IterateResult		iterate					(void);
+
+	const bool			m_isMaxCase;
+	const QueryType		m_verifierType;
+};
+
+TextureGatherLimitCase::TextureGatherLimitCase (Context& context, const char* name, const char* desc, bool isMaxCase, QueryType verifierType)
+	: TestCase			(context, name, desc)
+	, m_isMaxCase		(isMaxCase)
+	, m_verifierType	(verifierType)
+{
+}
+
+TextureGatherLimitCase::IterateResult TextureGatherLimitCase::iterate (void)
+{
+	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
+
+	gl.enableLogging(true);
+
+	if (m_isMaxCase)
+	{
+		// range [0, inf)
+		verifyStateIntegerMin(result, gl, GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET, 0, m_verifierType);
+	}
 	else
-		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid value");
+	{
+		// range (-inf, 0]
+		verifyStateIntegerMax(result, gl, GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET, 0, m_verifierType);
+	}
+
+	result.setTestContextResult(m_testCtx);
 	return STOP;
 }
 
@@ -618,19 +526,16 @@
 void IntegerStateQueryTests::init (void)
 {
 	// Verifiers
-	const VerifierType verifiers[] = { VERIFIER_GETBOOLEAN, VERIFIER_GETINTEGER, VERIFIER_GETINTEGER64, VERIFIER_GETFLOAT };
+	const QueryType verifiers[] = { QUERY_BOOLEAN, QUERY_INTEGER, QUERY_INTEGER64, QUERY_FLOAT };
 
 #define FOR_EACH_VERIFIER(X) \
 	for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(verifiers); ++verifierNdx)	\
 	{																						\
 		const char* verifierSuffix = getVerifierSuffix(verifiers[verifierNdx]);				\
-		const VerifierType verifier = verifiers[verifierNdx];								\
+		const QueryType verifier = verifiers[verifierNdx];									\
 		this->addChild(X);																	\
 	}
 
-	// No additional verifiers for sample_mask_value
-	this->addChild(new SampleMaskCase(m_context, "sample_mask_value", "Test sample mask value"));
-
 	FOR_EACH_VERIFIER(new MaxSamplesCase(m_context,		(std::string() + "max_color_texture_samples_" + verifierSuffix).c_str(),				"Test GL_MAX_COLOR_TEXTURE_SAMPLES",			GL_MAX_COLOR_TEXTURE_SAMPLES,		1,	verifier))
 	FOR_EACH_VERIFIER(new MaxSamplesCase(m_context,		(std::string() + "max_depth_texture_samples_" + verifierSuffix).c_str(),				"Test GL_MAX_DEPTH_TEXTURE_SAMPLES",			GL_MAX_DEPTH_TEXTURE_SAMPLES,		1,	verifier))
 	FOR_EACH_VERIFIER(new MaxSamplesCase(m_context,		(std::string() + "max_integer_samples_" + verifierSuffix).c_str(),						"Test GL_MAX_INTEGER_SAMPLES",					GL_MAX_INTEGER_SAMPLES,				1,	verifier))
@@ -641,9 +546,68 @@
 	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_vertex_attrib_relative_offset_" + verifierSuffix).c_str(),		"Test MAX_VERTEX_ATTRIB_RELATIVE_OFFSET",		GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET,	2047,	verifier))
 	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_vertex_attrib_bindings_" + verifierSuffix).c_str(),				"Test MAX_VERTEX_ATTRIB_BINDINGS",				GL_MAX_VERTEX_ATTRIB_BINDINGS,			16,		verifier))
 	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_vertex_attrib_stride_" + verifierSuffix).c_str(),					"Test MAX_VERTEX_ATTRIB_STRIDE",				GL_MAX_VERTEX_ATTRIB_STRIDE,			2048,	verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_sample_mask_words_" + verifierSuffix).c_str(),					"Test MAX_SAMPLE_MASK_WORDS",					GL_MAX_SAMPLE_MASK_WORDS,				1,		verifier))
 
 	FOR_EACH_VERIFIER(new AlignmentCase(m_context,		(std::string() + "shader_storage_buffer_offset_alignment_" + verifierSuffix).c_str(),	"Test SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT",	GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT,	256,	verifier))
 
+	FOR_EACH_VERIFIER(new BufferBindingCase(m_context,	(std::string() + "draw_indirect_buffer_binding_" + verifierSuffix).c_str(),				"Test DRAW_INDIRECT_BUFFER_BINDING",			GL_DRAW_INDIRECT_BUFFER_BINDING,		GL_DRAW_INDIRECT_BUFFER,		verifier))
+	FOR_EACH_VERIFIER(new BufferBindingCase(m_context,	(std::string() + "atomic_counter_buffer_binding_" + verifierSuffix).c_str(),			"Test ATOMIC_COUNTER_BUFFER_BINDING",			GL_ATOMIC_COUNTER_BUFFER_BINDING,		GL_ATOMIC_COUNTER_BUFFER,		verifier))
+	FOR_EACH_VERIFIER(new BufferBindingCase(m_context,	(std::string() + "shader_storage_buffer_binding_" + verifierSuffix).c_str(),			"Test SHADER_STORAGE_BUFFER_BINDING",			GL_SHADER_STORAGE_BUFFER_BINDING,		GL_SHADER_STORAGE_BUFFER,		verifier))
+	FOR_EACH_VERIFIER(new BufferBindingCase(m_context,	(std::string() + "dispatch_indirect_buffer_binding_" + verifierSuffix).c_str(),			"Test DISPATCH_INDIRECT_BUFFER_BINDING",		GL_DISPATCH_INDIRECT_BUFFER_BINDING,	GL_DISPATCH_INDIRECT_BUFFER,	verifier))
+
+	FOR_EACH_VERIFIER(new FramebufferMinimumValueCase(m_context,	(std::string() + "max_framebuffer_width_" + verifierSuffix).c_str(),		"Test MAX_FRAMEBUFFER_WIDTH",					GL_MAX_FRAMEBUFFER_WIDTH,				2048,	GL_MAX_TEXTURE_SIZE,	verifier))
+	FOR_EACH_VERIFIER(new FramebufferMinimumValueCase(m_context,	(std::string() + "max_framebuffer_height_" + verifierSuffix).c_str(),		"Test MAX_FRAMEBUFFER_HEIGHT",					GL_MAX_FRAMEBUFFER_HEIGHT,				2048,	GL_MAX_TEXTURE_SIZE,	verifier))
+	FOR_EACH_VERIFIER(new FramebufferMinimumValueCase(m_context,	(std::string() + "max_framebuffer_samples_" + verifierSuffix).c_str(),		"Test MAX_FRAMEBUFFER_SAMPLES",					GL_MAX_FRAMEBUFFER_SAMPLES,				4,		GL_MAX_SAMPLES,			verifier))
+
+	FOR_EACH_VERIFIER(new ProgramPipelineBindingCase(m_context,	(std::string() + "program_pipeline_binding_" + verifierSuffix).c_str(),			"Test PROGRAM_PIPELINE_BINDING",	verifier))
+
+	// vertex
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_vertex_atomic_counter_buffers_" + verifierSuffix).c_str(),		"Test MAX_VERTEX_ATOMIC_COUNTER_BUFFERS",		GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS,	0,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_vertex_atomic_counters_" + verifierSuffix).c_str(),				"Test MAX_VERTEX_ATOMIC_COUNTERS",				GL_MAX_VERTEX_ATOMIC_COUNTERS,			0,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_vertex_image_uniforms_" + verifierSuffix).c_str(),				"Test MAX_VERTEX_IMAGE_UNIFORMS",				GL_MAX_VERTEX_IMAGE_UNIFORMS,			0,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_vertex_shader_storage_blocks_" + verifierSuffix).c_str(),			"Test MAX_VERTEX_SHADER_STORAGE_BLOCKS",		GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS,	0,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_vertex_uniform_components_" + verifierSuffix).c_str(),			"Test MAX_VERTEX_UNIFORM_COMPONENTS",			GL_MAX_VERTEX_UNIFORM_COMPONENTS,		1024,	verifier))
+
+	// fragment
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_fragment_atomic_counter_buffers_" + verifierSuffix).c_str(),		"Test MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS",		GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS,	0,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_fragment_atomic_counters_" + verifierSuffix).c_str(),				"Test MAX_FRAGMENT_ATOMIC_COUNTERS",			GL_MAX_FRAGMENT_ATOMIC_COUNTERS,		0,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_fragment_image_uniforms_" + verifierSuffix).c_str(),				"Test MAX_FRAGMENT_IMAGE_UNIFORMS",				GL_MAX_FRAGMENT_IMAGE_UNIFORMS,			0,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_fragment_shader_storage_blocks_" + verifierSuffix).c_str(),		"Test MAX_FRAGMENT_SHADER_STORAGE_BLOCKS",		GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS,	0,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_fragment_uniform_components_" + verifierSuffix).c_str(),			"Test MAX_FRAGMENT_UNIFORM_COMPONENTS",			GL_MAX_FRAGMENT_UNIFORM_COMPONENTS,		1024,	verifier))
+
+	// compute
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_compute_work_group_invocations_" + verifierSuffix).c_str(),		"Test MAX_COMPUTE_WORK_GROUP_INVOCATIONS",		GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS,		128,	verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_compute_uniform_blocks_" + verifierSuffix).c_str(),				"Test MAX_COMPUTE_UNIFORM_BLOCKS",				GL_MAX_COMPUTE_UNIFORM_BLOCKS,				12,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_compute_texture_image_units_" + verifierSuffix).c_str(),			"Test MAX_COMPUTE_TEXTURE_IMAGE_UNITS",			GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS,			16,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_compute_shared_memory_size_" + verifierSuffix).c_str(),			"Test MAX_COMPUTE_SHARED_MEMORY_SIZE",			GL_MAX_COMPUTE_SHARED_MEMORY_SIZE,			16384,	verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_compute_uniform_components_" + verifierSuffix).c_str(),			"Test MAX_COMPUTE_UNIFORM_COMPONENTS",			GL_MAX_COMPUTE_UNIFORM_COMPONENTS,			1024,	verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_compute_atomic_counter_buffers_" + verifierSuffix).c_str(),		"Test MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS",		GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS,		1,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_compute_atomic_counters_" + verifierSuffix).c_str(),				"Test MAX_COMPUTE_ATOMIC_COUNTERS",				GL_MAX_COMPUTE_ATOMIC_COUNTERS,				8,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_compute_image_uniforms_" + verifierSuffix).c_str(),				"Test MAX_COMPUTE_IMAGE_UNIFORMS",				GL_MAX_COMPUTE_IMAGE_UNIFORMS,				4,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_compute_shader_storage_blocks_" + verifierSuffix).c_str(),		"Test MAX_COMPUTE_SHADER_STORAGE_BLOCKS",		GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS,		4,		verifier))
+
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_uniform_locations_" + verifierSuffix).c_str(),					"Test MAX_UNIFORM_LOCATIONS",					GL_MAX_UNIFORM_LOCATIONS,					1024,	verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_atomic_counter_buffer_bindings_" + verifierSuffix).c_str(),		"Test MAX_ATOMIC_COUNTER_BUFFER_BINDINGS",		GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS,		1,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_atomic_counter_buffer_size_" + verifierSuffix).c_str(),			"Test MAX_ATOMIC_COUNTER_BUFFER_SIZE",			GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE,			32,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_combined_atomic_counter_buffers_" + verifierSuffix).c_str(),		"Test MAX_COMBINED_ATOMIC_COUNTER_BUFFERS",		GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS,		1,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_combined_atomic_counters_" + verifierSuffix).c_str(),				"Test MAX_COMBINED_ATOMIC_COUNTERS",			GL_MAX_COMBINED_ATOMIC_COUNTERS,			8,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_image_units_" + verifierSuffix).c_str(),							"Test MAX_IMAGE_UNITS",							GL_MAX_IMAGE_UNITS,							4,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_combined_image_uniforms_" + verifierSuffix).c_str(),				"Test MAX_COMBINED_IMAGE_UNIFORMS",				GL_MAX_COMBINED_IMAGE_UNIFORMS,				4,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_shader_storage_buffer_bindings_" + verifierSuffix).c_str(),		"Test MAX_SHADER_STORAGE_BUFFER_BINDINGS",		GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS,		4,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_shader_storage_block_size_" + verifierSuffix).c_str(),			"Test MAX_SHADER_STORAGE_BLOCK_SIZE",			GL_MAX_SHADER_STORAGE_BLOCK_SIZE,			1<<27,	verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_combined_shader_storage_blocks_" + verifierSuffix).c_str(),		"Test MAX_COMBINED_SHADER_STORAGE_BLOCKS",		GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS,		4,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_uniform_buffer_bindings_" + verifierSuffix).c_str(),				"Test MAX_UNIFORM_BUFFER_BINDINGS",				GL_MAX_UNIFORM_BUFFER_BINDINGS,				36,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_combined_texture_image_units_" + verifierSuffix).c_str(),			"Test MAX_COMBINED_TEXTURE_IMAGE_UNITS",		GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,		48,		verifier))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_combined_shader_output_resources_" + verifierSuffix).c_str(),		"Test MAX_COMBINED_SHADER_OUTPUT_RESOURCES",	GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES,	4,		verifier))
+
+	FOR_EACH_VERIFIER(new CombinedComputeUniformComponentsCase(m_context,	(std::string() + "max_combined_compute_uniform_components_" + verifierSuffix).c_str(), "Test MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS", verifier))
+
+	FOR_EACH_VERIFIER(new LegacyVectorLimitCase(m_context,	(std::string() + "max_vertex_uniform_vectors_" + verifierSuffix).c_str(),			"Test MAX_VERTEX_UNIFORM_VECTORS",				GL_MAX_VERTEX_UNIFORM_VECTORS,			GL_MAX_VERTEX_UNIFORM_COMPONENTS,	verifier))
+	FOR_EACH_VERIFIER(new LegacyVectorLimitCase(m_context,	(std::string() + "max_fragment_uniform_vectors_" + verifierSuffix).c_str(),			"Test MAX_FRAGMENT_UNIFORM_VECTORS",			GL_MAX_FRAGMENT_UNIFORM_VECTORS,		GL_MAX_FRAGMENT_UNIFORM_COMPONENTS,	verifier))
+
+	FOR_EACH_VERIFIER(new TextureGatherLimitCase(m_context,	(std::string() + "min_program_texture_gather_offset_" + verifierSuffix).c_str(),	"Test MIN_PROGRAM_TEXTURE_GATHER_OFFSET",		false,		verifier))
+	FOR_EACH_VERIFIER(new TextureGatherLimitCase(m_context,	(std::string() + "max_program_texture_gather_offset_" + verifierSuffix).c_str(),	"Test MAX_PROGRAM_TEXTURE_GATHER_OFFSET",		true,		verifier))
+
 #undef FOR_EACH_VERIFIER
 }
 
diff --git a/modules/gles31/functional/es31fProgramPipelineStateQueryTests.cpp b/modules/gles31/functional/es31fProgramPipelineStateQueryTests.cpp
new file mode 100644
index 0000000..715f466
--- /dev/null
+++ b/modules/gles31/functional/es31fProgramPipelineStateQueryTests.cpp
@@ -0,0 +1,501 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Program Pipeline State Query tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "es31fProgramPipelineStateQueryTests.hpp"
+#include "glsStateQueryUtil.hpp"
+#include "gluRenderContext.hpp"
+#include "gluCallLogWrapper.hpp"
+#include "gluObjectWrapper.hpp"
+#include "gluShaderProgram.hpp"
+#include "glwFunctions.hpp"
+#include "glwEnums.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace
+{
+
+using namespace gls::StateQueryUtil;
+
+static const char* getVerifierSuffix (QueryType type)
+{
+	switch (type)
+	{
+		case QUERY_PIPELINE_INTEGER:	return "get_program_pipelineiv";
+		default:
+			DE_ASSERT(DE_FALSE);
+			return DE_NULL;
+	}
+}
+
+static const char* const s_vertexSource = 		"#version 310 es\n"
+												"out highp vec4 v_color;\n"
+												"void main()\n"
+												"{\n"
+												"	gl_Position = vec4(float(gl_VertexID) * 0.5, float(gl_VertexID+1) * 0.5, 0.0, 1.0);\n"
+												"	v_color = vec4(float(gl_VertexID), 1.0, 0.0, 1.0);\n"
+												"}\n";
+static const char* const s_fragmentSource = 	"#version 310 es\n"
+												"in highp vec4 v_color;\n"
+												"layout(location=0) out highp vec4 o_color;\n"
+												"void main()\n"
+												"{\n"
+												"	o_color = v_color;\n"
+												"}\n";
+static const char* const s_computeSource =	 	"#version 310 es\n"
+												"layout (local_size_x = 1, local_size_y = 1) in;\n"
+												"layout(binding = 0) buffer Output\n"
+												"{\n"
+												"	highp float val;\n"
+												"} sb_out;\n"
+												"\n"
+												"void main (void)\n"
+												"{\n"
+												"	sb_out.val = 1.0;\n"
+												"}\n";
+
+class ActiveProgramCase : public TestCase
+{
+public:
+						ActiveProgramCase	(Context& context, QueryType verifier, const char* name, const char* desc);
+	IterateResult		iterate				(void);
+
+private:
+	const QueryType		m_verifier;
+};
+
+ActiveProgramCase::ActiveProgramCase (Context& context, QueryType verifier, const char* name, const char* desc)
+	: TestCase		(context, name, desc)
+	, m_verifier	(verifier)
+{
+}
+
+ActiveProgramCase::IterateResult ActiveProgramCase::iterate (void)
+{
+	const glu::ShaderProgram	vtxProgram	(m_context.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << glu::VertexSource(s_vertexSource));
+	const glu::ShaderProgram	frgProgram	(m_context.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << glu::FragmentSource(s_fragmentSource));
+	const glu::ProgramPipeline	pipeline	(m_context.getRenderContext());
+	glu::CallLogWrapper			gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector		result		(m_testCtx.getLog(), " // ERROR: ");
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "VtxProg", "Vertex program");
+		m_testCtx.getLog() << vtxProgram;
+	}
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "FrgProg", "Fragment program");
+		m_testCtx.getLog() << frgProgram;
+	}
+
+	if (!vtxProgram.isOk() || !frgProgram.isOk())
+		throw tcu::TestError("failed to build program");
+
+	gl.enableLogging(true);
+	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+
+	gl.glBindProgramPipeline(pipeline.getPipeline());
+	gl.glUseProgramStages(pipeline.getPipeline(), GL_VERTEX_SHADER_BIT, vtxProgram.getProgram());
+	gl.glUseProgramStages(pipeline.getPipeline(), GL_FRAGMENT_SHADER_BIT, frgProgram.getProgram());
+	GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen pipeline");
+	gl.glBindProgramPipeline(0);
+	GLU_EXPECT_NO_ERROR(gl.glGetError(), "unbind pipeline");
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial");
+		verifyStatePipelineInteger(result, gl, pipeline.getPipeline(), GL_ACTIVE_PROGRAM, 0, m_verifier);
+	}
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Set", "Set");
+
+		gl.glActiveShaderProgram(pipeline.getPipeline(), frgProgram.getProgram());
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen pipeline");
+		verifyStatePipelineInteger(result, gl, pipeline.getPipeline(), GL_ACTIVE_PROGRAM, (int)frgProgram.getProgram(), m_verifier);
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class PipelineProgramCase : public TestCase
+{
+public:
+						PipelineProgramCase	(Context& context, QueryType verifier, const char* name, const char* desc, glw::GLenum stage);
+	IterateResult		iterate				(void);
+
+private:
+	const QueryType		m_verifier;
+	const glw::GLenum	m_targetStage;
+};
+
+PipelineProgramCase::PipelineProgramCase (Context& context, QueryType verifier, const char* name, const char* desc, glw::GLenum stage)
+	: TestCase		(context, name, desc)
+	, m_verifier	(verifier)
+	, m_targetStage	(stage)
+{
+}
+
+PipelineProgramCase::IterateResult PipelineProgramCase::iterate (void)
+{
+	glu::CallLogWrapper		gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result		(m_testCtx.getLog(), " // ERROR: ");
+	const int				stageBit	= (m_targetStage == GL_VERTEX_SHADER)	? (GL_VERTEX_SHADER_BIT)
+										: (m_targetStage == GL_FRAGMENT_SHADER)	? (GL_FRAGMENT_SHADER_BIT)
+										: (GL_COMPUTE_SHADER_BIT);
+	glu::ProgramSources	sources;
+
+	if (m_targetStage == GL_VERTEX_SHADER)
+		sources << glu::ProgramSeparable(true) << glu::VertexSource(s_vertexSource);
+	else if (m_targetStage == GL_FRAGMENT_SHADER)
+		sources << glu::ProgramSeparable(true) << glu::FragmentSource(s_fragmentSource);
+	else if (m_targetStage == GL_COMPUTE_SHADER)
+		sources << glu::ProgramSeparable(true) << glu::ComputeSource(s_computeSource);
+	else
+		DE_ASSERT(false);
+
+	gl.enableLogging(true);
+
+	{
+		glu::ShaderProgram program(m_context.getRenderContext(), sources);
+
+		{
+			const tcu::ScopedLogSection section(m_testCtx.getLog(), "program", "Program");
+			m_testCtx.getLog() << program;
+		}
+
+		if (!program.isOk())
+			throw tcu::TestError("failed to build program");
+
+		{
+			const tcu::ScopedLogSection section		(m_testCtx.getLog(), "Initial", "Initial");
+			glu::ProgramPipeline 		pipeline	(m_context.getRenderContext());
+
+			gl.glBindProgramPipeline(pipeline.getPipeline());
+			GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup pipeline");
+
+			verifyStatePipelineInteger(result, gl, pipeline.getPipeline(), m_targetStage, 0, m_verifier);
+		}
+
+		{
+			const tcu::ScopedLogSection section		(m_testCtx.getLog(), "Set", "Set");
+			glu::ProgramPipeline 		pipeline	(m_context.getRenderContext());
+
+			gl.glBindProgramPipeline(pipeline.getPipeline());
+			gl.glUseProgramStages(pipeline.getPipeline(), stageBit, program.getProgram());
+			GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup pipeline");
+
+			verifyStatePipelineInteger(result, gl, pipeline.getPipeline(), m_targetStage, program.getProgram(), m_verifier);
+		}
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class ValidateStatusCase : public TestCase
+{
+public:
+						ValidateStatusCase	(Context& context, QueryType verifier, const char* name, const char* desc);
+	IterateResult		iterate				(void);
+
+private:
+	const QueryType		m_verifier;
+};
+
+ValidateStatusCase::ValidateStatusCase (Context& context, QueryType verifier, const char* name, const char* desc)
+	: TestCase		(context, name, desc)
+	, m_verifier	(verifier)
+{
+}
+
+ValidateStatusCase::IterateResult ValidateStatusCase::iterate (void)
+{
+	glu::ShaderProgram		vtxProgram	(m_context.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << glu::VertexSource(s_vertexSource));
+	glu::ShaderProgram		frgProgram	(m_context.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << glu::FragmentSource(s_fragmentSource));
+	glu::ProgramPipeline	pipeline	(m_context.getRenderContext());
+	glu::CallLogWrapper		gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result		(m_testCtx.getLog(), " // ERROR: ");
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "VtxProg", "Vertex program");
+		m_testCtx.getLog() << vtxProgram;
+	}
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "FrgProg", "Fragment program");
+		m_testCtx.getLog() << frgProgram;
+	}
+
+	if (!vtxProgram.isOk() || !frgProgram.isOk())
+		throw tcu::TestError("failed to build program");
+
+	gl.enableLogging(true);
+
+	gl.glBindProgramPipeline(pipeline.getPipeline());
+	gl.glUseProgramStages(pipeline.getPipeline(), GL_VERTEX_SHADER_BIT, vtxProgram.getProgram());
+	gl.glUseProgramStages(pipeline.getPipeline(), GL_FRAGMENT_SHADER_BIT, frgProgram.getProgram());
+	GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen pipeline");
+	gl.glBindProgramPipeline(0);
+	GLU_EXPECT_NO_ERROR(gl.glGetError(), "unbind pipeline");
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial");
+		verifyStatePipelineInteger(result, gl, pipeline.getPipeline(), GL_VALIDATE_STATUS, 0, m_verifier);
+	}
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Set", "Validate");
+
+		gl.glValidateProgramPipeline(pipeline.getPipeline());
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen pipeline");
+		verifyStatePipelineInteger(result, gl, pipeline.getPipeline(), GL_VALIDATE_STATUS, GL_TRUE, m_verifier);
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class InfoLogCase : public TestCase
+{
+public:
+						InfoLogCase	(Context& context, const char* name, const char* desc);
+	IterateResult		iterate		(void);
+};
+
+InfoLogCase::InfoLogCase (Context& context, const char* name, const char* desc)
+	: TestCase(context, name, desc)
+{
+}
+
+InfoLogCase::IterateResult InfoLogCase::iterate (void)
+{
+	using gls::StateQueryUtil::StateQueryMemoryWriteGuard;
+
+	static const char* const s_incompatibleFragmentSource = "#version 310 es\n"
+															"in mediump vec2 v_colorB;\n"
+															"in mediump vec2 v_colorC;\n"
+															"layout(location=0) out highp vec4 o_color;\n"
+															"void main()\n"
+															"{\n"
+															"	o_color = v_colorB.xxyy + v_colorC.yyxy;\n"
+															"}\n";
+
+	glu::ShaderProgram		vtxProgram	(m_context.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << glu::VertexSource(s_vertexSource));
+	glu::ShaderProgram		frgProgram	(m_context.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << glu::FragmentSource(s_incompatibleFragmentSource));
+	glu::CallLogWrapper		gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result		(m_testCtx.getLog(), " // ERROR: ");
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "VtxProg", "Vertex program");
+		m_testCtx.getLog() << vtxProgram;
+	}
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "FrgProg", "Fragment program");
+		m_testCtx.getLog() << frgProgram;
+	}
+
+	if (!vtxProgram.isOk() || !frgProgram.isOk())
+		throw tcu::TestError("failed to build program");
+
+	gl.enableLogging(true);
+
+	{
+		const tcu::ScopedLogSection section		(m_testCtx.getLog(), "Initial", "Initial");
+		glu::ProgramPipeline		pipeline	(m_context.getRenderContext());
+		std::string					buf			(3, 'X');
+		int							written		= -1;
+
+		verifyStatePipelineInteger(result, gl, pipeline.getPipeline(), GL_INFO_LOG_LENGTH, 0, QUERY_PIPELINE_INTEGER);
+
+		gl.glGetProgramPipelineInfoLog(pipeline.getPipeline(), 2, &written, &buf[0]);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "query log");
+
+		if (written == -1)
+			result.fail("'length' was not written to");
+		else if (written != 0)
+			result.fail("'length' was not 0");
+		else if (buf[0] != '\0')
+			result.fail("log was not 0-sized null-terminated string");
+		else if (buf[1] != 'X' || buf[2] != 'X')
+			result.fail("buffer after returned length modified");
+	}
+
+	{
+		const tcu::ScopedLogSection 			superSection	(m_testCtx.getLog(), "ValidationFail", "Failed validation");
+		glu::ProgramPipeline					pipeline		(m_context.getRenderContext());
+		StateQueryMemoryWriteGuard<glw::GLint>	logLen;
+
+		gl.glBindProgramPipeline(pipeline.getPipeline());
+		gl.glUseProgramStages(pipeline.getPipeline(), GL_VERTEX_SHADER_BIT, vtxProgram.getProgram());
+		gl.glUseProgramStages(pipeline.getPipeline(), GL_FRAGMENT_SHADER_BIT, frgProgram.getProgram());
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen pipeline");
+
+		gl.glBindProgramPipeline(0);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "unbind pipeline");
+		gl.glValidateProgramPipeline(pipeline.getPipeline());
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen pipeline");
+
+		gl.glGetProgramPipelineiv(pipeline.getPipeline(), GL_INFO_LOG_LENGTH, &logLen);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "get INFO_LOG_LENGTH");
+
+		if (logLen.verifyValidity(m_testCtx))
+		{
+			{
+				const tcu::ScopedLogSection	section	(m_testCtx.getLog(), "QueryAll", "Query all");
+				std::string					buf		(logLen + 2, 'X');
+
+				buf[logLen + 1] = '\0';
+				gl.glGetProgramPipelineInfoLog(pipeline.getPipeline(), logLen, DE_NULL, &buf[0]);
+				GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetProgramPipelineInfoLog");
+
+				if (logLen > 0 && buf[logLen-1] != '\0')
+					result.fail("Return buffer was not INFO_LOG_LENGTH sized and null-terminated");
+				else if (buf[logLen] != 'X' && buf[logLen+1] != '\0')
+					result.fail("Buffer end guard modified, query wrote over the end of the buffer.");
+			}
+
+			{
+				const tcu::ScopedLogSection section	(m_testCtx.getLog(), "QueryMore", "Query more");
+				std::string					buf		(logLen + 4, 'X');
+				int							written	= -1;
+
+				buf[logLen + 3] = '\0';
+				gl.glGetProgramPipelineInfoLog(pipeline.getPipeline(), logLen+2, &written, &buf[0]);
+				GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetProgramPipelineInfoLog");
+
+				if (written == -1)
+					result.fail("'length' was not written to");
+				else if (buf[written] != '\0')
+					result.fail("Either length was incorrect or result was not null-terminated");
+				else if (logLen != 0 && (written + 1) > logLen)
+					result.fail("'length' characters + null terminator is larger than INFO_LOG_LENGTH");
+				else if ((written + 1) < logLen)
+					result.fail("'length' is not consistent with INFO_LOG_LENGTH");
+				else if (buf[logLen+2] != 'X' && buf[logLen+3] != '\0')
+					result.fail("Buffer end guard modified, query wrote over the end of the buffer.");
+				else if (written != (int)strlen(&buf[0]))
+					result.fail("'length' and written string length do not match");
+			}
+
+			if (logLen > 2)
+			{
+				const tcu::ScopedLogSection section	(m_testCtx.getLog(), "QueryLess", "Query less");
+				std::string					buf		(logLen + 2, 'X');
+				int							written	= -1;
+
+				gl.glGetProgramPipelineInfoLog(pipeline.getPipeline(), 2, &written, &buf[0]);
+				GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetProgramPipelineInfoLog");
+
+				if (written == -1)
+					result.fail("'length' was not written to");
+				else if (written != 1)
+					result.fail("Expected 'length' = 1");
+				else if (buf[1] != '\0')
+					result.fail("Expected null terminator at index 1");
+			}
+
+			if (logLen > 0)
+			{
+				const tcu::ScopedLogSection section	(m_testCtx.getLog(), "QueryOne", "Query one character");
+				std::string					buf		(logLen + 2, 'X');
+				int							written	= -1;
+
+				gl.glGetProgramPipelineInfoLog(pipeline.getPipeline(), 1, &written, &buf[0]);
+				GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetProgramPipelineInfoLog");
+
+				if (written == -1)
+					result.fail("'length' was not written to");
+				else if (written != 0)
+					result.fail("Expected 'length' = 0");
+				else if (buf[0] != '\0')
+					result.fail("Expected null terminator at index 0");
+			}
+
+			{
+				const tcu::ScopedLogSection section	(m_testCtx.getLog(), "QueryNone", "Query to zero-sized buffer");
+				std::string					buf		(logLen + 2, 'X');
+				int							written	= -1;
+
+				gl.glGetProgramPipelineInfoLog(pipeline.getPipeline(), 0, &written, &buf[0]);
+				GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetProgramPipelineInfoLog");
+
+				if (written == -1)
+					result.fail("'length' was not written to");
+				else if (written != 0)
+					result.fail("Expected 'length' = 0");
+				else if (buf[0] != 'X')
+					result.fail("Unexpected buffer mutation at index 0");
+			}
+		}
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+} // anonymous
+
+ProgramPipelineStateQueryTests::ProgramPipelineStateQueryTests (Context& context)
+	: TestCaseGroup(context, "program_pipeline", "Program Pipeline State Query tests")
+{
+}
+
+ProgramPipelineStateQueryTests::~ProgramPipelineStateQueryTests (void)
+{
+}
+
+void ProgramPipelineStateQueryTests::init (void)
+{
+	static const QueryType verifiers[] =
+	{
+		QUERY_PIPELINE_INTEGER,
+	};
+
+#define FOR_EACH_VERIFIER(X) \
+	for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(verifiers); ++verifierNdx)	\
+	{																						\
+		const char* verifierSuffix = getVerifierSuffix(verifiers[verifierNdx]);				\
+		const QueryType verifier = verifiers[verifierNdx];									\
+		this->addChild(X);																	\
+	}
+
+	FOR_EACH_VERIFIER(new ActiveProgramCase(m_context, verifier, (std::string("active_program_") + verifierSuffix).c_str(), "Test ACTIVE_PROGRAM"));
+	FOR_EACH_VERIFIER(new PipelineProgramCase(m_context, verifier, (std::string("vertex_shader_") + verifierSuffix).c_str(), "Test VERTEX_SHADER", GL_VERTEX_SHADER));
+	FOR_EACH_VERIFIER(new PipelineProgramCase(m_context, verifier, (std::string("fragment_shader_") + verifierSuffix).c_str(), "Test FRAGMENT_SHADER", GL_FRAGMENT_SHADER));
+	FOR_EACH_VERIFIER(new PipelineProgramCase(m_context, verifier, (std::string("compute_shader_") + verifierSuffix).c_str(), "Test COMPUTE_SHADER", GL_COMPUTE_SHADER));
+	FOR_EACH_VERIFIER(new ValidateStatusCase(m_context, verifier, (std::string("validate_status_") + verifierSuffix).c_str(), "Test VALIDATE_STATUS"));
+
+#undef FOR_EACH_VERIFIER
+
+	this->addChild(new InfoLogCase(m_context, "info_log", "Test info log"));
+}
+
+} // Functional
+} // gles31
+} // deqp
diff --git a/modules/gles31/functional/es31fProgramPipelineStateQueryTests.hpp b/modules/gles31/functional/es31fProgramPipelineStateQueryTests.hpp
new file mode 100644
index 0000000..b33f782
--- /dev/null
+++ b/modules/gles31/functional/es31fProgramPipelineStateQueryTests.hpp
@@ -0,0 +1,53 @@
+#ifndef _ES31FPROGRAMPIPELINESTATEQUERYTESTS_HPP
+#define _ES31FPROGRAMPIPELINESTATEQUERYTESTS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Program Pipeline State Query tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tes31TestCase.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+
+class ProgramPipelineStateQueryTests : public TestCaseGroup
+{
+public:
+										ProgramPipelineStateQueryTests		(Context& context);
+										~ProgramPipelineStateQueryTests		(void);
+
+	void								init								(void);
+
+private:
+										ProgramPipelineStateQueryTests		(const ProgramPipelineStateQueryTests& other);
+	ProgramPipelineStateQueryTests&		operator=							(const ProgramPipelineStateQueryTests& other);
+};
+
+} // Functional
+} // gles31
+} // deqp
+
+#endif // _ES31FPROGRAMPIPELINESTATEQUERYTESTS_HPP
diff --git a/modules/gles31/functional/es31fProgramStateQueryTests.cpp b/modules/gles31/functional/es31fProgramStateQueryTests.cpp
new file mode 100644
index 0000000..d66a8cd
--- /dev/null
+++ b/modules/gles31/functional/es31fProgramStateQueryTests.cpp
@@ -0,0 +1,390 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Program State Query tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "es31fProgramStateQueryTests.hpp"
+#include "glsStateQueryUtil.hpp"
+#include "gluRenderContext.hpp"
+#include "gluCallLogWrapper.hpp"
+#include "gluObjectWrapper.hpp"
+#include "gluShaderProgram.hpp"
+#include "glwFunctions.hpp"
+#include "glwEnums.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace
+{
+
+using namespace gls::StateQueryUtil;
+
+static const char* getVerifierSuffix (QueryType type)
+{
+	switch (type)
+	{
+		case QUERY_PROGRAM_INTEGER_VEC3:
+		case QUERY_PROGRAM_INTEGER:
+			return "get_programiv";
+
+		default:
+			DE_ASSERT(DE_FALSE);
+			return DE_NULL;
+	}
+}
+
+class ProgramSeparableCase : public TestCase
+{
+public:
+						ProgramSeparableCase	(Context& context, QueryType verifier, const char* name, const char* desc);
+	IterateResult		iterate					(void);
+
+private:
+	const QueryType		m_verifier;
+};
+
+ProgramSeparableCase::ProgramSeparableCase (Context& context, QueryType verifier, const char* name, const char* desc)
+	: TestCase		(context, name, desc)
+	, m_verifier	(verifier)
+{
+}
+
+ProgramSeparableCase::IterateResult ProgramSeparableCase::iterate (void)
+{
+	static const char* const s_vertexSource = 	"#version 310 es\n"
+												"out highp vec4 v_color;\n"
+												"void main()\n"
+												"{\n"
+												"	gl_Position = vec4(float(gl_VertexID) * 0.5, float(gl_VertexID+1) * 0.5, 0.0, 1.0);\n"
+												"	v_color = vec4(float(gl_VertexID), 1.0, 0.0, 1.0);\n"
+												"}\n";
+	static const char* const s_fragmentSource = "#version 310 es\n"
+												"in highp vec4 v_color;\n"
+												"layout(location=0) out highp vec4 o_color;\n"
+												"void main()\n"
+												"{\n"
+												"	o_color = v_color;\n"
+												"}\n";
+
+	glu::CallLogWrapper		gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result		(m_testCtx.getLog(), " // ERROR: ");
+	glu::Shader				vtxShader	(m_context.getRenderContext(), glu::SHADERTYPE_VERTEX);
+	glu::Shader				frgShader	(m_context.getRenderContext(), glu::SHADERTYPE_FRAGMENT);
+
+	vtxShader.setSources(1, &s_vertexSource, DE_NULL);
+	frgShader.setSources(1, &s_fragmentSource, DE_NULL);
+
+	vtxShader.compile();
+	frgShader.compile();
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "VtxShader", "Vertex shader");
+		m_testCtx.getLog() << vtxShader;
+	}
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "FrgShader", "Fragment shader");
+		m_testCtx.getLog() << frgShader;
+	}
+
+	if (!vtxShader.getCompileStatus() || !frgShader.getCompileStatus())
+		throw tcu::TestError("failed to build shaders");
+
+	gl.enableLogging(true);
+
+	{
+		const tcu::ScopedLogSection	section	(m_testCtx.getLog(), "Initial", "Initial");
+		glu::Program				program	(m_context.getRenderContext());
+
+		verifyStateProgramInteger(result, gl, program.getProgram(), GL_PROGRAM_SEPARABLE, 0, m_verifier);
+	}
+
+	{
+		const tcu::ScopedLogSection section		(m_testCtx.getLog(), "SetFalse", "SetFalse");
+		glu::Program				program		(m_context.getRenderContext());
+		int							linkStatus	= 0;
+
+		gl.glAttachShader(program.getProgram(), vtxShader.getShader());
+		gl.glAttachShader(program.getProgram(), frgShader.getShader());
+		gl.glProgramParameteri(program.getProgram(), GL_PROGRAM_SEPARABLE, GL_FALSE);
+		gl.glLinkProgram(program.getProgram());
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup program");
+
+		gl.glGetProgramiv(program.getProgram(), GL_LINK_STATUS, &linkStatus);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "query link status");
+
+		if (linkStatus == GL_FALSE)
+			throw tcu::TestError("failed to link program");
+
+		verifyStateProgramInteger(result, gl, program.getProgram(), GL_PROGRAM_SEPARABLE, 0, m_verifier);
+	}
+
+	{
+		const tcu::ScopedLogSection section		(m_testCtx.getLog(), "SetTrue", "SetTrue");
+		glu::Program				program		(m_context.getRenderContext());
+		int							linkStatus	= 0;
+
+		gl.glAttachShader(program.getProgram(), vtxShader.getShader());
+		gl.glAttachShader(program.getProgram(), frgShader.getShader());
+		gl.glProgramParameteri(program.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE);
+		gl.glLinkProgram(program.getProgram());
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup program");
+
+		gl.glGetProgramiv(program.getProgram(), GL_LINK_STATUS, &linkStatus);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "query link status");
+
+		if (linkStatus == GL_FALSE)
+			throw tcu::TestError("failed to link program");
+
+		verifyStateProgramInteger(result, gl, program.getProgram(), GL_PROGRAM_SEPARABLE, GL_TRUE, m_verifier);
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class ComputeWorkGroupSizeCase : public TestCase
+{
+public:
+						ComputeWorkGroupSizeCase	(Context& context, QueryType verifier, const char* name, const char* desc);
+	IterateResult		iterate						(void);
+
+private:
+	const QueryType		m_verifier;
+};
+
+ComputeWorkGroupSizeCase::ComputeWorkGroupSizeCase (Context& context, QueryType verifier, const char* name, const char* desc)
+	: TestCase		(context, name, desc)
+	, m_verifier	(verifier)
+{
+}
+
+ComputeWorkGroupSizeCase::IterateResult ComputeWorkGroupSizeCase::iterate (void)
+{
+	static const char* const s_computeSource1D =	"#version 310 es\n"
+													"layout (local_size_x = 3) in;\n"
+													"layout(binding = 0) buffer Output\n"
+													"{\n"
+													"	highp float val;\n"
+													"} sb_out;\n"
+													"\n"
+													"void main (void)\n"
+													"{\n"
+													"	sb_out.val = 1.0;\n"
+													"}\n";
+	static const char* const s_computeSource2D =	"#version 310 es\n"
+													"layout (local_size_x = 3, local_size_y = 2) in;\n"
+													"layout(binding = 0) buffer Output\n"
+													"{\n"
+													"	highp float val;\n"
+													"} sb_out;\n"
+													"\n"
+													"void main (void)\n"
+													"{\n"
+													"	sb_out.val = 1.0;\n"
+													"}\n";
+	static const char* const s_computeSource3D =	"#version 310 es\n"
+													"layout (local_size_x = 3, local_size_y = 2, local_size_z = 4) in;\n"
+													"layout(binding = 0) buffer Output\n"
+													"{\n"
+													"	highp float val;\n"
+													"} sb_out;\n"
+													"\n"
+													"void main (void)\n"
+													"{\n"
+													"	sb_out.val = 1.0;\n"
+													"}\n";
+
+	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
+
+	gl.enableLogging(true);
+
+	{
+		const tcu::ScopedLogSection section		(m_testCtx.getLog(), "OneDimensional", "1D");
+		glu::ShaderProgram			program		(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(s_computeSource1D));
+
+		m_testCtx.getLog() << program;
+		if (!program.isOk())
+			throw tcu::TestError("failed to build program");
+
+		verifyStateProgramIntegerVec3(result, gl, program.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, tcu::IVec3(3, 1, 1), m_verifier);
+	}
+
+	{
+		const tcu::ScopedLogSection section		(m_testCtx.getLog(), "TwoDimensional", "2D");
+		glu::ShaderProgram			program		(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(s_computeSource2D));
+
+		m_testCtx.getLog() << program;
+		if (!program.isOk())
+			throw tcu::TestError("failed to build program");
+
+		verifyStateProgramIntegerVec3(result, gl, program.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, tcu::IVec3(3, 2, 1), m_verifier);
+	}
+
+	{
+		const tcu::ScopedLogSection section		(m_testCtx.getLog(), "TreeDimensional", "3D");
+		glu::ShaderProgram			program		(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(s_computeSource3D));
+
+		m_testCtx.getLog() << program;
+		if (!program.isOk())
+			throw tcu::TestError("failed to build program");
+
+		verifyStateProgramIntegerVec3(result, gl, program.getProgram(), GL_COMPUTE_WORK_GROUP_SIZE, tcu::IVec3(3, 2, 4), m_verifier);
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class ActiveAtomicCounterBuffersCase : public TestCase
+{
+public:
+						ActiveAtomicCounterBuffersCase	(Context& context, QueryType verifier, const char* name, const char* desc);
+	IterateResult		iterate							(void);
+
+private:
+	const QueryType		m_verifier;
+};
+
+ActiveAtomicCounterBuffersCase::ActiveAtomicCounterBuffersCase (Context& context, QueryType verifier, const char* name, const char* desc)
+	: TestCase		(context, name, desc)
+	, m_verifier	(verifier)
+{
+}
+
+ActiveAtomicCounterBuffersCase::IterateResult ActiveAtomicCounterBuffersCase::iterate (void)
+{
+	static const char* const s_computeSource0 =	"#version 310 es\n"
+												"layout (local_size_x = 3) in;\n"
+												"layout(binding = 0) buffer Output\n"
+												"{\n"
+												"	highp float val;\n"
+												"} sb_out;\n"
+												"\n"
+												"void main (void)\n"
+												"{\n"
+												"	sb_out.val = 1.0;\n"
+												"}\n";
+	static const char* const s_computeSource1 =	"#version 310 es\n"
+												"layout (local_size_x = 3) in;\n"
+												"layout(binding = 0) uniform highp atomic_uint u_counters[2];\n"
+												"layout(binding = 0) buffer Output\n"
+												"{\n"
+												"	highp float val;\n"
+												"} sb_out;\n"
+												"\n"
+												"void main (void)\n"
+												"{\n"
+												"	sb_out.val = float(atomicCounterIncrement(u_counters[0])) + float(atomicCounterIncrement(u_counters[1]));\n"
+												"}\n";
+
+	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
+
+	gl.enableLogging(true);
+
+	{
+		const tcu::ScopedLogSection	section		(m_testCtx.getLog(), "Initial", "Initial");
+		glu::Program				program		(m_context.getRenderContext());
+
+		verifyStateProgramInteger(result, gl, program.getProgram(), GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, 0, m_verifier);
+	}
+
+	{
+		const tcu::ScopedLogSection	section		(m_testCtx.getLog(), "NoBuffers", "No buffers");
+		glu::ShaderProgram			program		(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(s_computeSource0));
+
+		m_testCtx.getLog() << program;
+		if (!program.isOk())
+			throw tcu::TestError("failed to build program");
+
+		verifyStateProgramInteger(result, gl, program.getProgram(), GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, 0, m_verifier);
+	}
+
+	{
+		const tcu::ScopedLogSection	section		(m_testCtx.getLog(), "OneBuffer", "One buffer");
+		glu::ShaderProgram			program		(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(s_computeSource1));
+
+		m_testCtx.getLog() << program;
+		if (!program.isOk())
+			throw tcu::TestError("failed to build program");
+
+		verifyStateProgramInteger(result, gl, program.getProgram(), GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, 1, m_verifier);
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+} // anonymous
+
+ProgramStateQueryTests::ProgramStateQueryTests (Context& context)
+	: TestCaseGroup(context, "program", "Program State Query tests")
+{
+}
+
+ProgramStateQueryTests::~ProgramStateQueryTests (void)
+{
+}
+
+void ProgramStateQueryTests::init (void)
+{
+	static const QueryType intVerifiers[] =
+	{
+		QUERY_PROGRAM_INTEGER,
+	};
+	static const QueryType intVec3Verifiers[] =
+	{
+		QUERY_PROGRAM_INTEGER_VEC3,
+	};
+
+#define FOR_EACH_INT_VERIFIER(X) \
+	for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(intVerifiers); ++verifierNdx)	\
+	{																							\
+		const char* verifierSuffix = getVerifierSuffix(intVerifiers[verifierNdx]);				\
+		const QueryType verifier = intVerifiers[verifierNdx];									\
+		this->addChild(X);																		\
+	}
+
+#define FOR_EACH_VEC_VERIFIER(X) \
+	for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(intVec3Verifiers); ++verifierNdx)	\
+	{																								\
+		const char* verifierSuffix = getVerifierSuffix(intVec3Verifiers[verifierNdx]);				\
+		const QueryType verifier = intVec3Verifiers[verifierNdx];									\
+		this->addChild(X);																			\
+	}
+
+	FOR_EACH_INT_VERIFIER(new ProgramSeparableCase				(m_context, verifier, (std::string("program_separable_") + verifierSuffix).c_str(),				"Test PROGRAM_SEPARABLE"));
+	FOR_EACH_VEC_VERIFIER(new ComputeWorkGroupSizeCase			(m_context, verifier, (std::string("compute_work_group_size_") + verifierSuffix).c_str(),		"Test COMPUTE_WORK_GROUP_SIZE"));
+	FOR_EACH_INT_VERIFIER(new ActiveAtomicCounterBuffersCase	(m_context, verifier, (std::string("active_atomic_counter_buffers_") + verifierSuffix).c_str(),	"Test ACTIVE_ATOMIC_COUNTER_BUFFERS"));
+
+#undef FOR_EACH_INT_VERIFIER
+#undef FOR_EACH_VEC_VERIFIER
+}
+
+} // Functional
+} // gles31
+} // deqp
diff --git a/modules/gles31/functional/es31fProgramStateQueryTests.hpp b/modules/gles31/functional/es31fProgramStateQueryTests.hpp
new file mode 100644
index 0000000..6bc0809
--- /dev/null
+++ b/modules/gles31/functional/es31fProgramStateQueryTests.hpp
@@ -0,0 +1,53 @@
+#ifndef _ES31FPROGRAMSTATEQUERYTESTS_HPP
+#define _ES31FPROGRAMSTATEQUERYTESTS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Program State Query tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tes31TestCase.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+
+class ProgramStateQueryTests : public TestCaseGroup
+{
+public:
+								ProgramStateQueryTests		(Context& context);
+								~ProgramStateQueryTests		(void);
+
+	void						init						(void);
+
+private:
+								ProgramStateQueryTests		(const ProgramStateQueryTests& other);
+	ProgramStateQueryTests&		operator=					(const ProgramStateQueryTests& other);
+};
+
+} // Functional
+} // gles31
+} // deqp
+
+#endif // _ES31FPROGRAMSTATEQUERYTESTS_HPP
diff --git a/modules/gles31/functional/es31fSampleShadingTests.cpp b/modules/gles31/functional/es31fSampleShadingTests.cpp
index 6daa5b9..a05b968 100644
--- a/modules/gles31/functional/es31fSampleShadingTests.cpp
+++ b/modules/gles31/functional/es31fSampleShadingTests.cpp
@@ -47,35 +47,24 @@
 namespace
 {
 
+using namespace gls::StateQueryUtil;
+
 class SampleShadingStateCase : public TestCase
 {
 public:
-	enum VerifierType
-	{
-		TYPE_IS_ENABLED = 0,
-		TYPE_GET_BOOLEAN,
-		TYPE_GET_INTEGER,
-		TYPE_GET_FLOAT,
-		TYPE_GET_INTEGER64,
-		TYPE_LAST
-	};
-
-						SampleShadingStateCase	(Context& ctx, const char* name, const char* desc, VerifierType);
+						SampleShadingStateCase	(Context& ctx, const char* name, const char* desc, QueryType);
 
 	void				init					(void);
 	IterateResult		iterate					(void);
 
 private:
-	bool				verify					(bool v);
-
-	const VerifierType	m_verifier;
+	const QueryType		m_verifier;
 };
 
-SampleShadingStateCase::SampleShadingStateCase (Context& ctx, const char* name, const char* desc, VerifierType type)
+SampleShadingStateCase::SampleShadingStateCase (Context& ctx, const char* name, const char* desc, QueryType type)
 	: TestCase		(ctx, name, desc)
 	, m_verifier	(type)
 {
-	DE_ASSERT(m_verifier < TYPE_LAST);
 }
 
 void SampleShadingStateCase::init (void)
@@ -86,16 +75,14 @@
 
 SampleShadingStateCase::IterateResult SampleShadingStateCase::iterate (void)
 {
-	bool				allOk	= true;
-	glu::CallLogWrapper gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
 	gl.enableLogging(true);
 
-	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
-
 	// initial
 	{
 		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying initial value" << tcu::TestLog::EndMessage;
-		allOk &= verify(false);
+		verifyStateBoolean(result, gl, GL_SAMPLE_SHADING, false, m_verifier);
 	}
 
 	// true and false too
@@ -103,132 +90,32 @@
 		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying random values" << tcu::TestLog::EndMessage;
 
 		gl.glEnable(GL_SAMPLE_SHADING);
-		allOk &= verify(true);
+		verifyStateBoolean(result, gl, GL_SAMPLE_SHADING, true, m_verifier);
 
 		gl.glDisable(GL_SAMPLE_SHADING);
-		allOk &= verify(false);
+		verifyStateBoolean(result, gl, GL_SAMPLE_SHADING, false, m_verifier);
 	}
 
-	if (!allOk && m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
-		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected value");
-
+	result.setTestContextResult(m_testCtx);
 	return STOP;
 }
 
-bool SampleShadingStateCase::verify (bool v)
-{
-	glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
-	gl.enableLogging(true);
-
-	switch (m_verifier)
-	{
-		case TYPE_IS_ENABLED:
-		{
-			const glw::GLboolean retVal = gl.glIsEnabled(GL_SAMPLE_SHADING);
-
-			if ((v && retVal==GL_TRUE) || (!v && retVal==GL_FALSE))
-				return true;
-
-			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << ((v) ? ("GL_TRUE") : ("GL_FALSE")) << ", got " << ((retVal == GL_TRUE) ? ("GL_TRUE") : (retVal == GL_FALSE) ? ("GL_FALSE") : ("not-a-boolean")) << tcu::TestLog::EndMessage;
-			return false;
-		}
-
-		case TYPE_GET_BOOLEAN:
-		{
-			gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLboolean> state;
-			gl.glGetBooleanv(GL_SAMPLE_SHADING, &state);
-
-			if (!state.verifyValidity(m_testCtx))
-				return false;
-
-			if ((v && state==GL_TRUE) || (!v && state==GL_FALSE))
-				return true;
-
-			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << ((v) ? ("GL_TRUE") : ("GL_FALSE")) << ", got " << ((state == GL_TRUE) ? ("GL_TRUE") : (state == GL_FALSE) ? ("GL_FALSE") : ("not-a-boolean")) << tcu::TestLog::EndMessage;
-			return false;
-		}
-
-		case TYPE_GET_INTEGER:
-		{
-			gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint> state;
-			gl.glGetIntegerv(GL_SAMPLE_SHADING, &state);
-
-			if (!state.verifyValidity(m_testCtx))
-				return false;
-
-			if ((v && state==1) || (!v && state==0))
-				return true;
-
-			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << ((v) ? ("1") : ("0")) << ", got " << state << tcu::TestLog::EndMessage;
-			return false;
-		}
-
-		case TYPE_GET_FLOAT:
-		{
-			gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLfloat> state;
-			gl.glGetFloatv(GL_SAMPLE_SHADING, &state);
-
-			if (!state.verifyValidity(m_testCtx))
-				return false;
-
-			if ((v && state==1.0f) || (!v && state==0.0f))
-				return true;
-
-			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << ((v) ? ("1.0") : ("0.0")) << ", got " << state << tcu::TestLog::EndMessage;
-			return false;
-		}
-
-		case TYPE_GET_INTEGER64:
-		{
-			gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint64> state;
-			gl.glGetInteger64v(GL_SAMPLE_SHADING, &state);
-
-			if (!state.verifyValidity(m_testCtx))
-				return false;
-
-			if ((v && state==1) || (!v && state==0))
-				return true;
-
-			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << ((v) ? ("1") : ("0")) << ", got " << state << tcu::TestLog::EndMessage;
-			return false;
-		}
-
-		default:
-		{
-			DE_ASSERT(false);
-			return false;
-		}
-	}
-}
-
 class MinSampleShadingValueCase : public TestCase
 {
 public:
-	enum VerifierType
-	{
-		TYPE_GET_BOOLEAN = 0,
-		TYPE_GET_INTEGER,
-		TYPE_GET_FLOAT,
-		TYPE_GET_INTEGER64,
-		TYPE_LAST
-	};
-
-						MinSampleShadingValueCase	(Context& ctx, const char* name, const char* desc, VerifierType);
+						MinSampleShadingValueCase	(Context& ctx, const char* name, const char* desc, QueryType);
 
 	void				init						(void);
 	IterateResult		iterate						(void);
 
 private:
-	bool				verify						(float v);
-
-	const VerifierType	m_verifier;
+	const QueryType		m_verifier;
 };
 
-MinSampleShadingValueCase::MinSampleShadingValueCase (Context& ctx, const char* name, const char* desc, VerifierType type)
+MinSampleShadingValueCase::MinSampleShadingValueCase (Context& ctx, const char* name, const char* desc, QueryType type)
 	: TestCase		(ctx, name, desc)
 	, m_verifier	(type)
 {
-	DE_ASSERT(m_verifier < TYPE_LAST);
 }
 
 void MinSampleShadingValueCase::init (void)
@@ -239,16 +126,15 @@
 
 MinSampleShadingValueCase::IterateResult MinSampleShadingValueCase::iterate (void)
 {
-	bool				allOk	= true;
-	glu::CallLogWrapper gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
-	gl.enableLogging(true);
+	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
 
-	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+	gl.enableLogging(true);
 
 	// initial
 	{
 		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying initial value" << tcu::TestLog::EndMessage;
-		allOk &= verify(0.0);
+		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 0.0, m_verifier);
 	}
 
 	// special values
@@ -256,13 +142,13 @@
 		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying special values" << tcu::TestLog::EndMessage;
 
 		gl.glMinSampleShading(0.0f);
-		allOk &= verify(0.0);
+		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 0.0, m_verifier);
 
 		gl.glMinSampleShading(1.0f);
-		allOk &= verify(1.0);
+		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 1.0, m_verifier);
 
 		gl.glMinSampleShading(0.5f);
-		allOk &= verify(0.5);
+		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 0.5, m_verifier);
 	}
 
 	// random values
@@ -277,91 +163,14 @@
 			const float value = rnd.getFloat();
 
 			gl.glMinSampleShading(value);
-			allOk &= verify(value);
+			verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, value, m_verifier);
 		}
 	}
 
-	if (!allOk && m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
-		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected value");
-
+	result.setTestContextResult(m_testCtx);
 	return STOP;
 }
 
-bool MinSampleShadingValueCase::verify (float v)
-{
-	glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
-	gl.enableLogging(true);
-
-	switch (m_verifier)
-	{
-		case TYPE_GET_BOOLEAN:
-		{
-			gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLboolean> state;
-			gl.glGetBooleanv(GL_MIN_SAMPLE_SHADING_VALUE, &state);
-
-			if (!state.verifyValidity(m_testCtx))
-				return false;
-
-			if ((v!=0.0f && state==GL_TRUE) || (v==0.0f && state==GL_FALSE))
-				return true;
-
-			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << ((v!=0.0f) ? ("GL_TRUE") : ("GL_FALSE")) << ", got " << ((state == GL_TRUE) ? ("GL_TRUE") : (state == GL_FALSE) ? ("GL_FALSE") : ("not-a-boolean")) << tcu::TestLog::EndMessage;
-			return false;
-		}
-
-		case TYPE_GET_INTEGER:
-		{
-			gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint> state;
-			gl.glGetIntegerv(GL_MIN_SAMPLE_SHADING_VALUE, &state);
-
-			if (!state.verifyValidity(m_testCtx))
-				return false;
-
-			if ((v>=0.5f && state==1) || (v<=0.5f && state==0))
-				return true;
-
-			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << ((v==0.5) ? ("0 or 1") : (v<0.5) ? ("0") : ("1")) << ", got " << state << tcu::TestLog::EndMessage;
-			return false;
-		}
-
-		case TYPE_GET_FLOAT:
-		{
-			gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLfloat> state;
-			gl.glGetFloatv(GL_MIN_SAMPLE_SHADING_VALUE, &state);
-
-			if (!state.verifyValidity(m_testCtx))
-				return false;
-
-			if (v == state)
-				return true;
-
-			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << v << ", got " << state << tcu::TestLog::EndMessage;
-			return false;
-		}
-
-		case TYPE_GET_INTEGER64:
-		{
-			gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint64> state;
-			gl.glGetInteger64v(GL_MIN_SAMPLE_SHADING_VALUE, &state);
-
-			if (!state.verifyValidity(m_testCtx))
-				return false;
-
-			if ((v>=0.5f && state==1) || (v<=0.5f && state==0))
-				return true;
-
-			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << ((v==0.5) ? ("0 or 1") : (v<0.5) ? ("0") : ("1")) << ", got " << state << tcu::TestLog::EndMessage;
-			return false;
-		}
-
-		default:
-		{
-			DE_ASSERT(false);
-			return false;
-		}
-	}
-}
-
 class MinSampleShadingValueClampingCase : public TestCase
 {
 public:
@@ -369,9 +178,6 @@
 
 	void				init								(void);
 	IterateResult		iterate								(void);
-
-private:
-	bool				verify								(float v);
 };
 
 MinSampleShadingValueClampingCase::MinSampleShadingValueClampingCase (Context& ctx, const char* name, const char* desc)
@@ -387,8 +193,8 @@
 
 MinSampleShadingValueClampingCase::IterateResult MinSampleShadingValueClampingCase::iterate (void)
 {
-	bool				allOk	= true;
-	glu::CallLogWrapper gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
 	gl.enableLogging(true);
 
 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
@@ -398,49 +204,28 @@
 		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying clamped values. Value is clamped when specified." << tcu::TestLog::EndMessage;
 
 		gl.glMinSampleShading(-0.5f);
-		allOk &= verify(0.0);
+		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 0.0, QUERY_FLOAT);
 
 		gl.glMinSampleShading(-1.0f);
-		allOk &= verify(0.0);
+		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 0.0, QUERY_FLOAT);
 
 		gl.glMinSampleShading(-1.5f);
-		allOk &= verify(0.0);
+		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 0.0, QUERY_FLOAT);
 
 		gl.glMinSampleShading(1.5f);
-		allOk &= verify(1.0);
+		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 1.0, QUERY_FLOAT);
 
 		gl.glMinSampleShading(2.0f);
-		allOk &= verify(1.0);
+		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 1.0, QUERY_FLOAT);
 
 		gl.glMinSampleShading(2.5f);
-		allOk &= verify(1.0);
+		verifyStateFloat(result, gl, GL_MIN_SAMPLE_SHADING_VALUE, 1.0, QUERY_FLOAT);
 	}
 
-	if (!allOk && m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
-		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected value");
-
+	result.setTestContextResult(m_testCtx);
 	return STOP;
 }
 
-bool MinSampleShadingValueClampingCase::verify (float v)
-{
-	glu::CallLogWrapper												gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
-	gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLfloat>	state;
-
-	gl.enableLogging(true);
-
-	gl.glGetFloatv(GL_MIN_SAMPLE_SHADING_VALUE, &state);
-
-	if (!state.verifyValidity(m_testCtx))
-		return false;
-
-	if (v == state)
-		return true;
-
-	m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << v << ", got " << state << tcu::TestLog::EndMessage;
-	return false;
-}
-
 class SampleShadingRenderingCase : public MultisampleShaderRenderUtil::MultisampleRenderCase
 {
 public:
@@ -666,15 +451,15 @@
 
 	// .state query
 	{
-		stateQueryGroup->addChild(new SampleShadingStateCase			(m_context, "sample_shading_is_enabled",				"test SAMPLE_SHADING",						SampleShadingStateCase::TYPE_IS_ENABLED));
-		stateQueryGroup->addChild(new SampleShadingStateCase			(m_context, "sample_shading_get_boolean",				"test SAMPLE_SHADING",						SampleShadingStateCase::TYPE_GET_BOOLEAN));
-		stateQueryGroup->addChild(new SampleShadingStateCase			(m_context, "sample_shading_get_integer",				"test SAMPLE_SHADING",						SampleShadingStateCase::TYPE_GET_INTEGER));
-		stateQueryGroup->addChild(new SampleShadingStateCase			(m_context, "sample_shading_get_float",					"test SAMPLE_SHADING",						SampleShadingStateCase::TYPE_GET_FLOAT));
-		stateQueryGroup->addChild(new SampleShadingStateCase			(m_context, "sample_shading_get_integer64",				"test SAMPLE_SHADING",						SampleShadingStateCase::TYPE_GET_INTEGER64));
-		stateQueryGroup->addChild(new MinSampleShadingValueCase			(m_context, "min_sample_shading_value_get_boolean",		"test MIN_SAMPLE_SHADING_VALUE",			MinSampleShadingValueCase::TYPE_GET_BOOLEAN));
-		stateQueryGroup->addChild(new MinSampleShadingValueCase			(m_context, "min_sample_shading_value_get_integer",		"test MIN_SAMPLE_SHADING_VALUE",			MinSampleShadingValueCase::TYPE_GET_INTEGER));
-		stateQueryGroup->addChild(new MinSampleShadingValueCase			(m_context, "min_sample_shading_value_get_float",		"test MIN_SAMPLE_SHADING_VALUE",			MinSampleShadingValueCase::TYPE_GET_FLOAT));
-		stateQueryGroup->addChild(new MinSampleShadingValueCase			(m_context, "min_sample_shading_value_get_integer64",	"test MIN_SAMPLE_SHADING_VALUE",			MinSampleShadingValueCase::TYPE_GET_INTEGER64));
+		stateQueryGroup->addChild(new SampleShadingStateCase			(m_context, "sample_shading_is_enabled",				"test SAMPLE_SHADING",						QUERY_ISENABLED));
+		stateQueryGroup->addChild(new SampleShadingStateCase			(m_context, "sample_shading_get_boolean",				"test SAMPLE_SHADING",						QUERY_BOOLEAN));
+		stateQueryGroup->addChild(new SampleShadingStateCase			(m_context, "sample_shading_get_integer",				"test SAMPLE_SHADING",						QUERY_INTEGER));
+		stateQueryGroup->addChild(new SampleShadingStateCase			(m_context, "sample_shading_get_float",					"test SAMPLE_SHADING",						QUERY_FLOAT));
+		stateQueryGroup->addChild(new SampleShadingStateCase			(m_context, "sample_shading_get_integer64",				"test SAMPLE_SHADING",						QUERY_INTEGER64));
+		stateQueryGroup->addChild(new MinSampleShadingValueCase			(m_context, "min_sample_shading_value_get_boolean",		"test MIN_SAMPLE_SHADING_VALUE",			QUERY_BOOLEAN));
+		stateQueryGroup->addChild(new MinSampleShadingValueCase			(m_context, "min_sample_shading_value_get_integer",		"test MIN_SAMPLE_SHADING_VALUE",			QUERY_INTEGER));
+		stateQueryGroup->addChild(new MinSampleShadingValueCase			(m_context, "min_sample_shading_value_get_float",		"test MIN_SAMPLE_SHADING_VALUE",			QUERY_FLOAT));
+		stateQueryGroup->addChild(new MinSampleShadingValueCase			(m_context, "min_sample_shading_value_get_integer64",	"test MIN_SAMPLE_SHADING_VALUE",			QUERY_INTEGER64));
 		stateQueryGroup->addChild(new MinSampleShadingValueClampingCase	(m_context, "min_sample_shading_value_clamping",		"test MIN_SAMPLE_SHADING_VALUE clamping"));
 	}
 
diff --git a/modules/gles31/functional/es31fShaderMultisampleInterpolationStateQueryTests.cpp b/modules/gles31/functional/es31fShaderMultisampleInterpolationStateQueryTests.cpp
index 2d19aa6..64fa4ed 100644
--- a/modules/gles31/functional/es31fShaderMultisampleInterpolationStateQueryTests.cpp
+++ b/modules/gles31/functional/es31fShaderMultisampleInterpolationStateQueryTests.cpp
@@ -40,207 +40,7 @@
 namespace
 {
 
-enum VerifierType
-{
-	VERIFIER_GET_BOOLEAN = 0,
-	VERIFIER_GET_INTEGER,
-	VERIFIER_GET_FLOAT,
-	VERIFIER_GET_INTEGER64,
-};
-
-static void verifyGreaterOrEqual (VerifierType verifier, glw::GLenum target, float minValue, Context& context)
-{
-	glu::CallLogWrapper gl(context.getRenderContext().getFunctions(), context.getTestContext().getLog());
-
-	gl.enableLogging(true);
-
-	switch (verifier)
-	{
-		case VERIFIER_GET_BOOLEAN:
-		{
-			gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLboolean>	value;
-
-			gl.glGetBooleanv(target, &value);
-			GLU_EXPECT_NO_ERROR(gl.glGetError(), "getBoolean");
-
-			if (!value.verifyValidity(context.getTestContext()))
-				return;
-			if (value != GL_TRUE && value != GL_FALSE)
-			{
-				context.getTestContext().getLog() << tcu::TestLog::Message << "Returned value is not a boolean"<< tcu::TestLog::EndMessage;
-				context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Got invalid boolean");
-				return;
-			}
-
-			if (value > 0.0f && value == GL_FALSE)
-			{
-				context.getTestContext().getLog() << tcu::TestLog::Message << "Expected GL_TRUE, got GL_FALSE" << tcu::TestLog::EndMessage;
-				context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Got invalid value");
-			}
-			break;
-		}
-
-		case VERIFIER_GET_INTEGER:
-		{
-			const glw::GLint											refValue = (glw::GLint)deFloatFloor(minValue);
-			gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint>	value;
-
-			gl.glGetIntegerv(target, &value);
-			GLU_EXPECT_NO_ERROR(gl.glGetError(), "getInteger");
-
-			if (!value.verifyValidity(context.getTestContext()))
-				return;
-
-			context.getTestContext().getLog() << tcu::TestLog::Message << "Expecting greater or equal to " << refValue << ", got " << value << tcu::TestLog::EndMessage;
-			if (value < refValue)
-			{
-				context.getTestContext().getLog() << tcu::TestLog::Message << "Value not in valid range" << tcu::TestLog::EndMessage;
-				context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Got invalid value");
-			}
-			break;
-		}
-
-		case VERIFIER_GET_FLOAT:
-		{
-			const float														refValue = minValue;
-			gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLfloat>	value;
-
-			gl.glGetFloatv(target, &value);
-			GLU_EXPECT_NO_ERROR(gl.glGetError(), "getFloat");
-
-			if (!value.verifyValidity(context.getTestContext()))
-				return;
-
-			context.getTestContext().getLog() << tcu::TestLog::Message << "Expecting greater or equal to " << refValue << ", got " << value << tcu::TestLog::EndMessage;
-			if (value < refValue)
-			{
-				context.getTestContext().getLog() << tcu::TestLog::Message << "Value not in valid range" << tcu::TestLog::EndMessage;
-				context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Got invalid value");
-			}
-			break;
-		}
-
-		case VERIFIER_GET_INTEGER64:
-		{
-			const glw::GLint64												refValue = (glw::GLint64)deFloatFloor(minValue);
-			gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint64>	value;
-
-			gl.glGetInteger64v(target, &value);
-			GLU_EXPECT_NO_ERROR(gl.glGetError(), "getInteger64");
-
-			if (!value.verifyValidity(context.getTestContext()))
-				return;
-
-			context.getTestContext().getLog() << tcu::TestLog::Message << "Expecting greater or equal to " << refValue << ", got " << value << tcu::TestLog::EndMessage;
-			if (value < refValue)
-			{
-				context.getTestContext().getLog() << tcu::TestLog::Message << "Value not in valid range" << tcu::TestLog::EndMessage;
-				context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Got invalid value");
-			}
-			break;
-		}
-
-		default:
-			DE_ASSERT(false);
-	}
-}
-
-static void verifyLessOrEqual (VerifierType verifier, glw::GLenum target, float minValue, Context& context)
-{
-	glu::CallLogWrapper gl(context.getRenderContext().getFunctions(), context.getTestContext().getLog());
-
-	gl.enableLogging(true);
-
-	switch (verifier)
-	{
-		case VERIFIER_GET_BOOLEAN:
-		{
-			gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLboolean>	value;
-
-			gl.glGetBooleanv(target, &value);
-			GLU_EXPECT_NO_ERROR(gl.glGetError(), "getBoolean");
-
-			if (!value.verifyValidity(context.getTestContext()))
-				return;
-			if (value != GL_TRUE && value != GL_FALSE)
-			{
-				context.getTestContext().getLog() << tcu::TestLog::Message << "Returned value is not a boolean"<< tcu::TestLog::EndMessage;
-				context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Got invalid boolean");
-				return;
-			}
-
-			if (value < 0.0f && value == GL_FALSE)
-			{
-				context.getTestContext().getLog() << tcu::TestLog::Message << "Expected GL_TRUE, got GL_FALSE" << tcu::TestLog::EndMessage;
-				context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Got invalid value");
-			}
-			break;
-		}
-
-		case VERIFIER_GET_INTEGER:
-		{
-			const glw::GLint											refValue = (glw::GLint)deFloatCeil(minValue);
-			gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint>	value;
-
-			gl.glGetIntegerv(target, &value);
-			GLU_EXPECT_NO_ERROR(gl.glGetError(), "getInteger");
-
-			if (!value.verifyValidity(context.getTestContext()))
-				return;
-
-			context.getTestContext().getLog() << tcu::TestLog::Message << "Expecting less or equal to " << refValue << ", got " << value << tcu::TestLog::EndMessage;
-			if (value > refValue)
-			{
-				context.getTestContext().getLog() << tcu::TestLog::Message << "Value not in valid range" << tcu::TestLog::EndMessage;
-				context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Got invalid value");
-			}
-			break;
-		}
-
-		case VERIFIER_GET_FLOAT:
-		{
-			const float														refValue = minValue;
-			gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLfloat>	value;
-
-			gl.glGetFloatv(target, &value);
-			GLU_EXPECT_NO_ERROR(gl.glGetError(), "getFloat");
-
-			if (!value.verifyValidity(context.getTestContext()))
-				return;
-
-			context.getTestContext().getLog() << tcu::TestLog::Message << "Expecting greater or equal to " << refValue << ", got " << value << tcu::TestLog::EndMessage;
-			if (value > refValue)
-			{
-				context.getTestContext().getLog() << tcu::TestLog::Message << "Value not in valid range" << tcu::TestLog::EndMessage;
-				context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Got invalid value");
-			}
-			break;
-		}
-
-		case VERIFIER_GET_INTEGER64:
-		{
-			const glw::GLint64												refValue = (glw::GLint64)deFloatCeil(minValue);
-			gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint64>	value;
-
-			gl.glGetInteger64v(target, &value);
-			GLU_EXPECT_NO_ERROR(gl.glGetError(), "getInteger64");
-
-			if (!value.verifyValidity(context.getTestContext()))
-				return;
-
-			context.getTestContext().getLog() << tcu::TestLog::Message << "Expecting greater or equal to " << refValue << ", got " << value << tcu::TestLog::EndMessage;
-			if (value > refValue)
-			{
-				context.getTestContext().getLog() << tcu::TestLog::Message << "Value not in valid range" << tcu::TestLog::EndMessage;
-				context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Got invalid value");
-			}
-			break;
-		}
-
-		default:
-			DE_ASSERT(false);
-	}
-}
+using namespace gls::StateQueryUtil;
 
 class InterpolationOffsetCase : public TestCase
 {
@@ -253,18 +53,18 @@
 		TEST_LAST
 	};
 
-						InterpolationOffsetCase		(Context& context, const char* name, const char* desc, VerifierType verifier, TestType testType);
+						InterpolationOffsetCase		(Context& context, const char* name, const char* desc, QueryType verifier, TestType testType);
 						~InterpolationOffsetCase	(void);
 
 	void				init						(void);
 	IterateResult		iterate						(void);
 
 private:
-	const VerifierType	m_verifier;
+	const QueryType		m_verifier;
 	const TestType		m_testType;
 };
 
-InterpolationOffsetCase::InterpolationOffsetCase (Context& context, const char* name, const char* desc, VerifierType verifier, TestType testType)
+InterpolationOffsetCase::InterpolationOffsetCase (Context& context, const char* name, const char* desc, QueryType verifier, TestType testType)
 	: TestCase		(context, name, desc)
 	, m_verifier	(verifier)
 	, m_testType	(testType)
@@ -284,32 +84,35 @@
 
 InterpolationOffsetCase::IterateResult InterpolationOffsetCase::iterate (void)
 {
-	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+	glu::CallLogWrapper 	gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
+	gl.enableLogging(true);
 
 	if (m_testType == TEST_MAX_OFFSET)
-		verifyGreaterOrEqual(m_verifier, GL_MAX_FRAGMENT_INTERPOLATION_OFFSET, 0.5, m_context);
+		verifyStateFloatMin(result, gl, GL_MAX_FRAGMENT_INTERPOLATION_OFFSET, 0.5, m_verifier);
 	else if (m_testType == TEST_MIN_OFFSET)
-		verifyLessOrEqual(m_verifier, GL_MIN_FRAGMENT_INTERPOLATION_OFFSET, -0.5, m_context);
+		verifyStateFloatMax(result, gl, GL_MIN_FRAGMENT_INTERPOLATION_OFFSET, -0.5, m_verifier);
 	else
 		DE_ASSERT(false);
 
+	result.setTestContextResult(m_testCtx);
 	return STOP;
 }
 
 class FragmentInterpolationOffsetBitsCase : public TestCase
 {
 public:
-						FragmentInterpolationOffsetBitsCase		(Context& context, const char* name, const char* desc, VerifierType verifier);
+						FragmentInterpolationOffsetBitsCase		(Context& context, const char* name, const char* desc, QueryType verifier);
 						~FragmentInterpolationOffsetBitsCase	(void);
 
 	void				init									(void);
 	IterateResult		iterate									(void);
 
 private:
-	const VerifierType	m_verifier;
+	const QueryType		m_verifier;
 };
 
-FragmentInterpolationOffsetBitsCase::FragmentInterpolationOffsetBitsCase (Context& context, const char* name, const char* desc, VerifierType verifier)
+FragmentInterpolationOffsetBitsCase::FragmentInterpolationOffsetBitsCase (Context& context, const char* name, const char* desc, QueryType verifier)
 	: TestCase		(context, name, desc)
 	, m_verifier	(verifier)
 {
@@ -327,8 +130,13 @@
 
 FragmentInterpolationOffsetBitsCase::IterateResult FragmentInterpolationOffsetBitsCase::iterate (void)
 {
-	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
-	verifyGreaterOrEqual(m_verifier, GL_FRAGMENT_INTERPOLATION_OFFSET_BITS, 4.0, m_context);
+	glu::CallLogWrapper 	gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
+	gl.enableLogging(true);
+
+	verifyStateIntegerMin(result, gl, GL_FRAGMENT_INTERPOLATION_OFFSET_BITS, 4, m_verifier);
+
+	result.setTestContextResult(m_testCtx);
 	return STOP;
 }
 
@@ -347,15 +155,15 @@
 {
 	static const struct Verifier
 	{
-		VerifierType	verifier;
+		QueryType		verifier;
 		const char*		name;
 		const char*		desc;
 	} verifiers[] =
 	{
-		{ VERIFIER_GET_BOOLEAN,		"get_boolean",		"Test using getBoolean"		},
-		{ VERIFIER_GET_INTEGER,		"get_integer",		"Test using getInteger"		},
-		{ VERIFIER_GET_FLOAT,		"get_float",		"Test using getFloat"		},
-		{ VERIFIER_GET_INTEGER64,	"get_integer64",	"Test using getInteger64"	},
+		{ QUERY_BOOLEAN,	"get_boolean",		"Test using getBoolean"		},
+		{ QUERY_INTEGER,	"get_integer",		"Test using getInteger"		},
+		{ QUERY_FLOAT,		"get_float",		"Test using getFloat"		},
+		{ QUERY_INTEGER64,	"get_integer64",	"Test using getInteger64"	},
 	};
 
 	// .min_fragment_interpolation_offset
diff --git a/modules/gles31/functional/es31fTextureLevelStateQueryTests.cpp b/modules/gles31/functional/es31fTextureLevelStateQueryTests.cpp
index bbd5119..2c202d1 100644
--- a/modules/gles31/functional/es31fTextureLevelStateQueryTests.cpp
+++ b/modules/gles31/functional/es31fTextureLevelStateQueryTests.cpp
@@ -33,6 +33,7 @@
 #include "glwEnums.hpp"
 #include "deStringUtil.hpp"
 #include "tcuTextureUtil.hpp"
+#include "tcuFormatUtil.hpp"
 
 namespace deqp
 {
@@ -43,11 +44,7 @@
 namespace
 {
 
-enum VerifierType
-{
-	VERIFIER_INT = 0,
-	VERIFIER_FLOAT
-};
+using namespace gls::StateQueryUtil;
 
 struct TextureGenerationSpec
 {
@@ -99,132 +96,53 @@
 };
 
 template <typename Printer>
-static bool verifyTextureLevelParameterEqualWithPrinter (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, int refValue, VerifierType type)
+static bool verifyTextureLevelParameterEqualWithPrinter (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, int refValue, QueryType type)
 {
+	QueriedState			state;
+	tcu::ResultCollector	result	(gl.getLog(), " // ERROR: ");
+
 	gl.getLog() << tcu::TestLog::Message << "Verifying " << glu::getTextureLevelParameterStr(pname) << ", expecting " << Printer::getIntegerName(refValue) << tcu::TestLog::EndMessage;
+	queryTextureLevelState(result, gl, type, target, level, pname, state);
 
-	if (type == VERIFIER_INT)
-	{
-		gls::StateQueryUtil::StateQueryMemoryWriteGuard<int> result;
-
-		gl.glGetTexLevelParameteriv(target, level, pname, &result);
-		GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetTexLevelParameteriv");
-
-		if (result.isUndefined())
-		{
-			gl.getLog() << tcu::TestLog::Message << "Error: Get* did not write a value." << tcu::TestLog::EndMessage;
-			return false;
-		}
-		else if (result.isMemoryContaminated())
-		{
-			gl.getLog() << tcu::TestLog::Message << "Error: detected illegal memory write." << tcu::TestLog::EndMessage;
-			return false;
-		}
-
-		if (result == refValue)
-			return true;
-
-		gl.getLog() << tcu::TestLog::Message << "Error: Expected " << Printer::getIntegerName(refValue) << ", got " << Printer::getIntegerName(result) << tcu::TestLog::EndMessage;
+	if (state.isUndefined())
 		return false;
-	}
-	else if (type == VERIFIER_FLOAT)
-	{
-		gls::StateQueryUtil::StateQueryMemoryWriteGuard<float> result;
 
-		gl.glGetTexLevelParameterfv(target, level, pname, &result);
-		GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetTexLevelParameterfv");
+	verifyInteger(result, state, refValue);
 
-		if (result.isUndefined())
-		{
-			gl.getLog() << tcu::TestLog::Message << "Error: Get* did not write a value." << tcu::TestLog::EndMessage;
-			return false;
-		}
-		else if (result.isMemoryContaminated())
-		{
-			gl.getLog() << tcu::TestLog::Message << "Error: detected illegal memory write." << tcu::TestLog::EndMessage;
-			return false;
-		}
-
-		if (result == (float)refValue)
-			return true;
-
-		gl.getLog() << tcu::TestLog::Message << "Error: Expected " << Printer::getIntegerName(refValue) << ", got " << Printer::getFloatName(result) << tcu::TestLog::EndMessage;
-		return false;
-	}
-
-	DE_ASSERT(DE_FALSE);
-	return false;
+	return result.getResult() == QP_TEST_RESULT_LAST;
 }
 
-static bool verifyTextureLevelParameterEqual (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, int refValue, VerifierType type)
+static bool verifyTextureLevelParameterEqual (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, int refValue, QueryType type)
 {
 	return verifyTextureLevelParameterEqualWithPrinter<IntegerPrinter>(gl, target, level, pname, refValue, type);
 }
 
-static bool verifyTextureLevelParameterInternalFormatEqual (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, int refValue, VerifierType type)
+static bool verifyTextureLevelParameterInternalFormatEqual (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, int refValue, QueryType type)
 {
 	return verifyTextureLevelParameterEqualWithPrinter<PixelFormatPrinter>(gl, target, level, pname, refValue, type);
 }
 
-static bool verifyTextureLevelParameterGreaterOrEqual (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, int refValue, VerifierType type)
+static bool verifyTextureLevelParameterGreaterOrEqual (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, int refValue, QueryType type)
 {
+	QueriedState			state;
+	tcu::ResultCollector	result	(gl.getLog(), " // ERROR: ");
+
 	gl.getLog() << tcu::TestLog::Message << "Verifying " << glu::getTextureLevelParameterStr(pname) << ", expecting " << refValue << " or greater" << tcu::TestLog::EndMessage;
+	queryTextureLevelState(result, gl, type, target, level, pname, state);
 
-	if (type == VERIFIER_INT)
-	{
-		gls::StateQueryUtil::StateQueryMemoryWriteGuard<int> result;
-
-		gl.glGetTexLevelParameteriv(target, level, pname, &result);
-		GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetTexLevelParameteriv");
-
-		if (result.isUndefined())
-		{
-			gl.getLog() << tcu::TestLog::Message << "Error: Get* did not write a value." << tcu::TestLog::EndMessage;
-			return false;
-		}
-		else if (result.isMemoryContaminated())
-		{
-			gl.getLog() << tcu::TestLog::Message << "Error: detected illegal memory write." << tcu::TestLog::EndMessage;
-			return false;
-		}
-
-		if (result >= refValue)
-			return true;
-
-		gl.getLog() << tcu::TestLog::Message << "Error: Expected " << refValue << " or larger, got " << result << tcu::TestLog::EndMessage;
+	if (state.isUndefined())
 		return false;
-	}
-	else if (type == VERIFIER_FLOAT)
-	{
-		gls::StateQueryUtil::StateQueryMemoryWriteGuard<float> result;
 
-		gl.glGetTexLevelParameterfv(target, level, pname, &result);
-		GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetTexLevelParameterfv");
+	verifyIntegerMin(result, state, refValue);
 
-		if (result.isUndefined())
-		{
-			gl.getLog() << tcu::TestLog::Message << "Error: Get* did not write a value." << tcu::TestLog::EndMessage;
-			return false;
-		}
-		else if (result.isMemoryContaminated())
-		{
-			gl.getLog() << tcu::TestLog::Message << "Error: detected illegal memory write." << tcu::TestLog::EndMessage;
-			return false;
-		}
-
-		if (result >= (float)refValue)
-			return true;
-
-		gl.getLog() << tcu::TestLog::Message << "Error: Expected " << refValue << " or larger, got " << result << tcu::TestLog::EndMessage;
-		return false;
-	}
-
-	DE_ASSERT(DE_FALSE);
-	return false;
+	return result.getResult() == QP_TEST_RESULT_LAST;
 }
 
-static bool verifyTextureLevelParameterInternalFormatAnyOf (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, const int* refValues, int numRefValues, VerifierType type)
+static bool verifyTextureLevelParameterInternalFormatAnyOf (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, const int* refValues, int numRefValues, QueryType type)
 {
+	QueriedState			state;
+	tcu::ResultCollector	result	(gl.getLog(), " // ERROR: ");
+
 	// Log what we try to do
 	{
 		tcu::MessageBuilder msg(&gl.getLog());
@@ -240,61 +158,35 @@
 		msg << tcu::TestLog::EndMessage;
 	}
 
+	queryTextureLevelState(result, gl, type, target, level, pname, state);
+	if (state.isUndefined())
+		return false;
+
 	// verify
-	if (type == VERIFIER_INT)
+	switch (state.getType())
 	{
-		gls::StateQueryUtil::StateQueryMemoryWriteGuard<int> result;
-
-		gl.glGetTexLevelParameteriv(target, level, pname, &result);
-		GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetTexLevelParameteriv");
-
-		if (result.isUndefined())
+		case DATATYPE_INTEGER:
 		{
-			gl.getLog() << tcu::TestLog::Message << "Error: Get* did not write a value." << tcu::TestLog::EndMessage;
+			for (int ndx = 0; ndx < numRefValues; ++ndx)
+				if (state.getIntAccess() == refValues[ndx])
+					return true;
+
+			gl.getLog() << tcu::TestLog::Message << "Error: got " << state.getIntAccess() << ", (" << glu::getPixelFormatStr(state.getIntAccess()) << ")" << tcu::TestLog::EndMessage;
 			return false;
 		}
-		else if (result.isMemoryContaminated())
+		case DATATYPE_FLOAT:
 		{
-			gl.getLog() << tcu::TestLog::Message << "Error: detected illegal memory write." << tcu::TestLog::EndMessage;
+			for (int ndx = 0; ndx < numRefValues; ++ndx)
+				if (state.getFloatAccess() == (float)refValues[ndx])
+					return true;
+
+			gl.getLog() << tcu::TestLog::Message << "Error: got " << state.getFloatAccess() << ", (" << glu::getPixelFormatStr((int)state.getFloatAccess()) << ")" << tcu::TestLog::EndMessage;
 			return false;
 		}
-
-		for (int ndx = 0; ndx < numRefValues; ++ndx)
-			if (result == refValues[ndx])
-				return true;
-
-		gl.getLog() << tcu::TestLog::Message << "Error: got " << result << ", (" << glu::getPixelFormatStr(result) << ")" << tcu::TestLog::EndMessage;
-		return false;
+		default:
+			DE_ASSERT(DE_FALSE);
+			return false;
 	}
-	else if (type == VERIFIER_FLOAT)
-	{
-		gls::StateQueryUtil::StateQueryMemoryWriteGuard<float> result;
-
-		gl.glGetTexLevelParameterfv(target, level, pname, &result);
-		GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetTexLevelParameterfv");
-
-		if (result.isUndefined())
-		{
-			gl.getLog() << tcu::TestLog::Message << "Error: Get* did not write a value." << tcu::TestLog::EndMessage;
-			return false;
-		}
-		else if (result.isMemoryContaminated())
-		{
-			gl.getLog() << tcu::TestLog::Message << "Error: detected illegal memory write." << tcu::TestLog::EndMessage;
-			return false;
-		}
-
-		for (int ndx = 0; ndx < numRefValues; ++ndx)
-			if (result == (float)refValues[ndx])
-				return true;
-
-		gl.getLog() << tcu::TestLog::Message << "Error: got " << result << ", (" << glu::getPixelFormatStr((int)result) << ")" << tcu::TestLog::EndMessage;
-		return false;
-	}
-
-	DE_ASSERT(DE_FALSE);
-	return false;
-
 }
 
 static void generateColorTextureGenerationGroup (std::vector<TextureGenerationSpec>& group, int max2DSamples, int max2DArraySamples, glw::GLenum internalFormat)
@@ -681,7 +573,7 @@
 class TextureLevelCase : public TestCase
 {
 public:
-										TextureLevelCase		(Context& ctx, const char* name, const char* desc, VerifierType type);
+										TextureLevelCase		(Context& ctx, const char* name, const char* desc, QueryType type);
 										~TextureLevelCase		(void);
 
 	void								init					(void);
@@ -694,7 +586,7 @@
 	virtual bool						checkTextureState		(glu::CallLogWrapper& gl, const TextureGenerationSpec& spec) = 0;
 	virtual void						generateTestIterations	(std::vector<TextureGenerationSpec>& iterations) = 0;
 
-	const VerifierType					m_type;
+	const QueryType						m_type;
 	const glw::GLenum					m_internalFormat;
 	glw::GLuint							m_texture;
 
@@ -705,7 +597,7 @@
 	std::vector<int>					m_failedIterations;
 };
 
-TextureLevelCase::TextureLevelCase (Context& ctx, const char* name, const char* desc, VerifierType type)
+TextureLevelCase::TextureLevelCase (Context& ctx, const char* name, const char* desc, QueryType type)
 	: TestCase			(ctx, name, desc)
 	, m_type			(type)
 	, m_internalFormat	(GL_RGBA8)
@@ -834,13 +726,13 @@
 class TextureLevelCommonCase : public TextureLevelCase
 {
 public:
-					TextureLevelCommonCase	(Context& ctx, const char* name, const char* desc, VerifierType type);
+					TextureLevelCommonCase	(Context& ctx, const char* name, const char* desc, QueryType type);
 
 protected:
 	virtual void	generateTestIterations	(std::vector<TextureGenerationSpec>& iterations);
 };
 
-TextureLevelCommonCase::TextureLevelCommonCase (Context& ctx, const char* name, const char* desc, VerifierType type)
+TextureLevelCommonCase::TextureLevelCommonCase (Context& ctx, const char* name, const char* desc, QueryType type)
 	: TextureLevelCase(ctx, name, desc, type)
 {
 }
@@ -867,13 +759,13 @@
 class TextureLevelMultisampleCase : public TextureLevelCase
 {
 public:
-					TextureLevelMultisampleCase	(Context& ctx, const char* name, const char* desc, VerifierType type);
+					TextureLevelMultisampleCase	(Context& ctx, const char* name, const char* desc, QueryType type);
 
 protected:
 	virtual void	generateTestIterations		(std::vector<TextureGenerationSpec>& iterations);
 };
 
-TextureLevelMultisampleCase::TextureLevelMultisampleCase (Context& ctx, const char* name, const char* desc, VerifierType type)
+TextureLevelMultisampleCase::TextureLevelMultisampleCase (Context& ctx, const char* name, const char* desc, QueryType type)
 	: TextureLevelCase(ctx, name, desc, type)
 {
 }
@@ -897,7 +789,7 @@
 class TextureLevelSampleCase : public TextureLevelMultisampleCase
 {
 public:
-	TextureLevelSampleCase (Context& ctx, const char* name, const char* desc, VerifierType type)
+	TextureLevelSampleCase (Context& ctx, const char* name, const char* desc, QueryType type)
 		: TextureLevelMultisampleCase(ctx, name, desc, type)
 	{
 	}
@@ -915,7 +807,7 @@
 class TextureLevelFixedSamplesCase : public TextureLevelMultisampleCase
 {
 public:
-	TextureLevelFixedSamplesCase (Context& ctx, const char* name, const char* desc, VerifierType type)
+	TextureLevelFixedSamplesCase (Context& ctx, const char* name, const char* desc, QueryType type)
 		: TextureLevelMultisampleCase(ctx, name, desc, type)
 	{
 	}
@@ -933,7 +825,7 @@
 class TextureLevelWidthCase : public TextureLevelCommonCase
 {
 public:
-	TextureLevelWidthCase (Context& ctx, const char* name, const char* desc, VerifierType type)
+	TextureLevelWidthCase (Context& ctx, const char* name, const char* desc, QueryType type)
 		: TextureLevelCommonCase(ctx, name, desc, type)
 	{
 	}
@@ -969,7 +861,7 @@
 class TextureLevelHeightCase : public TextureLevelCommonCase
 {
 public:
-	TextureLevelHeightCase (Context& ctx, const char* name, const char* desc, VerifierType type)
+	TextureLevelHeightCase (Context& ctx, const char* name, const char* desc, QueryType type)
 		: TextureLevelCommonCase(ctx, name, desc, type)
 	{
 	}
@@ -1005,7 +897,7 @@
 class TextureLevelDepthCase : public TextureLevelCommonCase
 {
 public:
-	TextureLevelDepthCase (Context& ctx, const char* name, const char* desc, VerifierType type)
+	TextureLevelDepthCase (Context& ctx, const char* name, const char* desc, QueryType type)
 		: TextureLevelCommonCase(ctx, name, desc, type)
 	{
 	}
@@ -1053,7 +945,7 @@
 class TextureLevelInternalFormatCase : public TextureLevelCase
 {
 public:
-	TextureLevelInternalFormatCase (Context& ctx, const char* name, const char* desc, VerifierType type)
+	TextureLevelInternalFormatCase (Context& ctx, const char* name, const char* desc, QueryType type)
 		: TextureLevelCase(ctx, name, desc, type)
 	{
 	}
@@ -1093,7 +985,7 @@
 class TextureLevelSizeCase : public TextureLevelCase
 {
 public:
-						TextureLevelSizeCase			(Context& ctx, const char* name, const char* desc, VerifierType type, glw::GLenum pname);
+						TextureLevelSizeCase			(Context& ctx, const char* name, const char* desc, QueryType type, glw::GLenum pname);
 
 private:
 	void				generateTestIterations			(std::vector<TextureGenerationSpec>& iterations);
@@ -1103,7 +995,7 @@
 	const glw::GLenum	m_pname;
 };
 
-TextureLevelSizeCase::TextureLevelSizeCase (Context& ctx, const char* name, const char* desc, VerifierType type, glw::GLenum pname)
+TextureLevelSizeCase::TextureLevelSizeCase (Context& ctx, const char* name, const char* desc, QueryType type, glw::GLenum pname)
 	: TextureLevelCase	(ctx, name, desc, type)
 	, m_pname			(pname)
 {
@@ -1215,7 +1107,7 @@
 class TextureLevelTypeCase : public TextureLevelCase
 {
 public:
-						TextureLevelTypeCase			(Context& ctx, const char* name, const char* desc, VerifierType type, glw::GLenum pname);
+						TextureLevelTypeCase			(Context& ctx, const char* name, const char* desc, QueryType type, glw::GLenum pname);
 
 private:
 	void				generateTestIterations			(std::vector<TextureGenerationSpec>& iterations);
@@ -1225,7 +1117,7 @@
 	const glw::GLenum	m_pname;
 };
 
-TextureLevelTypeCase::TextureLevelTypeCase (Context& ctx, const char* name, const char* desc, VerifierType type, glw::GLenum pname)
+TextureLevelTypeCase::TextureLevelTypeCase (Context& ctx, const char* name, const char* desc, QueryType type, glw::GLenum pname)
 	: TextureLevelCase	(ctx, name, desc, type)
 	, m_pname			(pname)
 {
@@ -1356,7 +1248,7 @@
 class TextureLevelCompressedCase : public TextureLevelCase
 {
 public:
-	TextureLevelCompressedCase (Context& ctx, const char* name, const char* desc, VerifierType type)
+	TextureLevelCompressedCase (Context& ctx, const char* name, const char* desc, QueryType type)
 		: TextureLevelCase(ctx, name, desc, type)
 	{
 	}
@@ -1412,7 +1304,7 @@
 	for (int groupNdx = 0; groupNdx < 2; ++groupNdx)
 	{
 		tcu::TestCaseGroup* const	group		= (groupNdx == 0) ? (integerGroup) : (floatGroup);
-		const VerifierType			verifier	= (groupNdx == 0) ? (VERIFIER_INT) : (VERIFIER_FLOAT);
+		const QueryType				verifier	= (groupNdx == 0) ? (QUERY_TEXTURE_LEVEL_INTEGER) : (QUERY_TEXTURE_LEVEL_FLOAT);
 
 
 		group->addChild(new TextureLevelSampleCase			(m_context, "texture_samples",					"Verify TEXTURE_SAMPLES",					verifier));
diff --git a/modules/gles31/functional/es31fTextureStateQueryTests.cpp b/modules/gles31/functional/es31fTextureStateQueryTests.cpp
new file mode 100644
index 0000000..0f27cc3
--- /dev/null
+++ b/modules/gles31/functional/es31fTextureStateQueryTests.cpp
@@ -0,0 +1,147 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Texture Param State Query tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "es31fTextureStateQueryTests.hpp"
+#include "glsStateQueryUtil.hpp"
+#include "gluRenderContext.hpp"
+#include "gluCallLogWrapper.hpp"
+#include "gluObjectWrapper.hpp"
+#include "glwFunctions.hpp"
+#include "glwEnums.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace
+{
+
+using namespace gls::StateQueryUtil;
+
+static const char* getVerifierSuffix (QueryType type)
+{
+	switch (type)
+	{
+		case QUERY_TEXTURE_PARAM_FLOAT:		return "get_tex_parameterfv";
+		case QUERY_TEXTURE_PARAM_INTEGER:	return "get_tex_parameteriv";
+		default:
+			DE_ASSERT(DE_FALSE);
+			return DE_NULL;
+	}
+}
+
+class DepthStencilModeCase : public TestCase
+{
+public:
+						DepthStencilModeCase	(Context& context, QueryType verifier, const char* name, const char* desc);
+	IterateResult		iterate					(void);
+
+private:
+	const QueryType		m_verifier;
+};
+
+DepthStencilModeCase::DepthStencilModeCase (Context& context, QueryType verifier, const char* name, const char* desc)
+	: TestCase		(context, name, desc)
+	, m_verifier	(verifier)
+{
+}
+
+DepthStencilModeCase::IterateResult DepthStencilModeCase::iterate (void)
+{
+	glu::Texture			texture	(m_context.getRenderContext());
+	glu::CallLogWrapper		gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
+	tcu::ResultCollector	result	(m_testCtx.getLog(), " // ERROR: ");
+
+	gl.enableLogging(true);
+
+	gl.glBindTexture(GL_TEXTURE_2D, *texture);
+	GLU_EXPECT_NO_ERROR(gl.glGetError(), "bind");
+
+	{
+		const tcu::ScopedLogSection section(m_testCtx.getLog(), "Initial", "Initial");
+		verifyStateTextureParamInteger(result, gl, GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_DEPTH_COMPONENT, m_verifier);
+	}
+
+	{
+		const tcu::ScopedLogSection	section				(m_testCtx.getLog(), "Toggle", "Toggle");
+		const glw::GLint			depthComponentInt	= GL_DEPTH_COMPONENT;
+		const glw::GLfloat			depthComponentFloat	= (glw::GLfloat)GL_DEPTH_COMPONENT;
+
+		gl.glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "set state");
+		verifyStateTextureParamInteger(result, gl, GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX, m_verifier);
+
+		gl.glTexParameteriv(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, &depthComponentInt);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "set state");
+		verifyStateTextureParamInteger(result, gl, GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_DEPTH_COMPONENT, m_verifier);
+
+		gl.glTexParameterf(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "set state");
+		verifyStateTextureParamInteger(result, gl, GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX, m_verifier);
+
+		gl.glTexParameterfv(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, &depthComponentFloat);
+		GLU_EXPECT_NO_ERROR(gl.glGetError(), "set state");
+		verifyStateTextureParamInteger(result, gl, GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_DEPTH_COMPONENT, m_verifier);
+	}
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+} // anonymous
+
+TextureStateQueryTests::TextureStateQueryTests (Context& context)
+	: TestCaseGroup(context, "texture", "Texture State Query tests")
+{
+}
+
+TextureStateQueryTests::~TextureStateQueryTests (void)
+{
+}
+
+void TextureStateQueryTests::init (void)
+{
+	static const QueryType verifiers[] =
+	{
+		QUERY_TEXTURE_PARAM_INTEGER,
+		QUERY_TEXTURE_PARAM_FLOAT,
+	};
+
+#define FOR_EACH_VERIFIER(X) \
+	for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(verifiers); ++verifierNdx)	\
+	{																						\
+		const char* verifierSuffix = getVerifierSuffix(verifiers[verifierNdx]);				\
+		const QueryType verifier = verifiers[verifierNdx];									\
+		this->addChild(X);																	\
+	}
+
+	FOR_EACH_VERIFIER(new DepthStencilModeCase(m_context, verifier, (std::string("depth_stencil_mode_case_") + verifierSuffix).c_str(), "Test DEPTH_STENCIL_TEXTURE_MODE"));
+
+#undef FOR_EACH_VERIFIER
+}
+
+} // Functional
+} // gles31
+} // deqp
diff --git a/modules/gles31/functional/es31fTextureStateQueryTests.hpp b/modules/gles31/functional/es31fTextureStateQueryTests.hpp
new file mode 100644
index 0000000..9198549
--- /dev/null
+++ b/modules/gles31/functional/es31fTextureStateQueryTests.hpp
@@ -0,0 +1,53 @@
+#ifndef _ES31FTEXTURESTATEQUERYTESTS_HPP
+#define _ES31FTEXTURESTATEQUERYTESTS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Texture Param State Query tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tes31TestCase.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+
+class TextureStateQueryTests : public TestCaseGroup
+{
+public:
+								TextureStateQueryTests	(Context& context);
+								~TextureStateQueryTests	(void);
+
+	void						init					(void);
+
+private:
+								TextureStateQueryTests	(const TextureStateQueryTests& other);
+	TextureStateQueryTests&		operator=				(const TextureStateQueryTests& other);
+};
+
+} // Functional
+} // gles31
+} // deqp
+
+#endif // _ES31FTEXTURESTATEQUERYTESTS_HPP
diff --git a/modules/gles31/functional/es31fVertexAttributeBindingStateQueryTests.cpp b/modules/gles31/functional/es31fVertexAttributeBindingStateQueryTests.cpp
index 80d3305..882a843 100644
--- a/modules/gles31/functional/es31fVertexAttributeBindingStateQueryTests.cpp
+++ b/modules/gles31/functional/es31fVertexAttributeBindingStateQueryTests.cpp
@@ -30,6 +30,7 @@
 #include "glsStateQueryUtil.hpp"
 #include "glwEnums.hpp"
 #include "glwFunctions.hpp"
+#include "glsStateQueryUtil.hpp"
 #include "deRandom.hpp"
 
 namespace deqp
@@ -41,25 +42,53 @@
 namespace
 {
 
-class AttributeBindingCase : public TestCase
+using namespace gls::StateQueryUtil;
+
+class AttributeCase : public TestCase
 {
 public:
-					AttributeBindingCase	(Context& context, const char* name, const char* desc);
-	IterateResult	iterate					(void);
+						AttributeCase		(Context& context, const char* name, const char* desc, QueryType verifier);
+
+	IterateResult		iterate				(void);
+	virtual void		test				(tcu::ResultCollector& result) = 0;
+
+protected:
+	const QueryType		m_verifier;
 };
 
-AttributeBindingCase::AttributeBindingCase (Context& context, const char* name, const char* desc)
-	: TestCase(context, name, desc)
+AttributeCase::AttributeCase (Context& context, const char* name, const char* desc, QueryType verifier)
+	: TestCase		(context, name, desc)
+	, m_verifier	(verifier)
 {
 }
 
-AttributeBindingCase::IterateResult AttributeBindingCase::iterate (void)
+AttributeCase::IterateResult AttributeCase::iterate (void)
+{
+	tcu::ResultCollector result(m_testCtx.getLog(), " // ERROR: ");
+
+	test(result);
+
+	result.setTestContextResult(m_testCtx);
+	return STOP;
+}
+
+class AttributeBindingCase : public AttributeCase
+{
+public:
+			AttributeBindingCase	(Context& context, const char* name, const char* desc, QueryType verifier);
+	void	test					(tcu::ResultCollector& result);
+};
+
+AttributeBindingCase::AttributeBindingCase (Context& context, const char* name, const char* desc, QueryType verifier)
+	: AttributeCase(context, name, desc, verifier)
+{
+}
+
+void AttributeBindingCase::test (tcu::ResultCollector& result)
 {
 	glu::CallLogWrapper gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
 	glu::VertexArray	vao			(m_context.getRenderContext());
-	glw::GLenum			error		= 0;
 	glw::GLint			maxAttrs	= -1;
-	bool				allOk		= true;
 
 	gl.enableLogging(true);
 
@@ -71,30 +100,13 @@
 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "initial", "Initial values");
 
 		for (int attr = 0; attr < de::max(16, maxAttrs); ++attr)
-		{
-			glw::GLint bindingState = -1;
-
-			gl.glGetVertexAttribiv(attr, GL_VERTEX_ATTRIB_BINDING, &bindingState);
-			error = gl.glGetError();
-
-			if (error != GL_NO_ERROR)
-			{
-				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got error " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
-				allOk = false;
-			}
-			else if (bindingState != attr)
-			{
-				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << attr << ", got " << bindingState << tcu::TestLog::EndMessage;
-				allOk = false;
-			}
-		}
+			verifyStateAttributeInteger(result, gl, GL_VERTEX_ATTRIB_BINDING, attr, attr, m_verifier);
 	}
 
 	// is part of vao
 	{
 		const tcu::ScopedLogSection section			(m_testCtx.getLog(), "vao", "VAO state");
 		glu::VertexArray			otherVao		(m_context.getRenderContext());
-		glw::GLint					bindingState	= -1;
 
 		// set to value A in vao1
 		gl.glVertexAttribBinding(1, 4);
@@ -105,19 +117,7 @@
 
 		// check value is still ok in original vao
 		gl.glBindVertexArray(*vao);
-		gl.glGetVertexAttribiv(1, GL_VERTEX_ATTRIB_BINDING, &bindingState);
-		error = gl.glGetError();
-
-		if (error != GL_NO_ERROR)
-		{
-			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got error " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
-			allOk = false;
-		}
-		else if (bindingState != 4)
-		{
-			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected 4, got " << bindingState << tcu::TestLog::EndMessage;
-			allOk = false;
-		}
+		verifyStateAttributeInteger(result, gl, GL_VERTEX_ATTRIB_BINDING, 1, 4, m_verifier);
 	}
 
 	// random values
@@ -131,51 +131,30 @@
 			// switch random va to random binding
 			const int	va				= rnd.getInt(0, de::max(16, maxAttrs)-1);
 			const int	binding			= rnd.getInt(0, 16);
-			glw::GLint	bindingState	= -1;
 
 			gl.glVertexAttribBinding(va, binding);
-			gl.glGetVertexAttribiv(va, GL_VERTEX_ATTRIB_BINDING, &bindingState);
-			error = gl.glGetError();
-
-			if (error != GL_NO_ERROR)
-			{
-				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got error " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
-				allOk = false;
-			}
-			else if (bindingState != binding)
-			{
-				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << binding << ", got " << bindingState << tcu::TestLog::EndMessage;
-				allOk = false;
-			}
+			verifyStateAttributeInteger(result, gl, GL_VERTEX_ATTRIB_BINDING, va, binding, m_verifier);
 		}
 	}
-
-	if (allOk)
-		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
-	else
-		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid value");
-	return STOP;
 }
 
-class AttributeRelativeOffsetCase : public TestCase
+class AttributeRelativeOffsetCase : public AttributeCase
 {
 public:
-					AttributeRelativeOffsetCase	(Context& context, const char* name, const char* desc);
-	IterateResult	iterate						(void);
+			AttributeRelativeOffsetCase	(Context& context, const char* name, const char* desc, QueryType verifier);
+	void	test						(tcu::ResultCollector& result);
 };
 
-AttributeRelativeOffsetCase::AttributeRelativeOffsetCase (Context& context, const char* name, const char* desc)
-	: TestCase(context, name, desc)
+AttributeRelativeOffsetCase::AttributeRelativeOffsetCase (Context& context, const char* name, const char* desc, QueryType verifier)
+	: AttributeCase(context, name, desc, verifier)
 {
 }
 
-AttributeRelativeOffsetCase::IterateResult AttributeRelativeOffsetCase::iterate (void)
+void AttributeRelativeOffsetCase::test (tcu::ResultCollector& result)
 {
 	glu::CallLogWrapper gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
 	glu::VertexArray	vao			(m_context.getRenderContext());
-	glw::GLenum			error		= 0;
 	glw::GLint			maxAttrs	= -1;
-	bool				allOk		= true;
 
 	gl.enableLogging(true);
 
@@ -187,30 +166,13 @@
 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "initial", "Initial values");
 
 		for (int attr = 0; attr < de::max(16, maxAttrs); ++attr)
-		{
-			glw::GLint relOffsetState = -1;
-
-			gl.glGetVertexAttribiv(attr, GL_VERTEX_ATTRIB_RELATIVE_OFFSET, &relOffsetState);
-			error = gl.glGetError();
-
-			if (error != GL_NO_ERROR)
-			{
-				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got error " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
-				allOk = false;
-			}
-			else if (relOffsetState != 0)
-			{
-				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected 0, got " << relOffsetState << tcu::TestLog::EndMessage;
-				allOk = false;
-			}
-		}
+			verifyStateAttributeInteger(result, gl, GL_VERTEX_ATTRIB_RELATIVE_OFFSET, attr, 0, m_verifier);
 	}
 
 	// is part of vao
 	{
 		const tcu::ScopedLogSection section			(m_testCtx.getLog(), "vao", "VAO state");
 		glu::VertexArray			otherVao		(m_context.getRenderContext());
-		glw::GLint					relOffsetState	= -1;
 
 		// set to value A in vao1
 		gl.glVertexAttribFormat(1, 4, GL_FLOAT, GL_FALSE, 9);
@@ -221,19 +183,7 @@
 
 		// check value is still ok in original vao
 		gl.glBindVertexArray(*vao);
-		gl.glGetVertexAttribiv(1, GL_VERTEX_ATTRIB_RELATIVE_OFFSET, &relOffsetState);
-		error = gl.glGetError();
-
-		if (error != GL_NO_ERROR)
-		{
-			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got error " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
-			allOk = false;
-		}
-		else if (relOffsetState != 9)
-		{
-			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected 9, got " << relOffsetState << tcu::TestLog::EndMessage;
-			allOk = false;
-		}
+		verifyStateAttributeInteger(result, gl, GL_VERTEX_ATTRIB_RELATIVE_OFFSET, 1, 9, m_verifier);
 	}
 
 	// random values
@@ -246,145 +196,54 @@
 		{
 			const int	va				= rnd.getInt(0, de::max(16, maxAttrs)-1);
 			const int	offset			= rnd.getInt(0, 2047);
-			glw::GLint	relOffsetState	= -1;
 
 			gl.glVertexAttribFormat(va, 4, GL_FLOAT, GL_FALSE, offset);
-			gl.glGetVertexAttribiv(va, GL_VERTEX_ATTRIB_RELATIVE_OFFSET, &relOffsetState);
-			error = gl.glGetError();
-
-			if (error != GL_NO_ERROR)
-			{
-				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got error " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
-				allOk = false;
-			}
-			else if (relOffsetState != offset)
-			{
-				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << offset << ", got " << relOffsetState << tcu::TestLog::EndMessage;
-				allOk = false;
-			}
+			verifyStateAttributeInteger(result, gl, GL_VERTEX_ATTRIB_RELATIVE_OFFSET, va, offset, m_verifier);
 		}
 	}
-
-	if (allOk)
-		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
-	else
-		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid value");
-	return STOP;
 }
 
 class IndexedCase : public TestCase
 {
 public:
-	enum VerifierType
-	{
-		VERIFIER_INT,
-		VERIFIER_INT64,
-
-		VERIFIER_LAST
-	};
-
-						IndexedCase			(Context& context, const char* name, const char* desc, VerifierType verifier);
+						IndexedCase			(Context& context, const char* name, const char* desc, QueryType verifier);
 
 	IterateResult		iterate				(void);
-	void				verifyValue			(glu::CallLogWrapper& gl, glw::GLenum name, int index, int expected);
+	virtual void		test				(tcu::ResultCollector& result) = 0;
 
-	virtual void		test				(void) = 0;
-private:
-	const VerifierType	m_verifier;
+protected:
+	const QueryType		m_verifier;
 };
 
-IndexedCase::IndexedCase (Context& context, const char* name, const char* desc, VerifierType verifier)
+IndexedCase::IndexedCase (Context& context, const char* name, const char* desc, QueryType verifier)
 	: TestCase		(context, name, desc)
 	, m_verifier	(verifier)
 {
-	DE_ASSERT(verifier < VERIFIER_LAST);
 }
 
 IndexedCase::IterateResult IndexedCase::iterate (void)
 {
-	// default value
-	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+	tcu::ResultCollector result(m_testCtx.getLog(), " // ERROR: ");
 
-	test();
+	test(result);
 
+	result.setTestContextResult(m_testCtx);
 	return STOP;
 }
 
-void IndexedCase::verifyValue (glu::CallLogWrapper& gl, glw::GLenum name, int index, int expected)
-{
-	if (m_verifier == VERIFIER_INT)
-	{
-		gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint>	value;
-		glw::GLenum													error = 0;
-
-		gl.glGetIntegeri_v(name, index, &value);
-		error = gl.glGetError();
-
-		if (error != GL_NO_ERROR)
-		{
-			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got unexpected error: " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
-			if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
-				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected error");
-		}
-		else if (!value.verifyValidity(m_testCtx))
-		{
-			// verifyValidity sets error
-		}
-		else
-		{
-			if (value != expected)
-			{
-				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << expected << ", got " << value << tcu::TestLog::EndMessage;
-				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
-					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected value");
-			}
-		}
-	}
-	else if (m_verifier == VERIFIER_INT64)
-	{
-		gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint64>	value;
-		glw::GLenum														error = 0;
-
-		gl.glGetInteger64i_v(name, index, &value);
-		error = gl.glGetError();
-
-		if (error != GL_NO_ERROR)
-		{
-			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got unexpected error: " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
-			if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
-				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected error");
-		}
-		else if (!value.verifyValidity(m_testCtx))
-		{
-			// verifyValidity sets error
-		}
-		else
-		{
-			if (value != expected)
-			{
-				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << expected << ", got " << value << tcu::TestLog::EndMessage;
-				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
-					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected value");
-			}
-		}
-	}
-	else
-		DE_ASSERT(false);
-}
-
 class VertexBindingDivisorCase : public IndexedCase
 {
 public:
-			VertexBindingDivisorCase	(Context& context, const char* name, const char* desc, VerifierType verifier);
-	void	test						(void);
+			VertexBindingDivisorCase	(Context& context, const char* name, const char* desc, QueryType verifier);
+	void	test						(tcu::ResultCollector& result);
 };
 
-VertexBindingDivisorCase::VertexBindingDivisorCase (Context& context, const char* name, const char* desc, VerifierType verifier)
+VertexBindingDivisorCase::VertexBindingDivisorCase (Context& context, const char* name, const char* desc, QueryType verifier)
 	: IndexedCase(context, name, desc, verifier)
 {
 }
 
-void VertexBindingDivisorCase::test (void)
+void VertexBindingDivisorCase::test (tcu::ResultCollector& result)
 {
 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
 	glu::VertexArray	vao					(m_context.getRenderContext());
@@ -402,7 +261,7 @@
 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "initial", "Initial values");
 
 		for (int binding = 0; binding < maxBindings; ++binding)
-			verifyValue(gl, GL_VERTEX_BINDING_DIVISOR, binding, 0);
+			verifyStateIndexedInteger(result, gl, GL_VERTEX_BINDING_DIVISOR, binding, 0, m_verifier);
 	}
 
 	// is part of vao
@@ -419,7 +278,7 @@
 
 		// check value is still ok in original vao
 		gl.glBindVertexArray(*vao);
-		verifyValue(gl, GL_VERTEX_BINDING_DIVISOR, 1, 4);
+		verifyStateIndexedInteger(result, gl, GL_VERTEX_BINDING_DIVISOR, 1, 4, m_verifier);
 	}
 
 	// random values
@@ -434,7 +293,7 @@
 			const int	divisor			= rnd.getInt(0, 2047);
 
 			gl.glVertexBindingDivisor(binding, divisor);
-			verifyValue(gl, GL_VERTEX_BINDING_DIVISOR, binding, divisor);
+			verifyStateIndexedInteger(result, gl, GL_VERTEX_BINDING_DIVISOR, binding, divisor, m_verifier);
 		}
 	}
 }
@@ -442,16 +301,16 @@
 class VertexBindingOffsetCase : public IndexedCase
 {
 public:
-			VertexBindingOffsetCase		(Context& context, const char* name, const char* desc, VerifierType verifier);
-	void	test						(void);
+			VertexBindingOffsetCase		(Context& context, const char* name, const char* desc, QueryType verifier);
+	void	test						(tcu::ResultCollector& result);
 };
 
-VertexBindingOffsetCase::VertexBindingOffsetCase (Context& context, const char* name, const char* desc, VerifierType verifier)
+VertexBindingOffsetCase::VertexBindingOffsetCase (Context& context, const char* name, const char* desc, QueryType verifier)
 	: IndexedCase(context, name, desc, verifier)
 {
 }
 
-void VertexBindingOffsetCase::test (void)
+void VertexBindingOffsetCase::test (tcu::ResultCollector& result)
 {
 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
 	glu::VertexArray	vao					(m_context.getRenderContext());
@@ -470,7 +329,7 @@
 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "initial", "Initial values");
 
 		for (int binding = 0; binding < maxBindings; ++binding)
-			verifyValue(gl, GL_VERTEX_BINDING_OFFSET, binding, 0);
+			verifyStateIndexedInteger(result, gl, GL_VERTEX_BINDING_OFFSET, binding, 0, m_verifier);
 	}
 
 	// is part of vao
@@ -487,7 +346,7 @@
 
 		// check value is still ok in original vao
 		gl.glBindVertexArray(*vao);
-		verifyValue(gl, GL_VERTEX_BINDING_OFFSET, 1, 4);
+		verifyStateIndexedInteger(result, gl, GL_VERTEX_BINDING_OFFSET, 1, 4, m_verifier);
 	}
 
 	// random values
@@ -502,7 +361,7 @@
 			const int	offset			= rnd.getInt(0, 4000);
 
 			gl.glBindVertexBuffer(binding, *buffer, offset, 32);
-			verifyValue(gl, GL_VERTEX_BINDING_OFFSET, binding, offset);
+			verifyStateIndexedInteger(result, gl, GL_VERTEX_BINDING_OFFSET, binding, offset, m_verifier);
 		}
 	}
 }
@@ -510,16 +369,16 @@
 class VertexBindingStrideCase : public IndexedCase
 {
 public:
-			VertexBindingStrideCase		(Context& context, const char* name, const char* desc, VerifierType verifier);
-	void	test						(void);
+			VertexBindingStrideCase		(Context& context, const char* name, const char* desc, QueryType verifier);
+	void	test						(tcu::ResultCollector& result);
 };
 
-VertexBindingStrideCase::VertexBindingStrideCase (Context& context, const char* name, const char* desc, VerifierType verifier)
+VertexBindingStrideCase::VertexBindingStrideCase (Context& context, const char* name, const char* desc, QueryType verifier)
 	: IndexedCase(context, name, desc, verifier)
 {
 }
 
-void VertexBindingStrideCase::test (void)
+void VertexBindingStrideCase::test (tcu::ResultCollector& result)
 {
 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
 	glu::VertexArray	vao					(m_context.getRenderContext());
@@ -538,7 +397,7 @@
 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "initial", "Initial values");
 
 		for (int binding = 0; binding < maxBindings; ++binding)
-			verifyValue(gl, GL_VERTEX_BINDING_STRIDE, binding, 16);
+			verifyStateIndexedInteger(result, gl, GL_VERTEX_BINDING_STRIDE, binding, 16, m_verifier);
 	}
 
 	// is part of vao
@@ -555,7 +414,7 @@
 
 		// check value is still ok in original vao
 		gl.glBindVertexArray(*vao);
-		verifyValue(gl, GL_VERTEX_BINDING_STRIDE, 1, 32);
+		verifyStateIndexedInteger(result, gl, GL_VERTEX_BINDING_STRIDE, 1, 32, m_verifier);
 	}
 
 	// random values
@@ -570,7 +429,7 @@
 			const int	stride			= rnd.getInt(0, 2048);
 
 			gl.glBindVertexBuffer(binding, *buffer, 0, stride);
-			verifyValue(gl, GL_VERTEX_BINDING_STRIDE, binding, stride);
+			verifyStateIndexedInteger(result, gl, GL_VERTEX_BINDING_STRIDE, binding, stride, m_verifier);
 		}
 	}
 }
@@ -578,16 +437,16 @@
 class VertexBindingBufferCase : public IndexedCase
 {
 public:
-			VertexBindingBufferCase		(Context& context, const char* name, const char* desc, VerifierType verifier);
-	void	test						(void);
+			VertexBindingBufferCase		(Context& context, const char* name, const char* desc, QueryType verifier);
+	void	test						(tcu::ResultCollector& result);
 };
 
-VertexBindingBufferCase::VertexBindingBufferCase (Context& context, const char* name, const char* desc, VerifierType verifier)
+VertexBindingBufferCase::VertexBindingBufferCase (Context& context, const char* name, const char* desc, QueryType verifier)
 	: IndexedCase(context, name, desc, verifier)
 {
 }
 
-void VertexBindingBufferCase::test (void)
+void VertexBindingBufferCase::test (tcu::ResultCollector& result)
 {
 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
 	glu::VertexArray	vao					(m_context.getRenderContext());
@@ -606,7 +465,7 @@
 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "initial", "Initial values");
 
 		for (int binding = 0; binding < maxBindings; ++binding)
-			verifyValue(gl, GL_VERTEX_BINDING_BUFFER, binding, 0);
+			verifyStateIndexedInteger(result, gl, GL_VERTEX_BINDING_BUFFER, binding, 0, m_verifier);
 	}
 
 	// is part of vao
@@ -624,7 +483,7 @@
 
 		// check value is still ok in original vao
 		gl.glBindVertexArray(*vao);
-		verifyValue(gl, GL_VERTEX_BINDING_BUFFER, 1, *buffer);
+		verifyStateIndexedInteger(result, gl, GL_VERTEX_BINDING_BUFFER, 1, *buffer, m_verifier);
 	}
 
 	// Is detached in delete from active vao and not from deactive
@@ -642,9 +501,9 @@
 
 		// delete buffer. This unbinds it from active (vao2) but not from unactive
 		gl.glDeleteBuffers(1, &otherBuffer);
-		verifyValue(gl, GL_VERTEX_BINDING_BUFFER, 1, 0);
+		verifyStateIndexedInteger(result, gl, GL_VERTEX_BINDING_BUFFER, 1, 0, m_verifier);
 		gl.glBindVertexArray(*vao);
-		verifyValue(gl, GL_VERTEX_BINDING_BUFFER, 1, otherBuffer);
+		verifyStateIndexedInteger(result, gl, GL_VERTEX_BINDING_BUFFER, 1, otherBuffer, m_verifier);
 	}
 }
 
@@ -652,15 +511,15 @@
 {
 public:
 			MixedVertexBindingDivisorCase	(Context& context, const char* name, const char* desc);
-	void	test							(void);
+	void	test							(tcu::ResultCollector& result);
 };
 
 MixedVertexBindingDivisorCase::MixedVertexBindingDivisorCase (Context& context, const char* name, const char* desc)
-	: IndexedCase(context, name, desc, VERIFIER_INT)
+	: IndexedCase(context, name, desc, QUERY_INDEXED_INTEGER)
 {
 }
 
-void MixedVertexBindingDivisorCase::test (void)
+void MixedVertexBindingDivisorCase::test (tcu::ResultCollector& result)
 {
 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
 	glu::VertexArray	vao					(m_context.getRenderContext());
@@ -668,22 +527,22 @@
 	gl.enableLogging(true);
 
 	gl.glVertexAttribDivisor(1, 4);
-	verifyValue(gl, GL_VERTEX_BINDING_DIVISOR, 1, 4);
+	verifyStateIndexedInteger(result, gl, GL_VERTEX_BINDING_DIVISOR, 1, 4, m_verifier);
 }
 
 class MixedVertexBindingOffsetCase : public IndexedCase
 {
 public:
 			MixedVertexBindingOffsetCase	(Context& context, const char* name, const char* desc);
-	void	test							(void);
+	void	test							(tcu::ResultCollector& result);
 };
 
 MixedVertexBindingOffsetCase::MixedVertexBindingOffsetCase (Context& context, const char* name, const char* desc)
-	: IndexedCase(context, name, desc, VERIFIER_INT)
+	: IndexedCase(context, name, desc, QUERY_INDEXED_INTEGER)
 {
 }
 
-void MixedVertexBindingOffsetCase::test (void)
+void MixedVertexBindingOffsetCase::test (tcu::ResultCollector& result)
 {
 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
 	glu::VertexArray	vao					(m_context.getRenderContext());
@@ -694,22 +553,22 @@
 	gl.glBindBuffer(GL_ARRAY_BUFFER, *buffer);
 	gl.glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (const deUint8*)DE_NULL + 12);
 
-	verifyValue(gl, GL_VERTEX_BINDING_OFFSET, 1, 12);
+	verifyStateIndexedInteger(result, gl, GL_VERTEX_BINDING_OFFSET, 1, 12, m_verifier);
 }
 
 class MixedVertexBindingStrideCase : public IndexedCase
 {
 public:
 			MixedVertexBindingStrideCase	(Context& context, const char* name, const char* desc);
-	void	test							(void);
+	void	test							(tcu::ResultCollector& result);
 };
 
 MixedVertexBindingStrideCase::MixedVertexBindingStrideCase (Context& context, const char* name, const char* desc)
-	: IndexedCase(context, name, desc, VERIFIER_INT)
+	: IndexedCase(context, name, desc, QUERY_INDEXED_INTEGER)
 {
 }
 
-void MixedVertexBindingStrideCase::test (void)
+void MixedVertexBindingStrideCase::test (tcu::ResultCollector& result)
 {
 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
 	glu::VertexArray	vao					(m_context.getRenderContext());
@@ -719,26 +578,26 @@
 
 	gl.glBindBuffer(GL_ARRAY_BUFFER, *buffer);
 	gl.glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 12, 0);
-	verifyValue(gl, GL_VERTEX_BINDING_STRIDE, 1, 12);
+	verifyStateIndexedInteger(result, gl, GL_VERTEX_BINDING_STRIDE, 1, 12, m_verifier);
 
 	// test effectiveStride
 	gl.glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
-	verifyValue(gl, GL_VERTEX_BINDING_STRIDE, 1, 16);
+	verifyStateIndexedInteger(result, gl, GL_VERTEX_BINDING_STRIDE, 1, 16, m_verifier);
 }
 
 class MixedVertexBindingBufferCase : public IndexedCase
 {
 public:
 			MixedVertexBindingBufferCase	(Context& context, const char* name, const char* desc);
-	void	test							(void);
+	void	test							(tcu::ResultCollector& result);
 };
 
 MixedVertexBindingBufferCase::MixedVertexBindingBufferCase (Context& context, const char* name, const char* desc)
-	: IndexedCase(context, name, desc, VERIFIER_INT)
+	: IndexedCase(context, name, desc, QUERY_INDEXED_INTEGER)
 {
 }
 
-void MixedVertexBindingBufferCase::test (void)
+void MixedVertexBindingBufferCase::test (tcu::ResultCollector& result)
 {
 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
 	glu::VertexArray	vao					(m_context.getRenderContext());
@@ -748,7 +607,7 @@
 
 	gl.glBindBuffer(GL_ARRAY_BUFFER, *buffer);
 	gl.glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
-	verifyValue(gl, GL_VERTEX_BINDING_BUFFER, 1, *buffer);
+	verifyStateIndexedInteger(result, gl, GL_VERTEX_BINDING_BUFFER, 1, *buffer, m_verifier);
 }
 
 } // anonymous
@@ -772,20 +631,36 @@
 
 	// .vertex_attrib
 	{
-		attributeGroup->addChild(new AttributeBindingCase		(m_context,	"vertex_attrib_binding",			"Test VERTEX_ATTRIB_BINDING"));
-		attributeGroup->addChild(new AttributeRelativeOffsetCase(m_context,	"vertex_attrib_relative_offset",	"Test VERTEX_ATTRIB_RELATIVE_OFFSET"));
+		static const struct Verifier
+		{
+			const char*		suffix;
+			QueryType		type;
+		} verifiers[] =
+		{
+			{ "",						QUERY_ATTRIBUTE_INTEGER					},	// avoid renaming tests
+			{ "_getvertexattribfv",		QUERY_ATTRIBUTE_FLOAT					},
+			{ "_getvertexattribiiv",	QUERY_ATTRIBUTE_PURE_INTEGER			},
+			{ "_getvertexattribiuiv",	QUERY_ATTRIBUTE_PURE_UNSIGNED_INTEGER	},
+		};
+
+		for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(verifiers); ++verifierNdx)
+		{
+			attributeGroup->addChild(new AttributeBindingCase		(m_context,	(std::string("vertex_attrib_binding") + verifiers[verifierNdx].suffix).c_str(),			"Test VERTEX_ATTRIB_BINDING",			verifiers[verifierNdx].type));
+			attributeGroup->addChild(new AttributeRelativeOffsetCase(m_context,	(std::string("vertex_attrib_relative_offset") + verifiers[verifierNdx].suffix).c_str(),	"Test VERTEX_ATTRIB_RELATIVE_OFFSET",	verifiers[verifierNdx].type));
+		}
 	}
 
-	// .indexed (and 64)
+	// .indexed
 	{
 		static const struct Verifier
 		{
-			const char*					name;
-			IndexedCase::VerifierType	type;
+			const char*		name;
+			QueryType		type;
 		} verifiers[] =
 		{
-			{ "getintegeri",	IndexedCase::VERIFIER_INT	},
-			{ "getintegeri64",	IndexedCase::VERIFIER_INT64	},
+			{ "getintegeri",	QUERY_INDEXED_INTEGER	},
+			{ "getintegeri64",	QUERY_INDEXED_INTEGER64	},
+			{ "getboolean",		QUERY_INDEXED_BOOLEAN	},
 		};
 
 		// states
diff --git a/modules/glshared/CMakeLists.txt b/modules/glshared/CMakeLists.txt
index 4a2b9aa..f86ceac 100644
--- a/modules/glshared/CMakeLists.txt
+++ b/modules/glshared/CMakeLists.txt
@@ -31,6 +31,7 @@
 	glsShaderPerformanceCase.hpp
 	glsShaderRenderCase.cpp
 	glsShaderRenderCase.hpp
+	glsStateQueryUtil.cpp
 	glsStateQueryUtil.hpp
 	glsScissorTests.cpp
 	glsScissorTests.hpp
diff --git a/modules/glshared/glsStateQueryUtil.cpp b/modules/glshared/glsStateQueryUtil.cpp
new file mode 100644
index 0000000..072582d
--- /dev/null
+++ b/modules/glshared/glsStateQueryUtil.cpp
@@ -0,0 +1,1164 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL (ES) Module
+ * -----------------------------------------------
+ *
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief State Query test utils.
+ *//*--------------------------------------------------------------------*/
+#include "glsStateQueryUtil.hpp"
+#include "tcuTestContext.hpp"
+#include "tcuFormatUtil.hpp"
+#include "gluCallLogWrapper.hpp"
+#include "gluStrUtil.hpp"
+#include "glwEnums.hpp"
+#include "deStringUtil.hpp"
+
+namespace deqp
+{
+namespace gls
+{
+namespace StateQueryUtil
+{
+
+static bool checkError (tcu::ResultCollector& result, glu::CallLogWrapper& gl, const char* msg)
+{
+	const glw::GLenum errorCode = gl.glGetError();
+
+	if (errorCode == GL_NO_ERROR)
+		return true;
+
+	result.fail(std::string(msg) + ": glGetError() returned " + glu::getErrorStr(errorCode).toString());
+	return false;
+}
+
+QueriedState::QueriedState (void)
+	: m_type(DATATYPE_LAST)
+{
+}
+
+QueriedState::QueriedState (glw::GLint v)
+	: m_type(DATATYPE_INTEGER)
+{
+	m_v.vInt = v;
+}
+
+QueriedState::QueriedState (glw::GLint64 v)
+	: m_type(DATATYPE_INTEGER64)
+{
+	m_v.vInt64 = v;
+}
+
+QueriedState::QueriedState (glw::GLboolean v)
+	: m_type(DATATYPE_BOOLEAN)
+{
+	m_v.vBool = v;
+}
+
+QueriedState::QueriedState (glw::GLfloat v)
+	: m_type(DATATYPE_FLOAT)
+{
+	m_v.vFloat = v;
+}
+
+QueriedState::QueriedState (glw::GLuint v)
+	: m_type(DATATYPE_UNSIGNED_INTEGER)
+{
+	m_v.vUint = v;
+}
+
+QueriedState::QueriedState (const GLIntVec3& v)
+	: m_type(DATATYPE_INTEGER_VEC3)
+{
+	m_v.vIntVec3[0] = v[0];
+	m_v.vIntVec3[1] = v[1];
+	m_v.vIntVec3[2] = v[2];
+}
+
+bool QueriedState::isUndefined (void) const
+{
+	return m_type == DATATYPE_LAST;
+}
+
+DataType QueriedState::getType (void) const
+{
+	return m_type;
+}
+
+glw::GLint& QueriedState::getIntAccess (void)
+{
+	DE_ASSERT(m_type == DATATYPE_INTEGER);
+	return m_v.vInt;
+}
+
+glw::GLint64& QueriedState::getInt64Access (void)
+{
+	DE_ASSERT(m_type == DATATYPE_INTEGER64);
+	return m_v.vInt64;
+}
+
+glw::GLboolean& QueriedState::getBoolAccess (void)
+{
+	DE_ASSERT(m_type == DATATYPE_BOOLEAN);
+	return m_v.vBool;
+}
+
+glw::GLfloat& QueriedState::getFloatAccess (void)
+{
+	DE_ASSERT(m_type == DATATYPE_FLOAT);
+	return m_v.vFloat;
+}
+
+glw::GLuint& QueriedState::getUintAccess (void)
+{
+	DE_ASSERT(m_type == DATATYPE_UNSIGNED_INTEGER);
+	return m_v.vUint;
+}
+
+QueriedState::GLIntVec3& QueriedState::getIntVec3Access (void)
+{
+	DE_ASSERT(m_type == DATATYPE_INTEGER_VEC3);
+	return m_v.vIntVec3;
+}
+
+// query
+
+void queryState (tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, QueriedState& state)
+{
+	switch (type)
+	{
+		case QUERY_ISENABLED:
+		{
+			const glw::GLboolean value = gl.glIsEnabled(target);
+
+			if (!checkError(result, gl, "glIsEnabled"))
+				return;
+
+			state = QueriedState(value);
+			break;
+		}
+
+		case QUERY_BOOLEAN:
+		{
+			StateQueryMemoryWriteGuard<glw::GLboolean> value;
+			gl.glGetBooleanv(target, &value);
+
+			if (!checkError(result, gl, "glGetBooleanv"))
+				return;
+
+			if (!value.verifyValidity(result))
+				return;
+
+			state = QueriedState(value);
+			break;
+		}
+
+		case QUERY_INTEGER:
+		{
+			StateQueryMemoryWriteGuard<glw::GLint> value;
+			gl.glGetIntegerv(target, &value);
+
+			if (!checkError(result, gl, "glGetIntegerv"))
+				return;
+
+			if (!value.verifyValidity(result))
+				return;
+
+			state = QueriedState(value);
+			break;
+		}
+
+		case QUERY_INTEGER64:
+		{
+			StateQueryMemoryWriteGuard<glw::GLint64> value;
+			gl.glGetInteger64v(target, &value);
+
+			if (!checkError(result, gl, "glGetInteger64v"))
+				return;
+
+			if (!value.verifyValidity(result))
+				return;
+
+			state = QueriedState(value);
+			break;
+		}
+
+		case QUERY_FLOAT:
+		{
+			StateQueryMemoryWriteGuard<glw::GLfloat> value;
+			gl.glGetFloatv(target, &value);
+
+			if (!checkError(result, gl, "glGetFloatv"))
+				return;
+
+			if (!value.verifyValidity(result))
+				return;
+
+			state = QueriedState(value);
+			break;
+		}
+
+		default:
+			DE_ASSERT(DE_FALSE);
+			break;
+	}
+}
+
+void queryIndexedState (tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, int index, QueriedState& state)
+{
+	switch (type)
+	{
+		case QUERY_INDEXED_BOOLEAN:
+		{
+			StateQueryMemoryWriteGuard<glw::GLboolean> value;
+			gl.glGetBooleani_v(target, index, &value);
+
+			if (!checkError(result, gl, "glGetBooleani_v"))
+				return;
+
+			if (!value.verifyValidity(result))
+				return;
+
+			state = QueriedState(value);
+			break;
+		}
+
+		case QUERY_INDEXED_INTEGER:
+		{
+			StateQueryMemoryWriteGuard<glw::GLint> value;
+			gl.glGetIntegeri_v(target, index, &value);
+
+			if (!checkError(result, gl, "glGetIntegeri_v"))
+				return;
+
+			if (!value.verifyValidity(result))
+				return;
+
+			state = QueriedState(value);
+			break;
+		}
+
+		case QUERY_INDEXED_INTEGER64:
+		{
+			StateQueryMemoryWriteGuard<glw::GLint64> value;
+			gl.glGetInteger64i_v(target, index, &value);
+
+			if (!checkError(result, gl, "glGetInteger64i_v"))
+				return;
+
+			if (!value.verifyValidity(result))
+				return;
+
+			state = QueriedState(value);
+			break;
+		}
+
+		default:
+			DE_ASSERT(DE_FALSE);
+			break;
+	}
+}
+
+void queryAttributeState (tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, int index, QueriedState& state)
+{
+	switch (type)
+	{
+		case QUERY_ATTRIBUTE_INTEGER:
+		{
+			StateQueryMemoryWriteGuard<glw::GLint> value;
+			gl.glGetVertexAttribiv(index, target, &value);
+
+			if (!checkError(result, gl, "glGetVertexAttribiv"))
+				return;
+
+			if (!value.verifyValidity(result))
+				return;
+
+			state = QueriedState(value);
+			break;
+		}
+		case QUERY_ATTRIBUTE_FLOAT:
+		{
+			StateQueryMemoryWriteGuard<glw::GLfloat> value;
+			gl.glGetVertexAttribfv(index, target, &value);
+
+			if (!checkError(result, gl, "glGetVertexAttribfv"))
+				return;
+
+			if (!value.verifyValidity(result))
+				return;
+
+			state = QueriedState(value);
+			break;
+		}
+		case QUERY_ATTRIBUTE_PURE_INTEGER:
+		{
+			StateQueryMemoryWriteGuard<glw::GLint> value;
+			gl.glGetVertexAttribIiv(index, target, &value);
+
+			if (!checkError(result, gl, "glGetVertexAttribIiv"))
+				return;
+
+			if (!value.verifyValidity(result))
+				return;
+
+			state = QueriedState(value);
+			break;
+		}
+		case QUERY_ATTRIBUTE_PURE_UNSIGNED_INTEGER:
+		{
+			StateQueryMemoryWriteGuard<glw::GLuint> value;
+			gl.glGetVertexAttribIuiv(index, target, &value);
+
+			if (!checkError(result, gl, "glGetVertexAttribIuiv"))
+				return;
+
+			if (!value.verifyValidity(result))
+				return;
+
+			state = QueriedState(value);
+			break;
+		}
+		default:
+			DE_ASSERT(false);
+	}
+}
+
+void queryFramebufferState (tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, glw::GLenum pname, QueriedState& state)
+{
+	switch (type)
+	{
+		case QUERY_FRAMEBUFFER_INTEGER:
+		{
+			StateQueryMemoryWriteGuard<glw::GLint> value;
+			gl.glGetFramebufferParameteriv(target, pname, &value);
+
+			if (!checkError(result, gl, "glGetVertexAttribiv"))
+				return;
+
+			if (!value.verifyValidity(result))
+				return;
+
+			state = QueriedState(value);
+			break;
+		}
+		default:
+			DE_ASSERT(false);
+	}
+}
+
+void queryProgramState (tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLuint program, glw::GLenum pname, QueriedState& state)
+{
+	switch (type)
+	{
+		case QUERY_PROGRAM_INTEGER:
+		{
+			StateQueryMemoryWriteGuard<glw::GLint> value;
+			gl.glGetProgramiv(program, pname, &value);
+
+			if (!checkError(result, gl, "glGetProgramiv"))
+				return;
+
+			if (!value.verifyValidity(result))
+				return;
+
+			state = QueriedState(value);
+			break;
+		}
+		case QUERY_PROGRAM_INTEGER_VEC3:
+		{
+			StateQueryMemoryWriteGuard<glw::GLint[3]> value;
+			gl.glGetProgramiv(program, pname, value);
+
+			if (!checkError(result, gl, "glGetProgramiv"))
+				return;
+
+			if (!value.verifyValidity(result))
+				return;
+
+			state = QueriedState(value);
+			break;
+		}
+		default:
+			DE_ASSERT(false);
+	}
+}
+
+void queryPipelineState (tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLuint pipeline, glw::GLenum pname, QueriedState& state)
+{
+	switch (type)
+	{
+		case QUERY_PIPELINE_INTEGER:
+		{
+			StateQueryMemoryWriteGuard<glw::GLint> value;
+			gl.glGetProgramPipelineiv(pipeline, pname, &value);
+
+			if (!checkError(result, gl, "glGetProgramiv"))
+				return;
+
+			if (!value.verifyValidity(result))
+				return;
+
+			state = QueriedState(value);
+			break;
+		}
+		default:
+			DE_ASSERT(false);
+	}
+}
+
+void queryTextureParamState (tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, glw::GLenum pname, QueriedState& state)
+{
+	switch (type)
+	{
+		case QUERY_TEXTURE_PARAM_INTEGER:
+		{
+			StateQueryMemoryWriteGuard<glw::GLint> value;
+			gl.glGetTexParameteriv(target, pname, &value);
+
+			if (!checkError(result, gl, "glGetTexParameteriv"))
+				return;
+
+			if (!value.verifyValidity(result))
+				return;
+
+			state = QueriedState(value);
+			break;
+		}
+		case QUERY_TEXTURE_PARAM_FLOAT:
+		{
+			StateQueryMemoryWriteGuard<glw::GLfloat> value;
+			gl.glGetTexParameterfv(target, pname, &value);
+
+			if (!checkError(result, gl, "glGetTexParameterfv"))
+				return;
+
+			if (!value.verifyValidity(result))
+				return;
+
+			state = QueriedState(value);
+			break;
+		}
+		default:
+			DE_ASSERT(false);
+	}
+}
+
+void queryTextureLevelState (tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, int level, glw::GLenum pname, QueriedState& state)
+{
+	switch (type)
+	{
+		case QUERY_TEXTURE_LEVEL_INTEGER:
+		{
+			StateQueryMemoryWriteGuard<glw::GLint> value;
+			gl.glGetTexLevelParameteriv(target, level, pname, &value);
+
+			if (!checkError(result, gl, "glGetTexLevelParameteriv"))
+				return;
+
+			if (!value.verifyValidity(result))
+				return;
+
+			state = QueriedState(value);
+			break;
+		}
+		case QUERY_TEXTURE_LEVEL_FLOAT:
+		{
+			StateQueryMemoryWriteGuard<glw::GLfloat> value;
+			gl.glGetTexLevelParameterfv(target, level, pname, &value);
+
+			if (!checkError(result, gl, "glGetTexLevelParameterfv"))
+				return;
+
+			if (!value.verifyValidity(result))
+				return;
+
+			state = QueriedState(value);
+			break;
+		}
+		default:
+			DE_ASSERT(false);
+	}
+}
+
+// verify
+
+void verifyBoolean (tcu::ResultCollector& result, QueriedState& state, bool expected)
+{
+	switch (state.getType())
+	{
+		case DATATYPE_BOOLEAN:
+		{
+			const glw::GLboolean reference = expected ? GL_TRUE : GL_FALSE;
+			if (state.getBoolAccess() != reference)
+			{
+				std::ostringstream buf;
+				buf << "Expected " << glu::getBooleanStr(reference) << ", got " << glu::getBooleanStr(state.getBoolAccess());
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		case DATATYPE_INTEGER:
+		{
+			const glw::GLint reference = expected ? 1 : 0;
+			if (state.getIntAccess() != reference)
+			{
+				std::ostringstream buf;
+				buf << "Expected " << reference << ", got " << state.getIntAccess();
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		case DATATYPE_INTEGER64:
+		{
+			const glw::GLint64 reference = expected ? 1 : 0;
+			if (state.getInt64Access() != reference)
+			{
+				std::ostringstream buf;
+				buf << "Expected " << reference << ", got " << state.getInt64Access();
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		case DATATYPE_FLOAT:
+		{
+			const glw::GLfloat reference = expected ? 1.0f : 0.0f;
+			if (state.getFloatAccess() != reference)
+			{
+				std::ostringstream buf;
+				buf << "Expected " << reference << ", got " << state.getFloatAccess();
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		default:
+			DE_ASSERT(DE_FALSE);
+			break;
+	}
+}
+
+void verifyInteger (tcu::ResultCollector& result, QueriedState& state, int expected)
+{
+	switch (state.getType())
+	{
+		case DATATYPE_BOOLEAN:
+		{
+			const glw::GLboolean reference = (expected == 0) ? (GL_FALSE) : (GL_TRUE);
+			if (state.getBoolAccess() != reference)
+			{
+				std::ostringstream buf;
+				buf << "Expected " << glu::getBooleanStr(reference) << ", got " << glu::getBooleanStr(state.getBoolAccess());
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		case DATATYPE_INTEGER:
+		{
+			const glw::GLint reference = expected;
+			if (state.getIntAccess() != reference)
+			{
+				std::ostringstream buf;
+				buf << "Expected " << reference << "(" << de::toString(tcu::Format::Hex<8>(reference))
+					<< ") , got " << state.getIntAccess() << "(" << de::toString(tcu::Format::Hex<8>(state.getIntAccess())) << ")";
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		case DATATYPE_INTEGER64:
+		{
+			const glw::GLint64 reference = (glw::GLint64)expected;
+			if (state.getInt64Access() != reference)
+			{
+				std::ostringstream buf;
+				buf << "Expected " << reference << "(" << de::toString(tcu::Format::Hex<8>(reference)) << "), got "
+					<< state.getInt64Access() << "(" << de::toString(tcu::Format::Hex<8>(state.getInt64Access())) << ")";
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		case DATATYPE_FLOAT:
+		{
+			const glw::GLint64 reference = (glw::GLfloat)expected;
+			if (state.getFloatAccess() != reference)
+			{
+				std::ostringstream buf;
+				buf << "Expected " << reference << ", got " << state.getFloatAccess();
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		case DATATYPE_UNSIGNED_INTEGER:
+		{
+			const glw::GLuint reference = (glw::GLuint)expected;
+			if (state.getUintAccess() != reference)
+			{
+				std::ostringstream buf;
+				buf << "Expected " << reference << "(" << de::toString(tcu::Format::Hex<8>(reference)) << "), got "
+					<< state.getInt64Access() << "(" << de::toString(tcu::Format::Hex<8>(state.getInt64Access())) << ")";
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		default:
+			DE_ASSERT(DE_FALSE);
+			break;
+	}
+}
+
+void verifyIntegerMin (tcu::ResultCollector& result, QueriedState& state, int minValue)
+{
+	switch (state.getType())
+	{
+		case DATATYPE_BOOLEAN:
+		{
+			if (minValue > 0 && state.getBoolAccess() != GL_TRUE)
+			{
+				std::ostringstream buf;
+				buf << "Expected GL_TRUE, got GL_FALSE";
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		case DATATYPE_INTEGER:
+		{
+			if (state.getIntAccess() < minValue)
+			{
+				std::ostringstream buf;
+				buf << "Expected greater or equal to " << minValue << ", got " << state.getIntAccess();
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		case DATATYPE_INTEGER64:
+		{
+			if (state.getInt64Access() < minValue)
+			{
+				std::ostringstream buf;
+				buf << "Expected greater or equal to " << minValue << ", got " << state.getInt64Access();
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		case DATATYPE_FLOAT:
+		{
+			if (state.getFloatAccess() < minValue)
+			{
+				std::ostringstream buf;
+				buf << "Expected greater or equal to " << minValue << ", got " << state.getFloatAccess();
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		default:
+			DE_ASSERT(DE_FALSE);
+			break;
+	}
+}
+
+void verifyIntegerMax (tcu::ResultCollector& result, QueriedState& state, int maxValue)
+{
+	switch (state.getType())
+	{
+		case DATATYPE_BOOLEAN:
+		{
+			if (maxValue < 0 && state.getBoolAccess() != GL_TRUE)
+			{
+				std::ostringstream buf;
+				buf << "Expected GL_TRUE, got GL_FALSE";
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		case DATATYPE_INTEGER:
+		{
+			if (state.getIntAccess() > maxValue)
+			{
+				std::ostringstream buf;
+				buf << "Expected less or equal to " << maxValue << ", got " << state.getIntAccess();
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		case DATATYPE_INTEGER64:
+		{
+			if (state.getInt64Access() > maxValue)
+			{
+				std::ostringstream buf;
+				buf << "Expected less or equal to " << maxValue << ", got " << state.getInt64Access();
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		case DATATYPE_FLOAT:
+		{
+			if (state.getFloatAccess() > maxValue)
+			{
+				std::ostringstream buf;
+				buf << "Expected less or equal to " << maxValue << ", got " << state.getFloatAccess();
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		default:
+			DE_ASSERT(DE_FALSE);
+			break;
+	}
+}
+
+void verifyFloat (tcu::ResultCollector& result, QueriedState& state, float expected)
+{
+	switch (state.getType())
+	{
+		case DATATYPE_BOOLEAN:
+		{
+			const glw::GLboolean reference = (expected == 0.0f) ? (GL_FALSE) : (GL_TRUE);
+			if (state.getBoolAccess() != reference)
+			{
+				std::ostringstream buf;
+				buf << "Expected " << glu::getBooleanStr(reference) << ", got " << glu::getBooleanStr(state.getBoolAccess());
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		case DATATYPE_INTEGER:
+		{
+			const glw::GLint refValueMin = roundGLfloatToNearestIntegerHalfDown<glw::GLint>(expected);
+			const glw::GLint refValueMax = roundGLfloatToNearestIntegerHalfUp<glw::GLint>(expected);
+
+			if (state.getIntAccess() < refValueMin ||
+				state.getIntAccess() > refValueMax)
+			{
+				std::ostringstream buf;
+
+				if (refValueMin == refValueMax)
+					buf << "Expected " << refValueMin << ", got " << state.getIntAccess();
+				else
+					buf << "Expected in range [" << refValueMin << ", " << refValueMax << "], got " << state.getIntAccess();
+
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		case DATATYPE_FLOAT:
+		{
+			if (state.getFloatAccess() != expected)
+			{
+				std::ostringstream buf;
+				buf << "Expected " << expected << ", got " << state.getFloatAccess();
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		case DATATYPE_INTEGER64:
+		{
+			const glw::GLint64 refValueMin = roundGLfloatToNearestIntegerHalfDown<glw::GLint64>(expected);
+			const glw::GLint64 refValueMax = roundGLfloatToNearestIntegerHalfUp<glw::GLint64>(expected);
+
+			if (state.getInt64Access() < refValueMin ||
+				state.getInt64Access() > refValueMax)
+			{
+				std::ostringstream buf;
+
+				if (refValueMin == refValueMax)
+					buf << "Expected " << refValueMin << ", got " << state.getInt64Access();
+				else
+					buf << "Expected in range [" << refValueMin << ", " << refValueMax << "], got " << state.getInt64Access();
+
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		default:
+			DE_ASSERT(DE_FALSE);
+			break;
+	}
+}
+
+void verifyFloatMin (tcu::ResultCollector& result, QueriedState& state, float minValue)
+{
+	switch (state.getType())
+	{
+		case DATATYPE_BOOLEAN:
+		{
+			if (minValue > 0.0f && state.getBoolAccess() != GL_TRUE)
+				result.fail("expected GL_TRUE, got GL_FALSE");
+			break;
+		}
+
+		case DATATYPE_INTEGER:
+		{
+			const glw::GLint refValue = roundGLfloatToNearestIntegerHalfDown<glw::GLint>(minValue);
+
+			if (state.getIntAccess() < refValue)
+			{
+				std::ostringstream buf;
+				buf << "Expected greater or equal to " << refValue << ", got " << state.getIntAccess();
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		case DATATYPE_FLOAT:
+		{
+			if (state.getFloatAccess() < minValue)
+			{
+				std::ostringstream buf;
+				buf << "Expected greater or equal to " << minValue << ", got " << state.getFloatAccess();
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		case DATATYPE_INTEGER64:
+		{
+			const glw::GLint64 refValue = roundGLfloatToNearestIntegerHalfDown<glw::GLint64>(minValue);
+
+			if (state.getInt64Access() < refValue)
+			{
+				std::ostringstream buf;
+				buf << "Expected greater or equal to " << refValue << ", got " << state.getInt64Access();
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		default:
+			DE_ASSERT(DE_FALSE);
+			break;
+	}
+}
+
+void verifyFloatMax (tcu::ResultCollector& result, QueriedState& state, float maxValue)
+{
+	switch (state.getType())
+	{
+		case DATATYPE_BOOLEAN:
+		{
+			if (maxValue < 0.0f && state.getBoolAccess() != GL_TRUE)
+				result.fail("expected GL_TRUE, got GL_FALSE");
+			break;
+		}
+
+		case DATATYPE_INTEGER:
+		{
+			const glw::GLint refValue = roundGLfloatToNearestIntegerHalfUp<glw::GLint>(maxValue);
+
+			if (state.getIntAccess() > refValue)
+			{
+				std::ostringstream buf;
+				buf << "Expected less or equal to " << refValue << ", got " << state.getIntAccess();
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		case DATATYPE_FLOAT:
+		{
+			if (state.getFloatAccess() > maxValue)
+			{
+				std::ostringstream buf;
+				buf << "Expected less or equal to " << maxValue << ", got " << state.getFloatAccess();
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		case DATATYPE_INTEGER64:
+		{
+			const glw::GLint64 refValue = roundGLfloatToNearestIntegerHalfUp<glw::GLint64>(maxValue);
+
+			if (state.getInt64Access() > refValue)
+			{
+				std::ostringstream buf;
+				buf << "Expected less or equal to " << refValue << ", got " << state.getInt64Access();
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		default:
+			DE_ASSERT(DE_FALSE);
+			break;
+	}
+}
+
+void verifyIntegerVec3 (tcu::ResultCollector& result, QueriedState& state, const tcu::IVec3& expected)
+{
+	switch (state.getType())
+	{
+		case DATATYPE_INTEGER_VEC3:
+		{
+			if (state.getIntVec3Access()[0] != expected[0] ||
+				state.getIntVec3Access()[1] != expected[1] ||
+				state.getIntVec3Access()[2] != expected[2])
+			{
+				std::ostringstream buf;
+				buf << "Expected " << expected << ", got " << state.getIntVec3Access();
+				result.fail(buf.str());
+			}
+			break;
+		}
+
+		default:
+			DE_ASSERT(DE_FALSE);
+			break;
+	}
+}
+
+// helpers
+
+void verifyStateBoolean (tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target, bool refValue, QueryType type)
+{
+	QueriedState state;
+
+	queryState(result, gl, type, target, state);
+
+	if (!state.isUndefined())
+		verifyBoolean(result, state, refValue);
+}
+
+void verifyStateInteger (tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target, int refValue, QueryType type)
+{
+	QueriedState state;
+
+	queryState(result, gl, type, target, state);
+
+	if (!state.isUndefined())
+		verifyInteger(result, state, refValue);
+}
+
+void verifyStateIntegerMin (tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target, int minValue, QueryType type)
+{
+	QueriedState state;
+
+	queryState(result, gl, type, target, state);
+
+	if (!state.isUndefined())
+		verifyIntegerMin(result, state, minValue);
+}
+
+void verifyStateIntegerMax (tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target, int maxValue, QueryType type)
+{
+	QueriedState state;
+
+	queryState(result, gl, type, target, state);
+
+	if (!state.isUndefined())
+		verifyIntegerMax(result, state, maxValue);
+}
+
+void verifyStateIntegerEqualToOther (tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target, glw::GLenum other, QueryType type)
+{
+	QueriedState stateA;
+	QueriedState stateB;
+
+	queryState(result, gl, type, target, stateA);
+	queryState(result, gl, type, other, stateB);
+
+	if (stateA.isUndefined() || stateB.isUndefined())
+		return;
+
+	switch (type)
+	{
+		case QUERY_BOOLEAN:
+		{
+			if (stateA.getBoolAccess() != stateB.getBoolAccess())
+				result.fail("expected equal results");
+			break;
+		}
+
+		case QUERY_INTEGER:
+		{
+			if (stateA.getIntAccess() != stateB.getIntAccess())
+				result.fail("expected equal results");
+			break;
+		}
+
+		case QUERY_INTEGER64:
+		{
+			if (stateA.getInt64Access() != stateB.getInt64Access())
+				result.fail("expected equal results");
+			break;
+		}
+
+		case QUERY_FLOAT:
+		{
+			if (stateA.getFloatAccess() != stateB.getFloatAccess())
+				result.fail("expected equal results");
+			break;
+		}
+
+		default:
+			DE_ASSERT(DE_FALSE);
+			break;
+	}
+}
+
+void verifyStateFloat (tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target, float reference, QueryType type)
+{
+	QueriedState state;
+
+	queryState(result, gl, type, target, state);
+
+	if (!state.isUndefined())
+		verifyFloat(result, state, reference);
+}
+
+void verifyStateFloatMin (tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target, float minValue, QueryType type)
+{
+	QueriedState state;
+
+	queryState(result, gl, type, target, state);
+
+	if (!state.isUndefined())
+		verifyFloatMin(result, state, minValue);
+}
+
+void verifyStateFloatMax (tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target, float maxValue, QueryType type)
+{
+	QueriedState state;
+
+	queryState(result, gl, type, target, state);
+
+	if (!state.isUndefined())
+		verifyFloatMax(result, state, maxValue);
+}
+
+void verifyStateIndexedBoolean (tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target, int index, bool expected, QueryType type)
+{
+	QueriedState state;
+
+	queryIndexedState(result, gl, type, target, index, state);
+
+	if (!state.isUndefined())
+		verifyBoolean(result, state, expected);
+}
+
+void verifyStateIndexedInteger (tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target, int index, int expected, QueryType type)
+{
+	QueriedState state;
+
+	queryIndexedState(result, gl, type, target, index, state);
+
+	if (!state.isUndefined())
+		verifyInteger(result, state, expected);
+}
+
+void verifyStateIndexedIntegerMin (tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target, int index, int minValue, QueryType type)
+{
+	QueriedState state;
+
+	queryIndexedState(result, gl, type, target, index, state);
+
+	if (!state.isUndefined())
+		verifyIntegerMin(result, state, minValue);
+}
+
+void verifyStateAttributeInteger (tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target, int index, int expected, QueryType type)
+{
+	QueriedState state;
+
+	queryAttributeState(result, gl, type, target, index, state);
+
+	if (!state.isUndefined())
+		verifyInteger(result, state, expected);
+}
+
+void verifyStateFramebufferInteger (tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target, glw::GLenum pname, int expected, QueryType type)
+{
+	QueriedState state;
+
+	queryFramebufferState(result, gl, type, target, pname, state);
+
+	if (!state.isUndefined())
+		verifyInteger(result, state, expected);
+}
+
+void verifyStateFramebufferIntegerMin (tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target, glw::GLenum pname, int minValue, QueryType type)
+{
+	QueriedState state;
+
+	queryFramebufferState(result, gl, type, target, pname, state);
+
+	if (!state.isUndefined())
+		verifyIntegerMin(result, state, minValue);
+}
+
+void verifyStateProgramInteger (tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLuint program, glw::GLenum pname, int expected, QueryType type)
+{
+	QueriedState state;
+
+	queryProgramState(result, gl, type, program, pname, state);
+
+	if (!state.isUndefined())
+		verifyInteger(result, state, expected);
+}
+
+void verifyStateProgramIntegerVec3 (tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLuint program, glw::GLenum pname, const tcu::IVec3& expected, QueryType type)
+{
+	QueriedState state;
+
+	queryProgramState(result, gl, type, program, pname, state);
+
+	if (!state.isUndefined())
+		verifyIntegerVec3(result, state, expected);
+}
+
+void verifyStatePipelineInteger (tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLuint pipeline, glw::GLenum pname, int expected, QueryType type)
+{
+	QueriedState state;
+
+	queryPipelineState(result, gl, type, pipeline, pname, state);
+
+	if (!state.isUndefined())
+		verifyInteger(result, state, expected);
+}
+
+void verifyStateTextureParamInteger (tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target, glw::GLenum pname, int expected, QueryType type)
+{
+	QueriedState state;
+
+	queryTextureParamState(result, gl, type, target, pname, state);
+
+	if (!state.isUndefined())
+		verifyInteger(result, state, expected);
+}
+
+} // StateQueryUtil
+} // gls
+} // deqp
diff --git a/modules/glshared/glsStateQueryUtil.hpp b/modules/glshared/glsStateQueryUtil.hpp
index e7a2a20..98be0b3 100644
--- a/modules/glshared/glsStateQueryUtil.hpp
+++ b/modules/glshared/glsStateQueryUtil.hpp
@@ -23,9 +23,16 @@
  * \brief State Query test utils.
  *//*--------------------------------------------------------------------*/
 
-#include "deMath.h"
 #include "tcuDefs.hpp"
 #include "tcuTestLog.hpp"
+#include "tcuTestContext.hpp"
+#include "glwDefs.hpp"
+#include "deMath.h"
+
+namespace glu
+{
+class CallLogWrapper;
+} // glu
 
 namespace deqp
 {
@@ -71,36 +78,35 @@
 
 	bool			isUndefined					(void) const;
 	bool			isMemoryContaminated		(void) const;
+	bool			isPreguardContaminated		(void) const;
+	bool			isPostguardContaminated		(void) const;
 	bool			verifyValidity				(tcu::TestContext& testCtx) const;
+	bool			verifyValidity				(tcu::ResultCollector& result) const;
 
 	const T&		get							(void) const { return m_value; }
 
 private:
 	enum
 	{
-		GUARD_VALUE = 0xDEDEADCD
-	};
-	enum
-	{
 		WRITE_GUARD_VALUE = 0xDE
 	};
 
-	deInt32			m_preguard;
-	union
-	{
-		T			m_value;
-		deUint8		m_isWrittenToGuard[sizeof(T)];
-	};
-	deInt32			m_postguard; // \note guards are not const qualified since the GL implementation might modify them
+	T				m_preguard;
+	T				m_value;
+	T				m_postguard; // \note guards are not const qualified since the GL implementation might modify them
 };
 
 template <typename T>
 StateQueryMemoryWriteGuard<T>::StateQueryMemoryWriteGuard (void)
-	: m_preguard	((deInt32)(GUARD_VALUE))
-	, m_postguard	((deInt32)(GUARD_VALUE))
 {
-	for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(m_isWrittenToGuard); ++i)
-		m_isWrittenToGuard[i] = (deUint8)WRITE_GUARD_VALUE;
+	DE_STATIC_ASSERT(sizeof(T) * 3 == sizeof(StateQueryMemoryWriteGuard<T>)); // tightly packed
+
+	for (size_t i = 0; i < sizeof(T); ++i)
+	{
+		((deUint8*)&m_preguard)[i]	= (deUint8)WRITE_GUARD_VALUE;
+		((deUint8*)&m_value)[i]		= (deUint8)WRITE_GUARD_VALUE;
+		((deUint8*)&m_postguard)[i]	= (deUint8)WRITE_GUARD_VALUE;
+	}
 }
 
 template <typename T>
@@ -118,8 +124,8 @@
 template <typename T>
 bool StateQueryMemoryWriteGuard<T>::isUndefined () const
 {
-	for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(m_isWrittenToGuard); ++i)
-		if (m_isWrittenToGuard[i] != (deUint8)WRITE_GUARD_VALUE)
+	for (size_t i = 0; i < sizeof(T); ++i)
+		if (((deUint8*)&m_value)[i] != (deUint8)WRITE_GUARD_VALUE)
 			return false;
 	return true;
 }
@@ -127,7 +133,25 @@
 template <typename T>
 bool StateQueryMemoryWriteGuard<T>::isMemoryContaminated () const
 {
-	return (m_preguard != (deInt32)(GUARD_VALUE)) || (m_postguard != (deInt32)(GUARD_VALUE));
+	return isPreguardContaminated() || isPostguardContaminated();
+}
+
+template <typename T>
+bool StateQueryMemoryWriteGuard<T>::isPreguardContaminated (void) const
+{
+	for (size_t i = 0; i < sizeof(T); ++i)
+		if (((deUint8*)&m_preguard)[i] != (deUint8)WRITE_GUARD_VALUE)
+			return true;
+	return false;
+}
+
+template <typename T>
+bool StateQueryMemoryWriteGuard<T>::isPostguardContaminated (void) const
+{
+	for (size_t i = 0; i < sizeof(T); ++i)
+		if (((deUint8*)&m_postguard)[i] != (deUint8)WRITE_GUARD_VALUE)
+			return true;
+	return false;
 }
 
 template <typename T>
@@ -135,7 +159,7 @@
 {
 	using tcu::TestLog;
 
-	if (m_preguard != (deInt32)(GUARD_VALUE))
+	if (isPreguardContaminated())
 	{
 		testCtx.getLog() << TestLog::Message << "// ERROR: Pre-guard value was modified " << TestLog::EndMessage;
 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS ||
@@ -144,7 +168,7 @@
 
 		return false;
 	}
-	else if (m_postguard != (deInt32)(GUARD_VALUE))
+	else if (isPostguardContaminated())
 	{
 		testCtx.getLog() << TestLog::Message << "// ERROR: Post-guard value was modified " << TestLog::EndMessage;
 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS ||
@@ -166,12 +190,171 @@
 	return true;
 }
 
+template <typename T>
+bool StateQueryMemoryWriteGuard<T>::verifyValidity (tcu::ResultCollector& result) const
+{
+	using tcu::TestLog;
+
+	if (isPreguardContaminated())
+	{
+		result.fail("pre-guard value was modified");
+		return false;
+	}
+	else if (isPostguardContaminated())
+	{
+		result.fail("post-guard value was modified");
+		return false;
+	}
+	else if (isUndefined())
+	{
+		result.fail("Get* did not return a value");
+		return false;
+	}
+
+	return true;
+}
+
 template<typename T>
 std::ostream& operator<< (std::ostream& str, const StateQueryMemoryWriteGuard<T>& guard)
 {
 	return str << guard.get();
 }
 
+// Verifiers
+
+enum QueryType
+{
+	QUERY_BOOLEAN = 0,
+	QUERY_BOOLEAN_VEC4,
+	QUERY_ISENABLED,
+	QUERY_INTEGER,
+	QUERY_INTEGER64,
+	QUERY_FLOAT,
+
+	// indexed
+	QUERY_INDEXED_BOOLEAN,
+	QUERY_INDEXED_INTEGER,
+	QUERY_INDEXED_INTEGER64,
+
+	// attributes
+	QUERY_ATTRIBUTE_INTEGER,
+	QUERY_ATTRIBUTE_FLOAT,
+	QUERY_ATTRIBUTE_PURE_INTEGER,
+	QUERY_ATTRIBUTE_PURE_UNSIGNED_INTEGER,
+
+	// fb
+	QUERY_FRAMEBUFFER_INTEGER,
+
+	// program
+	QUERY_PROGRAM_INTEGER,
+	QUERY_PROGRAM_INTEGER_VEC3,
+
+	// program pipeline
+	QUERY_PIPELINE_INTEGER,
+
+	// texture param
+	QUERY_TEXTURE_PARAM_INTEGER,
+	QUERY_TEXTURE_PARAM_FLOAT,
+
+	// texture level
+	QUERY_TEXTURE_LEVEL_INTEGER,
+	QUERY_TEXTURE_LEVEL_FLOAT,
+
+	QUERY_LAST
+};
+
+enum DataType
+{
+	DATATYPE_BOOLEAN = 0,
+	DATATYPE_INTEGER,
+	DATATYPE_INTEGER64,
+	DATATYPE_FLOAT,
+	DATATYPE_UNSIGNED_INTEGER,
+	DATATYPE_INTEGER_VEC3,
+
+	DATATYPE_LAST
+};
+
+class QueriedState
+{
+public:
+	typedef glw::GLint GLIntVec3[3];
+
+							QueriedState		(void);
+	explicit				QueriedState		(glw::GLint);
+	explicit				QueriedState		(glw::GLint64);
+	explicit				QueriedState		(glw::GLboolean);
+	explicit				QueriedState		(glw::GLfloat);
+	explicit				QueriedState		(glw::GLuint);
+	explicit				QueriedState		(const GLIntVec3&);
+
+	bool					isUndefined			(void) const;
+	DataType				getType				(void) const;
+
+	glw::GLint&				getIntAccess		(void);
+	glw::GLint64&			getInt64Access		(void);
+	glw::GLboolean&			getBoolAccess		(void);
+	glw::GLfloat&			getFloatAccess		(void);
+	glw::GLuint&			getUintAccess		(void);
+	GLIntVec3&				getIntVec3Access	(void);
+
+private:
+	DataType				m_type;
+	union
+	{
+		glw::GLint			vInt;
+		glw::GLint64		vInt64;
+		glw::GLboolean		vBool;
+		glw::GLfloat		vFloat;
+		glw::GLuint			vUint;
+		GLIntVec3			vIntVec3;
+	} m_v;
+};
+
+// query functions
+
+void queryState							(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, QueriedState& state);
+void queryIndexedState					(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, int index, QueriedState& state);
+void queryAttributeState				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, int index, QueriedState& state);
+void queryFramebufferState				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, glw::GLenum pname, QueriedState& state);
+void queryProgramState					(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLuint program, glw::GLenum pname, QueriedState& state);
+void queryPipelineState					(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLuint pipeline, glw::GLenum pname, QueriedState& state);
+void queryTextureParamState				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, glw::GLenum pname, QueriedState& state);
+void queryTextureLevelState				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, int level, glw::GLenum pname, QueriedState& state);
+
+// verification functions
+
+void verifyBoolean						(tcu::ResultCollector& result, QueriedState& state, bool expected);
+void verifyInteger						(tcu::ResultCollector& result, QueriedState& state, int expected);
+void verifyIntegerMin					(tcu::ResultCollector& result, QueriedState& state, int minValue);
+void verifyIntegerMax					(tcu::ResultCollector& result, QueriedState& state, int maxValue);
+void verifyIntegersEqual				(tcu::ResultCollector& result, QueriedState& stateA, QueriedState& stateB);
+void verifyFloat						(tcu::ResultCollector& result, QueriedState& state, float expected);
+void verifyFloatMin						(tcu::ResultCollector& result, QueriedState& state, float minValue);
+void verifyFloatMax						(tcu::ResultCollector& result, QueriedState& state, float maxValue);
+void verifyIntegerVec3					(tcu::ResultCollector& result, QueriedState& state, const tcu::IVec3& expected);
+
+// Helper functions that both query and verify
+
+void verifyStateBoolean					(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		bool expected,		QueryType type);
+void verifyStateInteger					(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int expected,		QueryType type);
+void verifyStateIntegerMin				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int minValue,		QueryType type);
+void verifyStateIntegerMax				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int maxValue,		QueryType type);
+void verifyStateIntegerEqualToOther		(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		glw::GLenum other,	QueryType type);
+void verifyStateFloat					(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		float reference,	QueryType type);
+void verifyStateFloatMin				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		float minValue,		QueryType type);
+void verifyStateFloatMax				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		float maxValue,		QueryType type);
+void verifyStateIndexedBoolean			(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int index,			bool expected,				QueryType type);
+void verifyStateIndexedInteger			(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int index,			int expected,				QueryType type);
+void verifyStateIndexedIntegerMin		(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int index,			int minValue,				QueryType type);
+void verifyStateAttributeInteger		(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int index,			int expected,				QueryType type);
+void verifyStateFramebufferInteger		(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		glw::GLenum pname,	int expected,				QueryType type);
+void verifyStateFramebufferIntegerMin	(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		glw::GLenum pname,	int minValue,				QueryType type);
+void verifyStateProgramInteger			(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLuint program,	glw::GLenum pname,	int expected,				QueryType type);
+void verifyStateProgramIntegerVec3		(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLuint program, 	glw::GLenum pname,	const tcu::IVec3& expected,	QueryType type);
+void verifyStatePipelineInteger			(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLuint pipeline,	glw::GLenum pname,	int expected,				QueryType type);
+void verifyStateTextureParamInteger		(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		glw::GLenum pname,	int expected,				QueryType type);
+
 } // StateQueryUtil
 } // gls
 } // deqp
diff --git a/scripts/opengl/gen_call_log_wrapper.py b/scripts/opengl/gen_call_log_wrapper.py
index 0f5f47e..10a4274 100644
--- a/scripts/opengl/gen_call_log_wrapper.py
+++ b/scripts/opengl/gen_call_log_wrapper.py
@@ -87,6 +87,7 @@
 	"glDeleteBuffers":						LogSpec({1: pointer(size = "n")}),
 	"glDeleteTextures":						LogSpec({1: pointer(size = "n")}),
 	"glDeleteVertexArrays":					LogSpec({1: pointer(size = "n")}),
+	"glDeleteProgramPipelines":				LogSpec({1: pointer(size = "n")}),
 	"glDepthFunc":							LogSpec({0: enum("CompareFunc")}),
 	"glDisable":							LogSpec({0: enum("EnableCap")}),
 	"glDrawArrays":							LogSpec({0: enum("PrimitiveType")}),
@@ -119,6 +120,7 @@
 	"glGenTextures":						LogSpec({}, argOutPrints = {1: pointer(size = "n")}),
 	"glGenTransformFeedbacks":				LogSpec({}, argOutPrints = {1: pointer(size = "n")}),
 	"glGenVertexArrays":					LogSpec({}, argOutPrints = {1: pointer(size = "n")}),
+	"glGenProgramPipelines":				LogSpec({}, argOutPrints = {1: pointer(size = "n")}),
 #	"glGetActiveAttrib":
 	"glGetActiveUniform":					LogSpec({}, argOutPrints = {3: pointer(size = "1"), 4: pointer(size = "1"), 5: enumPointer("ShaderVarType", size = "1"), 6: stringVal}),
 	"glGetActiveUniformsiv":				LogSpec({2: pointer(size = "uniformCount"), 3: enum("UniformParam")}, argOutPrints = {4: pointer(size = "uniformCount")}),
@@ -143,16 +145,25 @@
 				2: enum("FramebufferAttachmentParameter")
 			},
 			argOutPrints = {3: lambda name: "getFramebufferAttachmentParameterValueStr(pname, %s)" % name}),
-	"glGetFramebufferParameteriv":			LogSpec({0: enum("FramebufferTarget"), 1: enum("FramebufferParameter")}),
+	"glGetFramebufferParameteriv":			LogSpec({0: enum("FramebufferTarget"), 1: enum("FramebufferParameter")}, argOutPrints = {2: pointer(size = "1")}),
 	"glGetIntegerv":						LogSpec({0: enum("GettableState")}, argOutPrints = {1: pointer(size = "getBasicQueryNumArgsOut(pname)")}),
 	"glGetInteger64v":						LogSpec({0: enum("GettableState")}, argOutPrints = {1: pointer(size = "getBasicQueryNumArgsOut(pname)")}),
-	"glGetIntegeri_v":						LogSpec({0: enum("GettableIndexedState")}),
-	"glGetInteger64i_v":					LogSpec({0: enum("GettableIndexedState")}),
+	"glGetIntegeri_v":						LogSpec({0: enum("GettableIndexedState")}, argOutPrints = {2: pointer(size = "1")}),
+	"glGetInteger64i_v":					LogSpec({0: enum("GettableIndexedState")}, argOutPrints = {2: pointer(size = "1")}),
+	"glGetBooleani_v":
+		LogSpec(
+			{
+				0: enum("GettableIndexedState"),
+				2: voidPointer					# last argument has type of GLboolean* (aka. char*). Prevent
+												# wrapper from attempting to print the argument as a C string.
+			},
+			argOutPrints = {2: booleanPointer(size = "1")}),
 	"glGetInternalformativ":				LogSpec({0: enum("InternalFormatTarget"), 1: enum("PixelFormat"), 2: enum("InternalFormatParameter")}, argOutPrints = {4: pointer(size = "bufSize")}),
 	"glGetMultisamplefv":					LogSpec({0: enum("MultisampleParameter")}, argOutPrints = {2: pointer(size = "2")}),
-	"glGetProgramiv":						LogSpec({1: enum("ProgramParam")}, argOutPrints = {2: pointer(size = "1")}),
+	"glGetProgramiv":						LogSpec({1: enum("ProgramParam")}, argOutPrints = {2: pointer(size = "getProgramQueryNumArgsOut(pname)")}),
 #	"glGetProgramInfoLog":
 	"glGetProgramPipelineiv":				LogSpec({1: enum("PipelineParam")}, argOutPrints = {2: pointer(size = "1")}),
+	"glGetProgramPipelineInfoLog":			LogSpec({3: voidPointer}, argOutPrints = {2: pointer(size = "1")}),
 	"glGetQueryiv":							LogSpec({0: enum("QueryTarget"), 1: enum("QueryParam")}, argOutPrints = {2: pointer(size = "1")}),
 	"glGetQueryObjectiv":					LogSpec({1: enum("QueryObjectParam")}, argOutPrints = {2: pointer(size = "1")}),
 	"glGetQueryObjectuiv":					LogSpec({1: enum("QueryObjectParam")}, argOutPrints = {2: pointer(size = "1")}),
@@ -167,10 +178,10 @@
 #	"glGetShaderSource":
 	"glGetString":							LogSpec({0: enum("GettableString")}),
 	"glGetStringi":							LogSpec({0: enum("GettableString")}),
-	"glGetTexParameterfv":					LogSpec({0: enum("TextureTarget"), 1: enum("TextureParameter")}),
-	"glGetTexParameteriv":					LogSpec({0: enum("TextureTarget"), 1: enum("TextureParameter")}),
-	"glGetTexLevelParameterfv":				LogSpec({0: enum("TextureTarget"), 2: enum("TextureLevelParameter")}),
-	"glGetTexLevelParameteriv":				LogSpec({0: enum("TextureTarget"), 2: enum("TextureLevelParameter")}),
+	"glGetTexParameterfv":					LogSpec({0: enum("TextureTarget"), 1: enum("TextureParameter")}, argOutPrints = {2: pointer(size = "1")}),
+	"glGetTexParameteriv":					LogSpec({0: enum("TextureTarget"), 1: enum("TextureParameter")}, argOutPrints = {2: pointer(size = "1")}),
+	"glGetTexLevelParameterfv":				LogSpec({0: enum("TextureTarget"), 2: enum("TextureLevelParameter")}, argOutPrints = {3: pointer(size = "1")}),
+	"glGetTexLevelParameteriv":				LogSpec({0: enum("TextureTarget"), 2: enum("TextureLevelParameter")}, argOutPrints = {3: pointer(size = "1")}),
 #	"glGetUniformfv":
 #	"glGetUniformiv":
 	"glGetUniformIndices":					LogSpec({2: pointer(size = "uniformCount")}, argOutPrints = {3: pointer(size = "uniformCount")}),
@@ -201,9 +212,9 @@
 	"glTexStorage3DMultisample":			LogSpec({0: enum("TextureTarget"), 2: enum("PixelFormat"), 6: enum("Boolean")}),
 	# \todo [2012-03-08 pyry] Pointer values..
 	"glTexParameterf":						LogSpec({0: enum("TextureTarget"), 1: enum("TextureParameter")}),
-	"glTexParameterfv":						LogSpec({0: enum("TextureTarget"), 1: enum("TextureParameter")}),
+	"glTexParameterfv":						LogSpec({0: enum("TextureTarget"), 1: enum("TextureParameter"), 2: pointer(size = "1")}),
 	"glTexParameteri":						LogSpec({0: enum("TextureTarget"), 1: enum("TextureParameter"), 2: lambda name: "getTextureParameterValueStr(pname, %s)" % name}),
-	"glTexParameteriv":						LogSpec({0: enum("TextureTarget"), 1: enum("TextureParameter")}),
+	"glTexParameteriv":						LogSpec({0: enum("TextureTarget"), 1: enum("TextureParameter"), 2: pointer(size = "1")}),
 	"glTexSubImage1D":						LogSpec({0: enum("TextureTarget"), 4: enum("PixelFormat"), 5: enum("Type")}),
 	"glTexSubImage2D":						LogSpec({0: enum("TextureTarget"), 6: enum("PixelFormat"), 7: enum("Type")}),
 	"glTexSubImage3D":						LogSpec({0: enum("TextureTarget"), 8: enum("PixelFormat"), 9: enum("Type")}),
@@ -228,6 +239,8 @@
 	"glUniformMatrix3x4fv":					LogSpec({3: pointer(size = "(count * 3*4)")}),
 	"glUniformMatrix4x2fv":					LogSpec({3: pointer(size = "(count * 4*2)")}),
 	"glUniformMatrix4x3fv":					LogSpec({3: pointer(size = "(count * 4*3)")}),
+	"glUseProgramStages":					LogSpec({1: enum("ShaderTypeMask")}),
+	"glProgramParameteri":					LogSpec({1: enum("ProgramParam")}),
 	"glProgramUniform1fv":					LogSpec({3: pointer(size = "(count * 1)")}),
 	"glProgramUniform1iv":					LogSpec({3: pointer(size = "(count * 1)")}),
 	"glProgramUniform1uiv":					LogSpec({3: pointer(size = "(count * 1)")}),
@@ -363,13 +376,20 @@
 
 	if logSpec and len(logSpec.argOutPrints) > 0:
 		# Print values returned in pointers
-		src += "\tif (m_enableLog)\n\t{\n"
+		src += "\tif (m_enableLog)\n"
+		printouts = ""
+		numPrintouts = 0
 
 		for paramNdx, param in enumerate(command.params):
 			if paramNdx in logSpec.argOutPrints:
-				src += "\t\tm_log << TestLog::Message << \"// %s = \" << %s << TestLog::EndMessage;\n" % (param.name, logSpec.argOutPrints[paramNdx](param.name))
+				printouts += "\t\tm_log << TestLog::Message << \"// %s = \" << %s << TestLog::EndMessage;\n" % (param.name, logSpec.argOutPrints[paramNdx](param.name))
+				numPrintouts += 1
 
-		src += "\t}\n"
+		if numPrintouts > 1:
+			src += "\t{\n"
+		src += printouts
+		if numPrintouts > 1:
+			src += "\t}\n"
 
 	if not isVoid:
 		# Print return value
diff --git a/scripts/opengl/gen_query_util.py b/scripts/opengl/gen_query_util.py
index ea9b280..ac21b84 100644
--- a/scripts/opengl/gen_query_util.py
+++ b/scripts/opengl/gen_query_util.py
@@ -41,6 +41,10 @@
 	("Attribute", [
 		("CURRENT_VERTEX_ATTRIB",		4),
 		]),
+
+	("Program", [
+		("COMPUTE_WORK_GROUP_SIZE",		3),
+		]),
 ]
 
 def addNamePrefix (prefix, groups):
diff --git a/scripts/opengl/gen_str_util.py b/scripts/opengl/gen_str_util.py
index 91d9ceb..c85ed7f 100644
--- a/scripts/opengl/gen_str_util.py
+++ b/scripts/opengl/gen_str_util.py
@@ -57,7 +57,16 @@
 		"FRAMEBUFFER_BARRIER_BIT",
 		"TRANSFORM_FEEDBACK_BARRIER_BIT",
 		"ATOMIC_COUNTER_BARRIER_BIT"
-		])
+		]),
+	# ShaderTypeMask
+	("ShaderTypeMask",	[
+		"VERTEX_SHADER_BIT",
+		"FRAGMENT_SHADER_BIT",
+		"COMPUTE_SHADER_BIT",
+		"GEOMETRY_SHADER_BIT",
+		"TESS_CONTROL_SHADER_BIT",
+		"TESS_EVALUATION_SHADER_BIT"
+		]),
 ]
 
 # Enum mapping
@@ -184,6 +193,9 @@
 		"GEOMETRY_OUTPUT_TYPE",
 		"GEOMETRY_VERTICES_OUT",
 		"GEOMETRY_SHADER_INVOCATIONS",
+		"PROGRAM_SEPARABLE",
+		"COMPUTE_WORK_GROUP_SIZE",
+		"ACTIVE_ATOMIC_COUNTER_BUFFERS",
 		]),
 
 	# *missing*
@@ -259,7 +271,9 @@
 		"UNIFORM_BUFFER",
 		"DRAW_INDIRECT_BUFFER",
 		"SHADER_STORAGE_BUFFER",
-		"TEXTURE_BUFFER"
+		"TEXTURE_BUFFER",
+		"DISPATCH_INDIRECT_BUFFER",
+		"ATOMIC_COUNTER_BUFFER",
 		]),
 	("BufferBinding",		["ARRAY_BUFFER_BINDING", "ELEMENT_ARRAY_BUFFER_BINDING"]),
 	("Usage",				[
@@ -285,7 +299,7 @@
 							 "POLYGON_OFFSET_FILL", "SAMPLE_ALPHA_TO_COVERAGE", "SAMPLE_COVERAGE",
 							 "PRIMITIVE_RESTART_FIXED_INDEX", "RASTERIZER_DISCARD",
 							 "FRAMEBUFFER_SRGB", "SAMPLE_SHADING", "DEPTH_CLAMP",
-							 "PRIMITIVE_RESTART"]),
+							 "PRIMITIVE_RESTART", "SAMPLE_MASK"]),
 
 	# Polygon winding
 	("Winding",				["CW", "CCW"]),
@@ -357,6 +371,7 @@
 		"TEXTURE_SWIZZLE_A",
 		"TEXTURE_MIN_FILTER",
 		"TEXTURE_MAG_FILTER",
+		"DEPTH_STENCIL_TEXTURE_MODE",
 
 		# Gettable only
 		"TEXTURE_IMMUTABLE_LEVELS",
@@ -392,6 +407,7 @@
 	("CubeMapFace",			["TEXTURE_CUBE_MAP_POSITIVE_X", "TEXTURE_CUBE_MAP_NEGATIVE_X",
 							 "TEXTURE_CUBE_MAP_POSITIVE_Y", "TEXTURE_CUBE_MAP_NEGATIVE_Y",
 							 "TEXTURE_CUBE_MAP_POSITIVE_Z", "TEXTURE_CUBE_MAP_NEGATIVE_Z"]),
+	("TextureDepthStencilMode",	["DEPTH_COMPONENT", "STENCIL_INDEX"]),
 	("PixelStoreParameter",	[
 		"UNPACK_ALIGNMENT",
 		"UNPACK_IMAGE_HEIGHT",
@@ -677,7 +693,10 @@
 		"MAX_COMPUTE_IMAGE_UNIFORMS",		"MAX_COMPUTE_SHADER_STORAGE_BLOCKS","MAX_FRAGMENT_SHADER_STORAGE_BLOCKS", 				"MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS",	"MAX_VERTEX_ATOMIC_COUNTER_BUFFERS",
 		"MAX_VERTEX_ATOMIC_COUNTERS",		"MAX_VERTEX_IMAGE_UNIFORMS",		"MAX_VERTEX_SHADER_STORAGE_BLOCKS",					"MAX_COMBINED_SHADER_OUTPUT_RESOURCES",		"MAX_ATOMIC_COUNTER_BUFFER_BINDINGS",
 		"MAX_ATOMIC_COUNTER_BUFFER_SIZE",	"MAX_IMAGE_UNITS",					"MAX_COMBINED_ATOMIC_COUNTER_BUFFERS",				"MAX_COMBINED_IMAGE_UNIFORMS",				"MAX_SHADER_STORAGE_BUFFER_BINDINGS",
-		"MAX_SHADER_STORAGE_BLOCK_SIZE",	"MAX_COMBINED_ATOMIC_COUNTERS",		"MAX_COMBINED_SHADER_STORAGE_BLOCKS",				"SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT",	"PRIMITIVE_BOUNDING_BOX_EXT"
+		"MAX_SHADER_STORAGE_BLOCK_SIZE",	"MAX_COMBINED_ATOMIC_COUNTERS",		"MAX_COMBINED_SHADER_STORAGE_BLOCKS",				"SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT",	"PRIMITIVE_BOUNDING_BOX_EXT",
+		"DRAW_INDIRECT_BUFFER_BINDING",		"MAX_SAMPLE_MASK_WORDS",			"PROGRAM_PIPELINE_BINDING",							"ATOMIC_COUNTER_BUFFER_BINDING",			"SHADER_STORAGE_BUFFER_BINDING",
+		"DISPATCH_INDIRECT_BUFFER_BINDING",	"MAX_FRAMEBUFFER_WIDTH",			"MAX_FRAMEBUFFER_HEIGHT",							"MAX_FRAMEBUFFER_SAMPLES",					"MAX_COMPUTE_SHARED_MEMORY_SIZE",
+		"MIN_PROGRAM_TEXTURE_GATHER_OFFSET","MAX_PROGRAM_TEXTURE_GATHER_OFFSET","MAX_COMPUTE_WORK_GROUP_INVOCATIONS",				"MAX_UNIFORM_LOCATIONS",
 	]),
 
 	("GettableIndexedState", [
@@ -692,6 +711,20 @@
 		"VERTEX_BINDING_STRIDE",
 		"VERTEX_BINDING_DIVISOR",
 		"VERTEX_BINDING_BUFFER",
+		"MAX_COMPUTE_WORK_GROUP_COUNT",
+		"MAX_COMPUTE_WORK_GROUP_SIZE",
+		"ATOMIC_COUNTER_BUFFER_BINDING",
+		"ATOMIC_COUNTER_BUFFER_START",
+		"ATOMIC_COUNTER_BUFFER_SIZE",
+		"SHADER_STORAGE_BUFFER_BINDING",
+		"SHADER_STORAGE_BUFFER_START",
+		"SHADER_STORAGE_BUFFER_SIZE",
+		"IMAGE_BINDING_NAME",
+		"IMAGE_BINDING_LEVEL",
+		"IMAGE_BINDING_LAYERED",
+		"IMAGE_BINDING_LAYER",
+		"IMAGE_BINDING_ACCESS",
+		"IMAGE_BINDING_FORMAT",
 	]),
 
 	("GettableString", [