| /*------------------------------------------------------------------------- |
| * OpenGL Conformance Test Suite |
| * ----------------------------- |
| * |
| * Copyright (c) 2015-2016 The Khronos Group Inc. |
| * |
| * 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 |
| */ /*-------------------------------------------------------------------*/ |
| #include "esextcGeometryShaderLinking.hpp" |
| |
| #include "gluDefs.hpp" |
| #include "glwEnums.hpp" |
| #include "glwFunctions.hpp" |
| #include "tcuTestLog.hpp" |
| #include <cstring> |
| |
| namespace glcts |
| { |
| |
| static const char* dummy_fs_code = "${VERSION}\n" |
| "\n" |
| "precision highp float;\n" |
| "\n" |
| "out vec4 result;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " result = vec4(1.0);\n" |
| "}\n"; |
| |
| static const char* dummy_gs_code = "${VERSION}\n" |
| "${GEOMETRY_SHADER_REQUIRE}\n" |
| "\n" |
| "layout (points) in;\n" |
| "layout (points, max_vertices = 1) out;\n" |
| "\n" |
| "${OUT_PER_VERTEX_DECL}" |
| "${IN_DATA_DECL}" |
| "\n" |
| "void main()\n" |
| "{\n" |
| "${POSITION_WITH_IN_DATA}" |
| " EmitVertex();\n" |
| "}\n"; |
| |
| static const char* dummy_vs_code = "${VERSION}\n" |
| "\n" |
| "${OUT_PER_VERTEX_DECL}" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n" |
| "}\n"; |
| |
| /** Constructor |
| * |
| * @param context Test context |
| * @param extParams Not used. |
| * @param name Test case's name |
| * @param description Test case's description |
| **/ |
| GeometryShaderIncompleteProgramObjectsTest::GeometryShaderIncompleteProgramObjectsTest(Context& context, |
| const ExtParameters& extParams, |
| const char* name, |
| const char* description) |
| : TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0) |
| { |
| } |
| |
| /** Deinitializes GLES objects created during the test. */ |
| void GeometryShaderIncompleteProgramObjectsTest::deinit() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| if (m_fs_id != 0) |
| { |
| gl.deleteShader(m_fs_id); |
| |
| m_fs_id = 0; |
| } |
| |
| if (m_gs_id != 0) |
| { |
| gl.deleteShader(m_gs_id); |
| |
| m_gs_id = 0; |
| } |
| |
| if (m_po_id != 0) |
| { |
| gl.deleteProgram(m_po_id); |
| |
| m_po_id = 0; |
| } |
| |
| /* Release base class */ |
| TestCaseBase::deinit(); |
| } |
| |
| /** Initializes shader objects for the conformance test */ |
| void GeometryShaderIncompleteProgramObjectsTest::initShaderObjects() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| std::string specialized_fs_code = specializeShader(1, &dummy_fs_code); |
| const char* specialized_fs_code_raw = specialized_fs_code.c_str(); |
| std::string specialized_gs_code = specializeShader(1, &dummy_gs_code); |
| const char* specialized_gs_code_raw = specialized_gs_code.c_str(); |
| |
| m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); |
| m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); |
| |
| for (unsigned int n_shader_type = 0; n_shader_type < 2; /* fs, gs */ |
| n_shader_type++) |
| { |
| glw::GLint compile_status = GL_FALSE; |
| const char* so_code = (n_shader_type == 0) ? specialized_fs_code_raw : specialized_gs_code_raw; |
| glw::GLuint so_id = (n_shader_type == 0) ? m_fs_id : m_gs_id; |
| |
| gl.shaderSource(so_id, 1, /* count */ |
| &so_code, DE_NULL); /* length */ |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed"); |
| |
| gl.compileShader(so_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed"); |
| |
| gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed"); |
| |
| if (compile_status != GL_TRUE) |
| { |
| TCU_FAIL("Shader compilation process failed."); |
| } |
| } /* for (both shader stages) */ |
| } |
| |
| /** Initializes test runs, to be executed by the conformance test. */ |
| void GeometryShaderIncompleteProgramObjectsTest::initTestRuns() |
| { |
| /* use_fs| use_gs| use_separable_po |
| * ------|-------|-----------------*/ |
| m_test_runs.push_back(_run(false, true, false)); |
| m_test_runs.push_back(_run(false, true, true)); |
| m_test_runs.push_back(_run(true, true, false)); |
| m_test_runs.push_back(_run(true, true, true)); |
| } |
| |
| /** Executes the test. |
| * |
| * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. |
| * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. |
| * Note the function throws exception should an error occur! |
| **/ |
| tcu::TestNode::IterateResult GeometryShaderIncompleteProgramObjectsTest::iterate() |
| { |
| bool result = true; |
| |
| /* This test should only run if EXT_geometry_shader is supported. */ |
| if (!m_is_geometry_shader_extension_supported) |
| { |
| throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); |
| } |
| |
| /* Initialize test runs */ |
| initTestRuns(); |
| |
| /* Set up shader objects */ |
| initShaderObjects(); |
| |
| /* Iterate over the test run set */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| for (unsigned int run_index = 0; run_index < m_test_runs.size(); ++run_index) |
| { |
| const _run& current_run = m_test_runs[run_index]; |
| |
| /* Set up a program object */ |
| m_po_id = gl.createProgram(); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed"); |
| |
| if (current_run.use_separable_po) |
| { |
| gl.programParameteri(m_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed"); |
| } /* if (current_run.use_separable_po) */ |
| |
| if (current_run.use_fs) |
| { |
| gl.attachShader(m_po_id, m_fs_id); |
| } |
| |
| if (current_run.use_gs) |
| { |
| gl.attachShader(m_po_id, m_gs_id); |
| } |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed"); |
| |
| /* Try to link the PO */ |
| gl.linkProgram(m_po_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); |
| |
| /* Verify the link status */ |
| glw::GLint link_status = GL_FALSE; |
| |
| gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed"); |
| |
| if ((current_run.use_separable_po && link_status != GL_TRUE) || |
| (!current_run.use_separable_po && link_status == GL_TRUE)) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Invalid link status reported for a " |
| << ((current_run.use_separable_po) ? "separable" : "") |
| << " program object, to which the following SOs were attached: " |
| << "FS:" << ((current_run.use_fs) ? "YES" : "NO") |
| << ", GS:" << ((current_run.use_gs) ? "YES" : "NO") << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| |
| /* Clean up for the next iteration */ |
| gl.deleteProgram(m_po_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram() call failed"); |
| } /* for (all test runs) */ |
| |
| if (result) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| |
| return STOP; |
| } |
| |
| /** Constructor |
| * |
| * @param context Test context |
| * @param extParams Not used. |
| * @param name Test case's name |
| * @param description Test case's description |
| **/ |
| GeometryShaderIncompleteGSTest::GeometryShaderIncompleteGSTest(Context& context, const ExtParameters& extParams, |
| const char* name, const char* description) |
| : TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_vs_id(0) |
| { |
| } |
| |
| /** Deinitializes GLES objects created during the test. */ |
| void GeometryShaderIncompleteGSTest::deinit() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| deinitSOs(); |
| |
| if (m_po_id != 0) |
| { |
| gl.deleteProgram(m_po_id); |
| |
| m_po_id = 0; |
| } |
| |
| /* Release base class */ |
| TestCaseBase::deinit(); |
| } |
| |
| /** Deinitializes shader objects created for the conformance test. */ |
| void GeometryShaderIncompleteGSTest::deinitSOs() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| if (m_fs_id != 0) |
| { |
| gl.deleteShader(m_fs_id); |
| |
| m_fs_id = 0; |
| } |
| |
| if (m_gs_id != 0) |
| { |
| gl.deleteShader(m_gs_id); |
| |
| m_gs_id = 0; |
| } |
| |
| if (m_vs_id != 0) |
| { |
| gl.deleteShader(m_vs_id); |
| |
| m_vs_id = 0; |
| } |
| } |
| |
| /** Returns geometry shader's source code, built according to the test run's settings. |
| * |
| * @param current_run Test run descriptor. |
| * |
| * @return Requested string. |
| */ |
| std::string GeometryShaderIncompleteGSTest::getGeometryShaderCode(const _run& current_run) |
| { |
| std::stringstream gs_code_sstream; |
| |
| gs_code_sstream << "${VERSION}\n" |
| "${GEOMETRY_SHADER_REQUIRE}\n" |
| "\n"; |
| |
| if (current_run.is_input_primitive_type_defined) |
| { |
| gs_code_sstream << "layout(points) in;\n"; |
| } |
| |
| if (current_run.is_max_vertices_defined || current_run.is_output_primitive_type_defined) |
| { |
| gs_code_sstream << "layout("; |
| |
| if (current_run.is_max_vertices_defined) |
| { |
| gs_code_sstream << "max_vertices = 1"; |
| |
| if (current_run.is_output_primitive_type_defined) |
| { |
| gs_code_sstream << ", "; |
| } |
| } /* if (current_run.is_max_vertices_defined) */ |
| |
| if (current_run.is_output_primitive_type_defined) |
| { |
| gs_code_sstream << "points"; |
| } |
| |
| gs_code_sstream << ") out;\n"; |
| } |
| |
| gs_code_sstream << "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = gl_in[0].gl_Position;\n" |
| " EmitVertex();\n" |
| "}\n"; |
| |
| return gs_code_sstream.str(); |
| } |
| |
| /** Initializes fragment / geometry / vertex shader objects, according to the test run descriptor. |
| * |
| * @param current_run Test run descriptor. |
| * @param out_has_fs_compiled_successfully Deref will be set to false, if FS has failed to compile |
| * successfully. Otherwise, it will be set to true. |
| * @param out_has_gs_compiled_successfully Deref will be set to false, if GS has failed to compile |
| * successfully. Otherwise, it will be set to true. |
| * @param out_has_vs_compiled_successfully Deref will be set to false, if VS has failed to compile |
| * successfully. Otherwise, it will be set to true. |
| * |
| */ |
| void GeometryShaderIncompleteGSTest::initShaderObjects(const _run& current_run, bool* out_has_fs_compiled_successfully, |
| bool* out_has_gs_compiled_successfully, |
| bool* out_has_vs_compiled_successfully) |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| std::string specialized_fs_code = specializeShader(1, &dummy_fs_code); |
| std::string gs_code = getGeometryShaderCode(current_run); |
| const char* gs_code_raw = gs_code.c_str(); |
| std::string specialized_gs_code = specializeShader(1, &gs_code_raw); |
| std::string specialized_vs_code = specializeShader(1, &dummy_vs_code); |
| |
| const char* specialized_fs_code_raw = specialized_fs_code.c_str(); |
| const char* specialized_gs_code_raw = specialized_gs_code.c_str(); |
| const char* specialized_vs_code_raw = specialized_vs_code.c_str(); |
| |
| m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); |
| m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); |
| m_vs_id = gl.createShader(GL_VERTEX_SHADER); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); |
| |
| for (unsigned int n_shader_type = 0; n_shader_type < 3; /* fs, gs, vs */ |
| n_shader_type++) |
| { |
| glw::GLint compile_status = GL_FALSE; |
| bool* out_current_compile_result = |
| (n_shader_type == 0) ? |
| out_has_fs_compiled_successfully : |
| (n_shader_type == 1) ? out_has_gs_compiled_successfully : out_has_vs_compiled_successfully; |
| |
| const char* so_code = (n_shader_type == 0) ? |
| specialized_fs_code_raw : |
| (n_shader_type == 1) ? specialized_gs_code_raw : specialized_vs_code_raw; |
| |
| glw::GLuint so_id = (n_shader_type == 0) ? m_fs_id : (n_shader_type == 1) ? m_gs_id : m_vs_id; |
| |
| gl.shaderSource(so_id, 1, /* count */ |
| &so_code, DE_NULL); /* length */ |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed"); |
| |
| gl.compileShader(so_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed"); |
| |
| gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed"); |
| |
| *out_current_compile_result = (compile_status == GL_TRUE); |
| } /* for (both shader stages) */ |
| } |
| |
| /** Initializes all test runs */ |
| void GeometryShaderIncompleteGSTest::initTestRuns() |
| { |
| /* input_primitive_defined | max_vertices_defined | output_primitive_defined |
| * ------------------------|----------------------|-------------------------*/ |
| m_test_runs.push_back(_run(false, false, false)); |
| m_test_runs.push_back(_run(false, false, true)); |
| m_test_runs.push_back(_run(false, true, false)); |
| m_test_runs.push_back(_run(true, true, false)); |
| m_test_runs.push_back(_run(false, true, true)); |
| } |
| |
| /** Executes the test. |
| * |
| * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. |
| * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. |
| * Note the function throws exception should an error occur! |
| **/ |
| tcu::TestNode::IterateResult GeometryShaderIncompleteGSTest::iterate() |
| { |
| bool result = true; |
| |
| /* This test should only run if EXT_geometry_shader is supported. */ |
| if (!m_is_geometry_shader_extension_supported) |
| { |
| throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); |
| } |
| |
| /* Initialize test runs */ |
| initTestRuns(); |
| |
| /* Iterate over the test run set */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| for (unsigned int run_index = 0; run_index < m_test_runs.size(); ++run_index) |
| { |
| const _run& current_run = m_test_runs[run_index]; |
| |
| /* Release shader objects initialized in previous iterations */ |
| deinitSOs(); |
| |
| /* Set up shader objects */ |
| bool has_fs_compiled = false; |
| bool has_gs_compiled = false; |
| bool has_vs_compiled = false; |
| |
| initShaderObjects(current_run, &has_fs_compiled, &has_gs_compiled, &has_vs_compiled); |
| |
| if (!has_fs_compiled || !has_vs_compiled) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Dummy FS and/or dummy VS failed to compile" |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| break; |
| } |
| |
| /* Set up a program object */ |
| m_po_id = gl.createProgram(); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed"); |
| |
| gl.attachShader(m_po_id, m_fs_id); |
| gl.attachShader(m_po_id, m_gs_id); |
| gl.attachShader(m_po_id, m_vs_id); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed"); |
| |
| /* Try to link the PO */ |
| gl.linkProgram(m_po_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); |
| |
| /* Verify the link status */ |
| glw::GLint link_status = GL_FALSE; |
| |
| gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed"); |
| |
| if (link_status == GL_TRUE) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "PO with a malformed Geometry Shader was linked successfully." |
| << " [input primitive type]:" |
| << ((current_run.is_input_primitive_type_defined) ? "DEFINED" : "NOT DEFINED") |
| << " [output primitive type]:" |
| << ((current_run.is_output_primitive_type_defined) ? "DEFINED" : "NOT DEFINED") |
| << " [max_vertices]:" |
| << ((current_run.is_max_vertices_defined) ? "DEFINED" : "NOT DEFINED") |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| |
| /* Clean up for the next iteration */ |
| gl.deleteProgram(m_po_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram() call failed"); |
| } /* for (all test runs) */ |
| |
| if (result) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| |
| return STOP; |
| } |
| |
| /** Constructor |
| * |
| * @param context Test context |
| * @param extParams Not used. |
| * @param name Test case's name |
| * @param description Test case's description |
| **/ |
| GeometryShaderInvalidArrayedInputVariablesTest::GeometryShaderInvalidArrayedInputVariablesTest( |
| Context& context, const ExtParameters& extParams, const char* name, const char* description) |
| : TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_vs_id(0) |
| { |
| } |
| |
| /** Deinitializes GLES objects created during the test. */ |
| void GeometryShaderInvalidArrayedInputVariablesTest::deinit() |
| { |
| deinitSOs(); |
| |
| /* Release the PO */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| if (m_po_id != 0) |
| { |
| gl.deleteProgram(m_po_id); |
| |
| m_po_id = 0; |
| } |
| |
| /* Release base class */ |
| TestCaseBase::deinit(); |
| } |
| |
| /** Deinitializes shader objects created for the conformance test. */ |
| void GeometryShaderInvalidArrayedInputVariablesTest::deinitSOs() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| if (m_fs_id != 0) |
| { |
| gl.deleteShader(m_fs_id); |
| |
| m_fs_id = 0; |
| } |
| |
| if (m_gs_id != 0) |
| { |
| gl.deleteShader(m_gs_id); |
| |
| m_gs_id = 0; |
| } |
| |
| if (m_vs_id != 0) |
| { |
| gl.deleteShader(m_vs_id); |
| |
| m_vs_id = 0; |
| } |
| } |
| |
| /** Returns test-specific geometry shader source code, built for caller-specified input primitive type. |
| * |
| * @param gs_input_primitive_type Input primitive type to be used for the process. |
| * |
| * @return Requested shader source code. |
| **/ |
| std::string GeometryShaderInvalidArrayedInputVariablesTest::getGSCode(glw::GLenum gs_input_primitive_type) const |
| { |
| std::stringstream code_sstream; |
| const unsigned int valid_array_size = getValidInputVariableArraySize(gs_input_primitive_type); |
| |
| code_sstream << "${VERSION}\n" |
| "${GEOMETRY_SHADER_REQUIRE}\n" |
| "\n" |
| "layout (" |
| << getInputPrimitiveTypeQualifier(gs_input_primitive_type) |
| << ") in;\n" |
| "layout (points, max_vertices = 1) out;\n" |
| "\n" |
| "in vec4 data[" |
| << (valid_array_size + 1) << "];\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = data[" |
| << valid_array_size << "];\n" |
| " EmitVertex();\n" |
| "}\n"; |
| |
| return code_sstream.str(); |
| } |
| |
| /** Returns a string holding the ES SL layout qualifier corresponding to user-specified input primitive type |
| * expressed as a GLenum value. |
| * |
| * @param gs_input_primitive_type Geometry Shader's input primitive type, expressed as a GLenum value. |
| * |
| * @return Requested string |
| */ |
| std::string GeometryShaderInvalidArrayedInputVariablesTest::getInputPrimitiveTypeQualifier( |
| glw::GLenum gs_input_primitive_type) const |
| { |
| std::string result; |
| |
| switch (gs_input_primitive_type) |
| { |
| case GL_POINTS: |
| result = "points"; |
| break; |
| case GL_LINES: |
| result = "lines"; |
| break; |
| case GL_LINES_ADJACENCY: |
| result = "lines_adjacency"; |
| break; |
| case GL_TRIANGLES: |
| result = "triangles"; |
| break; |
| case GL_TRIANGLES_ADJACENCY: |
| result = "triangles_adjacency"; |
| break; |
| |
| default: |
| { |
| DE_ASSERT(0); |
| } |
| } /* switch (gs_input_primitive_type) */ |
| |
| return result; |
| } |
| |
| /** Retrieves a specialized version of the vertex shader to be used for the conformance test. */ |
| std::string GeometryShaderInvalidArrayedInputVariablesTest::getSpecializedVSCode() const |
| { |
| std::string vs_code = "${VERSION}\n" |
| "\n" |
| "out vec4 data;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " data = vec4(gl_VertexID, 0, 0, 1);\n" |
| "}\n"; |
| const char* vs_code_raw = vs_code.c_str(); |
| std::string specialized_vs_code = specializeShader(1, /* parts */ |
| &vs_code_raw); |
| |
| return specialized_vs_code; |
| } |
| |
| /** Returns array size that should be used for input variable declaration in GS, specific to |
| * to the caller-specified input primitive type. |
| * |
| * @param gs_input_primitive_type Input primitive type to use for the query. |
| * |
| * @return Requested value. |
| */ |
| glw::GLuint GeometryShaderInvalidArrayedInputVariablesTest::getValidInputVariableArraySize( |
| glw::GLenum gs_input_primitive_type) const |
| { |
| glw::GLuint result = 0; |
| |
| switch (gs_input_primitive_type) |
| { |
| case GL_POINTS: |
| result = 1; |
| break; |
| case GL_LINES: |
| result = 2; |
| break; |
| case GL_LINES_ADJACENCY: |
| result = 4; |
| break; |
| case GL_TRIANGLES: |
| result = 3; |
| break; |
| case GL_TRIANGLES_ADJACENCY: |
| result = 6; |
| break; |
| |
| default: |
| { |
| DE_ASSERT(0); |
| } |
| } /* switch (gs_input_primitive_type) */ |
| |
| return result; |
| } |
| |
| /** Initializes fragment / geometry / vertex shader objects, according to the user-specified GS input primitive type. |
| * |
| * @param gs_input_primitive_type Input primitive type, to be used for GS. |
| * @param out_has_fs_compiled_successfully Deref will be set to false, if FS has failed to compile |
| * successfully. Otherwise, it will be set to true. |
| * @param out_has_gs_compiled_successfully Deref will be set to false, if GS has failed to compile |
| * successfully. Otherwise, it will be set to true. |
| * @param out_has_vs_compiled_successfully Deref will be set to false, if VS has failed to compile |
| * successfully. Otherwise, it will be set to true. |
| * |
| */ |
| void GeometryShaderInvalidArrayedInputVariablesTest::initShaderObjects(glw::GLenum gs_input_primitive_type, |
| bool* out_has_fs_compiled_successfully, |
| bool* out_has_gs_compiled_successfully, |
| bool* out_has_vs_compiled_successfully) |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| std::string specialized_fs_code = specializeShader(1, &dummy_fs_code); |
| const char* specialized_fs_code_raw = specialized_fs_code.c_str(); |
| std::string gs_code = getGSCode(gs_input_primitive_type); |
| const char* gs_code_raw = gs_code.c_str(); |
| std::string specialized_gs_code = specializeShader(1, &gs_code_raw); |
| const char* specialized_gs_code_raw = specialized_gs_code.c_str(); |
| std::string specialized_vs_code = getSpecializedVSCode(); |
| const char* specialized_vs_code_raw = specialized_vs_code.c_str(); |
| |
| m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); |
| m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); |
| m_vs_id = gl.createShader(GL_VERTEX_SHADER); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); |
| |
| for (unsigned int n_shader_type = 0; n_shader_type < 3; /* fs, gs, vs */ |
| n_shader_type++) |
| { |
| glw::GLint compile_status = GL_FALSE; |
| bool* out_compile_result = (n_shader_type == 0) ? out_has_fs_compiled_successfully : |
| (n_shader_type == 1) ? out_has_gs_compiled_successfully : |
| out_has_vs_compiled_successfully; |
| |
| const char* so_code = (n_shader_type == 0) ? |
| specialized_fs_code_raw : |
| (n_shader_type == 1) ? specialized_gs_code_raw : specialized_vs_code_raw; |
| |
| glw::GLuint so_id = (n_shader_type == 0) ? m_fs_id : (n_shader_type == 1) ? m_gs_id : m_vs_id; |
| |
| gl.shaderSource(so_id, 1, /* count */ |
| &so_code, DE_NULL); /* length */ |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed"); |
| |
| gl.compileShader(so_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed"); |
| |
| gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed"); |
| |
| *out_compile_result = (compile_status == GL_TRUE); |
| } /* for (both shader stages) */ |
| } |
| |
| /** Executes the test. |
| * |
| * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. |
| * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. |
| * Note the function throws exception should an error occur! |
| **/ |
| tcu::TestNode::IterateResult GeometryShaderInvalidArrayedInputVariablesTest::iterate() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| bool result = true; |
| |
| /* This test should only run if EXT_geometry_shader is supported. */ |
| if (!m_is_geometry_shader_extension_supported) |
| { |
| throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); |
| } |
| |
| /* Iterate over all valid input primitive types */ |
| const glw::GLenum input_primitive_types[] = { GL_POINTS, GL_LINES, GL_LINES_ADJACENCY, GL_TRIANGLES, |
| GL_TRIANGLES_ADJACENCY }; |
| const unsigned int n_input_primitive_types = sizeof(input_primitive_types) / sizeof(input_primitive_types[0]); |
| |
| for (unsigned int n_input_primitive_type = 0; n_input_primitive_type < n_input_primitive_types; |
| ++n_input_primitive_type) |
| { |
| const glw::GLenum input_primitive_type = input_primitive_types[n_input_primitive_type]; |
| |
| /* Release shader objects initialized in previous iterations */ |
| deinitSOs(); |
| |
| /* Set up shader objects */ |
| bool has_fs_compiled = false; |
| bool has_gs_compiled = false; |
| bool has_vs_compiled = false; |
| |
| initShaderObjects(input_primitive_type, &has_fs_compiled, &has_gs_compiled, &has_vs_compiled); |
| |
| if (!has_fs_compiled || !has_gs_compiled || !has_vs_compiled) |
| { |
| m_testCtx.getLog() |
| << tcu::TestLog::Message |
| << "One of the shaders failed to compile (but shouldn't have). Shaders that failed to compile:" |
| << ((!has_fs_compiled) ? "FS " : "") << ((!has_gs_compiled) ? "GS " : "") |
| << ((!has_vs_compiled) ? "VS" : "") << ". Input primitive type: [" |
| << getInputPrimitiveTypeQualifier(input_primitive_type) << "]" << tcu::TestLog::EndMessage; |
| |
| continue; |
| } |
| |
| /* Set up a program object */ |
| m_po_id = gl.createProgram(); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed"); |
| |
| gl.attachShader(m_po_id, m_fs_id); |
| gl.attachShader(m_po_id, m_gs_id); |
| gl.attachShader(m_po_id, m_vs_id); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed"); |
| |
| /* Try to link the PO */ |
| gl.linkProgram(m_po_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); |
| |
| /* Verify the link status */ |
| glw::GLint link_status = GL_FALSE; |
| |
| gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed"); |
| |
| if (link_status == GL_TRUE) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "A PO using a malformed GS has linked successfully. " |
| << "Test input primitive type: " << getInputPrimitiveTypeQualifier(input_primitive_type) |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| } /* for (all input primitive types) */ |
| |
| if (result) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| |
| return STOP; |
| } |
| |
| /** Constructor |
| * |
| * @param context Test context |
| * @param extParams Not used. |
| * @param name Test case's name |
| * @param description Test case's description |
| **/ |
| GeometryShaderVSGSVariableTypeMismatchTest::GeometryShaderVSGSVariableTypeMismatchTest(Context& context, |
| const ExtParameters& extParams, |
| const char* name, |
| const char* description) |
| : TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_vs_id(0) |
| { |
| } |
| |
| /** Deinitializes GLES objects created during the test. */ |
| void GeometryShaderVSGSVariableTypeMismatchTest::deinit() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| if (m_fs_id != 0) |
| { |
| gl.deleteShader(m_fs_id); |
| |
| m_fs_id = 0; |
| } |
| |
| if (m_gs_id != 0) |
| { |
| gl.deleteShader(m_gs_id); |
| |
| m_gs_id = 0; |
| } |
| |
| if (m_po_id != 0) |
| { |
| gl.deleteProgram(m_po_id); |
| |
| m_po_id = 0; |
| } |
| |
| if (m_vs_id != 0) |
| { |
| gl.deleteShader(m_vs_id); |
| |
| m_vs_id = 0; |
| } |
| |
| /* Release base class */ |
| TestCaseBase::deinit(); |
| } |
| |
| /** Executes the test. |
| * |
| * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. |
| * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. |
| * Note the function throws exception should an error occur! |
| **/ |
| tcu::TestNode::IterateResult GeometryShaderVSGSVariableTypeMismatchTest::iterate() |
| { |
| bool has_shader_compilation_failed = true; |
| bool result = true; |
| |
| /* This test should only run if EXT_geometry_shader is supported. */ |
| if (!m_is_geometry_shader_extension_supported) |
| { |
| throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); |
| } |
| |
| /* Create a program object */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| m_po_id = gl.createProgram(); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); |
| |
| /* Create shader objects */ |
| m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); |
| m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); |
| m_vs_id = gl.createShader(GL_VERTEX_SHADER); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); |
| |
| /* Try to link the test program object */ |
| const char* gs_code_raw = "${VERSION}\n" |
| "${GEOMETRY_SHADER_REQUIRE}\n" |
| "\n" |
| "layout (points) in;\n" |
| "layout (points, max_vertices = 1) out;\n" |
| "\n" |
| "in vec4 test[];\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = test[0];\n" |
| " EmitVertex();\n" |
| "}\n"; |
| |
| const char* vs_code_raw = "${VERSION}\n" |
| "\n" |
| "out vec3 test;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " test = vec3(gl_VertexID);\n" |
| "}\n"; |
| |
| std::string fs_code_specialized = specializeShader(1, &dummy_fs_code); |
| const char* fs_code_specialized_raw = fs_code_specialized.c_str(); |
| std::string gs_code_specialized = specializeShader(1, &gs_code_raw); |
| const char* gs_code_specialized_raw = gs_code_specialized.c_str(); |
| std::string vs_code_specialized = specializeShader(1, &vs_code_raw); |
| const char* vs_code_specialized_raw = vs_code_specialized.c_str(); |
| |
| if (TestCaseBase::buildProgram(m_po_id, m_gs_id, 1, /* n_sh1_body_parts */ |
| &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */ |
| &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */ |
| &fs_code_specialized_raw, &has_shader_compilation_failed)) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "Program object was linked successfully, whereas a failure was expected." |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| |
| if (has_shader_compilation_failed) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Shader compilation failed unexpectedly." |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| |
| if (result) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| |
| return STOP; |
| } |
| |
| /** Constructor |
| * |
| * @param context Test context |
| * @param extParams Not used. |
| * @param name Test case's name |
| * @param description Test case's description |
| **/ |
| GeometryShaderVSGSVariableQualifierMismatchTest::GeometryShaderVSGSVariableQualifierMismatchTest( |
| Context& context, const ExtParameters& extParams, const char* name, const char* description) |
| : TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_vs_id(0) |
| { |
| } |
| |
| /** Deinitializes GLES objects created during the test. */ |
| void GeometryShaderVSGSVariableQualifierMismatchTest::deinit() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| if (m_fs_id != 0) |
| { |
| gl.deleteShader(m_fs_id); |
| |
| m_fs_id = 0; |
| } |
| |
| if (m_gs_id != 0) |
| { |
| gl.deleteShader(m_gs_id); |
| |
| m_gs_id = 0; |
| } |
| |
| if (m_po_id != 0) |
| { |
| gl.deleteProgram(m_po_id); |
| |
| m_po_id = 0; |
| } |
| |
| if (m_vs_id != 0) |
| { |
| gl.deleteShader(m_vs_id); |
| |
| m_vs_id = 0; |
| } |
| |
| /* Release base class */ |
| TestCaseBase::deinit(); |
| } |
| |
| /** Executes the test. |
| * |
| * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. |
| * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. |
| * Note the function throws exception should an error occur! |
| **/ |
| tcu::TestNode::IterateResult GeometryShaderVSGSVariableQualifierMismatchTest::iterate() |
| { |
| bool has_shader_compilation_failed = true; |
| bool result = true; |
| |
| /* This test should only run if EXT_geometry_shader is supported. */ |
| if (!m_is_geometry_shader_extension_supported) |
| { |
| throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); |
| } |
| |
| /* Create a program object */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| m_po_id = gl.createProgram(); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); |
| |
| /* Create shader objects */ |
| m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); |
| m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); |
| m_vs_id = gl.createShader(GL_VERTEX_SHADER); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); |
| |
| /* Try to link the test program object */ |
| const char* gs_code_raw = "${VERSION}\n" |
| "${GEOMETRY_SHADER_REQUIRE}\n" |
| "\n" |
| "layout (points) in;\n" |
| "layout (points, max_vertices = 1) out;\n" |
| "\n" |
| "in flat vec4 test[];\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = test[0];\n" |
| " EmitVertex();\n" |
| "}\n"; |
| |
| const char* vs_code_raw = "${VERSION}\n" |
| "${GEOMETRY_SHADER_REQUIRE}\n" |
| "\n" |
| "out vec4 test;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " test = vec4(gl_VertexID);\n" |
| "}\n"; |
| |
| std::string fs_code_specialized = specializeShader(1, &dummy_fs_code); |
| const char* fs_code_specialized_raw = fs_code_specialized.c_str(); |
| std::string gs_code_specialized = specializeShader(1, &gs_code_raw); |
| const char* gs_code_specialized_raw = gs_code_specialized.c_str(); |
| std::string vs_code_specialized = specializeShader(1, &vs_code_raw); |
| const char* vs_code_specialized_raw = vs_code_specialized.c_str(); |
| |
| bool buildSuccess = TestCaseBase::buildProgram(m_po_id, m_gs_id, 1, /* n_sh1_body_parts */ |
| &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */ |
| &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */ |
| &fs_code_specialized_raw, &has_shader_compilation_failed); |
| |
| if (!buildSuccess && glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0))) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed. Success was expected." |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| |
| if (buildSuccess && !glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0))) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "Program object was linked successfully, whereas a failure was expected." |
| << tcu::TestLog::EndMessage; |
| result = false; |
| } |
| |
| if (has_shader_compilation_failed) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Shader compilation failed unexpectedly." |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| |
| if (result) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| |
| return STOP; |
| } |
| |
| /** Constructor |
| * |
| * @param context Test context |
| * @param extParams Not used. |
| * @param name Test case's name |
| * @param description Test case's description |
| **/ |
| GeometryShaderVSGSArrayedVariableSizeMismatchTest::GeometryShaderVSGSArrayedVariableSizeMismatchTest( |
| Context& context, const ExtParameters& extParams, const char* name, const char* description) |
| : TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_vs_id(0) |
| { |
| } |
| |
| /** Deinitializes GLES objects created during the test. */ |
| void GeometryShaderVSGSArrayedVariableSizeMismatchTest::deinit() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| if (m_fs_id != 0) |
| { |
| gl.deleteShader(m_fs_id); |
| |
| m_fs_id = 0; |
| } |
| |
| if (m_gs_id != 0) |
| { |
| gl.deleteShader(m_gs_id); |
| |
| m_gs_id = 0; |
| } |
| |
| if (m_po_id != 0) |
| { |
| gl.deleteProgram(m_po_id); |
| |
| m_po_id = 0; |
| } |
| |
| if (m_vs_id != 0) |
| { |
| gl.deleteShader(m_vs_id); |
| |
| m_vs_id = 0; |
| } |
| |
| /* Release base class */ |
| TestCaseBase::deinit(); |
| } |
| |
| /** Executes the test. |
| * |
| * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. |
| * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. |
| * Note the function throws exception should an error occur! |
| **/ |
| tcu::TestNode::IterateResult GeometryShaderVSGSArrayedVariableSizeMismatchTest::iterate() |
| { |
| bool has_shader_compilation_failed = true; |
| bool result = true; |
| |
| /* This test should only run if EXT_geometry_shader is supported. */ |
| if (!m_is_geometry_shader_extension_supported) |
| { |
| throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); |
| } |
| |
| /* Create a program object */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| m_po_id = gl.createProgram(); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); |
| |
| /* Create shader objects */ |
| m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); |
| m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); |
| m_vs_id = gl.createShader(GL_VERTEX_SHADER); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); |
| |
| /* Try to link the test program object */ |
| const char* gs_code_raw = "${VERSION}\n" |
| "${GEOMETRY_SHADER_REQUIRE}\n" |
| "\n" |
| "layout (points) in;\n" |
| "layout (points, max_vertices = 1) out;\n" |
| "\n" |
| "in vec4 Color1[];\n" |
| "in vec4 Color2[2];\n" |
| "in vec4 Color3[3];\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = Color1[0] + Color2[1] + Color3[2];\n" |
| " EmitVertex();\n" |
| "}\n"; |
| |
| const char* vs_code_raw = "${VERSION}\n" |
| "${GEOMETRY_SHADER_REQUIRE}\n" |
| "\n" |
| "out vec4 Color1;\n" |
| "out vec4 Color2;\n" |
| "out vec4 Color3;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " Color1 = vec4(gl_VertexID, 0.0, 0.0, 0.0);\n" |
| " Color2 = vec4(0.0, gl_VertexID, 0.0, 0.0);\n" |
| " Color3 = vec4(0.0, 0.0, gl_VertexID, 0.0);\n" |
| "}\n"; |
| |
| std::string fs_code_specialized = specializeShader(1, &dummy_fs_code); |
| const char* fs_code_specialized_raw = fs_code_specialized.c_str(); |
| std::string gs_code_specialized = specializeShader(1, &gs_code_raw); |
| const char* gs_code_specialized_raw = gs_code_specialized.c_str(); |
| std::string vs_code_specialized = specializeShader(1, &vs_code_raw); |
| const char* vs_code_specialized_raw = vs_code_specialized.c_str(); |
| |
| if (TestCaseBase::buildProgram(m_po_id, m_gs_id, 1, /* n_sh1_body_parts */ |
| &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */ |
| &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */ |
| &fs_code_specialized_raw, &has_shader_compilation_failed)) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "Program object was linked successfully, whereas a failure was expected." |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| |
| if (result) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| |
| return STOP; |
| } |
| |
| /** Constructor |
| * |
| * @param context Test context |
| * @param extParams Not used. |
| * @param name Test case's name |
| * @param description Test case's description |
| **/ |
| GeometryShaderFragCoordRedeclarationTest::GeometryShaderFragCoordRedeclarationTest(Context& context, |
| const ExtParameters& extParams, |
| const char* name, |
| const char* description) |
| : TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_vs_id(0) |
| { |
| } |
| |
| /** Deinitializes GLES objects created during the test. */ |
| void GeometryShaderFragCoordRedeclarationTest::deinit() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| if (m_fs_id != 0) |
| { |
| gl.deleteShader(m_fs_id); |
| |
| m_fs_id = 0; |
| } |
| |
| if (m_gs_id != 0) |
| { |
| gl.deleteShader(m_gs_id); |
| |
| m_gs_id = 0; |
| } |
| |
| if (m_po_id != 0) |
| { |
| gl.deleteProgram(m_po_id); |
| |
| m_po_id = 0; |
| } |
| |
| if (m_vs_id != 0) |
| { |
| gl.deleteShader(m_vs_id); |
| |
| m_vs_id = 0; |
| } |
| |
| /* Release base class */ |
| TestCaseBase::deinit(); |
| } |
| |
| /** Executes the test. |
| * |
| * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. |
| * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. |
| * Note the function throws exception should an error occur! |
| **/ |
| tcu::TestNode::IterateResult GeometryShaderFragCoordRedeclarationTest::iterate() |
| { |
| bool has_shader_compilation_failed = true; |
| bool result = true; |
| |
| /* This test should only run if EXT_geometry_shader is supported. */ |
| if (!m_is_geometry_shader_extension_supported) |
| { |
| throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); |
| } |
| |
| /* Create a program object */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| m_po_id = gl.createProgram(); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); |
| |
| /* Create shader objects */ |
| m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); |
| m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); |
| m_vs_id = gl.createShader(GL_VERTEX_SHADER); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); |
| |
| /* Try to link the test program object */ |
| const char* gs_code_raw = "${VERSION}\n" |
| "${GEOMETRY_SHADER_REQUIRE}\n" |
| "\n" |
| "layout (points) in;\n" |
| "layout (points, max_vertices = 1) out;\n" |
| "\n" |
| "in vec4 gl_FragCoord;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = gl_FragCoord;\n" |
| " EmitVertex();\n" |
| "}\n"; |
| |
| std::string fs_code_specialized = specializeShader(1, &dummy_fs_code); |
| const char* fs_code_specialized_raw = fs_code_specialized.c_str(); |
| std::string gs_code_specialized = specializeShader(1, &gs_code_raw); |
| const char* gs_code_specialized_raw = gs_code_specialized.c_str(); |
| std::string vs_code_specialized = specializeShader(1, &dummy_vs_code); |
| const char* vs_code_specialized_raw = vs_code_specialized.c_str(); |
| |
| if (TestCaseBase::buildProgram(m_po_id, m_gs_id, 1, /* n_sh1_body_parts */ |
| &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */ |
| &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */ |
| &fs_code_specialized_raw, &has_shader_compilation_failed)) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "Program object was linked successfully, whereas a failure was expected." |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| |
| if (result) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| |
| return STOP; |
| } |
| |
| /** Constructor |
| * |
| * @param context Test context |
| * @param extParams Not used. |
| * @param name Test case's name |
| * @param description Test case's description |
| **/ |
| GeometryShaderLocationAliasingTest::GeometryShaderLocationAliasingTest(Context& context, const ExtParameters& extParams, |
| const char* name, const char* description) |
| : TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_vs_id(0) |
| { |
| } |
| |
| /** Deinitializes GLES objects created during the test. */ |
| void GeometryShaderLocationAliasingTest::deinit() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| if (m_fs_id != 0) |
| { |
| gl.deleteShader(m_fs_id); |
| |
| m_fs_id = 0; |
| } |
| |
| if (m_gs_id != 0) |
| { |
| gl.deleteShader(m_gs_id); |
| |
| m_gs_id = 0; |
| } |
| |
| if (m_po_id != 0) |
| { |
| gl.deleteProgram(m_po_id); |
| |
| m_po_id = 0; |
| } |
| |
| if (m_vs_id != 0) |
| { |
| gl.deleteShader(m_vs_id); |
| |
| m_vs_id = 0; |
| } |
| |
| /* Release base class */ |
| TestCaseBase::deinit(); |
| } |
| |
| /** Executes the test. |
| * |
| * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. |
| * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. |
| * Note the function throws exception should an error occur! |
| **/ |
| tcu::TestNode::IterateResult GeometryShaderLocationAliasingTest::iterate() |
| { |
| bool has_program_link_succeeded = true; |
| bool result = true; |
| |
| /* This test should only run if EXT_geometry_shader is supported. */ |
| if (!m_is_geometry_shader_extension_supported) |
| { |
| throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); |
| } |
| |
| /* Create a program object */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| m_po_id = gl.createProgram(); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); |
| |
| /* Create shader objects */ |
| m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); |
| m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); |
| m_vs_id = gl.createShader(GL_VERTEX_SHADER); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); |
| |
| /* Try to link the test program object */ |
| const char* gs_code_raw = "${VERSION}\n" |
| "${GEOMETRY_SHADER_REQUIRE}\n" |
| "\n" |
| "layout (points) in;\n" |
| "layout (points, max_vertices = 1) out;\n" |
| "\n" |
| "layout (location = 2) out vec4 test;\n" |
| "layout (location = 2) out vec4 test2;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = gl_in[0].gl_Position;\n" |
| " test = vec4(1.0, 0.0, 0.0, 1.0);\n" |
| " test2 = vec4(1.0, 0.0, 0.0, 1.0);\n" |
| " EmitVertex();\n" |
| "}\n"; |
| |
| std::string fs_code_specialized = specializeShader(1, &dummy_fs_code); |
| const char* fs_code_specialized_raw = fs_code_specialized.c_str(); |
| std::string gs_code_specialized = specializeShader(1, &gs_code_raw); |
| const char* gs_code_specialized_raw = gs_code_specialized.c_str(); |
| std::string vs_code_specialized = specializeShader(1, &dummy_vs_code); |
| const char* vs_code_specialized_raw = vs_code_specialized.c_str(); |
| |
| has_program_link_succeeded = TestCaseBase::buildProgram( |
| m_po_id, m_gs_id, 1 /* n_sh1_body_parts */, &gs_code_specialized_raw, m_vs_id, 1 /* n_sh2_body_parts */, |
| &vs_code_specialized_raw, m_fs_id, 1 /* n_sh3_body_parts */, &fs_code_specialized_raw, NULL); |
| if (has_program_link_succeeded) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "Program object was compiled and linked successfully, whereas a failure was expected." |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| |
| if (result) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| |
| return STOP; |
| } |
| |
| /** Constructor |
| * |
| * @param context Test context |
| * @param extParams Not used. |
| * @param name Test case's name |
| * @param description Test case's description |
| **/ |
| GeometryShaderMoreACsInGSThanSupportedTest::GeometryShaderMoreACsInGSThanSupportedTest(Context& context, |
| const ExtParameters& extParams, |
| const char* name, |
| const char* description) |
| : TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_vs_id(0) |
| { |
| } |
| |
| /** Deinitializes GLES objects created during the test. */ |
| void GeometryShaderMoreACsInGSThanSupportedTest::deinit() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| if (m_fs_id != 0) |
| { |
| gl.deleteShader(m_fs_id); |
| |
| m_fs_id = 0; |
| } |
| |
| if (m_gs_id != 0) |
| { |
| gl.deleteShader(m_gs_id); |
| |
| m_gs_id = 0; |
| } |
| |
| if (m_po_id != 0) |
| { |
| gl.deleteProgram(m_po_id); |
| |
| m_po_id = 0; |
| } |
| |
| if (m_vs_id != 0) |
| { |
| gl.deleteShader(m_vs_id); |
| |
| m_vs_id = 0; |
| } |
| |
| /* Release base class */ |
| TestCaseBase::deinit(); |
| } |
| |
| /* Retrieves test-specific geometry shader source code. |
| * |
| * @return Requested string. |
| */ |
| std::string GeometryShaderMoreACsInGSThanSupportedTest::getGSCode() |
| { |
| std::stringstream code_sstream; |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| glw::GLint gl_max_ACs_value = 0; |
| |
| /* Retrieve GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT pname value */ |
| gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_ATOMIC_COUNTERS, &gl_max_ACs_value); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT pname"); |
| |
| /* Form the GS */ |
| code_sstream << "${VERSION}\n" |
| "${GEOMETRY_SHADER_REQUIRE}\n" |
| "\n" |
| "layout (points) in;\n" |
| "layout (points, max_vertices = 1) out;\n" |
| "\n"; |
| |
| for (glw::GLint n_ac = 0; n_ac < (gl_max_ACs_value + 1); ++n_ac) |
| { |
| code_sstream << "layout(binding = 0) uniform atomic_uint counter" << n_ac << ";\n"; |
| } |
| |
| code_sstream << "\n" |
| "void main()\n" |
| "{\n"; |
| |
| for (glw::GLint n_ac = 0; n_ac < (gl_max_ACs_value + 1); ++n_ac) |
| { |
| code_sstream << " if ((gl_PrimitiveIDIn % " << (n_ac + 1) << ") == 0) atomicCounterIncrement(counter" << n_ac |
| << ");\n"; |
| } |
| |
| code_sstream << "\n" |
| " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" |
| " EmitVertex();\n" |
| "}\n"; |
| |
| /* Form a specialized version of the GS source code */ |
| std::string gs_code = code_sstream.str(); |
| const char* gs_code_raw = gs_code.c_str(); |
| std::string gs_code_specialized = specializeShader(1, /* parts */ |
| &gs_code_raw); |
| |
| return gs_code_specialized; |
| } |
| |
| /** Executes the test. |
| * |
| * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. |
| * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. |
| * Note the function throws exception should an error occur! |
| **/ |
| tcu::TestNode::IterateResult GeometryShaderMoreACsInGSThanSupportedTest::iterate() |
| { |
| bool has_shader_compilation_failed = true; |
| bool result = true; |
| |
| /* This test should only run if EXT_geometry_shader is supported. */ |
| if (!m_is_geometry_shader_extension_supported) |
| { |
| throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); |
| } |
| |
| /* Create a program object */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| m_po_id = gl.createProgram(); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); |
| |
| /* Create shader objects */ |
| m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); |
| m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); |
| m_vs_id = gl.createShader(GL_VERTEX_SHADER); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); |
| |
| /* Try to link the test program object */ |
| std::string fs_code_specialized = specializeShader(1, &dummy_fs_code); |
| const char* fs_code_specialized_raw = fs_code_specialized.c_str(); |
| std::string gs_code_specialized = getGSCode(); |
| const char* gs_code_specialized_raw = gs_code_specialized.c_str(); |
| std::string vs_code_specialized = specializeShader(1, &dummy_vs_code); |
| const char* vs_code_specialized_raw = vs_code_specialized.c_str(); |
| |
| if (TestCaseBase::buildProgram(m_po_id, m_gs_id, 1, /* n_sh1_body_parts */ |
| &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */ |
| &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */ |
| &fs_code_specialized_raw, &has_shader_compilation_failed)) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "Program object was linked successfully, whereas a failure was expected." |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| |
| if (result) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| |
| return STOP; |
| } |
| |
| /** Constructor |
| * |
| * @param context Test context |
| * @param extParams Not used. |
| * @param name Test case's name |
| * @param description Test case's description |
| **/ |
| GeometryShaderMoreACBsInGSThanSupportedTest::GeometryShaderMoreACBsInGSThanSupportedTest(Context& context, |
| const ExtParameters& extParams, |
| const char* name, |
| const char* description) |
| : TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_vs_id(0) |
| { |
| } |
| |
| /** Deinitializes GLES objects created during the test. */ |
| void GeometryShaderMoreACBsInGSThanSupportedTest::deinit() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| if (m_fs_id != 0) |
| { |
| gl.deleteShader(m_fs_id); |
| |
| m_fs_id = 0; |
| } |
| |
| if (m_gs_id != 0) |
| { |
| gl.deleteShader(m_gs_id); |
| |
| m_gs_id = 0; |
| } |
| |
| if (m_po_id != 0) |
| { |
| gl.deleteProgram(m_po_id); |
| |
| m_po_id = 0; |
| } |
| |
| if (m_vs_id != 0) |
| { |
| gl.deleteShader(m_vs_id); |
| |
| m_vs_id = 0; |
| } |
| |
| /* Release base class */ |
| TestCaseBase::deinit(); |
| } |
| |
| /* Retrieves test-specific geometry shader source code. |
| * |
| * @return Requested string. |
| */ |
| std::string GeometryShaderMoreACBsInGSThanSupportedTest::getGSCode() |
| { |
| std::stringstream code_sstream; |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| glw::GLint gl_max_ACBs_value = 0; |
| |
| /* Retrieve GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT pname value */ |
| gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS, &gl_max_ACBs_value); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT pname"); |
| |
| /* Form the GS */ |
| code_sstream << "${VERSION}\n" |
| "${GEOMETRY_SHADER_REQUIRE}\n" |
| "\n" |
| "layout (points) in;\n" |
| "layout (points, max_vertices = 1) out;\n" |
| "\n"; |
| |
| for (glw::GLint n_acb = 0; n_acb < (gl_max_ACBs_value + 1); ++n_acb) |
| { |
| code_sstream << "layout(binding = " << n_acb << ") uniform atomic_uint counter" << n_acb << ";\n"; |
| } |
| |
| code_sstream << "\n" |
| "void main()\n" |
| "{\n"; |
| |
| for (glw::GLint n_acb = 0; n_acb < (gl_max_ACBs_value + 1); ++n_acb) |
| { |
| code_sstream << " if ((gl_PrimitiveIDIn % " << (n_acb + 1) << ") == 0) atomicCounterIncrement(counter" |
| << n_acb << ");\n"; |
| } |
| |
| code_sstream << "\n" |
| " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" |
| " EmitVertex();\n" |
| "}\n"; |
| |
| /* Form a specialized version of the GS source code */ |
| std::string gs_code = code_sstream.str(); |
| const char* gs_code_raw = gs_code.c_str(); |
| std::string gs_code_specialized = specializeShader(1, /* parts */ |
| &gs_code_raw); |
| |
| return gs_code_specialized; |
| } |
| |
| /** Executes the test. |
| * |
| * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. |
| * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. |
| * Note the function throws exception should an error occur! |
| **/ |
| tcu::TestNode::IterateResult GeometryShaderMoreACBsInGSThanSupportedTest::iterate() |
| { |
| bool has_shader_compilation_failed = true; |
| bool result = true; |
| |
| /* This test should only run if EXT_geometry_shader is supported. */ |
| if (!m_is_geometry_shader_extension_supported) |
| { |
| throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); |
| } |
| |
| /* Create a program object */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| m_po_id = gl.createProgram(); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); |
| |
| /* Create shader objects */ |
| m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); |
| m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); |
| m_vs_id = gl.createShader(GL_VERTEX_SHADER); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); |
| |
| /* Try to link the test program object */ |
| std::string fs_code_specialized = specializeShader(1, &dummy_fs_code); |
| const char* fs_code_specialized_raw = fs_code_specialized.c_str(); |
| std::string gs_code_specialized = getGSCode(); |
| const char* gs_code_specialized_raw = gs_code_specialized.c_str(); |
| std::string vs_code_specialized = specializeShader(1, &dummy_vs_code); |
| const char* vs_code_specialized_raw = vs_code_specialized.c_str(); |
| |
| if (TestCaseBase::buildProgram(m_po_id, m_gs_id, 1, /* n_sh1_body_parts */ |
| &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */ |
| &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */ |
| &fs_code_specialized_raw, &has_shader_compilation_failed)) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "Program object was linked successfully, whereas a failure was expected." |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| |
| if (result) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| |
| return STOP; |
| } |
| |
| /** Constructor |
| * |
| * @param context Test context |
| * @param extParams Not used. |
| * @param name Test case's name |
| * @param description Test case's description |
| **/ |
| GeometryShaderCompilationFailTest::GeometryShaderCompilationFailTest(Context& context, const ExtParameters& extParams, |
| const char* name, const char* description) |
| : TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_vs_id(0) |
| { |
| } |
| |
| /** Deinitializes GLES objects created during the test. */ |
| void GeometryShaderCompilationFailTest::deinit() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| if (m_fs_id != 0) |
| { |
| gl.deleteShader(m_fs_id); |
| |
| m_fs_id = 0; |
| } |
| |
| if (m_gs_id != 0) |
| { |
| gl.deleteShader(m_gs_id); |
| |
| m_gs_id = 0; |
| } |
| |
| if (m_po_id != 0) |
| { |
| gl.deleteProgram(m_po_id); |
| |
| m_po_id = 0; |
| } |
| |
| if (m_vs_id != 0) |
| { |
| gl.deleteShader(m_vs_id); |
| |
| m_vs_id = 0; |
| } |
| |
| /* Release base class */ |
| TestCaseBase::deinit(); |
| } |
| |
| /** Executes the test. |
| * |
| * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. |
| * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. |
| * Note the function throws exception should an error occur! |
| **/ |
| tcu::TestNode::IterateResult GeometryShaderCompilationFailTest::iterate() |
| { |
| /* Define Vertex Shader's code for the purpose of this test. */ |
| const char* gs_code = "${VERSION}\n" |
| "${GEOMETRY_SHADER_REQUIRE}\n" |
| "\n" |
| "layout (points) in;\n" |
| "layout (points, max_vertices = 1) out;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = gl_in[0].gl_Position;\n" |
| " mitVertex();\n" |
| "}\n"; |
| |
| bool has_shader_compilation_failed = true; |
| bool result = true; |
| |
| /* This test should only run if EXT_geometry_shader is supported. */ |
| if (!m_is_geometry_shader_extension_supported) |
| { |
| throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); |
| } |
| |
| /* Create a program object */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| m_po_id = gl.createProgram(); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); |
| |
| /* Create shader objects */ |
| m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); |
| m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); |
| m_vs_id = gl.createShader(GL_VERTEX_SHADER); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); |
| |
| /* Try to link the test program object */ |
| std::string fs_code_specialized = specializeShader(1, &dummy_fs_code); |
| const char* fs_code_specialized_raw = fs_code_specialized.c_str(); |
| |
| std::string gs_code_specialized = specializeShader(1, &gs_code); |
| const char* gs_code_specialized_raw = gs_code_specialized.c_str(); |
| |
| std::string vs_code_specialized = specializeShader(1, &dummy_vs_code); |
| const char* vs_code_specialized_raw = vs_code_specialized.c_str(); |
| |
| if (TestCaseBase::buildProgram(m_po_id, m_gs_id, 1, /* n_sh1_body_parts */ |
| &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */ |
| &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */ |
| &fs_code_specialized_raw, &has_shader_compilation_failed)) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "Program object was linked successfully, whereas a failure was expected." |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| |
| if (!has_shader_compilation_failed) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Shader compilation succeeded, whereas a failure was expected." |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| |
| if (result) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| |
| return STOP; |
| } |
| |
| /** Constructor |
| * |
| * @param context Test context |
| * @param extParams Not used. |
| * @param name Test case's name |
| * @param description Test case's description |
| **/ |
| GeometryShaderMoreInputVerticesThanAvailableTest::GeometryShaderMoreInputVerticesThanAvailableTest( |
| Context& context, const ExtParameters& extParams, const char* name, const char* description) |
| : TestCaseBase(context, extParams, name, description) |
| , m_fs_id(0) |
| , m_gs_ids(NULL) |
| , m_number_of_gs(5 /*taken from test spec*/) |
| , m_po_ids(NULL) |
| , m_vs_id(0) |
| , m_vao_id(0) |
| { |
| } |
| |
| /** Deinitializes GLES objects created during the test. */ |
| void GeometryShaderMoreInputVerticesThanAvailableTest::deinit() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| if (m_fs_id != 0) |
| { |
| gl.deleteShader(m_fs_id); |
| m_fs_id = 0; |
| } |
| |
| if (m_gs_ids != 0) |
| { |
| for (glw::GLuint i = 0; i < m_number_of_gs; ++i) |
| { |
| gl.deleteShader(m_gs_ids[i]); |
| m_gs_ids[i] = 0; |
| } |
| |
| delete[] m_gs_ids; |
| m_gs_ids = NULL; |
| } |
| |
| if (m_po_ids != 0) |
| { |
| for (glw::GLuint i = 0; i < m_number_of_gs; ++i) |
| { |
| gl.deleteProgram(m_po_ids[i]); |
| m_po_ids[i] = 0; |
| } |
| |
| delete[] m_po_ids; |
| m_po_ids = NULL; |
| } |
| |
| if (m_vs_id != 0) |
| { |
| gl.deleteShader(m_vs_id); |
| m_vs_id = 0; |
| } |
| |
| if (m_vao_id != 0) |
| { |
| gl.deleteVertexArrays(1, &m_vao_id); |
| m_vao_id = 0; |
| } |
| |
| /* Release base class */ |
| TestCaseBase::deinit(); |
| } |
| |
| /** Executes the test. |
| * |
| * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. |
| * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. |
| * Note the function throws exception should an error occur! |
| **/ |
| tcu::TestNode::IterateResult GeometryShaderMoreInputVerticesThanAvailableTest::iterate() |
| { |
| /* Define 5 Geometry Shaders for purpose of this test. */ |
| const char* gs_code_points = "${VERSION}\n" |
| "${GEOMETRY_SHADER_REQUIRE}\n" |
| "\n" |
| "layout (points) in;\n" |
| "layout (points, max_vertices = 1) out;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = gl_in[1].gl_Position;\n" |
| " EmitVertex();\n" |
| "}\n"; |
| |
| const char* gs_code_lines = "${VERSION}\n" |
| "${GEOMETRY_SHADER_REQUIRE}\n" |
| "\n" |
| "layout (lines) in;\n" |
| "layout (points, max_vertices = 1) out;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = gl_in[2].gl_Position;\n" |
| " EmitVertex();\n" |
| "}\n"; |
| |
| const char* gs_code_lines_adjacency = "${VERSION}\n" |
| "${GEOMETRY_SHADER_REQUIRE}\n" |
| "\n" |
| "layout (lines_adjacency) in;\n" |
| "layout (points, max_vertices = 1) out;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = gl_in[4].gl_Position;\n" |
| " EmitVertex();\n" |
| "}\n"; |
| |
| const char* gs_code_triangles = "${VERSION}\n" |
| "${GEOMETRY_SHADER_REQUIRE}\n" |
| "\n" |
| "layout (triangles) in;\n" |
| "layout (points, max_vertices = 1) out;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = gl_in[3].gl_Position;\n" |
| " EmitVertex();\n" |
| "}\n"; |
| |
| const char* gs_code_triangles_adjacency = "${VERSION}\n" |
| "${GEOMETRY_SHADER_REQUIRE}\n" |
| "\n" |
| "layout (triangles_adjacency) in;\n" |
| "layout (points, max_vertices = 1) out;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = gl_in[6].gl_Position;\n" |
| " EmitVertex();\n" |
| "}\n"; |
| |
| bool has_shader_compilation_failed = true; |
| bool result = true; |
| |
| m_gs_ids = new glw::GLuint[m_number_of_gs]; |
| m_po_ids = new glw::GLuint[m_number_of_gs]; |
| |
| /* This test should only run if EXT_geometry_shader is supported. */ |
| if (!m_is_geometry_shader_extension_supported) |
| { |
| throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); |
| } |
| |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Create program objects & geometry shader objects. */ |
| for (glw::GLuint i = 0; i < m_number_of_gs; ++i) |
| { |
| m_gs_ids[i] = gl.createShader(GL_GEOMETRY_SHADER); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); |
| |
| m_po_ids[i] = gl.createProgram(); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); |
| } |
| |
| /* Create shader object. */ |
| m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); |
| m_vs_id = gl.createShader(GL_VERTEX_SHADER); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); |
| |
| /* Try to link the test program object */ |
| std::string fs_code_specialized = specializeShader(1, &dummy_fs_code); |
| const char* fs_code_specialized_raw = fs_code_specialized.c_str(); |
| |
| std::string gs_codes_specialized[] = { specializeShader(1, &gs_code_points), specializeShader(1, &gs_code_lines), |
| specializeShader(1, &gs_code_lines_adjacency), |
| specializeShader(1, &gs_code_triangles), |
| specializeShader(1, &gs_code_triangles_adjacency) }; |
| |
| const char* gs_codes_specialized_raw[] = { gs_codes_specialized[0].c_str(), gs_codes_specialized[1].c_str(), |
| gs_codes_specialized[2].c_str(), gs_codes_specialized[3].c_str(), |
| gs_codes_specialized[4].c_str() }; |
| |
| std::string vs_code_specialized = specializeShader(1, &dummy_vs_code); |
| const char* vs_code_specialized_raw = vs_code_specialized.c_str(); |
| |
| for (glw::GLuint i = 0; i < m_number_of_gs; ++i) |
| { |
| if (TestCaseBase::buildProgram(m_po_ids[i], m_fs_id, 1, /* n_sh1_body_parts */ |
| &fs_code_specialized_raw, m_gs_ids[i], 1, /* n_sh2_body_parts */ |
| &gs_codes_specialized_raw[i], m_vs_id, 1, /* n_sh3_body_parts */ |
| &vs_code_specialized_raw, &has_shader_compilation_failed)) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking successful for i = " |
| << "[" << i << "], whereas a failure was expected." << tcu::TestLog::EndMessage; |
| |
| result = false; |
| break; |
| } |
| } |
| |
| if (result) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| |
| return STOP; |
| } |
| |
| /** Constructor |
| * |
| * @param context Test context |
| * @param extParams Not used. |
| * @param name Test case's name |
| * @param description Test case's description |
| **/ |
| GeometryShaderTransformFeedbackVertexAndGeometryShaderCaptureTest:: |
| GeometryShaderTransformFeedbackVertexAndGeometryShaderCaptureTest(Context& context, const ExtParameters& extParams, |
| const char* name, const char* description) |
| : TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_vs_id(0) |
| { |
| } |
| |
| /** Deinitializes GLES objects created during the test. */ |
| void GeometryShaderTransformFeedbackVertexAndGeometryShaderCaptureTest::deinit() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| if (m_fs_id != 0) |
| { |
| gl.deleteShader(m_fs_id); |
| m_fs_id = 0; |
| } |
| |
| if (m_gs_id != 0) |
| { |
| gl.deleteShader(m_gs_id); |
| m_gs_id = 0; |
| } |
| |
| if (m_po_id != 0) |
| { |
| gl.deleteProgram(m_po_id); |
| m_po_id = 0; |
| } |
| |
| if (m_vs_id != 0) |
| { |
| gl.deleteShader(m_vs_id); |
| m_vs_id = 0; |
| } |
| |
| /* Release base class */ |
| TestCaseBase::deinit(); |
| } |
| |
| /** Executes the test. |
| * |
| * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. |
| * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. |
| * Note the function throws exception should an error occur! |
| **/ |
| tcu::TestNode::IterateResult GeometryShaderTransformFeedbackVertexAndGeometryShaderCaptureTest::iterate() |
| { |
| /* Define Geometry Shader for purpose of this test. */ |
| const char* gs_code = |
| "${VERSION}\n" |
| "${GEOMETRY_SHADER_REQUIRE}\n" |
| "\n" |
| "layout (points) in;\n" |
| "layout (points, max_vertices = 1) out;\n" |
| "\n" |
| "in int vertexID;\n" |
| "out vec4 out_gs_1;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " out_gs_1 = vec4(vertexID[0] * 2, vertexID[0] * 2 + 1, vertexID[0] * 2 + 2, vertexID[0] * 2 + 3);\n" |
| " gl_Position = vec4(0, 0, 0, 1);\n" |
| " EmitVertex();\n" |
| "}\n"; |
| |
| /* Define Vertex Shader for purpose of this test. */ |
| const char* vs_code = "${VERSION}\n" |
| "\n" |
| "flat out ivec4 out_vs_1;\n" |
| "flat out int vertexID;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " vertexID = gl_VertexID;\n" |
| " out_vs_1 = ivec4(gl_VertexID, gl_VertexID + 1, gl_VertexID + 2, gl_VertexID + 3);\n" |
| " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n" |
| "}\n"; |
| |
| bool has_shader_compilation_failed = true; |
| bool result = true; |
| |
| /* This test should only run if EXT_geometry_shader is supported. */ |
| if (!m_is_geometry_shader_extension_supported) |
| { |
| throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); |
| } |
| |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Create program object. */ |
| m_po_id = gl.createProgram(); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed."); |
| |
| /* Specify output variables to be captured. */ |
| const char* tf_varyings[] = { "out_vs_1", "out_gs_1" }; |
| |
| gl.transformFeedbackVaryings(m_po_id, 2 /*count*/, tf_varyings, GL_INTERLEAVED_ATTRIBS); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed."); |
| |
| /* Create shader objects. */ |
| m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); |
| m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); |
| m_vs_id = gl.createShader(GL_VERTEX_SHADER); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed."); |
| |
| /* Try to link the test program object */ |
| std::string fs_code_specialized = specializeShader(1, &dummy_fs_code); |
| const char* fs_code_specialized_raw = fs_code_specialized.c_str(); |
| |
| std::string gs_code_specialized = specializeShader(1, &gs_code); |
| const char* gs_code_specialized_raw = fs_code_specialized.c_str(); |
| |
| std::string vs_code_specialized = specializeShader(1, &vs_code); |
| const char* vs_code_specialized_raw = vs_code_specialized.c_str(); |
| |
| if (TestCaseBase::buildProgram(m_po_id, m_fs_id, 1, /* n_sh1_body_parts */ |
| &fs_code_specialized_raw, m_gs_id, 1, /* n_sh2_body_parts */ |
| &gs_code_specialized_raw, m_vs_id, 1, /* n_sh3_body_parts */ |
| &vs_code_specialized_raw, &has_shader_compilation_failed)) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "Program object linking successful, whereas a failure was expected." |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| |
| if (result) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| |
| return STOP; |
| } |
| |
| } // namespace glcts |