Add new framebuffer fetch extension tests
authorJohn Richardson <john.richardson@mobica.com>
Mon, 20 Mar 2017 17:29:54 +0000 (17:29 +0000)
committerMika Isojärvi <misojarvi@google.com>
Tue, 11 Jul 2017 17:30:10 +0000 (10:30 -0700)
New tests for EXT_shader_framebuffer_buffer_fetch extension. Test cases
for accessing existing framebuffer data as input in the fragment shader.
Includes negative tests cases for invalid shader usage.

New tests:
- dEQP-GLES31.functional.shaders.framebuffer_fetch.basic.*
- dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.*
- dEQP-GLES31.functional.debug.negative_coverage.*.framebuffer_fetch.*

Change-Id: I8f8aa2312e26c2c709d3e2e2733c497e24669da8

android/cts/master/gles31-master.txt
modules/gles31/functional/CMakeLists.txt
modules/gles31/functional/es31fDebugTests.cpp
modules/gles31/functional/es31fFunctionalTests.cpp
modules/gles31/functional/es31fNegativeShaderFramebufferFetchTests.cpp [new file with mode: 0644]
modules/gles31/functional/es31fNegativeShaderFramebufferFetchTests.hpp [new file with mode: 0644]
modules/gles31/functional/es31fShaderFramebufferFetchTests.cpp [new file with mode: 0644]
modules/gles31/functional/es31fShaderFramebufferFetchTests.hpp [new file with mode: 0644]

index f19e50a..f5c06b0 100644 (file)
@@ -5584,6 +5584,49 @@ dEQP-GLES31.functional.shaders.uniform_block.invalid.layout_std430_vertex
 dEQP-GLES31.functional.shaders.uniform_block.invalid.layout_std430_fragment
 dEQP-GLES31.functional.shaders.uniform_block.invalid.global_layout_std430_vertex
 dEQP-GLES31.functional.shaders.uniform_block.invalid.global_layout_std430_fragment
+dEQP-GLES31.functional.shaders.framebuffer_fetch.basic.texel_fetch
+dEQP-GLES31.functional.shaders.framebuffer_fetch.basic.last_frag_data
+dEQP-GLES31.functional.shaders.framebuffer_fetch.basic.fragment_discard
+dEQP-GLES31.functional.shaders.framebuffer_fetch.basic.multiple_assignment
+dEQP-GLES31.functional.shaders.framebuffer_fetch.basic.multiple_render_targets
+dEQP-GLES31.functional.shaders.framebuffer_fetch.basic.framebuffer_texture_level
+dEQP-GLES31.functional.shaders.framebuffer_fetch.basic.framebuffer_texture_layer
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rgba32i
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rgba32ui
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rgba16i
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rgba16ui
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rgba8
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rgba8i
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rgba8ui
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.srgb8_alpha8
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rgb10_a2
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rgb10_a2ui
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rgba4
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rgb5_a1
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rgb8
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rgb565
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rg32i
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rg32ui
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rg16i
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rg16ui
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rg8
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rg8i
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rg8ui
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.r32i
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.r32ui
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.r16i
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.r16ui
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.r8
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.r8i
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.r8ui
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rgba32f
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rgba16f
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.r11f_g11f_b10f
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rg32f
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rg16f
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.r32f
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.r16f
+dEQP-GLES31.functional.shaders.framebuffer_fetch.framebuffer_format.rgb16f
 dEQP-GLES31.functional.compute.basic.empty
 dEQP-GLES31.functional.compute.basic.ubo_to_ssbo_single_invocation
 dEQP-GLES31.functional.compute.basic.ubo_to_ssbo_single_group
@@ -16824,6 +16867,11 @@ dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.exceed_shared_m
 dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.exceed_uniform_components_limit
 dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.exceed_atomic_counter_buffer_limit
 dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.exceed_atomic_counters_limit
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.framebuffer_fetch.last_frag_data_not_defined
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.framebuffer_fetch.last_frag_data_readonly
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.framebuffer_fetch.invalid_inout_version
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.framebuffer_fetch.invalid_redeclaration_inout
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.framebuffer_fetch.invalid_vertex_inout
 dEQP-GLES31.functional.debug.negative_coverage.log.buffer.bind_buffer
 dEQP-GLES31.functional.debug.negative_coverage.log.buffer.delete_buffers
 dEQP-GLES31.functional.debug.negative_coverage.log.buffer.gen_buffers
@@ -17320,6 +17368,11 @@ dEQP-GLES31.functional.debug.negative_coverage.log.compute.exceed_shared_memory_
 dEQP-GLES31.functional.debug.negative_coverage.log.compute.exceed_uniform_components_limit
 dEQP-GLES31.functional.debug.negative_coverage.log.compute.exceed_atomic_counter_buffer_limit
 dEQP-GLES31.functional.debug.negative_coverage.log.compute.exceed_atomic_counters_limit
+dEQP-GLES31.functional.debug.negative_coverage.log.framebuffer_fetch.last_frag_data_not_defined
+dEQP-GLES31.functional.debug.negative_coverage.log.framebuffer_fetch.last_frag_data_readonly
+dEQP-GLES31.functional.debug.negative_coverage.log.framebuffer_fetch.invalid_inout_version
+dEQP-GLES31.functional.debug.negative_coverage.log.framebuffer_fetch.invalid_redeclaration_inout
+dEQP-GLES31.functional.debug.negative_coverage.log.framebuffer_fetch.invalid_vertex_inout
 dEQP-GLES31.functional.debug.negative_coverage.get_error.buffer.bind_buffer
 dEQP-GLES31.functional.debug.negative_coverage.get_error.buffer.delete_buffers
 dEQP-GLES31.functional.debug.negative_coverage.get_error.buffer.gen_buffers
@@ -17814,6 +17867,11 @@ dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.exceed_shared_m
 dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.exceed_uniform_components_limit
 dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.exceed_atomic_counter_buffer_limit
 dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.exceed_atomic_counters_limit
+dEQP-GLES31.functional.debug.negative_coverage.get_error.framebuffer_fetch.last_frag_data_not_defined
+dEQP-GLES31.functional.debug.negative_coverage.get_error.framebuffer_fetch.last_frag_data_readonly
+dEQP-GLES31.functional.debug.negative_coverage.get_error.framebuffer_fetch.invalid_inout_version
+dEQP-GLES31.functional.debug.negative_coverage.get_error.framebuffer_fetch.invalid_redeclaration_inout
+dEQP-GLES31.functional.debug.negative_coverage.get_error.framebuffer_fetch.invalid_vertex_inout
 dEQP-GLES31.functional.debug.externally_generated.application_messages
 dEQP-GLES31.functional.debug.externally_generated.third_party_messages
 dEQP-GLES31.functional.debug.externally_generated.push_pop_stack
index f9f21c7..a4ac348 100644 (file)
@@ -189,6 +189,10 @@ set(DEQP_GLES31_FUNCTIONAL_SRCS
        es31fDrawElementsBaseVertexTests.hpp
        es31fNegativeComputeTests.cpp
        es31fNegativeComputeTests.hpp
+       es31fShaderFramebufferFetchTests.cpp
+       es31fShaderFramebufferFetchTests.hpp
+       es31fNegativeShaderFramebufferFetchTests.cpp
+       es31fNegativeShaderFramebufferFetchTests.hpp
        )
 
 add_library(deqp-gles31-functional STATIC ${DEQP_GLES31_FUNCTIONAL_SRCS})
index 242974b..1613179 100644 (file)
@@ -41,6 +41,7 @@
 #include "es31fNegativeTessellationTests.hpp"
 #include "es31fNegativeComputeTests.hpp"
 #include "es31fNegativeSampleVariablesTests.hpp"
+#include "es31fNegativeShaderFramebufferFetchTests.hpp"
 
 #include "deUniquePtr.hpp"
 #include "deRandom.hpp"
@@ -2964,6 +2965,7 @@ void DebugTests::init (void)
        const vector<FunctionContainer> shaderStorageFuncs               = wrapCoreFunctions(NegativeTestShared::getNegativeShaderStorageTestFunctions());
        const vector<FunctionContainer> sampleVariablesFuncs     = wrapCoreFunctions(NegativeTestShared::getNegativeSampleVariablesTestFunctions());
        const vector<FunctionContainer> computeFuncs                     = wrapCoreFunctions(NegativeTestShared::getNegativeComputeTestFunctions());
+       const vector<FunctionContainer> framebufferFetchFuncs    = wrapCoreFunctions(NegativeTestShared::getNegativeShaderFramebufferFetchTestFunctions());
        const vector<FunctionContainer> externalFuncs                    = getUserMessageFuncs();
 
        {
@@ -3074,6 +3076,7 @@ void DebugTests::init (void)
                        host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "tessellation",                           "Negative Tessellation Cases",                                          tessellationFuncs));
                        host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "oes_sample_variables",           "Negative Sample Variables Cases",                                      sampleVariablesFuncs));
                        host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "compute",                                        "Negative Compute Cases",                                                       computeFuncs));
+                       host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "framebuffer_fetch",                      "Negative Framebuffer Fetch Cases",                                     framebufferFetchFuncs));
                }
 
                {
@@ -3101,6 +3104,7 @@ void DebugTests::init (void)
                        host->addChild(createChildCases(CASETYPE_LOG, m_context, "tessellation",                        "Negative Tessellation Cases",                                          tessellationFuncs));
                        host->addChild(createChildCases(CASETYPE_LOG, m_context, "oes_sample_variables",        "Negative Sample Variables Cases",                                      sampleVariablesFuncs));
                        host->addChild(createChildCases(CASETYPE_LOG, m_context, "compute",                                     "Negative Compute Cases",                                                       computeFuncs));
+                       host->addChild(createChildCases(CASETYPE_LOG, m_context, "framebuffer_fetch",           "Negative Framebuffer Fetch Cases",                                     framebufferFetchFuncs));
                }
 
                {
@@ -3128,6 +3132,7 @@ void DebugTests::init (void)
                        host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "tessellation",                           "Negative Tessellation Cases",                                          tessellationFuncs));
                        host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "oes_sample_variables",           "Negative Sample Variables Cases",                                      sampleVariablesFuncs));
                        host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "compute",                                        "Negative Compute Cases",                                                       computeFuncs));
+                       host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "framebuffer_fetch",                      "Negative Framebuffer Fetch Cases",                                     framebufferFetchFuncs));
                }
        }
 
index 866fcca..3fb407e 100644 (file)
@@ -91,6 +91,7 @@
 #include "es31fDefaultVertexArrayObjectTests.hpp"
 #include "es31fSRGBDecodeTests.hpp"
 #include "es31fDrawElementsBaseVertexTests.hpp"
+#include "es31fShaderFramebufferFetchTests.hpp"
 
 namespace deqp
 {
@@ -202,6 +203,7 @@ public:
                addChild(new ShaderHelperInvocationTests                (m_context));
                addChild(new ShaderLibraryTest                                  (m_context, "implicit_conversions", "GL_EXT_shader_implicit_conversions Tests"));
                addChild(new ShaderLibraryTest                                  (m_context, "uniform_block", "Uniform block tests"));
+               addChild(new ShaderFramebufferFetchTests                (m_context));
        }
 };
 
diff --git a/modules/gles31/functional/es31fNegativeShaderFramebufferFetchTests.cpp b/modules/gles31/functional/es31fNegativeShaderFramebufferFetchTests.cpp
new file mode 100644 (file)
index 0000000..b74c5a6
--- /dev/null
@@ -0,0 +1,267 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2017 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 Negative ShaderFramebufferFetch tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "es31fNegativeShaderFramebufferFetchTests.hpp"
+#include "gluContextInfo.hpp"
+#include "gluShaderProgram.hpp"
+#include "tcuStringTemplate.hpp"
+
+namespace deqp
+{
+
+using std::string;
+using std::map;
+
+namespace gles31
+{
+namespace Functional
+{
+namespace NegativeTestShared
+{
+namespace
+{
+
+static const char* vertexShaderSource          =       "${GLSL_VERSION_STRING}\n"
+                                                                                               "\n"
+                                                                                               "void main (void)\n"
+                                                                                               "{\n"
+                                                                                               "       gl_Position = vec4(0.0);\n"
+                                                                                               "}\n";
+
+static const char* fragmentShaderSource                =       "${GLSL_VERSION_STRING}\n"
+                                                                                               "layout(location = 0) out mediump vec4 fragColor;\n"
+                                                                                               "\n"
+                                                                                               "void main (void)\n"
+                                                                                               "{\n"
+                                                                                               "       fragColor = vec4(1.0);\n"
+                                                                                               "}\n";
+
+static void checkExtensionSupport (NegativeTestContext& ctx, const char* extName)
+{
+       if (!ctx.getContextInfo().isExtensionSupported(extName))
+               throw tcu::NotSupportedError(string(extName) + " not supported");
+}
+
+static void checkFramebufferFetchSupport (NegativeTestContext& ctx)
+{
+       checkExtensionSupport(ctx, "GL_EXT_shader_framebuffer_fetch");
+}
+
+enum ProgramError
+{
+       PROGRAM_ERROR_LINK = 0,
+       PROGRAM_ERROR_COMPILE,
+       PROGRAM_ERROR_COMPILE_OR_LINK,
+};
+
+void verifyProgramError (NegativeTestContext& ctx, const glu::ShaderProgram& program,  ProgramError error, glu::ShaderType shaderType)
+{
+       bool    testFailed = false;
+       string  message;
+
+       ctx.getLog() << program;
+
+       switch (error)
+       {
+               case PROGRAM_ERROR_LINK:
+               {
+                       message = "Program was not expected to link.";
+                       testFailed = (program.getProgramInfo().linkOk);
+                       break;
+               }
+               case PROGRAM_ERROR_COMPILE:
+               {
+                       message = "Program was not expected to compile.";
+                       testFailed = program.getShaderInfo(shaderType).compileOk;
+                       break;
+               }
+               case PROGRAM_ERROR_COMPILE_OR_LINK:
+               {
+                       message = "Program was not expected to compile or link.";
+                       testFailed = (program.getProgramInfo().linkOk) && (program.getShaderInfo(shaderType).compileOk);
+                       break;
+               }
+               default:
+               {
+                       DE_FATAL("Invalid program error type");
+                       break;
+               }
+       }
+
+       if (testFailed)
+       {
+               ctx.getLog() << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+               ctx.fail(message);
+       }
+}
+
+void last_frag_data_not_defined (NegativeTestContext& ctx)
+{
+       checkFramebufferFetchSupport(ctx);
+
+       const bool                                      isES32  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       map<string, string>                     args;
+       args["GLSL_VERSION_STRING"]                     = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+
+       const char* const fragShaderSource      =       "${GLSL_VERSION_STRING}\n"
+                                                                                       "#extension GL_EXT_shader_framebuffer_fetch : require\n"
+                                                                                       "layout(location = 0) out mediump vec4 fragColor;\n"
+                                                                                       "\n"
+                                                                                       "void main (void)\n"
+                                                                                       "{\n"
+                                                                                       "       fragColor = gl_LastFragData[0];\n"
+                                                                                       "}\n";
+
+       glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources()
+                       << glu::VertexSource(tcu::StringTemplate(vertexShaderSource).specialize(args))
+                       << glu::FragmentSource(tcu::StringTemplate(fragShaderSource).specialize(args)));
+
+       ctx.beginSection("A link error is generated if the built-in fragment outputs of ES 2.0 are used in #version 300 es shaders");
+       verifyProgramError(ctx, program, PROGRAM_ERROR_LINK, glu::SHADERTYPE_FRAGMENT);
+       ctx.endSection();
+}
+
+void last_frag_data_readonly (NegativeTestContext& ctx)
+{
+       checkFramebufferFetchSupport(ctx);
+
+       map<string, string>                     args;
+       args["GLSL_VERSION_STRING"]                     =       getGLSLVersionDeclaration(glu::GLSL_VERSION_100_ES);
+
+       const char* const fragShaderSource      =       "${GLSL_VERSION_STRING}\n"
+                                                                                       "#extension GL_EXT_shader_framebuffer_fetch : require\n"
+                                                                                       "\n"
+                                                                                       "void main (void)\n"
+                                                                                       "{\n"
+                                                                                       "       gl_LastFragData[0] = vec4(1.0);\n"
+                                                                                       "       gl_FragColor = gl_LastFragData[0];\n"
+                                                                                       "}\n";
+
+       glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources()
+                       << glu::VertexSource(tcu::StringTemplate(vertexShaderSource).specialize(args))
+                       << glu::FragmentSource(tcu::StringTemplate(fragShaderSource).specialize(args)));
+
+       ctx.beginSection("A compile-time or link error is generated if the built-in fragment outputs of ES 2.0 are written to.");
+       verifyProgramError(ctx, program, PROGRAM_ERROR_COMPILE_OR_LINK, glu::SHADERTYPE_FRAGMENT);
+       ctx.endSection();
+}
+
+void invalid_inout_version (NegativeTestContext& ctx)
+{
+       checkFramebufferFetchSupport(ctx);
+
+       map<string, string>                     args;
+       args["GLSL_VERSION_STRING"]                     =       getGLSLVersionDeclaration(glu::GLSL_VERSION_100_ES);
+
+       const char* const fragShaderSource      =       "${GLSL_VERSION_STRING}\n"
+                                                                                       "#extension GL_EXT_shader_framebuffer_fetch : require\n"
+                                                                                       "inout highp vec4 fragColor;\n"
+                                                                                       "\n"
+                                                                                       "void main (void)\n"
+                                                                                       "{\n"
+                                                                                       "       highp float product = dot(vec3(0.5), fragColor.rgb);\n"
+                                                                                       "       gl_FragColor = vec4(product);\n"
+                                                                                       "}\n";
+
+       glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources()
+                       << glu::VertexSource(tcu::StringTemplate(vertexShaderSource).specialize(args))
+                       << glu::FragmentSource(tcu::StringTemplate(fragShaderSource).specialize(args)));
+
+       ctx.beginSection("A compile-time or link error is generated if user-defined inout arrays are used in earlier versions of GLSL before ES 3.0");
+       verifyProgramError(ctx, program, PROGRAM_ERROR_COMPILE_OR_LINK, glu::SHADERTYPE_FRAGMENT);
+       ctx.endSection();
+}
+
+void invalid_redeclaration_inout (NegativeTestContext& ctx)
+{
+       checkFramebufferFetchSupport(ctx);
+
+       const bool                                      isES32  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       map<string, string>                     args;
+       args["GLSL_VERSION_STRING"]                     = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+
+       const char* const fragShaderSource      =       "${GLSL_VERSION_STRING}\n"
+                                                                                       "#extension GL_EXT_shader_framebuffer_fetch : require\n"
+                                                                                       "layout(location = 0) out mediump vec4 fragColor;\n"
+                                                                                       "inout highp float gl_FragDepth;\n"
+                                                                                       "\n"
+                                                                                       "void main (void)\n"
+                                                                                       "{\n"
+                                                                                       "       gl_FragDepth += 0.5f;\n"
+                                                                                       "       fragColor = vec4(1.0f);\n"
+                                                                                       "}\n";
+
+       glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources()
+                       << glu::VertexSource(tcu::StringTemplate(vertexShaderSource).specialize(args))
+                       << glu::FragmentSource(tcu::StringTemplate(fragShaderSource).specialize(args)));
+
+       ctx.beginSection("A compile-time or link error is generated if re-declaring an existing fragment output such as gl_FragDepth as inout");
+       verifyProgramError(ctx, program, PROGRAM_ERROR_COMPILE_OR_LINK, glu::SHADERTYPE_FRAGMENT);
+       ctx.endSection();
+}
+
+void invalid_vertex_inout (NegativeTestContext& ctx)
+{
+       checkFramebufferFetchSupport(ctx);
+
+       const bool                                      isES32  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       map<string, string>                     args;
+       args["GLSL_VERSION_STRING"]                     = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+
+       const char* const vertShaderSource      =       "${GLSL_VERSION_STRING}\n"
+                                                                                       "#extension GL_EXT_shader_framebuffer_fetch : require\n"
+                                                                                       "inout mediump vec4 v_color;\n"
+                                                                                       "\n"
+                                                                                       "void main (void)\n"
+                                                                                       "{\n"
+                                                                                       "}\n";
+
+       glu::ShaderProgram program(ctx.getRenderContext(), glu::ProgramSources()
+                       << glu::VertexSource(tcu::StringTemplate(vertShaderSource).specialize(args))
+                       << glu::FragmentSource(tcu::StringTemplate(fragmentShaderSource).specialize(args)));
+
+       ctx.beginSection("A compile-time error or link error is generated if inout variables are declared in the vertex shader\n");
+       verifyProgramError(ctx, program, PROGRAM_ERROR_COMPILE_OR_LINK, glu::SHADERTYPE_VERTEX);
+       ctx.endSection();
+}
+
+} // anonymous
+
+std::vector<FunctionContainer> getNegativeShaderFramebufferFetchTestFunctions (void)
+{
+       const FunctionContainer funcs[] =
+       {
+               { last_frag_data_not_defined,           "last_frag_data_not_defined",           "The built-in gl_LastFragData not defined in #version 300 es shaders"                           },
+               { last_frag_data_readonly,                      "last_frag_data_readonly",                      "Invalid write to readonly builtin in gl_LastFragData"                                                          },
+               { invalid_inout_version,                        "invalid_inout_version",                        "Invalid use of user-defined inout arrays in versions before GLSL #version 300 es."     },
+               { invalid_redeclaration_inout,          "invalid_redeclaration_inout",          "Existing fragment shader built-ins cannot be redeclared as inout arrays"                       },
+               { invalid_vertex_inout,                         "invalid_vertex_inout",                         "User defined inout arrays are not allowed in the vertex shader"                                        },
+       };
+
+       return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
+}
+
+} // NegativeTestShared
+} // Functional
+} // gles31
+} // deqp
diff --git a/modules/gles31/functional/es31fNegativeShaderFramebufferFetchTests.hpp b/modules/gles31/functional/es31fNegativeShaderFramebufferFetchTests.hpp
new file mode 100644 (file)
index 0000000..3fd55d7
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef _ES31FNEGATIVESHADERFRAMEBUFFERFETCHTESTS_HPP
+#define _ES31FNEGATIVESHADERFRAMEBUFFERFETCHTESTS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2017 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 Negative ShaderFramebufferFetch tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "es31fNegativeTestShared.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace NegativeTestShared
+{
+
+std::vector<FunctionContainer> getNegativeShaderFramebufferFetchTestFunctions (void);
+
+} // NegativeTestShared
+} // Functional
+} // gles3
+} // deqp
+
+#endif // _ES31FNEGATIVESHADERFRAMEBUFFERFETCHTESTS_HPP
diff --git a/modules/gles31/functional/es31fShaderFramebufferFetchTests.cpp b/modules/gles31/functional/es31fShaderFramebufferFetchTests.cpp
new file mode 100644 (file)
index 0000000..86c3262
--- /dev/null
@@ -0,0 +1,1410 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2017 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 EXT Shader Framebuffer Fetch Tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "es31fShaderFramebufferFetchTests.hpp"
+#include "es31fFboTestUtil.hpp"
+
+#include "tcuTestLog.hpp"
+#include "tcuSurface.hpp"
+#include "tcuTextureUtil.hpp"
+#include "tcuImageCompare.hpp"
+#include "tcuVectorUtil.hpp"
+
+#include "gluShaderProgram.hpp"
+#include "gluPixelTransfer.hpp"
+#include "gluTextureUtil.hpp"
+#include "gluContextInfo.hpp"
+#include "gluObjectWrapper.hpp"
+
+#include "glwFunctions.hpp"
+#include "glwEnums.hpp"
+
+#include "deStringUtil.hpp"
+
+#include <vector>
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace
+{
+
+using std::vector;
+using std::string;
+using tcu::TestLog;
+
+using namespace glw;
+using namespace FboTestUtil;
+
+static void checkExtensionSupport (Context& context, const char* extName)
+{
+       if (!context.getContextInfo().isExtensionSupported(extName))
+               throw tcu::NotSupportedError(string(extName) + " not supported");
+}
+
+static void checkFramebufferFetchSupport (Context& context)
+{
+       checkExtensionSupport(context, "GL_EXT_shader_framebuffer_fetch");
+}
+
+static bool isRequiredFormat (deUint32 format, glu::RenderContext& renderContext)
+{
+       const bool isES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
+       switch (format)
+       {
+               // Color-renderable formats
+               case GL_RGBA32I:
+               case GL_RGBA32UI:
+               case GL_RGBA16I:
+               case GL_RGBA16UI:
+               case GL_RGBA8:
+               case GL_RGBA8I:
+               case GL_RGBA8UI:
+               case GL_SRGB8_ALPHA8:
+               case GL_RGB10_A2:
+               case GL_RGB10_A2UI:
+               case GL_RGBA4:
+               case GL_RGB5_A1:
+               case GL_RGB8:
+               case GL_RGB565:
+               case GL_RG32I:
+               case GL_RG32UI:
+               case GL_RG16I:
+               case GL_RG16UI:
+               case GL_RG8:
+               case GL_RG8I:
+               case GL_RG8UI:
+               case GL_R32I:
+               case GL_R32UI:
+               case GL_R16I:
+               case GL_R16UI:
+               case GL_R8:
+               case GL_R8I:
+               case GL_R8UI:
+                       return true;
+
+               // Float format
+               case GL_RGBA32F:
+               case GL_RGB32F:
+               case GL_R11F_G11F_B10F:
+               case GL_RG32F:
+               case GL_R32F:
+                       return isES32;
+
+               default:
+                       return false;
+       }
+}
+
+tcu::TextureFormat getReadPixelFormat (const tcu::TextureFormat& format)
+{
+       switch (tcu::getTextureChannelClass(format.type))
+       {
+               case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
+                       return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32);
+
+               case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
+                       return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32);
+
+               case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
+               case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
+                       return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
+
+               case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
+                       return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT);
+
+               default:
+                       DE_ASSERT(false);
+                       return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
+       }
+}
+
+tcu::Vec4 getFixedPointFormatThreshold (const tcu::TextureFormat& sourceFormat, const tcu::TextureFormat& readPixelsFormat)
+{
+       DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
+       DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
+
+       DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
+       DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
+
+       DE_ASSERT(tcu::getTextureChannelClass(sourceFormat.type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
+       DE_ASSERT(tcu::getTextureChannelClass(readPixelsFormat.type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
+
+       const tcu::IVec4        srcBits         = tcu::getTextureFormatBitDepth(sourceFormat);
+       const tcu::IVec4        readBits        = tcu::getTextureFormatBitDepth(readPixelsFormat);
+
+       return tcu::Vec4(3.0f) / ((tcu::Vector<deUint64, 4>(1) << (tcu::min(srcBits, readBits).cast<deUint64>())) - tcu::Vector<deUint64, 4>(1)).cast<float>();
+}
+
+tcu::UVec4 getFloatULPThreshold (const tcu::TextureFormat& sourceFormat, const tcu::TextureFormat& readPixelsFormat)
+{
+       const tcu::IVec4        srcMantissaBits         = tcu::getTextureFormatMantissaBitDepth(sourceFormat);
+       const tcu::IVec4        readMantissaBits        = tcu::getTextureFormatMantissaBitDepth(readPixelsFormat);
+       tcu::IVec4                      ULPDiff(0);
+
+       for (int i = 0; i < 4; i++)
+               if (readMantissaBits[i] >= srcMantissaBits[i])
+                       ULPDiff[i] = readMantissaBits[i] - srcMantissaBits[i];
+
+       return tcu::UVec4(4) * (tcu::UVec4(1) << (ULPDiff.cast<deUint32>()));
+}
+
+static bool isAnyExtensionSupported (Context& context, const std::vector<std::string>& requiredExts)
+{
+       for (std::vector<std::string>::const_iterator iter = requiredExts.begin(); iter != requiredExts.end(); iter++)
+       {
+               const std::string& extension = *iter;
+
+               if (context.getContextInfo().isExtensionSupported(extension.c_str()))
+                       return true;
+       }
+
+       return false;
+}
+
+static std::string getColorOutputType(tcu::TextureFormat format)
+{
+       switch (tcu::getTextureChannelClass(format.type))
+       {
+               case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:         return "uvec4";
+               case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:           return "ivec4";
+               case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
+               case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
+               case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:           return "vec4";
+               default:
+                       DE_FATAL("Unsupported TEXTURECHANNELCLASS");
+                       return "";
+       }
+}
+
+static std::vector<std::string> getEnablingExtensions (deUint32 format, glu::RenderContext& renderContext)
+{
+       const bool                                      isES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2));
+       std::vector<std::string>        out;
+
+       DE_ASSERT(!isRequiredFormat(format, renderContext));
+
+       switch (format)
+       {
+               case GL_RGB16F:
+                       out.push_back("GL_EXT_color_buffer_half_float");
+                       break;
+
+               case GL_RGBA16F:
+               case GL_RG16F:
+               case GL_R16F:
+                       out.push_back("GL_EXT_color_buffer_half_float");
+
+               case GL_RGBA32F:
+               case GL_RGB32F:
+               case GL_R11F_G11F_B10F:
+               case GL_RG32F:
+               case GL_R32F:
+                       if (!isES32)
+                               out.push_back("GL_EXT_color_buffer_float");
+                       break;
+
+               default:
+                       break;
+       }
+
+       return out;
+}
+
+void checkFormatSupport (Context& context, deUint32 sizedFormat)
+{
+       const bool                                              isCoreFormat    = isRequiredFormat(sizedFormat, context.getRenderContext());
+       const std::vector<std::string>  requiredExts    = (!isCoreFormat) ? getEnablingExtensions(sizedFormat, context.getRenderContext()) : std::vector<std::string>();
+
+       // Check that we don't try to use invalid formats.
+       DE_ASSERT(isCoreFormat || !requiredExts.empty());
+
+       if (!requiredExts.empty() && !isAnyExtensionSupported(context, requiredExts))
+               throw tcu::NotSupportedError("Format not supported");
+}
+
+tcu::Vec4 scaleColorValue (tcu::TextureFormat format, const tcu::Vec4& color)
+{
+       const tcu::TextureFormatInfo    fmtInfo                 = tcu::getTextureFormatInfo(format);
+       const tcu::Vec4                                 cScale                  = fmtInfo.valueMax-fmtInfo.valueMin;
+       const tcu::Vec4                                 cBias                   = fmtInfo.valueMin;
+
+       return tcu::RGBA(color).toVec() * cScale + cBias;
+}
+
+// Base class for framebuffer fetch test cases
+
+class FramebufferFetchTestCase : public TestCase
+{
+public:
+                                                                       FramebufferFetchTestCase                (Context& context, const char* name, const char* desc, deUint32 format);
+                                                                       ~FramebufferFetchTestCase               (void);
+
+       void                                                    init                                                    (void);
+       void                                                    deinit                                                  (void);
+
+protected:
+       string                                                  genPassThroughVertSource                (void);
+       virtual glu::ProgramSources             genShaderSources                                (void);
+
+       void                                                    genFramebufferWithTexture               (const tcu::Vec4& color);
+       void                                                    genAttachementTexture                   (const tcu::Vec4& color);
+       void                                                    genUniformColor                                 (const tcu::Vec4& color);
+
+       void                                                    render                                                  (void);
+       void                                                    verifyRenderbuffer                              (TestLog& log, const tcu::TextureFormat& format, const tcu::TextureLevel& reference, const tcu::TextureLevel& result);
+
+       const glw::Functions&                   m_gl;
+       const deUint32                                  m_format;
+
+       glu::ShaderProgram*                             m_program;
+       GLuint                                                  m_framebuffer;
+       GLuint                                                  m_texColorBuffer;
+
+       tcu::TextureFormat                              m_texFmt;
+       glu::TransferFormat                             m_transferFmt;
+       bool                                                    m_isFilterable;
+
+       enum
+       {
+               VIEWPORT_WIDTH  = 64,
+               VIEWPORT_HEIGHT = 64,
+       };
+};
+
+FramebufferFetchTestCase::FramebufferFetchTestCase (Context& context, const char* name, const char* desc, deUint32 format)
+       : TestCase (context, name, desc)
+       , m_gl                                  (m_context.getRenderContext().getFunctions())
+       , m_format                              (format)
+       , m_program                             (DE_NULL)
+       , m_framebuffer                 (0)
+       , m_texColorBuffer              (0)
+       , m_texFmt                              (glu::mapGLInternalFormat(m_format))
+       , m_transferFmt                 (glu::getTransferFormat(m_texFmt))
+       , m_isFilterable                (glu::isGLInternalColorFormatFilterable(m_format))
+{
+}
+
+FramebufferFetchTestCase::~FramebufferFetchTestCase (void)
+{
+       FramebufferFetchTestCase::deinit();
+}
+
+void FramebufferFetchTestCase::init (void)
+{
+       checkFramebufferFetchSupport (m_context);
+       checkFormatSupport(m_context, m_format);
+
+       DE_ASSERT(!m_program);
+       m_program = new glu::ShaderProgram(m_context.getRenderContext(), genShaderSources());
+
+       m_testCtx.getLog() << *m_program;
+
+       if (!m_program->isOk())
+       {
+               delete m_program;
+               m_program = DE_NULL;
+               TCU_FAIL("Failed to compile shader program");
+       }
+
+       m_gl.useProgram(m_program->getProgram());
+}
+
+void FramebufferFetchTestCase::deinit (void)
+{
+       delete m_program;
+       m_program = DE_NULL;
+
+       if (m_framebuffer)
+       {
+               m_gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
+               m_gl.deleteFramebuffers(1, &m_framebuffer);
+               m_framebuffer = 0;
+       }
+
+       if (m_texColorBuffer)
+       {
+               m_gl.deleteTextures(1, &m_texColorBuffer);
+               m_texColorBuffer = 0;
+       }
+}
+
+string FramebufferFetchTestCase::genPassThroughVertSource (void)
+{
+       std::ostringstream vertShaderSource;
+
+       vertShaderSource        << "#version 310 es\n"
+                                               << "in highp vec4 a_position;\n"
+                                               << "\n"
+                                               << "void main (void)\n"
+                                               << "{\n"
+                                               << "    gl_Position = a_position;\n"
+                                               << "}\n";
+
+       return vertShaderSource.str();
+}
+
+glu::ProgramSources FramebufferFetchTestCase::genShaderSources (void)
+{
+       const string            vecType = getColorOutputType(m_texFmt);
+       std::ostringstream      fragShaderSource;
+
+       fragShaderSource        << "#version 310 es\n"
+                                               << "#extension GL_EXT_shader_framebuffer_fetch : require\n"
+                                               << "layout(location = 0) inout highp " << vecType << " o_color;\n"
+                                               << "uniform highp " << vecType << " u_color;\n"
+                                               << "\n"
+                                               << "void main (void)\n"
+                                               << "{\n"
+                                               << "    o_color += u_color;\n"
+                                               << "}\n";
+
+       return glu::makeVtxFragSources(genPassThroughVertSource(), fragShaderSource.str());
+}
+
+void FramebufferFetchTestCase::genFramebufferWithTexture (const tcu::Vec4& color)
+{
+       m_gl.genFramebuffers(1, &m_framebuffer);
+       m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
+
+       genAttachementTexture(color);
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "genAttachementTexture()");
+
+       m_gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texColorBuffer, 0);
+       TCU_CHECK(m_gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
+}
+
+void FramebufferFetchTestCase::genAttachementTexture (const tcu::Vec4& color)
+{
+       tcu::TextureLevel       data    (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
+
+       m_gl.genTextures(1, &m_texColorBuffer);
+       m_gl.bindTexture(GL_TEXTURE_2D, m_texColorBuffer);
+
+       m_gl.texParameteri(GL_TEXTURE_2D,       GL_TEXTURE_WRAP_S,              GL_CLAMP_TO_EDGE);
+       m_gl.texParameteri(GL_TEXTURE_2D,       GL_TEXTURE_WRAP_T,              GL_CLAMP_TO_EDGE);
+       m_gl.texParameteri(GL_TEXTURE_2D,       GL_TEXTURE_WRAP_R,              GL_CLAMP_TO_EDGE);
+       m_gl.texParameteri(GL_TEXTURE_2D,       GL_TEXTURE_MIN_FILTER,  m_isFilterable ? GL_LINEAR : GL_NEAREST);
+       m_gl.texParameteri(GL_TEXTURE_2D,       GL_TEXTURE_MAG_FILTER,  m_isFilterable ? GL_LINEAR : GL_NEAREST);
+
+       clear(data.getAccess(), color);
+
+       m_gl.texImage2D(GL_TEXTURE_2D, 0, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 0, m_transferFmt.format, m_transferFmt.dataType, data.getAccess().getDataPtr());
+       m_gl.bindTexture(GL_TEXTURE_2D, 0);
+}
+
+void FramebufferFetchTestCase::verifyRenderbuffer (TestLog&    log, const tcu::TextureFormat& format, const tcu::TextureLevel& reference, const tcu::TextureLevel&     result)
+{
+       m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+
+       switch (tcu::getTextureChannelClass(format.type))
+       {
+               case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
+               {
+                       const string            name            = "Renderbuffer";
+                       const string            desc            = "Compare renderbuffer (floating_point)";
+                       const tcu::UVec4        threshold       = getFloatULPThreshold(format, result.getFormat());
+
+                       if (!tcu::floatUlpThresholdCompare(log, name.c_str(), desc.c_str(), reference, result, threshold, tcu::COMPARE_LOG_RESULT))
+                               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+
+                       break;
+               }
+
+               case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
+               case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
+               {
+                       const string            name            = "Renderbuffer";
+                       const string            desc            = "Compare renderbuffer (integer)";
+                       const tcu::UVec4        threshold       (1, 1, 1, 1);
+
+                       if (!tcu::intThresholdCompare(log, name.c_str(), desc.c_str(), reference, result, threshold, tcu::COMPARE_LOG_RESULT))
+                               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+
+                       break;
+               }
+
+               case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
+               case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
+               {
+                       const string            name            = "Renderbuffer";
+                       const string            desc            = "Compare renderbuffer (fixed point)";
+                       const tcu::Vec4         threshold       = getFixedPointFormatThreshold(format, result.getFormat());
+
+                       if (!tcu::floatThresholdCompare(log, name.c_str(), desc.c_str(), reference, result, threshold, tcu::COMPARE_LOG_RESULT))
+                               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+
+                       break;
+               }
+
+               default:
+               {
+                       DE_ASSERT(DE_FALSE);
+                       m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+               }
+       }
+}
+
+void FramebufferFetchTestCase::genUniformColor (const tcu::Vec4& color)
+{
+       const GLuint colorLocation      = m_gl.getUniformLocation(m_program->getProgram(), "u_color");
+
+       switch (tcu::getTextureChannelClass(m_texFmt.type))
+       {
+               case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
+               {
+                       m_gl.uniform4uiv(colorLocation, 1, color.asUint().getPtr());
+                       break;
+               }
+
+               case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
+               {
+                       m_gl.uniform4iv(colorLocation, 1, color.asInt().getPtr());
+                       break;
+               }
+               case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
+               case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
+               case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
+               {
+                       m_gl.uniform4fv(colorLocation, 1, color.asFloat().getPtr());
+                       break;
+               }
+               default:
+                       DE_ASSERT(DE_FALSE);
+       }
+
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "genUniformColor()");
+}
+
+void FramebufferFetchTestCase::render (void)
+{
+       const GLfloat coords[] =
+       {
+               -1.0f, -1.0f,
+               +1.0f, -1.0f,
+               +1.0f, +1.0f,
+               -1.0f, +1.0f,
+       };
+
+       const GLushort indices[] =
+       {
+               0, 1, 2, 2, 3, 0,
+       };
+
+       const GLuint    coordLocation   = m_gl.getAttribLocation(m_program->getProgram(), "a_position");
+
+       m_gl.viewport(0, 0, VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
+
+       glu::Buffer coordinatesBuffer(m_context.getRenderContext());
+       glu::Buffer elementsBuffer(m_context.getRenderContext());
+
+       m_gl.bindBuffer(GL_ARRAY_BUFFER, *coordinatesBuffer);
+       m_gl.bufferData(GL_ARRAY_BUFFER, (GLsizeiptr)sizeof(coords), coords, GL_STATIC_DRAW);
+       m_gl.enableVertexAttribArray(coordLocation);
+       m_gl.vertexAttribPointer(coordLocation, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL);
+
+       m_gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, *elementsBuffer);
+       m_gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)sizeof(indices), &indices[0], GL_STATIC_DRAW);
+
+       m_gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, DE_NULL);
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "render()");
+}
+
+// Test description:
+// - Attach texture containing solid color to framebuffer.
+// - Draw full quad covering the entire viewport.
+// - Sum framebuffer read color with passed in uniform color.
+// - Compare resulting surface with reference.
+
+class TextureFormatTestCase : public FramebufferFetchTestCase
+{
+public:
+                                               TextureFormatTestCase           (Context& context, const char* name, const char* desc, deUint32 format);
+                                               ~TextureFormatTestCase          (void) {};
+
+       IterateResult           iterate                                         (void);
+
+private:
+       tcu::TextureLevel       genReferenceTexture                     (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor);
+};
+
+TextureFormatTestCase::TextureFormatTestCase (Context& context, const char* name, const char* desc, deUint32 format)
+       : FramebufferFetchTestCase(context, name, desc, format)
+{
+}
+
+tcu::TextureLevel TextureFormatTestCase::genReferenceTexture (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor)
+{
+       tcu::TextureLevel       reference       (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
+       tcu::clear(reference.getAccess(), fbColor + uniformColor);
+
+       return reference;
+}
+
+TextureFormatTestCase::IterateResult TextureFormatTestCase::iterate (void)
+{
+       const tcu::Vec4         uniformColor    = scaleColorValue(m_texFmt, tcu::Vec4(0.1f, 0.1f, 0.1f, 1.0f));
+       const tcu::Vec4         fbColor                 = scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f));
+
+       tcu::TextureLevel       reference               = genReferenceTexture(fbColor, uniformColor);
+       tcu::TextureLevel       result                  (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
+
+       genFramebufferWithTexture(fbColor);
+       genUniformColor(uniformColor);
+       render();
+
+       glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
+       verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);
+
+       return STOP;
+}
+
+// Test description:
+// - Attach multiple textures containing solid colors to framebuffer.
+// - Draw full quad covering the entire viewport.
+// - For each render target sum framebuffer read color with passed in uniform color.
+// - Compare resulting surfaces with references.
+
+class MultipleRenderTargetsTestCase : public FramebufferFetchTestCase
+{
+public:
+                                               MultipleRenderTargetsTestCase           (Context& context, const char* name, const char* desc, deUint32 format);
+                                               ~MultipleRenderTargetsTestCase          (void);
+
+       IterateResult           iterate                                                         (void);
+       void                            deinit                                                          (void);
+
+private:
+       void                            genFramebufferWithTextures                      (const vector<tcu::Vec4>& colors);
+       void                            genAttachementTextures                          (const vector<tcu::Vec4>& colors);
+       tcu::TextureLevel       genReferenceTexture                                     (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor);
+       glu::ProgramSources genShaderSources                                    (void);
+
+       enum
+       {
+               MAX_COLOR_BUFFERS = 4
+       };
+
+       GLuint                          m_texColorBuffers                                       [MAX_COLOR_BUFFERS];
+       GLenum                          m_colorBuffers                                          [MAX_COLOR_BUFFERS];
+};
+
+MultipleRenderTargetsTestCase::MultipleRenderTargetsTestCase (Context& context, const char* name, const char* desc, deUint32 format)
+       : FramebufferFetchTestCase(context, name, desc, format)
+       , m_texColorBuffers ()
+{
+       m_colorBuffers[0] = GL_COLOR_ATTACHMENT0;
+       m_colorBuffers[1] = GL_COLOR_ATTACHMENT1;
+       m_colorBuffers[2] = GL_COLOR_ATTACHMENT2;
+       m_colorBuffers[3] = GL_COLOR_ATTACHMENT3;
+}
+
+MultipleRenderTargetsTestCase::~MultipleRenderTargetsTestCase (void)
+{
+       MultipleRenderTargetsTestCase::deinit();
+}
+
+void MultipleRenderTargetsTestCase::deinit (void)
+{
+       // Clean up texture data
+       for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_texColorBuffers); ++i)
+       {
+               if (m_texColorBuffers[i])
+                       m_context.getRenderContext().getFunctions().deleteTextures(1, &m_texColorBuffers[i]);
+       }
+
+       FramebufferFetchTestCase::deinit();
+}
+
+void MultipleRenderTargetsTestCase::genFramebufferWithTextures (const vector<tcu::Vec4>& colors)
+{
+       m_gl.genFramebuffers(1, &m_framebuffer);
+       m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
+
+       genAttachementTextures(colors);
+
+       for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_texColorBuffers); ++i)
+               m_gl.framebufferTexture2D(GL_FRAMEBUFFER, m_colorBuffers[i], GL_TEXTURE_2D, m_texColorBuffers[i], 0);
+
+       TCU_CHECK(m_gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
+
+       m_gl.drawBuffers((glw::GLsizei)MAX_COLOR_BUFFERS, &m_colorBuffers[0]);
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "genFramebufferWithTextures()");
+}
+
+void MultipleRenderTargetsTestCase::genAttachementTextures (const vector<tcu::Vec4>& colors)
+{
+       tcu::TextureLevel       data    (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
+
+       m_gl.genTextures(MAX_COLOR_BUFFERS, m_texColorBuffers);
+
+       for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_texColorBuffers); ++i)
+       {
+               m_gl.bindTexture(GL_TEXTURE_2D, m_texColorBuffers[i]);
+
+               m_gl.texParameteri(GL_TEXTURE_2D,       GL_TEXTURE_WRAP_S,              GL_CLAMP_TO_EDGE);
+               m_gl.texParameteri(GL_TEXTURE_2D,       GL_TEXTURE_WRAP_T,              GL_CLAMP_TO_EDGE);
+               m_gl.texParameteri(GL_TEXTURE_2D,       GL_TEXTURE_WRAP_R,              GL_CLAMP_TO_EDGE);
+               m_gl.texParameteri(GL_TEXTURE_2D,       GL_TEXTURE_MIN_FILTER,  m_isFilterable ? GL_LINEAR : GL_NEAREST);
+               m_gl.texParameteri(GL_TEXTURE_2D,       GL_TEXTURE_MAG_FILTER,  m_isFilterable ? GL_LINEAR : GL_NEAREST);
+
+               clear(data.getAccess(), colors[i]);
+               m_gl.texImage2D(GL_TEXTURE_2D, 0, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 0, m_transferFmt.format, m_transferFmt.dataType, data.getAccess().getDataPtr());
+       }
+
+       m_gl.bindTexture(GL_TEXTURE_2D, 0);
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "genAttachementTextures()");
+}
+
+tcu::TextureLevel MultipleRenderTargetsTestCase::genReferenceTexture (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor)
+{
+       tcu::TextureLevel       reference       (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
+       tcu::clear(reference.getAccess(), fbColor + uniformColor);
+
+       return reference;
+}
+
+glu::ProgramSources MultipleRenderTargetsTestCase::genShaderSources (void)
+{
+       const string            vecType = getColorOutputType(m_texFmt);
+       std::ostringstream      fragShaderSource;
+
+       fragShaderSource        << "#version 310 es\n"
+                                               << "#extension GL_EXT_shader_framebuffer_fetch : require\n"
+                                               << "layout(location = 0) inout highp " << vecType << " o_color0;\n"
+                                               << "layout(location = 1) inout highp " << vecType << " o_color1;\n"
+                                               << "layout(location = 2) inout highp " << vecType << " o_color2;\n"
+                                               << "layout(location = 3) inout highp " << vecType << " o_color3;\n"
+                                               << "uniform highp " << vecType << " u_color;\n"
+                                               << "\n"
+                                               << "void main (void)\n"
+                                               << "{\n"
+                                               << "    o_color0 += u_color;\n"
+                                               << "    o_color1 += u_color;\n"
+                                               << "    o_color2 += u_color;\n"
+                                               << "    o_color3 += u_color;\n"
+                                               << "}\n";
+
+       return glu::makeVtxFragSources(genPassThroughVertSource(), fragShaderSource.str());
+}
+
+MultipleRenderTargetsTestCase::IterateResult MultipleRenderTargetsTestCase::iterate (void)
+{
+       const tcu::Vec4         uniformColor    = scaleColorValue(m_texFmt, tcu::Vec4(0.1f, 0.1f, 0.1f, 1.0f));
+       tcu::TextureLevel       result                  (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
+
+       vector<tcu::Vec4> colors;
+       colors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.9f, 0.0f, 0.0f, 1.0f)));
+       colors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 0.9f, 0.0f, 1.0f)));
+       colors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 0.0f, 0.9f, 1.0f)));
+       colors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 0.9f, 0.9f, 1.0f)));
+
+       genFramebufferWithTextures(colors);
+       genUniformColor(uniformColor);
+       render();
+
+       for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_colorBuffers); ++i)
+       {
+               tcu::TextureLevel       reference               = genReferenceTexture(colors[i], uniformColor);
+
+               m_gl.readBuffer(m_colorBuffers[i]);
+               glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
+               verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);
+       }
+
+       return STOP;
+}
+
+// Test description:
+// - Same as TextureFormatTestCase except uses built-in fragment output of ES 2.0
+
+class LastFragDataTestCase : public FramebufferFetchTestCase
+{
+public:
+                                               LastFragDataTestCase                    (Context& context, const char* name, const char* desc, deUint32 format);
+                                               ~LastFragDataTestCase                   (void) {};
+
+       IterateResult           iterate                                                 (void);
+
+private:
+       glu::ProgramSources genShaderSources                            (void);
+       tcu::TextureLevel       genReferenceTexture                             (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor);
+};
+
+LastFragDataTestCase::LastFragDataTestCase (Context& context, const char* name, const char* desc, deUint32 format)
+       : FramebufferFetchTestCase(context, name, desc, format)
+{
+}
+
+glu::ProgramSources LastFragDataTestCase::genShaderSources (void)
+{
+       const string            vecType = getColorOutputType(m_texFmt);
+       std::ostringstream      vertShaderSource;
+       std::ostringstream      fragShaderSource;
+
+       vertShaderSource        << "#version 100\n"
+                                               << "attribute vec4 a_position;\n"
+                                               << "\n"
+                                               << "void main (void)\n"
+                                               << "{\n"
+                                               << "    gl_Position = a_position;\n"
+                                               << "}\n";
+
+       fragShaderSource        << "#version 100\n"
+                                               << "#extension GL_EXT_shader_framebuffer_fetch : require\n"
+                                               << "uniform highp " << vecType << " u_color;\n"
+                                               << "\n"
+                                               << "void main (void)\n"
+                                               << "{\n"
+                                               << "    gl_FragColor = u_color + gl_LastFragData[0];\n"
+                                               << "}\n";
+
+       return glu::makeVtxFragSources(vertShaderSource.str(), fragShaderSource.str());
+}
+
+tcu::TextureLevel LastFragDataTestCase::genReferenceTexture (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor)
+{
+       tcu::TextureLevel       reference       (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
+       tcu::clear(reference.getAccess(), fbColor + uniformColor);
+
+       return reference;
+}
+
+LastFragDataTestCase::IterateResult LastFragDataTestCase::iterate (void)
+{
+       const tcu::Vec4         uniformColor    = scaleColorValue(m_texFmt, tcu::Vec4(0.1f, 0.1f, 0.1f, 1.0f));
+       const tcu::Vec4         fbColor                 = scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f));
+
+       tcu::TextureLevel       reference               = genReferenceTexture(fbColor, uniformColor);
+       tcu::TextureLevel       result                  (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
+
+       genFramebufferWithTexture(fbColor);
+       genUniformColor(uniformColor);
+       render();
+
+       glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
+       verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);
+
+       return STOP;
+}
+
+// Test description:
+// - Attach texture containing solid color to framebuffer.
+// - Create one 2D texture for sampler with a grid pattern
+// - Draw full screen quad covering the entire viewport.
+// - Sum color values taken from framebuffer texture and sampled texture
+// - Compare resulting surface with reference.
+
+class TexelFetchTestCase : public FramebufferFetchTestCase
+{
+public:
+                                               TexelFetchTestCase              (Context& context, const char* name, const char* desc, deUint32 format);
+                                               ~TexelFetchTestCase             (void) {}
+
+       IterateResult           iterate                                 (void);
+
+private:
+       glu::ProgramSources genShaderSources            (void);
+       tcu::TextureLevel       genReferenceTexture             (const tcu::Vec4& colorEven, const tcu::Vec4& colorOdd, const tcu::Vec4& fbColor);
+       void                            genSamplerTexture               (const tcu::Vec4& colorEven, const tcu::Vec4& colorOdd);
+
+       GLuint                          m_samplerTexture;
+};
+
+TexelFetchTestCase::TexelFetchTestCase (Context& context, const char* name, const char* desc, deUint32 format)
+       : FramebufferFetchTestCase(context, name, desc, format)
+       , m_samplerTexture(0)
+{
+}
+
+void TexelFetchTestCase::genSamplerTexture (const tcu::Vec4& colorEven, const tcu::Vec4& colorOdd)
+{
+       tcu::TextureLevel       data    (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
+
+       m_gl.activeTexture(GL_TEXTURE1);
+
+       m_gl.genTextures(1, &m_samplerTexture);
+       m_gl.bindTexture(GL_TEXTURE_2D, m_texColorBuffer);
+       m_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+       m_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+       tcu::fillWithGrid(data.getAccess(), 8, colorEven, colorOdd);
+
+       m_gl.texImage2D(GL_TEXTURE_2D, 0, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 0, m_transferFmt.format, m_transferFmt.dataType, data.getAccess().getDataPtr());
+       m_gl.bindTexture(GL_TEXTURE_2D, 0);
+
+       const GLuint samplerLocation = m_gl.getUniformLocation(m_program->getProgram(), "u_sampler");
+       m_gl.uniform1i(samplerLocation, 1);
+
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "genSamplerTexture()");
+}
+
+glu::ProgramSources TexelFetchTestCase::genShaderSources (void)
+{
+       const string            vecType = getColorOutputType(m_texFmt);
+       std::ostringstream      fragShaderSource;
+
+       fragShaderSource        << "#version 310 es\n"
+                                               << "#extension GL_EXT_shader_framebuffer_fetch : require\n"
+                                               << "layout(location = 0) inout highp " << vecType << " o_color;\n"
+                                               << "\n"
+                                               << "uniform sampler2D u_sampler;\n"
+                                               << "void main (void)\n"
+                                               << "{\n"
+                                               << "    o_color += texelFetch(u_sampler, ivec2(gl_FragCoord), 0);\n"
+                                               << "}\n";
+
+       return glu::makeVtxFragSources(genPassThroughVertSource(), fragShaderSource.str());
+}
+
+tcu::TextureLevel TexelFetchTestCase::genReferenceTexture (const tcu::Vec4& colorEven, const tcu::Vec4& colorOdd, const tcu::Vec4& fbColor)
+{
+       tcu::TextureLevel       reference       (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
+       tcu::fillWithGrid(reference.getAccess(), 8, colorEven + fbColor, colorOdd + fbColor);
+
+       return reference;
+}
+
+TexelFetchTestCase::IterateResult TexelFetchTestCase::iterate (void)
+{
+       const tcu::Vec4         fbColor                 = scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 0.5f, 1.0f));
+       const tcu::Vec4         colorEven               = scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.5f, 0.0f, 1.0f));
+       const tcu::Vec4         colorOdd                = scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 0.5f, 1.0f));
+
+       genSamplerTexture(colorEven, colorOdd);
+       tcu::TextureLevel       reference               = genReferenceTexture(colorEven, colorOdd, fbColor);
+       tcu::TextureLevel       result                  (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
+
+       genFramebufferWithTexture(fbColor);
+       render();
+
+       glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
+       verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);
+
+       // cleanup
+       m_gl.deleteTextures(1, &m_samplerTexture);
+
+       return STOP;
+}
+
+// Test description:
+// - Attach texture containing solid color to framebuffer.
+// - Draw full screen quad covering the entire viewport.
+// - Multiple assignments are made to the output color for fragments on the right vertical half of the screen.
+// - A single assignment is made to the output color for fragments on the left vertical centre of the screen.
+// - Values are calculated using the sum of the passed in uniform color and the previous framebuffer color.
+// - Compare resulting surface with reference.
+
+class MultipleAssignmentTestCase : public FramebufferFetchTestCase
+{
+public:
+                                               MultipleAssignmentTestCase              (Context& context, const char* name, const char* desc, deUint32 format);
+                                               ~MultipleAssignmentTestCase             (void) {}
+
+       IterateResult           iterate                                                 (void);
+
+private:
+       glu::ProgramSources genShaderSources                            (void);
+       tcu::TextureLevel       genReferenceTexture                             (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor);
+};
+
+MultipleAssignmentTestCase::MultipleAssignmentTestCase (Context& context, const char* name, const char* desc, deUint32 format)
+       : FramebufferFetchTestCase(context, name, desc, format)
+{
+}
+
+glu::ProgramSources MultipleAssignmentTestCase::genShaderSources (void)
+{
+       const string            vecType = getColorOutputType(m_texFmt);
+       std::ostringstream      vertShaderSource;
+       std::ostringstream      fragShaderSource;
+
+       vertShaderSource        << "#version 310 es\n"
+                                               << "in highp vec4 a_position;\n"
+                                               << "out highp vec4 v_position;\n"
+                                               << "\n"
+                                               << "void main (void)\n"
+                                               << "{\n"
+                                               << "    gl_Position = a_position;\n"
+                                               << "    v_position  = gl_Position;\n"
+                                               << "}\n";
+
+       fragShaderSource        << "#version 310 es\n"
+                                               << "#extension GL_EXT_shader_framebuffer_fetch : require\n"
+                                               << "in highp vec4 v_position;\n"
+                                               << "layout(location = 0) inout highp " << vecType << " o_color;\n"
+                                               << "uniform highp " << vecType << " u_color;\n"
+                                               << "\n"
+                                               << "void main (void)\n"
+                                               << "{\n"
+                                               << "    if (v_position.x > 0.0f)\n"
+                                               << "            o_color += u_color;\n"
+                                               << "\n"
+                                               << "    o_color += u_color;\n"
+                                               << "}\n";
+
+       return glu::makeVtxFragSources(vertShaderSource.str(), fragShaderSource.str());
+}
+
+tcu::TextureLevel MultipleAssignmentTestCase::genReferenceTexture (const tcu::Vec4& fbColor, const tcu::Vec4& uniformColor)
+{
+       tcu::TextureLevel       reference       (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
+
+       int     width   = reference.getAccess().getWidth();
+       int     height  = reference.getAccess().getHeight();
+       int     left    = width /2;
+       int     top             = height/2;
+
+       tcu::Vec4 compositeColor(uniformColor * 2.0f);
+
+       tcu::clear(getSubregion(reference.getAccess(), left,            0,              0, width-left,  top,            1),     fbColor + compositeColor);
+       tcu::clear(getSubregion(reference.getAccess(), 0,                       top,    0, left,                height-top,     1), fbColor + uniformColor);
+       tcu::clear(getSubregion(reference.getAccess(), left,            top,    0, width-left,  height-top, 1), fbColor + compositeColor);
+       tcu::clear(getSubregion(reference.getAccess(), 0,                       0,              0, left,                top,            1),     fbColor + uniformColor);
+
+       return reference;
+}
+
+MultipleAssignmentTestCase::IterateResult MultipleAssignmentTestCase::iterate (void)
+{
+       const tcu::Vec4         fbColor                 = scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f));
+       const tcu::Vec4         uniformColor    = scaleColorValue(m_texFmt, tcu::Vec4(0.25f, 0.0f, 0.0f, 1.0f));
+
+       tcu::TextureLevel       reference               = genReferenceTexture(fbColor, uniformColor);
+       tcu::TextureLevel       result                  (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
+
+       genFramebufferWithTexture(fbColor);
+       genUniformColor(uniformColor);
+       render();
+
+       glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
+       verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);
+
+       return STOP;
+}
+
+// Test description:
+// - Attach texture containing grid pattern to framebuffer.
+// - Using framebuffer reads discard odd squares in the grid.
+// - The even squares framebuffer color is added to the passed in uniform color.
+
+class FragmentDiscardTestCase : public FramebufferFetchTestCase
+{
+public:
+                                               FragmentDiscardTestCase         (Context& context, const char* name, const char* desc, deUint32 format);
+                                               ~FragmentDiscardTestCase        (void) {}
+
+       IterateResult           iterate                                         (void);
+
+private:
+       glu::ProgramSources genShaderSources                    (void);
+       void                            genFramebufferWithGrid          (const tcu::Vec4& fbColorEven, const tcu::Vec4& fbColorOdd);
+       tcu::TextureLevel       genReferenceTexture                     (const tcu::Vec4& fbColorEven, const tcu::Vec4& fbColorOdd);
+};
+
+FragmentDiscardTestCase::FragmentDiscardTestCase (Context& context, const char* name, const char* desc, deUint32 format)
+       : FramebufferFetchTestCase(context, name, desc, format)
+{
+}
+
+glu::ProgramSources FragmentDiscardTestCase::genShaderSources (void)
+{
+       const string            vecType = getColorOutputType(m_texFmt);
+       std::ostringstream      fragShaderSource;
+
+       fragShaderSource        << "#version 310 es\n"
+                                               << "#extension GL_EXT_shader_framebuffer_fetch : require\n"
+                                               << "layout(location = 0) inout highp " << vecType << " o_color;\n"
+                                               << "uniform highp " << vecType << " u_color;\n"
+                                               << "\n"
+                                               << "void main (void)\n"
+                                               << "{\n"
+                                               << "    const highp float threshold = 0.0005f;\n"
+                                               << "    bool valuesEqual = all(lessThan(abs(o_color - u_color), vec4(threshold)));\n\n"
+                                               << "    if (valuesEqual)\n"
+                                               << "            o_color += u_color;\n"
+                                               << "    else\n"
+                                               << "            discard;\n"
+                                               << "}\n";
+
+       return glu::makeVtxFragSources(genPassThroughVertSource(), fragShaderSource.str());
+}
+
+void FragmentDiscardTestCase::genFramebufferWithGrid (const tcu::Vec4& fbColorEven, const tcu::Vec4& fbColorOdd)
+{
+       tcu::TextureLevel data  (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
+
+       m_gl.genFramebuffers(1, &m_framebuffer);
+       m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
+
+       m_gl.genTextures(1, &m_texColorBuffer);
+       m_gl.bindTexture(GL_TEXTURE_2D, m_texColorBuffer);
+
+       tcu::fillWithGrid(data.getAccess(), 8, fbColorEven, fbColorOdd);
+
+       m_gl.texImage2D(GL_TEXTURE_2D, 0, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 0, m_transferFmt.format, m_transferFmt.dataType, data.getAccess().getDataPtr());
+       m_gl.bindTexture(GL_TEXTURE_2D, 0);
+
+       m_gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texColorBuffer, 0);
+       TCU_CHECK(m_gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
+}
+
+tcu::TextureLevel FragmentDiscardTestCase::genReferenceTexture (const tcu::Vec4& fbColorEven, const tcu::Vec4& fbColorOdd)
+{
+       tcu::TextureLevel       reference       (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
+       tcu::fillWithGrid(reference.getAccess(), 8, fbColorEven + fbColorEven, fbColorOdd);
+
+       return reference;
+}
+
+FragmentDiscardTestCase::IterateResult FragmentDiscardTestCase::iterate (void)
+{
+       const tcu::Vec4         fbColorEven             = scaleColorValue(m_texFmt, tcu::Vec4(0.5f, 0.0f, 1.0f, 1.0f));
+       const tcu::Vec4         fbColorOdd              = scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f));
+
+       tcu::TextureLevel       reference               = genReferenceTexture(fbColorEven, fbColorOdd);
+       tcu::TextureLevel       result                  (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
+       genFramebufferWithGrid(fbColorEven, fbColorOdd);
+
+       genUniformColor(fbColorEven);
+       render();
+
+       glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
+       verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);
+
+       return STOP;
+}
+
+// Test description:
+// - Create 2D texture array containing three mipmaps.
+// - Each mipmap level is assigned a different color.
+// - Attach single mipmap level to framebuffer and draw full screen quad.
+// - Sum framebuffer read color with passed in uniform color.
+// - Compare resulting surface with reference.
+// - Repeat for subsequent mipmap levels.
+
+class TextureLevelTestCase : public FramebufferFetchTestCase
+{
+public:
+                                               TextureLevelTestCase                    (Context& context, const char* name, const char* desc, deUint32 format);
+                                               ~TextureLevelTestCase                   (void) {}
+
+       IterateResult           iterate                                                 (void);
+
+private:
+       void                            create2DTextureArrayMipMaps             (const vector<tcu::Vec4>& colors);
+       tcu::TextureLevel       genReferenceTexture                             (int level, const vector<tcu::Vec4>& colors, const tcu::Vec4& uniformColor);
+       void                            genReferenceMipmap                              (int level, const tcu::Vec4& color, tcu::TextureLevel& reference);
+};
+
+TextureLevelTestCase::TextureLevelTestCase (Context& context, const char* name, const char* desc, deUint32 format)
+       : FramebufferFetchTestCase(context, name, desc, format)
+{
+}
+
+void TextureLevelTestCase::create2DTextureArrayMipMaps (const vector<tcu::Vec4>& colors)
+{
+       int                                             numLevels       = (int)colors.size();
+       tcu::TextureLevel               levelData       (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType));
+
+       m_gl.genTextures(1, &m_texColorBuffer);
+       m_gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_texColorBuffer);
+
+       m_gl.texImage3D(GL_TEXTURE_2D_ARRAY, 0, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1, 0, m_transferFmt.format, m_transferFmt.dataType, DE_NULL);
+       m_gl.generateMipmap(GL_TEXTURE_2D_ARRAY);
+
+       for (int level = 0; level < numLevels; level++)
+       {
+               int             levelW          = de::max(1, VIEWPORT_WIDTH             >> level);
+               int             levelH          = de::max(1, VIEWPORT_HEIGHT    >> level);
+
+               levelData.setSize(levelW, levelH, 1);
+
+               clear(levelData.getAccess(), colors[level]);
+               m_gl.texImage3D(GL_TEXTURE_2D_ARRAY, level, m_format, levelW, levelH, 1, 0, m_transferFmt.format, m_transferFmt.dataType, levelData.getAccess().getDataPtr());
+       }
+
+       m_gl.bindTexture(GL_TEXTURE_2D_ARRAY, 0);
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "create2DTextureArrayMipMaps()");
+}
+
+tcu::TextureLevel TextureLevelTestCase::genReferenceTexture (int level, const vector<tcu::Vec4>& colors, const tcu::Vec4& uniformColor)
+{
+       tcu::TextureLevel       reference       (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
+
+       // calculate reference image based on current mipmap level and previously
+       // rendered mipmaps in framebuffer
+       for (int ndx = 0; ndx <= level; ++ndx)
+               genReferenceMipmap(ndx, colors[ndx] + uniformColor, reference);
+
+       return reference;
+}
+
+void TextureLevelTestCase::genReferenceMipmap (int level, const tcu::Vec4& color, tcu::TextureLevel& reference)
+{
+       int     width   = reference.getAccess().getWidth();
+       int     height  = reference.getAccess().getHeight();
+       int     left    = width /2;
+       int     top             = height/2;
+
+       for (int i = 0; i < level; ++i)
+       {
+               width   = de::max(1, width      / 2);
+               height  = de::max(1, height / 2);
+               left    = width /2;
+               top             = height/2;
+       }
+
+       clear(getSubregion(reference.getAccess(), left,         0,              0, width-left,  top,            1),     color);
+       clear(getSubregion(reference.getAccess(), 0,            top,    0, left,                height-top,     1), color);
+       clear(getSubregion(reference.getAccess(), left,         top,    0, width-left,  height-top, 1), color);
+       clear(getSubregion(reference.getAccess(), 0,            0,              0, left,                top,            1),     color);
+}
+
+TextureLevelTestCase::IterateResult TextureLevelTestCase::iterate (void)
+{
+       const tcu::Vec4         uniformColor    = scaleColorValue(m_texFmt, tcu::Vec4(0.1f, 0.0f, 0.0f, 1.0f));
+       tcu::TextureLevel       result                  (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
+       vector<tcu::Vec4>       levelColors;
+
+       levelColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.4f, 0.0f, 0.0f, 1.0f)));
+       levelColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.2f, 0.0f, 0.0f, 1.0f)));
+       levelColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
+
+       m_gl.genFramebuffers(1, &m_framebuffer);
+       m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
+
+       create2DTextureArrayMipMaps(levelColors);
+
+       // attach successive mipmap layers to framebuffer and render
+       for (int level = 0; level < (int)levelColors.size(); ++level)
+       {
+               std::ostringstream name, desc;
+               name << "Level "                << level;
+               desc << "Mipmap level " << level;
+
+               const tcu::ScopedLogSection section                     (m_testCtx.getLog(), name.str(), desc.str());
+               tcu::TextureLevel                       reference               = genReferenceTexture(level, levelColors, uniformColor);
+
+               m_gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texColorBuffer, level);
+
+               genUniformColor(uniformColor);
+               render();
+
+               glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
+               verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);
+
+               if (m_testCtx.getTestResult() != QP_TEST_RESULT_PASS)
+                       return STOP;
+       }
+
+       return STOP;
+}
+
+class TextureLayerTestCase : public FramebufferFetchTestCase
+{
+public:
+                                               TextureLayerTestCase            (Context& context, const char* name, const char* desc, deUint32 format);
+                                               ~TextureLayerTestCase           (void) {}
+
+       IterateResult           iterate                                         (void);
+
+private:
+       void                            create2DTextureArrayLayers      (const vector<tcu::Vec4>&  colors);
+       tcu::TextureLevel       genReferenceTexture                     (int layer, const vector<tcu::Vec4>& colors, const tcu::Vec4& uniformColor);
+};
+
+TextureLayerTestCase::TextureLayerTestCase (Context& context, const char* name, const char* desc, deUint32 format)
+       : FramebufferFetchTestCase(context, name, desc, format)
+{
+}
+
+void TextureLayerTestCase::create2DTextureArrayLayers (const vector<tcu::Vec4>& colors)
+{
+       int                                             numLayers       = (int)colors.size();
+       tcu::TextureLevel               layerData       (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType));
+
+       m_gl.genTextures(1, &m_texColorBuffer);
+       m_gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_texColorBuffer);
+       m_gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1, m_format, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, numLayers);
+       m_gl.bindImageTexture(0, m_texColorBuffer, 0, GL_FALSE, 0, GL_READ_ONLY, m_format);
+
+       layerData.setSize(VIEWPORT_WIDTH, VIEWPORT_HEIGHT, numLayers);
+
+       for (int layer = 0; layer < numLayers; layer++)
+       {
+               clear(layerData.getAccess(), colors[layer]);
+               m_gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layer, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1, m_transferFmt.format, m_transferFmt.dataType, layerData.getAccess().getDataPtr());
+       }
+
+       m_gl.bindTexture(GL_TEXTURE_2D_ARRAY, 0);
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "create2DTextureArrayLayers()");
+}
+
+tcu::TextureLevel TextureLayerTestCase::genReferenceTexture (int layer, const vector<tcu::Vec4>& colors, const tcu::Vec4& uniformColor)
+{
+       tcu::TextureLevel       reference       (glu::mapGLTransferFormat(m_transferFmt.format, m_transferFmt.dataType), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 1);
+       clear(reference.getAccess(), colors[layer] + uniformColor);
+
+       return reference;
+}
+
+// Test description
+// - Create 2D texture array containing three layers.
+// - Each layer is assigned a different color.
+// - Attach single layer to framebuffer and draw full screen quad.
+// - Sum framebuffer read color with passed in uniform color.
+// - Compare resulting surface with reference.
+// - Repeat for subsequent texture layers.
+
+TextureLayerTestCase::IterateResult TextureLayerTestCase::iterate (void)
+{
+       const tcu::Vec4         uniformColor    = scaleColorValue(m_texFmt, tcu::Vec4(0.1f, 0.1f, 0.1f, 1.0f));
+       tcu::TextureLevel       result                  (getReadPixelFormat(m_texFmt), VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
+       vector<tcu::Vec4>       layerColors;
+
+       layerColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.4f, 0.0f, 0.0f, 1.0f)));
+       layerColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.2f, 0.0f, 0.0f, 1.0f)));
+       layerColors.push_back(scaleColorValue(m_texFmt, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
+
+       m_gl.genFramebuffers(1, &m_framebuffer);
+       m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
+
+       create2DTextureArrayLayers(layerColors);
+
+       for (int layer = 0; layer < (int)layerColors.size(); ++layer)
+       {
+               std::ostringstream name, desc;
+               name << "Layer " << layer;
+               desc << "Layer " << layer;
+
+               const tcu::ScopedLogSection section             (m_testCtx.getLog(), name.str(), desc.str());
+               tcu::TextureLevel                       reference       = genReferenceTexture(layer, layerColors, uniformColor);
+
+               m_gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texColorBuffer, 0, layer);
+
+               genUniformColor(uniformColor);
+               render();
+
+               glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
+               verifyRenderbuffer(m_testCtx.getLog(), m_texFmt, reference, result);
+
+               if (m_testCtx.getTestResult() != QP_TEST_RESULT_PASS)
+                       return STOP;
+       }
+
+       return STOP;
+}
+
+} // Anonymous
+
+ShaderFramebufferFetchTests::ShaderFramebufferFetchTests (Context& context)
+       : TestCaseGroup (context, "framebuffer_fetch", "GL_EXT_shader_framebuffer_fetch tests")
+{
+}
+
+ShaderFramebufferFetchTests::~ShaderFramebufferFetchTests (void)
+{
+}
+
+void ShaderFramebufferFetchTests::init (void)
+{
+       tcu::TestCaseGroup* const basicTestGroup                                = new tcu::TestCaseGroup(m_testCtx, "basic",                            "Basic framebuffer shader fetch tests");
+       tcu::TestCaseGroup* const framebufferFormatTestGroup    = new tcu::TestCaseGroup(m_testCtx, "framebuffer_format",       "Texture render target formats tests");
+
+       // basic
+       {
+               basicTestGroup->addChild(new TexelFetchTestCase                         (m_context,             "texel_fetch",                                  "Framebuffer fetches in conjunction with shader texel fetches",                 GL_RGBA8));
+               basicTestGroup->addChild(new LastFragDataTestCase                       (m_context,             "last_frag_data",                               "Framebuffer fetches with built-in fragment output of ES 2.0",                  GL_RGBA8));
+               basicTestGroup->addChild(new FragmentDiscardTestCase            (m_context,             "fragment_discard",                             "Framebuffer fetches in combination with fragment discards",                    GL_RGBA8));
+               basicTestGroup->addChild(new MultipleAssignmentTestCase         (m_context,             "multiple_assignment",                  "Multiple assignments to fragment color inout",                                                 GL_RGBA8));
+               basicTestGroup->addChild(new MultipleRenderTargetsTestCase      (m_context,             "multiple_render_targets",              "Framebuffer fetches used in combination with multiple render targets", GL_RGBA8));
+               basicTestGroup->addChild(new TextureLevelTestCase                       (m_context,             "framebuffer_texture_level",    "Framebuffer fetches with individual texture render target mipmaps",    GL_RGBA8));
+               basicTestGroup->addChild(new TextureLayerTestCase                       (m_context,             "framebuffer_texture_layer",    "Framebuffer fetches with individual texture render target layers",             GL_RGBA8));
+       }
+
+       // framebuffer formats
+       {
+               static const deUint32 colorFormats[] =
+               {
+                       // RGBA formats
+                       GL_RGBA32I,
+                       GL_RGBA32UI,
+                       GL_RGBA16I,
+                       GL_RGBA16UI,
+                       GL_RGBA8,
+                       GL_RGBA8I,
+                       GL_RGBA8UI,
+                       GL_SRGB8_ALPHA8,
+                       GL_RGB10_A2,
+                       GL_RGB10_A2UI, GL_RGBA4, GL_RGB5_A1,
+
+                       // RGB formats
+                       GL_RGB8,
+                       GL_RGB565,
+
+                       // RG formats
+                       GL_RG32I,
+                       GL_RG32UI,
+                       GL_RG16I,
+                       GL_RG16UI,
+                       GL_RG8,
+                       GL_RG8I,
+                       GL_RG8UI,
+
+                       // R formats
+                       GL_R32I,
+                       GL_R32UI,
+                       GL_R16I,
+                       GL_R16UI,
+                       GL_R8,
+                       GL_R8I,
+                       GL_R8UI,
+
+                       // GL_EXT_color_buffer_float
+                       GL_RGBA32F,
+                       GL_RGBA16F,
+                       GL_R11F_G11F_B10F,
+                       GL_RG32F,
+                       GL_RG16F,
+                       GL_R32F,
+                       GL_R16F,
+
+                       // GL_EXT_color_buffer_half_float
+                       GL_RGB16F
+               };
+
+               for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorFormats); ndx++)
+                       framebufferFormatTestGroup->addChild(new TextureFormatTestCase(m_context, getFormatName(colorFormats[ndx]), "Framebuffer fetches from texture attachments with varying formats", colorFormats[ndx]));
+       }
+
+       addChild(basicTestGroup);
+       addChild(framebufferFormatTestGroup);
+}
+
+} // Functional
+} // gles31
+} // deqp
diff --git a/modules/gles31/functional/es31fShaderFramebufferFetchTests.hpp b/modules/gles31/functional/es31fShaderFramebufferFetchTests.hpp
new file mode 100644 (file)
index 0000000..ec02d79
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef _ES31FSHADERFRAMEBUFFERFETCHTESTS_HPP
+#define _ES31FSHADERFRAMEBUFFERFETCHTESTS_HPP
+
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2017 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 EXT Shader Framebuffer Fetch Tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tes31TestCase.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+
+class ShaderFramebufferFetchTests : public TestCaseGroup
+{
+public:
+                                                                       ShaderFramebufferFetchTests             (Context& context);
+                                                                       ~ShaderFramebufferFetchTests    (void);
+
+       void                                                    init                                                    (void);
+
+private:
+       ShaderFramebufferFetchTests&    operator=                                               (const ShaderFramebufferFetchTests&);
+       ShaderFramebufferFetchTests                                                                             (const ShaderFramebufferFetchTests&);
+};
+
+} // Functional
+} // gles31
+} // deqp
+
+#endif // _ES31FSHADERFRAMEBUFFERFETCHTESTS_HPP