/*------------------------------------------------------------------------- * OpenGL Conformance Test Suite * ----------------------------- * * Copyright (c) 2014-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 esextcTextureBufferPrecision.hpp * \brief Texture Buffer Precision Qualifier (Test 10) */ /*-------------------------------------------------------------------*/ #include "esextcTextureBufferPrecision.hpp" #include "gluContextInfo.hpp" #include "gluDefs.hpp" #include "gluShaderUtil.hpp" #include "glwEnums.hpp" #include "glwFunctions.hpp" #include "tcuTestLog.hpp" #include #include namespace glcts { /* Head of the compute shader. */ const char* const TextureBufferPrecision::m_cs_code_head = "${VERSION}\n" "\n" "${TEXTURE_BUFFER_REQUIRE}\n" "\n"; /* Variables declarations for the compute shader without usage of the precision qualifier. */ const char* const TextureBufferPrecision::m_cs_code_declaration_without_precision[3] = { "layout (r32f) uniform imageBuffer image_buffer;\n" "\n" "buffer ComputeSSBO\n" "{\n" " float value;\n" "} computeSSBO;\n", "layout (r32i) uniform iimageBuffer image_buffer;\n" "\n" "buffer ComputeSSBO\n" "{\n" " int value;\n" "} computeSSBO;\n", "layout (r32ui) uniform uimageBuffer image_buffer;\n" "\n" "buffer ComputeSSBO\n" "{\n" " uint value;\n" "} computeSSBO;\n" }; /* Variables declarations for the compute shader with usage of the precision qualifier. */ const char* const TextureBufferPrecision::m_cs_code_declaration_with_precision[3] = { "layout (r32f) uniform highp imageBuffer image_buffer;\n" "\n" "buffer ComputeSSBO\n" "{\n" " float value;\n" "} computeSSBO;\n", "layout (r32i) uniform highp iimageBuffer image_buffer;\n" "\n" "buffer ComputeSSBO\n" "{\n" " int value;\n" "} computeSSBO;\n", "layout (r32ui) uniform highp uimageBuffer image_buffer;\n" "\n" "buffer ComputeSSBO\n" "{\n" " uint value;\n" "} computeSSBO;\n" }; /* The default precision qualifier declarations for the compute shader. */ const char* const TextureBufferPrecision::m_cs_code_global_precision[3] = { "precision highp imageBuffer;\n", "precision highp iimageBuffer;\n", "precision highp uimageBuffer;\n" }; /* The compute shader body. */ const char* const TextureBufferPrecision::m_cs_code_body = "\n" "void main()\n" "{\n" " computeSSBO.value = imageLoad(image_buffer, 0).x;\n" "}"; /* Head of the fragment shader. */ const char* const TextureBufferPrecision::m_fs_code_head = "${VERSION}\n" "\n" "${TEXTURE_BUFFER_REQUIRE}\n" "\n"; /* Variables declarations for the fragment shader without usage of the precision qualifier. */ const char* const TextureBufferPrecision::m_fs_code_declaration_without_precision[3] = { "uniform samplerBuffer sampler_buffer;\n" "\n" "layout(location = 0) out highp vec4 color;\n", "uniform isamplerBuffer sampler_buffer;\n" "\n" "layout(location = 0) out highp ivec4 color;\n", "uniform usamplerBuffer sampler_buffer;\n" "\n" "layout(location = 0) out highp uvec4 color;\n" }; /* Variables declarations for the fragment shader with usage of the precision qualifier. */ const char* const TextureBufferPrecision::m_fs_code_declaration_with_precision[3] = { "uniform highp samplerBuffer sampler_buffer;\n" "\n" "layout(location = 0) out highp vec4 color;\n", "uniform highp isamplerBuffer sampler_buffer;\n" "\n" "layout(location = 0) out highp ivec4 color;\n", "uniform highp usamplerBuffer sampler_buffer;\n" "\n" "layout(location = 0) out highp uvec4 color;\n", }; /* The default precision qualifier declarations for the fragment shader. */ const char* const TextureBufferPrecision::m_fs_code_global_precision[3] = { "precision highp samplerBuffer;\n", "precision highp isamplerBuffer;\n", "precision highp usamplerBuffer;\n", }; /* The fragment shader body. */ const char* const TextureBufferPrecision::m_fs_code_body = "\n" "void main()\n" "{\n" " color = texelFetch( sampler_buffer, 0 );\n" "}"; /** Constructor * * @param context Test context * @param name Test case's name * @param description Test case's description **/ TextureBufferPrecision::TextureBufferPrecision(Context& context, const ExtParameters& extParams, const char* name, const char* description) : TestCaseBase(context, extParams, name, description), m_po_id(0), m_sh_id(0) { //Bug-15063 Only GLSL 4.50 supports opaque types if (m_glslVersion >= glu::GLSL_VERSION_130) { m_glslVersion = glu::GLSL_VERSION_450; } } /** Deinitializes GLES objects created during the test */ void TextureBufferPrecision::deinit(void) { /* Retrieve GLES entry points. */ const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Delete GLES objects */ if (m_po_id != 0) { gl.deleteProgram(m_po_id); m_po_id = 0; } if (m_sh_id != 0) { gl.deleteShader(m_sh_id); m_sh_id = 0; } /* Deinitialize base class */ TestCaseBase::deinit(); } /** Check if the shader compiles. * * Note the function throws exception should an error occur! * * @param shader_type GL shader type. * @param sh_code_parts Shader source parts * @param parts_count Shader source parts count * * @return true if the shader compiles, return false otherwise. **/ glw::GLboolean TextureBufferPrecision::verifyShaderCompilationStatus(glw::GLenum shader_type, const char** sh_code_parts, const glw::GLuint parts_count, const glw::GLint expected_status) { /* Retrieve GLES entry points. */ const glw::Functions& gl = m_context.getRenderContext().getFunctions(); glw::GLboolean test_passed = true; m_po_id = gl.createProgram(); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create program object"); m_sh_id = gl.createShader(shader_type); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object"); std::string shader_code = specializeShader(parts_count, sh_code_parts); const char* shader_code_ptr = shader_code.c_str(); gl.shaderSource(m_sh_id, 1, &shader_code_ptr, DE_NULL); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set shader source"); gl.compileShader(m_sh_id); GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to perform compilation of shader object"); /* Retrieving compilation status */ glw::GLint compilation_status = GL_FALSE; gl.getShaderiv(m_sh_id, GL_COMPILE_STATUS, &compilation_status); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve shader compilation status"); if (compilation_status != expected_status) { test_passed = false; glw::GLsizei info_log_length = 0; gl.getShaderiv(m_sh_id, GL_INFO_LOG_LENGTH, &info_log_length); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not get shader info log length"); if (info_log_length > 0) { glw::GLchar* info_log = new glw::GLchar[info_log_length]; memset(info_log, 0, info_log_length * sizeof(glw::GLchar)); gl.getShaderInfoLog(m_sh_id, info_log_length, DE_NULL, info_log); m_testCtx.getLog() << tcu::TestLog::Message << "The following shader:\n\n" << shader_code << "\n\n did compile with result different than expected:\n" << expected_status << "\n\n Compilation info log: \n" << info_log << "\n" << tcu::TestLog::EndMessage; delete[] info_log; GLU_EXPECT_NO_ERROR(gl.getError(), "Could not get shader info log"); } } /* Clean up */ if (m_po_id != 0) { gl.deleteProgram(m_po_id); m_po_id = 0; } if (m_sh_id != 0) { gl.deleteShader(m_sh_id); m_sh_id = 0; } return test_passed; } /** Executes the test. * * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. * * Note the function throws exception should an error occur! * * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. **/ tcu::TestNode::IterateResult TextureBufferPrecision::iterate(void) { /* Skip if required extensions are not supported. */ if (!m_is_texture_buffer_supported) { throw tcu::NotSupportedError(TEXTURE_BUFFER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); } glu::ContextType contextType = m_context.getRenderContext().getType(); glw::GLboolean test_passed = true; glw::GLint expected_fail = glu::glslVersionIsES(m_glslVersion) ? GL_FALSE : GL_TRUE; /* Default precision qualifiers for opaque types are not supported prior to GLSL 4.50. */ if (glu::contextSupports(contextType, glu::ApiType::core(4, 5)) || glu::contextSupports(contextType, glu::ApiType::es(3, 1))) { /* Compute Shader Tests */ for (glw::GLuint i = 0; i < 3; ++i) /* For each from the set {imageBuffer, iimageBuffer, uimageBuffer} */ { const char* cs_code_without_precision[3] = { m_cs_code_head, m_cs_code_declaration_without_precision[i], m_cs_code_body }; const char* cs_code_with_precision[3] = { m_cs_code_head, m_cs_code_declaration_with_precision[i], m_cs_code_body }; const char* cs_code_with_global_precision[4] = { m_cs_code_head, m_cs_code_global_precision[i], m_cs_code_declaration_without_precision[i], m_cs_code_body }; test_passed = verifyShaderCompilationStatus(GL_COMPUTE_SHADER, cs_code_without_precision, 3, expected_fail) && test_passed; test_passed = verifyShaderCompilationStatus(GL_COMPUTE_SHADER, cs_code_with_precision, 3, GL_TRUE) && test_passed; test_passed = verifyShaderCompilationStatus(GL_COMPUTE_SHADER, cs_code_with_global_precision, 4, GL_TRUE) && test_passed; } } /* Fragment Shader Tests */ for (glw::GLuint i = 0; i < 3; ++i) /* For each from the set {samplerBuffer, isamplerBuffer, usamplerBuffer} */ { const char* fs_code_without_precision[3] = { m_fs_code_head, m_fs_code_declaration_without_precision[i], m_fs_code_body }; const char* fs_code_with_precision[3] = { m_fs_code_head, m_fs_code_declaration_with_precision[i], m_fs_code_body }; const char* fs_code_with_global_precision[4] = { m_fs_code_head, m_fs_code_global_precision[i], m_fs_code_declaration_without_precision[i], m_fs_code_body }; test_passed = verifyShaderCompilationStatus(GL_FRAGMENT_SHADER, fs_code_without_precision, 3, expected_fail) && test_passed; test_passed = verifyShaderCompilationStatus(GL_FRAGMENT_SHADER, fs_code_with_precision, 3, GL_TRUE) && test_passed; test_passed = verifyShaderCompilationStatus(GL_FRAGMENT_SHADER, fs_code_with_global_precision, 4, GL_TRUE) && test_passed; } if (test_passed) { m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); } else { m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); } return STOP; } } /* namespace glcts */