xref: /aosp_15_r20/external/deqp/external/openglcts/modules/common/glcLayoutLocationTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2018 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  * \file glcLayoutLocationTests.cpp
20  * \brief
21  */ /*-------------------------------------------------------------------*/
22 #include "glcLayoutLocationTests.hpp"
23 
24 #include "tcuRenderTarget.hpp"
25 #include "tcuStringTemplate.hpp"
26 #include "tcuSurface.hpp"
27 #include "tcuTestLog.hpp"
28 #include "tcuTexture.hpp"
29 #include "tcuTextureUtil.hpp"
30 
31 #include "deStringUtil.hpp"
32 
33 #include "glwDefs.hpp"
34 #include "glwEnums.hpp"
35 #include "glwFunctions.hpp"
36 
37 #include "gluDrawUtil.hpp"
38 #include "gluPixelTransfer.hpp"
39 #include "gluShaderProgram.hpp"
40 #include "gluTexture.hpp"
41 #include "gluTextureUtil.hpp"
42 
43 using namespace glw;
44 
45 namespace glcts
46 {
47 
48 static const GLuint WIDTH  = 2;
49 static const GLuint HEIGHT = 2;
50 
51 // Helper function used to set texture parameters
setTexParameters(const Functions & gl,GLenum target,bool depthTexture)52 void setTexParameters(const Functions &gl, GLenum target, bool depthTexture)
53 {
54     gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
55     gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
56 
57     if (depthTexture)
58     {
59         gl.texParameteri(target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
60         gl.texParameteri(target, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
61     }
62 }
63 
64 // Helper function used to create texture data
65 template <typename DATA_TYPE>
generateData(std::size_t width,std::size_t height,std::size_t components)66 std::vector<DATA_TYPE> generateData(std::size_t width, std::size_t height, std::size_t components)
67 {
68     DE_ASSERT((components == 1) || (components == 4));
69     std::size_t size = width * height * components;
70     std::vector<DATA_TYPE> data(size, 0);
71     for (std::size_t i = 0; i < size; i += components)
72         data[i] = static_cast<DATA_TYPE>(255);
73     return data;
74 }
75 
76 // Structure used to return id of created object it had to be defined to support
77 // GL_TEXTURE_BUFFER cases which require creation of both texture and buffer
78 struct ResultData
79 {
80     uint32_t textureId; // id of created texture
81     uint32_t bufferId;  // used only by GL_TEXTURE_BUFFER
82 
ResultDataglcts::ResultData83     ResultData(uint32_t tId) : textureId(tId), bufferId(0)
84     {
85     }
86 
ResultDataglcts::ResultData87     ResultData(uint32_t tId, uint32_t bId) : textureId(tId), bufferId(bId)
88     {
89     }
90 };
91 
92 template <typename DATA_TYPE>
createTexture1D(const Functions & gl,std::size_t components,GLenum internalFormat,GLenum format,GLenum type)93 ResultData createTexture1D(const Functions &gl, std::size_t components, GLenum internalFormat, GLenum format,
94                            GLenum type)
95 {
96     std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, 1, components);
97 
98     uint32_t id;
99     gl.genTextures(1, &id);
100     gl.bindTexture(GL_TEXTURE_1D, id);
101     gl.texImage1D(GL_TEXTURE_1D, 0, internalFormat, WIDTH, 0, format, type, &data[0]);
102     setTexParameters(gl, GL_TEXTURE_1D, components == 1);
103     return id;
104 }
105 
106 template <typename DATA_TYPE>
createTexture2D(const Functions & gl,std::size_t components,GLenum target,GLenum internalFormat,GLenum format,GLenum type)107 ResultData createTexture2D(const Functions &gl, std::size_t components, GLenum target, GLenum internalFormat,
108                            GLenum format, GLenum type)
109 {
110     std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, HEIGHT, components);
111 
112     uint32_t id;
113     gl.genTextures(1, &id);
114     gl.bindTexture(target, id);
115     gl.texStorage2D(target, 1, internalFormat, WIDTH, HEIGHT);
116     gl.texSubImage2D(target, 0, 0, 0, WIDTH, HEIGHT, format, type, &data[0]);
117     setTexParameters(gl, target, components == 1);
118     return id;
119 }
120 
121 template <typename DATA_TYPE>
createTexture3D(const Functions & gl,std::size_t components,GLenum internalFormat,GLenum format,GLenum type)122 ResultData createTexture3D(const Functions &gl, std::size_t components, GLenum internalFormat, GLenum format,
123                            GLenum type)
124 {
125     std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, HEIGHT, components);
126 
127     uint32_t id;
128     gl.genTextures(1, &id);
129     gl.bindTexture(GL_TEXTURE_3D, id);
130     gl.texStorage3D(GL_TEXTURE_3D, 1, internalFormat, WIDTH, HEIGHT, 1);
131     gl.texSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, WIDTH, HEIGHT, 1, format, type, &data[0]);
132     setTexParameters(gl, GL_TEXTURE_3D, components == 1);
133     return id;
134 }
135 
136 template <typename DATA_TYPE>
createCubeMap(const Functions & gl,std::size_t components,GLenum internalFormat,GLenum format,GLenum type)137 ResultData createCubeMap(const Functions &gl, std::size_t components, GLenum internalFormat, GLenum format, GLenum type)
138 {
139     std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, HEIGHT, components);
140 
141     uint32_t id;
142     gl.genTextures(1, &id);
143     gl.bindTexture(GL_TEXTURE_CUBE_MAP, id);
144     GLenum faces[] = {GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
145                       GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};
146     gl.texStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalFormat, WIDTH, HEIGHT);
147     for (int i = 0; i < 6; ++i)
148         gl.texSubImage2D(faces[i], 0, 0, 0, WIDTH, HEIGHT, format, type, &data[0]);
149     setTexParameters(gl, GL_TEXTURE_CUBE_MAP, components == 1);
150     return id;
151 }
152 
153 template <typename DATA_TYPE>
createTexture2DArray(const Functions & gl,std::size_t components,GLenum internalFormat,GLenum format,GLenum type)154 ResultData createTexture2DArray(const Functions &gl, std::size_t components, GLenum internalFormat, GLenum format,
155                                 GLenum type)
156 {
157     std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, HEIGHT, components);
158 
159     uint32_t id;
160     gl.genTextures(1, &id);
161     gl.bindTexture(GL_TEXTURE_2D_ARRAY, id);
162     gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1, internalFormat, WIDTH, HEIGHT, 1);
163     gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, WIDTH, HEIGHT, 1, format, type, &data[0]);
164     setTexParameters(gl, GL_TEXTURE_2D_ARRAY, components == 1);
165     return id;
166 }
167 
168 template <typename DATA_TYPE>
createTextureBuffer(const Functions & gl,GLenum internalFormat)169 ResultData createTextureBuffer(const Functions &gl, GLenum internalFormat)
170 {
171     std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, HEIGHT, 4);
172 
173     uint32_t bufferId;
174     gl.genBuffers(1, &bufferId);
175     gl.bindBuffer(GL_TEXTURE_BUFFER, bufferId);
176     gl.bufferData(GL_TEXTURE_BUFFER, WIDTH * HEIGHT * 4 * sizeof(DATA_TYPE), &data[0], GL_STATIC_DRAW);
177 
178     uint32_t textureId;
179     gl.genTextures(1, &textureId);
180     gl.bindTexture(GL_TEXTURE_BUFFER, textureId);
181     gl.texBuffer(GL_TEXTURE_BUFFER, internalFormat, bufferId);
182     return ResultData(textureId, bufferId);
183 }
184 
185 // create function was implemented for convinience. Specializations of this
186 // template simplify definition of test data by reducting the number of
187 // attributes which were moved to create fn implementation. This aproach
188 // also simplyfies texture creation in the test as create takes just a single
189 // parameter for all test cases.
190 template <GLenum, GLenum>
create(const Functions & gl)191 ResultData create(const Functions &gl)
192 {
193     (void)gl;
194     TCU_FAIL("Missing specialization implementation.");
195 }
196 
197 template <>
create(const Functions & gl)198 ResultData create<GL_TEXTURE_2D, GL_RGBA8>(const Functions &gl)
199 {
200     return createTexture2D<unsigned char>(gl, 4, GL_TEXTURE_2D, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
201 }
202 
203 template <>
create(const Functions & gl)204 ResultData create<GL_TEXTURE_3D, GL_RGBA8>(const Functions &gl)
205 {
206     return createTexture3D<unsigned char>(gl, 4, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
207 }
208 
209 template <>
create(const Functions & gl)210 ResultData create<GL_TEXTURE_CUBE_MAP, GL_RGBA8>(const Functions &gl)
211 {
212     return createCubeMap<unsigned char>(gl, 4, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
213 }
214 
215 template <>
create(const Functions & gl)216 ResultData create<GL_TEXTURE_CUBE_MAP, GL_DEPTH_COMPONENT16>(const Functions &gl)
217 {
218     return createCubeMap<short>(gl, 1, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);
219 }
220 
221 template <>
create(const Functions & gl)222 ResultData create<GL_TEXTURE_2D, GL_DEPTH_COMPONENT16>(const Functions &gl)
223 {
224     return createTexture2D<short>(gl, 1, GL_TEXTURE_2D, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);
225 }
226 
227 template <>
create(const Functions & gl)228 ResultData create<GL_TEXTURE_2D_ARRAY, GL_RGBA8>(const Functions &gl)
229 {
230     return createTexture2DArray<unsigned char>(gl, 4, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
231 }
232 
233 template <>
create(const Functions & gl)234 ResultData create<GL_TEXTURE_2D_ARRAY, GL_DEPTH_COMPONENT16>(const Functions &gl)
235 {
236     return createTexture2DArray<short>(gl, 1, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);
237 }
238 
239 template <>
create(const Functions & gl)240 ResultData create<GL_TEXTURE_2D, GL_RGBA32I>(const Functions &gl)
241 {
242     return createTexture2D<int>(gl, 4, GL_TEXTURE_2D, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT);
243 }
244 
245 template <>
create(const Functions & gl)246 ResultData create<GL_TEXTURE_3D, GL_RGBA32I>(const Functions &gl)
247 {
248     return createTexture3D<int>(gl, 4, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT);
249 }
250 
251 template <>
create(const Functions & gl)252 ResultData create<GL_TEXTURE_CUBE_MAP, GL_RGBA32I>(const Functions &gl)
253 {
254     return createCubeMap<int>(gl, 4, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT);
255 }
256 
257 template <>
create(const Functions & gl)258 ResultData create<GL_TEXTURE_2D_ARRAY, GL_RGBA32I>(const Functions &gl)
259 {
260     return createTexture2DArray<int>(gl, 4, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT);
261 }
262 
263 template <>
create(const Functions & gl)264 ResultData create<GL_TEXTURE_2D, GL_RGBA32UI>(const Functions &gl)
265 {
266     return createTexture2D<unsigned int>(gl, 4, GL_TEXTURE_2D, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT);
267 }
268 
269 template <>
create(const Functions & gl)270 ResultData create<GL_TEXTURE_3D, GL_RGBA32UI>(const Functions &gl)
271 {
272     return createTexture3D<unsigned int>(gl, 4, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT);
273 }
274 
275 template <>
create(const Functions & gl)276 ResultData create<GL_TEXTURE_CUBE_MAP, GL_RGBA32UI>(const Functions &gl)
277 {
278     return createCubeMap<unsigned int>(gl, 4, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT);
279 }
280 
281 template <>
create(const Functions & gl)282 ResultData create<GL_TEXTURE_2D_ARRAY, GL_RGBA32UI>(const Functions &gl)
283 {
284     return createTexture2DArray<unsigned int>(gl, 4, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT);
285 }
286 
287 template <>
create(const Functions & gl)288 ResultData create<GL_TEXTURE_1D, GL_RGBA8>(const Functions &gl)
289 {
290     return createTexture1D<unsigned char>(gl, 4, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
291 }
292 
293 template <>
create(const Functions & gl)294 ResultData create<GL_TEXTURE_1D, GL_DEPTH_COMPONENT16>(const Functions &gl)
295 {
296     return createTexture1D<unsigned short>(gl, 1, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);
297 }
298 
299 template <>
create(const Functions & gl)300 ResultData create<GL_TEXTURE_1D_ARRAY, GL_RGBA8>(const Functions &gl)
301 {
302     return createTexture2D<unsigned char>(gl, 4, GL_TEXTURE_1D_ARRAY, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
303 }
304 
305 template <>
create(const Functions & gl)306 ResultData create<GL_TEXTURE_1D_ARRAY, GL_DEPTH_COMPONENT16>(const Functions &gl)
307 {
308     return createTexture2D<short>(gl, 1, GL_TEXTURE_1D_ARRAY, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT,
309                                   GL_UNSIGNED_SHORT);
310 }
311 
312 template <>
create(const Functions & gl)313 ResultData create<GL_TEXTURE_BUFFER, GL_RGBA32F>(const Functions &gl)
314 {
315     return createTextureBuffer<float>(gl, GL_RGBA32F);
316 }
317 
318 template <>
create(const Functions & gl)319 ResultData create<GL_TEXTURE_BUFFER, GL_RGBA32I>(const Functions &gl)
320 {
321     return createTextureBuffer<int>(gl, GL_RGBA32I);
322 }
323 
324 template <>
create(const Functions & gl)325 ResultData create<GL_TEXTURE_BUFFER, GL_RGBA32UI>(const Functions &gl)
326 {
327     return createTextureBuffer<unsigned int>(gl, GL_RGBA32UI);
328 }
329 
330 // Structure used to define all test case data
331 struct SamplerCaseData
332 {
333     typedef ResultData (*CreateFnPtr)(const Functions &gl);
334 
335     CreateFnPtr create;                // pointer to function that will create texture
336     const char *name;                  // test case name
337     const char *opaqueType;            // sampler or image
338     const char *outAssignment;         // operation that determines fragment color
339     const int num_frag_image_uniforms; // the number of required fragment image uniform
340 };
341 
342 class SpecifiedLocationCase : public deqp::TestCase
343 {
344 public:
345     SpecifiedLocationCase(deqp::Context &context, const SamplerCaseData &data);
346     virtual ~SpecifiedLocationCase();
347 
348     tcu::TestNode::IterateResult iterate();
349 
350 private:
351     ResultData (*m_createFn)(const Functions &gl);
352     std::map<std::string, std::string> m_specializationMap;
353 
354     bool m_isImageCase;
355     GLenum m_imageFormat;
356     std::string m_imageFormatQualifier;
357     int m_num_frag_image_uniform;
358 };
359 
SpecifiedLocationCase(deqp::Context & context,const SamplerCaseData & data)360 SpecifiedLocationCase::SpecifiedLocationCase(deqp::Context &context, const SamplerCaseData &data)
361     : deqp::TestCase(context, data.name, "")
362     , m_createFn(data.create)
363 {
364     std::string type(data.opaqueType);
365     m_specializationMap["OPAQUE_TYPE"]    = type;
366     m_specializationMap["OUT_ASSIGNMENT"] = data.outAssignment;
367 
368     m_isImageCase = (type.find("sampler") == std::string::npos);
369     if (m_isImageCase)
370     {
371         m_specializationMap["OPAQUE_TYPE_NAME"] = "image";
372         m_specializationMap["ACCESS"]           = "readonly";
373 
374         if (type.find("iimage") != std::string::npos)
375         {
376             m_imageFormatQualifier = "rgba32i";
377             m_imageFormat          = GL_RGBA32I;
378         }
379         else if (type.find("uimage") != std::string::npos)
380         {
381             m_imageFormatQualifier = "rgba32ui";
382             m_imageFormat          = GL_RGBA32UI;
383         }
384         else
385         {
386             m_imageFormatQualifier = "rgba8";
387             m_imageFormat          = GL_RGBA8;
388         }
389     }
390     else
391     {
392         m_specializationMap["OPAQUE_TYPE_NAME"] = "sampler";
393         m_specializationMap["ACCESS"]           = "";
394     }
395     m_num_frag_image_uniform = data.num_frag_image_uniforms;
396 }
397 
~SpecifiedLocationCase()398 SpecifiedLocationCase::~SpecifiedLocationCase()
399 {
400 }
401 
iterate(void)402 tcu::TestNode::IterateResult SpecifiedLocationCase::iterate(void)
403 {
404     static const uint16_t quadIndices[] = {0, 1, 2, 2, 1, 3};
405     static const float positions[]      = {-1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0};
406 
407     static const char *vsTemplate = "${VERSION}\n"
408                                     "precision highp float;\n"
409                                     "layout(location=0) in highp vec2 inPosition;\n"
410                                     "layout(location=0) out highp vec2 coords;\n"
411                                     "void main(void)\n"
412                                     "{\n"
413                                     "  coords = vec2(max(0.0, inPosition.x), max(0.0, inPosition.y));\n"
414                                     "  gl_Position = vec4(inPosition, 0.0, 1.0);\n"
415                                     "}\n";
416 
417     static const char *fsTemplate =
418         "${VERSION}\n"
419         "precision highp float;\n"
420         "layout(location=0) in vec2 coords;\n"
421         "layout(location=0) out vec4 fragColor;\n"
422         "layout(${OPAQUE_TYPE_QUALIFIERS}) ${ACCESS} uniform highp ${OPAQUE_TYPE} ${OPAQUE_TYPE_NAME};\n"
423         "void main(void)\n"
424         "{\n"
425         "  fragColor = ${OUT_ASSIGNMENT};\n"
426         "}\n";
427 
428     glu::RenderContext &renderContext = m_context.getRenderContext();
429     glu::ContextType contextType      = renderContext.getType();
430     glu::GLSLVersion glslVersion      = glu::getContextTypeGLSLVersion(contextType);
431     const Functions &gl               = renderContext.getFunctions();
432     bool contextTypeES                = glu::isContextTypeES(contextType);
433     bool contextES32                  = glu::contextSupports(contextType, glu::ApiType::es(3, 2));
434     if (contextTypeES && !contextES32 &&
435         !m_context.getContextInfo().isExtensionSupported("GL_ANDROID_extension_pack_es31a"))
436         if (m_context.getContextInfo().getInt(GL_MAX_FRAGMENT_IMAGE_UNIFORMS) < m_num_frag_image_uniform)
437             throw tcu::NotSupportedError(
438                 "The number of required fragment image uniform is larger than GL_MAX_FRAGMENT_IMAGE_UNIFORMS");
439 
440     const int expectedLocation = 2;
441     const int definedBinding   = 1;
442 
443     std::ostringstream layoutSpecification;
444     layoutSpecification << "location=" << expectedLocation;
445     if (m_isImageCase)
446     {
447         if (contextTypeES)
448             layoutSpecification << ", binding=" << definedBinding;
449         layoutSpecification << ", " << m_imageFormatQualifier;
450     }
451 
452     m_specializationMap["VERSION"]                = glu::getGLSLVersionDeclaration(glslVersion);
453     m_specializationMap["OPAQUE_TYPE_QUALIFIERS"] = layoutSpecification.str();
454 
455     std::string vs = tcu::StringTemplate(vsTemplate).specialize(m_specializationMap);
456     std::string fs = tcu::StringTemplate(fsTemplate).specialize(m_specializationMap);
457     glu::ShaderProgram program(gl, glu::makeVtxFragSources(vs.c_str(), fs.c_str()));
458 
459     m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
460     if (!program.isOk())
461     {
462         m_testCtx.getLog() << program << tcu::TestLog::Message << "Creation of program failed."
463                            << tcu::TestLog::EndMessage;
464         return STOP;
465     }
466 
467     uint32_t programId = program.getProgram();
468     int location       = gl.getUniformLocation(programId, m_specializationMap["OPAQUE_TYPE_NAME"].c_str());
469     if (location != expectedLocation)
470     {
471         m_testCtx.getLog() << tcu::TestLog::Message << "Expected uniform to be at location " << expectedLocation
472                            << ", not at " << location << "." << tcu::TestLog::EndMessage;
473         return STOP;
474     }
475 
476     gl.useProgram(programId);
477     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
478 
479     // Prepare texture/buffer
480     gl.activeTexture(GL_TEXTURE1);
481     ResultData resultData = (*m_createFn)(gl);
482     GLU_EXPECT_NO_ERROR(gl.getError(), "GL object creation failed.");
483 
484     if (m_isImageCase)
485     {
486         gl.bindImageTexture(definedBinding, resultData.textureId, 0, GL_TRUE, 0, GL_READ_ONLY, m_imageFormat);
487         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture");
488     }
489 
490     // in ES image uniforms cannot be updated
491     // through any of the glUniform* commands
492     if (!(contextTypeES && m_isImageCase))
493     {
494         gl.uniform1i(expectedLocation, definedBinding);
495         GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
496     }
497 
498     // Create FBO with RBO
499     uint32_t rboId;
500     uint32_t fboId;
501     gl.genRenderbuffers(1, &rboId);
502     gl.bindRenderbuffer(GL_RENDERBUFFER, rboId);
503     gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, WIDTH, HEIGHT);
504     gl.genFramebuffers(1, &fboId);
505     gl.bindFramebuffer(GL_FRAMEBUFFER, fboId);
506     gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboId);
507 
508     // Render
509     gl.viewport(0, 0, WIDTH, HEIGHT);
510     const glu::VertexArrayBinding vertexArrays[] = {glu::va::Float("inPosition", 2, 4, 0, positions)};
511     glu::draw(renderContext, programId, DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays,
512               glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), quadIndices));
513 
514     // Grab surface
515     tcu::Surface resultFrame(WIDTH, HEIGHT);
516     glu::readPixels(renderContext, 0, 0, resultFrame.getAccess());
517 
518     // Verify color of just first pixel
519     const tcu::RGBA expectedColor(255, 0, 0, 0);
520     tcu::RGBA pixel = resultFrame.getPixel(0, 0);
521     if (pixel != expectedColor)
522     {
523         m_testCtx.getLog() << tcu::TestLog::Message << "Incorrect color was generated, expected: ["
524                            << expectedColor.getRed() << ", " << expectedColor.getGreen() << ", "
525                            << expectedColor.getBlue() << ", " << expectedColor.getAlpha() << "], got ["
526                            << pixel.getRed() << ", " << pixel.getGreen() << ", " << pixel.getBlue() << ", "
527                            << pixel.getAlpha() << "]" << tcu::TestLog::EndMessage;
528     }
529     else
530         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
531 
532     // Cleanup
533     if (resultData.bufferId)
534         gl.deleteBuffers(1, &resultData.bufferId);
535     gl.deleteFramebuffers(1, &fboId);
536     gl.deleteRenderbuffers(1, &rboId);
537     gl.deleteTextures(1, &resultData.textureId);
538 
539     return STOP;
540 }
541 
542 class NegativeLocationCase : public deqp::TestCase
543 {
544 public:
545     NegativeLocationCase(deqp::Context &context);
546     virtual ~NegativeLocationCase();
547 
548     tcu::TestNode::IterateResult iterate();
549 };
550 
NegativeLocationCase(deqp::Context & context)551 NegativeLocationCase::NegativeLocationCase(deqp::Context &context) : deqp::TestCase(context, "invalid_cases", "")
552 {
553 }
554 
~NegativeLocationCase()555 NegativeLocationCase::~NegativeLocationCase()
556 {
557 }
558 
iterate()559 tcu::TestNode::IterateResult NegativeLocationCase::iterate()
560 {
561     glu::RenderContext &renderContext = m_context.getRenderContext();
562     glu::ContextType contextType      = renderContext.getType();
563     glu::GLSLVersion glslVersion      = glu::getContextTypeGLSLVersion(contextType);
564     const Functions &gl               = renderContext.getFunctions();
565 
566     m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
567 
568     static const char *csTemplate = "${VERSION}\n"
569                                     "layout(location=2, binding=0) uniform atomic_uint u_atomic;\n"
570                                     "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
571                                     "layout(binding=0) buffer Output {\n  uint value;\n} sb_out;\n\n"
572                                     "void main (void) {\n"
573                                     "  sb_out.value = atomicCounterIncrement(u_atomic);\n"
574                                     "}";
575 
576     std::map<std::string, std::string> specializationMap;
577     specializationMap["VERSION"] = glu::getGLSLVersionDeclaration(glslVersion);
578     std::string cs               = tcu::StringTemplate(csTemplate).specialize(specializationMap);
579 
580     m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
581 
582     glu::ProgramSources sourcesCompute;
583     sourcesCompute.sources[glu::SHADERTYPE_COMPUTE].push_back(cs);
584     glu::ShaderProgram program(gl, sourcesCompute);
585     if (program.isOk())
586     {
587         m_testCtx.getLog() << program << tcu::TestLog::Message
588                            << "layout(location = N) is not allowed for atomic counters" << tcu::TestLog::EndMessage;
589         return STOP;
590     }
591 
592     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
593     return STOP;
594 }
595 
LayoutLocationTests(Context & context)596 LayoutLocationTests::LayoutLocationTests(Context &context) : TestCaseGroup(context, "layout_location", "")
597 {
598 }
599 
~LayoutLocationTests(void)600 LayoutLocationTests::~LayoutLocationTests(void)
601 {
602 }
603 
init(void)604 void LayoutLocationTests::init(void)
605 {
606     const SamplerCaseData commonArguments[] = {
607         {&create<GL_TEXTURE_2D, GL_RGBA8>, "sampler_2d", "sampler2D", "texture(sampler, coords)", 0},
608         {&create<GL_TEXTURE_3D, GL_RGBA8>, "sampler_3d", "sampler3D", "texture(sampler, vec3(coords, 0.0))", 0},
609         {&create<GL_TEXTURE_CUBE_MAP, GL_RGBA8>, "sampler_cube", "samplerCube", "texture(sampler, vec3(coords, 0.0))",
610          0},
611         {&create<GL_TEXTURE_CUBE_MAP, GL_DEPTH_COMPONENT16>, "sampler_cube_shadow", "samplerCubeShadow",
612          "vec4(texture(sampler, vec4(coords, 0.0, 0.0)), 0.0, 0.0, 0.0)", 0},
613         {&create<GL_TEXTURE_2D, GL_DEPTH_COMPONENT16>, "sampler_2d_shadow", "sampler2DShadow",
614          "vec4(texture(sampler, vec3(coords, 0.0)), 0.0, 0.0, 0.0)", 0},
615         {&create<GL_TEXTURE_2D_ARRAY, GL_RGBA8>, "sampler_2d_array", "sampler2DArray",
616          "texture(sampler, vec3(coords, 0.0))", 0},
617         {&create<GL_TEXTURE_2D_ARRAY, GL_DEPTH_COMPONENT16>, "sampler_2d_array_shadow", "sampler2DArrayShadow",
618          "vec4(texture(sampler, vec4(coords, 0.0, 0.0)), 0.0, 0.0, 0.0)", 0},
619         {&create<GL_TEXTURE_2D, GL_RGBA32I>, "isampler_2d", "isampler2D", "vec4(texture(sampler, coords))/255.0", 0},
620         {&create<GL_TEXTURE_3D, GL_RGBA32I>, "isampler_3d", "isampler3D",
621          "vec4(texture(sampler, vec3(coords, 0.0)))/255.0", 0},
622         {&create<GL_TEXTURE_CUBE_MAP, GL_RGBA32I>, "isampler_cube", "isamplerCube",
623          "vec4(texture(sampler, vec3(coords, 0.0)))/255.0", 0},
624         {&create<GL_TEXTURE_2D_ARRAY, GL_RGBA32I>, "isampler_2d_array", "isampler2DArray",
625          "vec4(texture(sampler, vec3(coords, 0.0)))/255.0", 0},
626         {&create<GL_TEXTURE_2D, GL_RGBA32UI>, "usampler_2d", "usampler2D", "vec4(texture(sampler, coords))/255.0", 0},
627         {&create<GL_TEXTURE_3D, GL_RGBA32UI>, "usampler_3d", "usampler3D",
628          "vec4(texture(sampler, vec3(coords, 0.0)))/255.0", 0},
629         {&create<GL_TEXTURE_CUBE_MAP, GL_RGBA32UI>, "usampler_cube", "usamplerCube",
630          "vec4(texture(sampler, vec3(coords, 0.0)))/255.0", 0},
631         {&create<GL_TEXTURE_2D_ARRAY, GL_RGBA32UI>, "usampler_2d_array", "usampler2DArray",
632          "vec4(texture(sampler, vec3(coords, 0.0)))/255.0", 0},
633 
634         {&create<GL_TEXTURE_2D, GL_RGBA8>, "image_2d", "image2D", "imageLoad(image, ivec2(0, 0))", 1},
635         {&create<GL_TEXTURE_2D, GL_RGBA32I>, "iimage_2d", "iimage2D", "vec4(imageLoad(image, ivec2(0, 0)))/255.0", 1},
636         {&create<GL_TEXTURE_2D, GL_RGBA32UI>, "uimage_2d", "uimage2D", "vec4(imageLoad(image, ivec2(0, 0)))/255.0", 1},
637         {&create<GL_TEXTURE_3D, GL_RGBA8>, "image_3d", "image3D", "imageLoad(image, ivec3(0, 0, 0))", 1},
638         {&create<GL_TEXTURE_3D, GL_RGBA32I>, "iimage_3d", "iimage3D", "vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0",
639          1},
640         {&create<GL_TEXTURE_3D, GL_RGBA32UI>, "uimage_3d", "uimage3D", "vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0",
641          1},
642         {&create<GL_TEXTURE_CUBE_MAP, GL_RGBA8>, "image_cube", "imageCube", "imageLoad(image, ivec3(0, 0, 0))", 1},
643         {&create<GL_TEXTURE_CUBE_MAP, GL_RGBA32I>, "iimage_cube", "iimageCube",
644          "vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0", 1},
645         {&create<GL_TEXTURE_CUBE_MAP, GL_RGBA32UI>, "uimage_cube", "uimageCube",
646          "vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0", 1},
647         {&create<GL_TEXTURE_2D_ARRAY, GL_RGBA8>, "image_2d_array", "image2DArray", "imageLoad(image, ivec3(0, 0, 0))",
648          1},
649         {&create<GL_TEXTURE_2D_ARRAY, GL_RGBA32I>, "iimage_2d_array", "iimage2DArray",
650          "vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0", 1},
651         {&create<GL_TEXTURE_2D_ARRAY, GL_RGBA32UI>, "uimage_2d_array", "uimage2DArray",
652          "vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0", 1},
653     };
654 
655     // Additional array containing entries for core gl
656     const SamplerCaseData coreArguments[] = {
657         {&create<GL_TEXTURE_BUFFER, GL_RGBA32F>, "sampler_buffer", "samplerBuffer", "texelFetch(sampler, 1)", 0},
658         {&create<GL_TEXTURE_BUFFER, GL_RGBA32I>, "isampler_buffer", "isamplerBuffer",
659          "vec4(texelFetch(sampler, 1))/255.0", 0},
660         {&create<GL_TEXTURE_BUFFER, GL_RGBA32UI>, "usampler_buffer", "usamplerBuffer",
661          "vec4(texelFetch(sampler, 1))/255.0", 0},
662         {&create<GL_TEXTURE_1D, GL_RGBA8>, "sampler_1d", "sampler1D", "texture(sampler, coords.x)", 0},
663         {&create<GL_TEXTURE_1D, GL_DEPTH_COMPONENT16>, "sampler_1d_shadow", "sampler1DShadow",
664          "vec4(texture(sampler, vec3(coords, 0.0)), 0.0, 0.0, 0.0)", 0},
665         {&create<GL_TEXTURE_1D_ARRAY, GL_RGBA8>, "sampler_1d_array", "sampler1DArray", "texture(sampler, coords, 0.0)",
666          0},
667         {&create<GL_TEXTURE_1D_ARRAY, GL_DEPTH_COMPONENT16>, "sampler_1d_array_shadow", "sampler1DArrayShadow",
668          "vec4(texture(sampler, vec3(coords, 0.0)), 0.0, 0.0, 0.0)", 0},
669     };
670 
671     for (int i = 0; i < DE_LENGTH_OF_ARRAY(commonArguments); ++i)
672         addChild(new SpecifiedLocationCase(m_context, commonArguments[i]));
673 
674     glu::RenderContext &renderContext = m_context.getRenderContext();
675     glu::ContextType contextType      = renderContext.getType();
676     if (!glu::isContextTypeES(contextType))
677     {
678         for (int i = 0; i < DE_LENGTH_OF_ARRAY(coreArguments); ++i)
679             addChild(new SpecifiedLocationCase(m_context, coreArguments[i]));
680     }
681 
682     addChild(new NegativeLocationCase(m_context));
683 }
684 
685 } // namespace glcts
686