| /*------------------------------------------------------------------------- |
| * 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 |
| */ /*-------------------------------------------------------------------*/ |
| |
| /** |
| */ /*! |
| * \file gl3cCommonBugsTests.cpp |
| * \brief Short conformance tests which verify functionality which has either |
| * been found to be broken on one publically available driver, or whose |
| * behavior varies between vendors. |
| */ /*-------------------------------------------------------------------*/ |
| |
| #include "gl3cCommonBugsTests.hpp" |
| #include "gluContextInfo.hpp" |
| #include "gluDefs.hpp" |
| #include "gluRenderContext.hpp" |
| #include "glwEnums.hpp" |
| #include "glwFunctions.hpp" |
| #include "tcuTestLog.hpp" |
| |
| #include <cstring> |
| #include <string> |
| #include <vector> |
| |
| #ifndef GL_SPARSE_BUFFER_PAGE_SIZE_ARB |
| #define GL_SPARSE_BUFFER_PAGE_SIZE_ARB 0x82F8 |
| #endif |
| #ifndef GL_SPARSE_STORAGE_BIT_ARB |
| #define GL_SPARSE_STORAGE_BIT_ARB 0x0400 |
| #endif |
| |
| namespace gl3cts |
| { |
| /** Constructor. |
| * |
| * @param context Rendering context |
| * @param name Test name |
| * @param description Test description |
| */ |
| GetProgramivActiveUniformBlockMaxNameLengthTest::GetProgramivActiveUniformBlockMaxNameLengthTest(deqp::Context& context) |
| : TestCase(context, "CommonBug_GetProgramivActiveUniformBlockMaxNameLength", |
| "Verifies GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH pname is recognized by glGetProgramiv()") |
| , m_fs_id(0) |
| , m_po_id(0) |
| , m_vs_id(0) |
| { |
| /* Left blank intentionally */ |
| } |
| |
| /** Tears down any GL objects set up to run the test. */ |
| void GetProgramivActiveUniformBlockMaxNameLengthTest::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_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; |
| } |
| } |
| |
| /** Stub init method */ |
| void GetProgramivActiveUniformBlockMaxNameLengthTest::init() |
| { |
| /* Nothing to do here */ |
| } |
| |
| /** Initializes all GL objects required to run the test */ |
| bool GetProgramivActiveUniformBlockMaxNameLengthTest::initTest() |
| { |
| glw::GLint compile_status = false; |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| glw::GLint link_status = false; |
| bool result = true; |
| |
| const char* fs_body = "#version 140\n" |
| "\n" |
| "uniform data\n" |
| "{\n" |
| " vec4 temp;\n" |
| "};\n" |
| "\n" |
| "out vec4 result;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " result = temp;\n" |
| "}\n"; |
| |
| const char* vs_body = "#version 140\n" |
| "\n" |
| "uniform data2\n" |
| "{\n" |
| " vec4 temp2;\n" |
| "};\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = temp2;\n" |
| "}\n"; |
| |
| m_po_id = gl.createProgram(); |
| m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); |
| m_vs_id = gl.createShader(GL_VERTEX_SHADER); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() / glCreateShader() call(s) failed."); |
| |
| gl.attachShader(m_po_id, m_fs_id); |
| gl.attachShader(m_po_id, m_vs_id); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed."); |
| |
| gl.shaderSource(m_fs_id, 1, /* count */ |
| &fs_body, DE_NULL); /* length */ |
| gl.shaderSource(m_vs_id, 1, /* count */ |
| &vs_body, DE_NULL); /* length */ |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed."); |
| |
| gl.compileShader(m_fs_id); |
| gl.compileShader(m_vs_id); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call(s) failed."); |
| |
| /* Have the shaders compiled successfully? */ |
| const glw::GLuint shader_ids[] = { m_fs_id, m_vs_id }; |
| const unsigned int n_shader_ids = static_cast<unsigned int>(sizeof(shader_ids) / sizeof(shader_ids[0])); |
| |
| for (unsigned int n_shader_id = 0; n_shader_id < n_shader_ids; ++n_shader_id) |
| { |
| gl.getShaderiv(shader_ids[n_shader_id], GL_COMPILE_STATUS, &compile_status); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); |
| |
| if (compile_status != GL_TRUE) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader compilation failure" |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| goto end; |
| } |
| } /* for (all shader IDs) */ |
| |
| /* Link the PO */ |
| gl.linkProgram(m_po_id); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); |
| |
| 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_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linking failure" |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| goto end; |
| } |
| |
| end: |
| return result; |
| } |
| |
| /** Executes test iteration. |
| * |
| * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. |
| */ |
| tcu::TestNode::IterateResult GetProgramivActiveUniformBlockMaxNameLengthTest::iterate() |
| { |
| bool result = true; |
| |
| /* Execute the query */ |
| glw::GLenum error_code = GL_NO_ERROR; |
| const glw::GLint expected_result_value = static_cast<glw::GLint>(strlen("data2") + 1 /* terminator */); |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| glw::GLint result_value = 0; |
| |
| /* Only execute if we're daeling with GL 3.1 or newer.. */ |
| if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 1))) |
| { |
| goto end; |
| } |
| |
| /* Set up the test program object */ |
| if (!initTest()) |
| { |
| result = false; |
| |
| goto end; |
| } |
| |
| gl.getProgramiv(m_po_id, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &result_value); |
| |
| error_code = gl.getError(); |
| |
| if (error_code != GL_NO_ERROR) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "glGetIntegerv() generated error [" << error_code |
| << "] for GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH" << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| else if (result_value != expected_result_value) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "glGetIntegerv() returned an invalid value of " << result_value |
| << " instead of the expected value of " << (strlen("data2") + 1 /* terminator */) |
| << " for the GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, " |
| "where the longest uniform block name is data2." |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| end: |
| m_testCtx.setTestResult(result ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, result ? "Pass" : "Fail"); |
| |
| return STOP; |
| } |
| |
| /** Constructor. |
| * |
| * @param context Rendering context |
| * @param name Test name |
| * @param description Test description |
| */ |
| InputVariablesCannotBeModifiedTest::InputVariablesCannotBeModifiedTest(deqp::Context& context) |
| : TestCase(context, "CommonBug_InputVariablesCannotBeModified", "Verifies that input variables cannot be modified.") |
| , m_fs_id(0) |
| , m_gs_id(0) |
| , m_tc_id(0) |
| , m_te_id(0) |
| , m_vs_id(0) |
| { |
| /* Left blank on purpose */ |
| } |
| |
| /** Deinitializes all GL objects created for the purpose of running the test, |
| * as well as any client-side buffers allocated at initialization time |
| */ |
| void InputVariablesCannotBeModifiedTest::deinit() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| glw::GLuint* so_id_ptrs[] = { |
| &m_fs_id, &m_gs_id, &m_tc_id, &m_te_id, &m_vs_id, |
| }; |
| const unsigned int n_so_id_ptrs = static_cast<unsigned int>(sizeof(so_id_ptrs) / sizeof(so_id_ptrs[0])); |
| |
| for (unsigned int n_so_id_ptr = 0; n_so_id_ptr < n_so_id_ptrs; ++n_so_id_ptr) |
| { |
| gl.deleteShader(*so_id_ptrs[n_so_id_ptr]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader() call failed."); |
| |
| *so_id_ptrs[n_so_id_ptr] = 0; |
| } /* for (all created shader objects) */ |
| } |
| |
| /** Empty init function */ |
| void InputVariablesCannotBeModifiedTest::init() |
| { |
| /* Left blank on purpose */ |
| } |
| |
| /** Retrieves a literal corresponding to the test iteration enum. |
| * |
| * @param iteration Enum to retrieve the string for. |
| * |
| * @return Requested object. |
| **/ |
| std::string InputVariablesCannotBeModifiedTest::getIterationName(_test_iteration iteration) const |
| { |
| std::string result; |
| |
| switch (iteration) |
| { |
| case TEST_ITERATION_INPUT_FS_VARIABLE: |
| result = "Fragment shader input variable"; |
| break; |
| case TEST_ITERATION_INPUT_FS_VARIABLE_IN_INPUT_BLOCK: |
| result = "Fragment shader input variable wrapped in an input block"; |
| break; |
| case TEST_ITERATION_INPUT_FS_VARIABLE_PASSED_TO_INOUT_FUNCTION_PARAMETER: |
| result = "Fragment shader input variable passed to an inout function parameter"; |
| break; |
| case TEST_ITERATION_INPUT_FS_VARIABLE_PASSED_TO_OUT_FUNCTION_PARAMETER: |
| result = "Fragment shader input variable passed to an out function parameter"; |
| break; |
| case TEST_ITERATION_INPUT_GS_VARIABLE: |
| result = "Geometry shader input variable"; |
| break; |
| case TEST_ITERATION_INPUT_GS_VARIABLE_IN_INPUT_BLOCK: |
| result = "Geometry shader input variable wrapped in an input block"; |
| break; |
| case TEST_ITERATION_INPUT_GS_VARIABLE_PASSED_TO_INOUT_FUNCTION_PARAMETER: |
| result = "Geometry shader input variable passed to an inout function parameter"; |
| break; |
| case TEST_ITERATION_INPUT_GS_VARIABLE_PASSED_TO_OUT_FUNCTION_PARAMETER: |
| result = "Geometry shader input variable passed to an out function parameter"; |
| break; |
| case TEST_ITERATION_INPUT_TC_VARIABLE_IN_INPUT_BLOCK: |
| result = "Tessellation control shader variable wrapped in an input block"; |
| break; |
| case TEST_ITERATION_INPUT_TC_VARIABLE_PASSED_TO_INOUT_FUNCTION_PARAMETER: |
| result = "Tessellation control shader variable passed to an inout function parameter"; |
| break; |
| case TEST_ITERATION_INPUT_TC_VARIABLE_PASSED_TO_OUT_FUNCTION_PARAMETER: |
| result = "Tessellation control shader variable passed to an out function parameter"; |
| break; |
| case TEST_ITERATION_INPUT_TE_PATCH_VARIABLE: |
| result = "Tessellation evaluation shader patch input variable"; |
| break; |
| case TEST_ITERATION_INPUT_TE_VARIABLE: |
| result = "Tessellation evaluation shader input variable"; |
| break; |
| case TEST_ITERATION_INPUT_TE_VARIABLE_IN_INPUT_BLOCK: |
| result = "Tessellation evaluation shader patch input variable wrapped in an input block"; |
| break; |
| case TEST_ITERATION_INPUT_TE_VARIABLE_PASSED_TO_INOUT_FUNCTION_PARAMETER: |
| result = "Tessellation evlauation shader patch input variable passed to an inout function parameter"; |
| break; |
| case TEST_ITERATION_INPUT_TE_VARIABLE_PASSED_TO_OUT_FUNCTION_PARAMETER: |
| result = "Tessellation evaluation shader patch input variable passed to an out function parameter"; |
| break; |
| case TEST_ITERATION_INPUT_VS_VARIABLE: |
| result = "Vertex shader input variable"; |
| break; |
| case TEST_ITERATION_INPUT_VS_VARIABLE_PASSED_TO_INOUT_FUNCTION_PARAMETER: |
| result = "Vertex shader input variable passed to an inout function parameter"; |
| break; |
| case TEST_ITERATION_INPUT_VS_VARIABLE_PASSED_TO_OUT_FUNCTION_PARAMETER: |
| result = "Vertex shader input variable passed to an out function parameter"; |
| break; |
| |
| default: |
| TCU_FAIL("Unrecognized test iteration type."); |
| } /* switch (iteration) */ |
| |
| return result; |
| } |
| |
| /** Retrieves a vertex shader body for the user-specified iteration enum. |
| * |
| * @param iteration Iteration to retrieve the shader body for. |
| * |
| * @return Requested string object. |
| */ |
| void InputVariablesCannotBeModifiedTest::getIterationData(_test_iteration iteration, |
| glu::ApiType* out_required_min_context_type_ptr, |
| _shader_stage* out_target_shader_stage_ptr, |
| std::string* out_body_ptr) const |
| { |
| switch (iteration) |
| { |
| case TEST_ITERATION_INPUT_FS_VARIABLE: |
| { |
| *out_required_min_context_type_ptr = glu::ApiType::core(3, 1); |
| *out_target_shader_stage_ptr = SHADER_STAGE_FRAGMENT; |
| |
| *out_body_ptr = "#version 140\n" |
| "\n" |
| "in vec4 data;\n" |
| "out vec4 result;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " data += vec4(1.0);\n" |
| " result = data;\n" |
| "}\n"; |
| |
| break; |
| } |
| |
| case TEST_ITERATION_INPUT_FS_VARIABLE_IN_INPUT_BLOCK: |
| { |
| *out_required_min_context_type_ptr = glu::ApiType::core(4, 0); |
| *out_target_shader_stage_ptr = SHADER_STAGE_FRAGMENT; |
| |
| *out_body_ptr = "#version 400\n" |
| "\n" |
| "in inputBlock\n" |
| "{\n" |
| " vec4 data;\n" |
| "};\n" |
| "\n" |
| "out vec4 result;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " data += vec4(1.0);\n" |
| " result = data;\n" |
| "}\n"; |
| |
| break; |
| } |
| |
| case TEST_ITERATION_INPUT_FS_VARIABLE_PASSED_TO_INOUT_FUNCTION_PARAMETER: |
| { |
| *out_required_min_context_type_ptr = glu::ApiType::core(3, 1); |
| *out_target_shader_stage_ptr = SHADER_STAGE_FRAGMENT; |
| |
| *out_body_ptr = "#version 140\n" |
| "\n" |
| "in vec4 data;\n" |
| "out vec4 result;\n" |
| "\n" |
| "void testFunc(inout vec4 arg)\n" |
| "{\n" |
| " arg += vec4(1.0);\n" |
| "}\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " testFunc(data);\n" |
| "\n" |
| " result = data;\n" |
| "}\n"; |
| |
| break; |
| } |
| |
| case TEST_ITERATION_INPUT_FS_VARIABLE_PASSED_TO_OUT_FUNCTION_PARAMETER: |
| { |
| *out_required_min_context_type_ptr = glu::ApiType::core(3, 1); |
| *out_target_shader_stage_ptr = SHADER_STAGE_FRAGMENT; |
| |
| *out_body_ptr = "#version 140\n" |
| "\n" |
| "in vec4 data;\n" |
| "out vec4 result;\n" |
| "\n" |
| "void testFunc(out vec4 arg)\n" |
| "{\n" |
| " arg = vec4(1.0);\n" |
| "}\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " testFunc(data);\n" |
| "\n" |
| " result = data;\n" |
| "}\n"; |
| |
| break; |
| } |
| |
| case TEST_ITERATION_INPUT_GS_VARIABLE: |
| { |
| *out_required_min_context_type_ptr = glu::ApiType::core(3, 2); |
| *out_target_shader_stage_ptr = SHADER_STAGE_GEOMETRY; |
| |
| *out_body_ptr = "#version 150\n" |
| "\n" |
| "layout(points) in;\n" |
| "layout(points, max_vertices = 1) out;\n" |
| "\n" |
| "in vec4 data[];\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " data[0] += vec4(1.0);\n" |
| " gl_Position = data[0];\n" |
| "\n" |
| " EmitVertex();\n" |
| "}\n"; |
| |
| break; |
| } |
| |
| case TEST_ITERATION_INPUT_GS_VARIABLE_IN_INPUT_BLOCK: |
| { |
| *out_required_min_context_type_ptr = glu::ApiType::core(4, 0); |
| *out_target_shader_stage_ptr = SHADER_STAGE_GEOMETRY; |
| |
| *out_body_ptr = "#version 400\n" |
| "\n" |
| "layout(points) in;\n" |
| "layout(points, max_vertices = 1) out;\n" |
| "\n" |
| "in inputBlock\n" |
| "{\n" |
| " vec4 data[];\n" |
| "};\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " data[0] += vec4(1.0);\n" |
| " gl_Position = data[0];\n" |
| "\n" |
| " EmitVertex();\n" |
| "}\n"; |
| |
| break; |
| } |
| |
| case TEST_ITERATION_INPUT_GS_VARIABLE_PASSED_TO_INOUT_FUNCTION_PARAMETER: |
| { |
| *out_required_min_context_type_ptr = glu::ApiType::core(3, 2); |
| *out_target_shader_stage_ptr = SHADER_STAGE_GEOMETRY; |
| |
| *out_body_ptr = "#version 150\n" |
| "\n" |
| "layout(points) in;\n" |
| "layout(points, max_vertices = 1) out;\n" |
| "\n" |
| "in vec4 data[];\n" |
| "\n" |
| "void testFunc(inout vec4 arg)\n" |
| "{\n" |
| " arg += vec4(1.0);\n" |
| "}\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " testFunc(data[0]);\n" |
| "\n" |
| " gl_Position = data[0];\n" |
| "\n" |
| " EmitVertex();\n" |
| "}\n"; |
| |
| break; |
| } |
| |
| case TEST_ITERATION_INPUT_GS_VARIABLE_PASSED_TO_OUT_FUNCTION_PARAMETER: |
| { |
| *out_required_min_context_type_ptr = glu::ApiType::core(3, 2); |
| *out_target_shader_stage_ptr = SHADER_STAGE_GEOMETRY; |
| |
| *out_body_ptr = "#version 150\n" |
| "\n" |
| "layout(points) in;\n" |
| "layout(points, max_vertices = 1) out;\n" |
| "\n" |
| "in vec4 data[];\n" |
| "\n" |
| "void testFunc(out vec4 arg)\n" |
| "{\n" |
| " arg = vec4(1.0);\n" |
| "}\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " testFunc(data[0]);\n" |
| "\n" |
| " gl_Position = data[0];\n" |
| "\n" |
| " EmitVertex();\n" |
| "}\n"; |
| |
| break; |
| } |
| |
| case TEST_ITERATION_INPUT_TC_VARIABLE: |
| { |
| *out_required_min_context_type_ptr = glu::ApiType::core(4, 0); |
| *out_target_shader_stage_ptr = SHADER_STAGE_TESSELLATION_CONTROL; |
| |
| *out_body_ptr = "#version 400\n" |
| "\n" |
| "layout(vertices = 4) out;\n" |
| "\n" |
| "in vec4 data[];\n" |
| "out vec4 result;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " data[0] += vec4(1.0);\n" |
| " result = data[0];\n" |
| "\n" |
| "}\n"; |
| |
| break; |
| } |
| |
| case TEST_ITERATION_INPUT_TC_VARIABLE_IN_INPUT_BLOCK: |
| { |
| *out_required_min_context_type_ptr = glu::ApiType::core(4, 0); |
| *out_target_shader_stage_ptr = SHADER_STAGE_TESSELLATION_CONTROL; |
| |
| *out_body_ptr = "#version 400\n" |
| "\n" |
| "layout(vertices = 4) out;\n" |
| "\n" |
| "in inputBlock\n" |
| "{\n" |
| " vec4 data;\n" |
| "} inData[];\n" |
| "\n" |
| "patch out vec4 result[];\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " inData[0].data += vec4(1.0);\n" |
| " result[gl_InvocationID] = inData[0].data;\n" |
| "\n" |
| " gl_TessLevelInner[0] = 1.0;\n" |
| " gl_TessLevelInner[1] = 1.0;\n" |
| " gl_TessLevelOuter[0] = 1.0;\n" |
| " gl_TessLevelOuter[1] = 1.0;\n" |
| " gl_TessLevelOuter[2] = 1.0;\n" |
| " gl_TessLevelOuter[3] = 1.0;\n" |
| "}\n"; |
| |
| break; |
| } |
| |
| case TEST_ITERATION_INPUT_TC_VARIABLE_PASSED_TO_INOUT_FUNCTION_PARAMETER: |
| { |
| *out_required_min_context_type_ptr = glu::ApiType::core(4, 0); |
| *out_target_shader_stage_ptr = SHADER_STAGE_TESSELLATION_CONTROL; |
| |
| *out_body_ptr = "#version 400\n" |
| "\n" |
| "layout(vertices = 4) out;\n" |
| "\n" |
| "in vec4 data[];\n" |
| "out vec4 result;\n" |
| "\n" |
| "void testFunc(inout vec4 arg)\n" |
| "{\n" |
| " arg += vec4(1.0);\n" |
| "}\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " testFunc(data[0]);\n" |
| "\n" |
| " result = data[0];\n" |
| "\n" |
| "}\n"; |
| |
| break; |
| } |
| |
| case TEST_ITERATION_INPUT_TC_VARIABLE_PASSED_TO_OUT_FUNCTION_PARAMETER: |
| { |
| *out_required_min_context_type_ptr = glu::ApiType::core(4, 0); |
| *out_target_shader_stage_ptr = SHADER_STAGE_TESSELLATION_CONTROL; |
| |
| *out_body_ptr = "#version 400\n" |
| "\n" |
| "layout(vertices = 4) out;\n" |
| "\n" |
| "in vec4 data[];\n" |
| "out vec4 result;\n" |
| "\n" |
| "void testFunc(out vec4 arg)\n" |
| "{\n" |
| " arg = vec4(1.0);\n" |
| "}\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " testFunc(data[0]);\n" |
| "\n" |
| " result = data[0];\n" |
| "\n" |
| "}\n"; |
| |
| break; |
| } |
| |
| case TEST_ITERATION_INPUT_TE_PATCH_VARIABLE: |
| case TEST_ITERATION_INPUT_TE_VARIABLE: |
| { |
| std::stringstream body_sstream; |
| |
| *out_required_min_context_type_ptr = glu::ApiType::core(4, 0); |
| *out_target_shader_stage_ptr = SHADER_STAGE_TESSELLATION_EVALUATION; |
| |
| body_sstream << "#version 400\n" |
| "\n" |
| "layout(triangles) in;\n" |
| "\n" |
| << ((iteration == TEST_ITERATION_INPUT_TE_PATCH_VARIABLE) ? "patch " : "") << "in vec4 data[];\n" |
| << " out vec4 result;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " data[0] += vec4(1.0);\n" |
| " gl_Position = data[0];\n" |
| "}\n"; |
| |
| *out_body_ptr = body_sstream.str(); |
| break; |
| } |
| |
| case TEST_ITERATION_INPUT_TE_VARIABLE_IN_INPUT_BLOCK: |
| { |
| *out_required_min_context_type_ptr = glu::ApiType::core(4, 0); |
| *out_target_shader_stage_ptr = SHADER_STAGE_TESSELLATION_EVALUATION; |
| |
| *out_body_ptr = "#version 400\n" |
| "\n" |
| "layout(triangles) in;\n" |
| "\n" |
| "in inputBlock\n" |
| "{\n" |
| " vec4 data;\n" |
| "} inData[];\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " inData[0].data += vec4(1.0);\n" |
| " gl_Position = inData[0].data;\n" |
| "}\n"; |
| |
| break; |
| } |
| |
| case TEST_ITERATION_INPUT_TE_VARIABLE_PASSED_TO_INOUT_FUNCTION_PARAMETER: |
| { |
| *out_required_min_context_type_ptr = glu::ApiType::core(4, 0); |
| *out_target_shader_stage_ptr = SHADER_STAGE_TESSELLATION_EVALUATION; |
| |
| *out_body_ptr = "#version 400\n" |
| "\n" |
| "layout(triangles) in;\n" |
| "\n" |
| "in vec4 data[];\n" |
| "out vec4 result;\n" |
| "\n" |
| "void testFunc(inout vec4 arg)\n" |
| "{\n" |
| " arg += vec4(1.0);\n" |
| "}\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " testFunc(data[0]);\n" |
| "\n" |
| " gl_Position = data[0];\n" |
| "}\n"; |
| |
| break; |
| } |
| |
| case TEST_ITERATION_INPUT_TE_VARIABLE_PASSED_TO_OUT_FUNCTION_PARAMETER: |
| { |
| *out_required_min_context_type_ptr = glu::ApiType::core(4, 0); |
| *out_target_shader_stage_ptr = SHADER_STAGE_TESSELLATION_EVALUATION; |
| |
| *out_body_ptr = "#version 400\n" |
| "\n" |
| "layout(triangles) in;\n" |
| "\n" |
| "in vec4 data[];\n" |
| "out vec4 result;\n" |
| "\n" |
| "void testFunc(out vec4 arg)\n" |
| "{\n" |
| " arg = vec4(1.0);\n" |
| "}\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " testFunc(data[0]);\n" |
| "\n" |
| " gl_Position = data[0];\n" |
| "}\n"; |
| |
| break; |
| } |
| |
| case TEST_ITERATION_INPUT_VS_VARIABLE: |
| { |
| *out_required_min_context_type_ptr = glu::ApiType::core(3, 1); |
| *out_target_shader_stage_ptr = SHADER_STAGE_VERTEX; |
| |
| *out_body_ptr = "#version 140\n" |
| "\n" |
| "in vec4 data;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " data += vec4(1.0);\n" |
| " gl_Position = data;\n" |
| "}\n"; |
| |
| break; |
| } |
| |
| case TEST_ITERATION_INPUT_VS_VARIABLE_PASSED_TO_INOUT_FUNCTION_PARAMETER: |
| { |
| *out_required_min_context_type_ptr = glu::ApiType::core(3, 1); |
| *out_target_shader_stage_ptr = SHADER_STAGE_VERTEX; |
| |
| *out_body_ptr = "#version 140\n" |
| "\n" |
| "in vec4 data;\n" |
| "\n" |
| "void testFunc(inout vec4 argument)\n" |
| "{\n" |
| " argument += vec4(1.0);\n" |
| "}\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " testFunc(data);\n" |
| "\n" |
| " gl_Position = data;\n" |
| "}\n"; |
| |
| break; |
| } |
| |
| case TEST_ITERATION_INPUT_VS_VARIABLE_PASSED_TO_OUT_FUNCTION_PARAMETER: |
| { |
| *out_required_min_context_type_ptr = glu::ApiType::core(3, 1); |
| *out_target_shader_stage_ptr = SHADER_STAGE_VERTEX; |
| |
| *out_body_ptr = "#version 140\n" |
| "\n" |
| "in vec4 data;\n" |
| "\n" |
| "void testFunc(out vec4 argument)\n" |
| "{\n" |
| " argument = vec4(1.0);\n" |
| "}\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " testFunc(data);\n" |
| "\n" |
| " gl_Position = data;\n" |
| "}\n"; |
| |
| break; |
| } |
| |
| default: |
| TCU_FAIL("Unrecognized test iteration type"); |
| } /* switch (iteration) */ |
| } |
| |
| /** Executes test iteration. |
| * |
| * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. |
| */ |
| tcu::TestNode::IterateResult InputVariablesCannotBeModifiedTest::iterate() |
| { |
| const glu::ContextType context_type = m_context.getRenderContext().getType(); |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| bool result = true; |
| |
| /* Create shader objects */ |
| if (glu::contextSupports(context_type, glu::ApiType::core(3, 2))) |
| { |
| m_gs_id = gl.createShader(GL_GEOMETRY_SHADER); |
| } |
| |
| if (glu::contextSupports(context_type, glu::ApiType::core(4, 0))) |
| { |
| m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER); |
| m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER); |
| } |
| |
| m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); |
| m_vs_id = gl.createShader(GL_VERTEX_SHADER); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); |
| |
| /* Execute all test iterations.. */ |
| for (int current_iteration = static_cast<int>(TEST_ITERATION_FIRST); |
| current_iteration < static_cast<int>(TEST_ITERATION_COUNT); current_iteration++) |
| { |
| glw::GLint compile_status = GL_FALSE; |
| std::string current_iteration_body; |
| const char* current_iteration_body_raw_ptr = NULL; |
| glu::ApiType current_iteration_min_context_type; |
| _shader_stage current_iteration_shader_stage; |
| glw::GLuint so_id = 0; |
| |
| getIterationData(static_cast<_test_iteration>(current_iteration), ¤t_iteration_min_context_type, |
| ¤t_iteration_shader_stage, ¤t_iteration_body); |
| |
| current_iteration_body_raw_ptr = current_iteration_body.c_str(); |
| |
| /* Determine shader ID for the iteration. If the shader stage is not supported |
| * for the running context, skip it. */ |
| if (!glu::contextSupports(context_type, current_iteration_min_context_type)) |
| { |
| continue; |
| } |
| |
| switch (current_iteration_shader_stage) |
| { |
| case SHADER_STAGE_FRAGMENT: |
| so_id = m_fs_id; |
| break; |
| case SHADER_STAGE_GEOMETRY: |
| so_id = m_gs_id; |
| break; |
| case SHADER_STAGE_TESSELLATION_CONTROL: |
| so_id = m_tc_id; |
| break; |
| case SHADER_STAGE_TESSELLATION_EVALUATION: |
| so_id = m_te_id; |
| break; |
| case SHADER_STAGE_VERTEX: |
| so_id = m_vs_id; |
| break; |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized shader stage type"); |
| } |
| } /* switch (current_iteration_shader_stage) */ |
| |
| DE_ASSERT(so_id != 0); |
| |
| /* Assign the source code to the SO */ |
| gl.shaderSource(so_id, 1, /* count */ |
| ¤t_iteration_body_raw_ptr, DE_NULL); /* length */ |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); |
| |
| /* Try to compile the shader object. */ |
| 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."); |
| |
| char temp[1024]; |
| |
| gl.getShaderInfoLog(so_id, 1024, NULL, temp); |
| |
| if (compile_status == GL_TRUE) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "The following " |
| << getShaderStageName(current_iteration_shader_stage) |
| << " shader, used for test iteration [" |
| << getIterationName(static_cast<_test_iteration>(current_iteration)) |
| << "] " |
| "was compiled successfully, even though it is invalid. Body:" |
| "\n>>\n" |
| << current_iteration_body << "\n<<\n" |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| } /* for (all test iterations) */ |
| |
| m_testCtx.setTestResult(result ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, result ? "Pass" : "Fail"); |
| |
| return STOP; |
| } |
| |
| /** Returns a literal corresponding to the shader stage enum used by the test. |
| * |
| * @param stage Shader stage to use for the query. |
| * |
| * @return Requested string. |
| **/ |
| std::string InputVariablesCannotBeModifiedTest::getShaderStageName(_shader_stage stage) const |
| { |
| std::string result = "?!"; |
| |
| switch (stage) |
| { |
| case SHADER_STAGE_FRAGMENT: |
| result = "fragment shader"; |
| break; |
| case SHADER_STAGE_GEOMETRY: |
| result = "geometry shader"; |
| break; |
| case SHADER_STAGE_TESSELLATION_CONTROL: |
| result = "tessellation control shader"; |
| break; |
| case SHADER_STAGE_TESSELLATION_EVALUATION: |
| result = "tessellation evaluation shader"; |
| break; |
| case SHADER_STAGE_VERTEX: |
| result = "vertex shader"; |
| break; |
| } /* switch (stage) */ |
| |
| return result; |
| } |
| |
| /** Constructor. |
| * |
| * @param context Rendering context |
| * @param name Test name |
| * @param description Test description |
| */ |
| InvalidUseCasesForAllNotFuncsAndExclMarkOpTest::InvalidUseCasesForAllNotFuncsAndExclMarkOpTest(deqp::Context& context) |
| : deqp::TestCase(context, "CommonBug_InvalidUseCasesForAllNotFuncsAndExclMarkOp", |
| "Verifies that ! operator does not accept bvec{2,3,4} arguments, " |
| "all() and not() functions do not accept a bool argument.") |
| , m_vs_id(0) |
| { |
| /* Left blank on purpose */ |
| } |
| |
| /** Deinitializes all GL objects created for the purpose of running the test, |
| * as well as any client-side buffers allocated at initialization time |
| */ |
| void InvalidUseCasesForAllNotFuncsAndExclMarkOpTest::deinit() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| if (m_vs_id != 0) |
| { |
| gl.deleteShader(m_vs_id); |
| |
| m_vs_id = 0; |
| } |
| } |
| |
| /** Empty init function */ |
| void InvalidUseCasesForAllNotFuncsAndExclMarkOpTest::init() |
| { |
| /* Left blank on purpose */ |
| } |
| |
| /** Retrieves a literal corresponding to the test iteration enum. |
| * |
| * @param iteration Enum to retrieve the string for. |
| * |
| * @return Requested object. |
| **/ |
| std::string InvalidUseCasesForAllNotFuncsAndExclMarkOpTest::getIterationName(_test_iteration iteration) const |
| { |
| std::string result; |
| |
| switch (iteration) |
| { |
| case TEST_ITERATION_EXCL_MARK_OP_MUST_NOT_ACCEPT_BVEC2: |
| result = "! operator must not accept bvec2 arg"; |
| break; |
| case TEST_ITERATION_EXCL_MARK_OP_MUST_NOT_ACCEPT_BVEC3: |
| result = "! operator must not accept bvec3 arg"; |
| break; |
| case TEST_ITERATION_EXCL_MARK_OP_MUST_NOT_ACCEPT_BVEC4: |
| result = "! operator must not accept bvec4 arg"; |
| break; |
| case TEST_ITERATION_ALL_FUNC_MUST_NOT_ACCEPT_BOOL: |
| result = "all() function must not accept bool arg"; |
| break; |
| case TEST_ITERATION_NOT_FUNC_MUST_NOT_ACCEPT_BOOL: |
| result = "not() function must not accept bool arg"; |
| break; |
| default: |
| { |
| TCU_FAIL("Unrecognized test iteration type."); |
| } |
| } /* switch (iteration) */ |
| |
| return result; |
| } |
| |
| /** Retrieves a vertex shader body for the user-specified iteration enum. |
| * |
| * @param iteration Iteration to retrieve the shader body for. |
| * |
| * @return Requested string object. |
| */ |
| std::string InvalidUseCasesForAllNotFuncsAndExclMarkOpTest::getShaderBody(_test_iteration iteration) const |
| { |
| std::string result; |
| |
| switch (iteration) |
| { |
| case TEST_ITERATION_EXCL_MARK_OP_MUST_NOT_ACCEPT_BVEC2: |
| case TEST_ITERATION_EXCL_MARK_OP_MUST_NOT_ACCEPT_BVEC3: |
| case TEST_ITERATION_EXCL_MARK_OP_MUST_NOT_ACCEPT_BVEC4: |
| { |
| /* From GL SL spec: |
| * |
| * The logical unary operator not (!). It operates only on a Boolean expression and results in a Boolean |
| * expression. To operate on a vector, use the built-in function not. |
| */ |
| std::stringstream result_sstream; |
| std::string type_string; |
| |
| type_string = (iteration == TEST_ITERATION_EXCL_MARK_OP_MUST_NOT_ACCEPT_BVEC2) ? |
| "bvec2" : |
| (iteration == TEST_ITERATION_EXCL_MARK_OP_MUST_NOT_ACCEPT_BVEC3) ? "bvec3" : "bvec4"; |
| |
| result_sstream << "#version 140\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " if (!" |
| << type_string << "(false))\n" |
| " {\n" |
| " gl_Position = vec4(1.0, 2.0, 3.0, 4.0);\n" |
| " }\n" |
| " else\n" |
| " {\n" |
| " gl_Position = vec4(2.0, 3.0, 4.0, 5.0);\n" |
| " }\n" |
| "}\n"; |
| |
| result = result_sstream.str(); |
| break; |
| } |
| |
| case TEST_ITERATION_ALL_FUNC_MUST_NOT_ACCEPT_BOOL: |
| case TEST_ITERATION_NOT_FUNC_MUST_NOT_ACCEPT_BOOL: |
| { |
| std::string op_string; |
| std::stringstream result_sstream; |
| |
| /* From GLSL spec, all() and not() functions are defined as: |
| * |
| * bool all(bvec x) |
| * bvec not(bvec x) |
| * |
| * where bvec is bvec2, bvec3 or bvec4. |
| */ |
| op_string = (iteration == TEST_ITERATION_ALL_FUNC_MUST_NOT_ACCEPT_BOOL) ? "all" : "not"; |
| |
| result_sstream << "#version 140\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = vec4(" |
| << op_string << "(false, true) ? 1.0 : 2.0);\n" |
| "}\n"; |
| |
| result = result_sstream.str(); |
| break; |
| } |
| |
| default: |
| TCU_FAIL("Unrecognized test iteration type"); |
| } /* switch (iteration) */ |
| |
| return result; |
| } |
| |
| /** Executes test iteration. |
| * |
| * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. |
| */ |
| tcu::TestNode::IterateResult InvalidUseCasesForAllNotFuncsAndExclMarkOpTest::iterate() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| bool result = true; |
| |
| /* Create a vertex shader object */ |
| m_vs_id = gl.createShader(GL_VERTEX_SHADER); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); |
| |
| /* Execute all test iterations.. */ |
| for (int current_iteration = static_cast<int>(TEST_ITERATION_FIRST); |
| current_iteration < static_cast<int>(TEST_ITERATION_COUNT); ++current_iteration) |
| { |
| const std::string body = getShaderBody(static_cast<_test_iteration>(current_iteration)); |
| const char* body_raw_ptr = body.c_str(); |
| glw::GLint compile_status = GL_FALSE; |
| |
| /* Assign the source code to the SO */ |
| gl.shaderSource(m_vs_id, 1, /* count */ |
| &body_raw_ptr, DE_NULL); /* length */ |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); |
| |
| /* Try to compile the shader object. */ |
| gl.compileShader(m_vs_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); |
| |
| gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); |
| |
| if (compile_status == GL_TRUE) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "The following vertex shader, used for test iteration [" |
| << getIterationName(static_cast<_test_iteration>(current_iteration)) |
| << "] " |
| "was compiled successfully, even though it is invalid. Body:" |
| "\n>>\n" |
| << body << "\n<<\n" |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| } /* for (all test iterations) */ |
| |
| m_testCtx.setTestResult(result ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, result ? "Pass" : "Fail"); |
| |
| return STOP; |
| } |
| |
| InvalidVSInputsTest::InvalidVSInputsTest(deqp::Context& context) |
| : TestCase(context, "CommonBug_InvalidVSInputs", |
| "Verifies that invalid types, as well as incompatible qualifiers, are " |
| "not accepted for vertex shader input variable declarations") |
| , m_vs_id(0) |
| { |
| /* Left blank on purpose */ |
| } |
| |
| /** Deinitializes all GL objects created for the purpose of running the test, |
| * as well as any client-side buffers allocated at initialization time |
| */ |
| void InvalidVSInputsTest::deinit() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| if (m_vs_id != 0) |
| { |
| gl.deleteShader(m_vs_id); |
| |
| m_vs_id = 0; |
| } |
| } |
| |
| /** Empty init function */ |
| void InvalidVSInputsTest::init() |
| { |
| /* Left blank on purpose */ |
| } |
| |
| /** Retrieves a literal corresponding to the test iteration enum. |
| * |
| * @param iteration Enum to retrieve the string for. |
| * |
| * @return Requested object. |
| **/ |
| std::string InvalidVSInputsTest::getIterationName(_test_iteration iteration) const |
| { |
| std::string result; |
| |
| switch (iteration) |
| { |
| case TEST_ITERATION_INVALID_BOOL_INPUT: |
| result = "Invalid bool input"; |
| break; |
| case TEST_ITERATION_INVALID_BVEC2_INPUT: |
| result = "Invalid bvec2 input"; |
| break; |
| case TEST_ITERATION_INVALID_BVEC3_INPUT: |
| result = "Invalid bvec3 input"; |
| break; |
| case TEST_ITERATION_INVALID_BVEC4_INPUT: |
| result = "Invalid bvec4 input"; |
| break; |
| case TEST_ITERATION_INVALID_CENTROID_QUALIFIED_INPUT: |
| result = "Invalid centroid-qualified input"; |
| break; |
| case TEST_ITERATION_INVALID_PATCH_QUALIFIED_INPUT: |
| result = "Invalid patch-qualified input"; |
| break; |
| case TEST_ITERATION_INVALID_OPAQUE_TYPE_INPUT: |
| result = "Invalid opaque type input"; |
| break; |
| case TEST_ITERATION_INVALID_STRUCTURE_INPUT: |
| result = "Invalid structure input"; |
| break; |
| case TEST_ITERATION_INVALID_SAMPLE_QUALIFIED_INPUT: |
| result = "Invalid sample-qualified input"; |
| break; |
| |
| default: |
| TCU_FAIL("Unrecognized test iteration type."); |
| } /* switch (iteration) */ |
| |
| return result; |
| } |
| |
| /** Retrieves a vertex shader body for the user-specified iteration enum. |
| * |
| * @param iteration Iteration to retrieve the shader body for. |
| * |
| * @return Requested string object. |
| */ |
| std::string InvalidVSInputsTest::getShaderBody(_test_iteration iteration) const |
| { |
| std::string result; |
| |
| switch (iteration) |
| { |
| case TEST_ITERATION_INVALID_BOOL_INPUT: |
| case TEST_ITERATION_INVALID_BVEC2_INPUT: |
| case TEST_ITERATION_INVALID_BVEC3_INPUT: |
| case TEST_ITERATION_INVALID_BVEC4_INPUT: |
| { |
| std::stringstream body_sstream; |
| const char* type = (iteration == TEST_ITERATION_INVALID_BOOL_INPUT) ? |
| "bool" : |
| (iteration == TEST_ITERATION_INVALID_BVEC2_INPUT) ? |
| "bvec2" : |
| (iteration == TEST_ITERATION_INVALID_BVEC3_INPUT) ? "bvec3" : "bvec4"; |
| |
| body_sstream << "#version 140\n" |
| "\n" |
| "in " |
| << type << " data;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| "}\n"; |
| |
| result = body_sstream.str(); |
| break; |
| } |
| |
| case TEST_ITERATION_INVALID_OPAQUE_TYPE_INPUT: |
| { |
| result = "#version 140\n" |
| "\n" |
| "in sampler2D data;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| "}\n"; |
| |
| break; |
| } |
| |
| case TEST_ITERATION_INVALID_STRUCTURE_INPUT: |
| { |
| result = "#version 140\n" |
| "\n" |
| "in struct\n" |
| "{\n" |
| " vec4 test;\n" |
| "} data;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| "}\n"; |
| |
| break; |
| } |
| |
| case TEST_ITERATION_INVALID_CENTROID_QUALIFIED_INPUT: |
| case TEST_ITERATION_INVALID_PATCH_QUALIFIED_INPUT: |
| case TEST_ITERATION_INVALID_SAMPLE_QUALIFIED_INPUT: |
| { |
| std::stringstream body_sstream; |
| const char* qualifier = (iteration == TEST_ITERATION_INVALID_CENTROID_QUALIFIED_INPUT) ? |
| "centroid" : |
| (iteration == TEST_ITERATION_INVALID_PATCH_QUALIFIED_INPUT) ? "patch" : "sample"; |
| |
| body_sstream << "#version 140\n" |
| "\n" |
| << qualifier << " in vec4 data;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| "}\n"; |
| |
| result = body_sstream.str(); |
| break; |
| } |
| |
| default: |
| TCU_FAIL("Unrecognized test iteration type"); |
| } /* switch (iteration) */ |
| |
| return result; |
| } |
| |
| /** Executes test iteration. |
| * |
| * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. |
| */ |
| tcu::TestNode::IterateResult InvalidVSInputsTest::iterate() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| bool result = true; |
| |
| /* Create a vertex shader object */ |
| m_vs_id = gl.createShader(GL_VERTEX_SHADER); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); |
| |
| /* Execute all test iterations.. */ |
| for (int current_iteration = static_cast<int>(TEST_ITERATION_FIRST); |
| current_iteration < static_cast<int>(TEST_ITERATION_COUNT); current_iteration++) |
| { |
| const std::string body = getShaderBody(static_cast<_test_iteration>(current_iteration)); |
| const char* body_raw_ptr = body.c_str(); |
| glw::GLint compile_status = GL_FALSE; |
| |
| /* Assign the source code to the SO */ |
| gl.shaderSource(m_vs_id, 1, /* count */ |
| &body_raw_ptr, DE_NULL); /* length */ |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); |
| |
| /* Try to compile the shader object. */ |
| gl.compileShader(m_vs_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); |
| |
| gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); |
| |
| if (compile_status == GL_TRUE) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "The following vertex shader, used for test iteration [" |
| << getIterationName(static_cast<_test_iteration>(current_iteration)) |
| << "] " |
| "was compiled successfully, even though it is invalid. Body:" |
| "\n>>\n" |
| << body << "\n<<\n" |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| } /* for (all test iterations) */ |
| |
| m_testCtx.setTestResult(result ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, result ? "Pass" : "Fail"); |
| |
| return STOP; |
| } |
| |
| /** Constructor. |
| * |
| * @param context Rendering context |
| * @param name Test name |
| * @param description Test description |
| */ |
| ParenthesisInLayoutQualifierIntegerValuesTest::ParenthesisInLayoutQualifierIntegerValuesTest(deqp::Context& context) |
| : TestCase(context, "CommonBug_ParenthesisInLayoutQualifierIntegerValue", |
| "Verifies parenthesis are not accepted in compute shaders, prior to GL4.4, " |
| "unless GL_ARB_enhanced_layouts is supported.") |
| , m_cs_id(0) |
| , m_po_id(0) |
| { |
| /* Left blank on purpose */ |
| } |
| |
| /** Deinitializes all GL objects created for the purpose of running the test, |
| * as well as any client-side buffers allocated at initialization time |
| */ |
| void ParenthesisInLayoutQualifierIntegerValuesTest::deinit() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| if (m_cs_id != 0) |
| { |
| gl.deleteShader(m_cs_id); |
| |
| m_cs_id = 0; |
| } |
| |
| if (m_po_id != 0) |
| { |
| gl.deleteProgram(m_po_id); |
| |
| m_po_id = 0; |
| } |
| } |
| |
| /** Empty init function */ |
| void ParenthesisInLayoutQualifierIntegerValuesTest::init() |
| { |
| /* Left blank on purpose */ |
| } |
| |
| /** Executes test iteration. |
| * |
| * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. |
| */ |
| tcu::TestNode::IterateResult ParenthesisInLayoutQualifierIntegerValuesTest::iterate() |
| { |
| /* Only execute the test on implementations supporting GL_ARB_compute_shader */ |
| const glu::ContextType context_type = m_context.getRenderContext().getType(); |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| bool result = true; |
| |
| glw::GLint link_status = GL_TRUE; |
| glw::GLint compile_status = GL_TRUE; |
| bool expected_outcome = glu::contextSupports(context_type, glu::ApiType::core(4, 4)); |
| |
| /* Prepare a compute shader program */ |
| static const char* cs_body_core = "\n" |
| "layout(local_size_x = (4) ) in;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| "}\n"; |
| |
| const char* cs_body_parts[] = { (!glu::contextSupports(context_type, glu::ApiType::core(4, 3))) ? |
| "#version 420 core\n" |
| "#extension GL_ARB_compute_shader : enable\n" : |
| (!glu::contextSupports(context_type, glu::ApiType::core(4, 4))) ? |
| "#version 430 core\n" : |
| "#version 440 core\n", |
| cs_body_core }; |
| const unsigned int n_cs_body_parts = |
| static_cast<unsigned int>(sizeof(cs_body_parts) / sizeof(cs_body_parts[0])); |
| |
| if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) |
| { |
| goto end; |
| } |
| |
| m_cs_id = gl.createShader(GL_COMPUTE_SHADER); |
| m_po_id = gl.createProgram(); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() and/or glCraeteProgram() call(s) failed."); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); |
| |
| gl.shaderSource(m_cs_id, n_cs_body_parts, cs_body_parts, DE_NULL); /* length */ |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); |
| |
| /* Try to compile the shader object. |
| * |
| * For GL contexts BEFORE 4.40, the test passes if either |
| * the compilation or the linking process fails. |
| * |
| * For GL contexts OF VERSION 4.40 or newer, the test passes |
| * if both the compilation and the linking process succeed. |
| * |
| * If GL_ARB_enhanced_layouts is supported, the latter holds for <= GL4.4 contexts. |
| **/ |
| if (m_context.getContextInfo().isExtensionSupported("GL_ARB_enhanced_layouts")) |
| { |
| expected_outcome = true; |
| } |
| |
| gl.compileShader(m_cs_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); |
| |
| gl.getShaderiv(m_cs_id, GL_COMPILE_STATUS, &compile_status); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); |
| |
| if (compile_status == GL_FALSE && !expected_outcome) |
| { |
| goto end; |
| } |
| |
| gl.attachShader(m_po_id, m_cs_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed."); |
| |
| gl.linkProgram(m_po_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); |
| |
| gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); |
| |
| if (link_status == GL_FALSE && !expected_outcome) |
| { |
| goto end; |
| } |
| |
| if (expected_outcome && (compile_status == GL_FALSE || link_status == GL_FALSE)) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "A compute program was expected to link successfully, but either the " |
| "compilation and/or linking process has/have failed" |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| else if (!expected_outcome && (compile_status == GL_TRUE && link_status == GL_TRUE)) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "A compute program was expected not to compile and link, but both processes " |
| "have been executed successfully." |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| |
| end: |
| m_testCtx.setTestResult(result ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, result ? "Pass" : "Fail"); |
| |
| return STOP; |
| } |
| |
| /** Constructor. |
| * |
| * @param context Rendering context |
| * @param name Test name |
| * @param description Test description |
| */ |
| PerVertexValidationTest::PerVertexValidationTest(deqp::Context& context) |
| : TestCase(context, "CommonBug_PerVertexValidation", |
| "Conformance test which verifies that various requirements regarding gl_PerVertex block re-declarations," |
| " as described by the spec, are followed by the implementation") |
| , m_fs_id(0) |
| , m_fs_po_id(0) |
| , m_gs_id(0) |
| , m_gs_po_id(0) |
| , m_pipeline_id(0) |
| , m_tc_id(0) |
| , m_tc_po_id(0) |
| , m_te_id(0) |
| , m_te_po_id(0) |
| , m_vs_id(0) |
| , m_vs_po_id(0) |
| { |
| /* Left blank on purpose */ |
| } |
| |
| /** Deinitializes all GL objects created for the purpose of running the test, |
| * as well as any client-side buffers allocated at initialization time |
| */ |
| void PerVertexValidationTest::deinit() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Release the pipeline object */ |
| if (m_pipeline_id != 0) |
| { |
| gl.deleteProgramPipelines(1, &m_pipeline_id); |
| |
| m_pipeline_id = 0; |
| } |
| |
| /* Release all dangling shader and shader program objects */ |
| destroyPOsAndSOs(); |
| } |
| |
| /** Releases any allocated program and shader objects. */ |
| void PerVertexValidationTest::destroyPOsAndSOs() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| glw::GLuint* po_id_ptrs[] = { &m_fs_po_id, &m_gs_po_id, &m_tc_po_id, &m_te_po_id, &m_vs_po_id }; |
| glw::GLuint* so_id_ptrs[] = { &m_fs_id, &m_gs_id, &m_tc_id, &m_te_id, &m_vs_id }; |
| const unsigned int n_po_id_ptrs = static_cast<unsigned int>(sizeof(po_id_ptrs) / sizeof(po_id_ptrs[0])); |
| const unsigned int n_so_id_ptrs = static_cast<unsigned int>(sizeof(so_id_ptrs) / sizeof(so_id_ptrs[0])); |
| |
| for (unsigned int n_po_id = 0; n_po_id < n_po_id_ptrs; ++n_po_id) |
| { |
| glw::GLuint* po_id_ptr = po_id_ptrs[n_po_id]; |
| |
| if (*po_id_ptr != 0) |
| { |
| gl.deleteProgram(*po_id_ptr); |
| |
| *po_id_ptr = 0; |
| } |
| } /* for (all shader program object ids) */ |
| |
| for (unsigned int n_so_id = 0; n_so_id < n_so_id_ptrs; ++n_so_id) |
| { |
| glw::GLuint* so_id_ptr = so_id_ptrs[n_so_id]; |
| |
| if (*so_id_ptr != 0) |
| { |
| gl.deleteShader(*so_id_ptr); |
| |
| *so_id_ptr = 0; |
| } |
| } /* for (all shader object ids) */ |
| } |
| |
| /** Tells whether the program pipeline validation process should fail for specified test iteration. |
| * |
| * @return VALIDATION_RESULT_TRUE if the pipeline validation process should be positive, |
| * VALIDATION_RESULT_FALSE if the validation should be negative |
| * VALIDATION_RESULT_UNDEFINED when the validation result is not defined */ |
| PerVertexValidationTest::_validation PerVertexValidationTest::getProgramPipelineValidationExpectedResult(void) const |
| { |
| /** All "undeclared in.." and "undeclared out.." test shaders are expected not to link successfully |
| * when used as separate programs - which leaves pipeline in undefined state. |
| * All "declaration mismatch" shaders should link, but the results are undefined. |
| * |
| * Currently the test does not exercise any defined case |
| */ |
| return VALIDATION_RESULT_UNDEFINED; |
| } |
| |
| /** Returns a literal corresponding to the shader stage enum. |
| * |
| * @param shader_stage Enum to return the string for. |
| * |
| * @return As per description. |
| */ |
| std::string PerVertexValidationTest::getShaderStageName(_shader_stage shader_stage) const |
| { |
| std::string result = "?!"; |
| |
| switch (shader_stage) |
| { |
| case SHADER_STAGE_FRAGMENT: |
| result = "fragment shader"; |
| break; |
| case SHADER_STAGE_GEOMETRY: |
| result = "geometry shader"; |
| break; |
| case SHADER_STAGE_TESSELLATION_CONTROL: |
| result = "tessellation control shader"; |
| break; |
| case SHADER_STAGE_TESSELLATION_EVALUATION: |
| result = "tessellation evaluation shader"; |
| break; |
| case SHADER_STAGE_VERTEX: |
| result = "vertex shader"; |
| break; |
| } |
| |
| return result; |
| } |
| |
| /** Returns a literal corresponding to the test iteration enum. |
| * |
| * @param iteration Enum to return the string for. |
| * |
| * @return As per description. |
| **/ |
| std::string PerVertexValidationTest::getTestIterationName(_test_iteration iteration) const |
| { |
| std::string result = "?!"; |
| |
| switch (iteration) |
| { |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_CLIPDISTANCE_USAGE: |
| result = "Input gl_ClipDistance usage in Geometry Shader without gl_PerVertex block redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_CULLDISTANCE_USAGE: |
| result = "Input gl_CullDistance usage in Geometry Shader without gl_PerVertex block redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_POINTSIZE_USAGE: |
| result = "Input gl_PointSize usage in a separable Geometry Shader without gl_PerVertex block redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_POSITION_USAGE: |
| result = "Input gl_Position usage in a separable Geometry Shader without gl_PerVertex block redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TC_GL_CLIPDISTANCE_USAGE: |
| result = "Input gl_ClipDistance usage in a separable Tessellation Control Shader without gl_PerVertex block " |
| "redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TC_GL_CULLDISTANCE_USAGE: |
| result = "Input gl_CullDistance usage in a separable Tessellation Control Shader without gl_PerVertex block " |
| "redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TC_GL_POINTSIZE_USAGE: |
| result = "Input gl_PointSize usage in a separable Tessellation Control Shader without gl_PerVertex block " |
| "redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TC_GL_POSITION_USAGE: |
| result = "Input gl_Position usage in a separable Tessellation Control Shader without gl_PerVertex block " |
| "redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TE_GL_CLIPDISTANCE_USAGE: |
| result = "Input gl_ClipDistance usage in a separable Tessellation Evaluation Shader without gl_PerVertex block " |
| "redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TE_GL_CULLDISTANCE_USAGE: |
| result = "Input gl_CullDistance usage in a separable Tessellation Evaluation Shader without gl_PerVertex block " |
| "redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TE_GL_POINTSIZE_USAGE: |
| result = "Input gl_PointSize usage in a separable Tessellation Evaluation Shader without gl_PerVertex block " |
| "redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TE_GL_POSITION_USAGE: |
| result = "Input gl_Position usage in a separable Tessellation Evaluation Shader without gl_PerVertex block " |
| "redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_CLIPDISTANCE_USAGE: |
| result = "Output gl_ClipDistance usage in Geometry Shader without gl_PerVertex block redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_CULLDISTANCE_USAGE: |
| result = "Output gl_CullDistance usage in Geometry Shader without gl_PerVertex block redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_POINTSIZE_USAGE: |
| result = "Output gl_PointSize usage in a separable Geometry Shader without gl_PerVertex block redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_POSITION_USAGE: |
| result = "Output gl_Position usage in a separable Geometry Shader without gl_PerVertex block redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TC_GL_CLIPDISTANCE_USAGE: |
| result = "Output gl_ClipDistance usage in a separable Tessellation Control Shader without gl_PerVertex block " |
| "redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TC_GL_CULLDISTANCE_USAGE: |
| result = "Output gl_CullDistance usage in a separable Tessellation Control Shader without gl_PerVertex block " |
| "redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TC_GL_POINTSIZE_USAGE: |
| result = "Output gl_PointSize usage in a separable Tessellation Control Shader without gl_PerVertex block " |
| "redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TC_GL_POSITION_USAGE: |
| result = "Output gl_Position usage in a separable Tessellation Control Shader without gl_PerVertex block " |
| "redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TE_GL_CLIPDISTANCE_USAGE: |
| result = "Output gl_ClipDistance usage in a separable Tessellation Evaluation Shader without gl_PerVertex " |
| "block redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TE_GL_CULLDISTANCE_USAGE: |
| result = "Output gl_CullDistance usage in a separable Tessellation Evaluation Shader without gl_PerVertex " |
| "block redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TE_GL_POINTSIZE_USAGE: |
| result = "Output gl_PointSize usage in a separable Tessellation Evaluation Shader without gl_PerVertex block " |
| "redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TE_GL_POSITION_USAGE: |
| result = "Output gl_Position usage in a separable Tessellation Evaluation Shader without gl_PerVertex block " |
| "redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_VS_GL_CLIPDISTANCE_USAGE: |
| result = "Output gl_ClipDistance usage in a separable Vertex Shader without gl_PerVertex block redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_VS_GL_CULLDISTANCE_USAGE: |
| result = "Output gl_CullDistance usage in a separable Vertex Shader without gl_PerVertex block redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_VS_GL_POINTSIZE_USAGE: |
| result = "Output gl_PointSize usage in a separable Vertex Shader without gl_PerVertex block redeclaration"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_VS_GL_POSITION_USAGE: |
| result = "Output gl_Position usage in a separable Vertex Shader without gl_PerVertex block redeclaration"; |
| break; |
| |
| case TEST_ITERATION_PERVERTEX_DECLARATION_MISMATCH_GS_VS: |
| result = "Geometry and Vertex Shaders use different gl_PerVertex block redeclaration"; |
| break; |
| case TEST_ITERATION_PERVERTEX_DECLARATION_MISMATCH_GS_TC_TE_VS: |
| result = "Geometry, Tessellation Control, Tessellation Evaluation and Vertex Shaders use a different " |
| "gl_PerVertex block redeclaration"; |
| break; |
| case TEST_ITERATION_PERVERTEX_DECLARATION_MISMATCH_TC_TE_VS: |
| result = "Tesselation Control, Tessellation Evaluation and Vertex Shaders use a different gl_PerVertex block " |
| "redeclaration"; |
| break; |
| |
| case TEST_ITERATION_PERVERTEX_BLOCK_UNDEFINED: |
| result = "No gl_PerVertex block defined in shader programs for all shader stages supported by the running " |
| "context"; |
| break; |
| default: |
| result = "Unknown"; |
| break; |
| } |
| |
| return result; |
| } |
| |
| /** Returns shader bodies, minimum context type and a bitfield describing shader stages used for the |
| * user-specified test iteration enum. |
| * |
| * @param context_type Running context's type. |
| * @param iteration Test iteration enum to return the properties for. |
| * @param out_min_context_type_ptr Deref will be set to the minimum context type supported by the |
| * specified test iteration. |
| * @param out_used_shader_stages_ptr Deref will be set to a combination of _shader_stage enum values, |
| * describing which shader stages are used by the test iteration. |
| * @param out_gs_body_ptr Deref will be updated with the geometry shader body, if used by the |
| * test iteration. |
| * @param out_tc_body_ptr Deref will be updated with the tessellation control shader body, if |
| * used by the test iteration. |
| * @param out_te_body_ptr Deref will be updated with the tessellation evaluation shader body, if |
| * used by the test iteration. |
| * @param out_vs_body_ptr Deref will be updated with the vertex shader body, if used by the |
| * test iteration. |
| * |
| */ |
| void PerVertexValidationTest::getTestIterationProperties(glu::ContextType context_type, _test_iteration iteration, |
| glu::ContextType* out_min_context_type_ptr, |
| _shader_stage* out_used_shader_stages_ptr, |
| std::string* out_gs_body_ptr, std::string* out_tc_body_ptr, |
| std::string* out_te_body_ptr, |
| std::string* out_vs_body_ptr) const |
| { |
| const bool include_cull_distance = glu::contextSupports(context_type, glu::ApiType::core(4, 5)); |
| |
| switch (iteration) |
| { |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_CLIPDISTANCE_USAGE: |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_CULLDISTANCE_USAGE: |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_POINTSIZE_USAGE: |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_POSITION_USAGE: |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_CLIPDISTANCE_USAGE: |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_CULLDISTANCE_USAGE: |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_POINTSIZE_USAGE: |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_POSITION_USAGE: |
| { |
| const bool is_cull_distance_iteration = |
| (iteration == TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_CULLDISTANCE_USAGE || |
| iteration == TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_CULLDISTANCE_USAGE); |
| std::stringstream gs_body_sstream; |
| |
| *out_min_context_type_ptr = (is_cull_distance_iteration) ? glu::ContextType(4, 5, glu::PROFILE_CORE) : |
| glu::ContextType(4, 1, glu::PROFILE_CORE); |
| *out_used_shader_stages_ptr = (_shader_stage)(SHADER_STAGE_GEOMETRY | SHADER_STAGE_VERTEX); |
| |
| /* Form the geometry shader body */ |
| gs_body_sstream << ((!is_cull_distance_iteration) ? "#version 410\n" : "version 450\n") |
| << "\n" |
| "layout(points) in;\n" |
| "layout(points, max_vertices = 1) out;\n" |
| "\n" |
| "in gl_PerVertex\n" |
| "{\n"; |
| |
| gs_body_sstream << ((iteration != TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_CLIPDISTANCE_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_CLIPDISTANCE_USAGE) ? |
| "float gl_ClipDistance[];\n" : |
| ""); |
| gs_body_sstream << ((iteration != TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_POINTSIZE_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_POINTSIZE_USAGE) ? |
| "float gl_PointSize;\n" : |
| ""); |
| gs_body_sstream << ((iteration != TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_POSITION_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_POSITION_USAGE) ? |
| "vec4 gl_Position;\n" : |
| ""); |
| |
| if (include_cull_distance) |
| { |
| gs_body_sstream << "float gl_CullDistance[];\n"; |
| } |
| |
| gs_body_sstream << "} gl_in[];\n" |
| "\n" |
| "out gl_PerVertex\n" |
| "{\n"; |
| |
| gs_body_sstream << ((iteration != TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_CLIPDISTANCE_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_CLIPDISTANCE_USAGE) ? |
| "float gl_ClipDistance[];\n" : |
| ""); |
| gs_body_sstream << ((iteration != TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_POINTSIZE_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_POINTSIZE_USAGE) ? |
| "float gl_PointSize;\n" : |
| ""); |
| gs_body_sstream << ((iteration != TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_POSITION_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_POSITION_USAGE) ? |
| "vec4 gl_Position;\n" : |
| ""); |
| |
| if (include_cull_distance) |
| { |
| gs_body_sstream << "float gl_CullDistance[];\n"; |
| } |
| |
| gs_body_sstream << "};\n" |
| "\n" |
| "void main()\n" |
| "{\n"; |
| |
| switch (iteration) |
| { |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_CLIPDISTANCE_USAGE: |
| gs_body_sstream << "gl_Position = vec4(gl_in[0].gl_ClipDistance[0]);\n"; |
| break; |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_CULLDISTANCE_USAGE: |
| gs_body_sstream << "gl_Position = vec4(gl_in[0].gl_CullDistance[0]);\n"; |
| break; |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_POINTSIZE_USAGE: |
| gs_body_sstream << "gl_Position = vec4(gl_in[0].gl_PointSize);\n"; |
| break; |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_POSITION_USAGE: |
| gs_body_sstream << "gl_Position = gl_in[0].gl_Position;\n"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_CLIPDISTANCE_USAGE: |
| gs_body_sstream << "gl_ClipDistance[0] = gl_in[0].gl_Position.x;\n"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_CULLDISTANCE_USAGE: |
| gs_body_sstream << "gl_CullDistance[0] = gl_in[0].gl_Position.x;\n"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_POINTSIZE_USAGE: |
| gs_body_sstream << "gl_PointSize = gl_in[0].gl_Position.x;\n"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_POSITION_USAGE: |
| gs_body_sstream << "gl_Position = vec4(gl_in[0].gl_PointSize);\n"; |
| break; |
| default: |
| gs_body_sstream << "\n"; |
| break; |
| } /* switch (iteration) */ |
| |
| gs_body_sstream << " EmitVertex();\n" |
| "}\n"; |
| |
| /* Store geometry & vertex shader bodies */ |
| *out_gs_body_ptr = gs_body_sstream.str(); |
| *out_vs_body_ptr = getVertexShaderBody(context_type, iteration); |
| |
| break; |
| } |
| |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TC_GL_CLIPDISTANCE_USAGE: |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TC_GL_CULLDISTANCE_USAGE: |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TC_GL_POINTSIZE_USAGE: |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TC_GL_POSITION_USAGE: |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TE_GL_CLIPDISTANCE_USAGE: |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TE_GL_CULLDISTANCE_USAGE: |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TE_GL_POINTSIZE_USAGE: |
| case TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TE_GL_POSITION_USAGE: |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TC_GL_CLIPDISTANCE_USAGE: |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TC_GL_CULLDISTANCE_USAGE: |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TC_GL_POINTSIZE_USAGE: |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TC_GL_POSITION_USAGE: |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TE_GL_CLIPDISTANCE_USAGE: |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TE_GL_CULLDISTANCE_USAGE: |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TE_GL_POINTSIZE_USAGE: |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TE_GL_POSITION_USAGE: |
| { |
| std::stringstream tc_sstream; |
| std::stringstream te_sstream; |
| |
| const bool is_clip_distance_iteration = |
| (iteration == TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TC_GL_CLIPDISTANCE_USAGE || |
| iteration == TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TE_GL_CLIPDISTANCE_USAGE || |
| iteration == TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TC_GL_CLIPDISTANCE_USAGE || |
| iteration == TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TE_GL_CLIPDISTANCE_USAGE); |
| const bool is_cull_distance_iteration = |
| (iteration == TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TC_GL_CULLDISTANCE_USAGE || |
| iteration == TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TE_GL_CULLDISTANCE_USAGE || |
| iteration == TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TC_GL_CULLDISTANCE_USAGE || |
| iteration == TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TE_GL_CULLDISTANCE_USAGE); |
| const bool is_pointsize_iteration = |
| (iteration == TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TC_GL_POINTSIZE_USAGE || |
| iteration == TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TE_GL_POINTSIZE_USAGE || |
| iteration == TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TC_GL_POINTSIZE_USAGE || |
| iteration == TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TE_GL_POINTSIZE_USAGE); |
| const bool is_position_iteration = (iteration == TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TC_GL_POSITION_USAGE || |
| iteration == TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TE_GL_POSITION_USAGE || |
| iteration == TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TC_GL_POSITION_USAGE || |
| iteration == TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TE_GL_POSITION_USAGE); |
| |
| *out_min_context_type_ptr = (is_cull_distance_iteration) ? glu::ContextType(4, 5, glu::PROFILE_CORE) : |
| glu::ContextType(4, 0, glu::PROFILE_CORE); |
| *out_used_shader_stages_ptr = (_shader_stage)(SHADER_STAGE_TESSELLATION_CONTROL | |
| SHADER_STAGE_TESSELLATION_EVALUATION | SHADER_STAGE_VERTEX); |
| |
| /* Form tessellation control & tessellation evaluation shader bodies */ |
| for (unsigned int n_iteration = 0; n_iteration < 2; ++n_iteration) |
| { |
| const bool is_tc_stage = (n_iteration == 0); |
| std::stringstream* current_sstream_ptr = (is_tc_stage) ? &tc_sstream : &te_sstream; |
| |
| *current_sstream_ptr << ((is_cull_distance_iteration) ? "#version 450 core\n" : "#version 410\n") << "\n"; |
| |
| if (is_tc_stage) |
| { |
| *current_sstream_ptr << "layout (vertices = 4) out;\n"; |
| } |
| else |
| { |
| *current_sstream_ptr << "layout (isolines) in;\n"; |
| } |
| |
| *current_sstream_ptr << "\n" |
| "in gl_PerVertex\n" |
| "{\n"; |
| |
| if (is_position_iteration) |
| { |
| *current_sstream_ptr << "vec4 gl_Position;\n"; |
| } |
| |
| if (!is_pointsize_iteration) |
| { |
| *current_sstream_ptr << "float gl_PointSize\n"; |
| } |
| |
| if (!is_clip_distance_iteration) |
| { |
| *current_sstream_ptr << "float gl_ClipDistance[];\n"; |
| } |
| |
| if (!is_cull_distance_iteration && include_cull_distance) |
| { |
| *current_sstream_ptr << "float gl_CullDistance[];\n"; |
| } |
| |
| *current_sstream_ptr << "} gl_in[gl_MaxPatchVertices];\n" |
| "\n" |
| "out gl_PerVertex\n" |
| "{\n"; |
| |
| if (!is_position_iteration) |
| { |
| *current_sstream_ptr << "vec4 gl_Position;\n"; |
| } |
| |
| if (!is_pointsize_iteration) |
| { |
| *current_sstream_ptr << "float gl_PointSize\n"; |
| } |
| |
| if (!is_clip_distance_iteration) |
| { |
| *current_sstream_ptr << "float gl_ClipDistance[];\n"; |
| } |
| |
| if (!is_cull_distance_iteration && include_cull_distance) |
| { |
| *current_sstream_ptr << "float gl_CullDistance[];\n"; |
| } |
| |
| if (is_tc_stage) |
| { |
| *current_sstream_ptr << "} gl_out[];\n"; |
| } |
| else |
| { |
| *current_sstream_ptr << "};\n"; |
| } |
| |
| *current_sstream_ptr << "\n" |
| "void main()\n" |
| "{\n"; |
| |
| if (is_tc_stage) |
| { |
| *current_sstream_ptr << "gl_out[gl_InvocationID]."; |
| } |
| |
| if (iteration == TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TC_GL_CLIPDISTANCE_USAGE || |
| iteration == TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TE_GL_CLIPDISTANCE_USAGE) |
| { |
| *current_sstream_ptr << "gl_Position = vec4(gl_in[0].gl_ClipDistance[0]);\n"; |
| } |
| else if (iteration == TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TC_GL_CULLDISTANCE_USAGE || |
| iteration == TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TE_GL_CULLDISTANCE_USAGE) |
| { |
| *current_sstream_ptr << "gl_Position = vec4(gl_in[0].gl_CullDistance[0]);\n"; |
| } |
| else if (iteration == TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TC_GL_POINTSIZE_USAGE || |
| iteration == TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TE_GL_POINTSIZE_USAGE) |
| { |
| *current_sstream_ptr << "gl_Position = vec4(gl_in[0].gl_PointSize);\n"; |
| } |
| else if (iteration == TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TC_GL_POSITION_USAGE || |
| iteration == TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TE_GL_POSITION_USAGE) |
| { |
| *current_sstream_ptr << "gl_Position = gl_in[0].gl_Position;\n"; |
| } |
| else if (iteration == TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TC_GL_CLIPDISTANCE_USAGE || |
| iteration == TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TE_GL_CLIPDISTANCE_USAGE) |
| { |
| *current_sstream_ptr << "gl_ClipDistance[0] = gl_in[0].gl_Position.x;\n"; |
| } |
| else if (iteration == TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TC_GL_CULLDISTANCE_USAGE || |
| iteration == TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TE_GL_CULLDISTANCE_USAGE) |
| { |
| *current_sstream_ptr << "gl_CullDistance[0] = gl_in[0].gl_Position.x;\n"; |
| } |
| else if (iteration == TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TC_GL_POINTSIZE_USAGE || |
| iteration == TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TE_GL_POINTSIZE_USAGE) |
| { |
| *current_sstream_ptr << "gl_PointSize = gl_in[0].gl_Position.x;\n"; |
| } |
| else if (iteration == TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TC_GL_POSITION_USAGE || |
| iteration == TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TE_GL_POSITION_USAGE) |
| { |
| *current_sstream_ptr << "gl_Position = vec4(gl_in[0].gl_PointSize);\n"; |
| } |
| |
| tc_sstream << "}\n"; |
| } /* for (both TC and TE stages) */ |
| |
| /* Store the bodies */ |
| *out_tc_body_ptr = tc_sstream.str(); |
| *out_te_body_ptr = te_sstream.str(); |
| *out_vs_body_ptr = getVertexShaderBody(context_type, iteration); |
| |
| break; |
| } |
| |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_VS_GL_CLIPDISTANCE_USAGE: |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_VS_GL_CULLDISTANCE_USAGE: |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_VS_GL_POINTSIZE_USAGE: |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_VS_GL_POSITION_USAGE: |
| { |
| const bool is_cull_distance_iteration = |
| (iteration == TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_VS_GL_CULLDISTANCE_USAGE); |
| |
| *out_min_context_type_ptr = (is_cull_distance_iteration) ? glu::ContextType(4, 5, glu::PROFILE_CORE) : |
| glu::ContextType(4, 1, glu::PROFILE_CORE); |
| *out_used_shader_stages_ptr = (_shader_stage)(SHADER_STAGE_VERTEX); |
| |
| /* Determine what the main() body contents should be. */ |
| std::string vs_main_body; |
| |
| switch (iteration) |
| { |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_VS_GL_CLIPDISTANCE_USAGE: |
| vs_main_body = "gl_ClipDistance[0] = 1.0;"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_VS_GL_CULLDISTANCE_USAGE: |
| vs_main_body = "gl_CullDistance[0] = 2.0;"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_VS_GL_POINTSIZE_USAGE: |
| vs_main_body = "gl_PointSize = 1.0;"; |
| break; |
| case TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_VS_GL_POSITION_USAGE: |
| vs_main_body = "gl_Position = vec4(1.0f, 2.0, 3.0, 4.0);"; |
| break; |
| default: |
| vs_main_body = ""; |
| break; |
| } |
| |
| /* Store the body */ |
| *out_vs_body_ptr = getVertexShaderBody(context_type, iteration, vs_main_body); |
| |
| break; |
| } |
| |
| case TEST_ITERATION_PERVERTEX_DECLARATION_MISMATCH_GS_VS: |
| case TEST_ITERATION_PERVERTEX_DECLARATION_MISMATCH_GS_TC_TE_VS: |
| case TEST_ITERATION_PERVERTEX_DECLARATION_MISMATCH_TC_TE_VS: |
| { |
| *out_min_context_type_ptr = glu::ContextType(4, 1, glu::PROFILE_CORE); |
| int used_shader_stages = SHADER_STAGE_VERTEX; |
| |
| if (iteration == TEST_ITERATION_PERVERTEX_DECLARATION_MISMATCH_GS_TC_TE_VS || |
| iteration == TEST_ITERATION_PERVERTEX_DECLARATION_MISMATCH_GS_VS) |
| { |
| used_shader_stages |= SHADER_STAGE_GEOMETRY; |
| } |
| |
| if (iteration == TEST_ITERATION_PERVERTEX_DECLARATION_MISMATCH_GS_TC_TE_VS || |
| iteration == TEST_ITERATION_PERVERTEX_DECLARATION_MISMATCH_TC_TE_VS) |
| { |
| used_shader_stages |= |
| SHADER_STAGE_TESSELLATION_CONTROL | SHADER_STAGE_TESSELLATION_EVALUATION; |
| } |
| |
| *out_used_shader_stages_ptr = (_shader_stage) used_shader_stages; |
| |
| /* Shader bodies are predefined in this case. */ |
| *out_gs_body_ptr = "#version 410\n" |
| "\n" |
| "layout (points) in;\n" |
| "layout (points, max_vertices = 4) out;\n" |
| "\n" |
| "in gl_PerVertex\n" |
| "{\n" |
| " float gl_ClipDistance[];\n" |
| "} gl_in[];\n" |
| "\n" |
| "out gl_PerVertex\n" |
| "{\n" |
| " float gl_ClipDistance[];\n" |
| "};\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_ClipDistance[0] = 0.5;\n" |
| " EmitVertex();\n" |
| "}\n"; |
| *out_tc_body_ptr = "#version 410\n" |
| "\n" |
| "layout (vertices = 4) out;\n" |
| "\n" |
| "in gl_PerVertex\n" |
| "{\n" |
| " float gl_PointSize;\n" |
| "} gl_in[];\n" |
| "\n" |
| "out gl_PerVertex\n" |
| "{\n" |
| " float gl_PointSize;\n" |
| "} gl_out[];\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_out[gl_InvocationID].gl_PointSize = gl_in[0].gl_PointSize + 1.0;\n" |
| "}\n"; |
| *out_te_body_ptr = "#version 410\n" |
| "\n" |
| "layout (isolines) in;\n" |
| "\n" |
| "in gl_PerVertex\n" |
| "{\n" |
| " float gl_PointSize;\n" |
| " vec4 gl_Position;\n" |
| "} gl_in[gl_MaxPatchVertices];\n" |
| "\n" |
| "out gl_PerVertex\n" |
| "{\n" |
| " float gl_PointSize;\n" |
| " vec4 gl_Position;\n" |
| "};\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = vec4(gl_in[0].gl_PointSize) + gl_in[1].gl_Position;\n" |
| "}\n"; |
| *out_vs_body_ptr = "#version 410\n" |
| "\n" |
| "out gl_PerVertex\n" |
| "{\n" |
| " vec4 gl_Position;\n" |
| "};\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = vec4(2.0);\n" |
| "}\n"; |
| |
| break; |
| } |
| |
| case TEST_ITERATION_PERVERTEX_BLOCK_UNDEFINED: |
| { |
| *out_min_context_type_ptr = glu::ContextType(4, 1, glu::PROFILE_CORE); |
| int used_shader_stages = SHADER_STAGE_VERTEX; |
| |
| if (glu::contextSupports(context_type, glu::ApiType::core(3, 2))) |
| { |
| used_shader_stages |= SHADER_STAGE_GEOMETRY; |
| } |
| |
| if (glu::contextSupports(context_type, glu::ApiType::core(4, 0))) |
| { |
| used_shader_stages |= |
| SHADER_STAGE_TESSELLATION_CONTROL | SHADER_STAGE_TESSELLATION_EVALUATION; |
| } |
| |
| *out_used_shader_stages_ptr = (_shader_stage) used_shader_stages; |
| |
| *out_gs_body_ptr = "#version 410\n" |
| "\n" |
| "layout (points) in;\n" |
| "layout (points, max_vertices = 4) out;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = vec4(1.0, 2.0, 3.0, 4.0);\n" |
| " EmitVertex();\n" |
| "}\n"; |
| *out_tc_body_ptr = "#version 410\n" |
| "\n" |
| "layout(vertices = 4) out;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" |
| "}\n"; |
| *out_te_body_ptr = "#version 410\n" |
| "\n" |
| "layout (isolines) in;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = gl_in[0].gl_Position;\n" |
| "}\n"; |
| *out_vs_body_ptr = "#version 410\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = vec4(1.0, 2.0, 3.0, 4.0);\n" |
| "}\n"; |
| |
| break; |
| } |
| |
| default: |
| TCU_FAIL("Unrecognized test iteration"); |
| } /* switch (iteration) */ |
| } |
| |
| /** Returns a vertex shader body, with main() entry-point using code passed by |
| * the @param main_body argument. |
| * |
| * @param context_type Running rendering context's type. |
| * @param iteration Test iteration to return the vertex shader body for. |
| * @param main_body Body to use for the main() entry-point. |
| * |
| * @return Requested object. |
| **/ |
| std::string PerVertexValidationTest::getVertexShaderBody(glu::ContextType context_type, _test_iteration iteration, |
| std::string main_body) const |
| { |
| const bool include_clip_distance = (iteration != TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_CLIPDISTANCE_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TC_GL_CLIPDISTANCE_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TE_GL_CLIPDISTANCE_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_CLIPDISTANCE_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TC_GL_CLIPDISTANCE_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TE_GL_CLIPDISTANCE_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_VS_GL_CLIPDISTANCE_USAGE); |
| const bool include_cull_distance = (iteration != TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_CULLDISTANCE_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TC_GL_CULLDISTANCE_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TE_GL_CULLDISTANCE_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_CULLDISTANCE_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TC_GL_CULLDISTANCE_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TE_GL_CULLDISTANCE_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_VS_GL_CULLDISTANCE_USAGE && |
| glu::contextSupports(context_type, glu::ApiType::core(4, 5))); |
| const bool include_pointsize = (iteration != TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_POINTSIZE_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TC_GL_POINTSIZE_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TE_GL_POINTSIZE_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_POINTSIZE_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TC_GL_POINTSIZE_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TE_GL_POINTSIZE_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_VS_GL_POINTSIZE_USAGE); |
| const bool include_position = (iteration != TEST_ITERATION_UNDECLARED_IN_PERVERTEX_GS_GL_POSITION_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TC_GL_POSITION_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_IN_PERVERTEX_TE_GL_POSITION_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_GS_GL_POSITION_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TC_GL_POSITION_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_TE_GL_POSITION_USAGE && |
| iteration != TEST_ITERATION_UNDECLARED_OUT_PERVERTEX_VS_GL_POSITION_USAGE); |
| std::stringstream vs_body_sstream; |
| |
| vs_body_sstream << "#version " << ((include_cull_distance) ? "450" : "410") << "\n" |
| << "\n" |
| "in gl_PerVertex\n" |
| "{\n"; |
| |
| vs_body_sstream << ((include_clip_distance) ? "float gl_ClipDistance[];\n" : ""); |
| vs_body_sstream << ((include_pointsize) ? "float gl_PointSize;\n" : ""); |
| vs_body_sstream << ((include_position) ? "vec4 gl_Position;\n" : ""); |
| vs_body_sstream << ((include_cull_distance) ? "float gl_CullDistance[];\n" : ""); |
| |
| vs_body_sstream << "};\n" |
| "\n" |
| "out gl_PerVertex\n" |
| "{\n"; |
| |
| vs_body_sstream << ((include_clip_distance) ? "float gl_ClipDistance[];\n" : ""); |
| vs_body_sstream << ((include_pointsize) ? "float gl_PointSize;\n" : ""); |
| vs_body_sstream << ((include_position) ? "vec4 gl_Position;\n" : ""); |
| vs_body_sstream << ((include_cull_distance) ? "float gl_CullDistance[];\n" : ""); |
| |
| vs_body_sstream << "};\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " " |
| << main_body << "\n" |
| "}\n"; |
| |
| return vs_body_sstream.str(); |
| } |
| |
| /** Empty init function */ |
| void PerVertexValidationTest::init() |
| { |
| /* Left blank on purpose */ |
| } |
| |
| /** Executes test iteration. |
| * |
| * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. |
| */ |
| tcu::TestNode::IterateResult PerVertexValidationTest::iterate() |
| { |
| const glu::ContextType context_type = m_context.getRenderContext().getType(); |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| bool result = true; |
| |
| /* Separable program objects went into core in GL 4.1 */ |
| if (!glu::contextSupports(context_type, glu::ApiType::core(4, 1))) |
| { |
| throw tcu::NotSupportedError("Test implemented for OpenGL 4.1 contexts or newer."); |
| } |
| |
| /* Each test iteration is going to be executed in two different modes: |
| * |
| * 1) Create separate shader programs for each stage. They should link just fine. |
| * Then create a pipeline and attach to it all the programs. At this stage, the |
| * validation should report failure. |
| * |
| * 2) Create a single separate shader program, holding all stages. Try to link it. |
| * This process should report failure. |
| */ |
| for (int test_iteration = static_cast<int>(TEST_ITERATION_FIRST); |
| test_iteration != static_cast<int>(TEST_ITERATION_COUNT); test_iteration++) |
| { |
| for (unsigned int n_test_mode = 0; n_test_mode < 2; ++n_test_mode) |
| { |
| /* Skip the second iteration if any of the shaders is expected not to compile. */ |
| if (isShaderProgramLinkingFailureExpected(static_cast<_test_iteration>(test_iteration))) |
| { |
| continue; |
| } |
| |
| /* Execute the actual test iteration */ |
| switch (n_test_mode) |
| { |
| case 0: |
| result &= runPipelineObjectValidationTestMode(static_cast<_test_iteration>(test_iteration)); |
| break; |
| case 1: |
| result &= runSeparateShaderTestMode(static_cast<_test_iteration>(test_iteration)); |
| break; |
| } |
| |
| /* Clean up */ |
| destroyPOsAndSOs(); |
| |
| if (m_pipeline_id != 0) |
| { |
| gl.deleteProgramPipelines(1, /* n */ |
| &m_pipeline_id); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgramPipelines() call failed"); |
| } |
| } /* for (both test modes) */ |
| } /* for (all test iterations) */ |
| m_testCtx.setTestResult(result ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, result ? "Pass" : "Fail"); |
| |
| return STOP; |
| } |
| |
| /** Tells whether the linking process should fail for specified test iteration. |
| * |
| * @param iteration Test iteration to query. |
| * |
| * @return true if the linking process should fail, false otherwise */ |
| bool PerVertexValidationTest::isShaderProgramLinkingFailureExpected(_test_iteration iteration) const |
| { |
| /** All "undeclared in.." and "undeclared out.." test shaders are expected not to link successfully |
| * when used as separate programs. |
| * Shaders built as a part of the remaining test iterations should compile and link successfully |
| * for separate programs implementing only a single shader stage. Later on, however, pipeline |
| * objects built of these programs should fail to validate, as they use incompatible gl_PerVertex |
| * block redeclarations. |
| */ |
| return (iteration < TEST_ITERATION_PERVERTEX_DECLARATION_MISMATCH_GS_VS) || |
| iteration == TEST_ITERATION_PERVERTEX_BLOCK_UNDEFINED; |
| } |
| |
| /** Runs the specified test iteration in the following mode: |
| * |
| * >> |
| * A pipeline object is created and shader programs are attached to it. It is expected that validation |
| * should fail. |
| * << |
| * |
| * @param iteration Test iteration to execute. |
| * |
| * @return true if the test passed, false otherwise. |
| */ |
| bool PerVertexValidationTest::runPipelineObjectValidationTestMode(_test_iteration iteration) |
| { |
| const glu::ContextType context_type = m_context.getRenderContext().getType(); |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| bool result = false; |
| |
| const char* body_raw_ptr = NULL; |
| glw::GLenum expected_result = getProgramPipelineValidationExpectedResult(); |
| std::string fs_body; |
| std::string gs_body; |
| glw::GLint link_status; |
| glu::ContextType min_context_type; |
| std::string tc_body; |
| std::string te_body; |
| _shader_stage used_shader_stages; |
| glw::GLint validate_status; |
| glw::GLint validate_expected_status; |
| std::string vs_body; |
| |
| struct _shader_program |
| { |
| std::string* body_ptr; |
| glw::GLuint* po_id_ptr; |
| _shader_stage shader_stage; |
| glw::GLenum shader_stage_bit_gl; |
| glw::GLenum shader_stage_gl; |
| } shader_programs[] = { |
| { &fs_body, &m_fs_po_id, SHADER_STAGE_FRAGMENT, GL_FRAGMENT_SHADER_BIT, GL_FRAGMENT_SHADER }, |
| { &gs_body, &m_gs_po_id, SHADER_STAGE_GEOMETRY, GL_GEOMETRY_SHADER_BIT, GL_GEOMETRY_SHADER }, |
| { &tc_body, &m_tc_po_id, SHADER_STAGE_TESSELLATION_CONTROL, GL_TESS_CONTROL_SHADER_BIT, |
| GL_TESS_CONTROL_SHADER }, |
| { &te_body, &m_te_po_id, SHADER_STAGE_TESSELLATION_EVALUATION, GL_TESS_EVALUATION_SHADER_BIT, |
| GL_TESS_EVALUATION_SHADER }, |
| { &vs_body, &m_vs_po_id, SHADER_STAGE_VERTEX, GL_VERTEX_SHADER_BIT, GL_VERTEX_SHADER }, |
| }; |
| const unsigned int n_shader_programs = |
| static_cast<unsigned int>(sizeof(shader_programs) / sizeof(shader_programs[0])); |
| |
| /* Make sure the test iteration can actually be run under the running rendering context |
| * version. |
| */ |
| getTestIterationProperties(context_type, iteration, &min_context_type, &used_shader_stages, &gs_body, &tc_body, |
| &te_body, &vs_body); |
| |
| if (!glu::contextSupports(context_type, min_context_type.getAPI())) |
| { |
| result = true; |
| |
| goto end; |
| } |
| |
| /* Set up shader program objects. All shader bodies by themselves are valid, so all shaders should |
| * link just fine. */ |
| for (unsigned int n_shader_program = 0; n_shader_program < n_shader_programs; ++n_shader_program) |
| { |
| _shader_program& current_shader_program = shader_programs[n_shader_program]; |
| |
| if ((used_shader_stages & current_shader_program.shader_stage) != 0) |
| { |
| body_raw_ptr = current_shader_program.body_ptr->c_str(); |
| *current_shader_program.po_id_ptr = |
| gl.createShaderProgramv(current_shader_program.shader_stage_gl, 1, /* count */ |
| &body_raw_ptr); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed."); |
| |
| gl.getProgramiv(*current_shader_program.po_id_ptr, GL_LINK_STATUS, &link_status); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); |
| |
| if (link_status != GL_TRUE) |
| { |
| char info_log[4096]; |
| |
| if (!isShaderProgramLinkingFailureExpected(iteration)) |
| { |
| gl.getProgramInfoLog(*current_shader_program.po_id_ptr, sizeof(info_log), DE_NULL, /* length */ |
| info_log); |
| |
| m_testCtx.getLog() << tcu::TestLog::Message << "The separate " |
| << getShaderStageName(current_shader_program.shader_stage) |
| << " program " |
| "failed to link, even though the shader body is valid.\n" |
| "\n" |
| "Body:\n>>\n" |
| << *current_shader_program.body_ptr << "<<\nInfo log\n>>\n" |
| << info_log << "<<\n" |
| << tcu::TestLog::EndMessage; |
| } |
| else |
| { |
| result = true; |
| } |
| |
| goto end; |
| } /* if (link_status != GL_TRUE) */ |
| } /* for (all shader programs) */ |
| } /* for (all shader stages) */ |
| |
| /* Now that all shader programs are ready, set up a test-specific pipeline object and validate it. */ |
| gl.genProgramPipelines(1, &m_pipeline_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed."); |
| |
| gl.bindProgramPipeline(m_pipeline_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed."); |
| |
| for (unsigned int n_shader_program = 0; n_shader_program < n_shader_programs; ++n_shader_program) |
| { |
| _shader_program& current_shader_program = shader_programs[n_shader_program]; |
| |
| if ((used_shader_stages & current_shader_program.shader_stage) != 0) |
| { |
| gl.useProgramStages(m_pipeline_id, current_shader_program.shader_stage_bit_gl, |
| *current_shader_program.po_id_ptr); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed."); |
| } |
| } /* for (all shader programs) */ |
| |
| gl.validateProgramPipeline(m_pipeline_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glValidateProgramPipeline() call failed."); |
| |
| gl.getProgramPipelineiv(m_pipeline_id, GL_VALIDATE_STATUS, &validate_status); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineiv() call failed."); |
| |
| if (VALIDATION_RESULT_UNDEFINED != expected_result) |
| { |
| switch (expected_result) |
| { |
| case VALIDATION_RESULT_FALSE: |
| validate_expected_status = GL_FALSE; |
| break; |
| case VALIDATION_RESULT_TRUE: |
| validate_expected_status = GL_TRUE; |
| break; |
| default: |
| TCU_FAIL("Invalid enum"); |
| } |
| |
| if (validate_status != validate_expected_status) |
| { |
| tcu::MessageBuilder message = m_testCtx.getLog().message(); |
| |
| if (GL_FALSE == validate_expected_status) |
| { |
| message << "A pipeline object was validated successfully, even though one"; |
| } |
| else |
| { |
| message << "A pipeline object was validated negatively, even though none"; |
| } |
| |
| message << " of the failure reasons given by spec was applicable.\n" |
| << "\n" |
| "Fragment shader body:\n>>\n" |
| << ((shader_programs[0].body_ptr->length() > 0) ? *shader_programs[0].body_ptr : "[not used]") |
| << "\n<<\nGeometry shader body:\n>>\n" |
| << ((shader_programs[1].body_ptr->length() > 0) ? *shader_programs[1].body_ptr : "[not used]") |
| << "\n<<\nTessellation control shader body:\n>>\n" |
| << ((shader_programs[2].body_ptr->length() > 0) ? *shader_programs[2].body_ptr : "[not used]") |
| << "\n<<\nTessellation evaluation shader body:\n>>\n" |
| << ((shader_programs[3].body_ptr->length() > 0) ? *shader_programs[3].body_ptr : "[not used]") |
| << "\n<<\nVertex shader body:\n>>\n" |
| << ((shader_programs[4].body_ptr->length() > 0) ? *shader_programs[4].body_ptr : "[not used]") |
| << tcu::TestLog::EndMessage; |
| } /* if (validate_status != validate_expected_status) */ |
| else |
| { |
| result = true; |
| } |
| } |
| else |
| { |
| result = true; |
| } |
| |
| end: |
| return result; |
| } |
| |
| /** Runs the specified test iteration in the following mode: |
| * |
| * >> |
| * A single separate shader program, to which all shader stages used by the test are attached, is linked. |
| * It is expected the linking process should fail. |
| * << |
| * |
| * @param iteration Test iteration to execute. |
| * |
| * @return true if the test passed, false otherwise. |
| */ |
| bool PerVertexValidationTest::runSeparateShaderTestMode(_test_iteration iteration) |
| { |
| glw::GLint compile_status; |
| glu::ContextType context_type = m_context.getRenderContext().getType(); |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| glw::GLint link_status; |
| glu::ContextType min_context_type; |
| bool result = false; |
| _shader_stage used_shader_stages; |
| |
| std::string fs_body; |
| std::string gs_body; |
| std::string tc_body; |
| std::string te_body; |
| std::string vs_body; |
| |
| struct _shader |
| { |
| std::string* body_ptr; |
| glw::GLuint* so_id_ptr; |
| _shader_stage shader_stage; |
| glw::GLenum shader_stage_bit_gl; |
| glw::GLenum shader_stage_gl; |
| } shaders[] = { { &fs_body, &m_fs_id, SHADER_STAGE_FRAGMENT, GL_FRAGMENT_SHADER_BIT, GL_FRAGMENT_SHADER }, |
| { &gs_body, &m_gs_id, SHADER_STAGE_GEOMETRY, GL_GEOMETRY_SHADER_BIT, GL_GEOMETRY_SHADER }, |
| { &tc_body, &m_tc_id, SHADER_STAGE_TESSELLATION_CONTROL, GL_TESS_CONTROL_SHADER_BIT, |
| GL_TESS_CONTROL_SHADER }, |
| { &te_body, &m_te_id, SHADER_STAGE_TESSELLATION_EVALUATION, GL_TESS_EVALUATION_SHADER_BIT, |
| GL_TESS_EVALUATION_SHADER }, |
| { &vs_body, &m_vs_id, SHADER_STAGE_VERTEX, GL_VERTEX_SHADER_BIT, GL_VERTEX_SHADER } }; |
| const unsigned int n_shaders = static_cast<unsigned int>(sizeof(shaders) / sizeof(shaders[0])); |
| |
| /* Retrieve iteration properties */ |
| getTestIterationProperties(context_type, iteration, &min_context_type, &used_shader_stages, &gs_body, &tc_body, |
| &te_body, &vs_body); |
| |
| if (!glu::contextSupports(context_type, min_context_type.getAPI())) |
| { |
| result = true; |
| |
| goto end; |
| } |
| |
| /* Bake a single shader with separate programs defined for all shader stages defined by the iteration |
| * and see what happens. |
| * |
| * For simplicity, we re-use m_vs_po_id to store the program object ID. |
| */ |
| m_vs_po_id = gl.createProgram(); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); |
| |
| for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader) |
| { |
| const char* body_raw_ptr = DE_NULL; |
| const std::string& current_body = *shaders[n_shader].body_ptr; |
| const _shader_stage& current_shader_stage = shaders[n_shader].shader_stage; |
| glw::GLuint& current_so_id = *shaders[n_shader].so_id_ptr; |
| const glw::GLenum& current_so_type_gl = shaders[n_shader].shader_stage_gl; |
| |
| if ((used_shader_stages & current_shader_stage) != 0) |
| { |
| body_raw_ptr = current_body.c_str(); |
| current_so_id = gl.createShader(current_so_type_gl); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); |
| |
| gl.shaderSource(current_so_id, 1, /* count */ |
| &body_raw_ptr, DE_NULL); /* length */ |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); |
| |
| /* Ensure the shader compiled successfully. */ |
| gl.compileShader(current_so_id); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); |
| |
| gl.getShaderiv(current_so_id, GL_COMPILE_STATUS, &compile_status); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); |
| |
| if (compile_status != GL_TRUE) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << getShaderStageName(current_shader_stage) |
| << " unexpectedly failed to compile.\n" |
| "\nBody:\n>>\n" |
| << current_body << "\n<<\n" |
| << tcu::TestLog::EndMessage; |
| |
| goto end; |
| } |
| |
| /* Attach the shader object to the test program object */ |
| gl.attachShader(m_vs_po_id, current_so_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed."); |
| } /* if ((used_shader_stages & current_shader_stage) != 0) */ |
| } /* for (all shader objects) */ |
| |
| /* Mark the program as separable */ |
| gl.programParameteri(m_vs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed."); |
| |
| /* Try to link the program and check the result. */ |
| gl.linkProgram(m_vs_po_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); |
| |
| gl.getProgramiv(m_vs_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 |
| << "Separable program, consisting of the following separate shaders, was linked " |
| "successfully, despite incompatible or missing gl_PerVertex block re-declarations.\n" |
| "\n" |
| "Fragment shader program:\n>>\n" |
| << ((fs_body.length() > 0) ? fs_body : "[not used]") |
| << "\n<<\nGeometry shader program:\n>>\n" |
| << ((gs_body.length() > 0) ? gs_body : "[not used]") |
| << "\n<<\nTessellation control shader program:\n>>\n" |
| << ((tc_body.length() > 0) ? tc_body : "[not used]") |
| << "\n<<\nTessellation evaluation shader program:\n>>\n" |
| << ((te_body.length() > 0) ? te_body : "[not used]") << "\n<<\nVertex shader program:\n>>\n" |
| << ((vs_body.length() > 0) ? vs_body : "[not used]") << tcu::TestLog::EndMessage; |
| |
| goto end; |
| } /* if (link_status == GL_TRUE) */ |
| |
| /* All done */ |
| result = true; |
| end: |
| if (!result) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Failed test description: " << getTestIterationName(iteration) |
| << tcu::TestLog::EndMessage; |
| } |
| return result; |
| } |
| |
| /** Constructor. |
| * |
| * @param context Rendering context |
| * @param name Test name |
| * @param description Test description |
| */ |
| ReservedNamesTest::ReservedNamesTest(deqp::Context& context) |
| : TestCase(context, "CommonBug_ReservedNames", |
| "Verifies that reserved variable names are rejected by the GL SL compiler" |
| " at the compilation time.") |
| , m_max_fs_ssbos(0) |
| , m_max_gs_acs(0) |
| , m_max_gs_ssbos(0) |
| , m_max_tc_acs(0) |
| , m_max_tc_ssbos(0) |
| , m_max_te_acs(0) |
| , m_max_te_ssbos(0) |
| , m_max_vs_acs(0) |
| , m_max_vs_ssbos(0) |
| { |
| memset(m_so_ids, 0, sizeof(m_so_ids)); |
| } |
| |
| /** Deinitializes all GL objects created for the purpose of running the test, |
| * as well as any client-side buffers allocated at initialization time |
| */ |
| void ReservedNamesTest::deinit() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| for (unsigned int n_so_id = 0; n_so_id < sizeof(m_so_ids) / sizeof(m_so_ids[0]); ++n_so_id) |
| { |
| const glw::GLuint current_so_id = m_so_ids[n_so_id]; |
| |
| if (current_so_id != 0) |
| { |
| gl.deleteShader(current_so_id); |
| } |
| } /* for (all usedshader object IDs) */ |
| } |
| |
| /** Returns a literal corresponding to the specified @param language_feature value. |
| * |
| * @param language_feature Enum to return the string object for. |
| * |
| * @return As specified. |
| */ |
| std::string ReservedNamesTest::getLanguageFeatureName(_language_feature language_feature) const |
| { |
| std::string result = "[?!]"; |
| |
| switch (language_feature) |
| { |
| case LANGUAGE_FEATURE_ATOMIC_COUNTER: |
| result = "atomic counter"; |
| break; |
| case LANGUAGE_FEATURE_ATTRIBUTE: |
| result = "attribute"; |
| break; |
| case LANGUAGE_FEATURE_CONSTANT: |
| result = "constant"; |
| break; |
| case LANGUAGE_FEATURE_FUNCTION_ARGUMENT_NAME: |
| result = "function argument name"; |
| break; |
| case LANGUAGE_FEATURE_FUNCTION_NAME: |
| result = "function name"; |
| break; |
| case LANGUAGE_FEATURE_INPUT: |
| result = "input variable"; |
| break; |
| case LANGUAGE_FEATURE_INPUT_BLOCK_INSTANCE_NAME: |
| result = "input block instance name"; |
| break; |
| case LANGUAGE_FEATURE_INPUT_BLOCK_MEMBER_NAME: |
| result = "input block member name"; |
| break; |
| case LANGUAGE_FEATURE_INPUT_BLOCK_NAME: |
| result = "input block name"; |
| break; |
| case LANGUAGE_FEATURE_OUTPUT: |
| result = "output variable"; |
| break; |
| case LANGUAGE_FEATURE_OUTPUT_BLOCK_INSTANCE_NAME: |
| result = "output block instance name"; |
| break; |
| case LANGUAGE_FEATURE_OUTPUT_BLOCK_MEMBER_NAME: |
| result = "output block member name"; |
| break; |
| case LANGUAGE_FEATURE_OUTPUT_BLOCK_NAME: |
| result = "output block name"; |
| break; |
| case LANGUAGE_FEATURE_SHADER_STORAGE_BLOCK_INSTANCE_NAME: |
| result = "shader storage block instance name"; |
| break; |
| case LANGUAGE_FEATURE_SHADER_STORAGE_BLOCK_MEMBER_NAME: |
| result = "shader storage block member name"; |
| break; |
| case LANGUAGE_FEATURE_SHADER_STORAGE_BLOCK_NAME: |
| result = "shader storage block name"; |
| break; |
| case LANGUAGE_FEATURE_SHARED_VARIABLE: |
| result = "shared variable"; |
| break; |
| case LANGUAGE_FEATURE_STRUCTURE_MEMBER: |
| result = "structure member"; |
| break; |
| case LANGUAGE_FEATURE_STRUCTURE_INSTANCE_NAME: |
| result = "structure instance name"; |
| break; |
| case LANGUAGE_FEATURE_STRUCTURE_NAME: |
| result = "structure name"; |
| break; |
| case LANGUAGE_FEATURE_SUBROUTINE_FUNCTION_NAME: |
| result = "subroutine function name"; |
| break; |
| case LANGUAGE_FEATURE_SUBROUTINE_TYPE: |
| result = "subroutine type"; |
| break; |
| case LANGUAGE_FEATURE_SUBROUTINE_UNIFORM: |
| result = "subroutine uniform"; |
| break; |
| case LANGUAGE_FEATURE_UNIFORM: |
| result = "uniform"; |
| break; |
| case LANGUAGE_FEATURE_UNIFORM_BLOCK_INSTANCE_NAME: |
| result = "uniform block instance name"; |
| break; |
| case LANGUAGE_FEATURE_UNIFORM_BLOCK_MEMBER_NAME: |
| result = "uniform block member name"; |
| break; |
| case LANGUAGE_FEATURE_UNIFORM_BLOCK_NAME: |
| result = "uniform block name"; |
| break; |
| case LANGUAGE_FEATURE_VARIABLE: |
| result = "variable"; |
| break; |
| case LANGUAGE_FEATURE_VARYING: |
| result = "varying"; |
| break; |
| default: |
| result = "unknown"; |
| break; |
| } /* switch (language_feature) */ |
| |
| return result; |
| } |
| |
| /** Returns keywords and reserved names, specific to the running context version. */ |
| std::vector<std::string> ReservedNamesTest::getReservedNames() const |
| { |
| const glu::ContextType context_type = m_context.getRenderContext().getType(); |
| std::vector<std::string> result; |
| |
| const char** context_keywords = NULL; |
| unsigned int context_n_keywords = 0; |
| unsigned int context_n_reserved = 0; |
| const char** context_reserved = NULL; |
| |
| /* Keywords and reserved names were taken straight from relevant shading language specification documents */ |
| static const char* keywords_gl31[] = { |
| "attribute", |
| "const", |
| "uniform", |
| "varying", |
| "layout", |
| "centroid", |
| "flat", |
| "smooth", |
| "noperspective", |
| "break", |
| "continue", |
| "do", |
| "for", |
| "while", |
| "switch", |
| "case", |
| "default", |
| "if", |
| "else", |
| "in", |
| "out", |
| "inout", |
| "float", |
| "int", |
| "void", |
| "bool", |
| "true", |
| "false", |
| "invariant", |
| "discard", |
| "return", |
| "mat2", |
| "mat3", |
| "mat4", |
| "mat2x2", |
| "mat2x3", |
| "mat2x4", |
| "mat3x2", |
| "mat3x3", |
| "mat3x4", |
| "mat4x2", |
| "mat4x3", |
| "mat4x4", |
| "vec2", |
| "vec3", |
| "vec4", |
| "ivec2", |
| "ivec3", |
| "ivec4", |
| "bvec2", |
| "bvec3", |
| "bvec4", |
| "uint", |
| "uvec2", |
| "uvec3", |
| "uvec4", |
| "lowp", |
| "mediump", |
| "highp", |
| "precision", |
| "sampler1D", |
| "sampler2D", |
| "sampler3D", |
| "samplerCube", |
| "sampler1DShadow", |
| "sampler2DShadow", |
| "samplerCubeShadow", |
| "sampler1DArray", |
| "sampler2DArray", |
| "sampler1DArrayShadow", |
| "sampler2DArrayShadow", |
| "isampler1D", |
| "isampler2D", |
| "isampler3D", |
| "isamplerCube", |
| "isampler1DArray", |
| "isampler2DArray", |
| "usampler1D", |
| "usampler2D", |
| "usampler3D", |
| "usamplerCube", |
| "usampler1DArray", |
| "usampler2DArray", |
| "sampler2DRect", |
| "sampler2DRectShadow", |
| "isampler2DRect", |
| "usampler2DRect", |
| "samplerBuffer", |
| "isamplerBuffer", |
| "usamplerBuffer", |
| }; |
| static const char* keywords_gl32[] = { |
| "attribute", |
| "const", |
| "uniform", |
| "varying", |
| "layout", |
| "centroid", |
| "flat", |
| "smooth", |
| "noperspective", |
| "break", |
| "continue", |
| "do", |
| "for", |
| "while", |
| "switch", |
| "case", |
| "default", |
| "if", |
| "else", |
| "in", |
| "out", |
| "inout", |
| "float", |
| "int", |
| "void", |
| "bool", |
| "true", |
| "false", |
| "invariant", |
| "discard", |
| "return", |
| "mat2", |
| "mat3", |
| "mat4", |
| "mat2x2", |
| "mat2x3", |
| "mat2x4", |
| "mat3x2", |
| "mat3x3", |
| "mat3x4", |
| "mat4x2", |
| "mat4x3", |
| "mat4x4", |
| "vec2", |
| "vec3", |
| "vec4", |
| "ivec2", |
| "ivec3", |
| "ivec4", |
| "bvec2", |
| "bvec3", |
| "bvec4", |
| "uint", |
| "uvec2", |
| "uvec3", |
| "uvec4", |
| "lowp", |
| "mediump", |
| "highp", |
| "precision", |
| "sampler1D", |
| "sampler2D", |
| "sampler3D", |
| "samplerCube", |
| "sampler1DShadow", |
| "sampler2DShadow", |
| "samplerCubeShadow", |
| "sampler1DArray", |
| "sampler2DArray", |
| "sampler1DArrayShadow", |
| "sampler2DArrayShadow", |
| "isampler1D", |
| "isampler2D", |
| "isampler3D", |
| "isamplerCube", |
| "isampler1DArray", |
| "isampler2DArray", |
| "usampler1D", |
| "usampler2D", |
| "usampler3D", |
| "usamplerCube", |
| "usampler1DArray", |
| "usampler2DArray", |
| "sampler2DRect", |
| "sampler2DRectShadow", |
| "isampler2DRect", |
| "usampler2DRect", |
| "samplerBuffer", |
| "isamplerBuffer", |
| "usamplerBuffer", |
| "sampler2DMS", |
| "isampler2DMS", |
| "usampler2DMS", |
| "sampler2DMSArray", |
| "isampler2DMSArray", |
| "usampler2DMSArray", |
| }; |
| static const char* keywords_gl33[] = { |
| "attribute", |
| "const", |
| "uniform", |
| "varying", |
| "layout", |
| "centroid", |
| "flat", |
| "smooth", |
| "noperspective", |
| "break", |
| "continue", |
| "do", |
| "for", |
| "while", |
| "switch", |
| "case", |
| "default", |
| "if", |
| "else", |
| "in", |
| "out", |
| "inout", |
| "float", |
| "int", |
| "void", |
| "bool", |
| "true", |
| "false", |
| "invariant", |
| "discard", |
| "return", |
| "mat2", |
| "mat3", |
| "mat4", |
| "mat2x2", |
| "mat2x3", |
| "mat2x4", |
| "mat3x2", |
| "mat3x3", |
| "mat3x4", |
| "mat4x2", |
| "mat4x3", |
| "mat4x4", |
| "vec2", |
| "vec3", |
| "vec4", |
| "ivec2", |
| "ivec3", |
| "ivec4", |
| "bvec2", |
| "bvec3", |
| "bvec4", |
| "uint", |
| "uvec2", |
| "uvec3", |
| "uvec4", |
| "lowp", |
| "mediump", |
| "highp", |
| "precision", |
| "sampler1D", |
| "sampler2D", |
| "sampler3D", |
| "samplerCube", |
| "sampler1DShadow", |
| "sampler2DShadow", |
| "samplerCubeShadow", |
| "sampler1DArray", |
| "sampler2DArray", |
| "sampler1DArrayShadow", |
| "sampler2DArrayShadow", |
| "isampler1D", |
| "isampler2D", |
| "isampler3D", |
| "isamplerCube", |
| "isampler1DArray", |
| "isampler2DArray", |
| "usampler1D", |
| "usampler2D", |
| "usampler3D", |
| "usamplerCube", |
| "usampler1DArray", |
| "usampler2DArray", |
| "sampler2DRect", |
| "sampler2DRectShadow", |
| "isampler2DRect", |
| "usampler2DRect", |
| "samplerBuffer", |
| "isamplerBuffer", |
| "usamplerBuffer", |
| "sampler2DMS", |
| "isampler2DMS", |
| "usampler2DMS", |
| "sampler2DMSArray", |
| "isampler2DMSArray", |
| "usampler2DMSArray", |
| }; |
| static const char* keywords_gl40[] = { |
| "attribute", |
| "const", |
| "uniform", |
| "varying", |
| "layout", |
| "centroid", |
| "flat", |
| "smooth", |
| "noperspective", |
| "patch", |
| "sample", |
| "break", |
| "continue", |
| "do", |
| "for", |
| "while", |
| "switch", |
| "case", |
| "default", |
| "if", |
| "else", |
| "subroutine", |
| "in", |
| "out", |
| "inout", |
| "float", |
| "double", |
| "int", |
| "void", |
| "bool", |
| "true", |
| "false", |
| "invariant", |
| "discard", |
| "return", |
| "mat2", |
| "mat3", |
| "mat4", |
| "dmat2", |
| "dmat3", |
| "dmat4", |
| "mat2x2", |
| "mat2x3", |
| "mat2x4", |
| "dmat2x2", |
| "dmat2x3", |
| "dmat2x4", |
| "mat3x2", |
| "mat3x3", |
| "mat3x4", |
| "dmat3x2", |
| "dmat3x3", |
| "dmat3x4", |
| "mat4x2", |
| "mat4x3", |
| "mat4x4", |
| "dmat4x2", |
| "dmat4x3", |
| "dmat4x4", |
| "vec2", |
| "vec3", |
| "vec4", |
| "ivec2", |
| "ivec3", |
| "ivec4", |
| "bvec2", |
| "bvec3", |
| "bvec4", |
| "dvec2", |
| "dvec3", |
| "dvec4", |
| "uint", |
| "uvec2", |
| "uvec3", |
| "uvec4", |
| "lowp", |
| "mediump", |
| "highp", |
| "precision", |
| "sampler1D", |
| "sampler2D", |
| "sampler3D", |
| "samplerCube", |
| "sampler1DShadow", |
| "sampler2DShadow", |
| "samplerCubeShadow", |
| "sampler1DArray", |
| "sampler2DArray", |
| "sampler1DArrayShadow", |
| "sampler2DArrayShadow", |
| "isampler1D", |
| "isampler2D", |
| "isampler3D", |
| "isamplerCube", |
| "isampler1DArray", |
| "isampler2DArray", |
| "usampler1D", |
| "usampler2D", |
| "usampler3D", |
| "usamplerCube", |
| "usampler1DArray", |
| "usampler2DArray", |
| "sampler2DRect", |
| "sampler2DRectShadow", |
| "isampler2DRect", |
| "usampler2DRect", |
| "samplerBuffer", |
| "isamplerBuffer", |
| "usamplerBuffer", |
| "sampler2DMS", |
| "isampler2DMS", |
| "usampler2DMS", |
| "sampler2DMSArray", |
| "isampler2DMSArray", |
| "usampler2DMSArray", |
| "samplerCubeArray", |
| "samplerCubeArrayShadow", |
| "isamplerCubeArray", |
| "usamplerCubeArray", |
| }; |
| static const char* keywords_gl41[] = { |
| "attribute", |
| "const", |
| "uniform", |
| "varying", |
| "layout", |
| "centroid", |
| "flat", |
| "smooth", |
| "noperspective", |
| "patch", |
| "sample", |
| "break", |
| "continue", |
| "do", |
| "for", |
| "while", |
| "switch", |
| "case", |
| "default", |
| "if", |
| "else", |
| "subroutine", |
| "in", |
| "out", |
| "inout", |
| "float", |
| "double", |
| "int", |
| "void", |
| "bool", |
| "true", |
| "false", |
| "invariant", |
| "discard", |
| "return", |
| "mat2", |
| "mat3", |
| "mat4", |
| "dmat2", |
| "dmat3", |
| "dmat4", |
| "mat2x2", |
| "mat2x3", |
| "mat2x4", |
| "dmat2x2", |
| "dmat2x3", |
| "dmat2x4", |
| "mat3x2", |
| "mat3x3", |
| "mat3x4", |
| "dmat3x2", |
| "dmat3x3", |
| "dmat3x4", |
| "mat4x2", |
| "mat4x3", |
| "mat4x4", |
| "dmat4x2", |
| "dmat4x3", |
| "dmat4x4", |
| "vec2", |
| "vec3", |
| "vec4", |
| "ivec2", |
| "ivec3", |
| "ivec4", |
| "bvec2", |
| "bvec3", |
| "bvec4", |
| "dvec2", |
| "dvec3", |
| "dvec4", |
| "uint", |
| "uvec2", |
| "uvec3", |
| "uvec4", |
| "lowp", |
| "mediump", |
| "highp", |
| "precision", |
| "sampler1D", |
| "sampler2D", |
| "sampler3D", |
| "samplerCube", |
| "sampler1DShadow", |
| "sampler2DShadow", |
| "samplerCubeShadow", |
| "sampler1DArray", |
| "sampler2DArray", |
| "sampler1DArrayShadow", |
| "sampler2DArrayShadow", |
| "isampler1D", |
| "isampler2D", |
| "isampler3D", |
| "isamplerCube", |
| "isampler1DArray", |
| "isampler2DArray", |
| "usampler1D", |
| "usampler2D", |
| "usampler3D", |
| "usamplerCube", |
| "usampler1DArray", |
| "usampler2DArray", |
| "sampler2DRect", |
| "sampler2DRectShadow", |
| "isampler2DRect", |
| "usampler2DRect", |
| "samplerBuffer", |
| "isamplerBuffer", |
| "usamplerBuffer", |
| "sampler2DMS", |
| "isampler2DMS", |
| "usampler2DMS", |
| "sampler2DMSArray", |
| "isampler2DMSArray", |
| "usampler2DMSArray", |
| "samplerCubeArray", |
| "samplerCubeArrayShadow", |
| "isamplerCubeArray", |
| "usamplerCubeArray", |
| }; |
| static const char* keywords_gl42[] = { |
| "attribute", |
| "const", |
| "uniform", |
| "varying", |
| "coherent", |
| "volatile", |
| "restrict", |
| "readonly", |
| "writeonly", |
| "atomic_uint", |
| "layout", |
| "centroid", |
| "flat", |
| "smooth", |
| "noperspective", |
| "patch", |
| "sample", |
| "break", |
| "continue", |
| "do", |
| "for", |
| "while", |
| "switch", |
| "case", |
| "default", |
| "if", |
| "else", |
| "subroutine", |
| "in", |
| "out", |
| "inout", |
| "float", |
| "double", |
| "int", |
| "void", |
| "bool", |
| "true", |
| "false", |
| "invariant", |
| "discard", |
| "return", |
| "mat2", |
| "mat3", |
| "mat4", |
| "dmat2", |
| "dmat3", |
| "dmat4", |
| "mat2x2", |
| "mat2x3", |
| "mat2x4", |
| "dmat2x2", |
| "dmat2x3", |
| "dmat2x4", |
| "mat3x2", |
| "mat3x3", |
| "mat3x4", |
| "dmat3x2", |
| "dmat3x3", |
| "dmat3x4", |
| "mat4x2", |
| "mat4x3", |
| "mat4x4", |
| "dmat4x2", |
| "dmat4x3", |
| "dmat4x4", |
| "vec2", |
| "vec3", |
| "vec4", |
| "ivec2", |
| "ivec3", |
| "ivec4", |
| "bvec2", |
| "bvec3", |
| "bvec4", |
| "dvec2", |
| "dvec3", |
| "dvec4", |
| "uint", |
| "uvec2", |
| "uvec3", |
| "uvec4", |
| "lowp", |
| "mediump", |
| "highp", |
| "precision", |
| "sampler1D", |
| "sampler2D", |
| "sampler3D", |
| "samplerCube", |
| "sampler1DShadow", |
| "sampler2DShadow", |
| "samplerCubeShadow", |
| "sampler1DArray", |
| "sampler2DArray", |
| "sampler1DArrayShadow", |
| "sampler2DArrayShadow", |
| "isampler1D", |
| "isampler2D", |
| "isampler3D", |
| "isamplerCube", |
| "isampler1DArray", |
| "isampler2DArray", |
| "usampler1D", |
| "usampler2D", |
| "usampler3D", |
| "usamplerCube", |
| "usampler1DArray", |
| "usampler2DArray", |
| "sampler2DRect", |
| "sampler2DRectShadow", |
| "isampler2DRect", |
| "usampler2DRect", |
| "samplerBuffer", |
| "isamplerBuffer", |
| "usamplerBuffer", |
| "sampler2DMS", |
| "isampler2DMS", |
| "usampler2DMS", |
| "sampler2DMSArray", |
| "isampler2DMSArray", |
| "usampler2DMSArray", |
| "samplerCubeArray", |
| "samplerCubeArrayShadow", |
| "isamplerCubeArray", |
| "usamplerCubeArray", |
| "image1D", |
| "iimage1D", |
| "uimage1D", |
| "image2D", |
| "iimage2D", |
| "uimage2D", |
| "image3D", |
| "iimage3D", |
| "uimage3D", |
| "image2DRect", |
| "iimage2DRect", |
| "uimage2DRect", |
| "imageCube", |
| "iimageCube", |
| "uimageCube", |
| "imageBuffer", |
| "iimageBuffer", |
| "uimageBuffer", |
| "image1DArray", |
| "iimage1DArray", |
| "uimage1DArray", |
| "image2DArray", |
| "iimage2DArray", |
| "uimage2DArray", |
| "imageCubeArray", |
| "iimageCubeArray", |
| "uimageCubeArray", |
| "image2DMS", |
| "iimage2DMS", |
| "uimage2DMS", |
| "image2DMSArray", |
| "iimage2DMSArray", |
| "uimage2DMSArray", |
| }; |
| static const char* keywords_gl43[] = { |
| "attribute", |
| "const", |
| "uniform", |
| "varying", |
| "buffer", |
| "shared", |
| "coherent", |
| "volatile", |
| "restrict", |
| "readonly", |
| "writeonly", |
| "atomic_uint", |
| "layout", |
| "centroid", |
| "flat", |
| "smooth", |
| "noperspective", |
| "patch", |
| "sample", |
| "break", |
| "continue", |
| "do", |
| "for", |
| "while", |
| "switch", |
| "case", |
| "default", |
| "if", |
| "else", |
| "subroutine", |
| "in", |
| "out", |
| "inout", |
| "float", |
| "double", |
| "int", |
| "void", |
| "bool", |
| "true", |
| "false", |
| "invariant", |
| "precise", |
| "discard", |
| "return", |
| "mat2", |
| "mat3", |
| "mat4", |
| "dmat2", |
| "dmat3", |
| "dmat4", |
| "mat2x2", |
| "mat2x3", |
| "mat2x4", |
| "dmat2x2", |
| "dmat2x3", |
| "dmat2x4", |
| "mat3x2", |
| "mat3x3", |
| "mat3x4", |
| "dmat3x2", |
| "dmat3x3", |
| "dmat3x4", |
| "mat4x2", |
| "mat4x3", |
| "mat4x4", |
| "dmat4x2", |
| "dmat4x3", |
| "dmat4x4", |
| "vec2", |
| "vec3", |
| "vec4", |
| "ivec2", |
| "ivec3", |
| "ivec4", |
| "bvec2", |
| "bvec3", |
| "bvec4", |
| "dvec2", |
| "dvec3", |
| "dvec4", |
| "uint", |
| "uvec2", |
| "uvec3", |
| "uvec4", |
| "lowp", |
| "mediump", |
| "highp", |
| "precision", |
| "sampler1D", |
| "sampler2D", |
| "sampler3D", |
| "samplerCube", |
| "sampler1DShadow", |
| "sampler2DShadow", |
| "samplerCubeShadow", |
| "sampler1DArray", |
| "sampler2DArray", |
| "sampler1DArrayShadow", |
| "sampler2DArrayShadow", |
| "isampler1D", |
| "isampler2D", |
| "isampler3D", |
| "isamplerCube", |
| "isampler1DArray", |
| "isampler2DArray", |
| "usampler1D", |
| "usampler2D", |
| "usampler3D", |
| "usamplerCube", |
| "usampler1DArray", |
| "usampler2DArray", |
| "sampler2DRect", |
| "sampler2DRectShadow", |
| "isampler2DRect", |
| "usampler2DRect", |
| "samplerBuffer", |
| "isamplerBuffer", |
| "usamplerBuffer", |
| "sampler2DMS", |
| "isampler2DMS", |
| "usampler2DMS", |
| "sampler2DMSArray", |
| "isampler2DMSArray", |
| "usampler2DMSArray", |
| "samplerCubeArray", |
| "samplerCubeArrayShadow", |
| "isamplerCubeArray", |
| "usamplerCubeArray", |
| "image1D", |
| "iimage1D", |
| "uimage1D", |
| "image2D", |
| "iimage2D", |
| "uimage2D", |
| "image3D", |
| "iimage3D", |
| "uimage3D", |
| "image2DRect", |
| "iimage2DRect", |
| "uimage2DRect", |
| "imageCube", |
| "iimageCube", |
| "uimageCube", |
| "imageBuffer", |
| "iimageBuffer", |
| "uimageBuffer", |
| "image1DArray", |
| "iimage1DArray", |
| "uimage1DArray", |
| "image2DArray", |
| "iimage2DArray", |
| "uimage2DArray", |
| "imageCubeArray", |
| "iimageCubeArray", |
| "uimageCubeArray", |
| "image2DMS", |
| "iimage2DMS", |
| "uimage2DMS", |
| "image2DMSArray", |
| "iimage2DMSArray", |
| "uimage2DMSArray", |
| }; |
| static const char* keywords_gl44[] = { |
| "attribute", |
| "const", |
| "uniform", |
| "varying", |
| "buffer", |
| "shared", |
| "coherent", |
| "volatile", |
| "restrict", |
| "readonly", |
| "writeonly", |
| "atomic_uint", |
| "layout", |
| "centroid", |
| "flat", |
| "smooth", |
| "noperspective", |
| "patch", |
| "sample", |
| "break", |
| "continue", |
| "do", |
| "for", |
| "while", |
| "switch", |
| "case", |
| "default", |
| "if", |
| "else", |
| "subroutine", |
| "in", |
| "out", |
| "inout", |
| "float", |
| "double", |
| "int", |
| "void", |
| "bool", |
| "true", |
| "false", |
| "invariant", |
| "precise", |
| "discard", |
| "return", |
| "mat2", |
| "mat3", |
| "mat4", |
| "dmat2", |
| "dmat3", |
| "dmat4", |
| "mat2x2", |
| "mat2x3", |
| "mat2x4", |
| "dmat2x2", |
| "dmat2x3", |
| "dmat2x4", |
| "mat3x2", |
| "mat3x3", |
| "mat3x4", |
| "dmat3x2", |
| "dmat3x3", |
| "dmat3x4", |
| "mat4x2", |
| "mat4x3", |
| "mat4x4", |
| "dmat4x2", |
| "dmat4x3", |
| "dmat4x4", |
| "vec2", |
| "vec3", |
| "vec4", |
| "ivec2", |
| "ivec3", |
| "ivec4", |
| "bvec2", |
| "bvec3", |
| "bvec4", |
| "dvec2", |
| "dvec3", |
| "dvec4", |
| "uint", |
| "uvec2", |
| "uvec3", |
| "uvec4", |
| "lowp", |
| "mediump", |
| "highp", |
| "precision", |
| "sampler1D", |
| "sampler2D", |
| "sampler3D", |
| "samplerCube", |
| "sampler1DShadow", |
| "sampler2DShadow", |
| "samplerCubeShadow", |
| "sampler1DArray", |
| "sampler2DArray", |
| "sampler1DArrayShadow", |
| "sampler2DArrayShadow", |
| "isampler1D", |
| "isampler2D", |
| "isampler3D", |
| "isamplerCube", |
| "isampler1DArray", |
| "isampler2DArray", |
| "usampler1D", |
| "usampler2D", |
| "usampler3D", |
| "usamplerCube", |
| "usampler1DArray", |
| "usampler2DArray", |
| "sampler2DRect", |
| "sampler2DRectShadow", |
| "isampler2DRect", |
| "usampler2DRect", |
| "samplerBuffer", |
| "isamplerBuffer", |
| "usamplerBuffer", |
| "sampler2DMS", |
| "isampler2DMS", |
| "usampler2DMS", |
| "sampler2DMSArray", |
| "isampler2DMSArray", |
| "usampler2DMSArray", |
| "samplerCubeArray", |
| "samplerCubeArrayShadow", |
| "isamplerCubeArray", |
| "usamplerCubeArray", |
| "image1D", |
| "iimage1D", |
| "uimage1D", |
| "image2D", |
| "iimage2D", |
| "uimage2D", |
| "image3D", |
| "iimage3D", |
| "uimage3D", |
| "image2DRect", |
| "iimage2DRect", |
| "uimage2DRect", |
| "imageCube", |
| "iimageCube", |
| "uimageCube", |
| "imageBuffer", |
| "iimageBuffer", |
| "uimageBuffer", |
| "image1DArray", |
| "iimage1DArray", |
| "uimage1DArray", |
| "image2DArray", |
| "iimage2DArray", |
| "uimage2DArray", |
| "imageCubeArray", |
| "iimageCubeArray", |
| "uimageCubeArray", |
| "image2DMS", |
| "iimage2DMS", |
| "uimage2DMS", |
| "image2DMSArray", |
| "iimage2DMSArray", |
| "uimage2DMSArray", |
| }; |
| static const char* keywords_gl45[] = { |
| "attribute", |
| "const", |
| "uniform", |
| "varying", |
| "buffer", |
| "shared", |
| "coherent", |
| "volatile", |
| "restrict", |
| "readonly", |
| "writeonly", |
| "atomic_uint", |
| "layout", |
| "centroid", |
| "flat", |
| "smooth", |
| "noperspective", |
| "patch", |
| "sample", |
| "break", |
| "continue", |
| "do", |
| "for", |
| "while", |
| "switch", |
| "case", |
| "default", |
| "if", |
| "else", |
| "subroutine", |
| "in", |
| "out", |
| "inout", |
| "float", |
| "double", |
| "int", |
| "void", |
| "bool", |
| "true", |
| "false", |
| "invariant", |
| "precise", |
| "discard", |
| "return", |
| "mat2", |
| "mat3", |
| "mat4", |
| "dmat2", |
| "dmat3", |
| "dmat4", |
| "mat2x2", |
| "mat2x3", |
| "mat2x4", |
| "dmat2x2", |
| "dmat2x3", |
| "dmat2x4", |
| "mat3x2", |
| "mat3x3", |
| "mat3x4", |
| "dmat3x2", |
| "dmat3x3", |
| "dmat3x4", |
| "mat4x2", |
| "mat4x3", |
| "mat4x4", |
| "dmat4x2", |
| "dmat4x3", |
| "dmat4x4", |
| "vec2", |
| "vec3", |
| "vec4", |
| "ivec2", |
| "ivec3", |
| "ivec4", |
| "bvec2", |
| "bvec3", |
| "bvec4", |
| "dvec2", |
| "dvec3", |
| "dvec4", |
| "uint", |
| "uvec2", |
| "uvec3", |
| "uvec4", |
| "lowp", |
| "mediump", |
| "highp", |
| "precision", |
| "sampler1D", |
| "sampler2D", |
| "sampler3D", |
| "samplerCube", |
| "sampler1DShadow", |
| "sampler2DShadow", |
| "samplerCubeShadow", |
| "sampler1DArray", |
| "sampler2DArray", |
| "sampler1DArrayShadow", |
| "sampler2DArrayShadow", |
| "isampler1D", |
| "isampler2D", |
| "isampler3D", |
| "isamplerCube", |
| "isampler1DArray", |
| "isampler2DArray", |
| "usampler1D", |
| "usampler2D", |
| "usampler3D", |
| "usamplerCube", |
| "usampler1DArray", |
| "usampler2DArray", |
| "sampler2DRect", |
| "sampler2DRectShadow", |
| "isampler2DRect", |
| "usampler2DRect", |
| "samplerBuffer", |
| "isamplerBuffer", |
| "usamplerBuffer", |
| "sampler2DMS", |
| "isampler2DMS", |
| "usampler2DMS", |
| "sampler2DMSArray", |
| "isampler2DMSArray", |
| "usampler2DMSArray", |
| "samplerCubeArray", |
| "samplerCubeArrayShadow", |
| "isamplerCubeArray", |
| "usamplerCubeArray", |
| "image1D", |
| "iimage1D", |
| "uimage1D", |
| "image2D", |
| "iimage2D", |
| "uimage2D", |
| "image3D", |
| "iimage3D", |
| "uimage3D", |
| "image2DRect", |
| "iimage2DRect", |
| "uimage2DRect", |
| "imageCube", |
| "iimageCube", |
| "uimageCube", |
| "imageBuffer", |
| "iimageBuffer", |
| "uimageBuffer", |
| "image1DArray", |
| "iimage1DArray", |
| "uimage1DArray", |
| "image2DArray", |
| "iimage2DArray", |
| "uimage2DArray", |
| "imageCubeArray", |
| "iimageCubeArray", |
| "uimageCubeArray", |
| "image2DMS", |
| "iimage2DMS", |
| "uimage2DMS", |
| "image2DMSArray", |
| "iimage2DMSArray", |
| "uimage2DMSArray", |
| }; |
| static const char* keywords_gl46[] = { |
| "attribute", |
| "const", |
| "uniform", |
| "varying", |
| "buffer", |
| "shared", |
| "coherent", |
| "volatile", |
| "restrict", |
| "readonly", |
| "writeonly", |
| "atomic_uint", |
| "layout", |
| "centroid", |
| "flat", |
| "smooth", |
| "noperspective", |
| "patch", |
| "sample", |
| "break", |
| "continue", |
| "do", |
| "for", |
| "while", |
| "switch", |
| "case", |
| "default", |
| "if", |
| "else", |
| "subroutine", |
| "in", |
| "out", |
| "inout", |
| "float", |
| "double", |
| "int", |
| "void", |
| "bool", |
| "true", |
| "false", |
| "invariant", |
| "precise", |
| "discard", |
| "return", |
| "mat2", |
| "mat3", |
| "mat4", |
| "dmat2", |
| "dmat3", |
| "dmat4", |
| "mat2x2", |
| "mat2x3", |
| "mat2x4", |
| "dmat2x2", |
| "dmat2x3", |
| "dmat2x4", |
| "mat3x2", |
| "mat3x3", |
| "mat3x4", |
| "dmat3x2", |
| "dmat3x3", |
| "dmat3x4", |
| "mat4x2", |
| "mat4x3", |
| "mat4x4", |
| "dmat4x2", |
| "dmat4x3", |
| "dmat4x4", |
| "vec2", |
| "vec3", |
| "vec4", |
| "ivec2", |
| "ivec3", |
| "ivec4", |
| "bvec2", |
| "bvec3", |
| "bvec4", |
| "dvec2", |
| "dvec3", |
| "dvec4", |
| "uint", |
| "uvec2", |
| "uvec3", |
| "uvec4", |
| "lowp", |
| "mediump", |
| "highp", |
| "precision", |
| "sampler1D", |
| "sampler2D", |
| "sampler3D", |
| "samplerCube", |
| "sampler1DShadow", |
| "sampler2DShadow", |
| "samplerCubeShadow", |
| "sampler1DArray", |
| "sampler2DArray", |
| "sampler1DArrayShadow", |
| "sampler2DArrayShadow", |
| "isampler1D", |
| "isampler2D", |
| "isampler3D", |
| "isamplerCube", |
| "isampler1DArray", |
| "isampler2DArray", |
| "usampler1D", |
| "usampler2D", |
| "usampler3D", |
| "usamplerCube", |
| "usampler1DArray", |
| "usampler2DArray", |
| "sampler2DRect", |
| "sampler2DRectShadow", |
| "isampler2DRect", |
| "usampler2DRect", |
| "samplerBuffer", |
| "isamplerBuffer", |
| "usamplerBuffer", |
| "sampler2DMS", |
| "isampler2DMS", |
| "usampler2DMS", |
| "sampler2DMSArray", |
| "isampler2DMSArray", |
| "usampler2DMSArray", |
| "samplerCubeArray", |
| "samplerCubeArrayShadow", |
| "isamplerCubeArray", |
| "usamplerCubeArray", |
| "image1D", |
| "iimage1D", |
| "uimage1D", |
| "image2D", |
| "iimage2D", |
| "uimage2D", |
| "image3D", |
| "iimage3D", |
| "uimage3D", |
| "image2DRect", |
| "iimage2DRect", |
| "uimage2DRect", |
| "imageCube", |
| "iimageCube", |
| "uimageCube", |
| "imageBuffer", |
| "iimageBuffer", |
| "uimageBuffer", |
| "image1DArray", |
| "iimage1DArray", |
| "uimage1DArray", |
| "image2DArray", |
| "iimage2DArray", |
| "uimage2DArray", |
| "imageCubeArray", |
| "iimageCubeArray", |
| "uimageCubeArray", |
| "image2DMS", |
| "iimage2DMS", |
| "uimage2DMS", |
| "image2DMSArray", |
| "iimage2DMSArray", |
| "uimage2DMSArray", |
| "struct" |
| }; |
| static const char* reserved_gl31[] = { |
| "common", |
| "partition", |
| "active", |
| "asm", |
| "class", |
| "union", |
| "enum", |
| "typedef", |
| "template", |
| "this", |
| "packed", |
| "goto", |
| "inline", |
| "noinline", |
| "volatile", |
| "public", |
| "static", |
| "extern", |
| "external", |
| "interface", |
| "long", |
| "short", |
| "double", |
| "half", |
| "fixed", |
| "unsigned", |
| "superp", |
| "input", |
| "output", |
| "hvec2", |
| "hvec3", |
| "hvec4", |
| "dvec2", |
| "dvec3", |
| "dvec4", |
| "fvec2", |
| "fvec3", |
| "fvec4", |
| "sampler3DRect", |
| "filter", |
| "image1D", |
| "image2D", |
| "image3D", |
| "imageCube", |
| "iimage1D", |
| "iimage2D", |
| "iimage3D", |
| "iimageCube", |
| "uimage1D", |
| "uimage2D", |
| "uimage3D", |
| "uimageCube", |
| "image1DArray", |
| "image2DArray", |
| "iimage1DArray", |
| "iimage2DArray", |
| "uimage1DArray", |
| "uimage2DArray", |
| "image1DShadow", |
| "image2DShadow", |
| "image1DArrayShadow", |
| "image2DArrayShadow", |
| "imageBuffer", |
| "iimageBuffer", |
| "uimageBuffer", |
| "sizeof", |
| "cast", |
| "namespace", |
| "using", |
| "row_major", |
| }; |
| static const char* reserved_gl32[] = { |
| "common", |
| "partition", |
| "active", |
| "asm", |
| "class", |
| "union", |
| "enum", |
| "typedef", |
| "template", |
| "this", |
| "packed", |
| "goto", |
| "inline", |
| "noinline", |
| "volatile", |
| "public", |
| "static", |
| "extern", |
| "external", |
| "interface", |
| "long", |
| "short", |
| "double", |
| "half", |
| "fixed", |
| "unsigned", |
| "superp", |
| "input", |
| "output", |
| "hvec2", |
| "hvec3", |
| "hvec4", |
| "dvec2", |
| "dvec3", |
| "dvec4", |
| "fvec2", |
| "fvec3", |
| "fvec4", |
| "sampler3DRect", |
| "filter", |
| "image1D", |
| "image2D", |
| "image3D", |
| "imageCube", |
| "iimage1D", |
| "iimage2D", |
| "iimage3D", |
| "iimageCube", |
| "uimage1D", |
| "uimage2D", |
| "uimage3D", |
| "uimageCube", |
| "image1DArray", |
| "image2DArray", |
| "iimage1DArray", |
| "iimage2DArray", |
| "uimage1DArray", |
| "uimage2DArray", |
| "image1DShadow", |
| "image2DShadow", |
| "image1DArrayShadow", |
| "image2DArrayShadow", |
| "imageBuffer", |
| "iimageBuffer", |
| "uimageBuffer", |
| "sizeof", |
| "cast", |
| "namespace", |
| "using", |
| "row_major", |
| }; |
| static const char* reserved_gl33[] = { |
| "common", |
| "partition", |
| "active", |
| "asm", |
| "class", |
| "union", |
| "enum", |
| "typedef", |
| "template", |
| "this", |
| "packed", |
| "goto", |
| "inline", |
| "noinline", |
| "volatile", |
| "public", |
| "static", |
| "extern", |
| "external", |
| "interface", |
| "long", |
| "short", |
| "double", |
| "half", |
| "fixed", |
| "unsigned", |
| "superp", |
| "input", |
| "output", |
| "hvec2", |
| "hvec3", |
| "hvec4", |
| "dvec2", |
| "dvec3", |
| "dvec4", |
| "fvec2", |
| "fvec3", |
| "fvec4", |
| "sampler3DRect", |
| "filter", |
| "image1D", |
| "image2D", |
| "image3D", |
| "imageCube", |
| "iimage1D", |
| "iimage2D", |
| "iimage3D", |
| "iimageCube", |
| "uimage1D", |
| "uimage2D", |
| "uimage3D", |
| "uimageCube", |
| "image1DArray", |
| "image2DArray", |
| "iimage1DArray", |
| "iimage2DArray", |
| "uimage1DArray", |
| "uimage2DArray", |
| "image1DShadow", |
| "image2DShadow", |
| "image1DArrayShadow", |
| "image2DArrayShadow", |
| "imageBuffer", |
| "iimageBuffer", |
| "uimageBuffer", |
| "sizeof", |
| "cast", |
| "namespace", |
| "using", |
| "row_major", |
| }; |
| static const char* reserved_gl40[] = { |
| "common", |
| "partition", |
| "active", |
| "asm", |
| "class", |
| "union", |
| "enum", |
| "typedef", |
| "template", |
| "this", |
| "packed", |
| "goto", |
| "inline", |
| "noinline", |
| "volatile", |
| "public", |
| "static", |
| "extern", |
| "external", |
| "interface", |
| "long", |
| "short", |
| "half", |
| "fixed", |
| "unsigned", |
| "superp", |
| "input", |
| "output", |
| "hvec2", |
| "hvec3", |
| "hvec4", |
| "fvec2", |
| "fvec3", |
| "fvec4", |
| "sampler3DRect", |
| "filter", |
| "image1D", |
| "image2D", |
| "image3D", |
| "imageCube", |
| "iimage1D", |
| "iimage2D", |
| "iimage3D", |
| "iimageCube", |
| "uimage1D", |
| "uimage2D", |
| "uimage3D", |
| "uimageCube", |
| "image1DArray", |
| "image2DArray", |
| "iimage1DArray", |
| "iimage2DArray", |
| "uimage1DArray", |
| "uimage2DArray", |
| "image1DShadow", |
| "image2DShadow", |
| "image1DArrayShadow", |
| "image2DArrayShadow", |
| "imageBuffer", |
| "iimageBuffer", |
| "uimageBuffer", |
| "sizeof", |
| "cast", |
| "namespace", |
| "using", |
| "row_major", |
| }; |
| static const char* reserved_gl41[] = { |
| "common", |
| "partition", |
| "active", |
| "asm", |
| "class", |
| "union", |
| "enum", |
| "typedef", |
| "template", |
| "this", |
| "packed", |
| "goto", |
| "inline", |
| "noinline", |
| "volatile", |
| "public", |
| "static", |
| "extern", |
| "external", |
| "interface", |
| "long", |
| "short", |
| "half", |
| "fixed", |
| "unsigned", |
| "superp", |
| "input", |
| "output", |
| "hvec2", |
| "hvec3", |
| "hvec4", |
| "fvec2", |
| "fvec3", |
| "fvec4", |
| "sampler3DRect", |
| "filter", |
| "image1D", |
| "image2D", |
| "image3D", |
| "imageCube", |
| "iimage1D", |
| "iimage2D", |
| "iimage3D", |
| "iimageCube", |
| "uimage1D", |
| "uimage2D", |
| "uimage3D", |
| "uimageCube", |
| "image1DArray", |
| "image2DArray", |
| "iimage1DArray", |
| "iimage2DArray", |
| "uimage1DArray", |
| "uimage2DArray", |
| "image1DShadow", |
| "image2DShadow", |
| "image1DArrayShadow", |
| "image2DArrayShadow", |
| "imageBuffer", |
| "iimageBuffer", |
| "uimageBuffer", |
| "sizeof", |
| "cast", |
| "namespace", |
| "using", |
| "row_major", |
| }; |
| static const char* reserved_gl42[] = { |
| "common", "partition", "active", "asm", "class", "union", "enum", "typedef", "template", |
| "this", "packed", "resource", "goto", "inline", "noinline", "public", "static", "extern", |
| "external", "interface", "long", "short", "half", "fixed", "unsigned", "superp", "input", |
| "output", "hvec2", "hvec3", "hvec4", "fvec2", "fvec3", "fvec4", "sampler3DRect", "filter", |
| "sizeof", "cast", "namespace", "using", "row_major", |
| }; |
| static const char* reserved_gl43[] = { |
| "common", "partition", "active", "asm", "class", "union", "enum", "typedef", "template", |
| "this", "packed", "resource", "goto", "inline", "noinline", "public", "static", "extern", |
| "external", "interface", "long", "short", "half", "fixed", "unsigned", "superp", "input", |
| "output", "hvec2", "hvec3", "hvec4", "fvec2", "fvec3", "fvec4", "sampler3DRect", "filter", |
| "sizeof", "cast", "namespace", "using", "row_major", |
| }; |
| static const char* reserved_gl44[] = { |
| "common", "partition", "active", "asm", "class", "union", "enum", "typedef", |
| "template", "this", "resource", "goto", "inline", "noinline", "public", "static", |
| "extern", "external", "interface", "long", "short", "half", "fixed", "unsigned", |
| "superp", "input", "output", "hvec2", "hvec3", "hvec4", "fvec2", "fvec3", |
| "fvec4", "sampler3DRect", "filter", "sizeof", "cast", "namespace", "using", |
| }; |
| static const char* reserved_gl45[] = { |
| "common", "partition", "active", "asm", "class", "union", "enum", "typedef", |
| "template", "this", "resource", "goto", "inline", "noinline", "public", "static", |
| "extern", "external", "interface", "long", "short", "half", "fixed", "unsigned", |
| "superp", "input", "output", "hvec2", "hvec3", "hvec4", "fvec2", "fvec3", |
| "fvec4", "sampler3DRect", "filter", "sizeof", "cast", "namespace", "using", |
| }; |
| static const char* reserved_gl46[] = { |
| "common", "partition", "active", "asm", "class", "union", "enum", "typedef", |
| "template", "this", "resource", "goto", "inline", "noinline", "public", "static", |
| "extern", "external", "interface", "long", "short", "half", "fixed", "unsigned", |
| "superp", "input", "output", "hvec2", "hvec3", "hvec4", "fvec2", "fvec3", |
| "fvec4", "sampler3DRect", "filter", "sizeof", "cast", "namespace", "using", |
| }; |
| |
| glu::ApiType apiType = context_type.getAPI(); |
| if (apiType == glu::ApiType::core(3, 1)) |
| { |
| context_keywords = keywords_gl31; |
| context_reserved = reserved_gl31; |
| context_n_keywords = static_cast<unsigned int>(sizeof(keywords_gl31) / sizeof(keywords_gl31[0])); |
| context_n_reserved = static_cast<unsigned int>(sizeof(reserved_gl31) / sizeof(reserved_gl31[0])); |
| } |
| else if (apiType == glu::ApiType::core(3, 2)) |
| { |
| context_keywords = keywords_gl32; |
| context_reserved = reserved_gl32; |
| context_n_keywords = static_cast<unsigned int>(sizeof(keywords_gl32) / sizeof(keywords_gl32[0])); |
| context_n_reserved = static_cast<unsigned int>(sizeof(reserved_gl32) / sizeof(reserved_gl32[0])); |
| } |
| else if (apiType == glu::ApiType::core(3, 3)) |
| { |
| context_keywords = keywords_gl33; |
| context_reserved = reserved_gl33; |
| context_n_keywords = static_cast<unsigned int>(sizeof(keywords_gl33) / sizeof(keywords_gl33[0])); |
| context_n_reserved = static_cast<unsigned int>(sizeof(reserved_gl33) / sizeof(reserved_gl33[0])); |
| } |
| else if (apiType == glu::ApiType::core(4, 0)) |
| { |
| context_keywords = keywords_gl40; |
| context_reserved = reserved_gl40; |
| context_n_keywords = static_cast<unsigned int>(sizeof(keywords_gl40) / sizeof(keywords_gl40[0])); |
| context_n_reserved = static_cast<unsigned int>(sizeof(reserved_gl40) / sizeof(reserved_gl40[0])); |
| } |
| else if (apiType == glu::ApiType::core(4, 1)) |
| { |
| context_keywords = keywords_gl41; |
| context_reserved = reserved_gl41; |
| context_n_keywords = static_cast<unsigned int>(sizeof(keywords_gl41) / sizeof(keywords_gl41[0])); |
| context_n_reserved = static_cast<unsigned int>(sizeof(reserved_gl41) / sizeof(reserved_gl41[0])); |
| } |
| else if (apiType == glu::ApiType::core(4, 2)) |
| { |
| context_keywords = keywords_gl42; |
| context_reserved = reserved_gl42; |
| context_n_keywords = static_cast<unsigned int>(sizeof(keywords_gl42) / sizeof(keywords_gl42[0])); |
| context_n_reserved = static_cast<unsigned int>(sizeof(reserved_gl42) / sizeof(reserved_gl42[0])); |
| } |
| else if (apiType == glu::ApiType::core(4, 3)) |
| { |
| context_keywords = keywords_gl43; |
| context_reserved = reserved_gl43; |
| context_n_keywords = static_cast<unsigned int>(sizeof(keywords_gl43) / sizeof(keywords_gl43[0])); |
| context_n_reserved = static_cast<unsigned int>(sizeof(reserved_gl43) / sizeof(reserved_gl43[0])); |
| } |
| else if (apiType == glu::ApiType::core(4, 4)) |
| { |
| context_keywords = keywords_gl44; |
| context_reserved = reserved_gl44; |
| context_n_keywords = static_cast<unsigned int>(sizeof(keywords_gl44) / sizeof(keywords_gl44[0])); |
| context_n_reserved = static_cast<unsigned int>(sizeof(reserved_gl44) / sizeof(reserved_gl44[0])); |
| } |
| else if (apiType == glu::ApiType::core(4, 5)) |
| { |
| context_keywords = keywords_gl45; |
| context_reserved = reserved_gl45; |
| context_n_keywords = static_cast<unsigned int>(sizeof(keywords_gl45) / sizeof(keywords_gl45[0])); |
| context_n_reserved = static_cast<unsigned int>(sizeof(reserved_gl45) / sizeof(reserved_gl45[0])); |
| } |
| else if (apiType == glu::ApiType::core(4, 6)) |
| { |
| context_keywords = keywords_gl46; |
| context_reserved = reserved_gl46; |
| context_n_keywords = static_cast<unsigned int>(sizeof(keywords_gl46) / sizeof(keywords_gl46[0])); |
| context_n_reserved = static_cast<unsigned int>(sizeof(reserved_gl46) / sizeof(reserved_gl46[0])); |
| } |
| else |
| { |
| TCU_FAIL("Unsupported GL context version - please implement."); |
| } |
| |
| for (unsigned int n_current_context_keyword = 0; n_current_context_keyword < context_n_keywords; |
| ++n_current_context_keyword) |
| { |
| const char* current_context_keyword = context_keywords[n_current_context_keyword]; |
| |
| result.push_back(current_context_keyword); |
| } /* for (all context keywords) */ |
| |
| for (unsigned int n_current_context_reserved = 0; n_current_context_reserved < context_n_reserved; |
| ++n_current_context_reserved) |
| { |
| const char* current_context_reserved = context_reserved[n_current_context_reserved]; |
| |
| result.push_back(current_context_reserved); |
| } /* for (all context reserved names) */ |
| |
| /* All done! */ |
| return result; |
| } |
| |
| /** Returns a shader body to use for the test. The body is formed, according to the user-specified |
| * requirements. |
| * |
| * @param shader_type Shader stage the shader body should be returned for. |
| * @param language_feature Language feature to test. |
| * @param invalid_name Name to use for the language feature instance. The string should come |
| * from the list of keywords or reserved names, specific to the currently |
| * running rendering context's version. |
| * |
| * @return Requested shader body. |
| */ |
| std::string ReservedNamesTest::getShaderBody(_shader_type shader_type, _language_feature language_feature, |
| const char* invalid_name) const |
| { |
| std::stringstream body_sstream; |
| const glu::ContextType context_type = m_context.getRenderContext().getType(); |
| |
| /* Preamble: shader language version */ |
| body_sstream << "#version "; |
| |
| glu::ApiType apiType = context_type.getAPI(); |
| if (apiType == glu::ApiType::core(3, 1)) |
| body_sstream << "140"; |
| else if (apiType == glu::ApiType::core(3, 2)) |
| body_sstream << "150"; |
| else if (apiType == glu::ApiType::core(3, 3)) |
| body_sstream << "330"; |
| else if (apiType == glu::ApiType::core(4, 0)) |
| body_sstream << "400"; |
| else if (apiType == glu::ApiType::core(4, 1)) |
| body_sstream << "410"; |
| else if (apiType == glu::ApiType::core(4, 2)) |
| body_sstream << "420"; |
| else if (apiType == glu::ApiType::core(4, 3)) |
| body_sstream << "430"; |
| else if (apiType == glu::ApiType::core(4, 4)) |
| body_sstream << "440"; |
| else if (apiType == glu::ApiType::core(4, 5)) |
| body_sstream << "450"; |
| else if (apiType == glu::ApiType::core(4, 6)) |
| body_sstream << "460"; |
| else |
| { |
| TCU_FAIL("Unsupported GL context version - please implement"); |
| } |
| |
| body_sstream << "\n\n"; |
| |
| /* Preamble: layout qualifiers - required for CS, TC and TE shader stages */ |
| if (shader_type == SHADER_TYPE_COMPUTE) |
| { |
| body_sstream << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"; |
| } |
| else if (shader_type == SHADER_TYPE_TESS_CONTROL) |
| { |
| body_sstream << "layout(vertices = 3) out;\n"; |
| } |
| else if (shader_type == SHADER_TYPE_TESS_EVALUATION) |
| { |
| body_sstream << "layout(triangles) in;\n"; |
| } |
| |
| body_sstream << "\n\n"; |
| |
| /* Language feature: insert incorrectly named atomic counter declaration if needed */ |
| if (language_feature == LANGUAGE_FEATURE_ATOMIC_COUNTER) |
| { |
| body_sstream << "layout(binding = 0, offset = 0) uniform atomic_uint " << invalid_name << ";\n"; |
| } |
| |
| /* Language feature: insert incorrectly named attribute declaration if needed */ |
| if (language_feature == LANGUAGE_FEATURE_ATTRIBUTE) |
| { |
| body_sstream << "attribute vec4 " << invalid_name << ";\n"; |
| } |
| |
| /* Language feature: insert incorrectly name constant declaration if needed */ |
| if (language_feature == LANGUAGE_FEATURE_CONSTANT) |
| { |
| body_sstream << "const vec4 " << invalid_name << " = vec4(2.0, 3.0, 4.0, 5.0);\n"; |
| } |
| |
| /* Language feature: insert a function with incorrectly named argument if needed */ |
| if (language_feature == LANGUAGE_FEATURE_FUNCTION_ARGUMENT_NAME) |
| { |
| body_sstream << "void test(in vec4 " << invalid_name << ")\n" |
| "{\n" |
| "}\n"; |
| } |
| |
| /* Language feature: insert incorrectly named function if needed */ |
| if (language_feature == LANGUAGE_FEATURE_FUNCTION_NAME) |
| { |
| body_sstream << "void " << invalid_name << "(in vec4 test)\n" |
| "{\n" |
| "}\n"; |
| } |
| |
| /* Language feature: insert incorrectly named input variable if needed */ |
| if (language_feature == LANGUAGE_FEATURE_INPUT) |
| { |
| body_sstream << "in vec4 " << invalid_name; |
| |
| if (shader_type == SHADER_TYPE_GEOMETRY || shader_type == SHADER_TYPE_TESS_CONTROL || |
| shader_type == SHADER_TYPE_TESS_EVALUATION) |
| { |
| body_sstream << "[]"; |
| } |
| |
| body_sstream << ";\n"; |
| } |
| |
| /* Language feature: insert declaration of an incorrectly named input block instance if needed */ |
| if (language_feature == LANGUAGE_FEATURE_INPUT_BLOCK_INSTANCE_NAME) |
| { |
| body_sstream << "in testBlock\n" |
| "{\n" |
| " vec4 test;\n" |
| "} " |
| << invalid_name; |
| |
| if (shader_type == SHADER_TYPE_GEOMETRY || shader_type == SHADER_TYPE_TESS_CONTROL || |
| shader_type == SHADER_TYPE_TESS_EVALUATION) |
| { |
| body_sstream << "[]"; |
| } |
| |
| body_sstream << ";\n"; |
| } |
| |
| /* Language feature: insert declaration of an input block holding an incorrectly named member variable */ |
| if (language_feature == LANGUAGE_FEATURE_INPUT_BLOCK_MEMBER_NAME) |
| { |
| body_sstream << "in testBlock\n" |
| "{\n" |
| " vec4 " |
| << invalid_name << ";\n" |
| "} testBlockInstance"; |
| |
| if (shader_type == SHADER_TYPE_GEOMETRY || shader_type == SHADER_TYPE_TESS_CONTROL || |
| shader_type == SHADER_TYPE_TESS_EVALUATION) |
| { |
| body_sstream << "[]"; |
| } |
| |
| body_sstream << ";\n"; |
| } |
| |
| /* Language feature: insert declaration of an incorrectly named input block */ |
| if (language_feature == LANGUAGE_FEATURE_INPUT_BLOCK_NAME) |
| { |
| body_sstream << "in " << invalid_name << "\n" |
| "{\n" |
| " vec4 test;\n" |
| "} testBlockInstance"; |
| |
| if (shader_type == SHADER_TYPE_GEOMETRY || shader_type == SHADER_TYPE_TESS_CONTROL || |
| shader_type == SHADER_TYPE_TESS_EVALUATION) |
| { |
| body_sstream << "[]"; |
| } |
| |
| body_sstream << ";\n"; |
| } |
| |
| /* Language feature: insert incorrectly named output variable if needed */ |
| if (language_feature == LANGUAGE_FEATURE_OUTPUT) |
| { |
| body_sstream << "out vec4 " << invalid_name; |
| |
| if (shader_type == SHADER_TYPE_TESS_CONTROL) |
| { |
| body_sstream << "[]"; |
| } |
| |
| body_sstream << ";\n"; |
| } |
| |
| /* Language feature: insert declaration of an incorrectly named output block instance if needed */ |
| if (language_feature == LANGUAGE_FEATURE_OUTPUT_BLOCK_INSTANCE_NAME) |
| { |
| body_sstream << "out testBlock\n" |
| "{\n" |
| " vec4 test;\n" |
| "} " |
| << invalid_name; |
| |
| if (shader_type == SHADER_TYPE_TESS_CONTROL) |
| { |
| body_sstream << "[]"; |
| } |
| |
| body_sstream << ";\n"; |
| } |
| |
| /* Language feature: insert declaration of an output block holding an incorrectly named member variable */ |
| if (language_feature == LANGUAGE_FEATURE_OUTPUT_BLOCK_MEMBER_NAME) |
| { |
| body_sstream << "out testBlock\n" |
| "{\n" |
| " vec4 " |
| << invalid_name << ";\n" |
| "} testBlockInstance"; |
| |
| if (shader_type == SHADER_TYPE_TESS_CONTROL) |
| { |
| body_sstream << "[]"; |
| } |
| |
| body_sstream << ";\n"; |
| } |
| |
| /* Language feature: insert declaration of an incorrectly named output block */ |
| if (language_feature == LANGUAGE_FEATURE_OUTPUT_BLOCK_NAME) |
| { |
| body_sstream << "out " << invalid_name << "\n" |
| "{\n" |
| " vec4 test;\n" |
| "} testBlockInstance"; |
| |
| if (shader_type == SHADER_TYPE_TESS_CONTROL) |
| { |
| body_sstream << "[]"; |
| } |
| |
| body_sstream << ";\n"; |
| } |
| |
| /* Language feature: insert declaration of an incorrectly named shader storage block instance if needed */ |
| if (language_feature == LANGUAGE_FEATURE_SHADER_STORAGE_BLOCK_INSTANCE_NAME) |
| { |
| body_sstream << "buffer testBlock\n" |
| "{\n" |
| " vec4 test;\n" |
| "} " |
| << invalid_name << ";\n"; |
| } |
| |
| /* Language feature: insert declaration of a shader storage block holding an incorrectly named member variable */ |
| if (language_feature == LANGUAGE_FEATURE_SHADER_STORAGE_BLOCK_MEMBER_NAME) |
| { |
| body_sstream << "buffer testBlock\n" |
| "{\n" |
| " vec4 " |
| << invalid_name << ";\n" |
| "};\n"; |
| } |
| |
| /* Language feature: insert declaration of an incorrectly named shader storage block */ |
| if (language_feature == LANGUAGE_FEATURE_SHADER_STORAGE_BLOCK_NAME) |
| { |
| body_sstream << "buffer " << invalid_name << "\n" |
| "{\n" |
| " vec4 test;\n" |
| "};\n"; |
| } |
| |
| /* Language feature: insert declaration of a subroutine function with invalid name */ |
| if (language_feature == LANGUAGE_FEATURE_SUBROUTINE_FUNCTION_NAME) |
| { |
| body_sstream << "subroutine void exampleSubroutine(inout vec4 " << invalid_name |
| << ");\n" |
| "\n" |
| "subroutine (exampleSubroutine) void invert(inout vec4 " |
| << invalid_name << ")\n" |
| "{\n" |
| " " |
| << invalid_name << " += vec4(0.0, 1.0, 2.0, 3.0);\n" |
| "}\n" |
| "\n" |
| "subroutine uniform exampleSubroutine testSubroutine;\n"; |
| } |
| |
| /* Language feature: insert declaration of a subroutine of incorrectly named type */ |
| if (language_feature == LANGUAGE_FEATURE_SUBROUTINE_TYPE) |
| { |
| body_sstream << "subroutine void " << invalid_name << "(inout vec4 arg);\n" |
| "\n" |
| "subroutine (" |
| << invalid_name << ") void invert(inout vec4 arg)\n" |
| "{\n" |
| " arg += vec4(0.0, 1.0, 2.0, 3.0);\n" |
| "}\n" |
| "\n" |
| "subroutine uniform " |
| << invalid_name << " testSubroutine;\n"; |
| } |
| |
| /* Language feature: insert declaration of a subroutine, followed by a declaration of |
| * an incorrectly named subroutine uniform. |
| */ |
| if (language_feature == LANGUAGE_FEATURE_SUBROUTINE_UNIFORM) |
| { |
| body_sstream << "subroutine void exampleSubroutine(inout vec4 arg);\n" |
| "\n" |
| "subroutine (exampleSubroutine) void invert(inout vec4 arg)\n" |
| "{\n" |
| " arg += vec4(0.0, 1.0, 2.0, 3.0);\n" |
| "}\n" |
| "\n" |
| "subroutine uniform exampleSubroutine " |
| << invalid_name << ";\n"; |
| } |
| |
| /* Language feature: insert declaration of an incorrectly named uniform. */ |
| if (language_feature == LANGUAGE_FEATURE_UNIFORM) |
| { |
| body_sstream << "uniform sampler2D " << invalid_name << ";\n"; |
| } |
| |
| /* Language feature: insert declaration of an incorrectly named uniform block instance if needed */ |
| if (language_feature == LANGUAGE_FEATURE_UNIFORM_BLOCK_INSTANCE_NAME) |
| { |
| body_sstream << "uniform testBlock\n" |
| "{\n" |
| " vec4 test;\n" |
| "} " |
| << invalid_name << ";\n"; |
| } |
| |
| /* Language feature: insert declaration of an uniform block holding an incorrectly named member variable */ |
| if (language_feature == LANGUAGE_FEATURE_UNIFORM_BLOCK_MEMBER_NAME) |
| { |
| body_sstream << "uniform testBlock\n" |
| "{\n" |
| " vec4 " |
| << invalid_name << ";\n" |
| "};\n"; |
| } |
| |
| /* Language feature: insert declaration of an incorrectly named uniform block */ |
| if (language_feature == LANGUAGE_FEATURE_UNIFORM_BLOCK_NAME) |
| { |
| body_sstream << "uniform " << invalid_name << "\n" |
| "{\n" |
| " vec4 test;\n" |
| "};\n"; |
| } |
| |
| /* Language feature: insert declaration of an incorrectly named varying */ |
| if (language_feature == LANGUAGE_FEATURE_VARYING) |
| { |
| body_sstream << "varying vec4 " << invalid_name << ";\n"; |
| } |
| |
| /* Start implementation of the main entry-point. */ |
| body_sstream << "void main()\n" |
| "{\n"; |
| |
| /* Language feature: insert declaration of an incorrectly named shared variable. */ |
| if (language_feature == LANGUAGE_FEATURE_SHARED_VARIABLE) |
| { |
| body_sstream << "shared vec4 " << invalid_name << ";\n"; |
| } |
| |
| /* Language feature: insert declaration of a structure, whose instance name is incorrect */ |
| if (language_feature == LANGUAGE_FEATURE_STRUCTURE_INSTANCE_NAME) |
| { |
| body_sstream << "struct\n" |
| "{\n" |
| " vec4 test;\n" |
| "} " |
| << invalid_name << ";\n"; |
| } |
| |
| /* Language feature: insert declaration of a structure with one of its member variables being incorrectly named. */ |
| if (language_feature == LANGUAGE_FEATURE_STRUCTURE_MEMBER) |
| { |
| body_sstream << "struct\n" |
| "{\n" |
| " vec4 " |
| << invalid_name << ";\n" |
| "} testInstance;\n"; |
| } |
| |
| /* Language feature: insert declaration of a structure whose name is incorrect */ |
| if (language_feature == LANGUAGE_FEATURE_STRUCTURE_NAME) |
| { |
| body_sstream << "struct " << invalid_name << "{\n" |
| " vec4 test;\n" |
| << "};\n"; |
| } |
| |
| /* Language feature: insert declaration of a variable with incorrect name. */ |
| if (language_feature == LANGUAGE_FEATURE_VARIABLE) |
| { |
| body_sstream << "vec4 " << invalid_name << ";\n"; |
| } |
| |
| /* Close the main entry-point implementation */ |
| body_sstream << "}\n"; |
| |
| return body_sstream.str(); |
| } |
| |
| /** Retrieves a literal corresponding to the user-specified shader type value. |
| * |
| * @param shader_type Enum to return the string for. |
| * |
| * @return As specified. |
| */ |
| std::string ReservedNamesTest::getShaderTypeName(_shader_type shader_type) const |
| { |
| std::string result = "[?!]"; |
| |
| switch (shader_type) |
| { |
| case SHADER_TYPE_COMPUTE: |
| result = "compute shader"; |
| break; |
| case SHADER_TYPE_FRAGMENT: |
| result = "fragment shader"; |
| break; |
| case SHADER_TYPE_GEOMETRY: |
| result = "geometry shader"; |
| break; |
| case SHADER_TYPE_TESS_CONTROL: |
| result = "tessellation control shader"; |
| break; |
| case SHADER_TYPE_TESS_EVALUATION: |
| result = "tessellation evaluation shader"; |
| break; |
| case SHADER_TYPE_VERTEX: |
| result = "vertex shader"; |
| break; |
| default: |
| result = "unknown"; |
| break; |
| } /* switch (shader_type) */ |
| |
| return result; |
| } |
| |
| /** Returns a vector of _language_feature enums, telling which language features are supported, given running context's |
| * version and shader type, in which the features are planned to be used. |
| * |
| * @param shader_type Shader stage the language features will be used in. |
| * |
| * @return As specified. |
| **/ |
| std::vector<ReservedNamesTest::_language_feature> ReservedNamesTest::getSupportedLanguageFeatures( |
| _shader_type shader_type) const |
| { |
| const glu::ContextType context_type = m_context.getRenderContext().getType(); |
| std::vector<_language_feature> result; |
| |
| /* Atomic counters are available, starting with GL 4.2. Availability for each shader stage |
| * depends on the reported GL constant values, apart from CS & FS, for which AC support is guaranteed. |
| */ |
| if (glu::contextSupports(context_type, glu::ApiType::core(4, 2))) |
| { |
| if (shader_type == SHADER_TYPE_COMPUTE || shader_type == SHADER_TYPE_FRAGMENT || |
| (shader_type == SHADER_TYPE_GEOMETRY && m_max_gs_acs > 0) || |
| (shader_type == SHADER_TYPE_TESS_CONTROL && m_max_tc_acs > 0) || |
| (shader_type == SHADER_TYPE_TESS_EVALUATION && m_max_te_acs > 0) || |
| (shader_type == SHADER_TYPE_VERTEX && m_max_vs_acs)) |
| { |
| result.push_back(LANGUAGE_FEATURE_ATOMIC_COUNTER); |
| } |
| } /* if (context_type >= glu::CONTEXTTYPE_GL43_CORE) */ |
| |
| /* Attributes are only supported until GL 4.1, for VS shader stage only. */ |
| if (shader_type == SHADER_TYPE_VERTEX && !glu::contextSupports(context_type, glu::ApiType::core(4, 2))) |
| { |
| result.push_back(LANGUAGE_FEATURE_ATTRIBUTE); |
| } |
| |
| /* Constants are always supported */ |
| result.push_back(LANGUAGE_FEATURE_CONSTANT); |
| |
| /* Functions are supported in all GL SL versions for all shader types. */ |
| result.push_back(LANGUAGE_FEATURE_FUNCTION_ARGUMENT_NAME); |
| result.push_back(LANGUAGE_FEATURE_FUNCTION_NAME); |
| |
| /* Inputs are supported in all GL SL versions for FS, GS, TC, TE and VS stages */ |
| if (shader_type == SHADER_TYPE_FRAGMENT || shader_type == SHADER_TYPE_GEOMETRY || |
| shader_type == SHADER_TYPE_TESS_CONTROL || shader_type == SHADER_TYPE_TESS_EVALUATION || |
| shader_type == SHADER_TYPE_VERTEX) |
| { |
| result.push_back(LANGUAGE_FEATURE_INPUT); |
| } |
| |
| /* Input blocks are available, starting with GL 3.2 for FS, GS, TC and TE stages. */ |
| if ((shader_type == SHADER_TYPE_FRAGMENT || shader_type == SHADER_TYPE_GEOMETRY || |
| shader_type == SHADER_TYPE_TESS_CONTROL || shader_type == SHADER_TYPE_TESS_EVALUATION || |
| shader_type == SHADER_TYPE_VERTEX) && |
| glu::contextSupports(context_type, glu::ApiType::core(3, 2))) |
| { |
| result.push_back(LANGUAGE_FEATURE_INPUT_BLOCK_INSTANCE_NAME); |
| result.push_back(LANGUAGE_FEATURE_INPUT_BLOCK_MEMBER_NAME); |
| result.push_back(LANGUAGE_FEATURE_INPUT_BLOCK_NAME); |
| } |
| |
| /* Outputs are supported in all GL SL versions for all shader stages expect CS */ |
| if (shader_type != SHADER_TYPE_COMPUTE) |
| { |
| result.push_back(LANGUAGE_FEATURE_OUTPUT); |
| } |
| |
| /* Output blocks are available, starting with GL 3.2 for GS, TC, TE and VS stages. */ |
| if ((shader_type == SHADER_TYPE_GEOMETRY || shader_type == SHADER_TYPE_TESS_CONTROL || |
| shader_type == SHADER_TYPE_TESS_EVALUATION || shader_type == SHADER_TYPE_VERTEX) && |
| glu::contextSupports(context_type, glu::ApiType::core(3, 2))) |
| { |
| result.push_back(LANGUAGE_FEATURE_OUTPUT_BLOCK_INSTANCE_NAME); |
| result.push_back(LANGUAGE_FEATURE_OUTPUT_BLOCK_MEMBER_NAME); |
| result.push_back(LANGUAGE_FEATURE_OUTPUT_BLOCK_NAME); |
| } |
| |
| /* Shader storage blocks are available, starting with GL 4.3. Availability for each shader stage |
| * depends on the reported GL constant values, apart from CS, for which SSBO support is guaranteed. |
| */ |
| if (glu::contextSupports(context_type, glu::ApiType::core(4, 3))) |
| { |
| if (shader_type == SHADER_TYPE_COMPUTE || (shader_type == SHADER_TYPE_FRAGMENT && m_max_fs_ssbos > 0) || |
| (shader_type == SHADER_TYPE_GEOMETRY && m_max_gs_ssbos > 0) || |
| (shader_type == SHADER_TYPE_TESS_CONTROL && m_max_tc_ssbos > 0) || |
| (shader_type == SHADER_TYPE_TESS_EVALUATION && m_max_te_ssbos > 0) || |
| (shader_type == SHADER_TYPE_VERTEX && m_max_vs_ssbos)) |
| { |
| result.push_back(LANGUAGE_FEATURE_SHADER_STORAGE_BLOCK_INSTANCE_NAME); |
| result.push_back(LANGUAGE_FEATURE_SHADER_STORAGE_BLOCK_MEMBER_NAME); |
| result.push_back(LANGUAGE_FEATURE_SHADER_STORAGE_BLOCK_NAME); |
| } |
| } /* if (context_type >= glu::CONTEXTTYPE_GL43_CORE) */ |
| |
| /* Shared variables are only supported for compute shaders */ |
| if (shader_type == SHADER_TYPE_COMPUTE) |
| { |
| result.push_back(LANGUAGE_FEATURE_SHARED_VARIABLE); |
| } |
| |
| /* Structures are available everywhere, and so are structures. */ |
| result.push_back(LANGUAGE_FEATURE_STRUCTURE_INSTANCE_NAME); |
| result.push_back(LANGUAGE_FEATURE_STRUCTURE_MEMBER); |
| result.push_back(LANGUAGE_FEATURE_STRUCTURE_NAME); |
| |
| /* Subroutines are available, starting with GL 4.0, for all shader stages except CS */ |
| if (glu::contextSupports(context_type, glu::ApiType::core(4, 0))) |
| { |
| if (shader_type != SHADER_TYPE_COMPUTE) |
| { |
| result.push_back(LANGUAGE_FEATURE_SUBROUTINE_FUNCTION_NAME); |
| result.push_back(LANGUAGE_FEATURE_SUBROUTINE_TYPE); |
| result.push_back(LANGUAGE_FEATURE_SUBROUTINE_UNIFORM); |
| } |
| } /* if (context_type >= glu::CONTEXTTYPE_GL40_CORE) */ |
| |
| /* Uniform blocks and uniforms are available everywhere, for all shader stages except CS */ |
| if (shader_type != SHADER_TYPE_COMPUTE) |
| { |
| result.push_back(LANGUAGE_FEATURE_UNIFORM_BLOCK_INSTANCE_NAME); |
| result.push_back(LANGUAGE_FEATURE_UNIFORM_BLOCK_MEMBER_NAME); |
| result.push_back(LANGUAGE_FEATURE_UNIFORM_BLOCK_NAME); |
| |
| result.push_back(LANGUAGE_FEATURE_UNIFORM); |
| } |
| |
| /* Variables are available, well, everywhere. */ |
| result.push_back(LANGUAGE_FEATURE_VARIABLE); |
| |
| /* Varyings are supported until GL 4.2 for FS and VS shader stages. Starting with GL 4.3, |
| * they are no longer legal. */ |
| if ((shader_type == SHADER_TYPE_FRAGMENT || shader_type == SHADER_TYPE_VERTEX) && |
| !glu::contextSupports(context_type, glu::ApiType::core(4, 3))) |
| { |
| result.push_back(LANGUAGE_FEATURE_VARYING); |
| } |
| |
| return result; |
| } |
| |
| /** Returns a vector of _shader_type enums, telling which shader stages are supported |
| * under running rendering context. For simplicity, the function ignores any extensions |
| * which extend the core functionality |
| * |
| * @return As specified. |
| */ |
| std::vector<ReservedNamesTest::_shader_type> ReservedNamesTest::getSupportedShaderTypes() const |
| { |
| const glu::ContextType context_type = m_context.getRenderContext().getType(); |
| std::vector<_shader_type> result; |
| |
| /* CS: Available, starting with GL 4.3 */ |
| if (glu::contextSupports(context_type, glu::ApiType::core(4, 3))) |
| { |
| result.push_back(SHADER_TYPE_COMPUTE); |
| } |
| |
| /* FS: Always supported */ |
| result.push_back(SHADER_TYPE_FRAGMENT); |
| |
| /* GS: Available, starting with GL 3.2 */ |
| if (glu::contextSupports(context_type, glu::ApiType::core(3, 2))) |
| { |
| result.push_back(SHADER_TYPE_GEOMETRY); |
| } |
| |
| /* TC: Available, starting with GL 4.0 */ |
| /* TE: Available, starting with GL 4.0 */ |
| if (glu::contextSupports(context_type, glu::ApiType::core(4, 0))) |
| { |
| result.push_back(SHADER_TYPE_TESS_CONTROL); |
| result.push_back(SHADER_TYPE_TESS_EVALUATION); |
| } |
| |
| /* VS: Always supported */ |
| result.push_back(SHADER_TYPE_VERTEX); |
| |
| return result; |
| } |
| |
| bool ReservedNamesTest::isStructAllowed(_shader_type shader_type, _language_feature language_feature) const |
| { |
| bool structAllowed = false; |
| |
| if (language_feature == LANGUAGE_FEATURE_UNIFORM || language_feature == LANGUAGE_FEATURE_UNIFORM_BLOCK_NAME) |
| { |
| return true; |
| } |
| |
| switch (shader_type) |
| { |
| case SHADER_TYPE_FRAGMENT: |
| { |
| if (language_feature == LANGUAGE_FEATURE_INPUT_BLOCK_NAME) |
| { |
| structAllowed = true; |
| } |
| } |
| break; |
| case SHADER_TYPE_GEOMETRY: |
| case SHADER_TYPE_TESS_CONTROL: |
| case SHADER_TYPE_TESS_EVALUATION: |
| { |
| if (language_feature == LANGUAGE_FEATURE_OUTPUT_BLOCK_NAME) |
| { |
| structAllowed = true; |
| } |
| else if (language_feature == LANGUAGE_FEATURE_INPUT_BLOCK_NAME) |
| { |
| structAllowed = true; |
| } |
| } |
| break; |
| case SHADER_TYPE_VERTEX: |
| { |
| if (language_feature == LANGUAGE_FEATURE_OUTPUT_BLOCK_NAME) |
| { |
| structAllowed = true; |
| } |
| } |
| break; |
| case SHADER_TYPE_COMPUTE: |
| default: |
| break; |
| } |
| |
| return structAllowed; |
| } |
| |
| /** Empty init function */ |
| void ReservedNamesTest::init() |
| { |
| /* Left blank on purpose */ |
| } |
| |
| /** Executes test iteration. |
| * |
| * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. |
| */ |
| tcu::TestNode::IterateResult ReservedNamesTest::iterate() |
| { |
| glw::GLint compile_status = GL_TRUE; |
| glu::ContextType context_type = m_context.getRenderContext().getType(); |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| std::vector<_language_feature> language_features; |
| std::vector<std::string> reserved_names; |
| bool result = true; |
| std::vector<_shader_type> shader_types; |
| |
| /* Retrieve important GL constant values */ |
| if (glu::contextSupports(context_type, glu::ApiType::core(4, 2))) |
| { |
| gl.getIntegerv(GL_MAX_GEOMETRY_ATOMIC_COUNTERS, &m_max_gs_acs); |
| gl.getIntegerv(GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS, &m_max_tc_acs); |
| gl.getIntegerv(GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS, &m_max_te_acs); |
| gl.getIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTERS, &m_max_vs_acs); |
| } |
| |
| if (glu::contextSupports(context_type, glu::ApiType::core(4, 3))) |
| { |
| gl.getIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &m_max_fs_ssbos); |
| gl.getIntegerv(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, &m_max_gs_ssbos); |
| gl.getIntegerv(GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, &m_max_tc_ssbos); |
| gl.getIntegerv(GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, &m_max_te_ssbos); |
| gl.getIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &m_max_vs_ssbos); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call(s) failed."); |
| } |
| |
| /* Create the shader objects */ |
| if (glu::contextSupports(context_type, glu::ApiType::core(4, 0))) |
| { |
| m_so_ids[SHADER_TYPE_TESS_CONTROL] = gl.createShader(GL_TESS_CONTROL_SHADER); |
| m_so_ids[SHADER_TYPE_TESS_EVALUATION] = gl.createShader(GL_TESS_EVALUATION_SHADER); |
| } |
| |
| if (glu::contextSupports(context_type, glu::ApiType::core(4, 3))) |
| { |
| m_so_ids[SHADER_TYPE_COMPUTE] = gl.createShader(GL_COMPUTE_SHADER); |
| } |
| |
| m_so_ids[SHADER_TYPE_FRAGMENT] = gl.createShader(GL_FRAGMENT_SHADER); |
| m_so_ids[SHADER_TYPE_GEOMETRY] = gl.createShader(GL_GEOMETRY_SHADER); |
| m_so_ids[SHADER_TYPE_VERTEX] = gl.createShader(GL_VERTEX_SHADER); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); |
| |
| /* Retrieve context version-specific data */ |
| reserved_names = getReservedNames(); |
| shader_types = getSupportedShaderTypes(); |
| |
| /* Iterate over all supported shader stages.. */ |
| for (std::vector<_shader_type>::const_iterator shader_type_it = shader_types.begin(); |
| shader_type_it != shader_types.end(); ++shader_type_it) |
| { |
| _shader_type current_shader_type = *shader_type_it; |
| |
| if (m_so_ids[current_shader_type] == 0) |
| { |
| /* Skip stages not supported by the currently running context version. */ |
| continue; |
| } |
| |
| language_features = getSupportedLanguageFeatures(current_shader_type); |
| |
| /* ..and all language features we can test for the running context */ |
| for (std::vector<_language_feature>::const_iterator language_feature_it = language_features.begin(); |
| language_feature_it != language_features.end(); ++language_feature_it) |
| { |
| _language_feature current_language_feature = *language_feature_it; |
| |
| bool structAllowed = isStructAllowed(current_shader_type, current_language_feature); |
| |
| /* Finally, all the reserved names we need to test - loop over them at this point */ |
| for (std::vector<std::string>::const_iterator reserved_name_it = reserved_names.begin(); |
| reserved_name_it != reserved_names.end(); ++reserved_name_it) |
| { |
| std::string current_invalid_name = *reserved_name_it; |
| std::string so_body_string; |
| const char* so_body_string_raw = NULL; |
| |
| // There are certain shader types that allow struct for in/out declarations |
| if (structAllowed && current_invalid_name.compare("struct") == 0) |
| { |
| continue; |
| } |
| |
| /* Form the shader body */ |
| so_body_string = |
| getShaderBody(current_shader_type, current_language_feature, current_invalid_name.c_str()); |
| so_body_string_raw = so_body_string.c_str(); |
| |
| /* Try to compile the shader */ |
| gl.shaderSource(m_so_ids[current_shader_type], 1, /* count */ |
| &so_body_string_raw, NULL); /* length */ |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); |
| |
| gl.compileShader(m_so_ids[current_shader_type]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); |
| |
| gl.getShaderiv(m_so_ids[current_shader_type], GL_COMPILE_STATUS, &compile_status); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); |
| |
| /* Left for the debugging purposes for those in need .. */ |
| #if 0 |
| char temp[4096]; |
| |
| gl.getShaderInfoLog(m_so_ids[current_shader_type], |
| 4096, |
| NULL, |
| temp); |
| |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "\n" |
| "-----------------------------\n" |
| "Shader:\n" |
| ">>\n" |
| << so_body_string_raw |
| << "\n<<\n" |
| "\n" |
| "Info log:\n" |
| ">>\n" |
| << temp |
| << "\n<<\n\n" |
| << tcu::TestLog::EndMessage; |
| #endif |
| |
| if (compile_status != GL_FALSE) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "A " |
| << getLanguageFeatureName(current_language_feature) << " named [" |
| << current_invalid_name << "]" |
| << ", defined in " << getShaderTypeName(current_shader_type) |
| << ", was accepted by the compiler, " |
| "which is prohibited by the spec. Offending source code:\n" |
| ">>\n" |
| << so_body_string_raw << "\n<<\n\n" |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| |
| } /* for (all reserved names for the current context) */ |
| } /* for (all language features supported by the context) */ |
| } /* for (all shader types supported by the context) */ |
| |
| m_testCtx.setTestResult(result ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, result ? "Pass" : "Fail"); |
| |
| return STOP; |
| } |
| |
| /** Constructor. |
| * |
| * @param context Rendering context |
| * @param name Test name |
| * @param description Test description |
| */ |
| SparseBuffersWithCopyOpsTest::SparseBuffersWithCopyOpsTest(deqp::Context& context) |
| : TestCase(context, "CommonBug_SparseBuffersWithCopyOps", |
| "Verifies sparse buffer functionality works correctly when CPU->GPU and GPU->GPU" |
| " memory transfers are involved.") |
| , m_bo_id(0) |
| , m_bo_read_id(0) |
| , m_clear_buffer(DE_NULL) |
| , m_page_size(0) |
| , m_result_data_storage_size(0) |
| , m_n_iterations_to_run(16) |
| , m_n_pages_to_test(16) |
| , m_virtual_bo_size(512 /* MB */ * 1024768) |
| { |
| for (unsigned int n = 0; n < sizeof(m_reference_data) / sizeof(m_reference_data[0]); ++n) |
| { |
| m_reference_data[n] = static_cast<unsigned char>(n); |
| } |
| } |
| |
| /** Deinitializes all GL objects created for the purpose of running the test, |
| * as well as any client-side buffers allocated at initialization time |
| */ |
| void SparseBuffersWithCopyOpsTest::deinit() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| if (m_bo_id != 0) |
| { |
| gl.deleteBuffers(1, &m_bo_id); |
| |
| m_bo_id = 0; |
| } |
| |
| if (m_bo_read_id != 0) |
| { |
| gl.deleteBuffers(1, &m_bo_read_id); |
| |
| m_bo_read_id = 0; |
| } |
| |
| if (m_clear_buffer != DE_NULL) |
| { |
| delete[] m_clear_buffer; |
| |
| m_clear_buffer = DE_NULL; |
| } |
| } |
| |
| /** Empty init function */ |
| void SparseBuffersWithCopyOpsTest::init() |
| { |
| /* Nothing to do here */ |
| } |
| |
| /** Initializes all buffers and GL objects required to run the test. */ |
| bool SparseBuffersWithCopyOpsTest::initTest() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| bool result = true; |
| |
| /* Retrieve the platform-specific page size */ |
| gl.getIntegerv(GL_SPARSE_BUFFER_PAGE_SIZE_ARB, &m_page_size); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_SPARSE_BUFFER_PAGE_SIZE_ARB query"); |
| |
| /* Retrieve the func ptr */ |
| if (gl.bufferPageCommitmentARB == NULL) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "Could not retrieve function pointer for the glBufferPageCommitmentARB() entry-point." |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| goto end; |
| } |
| |
| /* Set up the test sparse buffer object */ |
| gl.genBuffers(1, &m_bo_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed."); |
| |
| gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed."); |
| |
| gl.bufferStorage(GL_ARRAY_BUFFER, m_virtual_bo_size, DE_NULL, /* data */ |
| GL_DYNAMIC_STORAGE_BIT | GL_SPARSE_STORAGE_BIT_ARB); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferStorage() call failed."); |
| |
| /* Set up the buffer object that will be used to read the result data */ |
| m_result_data_storage_size = static_cast<unsigned int>( |
| (m_page_size * m_n_pages_to_test / sizeof(m_reference_data)) * sizeof(m_reference_data)); |
| m_clear_buffer = new unsigned char[m_result_data_storage_size]; |
| |
| memset(m_clear_buffer, 0, m_result_data_storage_size); |
| |
| gl.genBuffers(1, &m_bo_read_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed."); |
| |
| gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bo_read_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed."); |
| |
| gl.bufferStorage(GL_ELEMENT_ARRAY_BUFFER, m_result_data_storage_size, NULL, /* data */ |
| GL_DYNAMIC_STORAGE_BIT | GL_MAP_READ_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferStorage() call failed."); |
| |
| end: |
| return result; |
| } |
| |
| /** Executes test iteration. |
| * |
| * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. |
| */ |
| tcu::TestNode::IterateResult SparseBuffersWithCopyOpsTest::iterate() |
| { |
| bool result = true; |
| |
| /* Execute the test */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Only execute if we're dealing with an OpenGL implementation which supports both: |
| * |
| * 1. GL_ARB_sparse_buffer extension |
| * 2. GL_ARB_buffer_storage extension |
| */ |
| if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_buffer") || |
| !m_context.getContextInfo().isExtensionSupported("GL_ARB_buffer_storage")) |
| { |
| goto end; |
| } |
| |
| /* Set up the test objects */ |
| if (!initTest()) |
| { |
| result = false; |
| |
| goto end; |
| } |
| for (unsigned int n_test_case = 0; n_test_case < 2; ++n_test_case) |
| { |
| for (unsigned int n_iteration = 0; n_iteration < m_n_iterations_to_run; ++n_iteration) |
| { |
| if (n_iteration != 0) |
| { |
| gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, /* offset */ |
| m_n_pages_to_test * m_page_size, GL_FALSE); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferPageCommitmentARB() call failed."); |
| } |
| |
| gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, 0, /* offset */ |
| m_page_size, GL_TRUE); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferPageCommitmentARB() call failed."); |
| |
| gl.bufferSubData(GL_ARRAY_BUFFER, 0, /* offset */ |
| sizeof(m_reference_data), m_reference_data); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed."); |
| |
| for (unsigned int n_page = 0; n_page < m_n_pages_to_test; ++n_page) |
| { |
| /* Try committing pages in a redundant manner. This is a legal behavior in light of |
| * the GL_ARB_sparse_buffer spec */ |
| gl.bufferPageCommitmentARB(GL_ARRAY_BUFFER, n_page * m_page_size, m_page_size, GL_TRUE); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferPageCommitmentARB() call failed."); |
| |
| for (int copy_dst_page_offset = static_cast<int>((n_page == 0) ? sizeof(m_reference_data) : 0); |
| copy_dst_page_offset < static_cast<int>(m_page_size); |
| copy_dst_page_offset += static_cast<int>(sizeof(m_reference_data))) |
| { |
| const int copy_src_page_offset = |
| static_cast<int>(copy_dst_page_offset - sizeof(m_reference_data)); |
| |
| switch (n_test_case) |
| { |
| case 0: |
| { |
| gl.copyBufferSubData(GL_ARRAY_BUFFER, GL_ARRAY_BUFFER, |
| n_page * m_page_size + copy_src_page_offset, |
| n_page * m_page_size + copy_dst_page_offset, sizeof(m_reference_data)); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCopyBufferSubData() call failed."); |
| |
| break; |
| } |
| |
| case 1: |
| { |
| gl.bufferSubData(GL_ARRAY_BUFFER, n_page * m_page_size + copy_dst_page_offset, |
| sizeof(m_reference_data), m_reference_data); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed."); |
| |
| break; |
| } |
| |
| default: |
| TCU_FAIL("Unrecognized test case index"); |
| } /* switch (n_test_case) */ |
| } /* for (all valid destination copy op offsets) */ |
| } /* for (all test pages) */ |
| |
| /* Copy data from the sparse buffer to a mappable immutable buffer storage */ |
| gl.copyBufferSubData(GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER, 0, /* readOffset */ |
| 0, /* writeOffset */ |
| m_result_data_storage_size); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCopyBufferSubData() call failed."); |
| |
| /* Map the data we have obtained */ |
| char* mapped_data = (char*)gl.mapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, /* offset */ |
| m_page_size * m_n_pages_to_test, GL_MAP_READ_BIT); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed."); |
| |
| /* Verify the data is valid */ |
| for (unsigned int n_temp_copy = 0; n_temp_copy < m_result_data_storage_size / sizeof(m_reference_data); |
| ++n_temp_copy) |
| { |
| const unsigned int cmp_offset = static_cast<unsigned int>(n_temp_copy * sizeof(m_reference_data)); |
| |
| if (memcmp(mapped_data + cmp_offset, m_reference_data, sizeof(m_reference_data)) != 0) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Invalid data found for page index " |
| "[" |
| << (cmp_offset / m_page_size) << "]" |
| ", BO data offset:" |
| "[" |
| << cmp_offset << "]." << tcu::TestLog::EndMessage; |
| |
| result = false; |
| goto end; |
| } |
| } /* for (all datasets) */ |
| |
| /* Clean up */ |
| gl.unmapBuffer(GL_ELEMENT_ARRAY_BUFFER); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed."); |
| |
| /* Also, zero out the other buffer object we copy the result data to, in case |
| * the glCopyBufferSubData() call does not modify it at all */ |
| gl.bufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, /* offset */ |
| m_result_data_storage_size, m_clear_buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed."); |
| |
| /* NOTE: This test passes fine on the misbehaving driver *if* the swapbuffers operation |
| * issued as a part of the call below is not executed. */ |
| m_context.getRenderContext().postIterate(); |
| } /* for (all test iterations) */ |
| } /* for (all test cases) */ |
| |
| end: |
| m_testCtx.setTestResult(result ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, result ? "Pass" : "Fail"); |
| |
| return STOP; |
| } |
| |
| /** Constructor. |
| * |
| * @param context Rendering context. |
| */ |
| CommonBugsTests::CommonBugsTests(deqp::Context& context) |
| : TestCaseGroup(context, "CommonBugs", "Contains conformance tests that verify various pieces of functionality" |
| " which were found broken in public drivers.") |
| { |
| } |
| |
| /** Initializes the test group contents. */ |
| void CommonBugsTests::init() |
| { |
| addChild(new GetProgramivActiveUniformBlockMaxNameLengthTest(m_context)); |
| addChild(new InputVariablesCannotBeModifiedTest(m_context)); |
| addChild(new InvalidUseCasesForAllNotFuncsAndExclMarkOpTest(m_context)); |
| addChild(new InvalidVSInputsTest(m_context)); |
| addChild(new ParenthesisInLayoutQualifierIntegerValuesTest(m_context)); |
| addChild(new PerVertexValidationTest(m_context)); |
| addChild(new ReservedNamesTest(m_context)); |
| addChild(new SparseBuffersWithCopyOpsTest(m_context)); |
| } |
| } /* glcts namespace */ |