From 2a609fb223ff773c6da74ce9b1e1891d55b5252e Mon Sep 17 00:00:00 2001 From: John Richardson Date: Mon, 20 Mar 2017 17:29:54 +0000 Subject: [PATCH] Add new framebuffer fetch extension tests 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 | 58 + modules/gles31/functional/CMakeLists.txt | 4 + modules/gles31/functional/es31fDebugTests.cpp | 5 + .../functional/es31fFunctionalTests.cpp | 2 + ...31fNegativeShaderFramebufferFetchTests.cpp | 267 ++++ ...31fNegativeShaderFramebufferFetchTests.hpp | 45 + .../es31fShaderFramebufferFetchTests.cpp | 1410 +++++++++++++++++ .../es31fShaderFramebufferFetchTests.hpp | 54 + 8 files changed, 1845 insertions(+) create mode 100644 modules/gles31/functional/es31fNegativeShaderFramebufferFetchTests.cpp create mode 100644 modules/gles31/functional/es31fNegativeShaderFramebufferFetchTests.hpp create mode 100644 modules/gles31/functional/es31fShaderFramebufferFetchTests.cpp create mode 100644 modules/gles31/functional/es31fShaderFramebufferFetchTests.hpp diff --git a/android/cts/master/gles31-master.txt b/android/cts/master/gles31-master.txt index f19e50a95..f5c06b02c 100644 --- a/android/cts/master/gles31-master.txt +++ b/android/cts/master/gles31-master.txt @@ -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 diff --git a/modules/gles31/functional/CMakeLists.txt b/modules/gles31/functional/CMakeLists.txt index f9f21c790..a4ac348f9 100644 --- a/modules/gles31/functional/CMakeLists.txt +++ b/modules/gles31/functional/CMakeLists.txt @@ -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}) diff --git a/modules/gles31/functional/es31fDebugTests.cpp b/modules/gles31/functional/es31fDebugTests.cpp index 242974baa..1613179e5 100644 --- a/modules/gles31/functional/es31fDebugTests.cpp +++ b/modules/gles31/functional/es31fDebugTests.cpp @@ -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 shaderStorageFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderStorageTestFunctions()); const vector sampleVariablesFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeSampleVariablesTestFunctions()); const vector computeFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeComputeTestFunctions()); + const vector framebufferFetchFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderFramebufferFetchTestFunctions()); const vector 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)); } } diff --git a/modules/gles31/functional/es31fFunctionalTests.cpp b/modules/gles31/functional/es31fFunctionalTests.cpp index 866fccadc..3fb407e37 100644 --- a/modules/gles31/functional/es31fFunctionalTests.cpp +++ b/modules/gles31/functional/es31fFunctionalTests.cpp @@ -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 index 000000000..b74c5a601 --- /dev/null +++ b/modules/gles31/functional/es31fNegativeShaderFramebufferFetchTests.cpp @@ -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 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 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 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 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 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 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(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 index 000000000..3fd55d72d --- /dev/null +++ b/modules/gles31/functional/es31fNegativeShaderFramebufferFetchTests.hpp @@ -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 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 index 000000000..86c326230 --- /dev/null +++ b/modules/gles31/functional/es31fShaderFramebufferFetchTests.cpp @@ -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 + +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(1) << (tcu::min(srcBits, readBits).cast())) - tcu::Vector(1)).cast(); +} + +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())); +} + +static bool isAnyExtensionSupported (Context& context, const std::vector& requiredExts) +{ + for (std::vector::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 getEnablingExtensions (deUint32 format, glu::RenderContext& renderContext) +{ + const bool isES32 = glu::contextSupports(renderContext.getType(), glu::ApiType::es(3, 2)); + std::vector 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 requiredExts = (!isCoreFormat) ? getEnablingExtensions(sizedFormat, context.getRenderContext()) : std::vector(); + + // 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& colors); + void genAttachementTextures (const vector& 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& 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& 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 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& colors); + tcu::TextureLevel genReferenceTexture (int level, const vector& 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& 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& 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 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& colors); + tcu::TextureLevel genReferenceTexture (int layer, const vector& 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& 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& 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 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 index 000000000..ec02d7980 --- /dev/null +++ b/modules/gles31/functional/es31fShaderFramebufferFetchTests.hpp @@ -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 -- 2.34.1