blob: 1668054f4c228d0d6a0d77c5d561ebccb0834eed [file] [log] [blame]
/*-------------------------------------------------------------------------
* 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 <cstring>
#include <stddef.h>
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 */