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 #include "gl4cShaderImageLoadStoreTests.hpp"
25 #include "gluContextInfo.hpp"
26 #include "glwEnums.hpp"
27 #include "tcuMatrix.hpp"
28 #include "tcuPlatform.hpp"
29 #include "tcuRenderTarget.hpp"
30 #include "tcuVectorUtil.hpp"
31 #include <assert.h>
32 #include <climits>
33 #include <cmath>
34 #include <cstdarg>
35 #include <deque>
36 #include <iomanip>
37 #include <map>
38 #include <sstream>
39 #include <tcuFloat.hpp>
40
41 namespace gl4cts
42 {
43 using namespace glw;
44
45 namespace
46 {
47 typedef tcu::Vec2 vec2;
48 typedef tcu::Vec4 vec4;
49 typedef tcu::IVec4 ivec4;
50 typedef tcu::UVec4 uvec4;
51 typedef tcu::Mat4 mat4;
52
53 class ShaderImageLoadStoreBase : public deqp::SubcaseBase
54 {
Title()55 virtual std::string Title()
56 {
57 return "";
58 }
59
Purpose()60 virtual std::string Purpose()
61 {
62 return "";
63 }
64
Method()65 virtual std::string Method()
66 {
67 return "";
68 }
69
PassCriteria()70 virtual std::string PassCriteria()
71 {
72 return "";
73 }
74
75 public:
SupportedInVS(int requiredVS)76 bool SupportedInVS(int requiredVS)
77 {
78 GLint imagesVS;
79 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &imagesVS);
80 if (imagesVS >= requiredVS)
81 return true;
82 else
83 {
84 std::ostringstream reason;
85 reason << "Required " << requiredVS << " VS image uniforms but only " << imagesVS << " available."
86 << std::endl;
87 OutputNotSupported(reason.str());
88 return false;
89 }
90 }
91
SupportedInTCS(int requiredTCS)92 bool SupportedInTCS(int requiredTCS)
93 {
94 GLint imagesTCS;
95 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &imagesTCS);
96 if (imagesTCS >= requiredTCS)
97 return true;
98 else
99 {
100 std::ostringstream reason;
101 reason << "Required " << requiredTCS << " TCS image uniforms but only " << imagesTCS << " available."
102 << std::endl;
103 OutputNotSupported(reason.str());
104 return false;
105 }
106 }
107
SupportedInTES(int requiredTES)108 bool SupportedInTES(int requiredTES)
109 {
110 GLint imagesTES;
111 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &imagesTES);
112 if (imagesTES >= requiredTES)
113 return true;
114 else
115 {
116 std::ostringstream reason;
117 reason << "Required " << requiredTES << " TES image uniforms but only " << imagesTES << " available."
118 << std::endl;
119 OutputNotSupported(reason.str());
120 return false;
121 }
122 }
123
SupportedInGS(int requiredGS)124 bool SupportedInGS(int requiredGS)
125 {
126 GLint imagesGS;
127 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &imagesGS);
128 if (imagesGS >= requiredGS)
129 return true;
130 else
131 {
132 std::ostringstream reason;
133 reason << "Required " << requiredGS << " GS image uniforms but only " << imagesGS << " available."
134 << std::endl;
135 OutputNotSupported(reason.str());
136 return false;
137 }
138 }
139
SupportedInGeomStages(int required)140 bool SupportedInGeomStages(int required)
141 {
142 return SupportedInVS(required) && SupportedInTCS(required) && SupportedInTES(required) &&
143 SupportedInGS(required);
144 }
145
SupportedInStage(int stage,int required)146 bool SupportedInStage(int stage, int required)
147 {
148 switch (stage)
149 {
150 case 0:
151 return SupportedInVS(required);
152 case 1:
153 return SupportedInTCS(required);
154 case 2:
155 return SupportedInTES(required);
156 case 3:
157 return SupportedInGS(required);
158 default:
159 return true;
160 }
161 }
162
SupportedSamples(int required)163 bool SupportedSamples(int required)
164 {
165 int i;
166 glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
167 if (i >= required)
168 return true;
169 else
170 {
171 std::ostringstream reason;
172 reason << "Required " << required << " image samples but only " << i << " available." << std::endl;
173 OutputNotSupported(reason.str());
174 return false;
175 }
176 }
177
getWindowWidth()178 int getWindowWidth()
179 {
180 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
181 return renderTarget.getWidth();
182 }
183
getWindowHeight()184 int getWindowHeight()
185 {
186 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
187 return renderTarget.getHeight();
188 }
189
scaleDimensionsToMemory(int & width,int & height,int devLayers,int sysLayers,int devBPP,int sysBPP)190 void scaleDimensionsToMemory(int& width, int& height, int devLayers, int sysLayers, int devBPP, int sysBPP)
191 {
192 tcu::PlatformMemoryLimits memoryLimits;
193 m_context.getTestContext().getPlatform().getMemoryLimits(memoryLimits);
194 GLsizeiptr sysSpace = memoryLimits.totalSystemMemory;
195 GLsizeiptr devSpace = memoryLimits.totalDeviceLocalMemory;
196 int devInSysLayers = 0;
197
198 if (devSpace == 0)
199 {
200 devInSysLayers = devLayers;
201 devLayers = 0;
202 }
203
204 // Check if available memory is enough
205 GLsizeiptr pixelsPerLayer = width * height;
206 GLsizeiptr sysRequired = pixelsPerLayer * ((sysBPP * sysLayers) + (devBPP * devInSysLayers));
207 GLsizeiptr devRequired = pixelsPerLayer * devBPP * devLayers;
208 if ((sysRequired <= sysSpace) && (devRequired <= devSpace))
209 {
210 return;
211 }
212
213 // Scales the width and height such that the overall texture fits into
214 // the available space for both system and device.
215 GLdouble scale = sqrt(sysSpace / GLdouble(sysRequired));
216 if (devSpace != 0)
217 {
218 GLdouble devScale = sqrt(devSpace / GLdouble(devRequired));
219 scale = de::min(devScale, scale);
220 }
221 int newWidth = int(width * scale);
222 int newHeight = int(height * scale);
223
224 m_context.getTestContext().getLog()
225 << tcu::TestLog::Message << "Reducing surface dimensions to fit in memory, from " << width << "x" << height
226 << " to " << newWidth << "x" << newHeight << "." << tcu::TestLog::EndMessage;
227
228 width = newWidth;
229 height = newHeight;
230 }
231
ColorEqual(const vec4 & c0,const vec4 & c1,const vec4 & epsilon)232 inline bool ColorEqual(const vec4& c0, const vec4& c1, const vec4& epsilon)
233 {
234 if (fabs(c0[0] - c1[0]) > epsilon[0])
235 return false;
236 if (fabs(c0[1] - c1[1]) > epsilon[1])
237 return false;
238 if (fabs(c0[2] - c1[2]) > epsilon[2])
239 return false;
240 if (fabs(c0[3] - c1[3]) > epsilon[3])
241 return false;
242 return true;
243 }
244
IsEqual(vec4 a,vec4 b)245 bool IsEqual(vec4 a, vec4 b)
246 {
247 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
248 }
249
Equal(const vec4 & v0,const vec4 & v1,GLenum internalformat)250 bool Equal(const vec4& v0, const vec4& v1, GLenum internalformat)
251 {
252 if (internalformat == GL_RGBA16_SNORM || internalformat == GL_RG16_SNORM || internalformat == GL_R16_SNORM)
253 {
254 return ColorEqual(v0, v1, vec4(0.0001f));
255 }
256 else if (internalformat == GL_RGBA8_SNORM || internalformat == GL_RG8_SNORM || internalformat == GL_R8_SNORM)
257 {
258 return ColorEqual(v0, v1, vec4(0.01f));
259 }
260 return (v0[0] == v1[0]) && (v0[1] == v1[1]) && (v0[2] == v1[2]) && (v0[3] == v1[3]);
261 }
262
Equal(const ivec4 & a,const ivec4 & b,GLenum)263 bool Equal(const ivec4& a, const ivec4& b, GLenum)
264 {
265 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
266 }
267
Equal(const uvec4 & a,const uvec4 & b,GLenum)268 bool Equal(const uvec4& a, const uvec4& b, GLenum)
269 {
270 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
271 }
272
273 template <class T>
ToString(T v)274 std::string ToString(T v)
275 {
276 std::ostringstream s;
277 s << "[";
278 for (int i = 0; i < 4; ++i)
279 s << v[i] << (i == 3 ? "" : ",");
280 s << "]";
281 return s.str();
282 }
283
ValidateReadBuffer(int x,int y,int w,int h,const vec4 & expected)284 bool ValidateReadBuffer(int x, int y, int w, int h, const vec4& expected)
285 {
286 bool status = true;
287 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
288 const tcu::PixelFormat& pixelFormat = renderTarget.getPixelFormat();
289 vec4 g_color_eps = vec4(
290 1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
291 1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
292
293 std::vector<vec4> fb(w * h);
294 glReadPixels(x, y, w, h, GL_RGBA, GL_FLOAT, &fb[0]);
295
296 for (int yy = 0; yy < h; ++yy)
297 {
298 for (int xx = 0; xx < w; ++xx)
299 {
300 const int idx = yy * w + xx;
301 if (!ColorEqual(fb[idx], expected, g_color_eps))
302 {
303 m_context.getTestContext().getLog()
304 << tcu::TestLog::Message << "First bad color: " << ToString(fb[idx])
305 << tcu::TestLog::EndMessage;
306 status = false;
307 return status;
308 }
309 }
310 }
311 return status;
312 }
313
CompileShader(GLuint shader)314 bool CompileShader(GLuint shader)
315 {
316 glCompileShader(shader);
317
318 GLint status;
319 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
320 if (status == GL_FALSE)
321 {
322 GLsizei length;
323 GLchar log[1024];
324 glGetShaderInfoLog(shader, sizeof(log), &length, log);
325 if (length > 1)
326 {
327 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
328 << log << tcu::TestLog::EndMessage;
329 }
330 return false;
331 }
332 return true;
333 }
334
LinkProgram(GLuint program)335 bool LinkProgram(GLuint program)
336 {
337 glLinkProgram(program);
338
339 GLint status;
340 glGetProgramiv(program, GL_LINK_STATUS, &status);
341 if (status == GL_FALSE)
342 {
343 GLsizei length;
344 GLchar log[1024];
345 glGetProgramInfoLog(program, sizeof(log), &length, log);
346 if (length > 1)
347 {
348 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
349 << log << tcu::TestLog::EndMessage;
350 }
351 return false;
352 }
353 return true;
354 }
355
BuildProgram(const char * src_vs,const char * src_tcs,const char * src_tes,const char * src_gs,const char * src_fs,bool * result=NULL)356 GLuint BuildProgram(const char* src_vs, const char* src_tcs, const char* src_tes, const char* src_gs,
357 const char* src_fs, bool* result = NULL)
358 {
359 const GLuint p = glCreateProgram();
360
361 if (src_vs)
362 {
363 GLuint sh = glCreateShader(GL_VERTEX_SHADER);
364 glAttachShader(p, sh);
365 glDeleteShader(sh);
366 glShaderSource(sh, 1, &src_vs, NULL);
367 if (!CompileShader(sh))
368 {
369 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage;
370 if (result)
371 *result = false;
372 return p;
373 }
374 }
375 if (src_tcs)
376 {
377 GLuint sh = glCreateShader(GL_TESS_CONTROL_SHADER);
378 glAttachShader(p, sh);
379 glDeleteShader(sh);
380 glShaderSource(sh, 1, &src_tcs, NULL);
381 if (!CompileShader(sh))
382 {
383 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage;
384 if (result)
385 *result = false;
386 return p;
387 }
388 }
389 if (src_tes)
390 {
391 GLuint sh = glCreateShader(GL_TESS_EVALUATION_SHADER);
392 glAttachShader(p, sh);
393 glDeleteShader(sh);
394 glShaderSource(sh, 1, &src_tes, NULL);
395 if (!CompileShader(sh))
396 {
397 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage;
398 if (result)
399 *result = false;
400 return p;
401 }
402 }
403 if (src_gs)
404 {
405 GLuint sh = glCreateShader(GL_GEOMETRY_SHADER);
406 glAttachShader(p, sh);
407 glDeleteShader(sh);
408 glShaderSource(sh, 1, &src_gs, NULL);
409 if (!CompileShader(sh))
410 {
411 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage;
412 if (result)
413 *result = false;
414 return p;
415 }
416 }
417 if (src_fs)
418 {
419 GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
420 glAttachShader(p, sh);
421 glDeleteShader(sh);
422 glShaderSource(sh, 1, &src_fs, NULL);
423 if (!CompileShader(sh))
424 {
425 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage;
426 if (result)
427 *result = false;
428 return p;
429 }
430 }
431 if (!LinkProgram(p))
432 {
433 if (src_vs)
434 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage;
435 if (src_tcs)
436 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage;
437 if (src_tes)
438 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage;
439 if (src_gs)
440 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage;
441 if (src_fs)
442 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage;
443 if (result)
444 *result = false;
445 return p;
446 }
447
448 return p;
449 }
450
BuildShaderProgram(GLenum type,const char * src)451 GLuint BuildShaderProgram(GLenum type, const char* src)
452 {
453 const GLuint p = glCreateShaderProgramv(type, 1, &src);
454
455 GLint status;
456 glGetProgramiv(p, GL_LINK_STATUS, &status);
457 if (status == GL_FALSE)
458 {
459 GLchar log[1024];
460 glGetProgramInfoLog(p, sizeof(log), NULL, log);
461 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
462 << log << "\n"
463 << src << tcu::TestLog::EndMessage;
464 }
465
466 return p;
467 }
468
CreateFullViewportQuad(GLuint * vao,GLuint * vbo,GLuint * ebo)469 void CreateFullViewportQuad(GLuint* vao, GLuint* vbo, GLuint* ebo)
470 {
471 assert(vao && vbo);
472
473 // interleaved data (vertex, color0 (green), color1 (blue), color2 (red))
474 const float v[] = {
475 -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f,
476 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
477 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
478 };
479 glGenBuffers(1, vbo);
480 glBindBuffer(GL_ARRAY_BUFFER, *vbo);
481 glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
482 glBindBuffer(GL_ARRAY_BUFFER, 0);
483
484 if (ebo)
485 {
486 std::vector<GLushort> index_data(4);
487 for (int i = 0; i < 4; ++i)
488 {
489 index_data[i] = static_cast<GLushort>(i);
490 }
491 glGenBuffers(1, ebo);
492 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
493 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * 4, &index_data[0], GL_STATIC_DRAW);
494 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
495 }
496
497 glGenVertexArrays(1, vao);
498 glBindVertexArray(*vao);
499 glBindBuffer(GL_ARRAY_BUFFER, *vbo);
500 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, 0);
501 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 2));
502 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 5));
503 glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 8));
504 glBindBuffer(GL_ARRAY_BUFFER, 0);
505 glEnableVertexAttribArray(0);
506 glEnableVertexAttribArray(1);
507 glEnableVertexAttribArray(2);
508 glEnableVertexAttribArray(3);
509 if (ebo)
510 {
511 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
512 }
513 glBindVertexArray(0);
514 }
515
FormatEnumToString(GLenum e)516 std::string FormatEnumToString(GLenum e)
517 {
518 switch (e)
519 {
520 case GL_RGBA32F:
521 return "rgba32f";
522 case GL_RGBA16F:
523 return "rgba16f";
524 case GL_RG32F:
525 return "rg32f";
526 case GL_RG16F:
527 return "rg16f";
528 case GL_R11F_G11F_B10F:
529 return "r11f_g11f_b10f";
530 case GL_R32F:
531 return "r32f";
532 case GL_R16F:
533 return "r16f";
534
535 case GL_RGBA32UI:
536 return "rgba32ui";
537 case GL_RGBA16UI:
538 return "rgba16ui";
539 case GL_RGB10_A2UI:
540 return "rgb10_a2ui";
541 case GL_RGBA8UI:
542 return "rgba8ui";
543 case GL_RG32UI:
544 return "rg32ui";
545 case GL_RG16UI:
546 return "rg16ui";
547 case GL_RG8UI:
548 return "rg8ui";
549 case GL_R32UI:
550 return "r32ui";
551 case GL_R16UI:
552 return "r16ui";
553 case GL_R8UI:
554 return "r8ui";
555
556 case GL_RGBA32I:
557 return "rgba32i";
558 case GL_RGBA16I:
559 return "rgba16i";
560 case GL_RGBA8I:
561 return "rgba8i";
562 case GL_RG32I:
563 return "rg32i";
564 case GL_RG16I:
565 return "rg16i";
566 case GL_RG8I:
567 return "rg8i";
568 case GL_R32I:
569 return "r32i";
570 case GL_R16I:
571 return "r16i";
572 case GL_R8I:
573 return "r8i";
574
575 case GL_RGBA16:
576 return "rgba16";
577 case GL_RGB10_A2:
578 return "rgb10_a2";
579 case GL_RGBA8:
580 return "rgba8";
581 case GL_RG16:
582 return "rg16";
583 case GL_RG8:
584 return "rg8";
585 case GL_R16:
586 return "r16";
587 case GL_R8:
588 return "r8";
589
590 case GL_RGBA16_SNORM:
591 return "rgba16_snorm";
592 case GL_RGBA8_SNORM:
593 return "rgba8_snorm";
594 case GL_RG16_SNORM:
595 return "rg16_snorm";
596 case GL_RG8_SNORM:
597 return "rg8_snorm";
598 case GL_R16_SNORM:
599 return "r16_snorm";
600 case GL_R8_SNORM:
601 return "r8_snorm";
602 }
603
604 assert(0);
605 return "";
606 }
607
StageName(int stage)608 const char* StageName(int stage)
609 {
610 switch (stage)
611 {
612 case 0:
613 return "Vertex Shader";
614 case 1:
615 return "Tessellation Control Shader";
616 case 2:
617 return "Tessellation Evaluation Shader";
618 case 3:
619 return "Geometry Shader";
620 case 4:
621 return "Compute Shader";
622 }
623 assert(0);
624 return NULL;
625 }
626
627 template <typename T>
628 GLenum Format();
629
630 template <typename T>
631 GLenum Type();
632
633 template <typename T>
634 std::string TypePrefix();
635
636 template <typename T>
637 GLenum ImageType(GLenum target);
638
ClearBuffer(GLenum buffer,GLint drawbuffer,const vec4 & color)639 void ClearBuffer(GLenum buffer, GLint drawbuffer, const vec4& color)
640 {
641 glClearBufferfv(buffer, drawbuffer, &color[0]);
642 }
643
ClearBuffer(GLenum buffer,GLint drawbuffer,const ivec4 & color)644 void ClearBuffer(GLenum buffer, GLint drawbuffer, const ivec4& color)
645 {
646 glClearBufferiv(buffer, drawbuffer, &color[0]);
647 }
648
ClearBuffer(GLenum buffer,GLint drawbuffer,const uvec4 & color)649 void ClearBuffer(GLenum buffer, GLint drawbuffer, const uvec4& color)
650 {
651 glClearBufferuiv(buffer, drawbuffer, &color[0]);
652 }
653
CheckUniform(GLuint program,const std::string & name,const std::map<std::string,GLuint> & name_index_map,GLint size,GLenum type)654 bool CheckUniform(GLuint program, const std::string& name, const std::map<std::string, GLuint>& name_index_map,
655 GLint size, GLenum type)
656 {
657 std::map<std::string, GLuint>::const_iterator iter = name_index_map.find(name);
658 assert(iter != name_index_map.end());
659
660 GLchar name_gl[32];
661 GLsizei length_gl;
662 GLint size_gl;
663 GLenum type_gl;
664
665 glGetActiveUniform(program, iter->second, sizeof(name_gl), &length_gl, &size_gl, &type_gl, name_gl);
666
667 if (std::string(name_gl) != name)
668 {
669 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform name is " << name_gl
670 << " should be " << name << tcu::TestLog::EndMessage;
671 return false;
672 }
673 if (length_gl != static_cast<GLsizei>(name.length()))
674 {
675 m_context.getTestContext().getLog()
676 << tcu::TestLog::Message << "Uniform length is " << length_gl << " should be " << name << "(" << name_gl
677 << ")" << tcu::TestLog::EndMessage;
678 return false;
679 }
680 if (size_gl != size)
681 {
682 m_context.getTestContext().getLog()
683 << tcu::TestLog::Message << "Uniform size is " << size_gl << " should be " << size << "(" << name_gl
684 << ")" << tcu::TestLog::EndMessage;
685 return false;
686 }
687 if (type_gl != type)
688 {
689 m_context.getTestContext().getLog()
690 << tcu::TestLog::Message << "Uniform type is " << type_gl << " should be " << type << "(" << name_gl
691 << ")" << tcu::TestLog::EndMessage;
692 return false;
693 }
694
695 return true;
696 }
697
CheckMax(GLenum pname,GLint min_value)698 bool CheckMax(GLenum pname, GLint min_value)
699 {
700 GLboolean b;
701 GLint i;
702 GLfloat f;
703 GLdouble d;
704 GLint64 i64;
705
706 glGetIntegerv(pname, &i);
707 if (i < min_value)
708 return false;
709
710 glGetBooleanv(pname, &b);
711 if (b != (i ? GL_TRUE : GL_FALSE))
712 return false;
713
714 glGetFloatv(pname, &f);
715 if (static_cast<GLint>(f) < min_value)
716 return false;
717
718 glGetDoublev(pname, &d);
719 if (static_cast<GLint>(d) < min_value)
720 return false;
721
722 glGetInteger64v(pname, &i64);
723 if (static_cast<GLint>(i64) < min_value)
724 return false;
725
726 return true;
727 }
728
CheckBinding(GLuint unit,GLuint texture,GLint level,GLboolean layered,GLint layer,GLenum access,GLenum format)729 bool CheckBinding(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access,
730 GLenum format)
731 {
732 GLint i;
733 GLboolean b;
734
735 glGetIntegeri_v(GL_IMAGE_BINDING_NAME, unit, &i);
736 if (static_cast<GLuint>(i) != texture)
737 {
738 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME is " << i
739 << " should be " << texture << tcu::TestLog::EndMessage;
740 return false;
741 }
742 glGetBooleani_v(GL_IMAGE_BINDING_NAME, unit, &b);
743 if (b != (i ? GL_TRUE : GL_FALSE))
744 {
745 m_context.getTestContext().getLog()
746 << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME (as boolean) is " << b << " should be "
747 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
748 return false;
749 }
750
751 glGetIntegeri_v(GL_IMAGE_BINDING_LEVEL, unit, &i);
752 if (i != level)
753 {
754 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL is " << i
755 << " should be " << level << tcu::TestLog::EndMessage;
756 return false;
757 }
758 glGetBooleani_v(GL_IMAGE_BINDING_LEVEL, unit, &b);
759 if (b != (i ? GL_TRUE : GL_FALSE))
760 {
761 m_context.getTestContext().getLog()
762 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL (as boolean) is " << b << " should be "
763 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
764 return false;
765 }
766
767 glGetIntegeri_v(GL_IMAGE_BINDING_LAYERED, unit, &i);
768 if (i != layered)
769 {
770 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED is " << i
771 << " should be " << layered << tcu::TestLog::EndMessage;
772 return false;
773 }
774 glGetBooleani_v(GL_IMAGE_BINDING_LAYERED, unit, &b);
775 if (b != (i ? GL_TRUE : GL_FALSE))
776 {
777 m_context.getTestContext().getLog()
778 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED (as boolean) is " << b << " should be "
779 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
780 return false;
781 }
782
783 glGetIntegeri_v(GL_IMAGE_BINDING_LAYER, unit, &i);
784 if (i != layer)
785 {
786 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER is " << i
787 << " should be " << layer << tcu::TestLog::EndMessage;
788 return false;
789 }
790 glGetBooleani_v(GL_IMAGE_BINDING_LAYER, unit, &b);
791 if (b != (i ? GL_TRUE : GL_FALSE))
792 {
793 m_context.getTestContext().getLog()
794 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER (as boolean) is " << b << " should be "
795 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
796 return false;
797 }
798
799 glGetIntegeri_v(GL_IMAGE_BINDING_ACCESS, unit, &i);
800 if (static_cast<GLenum>(i) != access)
801 {
802 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS is " << i
803 << " should be " << access << tcu::TestLog::EndMessage;
804 return false;
805 }
806 glGetBooleani_v(GL_IMAGE_BINDING_ACCESS, unit, &b);
807 if (b != (i ? GL_TRUE : GL_FALSE))
808 {
809 m_context.getTestContext().getLog()
810 << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS (as boolean) is " << b << " should be "
811 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
812 return false;
813 }
814
815 glGetIntegeri_v(GL_IMAGE_BINDING_FORMAT, unit, &i);
816 if (static_cast<GLenum>(i) != format)
817 {
818 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT is " << i
819 << " should be " << format << tcu::TestLog::EndMessage;
820 return false;
821 }
822 glGetBooleani_v(GL_IMAGE_BINDING_FORMAT, unit, &b);
823 if (b != (i ? GL_TRUE : GL_FALSE))
824 {
825 m_context.getTestContext().getLog()
826 << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT (as boolean) is " << b << " should be "
827 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
828 return false;
829 }
830
831 return true;
832 }
EnumToString(GLenum e)833 const char* EnumToString(GLenum e)
834 {
835 switch (e)
836 {
837 case GL_TEXTURE_1D:
838 return "GL_TEXTURE_1D";
839 case GL_TEXTURE_2D:
840 return "GL_TEXTURE_2D";
841 case GL_TEXTURE_3D:
842 return "GL_TEXTURE_3D";
843 case GL_TEXTURE_RECTANGLE:
844 return "GL_TEXTURE_RECTANGLE";
845 case GL_TEXTURE_CUBE_MAP:
846 return "GL_TEXTURE_CUBE_MAP";
847 case GL_TEXTURE_1D_ARRAY:
848 return "GL_TEXTURE_1D_ARRAY";
849 case GL_TEXTURE_2D_ARRAY:
850 return "GL_TEXTURE_2D_ARRAY";
851 case GL_TEXTURE_CUBE_MAP_ARRAY:
852 return "GL_TEXTURE_CUBE_MAP_ARRAY";
853
854 default:
855 assert(0);
856 break;
857 }
858 return NULL;
859 }
860 };
861
862 template <>
Format()863 GLenum ShaderImageLoadStoreBase::Format<vec4>()
864 {
865 return GL_RGBA;
866 }
867
868 template <>
Format()869 GLenum ShaderImageLoadStoreBase::Format<ivec4>()
870 {
871 return GL_RGBA_INTEGER;
872 }
873
874 template <>
Format()875 GLenum ShaderImageLoadStoreBase::Format<uvec4>()
876 {
877 return GL_RGBA_INTEGER;
878 }
879
880 template <>
Format()881 GLenum ShaderImageLoadStoreBase::Format<GLint>()
882 {
883 return GL_RED_INTEGER;
884 }
885
886 template <>
Format()887 GLenum ShaderImageLoadStoreBase::Format<GLuint>()
888 {
889 return GL_RED_INTEGER;
890 }
891
892 template <>
Type()893 GLenum ShaderImageLoadStoreBase::Type<vec4>()
894 {
895 return GL_FLOAT;
896 }
897
898 template <>
Type()899 GLenum ShaderImageLoadStoreBase::Type<ivec4>()
900 {
901 return GL_INT;
902 }
903
904 template <>
Type()905 GLenum ShaderImageLoadStoreBase::Type<uvec4>()
906 {
907 return GL_UNSIGNED_INT;
908 }
909
910 template <>
Type()911 GLenum ShaderImageLoadStoreBase::Type<GLint>()
912 {
913 return GL_INT;
914 }
915
916 template <>
Type()917 GLenum ShaderImageLoadStoreBase::Type<GLuint>()
918 {
919 return GL_UNSIGNED_INT;
920 }
921
922 template <>
TypePrefix()923 std::string ShaderImageLoadStoreBase::TypePrefix<vec4>()
924 {
925 return "";
926 }
927
928 template <>
TypePrefix()929 std::string ShaderImageLoadStoreBase::TypePrefix<ivec4>()
930 {
931 return "i";
932 }
933
934 template <>
TypePrefix()935 std::string ShaderImageLoadStoreBase::TypePrefix<uvec4>()
936 {
937 return "u";
938 }
939
940 template <>
TypePrefix()941 std::string ShaderImageLoadStoreBase::TypePrefix<GLint>()
942 {
943 return "i";
944 }
945
946 template <>
TypePrefix()947 std::string ShaderImageLoadStoreBase::TypePrefix<GLuint>()
948 {
949 return "u";
950 }
951
952 template <>
ImageType(GLenum target)953 GLenum ShaderImageLoadStoreBase::ImageType<vec4>(GLenum target)
954 {
955 switch (target)
956 {
957 case GL_TEXTURE_1D:
958 return GL_IMAGE_1D;
959 case GL_TEXTURE_2D:
960 return GL_IMAGE_2D;
961 case GL_TEXTURE_3D:
962 return GL_IMAGE_3D;
963 case GL_TEXTURE_RECTANGLE:
964 return GL_IMAGE_2D_RECT;
965 case GL_TEXTURE_CUBE_MAP:
966 return GL_IMAGE_CUBE;
967 case GL_TEXTURE_BUFFER:
968 return GL_IMAGE_BUFFER;
969 case GL_TEXTURE_1D_ARRAY:
970 return GL_IMAGE_1D_ARRAY;
971 case GL_TEXTURE_2D_ARRAY:
972 return GL_IMAGE_2D_ARRAY;
973 case GL_TEXTURE_CUBE_MAP_ARRAY:
974 return GL_IMAGE_CUBE_MAP_ARRAY;
975 case GL_TEXTURE_2D_MULTISAMPLE:
976 return GL_IMAGE_2D_MULTISAMPLE;
977 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
978 return GL_IMAGE_2D_MULTISAMPLE_ARRAY;
979 }
980 assert(0);
981 return 0;
982 }
983
984 template <>
ImageType(GLenum target)985 GLenum ShaderImageLoadStoreBase::ImageType<ivec4>(GLenum target)
986 {
987 switch (target)
988 {
989 case GL_TEXTURE_1D:
990 return GL_INT_IMAGE_1D;
991 case GL_TEXTURE_2D:
992 return GL_INT_IMAGE_2D;
993 case GL_TEXTURE_3D:
994 return GL_INT_IMAGE_3D;
995 case GL_TEXTURE_RECTANGLE:
996 return GL_INT_IMAGE_2D_RECT;
997 case GL_TEXTURE_CUBE_MAP:
998 return GL_INT_IMAGE_CUBE;
999 case GL_TEXTURE_BUFFER:
1000 return GL_INT_IMAGE_BUFFER;
1001 case GL_TEXTURE_1D_ARRAY:
1002 return GL_INT_IMAGE_1D_ARRAY;
1003 case GL_TEXTURE_2D_ARRAY:
1004 return GL_INT_IMAGE_2D_ARRAY;
1005 case GL_TEXTURE_CUBE_MAP_ARRAY:
1006 return GL_INT_IMAGE_CUBE_MAP_ARRAY;
1007 case GL_TEXTURE_2D_MULTISAMPLE:
1008 return GL_INT_IMAGE_2D_MULTISAMPLE;
1009 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1010 return GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY;
1011 }
1012 assert(0);
1013 return 0;
1014 }
1015
1016 template <>
ImageType(GLenum target)1017 GLenum ShaderImageLoadStoreBase::ImageType<uvec4>(GLenum target)
1018 {
1019 switch (target)
1020 {
1021 case GL_TEXTURE_1D:
1022 return GL_UNSIGNED_INT_IMAGE_1D;
1023 case GL_TEXTURE_2D:
1024 return GL_UNSIGNED_INT_IMAGE_2D;
1025 case GL_TEXTURE_3D:
1026 return GL_UNSIGNED_INT_IMAGE_3D;
1027 case GL_TEXTURE_RECTANGLE:
1028 return GL_UNSIGNED_INT_IMAGE_2D_RECT;
1029 case GL_TEXTURE_CUBE_MAP:
1030 return GL_UNSIGNED_INT_IMAGE_CUBE;
1031 case GL_TEXTURE_BUFFER:
1032 return GL_UNSIGNED_INT_IMAGE_BUFFER;
1033 case GL_TEXTURE_1D_ARRAY:
1034 return GL_UNSIGNED_INT_IMAGE_1D_ARRAY;
1035 case GL_TEXTURE_2D_ARRAY:
1036 return GL_UNSIGNED_INT_IMAGE_2D_ARRAY;
1037 case GL_TEXTURE_CUBE_MAP_ARRAY:
1038 return GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY;
1039 case GL_TEXTURE_2D_MULTISAMPLE:
1040 return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE;
1041 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1042 return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY;
1043 }
1044 assert(0);
1045 return 0;
1046 }
1047
1048 //-----------------------------------------------------------------------------
1049 // 1.1.1 BasicAPIGet
1050 //-----------------------------------------------------------------------------
1051 class BasicAPIGet : public ShaderImageLoadStoreBase
1052 {
Run()1053 virtual long Run()
1054 {
1055 if (!CheckMax(GL_MAX_IMAGE_UNITS, 8))
1056 {
1057 m_context.getTestContext().getLog()
1058 << tcu::TestLog::Message << "GL_MAX_IMAGE_UNITS value is invalid." << tcu::TestLog::EndMessage;
1059 return ERROR;
1060 }
1061 if (!CheckMax(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 8))
1062 {
1063 m_context.getTestContext().getLog()
1064 << tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES value is invalid."
1065 << tcu::TestLog::EndMessage;
1066 return ERROR;
1067 }
1068 if (!CheckMax(GL_MAX_IMAGE_SAMPLES, 0))
1069 {
1070 m_context.getTestContext().getLog()
1071 << tcu::TestLog::Message << "GL_MAX_IMAGE_SAMPLES value is invalid." << tcu::TestLog::EndMessage;
1072 return ERROR;
1073 }
1074 if (!CheckMax(GL_MAX_VERTEX_IMAGE_UNIFORMS, 0))
1075 {
1076 m_context.getTestContext().getLog()
1077 << tcu::TestLog::Message << "GL_MAX_VERTEX_IMAGE_UNIFORMS value is invalid."
1078 << tcu::TestLog::EndMessage;
1079 return ERROR;
1080 }
1081 if (!CheckMax(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, 0))
1082 {
1083 m_context.getTestContext().getLog()
1084 << tcu::TestLog::Message << "GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS value is invalid."
1085 << tcu::TestLog::EndMessage;
1086 return ERROR;
1087 }
1088 if (!CheckMax(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, 0))
1089 {
1090 m_context.getTestContext().getLog()
1091 << tcu::TestLog::Message << "GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS value is invalid."
1092 << tcu::TestLog::EndMessage;
1093 return ERROR;
1094 }
1095 if (!CheckMax(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, 0))
1096 {
1097 m_context.getTestContext().getLog()
1098 << tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS value is invalid."
1099 << tcu::TestLog::EndMessage;
1100 return ERROR;
1101 }
1102 if (!CheckMax(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, 8))
1103 {
1104 m_context.getTestContext().getLog()
1105 << tcu::TestLog::Message << "GL_MAX_FRAGMENT_IMAGE_UNIFORMS value is invalid."
1106 << tcu::TestLog::EndMessage;
1107 return ERROR;
1108 }
1109 if (!CheckMax(GL_MAX_COMBINED_IMAGE_UNIFORMS, 8))
1110 {
1111 m_context.getTestContext().getLog()
1112 << tcu::TestLog::Message << "GL_MAX_COMBINED_IMAGE_UNIFORMS value is invalid."
1113 << tcu::TestLog::EndMessage;
1114 return ERROR;
1115 }
1116 return NO_ERROR;
1117 }
1118 };
1119 //-----------------------------------------------------------------------------
1120 // 1.1.2 BasicAPIBind
1121 //-----------------------------------------------------------------------------
1122 class BasicAPIBind : public ShaderImageLoadStoreBase
1123 {
1124 GLuint m_texture;
1125
Setup()1126 virtual long Setup()
1127 {
1128 m_texture = 0;
1129 return NO_ERROR;
1130 }
1131
Run()1132 virtual long Run()
1133 {
1134 for (GLuint index = 0; index < 8; ++index)
1135 {
1136 if (!CheckBinding(index, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8))
1137 {
1138 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Binding point " << index
1139 << " has invalid default state." << tcu::TestLog::EndMessage;
1140 return ERROR;
1141 }
1142 }
1143
1144 glGenTextures(1, &m_texture);
1145 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
1146 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_R32F, 16, 16, 4, 0, GL_RED, GL_FLOAT, NULL);
1147 glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, 8, 8, 4, 0, GL_RED, GL_FLOAT, NULL);
1148 glTexImage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32F, 4, 4, 4, 0, GL_RED, GL_FLOAT, NULL);
1149 glTexImage3D(GL_TEXTURE_2D_ARRAY, 3, GL_R32F, 2, 2, 4, 0, GL_RED, GL_FLOAT, NULL);
1150 glTexImage3D(GL_TEXTURE_2D_ARRAY, 4, GL_R32F, 1, 1, 4, 0, GL_RED, GL_FLOAT, NULL);
1151 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1152
1153 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
1154 if (!CheckBinding(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F))
1155 return ERROR;
1156
1157 glBindImageTexture(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8);
1158 if (!CheckBinding(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8))
1159 return ERROR;
1160
1161 glBindImageTexture(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16);
1162 if (!CheckBinding(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16))
1163 return ERROR;
1164
1165 glBindImageTexture(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I);
1166 if (!CheckBinding(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I))
1167 return ERROR;
1168
1169 glDeleteTextures(1, &m_texture);
1170 m_texture = 0;
1171
1172 for (GLuint index = 0; index < 8; ++index)
1173 {
1174 GLint name;
1175 glGetIntegeri_v(GL_IMAGE_BINDING_NAME, index, &name);
1176 if (name != 0)
1177 {
1178 m_context.getTestContext().getLog()
1179 << tcu::TestLog::Message << "Binding point " << index
1180 << " should be set to 0 after texture deletion." << tcu::TestLog::EndMessage;
1181 return ERROR;
1182 }
1183 }
1184
1185 return NO_ERROR;
1186 }
1187
Cleanup()1188 virtual long Cleanup()
1189 {
1190 glDeleteTextures(1, &m_texture);
1191 return NO_ERROR;
1192 }
1193 };
1194 //-----------------------------------------------------------------------------
1195 // 1.1.3 BasicAPIBarrier
1196 //-----------------------------------------------------------------------------
1197 class BasicAPIBarrier : public ShaderImageLoadStoreBase
1198 {
Run()1199 virtual long Run()
1200 {
1201 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
1202 glMemoryBarrier(GL_ELEMENT_ARRAY_BARRIER_BIT);
1203 glMemoryBarrier(GL_UNIFORM_BARRIER_BIT);
1204 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
1205 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1206 glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
1207 glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT);
1208 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1209 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1210 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1211 glMemoryBarrier(GL_TRANSFORM_FEEDBACK_BARRIER_BIT);
1212 glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
1213
1214 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT |
1215 GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT |
1216 GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT |
1217 GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT);
1218
1219 glMemoryBarrier(GL_ALL_BARRIER_BITS);
1220
1221 return NO_ERROR;
1222 }
1223 };
1224 //-----------------------------------------------------------------------------
1225 // 1.1.4 BasicAPITexParam
1226 //-----------------------------------------------------------------------------
1227 class BasicAPITexParam : public ShaderImageLoadStoreBase
1228 {
1229 GLuint m_texture;
1230
Setup()1231 virtual long Setup()
1232 {
1233 m_texture = 0;
1234 return NO_ERROR;
1235 }
1236
Run()1237 virtual long Run()
1238 {
1239 glGenTextures(1, &m_texture);
1240 glBindTexture(GL_TEXTURE_2D, m_texture);
1241 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, 16, 16, 0, GL_RED, GL_FLOAT, NULL);
1242
1243 GLint i;
1244 GLfloat f;
1245 GLuint ui;
1246
1247 glGetTexParameteriv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1248 if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1249 {
1250 m_context.getTestContext().getLog()
1251 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1252 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1253 << tcu::TestLog::EndMessage;
1254 return ERROR;
1255 }
1256 glGetTexParameterfv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &f);
1257 if (static_cast<GLenum>(f) != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1258 {
1259 m_context.getTestContext().getLog()
1260 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1261 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1262 << tcu::TestLog::EndMessage;
1263 return ERROR;
1264 }
1265 glGetTexParameterIiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1266 if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1267 {
1268 m_context.getTestContext().getLog()
1269 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1270 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1271 << tcu::TestLog::EndMessage;
1272 return ERROR;
1273 }
1274 glGetTexParameterIuiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &ui);
1275 if (ui != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1276 {
1277 m_context.getTestContext().getLog()
1278 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1279 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1280 << tcu::TestLog::EndMessage;
1281 return ERROR;
1282 }
1283
1284 return NO_ERROR;
1285 }
1286
Cleanup()1287 virtual long Cleanup()
1288 {
1289 glDeleteTextures(1, &m_texture);
1290 return NO_ERROR;
1291 }
1292 };
1293 //-----------------------------------------------------------------------------
1294 // 1.2.1 BasicAllFormatsStore
1295 //-----------------------------------------------------------------------------
1296 class BasicAllFormatsStore : public ShaderImageLoadStoreBase
1297 {
1298 GLuint m_vao;
1299 GLuint m_vbo;
1300
Setup()1301 virtual long Setup()
1302 {
1303 m_vao = 0;
1304 m_vbo = 0;
1305 return NO_ERROR;
1306 }
1307
Run()1308 virtual long Run()
1309 {
1310 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1311
1312 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1313 return ERROR;
1314 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1315 return ERROR;
1316 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1317 return ERROR;
1318
1319 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1320 return ERROR;
1321 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1322 return ERROR;
1323 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1324 return ERROR;
1325
1326 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1327 return ERROR;
1328 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1329 return ERROR;
1330 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1331 return ERROR;
1332
1333 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1334 return ERROR;
1335
1336 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1337 return ERROR;
1338 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1339 return ERROR;
1340 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1341 return ERROR;
1342
1343 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1344 return ERROR;
1345 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1346 return ERROR;
1347 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1348 return ERROR;
1349
1350 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1351 return ERROR;
1352 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1353 return ERROR;
1354 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1355 return ERROR;
1356 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1357 return ERROR;
1358
1359 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1360 return ERROR;
1361 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1362 return ERROR;
1363 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1364 return ERROR;
1365
1366 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1367 return ERROR;
1368 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1369 return ERROR;
1370 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1371 return ERROR;
1372
1373 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1374 return ERROR;
1375 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1376 return ERROR;
1377 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1378 return ERROR;
1379 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1380 return ERROR;
1381
1382 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1383 return ERROR;
1384 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1385 return ERROR;
1386 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1387 return ERROR;
1388
1389 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1390 return ERROR;
1391 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1392 return ERROR;
1393 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1394 return ERROR;
1395
1396 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1397 return ERROR;
1398 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1399 return ERROR;
1400 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1401 return ERROR;
1402
1403 return NO_ERROR;
1404 }
1405
1406 template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)1407 bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
1408 {
1409 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
1410 " gl_Position = i_position;" NL "}";
1411 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str());
1412 const int kSize = 16;
1413 std::vector<T> data(kSize * kSize);
1414 GLuint texture;
1415 glGenTextures(1, &texture);
1416
1417 for (GLuint unit = 0; unit < 8; ++unit)
1418 {
1419 glBindTexture(GL_TEXTURE_2D, texture);
1420 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1421 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1422 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
1423 glBindTexture(GL_TEXTURE_2D, 0);
1424
1425 glViewport(0, 0, kSize, kSize);
1426 glUseProgram(program);
1427 glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
1428 glBindVertexArray(m_vao);
1429 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1430
1431 glBindTexture(GL_TEXTURE_2D, texture);
1432 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1433 glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
1434
1435 for (int i = 0; i < kSize * kSize; ++i)
1436 {
1437 if (!Equal(data[i], expected_value, internalformat))
1438 {
1439 glDeleteTextures(1, &texture);
1440 glUseProgram(0);
1441 glDeleteProgram(program);
1442 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[i])
1443 << ". Value should be: " << ToString(expected_value)
1444 << ". Format is: " << FormatEnumToString(internalformat)
1445 << ". Unit is: " << unit << tcu::TestLog::EndMessage;
1446 return false;
1447 }
1448 }
1449
1450 if (unit < 7)
1451 {
1452 glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1));
1453 }
1454 }
1455
1456 glDeleteTextures(1, &texture);
1457 glUseProgram(0);
1458 glDeleteProgram(program);
1459
1460 return true;
1461 }
1462
Cleanup()1463 virtual long Cleanup()
1464 {
1465 glViewport(0, 0, getWindowWidth(), getWindowHeight());
1466 glDeleteVertexArrays(1, &m_vao);
1467 glDeleteBuffers(1, &m_vbo);
1468 return NO_ERROR;
1469 }
1470
1471 template <typename T>
GenFS(GLenum internalformat,const T & value)1472 std::string GenFS(GLenum internalformat, const T& value)
1473 {
1474 std::ostringstream os;
1475 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1476 << TypePrefix<T>() << "image2D g_image;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
1477 " imageStore(g_image, coord, "
1478 << TypePrefix<T>() << "vec4" << value << ");" NL " discard;" NL "}";
1479 return os.str();
1480 }
1481 };
1482 //-----------------------------------------------------------------------------
1483 // 1.2.2 BasicAllFormatsLoad
1484 //-----------------------------------------------------------------------------
1485 class BasicAllFormatsLoad : public ShaderImageLoadStoreBase
1486 {
1487 GLuint m_vao;
1488 GLuint m_vbo;
1489
Setup()1490 virtual long Setup()
1491 {
1492 m_vao = 0;
1493 m_vbo = 0;
1494 return NO_ERROR;
1495 }
1496
Run()1497 virtual long Run()
1498 {
1499 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1500
1501 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1502 return ERROR;
1503 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1504 return ERROR;
1505 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1506 return ERROR;
1507
1508 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1509 return ERROR;
1510 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1511 return ERROR;
1512 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1513 return ERROR;
1514
1515 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1516 return ERROR;
1517 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1518 return ERROR;
1519 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1520 return ERROR;
1521
1522 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1523 return ERROR;
1524
1525 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1526 return ERROR;
1527 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1528 return ERROR;
1529 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1530 return ERROR;
1531
1532 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1533 return ERROR;
1534 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1535 return ERROR;
1536 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1537 return ERROR;
1538
1539 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1540 return ERROR;
1541 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1542 return ERROR;
1543 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1544 return ERROR;
1545 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1546 return ERROR;
1547
1548 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1549 return ERROR;
1550 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1551 return ERROR;
1552 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1553 return ERROR;
1554
1555 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1556 return ERROR;
1557 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1558 return ERROR;
1559 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1560 return ERROR;
1561
1562 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1563 return ERROR;
1564 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1565 return ERROR;
1566 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1567 return ERROR;
1568 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1569 return ERROR;
1570
1571 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1572 return ERROR;
1573 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1574 return ERROR;
1575 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1576 return ERROR;
1577
1578 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1579 return ERROR;
1580 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1581 return ERROR;
1582 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1583 return ERROR;
1584
1585 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1586 return ERROR;
1587 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1588 return ERROR;
1589 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1590 return ERROR;
1591
1592 return NO_ERROR;
1593 }
1594
1595 template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)1596 bool Read(GLenum internalformat, const T& value, const T& expected_value)
1597 {
1598 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
1599 " gl_Position = i_position;" NL "}";
1600 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str());
1601 const int kSize = 16;
1602 std::vector<T> data(kSize * kSize, value);
1603 GLuint texture;
1604 glGenTextures(1, &texture);
1605
1606 for (GLuint unit = 0; unit < 8; ++unit)
1607 {
1608 glBindTexture(GL_TEXTURE_2D, texture);
1609 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1610 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1611 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
1612 glBindTexture(GL_TEXTURE_2D, 0);
1613
1614 glViewport(0, 0, kSize, kSize);
1615 glClear(GL_COLOR_BUFFER_BIT);
1616 glUseProgram(program);
1617 glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
1618 glBindVertexArray(m_vao);
1619 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1620
1621 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
1622 {
1623 glDeleteTextures(1, &texture);
1624 glUseProgram(0);
1625 glDeleteProgram(program);
1626 m_context.getTestContext().getLog()
1627 << tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat)
1628 << ". Unit is: " << unit << tcu::TestLog::EndMessage;
1629 return false;
1630 }
1631
1632 if (unit < 7)
1633 {
1634 glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1));
1635 }
1636 }
1637
1638 glDeleteTextures(1, &texture);
1639 glUseProgram(0);
1640 glDeleteProgram(program);
1641
1642 return true;
1643 }
1644
Cleanup()1645 virtual long Cleanup()
1646 {
1647 glViewport(0, 0, getWindowWidth(), getWindowHeight());
1648 glDeleteVertexArrays(1, &m_vao);
1649 glDeleteBuffers(1, &m_vbo);
1650 return NO_ERROR;
1651 }
1652
1653 template <typename T>
GenFS(GLenum internalformat,const T & expected_value)1654 std::string GenFS(GLenum internalformat, const T& expected_value)
1655 {
1656 std::ostringstream os;
1657 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
1658 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
1659 << "image2D g_image;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " "
1660 << TypePrefix<T>() << "vec4 v = imageLoad(g_image, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
1661 << expected_value
1662 << ") o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL " else o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
1663 return os.str();
1664 }
1665 };
1666 //-----------------------------------------------------------------------------
1667 // 1.2.3 BasicAllFormatsStoreGeometryStages
1668 //-----------------------------------------------------------------------------
1669 class BasicAllFormatsStoreGeometryStages : public ShaderImageLoadStoreBase
1670 {
1671 GLuint m_vao;
1672
Setup()1673 virtual long Setup()
1674 {
1675 glGenVertexArrays(1, &m_vao);
1676 return NO_ERROR;
1677 }
1678
Run()1679 virtual long Run()
1680 {
1681 if (!SupportedInGeomStages(1))
1682 return NOT_SUPPORTED;
1683 glEnable(GL_RASTERIZER_DISCARD);
1684
1685 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1686 return ERROR;
1687 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1688 return ERROR;
1689 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1690 return ERROR;
1691
1692 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1693 return ERROR;
1694 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1695 return ERROR;
1696 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1697 return ERROR;
1698
1699 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1700 return ERROR;
1701 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1702 return ERROR;
1703 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1704 return ERROR;
1705
1706 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1707 return ERROR;
1708
1709 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1710 return ERROR;
1711 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1712 return ERROR;
1713 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1714 return ERROR;
1715
1716 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1717 return ERROR;
1718 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1719 return ERROR;
1720 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1721 return ERROR;
1722
1723 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1724 return ERROR;
1725 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1726 return ERROR;
1727 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1728 return ERROR;
1729 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1730 return ERROR;
1731
1732 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1733 return ERROR;
1734 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1735 return ERROR;
1736 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1737 return ERROR;
1738
1739 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1740 return ERROR;
1741 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1742 return ERROR;
1743 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1744 return ERROR;
1745
1746 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1747 return ERROR;
1748 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1749 return ERROR;
1750 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1751 return ERROR;
1752 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1753 return ERROR;
1754
1755 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1756 return ERROR;
1757 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1758 return ERROR;
1759 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1760 return ERROR;
1761
1762 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1763 return ERROR;
1764 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1765 return ERROR;
1766 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1767 return ERROR;
1768
1769 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1770 return ERROR;
1771 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1772 return ERROR;
1773 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1774 return ERROR;
1775
1776 return NO_ERROR;
1777 }
1778
1779 template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)1780 bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
1781 {
1782 const GLuint program =
1783 BuildProgram(GenVS(internalformat, write_value).c_str(), GenTCS(internalformat, write_value).c_str(),
1784 GenTES(internalformat, write_value).c_str(), GenGS(internalformat, write_value).c_str(), NULL);
1785 const int kSize = 1;
1786 std::vector<T> data(kSize * kSize);
1787 GLuint texture[4];
1788 glGenTextures(4, texture);
1789
1790 for (int i = 0; i < 4; ++i)
1791 {
1792 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1793 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1794 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1795 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]);
1796 }
1797 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1798
1799 glUseProgram(program);
1800 glUniform1i(glGetUniformLocation(program, "g_image0"), 0);
1801 glUniform1i(glGetUniformLocation(program, "g_image1"), 1);
1802 glUniform1i(glGetUniformLocation(program, "g_image2"), 2);
1803 glUniform1i(glGetUniformLocation(program, "g_image3"), 3);
1804 for (GLuint i = 0; i < 4; ++i)
1805 {
1806 glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
1807 }
1808 glBindVertexArray(m_vao);
1809 glPatchParameteri(GL_PATCH_VERTICES, 1);
1810 glDrawArrays(GL_PATCHES, 0, 1);
1811 glPatchParameteri(GL_PATCH_VERTICES, 3);
1812
1813 for (int i = 0; i < 4; ++i)
1814 {
1815 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1816 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1817 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
1818
1819 if (!Equal(data[0], expected_value, internalformat))
1820 {
1821 glDeleteTextures(4, texture);
1822 glUseProgram(0);
1823 glDeleteProgram(program);
1824 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[0])
1825 << ". Value should be: " << ToString(expected_value)
1826 << ". Format is: " << FormatEnumToString(internalformat)
1827 << ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage;
1828 return false;
1829 }
1830 }
1831 glDeleteTextures(4, texture);
1832 glUseProgram(0);
1833 glDeleteProgram(program);
1834 return true;
1835 }
1836
Cleanup()1837 virtual long Cleanup()
1838 {
1839 glDisable(GL_RASTERIZER_DISCARD);
1840 glDeleteVertexArrays(1, &m_vao);
1841 return NO_ERROR;
1842 }
1843
1844 template <typename T>
GenVS(GLenum internalformat,const T & value)1845 std::string GenVS(GLenum internalformat, const T& value)
1846 {
1847 std::ostringstream os;
1848 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1849 << TypePrefix<T>() << "image2DArray g_image0;" NL "void main() {" NL
1850 " ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL " imageStore(g_image0, coord, "
1851 << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1852 return os.str();
1853 }
1854
1855 template <typename T>
GenTCS(GLenum internalformat,const T & value)1856 std::string GenTCS(GLenum internalformat, const T& value)
1857 {
1858 std::ostringstream os;
1859 os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat)
1860 << ") writeonly uniform " << TypePrefix<T>()
1861 << "image2DArray g_image1;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL
1862 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL
1863 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL
1864 " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL " imageStore(g_image1, coord, "
1865 << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1866 return os.str();
1867 }
1868
1869 template <typename T>
GenTES(GLenum internalformat,const T & value)1870 std::string GenTES(GLenum internalformat, const T& value)
1871 {
1872 std::ostringstream os;
1873 os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout("
1874 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
1875 << "image2DArray g_image2;" NL "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL
1876 " imageStore(g_image2, coord, "
1877 << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1878 return os.str();
1879 }
1880
1881 template <typename T>
GenGS(GLenum internalformat,const T & value)1882 std::string GenGS(GLenum internalformat, const T& value)
1883 {
1884 std::ostringstream os;
1885 os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout("
1886 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
1887 << "image2DArray g_image3;" NL "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL
1888 " imageStore(g_image3, coord, "
1889 << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1890 return os.str();
1891 }
1892 };
1893 //-----------------------------------------------------------------------------
1894 // 1.2.4 BasicAllFormatsLoadGeometryStages
1895 //-----------------------------------------------------------------------------
1896 class BasicAllFormatsLoadGeometryStages : public ShaderImageLoadStoreBase
1897 {
1898 GLuint m_vao;
1899
Setup()1900 virtual long Setup()
1901 {
1902 glGenVertexArrays(1, &m_vao);
1903 return NO_ERROR;
1904 }
1905
Run()1906 virtual long Run()
1907 {
1908 if (!SupportedInGeomStages(2))
1909 return NOT_SUPPORTED;
1910 glEnable(GL_RASTERIZER_DISCARD);
1911
1912 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1913 return ERROR;
1914 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1915 return ERROR;
1916 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1917 return ERROR;
1918
1919 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1920 return ERROR;
1921 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1922 return ERROR;
1923 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1924 return ERROR;
1925
1926 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1927 return ERROR;
1928 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1929 return ERROR;
1930 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1931 return ERROR;
1932
1933 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1934 return ERROR;
1935
1936 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1937 return ERROR;
1938 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1939 return ERROR;
1940 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1941 return ERROR;
1942
1943 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1944 return ERROR;
1945 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1946 return ERROR;
1947 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1948 return ERROR;
1949
1950 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1951 return ERROR;
1952 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1953 return ERROR;
1954 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1955 return ERROR;
1956 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1957 return ERROR;
1958
1959 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1960 return ERROR;
1961 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1962 return ERROR;
1963 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1964 return ERROR;
1965
1966 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1967 return ERROR;
1968 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1969 return ERROR;
1970 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1971 return ERROR;
1972
1973 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1974 return ERROR;
1975 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1976 return ERROR;
1977 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1978 return ERROR;
1979 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1980 return ERROR;
1981
1982 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1983 return ERROR;
1984 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1985 return ERROR;
1986 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1987 return ERROR;
1988
1989 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1990 return ERROR;
1991 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1992 return ERROR;
1993 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1994 return ERROR;
1995
1996 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1997 return ERROR;
1998 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1999 return ERROR;
2000 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2001 return ERROR;
2002
2003 return NO_ERROR;
2004 }
2005
2006 template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)2007 bool Read(GLenum internalformat, const T& value, const T& expected_value)
2008 {
2009 const GLuint program = BuildProgram(
2010 GenVS(internalformat, expected_value).c_str(), GenTCS(internalformat, expected_value).c_str(),
2011 GenTES(internalformat, expected_value).c_str(), GenGS(internalformat, expected_value).c_str(), NULL);
2012 const int kSize = 1;
2013 std::vector<T> data(kSize * kSize, value);
2014 GLuint texture[8];
2015 glGenTextures(8, texture);
2016
2017 for (int i = 0; i < 4; ++i)
2018 {
2019 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
2020 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2021 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2022 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]);
2023 }
2024 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2025 vec4 zero(0);
2026 for (int i = 4; i < 8; ++i)
2027 {
2028 glBindTexture(GL_TEXTURE_2D, texture[i]);
2029 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2030 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2031 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &zero);
2032 }
2033 glBindTexture(GL_TEXTURE_2D, 0);
2034
2035 glUseProgram(program);
2036 glUniform1i(glGetUniformLocation(program, "g_image0"), 0);
2037 glUniform1i(glGetUniformLocation(program, "g_image1"), 1);
2038 glUniform1i(glGetUniformLocation(program, "g_image2"), 2);
2039 glUniform1i(glGetUniformLocation(program, "g_image3"), 3);
2040 glUniform1i(glGetUniformLocation(program, "g_image0_result"), 4);
2041 glUniform1i(glGetUniformLocation(program, "g_image1_result"), 5);
2042 glUniform1i(glGetUniformLocation(program, "g_image2_result"), 6);
2043 glUniform1i(glGetUniformLocation(program, "g_image3_result"), 7);
2044
2045 for (GLuint i = 0; i < 4; ++i)
2046 {
2047 glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2048 }
2049 for (GLuint i = 4; i < 8; ++i)
2050 {
2051 glBindImageTexture(i, texture[i], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
2052 }
2053 glBindVertexArray(m_vao);
2054 glPatchParameteri(GL_PATCH_VERTICES, 1);
2055 glDrawArrays(GL_PATCHES, 0, 1);
2056 glPatchParameteri(GL_PATCH_VERTICES, 3);
2057
2058 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
2059 const tcu::PixelFormat& pixelFormat = renderTarget.getPixelFormat();
2060 vec4 g_color_eps = vec4(
2061 1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
2062 1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
2063
2064 for (int i = 0; i < 4; ++i)
2065 {
2066 glBindTexture(GL_TEXTURE_2D, texture[i + 4]);
2067 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2068 vec4 result;
2069 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &result[0]);
2070 if (!ColorEqual(result, vec4(0, 1, 0, 1), g_color_eps))
2071 {
2072 glDeleteTextures(8, texture);
2073 glUseProgram(0);
2074 glDeleteProgram(program);
2075 m_context.getTestContext().getLog()
2076 << tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat)
2077 << ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage;
2078 return false;
2079 }
2080 }
2081 glDeleteTextures(8, texture);
2082 glUseProgram(0);
2083 glDeleteProgram(program);
2084 return true;
2085 }
2086
Cleanup()2087 virtual long Cleanup()
2088 {
2089 glDisable(GL_RASTERIZER_DISCARD);
2090 glDeleteVertexArrays(1, &m_vao);
2091 return NO_ERROR;
2092 }
2093
2094 template <typename T>
GenVS(GLenum internalformat,const T & expected_value)2095 std::string GenVS(GLenum internalformat, const T& expected_value)
2096 {
2097 std::ostringstream os;
2098 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
2099 << TypePrefix<T>()
2100 << "image2DArray g_image0;" NL "layout(rgba32f) writeonly uniform image2D g_image0_result;" NL
2101 "void main() {" NL " ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL " "
2102 << TypePrefix<T>() << "vec4 v = imageLoad(g_image0, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
2103 << expected_value << ") imageStore(g_image0_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2104 " else imageStore(g_image0_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2105 return os.str();
2106 }
2107
2108 template <typename T>
GenTCS(GLenum internalformat,const T & expected_value)2109 std::string GenTCS(GLenum internalformat, const T& expected_value)
2110 {
2111 std::ostringstream os;
2112 os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat)
2113 << ") readonly uniform " << TypePrefix<T>()
2114 << "image2DArray g_image1;" NL "layout(rgba32f) writeonly uniform image2D g_image1_result;" NL
2115 "void main() {" NL " gl_TessLevelInner[0] = 1;" NL " gl_TessLevelInner[1] = 1;" NL
2116 " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL " gl_TessLevelOuter[2] = 1;" NL
2117 " gl_TessLevelOuter[3] = 1;" NL " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL " "
2118 << TypePrefix<T>() << "vec4 v = imageLoad(g_image1, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
2119 << expected_value << ") imageStore(g_image1_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2120 " else imageStore(g_image1_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2121 return os.str();
2122 }
2123
2124 template <typename T>
GenTES(GLenum internalformat,const T & expected_value)2125 std::string GenTES(GLenum internalformat, const T& expected_value)
2126 {
2127 std::ostringstream os;
2128 os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout("
2129 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2130 << "image2DArray g_image2;" NL "layout(rgba32f) writeonly uniform image2D g_image2_result;" NL
2131 "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL " "
2132 << TypePrefix<T>() << "vec4 v = imageLoad(g_image2, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
2133 << expected_value << ") imageStore(g_image2_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2134 " else imageStore(g_image2_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2135 return os.str();
2136 }
2137
2138 template <typename T>
GenGS(GLenum internalformat,const T & expected_value)2139 std::string GenGS(GLenum internalformat, const T& expected_value)
2140 {
2141 std::ostringstream os;
2142 os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout("
2143 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2144 << "image2DArray g_image3;" NL "layout(rgba32f) writeonly uniform image2D g_image3_result;" NL
2145 "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL " "
2146 << TypePrefix<T>() << "vec4 v = imageLoad(g_image3, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
2147 << expected_value << ") imageStore(g_image3_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2148 " else imageStore(g_image3_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2149 return os.str();
2150 }
2151 };
2152 //-----------------------------------------------------------------------------
2153 // 1.2.5 BasicAllFormatsLoadStoreComputeStage
2154 //-----------------------------------------------------------------------------
2155 class BasicAllFormatsLoadStoreComputeStage : public ShaderImageLoadStoreBase
2156 {
Run()2157 virtual long Run()
2158 {
2159 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
2160 {
2161 m_context.getTestContext().getLog()
2162 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
2163 << tcu::TestLog::EndMessage;
2164 return NOT_SUPPORTED;
2165 }
2166
2167 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
2168 return ERROR;
2169 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
2170 return ERROR;
2171 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2172 return ERROR;
2173
2174 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
2175 return ERROR;
2176 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
2177 return ERROR;
2178 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2179 return ERROR;
2180
2181 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2182 return ERROR;
2183 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2184 return ERROR;
2185 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2186 return ERROR;
2187
2188 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
2189 return ERROR;
2190
2191 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2192 return ERROR;
2193 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2194 return ERROR;
2195 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2196 return ERROR;
2197
2198 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2199 return ERROR;
2200 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2201 return ERROR;
2202 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2203 return ERROR;
2204
2205 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2206 return ERROR;
2207 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2208 return ERROR;
2209 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2210 return ERROR;
2211 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2212 return ERROR;
2213
2214 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2215 return ERROR;
2216 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2217 return ERROR;
2218 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2219 return ERROR;
2220
2221 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2222 return ERROR;
2223 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2224 return ERROR;
2225 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2226 return ERROR;
2227
2228 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
2229 return ERROR;
2230 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
2231 return ERROR;
2232 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
2233 return ERROR;
2234 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2235 return ERROR;
2236
2237 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
2238 return ERROR;
2239 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
2240 return ERROR;
2241 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2242 return ERROR;
2243
2244 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2245 return ERROR;
2246 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2247 return ERROR;
2248 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2249 return ERROR;
2250
2251 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2252 return ERROR;
2253 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2254 return ERROR;
2255 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2256 return ERROR;
2257
2258 return NO_ERROR;
2259 }
2260
2261 template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)2262 bool Read(GLenum internalformat, const T& value, const T& expected_value)
2263 {
2264 GLuint program;
2265 std::string source = GenCS<T>(internalformat);
2266 const char* const src = source.c_str();
2267 GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
2268 glShaderSource(sh, 1, &src, NULL);
2269 glCompileShader(sh);
2270 program = glCreateProgram();
2271 glAttachShader(program, sh);
2272 glLinkProgram(program);
2273 glDeleteShader(sh);
2274
2275 const int kSize = 1;
2276 std::vector<T> data(kSize * kSize, value);
2277 GLuint texture[2];
2278 glGenTextures(2, texture);
2279
2280 glBindTexture(GL_TEXTURE_2D, texture[0]);
2281 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2282 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2283 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2284 glBindTexture(GL_TEXTURE_2D, texture[1]);
2285 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2286 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2287 vec4 zero(0);
2288 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &zero);
2289
2290 glBindTexture(GL_TEXTURE_2D, 0);
2291
2292 glUseProgram(program);
2293 glUniform1i(glGetUniformLocation(program, "g_image_read"), 0);
2294 glUniform1i(glGetUniformLocation(program, "g_image_write"), 1);
2295
2296 glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2297 glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2298
2299 glDispatchCompute(1, 1, 1);
2300
2301 for (int i = 0; i < 2; ++i)
2302 {
2303 glBindTexture(GL_TEXTURE_2D, texture[i]);
2304 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2305 glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
2306
2307 if (!Equal(data[0], expected_value, internalformat))
2308 {
2309 glDeleteTextures(4, texture);
2310 glUseProgram(0);
2311 glDeleteProgram(program);
2312 m_context.getTestContext().getLog()
2313 << tcu::TestLog::Message << "Value is: " << ToString(data[0])
2314 << ". Value should be: " << ToString(expected_value)
2315 << ". Format is: " << FormatEnumToString(internalformat) << tcu::TestLog::EndMessage;
2316 return false;
2317 }
2318 }
2319 glDeleteTextures(2, texture);
2320 glUseProgram(0);
2321 glDeleteProgram(program);
2322 return true;
2323 }
2324
2325 template <typename T>
GenCS(GLenum internalformat)2326 std::string GenCS(GLenum internalformat)
2327 {
2328 std::ostringstream os;
2329 os << "#version 420 core" NL "#extension GL_ARB_compute_shader : require" NL "layout(local_size_x = 1) in;" NL
2330 "layout("
2331 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2332 << "image2D g_image_read;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2333 << TypePrefix<T>() << "image2D g_image_write;" NL "void main() {" NL
2334 " ivec2 coord = ivec2(int(gl_GlobalInvocationID.x), 0);" NL " "
2335 << TypePrefix<T>()
2336 << "vec4 v = imageLoad(g_image_read, coord);" NL " imageStore(g_image_write, coord, v);" NL "}";
2337 return os.str();
2338 }
2339 };
2340 //-----------------------------------------------------------------------------
2341 // 1.3.1 BasicAllTargetsStore
2342 //-----------------------------------------------------------------------------
2343 class BasicAllTargetsStore : public ShaderImageLoadStoreBase
2344 {
2345 GLuint m_vao;
2346 GLuint m_vbo;
2347
Setup()2348 virtual long Setup()
2349 {
2350 m_vao = 0;
2351 m_vbo = 0;
2352 return NO_ERROR;
2353 }
2354
Run()2355 virtual long Run()
2356 {
2357 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2358
2359 if (!Write(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2360 return ERROR;
2361 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2362 return ERROR;
2363 if (!Write(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2364 return ERROR;
2365
2366 if (!WriteCubeArray(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2367 return ERROR;
2368 if (!WriteCubeArray(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2369 return ERROR;
2370 if (!WriteCubeArray(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2371 return ERROR;
2372
2373 if (SupportedSamples(4))
2374 {
2375 if (!WriteMS(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2376 return ERROR;
2377
2378 GLint isamples;
2379 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
2380 if (isamples >= 4)
2381 {
2382 if (!WriteMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2383 return ERROR;
2384 if (!WriteMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2385 return ERROR;
2386 }
2387 }
2388 return NO_ERROR;
2389 }
2390
Cleanup()2391 virtual long Cleanup()
2392 {
2393 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2394 glDeleteVertexArrays(1, &m_vao);
2395 glDeleteBuffers(1, &m_vbo);
2396 return NO_ERROR;
2397 }
2398
2399 template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)2400 bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
2401 {
2402 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2403 " gl_Position = i_position;" NL "}";
2404 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str());
2405 GLuint textures[8];
2406 GLuint buffer;
2407 glGenTextures(8, textures);
2408 glGenBuffers(1, &buffer);
2409
2410 const int kSize = 16;
2411 std::vector<T> data(kSize * kSize * 2);
2412
2413 glBindTexture(GL_TEXTURE_1D, textures[0]);
2414 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2415 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2416 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2417 glBindTexture(GL_TEXTURE_1D, 0);
2418
2419 glBindTexture(GL_TEXTURE_2D, textures[1]);
2420 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2421 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2422 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2423 glBindTexture(GL_TEXTURE_2D, 0);
2424
2425 glBindTexture(GL_TEXTURE_3D, textures[2]);
2426 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2427 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2428 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2429 glBindTexture(GL_TEXTURE_3D, 0);
2430
2431 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2432 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2433 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2434 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2435 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2436
2437 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2438 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2439 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2440 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2441 &data[0]);
2442 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2443 &data[0]);
2444 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2445 &data[0]);
2446 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2447 &data[0]);
2448 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2449 &data[0]);
2450 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2451 &data[0]);
2452 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2453
2454 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2455 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
2456 glBindBuffer(GL_TEXTURE_BUFFER, 0);
2457 glBindTexture(GL_TEXTURE_BUFFER, textures[5]);
2458 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
2459 glBindTexture(GL_TEXTURE_BUFFER, 0);
2460
2461 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]);
2462 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2463 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2464 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2465 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2466
2467 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2468 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2469 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2470 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2471 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2472
2473 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2474 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2475 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2476 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2477 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2478 glBindImageTexture(5, textures[5], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2479 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2480 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2481
2482 glUseProgram(program);
2483 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
2484 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
2485 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
2486 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
2487 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4);
2488 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5);
2489 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6);
2490 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7);
2491
2492 glBindVertexArray(m_vao);
2493 glViewport(0, 0, kSize, kSize);
2494 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2495
2496 bool status = true;
2497
2498 glBindTexture(GL_TEXTURE_1D, textures[0]);
2499 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2500 glGetTexImage(GL_TEXTURE_1D, 0, Format<T>(), Type<T>(), &data[0]);
2501 glBindTexture(GL_TEXTURE_1D, 0);
2502 for (int i = 0; i < kSize; ++i)
2503 {
2504 if (!tcu::allEqual(data[i], expected_value))
2505 {
2506 status = false;
2507 m_context.getTestContext().getLog()
2508 << tcu::TestLog::Message << "GL_TEXTURE_1D target failed. Value is: " << ToString(data[i])
2509 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2510 break;
2511 }
2512 }
2513 std::fill(data.begin(), data.end(), T(0));
2514
2515 glBindTexture(GL_TEXTURE_2D, textures[1]);
2516 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2517 glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
2518 glBindTexture(GL_TEXTURE_2D, 0);
2519 for (int i = 0; i < kSize * kSize; ++i)
2520 {
2521 if (!tcu::allEqual(data[i], expected_value))
2522 {
2523 status = false;
2524 m_context.getTestContext().getLog()
2525 << tcu::TestLog::Message << "GL_TEXTURE_2D target failed. Value is: " << ToString(data[i])
2526 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2527 break;
2528 }
2529 }
2530
2531 glBindTexture(GL_TEXTURE_3D, textures[2]);
2532 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2533 glGetTexImage(GL_TEXTURE_3D, 0, Format<T>(), Type<T>(), &data[0]);
2534 glBindTexture(GL_TEXTURE_3D, 0);
2535 for (int i = 0; i < kSize * kSize * 2; ++i)
2536 {
2537 if (!tcu::allEqual(data[i], expected_value))
2538 {
2539 status = false;
2540 m_context.getTestContext().getLog()
2541 << tcu::TestLog::Message << "GL_TEXTURE_3D target failed. Value is: " << ToString(data[i])
2542 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2543 break;
2544 }
2545 }
2546
2547 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2548 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2549 glGetTexImage(GL_TEXTURE_RECTANGLE, 0, Format<T>(), Type<T>(), &data[0]);
2550 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2551 for (int i = 0; i < kSize * kSize; ++i)
2552 {
2553 if (!tcu::allEqual(data[i], expected_value))
2554 {
2555 status = false;
2556 m_context.getTestContext().getLog()
2557 << tcu::TestLog::Message << "GL_TEXTURE_RECTANGLE target failed. Value is: " << ToString(data[i])
2558 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2559 break;
2560 }
2561 }
2562
2563 {
2564 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2565 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2566 for (int face = 0; face < 6; ++face)
2567 {
2568 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]);
2569 for (int i = 0; i < kSize * kSize; ++i)
2570 {
2571 if (!tcu::allEqual(data[i], expected_value))
2572 {
2573 status = false;
2574 m_context.getTestContext().getLog()
2575 << tcu::TestLog::Message
2576 << "GL_TEXTURE_CUBE_MAP_POSITIVE_X target failed. Value is: " << ToString(data[i])
2577 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2578 break;
2579 }
2580 }
2581 }
2582 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2583 }
2584
2585 glBindTexture(GL_TEXTURE_BUFFER, textures[5]);
2586 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2587 glBindTexture(GL_TEXTURE_BUFFER, 0);
2588 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2589 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, kSize * sizeof(T), &data[0]);
2590 glBindBuffer(GL_TEXTURE_BUFFER, 0);
2591 for (int i = 0; i < kSize; ++i)
2592 {
2593 if (!tcu::allEqual(data[i], expected_value))
2594 {
2595 status = false;
2596 m_context.getTestContext().getLog()
2597 << tcu::TestLog::Message << "GL_TEXTURE_BUFFER target failed. Value is: " << ToString(data[i])
2598 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2599 break;
2600 }
2601 }
2602
2603 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]);
2604 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2605 glGetTexImage(GL_TEXTURE_1D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2606 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2607 for (int i = 0; i < kSize * 2; ++i)
2608 {
2609 if (!tcu::allEqual(data[i], expected_value))
2610 {
2611 status = false;
2612 m_context.getTestContext().getLog()
2613 << tcu::TestLog::Message << "GL_TEXTURE_1D_ARRAY target failed. Value is: " << ToString(data[i])
2614 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2615 break;
2616 }
2617 }
2618
2619 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2620 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2621 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2622 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2623 for (int i = 0; i < kSize * kSize * 2; ++i)
2624 {
2625 if (!tcu::allEqual(data[i], expected_value))
2626 {
2627 status = false;
2628 m_context.getTestContext().getLog()
2629 << tcu::TestLog::Message << "GL_TEXTURE_2D_ARRAY target failed. Value is: " << ToString(data[i])
2630 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2631 break;
2632 }
2633 }
2634
2635 glUseProgram(0);
2636 glDeleteProgram(program);
2637 glDeleteTextures(8, textures);
2638 glDeleteBuffers(1, &buffer);
2639
2640 return status;
2641 }
2642
2643 template <typename T>
WriteMS(GLenum internalformat,const T & write_value,const T & expected_value)2644 bool WriteMS(GLenum internalformat, const T& write_value, const T& expected_value)
2645 {
2646
2647 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2648 " gl_Position = i_position;" NL "}";
2649 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, write_value).c_str());
2650 const GLuint val_program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMSVal(expected_value).c_str());
2651 GLuint textures[2];
2652 glGenTextures(2, textures);
2653
2654 const int kSize = 16;
2655
2656 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
2657 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
2658 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
2659
2660 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
2661 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
2662 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
2663
2664 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2665 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2666
2667 glClear(GL_COLOR_BUFFER_BIT);
2668 glUseProgram(program);
2669 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
2670 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
2671
2672 glBindVertexArray(m_vao);
2673 glViewport(0, 0, kSize, kSize);
2674 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2675
2676 bool status = true;
2677
2678 glActiveTexture(GL_TEXTURE0);
2679 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
2680 glActiveTexture(GL_TEXTURE1);
2681 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
2682
2683 glUseProgram(val_program);
2684 glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms"), 0);
2685 glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms_array"), 1);
2686
2687 glBindVertexArray(m_vao);
2688 glViewport(0, 0, kSize, kSize);
2689 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
2690 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2691
2692 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
2693 {
2694 status = false;
2695 m_context.getTestContext().getLog()
2696 << tcu::TestLog::Message
2697 << "GL_TEXTURE_2D_MULTISAMPLE or GL_TEXTURE_2D_MULTISAMPLE_ARRAY target failed."
2698 << tcu::TestLog::EndMessage;
2699 }
2700
2701 glActiveTexture(GL_TEXTURE0);
2702 glDeleteTextures(2, textures);
2703 glUseProgram(0);
2704 glDeleteProgram(program);
2705 glDeleteProgram(val_program);
2706
2707 return status;
2708 }
2709
2710 template <typename T>
WriteCubeArray(GLenum internalformat,const T & write_value,const T & expected_value)2711 bool WriteCubeArray(GLenum internalformat, const T& write_value, const T& expected_value)
2712 {
2713 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2714 " gl_Position = i_position;" NL "}";
2715 const GLuint program =
2716 BuildProgram(src_vs, NULL, NULL, NULL, GenFSCubeArray(internalformat, write_value).c_str());
2717 GLuint textures[1];
2718 glGenTextures(1, textures);
2719
2720 const int kSize = 16;
2721
2722 std::vector<T> data(kSize * kSize * 12);
2723 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]);
2724 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2725 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
2726 &data[0]);
2727 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
2728
2729 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2730
2731 glUseProgram(program);
2732 glBindVertexArray(m_vao);
2733 glViewport(0, 0, kSize, kSize);
2734 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2735
2736 bool status = true;
2737
2738 std::fill(data.begin(), data.end(), T(0));
2739 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]);
2740 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2741 glGetTexImage(GL_TEXTURE_CUBE_MAP_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2742 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
2743 for (int i = 0; i < kSize * kSize * 12; ++i)
2744 {
2745 if (!tcu::allEqual(data[i], expected_value))
2746 {
2747 status = false;
2748 m_context.getTestContext().getLog()
2749 << tcu::TestLog::Message
2750 << "GL_TEXTURE_CUBE_MAP_ARRAY target failed. Value is: " << ToString(data[i])
2751 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2752 break;
2753 }
2754 }
2755
2756 glDeleteTextures(1, textures);
2757 glUseProgram(0);
2758 glDeleteProgram(program);
2759
2760 return status;
2761 }
2762
2763 template <typename T>
GenFS(GLenum internalformat,const T & write_value)2764 std::string GenFS(GLenum internalformat, const T& write_value)
2765 {
2766 std::ostringstream os;
2767 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2768 << TypePrefix<T>() << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat)
2769 << ") writeonly uniform " << TypePrefix<T>() << "image2D g_image_2d;" NL "layout("
2770 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
2771 << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2772 << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat)
2773 << ") writeonly uniform " << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout("
2774 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
2775 << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2776 << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat)
2777 << ") writeonly uniform " << TypePrefix<T>()
2778 << "image2DArray g_image_2darray;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2779 " imageStore(g_image_1d, coord.x, "
2780 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2d, coord, " << TypePrefix<T>()
2781 << "vec4" << write_value << ");" NL " imageStore(g_image_3d, ivec3(coord.xy, 0), " << TypePrefix<T>()
2782 << "vec4" << write_value << ");" NL " imageStore(g_image_3d, ivec3(coord.xy, 1), " << TypePrefix<T>()
2783 << "vec4" << write_value << ");" NL " imageStore(g_image_2drect, coord, " << TypePrefix<T>() << "vec4"
2784 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 0), " << TypePrefix<T>() << "vec4"
2785 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 1), " << TypePrefix<T>() << "vec4"
2786 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 2), " << TypePrefix<T>() << "vec4"
2787 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 3), " << TypePrefix<T>() << "vec4"
2788 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 4), " << TypePrefix<T>() << "vec4"
2789 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 5), " << TypePrefix<T>() << "vec4"
2790 << write_value << ");" NL " imageStore(g_image_buffer, coord.x, " << TypePrefix<T>() << "vec4"
2791 << write_value << ");" NL " imageStore(g_image_1darray, ivec2(coord.x, 0), " << TypePrefix<T>() << "vec4"
2792 << write_value << ");" NL " imageStore(g_image_1darray, ivec2(coord.x, 1), " << TypePrefix<T>() << "vec4"
2793 << write_value << ");" NL " imageStore(g_image_2darray, ivec3(coord, 0), " << TypePrefix<T>() << "vec4"
2794 << write_value << ");" NL " imageStore(g_image_2darray, ivec3(coord, 1), " << TypePrefix<T>() << "vec4"
2795 << write_value << ");" NL " discard;" NL "}";
2796 return os.str();
2797 }
2798
2799 template <typename T>
GenFSMS(GLenum internalformat,const T & write_value)2800 std::string GenFSMS(GLenum internalformat, const T& write_value)
2801 {
2802 std::ostringstream os;
2803 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2804 << TypePrefix<T>() << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat)
2805 << ") writeonly uniform " << TypePrefix<T>()
2806 << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2807 " imageStore(g_image_2dms, coord, 0, "
2808 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2dms, coord, 1, "
2809 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2dms, coord, 2, "
2810 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2dms, coord, 3, "
2811 << TypePrefix<T>() << "vec4" << write_value
2812 << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 0, " << TypePrefix<T>() << "vec4"
2813 << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 1, " << TypePrefix<T>()
2814 << "vec4" << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 2, "
2815 << TypePrefix<T>() << "vec4" << write_value
2816 << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 3, " << TypePrefix<T>() << "vec4"
2817 << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 0, " << TypePrefix<T>()
2818 << "vec4" << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 1, "
2819 << TypePrefix<T>() << "vec4" << write_value
2820 << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 2, " << TypePrefix<T>() << "vec4"
2821 << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 3, " << TypePrefix<T>()
2822 << "vec4" << write_value << ");" NL " discard;" NL "}";
2823 return os.str();
2824 }
2825
2826 template <typename T>
GenFSMSVal(const T & expected_value)2827 std::string GenFSMSVal(const T& expected_value)
2828 {
2829 std::ostringstream os;
2830 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform " << TypePrefix<T>()
2831 << "sampler2DMS g_sampler_2dms;" NL "uniform " << TypePrefix<T>()
2832 << "sampler2DMSArray g_sampler_2dms_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
2833 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " if (texelFetch(g_sampler_2dms, coord, 0) != "
2834 << TypePrefix<T>() << "vec4" << expected_value
2835 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (texelFetch(g_sampler_2dms, coord, 1) != "
2836 << TypePrefix<T>() << "vec4" << expected_value
2837 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (texelFetch(g_sampler_2dms, coord, 2) != "
2838 << TypePrefix<T>() << "vec4" << expected_value
2839 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (texelFetch(g_sampler_2dms, coord, 3) != "
2840 << TypePrefix<T>() << "vec4" << expected_value
2841 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL
2842 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 0) != "
2843 << TypePrefix<T>() << "vec4" << expected_value
2844 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2845 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 1) != "
2846 << TypePrefix<T>() << "vec4" << expected_value
2847 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2848 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 2) != "
2849 << TypePrefix<T>() << "vec4" << expected_value
2850 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2851 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 3) != "
2852 << TypePrefix<T>() << "vec4" << expected_value
2853 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2854 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 0) != "
2855 << TypePrefix<T>() << "vec4" << expected_value
2856 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2857 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 1) != "
2858 << TypePrefix<T>() << "vec4" << expected_value
2859 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2860 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 2) != "
2861 << TypePrefix<T>() << "vec4" << expected_value
2862 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2863 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 3) != "
2864 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}";
2865 return os.str();
2866 }
2867
2868 template <typename T>
GenFSCubeArray(GLenum internalformat,const T & write_value)2869 std::string GenFSCubeArray(GLenum internalformat, const T& write_value)
2870 {
2871 std::ostringstream os;
2872 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2873 << TypePrefix<T>()
2874 << "imageCubeArray g_image_cube_array;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2875 " imageStore(g_image_cube_array, ivec3(coord, 0), "
2876 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 1), "
2877 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 2), "
2878 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 3), "
2879 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 4), "
2880 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 5), "
2881 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 6), "
2882 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 7), "
2883 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 8), "
2884 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 9), "
2885 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 10), "
2886 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 11), "
2887 << TypePrefix<T>() << "vec4" << write_value << ");" NL " discard;" NL "}";
2888 return os.str();
2889 }
2890 };
2891 //-----------------------------------------------------------------------------
2892 // 1.3.2.1 BasicAllTargetsLoadNonMS
2893 //-----------------------------------------------------------------------------
2894 class BasicAllTargetsLoadNonMS : public ShaderImageLoadStoreBase
2895 {
2896 GLuint m_vao;
2897 GLuint m_vbo;
2898
Setup()2899 virtual long Setup()
2900 {
2901 m_vao = 0;
2902 m_vbo = 0;
2903 return NO_ERROR;
2904 }
2905
Run()2906 virtual long Run()
2907 {
2908 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2909
2910 if (!Read(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
2911 return ERROR;
2912 if (!Read(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000)))
2913 return ERROR;
2914 if (!Read(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000)))
2915 return ERROR;
2916
2917 if (!ReadCube(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
2918 return ERROR;
2919 if (!ReadCube(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000)))
2920 return ERROR;
2921 if (!ReadCube(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000)))
2922 return ERROR;
2923
2924 return NO_ERROR;
2925 }
2926
Cleanup()2927 virtual long Cleanup()
2928 {
2929 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2930 glDeleteVertexArrays(1, &m_vao);
2931 glDeleteBuffers(1, &m_vbo);
2932 return NO_ERROR;
2933 }
2934
2935 template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)2936 bool Read(GLenum internalformat, const T& value, const T& expected_value)
2937 {
2938 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2939 " gl_Position = i_position;" NL "}";
2940 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str());
2941 GLuint textures[7];
2942 GLuint buffer;
2943 glGenTextures(7, textures);
2944 glGenBuffers(1, &buffer);
2945
2946 const int kSize = 16;
2947 std::vector<T> data(kSize * kSize * 2, value);
2948
2949 glBindTexture(GL_TEXTURE_1D, textures[0]);
2950 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2951 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2952 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2953 glBindTexture(GL_TEXTURE_1D, 0);
2954
2955 glBindTexture(GL_TEXTURE_2D, textures[1]);
2956 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2957 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2958 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2959 glBindTexture(GL_TEXTURE_2D, 0);
2960
2961 glBindTexture(GL_TEXTURE_3D, textures[2]);
2962 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2963 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2964 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2965 glBindTexture(GL_TEXTURE_3D, 0);
2966
2967 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2968 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2969 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2970 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2971 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2972
2973 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2974 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
2975 glBindBuffer(GL_TEXTURE_BUFFER, 0);
2976 glBindTexture(GL_TEXTURE_BUFFER, textures[4]);
2977 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
2978 glBindTexture(GL_TEXTURE_BUFFER, 0);
2979
2980 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]);
2981 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2982 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2983 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2984 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2985
2986 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]);
2987 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2988 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2989 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2990 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2991
2992 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2993 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2994 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2995 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2996 glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2997 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2998 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2999
3000 glClear(GL_COLOR_BUFFER_BIT);
3001
3002 glUseProgram(program);
3003 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
3004 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
3005 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
3006 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
3007 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4);
3008 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5);
3009 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6);
3010
3011 glBindVertexArray(m_vao);
3012 glViewport(0, 0, kSize, kSize);
3013 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3014
3015 bool status = true;
3016
3017 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3018 {
3019 status = false;
3020 }
3021
3022 std::map<std::string, GLuint> name_index_map;
3023 GLint uniforms;
3024 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3025 if (uniforms != 7)
3026 {
3027 status = false;
3028 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3029 << " should be 7." << tcu::TestLog::EndMessage;
3030 }
3031 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3032 {
3033 GLchar name[32];
3034 glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3035 name_index_map.insert(std::make_pair(std::string(name), index));
3036 }
3037
3038 if (!CheckUniform(program, "g_image_1d", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D)))
3039 status = false;
3040 if (!CheckUniform(program, "g_image_2d", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D)))
3041 status = false;
3042 if (!CheckUniform(program, "g_image_3d", name_index_map, 1, ImageType<T>(GL_TEXTURE_3D)))
3043 status = false;
3044 if (!CheckUniform(program, "g_image_2drect", name_index_map, 1, ImageType<T>(GL_TEXTURE_RECTANGLE)))
3045 status = false;
3046 if (!CheckUniform(program, "g_image_buffer", name_index_map, 1, ImageType<T>(GL_TEXTURE_BUFFER)))
3047 status = false;
3048 if (!CheckUniform(program, "g_image_1darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D_ARRAY)))
3049 status = false;
3050 if (!CheckUniform(program, "g_image_2darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_ARRAY)))
3051 status = false;
3052
3053 glUseProgram(0);
3054 glDeleteProgram(program);
3055 glDeleteTextures(7, textures);
3056 glDeleteBuffers(1, &buffer);
3057
3058 return status;
3059 }
3060
3061 template <typename T>
ReadCube(GLenum internalformat,const T & value,const T & expected_value)3062 bool ReadCube(GLenum internalformat, const T& value, const T& expected_value)
3063 {
3064 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3065 " gl_Position = i_position;" NL "}";
3066 const GLuint program =
3067 BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube(internalformat, expected_value).c_str());
3068 GLuint textures[2];
3069 glGenTextures(2, textures);
3070
3071 const int kSize = 16;
3072 std::vector<T> data(kSize * kSize * 12, value);
3073
3074 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]);
3075 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3076 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3077 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3078 &data[0]);
3079 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3080 &data[0]);
3081 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3082 &data[0]);
3083 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3084 &data[0]);
3085 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3086 &data[0]);
3087 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3088 &data[0]);
3089 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3090
3091 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]);
3092 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3093 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3094 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
3095 &data[0]);
3096 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
3097
3098 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3099 glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3100
3101 glClear(GL_COLOR_BUFFER_BIT);
3102
3103 glUseProgram(program);
3104 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0);
3105 glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1);
3106
3107 glBindVertexArray(m_vao);
3108 glViewport(0, 0, kSize, kSize);
3109 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3110
3111 bool status = true;
3112
3113 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3114 {
3115 status = false;
3116 }
3117
3118 std::map<std::string, GLuint> name_index_map;
3119 GLint uniforms;
3120 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3121 if (uniforms != 2)
3122 {
3123 status = false;
3124 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3125 << " should be 2." << tcu::TestLog::EndMessage;
3126 }
3127 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3128 {
3129 GLchar name[32];
3130 glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3131 name_index_map.insert(std::make_pair(std::string(name), index));
3132 }
3133
3134 if (!CheckUniform(program, "g_image_cube", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP)))
3135 status = false;
3136 if (!CheckUniform(program, "g_image_cube_array", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP_ARRAY)))
3137 status = false;
3138
3139 glUseProgram(0);
3140 glDeleteProgram(program);
3141 glDeleteTextures(2, textures);
3142
3143 return status;
3144 }
3145
3146 template <typename T>
GenFS(GLenum internalformat,const T & expected_value)3147 std::string GenFS(GLenum internalformat, const T& expected_value)
3148 {
3149 std::ostringstream os;
3150 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3151 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3152 << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3153 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3154 << ") readonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3155 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3156 << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3157 << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
3158 << ") readonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
3159 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3160 << "image2DArray g_image_2darray;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3161 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " "
3162 << TypePrefix<T>()
3163 << "vec4 v;" NL " v = imageLoad(g_image_1d, coord.x);" NL " if (v != " << TypePrefix<T>() << "vec4"
3164 << expected_value
3165 << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL " v = imageLoad(g_image_2d, coord);" NL " if (v != "
3166 << TypePrefix<T>() << "vec4" << expected_value
3167 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " v = imageLoad(g_image_3d, ivec3(coord.xy, 0));" NL
3168 " if (v != "
3169 << TypePrefix<T>() << "vec4" << expected_value
3170 << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL " v = imageLoad(g_image_3d, ivec3(coord.xy, 1));" NL
3171 " if (v != "
3172 << TypePrefix<T>() << "vec4" << expected_value
3173 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " v = imageLoad(g_image_2drect, coord);" NL " if (v != "
3174 << TypePrefix<T>() << "vec4" << expected_value
3175 << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL " v = imageLoad(g_image_buffer, coord.x);" NL " if (v != "
3176 << TypePrefix<T>() << "vec4" << expected_value
3177 << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL " v = imageLoad(g_image_1darray, ivec2(coord.x, 0));" NL
3178 " if (v != "
3179 << TypePrefix<T>() << "vec4" << expected_value
3180 << ") o_color = vec4(1.0, 0.0, 0.0, 0.65);" NL " v = imageLoad(g_image_1darray, ivec2(coord.x, 1));" NL
3181 " if (v != "
3182 << TypePrefix<T>() << "vec4" << expected_value
3183 << ") o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL " v = imageLoad(g_image_2darray, ivec3(coord, 0));" NL
3184 " if (v != "
3185 << TypePrefix<T>() << "vec4" << expected_value
3186 << ") o_color = vec4(1.0, 0.0, 0.0, 0.75);" NL " v = imageLoad(g_image_2darray, ivec3(coord, 1));" NL
3187 " if (v != "
3188 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL "}";
3189 return os.str();
3190 }
3191
3192 template <typename T>
GenFSCube(GLenum internalformat,const T & expected_value)3193 std::string GenFSCube(GLenum internalformat, const T& expected_value)
3194 {
3195 std::ostringstream os;
3196 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3197 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3198 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3199 << TypePrefix<T>()
3200 << "imageCubeArray g_image_cube_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3201 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " "
3202 << TypePrefix<T>()
3203 << "vec4 v;" NL " v = imageLoad(g_image_cube, ivec3(coord, 0));" NL " if (v != " << TypePrefix<T>()
3204 << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
3205 " v = imageLoad(g_image_cube, ivec3(coord, 1));" NL " if (v != "
3206 << TypePrefix<T>() << "vec4" << expected_value
3207 << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL " v = imageLoad(g_image_cube, ivec3(coord, 2));" NL
3208 " if (v != "
3209 << TypePrefix<T>() << "vec4" << expected_value
3210 << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL " v = imageLoad(g_image_cube, ivec3(coord, 3));" NL
3211 " if (v != "
3212 << TypePrefix<T>() << "vec4" << expected_value
3213 << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL " v = imageLoad(g_image_cube, ivec3(coord, 4));" NL
3214 " if (v != "
3215 << TypePrefix<T>() << "vec4" << expected_value
3216 << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL " v = imageLoad(g_image_cube, ivec3(coord, 5));" NL
3217 " if (v != "
3218 << TypePrefix<T>() << "vec4" << expected_value
3219 << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 0));" NL
3220 " if (v != "
3221 << TypePrefix<T>() << "vec4" << expected_value
3222 << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 1));" NL
3223 " if (v != "
3224 << TypePrefix<T>() << "vec4" << expected_value
3225 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 2));" NL
3226 " if (v != "
3227 << TypePrefix<T>() << "vec4" << expected_value
3228 << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 3));" NL
3229 " if (v != "
3230 << TypePrefix<T>() << "vec4" << expected_value
3231 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 4));" NL
3232 " if (v != "
3233 << TypePrefix<T>() << "vec4" << expected_value
3234 << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 5));" NL
3235 " if (v != "
3236 << TypePrefix<T>() << "vec4" << expected_value
3237 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 6));" NL
3238 " if (v != "
3239 << TypePrefix<T>() << "vec4" << expected_value
3240 << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 7));" NL
3241 " if (v != "
3242 << TypePrefix<T>() << "vec4" << expected_value
3243 << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 8));" NL
3244 " if (v != "
3245 << TypePrefix<T>() << "vec4" << expected_value
3246 << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 9));" NL
3247 " if (v != "
3248 << TypePrefix<T>() << "vec4" << expected_value
3249 << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 10));" NL
3250 " if (v != "
3251 << TypePrefix<T>() << "vec4" << expected_value
3252 << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 11));" NL
3253 " if (v != "
3254 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL "}";
3255 return os.str();
3256 }
3257 };
3258 //-----------------------------------------------------------------------------
3259 // 1.3.2.2 BasicAllTargetsLoadMS
3260 //-----------------------------------------------------------------------------
3261 class BasicAllTargetsLoadMS : public ShaderImageLoadStoreBase
3262 {
3263 GLuint m_vao;
3264 GLuint m_vbo;
3265
Setup()3266 virtual long Setup()
3267 {
3268 m_vao = 0;
3269 m_vbo = 0;
3270 return NO_ERROR;
3271 }
3272
Run()3273 virtual long Run()
3274 {
3275 if (!SupportedSamples(4))
3276 return NOT_SUPPORTED;
3277
3278 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3279
3280 if (!ReadMS(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
3281 return ERROR;
3282
3283 GLint isamples;
3284 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
3285 if (isamples >= 4)
3286 {
3287 if (!ReadMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
3288 return ERROR;
3289 if (!ReadMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
3290 return ERROR;
3291 }
3292
3293 return NO_ERROR;
3294 }
3295
Cleanup()3296 virtual long Cleanup()
3297 {
3298 glViewport(0, 0, getWindowWidth(), getWindowHeight());
3299 glDeleteVertexArrays(1, &m_vao);
3300 glDeleteBuffers(1, &m_vbo);
3301 return NO_ERROR;
3302 }
3303
3304 template <typename T>
ReadMS(GLenum internalformat,const T & value,const T & expected_value)3305 bool ReadMS(GLenum internalformat, const T& value, const T& expected_value)
3306 {
3307 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3308 " gl_Position = i_position;" NL "}";
3309 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, expected_value).c_str());
3310 GLuint textures[2];
3311 glGenTextures(2, textures);
3312
3313 const int kSize = 16;
3314
3315 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
3316 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
3317 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
3318
3319 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
3320 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
3321 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
3322
3323 GLuint fbo;
3324 glGenFramebuffers(1, &fbo);
3325 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3326 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
3327 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0);
3328 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1);
3329 const GLenum draw_buffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
3330 glDrawBuffers(3, draw_buffers);
3331 ClearBuffer(GL_COLOR, 0, value);
3332 ClearBuffer(GL_COLOR, 1, value);
3333 ClearBuffer(GL_COLOR, 2, value);
3334 glDeleteFramebuffers(1, &fbo);
3335
3336 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
3337 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3338
3339 glUseProgram(program);
3340 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
3341 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
3342
3343 glClear(GL_COLOR_BUFFER_BIT);
3344 glBindVertexArray(m_vao);
3345 glViewport(0, 0, kSize, kSize);
3346 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3347
3348 bool status = true;
3349
3350 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3351 {
3352 status = false;
3353 }
3354
3355 std::map<std::string, GLuint> name_index_map;
3356 GLint uniforms;
3357 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3358 if (uniforms != 2)
3359 {
3360 status = false;
3361 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3362 << " should be 2." << tcu::TestLog::EndMessage;
3363 }
3364 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3365 {
3366 GLchar name[32];
3367 glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3368 name_index_map.insert(std::make_pair(std::string(name), index));
3369 }
3370
3371 if (!CheckUniform(program, "g_image_2dms", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE)))
3372 status = false;
3373 if (!CheckUniform(program, "g_image_2dms_array", name_index_map, 1,
3374 ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE_ARRAY)))
3375 status = false;
3376
3377 glDeleteTextures(2, textures);
3378 glUseProgram(0);
3379 glDeleteProgram(program);
3380
3381 return status;
3382 }
3383
3384 template <typename T>
GenFSMS(GLenum internalformat,const T & expected_value)3385 std::string GenFSMS(GLenum internalformat, const T& expected_value)
3386 {
3387 std::ostringstream os;
3388 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3389 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3390 << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3391 << TypePrefix<T>()
3392 << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3393 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " if (imageLoad(g_image_2dms, coord, 0) != "
3394 << TypePrefix<T>() << "vec4" << expected_value
3395 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms, coord, 1) != "
3396 << TypePrefix<T>() << "vec4" << expected_value
3397 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms, coord, 2) != "
3398 << TypePrefix<T>() << "vec4" << expected_value
3399 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms, coord, 3) != "
3400 << TypePrefix<T>() << "vec4" << expected_value
3401 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 0) != "
3402 << TypePrefix<T>() << "vec4" << expected_value
3403 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 1) != "
3404 << TypePrefix<T>() << "vec4" << expected_value
3405 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 2) != "
3406 << TypePrefix<T>() << "vec4" << expected_value
3407 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 3) != "
3408 << TypePrefix<T>() << "vec4" << expected_value
3409 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 0) != "
3410 << TypePrefix<T>() << "vec4" << expected_value
3411 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 1) != "
3412 << TypePrefix<T>() << "vec4" << expected_value
3413 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 2) != "
3414 << TypePrefix<T>() << "vec4" << expected_value
3415 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 3) != "
3416 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}";
3417 return os.str();
3418 }
3419 };
3420 //-----------------------------------------------------------------------------
3421 // 1.3.3 BasicAllTargetsAtomic
3422 //-----------------------------------------------------------------------------
3423 class BasicAllTargetsAtomic : public ShaderImageLoadStoreBase
3424 {
3425 GLuint m_vao;
3426 GLuint m_vbo;
3427
Setup()3428 virtual long Setup()
3429 {
3430 m_vao = 0;
3431 m_vbo = 0;
3432 return NO_ERROR;
3433 }
3434
Run()3435 virtual long Run()
3436 {
3437 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3438
3439 if (!Atomic<GLint>(GL_R32I))
3440 return ERROR;
3441 if (!Atomic<GLuint>(GL_R32UI))
3442 return ERROR;
3443
3444 if (!AtomicCube<GLint>(GL_R32I))
3445 return ERROR;
3446 if (!AtomicCube<GLuint>(GL_R32UI))
3447 return ERROR;
3448
3449 GLint isamples;
3450 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
3451 if (SupportedSamples(4) && isamples >= 4)
3452 {
3453 if (!AtomicMS<GLint>(GL_R32I))
3454 return ERROR;
3455 if (!AtomicMS<GLuint>(GL_R32UI))
3456 return ERROR;
3457 }
3458
3459 return NO_ERROR;
3460 }
3461
Cleanup()3462 virtual long Cleanup()
3463 {
3464 glViewport(0, 0, getWindowWidth(), getWindowHeight());
3465 glDeleteVertexArrays(1, &m_vao);
3466 glDeleteBuffers(1, &m_vbo);
3467 return NO_ERROR;
3468 }
3469
3470 template <typename T>
Atomic(GLenum internalformat)3471 bool Atomic(GLenum internalformat)
3472 {
3473 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3474 " gl_Position = i_position;" NL "}";
3475 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS<T>(internalformat).c_str());
3476 GLuint textures[7];
3477 GLuint buffer;
3478 glGenTextures(7, textures);
3479 glGenBuffers(1, &buffer);
3480
3481 const int kSize = 16;
3482 std::vector<T> data(kSize * kSize * 2);
3483
3484 glBindTexture(GL_TEXTURE_1D, textures[0]);
3485 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3486 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3487 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3488 glBindTexture(GL_TEXTURE_1D, 0);
3489
3490 glBindTexture(GL_TEXTURE_2D, textures[1]);
3491 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3492 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3493 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3494 glBindTexture(GL_TEXTURE_2D, 0);
3495
3496 glBindTexture(GL_TEXTURE_3D, textures[2]);
3497 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3498 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3499 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3500 glBindTexture(GL_TEXTURE_3D, 0);
3501
3502 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
3503 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3504 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3505 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3506 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
3507
3508 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
3509 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
3510 glBindBuffer(GL_TEXTURE_BUFFER, 0);
3511 glBindTexture(GL_TEXTURE_BUFFER, textures[4]);
3512 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
3513 glBindTexture(GL_TEXTURE_BUFFER, 0);
3514
3515 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]);
3516 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3517 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3518 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3519 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
3520
3521 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]);
3522 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3523 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3524 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3525 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
3526
3527 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3528 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3529 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3530 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3531 glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3532 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3533 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3534
3535 glClear(GL_COLOR_BUFFER_BIT);
3536
3537 glUseProgram(program);
3538 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
3539 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
3540 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
3541 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
3542 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4);
3543 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5);
3544 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6);
3545
3546 glBindVertexArray(m_vao);
3547 glViewport(0, 0, kSize, 1);
3548 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3549
3550 bool status = true;
3551
3552 if (!ValidateReadBuffer(0, 0, kSize, 1, vec4(0, 1, 0, 1)))
3553 {
3554 status = false;
3555 }
3556
3557 glUseProgram(0);
3558 glDeleteProgram(program);
3559 glDeleteTextures(7, textures);
3560 glDeleteBuffers(1, &buffer);
3561
3562 return status;
3563 }
3564
3565 template <typename T>
AtomicCube(GLenum internalformat)3566 bool AtomicCube(GLenum internalformat)
3567 {
3568 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3569 " gl_Position = i_position;" NL "}";
3570 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube<T>(internalformat).c_str());
3571 GLuint textures[2];
3572 glGenTextures(2, textures);
3573
3574 const int kSize = 16;
3575 std::vector<T> data(kSize * kSize * 12);
3576
3577 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]);
3578 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3579 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3580 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3581 &data[0]);
3582 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3583 &data[0]);
3584 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3585 &data[0]);
3586 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3587 &data[0]);
3588 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3589 &data[0]);
3590 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3591 &data[0]);
3592 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3593
3594 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]);
3595 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3596 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3597 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
3598 &data[0]);
3599 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
3600
3601 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3602 glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3603
3604 glClear(GL_COLOR_BUFFER_BIT);
3605
3606 glUseProgram(program);
3607 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0);
3608 glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1);
3609
3610 glBindVertexArray(m_vao);
3611 glViewport(0, 0, kSize, kSize);
3612 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3613
3614 bool status = true;
3615
3616 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3617 {
3618 status = false;
3619 }
3620
3621 glUseProgram(0);
3622 glDeleteProgram(program);
3623 glDeleteTextures(2, textures);
3624
3625 return status;
3626 }
3627
3628 template <typename T>
AtomicMS(GLenum internalformat)3629 bool AtomicMS(GLenum internalformat)
3630 {
3631 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3632 " gl_Position = i_position;" NL "}";
3633 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS<T>(internalformat).c_str());
3634 GLuint textures[2];
3635 glGenTextures(2, textures);
3636
3637 const int kSize = 16;
3638
3639 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
3640 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
3641 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
3642
3643 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
3644 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
3645 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
3646
3647 GLuint fbo;
3648 glGenFramebuffers(1, &fbo);
3649 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3650 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
3651 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0);
3652 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1);
3653 const GLenum draw_buffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
3654 glDrawBuffers(3, draw_buffers);
3655 if (internalformat == GL_R32I)
3656 {
3657 const GLint value[4] = { 0, 0, 0, 0 };
3658 glClearBufferiv(GL_COLOR, 0, value);
3659 glClearBufferiv(GL_COLOR, 1, value);
3660 glClearBufferiv(GL_COLOR, 2, value);
3661 }
3662 else
3663 {
3664 const GLuint value[4] = { 0, 0, 0, 0 };
3665 glClearBufferuiv(GL_COLOR, 0, value);
3666 glClearBufferuiv(GL_COLOR, 1, value);
3667 glClearBufferuiv(GL_COLOR, 2, value);
3668 }
3669 glDeleteFramebuffers(1, &fbo);
3670
3671 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3672 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3673
3674 glUseProgram(program);
3675 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
3676 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
3677
3678 glClear(GL_COLOR_BUFFER_BIT);
3679 glBindVertexArray(m_vao);
3680 glViewport(0, 0, kSize, kSize);
3681 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3682
3683 bool status = true;
3684
3685 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3686 {
3687 status = false;
3688 }
3689
3690 glDeleteTextures(2, textures);
3691 glUseProgram(0);
3692 glDeleteProgram(program);
3693
3694 return status;
3695 }
3696
3697 template <typename T>
GenFS(GLenum internalformat)3698 std::string GenFS(GLenum internalformat)
3699 {
3700 std::ostringstream os;
3701 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3702 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3703 << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3704 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3705 << ") coherent uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3706 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3707 << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3708 << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
3709 << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
3710 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3711 << "image2DArray g_image_2darray;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3712 " ivec2 coord = ivec2(gl_FragCoord.xy);"
3713
3714 NL " if (imageAtomicAdd(g_image_1d, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3715 " if (imageAtomicMin(g_image_1d, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3716 " if (imageAtomicMax(g_image_1d, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3717 " if (imageAtomicAnd(g_image_1d, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3718 " if (imageAtomicOr(g_image_1d, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3719 " if (imageAtomicXor(g_image_1d, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3720 " if (imageAtomicExchange(g_image_1d, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3721 " if (imageAtomicCompSwap(g_image_1d, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3722 " if (imageAtomicExchange(g_image_1d, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3723
3724 NL " if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3725 " if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3726 " if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3727 " if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3728 " if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3729 " if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3730 " if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3731 " if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3732 " if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3733
3734 NL " if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3735 " if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3736 " if (imageAtomicMax(g_image_3d, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3737 " if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3738 " if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3739 " if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3740 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3741 " if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
3742 "1.0);" NL
3743 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3744
3745 NL " if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3746 " if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3747 " if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3748 " if (imageAtomicAnd(g_image_2drect, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3749 " if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3750 " if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3751 " if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3752 " if (imageAtomicCompSwap(g_image_2drect, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3753 " if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3754
3755 NL " if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3756 " if (imageAtomicMin(g_image_buffer, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3757 " if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3758 " if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3759 " if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3760 " if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3761 " if (imageAtomicExchange(g_image_buffer, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3762 " if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3763 " if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3764
3765 NL
3766 " if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3767 " if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3768 " if (imageAtomicMax(g_image_1darray, ivec2(coord.x, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3769 " if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3770 " if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3771 " if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3772 " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
3773 "1.0);" NL " if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = "
3774 "vec4(1.0, 0.0, 0.0, 1.0);" NL " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), "
3775 "0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3776
3777 NL " if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3778 " if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3779 " if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3780 " if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3781 " if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3782 " if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3783 " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
3784 "1.0);" NL " if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, "
3785 "0.0, 0.0, 1.0);" NL " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) "
3786 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
3787 return os.str();
3788 }
3789
3790 template <typename T>
GenFSCube(GLenum internalformat)3791 std::string GenFSCube(GLenum internalformat)
3792 {
3793 std::ostringstream os;
3794 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3795 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3796 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3797 << TypePrefix<T>()
3798 << "imageCube g_image_cube_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3799 " ivec2 coord = ivec2(gl_FragCoord.xy);"
3800
3801 NL " if (imageAtomicAdd(g_image_cube, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3802 " if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3803 " if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3804 " if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3805 " if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3806 " if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3807 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3808 " if (imageAtomicCompSwap(g_image_cube, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
3809 "1.0);" NL
3810 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3811
3812 NL " if (imageAtomicAdd(g_image_cube_array, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, "
3813 "1.0);" NL " if (imageAtomicMin(g_image_cube_array, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, "
3814 "0.0, 1.0);" NL " if (imageAtomicMax(g_image_cube_array, ivec3(coord, 0), 4) != 2) o_color "
3815 "= vec4(1.0, 0.0, 0.0, 1.0);" NL " if (imageAtomicAnd(g_image_cube_array, "
3816 "ivec3(coord, 0), 0) != 4) o_color = "
3817 "vec4(1.0, 0.0, 0.0, 1.0);" NL
3818 " if (imageAtomicOr(g_image_cube_array, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3819 " if (imageAtomicXor(g_image_cube_array, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, "
3820 "1.0);" NL " if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, "
3821 "0.0, 0.0, 1.0);" NL " if (imageAtomicCompSwap(g_image_cube_array, ivec3(coord, 0), 1, 6) != "
3822 "1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3823 " if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, "
3824 "1.0);" NL "}";
3825 return os.str();
3826 }
3827
3828 template <typename T>
GenFSMS(GLenum internalformat)3829 std::string GenFSMS(GLenum internalformat)
3830 {
3831 std::ostringstream os;
3832 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3833 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3834 << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3835 << TypePrefix<T>()
3836 << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3837 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
3838 " if (imageAtomicAdd(g_image_2dms, coord, 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3839 " if (imageAtomicMin(g_image_2dms, coord, 1, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3840 " if (imageAtomicMax(g_image_2dms, coord, 1, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3841 " if (imageAtomicAnd(g_image_2dms, coord, 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3842 " if (imageAtomicOr(g_image_2dms, coord, 1, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3843 " if (imageAtomicXor(g_image_2dms, coord, 1, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3844 " if (imageAtomicExchange(g_image_2dms, coord, 1, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3845 " if (imageAtomicCompSwap(g_image_2dms, coord, 1, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3846 " if (imageAtomicExchange(g_image_2dms, coord, 1, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL NL
3847 " if (imageAtomicAdd(g_image_2dms_array, ivec3(coord, 1), 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, "
3848 "1.0);" NL " if (imageAtomicMin(g_image_2dms_array, ivec3(coord, 1), 1, 3) != 2) o_color = vec4(1.0, "
3849 "0.0, 0.0, 1.0);" NL " if (imageAtomicMax(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 2) "
3850 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3851 " if (imageAtomicAnd(g_image_2dms_array, ivec3(coord, 1), 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, "
3852 "1.0);" NL " if (imageAtomicOr(g_image_2dms_array, ivec3(coord, 1), 1, 7) != 0) o_color = vec4(1.0, "
3853 "0.0, 0.0, 1.0);" NL " if (imageAtomicXor(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 7) "
3854 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3855 " if (imageAtomicExchange(g_image_2dms_array, ivec3(coord, 1), 1, 1) != 3) o_color = vec4(1.0, 0.0, "
3856 "0.0, 1.0);" NL " if (imageAtomicCompSwap(g_image_2dms_array, ivec3(coord, 1), 1, 1, 6) != 1) o_color = "
3857 "vec4(1.0, 0.0, 0.0, 1.0);" NL " if (imageAtomicExchange(g_image_2dms_array, "
3858 "ivec3(coord, 1), 1, 0) != 6) o_color = vec4(1.0, 0.0, "
3859 "0.0, 1.0);" NL "}";
3860 return os.str();
3861 }
3862 };
3863 //-----------------------------------------------------------------------------
3864 // LoadStoreMachine
3865 //-----------------------------------------------------------------------------
3866 class LoadStoreMachine : public ShaderImageLoadStoreBase
3867 {
3868 GLuint m_vao;
3869 int m_stage;
3870
Setup()3871 virtual long Setup()
3872 {
3873 glGenVertexArrays(1, &m_vao);
3874 return NO_ERROR;
3875 }
3876
Cleanup()3877 virtual long Cleanup()
3878 {
3879 glDisable(GL_RASTERIZER_DISCARD);
3880 glDeleteVertexArrays(1, &m_vao);
3881 return NO_ERROR;
3882 }
3883
3884 template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)3885 bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
3886 {
3887 const GLenum targets[] = { GL_TEXTURE_1D, GL_TEXTURE_2D,
3888 GL_TEXTURE_3D, GL_TEXTURE_RECTANGLE,
3889 GL_TEXTURE_CUBE_MAP, GL_TEXTURE_1D_ARRAY,
3890 GL_TEXTURE_2D_ARRAY, GL_TEXTURE_CUBE_MAP_ARRAY };
3891 const int kTargets = sizeof(targets) / sizeof(targets[0]);
3892 GLuint program_store = 0;
3893 GLuint program_load = 0;
3894 if (m_stage == 0)
3895 { // VS
3896 program_store =
3897 BuildProgram(GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL, NULL, NULL);
3898 program_load =
3899 BuildProgram(GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL, NULL, NULL);
3900 }
3901 else if (m_stage == 1)
3902 { // TCS
3903 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
3904 const char* const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
3905 program_store = BuildProgram(glsl_vs, GenStoreShader(m_stage, internalformat, write_value).c_str(),
3906 glsl_tes, NULL, NULL);
3907 program_load = BuildProgram(glsl_vs, GenLoadShader(m_stage, internalformat, expected_value).c_str(),
3908 glsl_tes, NULL, NULL);
3909 }
3910 else if (m_stage == 2)
3911 { // TES
3912 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
3913 program_store =
3914 BuildProgram(glsl_vs, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL);
3915 program_load =
3916 BuildProgram(glsl_vs, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL);
3917 }
3918 else if (m_stage == 3)
3919 { // GS
3920 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
3921 program_store =
3922 BuildProgram(glsl_vs, NULL, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL);
3923 program_load =
3924 BuildProgram(glsl_vs, NULL, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL);
3925 }
3926 else if (m_stage == 4)
3927 { // CS
3928 {
3929 std::string source = GenStoreShader(m_stage, internalformat, write_value);
3930 const char* const src = source.c_str();
3931 GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
3932 glShaderSource(sh, 1, &src, NULL);
3933 glCompileShader(sh);
3934 program_store = glCreateProgram();
3935 glAttachShader(program_store, sh);
3936 glLinkProgram(program_store);
3937 glDeleteShader(sh);
3938 }
3939 {
3940 std::string source = GenLoadShader(m_stage, internalformat, expected_value);
3941 const char* const src = source.c_str();
3942 GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
3943 glShaderSource(sh, 1, &src, NULL);
3944 glCompileShader(sh);
3945 program_load = glCreateProgram();
3946 glAttachShader(program_load, sh);
3947 glLinkProgram(program_load);
3948 glDeleteShader(sh);
3949 }
3950 }
3951 GLuint textures[kTargets], texture_result;
3952 glGenTextures(kTargets, textures);
3953 glGenTextures(1, &texture_result);
3954
3955 glBindTexture(GL_TEXTURE_2D, texture_result);
3956 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3957 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3958 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3959
3960 for (int i = 0; i < kTargets; ++i)
3961 {
3962 glBindTexture(targets[i], textures[i]);
3963 glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3964 glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3965
3966 if (targets[i] == GL_TEXTURE_1D)
3967 {
3968 glTexStorage1D(targets[i], 1, internalformat, 1);
3969 }
3970 else if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE)
3971 {
3972 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
3973 }
3974 else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
3975 {
3976 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2);
3977 }
3978 else if (targets[i] == GL_TEXTURE_CUBE_MAP)
3979 {
3980 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
3981 }
3982 else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY)
3983 {
3984 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 12);
3985 }
3986 else if (targets[i] == GL_TEXTURE_1D_ARRAY)
3987 {
3988 glTexStorage2D(targets[i], 1, internalformat, 1, 2);
3989 }
3990 }
3991 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3992 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3993 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3994 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3995 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3996 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3997 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3998 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3999
4000 glUseProgram(program_store);
4001 glUniform1i(glGetUniformLocation(program_store, "g_image_1d"), 0);
4002 glUniform1i(glGetUniformLocation(program_store, "g_image_2d"), 1);
4003 glUniform1i(glGetUniformLocation(program_store, "g_image_3d"), 2);
4004 glUniform1i(glGetUniformLocation(program_store, "g_image_2drect"), 3);
4005 glUniform1i(glGetUniformLocation(program_store, "g_image_cube"), 4);
4006 glUniform1i(glGetUniformLocation(program_store, "g_image_1darray"), 5);
4007 glUniform1i(glGetUniformLocation(program_store, "g_image_2darray"), 6);
4008 glUniform1i(glGetUniformLocation(program_store, "g_image_cube_array"), 7);
4009
4010 glBindVertexArray(m_vao);
4011 if (m_stage == 1 || m_stage == 2)
4012 { // TCS or TES
4013 glPatchParameteri(GL_PATCH_VERTICES, 1);
4014 glDrawArrays(GL_PATCHES, 0, 1);
4015 glPatchParameteri(GL_PATCH_VERTICES, 3);
4016 }
4017 else if (m_stage == 4)
4018 { // CS
4019 glDispatchCompute(1, 1, 1);
4020 }
4021 else
4022 {
4023 glDrawArrays(GL_POINTS, 0, 1);
4024 }
4025
4026 bool status = true;
4027 for (int i = 0; i < kTargets; ++i)
4028 {
4029 glBindTexture(targets[i], textures[i]);
4030 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4031
4032 if (targets[i] == GL_TEXTURE_CUBE_MAP)
4033 {
4034 for (int face = 0; face < 6; ++face)
4035 {
4036 T data;
4037 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]);
4038 if (!Equal(data, expected_value, internalformat))
4039 {
4040 status = false;
4041 m_context.getTestContext().getLog()
4042 << tcu::TestLog::Message << "Value is: " << ToString(data)
4043 << ". Value should be: " << ToString(expected_value)
4044 << ". Format is: " << FormatEnumToString(internalformat)
4045 << ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage)
4046 << tcu::TestLog::EndMessage;
4047 }
4048 }
4049 }
4050 else
4051 {
4052 T data[12];
4053
4054 for (deUint32 ndx = 0; ndx < DE_LENGTH_OF_ARRAY(data); ndx++)
4055 data[ndx] = T(0);
4056
4057 glGetTexImage(targets[i], 0, Format<T>(), Type<T>(), &data[0]);
4058
4059 int count = 1;
4060 if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
4061 count = 2;
4062 else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY)
4063 count = 12;
4064 else if (targets[i] == GL_TEXTURE_1D_ARRAY)
4065 count = 2;
4066
4067 for (int j = 0; j < count; ++j)
4068 {
4069 if (!Equal(data[j], expected_value, internalformat))
4070 {
4071 status = false;
4072 m_context.getTestContext().getLog()
4073 << tcu::TestLog::Message << "Value is: " << ToString(data[j])
4074 << ". Value should be: " << ToString(expected_value)
4075 << ". Format is: " << FormatEnumToString(internalformat)
4076 << ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage)
4077 << tcu::TestLog::EndMessage;
4078 }
4079 }
4080 }
4081 }
4082 glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4083 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
4084 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4085 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
4086 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4087 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4088 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4089 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4090
4091 glUseProgram(program_load);
4092 glUniform1i(glGetUniformLocation(program_load, "g_image_result"), 0);
4093 glUniform1i(glGetUniformLocation(program_load, "g_image_2d"), 1);
4094 glUniform1i(glGetUniformLocation(program_load, "g_image_3d"), 2);
4095 glUniform1i(glGetUniformLocation(program_load, "g_image_2drect"), 3);
4096 glUniform1i(glGetUniformLocation(program_load, "g_image_cube"), 4);
4097 glUniform1i(glGetUniformLocation(program_load, "g_image_1darray"), 5);
4098 glUniform1i(glGetUniformLocation(program_load, "g_image_2darray"), 6);
4099 glUniform1i(glGetUniformLocation(program_load, "g_image_cube_array"), 7);
4100
4101 if (m_stage == 1 || m_stage == 2)
4102 { // TCS or TES
4103 glPatchParameteri(GL_PATCH_VERTICES, 1);
4104 glDrawArrays(GL_PATCHES, 0, 1);
4105 glPatchParameteri(GL_PATCH_VERTICES, 3);
4106 }
4107 else if (m_stage == 4)
4108 { // CS
4109 glDispatchCompute(1, 1, 1);
4110 }
4111 else
4112 {
4113 glDrawArrays(GL_POINTS, 0, 1);
4114 }
4115 {
4116 vec4 color;
4117 glBindTexture(GL_TEXTURE_2D, texture_result);
4118 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4119 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]);
4120 if (!tcu::allEqual(color, vec4(0, 1, 0, 1)))
4121 {
4122 status = false;
4123 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color)
4124 << ". Format is: " << FormatEnumToString(internalformat)
4125 << ". Stage is: " << StageName(m_stage) << tcu::TestLog::EndMessage;
4126 }
4127 }
4128 glUseProgram(0);
4129 glDeleteProgram(program_store);
4130 glDeleteProgram(program_load);
4131 glDeleteTextures(kTargets, textures);
4132 glDeleteTextures(1, &texture_result);
4133 return status;
4134 }
4135
4136 template <typename T>
GenStoreShader(int stage,GLenum internalformat,const T & write_value)4137 std::string GenStoreShader(int stage, GLenum internalformat, const T& write_value)
4138 {
4139 std::ostringstream os;
4140 os << "#version 420 core";
4141 if (stage == 4)
4142 { // CS
4143 os << NL "#extension GL_ARB_compute_shader : require";
4144 }
4145 os << NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4146 << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
4147 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
4148 << ") writeonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
4149 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4150 << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
4151 << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat)
4152 << ") writeonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
4153 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4154 << "image2DArray g_image_2darray;" NL "layout(" << FormatEnumToString(internalformat)
4155 << ") writeonly uniform " << TypePrefix<T>() << "imageCubeArray g_image_cube_array;" NL "uniform "
4156 << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << write_value
4157 << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);";
4158 if (stage == 0)
4159 { // VS
4160 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
4161 }
4162 else if (stage == 1)
4163 { // TCS
4164 os << NL "layout(vertices = 1) out;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL
4165 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL
4166 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL
4167 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4168 }
4169 else if (stage == 2)
4170 { // TES
4171 os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4172 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4173 }
4174 else if (stage == 3)
4175 { // GS
4176 os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4177 " ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);";
4178 }
4179 else if (stage == 4)
4180 { // CS
4181 os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4182 " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
4183 }
4184 os << NL " imageStore(g_image_1d, coord.x, g_value);" NL " imageStore(g_image_2d, coord, g_value);" NL
4185 " imageStore(g_image_3d, ivec3(coord.xy, g_index[0]), g_value);" NL
4186 " imageStore(g_image_3d, ivec3(coord.xy, g_index[1]), g_value);" NL
4187 " imageStore(g_image_2drect, coord, g_value);" NL " for (int i = 0; i < 6; ++i) {" NL
4188 " imageStore(g_image_cube, ivec3(coord, g_index[i]), g_value);" NL " }" NL
4189 " imageStore(g_image_1darray, ivec2(coord.x, g_index[0]), g_value);" NL
4190 " imageStore(g_image_1darray, ivec2(coord.x, g_index[1]), g_value);" NL
4191 " imageStore(g_image_2darray, ivec3(coord, g_index[0]), g_value);" NL
4192 " imageStore(g_image_2darray, ivec3(coord, g_index[1]), g_value);" NL
4193 " for (int i = 0; i < 6; ++i) {" NL
4194 " imageStore(g_image_cube_array, ivec3(coord, g_index[i]), g_value);" NL " }" NL
4195 " for (int i = 0; i < 6; ++i) {" NL
4196 " imageStore(g_image_cube_array, ivec3(coord, g_index[i] + 6), g_value);" NL " }" NL "}";
4197 return os.str();
4198 }
4199
4200 template <typename T>
GenLoadShader(int stage,GLenum internalformat,const T & expected_value)4201 std::string GenLoadShader(int stage, GLenum internalformat, const T& expected_value)
4202 {
4203 std::ostringstream os;
4204 os << "#version 420 core";
4205 if (stage == 4)
4206 { // CS
4207 os << NL "#extension GL_ARB_compute_shader : require";
4208 }
4209 os << NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4210 << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
4211 << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
4212 << ") readonly uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout("
4213 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4214 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
4215 << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat)
4216 << ") readonly uniform " << TypePrefix<T>() << "image2DArray g_image_2darray;" NL "layout("
4217 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4218 << "imageCubeArray g_image_cube_array;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL
4219 "uniform "
4220 << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << expected_value
4221 << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);";
4222 if (stage == 0)
4223 { // VS
4224 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
4225 }
4226 else if (stage == 1)
4227 { // TCS
4228 os << NL "layout(vertices = 1) out;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL
4229 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL
4230 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL
4231 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4232 }
4233 else if (stage == 2)
4234 { // TES
4235 os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4236 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4237 }
4238 else if (stage == 3)
4239 { // GS
4240 os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4241 " ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);";
4242 }
4243 else if (stage == 4)
4244 { // CS
4245 os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4246 " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
4247 }
4248 os << NL " vec4 r = vec4(0, 1, 0, 1);" NL " " << TypePrefix<T>()
4249 << "vec4 v;" NL " v = imageLoad(g_image_2d, coord);" NL
4250 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4251 " v = imageLoad(g_image_3d, ivec3(coord, g_index[0]));" NL
4252 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL " v = imageLoad(g_image_2drect, coord);" NL
4253 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4254 " v = imageLoad(g_image_cube, ivec3(coord, g_index[0]));" NL
4255 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL " v = imageLoad(g_image_1darray, coord);" NL
4256 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4257 " v = imageLoad(g_image_2darray, ivec3(coord, g_index[0]));" NL
4258 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4259 " v = imageLoad(g_image_cube_array, ivec3(coord, g_index[0]));" NL
4260 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL " imageStore(g_image_result, coord, r);" NL "}";
4261 return os.str();
4262 }
4263
4264 protected:
RunStage(int stage)4265 long RunStage(int stage)
4266 {
4267 if (!SupportedInStage(stage, 8))
4268 return NOT_SUPPORTED;
4269
4270 glEnable(GL_RASTERIZER_DISCARD);
4271 m_stage = stage;
4272
4273 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
4274 return ERROR;
4275 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
4276 return ERROR;
4277 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4278 return ERROR;
4279
4280 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
4281 return ERROR;
4282 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
4283 return ERROR;
4284 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4285 return ERROR;
4286
4287 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4288 return ERROR;
4289 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4290 return ERROR;
4291 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4292 return ERROR;
4293
4294 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
4295 return ERROR;
4296
4297 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4298 return ERROR;
4299 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4300 return ERROR;
4301 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4302 return ERROR;
4303
4304 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4305 return ERROR;
4306 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4307 return ERROR;
4308 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4309 return ERROR;
4310
4311 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4312 return ERROR;
4313 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4314 return ERROR;
4315 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4316 return ERROR;
4317 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4318 return ERROR;
4319
4320 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4321 return ERROR;
4322 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4323 return ERROR;
4324 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4325 return ERROR;
4326
4327 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4328 return ERROR;
4329 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4330 return ERROR;
4331 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4332 return ERROR;
4333
4334 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
4335 return ERROR;
4336 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
4337 return ERROR;
4338 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
4339 return ERROR;
4340 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4341 return ERROR;
4342
4343 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
4344 return ERROR;
4345 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
4346 return ERROR;
4347 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4348 return ERROR;
4349
4350 //
4351 {
4352 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
4353 return ERROR;
4354 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
4355 return ERROR;
4356 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
4357 return ERROR;
4358
4359 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
4360 return ERROR;
4361 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
4362 return ERROR;
4363 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
4364 return ERROR;
4365 }
4366 return NO_ERROR;
4367 }
4368 };
4369 //-----------------------------------------------------------------------------
4370 // AtomicMachine
4371 //-----------------------------------------------------------------------------
4372 class AtomicMachine : public ShaderImageLoadStoreBase
4373 {
4374 GLuint m_vao;
4375
Setup()4376 virtual long Setup()
4377 {
4378 glEnable(GL_RASTERIZER_DISCARD);
4379 glGenVertexArrays(1, &m_vao);
4380 return NO_ERROR;
4381 }
4382
Cleanup()4383 virtual long Cleanup()
4384 {
4385 glDisable(GL_RASTERIZER_DISCARD);
4386 glDeleteVertexArrays(1, &m_vao);
4387 return NO_ERROR;
4388 }
4389
4390 template <typename T>
Atomic(int stage,GLenum internalformat)4391 bool Atomic(int stage, GLenum internalformat)
4392 {
4393 GLuint program = 0;
4394 if (stage == 0)
4395 { // VS
4396 program = BuildProgram(GenShader<T>(stage, internalformat).c_str(), NULL, NULL, NULL, NULL);
4397 }
4398 else if (stage == 1)
4399 { // TCS
4400 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
4401 const char* const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
4402 program = BuildProgram(glsl_vs, GenShader<T>(stage, internalformat).c_str(), glsl_tes, NULL, NULL);
4403 }
4404 else if (stage == 2)
4405 { // TES
4406 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
4407 program = BuildProgram(glsl_vs, NULL, GenShader<T>(stage, internalformat).c_str(), NULL, NULL);
4408 }
4409 else if (stage == 3)
4410 { // GS
4411 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
4412 program = BuildProgram(glsl_vs, NULL, NULL, GenShader<T>(stage, internalformat).c_str(), NULL);
4413 }
4414 else if (stage == 4)
4415 { // CS
4416 std::string source = GenShader<T>(stage, internalformat);
4417 const char* const src = source.c_str();
4418 GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
4419 glShaderSource(sh, 1, &src, NULL);
4420 glCompileShader(sh);
4421 program = glCreateProgram();
4422 glAttachShader(program, sh);
4423 glLinkProgram(program);
4424 glDeleteShader(sh);
4425 }
4426 GLuint texture_result;
4427 glGenTextures(1, &texture_result);
4428 glBindTexture(GL_TEXTURE_2D, texture_result);
4429 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4430 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4431 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
4432
4433 const GLenum targets[] = { GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP,
4434 GL_TEXTURE_BUFFER, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY };
4435 const int kTargets = sizeof(targets) / sizeof(targets[0]);
4436
4437 GLuint textures[kTargets];
4438 GLuint buffer;
4439 glGenTextures(kTargets, textures);
4440 glGenBuffers(1, &buffer);
4441
4442 for (int i = 0; i < kTargets; ++i)
4443 {
4444 glBindTexture(targets[i], textures[i]);
4445 if (targets[i] != GL_TEXTURE_BUFFER)
4446 {
4447 glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4448 glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4449 }
4450 if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE)
4451 {
4452 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
4453 }
4454 else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
4455 {
4456 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2);
4457 }
4458 else if (targets[i] == GL_TEXTURE_CUBE_MAP)
4459 {
4460 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
4461 }
4462 else if (targets[i] == GL_TEXTURE_BUFFER)
4463 {
4464 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
4465 glBufferData(GL_TEXTURE_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
4466 glBindBuffer(GL_TEXTURE_BUFFER, 0);
4467 glTexBuffer(targets[i], internalformat, buffer);
4468 }
4469 else if (targets[i] == GL_TEXTURE_1D_ARRAY)
4470 {
4471 glTexStorage2D(targets[i], 1, internalformat, 1, 2);
4472 }
4473 }
4474 glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4475 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4476 glBindImageTexture(2, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4477 glBindImageTexture(3, textures[2], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4478 glBindImageTexture(4, textures[3], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4479 glBindImageTexture(5, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4480 glBindImageTexture(6, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4481 glBindImageTexture(7, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4482
4483 glUseProgram(program);
4484 glUniform1i(glGetUniformLocation(program, "g_image_result"), 0);
4485 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
4486 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
4487 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
4488 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4);
4489 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5);
4490 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6);
4491 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7);
4492
4493 glBindVertexArray(m_vao);
4494 if (stage == 1 || stage == 2)
4495 { // TCS or TES
4496 glPatchParameteri(GL_PATCH_VERTICES, 1);
4497 glDrawArrays(GL_PATCHES, 0, 1);
4498 glPatchParameteri(GL_PATCH_VERTICES, 3);
4499 }
4500 else if (stage == 4)
4501 { // CS
4502 glDispatchCompute(1, 1, 1);
4503 }
4504 else
4505 {
4506 glDrawArrays(GL_POINTS, 0, 1);
4507 }
4508
4509 bool status = true;
4510 {
4511 vec4 color;
4512 glBindTexture(GL_TEXTURE_2D, texture_result);
4513 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4514 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]);
4515 if (!tcu::allEqual(color, vec4(0, 1, 0, 1)))
4516 {
4517 status = false;
4518 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color)
4519 << ". Format is: " << FormatEnumToString(internalformat)
4520 << ". Stage is: " << StageName(stage) << tcu::TestLog::EndMessage;
4521 }
4522 }
4523 glUseProgram(0);
4524 glDeleteProgram(program);
4525 glDeleteTextures(7, textures);
4526 glDeleteTextures(1, &texture_result);
4527 glDeleteBuffers(1, &buffer);
4528 return status;
4529 }
4530
4531 template <typename T>
GenShader(int stage,GLenum internalformat)4532 std::string GenShader(int stage, GLenum internalformat)
4533 {
4534 std::ostringstream os;
4535 os << "#version 420 core";
4536 if (stage == 4)
4537 { // CS
4538 os << NL "#extension GL_ARB_compute_shader : require";
4539 }
4540 os << NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4541 << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
4542 << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
4543 << ") coherent uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout("
4544 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4545 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
4546 << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
4547 << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
4548 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4549 << "image2DArray g_image_2darray;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL
4550 "uniform int g_value[6] = int[](0, 1, 2, 3, 4, 5);";
4551 if (stage == 0)
4552 { // VS
4553 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_VertexID, g_value[0]);";
4554 }
4555 else if (stage == 1)
4556 { // TCS
4557 os << NL "layout(vertices = 1) out;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL
4558 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL
4559 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL
4560 " ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);";
4561 }
4562 else if (stage == 2)
4563 { // TES
4564 os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4565 " ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);";
4566 }
4567 else if (stage == 3)
4568 { // GS
4569 os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4570 " ivec2 coord = ivec2(gl_PrimitiveIDIn, g_value[0]);";
4571 }
4572 else if (stage == 4)
4573 { // CS
4574 os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4575 " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_value[0]);";
4576 }
4577 os << NL
4578 " vec4 o_color = vec4(0, 1, 0, 1);" NL " imageAtomicExchange(g_image_2d, coord, 0);" NL
4579 " if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4580 " if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4581 " if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4582 " if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4583 " if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4584 " if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4585 " if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4586 " if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4587 " if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4588
4589 NL " imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0);" NL
4590 " if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4591 " if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4592 " if (imageAtomicMax(g_image_3d, ivec3(coord, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4593 " if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4594 " if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4595 " if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4596 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4597 " if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4598 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4599
4600 NL " imageAtomicExchange(g_image_2drect, coord, 0);" NL
4601 " if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4602 " if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4603 " if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4604 " if (imageAtomicAnd(g_image_2drect, coord, 0) != g_value[4]) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4605 " if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4606 " if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4607 " if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4608 " if (imageAtomicCompSwap(g_image_2drect, coord, g_value[1], 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
4609 "1.0);" NL " if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4610
4611 NL " imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0);" NL " if (imageAtomicAdd(g_image_cube, "
4612 "ivec3(coord, 0), g_value[2]) != 0) "
4613 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4614 " if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4615 " if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4616 " if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4617 " if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4618 " if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4619 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4620 " if (imageAtomicCompSwap(g_image_cube, ivec3(coord, g_value[0]), 1, 6) != 1) o_color = vec4(1.0, 0.0, "
4621 "0.0, 1.0);" NL
4622 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4623
4624 NL " imageAtomicExchange(g_image_buffer, coord.x, g_value[0]);" NL
4625 " if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4626 " if (imageAtomicMin(g_image_buffer, coord.x, g_value[3]) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4627 " if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4628 " if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4629 " if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4630 " if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4631 " if (imageAtomicExchange(g_image_buffer, coord.x, g_value[1]) != 3) o_color = vec4(1.0, 0.0, 0.0, "
4632 "1.0);" NL
4633 " if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4634 " if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4635
4636 NL " imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0);" NL
4637 " if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4638 " if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4639 " if (imageAtomicMax(g_image_1darray, ivec2(coord.x, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, "
4640 "1.0);" NL
4641 " if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4642 " if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4643 " if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4644 " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
4645 "1.0);" NL " if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = vec4(1.0, "
4646 "0.0, 0.0, 1.0);" NL
4647 " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4648
4649 NL " imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0);" NL
4650 " if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4651 " if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4652 " if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4653 " if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4654 " if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4655 " if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), g_value[4]) != 7) o_color = vec4(1.0, 0.0, 0.0, "
4656 "1.0);" NL " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, "
4657 "0.0, 1.0);" NL " if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) "
4658 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4659 " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4660
4661 NL " imageStore(g_image_result, coord, o_color);" NL "}";
4662 return os.str();
4663 }
4664
4665 protected:
RunStage(int stage)4666 long RunStage(int stage)
4667 {
4668 if (!SupportedInStage(stage, 8))
4669 return NOT_SUPPORTED;
4670 if (!Atomic<GLint>(stage, GL_R32I))
4671 return ERROR;
4672 if (!Atomic<GLuint>(stage, GL_R32UI))
4673 return ERROR;
4674 return NO_ERROR;
4675 }
4676 };
4677 //-----------------------------------------------------------------------------
4678 // 1.3.4 BasicAllTargetsLoadStoreVS
4679 //-----------------------------------------------------------------------------
4680 class BasicAllTargetsLoadStoreVS : public LoadStoreMachine
4681 {
Run()4682 virtual long Run()
4683 {
4684 return RunStage(0);
4685 }
4686 };
4687 //-----------------------------------------------------------------------------
4688 // 1.3.5 BasicAllTargetsLoadStoreTCS
4689 //-----------------------------------------------------------------------------
4690 class BasicAllTargetsLoadStoreTCS : public LoadStoreMachine
4691 {
Run()4692 virtual long Run()
4693 {
4694 return RunStage(1);
4695 }
4696 };
4697 //-----------------------------------------------------------------------------
4698 // 1.3.6 BasicAllTargetsLoadStoreTES
4699 //-----------------------------------------------------------------------------
4700 class BasicAllTargetsLoadStoreTES : public LoadStoreMachine
4701 {
Run()4702 virtual long Run()
4703 {
4704 return RunStage(2);
4705 }
4706 };
4707 //-----------------------------------------------------------------------------
4708 // 1.3.7 BasicAllTargetsLoadStoreGS
4709 //-----------------------------------------------------------------------------
4710 class BasicAllTargetsLoadStoreGS : public LoadStoreMachine
4711 {
Run()4712 virtual long Run()
4713 {
4714 return RunStage(3);
4715 }
4716 };
4717 //-----------------------------------------------------------------------------
4718 // 1.3.8 BasicAllTargetsLoadStoreCS
4719 //-----------------------------------------------------------------------------
4720 class BasicAllTargetsLoadStoreCS : public LoadStoreMachine
4721 {
Run()4722 virtual long Run()
4723 {
4724 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
4725 {
4726 m_context.getTestContext().getLog()
4727 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
4728 << tcu::TestLog::EndMessage;
4729 return NO_ERROR;
4730 }
4731
4732 return RunStage(4);
4733 }
4734 };
4735 //-----------------------------------------------------------------------------
4736 // 1.3.9 BasicAllTargetsAtomicVS
4737 //-----------------------------------------------------------------------------
4738 class BasicAllTargetsAtomicVS : public AtomicMachine
4739 {
Run()4740 virtual long Run()
4741 {
4742 return RunStage(0);
4743 }
4744 };
4745 //-----------------------------------------------------------------------------
4746 // 1.3.10 BasicAllTargetsAtomicTCS
4747 //-----------------------------------------------------------------------------
4748 class BasicAllTargetsAtomicTCS : public AtomicMachine
4749 {
Run()4750 virtual long Run()
4751 {
4752 return RunStage(1);
4753 }
4754 };
4755 //-----------------------------------------------------------------------------
4756 // 1.3.11 BasicAllTargetsAtomicTES
4757 //-----------------------------------------------------------------------------
4758 class BasicAllTargetsAtomicTES : public AtomicMachine
4759 {
Run()4760 virtual long Run()
4761 {
4762 return RunStage(2);
4763 }
4764 };
4765 //-----------------------------------------------------------------------------
4766 // 1.3.12 BasicAllTargetsAtomicGS
4767 //-----------------------------------------------------------------------------
4768 class BasicAllTargetsAtomicGS : public AtomicMachine
4769 {
Run()4770 virtual long Run()
4771 {
4772 return RunStage(3);
4773 }
4774 };
4775 //-----------------------------------------------------------------------------
4776 // 1.3.13 BasicAllTargetsAtomicCS
4777 //-----------------------------------------------------------------------------
4778 class BasicAllTargetsAtomicCS : public AtomicMachine
4779 {
Run()4780 virtual long Run()
4781 {
4782 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
4783 {
4784 m_context.getTestContext().getLog()
4785 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
4786 << tcu::TestLog::EndMessage;
4787 return NO_ERROR;
4788 }
4789
4790 return RunStage(4);
4791 }
4792 };
4793 //-----------------------------------------------------------------------------
4794 // 1.4.1 BasicGLSLMisc
4795 //-----------------------------------------------------------------------------
4796 class BasicGLSLMisc : public ShaderImageLoadStoreBase
4797 {
4798 GLuint m_texture;
4799 GLuint m_program;
4800 GLuint m_vao, m_vbo;
4801
Setup()4802 virtual long Setup()
4803 {
4804 m_texture = 0;
4805 m_program = 0;
4806 m_vao = m_vbo = 0;
4807 return NO_ERROR;
4808 }
4809
Run()4810 virtual long Run()
4811 {
4812 const int kSize = 32;
4813 std::vector<vec4> data(kSize * kSize * 4, vec4(0.0f));
4814
4815 glGenTextures(1, &m_texture);
4816 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
4817 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4818 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, kSize, kSize, 4, 0, GL_RGBA, GL_FLOAT, &data[0]);
4819 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
4820
4821 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4822 " gl_Position = i_position;" NL "}";
4823 const char* src_fs =
4824 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
4825 "layout(rgba32f) coherent volatile restrict uniform image2D g_image_layer0;" NL
4826 "layout(rgba32f) volatile uniform image2D g_image_layer1;" NL
4827 "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
4828 " imageStore(g_image_layer0, coord, vec4(1.0));" NL " memoryBarrier();" NL
4829 " imageStore(g_image_layer0, coord, vec4(2.0));" NL " memoryBarrier();" NL
4830 " imageStore(g_image_layer0, coord, vec4(0.0, 1.0, 0.0, 1.0));" NL " memoryBarrier();" NL
4831 " o_color = imageLoad(g_image_layer0, coord) + imageLoad(g_image_layer1, coord);" NL "}";
4832 m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs);
4833
4834 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4835
4836 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4837 glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_ONLY, GL_RGBA32F);
4838
4839 glClear(GL_COLOR_BUFFER_BIT);
4840 glViewport(0, 0, kSize, kSize);
4841
4842 glUseProgram(m_program);
4843 glUniform1i(glGetUniformLocation(m_program, "g_image_layer0"), 0);
4844 glUniform1i(glGetUniformLocation(m_program, "g_image_layer1"), 1);
4845
4846 glBindVertexArray(m_vao);
4847 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4848
4849 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
4850 {
4851 return ERROR;
4852 }
4853 return NO_ERROR;
4854 }
4855
Cleanup()4856 virtual long Cleanup()
4857 {
4858 glViewport(0, 0, getWindowWidth(), getWindowHeight());
4859 glDeleteTextures(1, &m_texture);
4860 glDeleteVertexArrays(1, &m_vao);
4861 glDeleteBuffers(1, &m_vbo);
4862 glUseProgram(0);
4863 glDeleteProgram(m_program);
4864 return NO_ERROR;
4865 }
4866 };
4867 //-----------------------------------------------------------------------------
4868 // 1.4.2 BasicGLSLEarlyFragTests
4869 //-----------------------------------------------------------------------------
4870 class BasicGLSLEarlyFragTests : public ShaderImageLoadStoreBase
4871 {
4872 GLuint m_texture[2];
4873 GLuint m_program[2];
4874 GLuint m_vao, m_vbo;
4875
Setup()4876 virtual long Setup()
4877 {
4878 m_texture[0] = m_texture[1] = 0;
4879 m_program[0] = m_program[1] = 0;
4880 m_vao = m_vbo = 0;
4881 return NO_ERROR;
4882 }
4883
Run()4884 virtual long Run()
4885 {
4886 int ds = m_context.getRenderContext().getRenderTarget().getDepthBits();
4887
4888 const int kSize = 32;
4889 std::vector<vec4> data(kSize * kSize);
4890
4891 glGenTextures(2, m_texture);
4892 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4893 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4894 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]);
4895 glBindTexture(GL_TEXTURE_2D, 0);
4896
4897 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4898 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4899 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]);
4900 glBindTexture(GL_TEXTURE_2D, 0);
4901
4902 const char* glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4903 " gl_Position = i_position;" NL "}";
4904 const char* glsl_early_frag_tests_fs =
4905 "#version 420 core" NL "layout(early_fragment_tests) in;" NL "layout(location = 0) out vec4 o_color;" NL
4906 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL
4907 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(1.0));" NL
4908 " o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
4909 const char* glsl_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
4910 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL
4911 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(1.0));" NL
4912 " o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
4913 m_program[0] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_early_frag_tests_fs);
4914 m_program[1] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
4915
4916 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4917
4918 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4919 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4920
4921 glViewport(0, 0, kSize, kSize);
4922 glBindVertexArray(m_vao);
4923
4924 glEnable(GL_DEPTH_TEST);
4925 glClearColor(0.0, 1.0f, 0.0, 1.0f);
4926 glClearDepthf(0.0f);
4927
4928 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4929 glUseProgram(m_program[0]);
4930 glUniform1i(glGetUniformLocation(m_program[0], "g_image"), 0);
4931
4932 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4933
4934 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4935 glUseProgram(m_program[1]);
4936 glUniform1i(glGetUniformLocation(m_program[1], "g_image"), 1);
4937 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4938
4939 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4940 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4941 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]);
4942 for (int i = 0; i < kSize * kSize; ++i)
4943 {
4944 if (IsEqual(data[i], vec4(1.0f)) && ds != 0)
4945 return ERROR;
4946 }
4947
4948 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4949 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4950 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]);
4951 for (int i = 0; i < kSize * kSize; ++i)
4952 {
4953 if (!IsEqual(data[i], vec4(1.0f)) && ds != 0)
4954 return ERROR;
4955 }
4956
4957 return NO_ERROR;
4958 }
4959
Cleanup()4960 virtual long Cleanup()
4961 {
4962 glDisable(GL_DEPTH_TEST);
4963 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
4964 glClearDepthf(1.0f);
4965 glViewport(0, 0, getWindowWidth(), getWindowHeight());
4966 glDeleteTextures(2, m_texture);
4967 glDeleteVertexArrays(1, &m_vao);
4968 glDeleteBuffers(1, &m_vbo);
4969 glUseProgram(0);
4970 glDeleteProgram(m_program[0]);
4971 glDeleteProgram(m_program[1]);
4972 return NO_ERROR;
4973 }
4974 };
4975 //-----------------------------------------------------------------------------
4976 // 1.4.3 BasicGLSLConst
4977 //-----------------------------------------------------------------------------
4978 class BasicGLSLConst : public ShaderImageLoadStoreBase
4979 {
4980 GLuint m_program;
4981 GLuint m_vao, m_vbo;
4982
Setup()4983 virtual long Setup()
4984 {
4985 m_program = 0;
4986 m_vao = m_vbo = 0;
4987 return NO_ERROR;
4988 }
4989
Run()4990 virtual long Run()
4991 {
4992 bool isAtLeast44Context =
4993 glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 4));
4994
4995 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4996 " gl_Position = i_position;" NL "}";
4997 std::ostringstream src_fs;
4998 src_fs << "#version " << (isAtLeast44Context ? "440" : "420") << " core";
4999 src_fs << NL "layout(location = 0) out vec4 o_color;" NL "uniform int MaxImageUnits;" NL
5000 "uniform int MaxCombinedShaderOutputResources;" NL "uniform int MaxImageSamples;" NL
5001 "uniform int MaxVertexImageUniforms;" NL "uniform int MaxTessControlImageUniforms;" NL
5002 "uniform int MaxTessEvaluationImageUniforms;" NL "uniform int MaxGeometryImageUniforms;" NL
5003 "uniform int MaxFragmentImageUniforms;" NL "uniform int MaxCombinedImageUniforms;" NL
5004 "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
5005 " if (gl_MaxImageUnits != MaxImageUnits) o_color = vec4(1.0, 0.0, 0.0, 0.1);";
5006 if (isAtLeast44Context)
5007 src_fs << NL " if (gl_MaxCombinedShaderOutputResources != MaxCombinedShaderOutputResources) o_color = "
5008 "vec4(0.2, 0.0, 0.0, 0.2);";
5009 else
5010 src_fs << NL " if (gl_MaxCombinedImageUnitsAndFragmentOutputs != MaxCombinedShaderOutputResources) "
5011 "o_color = vec4(0.2, 0.0, 0.0, 0.2);";
5012 src_fs << NL
5013 " if (gl_MaxImageSamples != MaxImageSamples) o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
5014 " if (gl_MaxVertexImageUniforms != MaxVertexImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL
5015 " if (gl_MaxTessControlImageUniforms != MaxTessControlImageUniforms) o_color = vec4(1.0, 0.0, 0.0, "
5016 "0.5);" NL " if (gl_MaxTessEvaluationImageUniforms != MaxTessEvaluationImageUniforms) o_color = vec4(1.0, "
5017 "0.0, 0.0, 0.6);" NL
5018 " if (gl_MaxGeometryImageUniforms != MaxGeometryImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL
5019 " if (gl_MaxFragmentImageUniforms != MaxFragmentImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL
5020 " if (gl_MaxCombinedImageUniforms != MaxCombinedImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.9);" NL "}";
5021
5022 m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs.str().c_str());
5023 glUseProgram(m_program);
5024
5025 GLint i;
5026 glGetIntegerv(GL_MAX_IMAGE_UNITS, &i);
5027 glUniform1i(glGetUniformLocation(m_program, "MaxImageUnits"), i);
5028
5029 glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &i);
5030 glUniform1i(glGetUniformLocation(m_program, "MaxCombinedShaderOutputResources"), i);
5031
5032 glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
5033 glUniform1i(glGetUniformLocation(m_program, "MaxImageSamples"), i);
5034
5035 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &i);
5036 glUniform1i(glGetUniformLocation(m_program, "MaxVertexImageUniforms"), i);
5037
5038 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &i);
5039 glUniform1i(glGetUniformLocation(m_program, "MaxTessControlImageUniforms"), i);
5040
5041 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &i);
5042 glUniform1i(glGetUniformLocation(m_program, "MaxTessEvaluationImageUniforms"), i);
5043
5044 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &i);
5045 glUniform1i(glGetUniformLocation(m_program, "MaxGeometryImageUniforms"), i);
5046
5047 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &i);
5048 glUniform1i(glGetUniformLocation(m_program, "MaxFragmentImageUniforms"), i);
5049
5050 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &i);
5051 glUniform1i(glGetUniformLocation(m_program, "MaxCombinedImageUniforms"), i);
5052
5053 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5054
5055 glClear(GL_COLOR_BUFFER_BIT);
5056 glBindVertexArray(m_vao);
5057 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5058
5059 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5060 {
5061 return ERROR;
5062 }
5063 return NO_ERROR;
5064 }
5065
Cleanup()5066 virtual long Cleanup()
5067 {
5068 glDeleteVertexArrays(1, &m_vao);
5069 glDeleteBuffers(1, &m_vbo);
5070 glUseProgram(0);
5071 glDeleteProgram(m_program);
5072 return NO_ERROR;
5073 }
5074 };
5075 //-----------------------------------------------------------------------------
5076 // 2.1.1 AdvancedSyncImageAccess
5077 //-----------------------------------------------------------------------------
5078 class AdvancedSyncImageAccess : public ShaderImageLoadStoreBase
5079 {
5080 GLuint m_buffer;
5081 GLuint m_buffer_tex;
5082 GLuint m_store_program;
5083 GLuint m_draw_program;
5084 GLuint m_attribless_vao;
5085
Setup()5086 virtual long Setup()
5087 {
5088 m_buffer = 0;
5089 m_buffer_tex = 0;
5090 m_store_program = 0;
5091 m_draw_program = 0;
5092 m_attribless_vao = 0;
5093 return NO_ERROR;
5094 }
5095
Run()5096 virtual long Run()
5097 {
5098 if (!SupportedInVS(1))
5099 return NOT_SUPPORTED;
5100 const char* const glsl_store_vs =
5101 "#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL
5102 " vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
5103 " imageStore(g_output_data, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL "}";
5104 const char* const glsl_draw_vs =
5105 "#version 420 core" NL "out vec4 vs_color;" NL "layout(rg32f) readonly uniform imageBuffer g_image;" NL
5106 "uniform samplerBuffer g_sampler;" NL "void main() {" NL " vec4 pi = imageLoad(g_image, gl_VertexID);" NL
5107 " vec4 ps = texelFetch(g_sampler, gl_VertexID);" NL
5108 " if (pi != ps) vs_color = vec4(1.0, 0.0, 0.0, 1.0);" NL " else vs_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
5109 " gl_Position = pi;" NL "}";
5110 const char* const glsl_draw_fs =
5111 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
5112 " o_color = vs_color;" NL "}";
5113 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5114 m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5115
5116 glGenVertexArrays(1, &m_attribless_vao);
5117 glBindVertexArray(m_attribless_vao);
5118
5119 glGenBuffers(1, &m_buffer);
5120 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5121 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW);
5122 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5123
5124 glGenTextures(1, &m_buffer_tex);
5125 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5126 glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_buffer);
5127
5128 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG32F);
5129
5130 glEnable(GL_RASTERIZER_DISCARD);
5131 glUseProgram(m_store_program);
5132 glDrawArrays(GL_POINTS, 0, 4);
5133
5134 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT);
5135
5136 glDisable(GL_RASTERIZER_DISCARD);
5137 glClear(GL_COLOR_BUFFER_BIT);
5138 glUseProgram(m_draw_program);
5139 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5140
5141 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5142 {
5143 return ERROR;
5144 }
5145 return NO_ERROR;
5146 }
5147
Cleanup()5148 virtual long Cleanup()
5149 {
5150 glUseProgram(0);
5151 glDeleteBuffers(1, &m_buffer);
5152 glDeleteTextures(1, &m_buffer_tex);
5153 glDeleteProgram(m_store_program);
5154 glDeleteProgram(m_draw_program);
5155 glDeleteVertexArrays(1, &m_attribless_vao);
5156 return NO_ERROR;
5157 }
5158 };
5159 //-----------------------------------------------------------------------------
5160 // 2.1.2 AdvancedSyncVertexArray
5161 //-----------------------------------------------------------------------------
5162 class AdvancedSyncVertexArray : public ShaderImageLoadStoreBase
5163 {
5164 GLuint m_position_buffer;
5165 GLuint m_color_buffer;
5166 GLuint m_element_buffer;
5167 GLuint m_position_buffer_tex;
5168 GLuint m_color_buffer_tex;
5169 GLuint m_element_buffer_tex;
5170 GLuint m_store_program;
5171 GLuint m_draw_program;
5172 GLuint m_attribless_vao;
5173 GLuint m_draw_vao;
5174
Setup()5175 virtual long Setup()
5176 {
5177 m_position_buffer = 0;
5178 m_color_buffer = 0;
5179 m_element_buffer = 0;
5180 m_position_buffer_tex = 0;
5181 m_color_buffer_tex = 0;
5182 m_element_buffer_tex = 0;
5183 m_store_program = 0;
5184 m_draw_program = 0;
5185 m_attribless_vao = 0;
5186 m_draw_vao = 0;
5187 return NO_ERROR;
5188 }
5189
Run()5190 virtual long Run()
5191 {
5192 if (!SupportedInVS(3))
5193 return NOT_SUPPORTED;
5194 const char* const glsl_store_vs =
5195 "#version 420 core" NL "layout(rg32f) writeonly uniform imageBuffer g_position_buffer;" NL
5196 "layout(rgba32f) writeonly uniform imageBuffer g_color_buffer;" NL
5197 "layout(r32ui) writeonly uniform uimageBuffer g_element_buffer;" NL "uniform vec4 g_color;" NL
5198 "void main() {" NL " vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
5199 " imageStore(g_position_buffer, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL
5200 " imageStore(g_color_buffer, gl_VertexID, g_color);" NL
5201 " imageStore(g_element_buffer, gl_VertexID, uvec4(gl_VertexID));" NL "}";
5202 const char* const glsl_draw_vs =
5203 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5204 "layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL "void main() {" NL
5205 " gl_Position = i_position;" NL " vs_color = i_color;" NL "}";
5206 const char* const glsl_draw_fs =
5207 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
5208 " o_color = vs_color;" NL "}";
5209 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5210 glUseProgram(m_store_program);
5211 glUniform1i(glGetUniformLocation(m_store_program, "g_position_buffer"), 0);
5212 glUniform1i(glGetUniformLocation(m_store_program, "g_color_buffer"), 1);
5213 glUniform1i(glGetUniformLocation(m_store_program, "g_element_buffer"), 2);
5214 glUseProgram(0);
5215
5216 m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5217
5218 glGenBuffers(1, &m_position_buffer);
5219 glBindBuffer(GL_TEXTURE_BUFFER, m_position_buffer);
5220 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW);
5221 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5222
5223 glGenBuffers(1, &m_color_buffer);
5224 glBindBuffer(GL_TEXTURE_BUFFER, m_color_buffer);
5225 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_DYNAMIC_DRAW);
5226 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5227
5228 glGenBuffers(1, &m_element_buffer);
5229 glBindBuffer(GL_TEXTURE_BUFFER, m_element_buffer);
5230 glBufferData(GL_TEXTURE_BUFFER, sizeof(GLuint) * 4, NULL, GL_DYNAMIC_DRAW);
5231 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5232
5233 glGenTextures(1, &m_position_buffer_tex);
5234 glBindTexture(GL_TEXTURE_BUFFER, m_position_buffer_tex);
5235 glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_position_buffer);
5236 glBindTexture(GL_TEXTURE_BUFFER, 0);
5237
5238 glGenTextures(1, &m_color_buffer_tex);
5239 glBindTexture(GL_TEXTURE_BUFFER, m_color_buffer_tex);
5240 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_color_buffer);
5241 glBindTexture(GL_TEXTURE_BUFFER, 0);
5242
5243 glGenTextures(1, &m_element_buffer_tex);
5244 glBindTexture(GL_TEXTURE_BUFFER, m_element_buffer_tex);
5245 glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, m_element_buffer);
5246 glBindTexture(GL_TEXTURE_BUFFER, 0);
5247
5248 glGenVertexArrays(1, &m_attribless_vao);
5249
5250 glGenVertexArrays(1, &m_draw_vao);
5251 glBindVertexArray(m_draw_vao);
5252 glBindBuffer(GL_ARRAY_BUFFER, m_position_buffer);
5253 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
5254 glBindBuffer(GL_ARRAY_BUFFER, m_color_buffer);
5255 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
5256 glBindBuffer(GL_ARRAY_BUFFER, 0);
5257 glEnableVertexAttribArray(0);
5258 glEnableVertexAttribArray(1);
5259 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_element_buffer);
5260 glBindVertexArray(0);
5261
5262 glEnable(GL_RASTERIZER_DISCARD);
5263 glBindImageTexture(0, m_position_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RG32F);
5264 glBindImageTexture(1, m_color_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5265 glBindImageTexture(2, m_element_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
5266 glUseProgram(m_store_program);
5267 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
5268 glBindVertexArray(m_attribless_vao);
5269 glDrawArrays(GL_POINTS, 0, 4);
5270
5271 glDisable(GL_RASTERIZER_DISCARD);
5272 glClear(GL_COLOR_BUFFER_BIT);
5273 glUseProgram(m_draw_program);
5274 glBindVertexArray(m_draw_vao);
5275 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
5276 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
5277
5278 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5279 {
5280 return ERROR;
5281 }
5282
5283 glEnable(GL_RASTERIZER_DISCARD);
5284 glUseProgram(m_store_program);
5285 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 0.0f, 1.0f, 1.0f);
5286 glBindVertexArray(m_attribless_vao);
5287 glDrawArrays(GL_POINTS, 0, 4);
5288
5289 glDisable(GL_RASTERIZER_DISCARD);
5290 glClear(GL_COLOR_BUFFER_BIT);
5291 glUseProgram(m_draw_program);
5292 glBindVertexArray(m_draw_vao);
5293 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
5294 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
5295
5296 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 0, 1, 1)))
5297 {
5298 return ERROR;
5299 }
5300 return NO_ERROR;
5301 }
5302
Cleanup()5303 virtual long Cleanup()
5304 {
5305 glDisable(GL_RASTERIZER_DISCARD);
5306 glUseProgram(0);
5307 glDeleteBuffers(1, &m_position_buffer);
5308 glDeleteBuffers(1, &m_color_buffer);
5309 glDeleteBuffers(1, &m_element_buffer);
5310 glDeleteTextures(1, &m_position_buffer_tex);
5311 glDeleteTextures(1, &m_color_buffer_tex);
5312 glDeleteTextures(1, &m_element_buffer_tex);
5313 glDeleteProgram(m_store_program);
5314 glDeleteProgram(m_draw_program);
5315 glDeleteVertexArrays(1, &m_attribless_vao);
5316 glDeleteVertexArrays(1, &m_draw_vao);
5317 return NO_ERROR;
5318 }
5319 };
5320
5321 //-----------------------------------------------------------------------------
5322 // 2.1.4 AdvancedSyncDrawIndirect
5323 //-----------------------------------------------------------------------------
5324 class AdvancedSyncDrawIndirect : public ShaderImageLoadStoreBase
5325 {
5326 GLuint m_draw_command_buffer;
5327 GLuint m_draw_command_buffer_tex;
5328 GLuint m_store_program;
5329 GLuint m_draw_program;
5330 GLuint m_attribless_vao;
5331 GLuint m_draw_vao;
5332 GLuint m_draw_vbo;
5333
Setup()5334 virtual long Setup()
5335 {
5336 m_draw_command_buffer = 0;
5337 m_draw_command_buffer_tex = 0;
5338 m_store_program = 0;
5339 m_draw_program = 0;
5340 m_attribless_vao = 0;
5341 m_draw_vao = 0;
5342 m_draw_vbo = 0;
5343 return NO_ERROR;
5344 }
5345
Run()5346 virtual long Run()
5347 {
5348 if (!SupportedInVS(1))
5349 return NOT_SUPPORTED;
5350 const char* const glsl_store_vs =
5351 "#version 420 core" NL "writeonly uniform uimageBuffer g_draw_command_buffer;" NL "void main() {" NL
5352 " imageStore(g_draw_command_buffer, 0, uvec4(4, 1, 0, 0));" NL "}";
5353 const char* const glsl_draw_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5354 "void main() {" NL " gl_Position = i_position;" NL "}";
5355 const char* const glsl_draw_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
5356 "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
5357 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5358 m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5359
5360 glGenBuffers(1, &m_draw_command_buffer);
5361 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer);
5362 glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(uvec4), NULL, GL_DYNAMIC_DRAW);
5363 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
5364
5365 glGenTextures(1, &m_draw_command_buffer_tex);
5366 glBindTexture(GL_TEXTURE_BUFFER, m_draw_command_buffer_tex);
5367 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, m_draw_command_buffer);
5368 glBindTexture(GL_TEXTURE_BUFFER, 0);
5369
5370 glGenVertexArrays(1, &m_attribless_vao);
5371 CreateFullViewportQuad(&m_draw_vao, &m_draw_vbo, NULL);
5372
5373 glBindImageTexture(0, m_draw_command_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
5374
5375 glEnable(GL_RASTERIZER_DISCARD);
5376 glUseProgram(m_store_program);
5377 glBindVertexArray(m_attribless_vao);
5378 glDrawArrays(GL_POINTS, 0, 1);
5379
5380 glDisable(GL_RASTERIZER_DISCARD);
5381 glClear(GL_COLOR_BUFFER_BIT);
5382 glUseProgram(m_draw_program);
5383 glBindVertexArray(m_draw_vao);
5384 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer);
5385 glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
5386 glDrawArraysIndirect(GL_TRIANGLE_STRIP, 0);
5387
5388 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5389 {
5390 return ERROR;
5391 }
5392 return NO_ERROR;
5393 }
5394
Cleanup()5395 virtual long Cleanup()
5396 {
5397 glUseProgram(0);
5398 glDeleteBuffers(1, &m_draw_command_buffer);
5399 glDeleteTextures(1, &m_draw_command_buffer_tex);
5400 glDeleteProgram(m_store_program);
5401 glDeleteProgram(m_draw_program);
5402 glDeleteVertexArrays(1, &m_attribless_vao);
5403 glDeleteVertexArrays(1, &m_draw_vao);
5404 glDeleteBuffers(1, &m_draw_vbo);
5405 return NO_ERROR;
5406 }
5407 };
5408 //-----------------------------------------------------------------------------
5409 // 2.1.5 AdvancedSyncTextureUpdate
5410 //-----------------------------------------------------------------------------
5411 class AdvancedSyncTextureUpdate : public ShaderImageLoadStoreBase
5412 {
5413 GLuint m_texture;
5414 GLuint m_store_program;
5415 GLuint m_draw_program;
5416 GLuint m_vao;
5417 GLuint m_vbo;
5418 GLuint m_pbo;
5419
Setup()5420 virtual long Setup()
5421 {
5422 m_texture = 0;
5423 m_store_program = 0;
5424 m_draw_program = 0;
5425 m_vao = 0;
5426 m_vbo = 0;
5427 m_pbo = 0;
5428 return NO_ERROR;
5429 }
5430
Run()5431 virtual long Run()
5432 {
5433 const char* const glsl_vs =
5434 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL
5435 "void main() {" NL " gl_Position = i_position;" NL " vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}";
5436 const char* const glsl_store_fs =
5437 "#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL
5438 " imageStore(g_image, ivec2(gl_FragCoord.xy), gl_FragCoord);" NL " discard;" NL "}";
5439 const char* const glsl_draw_fs =
5440 "#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL
5441 "uniform sampler2D g_sampler;" NL "void main() {" NL " o_color = texture(g_sampler, vs_texcoord);" NL "}";
5442 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
5443 m_draw_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs);
5444
5445 std::vector<vec4> data(16 * 16, vec4(1.0f));
5446 glGenBuffers(1, &m_pbo);
5447 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
5448 glBufferData(GL_PIXEL_UNPACK_BUFFER, 16 * 16 * sizeof(vec4), &data[0], GL_DYNAMIC_READ);
5449 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
5450
5451 glGenTextures(1, &m_texture);
5452 glBindTexture(GL_TEXTURE_2D, m_texture);
5453 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5454 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
5455 glBindTexture(GL_TEXTURE_2D, 0);
5456
5457 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5458
5459 glViewport(0, 0, 16, 16);
5460 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5461 glUseProgram(m_store_program);
5462 glBindVertexArray(m_vao);
5463 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5464
5465 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
5466 glBindTexture(GL_TEXTURE_2D, m_texture);
5467 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
5468 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGBA, GL_FLOAT, 0);
5469 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
5470
5471 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5472 glClear(GL_COLOR_BUFFER_BIT);
5473 glUseProgram(m_draw_program);
5474 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5475
5476 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(1, 1, 1, 1)))
5477 {
5478 return ERROR;
5479 }
5480 return NO_ERROR;
5481 }
5482
Cleanup()5483 virtual long Cleanup()
5484 {
5485 glUseProgram(0);
5486 glDeleteBuffers(1, &m_vbo);
5487 glDeleteBuffers(1, &m_pbo);
5488 glDeleteTextures(1, &m_texture);
5489 glDeleteProgram(m_store_program);
5490 glDeleteProgram(m_draw_program);
5491 glDeleteVertexArrays(1, &m_vao);
5492 return NO_ERROR;
5493 }
5494 };
5495 //-----------------------------------------------------------------------------
5496 // 2.1.6 AdvancedSyncImageAccess2
5497 //-----------------------------------------------------------------------------
5498 class AdvancedSyncImageAccess2 : public ShaderImageLoadStoreBase
5499 {
5500 GLuint m_texture;
5501 GLuint m_store_program;
5502 GLuint m_draw_program;
5503 GLuint m_vao;
5504 GLuint m_vbo;
5505
Setup()5506 virtual long Setup()
5507 {
5508 m_texture = 0;
5509 m_store_program = 0;
5510 m_draw_program = 0;
5511 m_vao = 0;
5512 m_vbo = 0;
5513 return NO_ERROR;
5514 }
5515
Run()5516 virtual long Run()
5517 {
5518 const char* const glsl_vs =
5519 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL
5520 "void main() {" NL " gl_Position = i_position;" NL " vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}";
5521 const char* const glsl_store_fs =
5522 "#version 420 core" NL "writeonly uniform image2D g_image;" NL "uniform vec4 g_color;" NL "void main() {" NL
5523 " imageStore(g_image, ivec2(gl_FragCoord.xy), g_color);" NL " discard;" NL "}";
5524 const char* const glsl_draw_fs =
5525 "#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL
5526 "uniform sampler2D g_sampler;" NL "void main() {" NL " o_color = texture(g_sampler, vs_texcoord);" NL "}";
5527 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
5528 m_draw_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs);
5529
5530 int width = getWindowWidth();
5531 int height = getWindowHeight();
5532 scaleDimensionsToMemory(width, height, 1, 1, 16, 16);
5533
5534 glGenTextures(1, &m_texture);
5535 glBindTexture(GL_TEXTURE_2D, m_texture);
5536 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5537 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
5538 glBindTexture(GL_TEXTURE_2D, 0);
5539
5540 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5541
5542 glViewport(0, 0, width, height);
5543 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5544 glUseProgram(m_store_program);
5545 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 1.0f, 0.0f, 0.0f, 1.0f);
5546 glBindVertexArray(m_vao);
5547 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5548
5549 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5550
5551 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
5552 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5553
5554 glClear(GL_COLOR_BUFFER_BIT);
5555 glBindTexture(GL_TEXTURE_2D, m_texture);
5556 glUseProgram(m_draw_program);
5557 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5558
5559 if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
5560 {
5561 return ERROR;
5562 }
5563 return NO_ERROR;
5564 }
5565
Cleanup()5566 virtual long Cleanup()
5567 {
5568 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5569 glUseProgram(0);
5570 glDeleteBuffers(1, &m_vbo);
5571 glDeleteTextures(1, &m_texture);
5572 glDeleteProgram(m_store_program);
5573 glDeleteProgram(m_draw_program);
5574 glDeleteVertexArrays(1, &m_vao);
5575 return NO_ERROR;
5576 }
5577 };
5578 //-----------------------------------------------------------------------------
5579 // 2.1.7 AdvancedSyncBufferUpdate
5580 //-----------------------------------------------------------------------------
5581 class AdvancedSyncBufferUpdate : public ShaderImageLoadStoreBase
5582 {
5583 GLuint m_buffer;
5584 GLuint m_buffer_tex;
5585 GLuint m_store_program;
5586 GLuint m_attribless_vao;
5587
Setup()5588 virtual long Setup()
5589 {
5590 m_buffer = 0;
5591 m_buffer_tex = 0;
5592 m_store_program = 0;
5593 m_attribless_vao = 0;
5594 return NO_ERROR;
5595 }
5596
Run()5597 virtual long Run()
5598 {
5599 if (!SupportedInVS(1))
5600 return NOT_SUPPORTED;
5601 const char* const glsl_store_vs =
5602 "#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL
5603 " imageStore(g_output_data, gl_VertexID, vec4(gl_VertexID));" NL "}";
5604 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5605
5606 glGenVertexArrays(1, &m_attribless_vao);
5607 glBindVertexArray(m_attribless_vao);
5608
5609 glGenBuffers(1, &m_buffer);
5610 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5611 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 1000, NULL, GL_DYNAMIC_DRAW);
5612 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5613
5614 glGenTextures(1, &m_buffer_tex);
5615 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5616 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5617
5618 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5619
5620 glEnable(GL_RASTERIZER_DISCARD);
5621 glUseProgram(m_store_program);
5622 glDrawArrays(GL_POINTS, 0, 1000);
5623
5624 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5625
5626 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5627 vec4* ptr =
5628 reinterpret_cast<vec4*>(glMapBufferRange(GL_TEXTURE_BUFFER, 0, 1000 * sizeof(vec4), GL_MAP_READ_BIT));
5629 for (int i = 0; i < 1000; ++i)
5630 {
5631 if (!IsEqual(ptr[i], vec4(static_cast<float>(i))))
5632 {
5633 m_context.getTestContext().getLog()
5634 << tcu::TestLog::Message << "Bad buffer value found at index " << i << tcu::TestLog::EndMessage;
5635 return ERROR;
5636 }
5637 }
5638 return NO_ERROR;
5639 }
5640
Cleanup()5641 virtual long Cleanup()
5642 {
5643 glDisable(GL_RASTERIZER_DISCARD);
5644 glUseProgram(0);
5645 glDeleteBuffers(1, &m_buffer);
5646 glDeleteTextures(1, &m_buffer_tex);
5647 glDeleteProgram(m_store_program);
5648 glDeleteVertexArrays(1, &m_attribless_vao);
5649 return NO_ERROR;
5650 }
5651 };
5652 //-----------------------------------------------------------------------------
5653 // 2.2.1 AdvancedAllStagesOneImage
5654 //-----------------------------------------------------------------------------
5655 class AdvancedAllStagesOneImage : public ShaderImageLoadStoreBase
5656 {
5657 GLuint m_program;
5658 GLuint m_vao;
5659 GLuint m_vbo;
5660 GLuint m_ebo;
5661 GLuint m_buffer;
5662 GLuint m_buffer_tex;
5663 GLuint m_texture;
5664
Setup()5665 virtual long Setup()
5666 {
5667 m_program = 0;
5668 m_vao = 0;
5669 m_vbo = 0;
5670 m_ebo = 0;
5671 m_buffer = 0;
5672 m_buffer_tex = 0;
5673 m_texture = 0;
5674 return NO_ERROR;
5675 }
5676
Run()5677 virtual long Run()
5678 {
5679 if (!SupportedInGeomStages(2))
5680 return NOT_SUPPORTED;
5681 const char* const glsl_vs =
5682 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5683 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5684 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5685 " gl_Position = i_position + vec4(1.0, 1.0, 0.0, 0.0);" NL " imageAtomicAdd(g_buffer, 0, 1);" NL
5686 " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}";
5687 const char* const glsl_tcs =
5688 "#version 420 core" NL "layout(vertices = 1) out;" NL
5689 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5690 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5691 " gl_out[gl_InvocationID].gl_Position = gl_in[0].gl_Position;" NL " gl_TessLevelInner[0] = 1.0;" NL
5692 " gl_TessLevelInner[1] = 1.0;" NL " gl_TessLevelOuter[0] = 1.0;" NL " gl_TessLevelOuter[1] = 1.0;" NL
5693 " gl_TessLevelOuter[2] = 1.0;" NL " gl_TessLevelOuter[3] = 1.0;" NL " imageAtomicAdd(g_buffer, 0, 1);" NL
5694 " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}";
5695 const char* const glsl_tes =
5696 "#version 420 core" NL "layout(triangles, point_mode) in;" NL
5697 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5698 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5699 " imageAtomicAdd(g_buffer, 0, 1);" NL " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5700 " gl_Position = gl_in[0].gl_Position;" NL "}";
5701 const char* const glsl_gs =
5702 "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL
5703 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5704 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5705 " imageAtomicAdd(g_buffer, 0, 1);" NL " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5706 " gl_Position = gl_in[0].gl_Position;" NL " EmitVertex();" NL "}";
5707 const char* const glsl_fs =
5708 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
5709 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5710 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5711 " imageAtomicAdd(g_buffer, 0, 1);" NL " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5712 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
5713 m_program = BuildProgram(glsl_vs, glsl_tcs, glsl_tes, glsl_gs, glsl_fs);
5714 glUseProgram(m_program);
5715 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5716 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5717
5718 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
5719
5720 GLint i32 = 0;
5721 glGenBuffers(1, &m_buffer);
5722 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5723 glBufferData(GL_TEXTURE_BUFFER, 4, &i32, GL_STATIC_DRAW);
5724 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5725
5726 glGenTextures(1, &m_buffer_tex);
5727 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5728 glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, m_buffer);
5729 glBindTexture(GL_TEXTURE_BUFFER, 0);
5730
5731 GLuint ui32 = 0;
5732 glGenTextures(1, &m_texture);
5733 glBindTexture(GL_TEXTURE_2D, m_texture);
5734 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5735 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5736 glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 1, 1, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32);
5737 glBindTexture(GL_TEXTURE_2D, 0);
5738
5739 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
5740 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
5741
5742 glBindVertexArray(m_vao);
5743 glPatchParameteri(GL_PATCH_VERTICES, 1);
5744
5745 glDrawElementsInstancedBaseVertex(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1, 0);
5746 glDrawElementsInstanced(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1);
5747
5748 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5749 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5750 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, 4, &i32);
5751 if (i32 < 20 || i32 > 50)
5752 {
5753 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Buffer value is " << i32
5754 << " should be in the range [20;50]" << tcu::TestLog::EndMessage;
5755 return ERROR;
5756 }
5757
5758 glBindTexture(GL_TEXTURE_2D, m_texture);
5759 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32);
5760 if (ui32 < 40 || ui32 != static_cast<GLuint>(2 * i32))
5761 {
5762 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texture value is " << ui32 << " should be "
5763 << (2 * i32) << tcu::TestLog::EndMessage;
5764 return ERROR;
5765 }
5766
5767 return NO_ERROR;
5768 }
5769
Cleanup()5770 virtual long Cleanup()
5771 {
5772 glPatchParameteri(GL_PATCH_VERTICES, 3);
5773 glUseProgram(0);
5774 glDeleteBuffers(1, &m_buffer);
5775 glDeleteBuffers(1, &m_vbo);
5776 glDeleteBuffers(1, &m_ebo);
5777 glDeleteTextures(1, &m_buffer_tex);
5778 glDeleteTextures(1, &m_texture);
5779 glDeleteProgram(m_program);
5780 glDeleteVertexArrays(1, &m_vao);
5781 return NO_ERROR;
5782 }
5783 };
5784 //-----------------------------------------------------------------------------
5785 // 2.3.1 AdvancedMemoryDependentInvocation
5786 //-----------------------------------------------------------------------------
5787 class AdvancedMemoryDependentInvocation : public ShaderImageLoadStoreBase
5788 {
5789 GLuint m_buffer;
5790 GLuint m_buffer_tex;
5791 GLuint m_texture;
5792 GLuint m_program;
5793 GLuint m_vao;
5794 GLuint m_vbo;
5795
Setup()5796 virtual long Setup()
5797 {
5798 m_buffer = 0;
5799 m_buffer_tex = 0;
5800 m_texture = 0;
5801 m_program = 0;
5802 m_vao = 0;
5803 m_vbo = 0;
5804 return NO_ERROR;
5805 }
5806
Run()5807 virtual long Run()
5808 {
5809 if (!SupportedInVS(2))
5810 return NOT_SUPPORTED;
5811 const char* const glsl_vs =
5812 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5813 "layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL
5814 "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL
5815 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL " gl_Position = i_position;" NL
5816 " vs_color = i_color;" NL " imageStore(g_buffer, 0, vec4(1.0));" NL
5817 " imageStore(g_image, ivec2(0, 0), vec4(2.0));" NL " memoryBarrier();" NL "}";
5818 const char* const glsl_fs =
5819 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
5820 "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL
5821 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL " o_color = vs_color;" NL
5822 " if (imageLoad(g_buffer, 0) != vec4(1.0)) o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL
5823 " if (imageLoad(g_image, ivec2(0, 0)) != vec4(2.0)) o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "}";
5824 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
5825 glUseProgram(m_program);
5826 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5827 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5828
5829 vec4 zero(0);
5830 glGenBuffers(1, &m_buffer);
5831 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5832 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4), &zero, GL_STATIC_DRAW);
5833 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5834
5835 glGenTextures(1, &m_buffer_tex);
5836 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5837 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5838 glBindTexture(GL_TEXTURE_BUFFER, 0);
5839
5840 glGenTextures(1, &m_texture);
5841 glBindTexture(GL_TEXTURE_2D, m_texture);
5842 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5843 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, &zero);
5844 glBindTexture(GL_TEXTURE_2D, 0);
5845
5846 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5847 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5848
5849 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5850
5851 glClear(GL_COLOR_BUFFER_BIT);
5852 glBindVertexArray(m_vao);
5853 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5854
5855 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5856 {
5857 return ERROR;
5858 }
5859 return NO_ERROR;
5860 }
5861
Cleanup()5862 virtual long Cleanup()
5863 {
5864 glUseProgram(0);
5865 glDeleteBuffers(1, &m_vbo);
5866 glDeleteBuffers(1, &m_buffer);
5867 glDeleteTextures(1, &m_texture);
5868 glDeleteTextures(1, &m_buffer_tex);
5869 glDeleteProgram(m_program);
5870 glDeleteVertexArrays(1, &m_vao);
5871 return NO_ERROR;
5872 }
5873 };
5874 //-----------------------------------------------------------------------------
5875 // 2.3.2 AdvancedMemoryOrder
5876 //-----------------------------------------------------------------------------
5877 class AdvancedMemoryOrder : public ShaderImageLoadStoreBase
5878 {
5879 GLuint m_buffer;
5880 GLuint m_buffer_tex;
5881 GLuint m_texture;
5882 GLuint m_program;
5883 GLuint m_vao;
5884 GLuint m_vbo;
5885
Setup()5886 virtual long Setup()
5887 {
5888 m_buffer = 0;
5889 m_buffer_tex = 0;
5890 m_texture = 0;
5891 m_program = 0;
5892 m_vao = 0;
5893 m_vbo = 0;
5894 return NO_ERROR;
5895 }
5896
Run()5897 virtual long Run()
5898 {
5899 if (!SupportedInVS(1))
5900 return NOT_SUPPORTED;
5901 const char* const glsl_vs =
5902 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec4 vs_color;" NL
5903 "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL "void main() {" NL
5904 " gl_Position = i_position;" NL " vs_color = vec4(0, 1, 0, 1);" NL
5905 " imageStore(g_buffer, gl_VertexID, vec4(1.0));" NL " imageStore(g_buffer, gl_VertexID, vec4(2.0));" NL
5906 " imageStore(g_buffer, gl_VertexID, vec4(3.0));" NL
5907 " if (imageLoad(g_buffer, gl_VertexID) != vec4(3.0)) vs_color = vec4(1, 0, 0, 1);" NL "}";
5908 const char* const glsl_fs =
5909 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
5910 "layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL " o_color = vs_color;" NL
5911 " ivec2 coord = ivec2(gl_FragCoord);" NL " for (int i = 0; i < 3; ++i) {" NL
5912 " imageStore(g_image, coord, vec4(i));" NL " vec4 v = imageLoad(g_image, coord);" NL
5913 " if (v != vec4(i)) {" NL " o_color = vec4(v.xyz, 0.0);" NL " break;" NL " }" NL " }" NL
5914 "}";
5915 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
5916 glUseProgram(m_program);
5917 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5918 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5919
5920 glGenBuffers(1, &m_buffer);
5921 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5922 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW);
5923 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5924
5925 glGenTextures(1, &m_buffer_tex);
5926 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5927 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5928 glBindTexture(GL_TEXTURE_BUFFER, 0);
5929
5930 int width = getWindowWidth();
5931 int height = getWindowHeight();
5932 scaleDimensionsToMemory(width, height, 1, 2, 16, 16);
5933
5934 std::vector<vec4> data(width * height);
5935 glGenTextures(1, &m_texture);
5936 glBindTexture(GL_TEXTURE_2D, m_texture);
5937 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5938 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &data[0]);
5939 glBindTexture(GL_TEXTURE_2D, 0);
5940
5941 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5942 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5943
5944 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5945
5946 glClear(GL_COLOR_BUFFER_BIT);
5947 glViewport(0, 0, width, height);
5948 glBindVertexArray(m_vao);
5949 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5950
5951 if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
5952 {
5953 return ERROR;
5954 }
5955 return NO_ERROR;
5956 }
5957
Cleanup()5958 virtual long Cleanup()
5959 {
5960 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5961 glUseProgram(0);
5962 glDeleteBuffers(1, &m_vbo);
5963 glDeleteBuffers(1, &m_buffer);
5964 glDeleteTextures(1, &m_texture);
5965 glDeleteTextures(1, &m_buffer_tex);
5966 glDeleteProgram(m_program);
5967 glDeleteVertexArrays(1, &m_vao);
5968 return NO_ERROR;
5969 }
5970 };
5971 //-----------------------------------------------------------------------------
5972 // 2.4.1 AdvancedSSOSimple
5973 //-----------------------------------------------------------------------------
5974 class AdvancedSSOSimple : public ShaderImageLoadStoreBase
5975 {
5976 GLuint m_texture;
5977 GLuint m_pipeline[2];
5978 GLuint m_vsp, m_fsp0, m_fsp1;
5979 GLuint m_vao, m_vbo;
5980
Setup()5981 virtual long Setup()
5982 {
5983 glGenTextures(1, &m_texture);
5984 glGenProgramPipelines(2, m_pipeline);
5985 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5986
5987 const char* const glsl_vs =
5988 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL
5989 " vec4 gl_Position;" NL "};" NL "void main() {" NL " gl_Position = i_position;" NL "}";
5990 const char* const glsl_fs0 =
5991 "#version 420 core" NL "layout(rgba32f) uniform image2D g_image[4];" NL "void main() {" NL
5992 " for (int i = 0; i < g_image.length(); ++i) {" NL
5993 " imageStore(g_image[i], ivec2(gl_FragCoord), vec4(1.0));" NL " }" NL " discard;" NL "}";
5994 const char* const glsl_fs1 =
5995 "#version 420 core" NL "writeonly uniform image2D g_image[4];" NL "void main() {" NL
5996 " for (int i = 0; i < g_image.length(); ++i) {" NL
5997 " imageStore(g_image[i], ivec2(gl_FragCoord), vec4(2.0));" NL " }" NL " discard;" NL "}";
5998 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
5999 m_fsp0 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs0);
6000 m_fsp1 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs1);
6001
6002 return NO_ERROR;
6003 }
6004
Run()6005 virtual long Run()
6006 {
6007 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[0]"), 0);
6008 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[1]"), 2);
6009 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[2]"), 4);
6010 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[3]"), 6);
6011
6012 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[0]"), 1);
6013 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[1]"), 3);
6014 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[2]"), 5);
6015 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[3]"), 7);
6016
6017 glUseProgramStages(m_pipeline[0], GL_VERTEX_SHADER_BIT, m_vsp);
6018 glUseProgramStages(m_pipeline[0], GL_FRAGMENT_SHADER_BIT, m_fsp0);
6019
6020 glUseProgramStages(m_pipeline[1], GL_VERTEX_SHADER_BIT, m_vsp);
6021 glUseProgramStages(m_pipeline[1], GL_FRAGMENT_SHADER_BIT, m_fsp1);
6022
6023 int width = getWindowWidth();
6024 int height = getWindowHeight();
6025 scaleDimensionsToMemory(width, height, 8, 8, 16, 16);
6026
6027 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
6028 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6029 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, width, height, 8, 0, GL_RGBA, GL_FLOAT, NULL);
6030
6031 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6032 glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_RGBA32F);
6033 glBindImageTexture(2, m_texture, 0, GL_FALSE, 2, GL_READ_WRITE, GL_RGBA32F);
6034 glBindImageTexture(3, m_texture, 0, GL_FALSE, 3, GL_READ_WRITE, GL_RGBA32F);
6035 glBindImageTexture(4, m_texture, 0, GL_FALSE, 4, GL_READ_WRITE, GL_RGBA32F);
6036 glBindImageTexture(5, m_texture, 0, GL_FALSE, 5, GL_READ_WRITE, GL_RGBA32F);
6037 glBindImageTexture(6, m_texture, 0, GL_FALSE, 6, GL_READ_WRITE, GL_RGBA32F);
6038 glBindImageTexture(7, m_texture, 0, GL_FALSE, 7, GL_READ_WRITE, GL_RGBA32F);
6039
6040 glBindVertexArray(m_vao);
6041
6042 glViewport(0, 0, width, height);
6043 glBindProgramPipeline(m_pipeline[0]);
6044 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
6045
6046 glBindProgramPipeline(m_pipeline[1]);
6047 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6048
6049 std::vector<vec4> data(width * height * 8);
6050 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6051
6052 for (int layer = 0; layer < 8; ++layer)
6053 {
6054 for (int h = 0; h < height; ++h)
6055 {
6056 for (int w = 0; w < width; ++w)
6057 {
6058 const vec4 c = data[layer * width * height + h * width + w];
6059 if (layer % 2)
6060 {
6061 if (!IsEqual(c, vec4(2.0f)))
6062 {
6063 return ERROR;
6064 }
6065 }
6066 else
6067 {
6068 if (!IsEqual(c, vec4(1.0f)))
6069 {
6070 return ERROR;
6071 }
6072 }
6073 }
6074 }
6075 }
6076 return NO_ERROR;
6077 }
6078
Cleanup()6079 virtual long Cleanup()
6080 {
6081 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6082 glDeleteBuffers(1, &m_vbo);
6083 glDeleteTextures(1, &m_texture);
6084 glDeleteProgram(m_vsp);
6085 glDeleteProgram(m_fsp0);
6086 glDeleteProgram(m_fsp1);
6087 glDeleteVertexArrays(1, &m_vao);
6088 glDeleteProgramPipelines(2, m_pipeline);
6089 return NO_ERROR;
6090 }
6091 };
6092 //-----------------------------------------------------------------------------
6093 // 2.4.2 AdvancedSSOAtomicCounters
6094 //-----------------------------------------------------------------------------
6095 class AdvancedSSOAtomicCounters : public ShaderImageLoadStoreBase
6096 {
6097 GLuint m_buffer, m_buffer_tex;
6098 GLuint m_counter_buffer;
6099 GLuint m_transform_buffer;
6100 GLuint m_pipeline;
6101 GLuint m_vao, m_vbo;
6102 GLuint m_vsp, m_fsp;
6103
Setup()6104 virtual long Setup()
6105 {
6106 m_vao = 0;
6107 m_vbo = 0;
6108 m_vsp = 0;
6109 m_fsp = 0;
6110 glGenBuffers(1, &m_buffer);
6111 glGenTextures(1, &m_buffer_tex);
6112 glGenBuffers(1, &m_counter_buffer);
6113 glGenBuffers(1, &m_transform_buffer);
6114 glGenProgramPipelines(1, &m_pipeline);
6115 return NO_ERROR;
6116 }
6117
Run()6118 virtual long Run()
6119 {
6120 if (!SupportedInVS(1))
6121 return NOT_SUPPORTED;
6122
6123 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
6124 const char* const glsl_vs =
6125 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6126 "layout(location = 1) in vec4 i_color;" NL "layout(location = 3) out vec4 o_color;" NL
6127 "out gl_PerVertex {" NL " vec4 gl_Position;" NL "};" NL "layout(std140) uniform Transform {" NL
6128 " mat4 mvp;" NL "} g_transform;" NL "writeonly uniform imageBuffer g_buffer;" NL
6129 "layout(binding = 0, offset = 0) uniform atomic_uint g_counter;" NL "void main() {" NL
6130 " gl_Position = g_transform.mvp * i_position;" NL " o_color = i_color;" NL
6131 " const uint index = atomicCounterIncrement(g_counter);" NL
6132 " imageStore(g_buffer, int(index), gl_Position);" NL "}";
6133 const char* const glsl_fs =
6134 "#version 420 core" NL "layout(location = 3) in vec4 i_color;" NL
6135 "layout(location = 0) out vec4 o_color;" NL "void main() {" NL " o_color = i_color;" NL "}";
6136 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6137 m_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs);
6138
6139 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
6140 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_fsp);
6141
6142 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
6143 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW);
6144
6145 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
6146 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
6147
6148 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_counter_buffer);
6149 vec4 zero(0);
6150 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), &zero, GL_STATIC_DRAW);
6151
6152 glBindBuffer(GL_UNIFORM_BUFFER, m_transform_buffer);
6153 mat4 identity(1);
6154 glBufferData(GL_UNIFORM_BUFFER, sizeof(mat4), &identity, GL_STATIC_DRAW);
6155
6156 glClear(GL_COLOR_BUFFER_BIT);
6157 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_counter_buffer);
6158 glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_transform_buffer);
6159 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6160 glBindVertexArray(m_vao);
6161 glBindProgramPipeline(m_pipeline);
6162 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
6163
6164 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6165 {
6166 return ERROR;
6167 }
6168
6169 std::vector<vec4> data(4);
6170 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
6171 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(vec4) * 4, &data[0]);
6172
6173 for (int i = 0; i < 4; ++i)
6174 {
6175 if (!IsEqual(data[i], vec4(-1.0f, -1.0f, 0.0f, 1.0f)) && !IsEqual(data[i], vec4(1.0f, -1.0f, 0.0f, 1.0f)) &&
6176 !IsEqual(data[i], vec4(-1.0f, 1.0f, 0.0f, 1.0f)) && !IsEqual(data[i], vec4(1.0f, 1.0f, 0.0f, 1.0f)))
6177 {
6178 return ERROR;
6179 }
6180 }
6181
6182 return NO_ERROR;
6183 }
6184
Cleanup()6185 virtual long Cleanup()
6186 {
6187 glDeleteBuffers(1, &m_buffer);
6188 glDeleteBuffers(1, &m_vbo);
6189 glDeleteBuffers(1, &m_counter_buffer);
6190 glDeleteBuffers(1, &m_transform_buffer);
6191 glDeleteTextures(1, &m_buffer_tex);
6192 glDeleteProgram(m_vsp);
6193 glDeleteProgram(m_fsp);
6194 glDeleteVertexArrays(1, &m_vao);
6195 glDeleteProgramPipelines(1, &m_pipeline);
6196 return NO_ERROR;
6197 }
6198 };
6199 //-----------------------------------------------------------------------------
6200 // 2.4.3 AdvancedSSOSubroutine
6201 //-----------------------------------------------------------------------------
6202 class AdvancedSSOSubroutine : public ShaderImageLoadStoreBase
6203 {
6204 GLuint m_texture;
6205 GLuint m_attribless_vao;
6206 GLuint m_program;
6207 GLint m_draw_buffer;
6208
Setup()6209 virtual long Setup()
6210 {
6211 glGenTextures(1, &m_texture);
6212 glGenVertexArrays(1, &m_attribless_vao);
6213
6214 const char* const glsl_vs = "#version 420 core" NL "const int kSize = 3;" NL
6215 "const vec2 g_triangle[kSize] = vec2[3](vec2(-1, -1), vec2(3, -1), vec2(-1, 3));" NL
6216 "void main() {" NL " gl_Position = vec4(g_triangle[gl_VertexID], 0, 1);" NL "}";
6217 const char* const glsl_fs =
6218 "#version 420 core" NL "writeonly uniform image2DArray g_image0;" NL
6219 "writeonly uniform image2DArray g_image1;" NL "subroutine void Brush(ivec2 coord);" NL
6220 "subroutine uniform Brush g_brush;" NL "subroutine(Brush) void Brush0(ivec2 coord) {" NL
6221 " imageStore(g_image0, ivec3(coord, 0), vec4(1.0, 0.0, 0.0, 1.0));" NL
6222 " imageStore(g_image0, ivec3(coord, 1), vec4(0.0, 1.0, 0.0, 1.0));" NL
6223 " imageStore(g_image0, ivec3(coord, 2), vec4(0.0, 0.0, 1.0, 1.0));" NL "}" NL
6224 "subroutine(Brush) void Brush1(ivec2 coord) {" NL
6225 " imageStore(g_image1, ivec3(coord, 0), vec4(0.0, 1.0, 0.0, 1.0));" NL
6226 " imageStore(g_image1, ivec3(coord, 1), vec4(0.0, 0.0, 1.0, 1.0));" NL
6227 " imageStore(g_image1, ivec3(coord, 2), vec4(1.0, 0.0, 0.0, 1.0));" NL "}" NL "void main() {" NL
6228 " g_brush(ivec2(gl_FragCoord));" NL "}";
6229 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6230
6231 return NO_ERROR;
6232 }
6233
Run()6234 virtual long Run()
6235 {
6236 int width = getWindowWidth();
6237 int height = getWindowHeight();
6238 scaleDimensionsToMemory(width, height, 3, 3, 16, 16);
6239
6240 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image0"), 1);
6241 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image1"), 1);
6242
6243 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
6244 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6245 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, width, height, 3, 0, GL_RGBA, GL_FLOAT, NULL);
6246
6247 glGetIntegerv(GL_DRAW_BUFFER, &m_draw_buffer);
6248
6249 glDrawBuffer(GL_NONE);
6250 glBindImageTexture(1, m_texture, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32F);
6251 glUseProgram(m_program);
6252 glBindVertexArray(m_attribless_vao);
6253
6254 const GLuint indices[2] = { glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush0"),
6255 glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush1") };
6256
6257 glViewport(0, 0, width, height);
6258 glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[0]);
6259 glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
6260
6261 std::vector<vec4> data(width * height * 3);
6262 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6263 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6264
6265 for (int layer = 0; layer < 3; ++layer)
6266 {
6267 for (int h = 0; h < height; ++h)
6268 {
6269 for (int w = 0; w < width; ++w)
6270 {
6271 const vec4 c = data[layer * width * height + h * width + w];
6272 if (layer == 0 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f)))
6273 {
6274 m_context.getTestContext().getLog()
6275 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6276 << ") should be (1 0 0 1)" << tcu::TestLog::EndMessage;
6277 return ERROR;
6278 }
6279 else if (layer == 1 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f)))
6280 {
6281 m_context.getTestContext().getLog()
6282 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6283 << ") should be (0 1 0 1)" << tcu::TestLog::EndMessage;
6284 return ERROR;
6285 }
6286 else if (layer == 2 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f)))
6287 {
6288 m_context.getTestContext().getLog()
6289 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6290 << ") should be (0 0 1 1)" << tcu::TestLog::EndMessage;
6291 return ERROR;
6292 }
6293 }
6294 }
6295 }
6296
6297 glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[1]);
6298 glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
6299
6300 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6301 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6302
6303 for (int layer = 0; layer < 3; ++layer)
6304 {
6305 for (int h = 0; h < height; ++h)
6306 {
6307 for (int w = 0; w < width; ++w)
6308 {
6309 const vec4 c = data[layer * width * height + h * width + w];
6310 if (layer == 0 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f)))
6311 {
6312 m_context.getTestContext().getLog()
6313 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6314 << ") should be (0 1 0 1)" << tcu::TestLog::EndMessage;
6315 return ERROR;
6316 }
6317 else if (layer == 1 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f)))
6318 {
6319 m_context.getTestContext().getLog()
6320 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6321 << ") should be (0 0 1 1)" << tcu::TestLog::EndMessage;
6322 return ERROR;
6323 }
6324 else if (layer == 2 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f)))
6325 {
6326 m_context.getTestContext().getLog()
6327 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6328 << ") should be (1 0 0 1)" << tcu::TestLog::EndMessage;
6329 return ERROR;
6330 }
6331 }
6332 }
6333 }
6334 return NO_ERROR;
6335 }
6336
Cleanup()6337 virtual long Cleanup()
6338 {
6339 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6340 glDrawBuffer(m_draw_buffer);
6341 glDeleteTextures(1, &m_texture);
6342 glUseProgram(0);
6343 glDeleteProgram(m_program);
6344 glDeleteVertexArrays(1, &m_attribless_vao);
6345 return NO_ERROR;
6346 }
6347 };
6348 //-----------------------------------------------------------------------------
6349 // 2.4.4 AdvancedSSOPerSample
6350 //-----------------------------------------------------------------------------
6351 class AdvancedSSOPerSample : public ShaderImageLoadStoreBase
6352 {
6353 GLuint m_texture;
6354 GLuint m_pipeline;
6355 GLuint m_vao, m_vbo, m_ebo;
6356 GLuint m_vsp, m_store_fsp, m_load_fsp;
6357
Setup()6358 virtual long Setup()
6359 {
6360 m_vao = 0;
6361 m_vbo = 0;
6362 m_ebo = 0;
6363 m_vsp = 0;
6364 m_store_fsp = 0;
6365 m_load_fsp = 0;
6366 glGenTextures(1, &m_texture);
6367 glGenProgramPipelines(1, &m_pipeline);
6368
6369 return NO_ERROR;
6370 }
6371
Run()6372 virtual long Run()
6373 {
6374 if (!SupportedSamples(4))
6375 return NOT_SUPPORTED;
6376
6377 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6378
6379 const char* const glsl_vs =
6380 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL
6381 " vec4 gl_Position;" NL "};" NL "void main() {" NL " gl_Position = i_position;" NL "}";
6382 const char* const glsl_store_fs =
6383 "#version 420 core" NL "layout(rgba32f) writeonly uniform image2DMS g_image;" NL "void main() {" NL
6384 " imageStore(g_image, ivec2(gl_FragCoord), gl_SampleID, vec4(gl_SampleID+1));" NL "}";
6385 const char* const glsl_load_fs =
6386 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6387 "layout(rgba32f) readonly uniform image2DMS g_image;" NL "void main() {" NL
6388 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " if (imageLoad(g_image, ivec2(gl_FragCoord), gl_SampleID) != "
6389 "vec4(gl_SampleID+1)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
6390 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6391 m_store_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_store_fs);
6392 m_load_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_load_fs);
6393
6394 int width = getWindowWidth();
6395 int height = getWindowHeight();
6396 scaleDimensionsToMemory(width, height, 1, 1, /* bpp*samples */ 16 * 4, 16);
6397
6398 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texture);
6399 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA32F, width, height, GL_FALSE);
6400 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
6401
6402 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
6403 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_store_fsp);
6404
6405 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6406
6407 glClear(GL_COLOR_BUFFER_BIT);
6408 glViewport(0, 0, width, height);
6409 glBindVertexArray(m_vao);
6410 glBindProgramPipeline(m_pipeline);
6411 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6412
6413 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
6414
6415 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_load_fsp);
6416 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6417
6418 if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
6419 {
6420 return ERROR;
6421 }
6422 return NO_ERROR;
6423 }
6424
Cleanup()6425 virtual long Cleanup()
6426 {
6427 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6428 glDeleteBuffers(1, &m_vbo);
6429 glDeleteBuffers(1, &m_ebo);
6430 glDeleteTextures(1, &m_texture);
6431 glDeleteProgram(m_vsp);
6432 glDeleteProgram(m_store_fsp);
6433 glDeleteProgram(m_load_fsp);
6434 glDeleteVertexArrays(1, &m_vao);
6435 glDeleteProgramPipelines(1, &m_pipeline);
6436 return NO_ERROR;
6437 }
6438 };
6439
6440 //-----------------------------------------------------------------------------
6441 // 2.5 AdvancedCopyImage
6442 //-----------------------------------------------------------------------------
6443 class AdvancedCopyImage : public ShaderImageLoadStoreBase
6444 {
6445 GLuint m_texture[2];
6446 GLuint m_program;
6447 GLuint m_vao, m_vbo, m_ebo;
6448
Setup()6449 virtual long Setup()
6450 {
6451 glGenTextures(2, m_texture);
6452 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6453
6454 const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6455 "void main() {" NL " gl_Position = i_position;" NL "}";
6456 const char* const glsl_fs =
6457 "#version 420 core" NL "layout(rgba32f) readonly uniform image2D g_input_image;" NL
6458 "layout(rgba32f) writeonly uniform image2D g_output_image;" NL "void main() {" NL
6459 " ivec2 coord = ivec2(gl_FragCoord);" NL
6460 " imageStore(g_output_image, coord, imageLoad(g_input_image, coord));" NL " discard;" NL "}";
6461 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6462
6463 return NO_ERROR;
6464 }
6465
Run()6466 virtual long Run()
6467 {
6468 int width = getWindowWidth();
6469 int height = getWindowHeight();
6470 scaleDimensionsToMemory(width, height, 2, 2, 16, 16);
6471
6472 glUseProgram(m_program);
6473 glUniform1i(glGetUniformLocation(m_program, "g_input_image"), 0);
6474 glUniform1i(glGetUniformLocation(m_program, "g_output_image"), 1);
6475
6476 std::vector<vec4> data(width * height, vec4(7.0f));
6477 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6478 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6479 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &data[0]);
6480
6481 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6482 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6483 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
6484
6485 glBindTexture(GL_TEXTURE_2D, 0);
6486
6487 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
6488 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
6489
6490 glClear(GL_COLOR_BUFFER_BIT);
6491 glViewport(0, 0, width, height);
6492 glBindVertexArray(m_vao);
6493 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6494
6495 std::vector<vec4> rdata(width * height);
6496 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6497 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &rdata[0]);
6498
6499 for (int h = 0; h < height; ++h)
6500 {
6501 for (int w = 0; w < width; ++w)
6502 {
6503 if (!IsEqual(rdata[h * width + w], vec4(7.0f)))
6504 {
6505 return ERROR;
6506 }
6507 }
6508 }
6509 return NO_ERROR;
6510 }
6511
Cleanup()6512 virtual long Cleanup()
6513 {
6514 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6515 glUseProgram(0);
6516 glDeleteBuffers(1, &m_vbo);
6517 glDeleteBuffers(1, &m_ebo);
6518 glDeleteTextures(2, m_texture);
6519 glDeleteProgram(m_program);
6520 glDeleteVertexArrays(1, &m_vao);
6521 return NO_ERROR;
6522 }
6523 };
6524 //-----------------------------------------------------------------------------
6525 // 2.6 AdvancedAllMips
6526 //-----------------------------------------------------------------------------
6527 class AdvancedAllMips : public ShaderImageLoadStoreBase
6528 {
6529 GLuint m_texture;
6530 GLuint m_store_program, m_load_program;
6531 GLuint m_vao, m_vbo, m_ebo;
6532
Setup()6533 virtual long Setup()
6534 {
6535 glGenTextures(1, &m_texture);
6536 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6537
6538 const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6539 "void main() {" NL " gl_Position = i_position;" NL "}";
6540 const char* const glsl_store_fs =
6541 "#version 420 core" NL "layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL
6542 " for (int i = 0; i < 6; ++i) {" NL " imageStore(g_image[i], ivec2(gl_FragCoord), vec4(i));" NL " }" NL
6543 " discard;" NL "}";
6544 const char* const glsl_load_fs =
6545 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6546 "layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL
6547 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " for (int i = 0; i < 6; ++i) {" NL
6548 " const ivec2 coord = ivec2(gl_FragCoord);" NL " const vec4 c = imageLoad(g_image[i], coord);" NL
6549 " if (c != vec4(i) && c != vec4(0.0)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL " }" NL "}";
6550 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
6551 m_load_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_load_fs);
6552
6553 return NO_ERROR;
6554 }
6555
Run()6556 virtual long Run()
6557 {
6558 glUseProgram(m_store_program);
6559 glUniform1i(glGetUniformLocation(m_store_program, "g_image[0]"), 0);
6560 glUniform1i(glGetUniformLocation(m_store_program, "g_image[1]"), 1);
6561 glUniform1i(glGetUniformLocation(m_store_program, "g_image[2]"), 2);
6562 glUniform1i(glGetUniformLocation(m_store_program, "g_image[3]"), 3);
6563 glUniform1i(glGetUniformLocation(m_store_program, "g_image[4]"), 4);
6564 glUniform1i(glGetUniformLocation(m_store_program, "g_image[5]"), 5);
6565 glUseProgram(0);
6566
6567 glUseProgram(m_load_program);
6568 glUniform1i(glGetUniformLocation(m_load_program, "g_image[0]"), 0);
6569 glUniform1i(glGetUniformLocation(m_load_program, "g_image[1]"), 1);
6570 glUniform1i(glGetUniformLocation(m_load_program, "g_image[2]"), 2);
6571 glUniform1i(glGetUniformLocation(m_load_program, "g_image[3]"), 3);
6572 glUniform1i(glGetUniformLocation(m_load_program, "g_image[4]"), 4);
6573 glUniform1i(glGetUniformLocation(m_load_program, "g_image[5]"), 5);
6574 glUseProgram(0);
6575
6576 glBindTexture(GL_TEXTURE_2D, m_texture);
6577 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 32, 32, 0, GL_RGBA, GL_FLOAT, NULL);
6578 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
6579 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA32F, 8, 8, 0, GL_RGBA, GL_FLOAT, NULL);
6580 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA32F, 4, 4, 0, GL_RGBA, GL_FLOAT, NULL);
6581 glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA32F, 2, 2, 0, GL_RGBA, GL_FLOAT, NULL);
6582 glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, NULL);
6583 glBindTexture(GL_TEXTURE_2D, 0);
6584
6585 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6586 glBindImageTexture(1, m_texture, 1, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6587 glBindImageTexture(2, m_texture, 2, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6588 glBindImageTexture(3, m_texture, 3, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6589 glBindImageTexture(4, m_texture, 4, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6590 glBindImageTexture(5, m_texture, 5, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6591
6592 glViewport(0, 0, 32, 32);
6593 glBindVertexArray(m_vao);
6594
6595 glClear(GL_COLOR_BUFFER_BIT);
6596 glUseProgram(m_store_program);
6597 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6598
6599 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
6600
6601 glUseProgram(m_load_program);
6602 glDrawElementsInstancedBaseVertex(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6603
6604 if (!ValidateReadBuffer(0, 0, 32, 32, vec4(0, 1, 0, 1)))
6605 {
6606 return ERROR;
6607 }
6608 return NO_ERROR;
6609 }
6610
Cleanup()6611 virtual long Cleanup()
6612 {
6613 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6614 glUseProgram(0);
6615 glDeleteBuffers(1, &m_vbo);
6616 glDeleteBuffers(1, &m_ebo);
6617 glDeleteTextures(1, &m_texture);
6618 glDeleteProgram(m_store_program);
6619 glDeleteProgram(m_load_program);
6620 glDeleteVertexArrays(1, &m_vao);
6621 return NO_ERROR;
6622 }
6623 };
6624 //-----------------------------------------------------------------------------
6625 // 2.7 AdvancedCast
6626 //-----------------------------------------------------------------------------
6627 class AdvancedCast : public ShaderImageLoadStoreBase
6628 {
6629 GLuint m_texture[2];
6630 GLuint m_program;
6631 GLuint m_vao, m_vbo, m_ebo;
6632
Setup()6633 virtual long Setup()
6634 {
6635 glGenTextures(2, m_texture);
6636 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6637
6638 const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6639 "void main() {" NL " gl_Position = i_position;" NL "}";
6640 const char* const glsl_fs =
6641 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6642 "layout(r32i) coherent uniform iimage2D g_image0;" NL "layout(r32ui) coherent uniform uimage2D g_image1;" NL
6643 "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " ivec2 coord = ivec2(gl_FragCoord);" NL
6644 " if (imageAtomicAdd(g_image0, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6645 " if (imageAtomicAdd(g_image0, coord, -1) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6646 " if (imageAtomicAdd(g_image1, coord, 1) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6647 " if (imageAtomicAdd(g_image1, coord, 2) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
6648 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6649
6650 return NO_ERROR;
6651 }
6652
Run()6653 virtual long Run()
6654 {
6655 glUseProgram(m_program);
6656 glUniform1i(glGetUniformLocation(m_program, "g_image0"), 0);
6657 glUniform1i(glGetUniformLocation(m_program, "g_image1"), 1);
6658
6659 {
6660 std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4);
6661 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6662 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6663 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
6664 &data[0]);
6665
6666 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6667 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6668 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
6669 &data[0]);
6670
6671 glBindTexture(GL_TEXTURE_2D, 0);
6672 }
6673
6674 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
6675 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
6676
6677 glClear(GL_COLOR_BUFFER_BIT);
6678 glBindVertexArray(m_vao);
6679 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6680
6681 std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4);
6682 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6683 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6684 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
6685
6686 for (int h = 0; h < getWindowHeight(); ++h)
6687 {
6688 for (int w = 0; w < getWindowWidth(); ++w)
6689 {
6690 const GLubyte c[4] = {
6691 data[h * (getWindowWidth() * 4) + w * 4 + 0], data[h * (getWindowWidth() * 4) + w * 4 + 1],
6692 data[h * (getWindowWidth() * 4) + w * 4 + 2], data[h * (getWindowWidth() * 4) + w * 4 + 3],
6693 };
6694 if (c[0] != 1 || c[1] != 0 || c[2] != 0 || c[3] != 0)
6695 {
6696 m_context.getTestContext().getLog()
6697 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6698 << ") should be (1 0 0 0)" << tcu::TestLog::EndMessage;
6699 return ERROR;
6700 }
6701 }
6702 }
6703
6704 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6705 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
6706
6707 for (int h = 0; h < getWindowHeight(); ++h)
6708 {
6709 for (int w = 0; w < getWindowWidth(); ++w)
6710 {
6711 const GLubyte c[4] = {
6712 data[h * (getWindowWidth() * 4) + w * 4 + 0], data[h * (getWindowWidth() * 4) + w * 4 + 1],
6713 data[h * (getWindowWidth() * 4) + w * 4 + 2], data[h * (getWindowWidth() * 4) + w * 4 + 3],
6714 };
6715 if (c[0] != 3 || c[1] != 0 || c[2] != 0 || c[3] != 0)
6716 {
6717 m_context.getTestContext().getLog()
6718 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6719 << ") should be (3 0 0 0)" << tcu::TestLog::EndMessage;
6720 return ERROR;
6721 }
6722 }
6723 }
6724
6725 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6726 {
6727 return ERROR;
6728 }
6729 return NO_ERROR;
6730 }
6731
Cleanup()6732 virtual long Cleanup()
6733 {
6734 glUseProgram(0);
6735 glDeleteBuffers(1, &m_vbo);
6736 glDeleteBuffers(1, &m_ebo);
6737 glDeleteTextures(2, m_texture);
6738 glDeleteProgram(m_program);
6739 glDeleteVertexArrays(1, &m_vao);
6740 return NO_ERROR;
6741 }
6742 };
6743
6744 /** Test "imageLoad() and imageStore() for single-byte data alignment" description follows.
6745 *
6746 * Steps:
6747 * - create two textures: "source" and "destination". Fill "source"
6748 * texture with unique values. Fill "destination" texture with zeros,
6749 * - prepare a program object that will read texel from "source" image at given
6750 * coordinates and write its value to "destination" image at same
6751 * coordinates,
6752 * - bind "source" and "destination" textures as "source" and "destination"
6753 * image uniforms,
6754 * - render "full screen" quad (left bottom corner at -1,-1 and right top
6755 * corner at 1,1),
6756 * - verify that texel values in "destination" texture match those in
6757 * "source" texture (use glGetTexImage).
6758 *
6759 * Test with 2D R8UI textures with following dimensions:
6760 * - 16x16,
6761 * - 16x17,
6762 * - 17x16,
6763 * - 17x17,
6764 * - 16x18,
6765 * - 18x16,
6766 * - 18x18,
6767 * - 19x16,
6768 * - 16x19,
6769 * - 19x19.
6770 *
6771 * Note that default data alignment should cause problems with packing/
6772 * /unpacking. Therefore GL_PACK_ALIGNMENT and GL_UNPACK_ALIGNMENT parameters
6773 * of pixel storage mode have to be changed to one byte alignment.
6774 *
6775 * Program should consist of vertex and fragment shader. Vertex shader should
6776 * pass vertex position through. Fragment shader should do imageLoad() and
6777 * imageStore() operations at coordinates gl_FragCoord.
6778 **/
6779 class ImageLoadStoreDataAlignmentTest : public ShaderImageLoadStoreBase
6780 {
6781 private:
6782 /* Structures */
6783 struct TextureDimensions
6784 {
6785 GLuint m_width;
6786 GLuint m_height;
6787
TextureDimensionsgl4cts::__anonb14d91fe0111::ImageLoadStoreDataAlignmentTest::TextureDimensions6788 TextureDimensions(GLuint width, GLuint height) : m_width(width), m_height(height)
6789 {
6790 }
6791 };
6792
6793 /* Typedefs */
6794 typedef std::deque<TextureDimensions> TextureDimensionsList;
6795
6796 /* Fields */
6797 GLuint m_destination_texture_id;
6798 GLuint m_program_id;
6799 TextureDimensionsList m_texture_dimensions;
6800 GLuint m_source_texture_id;
6801 GLuint m_vertex_array_object_id;
6802 GLuint m_vertex_buffer_id;
6803
6804 public:
6805 /* Constructor */
ImageLoadStoreDataAlignmentTest()6806 ImageLoadStoreDataAlignmentTest()
6807 : m_destination_texture_id(0)
6808 , m_program_id(0)
6809 , m_source_texture_id(0)
6810 , m_vertex_array_object_id(0)
6811 , m_vertex_buffer_id(0)
6812 {
6813 /* Nothing to be done here */
6814 }
6815
6816 /* Methods inherited from SubcaseBase */
Setup()6817 virtual long Setup()
6818 {
6819 /* Shaders code */
6820 const char* const vertex_shader_code = "#version 400 core\n"
6821 "#extension GL_ARB_shader_image_load_store : require\n"
6822 "\n"
6823 "precision highp float;\n"
6824 "\n"
6825 "in vec4 vs_in_position;\n"
6826 "\n"
6827 "void main()\n"
6828 "{\n"
6829 " gl_Position = vs_in_position;\n"
6830 "}\n";
6831
6832 const char* const fragment_shader_code =
6833 "#version 400 core\n"
6834 "#extension GL_ARB_shader_image_load_store : require\n"
6835 "\n"
6836 "precision highp float;\n"
6837 "\n"
6838 "layout(r8ui) writeonly uniform uimage2D u_destination_image;\n"
6839 "layout(r8ui) readonly uniform uimage2D u_source_image;\n"
6840 "\n"
6841 "void main()\n"
6842 "{\n"
6843 " uvec4 loaded_color = imageLoad (u_source_image, ivec2(gl_FragCoord));\n"
6844 " imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n"
6845 "\n"
6846 " discard;\n"
6847 "}\n";
6848
6849 /* Vertex postions for "full screen" quad, made with triangle strip */
6850 static const GLfloat m_vertex_buffer_data[] = {
6851 -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
6852 -1.0f, 1.0f, 0.0f, 1.0f, /* left top */
6853 1.0f, -1.0f, 0.0f, 1.0f, /* right bottom */
6854 1.0f, 1.0f, 0.0f, 1.0f, /* right top */
6855 };
6856
6857 /* Result of BuildProgram operation */
6858 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
6859
6860 /* Add all tested texture dimensions */
6861 m_texture_dimensions.push_back(TextureDimensions(16, 16));
6862 m_texture_dimensions.push_back(TextureDimensions(16, 17));
6863 m_texture_dimensions.push_back(TextureDimensions(17, 16));
6864 m_texture_dimensions.push_back(TextureDimensions(17, 17));
6865 m_texture_dimensions.push_back(TextureDimensions(16, 18));
6866 m_texture_dimensions.push_back(TextureDimensions(18, 16));
6867 m_texture_dimensions.push_back(TextureDimensions(18, 18));
6868 m_texture_dimensions.push_back(TextureDimensions(16, 19));
6869 m_texture_dimensions.push_back(TextureDimensions(19, 16));
6870 m_texture_dimensions.push_back(TextureDimensions(19, 19));
6871
6872 /* Clean previous error */
6873 glGetError();
6874
6875 /* Set single-byte data alignment */
6876 glPixelStorei(GL_PACK_ALIGNMENT, 1);
6877 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
6878 GLU_EXPECT_NO_ERROR(glGetError(), "PixelStorei");
6879
6880 /* Prepare buffer with vertex positions of "full screen" quad" */
6881 glGenBuffers(1, &m_vertex_buffer_id);
6882 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
6883
6884 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
6885 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
6886
6887 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
6888 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
6889
6890 /* Generate vertex array object */
6891 glGenVertexArrays(1, &m_vertex_array_object_id);
6892 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
6893
6894 /* Prepare program object */
6895 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */,
6896 fragment_shader_code, &is_program_correct);
6897 if (false == is_program_correct)
6898 {
6899 return ERROR;
6900 }
6901
6902 /* Done */
6903 return NO_ERROR;
6904 }
6905
Cleanup()6906 virtual long Cleanup()
6907 {
6908 /* Reset OpenGL state */
6909 glBindBuffer(GL_ARRAY_BUFFER, 0);
6910 glBindTexture(GL_TEXTURE_2D, 0);
6911 glBindVertexArray(0);
6912 glUseProgram(0);
6913
6914 /* Delete program */
6915 if (0 != m_program_id)
6916 {
6917 glDeleteProgram(m_program_id);
6918 m_program_id = 0;
6919 }
6920
6921 /* Delete textures */
6922 if (0 != m_destination_texture_id)
6923 {
6924 glDeleteTextures(1, &m_destination_texture_id);
6925 m_destination_texture_id = 0;
6926 }
6927
6928 if (0 != m_source_texture_id)
6929 {
6930 glDeleteTextures(1, &m_source_texture_id);
6931 m_source_texture_id = 0;
6932 }
6933
6934 /* Delete vertex array object */
6935 if (0 != m_vertex_array_object_id)
6936 {
6937 glDeleteVertexArrays(1, &m_vertex_array_object_id);
6938 m_vertex_array_object_id = 0;
6939 }
6940
6941 /* Delete buffer */
6942 if (0 != m_vertex_buffer_id)
6943 {
6944 glDeleteBuffers(1, &m_vertex_buffer_id);
6945 m_vertex_buffer_id = 0;
6946 }
6947
6948 /* Done */
6949 return NO_ERROR;
6950 }
6951
Run()6952 virtual long Run()
6953 {
6954 bool result = true;
6955
6956 /* For each dimension */
6957 for (TextureDimensionsList::const_iterator it = m_texture_dimensions.begin(); m_texture_dimensions.end() != it;
6958 ++it)
6959 {
6960 /* Prepare "source" and "destination" textures */
6961 GLU_EXPECT_NO_ERROR(Create2DR8UIDestinationTexture(it->m_width, it->m_height, m_destination_texture_id),
6962 "Create2DR8UIDestinationTexture");
6963 GLU_EXPECT_NO_ERROR(Create2DR8UISourceTexture(it->m_width, it->m_height, m_source_texture_id),
6964 "Create2DR8UISourceTexture");
6965
6966 /* Copy texture data with imageLoad() and imageStore() operations */
6967 Copy2DR8UITexture(m_destination_texture_id, m_source_texture_id);
6968
6969 /* Compare "source" and "destination" textures */
6970 if (false ==
6971 Compare2DR8UITextures(m_destination_texture_id, m_source_texture_id, it->m_width, it->m_height))
6972 {
6973 m_context.getTestContext().getLog()
6974 << tcu::TestLog::Message
6975 << "Copy with imageLoad and imageStore failed for textures: " << it->m_width << "x" << it->m_height
6976 << ". Source and destination textures are different" << tcu::TestLog::EndMessage;
6977
6978 result = false;
6979 }
6980
6981 /* Destroy "source" and "destination" textures */
6982 glDeleteTextures(1, &m_destination_texture_id);
6983 glDeleteTextures(1, &m_source_texture_id);
6984
6985 m_destination_texture_id = 0;
6986 m_source_texture_id = 0;
6987 }
6988
6989 if (false == result)
6990 {
6991 return ERROR;
6992 }
6993
6994 /* Done */
6995 return NO_ERROR;
6996 }
6997
6998 private:
6999 /* Private methods */
7000
7001 /** Binds a texture to user-specified image unit and updates relevant sampler uniform
7002 *
7003 * @param program_id Program object id
7004 * @param texture_id Texture id
7005 * @param image_unit Index of image unit
7006 * @param uniform_name Name of image uniform
7007 **/
BindTextureToImage(GLuint program_id,GLuint texture_id,GLuint image_unit,const char * uniform_name)7008 void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, const char* uniform_name)
7009 {
7010 /* Uniform location and invalid value */
7011 static const GLint invalid_uniform_location = -1;
7012 GLint image_uniform_location = 0;
7013
7014 /* Get uniform location */
7015 image_uniform_location = glGetUniformLocation(program_id, uniform_name);
7016 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
7017 if (invalid_uniform_location == image_uniform_location)
7018 {
7019 throw tcu::InternalError("A required uniform is considered inactive", uniform_name, __FILE__, __LINE__);
7020 }
7021
7022 /* Bind texture to image unit */
7023 glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_R8UI);
7024 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
7025
7026 /* Set uniform to image unit */
7027 glUniform1i(image_uniform_location, image_unit);
7028 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
7029 }
7030
7031 /** Compare two 2D R8UI textures
7032 *
7033 * @param left_texture_id Id of "left" texture object
7034 * @param right_texture_id Id of "right" texture object
7035 * @param width Width of the textures
7036 * @param height Height of the textures
7037 *
7038 * @return true when texture data is identical, false otherwise
7039 **/
Compare2DR8UITextures(GLuint left_texture_id,GLuint right_texture_id,GLuint width,GLuint height)7040 bool Compare2DR8UITextures(GLuint left_texture_id, GLuint right_texture_id, GLuint width, GLuint height)
7041 {
7042 /* Size of textures */
7043 const GLuint texture_data_size = width * height;
7044
7045 /* Storage for texture data */
7046 std::vector<GLubyte> left_texture_data;
7047 std::vector<GLubyte> right_texture_data;
7048
7049 /* Alocate memory for texture data */
7050 left_texture_data.resize(texture_data_size);
7051 right_texture_data.resize(texture_data_size);
7052
7053 /* Get "left" texture data */
7054 glBindTexture(GL_TEXTURE_2D, left_texture_id);
7055 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7056
7057 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &left_texture_data[0]);
7058 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7059
7060 /* Get "right" texture data */
7061 glBindTexture(GL_TEXTURE_2D, right_texture_id);
7062 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7063
7064 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &right_texture_data[0]);
7065 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7066
7067 /* Compare texels */
7068 return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size));
7069 }
7070
7071 /** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations
7072 *
7073 * @param destination_texture_id Id of "destination" texture object
7074 * @param source_texture_id Id of "source" texture object
7075 **/
Copy2DR8UITexture(GLuint destination_texture_id,GLuint source_texture_id)7076 void Copy2DR8UITexture(GLuint destination_texture_id, GLuint source_texture_id)
7077 {
7078 /* Uniform names */
7079 static const char* const destination_image_uniform_name = "u_destination_image";
7080 static const char* const source_image_uniform_name = "u_source_image";
7081
7082 /* Attribute name */
7083 static const char* const position_attribute_name = "vs_in_position";
7084
7085 /* Attribute location and invalid value */
7086 static const GLint invalid_attribute_location = -1;
7087 GLint position_attribute_location = 0;
7088
7089 /* Set current program */
7090 glUseProgram(m_program_id);
7091 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
7092
7093 /* Bind vertex array object */
7094 glBindVertexArray(m_vertex_array_object_id);
7095 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
7096
7097 /* Bind buffer with quad vertex positions */
7098 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7099 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7100
7101 /* Set up position attribute */
7102 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
7103 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
7104 if (invalid_attribute_location == position_attribute_location)
7105 {
7106 throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
7107 __LINE__);
7108 }
7109
7110 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */,
7111 0 /* stride */, 0);
7112 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
7113
7114 glEnableVertexAttribArray(position_attribute_location);
7115 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
7116
7117 /* Set up textures as source and destination images */
7118 BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, destination_image_uniform_name);
7119 BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, source_image_uniform_name);
7120
7121 /* Execute draw */
7122 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
7123 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
7124 }
7125
7126 /** Create 2D R8UI texture and fills it with zeros
7127 *
7128 * @param width Width of created texture
7129 * @param height Height of created texture
7130 * @param out_texture_id Id of created texture, not modified if operation fails
7131 *
7132 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7133 **/
Create2DR8UIDestinationTexture(GLuint width,GLuint height,GLuint & out_texture_id)7134 GLenum Create2DR8UIDestinationTexture(GLuint width, GLuint height, GLuint& out_texture_id)
7135 {
7136 /* Texture size */
7137 const GLuint texture_size = width * height;
7138
7139 /* Prepare storage for texture data */
7140 std::vector<GLubyte> texture_data;
7141 texture_data.resize(texture_size);
7142
7143 /* Set all texels */
7144 for (GLuint i = 0; i < texture_size; ++i)
7145 {
7146 texture_data[i] = 0;
7147 }
7148
7149 /* Create texture */
7150 return Create2DR8UITexture(width, height, texture_data, out_texture_id);
7151 }
7152
7153 /** Create 2D R8UI texture and fills it with increasing values, starting from 0
7154 *
7155 * @param width Width of created texture
7156 * @param height Height of created texture
7157 * @param out_texture_id Id of created texture, not modified if operation fails
7158 *
7159 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7160 **/
Create2DR8UISourceTexture(GLuint width,GLuint height,GLuint & out_texture_id)7161 GLenum Create2DR8UISourceTexture(GLuint width, GLuint height, GLuint& out_texture_id)
7162 {
7163 /* Texture size */
7164 const GLuint texture_size = width * height;
7165
7166 /* Value of texel */
7167 GLubyte texel_value = 0;
7168
7169 /* Prepare storage for texture data */
7170 std::vector<GLubyte> texture_data;
7171 texture_data.resize(texture_size);
7172
7173 /* Set all texels */
7174 for (GLuint i = 0; i < texture_size; ++i)
7175 {
7176 texture_data[i] = texel_value++;
7177 }
7178
7179 /* Create texture */
7180 return Create2DR8UITexture(width, height, texture_data, out_texture_id);
7181 }
7182
7183 /** Create 2D R8UI texture and fills it with user-provided data
7184 *
7185 * @param width Width of created texture
7186 * @param height Height of created texture
7187 * @param texture_data Texture data
7188 * @param out_texture_id Id of created texture, not modified if operation fails
7189 *
7190 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7191 **/
Create2DR8UITexture(GLuint width,GLuint height,const std::vector<GLubyte> & texture_data,GLuint & out_texture_id)7192 GLenum Create2DR8UITexture(GLuint width, GLuint height, const std::vector<GLubyte>& texture_data,
7193 GLuint& out_texture_id)
7194 {
7195 GLenum err = 0;
7196 GLuint texture_id = 0;
7197
7198 /* Generate texture */
7199 glGenTextures(1, &texture_id);
7200 err = glGetError();
7201 if (GL_NO_ERROR != err)
7202 {
7203 return err;
7204 }
7205
7206 /* Bind texture */
7207 glBindTexture(GL_TEXTURE_2D, texture_id);
7208 err = glGetError();
7209 if (GL_NO_ERROR != err)
7210 {
7211 glDeleteTextures(1, &texture_id);
7212 return err;
7213 }
7214
7215 /* Allocate storage and fill texture */
7216 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R8UI, width, height, 0 /* border */, GL_RED_INTEGER,
7217 GL_UNSIGNED_BYTE, &texture_data[0]);
7218 err = glGetError();
7219 if (GL_NO_ERROR != err)
7220 {
7221 glDeleteTextures(1, &texture_id);
7222 return err;
7223 }
7224
7225 /* Make texture complete */
7226 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
7227 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
7228 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7229 err = glGetError();
7230 if (GL_NO_ERROR != err)
7231 {
7232 glDeleteTextures(1, &texture_id);
7233 return err;
7234 }
7235
7236 /* Set out_texture_id */
7237 out_texture_id = texture_id;
7238
7239 /* Done */
7240 return GL_NO_ERROR;
7241 }
7242 };
7243
7244 /** Test "imageLoad() and imageStore() for non-layered image bindings" description follows.
7245 *
7246 * Steps: same as in test 1 (ImageLoadStoreDataAlignmentTest).
7247 *
7248 * Test non-layered image bindings (BindImageTexture <layered>: false) with:
7249 * | Type | Dimensions |
7250 * | 2D_ARRAY | 64x64x6 |
7251 * | 3D | 64x64x6 |
7252 * | CUBE_MAP | 64 |
7253 * | CUBE_MAP_ARRAY | 64x3 |
7254 *
7255 * Use RGBA8 format. All layers shall be tested.
7256 *
7257 * Program should consist of vertex and fragment shader. Vertex shader should
7258 * pass vertex position through. Fragment shader should do imageLoad() and
7259 * imageStore() operations at coordinates gl_FragCoord. Fragment shader should
7260 * use image2D as image type.
7261 **/
7262 class ImageLoadStoreNonLayeredBindingTest : public ShaderImageLoadStoreBase
7263 {
7264 private:
7265 /* Structures */
7266 struct TextureShapeDefinition
7267 {
7268 GLuint m_edge;
7269 GLuint m_n_elements;
7270 GLenum m_type;
7271
TextureShapeDefinitiongl4cts::__anonb14d91fe0111::ImageLoadStoreNonLayeredBindingTest::TextureShapeDefinition7272 TextureShapeDefinition(GLuint edge, GLuint n_elements, GLenum type)
7273 : m_edge(edge), m_n_elements(n_elements), m_type(type)
7274 {
7275 }
7276 };
7277
7278 /* Typedefs */
7279 typedef std::deque<TextureShapeDefinition> TextureShapeDefinitionList;
7280
7281 /* Fields */
7282 GLuint m_destination_texture_id;
7283 GLuint m_program_id;
7284 TextureShapeDefinitionList m_texture_shape_definitions;
7285 GLuint m_source_texture_id;
7286 GLuint m_vertex_array_object_id;
7287 GLuint m_vertex_buffer_id;
7288
7289 public:
7290 /* Constructor */
ImageLoadStoreNonLayeredBindingTest()7291 ImageLoadStoreNonLayeredBindingTest()
7292 : m_destination_texture_id(0)
7293 , m_program_id(0)
7294 , m_source_texture_id(0)
7295 , m_vertex_array_object_id(0)
7296 , m_vertex_buffer_id(0)
7297 {
7298 /* Nothing to be done here */
7299 }
7300
7301 /* Methods inherited from SubcaseBase */
Setup()7302 virtual long Setup()
7303 {
7304 /* Shaders code */
7305 const char* const vertex_shader_code = "#version 400 core\n"
7306 "#extension GL_ARB_shader_image_load_store : require\n"
7307 "\n"
7308 "precision highp float;\n"
7309 "\n"
7310 "in vec4 vs_in_position;\n"
7311 "\n"
7312 "void main()\n"
7313 "{\n"
7314 " gl_Position = vs_in_position;\n"
7315 "}\n";
7316
7317 const char* const fragment_shader_code =
7318 "#version 400 core\n"
7319 "#extension GL_ARB_shader_image_load_store : require\n"
7320 "\n"
7321 "precision highp float;\n"
7322 "\n"
7323 "layout(rgba8) writeonly uniform image2D u_destination_image;\n"
7324 "layout(rgba8) readonly uniform image2D u_source_image;\n"
7325 "\n"
7326 "void main()\n"
7327 "{\n"
7328 " vec4 loaded_color = imageLoad (u_source_image, ivec2(gl_FragCoord));\n"
7329 " imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n"
7330 "\n"
7331 " discard;\n"
7332 "}\n";
7333
7334 /* Vertex postions for "full screen" quad, defined as a triangle strip */
7335 static const GLfloat m_vertex_buffer_data[] = {
7336 -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
7337 -1.0f, 1.0f, 0.0f, 1.0f, /* left top */
7338 1.0f, -1.0f, 0.0f, 1.0f, /* right bottom */
7339 1.0f, 1.0f, 0.0f, 1.0f, /* right top */
7340 };
7341
7342 /* Result of BuildProgram operation */
7343 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
7344
7345 /* Add all tested texture shapes */
7346 int texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
7347 m_texture_shape_definitions.push_back(
7348 TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_2D_ARRAY));
7349 m_texture_shape_definitions.push_back(
7350 TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_3D));
7351 m_texture_shape_definitions.push_back(
7352 TextureShapeDefinition(texture_edge /* edge */, 1 /* n_elements */, GL_TEXTURE_CUBE_MAP));
7353 m_texture_shape_definitions.push_back(
7354 TextureShapeDefinition(texture_edge /* edge */, 3 /* n_elements */, GL_TEXTURE_CUBE_MAP_ARRAY));
7355
7356 /* Prepare buffer with vertex positions of "full screen" quad" */
7357 glGenBuffers(1, &m_vertex_buffer_id);
7358 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
7359
7360 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7361 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7362
7363 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
7364 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
7365
7366 /* Generate vertex array object */
7367 glGenVertexArrays(1, &m_vertex_array_object_id);
7368 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
7369
7370 /* Prepare program object */
7371 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /* src_gs */,
7372 fragment_shader_code, &is_program_correct);
7373 if (false == is_program_correct)
7374 {
7375 return ERROR;
7376 }
7377
7378 /* Done */
7379 return NO_ERROR;
7380 }
7381
Cleanup()7382 virtual long Cleanup()
7383 {
7384 /* Reset OpenGL state */
7385 glBindBuffer(GL_ARRAY_BUFFER, 0);
7386 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
7387 glBindTexture(GL_TEXTURE_3D, 0);
7388 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
7389 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
7390 glBindVertexArray(0);
7391 glUseProgram(0);
7392
7393 /* Delete program */
7394 if (0 != m_program_id)
7395 {
7396 glDeleteProgram(m_program_id);
7397 m_program_id = 0;
7398 }
7399
7400 /* Delete textures */
7401 if (0 != m_destination_texture_id)
7402 {
7403 glDeleteTextures(1, &m_destination_texture_id);
7404 m_destination_texture_id = 0;
7405 }
7406
7407 if (0 != m_source_texture_id)
7408 {
7409 glDeleteTextures(1, &m_source_texture_id);
7410 m_source_texture_id = 0;
7411 }
7412
7413 /* Delete vertex array object */
7414 if (0 != m_vertex_array_object_id)
7415 {
7416 glDeleteVertexArrays(1, &m_vertex_array_object_id);
7417 m_vertex_array_object_id = 0;
7418 }
7419
7420 /* Delete buffer */
7421 if (0 != m_vertex_buffer_id)
7422 {
7423 glDeleteBuffers(1, &m_vertex_buffer_id);
7424 m_vertex_buffer_id = 0;
7425 }
7426
7427 /* Done */
7428 return NO_ERROR;
7429 }
7430
Run()7431 virtual long Run()
7432 {
7433 bool result = true;
7434
7435 /* For each shape */
7436 for (TextureShapeDefinitionList::const_iterator it = m_texture_shape_definitions.begin();
7437 m_texture_shape_definitions.end() != it; ++it)
7438 {
7439 const GLuint n_layers = GetTotalNumberOfLayers(it->m_n_elements, it->m_type);
7440
7441 /* Prepare "source" and "destination" textures */
7442 GLU_EXPECT_NO_ERROR(
7443 CreateRGBA8DestinationTexture(it->m_edge, it->m_n_elements, it->m_type, m_destination_texture_id),
7444 "Create2DR8UIDestinationTexture");
7445 GLU_EXPECT_NO_ERROR(CreateRGBA8SourceTexture(it->m_edge, it->m_n_elements, it->m_type, m_source_texture_id),
7446 "Create2DR8UISourceTexture");
7447
7448 /* Copy texture data with imageLoad() and imageStore() operations */
7449 CopyRGBA8Texture(m_destination_texture_id, m_source_texture_id, n_layers);
7450
7451 /* Compare "source" and "destination" textures */
7452 if (false ==
7453 CompareRGBA8Textures(m_destination_texture_id, m_source_texture_id, it->m_edge, n_layers, it->m_type))
7454 {
7455 const char* texture_type = "";
7456 switch (it->m_type)
7457 {
7458 case GL_TEXTURE_2D_ARRAY:
7459 texture_type = "2d array";
7460 break;
7461 case GL_TEXTURE_3D:
7462 texture_type = "3d";
7463 break;
7464 case GL_TEXTURE_CUBE_MAP:
7465 texture_type = "Cube map";
7466 break;
7467 case GL_TEXTURE_CUBE_MAP_ARRAY:
7468 texture_type = "Cube map array";
7469 break;
7470 }
7471
7472 m_context.getTestContext().getLog()
7473 << tcu::TestLog::Message
7474 << "Copy with imageLoad and imageStore failed for texture type: " << texture_type
7475 << ". Source and destination textures are different" << tcu::TestLog::EndMessage;
7476
7477 result = false;
7478 }
7479
7480 /* Destroy "source" and "destination" textures */
7481 glDeleteTextures(1, &m_destination_texture_id);
7482 glDeleteTextures(1, &m_source_texture_id);
7483
7484 m_destination_texture_id = 0;
7485 m_source_texture_id = 0;
7486 }
7487
7488 if (false == result)
7489 {
7490 return ERROR;
7491 }
7492
7493 /* Done */
7494 return NO_ERROR;
7495 }
7496
7497 private:
7498 /* Private methods */
7499
7500 /** Binds a texture to user-specified image unit and update relevant sampler uniform
7501 *
7502 * @param program_id Program object id
7503 * @param texture_id Texture id
7504 * @param image_unit Index of image unit
7505 * @param layer Index of layer bound to unit
7506 * @param uniform_name Name of image uniform
7507 **/
BindTextureToImage(GLuint program_id,GLuint texture_id,GLuint image_unit,GLuint layer,const char * uniform_name)7508 void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, GLuint layer,
7509 const char* uniform_name)
7510 {
7511 static const GLint invalid_uniform_location = -1;
7512 GLint image_uniform_location = 0;
7513
7514 /* Get uniform location */
7515 image_uniform_location = glGetUniformLocation(program_id, uniform_name);
7516 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
7517 if (invalid_uniform_location == image_uniform_location)
7518 {
7519 throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__);
7520 }
7521
7522 /* Bind texture to image unit */
7523 glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE /* layered */, layer, GL_READ_WRITE,
7524 GL_RGBA8);
7525 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
7526
7527 /* Set uniform to image unit */
7528 glUniform1i(image_uniform_location, image_unit);
7529 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
7530 }
7531
7532 /** Compare two 2D R8UI textures
7533 *
7534 * @param left_texture_id Id of "left" texture object
7535 * @param right_texture_id Id of "right" texture object
7536 * @param edge Length of texture edge
7537 * @param n_layers Number of layers to compare
7538 * @param type Type of texture
7539 *
7540 * @return true when texture data is found identical, false otherwise
7541 **/
CompareRGBA8Textures(GLuint left_texture_id,GLuint right_texture_id,GLuint edge,GLuint n_layers,GLenum type)7542 bool CompareRGBA8Textures(GLuint left_texture_id, GLuint right_texture_id, GLuint edge, GLuint n_layers,
7543 GLenum type)
7544 {
7545 static const GLuint n_components = 4; /* RGBA */
7546 const GLuint texture_data_size = edge * edge * n_layers * n_components;
7547
7548 /* Storage for texture data */
7549 std::vector<GLubyte> left_texture_data;
7550 std::vector<GLubyte> right_texture_data;
7551
7552 ExtractTextureData(left_texture_id, edge, n_layers, type, left_texture_data);
7553 ExtractTextureData(right_texture_id, edge, n_layers, type, right_texture_data);
7554
7555 /* Compare texels */
7556 return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size));
7557 }
7558
7559 /** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations
7560 *
7561 * @param destination_texture_id Id of "destination" texture object
7562 * @param source_texture_id Id of "source" texture object
7563 * @param n_layers Number of layers
7564 **/
CopyRGBA8Texture(GLuint destination_texture_id,GLuint source_texture_id,GLuint n_layers)7565 void CopyRGBA8Texture(GLuint destination_texture_id, GLuint source_texture_id, GLuint n_layers)
7566 {
7567 for (GLuint layer = 0; layer < n_layers; ++layer)
7568 {
7569 CopyRGBA8TextureLayer(destination_texture_id, source_texture_id, layer);
7570 }
7571 }
7572
7573 /** Copy contents of layer from "source" texture to "destination" texture with imageLoad() and imageStore() operations
7574 *
7575 * @param destination_texture_id Id of "destination" texture object
7576 * @param source_texture_id Id of "source" texture object
7577 * @param layer Index of layer
7578 **/
CopyRGBA8TextureLayer(GLuint destination_texture_id,GLuint source_texture_id,GLuint layer)7579 void CopyRGBA8TextureLayer(GLuint destination_texture_id, GLuint source_texture_id, GLuint layer)
7580 {
7581 /* Uniform names */
7582 static const char* const destination_image_uniform_name = "u_destination_image";
7583 static const char* const source_image_uniform_name = "u_source_image";
7584
7585 /* Attribute name */
7586 static const char* const position_attribute_name = "vs_in_position";
7587
7588 /* Attribute location and invalid value */
7589 static const GLint invalid_attribute_location = -1;
7590 GLint position_attribute_location = 0;
7591
7592 /* Set current program */
7593 glUseProgram(m_program_id);
7594 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
7595
7596 /* Bind vertex array object */
7597 glBindVertexArray(m_vertex_array_object_id);
7598 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
7599
7600 /* Bind buffer with quad vertex positions */
7601 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7602 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7603
7604 /* Set up vertex attribute array for position attribute */
7605 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
7606 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
7607 if (invalid_attribute_location == position_attribute_location)
7608 {
7609 throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
7610 __LINE__);
7611 }
7612
7613 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */,
7614 0 /* stride */, 0 /* pointer */);
7615 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
7616
7617 glEnableVertexAttribArray(position_attribute_location);
7618 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
7619
7620 /* Set up textures as source and destination image samplers */
7621 BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, layer,
7622 destination_image_uniform_name);
7623 BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, layer, source_image_uniform_name);
7624
7625 /* Execute draw */
7626 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
7627 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
7628 }
7629
7630 /** Creates RGBA8 texture of given type and fills it with zeros
7631 *
7632 * @param edge Edge of created texture
7633 * @param n_elements Number of elements in texture array
7634 * @param target Target of created texture
7635 * @param out_texture_id Id of created texture, not modified if operation fails
7636 *
7637 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7638 **/
CreateRGBA8DestinationTexture(GLuint edge,GLuint n_elements,GLenum target,GLuint & out_texture_id)7639 GLenum CreateRGBA8DestinationTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint& out_texture_id)
7640 {
7641 /* Constasts to calculate texture size */
7642 static const GLuint n_components = 4; /* RGBA */
7643 const GLuint layer_size = edge * edge * n_components;
7644 const GLuint n_layers = GetTotalNumberOfLayers(n_elements, target);
7645 const GLuint texture_size = layer_size * n_layers;
7646
7647 /* Prepare storage for texture data */
7648 std::vector<GLubyte> texture_data;
7649 texture_data.resize(texture_size);
7650
7651 /* Set all texels */
7652 for (GLuint i = 0; i < texture_size; ++i)
7653 {
7654 texture_data[i] = 0;
7655 }
7656
7657 /* Create texture */
7658 return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id);
7659 }
7660
7661 /** Creates RGBA8 texture and fills it with [x, y, layer, 0xaa]
7662 *
7663 * @param edge Edge of created texture
7664 * @param n_elements Number of elements in texture array
7665 * @param target Target of created texture
7666 * @param out_texture_id Id of created texture, not modified if operation fails
7667 *
7668 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7669 **/
CreateRGBA8SourceTexture(GLuint edge,GLuint n_elements,GLenum target,GLuint & out_texture_id)7670 GLenum CreateRGBA8SourceTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint& out_texture_id)
7671 {
7672 /* Constants to calculate texture size */
7673 static const GLuint n_components = 4; /* RGBA */
7674 const GLuint layer_size = edge * edge * n_components;
7675 const GLuint n_layers = GetTotalNumberOfLayers(n_elements, target);
7676 const GLuint texture_size = layer_size * n_layers;
7677
7678 /* Value of texel */
7679 GLubyte texel[4] = { 0, 0, 0, 0xaa };
7680
7681 /* Prepare storage for texture data */
7682 std::vector<GLubyte> texture_data;
7683 texture_data.resize(texture_size);
7684
7685 /* Set all texels */
7686 for (GLuint layer = 0; layer < n_layers; ++layer)
7687 {
7688 const GLuint layer_offset = layer_size * layer;
7689
7690 texel[2] = static_cast<GLubyte>(layer);
7691
7692 for (GLuint y = 0; y < edge; ++y)
7693 {
7694 const GLuint line_offset = y * edge * n_components + layer_offset;
7695
7696 texel[1] = static_cast<GLubyte>(y);
7697
7698 for (GLuint x = 0; x < edge; ++x)
7699 {
7700 const GLuint texel_offset = x * n_components + line_offset;
7701 texel[0] = static_cast<GLubyte>(x);
7702
7703 for (GLuint component = 0; component < n_components; ++component)
7704 {
7705 texture_data[texel_offset + component] = texel[component];
7706 }
7707 }
7708 }
7709 }
7710
7711 /* Create texture */
7712 return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id);
7713 }
7714
7715 /** Creates RGBA8 texture of given type and fills it provided data
7716 *
7717 * @param edge Edge of created texture
7718 * @param n_elements Number of elements in texture array
7719 * @param target Target of created texture
7720 * @param texture_data Texture data
7721 * @param out_texture_id Id of created texture, not modified if operation fails
7722 *
7723 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7724 **/
CreateRGBA8Texture(GLuint edge,GLenum target,GLuint n_layers,const std::vector<GLubyte> & texture_data,GLuint & out_texture_id)7725 GLenum CreateRGBA8Texture(GLuint edge, GLenum target, GLuint n_layers, const std::vector<GLubyte>& texture_data,
7726 GLuint& out_texture_id)
7727 {
7728 GLenum err = 0;
7729 GLuint texture_id = 0;
7730
7731 /* Generate texture */
7732 glGenTextures(1, &texture_id);
7733 err = glGetError();
7734 if (GL_NO_ERROR != err)
7735 {
7736 return err;
7737 }
7738
7739 /* Bind texture */
7740 glBindTexture(target, texture_id);
7741 err = glGetError();
7742 if (GL_NO_ERROR != err)
7743 {
7744 glDeleteTextures(1, &texture_id);
7745 return err;
7746 }
7747
7748 /* Allocate storage and fill texture */
7749 if (GL_TEXTURE_CUBE_MAP != target)
7750 {
7751 glTexImage3D(target, 0 /* level */, GL_RGBA8, edge, edge, n_layers, 0 /* border */, GL_RGBA,
7752 GL_UNSIGNED_BYTE, &texture_data[0]);
7753 }
7754 else
7755 {
7756 const GLuint n_components = 4;
7757 const GLuint layer_size = edge * edge * n_components;
7758
7759 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7760 GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]);
7761 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7762 GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]);
7763 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7764 GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]);
7765 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7766 GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]);
7767 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7768 GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]);
7769 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7770 GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]);
7771 }
7772 err = glGetError();
7773 if (GL_NO_ERROR != err)
7774 {
7775 glDeleteTextures(1, &texture_id);
7776 return err;
7777 }
7778
7779 /* Make texture complete */
7780 glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0);
7781 glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 0);
7782 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7783 err = glGetError();
7784 if (GL_NO_ERROR != err)
7785 {
7786 glDeleteTextures(1, &texture_id);
7787 return err;
7788 }
7789
7790 /* Set out_texture_id */
7791 out_texture_id = texture_id;
7792
7793 /* Done */
7794 return GL_NO_ERROR;
7795 }
7796
7797 /** Extracts texture data
7798 *
7799 * @param texture_id Id of texture object
7800 * @param edge Length of texture edge
7801 * @param n_layers Number of layers
7802 * @param target Target of texture
7803 * @param texture_data Extracted texture data
7804 **/
ExtractTextureData(GLuint texture_id,GLuint edge,GLuint n_layers,GLenum target,std::vector<GLubyte> & texture_data)7805 void ExtractTextureData(GLuint texture_id, GLuint edge, GLuint n_layers, GLenum target,
7806 std::vector<GLubyte>& texture_data)
7807 {
7808 static const GLuint n_components = 4; /* RGBA */
7809 const GLuint texture_data_size = edge * edge * n_layers * n_components;
7810
7811 /* Alocate memory for texture data */
7812 texture_data.resize(texture_data_size);
7813
7814 /* Bind texture */
7815 glBindTexture(target, texture_id);
7816 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7817
7818 /* Get data */
7819 if (GL_TEXTURE_CUBE_MAP != target)
7820 {
7821 glGetTexImage(target, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
7822 }
7823 else
7824 {
7825 const GLuint layer_size = edge * edge * n_components;
7826
7827 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]);
7828 glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]);
7829 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]);
7830 glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]);
7831 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]);
7832 glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]);
7833 }
7834
7835 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7836 }
7837
7838 /** Get number of layers per single element for given type of texture
7839 *
7840 * @param target Target of texture
7841 *
7842 * @return Number of layers
7843 **/
GetLayersPerElement(GLenum target)7844 GLuint GetLayersPerElement(GLenum target)
7845 {
7846 switch (target)
7847 {
7848 case GL_TEXTURE_2D_ARRAY:
7849 case GL_TEXTURE_3D:
7850 return 1;
7851 case GL_TEXTURE_CUBE_MAP:
7852 case GL_TEXTURE_CUBE_MAP_ARRAY:
7853 return 6;
7854 default:
7855 throw tcu::InternalError("Not supported texture type", "", __FILE__, __LINE__);
7856 }
7857 }
7858
7859 /** Get total number of layers in texture of given type and number of array elements
7860 *
7861 * @param n_elements Number of elements in texture array
7862 * @param target Target of texture
7863 *
7864 * @return Number of layers
7865 **/
GetTotalNumberOfLayers(GLuint n_elements,GLenum target)7866 GLuint GetTotalNumberOfLayers(GLuint n_elements, GLenum target)
7867 {
7868 return GetLayersPerElement(target) * n_elements;
7869 }
7870 };
7871
7872 /** Test "imageLoad() and imageStore() for incomplete textures" description follows.
7873 *
7874 * Load from incomplete textures should return 0.
7875 * Store to incomplete textures should be ignored.
7876 *
7877 * Steps:
7878 * - create two incomplete textures: "incomplete_source" and
7879 * "incomplete_destination",
7880 * - create two complete textures: "complete_source" and
7881 * "complete_destination",
7882 * - fill all textures with unique values,
7883 * - prepare program that will:
7884 * * load texel from "incomplete_source" and store its value to
7885 * "complete_destination",
7886 * * load texel from "complete_source" and store its value to
7887 * "incomplete_destination".
7888 * - bind textures to corresponding image uniforms
7889 * - execute program for all texels,
7890 * - verify that "incomplete_destination" was not modified and
7891 * "complete_destination" is filled with zeros.
7892 *
7893 * Texture is considered incomplete when it has enabled mipmaping (see below)
7894 * and does not have all mipmap levels defined. But for the case of Image
7895 * accessing, it is considered invalid if it is mipmap-incomplete and the
7896 * level is different to the base level (base-incomplete).
7897 *
7898 * Creation of incomplete texture:
7899 * - generate and bind texture object id,
7900 * - call TexImage2D with <level>: 0,
7901 * - set GL_TEXTURE_MIN_FILTER? parameter to GL_NEAREST_MIPMAP_LINEAR, (to make
7902 * sure, it should be initial value),
7903 * - set GL_TEXTURE_BASE_LEVEL parameter to 0.
7904 * - set GL_TEXTURE_MAX_LEVEL parameter, for 64x64 set 7 (log2(min(width,
7905 * height)).
7906 *
7907 * Creation of complete texture:
7908 * - generate and bind texture object id,
7909 * - call TexImage2D with <level>: 0,
7910 * - set GL_TEXTURE_BASE_LEVEL parameter to 0.
7911 * - set GL_TEXTURE_MAX_LEVEL parameter to 0.
7912 *
7913 * Binding:
7914 * - Set level == base_level for complete destinations.
7915 * - Set level != base_level for incomplete destinations that are using
7916 * mipmap-incomplete textures.
7917 *
7918 * Test with 2D 64x64 RGBA8 textures.
7919 *
7920 * Program should consist of vertex and fragment shader. Vertex shader should
7921 * pass vertex position through. Fragment shader should do imageLoad() and
7922 * imageStore() operations at coordinates gl_FragCoord.
7923 **/
7924 class ImageLoadStoreIncompleteTexturesTest : public ShaderImageLoadStoreBase
7925 {
7926 private:
7927 /* Constants */
7928 /* Magic numbers that will identify textures, which will be used as their
7929 * texel value.
7930 */
7931 static const GLubyte m_complete_destination_magic_number = 0x11;
7932 static const GLubyte m_complete_source_magic_number = 0x22;
7933 static const GLubyte m_incomplete_destination_magic_number = 0x33;
7934 static const GLubyte m_incomplete_source_magic_number = 0x44;
7935
7936 /* Texture edge */
7937 GLuint m_texture_edge;
7938
7939 /* Fields */
7940 GLuint m_complete_destination_texture_id;
7941 GLuint m_complete_source_texture_id;
7942 GLuint m_incomplete_destination_texture_id;
7943 GLuint m_incomplete_source_texture_id;
7944 GLuint m_program_id;
7945 GLuint m_vertex_array_object_id;
7946 GLuint m_vertex_buffer_id;
7947
7948 public:
7949 /* Constructor */
ImageLoadStoreIncompleteTexturesTest()7950 ImageLoadStoreIncompleteTexturesTest()
7951 : m_texture_edge(0)
7952 , m_complete_destination_texture_id(0)
7953 , m_complete_source_texture_id(0)
7954 , m_incomplete_destination_texture_id(0)
7955 , m_incomplete_source_texture_id(0)
7956 , m_program_id(0)
7957 , m_vertex_array_object_id(0)
7958 , m_vertex_buffer_id(0)
7959 {
7960 /* Nothing to be done here */
7961 }
7962
7963 /* Methods inherited from SubcaseBase */
Setup()7964 virtual long Setup()
7965 {
7966 /* Shaders code */
7967 const char* const vertex_shader_code = "#version 400 core\n"
7968 "#extension GL_ARB_shader_image_load_store : require\n"
7969 "\n"
7970 "precision highp float;\n"
7971 "\n"
7972 "in vec4 vs_in_position;\n"
7973 "\n"
7974 "void main()\n"
7975 "{\n"
7976 " gl_Position = vs_in_position;\n"
7977 "}\n";
7978
7979 const char* const fragment_shader_code =
7980 "#version 400 core\n"
7981 "#extension GL_ARB_shader_image_load_store : require\n"
7982 "\n"
7983 "precision highp float;\n"
7984 "\n"
7985 "layout(rgba8) writeonly uniform image2D u_complete_destination_image;\n"
7986 "layout(rgba8) readonly uniform image2D u_complete_source_image;\n"
7987 "layout(rgba8) writeonly uniform image2D u_incomplete_destination_image;\n"
7988 "layout(rgba8) readonly uniform image2D u_incomplete_source_image;\n"
7989 "\n"
7990 "void main()\n"
7991 "{\n"
7992 " vec4 complete_loaded_color = imageLoad (u_complete_source_image, ivec2(gl_FragCoord));\n"
7993 " vec4 incomplete_loaded_color = imageLoad (u_incomplete_source_image, ivec2(gl_FragCoord));\n"
7994
7995 " imageStore(u_complete_destination_image,\n"
7996 " ivec2(gl_FragCoord),\n"
7997 " incomplete_loaded_color);\n"
7998 " imageStore(u_incomplete_destination_image,\n"
7999 " ivec2(gl_FragCoord),\n"
8000 " complete_loaded_color);\n"
8001 "\n"
8002 " discard;\n"
8003 "}\n";
8004
8005 /* Vertex postions for "full screen" quad, made with triangle strip */
8006 static const GLfloat m_vertex_buffer_data[] = {
8007 -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
8008 -1.0f, 1.0f, 0.0f, 1.0f, /* left top */
8009 1.0f, -1.0f, 0.0f, 1.0f, /* right bottom */
8010 1.0f, 1.0f, 0.0f, 1.0f, /* right top */
8011 };
8012
8013 /* Result of BuildProgram operation */
8014 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
8015
8016 /* Clean previous error */
8017 glGetError();
8018
8019 m_texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
8020
8021 /* Prepare textures */
8022 GLU_EXPECT_NO_ERROR(
8023 Create2DRGBA8CompleteTexture(m_complete_destination_magic_number, m_complete_destination_texture_id),
8024 "Create2DRGBA8CompleteTexture");
8025 GLU_EXPECT_NO_ERROR(Create2DRGBA8CompleteTexture(m_complete_source_magic_number, m_complete_source_texture_id),
8026 "Create2DRGBA8CompleteTexture");
8027 GLU_EXPECT_NO_ERROR(
8028 Create2DRGBA8IncompleteTexture(m_incomplete_destination_magic_number, m_incomplete_destination_texture_id),
8029 "Create2DRGBA8IncompleteTexture");
8030 GLU_EXPECT_NO_ERROR(
8031 Create2DRGBA8IncompleteTexture(m_incomplete_source_magic_number, m_incomplete_source_texture_id),
8032 "Create2DRGBA8IncompleteTexture");
8033
8034 /* Prepare buffer with vertex positions of "full screen" quad" */
8035 glGenBuffers(1, &m_vertex_buffer_id);
8036 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
8037
8038 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
8039 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
8040
8041 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
8042 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
8043
8044 /* Generate vertex array object */
8045 glGenVertexArrays(1, &m_vertex_array_object_id);
8046 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
8047
8048 /* Prepare program object */
8049 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */,
8050 fragment_shader_code, &is_program_correct);
8051
8052 if (false == is_program_correct)
8053 {
8054 return ERROR;
8055 }
8056
8057 /* Done */
8058 return NO_ERROR;
8059 }
8060
Cleanup()8061 virtual long Cleanup()
8062 {
8063 /* Reset OpenGL state */
8064 glBindBuffer(GL_ARRAY_BUFFER, 0);
8065 glBindTexture(GL_TEXTURE_2D, 0);
8066 glBindVertexArray(0);
8067 glUseProgram(0);
8068
8069 /* Delete program */
8070 if (0 != m_program_id)
8071 {
8072 glDeleteProgram(m_program_id);
8073 m_program_id = 0;
8074 }
8075
8076 /* Delete textures */
8077 if (0 != m_complete_destination_texture_id)
8078 {
8079 glDeleteTextures(1, &m_complete_destination_texture_id);
8080 m_complete_destination_texture_id = 0;
8081 }
8082
8083 if (0 != m_complete_source_texture_id)
8084 {
8085 glDeleteTextures(1, &m_complete_source_texture_id);
8086 m_complete_source_texture_id = 0;
8087 }
8088
8089 if (0 != m_incomplete_destination_texture_id)
8090 {
8091 glDeleteTextures(1, &m_incomplete_destination_texture_id);
8092 m_incomplete_destination_texture_id = 0;
8093 }
8094
8095 if (0 != m_incomplete_source_texture_id)
8096 {
8097 glDeleteTextures(1, &m_incomplete_source_texture_id);
8098 m_incomplete_source_texture_id = 0;
8099 }
8100
8101 /* Delete vertex array object */
8102 if (0 != m_vertex_array_object_id)
8103 {
8104 glDeleteVertexArrays(1, &m_vertex_array_object_id);
8105 m_vertex_array_object_id = 0;
8106 }
8107
8108 /* Delete buffer */
8109 if (0 != m_vertex_buffer_id)
8110 {
8111 glDeleteBuffers(1, &m_vertex_buffer_id);
8112 m_vertex_buffer_id = 0;
8113 }
8114
8115 /* Done */
8116 return NO_ERROR;
8117 }
8118
Run()8119 virtual long Run()
8120 {
8121 bool result = true;
8122
8123 /* Copy textures data with imageLoad() and imageStore() operations */
8124 Copy2DRGBA8Textures(m_complete_destination_texture_id, m_incomplete_destination_texture_id,
8125 m_complete_source_texture_id, m_incomplete_source_texture_id);
8126
8127 glMemoryBarrier(GL_ALL_BARRIER_BITS);
8128
8129 /* Verify that store to "incomplete destination" was ignored */
8130 if (true ==
8131 CheckIfTextureWasModified(m_incomplete_destination_texture_id, m_incomplete_destination_magic_number))
8132 {
8133 m_context.getTestContext().getLog()
8134 << tcu::TestLog::Message << "Problem with imageStore, operation modified contents of incomplete texture"
8135 << tcu::TestLog::EndMessage;
8136
8137 result = false;
8138 }
8139
8140 /* Verify that load from "incomplete source" returned 0 */
8141 if (false == CheckIfTextureIsBlack(m_complete_destination_texture_id))
8142 {
8143 m_context.getTestContext().getLog()
8144 << tcu::TestLog::Message
8145 << "Problem with imageLoad, operation returned non 0 result for incomplete texture"
8146 << tcu::TestLog::EndMessage;
8147
8148 result = false;
8149 }
8150
8151 if (false == result)
8152 {
8153 return ERROR;
8154 }
8155
8156 /* Done */
8157 return NO_ERROR;
8158 }
8159
8160 private:
8161 /* Private methods */
8162
8163 /** Bind texture to image unit and sets image uniform to that unit
8164 *
8165 * @param program_id Program object id
8166 * @param texture_id Texture id
8167 * @param level Texture level
8168 * @param image_unit Index of image unit
8169 * @param uniform_name Name of image uniform
8170 **/
BindTextureToImage(GLuint program_id,GLuint texture_id,GLint level,GLuint image_unit,const char * uniform_name)8171 void BindTextureToImage(GLuint program_id, GLuint texture_id, GLint level, GLuint image_unit, const char* uniform_name)
8172 {
8173 /* Uniform location and invalid value */
8174 static const GLint invalid_uniform_location = -1;
8175 GLint image_uniform_location = 0;
8176
8177 /* Get uniform location */
8178 image_uniform_location = glGetUniformLocation(program_id, uniform_name);
8179 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
8180 if (invalid_uniform_location == image_uniform_location)
8181 {
8182 throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__);
8183 }
8184
8185 /* Bind texture to image unit */
8186 glBindImageTexture(image_unit, texture_id, level, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_RGBA8);
8187 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
8188
8189 /* Set uniform to image unit */
8190 glUniform1i(image_uniform_location, image_unit);
8191 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
8192 }
8193
8194 /** Check if texture is filled with black color, zeros
8195 *
8196 * @param texture_id Id of texture object
8197 *
8198 * @return true when texture is fully black, false otherwise
8199 **/
CheckIfTextureIsBlack(GLuint texture_id)8200 bool CheckIfTextureIsBlack(GLuint texture_id)
8201 {
8202 /* Constants to calculate size of texture */
8203 static const GLuint n_components = 4; /* RGBA */
8204 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components;
8205
8206 /* Storage for texture data */
8207 std::vector<GLubyte> black_texture_data;
8208 std::vector<GLubyte> texture_data;
8209
8210 /* Allocate memory */
8211 black_texture_data.resize(texture_data_size);
8212 texture_data.resize(texture_data_size);
8213
8214 /* Set all texels to black */
8215 for (GLuint i = 0; i < texture_data_size; ++i)
8216 {
8217 black_texture_data[i] = 0;
8218 }
8219
8220 /* Bind texture */
8221 glBindTexture(GL_TEXTURE_2D, texture_id);
8222 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
8223
8224 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
8225 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
8226
8227 /* Compare texels */
8228 return (0 == memcmp(&texture_data[0], &black_texture_data[0], texture_data_size));
8229 }
8230
8231 /** Check if texture was modified
8232 *
8233 * @param texture_id Id of texture object
8234 * @param nagic_number Magic number that was to create texture
8235 *
8236 * @return true if texture contents match expected values, false otherwise
8237 **/
CheckIfTextureWasModified(GLuint texture_id,GLubyte magic_number)8238 bool CheckIfTextureWasModified(GLuint texture_id, GLubyte magic_number)
8239 {
8240 /* Constants to calculate size of texture */
8241 static const GLuint n_components = 4; /* RGBA */
8242 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components;
8243
8244 /* Storage for texture data */
8245 std::vector<GLubyte> expected_texture_data;
8246 std::vector<GLubyte> texture_data;
8247
8248 /* Allocate memory */
8249 expected_texture_data.resize(texture_data_size);
8250 texture_data.resize(texture_data_size);
8251
8252 /* Prepare expected texels */
8253 for (GLuint y = 0; y < m_texture_edge; ++y)
8254 {
8255 const GLuint line_offset = y * m_texture_edge * n_components;
8256
8257 for (GLuint x = 0; x < m_texture_edge; ++x)
8258 {
8259 const GLuint texel_offset = x * n_components + line_offset;
8260
8261 SetTexel(&expected_texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y),
8262 magic_number);
8263 }
8264 }
8265
8266 /* Bind texture */
8267 glBindTexture(GL_TEXTURE_2D, texture_id);
8268 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
8269
8270 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
8271 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
8272
8273 /* Compare texels, true when textures are different */
8274 return (0 != memcmp(&texture_data[0], &expected_texture_data[0], texture_data_size));
8275 }
8276
8277 /** Copy contents of "source" textures to "destination" textures with imageLoad() and imageStore() operations
8278 *
8279 * @param complete_destination_texture_id Id of "complete destination" texture object
8280 * @param incomplete_destination_texture_id Id of "incomplete destination" texture object
8281 * @param complete_source_texture_id Id of "complete source" texture object
8282 * @param incomplete_source_texture_id Id of "incomplete source" texture object
8283 **/
Copy2DRGBA8Textures(GLuint complete_destination_texture_id,GLuint incomplete_destination_texture_id,GLuint complete_source_texture_id,GLuint incomplete_source_texture_id)8284 void Copy2DRGBA8Textures(GLuint complete_destination_texture_id, GLuint incomplete_destination_texture_id,
8285 GLuint complete_source_texture_id, GLuint incomplete_source_texture_id)
8286 {
8287 /* Uniform names */
8288 static const char* const complete_destination_image_uniform_name = "u_complete_destination_image";
8289 static const char* const complete_source_image_uniform_name = "u_complete_source_image";
8290 static const char* const incomplete_destination_image_uniform_name = "u_incomplete_destination_image";
8291 static const char* const incomplete_source_image_uniform_name = "u_incomplete_source_image";
8292
8293 /* Attribute name */
8294 static const char* const position_attribute_name = "vs_in_position";
8295
8296 /* Attribute location and invalid value */
8297 static const GLint invalid_attribute_location = -1;
8298 GLint position_attribute_location = 0;
8299
8300 /* Set current program */
8301 glUseProgram(m_program_id);
8302 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
8303
8304 /* Bind vertex array object */
8305 glBindVertexArray(m_vertex_array_object_id);
8306 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
8307
8308 /* Bind buffer with quad vertex positions */
8309 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
8310 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
8311
8312 /* Setup position attribute */
8313 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
8314 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
8315 if (invalid_attribute_location == position_attribute_location)
8316 {
8317 throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
8318 __LINE__);
8319 }
8320
8321 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE, 0 /* stride */, 0);
8322 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
8323
8324 glEnableVertexAttribArray(position_attribute_location);
8325 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
8326
8327 /* Setup textures as source and destination images */
8328 BindTextureToImage(m_program_id, complete_destination_texture_id,
8329 0 /* texture level */, 0 /* image_unit */,
8330 complete_destination_image_uniform_name);
8331 BindTextureToImage(m_program_id, complete_source_texture_id,
8332 0 /* texture level */, 1 /* image_unit */,
8333 complete_source_image_uniform_name);
8334 BindTextureToImage(m_program_id, incomplete_destination_texture_id,
8335 2 /* texture level */, 2 /* image_unit */,
8336 incomplete_destination_image_uniform_name);
8337 BindTextureToImage(m_program_id, incomplete_source_texture_id,
8338 2 /* texture level */, 3 /* image_unit */,
8339 incomplete_source_image_uniform_name);
8340
8341 /* Execute draw */
8342 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
8343 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
8344 }
8345
8346 /** Create complete 2D RGBA8 texture.
8347 *
8348 * @param magic_number Magic number of texture
8349 * @param out_texture_id Id of created texture, not modified if operation fails
8350 *
8351 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
8352 **/
Create2DRGBA8CompleteTexture(GLubyte magic_number,GLuint & out_texture_id)8353 GLenum Create2DRGBA8CompleteTexture(GLubyte magic_number, GLuint& out_texture_id)
8354 {
8355 /* Constants to calculate size of texture */
8356 static const GLuint n_components = 4; /* RGBA */
8357 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components;
8358
8359 /* Error code */
8360 GLenum err = 0;
8361
8362 /* Texture id */
8363 GLuint texture_id = 0;
8364
8365 /* Prepare storage for texture data */
8366 std::vector<GLubyte> texture_data;
8367 texture_data.resize(texture_data_size);
8368
8369 /* Prepare texture data */
8370 for (GLuint y = 0; y < m_texture_edge; ++y)
8371 {
8372 const GLuint line_offset = y * m_texture_edge * n_components;
8373
8374 for (GLuint x = 0; x < m_texture_edge; ++x)
8375 {
8376 const GLuint texel_offset = x * n_components + line_offset;
8377
8378 SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number);
8379 }
8380 }
8381
8382 /* Generate texture */
8383 glGenTextures(1, &texture_id);
8384 err = glGetError();
8385 if (GL_NO_ERROR != err)
8386 {
8387 return err;
8388 }
8389
8390 /* Bind texture */
8391 glBindTexture(GL_TEXTURE_2D, texture_id);
8392 err = glGetError();
8393 if (GL_NO_ERROR != err)
8394 {
8395 glDeleteTextures(1, &texture_id);
8396 return err;
8397 }
8398
8399 /* Allocate storage and fill texture */
8400 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA,
8401 GL_UNSIGNED_BYTE, &texture_data[0]);
8402 err = glGetError();
8403 if (GL_NO_ERROR != err)
8404 {
8405 glDeleteTextures(1, &texture_id);
8406 return err;
8407 }
8408
8409 /* Make texture complete */
8410 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8411 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
8412 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8413 err = glGetError();
8414 if (GL_NO_ERROR != err)
8415 {
8416 glDeleteTextures(1, &texture_id);
8417 return err;
8418 }
8419
8420 /* Set out_texture_id */
8421 out_texture_id = texture_id;
8422
8423 /* Done */
8424 return GL_NO_ERROR;
8425 }
8426
8427 /** Create incomplete 2D RGBA8 texture
8428 *
8429 * @param magic_number Magic number of texture
8430 * @param out_texture_id Id of created texture, not modified if operation fails
8431 *
8432 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
8433 **/
Create2DRGBA8IncompleteTexture(GLubyte magic_number,GLuint & out_texture_id)8434 GLenum Create2DRGBA8IncompleteTexture(GLubyte magic_number, GLuint& out_texture_id)
8435 {
8436 /* Constants to calculate size of texture */
8437 static const GLuint n_components = 4; /* RGBA */
8438 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components;
8439
8440 /* Error code */
8441 GLenum err = 0;
8442
8443 /* Texture id */
8444 GLuint texture_id = 0;
8445
8446 /* Prepare storage for texture data */
8447 std::vector<GLubyte> texture_data;
8448 texture_data.resize(texture_data_size);
8449
8450 /* Prepare texture data */
8451 for (GLuint y = 0; y < m_texture_edge; ++y)
8452 {
8453 const GLuint line_offset = y * m_texture_edge * n_components;
8454
8455 for (GLuint x = 0; x < m_texture_edge; ++x)
8456 {
8457 const GLuint texel_offset = x * n_components + line_offset;
8458
8459 SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number);
8460 }
8461 }
8462
8463 /* Generate texture */
8464 glGenTextures(1, &texture_id);
8465 err = glGetError();
8466 if (GL_NO_ERROR != err)
8467 {
8468 return err;
8469 }
8470
8471 /* Bind texture */
8472 glBindTexture(GL_TEXTURE_2D, texture_id);
8473 err = glGetError();
8474 if (GL_NO_ERROR != err)
8475 {
8476 glDeleteTextures(1, &texture_id);
8477 return err;
8478 }
8479
8480 /* Allocate storage and fill texture */
8481 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA,
8482 GL_UNSIGNED_BYTE, &texture_data[0]);
8483 err = glGetError();
8484 if (GL_NO_ERROR != err)
8485 {
8486 glDeleteTextures(1, &texture_id);
8487 return err;
8488 }
8489
8490 /* Make texture incomplete */
8491 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8492 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 7);
8493 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
8494 err = glGetError();
8495 if (GL_NO_ERROR != err)
8496 {
8497 glDeleteTextures(1, &texture_id);
8498 return err;
8499 }
8500
8501 /* Set out_texture_id */
8502 out_texture_id = texture_id;
8503
8504 /* Done */
8505 return GL_NO_ERROR;
8506 }
8507
8508 /** Prepare "unique" texels.
8509 * Texel is assigned with such values: [x_coordinate, y_coordinate, magic_number, 0xcc].
8510 *
8511 * @param texel Storage of texel
8512 * @param x_coordinate X coordiante of texel
8513 * @param y_coordinate Y coordinate of texel
8514 * @param magic_number Magic number of texture
8515 **/
SetTexel(GLubyte texel[4],GLubyte x_coordinate,GLubyte y_coordinate,GLubyte magic_number)8516 void SetTexel(GLubyte texel[4], GLubyte x_coordinate, GLubyte y_coordinate, GLubyte magic_number)
8517 {
8518 texel[0] = x_coordinate;
8519 texel[1] = y_coordinate;
8520 texel[2] = magic_number;
8521 texel[3] = 0xcc;
8522 }
8523 };
8524
8525 /** Test "Refer to the same image unit using multiple uniforms", description follows.
8526 *
8527 * Steps:
8528 * - prepare program object, see details below,
8529 * - prepare 2D R32I texture, width should be equal to the number of image
8530 * uniforms used by program object, height should be 2, fill first row with
8531 * unique values, fill second row with zeros,
8532 * - bind texture to first image unit,
8533 * - set all image uniforms to first image unit,
8534 * - execute program for a single vertex,
8535 * - verify that:
8536 * - values in first row were negated,
8537 * - values from first row were copied to second row,
8538 *
8539 * Repeat steps to test all shader stages that support at least 2 image
8540 * uniforms.
8541 *
8542 * Program has to contain all necessary shader stages. Use boilerplate shaders
8543 * for shader stages that are not important for the test.
8544 *
8545 * Tested shader stage should:
8546 * - Use as many different image formats as possible, image formats compatible
8547 * with R32I:
8548 * * rg16f
8549 * * r11f_g11f_b10f
8550 * * r32f
8551 * * rgb10_a2ui
8552 * * rgba8ui
8553 * * rg16ui
8554 * * r32ui
8555 * * rgba8i
8556 * * rg16i
8557 * * r32i
8558 * * rgb10_a2
8559 * * rgba8
8560 * * rg16
8561 * * rgba8_snorm
8562 * * rg16_snorm.
8563 * - Declare maximum allowed number of image uniforms,
8564 *
8565 * layout(format) uniform gimage2D u_image;
8566 *
8567 * where <format> is selected image format, <gimage2D> is type of 2D image
8568 * compatible with <format> and <u_image> is unique name of uniform.
8569 * Note that image uniforms cannot be declared as array, due to different image
8570 * formats. Therefore separate uniforms have to be used.
8571 * - Include following code snippet:
8572 * for (int i = 0; i < gl_Max*ImageUniforms; ++i)
8573 * {
8574 * vec row_1_coord(i,0);
8575 * vec row_2_coord(i,1);
8576 *
8577 * row_1_value = imageLoad(u_image[i], row_1_coord);
8578 * imageStore(u_image[i], row_1_coord, -row_1_value);
8579 * imageStore(u_image[i], row_2_coord, row_1_value);
8580 * }
8581 * where gl_Max*ImageUniforms is the constant corresponding to tested shader
8582 * stage.
8583 **/
8584 class ImageLoadStoreMultipleUniformsTest : public ShaderImageLoadStoreBase
8585 {
8586 private:
8587 /* Types */
8588 /** Details of image format
8589 *
8590 **/
8591 struct imageFormatDetails
8592 {
8593 typedef bool (*verificationRoutine)(GLint, GLint, GLint);
8594
8595 const char* m_image_format;
8596 const char* m_image_type;
8597 const char* m_color_type;
8598 GLenum m_image_unit_format;
8599 verificationRoutine m_verification_routine;
8600 };
8601
8602 template <typename T, GLuint SIZE, GLuint OFFSET, bool = (OFFSET < sizeof(T) * CHAR_BIT)>
8603 struct Masks
8604 {
8605 /** Get mask of bits used to store in bit-field
8606 *
8607 * @return Mask
8608 **/
RawMaskgl4cts::__anonb14d91fe0111::ImageLoadStoreMultipleUniformsTest::Masks8609 static inline T RawMask()
8610 {
8611 static const T mask = ValueMask() << OFFSET;
8612
8613 return mask;
8614 }
8615
8616 /** Get mask of bits used to store value.
8617 *
8618 * @return Mask
8619 **/
ValueMaskgl4cts::__anonb14d91fe0111::ImageLoadStoreMultipleUniformsTest::Masks8620 static inline T ValueMask()
8621 {
8622 static const T mask = (1 << SIZE) - 1;
8623
8624 return mask;
8625 }
8626
8627 /** Get offset.
8628 *
8629 * @return offset
8630 **/
Offsetgl4cts::__anonb14d91fe0111::ImageLoadStoreMultipleUniformsTest::Masks8631 static inline T Offset()
8632 {
8633 return OFFSET;
8634 }
8635 };
8636
8637 template <typename T, GLuint SIZE, GLuint OFFSET>
8638 struct Masks<T, SIZE, OFFSET, false>
8639 {
8640 /** Get mask of bits used to store in bit-field
8641 *
8642 * @return Mask
8643 **/
RawMaskgl4cts::__anonb14d91fe0111::ImageLoadStoreMultipleUniformsTest::Masks8644 static inline T RawMask()
8645 {
8646 DE_ASSERT(DE_FALSE && "Shouldn't be called");
8647 return 0;
8648 }
8649
8650 /** Get mask of bits used to store value.
8651 *
8652 * @return Mask
8653 **/
ValueMaskgl4cts::__anonb14d91fe0111::ImageLoadStoreMultipleUniformsTest::Masks8654 static inline T ValueMask()
8655 {
8656 DE_ASSERT(DE_FALSE && "Shouldn't be called");
8657 return 0;
8658 }
8659
8660 /** Get offset.
8661 *
8662 * @return offset
8663 **/
Offsetgl4cts::__anonb14d91fe0111::ImageLoadStoreMultipleUniformsTest::Masks8664 static inline T Offset()
8665 {
8666 DE_ASSERT(DE_FALSE && "Shouldn't be called");
8667 return 0;
8668 }
8669 };
8670
8671 /** Template class for accessing integer values stored in bit-fields
8672 *
8673 **/
8674 template <typename T, GLuint SIZE, GLuint OFFSET>
8675 class Integer
8676 {
8677 public:
8678 /** Constructor
8679 *
8680 **/
Integer(T raw)8681 Integer(T raw) : m_raw(raw)
8682 {
8683 }
8684
8685 /** Extract value from bit-field
8686 *
8687 * @return Value
8688 **/
Get() const8689 T Get() const
8690 {
8691 const T mask = Masks<T, SIZE, OFFSET>::RawMask();
8692
8693 const T bits = m_raw & mask;
8694 const T result = (unsigned)bits >> Masks<T, SIZE, OFFSET>::Offset();
8695
8696 return result;
8697 }
8698
8699 /** Extract value from bit-field and negate it
8700 *
8701 * @return Negated value
8702 **/
GetNegated() const8703 T GetNegated() const
8704 {
8705 const T mask = Masks<T, SIZE, OFFSET>::ValueMask();
8706 const T value = Get();
8707
8708 return Clamp((~value) + 1) & mask;
8709 }
8710
Clamp(T n) const8711 T Clamp(T n) const
8712 {
8713 const bool isUnsigned = (T(0) < T(-1));
8714 const T min = T(isUnsigned ? 0.L : -pow(2.L, int(SIZE - 1)));
8715 const T max = T(isUnsigned ? pow(2.L, int(SIZE)) - 1.L : pow(2.L, int(SIZE - 1)) - 1.L);
8716 const T x = n > max ? max : n;
8717 return x < min ? min : x;
8718 }
8719
8720 private:
8721 T m_raw;
8722 };
8723
8724 /* Enums */
8725 /** Shader stage identification
8726 *
8727 **/
8728 enum shaderStage
8729 {
8730 fragmentShaderStage = 2,
8731 geometryShaderStage = 4,
8732 tesselationControlShaderStage = 8,
8733 tesselationEvalutaionShaderStage = 16,
8734 vertexShaderStage = 32,
8735 };
8736
8737 /** Test result
8738 *
8739 **/
8740 enum testResult
8741 {
8742 testFailed = -1,
8743 testNotSupported = 1,
8744 testPassed = 0
8745 };
8746
8747 /* Constants */
8748 static const GLint m_min_required_image_uniforms = 2;
8749
8750 /* Fields */
8751 GLuint m_program_to_test_fs_stage_id;
8752 GLuint m_program_to_test_gs_stage_id;
8753 GLuint m_program_to_test_tcs_stage_id;
8754 GLuint m_program_to_test_tes_stage_id;
8755 GLuint m_program_to_test_vs_stage_id;
8756 GLuint m_texture_to_test_fs_stage_id;
8757 GLuint m_texture_to_test_gs_stage_id;
8758 GLuint m_texture_to_test_tcs_stage_id;
8759 GLuint m_texture_to_test_tes_stage_id;
8760 GLuint m_texture_to_test_vs_stage_id;
8761 GLuint m_vertex_array_object_id;
8762
8763 public:
8764 /* Constructor */
ImageLoadStoreMultipleUniformsTest()8765 ImageLoadStoreMultipleUniformsTest()
8766 : m_program_to_test_fs_stage_id(0)
8767 , m_program_to_test_gs_stage_id(0)
8768 , m_program_to_test_tcs_stage_id(0)
8769 , m_program_to_test_tes_stage_id(0)
8770 , m_program_to_test_vs_stage_id(0)
8771 , m_texture_to_test_fs_stage_id(0)
8772 , m_texture_to_test_gs_stage_id(0)
8773 , m_texture_to_test_tcs_stage_id(0)
8774 , m_texture_to_test_tes_stage_id(0)
8775 , m_texture_to_test_vs_stage_id(0)
8776 , m_vertex_array_object_id(0)
8777 {
8778 /* Nothing to be done here */
8779 }
8780
8781 /* Methods inherited from SubcaseBase */
Setup()8782 virtual long Setup()
8783 {
8784 /* Prepare programs */
8785 m_program_to_test_fs_stage_id = buildProgramToTestShaderStage(fragmentShaderStage);
8786 m_program_to_test_gs_stage_id = buildProgramToTestShaderStage(geometryShaderStage);
8787 m_program_to_test_tcs_stage_id = buildProgramToTestShaderStage(tesselationControlShaderStage);
8788 m_program_to_test_tes_stage_id = buildProgramToTestShaderStage(tesselationEvalutaionShaderStage);
8789 m_program_to_test_vs_stage_id = buildProgramToTestShaderStage(vertexShaderStage);
8790
8791 /* Prepare textures */
8792 m_texture_to_test_fs_stage_id = createTextureToTestShaderStage(fragmentShaderStage);
8793 m_texture_to_test_gs_stage_id = createTextureToTestShaderStage(geometryShaderStage);
8794 m_texture_to_test_tcs_stage_id = createTextureToTestShaderStage(tesselationControlShaderStage);
8795 m_texture_to_test_tes_stage_id = createTextureToTestShaderStage(tesselationEvalutaionShaderStage);
8796 m_texture_to_test_vs_stage_id = createTextureToTestShaderStage(vertexShaderStage);
8797
8798 /* Generate vertex array object */
8799 glGenVertexArrays(1, &m_vertex_array_object_id);
8800 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
8801
8802 /* Bind vertex array object */
8803 glBindVertexArray(m_vertex_array_object_id);
8804 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
8805
8806 /* Set vertices number for patches */
8807 glPatchParameteri(GL_PATCH_VERTICES, 1);
8808
8809 /* Done */
8810 return NO_ERROR;
8811 }
8812
Cleanup()8813 virtual long Cleanup()
8814 {
8815 glUseProgram(0);
8816
8817 /* Delete programs */
8818 if (0 != m_program_to_test_fs_stage_id)
8819 {
8820 glDeleteProgram(m_program_to_test_fs_stage_id);
8821 m_program_to_test_fs_stage_id = 0;
8822 }
8823
8824 if (0 != m_program_to_test_gs_stage_id)
8825 {
8826 glDeleteProgram(m_program_to_test_gs_stage_id);
8827 m_program_to_test_gs_stage_id = 0;
8828 }
8829
8830 if (0 != m_program_to_test_tcs_stage_id)
8831 {
8832 glDeleteProgram(m_program_to_test_tcs_stage_id);
8833 m_program_to_test_tcs_stage_id = 0;
8834 }
8835
8836 if (0 != m_program_to_test_tes_stage_id)
8837 {
8838 glDeleteProgram(m_program_to_test_tes_stage_id);
8839 m_program_to_test_tes_stage_id = 0;
8840 }
8841
8842 if (0 != m_program_to_test_vs_stage_id)
8843 {
8844 glDeleteProgram(m_program_to_test_vs_stage_id);
8845 m_program_to_test_vs_stage_id = 0;
8846 }
8847
8848 /* Delete textures */
8849 if (0 != m_texture_to_test_fs_stage_id)
8850 {
8851 glDeleteTextures(1, &m_texture_to_test_fs_stage_id);
8852 m_texture_to_test_fs_stage_id = 0;
8853 }
8854
8855 if (0 != m_texture_to_test_gs_stage_id)
8856 {
8857 glDeleteTextures(1, &m_texture_to_test_gs_stage_id);
8858 m_texture_to_test_gs_stage_id = 0;
8859 }
8860
8861 if (0 != m_texture_to_test_tcs_stage_id)
8862 {
8863 glDeleteTextures(1, &m_texture_to_test_tcs_stage_id);
8864 m_texture_to_test_tcs_stage_id = 0;
8865 }
8866
8867 if (0 != m_texture_to_test_tes_stage_id)
8868 {
8869 glDeleteTextures(1, &m_texture_to_test_tes_stage_id);
8870 m_texture_to_test_tes_stage_id = 0;
8871 }
8872
8873 if (0 != m_texture_to_test_vs_stage_id)
8874 {
8875 glDeleteTextures(1, &m_texture_to_test_vs_stage_id);
8876 m_texture_to_test_vs_stage_id = 0;
8877 }
8878
8879 /* Delete vertex array object id */
8880 if (0 != m_vertex_array_object_id)
8881 {
8882 glDeleteVertexArrays(1, &m_vertex_array_object_id);
8883 m_vertex_array_object_id = 0;
8884 }
8885
8886 /* Done */
8887 return NO_ERROR;
8888 }
8889
Run()8890 virtual long Run()
8891 {
8892 bool result = true;
8893
8894 if (testFailed == testShaderStage(fragmentShaderStage))
8895 {
8896 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with fragment shader stage!"
8897 << tcu::TestLog::EndMessage;
8898
8899 result = false;
8900 }
8901
8902 if (testFailed == testShaderStage(geometryShaderStage))
8903 {
8904 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with geometry shader stage!"
8905 << tcu::TestLog::EndMessage;
8906
8907 result = false;
8908 }
8909
8910 if (testFailed == testShaderStage(tesselationControlShaderStage))
8911 {
8912 m_context.getTestContext().getLog() << tcu::TestLog::Message
8913 << "Problems with tesselation control shader stage!"
8914 << tcu::TestLog::EndMessage;
8915
8916 result = false;
8917 }
8918
8919 if (testFailed == testShaderStage(tesselationEvalutaionShaderStage))
8920 {
8921 m_context.getTestContext().getLog() << tcu::TestLog::Message
8922 << "Problems with tesselation evaluation shader stage!"
8923 << tcu::TestLog::EndMessage;
8924
8925 result = false;
8926 }
8927
8928 if (testFailed == testShaderStage(vertexShaderStage))
8929 {
8930 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with vertex shader stage!"
8931 << tcu::TestLog::EndMessage;
8932
8933 result = false;
8934 }
8935
8936 if (false == result)
8937 {
8938 return ERROR;
8939 }
8940
8941 /* Done */
8942 return NO_ERROR;
8943 }
8944
8945 private:
8946 /* Static routines */
8947 /** Provide image format details for given index
8948 *
8949 * @param index Index
8950 * @param out_details Image format detail instance
8951 **/
getImageUniformDeclarationDetails(GLuint index,imageFormatDetails & out_details)8952 static void getImageUniformDeclarationDetails(GLuint index, imageFormatDetails& out_details)
8953 {
8954 static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails default_format_details = {
8955 "r32i", "iimage2D", "ivec4", GL_R32I, ImageLoadStoreMultipleUniformsTest::verifyInteger
8956 };
8957
8958 static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details[] = {
8959 { "rg16f", "image2D", "vec4", GL_RG16F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLushort> },
8960 { "r11f_g11f_b10f", "image2D", "vec4", GL_R11F_G11F_B10F,
8961 ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8962 { "r32f", "image2D", "vec4", GL_R32F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLuint> },
8963 { "rgb10_a2", "image2D", "vec4", GL_RGB10_A2,
8964 ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8965 { "rgba8", "image2D", "vec4", GL_RGBA8, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8966 { "rg16", "image2D", "vec4", GL_RG16, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8967 { "rgba8_snorm", "image2D", "vec4", GL_RGBA8_SNORM,
8968 ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLbyte> },
8969 { "rg16_snorm", "image2D", "vec4", GL_RG16_SNORM,
8970 ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLshort> },
8971 { "rgb10_a2ui", "uimage2D", "uvec4", GL_RGB10_A2UI,
8972 ImageLoadStoreMultipleUniformsTest::verifyInteger<10, 10, 10, 2, GLuint> },
8973 { "rgba8ui", "uimage2D", "uvec4", GL_RGBA8UI,
8974 ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLuint> },
8975 { "rg16ui", "uimage2D", "uvec4", GL_RG16UI,
8976 ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLuint> },
8977 { "r32ui", "uimage2D", "uvec4", GL_R32UI, ImageLoadStoreMultipleUniformsTest::verifyInteger },
8978 { "rgba8i", "iimage2D", "ivec4", GL_RGBA8I,
8979 ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLint> },
8980 { "rg16i", "iimage2D", "ivec4", GL_RG16I,
8981 ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLint> }
8982 };
8983
8984 static const GLuint n_imageUniformFormatDetails =
8985 sizeof(format_details) / sizeof(ImageLoadStoreMultipleUniformsTest::imageFormatDetails);
8986
8987 if (n_imageUniformFormatDetails <= index)
8988 {
8989 out_details = default_format_details;
8990 }
8991 else
8992 {
8993 out_details = format_details[index];
8994 }
8995 }
8996
8997 /** Write name of image uniform at given index to output stream
8998 *
8999 * @param stream Output stream
9000 * @param index Index
9001 **/
writeImageUniformNameToStream(std::ostream & stream,GLuint index)9002 static void writeImageUniformNameToStream(std::ostream& stream, GLuint index)
9003 {
9004 /* u_image_0 */
9005 stream << "u_image_" << index;
9006 }
9007
9008 /** Write name of variable used to store value loaded from image at given index to output stream
9009 *
9010 * @param stream Output stream
9011 * @param index Index
9012 **/
writeLoadedValueVariableNameToStream(std::ostream & stream,GLuint index)9013 static void writeLoadedValueVariableNameToStream(std::ostream& stream, GLuint index)
9014 {
9015 /* loaded_value_0 */
9016 stream << "loaded_value_" << index;
9017 }
9018
9019 /** Write name of variable used to store coordinate of texel at given row to output stream
9020 *
9021 * @param stream Output stream
9022 * @param index Index of image uniform
9023 * @param row Row of image
9024 **/
writeCoordinatesVariableNameToStream(std::ostream & stream,GLuint index,GLuint row)9025 static void writeCoordinatesVariableNameToStream(std::ostream& stream, GLuint index, GLuint row)
9026 {
9027 /* row_0_coordinates_0 */
9028 stream << "row_" << row << "_coordinates_" << index;
9029 }
9030
9031 struct imageUniformDeclaration
9032 {
imageUniformDeclarationgl4cts::__anonb14d91fe0111::ImageLoadStoreMultipleUniformsTest::imageUniformDeclaration9033 imageUniformDeclaration(GLuint index) : m_index(index)
9034 {
9035 }
9036
9037 GLuint m_index;
9038 };
9039
9040 /** Write declaration of image uniform at given index to output stream
9041 *
9042 * @param stream Output stream
9043 * @param imageUniformDeclaration Declaration details
9044 *
9045 * @return stream
9046 **/
operator <<(std::ostream & stream,const imageUniformDeclaration & declaration)9047 friend std::ostream& operator<<(std::ostream& stream, const imageUniformDeclaration& declaration)
9048 {
9049 ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details;
9050 getImageUniformDeclarationDetails(declaration.m_index, format_details);
9051
9052 /* layout(r32f) uniform image2D u_image_0; */
9053 stream << "layout(" << format_details.m_image_format << ") uniform " << format_details.m_image_type << " ";
9054
9055 ImageLoadStoreMultipleUniformsTest::writeImageUniformNameToStream(stream, declaration.m_index);
9056
9057 stream << ";";
9058
9059 return stream;
9060 }
9061
9062 struct imageLoadCall
9063 {
imageLoadCallgl4cts::__anonb14d91fe0111::ImageLoadStoreMultipleUniformsTest::imageLoadCall9064 imageLoadCall(GLuint index) : m_index(index)
9065 {
9066 }
9067
9068 GLuint m_index;
9069 };
9070
9071 /* Stream operators */
9072 /** Write code that execute imageLoad routine for image at given index to output stream
9073 *
9074 * @param stream Output stream
9075 * @param load imageLoad call details
9076 *
9077 * @return stream
9078 **/
operator <<(std::ostream & stream,const imageLoadCall & load)9079 friend std::ostream& operator<<(std::ostream& stream, const imageLoadCall& load)
9080 {
9081 ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details;
9082 getImageUniformDeclarationDetails(load.m_index, format_details);
9083
9084 /* vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates_0); */
9085 stream << format_details.m_color_type << " ";
9086
9087 writeLoadedValueVariableNameToStream(stream, load.m_index);
9088
9089 stream << " = imageLoad(";
9090
9091 writeImageUniformNameToStream(stream, load.m_index);
9092
9093 stream << ", ";
9094
9095 writeCoordinatesVariableNameToStream(stream, load.m_index, 0 /* row */);
9096
9097 stream << ");";
9098
9099 return stream;
9100 }
9101
9102 struct imageStoreCall
9103 {
imageStoreCallgl4cts::__anonb14d91fe0111::ImageLoadStoreMultipleUniformsTest::imageStoreCall9104 imageStoreCall(GLuint index, GLuint row) : m_index(index), m_row(row)
9105 {
9106 }
9107
9108 GLuint m_index;
9109 GLuint m_row;
9110 };
9111
9112 /** Write code that execute imageStore to image at given index to output stream
9113 *
9114 * @param stream Output stream
9115 * @param store imageStore call details
9116 *
9117 * @return stream
9118 **/
operator <<(std::ostream & stream,const imageStoreCall & store)9119 friend std::ostream& operator<<(std::ostream& stream, const imageStoreCall& store)
9120 {
9121 /* imageStore(u_image_0, row_0_coordinates_0, -loaded_value_0); */
9122 stream << "imageStore(";
9123
9124 writeImageUniformNameToStream(stream, store.m_index);
9125
9126 stream << ", ";
9127
9128 writeCoordinatesVariableNameToStream(stream, store.m_index, store.m_row);
9129
9130 if (0 == store.m_row)
9131 {
9132 stream << ", -";
9133 }
9134 else
9135 {
9136 stream << ", ";
9137 }
9138
9139 writeLoadedValueVariableNameToStream(stream, store.m_index);
9140 stream << ");";
9141
9142 return stream;
9143 }
9144
9145 struct coordinatesVariableDeclaration
9146 {
coordinatesVariableDeclarationgl4cts::__anonb14d91fe0111::ImageLoadStoreMultipleUniformsTest::coordinatesVariableDeclaration9147 coordinatesVariableDeclaration(GLuint index, GLuint row) : m_index(index), m_row(row)
9148 {
9149 }
9150 GLuint m_index;
9151 GLuint m_row;
9152 };
9153
9154 /** Write declaration of variable for coordinate at given row to output stream
9155 *
9156 * @param stream Output stream
9157 * @param declaration Declaration details
9158 *
9159 * @return stream
9160 **/
operator <<(std::ostream & stream,const coordinatesVariableDeclaration & declaration)9161 friend std::ostream& operator<<(std::ostream& stream, const coordinatesVariableDeclaration& declaration)
9162 {
9163 stream << "const ivec2 ";
9164
9165 writeCoordinatesVariableNameToStream(stream, declaration.m_index, declaration.m_row);
9166
9167 stream << " = ivec2(" << declaration.m_index << ", " << declaration.m_row << ");";
9168
9169 return stream;
9170 }
9171
9172 /* Methods */
9173 /** Build program to test specified shader stage
9174 *
9175 * Throws exception in case of any failure
9176 *
9177 * @param stage Stage id
9178 *
9179 * @return Program id
9180 **/
buildProgramToTestShaderStage(shaderStage stage)9181 GLuint buildProgramToTestShaderStage(shaderStage stage)
9182 {
9183 static const char* const boilerplate_fragment_shader_code =
9184 "#version 400 core\n"
9185 "#extension GL_ARB_shader_image_load_store : require\n"
9186 "\n"
9187 "precision highp float;\n"
9188 "\n"
9189 "void main()\n"
9190 "{\n"
9191 " discard;\n"
9192 "}\n";
9193
9194 static const char* const boilerplate_tesselation_evaluation_shader_code =
9195 "#version 400 core\n"
9196 "#extension GL_ARB_shader_image_load_store : require\n"
9197 "\n"
9198 "precision highp float;\n"
9199 "\n"
9200 "layout(quads, equal_spacing, ccw) in;\n"
9201 "\n"
9202 "void main()\n"
9203 "{\n"
9204 "\n"
9205 "}\n";
9206
9207 static const char* const boilerplate_vertex_shader_code =
9208 "#version 400 core\n"
9209 "#extension GL_ARB_shader_image_load_store : require\n"
9210 "\n"
9211 "precision highp float;\n"
9212 "\n"
9213 "layout(location = 0) in vec4 i_position;\n"
9214 "\n"
9215 "void main()\n"
9216 "{\n"
9217 " gl_Position = i_position;\n"
9218 "}\n";
9219
9220 const char* fragment_shader_code = boilerplate_fragment_shader_code;
9221 const char* geometry_shader_code = 0;
9222 bool is_program_built = true;
9223 GLuint program_object_id = 0;
9224 const char* tesselation_control_shader_code = 0;
9225 const char* tesselation_evaluation_shader_code = 0;
9226 std::string tested_shader_stage_code;
9227 const char* vertex_shader_code = boilerplate_vertex_shader_code;
9228
9229 /* Get source code for tested shader stage */
9230 prepareShaderForTestedShaderStage(stage, tested_shader_stage_code);
9231
9232 if (true == tested_shader_stage_code.empty())
9233 {
9234 return 0;
9235 }
9236
9237 /* Set up source code for all required stages */
9238 switch (stage)
9239 {
9240 case fragmentShaderStage:
9241 fragment_shader_code = tested_shader_stage_code.c_str();
9242 break;
9243
9244 case geometryShaderStage:
9245 geometry_shader_code = tested_shader_stage_code.c_str();
9246 break;
9247
9248 case tesselationControlShaderStage:
9249 tesselation_control_shader_code = tested_shader_stage_code.c_str();
9250 tesselation_evaluation_shader_code = boilerplate_tesselation_evaluation_shader_code;
9251 break;
9252
9253 case tesselationEvalutaionShaderStage:
9254 tesselation_evaluation_shader_code = tested_shader_stage_code.c_str();
9255 break;
9256
9257 case vertexShaderStage:
9258 vertex_shader_code = tested_shader_stage_code.c_str();
9259 break;
9260
9261 default:
9262 TCU_FAIL("Invalid shader stage");
9263 }
9264
9265 /* Build program */
9266 program_object_id =
9267 BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
9268 geometry_shader_code, fragment_shader_code, &is_program_built);
9269
9270 /* Check if program was built */
9271 if (false == is_program_built)
9272 {
9273 throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__);
9274 }
9275
9276 /* Done */
9277 return program_object_id;
9278 }
9279
9280 /** Create texture to test given shader stage
9281 *
9282 * Throws exception in case of any failure
9283 *
9284 * @param stage Stage id
9285 *
9286 * @return Texture id
9287 **/
createTextureToTestShaderStage(shaderStage stage)9288 GLuint createTextureToTestShaderStage(shaderStage stage)
9289 {
9290 GLenum error = glGetError();
9291 const GLint max_image_uniforms = getMaximumImageUniformsForStage(stage);
9292 GLuint texture_id = 0;
9293 std::vector<GLint> texture_data;
9294
9295 const GLsizei height = 2;
9296 const GLsizei width = max_image_uniforms;
9297
9298 if (m_min_required_image_uniforms > max_image_uniforms)
9299 {
9300 return 0;
9301 }
9302
9303 /* Generate texture id */
9304 glGenTextures(1, &texture_id);
9305 GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures");
9306
9307 /* Bind texture */
9308 glBindTexture(GL_TEXTURE_2D, texture_id);
9309 error = glGetError();
9310 if (GL_NO_ERROR != error)
9311 {
9312 glDeleteTextures(1, &texture_id);
9313 GLU_EXPECT_NO_ERROR(error, "BindTexture");
9314 }
9315
9316 /* Prepare storage for texture data */
9317 texture_data.resize(width * height);
9318 for (GLint i = 0; i < max_image_uniforms; ++i)
9319 {
9320 texture_data[i] = getExpectedValue(i);
9321 texture_data[i + width] = 0;
9322 }
9323
9324 /* Create first level of texture */
9325 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R32I, width, height, 0 /*border */, GL_RED_INTEGER, GL_INT,
9326 &texture_data[0]);
9327 error = glGetError();
9328 if (GL_NO_ERROR != error)
9329 {
9330 glDeleteTextures(1, &texture_id);
9331 GLU_EXPECT_NO_ERROR(error, "TexImage2D");
9332 }
9333
9334 /* Make texture complete */
9335 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
9336 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
9337 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9338 error = glGetError();
9339 if (GL_NO_ERROR != error)
9340 {
9341 glDeleteTextures(1, &texture_id);
9342 GLU_EXPECT_NO_ERROR(error, "TexParameteri");
9343 }
9344
9345 /* Done */
9346 return texture_id;
9347 }
9348
9349 /** Get value of texel for image at given index
9350 *
9351 * @param index Index of image uniform
9352 *
9353 * @return Value of texel
9354 **/
getExpectedValue(GLint index)9355 GLint getExpectedValue(GLint index)
9356 {
9357 // To fix denorm issues with r32f, rg16f and r11f_g11f_b10f
9358 // we set one bit in the exponent of each component of those pixel format
9359 return 0x40104200 + index;
9360 }
9361
9362 /** Get name of uniform at given index
9363 *
9364 * @param index Index of uniform
9365 * @param out_name Name of uniform
9366 **/
getImageUniformName(GLuint index,std::string & out_name)9367 void getImageUniformName(GLuint index, std::string& out_name)
9368 {
9369 std::stringstream stream;
9370
9371 writeImageUniformNameToStream(stream, index);
9372
9373 out_name = stream.str();
9374 }
9375
9376 /** Get maximum number of image uniforms allowed for given shader stage
9377 *
9378 * @param stage Stage id
9379 *
9380 * @return Maximum allowed image uniforms
9381 **/
getMaximumImageUniformsForStage(shaderStage stage)9382 GLint getMaximumImageUniformsForStage(shaderStage stage)
9383 {
9384 GLint max_image_uniforms = 0;
9385 GLenum pname = 0;
9386
9387 switch (stage)
9388 {
9389 case fragmentShaderStage:
9390 pname = GL_MAX_FRAGMENT_IMAGE_UNIFORMS;
9391 break;
9392
9393 case geometryShaderStage:
9394 pname = GL_MAX_GEOMETRY_IMAGE_UNIFORMS;
9395 break;
9396
9397 case tesselationControlShaderStage:
9398 pname = GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS;
9399 break;
9400
9401 case tesselationEvalutaionShaderStage:
9402 pname = GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS;
9403 break;
9404
9405 case vertexShaderStage:
9406 pname = GL_MAX_VERTEX_IMAGE_UNIFORMS;
9407 break;
9408
9409 default:
9410 TCU_FAIL("Invalid shader stage");
9411 }
9412
9413 glGetIntegerv(pname, &max_image_uniforms);
9414 GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv");
9415
9416 return max_image_uniforms;
9417 }
9418
9419 /** Prepare source for tested shader stage
9420 *
9421 * @param stage Stage id
9422 * @param out_code Source code
9423 **/
prepareShaderForTestedShaderStage(shaderStage stage,std::string & out_code)9424 void prepareShaderForTestedShaderStage(shaderStage stage, std::string& out_code)
9425 {
9426 GLint max_image_uniforms = getMaximumImageUniformsForStage(stage);
9427 const char* stage_specific_layout = "";
9428 const char* stage_specific_predicate = "true";
9429 std::stringstream stream;
9430
9431 if (m_min_required_image_uniforms > max_image_uniforms)
9432 {
9433 return;
9434 }
9435
9436 /* Expected result follows
9437 *
9438 * #version 400 core
9439 * #extension GL_ARB_shader_image_load_store : require
9440 *
9441 * precision highp float;
9442 *
9443 * stage_specific_layout goes here
9444 *
9445 * Uniform declarations go here
9446 *
9447 * void main()
9448 * {
9449 * const ivec2 row_0_coordinates(0, 0);
9450 * const ivec2 row_1_coordinates(0, 1);
9451 *
9452 * For each index <0, GL_MAX_*_IMAGE_UNIFORMS>
9453 *
9454 * vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates);
9455 *
9456 * imageStore(u_image_0, row_0_coordinates, -loaded_value_0);
9457 * imageStore(u_image_0, row_1_coordinates, loaded_value_0);
9458 * }
9459 */
9460
9461 /* Get piece of code specific for stage */
9462 switch (stage)
9463 {
9464 case fragmentShaderStage:
9465 break;
9466
9467 case geometryShaderStage:
9468 stage_specific_layout = "layout(points) in;\n"
9469 "layout(points, max_vertices = 1) out;\n"
9470 "\n";
9471 break;
9472
9473 case tesselationControlShaderStage:
9474 stage_specific_layout = "layout(vertices = 4) out;\n"
9475 "\n";
9476 stage_specific_predicate = "gl_InvocationID == 0";
9477 break;
9478
9479 case tesselationEvalutaionShaderStage:
9480 stage_specific_layout = "layout(quads, equal_spacing, ccw) in;\n"
9481 "\n";
9482 break;
9483
9484 case vertexShaderStage:
9485 break;
9486
9487 default:
9488 TCU_FAIL("Invalid shader stage");
9489 }
9490
9491 /* Preamble */
9492 stream << "#version 400 core\n"
9493 "#extension GL_ARB_shader_image_load_store : require\n"
9494 "\n"
9495 "precision highp float;\n"
9496 "\n"
9497 << stage_specific_layout;
9498
9499 /* Image uniforms declarations */
9500 for (GLint i = 0; i < max_image_uniforms; ++i)
9501 {
9502 stream << imageUniformDeclaration(i) << "\n";
9503 }
9504
9505 /* Main opening */
9506 stream << "\n"
9507 "void main()\n"
9508 "{\n";
9509
9510 stream << " if (" << stage_specific_predicate << ")\n";
9511 stream << " {\n";
9512
9513 /* imageLoad and imageStores for each uniform */
9514 for (GLint i = 0; i < max_image_uniforms; ++i)
9515 {
9516 stream << " " << coordinatesVariableDeclaration(i, 0) << "\n"
9517 << " " << coordinatesVariableDeclaration(i, 1) << "\n"
9518 << "\n"
9519 << " " << imageLoadCall(i) << "\n"
9520 << "\n"
9521 << " " << imageStoreCall(i, 0) << "\n"
9522 << " " << imageStoreCall(i, 1) << "\n";
9523
9524 if (max_image_uniforms > i + 1)
9525 {
9526 stream << "\n";
9527 }
9528 }
9529
9530 stream << " }\n";
9531
9532 /* Main closing */
9533 stream << "}\n\n";
9534
9535 /* Done */
9536 out_code = stream.str();
9537 }
9538
9539 /** Test given shader stage
9540 *
9541 * @param stage Stage id
9542 *
9543 * @return m_test_not_supported if shader stage does not support at least m_min_required_image_uniforms image uniforms;
9544 * testFailed when test result is negative;
9545 * m_test_passed when test result is positive;
9546 **/
testShaderStage(shaderStage stage)9547 testResult testShaderStage(shaderStage stage)
9548 {
9549 std::string image_uniform_name;
9550 static const GLint invalid_uniform_location = -1;
9551 const GLint max_image_uniforms = getMaximumImageUniformsForStage(stage);
9552 GLenum primitive_mode = GL_POINTS;
9553 GLuint program_id = 0;
9554 testResult result = testPassed;
9555 std::vector<GLint> texture_data;
9556 GLuint texture_id = 0;
9557
9558 static const GLuint height = 2;
9559 const GLuint width = max_image_uniforms;
9560
9561 const GLuint positive_value_index = width;
9562 static const GLuint negated_value_index = 0;
9563
9564 if (m_min_required_image_uniforms > max_image_uniforms)
9565 {
9566 return testNotSupported;
9567 }
9568
9569 /* Select program and texture ids for given stage */
9570 switch (stage)
9571 {
9572 case fragmentShaderStage:
9573 program_id = m_program_to_test_fs_stage_id;
9574 texture_id = m_texture_to_test_fs_stage_id;
9575 break;
9576
9577 case geometryShaderStage:
9578 program_id = m_program_to_test_gs_stage_id;
9579 texture_id = m_texture_to_test_gs_stage_id;
9580 break;
9581
9582 case tesselationControlShaderStage:
9583 primitive_mode = GL_PATCHES;
9584 program_id = m_program_to_test_tcs_stage_id;
9585 texture_id = m_texture_to_test_tcs_stage_id;
9586 break;
9587
9588 case tesselationEvalutaionShaderStage:
9589 primitive_mode = GL_PATCHES;
9590 program_id = m_program_to_test_tes_stage_id;
9591 texture_id = m_texture_to_test_tes_stage_id;
9592 break;
9593
9594 case vertexShaderStage:
9595 program_id = m_program_to_test_vs_stage_id;
9596 texture_id = m_texture_to_test_vs_stage_id;
9597 break;
9598
9599 default:
9600 TCU_FAIL("Invalid shader stage");
9601 }
9602
9603 /* Set program */
9604 glUseProgram(program_id);
9605 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
9606
9607 /* Bind texture to image units */
9608 for (GLint i = 0; i < max_image_uniforms; ++i)
9609 {
9610 imageFormatDetails format_details;
9611 getImageUniformDeclarationDetails(i, format_details);
9612
9613 glBindImageTexture(i /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
9614 GL_READ_WRITE, format_details.m_image_unit_format);
9615 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
9616 }
9617
9618 /* Set all image uniforms to corresponding image units */
9619 for (GLint i = 0; i < max_image_uniforms; ++i)
9620 {
9621 /* Get name */
9622 getImageUniformName(i, image_uniform_name);
9623
9624 /* Get location */
9625 GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name.c_str());
9626 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
9627
9628 if (invalid_uniform_location == image_uniform_location)
9629 {
9630 throw tcu::InternalError("Uniform location is not available", image_uniform_name.c_str(), __FILE__,
9631 __LINE__);
9632 }
9633
9634 /* Set uniform value */
9635 glUniform1i(image_uniform_location, i /* image_unit */);
9636 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
9637 }
9638
9639 /* Execute draw */
9640 glDrawArrays(primitive_mode, 0 /* first vertex */, 1 /* one vertex */);
9641 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
9642
9643 glMemoryBarrier(GL_ALL_BARRIER_BITS);
9644
9645 texture_data.resize(width * height);
9646
9647 /* Get texture data */
9648 glBindTexture(GL_TEXTURE_2D, texture_id);
9649 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
9650
9651 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_INT, &texture_data[0]);
9652 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
9653
9654 /* Verify each image uniform */
9655 for (GLint i = 0; i < max_image_uniforms; ++i)
9656 {
9657 imageFormatDetails format_details;
9658 getImageUniformDeclarationDetails(i, format_details);
9659
9660 if (false ==
9661 format_details.m_verification_routine(getExpectedValue(i), texture_data[positive_value_index + i],
9662 texture_data[negated_value_index + i]))
9663 {
9664 m_context.getTestContext().getLog()
9665 << tcu::TestLog::Message << "Invalid result!"
9666 << " Image format: " << format_details.m_image_format << " Original value: "
9667 << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16) << getExpectedValue(i)
9668 << " Copied value: "
9669 << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16)
9670 << texture_data[positive_value_index + i] << " Negated value: "
9671 << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16)
9672 << texture_data[negated_value_index + i] << tcu::TestLog::EndMessage;
9673
9674 result = testFailed;
9675 }
9676 }
9677
9678 /* Done */
9679 return result;
9680 }
9681
9682 /** Verifies if original_value, positive_value and negated_value match
9683 *
9684 * @tparam T Type used during verification process, it should match float values by size
9685 *
9686 * @param original_value Original value of texel, used when creating a texture
9687 * @param positive_value Value stored by shader as read
9688 * @param negated_value Value stored by shader after negation
9689 *
9690 * @return true if values match, false otherwise
9691 **/
9692 template <typename T>
verifyFloat(GLint original_value,GLint positive_value,GLint negated_value)9693 static bool verifyFloat(GLint original_value, GLint positive_value, GLint negated_value)
9694 {
9695 if (original_value != positive_value)
9696 {
9697 return false;
9698 }
9699
9700 static const GLuint n_elements = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */
9701 static const GLuint sign_bit_index = sizeof(T) * 8 - 1; /* 7, 15, 31 */
9702 static const T sign_bit_mask = 1 << sign_bit_index; /* 0x80.. */
9703 static const T sign_bit_inv_mask = (T)~sign_bit_mask; /* 0x7f.. */
9704
9705 const T* positive_elements = (T*)&positive_value;
9706 const T* negated_elements = (T*)&negated_value;
9707
9708 for (GLuint i = 0; i < n_elements; ++i)
9709 {
9710 const T positive_element = positive_elements[i];
9711 const T negated_element = negated_elements[i];
9712
9713 const T positive_sign_bit = positive_element & sign_bit_mask;
9714 const T negated_sign_bit = negated_element & sign_bit_mask;
9715
9716 const T positive_data = positive_element & sign_bit_inv_mask;
9717 const T negated_data = negated_element & sign_bit_inv_mask;
9718
9719 /* Compare data bits */
9720 if (positive_data != negated_data)
9721 {
9722 return false;
9723 }
9724
9725 /* Verify that sign bit is inverted */
9726 if (positive_sign_bit == negated_sign_bit)
9727 {
9728 return false;
9729 }
9730 }
9731
9732 return true;
9733 }
9734
9735 /** Verifies if original_value, positive_value and negated_value match
9736 *
9737 * @tparam T Type used during verification process, it should match float values by size
9738 *
9739 * @param original_value Original value of texel, used when creating a texture
9740 * @param positive_value Value stored by shader as read
9741 * @param negated_value Value stored by shader after negation
9742 *
9743 * @return true if values match, false otherwise
9744 **/
9745 template <typename T>
verifyFloatSignedNorm(GLint original_value,GLint positive_value,GLint negated_value)9746 static bool verifyFloatSignedNorm(GLint original_value, GLint positive_value, GLint negated_value)
9747 {
9748 if (original_value != positive_value)
9749 {
9750 return false;
9751 }
9752
9753 static const GLuint n_elements = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */
9754
9755 const T* positive_elements = (T*)&positive_value;
9756 const T* negated_elements = (T*)&negated_value;
9757
9758 for (GLuint i = 0; i < n_elements; ++i)
9759 {
9760 const T positive_element = positive_elements[i];
9761 const T negated_element = negated_elements[i];
9762
9763 /* Compare data bits */
9764 if (positive_element != -negated_element)
9765 {
9766 return false;
9767 }
9768 }
9769
9770 return true;
9771 }
9772
9773 /** Verifies if original_value, positive_value and negated_value match
9774 *
9775 * @tparam R Number of bits for red channel
9776 * @tparam G Number of bits for green channel
9777 * @tparam B Number of bits for blue channel
9778 * @tparam A Number of bits for alpha channel
9779 *
9780 * @param original_value Original value of texel, used when creating a texture
9781 * @param positive_value Value stored by shader as read
9782 * @param negated_value Value stored by shader after negation
9783 *
9784 * @return true if values match, false otherwise
9785 **/
9786 template <GLuint R, GLuint G, GLuint B, GLuint A, typename T>
verifyInteger(GLint original_value,GLint positive_value,GLint negated_value)9787 static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value)
9788 {
9789 if (original_value != positive_value)
9790 {
9791 return false;
9792 }
9793
9794 Integer<T, R, 0> positive_red(positive_value);
9795 Integer<T, R, 0> negated_red(negated_value);
9796
9797 Integer<T, G, R> positive_green(positive_value);
9798 Integer<T, G, R> negated_green(negated_value);
9799
9800 Integer<T, B, R + G> positive_blue(positive_value);
9801 Integer<T, B, R + G> negated_blue(negated_value);
9802
9803 Integer<T, A, R + G + B> positive_alpha(positive_value);
9804 Integer<T, A, R + G + B> negated_alpha(negated_value);
9805
9806 if (((0 != R) && (positive_red.GetNegated() != negated_red.Get())) ||
9807 ((0 != B) && (positive_blue.GetNegated() != negated_blue.Get())) ||
9808 ((0 != G) && (positive_green.GetNegated() != negated_green.Get())) ||
9809 ((0 != A) && (positive_alpha.GetNegated() != negated_alpha.Get())))
9810 {
9811 return false;
9812 }
9813
9814 return true;
9815 }
9816
9817 /** Verifies if original_value, positive_value and negated_value match
9818 *
9819 * @param original_value Original value of texel, used when creating a texture
9820 * @param positive_value Value stored by shader as read
9821 * @param negated_value Value stored by shader after negation
9822 *
9823 * @return true if values match, false otherwise
9824 **/
verifyInteger(GLint original_value,GLint positive_value,GLint negated_value)9825 static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value)
9826 {
9827 if (original_value != positive_value)
9828 {
9829 return false;
9830 }
9831
9832 if (positive_value != -negated_value)
9833 {
9834 return false;
9835 }
9836
9837 return true;
9838 }
9839
9840 /** Verifies if original_value, positive_value and negated_value match
9841 *
9842 * @param original_value Original value of texel, used when creating a texture
9843 * @param positive_value Value stored by shader as read
9844 * @param negated_value Value stored by shader after negation
9845 *
9846 * @return true if values match, false otherwise
9847 **/
9848 template <typename T>
verifyFloatUnsigned(GLint original_value,GLint positive_value,GLint negated_value)9849 static bool verifyFloatUnsigned(GLint original_value, GLint positive_value, GLint negated_value)
9850 {
9851 if (original_value != positive_value)
9852 {
9853 return false;
9854 }
9855
9856 if (0 != negated_value)
9857 {
9858 return false;
9859 }
9860
9861 return true;
9862 }
9863 };
9864
9865 /** Test "Early fragment tests" description follows.
9866 *
9867 * BasicGLSLEarlyFragTests verifies that:
9868 * - early z test is applied when enabled,
9869 * - early z test is not applied when disabled.
9870 *
9871 * Proposed modifications:
9872 * - verify that early z test does not discard all fragments when enabled,
9873 * - verify that early stencil test is applied when enabled,
9874 * - verify that early stencil test does not discard all fragments when
9875 * enabled,
9876 * - verify that early stencil test is not applied when disabled.
9877 *
9878 * Steps:
9879 * - prepare 2 programs that store 1.0 at red channel to image in fragment
9880 * shader stage:
9881 * a) one program should enable early fragment tests
9882 * ("layout(early_fragment_tests) in;"),
9883 * b) second program should disable early fragment tests,
9884 * - prepare frame buffer with 64x64 R32F color and GL_DEPTH_STENCIL
9885 * depth-stencil attachments,
9886 * - prepare 2D texture 64x64 R32F,
9887 * - enable depth test,
9888 * - verify that early z test is applied when enabled:
9889 * - use program enabling early fragment tests,
9890 * - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9891 * - fill texture with zeros,
9892 * - bind texture to image uniform,
9893 * - draw "full screen" quad (left bottom corner at -1,-1 and right top
9894 * corner at 1,1) at z: 0.75
9895 * - verify that texture is still filled with zeros,
9896 * - verify that early z test does not discard all fragments:
9897 * - use program enabling early fragment tests,
9898 * - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9899 * - fill texture with zeros,
9900 * - bind texture to image uniform,
9901 * - draw "full screen" quad at z: 0.25
9902 * - verify that texture is now filled with 1.0,
9903 * -verify that early z test is not applied when disabled:
9904 * - use program disabling early fragment tests,
9905 * - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9906 * - fill texture with zeros,
9907 * - bind texture to image uniform,
9908 * - draw "full screen" quad at z: 0.75
9909 * - verify that texture is now filled with 1.0.
9910 * - disable depth test
9911 * - enable stencil test
9912 * - verify that early stencil test is applied when enabled:
9913 * - use program enabling early fragment tests,
9914 * - clean frame buffer with color: 0, stencil: 0 and depth 1,
9915 * - fill texture with zeros,
9916 * - set stencil test to:
9917 * - <func> to GL_LESS,
9918 * - <ref> to 128,
9919 * - <mask> 0xffffffff,
9920 * - bind texture to image uniform,
9921 * - draw "full screen" quad at z: 0,
9922 * - verify that texture is still filled with zeros,
9923 * - verify that early stencil test does not discard all fragments:
9924 * - use program enabling early fragment tests,
9925 * - clean frame buffer with color: 0, stencil: 128 and depth 1,
9926 * - fill texture with zeros,
9927 * - set stencil test to:
9928 * - <func> to GL_LESS,
9929 * - <ref> to 0,
9930 * - <mask> 0xffffffff,
9931 * - bind texture to image uniform,
9932 * - draw "full screen" quad at z: 0,
9933 * - verify that texture is now filled with 1.0,
9934 * - verify that early stencil test is not applied when disabled:
9935 * - use program disabling early fragment tests,
9936 * - clean frame buffer with color: 0, stencil: 0 and depth 1,
9937 * - fill texture with zeros,
9938 * - set stencil test to:
9939 * - <func> to GL_LESS,
9940 * - <ref> to 128,
9941 * - <mask> 0xffffffff,
9942 * - bind texture to image uniform,
9943 * - draw "full screen" quad at z: 0,
9944 * - verify that texture is now filled with 1.0
9945 **/
9946 class ImageLoadStoreEarlyFragmentTestsTest : public ShaderImageLoadStoreBase
9947 {
9948 private:
9949 /* Constants */
9950 GLuint m_image_edge;
9951 static const GLint m_invalid_uniform_location = -1;
9952
9953 /* Types */
9954 /** Store id and uniform locations for a single program object
9955 *
9956 **/
9957 struct programDetails
9958 {
9959 GLint m_depth_uniform_location;
9960 GLint m_image_uniform_location;
9961 GLuint m_program_id;
9962
programDetailsgl4cts::__anonb14d91fe0111::ImageLoadStoreEarlyFragmentTestsTest::programDetails9963 programDetails()
9964 : m_depth_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location)
9965 , m_image_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location)
9966 , m_program_id(0)
9967 {
9968 /* Nothing to be done here */
9969 }
9970 };
9971
9972 /* Fileds */
9973 /* Storage for texture data */
9974 std::vector<GLfloat> m_clean_texture_data;
9975 std::vector<GLfloat> m_extracted_texture_data;
9976
9977 /* Program details */
9978 programDetails m_disabled_early_tests;
9979 programDetails m_enabled_early_tests;
9980
9981 /* Ids of GL objects */
9982 GLuint m_color_renderbuffer_id;
9983 GLuint m_depth_stencil_renderbuffer_id;
9984 GLuint m_framebuffer_id;
9985 GLuint m_texture_id;
9986 GLuint m_vertex_array_object_id;
9987
9988 public:
9989 /* Constructor */
ImageLoadStoreEarlyFragmentTestsTest()9990 ImageLoadStoreEarlyFragmentTestsTest()
9991 : m_image_edge(0)
9992 , m_color_renderbuffer_id(0)
9993 , m_depth_stencil_renderbuffer_id(0)
9994 , m_framebuffer_id(0)
9995 , m_texture_id(0)
9996 , m_vertex_array_object_id(0)
9997 {
9998 /* Nothing to be done here */
9999 }
10000
10001 /* Methods inherited from SubcaseBase */
Cleanup()10002 virtual long Cleanup()
10003 {
10004 /* Restore defaults */
10005 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
10006 glBindRenderbuffer(GL_RENDERBUFFER, 0);
10007 glBindTexture(GL_TEXTURE_2D, 0);
10008 glBindVertexArray(0);
10009 glDisable(GL_DEPTH_TEST);
10010 glDisable(GL_STENCIL_TEST);
10011 glUseProgram(0);
10012
10013 /* Delete objects */
10014 if (0 != m_disabled_early_tests.m_program_id)
10015 {
10016 glDeleteProgram(m_disabled_early_tests.m_program_id);
10017 m_disabled_early_tests.m_program_id = 0;
10018 }
10019
10020 if (0 != m_enabled_early_tests.m_program_id)
10021 {
10022 glDeleteProgram(m_enabled_early_tests.m_program_id);
10023 m_enabled_early_tests.m_program_id = 0;
10024 }
10025
10026 if (0 != m_color_renderbuffer_id)
10027 {
10028 glDeleteRenderbuffers(1, &m_color_renderbuffer_id);
10029 m_color_renderbuffer_id = 0;
10030 }
10031
10032 if (0 != m_depth_stencil_renderbuffer_id)
10033 {
10034 glDeleteRenderbuffers(1, &m_depth_stencil_renderbuffer_id);
10035 m_depth_stencil_renderbuffer_id = 0;
10036 }
10037
10038 if (0 != m_framebuffer_id)
10039 {
10040 glDeleteFramebuffers(1, &m_framebuffer_id);
10041 m_framebuffer_id = 0;
10042 }
10043
10044 if (0 != m_texture_id)
10045 {
10046 glDeleteTextures(1, &m_texture_id);
10047 m_texture_id = 0;
10048 }
10049
10050 if (0 != m_vertex_array_object_id)
10051 {
10052 glDeleteVertexArrays(1, &m_vertex_array_object_id);
10053 m_vertex_array_object_id = 0;
10054 }
10055
10056 /* Done */
10057 return NO_ERROR;
10058 }
10059
Run()10060 virtual long Run()
10061 {
10062 bool result = true;
10063
10064 /* Bind texture to first image unit */
10065 glBindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
10066 GL_READ_WRITE, GL_R32F);
10067 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
10068
10069 /* Run tests for depth test */
10070 if (false == testEarlyZ())
10071 {
10072 result = false;
10073 }
10074
10075 /* Run tests for stencil test */
10076 if (false == testEarlyStencil())
10077 {
10078 result = false;
10079 }
10080
10081 /* Return ERROR if any problem was found */
10082 if (false == result)
10083 {
10084 return ERROR;
10085 }
10086
10087 /* Done */
10088 return NO_ERROR;
10089 }
10090
Setup()10091 virtual long Setup()
10092 {
10093 m_image_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
10094
10095 /* Prepare storage for texture data */
10096 m_clean_texture_data.resize(m_image_edge * m_image_edge);
10097 m_extracted_texture_data.resize(m_image_edge * m_image_edge);
10098
10099 /* Prepare programs, framebuffer and texture */
10100 buildPrograms();
10101 createFramebuffer();
10102 createTexture();
10103
10104 /* Generate vertex array object */
10105 glGenVertexArrays(1, &m_vertex_array_object_id);
10106 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
10107
10108 /* Bind vertex array object */
10109 glBindVertexArray(m_vertex_array_object_id);
10110 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
10111
10112 /* Set clear color */
10113 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
10114 GLU_EXPECT_NO_ERROR(glGetError(), "ClearColor");
10115
10116 /* Done */
10117 return NO_ERROR;
10118 }
10119
10120 private:
10121 /** Build two programs: with enabled and disabled early fragment tests
10122 *
10123 **/
buildPrograms()10124 void buildPrograms()
10125 {
10126 static const char* const fragment_shader_with_disabled_early_tests =
10127 "#version 400 core\n"
10128 "#extension GL_ARB_shader_image_load_store : require\n"
10129 "\n"
10130 "precision highp float;\n"
10131 "\n"
10132 "layout(r32f) uniform image2D u_image;\n"
10133 "\n"
10134 "void main()\n"
10135 "{\n"
10136 " vec4 color = vec4(1.0, 0, 0, 0);\n"
10137 "\n"
10138 " imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n"
10139 "\n"
10140 " discard;\n"
10141 "}\n\n";
10142
10143 static const char* const fragment_shader_with_enabled_early_tests =
10144 "#version 400 core\n"
10145 "#extension GL_ARB_shader_image_load_store : require\n"
10146 "\n"
10147 "precision highp float;\n"
10148 "\n"
10149 "layout(early_fragment_tests) in;\n"
10150 "\n"
10151 "layout(r32f) uniform image2D u_image;\n"
10152 "\n"
10153 "void main()\n"
10154 "{\n"
10155 " vec4 color = vec4(1.0, 0, 0, 0);\n"
10156 "\n"
10157 " imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n"
10158 "\n"
10159 " discard;\n"
10160 "}\n\n";
10161
10162 static const char* const geometry_shader_code = "#version 400 core\n"
10163 "#extension GL_ARB_shader_image_load_store : require\n"
10164 "\n"
10165 "precision highp float;\n"
10166 "\n"
10167 "layout(points) in;\n"
10168 "layout(triangle_strip, max_vertices = 4) out;\n"
10169 "\n"
10170 "uniform float u_depth;\n"
10171 "\n"
10172 "void main()\n"
10173 "{\n"
10174 " // Left-bottom\n"
10175 " gl_Position = vec4(-1, -1, u_depth, 1);\n"
10176 " EmitVertex();\n"
10177 "\n"
10178 " // Left-top\n"
10179 " gl_Position = vec4(-1, 1, u_depth, 1);\n"
10180 " EmitVertex();\n"
10181 "\n"
10182 " // Right-bottom\n"
10183 " gl_Position = vec4( 1, -1, u_depth, 1);\n"
10184 " EmitVertex();\n"
10185 "\n"
10186 " // Right-top\n"
10187 " gl_Position = vec4( 1, 1, u_depth, 1);\n"
10188 " EmitVertex();\n"
10189 "}\n\n";
10190
10191 static const char* const vertex_shader_code = "#version 400 core\n"
10192 "#extension GL_ARB_shader_image_load_store : require\n"
10193 "\n"
10194 "precision highp float;\n"
10195 "\n"
10196 "void main()\n"
10197 "{\n"
10198 "}\n\n";
10199
10200 prepareProgramDetails(fragment_shader_with_disabled_early_tests, geometry_shader_code, vertex_shader_code,
10201 m_disabled_early_tests);
10202
10203 prepareProgramDetails(fragment_shader_with_enabled_early_tests, geometry_shader_code, vertex_shader_code,
10204 m_enabled_early_tests);
10205 }
10206
10207 /** Fill texture with zeros
10208 *
10209 **/
cleanTexture()10210 void cleanTexture()
10211 {
10212 glTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, m_image_edge, m_image_edge,
10213 GL_RED, GL_FLOAT, &m_clean_texture_data[0]);
10214 GLU_EXPECT_NO_ERROR(glGetError(), "TexSubImage2D");
10215 }
10216
10217 /** Create and bind (draw) framebuffer with color and depth-stencil attachments
10218 *
10219 **/
createFramebuffer()10220 void createFramebuffer()
10221 {
10222 /* Generate render buffers */
10223 glGenRenderbuffers(1, &m_color_renderbuffer_id);
10224 GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers");
10225
10226 glGenRenderbuffers(1, &m_depth_stencil_renderbuffer_id);
10227 GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers");
10228
10229 /* Generate and bind framebuffer object */
10230 glGenFramebuffers(1, &m_framebuffer_id);
10231 GLU_EXPECT_NO_ERROR(glGetError(), "GenFramebuffers");
10232
10233 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
10234 GLU_EXPECT_NO_ERROR(glGetError(), "BindFramebuffer");
10235
10236 /* Prepare color render buffer */
10237 glBindRenderbuffer(GL_RENDERBUFFER, m_color_renderbuffer_id);
10238 GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer");
10239
10240 glRenderbufferStorage(GL_RENDERBUFFER, GL_R32F, m_image_edge, m_image_edge);
10241 GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage");
10242
10243 /* Set up color attachment */
10244 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_color_renderbuffer_id);
10245 GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer");
10246
10247 /* Prepare depth-stencil render buffer */
10248 glBindRenderbuffer(GL_RENDERBUFFER, m_depth_stencil_renderbuffer_id);
10249 GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer");
10250
10251 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_image_edge, m_image_edge);
10252 GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage");
10253
10254 /* Set up depth-stencil attachment */
10255 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
10256 m_depth_stencil_renderbuffer_id);
10257 GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer");
10258 }
10259
10260 /** Create 2D R32F texture
10261 *
10262 **/
createTexture()10263 void createTexture()
10264 {
10265 glGenTextures(1, &m_texture_id);
10266 GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures");
10267
10268 glBindTexture(GL_TEXTURE_2D, m_texture_id);
10269 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
10270
10271 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, m_image_edge, m_image_edge);
10272 GLU_EXPECT_NO_ERROR(glGetError(), "TexStorage2D");
10273 }
10274
10275 /** Extracts red channel from texture and verify if all texels are set to specified value
10276 *
10277 * @param value Expected value
10278 *
10279 * @return true if all texel match expected value, false otherwise
10280 **/
isTextureFilledWithValue(GLfloat value)10281 bool isTextureFilledWithValue(GLfloat value)
10282 {
10283 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED, GL_FLOAT, &m_extracted_texture_data[0]);
10284 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
10285
10286 for (GLuint i = 0; i < m_image_edge * m_image_edge; ++i)
10287 {
10288 if (value != m_extracted_texture_data[i])
10289 {
10290 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texel at location " << i
10291 << " has invalid value: " << m_extracted_texture_data[i]
10292 << " expected: " << value << tcu::TestLog::EndMessage;
10293
10294 return false;
10295 }
10296 }
10297
10298 return true;
10299 }
10300
10301 /** Build program, extract location of uniforms and store results in programDetails instance
10302 *
10303 * Throws tcu::InternalError if uniforms are inactive
10304 *
10305 * @param fragment_shader_code Source of fragment shader
10306 * @param geometry_shader_code Source of geometry shader
10307 * @param vertex_shader_code Source of vertex shader
10308 * @param out_program_details Instance of programDetails
10309 **/
prepareProgramDetails(const char * fragment_shader_code,const char * geometry_shader_code,const char * vertex_shader_code,programDetails & out_program_details)10310 void prepareProgramDetails(const char* fragment_shader_code, const char* geometry_shader_code,
10311 const char* vertex_shader_code, programDetails& out_program_details)
10312 {
10313 static const char* const depth_uniform_name = "u_depth";
10314 static const char* const image_uniform_name = "u_image";
10315 bool is_program_built = true;
10316
10317 GLuint program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, geometry_shader_code,
10318 fragment_shader_code, &is_program_built);
10319
10320 if (false == is_program_built)
10321 {
10322 throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__);
10323 }
10324
10325 /* Get depth uniform location */
10326 GLint depth_uniform_location = glGetUniformLocation(program_id, depth_uniform_name);
10327 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
10328
10329 if (m_invalid_uniform_location == depth_uniform_location)
10330 {
10331 throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__);
10332 }
10333
10334 /* Get image uniform location */
10335 GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name);
10336 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
10337
10338 if (m_invalid_uniform_location == image_uniform_location)
10339 {
10340 throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__);
10341 }
10342
10343 /* Store results */
10344 out_program_details.m_depth_uniform_location = depth_uniform_location;
10345 out_program_details.m_image_uniform_location = image_uniform_location;
10346 out_program_details.m_program_id = program_id;
10347 }
10348
10349 /** Test if early fragment stencil test works as expected.
10350 *
10351 * @return true if successful, false otherwise
10352 **/
testEarlyStencil()10353 bool testEarlyStencil()
10354 {
10355 bool result = true;
10356
10357 glEnable(GL_STENCIL_TEST);
10358 GLU_EXPECT_NO_ERROR(glGetError(), "glEnable");
10359
10360 glClearDepthf(1.0f);
10361 GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf");
10362
10363 /* verify that early stencil test is applied when enabled */
10364 {
10365 glUseProgram(m_enabled_early_tests.m_program_id);
10366 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10367
10368 glClearStencil(0);
10369 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10370
10371 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10372 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10373
10374 cleanTexture();
10375
10376 glStencilFunc(GL_LESS, 128, 0xffffffff);
10377 GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10378
10379 glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10380 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10381
10382 glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.0f /* depth */);
10383 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10384
10385 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10386 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10387
10388 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10389 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10390
10391 if (false == isTextureFilledWithValue(0.0f))
10392 {
10393 m_context.getTestContext().getLog() << tcu::TestLog::Message
10394 << "Problem with early stencil test. It is not applied"
10395 << tcu::TestLog::EndMessage;
10396
10397 result = false;
10398 }
10399 }
10400
10401 /* verify that early stencil test does not discard all fragments */
10402 {
10403 glClearStencil(128);
10404 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10405
10406 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10407 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10408
10409 cleanTexture();
10410
10411 glStencilFunc(GL_LESS, 0, 0xffffffff);
10412 GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10413
10414 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10415 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10416
10417 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10418 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10419
10420 if (false == isTextureFilledWithValue(1.0f))
10421 {
10422 m_context.getTestContext().getLog()
10423 << tcu::TestLog::Message
10424 << "Problem with early stencil test. It discards fragments, that shall be drawn"
10425 << tcu::TestLog::EndMessage;
10426
10427 result = false;
10428 }
10429 }
10430
10431 /* verify that early stencil test is not applied when disabled */
10432 {
10433 glUseProgram(m_disabled_early_tests.m_program_id);
10434 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10435
10436 glClearStencil(0);
10437 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10438
10439 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10440 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10441
10442 cleanTexture();
10443
10444 glStencilFunc(GL_LESS, 128, 0xffffffff);
10445 GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10446
10447 glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10448 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10449
10450 glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.0f /* depth */);
10451 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10452
10453 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10454 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10455
10456 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10457 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10458
10459 if (false == isTextureFilledWithValue(1.0f))
10460 {
10461 m_context.getTestContext().getLog() << tcu::TestLog::Message
10462 << "Problem with early stencil test. It is applied when disabled"
10463 << tcu::TestLog::EndMessage;
10464
10465 result = false;
10466 }
10467 }
10468
10469 glDisable(GL_STENCIL_TEST);
10470 GLU_EXPECT_NO_ERROR(glGetError(), "Disable");
10471
10472 /* Done */
10473 return result;
10474 }
10475
10476 /** Test if early fragment depth test works as expected.
10477 *
10478 * @return true if successful, false otherwise
10479 **/
testEarlyZ()10480 bool testEarlyZ()
10481 {
10482 bool result = true;
10483
10484 glEnable(GL_DEPTH_TEST);
10485 GLU_EXPECT_NO_ERROR(glGetError(), "glEnable");
10486
10487 glClearDepthf(0.5f);
10488 GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf");
10489
10490 glClearStencil(0);
10491 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10492
10493 /* verify that early z test is applied when enabled */
10494 {
10495 glUseProgram(m_enabled_early_tests.m_program_id);
10496 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10497
10498 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10499 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10500
10501 cleanTexture();
10502
10503 glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10504 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10505
10506 glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.5f /* depth */);
10507 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10508
10509 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10510 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10511
10512 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10513 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10514
10515 if (false == isTextureFilledWithValue(0.0f))
10516 {
10517 m_context.getTestContext().getLog() << tcu::TestLog::Message
10518 << "Problem with early z test. It is not applied"
10519 << tcu::TestLog::EndMessage;
10520
10521 result = false;
10522 }
10523 }
10524
10525 /* verify that early z test does not discard all fragments */
10526 {
10527 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10528 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10529
10530 cleanTexture();
10531
10532 glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10533 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10534
10535 glUniform1f(m_enabled_early_tests.m_depth_uniform_location, -0.5f /* depth */);
10536 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10537
10538 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10539 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10540
10541 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10542 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10543
10544 if (false == isTextureFilledWithValue(1.0f))
10545 {
10546 m_context.getTestContext().getLog()
10547 << tcu::TestLog::Message << "Problem with early z test. It discards fragments, that shall be drawn"
10548 << tcu::TestLog::EndMessage;
10549
10550 result = false;
10551 }
10552 }
10553
10554 /* verify that early z test is not applied when disabled */
10555 {
10556 glUseProgram(m_disabled_early_tests.m_program_id);
10557 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10558
10559 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10560 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10561
10562 cleanTexture();
10563
10564 glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10565 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10566
10567 glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.5f /* depth */);
10568 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10569
10570 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10571 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10572
10573 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10574 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10575
10576 if (false == isTextureFilledWithValue(1.0f))
10577 {
10578 m_context.getTestContext().getLog() << tcu::TestLog::Message
10579 << "Problem with early z test. It is applied when disabled"
10580 << tcu::TestLog::EndMessage;
10581
10582 result = false;
10583 }
10584 }
10585
10586 glDisable(GL_DEPTH_TEST);
10587 GLU_EXPECT_NO_ERROR(glGetError(), "Disable");
10588
10589 /* Done */
10590 return result;
10591 }
10592 };
10593
10594 //-----------------------------------------------------------------------------
10595 // 4.1 NegativeUniform
10596 //-----------------------------------------------------------------------------
10597 class NegativeUniform : public ShaderImageLoadStoreBase
10598 {
10599 GLuint m_program;
10600
Setup()10601 virtual long Setup()
10602 {
10603 m_program = 0;
10604 return NO_ERROR;
10605 }
10606
Run()10607 virtual long Run()
10608 {
10609 const char* glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
10610 " gl_Position = i_position;" NL "}";
10611 const char* glsl_fs = "#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL
10612 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(0.0));" NL
10613 " discard;" NL "}";
10614 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
10615
10616 GLint max_image_units;
10617 glGetIntegerv(GL_MAX_IMAGE_UNITS, &max_image_units);
10618 glUseProgram(m_program);
10619
10620 glUniform1i(glGetUniformLocation(m_program, "g_image"), -1);
10621 if (glGetError() != GL_INVALID_VALUE)
10622 {
10623 m_context.getTestContext().getLog()
10624 << tcu::TestLog::Message << "glUniform1i should generate INVALID_VALUE when <value> is less than zero."
10625 << tcu::TestLog::EndMessage;
10626 return ERROR;
10627 }
10628 glUniform1i(glGetUniformLocation(m_program, "g_image"), max_image_units);
10629 if (glGetError() != GL_INVALID_VALUE)
10630 {
10631 m_context.getTestContext().getLog()
10632 << tcu::TestLog::Message
10633 << "glUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the value of "
10634 << "MAX_IMAGE_UNITS." << tcu::TestLog::EndMessage;
10635 return ERROR;
10636 }
10637
10638 GLint i = -3;
10639 glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
10640 if (glGetError() != GL_INVALID_VALUE)
10641 {
10642 m_context.getTestContext().getLog()
10643 << tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is less than zero."
10644 << tcu::TestLog::EndMessage;
10645 return ERROR;
10646 }
10647 i = max_image_units + 1;
10648 glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
10649 if (glGetError() != GL_INVALID_VALUE)
10650 {
10651 m_context.getTestContext().getLog()
10652 << tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is greater "
10653 "than or equal to the value of MAX_IMAGE_UNITS."
10654 << tcu::TestLog::EndMessage;
10655 return ERROR;
10656 }
10657
10658 glUniform1ui(glGetUniformLocation(m_program, "g_image"), 0);
10659 if (glGetError() != GL_INVALID_OPERATION)
10660 {
10661 m_context.getTestContext().getLog()
10662 << tcu::TestLog::Message
10663 << "glUniform1iv should generate INVALID_OPERATION if the location refers to an image variable."
10664 << tcu::TestLog::EndMessage;
10665 return ERROR;
10666 }
10667 glUniform2i(glGetUniformLocation(m_program, "g_image"), 0, 0);
10668 if (glGetError() != GL_INVALID_OPERATION)
10669 {
10670 m_context.getTestContext().getLog()
10671 << tcu::TestLog::Message
10672 << "glUniform2i should generate INVALID_OPERATION if the location refers to an image variable."
10673 << tcu::TestLog::EndMessage;
10674 return ERROR;
10675 }
10676
10677 {
10678 glUseProgram(0);
10679
10680 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), -1);
10681 if (glGetError() != GL_INVALID_VALUE)
10682 {
10683 m_context.getTestContext().getLog()
10684 << tcu::TestLog::Message
10685 << "glProgramUniform1i should generate INVALID_VALUE when <value> is less than zero."
10686 << tcu::TestLog::EndMessage;
10687 return ERROR;
10688 }
10689 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), max_image_units);
10690 if (glGetError() != GL_INVALID_VALUE)
10691 {
10692 m_context.getTestContext().getLog()
10693 << tcu::TestLog::Message
10694 << "glProgramUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the "
10695 "value of MAX_IMAGE_UNITS."
10696 << tcu::TestLog::EndMessage;
10697 return ERROR;
10698 }
10699
10700 GLint ii = -3;
10701 glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii);
10702 if (glGetError() != GL_INVALID_VALUE)
10703 {
10704 m_context.getTestContext().getLog()
10705 << tcu::TestLog::Message
10706 << "glProgramUniform1iv should generate INVALID_VALUE when <value> is less than zero."
10707 << tcu::TestLog::EndMessage;
10708 return ERROR;
10709 }
10710 ii = max_image_units + 1;
10711 glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii);
10712 if (glGetError() != GL_INVALID_VALUE)
10713 {
10714 m_context.getTestContext().getLog()
10715 << tcu::TestLog::Message << "glProgramUniform1iv should generate INVALID_VALUE when <value> "
10716 "is greater than or equal to the value of MAX_IMAGE_UNITS."
10717 << tcu::TestLog::EndMessage;
10718 return ERROR;
10719 }
10720
10721 glProgramUniform1ui(m_program, glGetUniformLocation(m_program, "g_image"), 0);
10722 if (glGetError() != GL_INVALID_OPERATION)
10723 {
10724 m_context.getTestContext().getLog()
10725 << tcu::TestLog::Message << "glProgramUniform1ui should generate INVALID_OPERATION if the "
10726 "location refers to an image variable."
10727 << tcu::TestLog::EndMessage;
10728 return ERROR;
10729 }
10730 glProgramUniform2i(m_program, glGetUniformLocation(m_program, "g_image"), 0, 0);
10731 if (glGetError() != GL_INVALID_OPERATION)
10732 {
10733 m_context.getTestContext().getLog()
10734 << tcu::TestLog::Message << "glProgramUniform2i should generate INVALID_OPERATION if the "
10735 "location refers to an image variable."
10736 << tcu::TestLog::EndMessage;
10737 return ERROR;
10738 }
10739 }
10740
10741 return NO_ERROR;
10742 }
10743
Cleanup()10744 virtual long Cleanup()
10745 {
10746 glUseProgram(0);
10747 glDeleteProgram(m_program);
10748 return NO_ERROR;
10749 }
10750 };
10751 //-----------------------------------------------------------------------------
10752 // 4.2 NegativeBind
10753 //-----------------------------------------------------------------------------
10754 class NegativeBind : public ShaderImageLoadStoreBase
10755 {
Setup()10756 virtual long Setup()
10757 {
10758 return NO_ERROR;
10759 }
10760
Run()10761 virtual long Run()
10762 {
10763 glBindImageTexture(100, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
10764 if (glGetError() != GL_INVALID_VALUE)
10765 {
10766 m_context.getTestContext().getLog()
10767 << tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <unit> is "
10768 "greater than or equal to the value of MAX_IMAGE_UNITS."
10769 << tcu::TestLog::EndMessage;
10770 return ERROR;
10771 }
10772
10773 glBindImageTexture(0, 123, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
10774 if (glGetError() != GL_INVALID_VALUE)
10775 {
10776 m_context.getTestContext().getLog()
10777 << tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <texture> is not "
10778 "the name of an existing texture object."
10779 << tcu::TestLog::EndMessage;
10780 return ERROR;
10781 }
10782
10783 glBindImageTexture(1, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA + 1234);
10784 if (glGetError() != GL_INVALID_VALUE)
10785 {
10786 m_context.getTestContext().getLog()
10787 << tcu::TestLog::Message
10788 << "BindImageTexture should generate INVALID_VALUE if <format> is not a legal format."
10789 << tcu::TestLog::EndMessage;
10790 return ERROR;
10791 }
10792 return NO_ERROR;
10793 }
10794
Cleanup()10795 virtual long Cleanup()
10796 {
10797 return NO_ERROR;
10798 }
10799 };
10800 //-----------------------------------------------------------------------------
10801 // 4.3 NegativeCompileErrors
10802 //-----------------------------------------------------------------------------
10803 class NegativeCompileErrors : public ShaderImageLoadStoreBase
10804 {
Run()10805 virtual long Run()
10806 {
10807 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10808 "layout(rgba32f) writeonly readonly uniform image2D g_image;" NL "void main() {" NL
10809 " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10810 return ERROR;
10811
10812 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10813 "layout(rgba32f) writeonly uniform image2D g_image;" NL "void main() {" NL
10814 " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10815 return ERROR;
10816
10817 if (!Compile("#version 420 core" NL "in vec4 i_color;" NL "layout(location = 0) out vec4 o_color;" NL
10818 "layout(rgba32f) readonly uniform image2D g_image;" NL "void main() {" NL
10819 " imageStore(g_image, ivec2(0), i_color);" NL " o_color = i_color;" NL "}"))
10820 return ERROR;
10821
10822 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform image2D g_image;" NL
10823 "void main() {" NL " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10824 return ERROR;
10825
10826 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10827 "readonly uniform image2D g_image;" NL "void main() {" NL
10828 " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10829 return ERROR;
10830
10831 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10832 "layout(rg16i) uniform image1D g_image;" NL "void main() {" NL " o_color = vec4(1.0);" NL "}"))
10833 return ERROR;
10834
10835 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10836 "layout(rg16) uniform iimage2D g_image;" NL "void main() {" NL " o_color = vec4(1.0);" NL "}"))
10837 return ERROR;
10838
10839 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10840 "layout(r32f) coherent uniform image2D g_image;" NL "void main() {" NL
10841 " imageAtomicAdd(g_image, ivec2(1), 10);" NL " o_color = vec4(1.0);" NL "}"))
10842 return ERROR;
10843
10844 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10845 "layout(r16i) coherent uniform iimage2D g_image;" NL "void main() {" NL
10846 " imageAtomicAdd(g_image, ivec2(1), 1u);" NL " o_color = vec4(1.0);" NL "}"))
10847 return ERROR;
10848
10849 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10850 "layout(r32ui) uniform iimage3D g_image;" NL "void main() {" NL
10851 " imageStore(g_image, ivec3(1), ivec4(1));" NL " o_color = vec4(1.0);" NL "}"))
10852 return ERROR;
10853
10854 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10855 "layout(rgba8) uniform uimage2DArray g_image;" NL "void main() {" NL
10856 " imageStore(g_image, ivec3(0), uvec4(1));" NL " o_color = vec4(1.0);" NL "}"))
10857 return ERROR;
10858
10859 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10860 "layout(rgba32f) coherent uniform image2D g_image;" NL "vec4 Load(image2D image) {" NL
10861 " return imageLoad(image, vec2(0));" NL "}" NL "void main() {" NL " o_color = Load(g_image);" NL
10862 "}"))
10863 return ERROR;
10864
10865 return NO_ERROR;
10866 }
10867
Compile(const std::string & source)10868 bool Compile(const std::string& source)
10869 {
10870 const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
10871
10872 const char* const src = source.c_str();
10873 glShaderSource(sh, 1, &src, NULL);
10874 glCompileShader(sh);
10875
10876 GLchar log[1024];
10877 glGetShaderInfoLog(sh, sizeof(log), NULL, log);
10878 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
10879 << log << tcu::TestLog::EndMessage;
10880
10881 GLint status;
10882 glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
10883 glDeleteShader(sh);
10884
10885 if (status == GL_TRUE)
10886 {
10887 m_context.getTestContext().getLog()
10888 << tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage;
10889 return false;
10890 }
10891
10892 return true;
10893 }
10894 };
10895 //-----------------------------------------------------------------------------
10896 // 4.4 NegativeLinkErrors
10897 //-----------------------------------------------------------------------------
10898 class NegativeLinkErrors : public ShaderImageLoadStoreBase
10899 {
Run()10900 virtual long Run()
10901 {
10902 if (!SupportedInVS(1))
10903 return NOT_SUPPORTED;
10904
10905 if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
10906 "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL
10907 " imageStore(g_image, gl_VertexID, vec4(0));" NL " gl_Position = i_position;" NL "}",
10908 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10909 "layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL
10910 " imageStore(g_image, ivec2(gl_FragCoord), vec4(1.0));" NL " o_color = vec4(1.0);" NL "}"))
10911 return ERROR;
10912
10913 if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
10914 "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL
10915 " imageStore(g_image, gl_VertexID, vec4(0));" NL " gl_Position = i_position;" NL "}",
10916 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10917 "layout(rg32f) uniform image1D g_image;" NL "void main() {" NL
10918 " imageStore(g_image, int(gl_FragCoord.x), vec4(1.0));" NL " o_color = vec4(1.0);" NL "}"))
10919 return ERROR;
10920
10921 return NO_ERROR;
10922 }
10923
Link(const std::string & vs,const std::string & fs)10924 bool Link(const std::string& vs, const std::string& fs)
10925 {
10926 const GLuint p = glCreateProgram();
10927
10928 const GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
10929 glAttachShader(p, vsh);
10930 glDeleteShader(vsh);
10931 const char* const vssrc = vs.c_str();
10932 glShaderSource(vsh, 1, &vssrc, NULL);
10933 glCompileShader(vsh);
10934
10935 const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
10936 glAttachShader(p, fsh);
10937 glDeleteShader(fsh);
10938 const char* const fssrc = fs.c_str();
10939 glShaderSource(fsh, 1, &fssrc, NULL);
10940 glCompileShader(fsh);
10941
10942 GLint status;
10943 glGetShaderiv(vsh, GL_COMPILE_STATUS, &status);
10944 if (status == GL_FALSE)
10945 {
10946 glDeleteProgram(p);
10947 m_context.getTestContext().getLog()
10948 << tcu::TestLog::Message << "VS compilation should be ok." << tcu::TestLog::EndMessage;
10949 return false;
10950 }
10951 glGetShaderiv(fsh, GL_COMPILE_STATUS, &status);
10952 if (status == GL_FALSE)
10953 {
10954 glDeleteProgram(p);
10955 m_context.getTestContext().getLog()
10956 << tcu::TestLog::Message << "FS compilation should be ok." << tcu::TestLog::EndMessage;
10957 return false;
10958 }
10959
10960 glLinkProgram(p);
10961
10962 GLchar log[1024];
10963 glGetProgramInfoLog(p, sizeof(log), NULL, log);
10964 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
10965 << log << tcu::TestLog::EndMessage;
10966
10967 glGetProgramiv(p, GL_LINK_STATUS, &status);
10968 glDeleteProgram(p);
10969
10970 if (status == GL_TRUE)
10971 {
10972 m_context.getTestContext().getLog()
10973 << tcu::TestLog::Message << "Link operation should fail." << tcu::TestLog::EndMessage;
10974 return false;
10975 }
10976
10977 return true;
10978 }
10979 };
10980
10981 /** Negative Test "Active image uniform limits", description follows.
10982 *
10983 * Program that exceeds resource limits should not compile and/or link.
10984 *
10985 * Steps:
10986 * - try to compile and link a program that uses too many image uniforms in
10987 * fragment shader stage,
10988 * - try to compile and link a program that uses too many image uniforms in
10989 * vertex shader stage,
10990 * - try to compile and link a program that uses too many image uniforms in
10991 * tessellation control shader stage,
10992 * - try to compile and link a program that uses too many image uniforms in
10993 * tessellation evaluation shader stage,
10994 * - try to compile and link a program that uses too many image uniforms in
10995 * geometry shader stage,
10996 * - try to compile and link a program that uses too many image uniforms in all
10997 * shader stages combined, any single stage should not exceed its limits, this
10998 * step might be impossible to fulfill.
10999 *
11000 * Test should use the following declaration of image uniforms:
11001 * layout(r32i) uniform iimage2D u_image[N_UNIFORMS];
11002 *
11003 * For cases where limit for single stage is tested, N_UNIFORMS should be
11004 * defined as gl_Max*ImageUniforms + 1, where gl_Max*ImageUniforms is constant
11005 * corresponding to tested shader stage.
11006 *
11007 * For case where limit for combined stages is tested:
11008 * - u_image name should be appended with the name of shader stage, like
11009 * u_image_vertex,
11010 * - N_UNIFORMS should be defined as gl_Max*ImageUniforms, where
11011 * gl_Max*ImageUniforms is constant corresponding to tested shader stage,
11012 * - compilation and linking shall succeed, when sum of all
11013 * gl_Max*ImageUniforms corresponding to shader stages is equal (or less) to
11014 * gl_MaxCombinedImageUniforms.
11015 *
11016 * All defined image uniforms have to be active. Each shader stage that declare
11017 * image uniforms should include following code snippet:
11018 * value = 1;
11019 * for (int i = 0; i < N_UNIFORMS; ++i)
11020 * {
11021 * value = imageAtomicAdd(u_image[i], coord, value);
11022 * }
11023 **/
11024 class ImageLoadStoreUniformLimitsTest : public ShaderImageLoadStoreBase
11025 {
11026 private:
11027 /* Fields */
11028 /* Results */
11029 bool m_result_for_combined;
11030 bool m_result_for_fragment_shader;
11031 bool m_result_for_geometry_shader;
11032 bool m_result_for_tesselation_control_shader;
11033 bool m_result_for_tesselatioon_evaluation_shader;
11034 bool m_result_for_vertex_shader;
11035
11036 public:
11037 /* Constructor */
ImageLoadStoreUniformLimitsTest()11038 ImageLoadStoreUniformLimitsTest()
11039 : m_result_for_combined(false)
11040 , m_result_for_fragment_shader(false)
11041 , m_result_for_geometry_shader(false)
11042 , m_result_for_tesselation_control_shader(false)
11043 , m_result_for_tesselatioon_evaluation_shader(false)
11044 , m_result_for_vertex_shader(false)
11045 {
11046 /* Nothing to be done */
11047 }
11048
11049 /* Methods inherited from SubcaseBase */
Cleanup()11050 virtual long Cleanup()
11051 {
11052 /* Done */
11053 return NO_ERROR;
11054 }
11055
Run()11056 virtual long Run()
11057 {
11058 m_context.getTestContext().getLog() << tcu::TestLog::Message
11059 << "This test tries to build invalid programs, expect error messages about "
11060 "exceeded number of active image uniforms"
11061 << tcu::TestLog::EndMessage;
11062
11063 testFragmentShaderStage();
11064 testGeometryShaderStage();
11065 testTesselationControlShaderStage();
11066 testTesselationEvaluationShaderStage();
11067 testVertexShaderStage();
11068 testCombinedShaderStages();
11069
11070 /* Return error if any stage failed */
11071 if ((false == m_result_for_combined) || (false == m_result_for_fragment_shader) ||
11072 (false == m_result_for_geometry_shader) || (false == m_result_for_tesselation_control_shader) ||
11073 (false == m_result_for_tesselatioon_evaluation_shader) || (false == m_result_for_vertex_shader))
11074 {
11075 return ERROR;
11076 }
11077
11078 /* Done */
11079 return NO_ERROR;
11080 }
11081
Setup()11082 virtual long Setup()
11083 {
11084 /* Done */
11085 return NO_ERROR;
11086 }
11087
11088 private:
11089 /** Test fragment shader stage
11090 *
11091 **/
testFragmentShaderStage()11092 void testFragmentShaderStage()
11093 {
11094 static const char* const fragment_shader_code =
11095 "#version 400 core\n"
11096 "#extension GL_ARB_shader_image_load_store : require\n"
11097 "\n"
11098 "precision highp float;\n"
11099 "\n"
11100 "#define N_UNIFORMS gl_MaxFragmentImageUniforms + 1\n"
11101 "\n"
11102 "flat in ivec2 vs_fs_coord;\n"
11103 "\n"
11104 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11105 "\n"
11106 "void main()\n"
11107 "{\n"
11108 " int value = 1;\n"
11109 "\n"
11110 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11111 " {\n"
11112 " value = imageAtomicAdd(u_image[i], vs_fs_coord, value);\n"
11113 " }\n"
11114 "\n"
11115 " discard;\n"
11116 "}\n\n";
11117
11118 static const char* const vertex_shader_code = "#version 400 core\n"
11119 "#extension GL_ARB_shader_image_load_store : require\n"
11120 "\n"
11121 "precision highp float;\n"
11122 "\n"
11123 " in ivec2 vs_in_coord;\n"
11124 "flat out ivec2 vs_fs_coord;\n"
11125 "\n"
11126 "void main()\n"
11127 "{\n"
11128 " vs_fs_coord = vs_in_coord;\n"
11129 "}\n\n";
11130
11131 m_result_for_fragment_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */,
11132 0 /* tesselation_control_shader_code */,
11133 0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11134
11135 if (false == m_result_for_fragment_shader)
11136 {
11137 m_context.getTestContext().getLog()
11138 << tcu::TestLog::Message
11139 << "Program which exceeds limit of GL_MAX_FRAGMENT_IMAGE_UNIFORMS was linked successfully."
11140 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11141 << fragment_shader_code << tcu::TestLog::EndMessage;
11142 }
11143 }
11144
11145 /** Test geometry shader stage
11146 *
11147 **/
testGeometryShaderStage()11148 void testGeometryShaderStage()
11149 {
11150 static const char* const fragment_shader_code = "#version 400 core\n"
11151 "#extension GL_ARB_shader_image_load_store : require\n"
11152 "\n"
11153 "precision highp float;\n"
11154 "\n"
11155 "void main()\n"
11156 "{\n"
11157 " discard;\n"
11158 "}\n\n";
11159
11160 static const char* const geometry_shader_code =
11161 "#version 400 core\n"
11162 "#extension GL_ARB_shader_image_load_store : require\n"
11163 "\n"
11164 "precision highp float;\n"
11165 "\n"
11166 "layout(points) in;\n"
11167 "layout(points, max_vertices = 1) out;\n"
11168 "\n"
11169 "#define N_UNIFORMS gl_MaxGeometryImageUniforms + 1\n"
11170 "\n"
11171 "in ivec2 vs_gs_coord[];\n"
11172 "\n"
11173 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11174 "\n"
11175 "void main()\n"
11176 "{\n"
11177 " int value = 1;\n"
11178 "\n"
11179 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11180 " {\n"
11181 " value = imageAtomicAdd(u_image[i], vs_gs_coord[0], value);\n"
11182 " }\n"
11183 "}\n\n";
11184
11185 static const char* const vertex_shader_code = "#version 400 core\n"
11186 "#extension GL_ARB_shader_image_load_store : require\n"
11187 "\n"
11188 "precision highp float;\n"
11189 "\n"
11190 "in ivec2 vs_in_coord;\n"
11191 "out ivec2 vs_gs_coord;\n"
11192 "\n"
11193 "void main()\n"
11194 "{\n"
11195 " vs_gs_coord = vs_in_coord;\n"
11196 "}\n\n";
11197
11198 m_result_for_geometry_shader =
11199 !doesProgramLink(fragment_shader_code, geometry_shader_code, 0 /* tesselation_control_shader_code */,
11200 0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11201
11202 if (false == m_result_for_geometry_shader)
11203 {
11204 m_context.getTestContext().getLog()
11205 << tcu::TestLog::Message
11206 << "Program which exceeds limit of GL_MAX_GEOMETRY_IMAGE_UNIFORMS was linked successfully."
11207 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11208 << geometry_shader_code << tcu::TestLog::EndMessage;
11209 }
11210 }
11211
11212 /** Test tesselation control shader stage
11213 *
11214 **/
testTesselationControlShaderStage()11215 void testTesselationControlShaderStage()
11216 {
11217 static const char* const fragment_shader_code = "#version 400 core\n"
11218 "#extension GL_ARB_shader_image_load_store : require\n"
11219 "\n"
11220 "precision highp float;\n"
11221 "\n"
11222 "void main()\n"
11223 "{\n"
11224 " discard;\n"
11225 "}\n\n";
11226
11227 static const char* const tesselation_control_shader_code =
11228 "#version 400 core\n"
11229 "#extension GL_ARB_shader_image_load_store : require\n"
11230 "\n"
11231 "precision highp float;\n"
11232 "\n"
11233 "layout(vertices = 4) out;\n"
11234 "\n"
11235 "#define N_UNIFORMS gl_MaxTessControlImageUniforms + 1\n"
11236 "\n"
11237 "in ivec2 vs_tcs_coord[];\n"
11238 "\n"
11239 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11240 "\n"
11241 "void main()\n"
11242 "{\n"
11243 " int value = 1;\n"
11244 "\n"
11245 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11246 " {\n"
11247 " value = imageAtomicAdd(u_image[i], vs_tcs_coord[0], value);\n"
11248 " }\n"
11249 "}\n\n";
11250
11251 static const char* const tesselation_evaluation_shader_code =
11252 "#version 400 core\n"
11253 "#extension GL_ARB_shader_image_load_store : require\n"
11254 "\n"
11255 "precision highp float;\n"
11256 "\n"
11257 "layout(quads, equal_spacing, ccw) in;\n"
11258 "\n"
11259 "void main()\n"
11260 "{\n"
11261 "}\n";
11262
11263 static const char* const vertex_shader_code = "#version 400 core\n"
11264 "#extension GL_ARB_shader_image_load_store : require\n"
11265 "\n"
11266 "precision highp float;\n"
11267 "\n"
11268 "in ivec2 vs_in_coord;\n"
11269 "out ivec2 vs_tcs_coord;\n"
11270 "\n"
11271 "void main()\n"
11272 "{\n"
11273 " vs_tcs_coord = vs_in_coord;\n"
11274 "}\n\n";
11275
11276 m_result_for_tesselation_control_shader =
11277 !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */, tesselation_control_shader_code,
11278 tesselation_evaluation_shader_code, vertex_shader_code);
11279
11280 if (false == m_result_for_tesselation_control_shader)
11281 {
11282 m_context.getTestContext().getLog()
11283 << tcu::TestLog::Message
11284 << "Program which exceeds limit of GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS was linked successfully."
11285 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11286 << tesselation_control_shader_code << tcu::TestLog::EndMessage;
11287 }
11288 }
11289
11290 /** Test teselation evaluation shader stage
11291 *
11292 **/
testTesselationEvaluationShaderStage()11293 void testTesselationEvaluationShaderStage()
11294 {
11295 static const char* const fragment_shader_code = "#version 400 core\n"
11296 "#extension GL_ARB_shader_image_load_store : require\n"
11297 "\n"
11298 "precision highp float;\n"
11299 "\n"
11300 "void main()\n"
11301 "{\n"
11302 " discard;\n"
11303 "}\n\n";
11304
11305 static const char* const tesselation_evaluation_shader_code =
11306 "#version 400 core\n"
11307 "#extension GL_ARB_shader_image_load_store : require\n"
11308 "\n"
11309 "precision highp float;\n"
11310 "\n"
11311 "layout(quads, equal_spacing, ccw) in;\n"
11312 "\n"
11313 "#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms + 1\n"
11314 "\n"
11315 "in ivec2 vs_tes_coord[];\n"
11316 "\n"
11317 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11318 "\n"
11319 "void main()\n"
11320 "{\n"
11321 " int value = 1;\n"
11322 "\n"
11323 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11324 " {\n"
11325 " value = imageAtomicAdd(u_image[i], vs_tes_coord[0], value);\n"
11326 " }\n"
11327 "}\n\n";
11328
11329 static const char* const vertex_shader_code = "#version 400 core\n"
11330 "#extension GL_ARB_shader_image_load_store : require\n"
11331 "\n"
11332 "precision highp float;\n"
11333 "\n"
11334 "in ivec2 vs_in_coord;\n"
11335 "out ivec2 vs_tes_coord;\n"
11336 "\n"
11337 "void main()\n"
11338 "{\n"
11339 " vs_tes_coord = vs_in_coord;\n"
11340 "}\n\n";
11341
11342 m_result_for_tesselatioon_evaluation_shader = !doesProgramLink(
11343 fragment_shader_code, 0 /* geometry_shader_code */, 0 /* tesselation_control_shader_code */,
11344 tesselation_evaluation_shader_code, vertex_shader_code);
11345
11346 if (false == m_result_for_tesselatioon_evaluation_shader)
11347 {
11348 m_context.getTestContext().getLog()
11349 << tcu::TestLog::Message
11350 << "Program which exceeds limit of GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS was linked successfully."
11351 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11352 << tesselation_evaluation_shader_code << tcu::TestLog::EndMessage;
11353 }
11354 }
11355
11356 /** Test vertex shader stage
11357 *
11358 **/
testVertexShaderStage()11359 void testVertexShaderStage()
11360 {
11361 static const char* const fragment_shader_code = "#version 400 core\n"
11362 "#extension GL_ARB_shader_image_load_store : require\n"
11363 "\n"
11364 "precision highp float;\n"
11365 "\n"
11366 "void main()\n"
11367 "{\n"
11368 " discard;\n"
11369 "}\n\n";
11370
11371 static const char* const vertex_shader_code =
11372 "#version 400 core\n"
11373 "#extension GL_ARB_shader_image_load_store : require\n"
11374 "\n"
11375 "precision highp float;\n"
11376 "\n"
11377 "in ivec2 vs_in_coord;\n"
11378 "\n"
11379 "#define N_UNIFORMS gl_MaxVertexImageUniforms + 1\n"
11380 "\n"
11381 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11382 "\n"
11383 "void main()\n"
11384 "{\n"
11385 " int value = 1;\n"
11386 "\n"
11387 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11388 " {\n"
11389 " value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n"
11390 " }\n"
11391 "}\n\n";
11392
11393 m_result_for_vertex_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */,
11394 0 /* tesselation_control_shader_code */,
11395 0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11396
11397 if (false == m_result_for_vertex_shader)
11398 {
11399 m_context.getTestContext().getLog()
11400 << tcu::TestLog::Message
11401 << "Program which exceeds limit of GL_MAX_VERTEX_IMAGE_UNIFORMS was linked successfully."
11402 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11403 << vertex_shader_code << tcu::TestLog::EndMessage;
11404 }
11405 }
11406
11407 /** Test combined shader stages
11408 *
11409 **/
testCombinedShaderStages()11410 void testCombinedShaderStages()
11411 {
11412 std::string fragment_shader_code =
11413 "#version 400 core\n"
11414 "#extension GL_ARB_shader_image_load_store : require\n"
11415 "\n"
11416 "precision highp float;\n"
11417 "\n"
11418 "#define N_UNIFORMS gl_MaxFragmentImageUniforms\n"
11419 "\n"
11420 "flat in ivec2 gs_fs_coord;\n"
11421 "\n"
11422 "layout(r32i) uniform iimage2D u_image_fragment[N_UNIFORMS];\n"
11423 "\n"
11424 "void main()\n"
11425 "{\n"
11426 " int value = 1;\n"
11427 "\n"
11428 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11429 " {\n"
11430 " value = imageAtomicAdd(u_image_fragment[i], gs_fs_coord, value);\n"
11431 " }\n"
11432 "\n"
11433 " discard;\n"
11434 "}\n\n";
11435
11436 std::string geometry_shader_code =
11437 "#version 400 core\n"
11438 "#extension GL_ARB_shader_image_load_store : require\n"
11439 "\n"
11440 "precision highp float;\n"
11441 "\n"
11442 "layout(points) in;\n"
11443 "layout(points, max_vertices = 1) out;\n"
11444 "\n"
11445 "#define N_UNIFORMS gl_MaxGeometryImageUniforms\n"
11446 "\n"
11447 "flat in ivec2 tes_gs_coord[];\n"
11448 "flat out ivec2 gs_fs_coord;\n"
11449 "\n"
11450 "#ifdef IMAGES\n"
11451 "layout(r32i) uniform iimage2D u_image_geometry[N_UNIFORMS];\n"
11452 "#endif\n"
11453 "\n"
11454 "void main()\n"
11455 "{\n"
11456 "#ifdef IMAGES\n"
11457 " int value = 1;\n"
11458 "\n"
11459 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11460 " {\n"
11461 " value = imageAtomicAdd(u_image_geometry[i], tes_gs_coord[0], value);\n"
11462 " }\n"
11463 "\n"
11464 "#endif\n"
11465 " gs_fs_coord = tes_gs_coord[0];\n"
11466 " EmitVertex();\n"
11467 "}\n\n";
11468
11469 std::string tesselation_control_shader_code =
11470 "#version 400 core\n"
11471 "#extension GL_ARB_shader_image_load_store : require\n"
11472 "\n"
11473 "precision highp float;\n"
11474 "\n"
11475 "layout(vertices = 4) out;\n"
11476 "\n"
11477 "#define N_UNIFORMS gl_MaxTessControlImageUniforms\n"
11478 "\n"
11479 "flat in ivec2 vs_tcs_coord[];\n"
11480 "flat out ivec2 tcs_tes_coord[];\n"
11481 "\n"
11482 "#ifdef IMAGES\n"
11483 "layout(r32i) uniform iimage2D u_image_tess_control[N_UNIFORMS];\n"
11484 "#endif\n"
11485 "\n"
11486 "void main()\n"
11487 "{\n"
11488 "#ifdef IMAGES\n"
11489 " int value = 1;\n"
11490 "\n"
11491 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11492 " {\n"
11493 " value = imageAtomicAdd(u_image_tess_control[i], vs_tcs_coord[0], value);\n"
11494 " }\n"
11495 "\n"
11496 "#endif\n"
11497 " tcs_tes_coord[gl_InvocationID] = vs_tcs_coord[0];\n"
11498 "}\n\n";
11499
11500 std::string tesselation_evaluation_shader_code =
11501 "#version 400 core\n"
11502 "#extension GL_ARB_shader_image_load_store : require\n"
11503 "\n"
11504 "precision highp float;\n"
11505 "\n"
11506 "layout(quads, equal_spacing, ccw) in;\n"
11507 "\n"
11508 "#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms\n"
11509 "\n"
11510 "flat in ivec2 tcs_tes_coord[];\n"
11511 "flat out ivec2 tes_gs_coord;\n"
11512 "\n"
11513 "#ifdef IMAGES\n"
11514 "layout(r32i) uniform iimage2D u_image_tess_evaluation[N_UNIFORMS];\n"
11515 "#endif\n"
11516 "\n"
11517 "void main()\n"
11518 "{\n"
11519 "#ifdef IMAGES\n"
11520 " int value = 1;\n"
11521 "\n"
11522 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11523 " {\n"
11524 " value = imageAtomicAdd(u_image_tess_evaluation[i], tcs_tes_coord[0], value);\n"
11525 " }\n"
11526 "\n"
11527 "#endif\n"
11528 " tes_gs_coord = tcs_tes_coord[0];\n"
11529 "}\n\n";
11530
11531 std::string vertex_shader_code =
11532 "#version 400 core\n"
11533 "#extension GL_ARB_shader_image_load_store : require\n"
11534 "\n"
11535 "precision highp float;\n"
11536 "\n"
11537 " in ivec2 vs_in_coord;\n"
11538 "flat out ivec2 vs_tcs_coord;\n"
11539 "\n"
11540 "#define N_UNIFORMS gl_MaxVertexImageUniforms\n"
11541 "\n"
11542 "#ifdef IMAGES\n"
11543 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11544 "#endif\n"
11545 "\n"
11546 "void main()\n"
11547 "{\n"
11548 "#ifdef IMAGES\n"
11549 " int value = 1;\n"
11550 "\n"
11551 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11552 " {\n"
11553 " value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n"
11554 " }\n"
11555 "\n"
11556 "#endif\n"
11557 " vs_tcs_coord = vs_tcs_coord;\n"
11558 "}\n\n";
11559
11560 /* Active image uniform limits */
11561 GLint max_combined_image_uniforms = 0;
11562 GLint max_fragment_image_uniforms = 0;
11563 GLint max_geometry_image_uniforms = 0;
11564 GLint max_tesselation_control_image_uniforms = 0;
11565 GLint max_tesselation_evaluation_image_uniforms = 0;
11566 GLint max_vertex_image_uniforms = 0;
11567
11568 /* Get limit values */
11569 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &max_combined_image_uniforms);
11570 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &max_fragment_image_uniforms);
11571 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &max_geometry_image_uniforms);
11572 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &max_tesselation_control_image_uniforms);
11573 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &max_tesselation_evaluation_image_uniforms);
11574 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &max_vertex_image_uniforms);
11575 GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv");
11576
11577 if (max_vertex_image_uniforms)
11578 vertex_shader_code.insert(18, "#define IMAGES\n");
11579 if (max_geometry_image_uniforms)
11580 geometry_shader_code.insert(18, "#define IMAGES\n");
11581 if (max_tesselation_control_image_uniforms)
11582 tesselation_control_shader_code.insert(18, "#define IMAGES\n");
11583 if (max_tesselation_evaluation_image_uniforms)
11584 tesselation_evaluation_shader_code.insert(18, "#define IMAGES\n");
11585
11586 /* Check if program builds */
11587 m_result_for_combined =
11588 !doesProgramLink(fragment_shader_code.c_str(),
11589 geometry_shader_code.c_str(),
11590 tesselation_control_shader_code.c_str(),
11591 tesselation_evaluation_shader_code.c_str(),
11592 vertex_shader_code.c_str());
11593
11594 /* Result depends on the limit values */
11595 if (max_combined_image_uniforms >=
11596 (max_fragment_image_uniforms + max_geometry_image_uniforms + max_tesselation_control_image_uniforms +
11597 max_tesselation_evaluation_image_uniforms + max_vertex_image_uniforms))
11598 {
11599 /* In this case, combined image uniforms limit cannot be exeeded, therefore successful linking is expected */
11600 m_result_for_combined = !m_result_for_combined;
11601
11602 if (false == m_result_for_combined)
11603 {
11604 m_context.getTestContext().getLog()
11605 << tcu::TestLog::Message << "There was an error while building a program."
11606 << " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n"
11607 << vertex_shader_code << "\nTesselation control shader code:\n"
11608 << tesselation_control_shader_code << "\nTesselation evaluation shader code:\n"
11609 << tesselation_evaluation_shader_code << "\nGeometry shader code:\n"
11610 << geometry_shader_code << "\nFragment shader code:\n"
11611 << fragment_shader_code << tcu::TestLog::EndMessage;
11612 }
11613 }
11614 else
11615 {
11616 /* In this case, combined image uniforms can be exceeded, therefore failed linking is expected */
11617 if (false == m_result_for_combined)
11618 {
11619 m_context.getTestContext().getLog()
11620 << tcu::TestLog::Message
11621 << "Program which exceeds limit of GL_MAX_COMBINED_IMAGE_UNIFORMS was linked successfully."
11622 << " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n"
11623 << vertex_shader_code << "\nTesselation control shader code:\n"
11624 << tesselation_control_shader_code << "\nTesselation evaluation shader code:\n"
11625 << tesselation_evaluation_shader_code << "\nGeometry shader code:\n"
11626 << geometry_shader_code << "\nFragment shader code:\n"
11627 << fragment_shader_code << tcu::TestLog::EndMessage;
11628 }
11629 }
11630 }
11631
11632 /** Check if program builds successfully
11633 *
11634 * @param fragment_shader_code Source code for fragment shader stage
11635 * @param geometry_shader_code Source code for geometry shader stage
11636 * @param tesselation_control_shader_code Source code for tesselation control shader stage
11637 * @param tesselation_evaluation_shader_code Source code for tesselation evaluation shader stage
11638 * @param vertex_shader_code Source code for vertex shader stage
11639 *
11640 * @return true if program was built without errors, false otherwise
11641 **/
doesProgramLink(const char * fragment_shader_code,const char * geometry_shader_code,const char * tesselation_control_shader_code,const char * tesselation_evaluation_shader_code,const char * vertex_shader_code)11642 bool doesProgramLink(const char* fragment_shader_code, const char* geometry_shader_code,
11643 const char* tesselation_control_shader_code, const char* tesselation_evaluation_shader_code,
11644 const char* vertex_shader_code)
11645 {
11646 bool is_program_built = true;
11647 GLuint program_id = 0;
11648
11649 program_id =
11650 BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
11651 geometry_shader_code, fragment_shader_code, &is_program_built);
11652
11653 if (0 != program_id)
11654 {
11655 glDeleteProgram(program_id);
11656 }
11657
11658 return is_program_built;
11659 }
11660 };
11661 }
11662
ShaderImageLoadStoreTests(deqp::Context & context)11663 ShaderImageLoadStoreTests::ShaderImageLoadStoreTests(deqp::Context& context)
11664 : TestCaseGroup(context, "shader_image_load_store", "")
11665 {
11666 }
11667
~ShaderImageLoadStoreTests(void)11668 ShaderImageLoadStoreTests::~ShaderImageLoadStoreTests(void)
11669 {
11670 }
11671
init()11672 void ShaderImageLoadStoreTests::init()
11673 {
11674 using namespace deqp;
11675 addChild(new TestSubcase(m_context, "basic-api-get", TestSubcase::Create<BasicAPIGet>));
11676 addChild(new TestSubcase(m_context, "basic-api-bind", TestSubcase::Create<BasicAPIBind>));
11677 addChild(new TestSubcase(m_context, "basic-api-barrier", TestSubcase::Create<BasicAPIBarrier>));
11678 addChild(new TestSubcase(m_context, "basic-api-texParam", TestSubcase::Create<BasicAPITexParam>));
11679 addChild(new TestSubcase(m_context, "basic-allFormats-store", TestSubcase::Create<BasicAllFormatsStore>));
11680 addChild(new TestSubcase(m_context, "basic-allFormats-load", TestSubcase::Create<BasicAllFormatsLoad>));
11681 addChild(new TestSubcase(m_context, "basic-allFormats-storeGeometryStages",
11682 TestSubcase::Create<BasicAllFormatsStoreGeometryStages>));
11683 addChild(new TestSubcase(m_context, "basic-allFormats-loadGeometryStages",
11684 TestSubcase::Create<BasicAllFormatsLoadGeometryStages>));
11685 addChild(new TestSubcase(m_context, "basic-allFormats-loadStoreComputeStage",
11686 TestSubcase::Create<BasicAllFormatsLoadStoreComputeStage>));
11687 addChild(new TestSubcase(m_context, "basic-allTargets-store", TestSubcase::Create<BasicAllTargetsStore>));
11688 addChild(new TestSubcase(m_context, "basic-allTargets-load-nonMS", TestSubcase::Create<BasicAllTargetsLoadNonMS>));
11689 addChild(new TestSubcase(m_context, "basic-allTargets-load-ms", TestSubcase::Create<BasicAllTargetsLoadMS>));
11690 addChild(new TestSubcase(m_context, "basic-allTargets-atomic", TestSubcase::Create<BasicAllTargetsAtomic>));
11691 addChild(
11692 new TestSubcase(m_context, "basic-allTargets-loadStoreVS", TestSubcase::Create<BasicAllTargetsLoadStoreVS>));
11693 addChild(
11694 new TestSubcase(m_context, "basic-allTargets-loadStoreTCS", TestSubcase::Create<BasicAllTargetsLoadStoreTCS>));
11695 addChild(
11696 new TestSubcase(m_context, "basic-allTargets-loadStoreTES", TestSubcase::Create<BasicAllTargetsLoadStoreTES>));
11697 addChild(
11698 new TestSubcase(m_context, "basic-allTargets-loadStoreGS", TestSubcase::Create<BasicAllTargetsLoadStoreGS>));
11699 addChild(
11700 new TestSubcase(m_context, "basic-allTargets-loadStoreCS", TestSubcase::Create<BasicAllTargetsLoadStoreCS>));
11701 addChild(new TestSubcase(m_context, "basic-allTargets-atomicVS", TestSubcase::Create<BasicAllTargetsAtomicVS>));
11702 addChild(new TestSubcase(m_context, "basic-allTargets-atomicTCS", TestSubcase::Create<BasicAllTargetsAtomicTCS>));
11703 addChild(new TestSubcase(m_context, "basic-allTargets-atomicGS", TestSubcase::Create<BasicAllTargetsAtomicGS>));
11704 addChild(new TestSubcase(m_context, "basic-allTargets-atomicCS", TestSubcase::Create<BasicAllTargetsAtomicCS>));
11705 addChild(new TestSubcase(m_context, "basic-glsl-misc", TestSubcase::Create<BasicGLSLMisc>));
11706 addChild(new TestSubcase(m_context, "basic-glsl-earlyFragTests", TestSubcase::Create<BasicGLSLEarlyFragTests>));
11707 addChild(new TestSubcase(m_context, "basic-glsl-const", TestSubcase::Create<BasicGLSLConst>));
11708 addChild(new TestSubcase(m_context, "advanced-sync-imageAccess", TestSubcase::Create<AdvancedSyncImageAccess>));
11709 addChild(new TestSubcase(m_context, "advanced-sync-vertexArray", TestSubcase::Create<AdvancedSyncVertexArray>));
11710 addChild(new TestSubcase(m_context, "advanced-sync-drawIndirect", TestSubcase::Create<AdvancedSyncDrawIndirect>));
11711 addChild(new TestSubcase(m_context, "advanced-sync-textureUpdate", TestSubcase::Create<AdvancedSyncTextureUpdate>));
11712 addChild(new TestSubcase(m_context, "advanced-sync-imageAccess2", TestSubcase::Create<AdvancedSyncImageAccess2>));
11713 addChild(new TestSubcase(m_context, "advanced-sync-bufferUpdate", TestSubcase::Create<AdvancedSyncBufferUpdate>));
11714 addChild(new TestSubcase(m_context, "advanced-allStages-oneImage", TestSubcase::Create<AdvancedAllStagesOneImage>));
11715 addChild(new TestSubcase(m_context, "advanced-memory-dependentInvocation",
11716 TestSubcase::Create<AdvancedMemoryDependentInvocation>));
11717 addChild(new TestSubcase(m_context, "advanced-memory-order", TestSubcase::Create<AdvancedMemoryOrder>));
11718 addChild(new TestSubcase(m_context, "advanced-sso-simple", TestSubcase::Create<AdvancedSSOSimple>));
11719 addChild(new TestSubcase(m_context, "advanced-sso-atomicCounters", TestSubcase::Create<AdvancedSSOAtomicCounters>));
11720 addChild(new TestSubcase(m_context, "advanced-sso-subroutine", TestSubcase::Create<AdvancedSSOSubroutine>));
11721 addChild(new TestSubcase(m_context, "advanced-sso-perSample", TestSubcase::Create<AdvancedSSOPerSample>));
11722 addChild(new TestSubcase(m_context, "advanced-copyImage", TestSubcase::Create<AdvancedCopyImage>));
11723 addChild(new TestSubcase(m_context, "advanced-allMips", TestSubcase::Create<AdvancedAllMips>));
11724 addChild(new TestSubcase(m_context, "advanced-cast", TestSubcase::Create<AdvancedCast>));
11725 addChild(
11726 new TestSubcase(m_context, "single-byte_data_alignment", TestSubcase::Create<ImageLoadStoreDataAlignmentTest>));
11727 addChild(
11728 new TestSubcase(m_context, "non-layered_binding", TestSubcase::Create<ImageLoadStoreNonLayeredBindingTest>));
11729 addChild(
11730 new TestSubcase(m_context, "incomplete_textures", TestSubcase::Create<ImageLoadStoreIncompleteTexturesTest>));
11731 addChild(new TestSubcase(m_context, "multiple-uniforms", TestSubcase::Create<ImageLoadStoreMultipleUniformsTest>));
11732 addChild(
11733 new TestSubcase(m_context, "early-fragment-tests", TestSubcase::Create<ImageLoadStoreEarlyFragmentTestsTest>));
11734 addChild(new TestSubcase(m_context, "negative-uniform", TestSubcase::Create<NegativeUniform>));
11735 addChild(new TestSubcase(m_context, "negative-bind", TestSubcase::Create<NegativeBind>));
11736 addChild(new TestSubcase(m_context, "negative-compileErrors", TestSubcase::Create<NegativeCompileErrors>));
11737 addChild(new TestSubcase(m_context, "negative-linkErrors", TestSubcase::Create<NegativeLinkErrors>));
11738 addChild(new TestSubcase(m_context, "uniform-limits", TestSubcase::Create<ImageLoadStoreUniformLimitsTest>));
11739 }
11740 }
11741