1 /*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2014-2016 The Khronos Group Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 */ /*! 20 * \file 21 * \brief 22 */ /*-------------------------------------------------------------------*/ 23 24 /*! 25 * \file esextcTextureBufferPrecision.hpp 26 * \brief Texture Buffer Precision Qualifier (Test 10) 27 */ /*-------------------------------------------------------------------*/ 28 29 #include "esextcTextureBufferPrecision.hpp" 30 #include "gluContextInfo.hpp" 31 #include "gluDefs.hpp" 32 #include "gluShaderUtil.hpp" 33 #include "glwEnums.hpp" 34 #include "glwFunctions.hpp" 35 #include "tcuTestLog.hpp" 36 #include <cstring> 37 #include <stddef.h> 38 39 namespace glcts 40 { 41 /* Head of the compute shader. */ 42 const char* const TextureBufferPrecision::m_cs_code_head = "${VERSION}\n" 43 "\n" 44 "${TEXTURE_BUFFER_REQUIRE}\n" 45 "\n"; 46 47 /* Variables declarations for the compute shader without usage of the precision qualifier. */ 48 const char* const TextureBufferPrecision::m_cs_code_declaration_without_precision[3] = { 49 "layout (r32f) uniform imageBuffer image_buffer;\n" 50 "\n" 51 "buffer ComputeSSBO\n" 52 "{\n" 53 " float value;\n" 54 "} computeSSBO;\n", 55 56 "layout (r32i) uniform iimageBuffer image_buffer;\n" 57 "\n" 58 "buffer ComputeSSBO\n" 59 "{\n" 60 " int value;\n" 61 "} computeSSBO;\n", 62 63 "layout (r32ui) uniform uimageBuffer image_buffer;\n" 64 "\n" 65 "buffer ComputeSSBO\n" 66 "{\n" 67 " uint value;\n" 68 "} computeSSBO;\n" 69 }; 70 71 /* Variables declarations for the compute shader with usage of the precision qualifier. */ 72 const char* const TextureBufferPrecision::m_cs_code_declaration_with_precision[3] = { 73 "layout (r32f) uniform highp imageBuffer image_buffer;\n" 74 "\n" 75 "buffer ComputeSSBO\n" 76 "{\n" 77 " float value;\n" 78 "} computeSSBO;\n", 79 80 "layout (r32i) uniform highp iimageBuffer image_buffer;\n" 81 "\n" 82 "buffer ComputeSSBO\n" 83 "{\n" 84 " int value;\n" 85 "} computeSSBO;\n", 86 87 "layout (r32ui) uniform highp uimageBuffer image_buffer;\n" 88 "\n" 89 "buffer ComputeSSBO\n" 90 "{\n" 91 " uint value;\n" 92 "} computeSSBO;\n" 93 }; 94 95 /* The default precision qualifier declarations for the compute shader. */ 96 const char* const TextureBufferPrecision::m_cs_code_global_precision[3] = { "precision highp imageBuffer;\n", 97 "precision highp iimageBuffer;\n", 98 "precision highp uimageBuffer;\n" }; 99 100 /* The compute shader body. */ 101 const char* const TextureBufferPrecision::m_cs_code_body = "\n" 102 "void main()\n" 103 "{\n" 104 " computeSSBO.value = imageLoad(image_buffer, 0).x;\n" 105 "}"; 106 107 /* Head of the fragment shader. */ 108 const char* const TextureBufferPrecision::m_fs_code_head = "${VERSION}\n" 109 "\n" 110 "${TEXTURE_BUFFER_REQUIRE}\n" 111 "\n"; 112 113 /* Variables declarations for the fragment shader without usage of the precision qualifier. */ 114 const char* const TextureBufferPrecision::m_fs_code_declaration_without_precision[3] = { 115 "uniform samplerBuffer sampler_buffer;\n" 116 "\n" 117 "layout(location = 0) out highp vec4 color;\n", 118 119 "uniform isamplerBuffer sampler_buffer;\n" 120 "\n" 121 "layout(location = 0) out highp ivec4 color;\n", 122 123 "uniform usamplerBuffer sampler_buffer;\n" 124 "\n" 125 "layout(location = 0) out highp uvec4 color;\n" 126 }; 127 128 /* Variables declarations for the fragment shader with usage of the precision qualifier. */ 129 const char* const TextureBufferPrecision::m_fs_code_declaration_with_precision[3] = { 130 "uniform highp samplerBuffer sampler_buffer;\n" 131 "\n" 132 "layout(location = 0) out highp vec4 color;\n", 133 134 "uniform highp isamplerBuffer sampler_buffer;\n" 135 "\n" 136 "layout(location = 0) out highp ivec4 color;\n", 137 138 "uniform highp usamplerBuffer sampler_buffer;\n" 139 "\n" 140 "layout(location = 0) out highp uvec4 color;\n", 141 }; 142 143 /* The default precision qualifier declarations for the fragment shader. */ 144 const char* const TextureBufferPrecision::m_fs_code_global_precision[3] = { 145 "precision highp samplerBuffer;\n", "precision highp isamplerBuffer;\n", "precision highp usamplerBuffer;\n", 146 }; 147 148 /* The fragment shader body. */ 149 const char* const TextureBufferPrecision::m_fs_code_body = "\n" 150 "void main()\n" 151 "{\n" 152 " color = texelFetch( sampler_buffer, 0 );\n" 153 "}"; 154 155 /** Constructor 156 * 157 * @param context Test context 158 * @param name Test case's name 159 * @param description Test case's description 160 **/ 161 TextureBufferPrecision::TextureBufferPrecision(Context& context, const ExtParameters& extParams, const char* name, 162 const char* description) 163 : TestCaseBase(context, extParams, name, description), m_po_id(0), m_sh_id(0) 164 { 165 //Bug-15063 Only GLSL 4.50 supports opaque types 166 if (m_glslVersion >= glu::GLSL_VERSION_130) 167 { 168 m_glslVersion = glu::GLSL_VERSION_450; 169 } 170 } 171 172 /** Deinitializes GLES objects created during the test */ 173 void TextureBufferPrecision::deinit(void) 174 { 175 /* Retrieve GLES entry points. */ 176 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 177 178 /* Delete GLES objects */ 179 if (m_po_id != 0) 180 { 181 gl.deleteProgram(m_po_id); 182 m_po_id = 0; 183 } 184 185 if (m_sh_id != 0) 186 { 187 gl.deleteShader(m_sh_id); 188 m_sh_id = 0; 189 } 190 191 /* Deinitialize base class */ 192 TestCaseBase::deinit(); 193 } 194 195 /** Check if the shader compiles. 196 * 197 * Note the function throws exception should an error occur! 198 * 199 * @param shader_type GL shader type. 200 * @param sh_code_parts Shader source parts 201 * @param parts_count Shader source parts count 202 * 203 * @return true if the shader compiles, return false otherwise. 204 **/ 205 glw::GLboolean TextureBufferPrecision::verifyShaderCompilationStatus(glw::GLenum shader_type, 206 const char** sh_code_parts, 207 const glw::GLuint parts_count, 208 const glw::GLint expected_status) 209 { 210 /* Retrieve GLES entry points. */ 211 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 212 213 glw::GLboolean test_passed = true; 214 215 m_po_id = gl.createProgram(); 216 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create program object"); 217 218 m_sh_id = gl.createShader(shader_type); 219 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object"); 220 221 std::string shader_code = specializeShader(parts_count, sh_code_parts); 222 const char* shader_code_ptr = shader_code.c_str(); 223 gl.shaderSource(m_sh_id, 1, &shader_code_ptr, DE_NULL); 224 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set shader source"); 225 226 gl.compileShader(m_sh_id); 227 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to perform compilation of shader object"); 228 229 /* Retrieving compilation status */ 230 glw::GLint compilation_status = GL_FALSE; 231 gl.getShaderiv(m_sh_id, GL_COMPILE_STATUS, &compilation_status); 232 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not retrieve shader compilation status"); 233 234 if (compilation_status != expected_status) 235 { 236 test_passed = false; 237 238 glw::GLsizei info_log_length = 0; 239 gl.getShaderiv(m_sh_id, GL_INFO_LOG_LENGTH, &info_log_length); 240 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not get shader info log length"); 241 242 if (info_log_length > 0) 243 { 244 glw::GLchar* info_log = new glw::GLchar[info_log_length]; 245 memset(info_log, 0, info_log_length * sizeof(glw::GLchar)); 246 gl.getShaderInfoLog(m_sh_id, info_log_length, DE_NULL, info_log); 247 248 m_testCtx.getLog() << tcu::TestLog::Message << "The following shader:\n\n" 249 << shader_code << "\n\n did compile with result different than expected:\n" 250 << expected_status << "\n\n Compilation info log: \n" 251 << info_log << "\n" 252 << tcu::TestLog::EndMessage; 253 254 delete[] info_log; 255 256 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not get shader info log"); 257 } 258 } 259 260 /* Clean up */ 261 if (m_po_id != 0) 262 { 263 gl.deleteProgram(m_po_id); 264 m_po_id = 0; 265 } 266 267 if (m_sh_id != 0) 268 { 269 gl.deleteShader(m_sh_id); 270 m_sh_id = 0; 271 } 272 273 return test_passed; 274 } 275 276 /** Executes the test. 277 * 278 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 279 * 280 * Note the function throws exception should an error occur! 281 * 282 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 283 **/ 284 tcu::TestNode::IterateResult TextureBufferPrecision::iterate(void) 285 { 286 /* Skip if required extensions are not supported. */ 287 if (!m_is_texture_buffer_supported) 288 { 289 throw tcu::NotSupportedError(TEXTURE_BUFFER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 290 } 291 292 glu::ContextType contextType = m_context.getRenderContext().getType(); 293 glw::GLboolean test_passed = true; 294 glw::GLint expected_fail = glu::glslVersionIsES(m_glslVersion) ? GL_FALSE : GL_TRUE; 295 296 /* Default precision qualifiers for opaque types are not supported prior to GLSL 4.50. */ 297 if (glu::contextSupports(contextType, glu::ApiType::core(4, 5)) || 298 glu::contextSupports(contextType, glu::ApiType::es(3, 1))) 299 { 300 /* Compute Shader Tests */ 301 for (glw::GLuint i = 0; i < 3; ++i) /* For each from the set {imageBuffer, iimageBuffer, uimageBuffer} */ 302 { 303 const char* cs_code_without_precision[3] = { m_cs_code_head, m_cs_code_declaration_without_precision[i], 304 m_cs_code_body }; 305 306 const char* cs_code_with_precision[3] = { m_cs_code_head, m_cs_code_declaration_with_precision[i], 307 m_cs_code_body }; 308 309 const char* cs_code_with_global_precision[4] = { m_cs_code_head, m_cs_code_global_precision[i], 310 m_cs_code_declaration_without_precision[i], 311 m_cs_code_body }; 312 313 test_passed = 314 verifyShaderCompilationStatus(GL_COMPUTE_SHADER, cs_code_without_precision, 3, expected_fail) && 315 test_passed; 316 test_passed = 317 verifyShaderCompilationStatus(GL_COMPUTE_SHADER, cs_code_with_precision, 3, GL_TRUE) && test_passed; 318 test_passed = verifyShaderCompilationStatus(GL_COMPUTE_SHADER, cs_code_with_global_precision, 4, GL_TRUE) && 319 test_passed; 320 } 321 } 322 323 /* Fragment Shader Tests */ 324 for (glw::GLuint i = 0; i < 3; ++i) /* For each from the set {samplerBuffer, isamplerBuffer, usamplerBuffer} */ 325 { 326 const char* fs_code_without_precision[3] = { m_fs_code_head, m_fs_code_declaration_without_precision[i], 327 m_fs_code_body }; 328 329 const char* fs_code_with_precision[3] = { m_fs_code_head, m_fs_code_declaration_with_precision[i], 330 m_fs_code_body }; 331 332 const char* fs_code_with_global_precision[4] = { m_fs_code_head, m_fs_code_global_precision[i], 333 m_fs_code_declaration_without_precision[i], m_fs_code_body }; 334 335 test_passed = verifyShaderCompilationStatus(GL_FRAGMENT_SHADER, fs_code_without_precision, 3, expected_fail) && 336 test_passed; 337 test_passed = 338 verifyShaderCompilationStatus(GL_FRAGMENT_SHADER, fs_code_with_precision, 3, GL_TRUE) && test_passed; 339 test_passed = 340 verifyShaderCompilationStatus(GL_FRAGMENT_SHADER, fs_code_with_global_precision, 4, GL_TRUE) && test_passed; 341 } 342 343 if (test_passed) 344 { 345 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 346 } 347 else 348 { 349 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 350 } 351 352 return STOP; 353 } 354 355 } /* namespace glcts */ 356