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 /* Variables declarations for the compute shader with usage of the precision qualifier. */
71 const char *const TextureBufferPrecision::m_cs_code_declaration_with_precision[3] = {
72     "layout (r32f)  uniform highp  imageBuffer image_buffer;\n"
73     "\n"
74     "buffer ComputeSSBO\n"
75     "{\n"
76     "    float value;\n"
77     "} computeSSBO;\n",
78 
79     "layout (r32i)  uniform highp iimageBuffer image_buffer;\n"
80     "\n"
81     "buffer ComputeSSBO\n"
82     "{\n"
83     "    int value;\n"
84     "} computeSSBO;\n",
85 
86     "layout (r32ui) uniform highp uimageBuffer image_buffer;\n"
87     "\n"
88     "buffer ComputeSSBO\n"
89     "{\n"
90     "    uint value;\n"
91     "} computeSSBO;\n"};
92 
93 /* The default precision qualifier declarations for the compute shader. */
94 const char *const TextureBufferPrecision::m_cs_code_global_precision[3] = {
95     "precision highp  imageBuffer;\n", "precision highp iimageBuffer;\n", "precision highp uimageBuffer;\n"};
96 
97 /* The compute shader body. */
98 const char *const TextureBufferPrecision::m_cs_code_body = "\n"
99                                                            "void main()\n"
100                                                            "{\n"
101                                                            "    computeSSBO.value = imageLoad(image_buffer, 0).x;\n"
102                                                            "}";
103 
104 /* Head of the fragment shader. */
105 const char *const TextureBufferPrecision::m_fs_code_head = "${VERSION}\n"
106                                                            "\n"
107                                                            "${TEXTURE_BUFFER_REQUIRE}\n"
108                                                            "\n";
109 
110 /* Variables declarations for the fragment shader without usage of the precision qualifier. */
111 const char *const TextureBufferPrecision::m_fs_code_declaration_without_precision[3] = {
112     "uniform  samplerBuffer sampler_buffer;\n"
113     "\n"
114     "layout(location = 0) out highp vec4 color;\n",
115 
116     "uniform isamplerBuffer sampler_buffer;\n"
117     "\n"
118     "layout(location = 0) out highp ivec4 color;\n",
119 
120     "uniform usamplerBuffer sampler_buffer;\n"
121     "\n"
122     "layout(location = 0) out highp uvec4 color;\n"};
123 
124 /* Variables declarations for the fragment shader with usage of the precision qualifier. */
125 const char *const TextureBufferPrecision::m_fs_code_declaration_with_precision[3] = {
126     "uniform highp  samplerBuffer sampler_buffer;\n"
127     "\n"
128     "layout(location = 0) out highp vec4 color;\n",
129 
130     "uniform highp isamplerBuffer sampler_buffer;\n"
131     "\n"
132     "layout(location = 0) out highp ivec4 color;\n",
133 
134     "uniform highp usamplerBuffer sampler_buffer;\n"
135     "\n"
136     "layout(location = 0) out highp uvec4 color;\n",
137 };
138 
139 /* The default precision qualifier declarations for the fragment shader. */
140 const char *const TextureBufferPrecision::m_fs_code_global_precision[3] = {
141     "precision highp  samplerBuffer;\n",
142     "precision highp isamplerBuffer;\n",
143     "precision highp usamplerBuffer;\n",
144 };
145 
146 /* The fragment shader body. */
147 const char *const TextureBufferPrecision::m_fs_code_body = "\n"
148                                                            "void main()\n"
149                                                            "{\n"
150                                                            "    color = texelFetch( sampler_buffer, 0 );\n"
151                                                            "}";
152 
153 /** Constructor
154  *
155  * @param context     Test context
156  * @param name        Test case's name
157  * @param description Test case's description
158  **/
TextureBufferPrecision(Context & context,const ExtParameters & extParams,const char * name,const char * description)159 TextureBufferPrecision::TextureBufferPrecision(Context &context, const ExtParameters &extParams, const char *name,
160                                                const char *description)
161     : TestCaseBase(context, extParams, name, description)
162     , m_po_id(0)
163     , 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 */
deinit(void)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  **/
verifyShaderCompilationStatus(glw::GLenum shader_type,const char ** sh_code_parts,const glw::GLuint parts_count,const glw::GLint expected_status)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  **/
iterate(void)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], m_cs_code_body};
311 
312             test_passed =
313                 verifyShaderCompilationStatus(GL_COMPUTE_SHADER, cs_code_without_precision, 3, expected_fail) &&
314                 test_passed;
315             test_passed =
316                 verifyShaderCompilationStatus(GL_COMPUTE_SHADER, cs_code_with_precision, 3, GL_TRUE) && test_passed;
317             test_passed = verifyShaderCompilationStatus(GL_COMPUTE_SHADER, cs_code_with_global_precision, 4, GL_TRUE) &&
318                           test_passed;
319         }
320     }
321 
322     /* Fragment Shader Tests */
323     for (glw::GLuint i = 0; i < 3; ++i) /* For each from the set {samplerBuffer, isamplerBuffer, usamplerBuffer} */
324     {
325         const char *fs_code_without_precision[3] = {m_fs_code_head, m_fs_code_declaration_without_precision[i],
326                                                     m_fs_code_body};
327 
328         const char *fs_code_with_precision[3] = {m_fs_code_head, m_fs_code_declaration_with_precision[i],
329                                                  m_fs_code_body};
330 
331         const char *fs_code_with_global_precision[4] = {m_fs_code_head, m_fs_code_global_precision[i],
332                                                         m_fs_code_declaration_without_precision[i], m_fs_code_body};
333 
334         test_passed = verifyShaderCompilationStatus(GL_FRAGMENT_SHADER, fs_code_without_precision, 3, expected_fail) &&
335                       test_passed;
336         test_passed =
337             verifyShaderCompilationStatus(GL_FRAGMENT_SHADER, fs_code_with_precision, 3, GL_TRUE) && test_passed;
338         test_passed =
339             verifyShaderCompilationStatus(GL_FRAGMENT_SHADER, fs_code_with_global_precision, 4, GL_TRUE) && test_passed;
340     }
341 
342     if (test_passed)
343     {
344         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
345     }
346     else
347     {
348         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
349     }
350 
351     return STOP;
352 }
353 
354 } /* namespace glcts */
355