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 "vkPlatform.hpp"
32 #include <assert.h>
33 #include <climits>
34 #include <cmath>
35 #include <cstdarg>
36 #include <deque>
37 #include <iomanip>
38 #include <map>
39 #include <sstream>
40 #include <tcuFloat.hpp>
41
42 namespace gl4cts
43 {
44 using namespace glw;
45
46 namespace
47 {
48 typedef tcu::Vec2 vec2;
49 typedef tcu::Vec4 vec4;
50 typedef tcu::IVec4 ivec4;
51 typedef tcu::UVec4 uvec4;
52 typedef tcu::Mat4 mat4;
53
54 class ShaderImageLoadStoreBase : public deqp::SubcaseBase
55 {
Title()56 virtual std::string Title()
57 {
58 return "";
59 }
60
Purpose()61 virtual std::string Purpose()
62 {
63 return "";
64 }
65
Method()66 virtual std::string Method()
67 {
68 return "";
69 }
70
PassCriteria()71 virtual std::string PassCriteria()
72 {
73 return "";
74 }
75
76 public:
SupportedInVS(int requiredVS)77 bool SupportedInVS(int requiredVS)
78 {
79 GLint imagesVS;
80 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &imagesVS);
81 if (imagesVS >= requiredVS)
82 return true;
83 else
84 {
85 std::ostringstream reason;
86 reason << "Required " << requiredVS << " VS image uniforms but only " << imagesVS << " available."
87 << std::endl;
88 OutputNotSupported(reason.str());
89 return false;
90 }
91 }
92
SupportedInTCS(int requiredTCS)93 bool SupportedInTCS(int requiredTCS)
94 {
95 GLint imagesTCS;
96 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &imagesTCS);
97 if (imagesTCS >= requiredTCS)
98 return true;
99 else
100 {
101 std::ostringstream reason;
102 reason << "Required " << requiredTCS << " TCS image uniforms but only " << imagesTCS << " available."
103 << std::endl;
104 OutputNotSupported(reason.str());
105 return false;
106 }
107 }
108
SupportedInTES(int requiredTES)109 bool SupportedInTES(int requiredTES)
110 {
111 GLint imagesTES;
112 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &imagesTES);
113 if (imagesTES >= requiredTES)
114 return true;
115 else
116 {
117 std::ostringstream reason;
118 reason << "Required " << requiredTES << " TES image uniforms but only " << imagesTES << " available."
119 << std::endl;
120 OutputNotSupported(reason.str());
121 return false;
122 }
123 }
124
SupportedInGS(int requiredGS)125 bool SupportedInGS(int requiredGS)
126 {
127 GLint imagesGS;
128 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &imagesGS);
129 if (imagesGS >= requiredGS)
130 return true;
131 else
132 {
133 std::ostringstream reason;
134 reason << "Required " << requiredGS << " GS image uniforms but only " << imagesGS << " available."
135 << std::endl;
136 OutputNotSupported(reason.str());
137 return false;
138 }
139 }
140
SupportedInGeomStages(int required)141 bool SupportedInGeomStages(int required)
142 {
143 return SupportedInVS(required) && SupportedInTCS(required) && SupportedInTES(required) &&
144 SupportedInGS(required);
145 }
146
SupportedInStage(int stage,int required)147 bool SupportedInStage(int stage, int required)
148 {
149 switch (stage)
150 {
151 case 0:
152 return SupportedInVS(required);
153 case 1:
154 return SupportedInTCS(required);
155 case 2:
156 return SupportedInTES(required);
157 case 3:
158 return SupportedInGS(required);
159 default:
160 return true;
161 }
162 }
163
SupportedSamples(int required)164 bool SupportedSamples(int required)
165 {
166 int i;
167 glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
168 if (i >= required)
169 return true;
170 else
171 {
172 std::ostringstream reason;
173 reason << "Required " << required << " image samples but only " << i << " available." << std::endl;
174 OutputNotSupported(reason.str());
175 return false;
176 }
177 }
178
getWindowWidth()179 int getWindowWidth()
180 {
181 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
182 return renderTarget.getWidth();
183 }
184
getWindowHeight()185 int getWindowHeight()
186 {
187 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
188 return renderTarget.getHeight();
189 }
190
scaleDimensionsToMemory(int & width,int & height,int devLayers,int sysLayers,int devBPP,int sysBPP)191 void scaleDimensionsToMemory(int& width, int& height, int devLayers, int sysLayers, int devBPP, int sysBPP)
192 {
193 vk::PlatformMemoryLimits memoryLimits;
194 m_context.getTestContext().getPlatform().getVulkanPlatform().getMemoryLimits(memoryLimits);
195 GLsizeiptr sysSpace = memoryLimits.totalSystemMemory;
196 GLsizeiptr devSpace = memoryLimits.totalDeviceLocalMemory;
197 int devInSysLayers = 0;
198
199 if (devSpace == 0)
200 {
201 devInSysLayers = devLayers;
202 devLayers = 0;
203 }
204
205 // Check if available memory is enough
206 GLsizeiptr pixelsPerLayer = width * height;
207 GLsizeiptr sysRequired = pixelsPerLayer * ((sysBPP * sysLayers) + (devBPP * devInSysLayers));
208 GLsizeiptr devRequired = pixelsPerLayer * devBPP * devLayers;
209 if ((sysRequired <= sysSpace) && (devRequired <= devSpace))
210 {
211 return;
212 }
213
214 // Scales the width and height such that the overall texture fits into
215 // the available space for both system and device.
216 GLdouble scale = sqrt(sysSpace / GLdouble(sysRequired));
217 if (devSpace != 0)
218 {
219 GLdouble devScale = sqrt(devSpace / GLdouble(devRequired));
220 scale = de::min(devScale, scale);
221 }
222 int newWidth = int(width * scale);
223 int newHeight = int(height * scale);
224
225 m_context.getTestContext().getLog()
226 << tcu::TestLog::Message << "Reducing surface dimensions to fit in memory, from " << width << "x" << height
227 << " to " << newWidth << "x" << newHeight << "." << tcu::TestLog::EndMessage;
228
229 width = newWidth;
230 height = newHeight;
231 }
232
ColorEqual(const vec4 & c0,const vec4 & c1,const vec4 & epsilon)233 inline bool ColorEqual(const vec4& c0, const vec4& c1, const vec4& epsilon)
234 {
235 if (fabs(c0[0] - c1[0]) > epsilon[0])
236 return false;
237 if (fabs(c0[1] - c1[1]) > epsilon[1])
238 return false;
239 if (fabs(c0[2] - c1[2]) > epsilon[2])
240 return false;
241 if (fabs(c0[3] - c1[3]) > epsilon[3])
242 return false;
243 return true;
244 }
245
IsEqual(vec4 a,vec4 b)246 bool IsEqual(vec4 a, vec4 b)
247 {
248 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
249 }
250
Equal(const vec4 & v0,const vec4 & v1,GLenum internalformat)251 bool Equal(const vec4& v0, const vec4& v1, GLenum internalformat)
252 {
253 if (internalformat == GL_RGBA16_SNORM || internalformat == GL_RG16_SNORM || internalformat == GL_R16_SNORM)
254 {
255 return ColorEqual(v0, v1, vec4(0.0001f));
256 }
257 else if (internalformat == GL_RGBA8_SNORM || internalformat == GL_RG8_SNORM || internalformat == GL_R8_SNORM)
258 {
259 return ColorEqual(v0, v1, vec4(0.01f));
260 }
261 return (v0[0] == v1[0]) && (v0[1] == v1[1]) && (v0[2] == v1[2]) && (v0[3] == v1[3]);
262 }
263
Equal(const ivec4 & a,const ivec4 & b,GLenum)264 bool Equal(const ivec4& a, const ivec4& b, GLenum)
265 {
266 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
267 }
268
Equal(const uvec4 & a,const uvec4 & b,GLenum)269 bool Equal(const uvec4& a, const uvec4& b, GLenum)
270 {
271 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
272 }
273
274 template <class T>
ToString(T v)275 std::string ToString(T v)
276 {
277 std::ostringstream s;
278 s << "[";
279 for (int i = 0; i < 4; ++i)
280 s << v[i] << (i == 3 ? "" : ",");
281 s << "]";
282 return s.str();
283 }
284
ValidateReadBuffer(int x,int y,int w,int h,const vec4 & expected)285 bool ValidateReadBuffer(int x, int y, int w, int h, const vec4& expected)
286 {
287 bool status = true;
288 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
289 const tcu::PixelFormat& pixelFormat = renderTarget.getPixelFormat();
290 vec4 g_color_eps = vec4(
291 1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
292 1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
293
294 std::vector<vec4> fb(w * h);
295 glReadPixels(x, y, w, h, GL_RGBA, GL_FLOAT, &fb[0]);
296
297 for (int yy = 0; yy < h; ++yy)
298 {
299 for (int xx = 0; xx < w; ++xx)
300 {
301 const int idx = yy * w + xx;
302 if (!ColorEqual(fb[idx], expected, g_color_eps))
303 {
304 m_context.getTestContext().getLog()
305 << tcu::TestLog::Message << "First bad color: " << ToString(fb[idx])
306 << tcu::TestLog::EndMessage;
307 status = false;
308 return status;
309 }
310 }
311 }
312 return status;
313 }
314
CompileShader(GLuint shader)315 bool CompileShader(GLuint shader)
316 {
317 glCompileShader(shader);
318
319 GLint status;
320 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
321 if (status == GL_FALSE)
322 {
323 GLsizei length;
324 GLchar log[1024];
325 glGetShaderInfoLog(shader, sizeof(log), &length, log);
326 if (length > 1)
327 {
328 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
329 << log << tcu::TestLog::EndMessage;
330 }
331 return false;
332 }
333 return true;
334 }
335
LinkProgram(GLuint program)336 bool LinkProgram(GLuint program)
337 {
338 glLinkProgram(program);
339
340 GLint status;
341 glGetProgramiv(program, GL_LINK_STATUS, &status);
342 if (status == GL_FALSE)
343 {
344 GLsizei length;
345 GLchar log[1024];
346 glGetProgramInfoLog(program, sizeof(log), &length, log);
347 if (length > 1)
348 {
349 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
350 << log << tcu::TestLog::EndMessage;
351 }
352 return false;
353 }
354 return true;
355 }
356
BuildProgram(const char * src_vs,const char * src_tcs,const char * src_tes,const char * src_gs,const char * src_fs,bool * result=NULL)357 GLuint BuildProgram(const char* src_vs, const char* src_tcs, const char* src_tes, const char* src_gs,
358 const char* src_fs, bool* result = NULL)
359 {
360 const GLuint p = glCreateProgram();
361
362 if (src_vs)
363 {
364 GLuint sh = glCreateShader(GL_VERTEX_SHADER);
365 glAttachShader(p, sh);
366 glDeleteShader(sh);
367 glShaderSource(sh, 1, &src_vs, NULL);
368 if (!CompileShader(sh))
369 {
370 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage;
371 if (result)
372 *result = false;
373 return p;
374 }
375 }
376 if (src_tcs)
377 {
378 GLuint sh = glCreateShader(GL_TESS_CONTROL_SHADER);
379 glAttachShader(p, sh);
380 glDeleteShader(sh);
381 glShaderSource(sh, 1, &src_tcs, NULL);
382 if (!CompileShader(sh))
383 {
384 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage;
385 if (result)
386 *result = false;
387 return p;
388 }
389 }
390 if (src_tes)
391 {
392 GLuint sh = glCreateShader(GL_TESS_EVALUATION_SHADER);
393 glAttachShader(p, sh);
394 glDeleteShader(sh);
395 glShaderSource(sh, 1, &src_tes, NULL);
396 if (!CompileShader(sh))
397 {
398 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage;
399 if (result)
400 *result = false;
401 return p;
402 }
403 }
404 if (src_gs)
405 {
406 GLuint sh = glCreateShader(GL_GEOMETRY_SHADER);
407 glAttachShader(p, sh);
408 glDeleteShader(sh);
409 glShaderSource(sh, 1, &src_gs, NULL);
410 if (!CompileShader(sh))
411 {
412 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage;
413 if (result)
414 *result = false;
415 return p;
416 }
417 }
418 if (src_fs)
419 {
420 GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
421 glAttachShader(p, sh);
422 glDeleteShader(sh);
423 glShaderSource(sh, 1, &src_fs, NULL);
424 if (!CompileShader(sh))
425 {
426 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage;
427 if (result)
428 *result = false;
429 return p;
430 }
431 }
432 if (!LinkProgram(p))
433 {
434 if (src_vs)
435 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage;
436 if (src_tcs)
437 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage;
438 if (src_tes)
439 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage;
440 if (src_gs)
441 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage;
442 if (src_fs)
443 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage;
444 if (result)
445 *result = false;
446 return p;
447 }
448
449 return p;
450 }
451
BuildShaderProgram(GLenum type,const char * src)452 GLuint BuildShaderProgram(GLenum type, const char* src)
453 {
454 const GLuint p = glCreateShaderProgramv(type, 1, &src);
455
456 GLint status;
457 glGetProgramiv(p, GL_LINK_STATUS, &status);
458 if (status == GL_FALSE)
459 {
460 GLchar log[1024];
461 glGetProgramInfoLog(p, sizeof(log), NULL, log);
462 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
463 << log << "\n"
464 << src << tcu::TestLog::EndMessage;
465 }
466
467 return p;
468 }
469
CreateFullViewportQuad(GLuint * vao,GLuint * vbo,GLuint * ebo)470 void CreateFullViewportQuad(GLuint* vao, GLuint* vbo, GLuint* ebo)
471 {
472 assert(vao && vbo);
473
474 // interleaved data (vertex, color0 (green), color1 (blue), color2 (red))
475 const float v[] = {
476 -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,
477 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,
478 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,
479 };
480 glGenBuffers(1, vbo);
481 glBindBuffer(GL_ARRAY_BUFFER, *vbo);
482 glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
483 glBindBuffer(GL_ARRAY_BUFFER, 0);
484
485 if (ebo)
486 {
487 std::vector<GLushort> index_data(4);
488 for (int i = 0; i < 4; ++i)
489 {
490 index_data[i] = static_cast<GLushort>(i);
491 }
492 glGenBuffers(1, ebo);
493 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
494 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * 4, &index_data[0], GL_STATIC_DRAW);
495 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
496 }
497
498 glGenVertexArrays(1, vao);
499 glBindVertexArray(*vao);
500 glBindBuffer(GL_ARRAY_BUFFER, *vbo);
501 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, 0);
502 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 2));
503 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 5));
504 glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 8));
505 glBindBuffer(GL_ARRAY_BUFFER, 0);
506 glEnableVertexAttribArray(0);
507 glEnableVertexAttribArray(1);
508 glEnableVertexAttribArray(2);
509 glEnableVertexAttribArray(3);
510 if (ebo)
511 {
512 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
513 }
514 glBindVertexArray(0);
515 }
516
FormatEnumToString(GLenum e)517 std::string FormatEnumToString(GLenum e)
518 {
519 switch (e)
520 {
521 case GL_RGBA32F:
522 return "rgba32f";
523 case GL_RGBA16F:
524 return "rgba16f";
525 case GL_RG32F:
526 return "rg32f";
527 case GL_RG16F:
528 return "rg16f";
529 case GL_R11F_G11F_B10F:
530 return "r11f_g11f_b10f";
531 case GL_R32F:
532 return "r32f";
533 case GL_R16F:
534 return "r16f";
535
536 case GL_RGBA32UI:
537 return "rgba32ui";
538 case GL_RGBA16UI:
539 return "rgba16ui";
540 case GL_RGB10_A2UI:
541 return "rgb10_a2ui";
542 case GL_RGBA8UI:
543 return "rgba8ui";
544 case GL_RG32UI:
545 return "rg32ui";
546 case GL_RG16UI:
547 return "rg16ui";
548 case GL_RG8UI:
549 return "rg8ui";
550 case GL_R32UI:
551 return "r32ui";
552 case GL_R16UI:
553 return "r16ui";
554 case GL_R8UI:
555 return "r8ui";
556
557 case GL_RGBA32I:
558 return "rgba32i";
559 case GL_RGBA16I:
560 return "rgba16i";
561 case GL_RGBA8I:
562 return "rgba8i";
563 case GL_RG32I:
564 return "rg32i";
565 case GL_RG16I:
566 return "rg16i";
567 case GL_RG8I:
568 return "rg8i";
569 case GL_R32I:
570 return "r32i";
571 case GL_R16I:
572 return "r16i";
573 case GL_R8I:
574 return "r8i";
575
576 case GL_RGBA16:
577 return "rgba16";
578 case GL_RGB10_A2:
579 return "rgb10_a2";
580 case GL_RGBA8:
581 return "rgba8";
582 case GL_RG16:
583 return "rg16";
584 case GL_RG8:
585 return "rg8";
586 case GL_R16:
587 return "r16";
588 case GL_R8:
589 return "r8";
590
591 case GL_RGBA16_SNORM:
592 return "rgba16_snorm";
593 case GL_RGBA8_SNORM:
594 return "rgba8_snorm";
595 case GL_RG16_SNORM:
596 return "rg16_snorm";
597 case GL_RG8_SNORM:
598 return "rg8_snorm";
599 case GL_R16_SNORM:
600 return "r16_snorm";
601 case GL_R8_SNORM:
602 return "r8_snorm";
603 }
604
605 assert(0);
606 return "";
607 }
608
StageName(int stage)609 const char* StageName(int stage)
610 {
611 switch (stage)
612 {
613 case 0:
614 return "Vertex Shader";
615 case 1:
616 return "Tessellation Control Shader";
617 case 2:
618 return "Tessellation Evaluation Shader";
619 case 3:
620 return "Geometry Shader";
621 case 4:
622 return "Compute Shader";
623 }
624 assert(0);
625 return NULL;
626 }
627
628 template <typename T>
629 GLenum Format();
630
631 template <typename T>
632 GLenum Type();
633
634 template <typename T>
635 std::string TypePrefix();
636
637 template <typename T>
638 GLenum ImageType(GLenum target);
639
ClearBuffer(GLenum buffer,GLint drawbuffer,const vec4 & color)640 void ClearBuffer(GLenum buffer, GLint drawbuffer, const vec4& color)
641 {
642 glClearBufferfv(buffer, drawbuffer, &color[0]);
643 }
644
ClearBuffer(GLenum buffer,GLint drawbuffer,const ivec4 & color)645 void ClearBuffer(GLenum buffer, GLint drawbuffer, const ivec4& color)
646 {
647 glClearBufferiv(buffer, drawbuffer, &color[0]);
648 }
649
ClearBuffer(GLenum buffer,GLint drawbuffer,const uvec4 & color)650 void ClearBuffer(GLenum buffer, GLint drawbuffer, const uvec4& color)
651 {
652 glClearBufferuiv(buffer, drawbuffer, &color[0]);
653 }
654
CheckUniform(GLuint program,const std::string & name,const std::map<std::string,GLuint> & name_index_map,GLint size,GLenum type)655 bool CheckUniform(GLuint program, const std::string& name, const std::map<std::string, GLuint>& name_index_map,
656 GLint size, GLenum type)
657 {
658 std::map<std::string, GLuint>::const_iterator iter = name_index_map.find(name);
659 assert(iter != name_index_map.end());
660
661 GLchar name_gl[32];
662 GLsizei length_gl;
663 GLint size_gl;
664 GLenum type_gl;
665
666 glGetActiveUniform(program, iter->second, sizeof(name_gl), &length_gl, &size_gl, &type_gl, name_gl);
667
668 if (std::string(name_gl) != name)
669 {
670 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform name is " << name_gl
671 << " should be " << name << tcu::TestLog::EndMessage;
672 return false;
673 }
674 if (length_gl != static_cast<GLsizei>(name.length()))
675 {
676 m_context.getTestContext().getLog()
677 << tcu::TestLog::Message << "Uniform length is " << length_gl << " should be " << name << "(" << name_gl
678 << ")" << tcu::TestLog::EndMessage;
679 return false;
680 }
681 if (size_gl != size)
682 {
683 m_context.getTestContext().getLog()
684 << tcu::TestLog::Message << "Uniform size is " << size_gl << " should be " << size << "(" << name_gl
685 << ")" << tcu::TestLog::EndMessage;
686 return false;
687 }
688 if (type_gl != type)
689 {
690 m_context.getTestContext().getLog()
691 << tcu::TestLog::Message << "Uniform type is " << type_gl << " should be " << type << "(" << name_gl
692 << ")" << tcu::TestLog::EndMessage;
693 return false;
694 }
695
696 return true;
697 }
698
CheckMax(GLenum pname,GLint min_value)699 bool CheckMax(GLenum pname, GLint min_value)
700 {
701 GLboolean b;
702 GLint i;
703 GLfloat f;
704 GLdouble d;
705 GLint64 i64;
706
707 glGetIntegerv(pname, &i);
708 if (i < min_value)
709 return false;
710
711 glGetBooleanv(pname, &b);
712 if (b != (i ? GL_TRUE : GL_FALSE))
713 return false;
714
715 glGetFloatv(pname, &f);
716 if (static_cast<GLint>(f) < min_value)
717 return false;
718
719 glGetDoublev(pname, &d);
720 if (static_cast<GLint>(d) < min_value)
721 return false;
722
723 glGetInteger64v(pname, &i64);
724 if (static_cast<GLint>(i64) < min_value)
725 return false;
726
727 return true;
728 }
729
CheckBinding(GLuint unit,GLuint texture,GLint level,GLboolean layered,GLint layer,GLenum access,GLenum format)730 bool CheckBinding(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access,
731 GLenum format)
732 {
733 GLint i;
734 GLboolean b;
735
736 glGetIntegeri_v(GL_IMAGE_BINDING_NAME, unit, &i);
737 if (static_cast<GLuint>(i) != texture)
738 {
739 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME is " << i
740 << " should be " << texture << tcu::TestLog::EndMessage;
741 return false;
742 }
743 glGetBooleani_v(GL_IMAGE_BINDING_NAME, unit, &b);
744 if (b != (i ? GL_TRUE : GL_FALSE))
745 {
746 m_context.getTestContext().getLog()
747 << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME (as boolean) is " << b << " should be "
748 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
749 return false;
750 }
751
752 glGetIntegeri_v(GL_IMAGE_BINDING_LEVEL, unit, &i);
753 if (i != level)
754 {
755 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL is " << i
756 << " should be " << level << tcu::TestLog::EndMessage;
757 return false;
758 }
759 glGetBooleani_v(GL_IMAGE_BINDING_LEVEL, unit, &b);
760 if (b != (i ? GL_TRUE : GL_FALSE))
761 {
762 m_context.getTestContext().getLog()
763 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL (as boolean) is " << b << " should be "
764 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
765 return false;
766 }
767
768 glGetIntegeri_v(GL_IMAGE_BINDING_LAYERED, unit, &i);
769 if (i != layered)
770 {
771 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED is " << i
772 << " should be " << layered << tcu::TestLog::EndMessage;
773 return false;
774 }
775 glGetBooleani_v(GL_IMAGE_BINDING_LAYERED, unit, &b);
776 if (b != (i ? GL_TRUE : GL_FALSE))
777 {
778 m_context.getTestContext().getLog()
779 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED (as boolean) is " << b << " should be "
780 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
781 return false;
782 }
783
784 glGetIntegeri_v(GL_IMAGE_BINDING_LAYER, unit, &i);
785 if (i != layer)
786 {
787 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER is " << i
788 << " should be " << layer << tcu::TestLog::EndMessage;
789 return false;
790 }
791 glGetBooleani_v(GL_IMAGE_BINDING_LAYER, unit, &b);
792 if (b != (i ? GL_TRUE : GL_FALSE))
793 {
794 m_context.getTestContext().getLog()
795 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER (as boolean) is " << b << " should be "
796 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
797 return false;
798 }
799
800 glGetIntegeri_v(GL_IMAGE_BINDING_ACCESS, unit, &i);
801 if (static_cast<GLenum>(i) != access)
802 {
803 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS is " << i
804 << " should be " << access << tcu::TestLog::EndMessage;
805 return false;
806 }
807 glGetBooleani_v(GL_IMAGE_BINDING_ACCESS, unit, &b);
808 if (b != (i ? GL_TRUE : GL_FALSE))
809 {
810 m_context.getTestContext().getLog()
811 << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS (as boolean) is " << b << " should be "
812 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
813 return false;
814 }
815
816 glGetIntegeri_v(GL_IMAGE_BINDING_FORMAT, unit, &i);
817 if (static_cast<GLenum>(i) != format)
818 {
819 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT is " << i
820 << " should be " << format << tcu::TestLog::EndMessage;
821 return false;
822 }
823 glGetBooleani_v(GL_IMAGE_BINDING_FORMAT, unit, &b);
824 if (b != (i ? GL_TRUE : GL_FALSE))
825 {
826 m_context.getTestContext().getLog()
827 << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT (as boolean) is " << b << " should be "
828 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
829 return false;
830 }
831
832 return true;
833 }
EnumToString(GLenum e)834 const char* EnumToString(GLenum e)
835 {
836 switch (e)
837 {
838 case GL_TEXTURE_1D:
839 return "GL_TEXTURE_1D";
840 case GL_TEXTURE_2D:
841 return "GL_TEXTURE_2D";
842 case GL_TEXTURE_3D:
843 return "GL_TEXTURE_3D";
844 case GL_TEXTURE_RECTANGLE:
845 return "GL_TEXTURE_RECTANGLE";
846 case GL_TEXTURE_CUBE_MAP:
847 return "GL_TEXTURE_CUBE_MAP";
848 case GL_TEXTURE_1D_ARRAY:
849 return "GL_TEXTURE_1D_ARRAY";
850 case GL_TEXTURE_2D_ARRAY:
851 return "GL_TEXTURE_2D_ARRAY";
852 case GL_TEXTURE_CUBE_MAP_ARRAY:
853 return "GL_TEXTURE_CUBE_MAP_ARRAY";
854
855 default:
856 assert(0);
857 break;
858 }
859 return NULL;
860 }
861 };
862
863 template <>
Format()864 GLenum ShaderImageLoadStoreBase::Format<vec4>()
865 {
866 return GL_RGBA;
867 }
868
869 template <>
Format()870 GLenum ShaderImageLoadStoreBase::Format<ivec4>()
871 {
872 return GL_RGBA_INTEGER;
873 }
874
875 template <>
Format()876 GLenum ShaderImageLoadStoreBase::Format<uvec4>()
877 {
878 return GL_RGBA_INTEGER;
879 }
880
881 template <>
Format()882 GLenum ShaderImageLoadStoreBase::Format<GLint>()
883 {
884 return GL_RED_INTEGER;
885 }
886
887 template <>
Format()888 GLenum ShaderImageLoadStoreBase::Format<GLuint>()
889 {
890 return GL_RED_INTEGER;
891 }
892
893 template <>
Type()894 GLenum ShaderImageLoadStoreBase::Type<vec4>()
895 {
896 return GL_FLOAT;
897 }
898
899 template <>
Type()900 GLenum ShaderImageLoadStoreBase::Type<ivec4>()
901 {
902 return GL_INT;
903 }
904
905 template <>
Type()906 GLenum ShaderImageLoadStoreBase::Type<uvec4>()
907 {
908 return GL_UNSIGNED_INT;
909 }
910
911 template <>
Type()912 GLenum ShaderImageLoadStoreBase::Type<GLint>()
913 {
914 return GL_INT;
915 }
916
917 template <>
Type()918 GLenum ShaderImageLoadStoreBase::Type<GLuint>()
919 {
920 return GL_UNSIGNED_INT;
921 }
922
923 template <>
TypePrefix()924 std::string ShaderImageLoadStoreBase::TypePrefix<vec4>()
925 {
926 return "";
927 }
928
929 template <>
TypePrefix()930 std::string ShaderImageLoadStoreBase::TypePrefix<ivec4>()
931 {
932 return "i";
933 }
934
935 template <>
TypePrefix()936 std::string ShaderImageLoadStoreBase::TypePrefix<uvec4>()
937 {
938 return "u";
939 }
940
941 template <>
TypePrefix()942 std::string ShaderImageLoadStoreBase::TypePrefix<GLint>()
943 {
944 return "i";
945 }
946
947 template <>
TypePrefix()948 std::string ShaderImageLoadStoreBase::TypePrefix<GLuint>()
949 {
950 return "u";
951 }
952
953 template <>
ImageType(GLenum target)954 GLenum ShaderImageLoadStoreBase::ImageType<vec4>(GLenum target)
955 {
956 switch (target)
957 {
958 case GL_TEXTURE_1D:
959 return GL_IMAGE_1D;
960 case GL_TEXTURE_2D:
961 return GL_IMAGE_2D;
962 case GL_TEXTURE_3D:
963 return GL_IMAGE_3D;
964 case GL_TEXTURE_RECTANGLE:
965 return GL_IMAGE_2D_RECT;
966 case GL_TEXTURE_CUBE_MAP:
967 return GL_IMAGE_CUBE;
968 case GL_TEXTURE_BUFFER:
969 return GL_IMAGE_BUFFER;
970 case GL_TEXTURE_1D_ARRAY:
971 return GL_IMAGE_1D_ARRAY;
972 case GL_TEXTURE_2D_ARRAY:
973 return GL_IMAGE_2D_ARRAY;
974 case GL_TEXTURE_CUBE_MAP_ARRAY:
975 return GL_IMAGE_CUBE_MAP_ARRAY;
976 case GL_TEXTURE_2D_MULTISAMPLE:
977 return GL_IMAGE_2D_MULTISAMPLE;
978 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
979 return GL_IMAGE_2D_MULTISAMPLE_ARRAY;
980 }
981 assert(0);
982 return 0;
983 }
984
985 template <>
ImageType(GLenum target)986 GLenum ShaderImageLoadStoreBase::ImageType<ivec4>(GLenum target)
987 {
988 switch (target)
989 {
990 case GL_TEXTURE_1D:
991 return GL_INT_IMAGE_1D;
992 case GL_TEXTURE_2D:
993 return GL_INT_IMAGE_2D;
994 case GL_TEXTURE_3D:
995 return GL_INT_IMAGE_3D;
996 case GL_TEXTURE_RECTANGLE:
997 return GL_INT_IMAGE_2D_RECT;
998 case GL_TEXTURE_CUBE_MAP:
999 return GL_INT_IMAGE_CUBE;
1000 case GL_TEXTURE_BUFFER:
1001 return GL_INT_IMAGE_BUFFER;
1002 case GL_TEXTURE_1D_ARRAY:
1003 return GL_INT_IMAGE_1D_ARRAY;
1004 case GL_TEXTURE_2D_ARRAY:
1005 return GL_INT_IMAGE_2D_ARRAY;
1006 case GL_TEXTURE_CUBE_MAP_ARRAY:
1007 return GL_INT_IMAGE_CUBE_MAP_ARRAY;
1008 case GL_TEXTURE_2D_MULTISAMPLE:
1009 return GL_INT_IMAGE_2D_MULTISAMPLE;
1010 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1011 return GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY;
1012 }
1013 assert(0);
1014 return 0;
1015 }
1016
1017 template <>
ImageType(GLenum target)1018 GLenum ShaderImageLoadStoreBase::ImageType<uvec4>(GLenum target)
1019 {
1020 switch (target)
1021 {
1022 case GL_TEXTURE_1D:
1023 return GL_UNSIGNED_INT_IMAGE_1D;
1024 case GL_TEXTURE_2D:
1025 return GL_UNSIGNED_INT_IMAGE_2D;
1026 case GL_TEXTURE_3D:
1027 return GL_UNSIGNED_INT_IMAGE_3D;
1028 case GL_TEXTURE_RECTANGLE:
1029 return GL_UNSIGNED_INT_IMAGE_2D_RECT;
1030 case GL_TEXTURE_CUBE_MAP:
1031 return GL_UNSIGNED_INT_IMAGE_CUBE;
1032 case GL_TEXTURE_BUFFER:
1033 return GL_UNSIGNED_INT_IMAGE_BUFFER;
1034 case GL_TEXTURE_1D_ARRAY:
1035 return GL_UNSIGNED_INT_IMAGE_1D_ARRAY;
1036 case GL_TEXTURE_2D_ARRAY:
1037 return GL_UNSIGNED_INT_IMAGE_2D_ARRAY;
1038 case GL_TEXTURE_CUBE_MAP_ARRAY:
1039 return GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY;
1040 case GL_TEXTURE_2D_MULTISAMPLE:
1041 return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE;
1042 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1043 return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY;
1044 }
1045 assert(0);
1046 return 0;
1047 }
1048
1049 //-----------------------------------------------------------------------------
1050 // 1.1.1 BasicAPIGet
1051 //-----------------------------------------------------------------------------
1052 class BasicAPIGet : public ShaderImageLoadStoreBase
1053 {
Run()1054 virtual long Run()
1055 {
1056 if (!CheckMax(GL_MAX_IMAGE_UNITS, 8))
1057 {
1058 m_context.getTestContext().getLog()
1059 << tcu::TestLog::Message << "GL_MAX_IMAGE_UNITS value is invalid." << tcu::TestLog::EndMessage;
1060 return ERROR;
1061 }
1062 if (!CheckMax(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 8))
1063 {
1064 m_context.getTestContext().getLog()
1065 << tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES value is invalid."
1066 << tcu::TestLog::EndMessage;
1067 return ERROR;
1068 }
1069 if (!CheckMax(GL_MAX_IMAGE_SAMPLES, 0))
1070 {
1071 m_context.getTestContext().getLog()
1072 << tcu::TestLog::Message << "GL_MAX_IMAGE_SAMPLES value is invalid." << tcu::TestLog::EndMessage;
1073 return ERROR;
1074 }
1075 if (!CheckMax(GL_MAX_VERTEX_IMAGE_UNIFORMS, 0))
1076 {
1077 m_context.getTestContext().getLog()
1078 << tcu::TestLog::Message << "GL_MAX_VERTEX_IMAGE_UNIFORMS value is invalid."
1079 << tcu::TestLog::EndMessage;
1080 return ERROR;
1081 }
1082 if (!CheckMax(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, 0))
1083 {
1084 m_context.getTestContext().getLog()
1085 << tcu::TestLog::Message << "GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS value is invalid."
1086 << tcu::TestLog::EndMessage;
1087 return ERROR;
1088 }
1089 if (!CheckMax(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, 0))
1090 {
1091 m_context.getTestContext().getLog()
1092 << tcu::TestLog::Message << "GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS value is invalid."
1093 << tcu::TestLog::EndMessage;
1094 return ERROR;
1095 }
1096 if (!CheckMax(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, 0))
1097 {
1098 m_context.getTestContext().getLog()
1099 << tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS value is invalid."
1100 << tcu::TestLog::EndMessage;
1101 return ERROR;
1102 }
1103 if (!CheckMax(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, 8))
1104 {
1105 m_context.getTestContext().getLog()
1106 << tcu::TestLog::Message << "GL_MAX_FRAGMENT_IMAGE_UNIFORMS value is invalid."
1107 << tcu::TestLog::EndMessage;
1108 return ERROR;
1109 }
1110 if (!CheckMax(GL_MAX_COMBINED_IMAGE_UNIFORMS, 8))
1111 {
1112 m_context.getTestContext().getLog()
1113 << tcu::TestLog::Message << "GL_MAX_COMBINED_IMAGE_UNIFORMS value is invalid."
1114 << tcu::TestLog::EndMessage;
1115 return ERROR;
1116 }
1117 return NO_ERROR;
1118 }
1119 };
1120 //-----------------------------------------------------------------------------
1121 // 1.1.2 BasicAPIBind
1122 //-----------------------------------------------------------------------------
1123 class BasicAPIBind : public ShaderImageLoadStoreBase
1124 {
1125 GLuint m_texture;
1126
Setup()1127 virtual long Setup()
1128 {
1129 m_texture = 0;
1130 return NO_ERROR;
1131 }
1132
Run()1133 virtual long Run()
1134 {
1135 for (GLuint index = 0; index < 8; ++index)
1136 {
1137 if (!CheckBinding(index, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8))
1138 {
1139 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Binding point " << index
1140 << " has invalid default state." << tcu::TestLog::EndMessage;
1141 return ERROR;
1142 }
1143 }
1144
1145 glGenTextures(1, &m_texture);
1146 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
1147 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_R32F, 16, 16, 4, 0, GL_RED, GL_FLOAT, NULL);
1148 glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, 8, 8, 4, 0, GL_RED, GL_FLOAT, NULL);
1149 glTexImage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32F, 4, 4, 4, 0, GL_RED, GL_FLOAT, NULL);
1150 glTexImage3D(GL_TEXTURE_2D_ARRAY, 3, GL_R32F, 2, 2, 4, 0, GL_RED, GL_FLOAT, NULL);
1151 glTexImage3D(GL_TEXTURE_2D_ARRAY, 4, GL_R32F, 1, 1, 4, 0, GL_RED, GL_FLOAT, NULL);
1152 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1153
1154 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
1155 if (!CheckBinding(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F))
1156 return ERROR;
1157
1158 glBindImageTexture(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8);
1159 if (!CheckBinding(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8))
1160 return ERROR;
1161
1162 glBindImageTexture(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16);
1163 if (!CheckBinding(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16))
1164 return ERROR;
1165
1166 glBindImageTexture(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I);
1167 if (!CheckBinding(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I))
1168 return ERROR;
1169
1170 glDeleteTextures(1, &m_texture);
1171 m_texture = 0;
1172
1173 for (GLuint index = 0; index < 8; ++index)
1174 {
1175 GLint name;
1176 glGetIntegeri_v(GL_IMAGE_BINDING_NAME, index, &name);
1177 if (name != 0)
1178 {
1179 m_context.getTestContext().getLog()
1180 << tcu::TestLog::Message << "Binding point " << index
1181 << " should be set to 0 after texture deletion." << tcu::TestLog::EndMessage;
1182 return ERROR;
1183 }
1184 }
1185
1186 return NO_ERROR;
1187 }
1188
Cleanup()1189 virtual long Cleanup()
1190 {
1191 glDeleteTextures(1, &m_texture);
1192 return NO_ERROR;
1193 }
1194 };
1195 //-----------------------------------------------------------------------------
1196 // 1.1.3 BasicAPIBarrier
1197 //-----------------------------------------------------------------------------
1198 class BasicAPIBarrier : public ShaderImageLoadStoreBase
1199 {
Run()1200 virtual long Run()
1201 {
1202 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
1203 glMemoryBarrier(GL_ELEMENT_ARRAY_BARRIER_BIT);
1204 glMemoryBarrier(GL_UNIFORM_BARRIER_BIT);
1205 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
1206 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1207 glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
1208 glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT);
1209 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1210 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1211 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1212 glMemoryBarrier(GL_TRANSFORM_FEEDBACK_BARRIER_BIT);
1213 glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
1214
1215 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT |
1216 GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT |
1217 GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT |
1218 GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT);
1219
1220 glMemoryBarrier(GL_ALL_BARRIER_BITS);
1221
1222 return NO_ERROR;
1223 }
1224 };
1225 //-----------------------------------------------------------------------------
1226 // 1.1.4 BasicAPITexParam
1227 //-----------------------------------------------------------------------------
1228 class BasicAPITexParam : public ShaderImageLoadStoreBase
1229 {
1230 GLuint m_texture;
1231
Setup()1232 virtual long Setup()
1233 {
1234 m_texture = 0;
1235 return NO_ERROR;
1236 }
1237
Run()1238 virtual long Run()
1239 {
1240 glGenTextures(1, &m_texture);
1241 glBindTexture(GL_TEXTURE_2D, m_texture);
1242 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, 16, 16, 0, GL_RED, GL_FLOAT, NULL);
1243
1244 GLint i;
1245 GLfloat f;
1246 GLuint ui;
1247
1248 glGetTexParameteriv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1249 if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1250 {
1251 m_context.getTestContext().getLog()
1252 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1253 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1254 << tcu::TestLog::EndMessage;
1255 return ERROR;
1256 }
1257 glGetTexParameterfv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &f);
1258 if (static_cast<GLenum>(f) != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1259 {
1260 m_context.getTestContext().getLog()
1261 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1262 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1263 << tcu::TestLog::EndMessage;
1264 return ERROR;
1265 }
1266 glGetTexParameterIiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1267 if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1268 {
1269 m_context.getTestContext().getLog()
1270 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1271 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1272 << tcu::TestLog::EndMessage;
1273 return ERROR;
1274 }
1275 glGetTexParameterIuiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &ui);
1276 if (ui != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1277 {
1278 m_context.getTestContext().getLog()
1279 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1280 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1281 << tcu::TestLog::EndMessage;
1282 return ERROR;
1283 }
1284
1285 return NO_ERROR;
1286 }
1287
Cleanup()1288 virtual long Cleanup()
1289 {
1290 glDeleteTextures(1, &m_texture);
1291 return NO_ERROR;
1292 }
1293 };
1294 //-----------------------------------------------------------------------------
1295 // 1.2.1 BasicAllFormatsStore
1296 //-----------------------------------------------------------------------------
1297 class BasicAllFormatsStore : public ShaderImageLoadStoreBase
1298 {
1299 GLuint m_vao;
1300 GLuint m_vbo;
1301
Setup()1302 virtual long Setup()
1303 {
1304 m_vao = 0;
1305 m_vbo = 0;
1306 return NO_ERROR;
1307 }
1308
Run()1309 virtual long Run()
1310 {
1311 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1312
1313 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1314 return ERROR;
1315 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1316 return ERROR;
1317 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1318 return ERROR;
1319
1320 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1321 return ERROR;
1322 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1323 return ERROR;
1324 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1325 return ERROR;
1326
1327 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1328 return ERROR;
1329 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1330 return ERROR;
1331 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1332 return ERROR;
1333
1334 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1335 return ERROR;
1336
1337 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1338 return ERROR;
1339 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1340 return ERROR;
1341 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1342 return ERROR;
1343
1344 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1345 return ERROR;
1346 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1347 return ERROR;
1348 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1349 return ERROR;
1350
1351 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1352 return ERROR;
1353 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1354 return ERROR;
1355 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1356 return ERROR;
1357 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1358 return ERROR;
1359
1360 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1361 return ERROR;
1362 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1363 return ERROR;
1364 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1365 return ERROR;
1366
1367 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1368 return ERROR;
1369 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1370 return ERROR;
1371 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1372 return ERROR;
1373
1374 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1375 return ERROR;
1376 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1377 return ERROR;
1378 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1379 return ERROR;
1380 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1381 return ERROR;
1382
1383 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1384 return ERROR;
1385 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1386 return ERROR;
1387 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1388 return ERROR;
1389
1390 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1391 return ERROR;
1392 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1393 return ERROR;
1394 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1395 return ERROR;
1396
1397 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1398 return ERROR;
1399 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1400 return ERROR;
1401 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1402 return ERROR;
1403
1404 return NO_ERROR;
1405 }
1406
1407 template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)1408 bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
1409 {
1410 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
1411 " gl_Position = i_position;" NL "}";
1412 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str());
1413 const int kSize = 16;
1414 std::vector<T> data(kSize * kSize);
1415 GLuint texture;
1416 glGenTextures(1, &texture);
1417
1418 for (GLuint unit = 0; unit < 8; ++unit)
1419 {
1420 glBindTexture(GL_TEXTURE_2D, texture);
1421 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1422 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1423 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
1424 glBindTexture(GL_TEXTURE_2D, 0);
1425
1426 glViewport(0, 0, kSize, kSize);
1427 glUseProgram(program);
1428 glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
1429 glBindVertexArray(m_vao);
1430 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1431
1432 glBindTexture(GL_TEXTURE_2D, texture);
1433 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1434 glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
1435
1436 for (int i = 0; i < kSize * kSize; ++i)
1437 {
1438 if (!Equal(data[i], expected_value, internalformat))
1439 {
1440 glDeleteTextures(1, &texture);
1441 glUseProgram(0);
1442 glDeleteProgram(program);
1443 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[i])
1444 << ". Value should be: " << ToString(expected_value)
1445 << ". Format is: " << FormatEnumToString(internalformat)
1446 << ". Unit is: " << unit << tcu::TestLog::EndMessage;
1447 return false;
1448 }
1449 }
1450
1451 if (unit < 7)
1452 {
1453 glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1));
1454 }
1455 }
1456
1457 glDeleteTextures(1, &texture);
1458 glUseProgram(0);
1459 glDeleteProgram(program);
1460
1461 return true;
1462 }
1463
Cleanup()1464 virtual long Cleanup()
1465 {
1466 glViewport(0, 0, getWindowWidth(), getWindowHeight());
1467 glDeleteVertexArrays(1, &m_vao);
1468 glDeleteBuffers(1, &m_vbo);
1469 return NO_ERROR;
1470 }
1471
1472 template <typename T>
GenFS(GLenum internalformat,const T & value)1473 std::string GenFS(GLenum internalformat, const T& value)
1474 {
1475 std::ostringstream os;
1476 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1477 << TypePrefix<T>() << "image2D g_image;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
1478 " imageStore(g_image, coord, "
1479 << TypePrefix<T>() << "vec4" << value << ");" NL " discard;" NL "}";
1480 return os.str();
1481 }
1482 };
1483 //-----------------------------------------------------------------------------
1484 // 1.2.2 BasicAllFormatsLoad
1485 //-----------------------------------------------------------------------------
1486 class BasicAllFormatsLoad : public ShaderImageLoadStoreBase
1487 {
1488 GLuint m_vao;
1489 GLuint m_vbo;
1490
Setup()1491 virtual long Setup()
1492 {
1493 m_vao = 0;
1494 m_vbo = 0;
1495 return NO_ERROR;
1496 }
1497
Run()1498 virtual long Run()
1499 {
1500 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1501
1502 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1503 return ERROR;
1504 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1505 return ERROR;
1506 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1507 return ERROR;
1508
1509 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1510 return ERROR;
1511 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1512 return ERROR;
1513 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1514 return ERROR;
1515
1516 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1517 return ERROR;
1518 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1519 return ERROR;
1520 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1521 return ERROR;
1522
1523 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1524 return ERROR;
1525
1526 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1527 return ERROR;
1528 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1529 return ERROR;
1530 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1531 return ERROR;
1532
1533 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1534 return ERROR;
1535 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1536 return ERROR;
1537 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1538 return ERROR;
1539
1540 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1541 return ERROR;
1542 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1543 return ERROR;
1544 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1545 return ERROR;
1546 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1547 return ERROR;
1548
1549 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1550 return ERROR;
1551 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1552 return ERROR;
1553 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1554 return ERROR;
1555
1556 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1557 return ERROR;
1558 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1559 return ERROR;
1560 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1561 return ERROR;
1562
1563 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1564 return ERROR;
1565 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1566 return ERROR;
1567 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1568 return ERROR;
1569 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1570 return ERROR;
1571
1572 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1573 return ERROR;
1574 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1575 return ERROR;
1576 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1577 return ERROR;
1578
1579 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1580 return ERROR;
1581 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1582 return ERROR;
1583 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1584 return ERROR;
1585
1586 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1587 return ERROR;
1588 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1589 return ERROR;
1590 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1591 return ERROR;
1592
1593 return NO_ERROR;
1594 }
1595
1596 template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)1597 bool Read(GLenum internalformat, const T& value, const T& expected_value)
1598 {
1599 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
1600 " gl_Position = i_position;" NL "}";
1601 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str());
1602 const int kSize = 16;
1603 std::vector<T> data(kSize * kSize, value);
1604 GLuint texture;
1605 glGenTextures(1, &texture);
1606
1607 for (GLuint unit = 0; unit < 8; ++unit)
1608 {
1609 glBindTexture(GL_TEXTURE_2D, texture);
1610 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1611 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1612 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
1613 glBindTexture(GL_TEXTURE_2D, 0);
1614
1615 glViewport(0, 0, kSize, kSize);
1616 glClear(GL_COLOR_BUFFER_BIT);
1617 glUseProgram(program);
1618 glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
1619 glBindVertexArray(m_vao);
1620 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1621
1622 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
1623 {
1624 glDeleteTextures(1, &texture);
1625 glUseProgram(0);
1626 glDeleteProgram(program);
1627 m_context.getTestContext().getLog()
1628 << tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat)
1629 << ". Unit is: " << unit << tcu::TestLog::EndMessage;
1630 return false;
1631 }
1632
1633 if (unit < 7)
1634 {
1635 glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1));
1636 }
1637 }
1638
1639 glDeleteTextures(1, &texture);
1640 glUseProgram(0);
1641 glDeleteProgram(program);
1642
1643 return true;
1644 }
1645
Cleanup()1646 virtual long Cleanup()
1647 {
1648 glViewport(0, 0, getWindowWidth(), getWindowHeight());
1649 glDeleteVertexArrays(1, &m_vao);
1650 glDeleteBuffers(1, &m_vbo);
1651 return NO_ERROR;
1652 }
1653
1654 template <typename T>
GenFS(GLenum internalformat,const T & expected_value)1655 std::string GenFS(GLenum internalformat, const T& expected_value)
1656 {
1657 std::ostringstream os;
1658 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
1659 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
1660 << "image2D g_image;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " "
1661 << TypePrefix<T>() << "vec4 v = imageLoad(g_image, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
1662 << expected_value
1663 << ") 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 "}";
1664 return os.str();
1665 }
1666 };
1667 //-----------------------------------------------------------------------------
1668 // 1.2.3 BasicAllFormatsStoreGeometryStages
1669 //-----------------------------------------------------------------------------
1670 class BasicAllFormatsStoreGeometryStages : public ShaderImageLoadStoreBase
1671 {
1672 GLuint m_vao;
1673
Setup()1674 virtual long Setup()
1675 {
1676 glGenVertexArrays(1, &m_vao);
1677 return NO_ERROR;
1678 }
1679
Run()1680 virtual long Run()
1681 {
1682 if (!SupportedInGeomStages(1))
1683 return NOT_SUPPORTED;
1684 glEnable(GL_RASTERIZER_DISCARD);
1685
1686 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1687 return ERROR;
1688 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1689 return ERROR;
1690 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1691 return ERROR;
1692
1693 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1694 return ERROR;
1695 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1696 return ERROR;
1697 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1698 return ERROR;
1699
1700 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1701 return ERROR;
1702 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1703 return ERROR;
1704 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1705 return ERROR;
1706
1707 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1708 return ERROR;
1709
1710 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1711 return ERROR;
1712 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1713 return ERROR;
1714 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1715 return ERROR;
1716
1717 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1718 return ERROR;
1719 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1720 return ERROR;
1721 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1722 return ERROR;
1723
1724 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1725 return ERROR;
1726 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1727 return ERROR;
1728 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1729 return ERROR;
1730 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1731 return ERROR;
1732
1733 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1734 return ERROR;
1735 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1736 return ERROR;
1737 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1738 return ERROR;
1739
1740 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1741 return ERROR;
1742 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1743 return ERROR;
1744 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1745 return ERROR;
1746
1747 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1748 return ERROR;
1749 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1750 return ERROR;
1751 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1752 return ERROR;
1753 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1754 return ERROR;
1755
1756 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1757 return ERROR;
1758 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1759 return ERROR;
1760 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1761 return ERROR;
1762
1763 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1764 return ERROR;
1765 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1766 return ERROR;
1767 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1768 return ERROR;
1769
1770 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1771 return ERROR;
1772 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1773 return ERROR;
1774 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1775 return ERROR;
1776
1777 return NO_ERROR;
1778 }
1779
1780 template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)1781 bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
1782 {
1783 const GLuint program =
1784 BuildProgram(GenVS(internalformat, write_value).c_str(), GenTCS(internalformat, write_value).c_str(),
1785 GenTES(internalformat, write_value).c_str(), GenGS(internalformat, write_value).c_str(), NULL);
1786 const int kSize = 1;
1787 std::vector<T> data(kSize * kSize);
1788 GLuint texture[4];
1789 glGenTextures(4, texture);
1790
1791 for (int i = 0; i < 4; ++i)
1792 {
1793 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1794 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1795 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1796 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]);
1797 }
1798 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1799
1800 glUseProgram(program);
1801 glUniform1i(glGetUniformLocation(program, "g_image0"), 0);
1802 glUniform1i(glGetUniformLocation(program, "g_image1"), 1);
1803 glUniform1i(glGetUniformLocation(program, "g_image2"), 2);
1804 glUniform1i(glGetUniformLocation(program, "g_image3"), 3);
1805 for (GLuint i = 0; i < 4; ++i)
1806 {
1807 glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
1808 }
1809 glBindVertexArray(m_vao);
1810 glPatchParameteri(GL_PATCH_VERTICES, 1);
1811 glDrawArrays(GL_PATCHES, 0, 1);
1812 glPatchParameteri(GL_PATCH_VERTICES, 3);
1813
1814 for (int i = 0; i < 4; ++i)
1815 {
1816 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1817 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1818 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
1819
1820 if (!Equal(data[0], expected_value, internalformat))
1821 {
1822 glDeleteTextures(4, texture);
1823 glUseProgram(0);
1824 glDeleteProgram(program);
1825 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[0])
1826 << ". Value should be: " << ToString(expected_value)
1827 << ". Format is: " << FormatEnumToString(internalformat)
1828 << ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage;
1829 return false;
1830 }
1831 }
1832 glDeleteTextures(4, texture);
1833 glUseProgram(0);
1834 glDeleteProgram(program);
1835 return true;
1836 }
1837
Cleanup()1838 virtual long Cleanup()
1839 {
1840 glDisable(GL_RASTERIZER_DISCARD);
1841 glDeleteVertexArrays(1, &m_vao);
1842 return NO_ERROR;
1843 }
1844
1845 template <typename T>
GenVS(GLenum internalformat,const T & value)1846 std::string GenVS(GLenum internalformat, const T& value)
1847 {
1848 std::ostringstream os;
1849 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1850 << TypePrefix<T>() << "image2DArray g_image0;" NL "void main() {" NL
1851 " ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL " imageStore(g_image0, coord, "
1852 << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1853 return os.str();
1854 }
1855
1856 template <typename T>
GenTCS(GLenum internalformat,const T & value)1857 std::string GenTCS(GLenum internalformat, const T& value)
1858 {
1859 std::ostringstream os;
1860 os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat)
1861 << ") writeonly uniform " << TypePrefix<T>()
1862 << "image2DArray g_image1;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL
1863 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL
1864 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL
1865 " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL " imageStore(g_image1, coord, "
1866 << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1867 return os.str();
1868 }
1869
1870 template <typename T>
GenTES(GLenum internalformat,const T & value)1871 std::string GenTES(GLenum internalformat, const T& value)
1872 {
1873 std::ostringstream os;
1874 os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout("
1875 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
1876 << "image2DArray g_image2;" NL "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL
1877 " imageStore(g_image2, coord, "
1878 << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1879 return os.str();
1880 }
1881
1882 template <typename T>
GenGS(GLenum internalformat,const T & value)1883 std::string GenGS(GLenum internalformat, const T& value)
1884 {
1885 std::ostringstream os;
1886 os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout("
1887 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
1888 << "image2DArray g_image3;" NL "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL
1889 " imageStore(g_image3, coord, "
1890 << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1891 return os.str();
1892 }
1893 };
1894 //-----------------------------------------------------------------------------
1895 // 1.2.4 BasicAllFormatsLoadGeometryStages
1896 //-----------------------------------------------------------------------------
1897 class BasicAllFormatsLoadGeometryStages : public ShaderImageLoadStoreBase
1898 {
1899 GLuint m_vao;
1900
Setup()1901 virtual long Setup()
1902 {
1903 glGenVertexArrays(1, &m_vao);
1904 return NO_ERROR;
1905 }
1906
Run()1907 virtual long Run()
1908 {
1909 if (!SupportedInGeomStages(2))
1910 return NOT_SUPPORTED;
1911 glEnable(GL_RASTERIZER_DISCARD);
1912
1913 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1914 return ERROR;
1915 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1916 return ERROR;
1917 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1918 return ERROR;
1919
1920 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1921 return ERROR;
1922 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1923 return ERROR;
1924 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1925 return ERROR;
1926
1927 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1928 return ERROR;
1929 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1930 return ERROR;
1931 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1932 return ERROR;
1933
1934 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1935 return ERROR;
1936
1937 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1938 return ERROR;
1939 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1940 return ERROR;
1941 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1942 return ERROR;
1943
1944 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1945 return ERROR;
1946 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1947 return ERROR;
1948 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1949 return ERROR;
1950
1951 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1952 return ERROR;
1953 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1954 return ERROR;
1955 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1956 return ERROR;
1957 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1958 return ERROR;
1959
1960 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1961 return ERROR;
1962 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1963 return ERROR;
1964 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1965 return ERROR;
1966
1967 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1968 return ERROR;
1969 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1970 return ERROR;
1971 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1972 return ERROR;
1973
1974 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1975 return ERROR;
1976 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1977 return ERROR;
1978 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1979 return ERROR;
1980 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1981 return ERROR;
1982
1983 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1984 return ERROR;
1985 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1986 return ERROR;
1987 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1988 return ERROR;
1989
1990 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1991 return ERROR;
1992 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1993 return ERROR;
1994 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1995 return ERROR;
1996
1997 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1998 return ERROR;
1999 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2000 return ERROR;
2001 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2002 return ERROR;
2003
2004 return NO_ERROR;
2005 }
2006
2007 template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)2008 bool Read(GLenum internalformat, const T& value, const T& expected_value)
2009 {
2010 const GLuint program = BuildProgram(
2011 GenVS(internalformat, expected_value).c_str(), GenTCS(internalformat, expected_value).c_str(),
2012 GenTES(internalformat, expected_value).c_str(), GenGS(internalformat, expected_value).c_str(), NULL);
2013 const int kSize = 1;
2014 std::vector<T> data(kSize * kSize, value);
2015 GLuint texture[8];
2016 glGenTextures(8, texture);
2017
2018 for (int i = 0; i < 4; ++i)
2019 {
2020 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
2021 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2022 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2023 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]);
2024 }
2025 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2026 vec4 zero(0);
2027 for (int i = 4; i < 8; ++i)
2028 {
2029 glBindTexture(GL_TEXTURE_2D, texture[i]);
2030 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2031 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2032 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &zero);
2033 }
2034 glBindTexture(GL_TEXTURE_2D, 0);
2035
2036 glUseProgram(program);
2037 glUniform1i(glGetUniformLocation(program, "g_image0"), 0);
2038 glUniform1i(glGetUniformLocation(program, "g_image1"), 1);
2039 glUniform1i(glGetUniformLocation(program, "g_image2"), 2);
2040 glUniform1i(glGetUniformLocation(program, "g_image3"), 3);
2041 glUniform1i(glGetUniformLocation(program, "g_image0_result"), 4);
2042 glUniform1i(glGetUniformLocation(program, "g_image1_result"), 5);
2043 glUniform1i(glGetUniformLocation(program, "g_image2_result"), 6);
2044 glUniform1i(glGetUniformLocation(program, "g_image3_result"), 7);
2045
2046 for (GLuint i = 0; i < 4; ++i)
2047 {
2048 glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2049 }
2050 for (GLuint i = 4; i < 8; ++i)
2051 {
2052 glBindImageTexture(i, texture[i], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
2053 }
2054 glBindVertexArray(m_vao);
2055 glPatchParameteri(GL_PATCH_VERTICES, 1);
2056 glDrawArrays(GL_PATCHES, 0, 1);
2057 glPatchParameteri(GL_PATCH_VERTICES, 3);
2058
2059 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
2060 const tcu::PixelFormat& pixelFormat = renderTarget.getPixelFormat();
2061 vec4 g_color_eps = vec4(
2062 1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
2063 1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
2064
2065 for (int i = 0; i < 4; ++i)
2066 {
2067 glBindTexture(GL_TEXTURE_2D, texture[i + 4]);
2068 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2069 vec4 result;
2070 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &result[0]);
2071 if (!ColorEqual(result, vec4(0, 1, 0, 1), g_color_eps))
2072 {
2073 glDeleteTextures(8, texture);
2074 glUseProgram(0);
2075 glDeleteProgram(program);
2076 m_context.getTestContext().getLog()
2077 << tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat)
2078 << ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage;
2079 return false;
2080 }
2081 }
2082 glDeleteTextures(8, texture);
2083 glUseProgram(0);
2084 glDeleteProgram(program);
2085 return true;
2086 }
2087
Cleanup()2088 virtual long Cleanup()
2089 {
2090 glDisable(GL_RASTERIZER_DISCARD);
2091 glDeleteVertexArrays(1, &m_vao);
2092 return NO_ERROR;
2093 }
2094
2095 template <typename T>
GenVS(GLenum internalformat,const T & expected_value)2096 std::string GenVS(GLenum internalformat, const T& expected_value)
2097 {
2098 std::ostringstream os;
2099 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
2100 << TypePrefix<T>()
2101 << "image2DArray g_image0;" NL "layout(rgba32f) writeonly uniform image2D g_image0_result;" NL
2102 "void main() {" NL " ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL " "
2103 << TypePrefix<T>() << "vec4 v = imageLoad(g_image0, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
2104 << expected_value << ") imageStore(g_image0_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2105 " else imageStore(g_image0_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2106 return os.str();
2107 }
2108
2109 template <typename T>
GenTCS(GLenum internalformat,const T & expected_value)2110 std::string GenTCS(GLenum internalformat, const T& expected_value)
2111 {
2112 std::ostringstream os;
2113 os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat)
2114 << ") readonly uniform " << TypePrefix<T>()
2115 << "image2DArray g_image1;" NL "layout(rgba32f) writeonly uniform image2D g_image1_result;" NL
2116 "void main() {" NL " gl_TessLevelInner[0] = 1;" NL " gl_TessLevelInner[1] = 1;" NL
2117 " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL " gl_TessLevelOuter[2] = 1;" NL
2118 " gl_TessLevelOuter[3] = 1;" NL " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL " "
2119 << TypePrefix<T>() << "vec4 v = imageLoad(g_image1, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
2120 << expected_value << ") imageStore(g_image1_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2121 " else imageStore(g_image1_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2122 return os.str();
2123 }
2124
2125 template <typename T>
GenTES(GLenum internalformat,const T & expected_value)2126 std::string GenTES(GLenum internalformat, const T& expected_value)
2127 {
2128 std::ostringstream os;
2129 os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout("
2130 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2131 << "image2DArray g_image2;" NL "layout(rgba32f) writeonly uniform image2D g_image2_result;" NL
2132 "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL " "
2133 << TypePrefix<T>() << "vec4 v = imageLoad(g_image2, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
2134 << expected_value << ") imageStore(g_image2_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2135 " else imageStore(g_image2_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2136 return os.str();
2137 }
2138
2139 template <typename T>
GenGS(GLenum internalformat,const T & expected_value)2140 std::string GenGS(GLenum internalformat, const T& expected_value)
2141 {
2142 std::ostringstream os;
2143 os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout("
2144 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2145 << "image2DArray g_image3;" NL "layout(rgba32f) writeonly uniform image2D g_image3_result;" NL
2146 "void main() {" NL " ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL " "
2147 << TypePrefix<T>() << "vec4 v = imageLoad(g_image3, coord);" NL " if (v != " << TypePrefix<T>() << "vec4"
2148 << expected_value << ") imageStore(g_image3_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2149 " else imageStore(g_image3_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2150 return os.str();
2151 }
2152 };
2153 //-----------------------------------------------------------------------------
2154 // 1.2.5 BasicAllFormatsLoadStoreComputeStage
2155 //-----------------------------------------------------------------------------
2156 class BasicAllFormatsLoadStoreComputeStage : public ShaderImageLoadStoreBase
2157 {
Run()2158 virtual long Run()
2159 {
2160 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
2161 {
2162 m_context.getTestContext().getLog()
2163 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
2164 << tcu::TestLog::EndMessage;
2165 return NOT_SUPPORTED;
2166 }
2167
2168 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
2169 return ERROR;
2170 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
2171 return ERROR;
2172 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2173 return ERROR;
2174
2175 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
2176 return ERROR;
2177 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
2178 return ERROR;
2179 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2180 return ERROR;
2181
2182 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2183 return ERROR;
2184 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2185 return ERROR;
2186 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2187 return ERROR;
2188
2189 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
2190 return ERROR;
2191
2192 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2193 return ERROR;
2194 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2195 return ERROR;
2196 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2197 return ERROR;
2198
2199 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2200 return ERROR;
2201 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2202 return ERROR;
2203 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2204 return ERROR;
2205
2206 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2207 return ERROR;
2208 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2209 return ERROR;
2210 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2211 return ERROR;
2212 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2213 return ERROR;
2214
2215 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2216 return ERROR;
2217 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2218 return ERROR;
2219 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2220 return ERROR;
2221
2222 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2223 return ERROR;
2224 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2225 return ERROR;
2226 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2227 return ERROR;
2228
2229 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
2230 return ERROR;
2231 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
2232 return ERROR;
2233 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
2234 return ERROR;
2235 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2236 return ERROR;
2237
2238 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
2239 return ERROR;
2240 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
2241 return ERROR;
2242 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2243 return ERROR;
2244
2245 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2246 return ERROR;
2247 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2248 return ERROR;
2249 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2250 return ERROR;
2251
2252 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2253 return ERROR;
2254 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2255 return ERROR;
2256 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2257 return ERROR;
2258
2259 return NO_ERROR;
2260 }
2261
2262 template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)2263 bool Read(GLenum internalformat, const T& value, const T& expected_value)
2264 {
2265 GLuint program;
2266 std::string source = GenCS<T>(internalformat);
2267 const char* const src = source.c_str();
2268 GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
2269 glShaderSource(sh, 1, &src, NULL);
2270 glCompileShader(sh);
2271 program = glCreateProgram();
2272 glAttachShader(program, sh);
2273 glLinkProgram(program);
2274 glDeleteShader(sh);
2275
2276 const int kSize = 1;
2277 std::vector<T> data(kSize * kSize, value);
2278 GLuint texture[2];
2279 glGenTextures(2, texture);
2280
2281 glBindTexture(GL_TEXTURE_2D, texture[0]);
2282 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2283 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2284 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2285 glBindTexture(GL_TEXTURE_2D, texture[1]);
2286 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2287 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2288 vec4 zero(0);
2289 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &zero);
2290
2291 glBindTexture(GL_TEXTURE_2D, 0);
2292
2293 glUseProgram(program);
2294 glUniform1i(glGetUniformLocation(program, "g_image_read"), 0);
2295 glUniform1i(glGetUniformLocation(program, "g_image_write"), 1);
2296
2297 glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2298 glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2299
2300 glDispatchCompute(1, 1, 1);
2301
2302 for (int i = 0; i < 2; ++i)
2303 {
2304 glBindTexture(GL_TEXTURE_2D, texture[i]);
2305 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2306 glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
2307
2308 if (!Equal(data[0], expected_value, internalformat))
2309 {
2310 glDeleteTextures(4, texture);
2311 glUseProgram(0);
2312 glDeleteProgram(program);
2313 m_context.getTestContext().getLog()
2314 << tcu::TestLog::Message << "Value is: " << ToString(data[0])
2315 << ". Value should be: " << ToString(expected_value)
2316 << ". Format is: " << FormatEnumToString(internalformat) << tcu::TestLog::EndMessage;
2317 return false;
2318 }
2319 }
2320 glDeleteTextures(2, texture);
2321 glUseProgram(0);
2322 glDeleteProgram(program);
2323 return true;
2324 }
2325
2326 template <typename T>
GenCS(GLenum internalformat)2327 std::string GenCS(GLenum internalformat)
2328 {
2329 std::ostringstream os;
2330 os << "#version 420 core" NL "#extension GL_ARB_compute_shader : require" NL "layout(local_size_x = 1) in;" NL
2331 "layout("
2332 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2333 << "image2D g_image_read;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2334 << TypePrefix<T>() << "image2D g_image_write;" NL "void main() {" NL
2335 " ivec2 coord = ivec2(int(gl_GlobalInvocationID.x), 0);" NL " "
2336 << TypePrefix<T>()
2337 << "vec4 v = imageLoad(g_image_read, coord);" NL " imageStore(g_image_write, coord, v);" NL "}";
2338 return os.str();
2339 }
2340 };
2341 //-----------------------------------------------------------------------------
2342 // 1.3.1 BasicAllTargetsStore
2343 //-----------------------------------------------------------------------------
2344 class BasicAllTargetsStore : public ShaderImageLoadStoreBase
2345 {
2346 GLuint m_vao;
2347 GLuint m_vbo;
2348
Setup()2349 virtual long Setup()
2350 {
2351 m_vao = 0;
2352 m_vbo = 0;
2353 return NO_ERROR;
2354 }
2355
Run()2356 virtual long Run()
2357 {
2358 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2359
2360 if (!Write(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2361 return ERROR;
2362 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2363 return ERROR;
2364 if (!Write(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2365 return ERROR;
2366
2367 if (!WriteCubeArray(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2368 return ERROR;
2369 if (!WriteCubeArray(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2370 return ERROR;
2371 if (!WriteCubeArray(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2372 return ERROR;
2373
2374 if (SupportedSamples(4))
2375 {
2376 if (!WriteMS(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2377 return ERROR;
2378
2379 GLint isamples;
2380 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
2381 if (isamples >= 4)
2382 {
2383 if (!WriteMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2384 return ERROR;
2385 if (!WriteMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2386 return ERROR;
2387 }
2388 }
2389 return NO_ERROR;
2390 }
2391
Cleanup()2392 virtual long Cleanup()
2393 {
2394 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2395 glDeleteVertexArrays(1, &m_vao);
2396 glDeleteBuffers(1, &m_vbo);
2397 return NO_ERROR;
2398 }
2399
2400 template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)2401 bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
2402 {
2403 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2404 " gl_Position = i_position;" NL "}";
2405 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str());
2406 GLuint textures[8];
2407 GLuint buffer;
2408 glGenTextures(8, textures);
2409 glGenBuffers(1, &buffer);
2410
2411 const int kSize = 16;
2412 std::vector<T> data(kSize * kSize * 2);
2413
2414 glBindTexture(GL_TEXTURE_1D, textures[0]);
2415 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2416 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2417 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2418 glBindTexture(GL_TEXTURE_1D, 0);
2419
2420 glBindTexture(GL_TEXTURE_2D, textures[1]);
2421 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2422 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2423 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2424 glBindTexture(GL_TEXTURE_2D, 0);
2425
2426 glBindTexture(GL_TEXTURE_3D, textures[2]);
2427 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2428 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2429 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2430 glBindTexture(GL_TEXTURE_3D, 0);
2431
2432 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2433 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2434 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2435 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2436 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2437
2438 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2439 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2440 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2441 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2442 &data[0]);
2443 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2444 &data[0]);
2445 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2446 &data[0]);
2447 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2448 &data[0]);
2449 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2450 &data[0]);
2451 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2452 &data[0]);
2453 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2454
2455 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2456 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
2457 glBindBuffer(GL_TEXTURE_BUFFER, 0);
2458 glBindTexture(GL_TEXTURE_BUFFER, textures[5]);
2459 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
2460 glBindTexture(GL_TEXTURE_BUFFER, 0);
2461
2462 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]);
2463 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2464 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2465 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2466 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2467
2468 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2469 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2470 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2471 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2472 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2473
2474 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2475 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2476 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2477 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2478 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2479 glBindImageTexture(5, textures[5], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2480 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2481 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2482
2483 glUseProgram(program);
2484 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
2485 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
2486 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
2487 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
2488 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4);
2489 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5);
2490 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6);
2491 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7);
2492
2493 glBindVertexArray(m_vao);
2494 glViewport(0, 0, kSize, kSize);
2495 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2496
2497 bool status = true;
2498
2499 glBindTexture(GL_TEXTURE_1D, textures[0]);
2500 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2501 glGetTexImage(GL_TEXTURE_1D, 0, Format<T>(), Type<T>(), &data[0]);
2502 glBindTexture(GL_TEXTURE_1D, 0);
2503 for (int i = 0; i < kSize; ++i)
2504 {
2505 if (!tcu::allEqual(data[i], expected_value))
2506 {
2507 status = false;
2508 m_context.getTestContext().getLog()
2509 << tcu::TestLog::Message << "GL_TEXTURE_1D target failed. Value is: " << ToString(data[i])
2510 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2511 break;
2512 }
2513 }
2514 std::fill(data.begin(), data.end(), T(0));
2515
2516 glBindTexture(GL_TEXTURE_2D, textures[1]);
2517 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2518 glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
2519 glBindTexture(GL_TEXTURE_2D, 0);
2520 for (int i = 0; i < kSize * kSize; ++i)
2521 {
2522 if (!tcu::allEqual(data[i], expected_value))
2523 {
2524 status = false;
2525 m_context.getTestContext().getLog()
2526 << tcu::TestLog::Message << "GL_TEXTURE_2D target failed. Value is: " << ToString(data[i])
2527 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2528 break;
2529 }
2530 }
2531
2532 glBindTexture(GL_TEXTURE_3D, textures[2]);
2533 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2534 glGetTexImage(GL_TEXTURE_3D, 0, Format<T>(), Type<T>(), &data[0]);
2535 glBindTexture(GL_TEXTURE_3D, 0);
2536 for (int i = 0; i < kSize * kSize * 2; ++i)
2537 {
2538 if (!tcu::allEqual(data[i], expected_value))
2539 {
2540 status = false;
2541 m_context.getTestContext().getLog()
2542 << tcu::TestLog::Message << "GL_TEXTURE_3D target failed. Value is: " << ToString(data[i])
2543 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2544 break;
2545 }
2546 }
2547
2548 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2549 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2550 glGetTexImage(GL_TEXTURE_RECTANGLE, 0, Format<T>(), Type<T>(), &data[0]);
2551 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2552 for (int i = 0; i < kSize * kSize; ++i)
2553 {
2554 if (!tcu::allEqual(data[i], expected_value))
2555 {
2556 status = false;
2557 m_context.getTestContext().getLog()
2558 << tcu::TestLog::Message << "GL_TEXTURE_RECTANGLE target failed. Value is: " << ToString(data[i])
2559 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2560 break;
2561 }
2562 }
2563
2564 {
2565 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2566 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2567 for (int face = 0; face < 6; ++face)
2568 {
2569 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]);
2570 for (int i = 0; i < kSize * kSize; ++i)
2571 {
2572 if (!tcu::allEqual(data[i], expected_value))
2573 {
2574 status = false;
2575 m_context.getTestContext().getLog()
2576 << tcu::TestLog::Message
2577 << "GL_TEXTURE_CUBE_MAP_POSITIVE_X target failed. Value is: " << ToString(data[i])
2578 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2579 break;
2580 }
2581 }
2582 }
2583 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2584 }
2585
2586 glBindTexture(GL_TEXTURE_BUFFER, textures[5]);
2587 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2588 glBindTexture(GL_TEXTURE_BUFFER, 0);
2589 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2590 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, kSize * sizeof(T), &data[0]);
2591 glBindBuffer(GL_TEXTURE_BUFFER, 0);
2592 for (int i = 0; i < kSize; ++i)
2593 {
2594 if (!tcu::allEqual(data[i], expected_value))
2595 {
2596 status = false;
2597 m_context.getTestContext().getLog()
2598 << tcu::TestLog::Message << "GL_TEXTURE_BUFFER target failed. Value is: " << ToString(data[i])
2599 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2600 break;
2601 }
2602 }
2603
2604 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]);
2605 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2606 glGetTexImage(GL_TEXTURE_1D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2607 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2608 for (int i = 0; i < kSize * 2; ++i)
2609 {
2610 if (!tcu::allEqual(data[i], expected_value))
2611 {
2612 status = false;
2613 m_context.getTestContext().getLog()
2614 << tcu::TestLog::Message << "GL_TEXTURE_1D_ARRAY target failed. Value is: " << ToString(data[i])
2615 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2616 break;
2617 }
2618 }
2619
2620 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2621 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2622 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2623 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2624 for (int i = 0; i < kSize * kSize * 2; ++i)
2625 {
2626 if (!tcu::allEqual(data[i], expected_value))
2627 {
2628 status = false;
2629 m_context.getTestContext().getLog()
2630 << tcu::TestLog::Message << "GL_TEXTURE_2D_ARRAY target failed. Value is: " << ToString(data[i])
2631 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2632 break;
2633 }
2634 }
2635
2636 glUseProgram(0);
2637 glDeleteProgram(program);
2638 glDeleteTextures(8, textures);
2639 glDeleteBuffers(1, &buffer);
2640
2641 return status;
2642 }
2643
2644 template <typename T>
WriteMS(GLenum internalformat,const T & write_value,const T & expected_value)2645 bool WriteMS(GLenum internalformat, const T& write_value, const T& expected_value)
2646 {
2647
2648 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2649 " gl_Position = i_position;" NL "}";
2650 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, write_value).c_str());
2651 const GLuint val_program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMSVal(expected_value).c_str());
2652 GLuint textures[2];
2653 glGenTextures(2, textures);
2654
2655 const int kSize = 16;
2656
2657 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
2658 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
2659 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
2660
2661 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
2662 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
2663 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
2664
2665 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2666 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2667
2668 glClear(GL_COLOR_BUFFER_BIT);
2669 glUseProgram(program);
2670 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
2671 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
2672
2673 glBindVertexArray(m_vao);
2674 glViewport(0, 0, kSize, kSize);
2675 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2676
2677 bool status = true;
2678
2679 glActiveTexture(GL_TEXTURE0);
2680 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
2681 glActiveTexture(GL_TEXTURE1);
2682 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
2683
2684 glUseProgram(val_program);
2685 glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms"), 0);
2686 glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms_array"), 1);
2687
2688 glBindVertexArray(m_vao);
2689 glViewport(0, 0, kSize, kSize);
2690 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
2691 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2692
2693 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
2694 {
2695 status = false;
2696 m_context.getTestContext().getLog()
2697 << tcu::TestLog::Message
2698 << "GL_TEXTURE_2D_MULTISAMPLE or GL_TEXTURE_2D_MULTISAMPLE_ARRAY target failed."
2699 << tcu::TestLog::EndMessage;
2700 }
2701
2702 glActiveTexture(GL_TEXTURE0);
2703 glDeleteTextures(2, textures);
2704 glUseProgram(0);
2705 glDeleteProgram(program);
2706 glDeleteProgram(val_program);
2707
2708 return status;
2709 }
2710
2711 template <typename T>
WriteCubeArray(GLenum internalformat,const T & write_value,const T & expected_value)2712 bool WriteCubeArray(GLenum internalformat, const T& write_value, const T& expected_value)
2713 {
2714 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2715 " gl_Position = i_position;" NL "}";
2716 const GLuint program =
2717 BuildProgram(src_vs, NULL, NULL, NULL, GenFSCubeArray(internalformat, write_value).c_str());
2718 GLuint textures[1];
2719 glGenTextures(1, textures);
2720
2721 const int kSize = 16;
2722
2723 std::vector<T> data(kSize * kSize * 12);
2724 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]);
2725 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2726 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
2727 &data[0]);
2728 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
2729
2730 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2731
2732 glUseProgram(program);
2733 glBindVertexArray(m_vao);
2734 glViewport(0, 0, kSize, kSize);
2735 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2736
2737 bool status = true;
2738
2739 std::fill(data.begin(), data.end(), T(0));
2740 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]);
2741 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2742 glGetTexImage(GL_TEXTURE_CUBE_MAP_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2743 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
2744 for (int i = 0; i < kSize * kSize * 12; ++i)
2745 {
2746 if (!tcu::allEqual(data[i], expected_value))
2747 {
2748 status = false;
2749 m_context.getTestContext().getLog()
2750 << tcu::TestLog::Message
2751 << "GL_TEXTURE_CUBE_MAP_ARRAY target failed. Value is: " << ToString(data[i])
2752 << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2753 break;
2754 }
2755 }
2756
2757 glDeleteTextures(1, textures);
2758 glUseProgram(0);
2759 glDeleteProgram(program);
2760
2761 return status;
2762 }
2763
2764 template <typename T>
GenFS(GLenum internalformat,const T & write_value)2765 std::string GenFS(GLenum internalformat, const T& write_value)
2766 {
2767 std::ostringstream os;
2768 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2769 << TypePrefix<T>() << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat)
2770 << ") writeonly uniform " << TypePrefix<T>() << "image2D g_image_2d;" NL "layout("
2771 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
2772 << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2773 << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat)
2774 << ") writeonly uniform " << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout("
2775 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
2776 << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2777 << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat)
2778 << ") writeonly uniform " << TypePrefix<T>()
2779 << "image2DArray g_image_2darray;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2780 " imageStore(g_image_1d, coord.x, "
2781 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2d, coord, " << TypePrefix<T>()
2782 << "vec4" << write_value << ");" NL " imageStore(g_image_3d, ivec3(coord.xy, 0), " << TypePrefix<T>()
2783 << "vec4" << write_value << ");" NL " imageStore(g_image_3d, ivec3(coord.xy, 1), " << TypePrefix<T>()
2784 << "vec4" << write_value << ");" NL " imageStore(g_image_2drect, coord, " << TypePrefix<T>() << "vec4"
2785 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 0), " << TypePrefix<T>() << "vec4"
2786 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 1), " << TypePrefix<T>() << "vec4"
2787 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 2), " << TypePrefix<T>() << "vec4"
2788 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 3), " << TypePrefix<T>() << "vec4"
2789 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 4), " << TypePrefix<T>() << "vec4"
2790 << write_value << ");" NL " imageStore(g_image_cube, ivec3(coord, 5), " << TypePrefix<T>() << "vec4"
2791 << write_value << ");" NL " imageStore(g_image_buffer, coord.x, " << TypePrefix<T>() << "vec4"
2792 << write_value << ");" NL " imageStore(g_image_1darray, ivec2(coord.x, 0), " << TypePrefix<T>() << "vec4"
2793 << write_value << ");" NL " imageStore(g_image_1darray, ivec2(coord.x, 1), " << TypePrefix<T>() << "vec4"
2794 << write_value << ");" NL " imageStore(g_image_2darray, ivec3(coord, 0), " << TypePrefix<T>() << "vec4"
2795 << write_value << ");" NL " imageStore(g_image_2darray, ivec3(coord, 1), " << TypePrefix<T>() << "vec4"
2796 << write_value << ");" NL " discard;" NL "}";
2797 return os.str();
2798 }
2799
2800 template <typename T>
GenFSMS(GLenum internalformat,const T & write_value)2801 std::string GenFSMS(GLenum internalformat, const T& write_value)
2802 {
2803 std::ostringstream os;
2804 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2805 << TypePrefix<T>() << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat)
2806 << ") writeonly uniform " << TypePrefix<T>()
2807 << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2808 " imageStore(g_image_2dms, coord, 0, "
2809 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2dms, coord, 1, "
2810 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2dms, coord, 2, "
2811 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_2dms, coord, 3, "
2812 << TypePrefix<T>() << "vec4" << write_value
2813 << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 0, " << TypePrefix<T>() << "vec4"
2814 << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 1, " << TypePrefix<T>()
2815 << "vec4" << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 2, "
2816 << TypePrefix<T>() << "vec4" << write_value
2817 << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 0), 3, " << TypePrefix<T>() << "vec4"
2818 << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 0, " << TypePrefix<T>()
2819 << "vec4" << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 1, "
2820 << TypePrefix<T>() << "vec4" << write_value
2821 << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 2, " << TypePrefix<T>() << "vec4"
2822 << write_value << ");" NL " imageStore(g_image_2dms_array, ivec3(coord, 1), 3, " << TypePrefix<T>()
2823 << "vec4" << write_value << ");" NL " discard;" NL "}";
2824 return os.str();
2825 }
2826
2827 template <typename T>
GenFSMSVal(const T & expected_value)2828 std::string GenFSMSVal(const T& expected_value)
2829 {
2830 std::ostringstream os;
2831 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform " << TypePrefix<T>()
2832 << "sampler2DMS g_sampler_2dms;" NL "uniform " << TypePrefix<T>()
2833 << "sampler2DMSArray g_sampler_2dms_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
2834 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " if (texelFetch(g_sampler_2dms, coord, 0) != "
2835 << TypePrefix<T>() << "vec4" << expected_value
2836 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (texelFetch(g_sampler_2dms, coord, 1) != "
2837 << TypePrefix<T>() << "vec4" << expected_value
2838 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (texelFetch(g_sampler_2dms, coord, 2) != "
2839 << TypePrefix<T>() << "vec4" << expected_value
2840 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (texelFetch(g_sampler_2dms, coord, 3) != "
2841 << TypePrefix<T>() << "vec4" << expected_value
2842 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL
2843 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 0) != "
2844 << TypePrefix<T>() << "vec4" << expected_value
2845 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2846 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 1) != "
2847 << TypePrefix<T>() << "vec4" << expected_value
2848 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2849 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 2) != "
2850 << TypePrefix<T>() << "vec4" << expected_value
2851 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2852 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 3) != "
2853 << TypePrefix<T>() << "vec4" << expected_value
2854 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2855 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 0) != "
2856 << TypePrefix<T>() << "vec4" << expected_value
2857 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2858 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 1) != "
2859 << TypePrefix<T>() << "vec4" << expected_value
2860 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2861 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 2) != "
2862 << TypePrefix<T>() << "vec4" << expected_value
2863 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2864 " if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 3) != "
2865 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}";
2866 return os.str();
2867 }
2868
2869 template <typename T>
GenFSCubeArray(GLenum internalformat,const T & write_value)2870 std::string GenFSCubeArray(GLenum internalformat, const T& write_value)
2871 {
2872 std::ostringstream os;
2873 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2874 << TypePrefix<T>()
2875 << "imageCubeArray g_image_cube_array;" NL "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2876 " imageStore(g_image_cube_array, ivec3(coord, 0), "
2877 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 1), "
2878 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 2), "
2879 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 3), "
2880 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 4), "
2881 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 5), "
2882 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 6), "
2883 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 7), "
2884 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 8), "
2885 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 9), "
2886 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 10), "
2887 << TypePrefix<T>() << "vec4" << write_value << ");" NL " imageStore(g_image_cube_array, ivec3(coord, 11), "
2888 << TypePrefix<T>() << "vec4" << write_value << ");" NL " discard;" NL "}";
2889 return os.str();
2890 }
2891 };
2892 //-----------------------------------------------------------------------------
2893 // 1.3.2.1 BasicAllTargetsLoadNonMS
2894 //-----------------------------------------------------------------------------
2895 class BasicAllTargetsLoadNonMS : public ShaderImageLoadStoreBase
2896 {
2897 GLuint m_vao;
2898 GLuint m_vbo;
2899
Setup()2900 virtual long Setup()
2901 {
2902 m_vao = 0;
2903 m_vbo = 0;
2904 return NO_ERROR;
2905 }
2906
Run()2907 virtual long Run()
2908 {
2909 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2910
2911 if (!Read(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
2912 return ERROR;
2913 if (!Read(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000)))
2914 return ERROR;
2915 if (!Read(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000)))
2916 return ERROR;
2917
2918 if (!ReadCube(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
2919 return ERROR;
2920 if (!ReadCube(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000)))
2921 return ERROR;
2922 if (!ReadCube(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000)))
2923 return ERROR;
2924
2925 return NO_ERROR;
2926 }
2927
Cleanup()2928 virtual long Cleanup()
2929 {
2930 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2931 glDeleteVertexArrays(1, &m_vao);
2932 glDeleteBuffers(1, &m_vbo);
2933 return NO_ERROR;
2934 }
2935
2936 template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value)2937 bool Read(GLenum internalformat, const T& value, const T& expected_value)
2938 {
2939 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2940 " gl_Position = i_position;" NL "}";
2941 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str());
2942 GLuint textures[7];
2943 GLuint buffer;
2944 glGenTextures(7, textures);
2945 glGenBuffers(1, &buffer);
2946
2947 const int kSize = 16;
2948 std::vector<T> data(kSize * kSize * 2, value);
2949
2950 glBindTexture(GL_TEXTURE_1D, textures[0]);
2951 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2952 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2953 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2954 glBindTexture(GL_TEXTURE_1D, 0);
2955
2956 glBindTexture(GL_TEXTURE_2D, textures[1]);
2957 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2958 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2959 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2960 glBindTexture(GL_TEXTURE_2D, 0);
2961
2962 glBindTexture(GL_TEXTURE_3D, textures[2]);
2963 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2964 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2965 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2966 glBindTexture(GL_TEXTURE_3D, 0);
2967
2968 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2969 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2970 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2971 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2972 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2973
2974 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2975 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
2976 glBindBuffer(GL_TEXTURE_BUFFER, 0);
2977 glBindTexture(GL_TEXTURE_BUFFER, textures[4]);
2978 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
2979 glBindTexture(GL_TEXTURE_BUFFER, 0);
2980
2981 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]);
2982 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2983 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2984 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2985 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2986
2987 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]);
2988 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2989 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2990 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2991 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2992
2993 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2994 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2995 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2996 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2997 glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2998 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2999 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3000
3001 glClear(GL_COLOR_BUFFER_BIT);
3002
3003 glUseProgram(program);
3004 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
3005 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
3006 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
3007 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
3008 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4);
3009 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5);
3010 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6);
3011
3012 glBindVertexArray(m_vao);
3013 glViewport(0, 0, kSize, kSize);
3014 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3015
3016 bool status = true;
3017
3018 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3019 {
3020 status = false;
3021 }
3022
3023 std::map<std::string, GLuint> name_index_map;
3024 GLint uniforms;
3025 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3026 if (uniforms != 7)
3027 {
3028 status = false;
3029 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3030 << " should be 7." << tcu::TestLog::EndMessage;
3031 }
3032 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3033 {
3034 GLchar name[32];
3035 glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3036 name_index_map.insert(std::make_pair(std::string(name), index));
3037 }
3038
3039 if (!CheckUniform(program, "g_image_1d", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D)))
3040 status = false;
3041 if (!CheckUniform(program, "g_image_2d", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D)))
3042 status = false;
3043 if (!CheckUniform(program, "g_image_3d", name_index_map, 1, ImageType<T>(GL_TEXTURE_3D)))
3044 status = false;
3045 if (!CheckUniform(program, "g_image_2drect", name_index_map, 1, ImageType<T>(GL_TEXTURE_RECTANGLE)))
3046 status = false;
3047 if (!CheckUniform(program, "g_image_buffer", name_index_map, 1, ImageType<T>(GL_TEXTURE_BUFFER)))
3048 status = false;
3049 if (!CheckUniform(program, "g_image_1darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D_ARRAY)))
3050 status = false;
3051 if (!CheckUniform(program, "g_image_2darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_ARRAY)))
3052 status = false;
3053
3054 glUseProgram(0);
3055 glDeleteProgram(program);
3056 glDeleteTextures(7, textures);
3057 glDeleteBuffers(1, &buffer);
3058
3059 return status;
3060 }
3061
3062 template <typename T>
ReadCube(GLenum internalformat,const T & value,const T & expected_value)3063 bool ReadCube(GLenum internalformat, const T& value, const T& expected_value)
3064 {
3065 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3066 " gl_Position = i_position;" NL "}";
3067 const GLuint program =
3068 BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube(internalformat, expected_value).c_str());
3069 GLuint textures[2];
3070 glGenTextures(2, textures);
3071
3072 const int kSize = 16;
3073 std::vector<T> data(kSize * kSize * 12, value);
3074
3075 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]);
3076 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3077 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3078 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3079 &data[0]);
3080 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3081 &data[0]);
3082 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3083 &data[0]);
3084 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3085 &data[0]);
3086 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3087 &data[0]);
3088 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3089 &data[0]);
3090 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3091
3092 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]);
3093 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3094 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3095 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
3096 &data[0]);
3097 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
3098
3099 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3100 glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3101
3102 glClear(GL_COLOR_BUFFER_BIT);
3103
3104 glUseProgram(program);
3105 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0);
3106 glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1);
3107
3108 glBindVertexArray(m_vao);
3109 glViewport(0, 0, kSize, kSize);
3110 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3111
3112 bool status = true;
3113
3114 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3115 {
3116 status = false;
3117 }
3118
3119 std::map<std::string, GLuint> name_index_map;
3120 GLint uniforms;
3121 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3122 if (uniforms != 2)
3123 {
3124 status = false;
3125 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3126 << " should be 2." << tcu::TestLog::EndMessage;
3127 }
3128 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3129 {
3130 GLchar name[32];
3131 glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3132 name_index_map.insert(std::make_pair(std::string(name), index));
3133 }
3134
3135 if (!CheckUniform(program, "g_image_cube", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP)))
3136 status = false;
3137 if (!CheckUniform(program, "g_image_cube_array", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP_ARRAY)))
3138 status = false;
3139
3140 glUseProgram(0);
3141 glDeleteProgram(program);
3142 glDeleteTextures(2, textures);
3143
3144 return status;
3145 }
3146
3147 template <typename T>
GenFS(GLenum internalformat,const T & expected_value)3148 std::string GenFS(GLenum internalformat, const T& expected_value)
3149 {
3150 std::ostringstream os;
3151 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3152 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3153 << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3154 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3155 << ") readonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3156 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3157 << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3158 << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
3159 << ") readonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
3160 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3161 << "image2DArray g_image_2darray;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3162 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " "
3163 << TypePrefix<T>()
3164 << "vec4 v;" NL " v = imageLoad(g_image_1d, coord.x);" NL " if (v != " << TypePrefix<T>() << "vec4"
3165 << expected_value
3166 << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL " v = imageLoad(g_image_2d, coord);" NL " if (v != "
3167 << TypePrefix<T>() << "vec4" << expected_value
3168 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " v = imageLoad(g_image_3d, ivec3(coord.xy, 0));" NL
3169 " if (v != "
3170 << TypePrefix<T>() << "vec4" << expected_value
3171 << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL " v = imageLoad(g_image_3d, ivec3(coord.xy, 1));" NL
3172 " if (v != "
3173 << TypePrefix<T>() << "vec4" << expected_value
3174 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " v = imageLoad(g_image_2drect, coord);" NL " if (v != "
3175 << TypePrefix<T>() << "vec4" << expected_value
3176 << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL " v = imageLoad(g_image_buffer, coord.x);" NL " if (v != "
3177 << TypePrefix<T>() << "vec4" << expected_value
3178 << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL " v = imageLoad(g_image_1darray, ivec2(coord.x, 0));" NL
3179 " if (v != "
3180 << TypePrefix<T>() << "vec4" << expected_value
3181 << ") o_color = vec4(1.0, 0.0, 0.0, 0.65);" NL " v = imageLoad(g_image_1darray, ivec2(coord.x, 1));" NL
3182 " if (v != "
3183 << TypePrefix<T>() << "vec4" << expected_value
3184 << ") o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL " v = imageLoad(g_image_2darray, ivec3(coord, 0));" NL
3185 " if (v != "
3186 << TypePrefix<T>() << "vec4" << expected_value
3187 << ") o_color = vec4(1.0, 0.0, 0.0, 0.75);" NL " v = imageLoad(g_image_2darray, ivec3(coord, 1));" NL
3188 " if (v != "
3189 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL "}";
3190 return os.str();
3191 }
3192
3193 template <typename T>
GenFSCube(GLenum internalformat,const T & expected_value)3194 std::string GenFSCube(GLenum internalformat, const T& expected_value)
3195 {
3196 std::ostringstream os;
3197 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3198 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3199 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3200 << TypePrefix<T>()
3201 << "imageCubeArray g_image_cube_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3202 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " "
3203 << TypePrefix<T>()
3204 << "vec4 v;" NL " v = imageLoad(g_image_cube, ivec3(coord, 0));" NL " if (v != " << TypePrefix<T>()
3205 << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
3206 " v = imageLoad(g_image_cube, ivec3(coord, 1));" NL " if (v != "
3207 << TypePrefix<T>() << "vec4" << expected_value
3208 << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL " v = imageLoad(g_image_cube, ivec3(coord, 2));" NL
3209 " if (v != "
3210 << TypePrefix<T>() << "vec4" << expected_value
3211 << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL " v = imageLoad(g_image_cube, ivec3(coord, 3));" NL
3212 " if (v != "
3213 << TypePrefix<T>() << "vec4" << expected_value
3214 << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL " v = imageLoad(g_image_cube, ivec3(coord, 4));" NL
3215 " if (v != "
3216 << TypePrefix<T>() << "vec4" << expected_value
3217 << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL " v = imageLoad(g_image_cube, ivec3(coord, 5));" NL
3218 " if (v != "
3219 << TypePrefix<T>() << "vec4" << expected_value
3220 << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 0));" NL
3221 " if (v != "
3222 << TypePrefix<T>() << "vec4" << expected_value
3223 << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 1));" NL
3224 " if (v != "
3225 << TypePrefix<T>() << "vec4" << expected_value
3226 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 2));" NL
3227 " if (v != "
3228 << TypePrefix<T>() << "vec4" << expected_value
3229 << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 3));" NL
3230 " if (v != "
3231 << TypePrefix<T>() << "vec4" << expected_value
3232 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 4));" NL
3233 " if (v != "
3234 << TypePrefix<T>() << "vec4" << expected_value
3235 << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 5));" NL
3236 " if (v != "
3237 << TypePrefix<T>() << "vec4" << expected_value
3238 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 6));" NL
3239 " if (v != "
3240 << TypePrefix<T>() << "vec4" << expected_value
3241 << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 7));" NL
3242 " if (v != "
3243 << TypePrefix<T>() << "vec4" << expected_value
3244 << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 8));" NL
3245 " if (v != "
3246 << TypePrefix<T>() << "vec4" << expected_value
3247 << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 9));" NL
3248 " if (v != "
3249 << TypePrefix<T>() << "vec4" << expected_value
3250 << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 10));" NL
3251 " if (v != "
3252 << TypePrefix<T>() << "vec4" << expected_value
3253 << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL " v = imageLoad(g_image_cube_array, ivec3(coord, 11));" NL
3254 " if (v != "
3255 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL "}";
3256 return os.str();
3257 }
3258 };
3259 //-----------------------------------------------------------------------------
3260 // 1.3.2.2 BasicAllTargetsLoadMS
3261 //-----------------------------------------------------------------------------
3262 class BasicAllTargetsLoadMS : public ShaderImageLoadStoreBase
3263 {
3264 GLuint m_vao;
3265 GLuint m_vbo;
3266
Setup()3267 virtual long Setup()
3268 {
3269 m_vao = 0;
3270 m_vbo = 0;
3271 return NO_ERROR;
3272 }
3273
Run()3274 virtual long Run()
3275 {
3276 if (!SupportedSamples(4))
3277 return NOT_SUPPORTED;
3278
3279 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3280
3281 if (!ReadMS(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
3282 return ERROR;
3283
3284 GLint isamples;
3285 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
3286 if (isamples >= 4)
3287 {
3288 if (!ReadMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
3289 return ERROR;
3290 if (!ReadMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
3291 return ERROR;
3292 }
3293
3294 return NO_ERROR;
3295 }
3296
Cleanup()3297 virtual long Cleanup()
3298 {
3299 glViewport(0, 0, getWindowWidth(), getWindowHeight());
3300 glDeleteVertexArrays(1, &m_vao);
3301 glDeleteBuffers(1, &m_vbo);
3302 return NO_ERROR;
3303 }
3304
3305 template <typename T>
ReadMS(GLenum internalformat,const T & value,const T & expected_value)3306 bool ReadMS(GLenum internalformat, const T& value, const T& expected_value)
3307 {
3308 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3309 " gl_Position = i_position;" NL "}";
3310 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, expected_value).c_str());
3311 GLuint textures[2];
3312 glGenTextures(2, textures);
3313
3314 const int kSize = 16;
3315
3316 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
3317 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
3318 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
3319
3320 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
3321 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
3322 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
3323
3324 GLuint fbo;
3325 glGenFramebuffers(1, &fbo);
3326 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3327 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
3328 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0);
3329 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1);
3330 const GLenum draw_buffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
3331 glDrawBuffers(3, draw_buffers);
3332 ClearBuffer(GL_COLOR, 0, value);
3333 ClearBuffer(GL_COLOR, 1, value);
3334 ClearBuffer(GL_COLOR, 2, value);
3335 glDeleteFramebuffers(1, &fbo);
3336
3337 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
3338 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3339
3340 glUseProgram(program);
3341 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
3342 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
3343
3344 glClear(GL_COLOR_BUFFER_BIT);
3345 glBindVertexArray(m_vao);
3346 glViewport(0, 0, kSize, kSize);
3347 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3348
3349 bool status = true;
3350
3351 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3352 {
3353 status = false;
3354 }
3355
3356 std::map<std::string, GLuint> name_index_map;
3357 GLint uniforms;
3358 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3359 if (uniforms != 2)
3360 {
3361 status = false;
3362 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3363 << " should be 2." << tcu::TestLog::EndMessage;
3364 }
3365 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3366 {
3367 GLchar name[32];
3368 glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3369 name_index_map.insert(std::make_pair(std::string(name), index));
3370 }
3371
3372 if (!CheckUniform(program, "g_image_2dms", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE)))
3373 status = false;
3374 if (!CheckUniform(program, "g_image_2dms_array", name_index_map, 1,
3375 ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE_ARRAY)))
3376 status = false;
3377
3378 glDeleteTextures(2, textures);
3379 glUseProgram(0);
3380 glDeleteProgram(program);
3381
3382 return status;
3383 }
3384
3385 template <typename T>
GenFSMS(GLenum internalformat,const T & expected_value)3386 std::string GenFSMS(GLenum internalformat, const T& expected_value)
3387 {
3388 std::ostringstream os;
3389 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3390 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3391 << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3392 << TypePrefix<T>()
3393 << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3394 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " if (imageLoad(g_image_2dms, coord, 0) != "
3395 << TypePrefix<T>() << "vec4" << expected_value
3396 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms, coord, 1) != "
3397 << TypePrefix<T>() << "vec4" << expected_value
3398 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms, coord, 2) != "
3399 << TypePrefix<T>() << "vec4" << expected_value
3400 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms, coord, 3) != "
3401 << TypePrefix<T>() << "vec4" << expected_value
3402 << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 0) != "
3403 << TypePrefix<T>() << "vec4" << expected_value
3404 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 1) != "
3405 << TypePrefix<T>() << "vec4" << expected_value
3406 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 2) != "
3407 << TypePrefix<T>() << "vec4" << expected_value
3408 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 3) != "
3409 << TypePrefix<T>() << "vec4" << expected_value
3410 << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 0) != "
3411 << TypePrefix<T>() << "vec4" << expected_value
3412 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 1) != "
3413 << TypePrefix<T>() << "vec4" << expected_value
3414 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 2) != "
3415 << TypePrefix<T>() << "vec4" << expected_value
3416 << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL " if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 3) != "
3417 << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}";
3418 return os.str();
3419 }
3420 };
3421 //-----------------------------------------------------------------------------
3422 // 1.3.3 BasicAllTargetsAtomic
3423 //-----------------------------------------------------------------------------
3424 class BasicAllTargetsAtomic : public ShaderImageLoadStoreBase
3425 {
3426 GLuint m_vao;
3427 GLuint m_vbo;
3428
Setup()3429 virtual long Setup()
3430 {
3431 m_vao = 0;
3432 m_vbo = 0;
3433 return NO_ERROR;
3434 }
3435
Run()3436 virtual long Run()
3437 {
3438 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3439
3440 if (!Atomic<GLint>(GL_R32I))
3441 return ERROR;
3442 if (!Atomic<GLuint>(GL_R32UI))
3443 return ERROR;
3444
3445 if (!AtomicCube<GLint>(GL_R32I))
3446 return ERROR;
3447 if (!AtomicCube<GLuint>(GL_R32UI))
3448 return ERROR;
3449
3450 GLint isamples;
3451 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
3452 if (SupportedSamples(4) && isamples >= 4)
3453 {
3454 if (!AtomicMS<GLint>(GL_R32I))
3455 return ERROR;
3456 if (!AtomicMS<GLuint>(GL_R32UI))
3457 return ERROR;
3458 }
3459
3460 return NO_ERROR;
3461 }
3462
Cleanup()3463 virtual long Cleanup()
3464 {
3465 glViewport(0, 0, getWindowWidth(), getWindowHeight());
3466 glDeleteVertexArrays(1, &m_vao);
3467 glDeleteBuffers(1, &m_vbo);
3468 return NO_ERROR;
3469 }
3470
3471 template <typename T>
Atomic(GLenum internalformat)3472 bool Atomic(GLenum internalformat)
3473 {
3474 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3475 " gl_Position = i_position;" NL "}";
3476 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS<T>(internalformat).c_str());
3477 GLuint textures[7];
3478 GLuint buffer;
3479 glGenTextures(7, textures);
3480 glGenBuffers(1, &buffer);
3481
3482 const int kSize = 16;
3483 std::vector<T> data(kSize * kSize * 2);
3484
3485 glBindTexture(GL_TEXTURE_1D, textures[0]);
3486 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3487 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3488 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3489 glBindTexture(GL_TEXTURE_1D, 0);
3490
3491 glBindTexture(GL_TEXTURE_2D, textures[1]);
3492 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3493 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3494 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3495 glBindTexture(GL_TEXTURE_2D, 0);
3496
3497 glBindTexture(GL_TEXTURE_3D, textures[2]);
3498 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3499 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3500 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3501 glBindTexture(GL_TEXTURE_3D, 0);
3502
3503 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
3504 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3505 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3506 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3507 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
3508
3509 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
3510 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
3511 glBindBuffer(GL_TEXTURE_BUFFER, 0);
3512 glBindTexture(GL_TEXTURE_BUFFER, textures[4]);
3513 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
3514 glBindTexture(GL_TEXTURE_BUFFER, 0);
3515
3516 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]);
3517 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3518 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3519 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3520 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
3521
3522 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]);
3523 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3524 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3525 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3526 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
3527
3528 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3529 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3530 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3531 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3532 glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3533 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3534 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3535
3536 glClear(GL_COLOR_BUFFER_BIT);
3537
3538 glUseProgram(program);
3539 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
3540 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
3541 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
3542 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
3543 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4);
3544 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5);
3545 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6);
3546
3547 glBindVertexArray(m_vao);
3548 glViewport(0, 0, kSize, 1);
3549 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3550
3551 bool status = true;
3552
3553 if (!ValidateReadBuffer(0, 0, kSize, 1, vec4(0, 1, 0, 1)))
3554 {
3555 status = false;
3556 }
3557
3558 glUseProgram(0);
3559 glDeleteProgram(program);
3560 glDeleteTextures(7, textures);
3561 glDeleteBuffers(1, &buffer);
3562
3563 return status;
3564 }
3565
3566 template <typename T>
AtomicCube(GLenum internalformat)3567 bool AtomicCube(GLenum internalformat)
3568 {
3569 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3570 " gl_Position = i_position;" NL "}";
3571 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube<T>(internalformat).c_str());
3572 GLuint textures[2];
3573 glGenTextures(2, textures);
3574
3575 const int kSize = 16;
3576 std::vector<T> data(kSize * kSize * 12);
3577
3578 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]);
3579 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3580 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3581 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3582 &data[0]);
3583 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3584 &data[0]);
3585 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3586 &data[0]);
3587 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3588 &data[0]);
3589 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3590 &data[0]);
3591 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3592 &data[0]);
3593 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3594
3595 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]);
3596 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3597 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3598 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
3599 &data[0]);
3600 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
3601
3602 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3603 glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3604
3605 glClear(GL_COLOR_BUFFER_BIT);
3606
3607 glUseProgram(program);
3608 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0);
3609 glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1);
3610
3611 glBindVertexArray(m_vao);
3612 glViewport(0, 0, kSize, kSize);
3613 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3614
3615 bool status = true;
3616
3617 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3618 {
3619 status = false;
3620 }
3621
3622 glUseProgram(0);
3623 glDeleteProgram(program);
3624 glDeleteTextures(2, textures);
3625
3626 return status;
3627 }
3628
3629 template <typename T>
AtomicMS(GLenum internalformat)3630 bool AtomicMS(GLenum internalformat)
3631 {
3632 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3633 " gl_Position = i_position;" NL "}";
3634 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS<T>(internalformat).c_str());
3635 GLuint textures[2];
3636 glGenTextures(2, textures);
3637
3638 const int kSize = 16;
3639
3640 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
3641 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
3642 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
3643
3644 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
3645 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
3646 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
3647
3648 GLuint fbo;
3649 glGenFramebuffers(1, &fbo);
3650 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3651 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
3652 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0);
3653 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1);
3654 const GLenum draw_buffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
3655 glDrawBuffers(3, draw_buffers);
3656 if (internalformat == GL_R32I)
3657 {
3658 const GLint value[4] = { 0, 0, 0, 0 };
3659 glClearBufferiv(GL_COLOR, 0, value);
3660 glClearBufferiv(GL_COLOR, 1, value);
3661 glClearBufferiv(GL_COLOR, 2, value);
3662 }
3663 else
3664 {
3665 const GLuint value[4] = { 0, 0, 0, 0 };
3666 glClearBufferuiv(GL_COLOR, 0, value);
3667 glClearBufferuiv(GL_COLOR, 1, value);
3668 glClearBufferuiv(GL_COLOR, 2, value);
3669 }
3670 glDeleteFramebuffers(1, &fbo);
3671
3672 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3673 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3674
3675 glUseProgram(program);
3676 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
3677 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
3678
3679 glClear(GL_COLOR_BUFFER_BIT);
3680 glBindVertexArray(m_vao);
3681 glViewport(0, 0, kSize, kSize);
3682 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3683
3684 bool status = true;
3685
3686 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3687 {
3688 status = false;
3689 }
3690
3691 glDeleteTextures(2, textures);
3692 glUseProgram(0);
3693 glDeleteProgram(program);
3694
3695 return status;
3696 }
3697
3698 template <typename T>
GenFS(GLenum internalformat)3699 std::string GenFS(GLenum internalformat)
3700 {
3701 std::ostringstream os;
3702 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3703 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3704 << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3705 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3706 << ") coherent uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3707 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3708 << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3709 << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
3710 << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
3711 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3712 << "image2DArray g_image_2darray;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3713 " ivec2 coord = ivec2(gl_FragCoord.xy);"
3714
3715 NL " if (imageAtomicAdd(g_image_1d, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3716 " if (imageAtomicMin(g_image_1d, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3717 " if (imageAtomicMax(g_image_1d, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3718 " if (imageAtomicAnd(g_image_1d, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3719 " if (imageAtomicOr(g_image_1d, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3720 " if (imageAtomicXor(g_image_1d, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3721 " if (imageAtomicExchange(g_image_1d, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3722 " if (imageAtomicCompSwap(g_image_1d, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3723 " if (imageAtomicExchange(g_image_1d, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3724
3725 NL " if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3726 " if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3727 " if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3728 " if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3729 " if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3730 " if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3731 " if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3732 " if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3733 " if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3734
3735 NL " if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3736 " if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3737 " if (imageAtomicMax(g_image_3d, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3738 " if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3739 " if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3740 " if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3741 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3742 " if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
3743 "1.0);" NL
3744 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3745
3746 NL " if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3747 " if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3748 " if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3749 " if (imageAtomicAnd(g_image_2drect, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3750 " if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3751 " if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3752 " if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3753 " if (imageAtomicCompSwap(g_image_2drect, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3754 " if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3755
3756 NL " if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3757 " if (imageAtomicMin(g_image_buffer, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3758 " if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3759 " if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3760 " if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3761 " if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3762 " if (imageAtomicExchange(g_image_buffer, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3763 " if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3764 " if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3765
3766 NL
3767 " if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3768 " if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3769 " if (imageAtomicMax(g_image_1darray, ivec2(coord.x, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3770 " if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3771 " if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3772 " if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3773 " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
3774 "1.0);" NL " if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = "
3775 "vec4(1.0, 0.0, 0.0, 1.0);" NL " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), "
3776 "0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3777
3778 NL " if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3779 " if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3780 " if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3781 " if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3782 " if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3783 " if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3784 " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
3785 "1.0);" NL " if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, "
3786 "0.0, 0.0, 1.0);" NL " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) "
3787 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
3788 return os.str();
3789 }
3790
3791 template <typename T>
GenFSCube(GLenum internalformat)3792 std::string GenFSCube(GLenum internalformat)
3793 {
3794 std::ostringstream os;
3795 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3796 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3797 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3798 << TypePrefix<T>()
3799 << "imageCube g_image_cube_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3800 " ivec2 coord = ivec2(gl_FragCoord.xy);"
3801
3802 NL " if (imageAtomicAdd(g_image_cube, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3803 " if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3804 " if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3805 " if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3806 " if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3807 " if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3808 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3809 " if (imageAtomicCompSwap(g_image_cube, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
3810 "1.0);" NL
3811 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3812
3813 NL " if (imageAtomicAdd(g_image_cube_array, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, "
3814 "1.0);" NL " if (imageAtomicMin(g_image_cube_array, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, "
3815 "0.0, 1.0);" NL " if (imageAtomicMax(g_image_cube_array, ivec3(coord, 0), 4) != 2) o_color "
3816 "= vec4(1.0, 0.0, 0.0, 1.0);" NL " if (imageAtomicAnd(g_image_cube_array, "
3817 "ivec3(coord, 0), 0) != 4) o_color = "
3818 "vec4(1.0, 0.0, 0.0, 1.0);" NL
3819 " if (imageAtomicOr(g_image_cube_array, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3820 " if (imageAtomicXor(g_image_cube_array, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, "
3821 "1.0);" NL " if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, "
3822 "0.0, 0.0, 1.0);" NL " if (imageAtomicCompSwap(g_image_cube_array, ivec3(coord, 0), 1, 6) != "
3823 "1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3824 " if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, "
3825 "1.0);" NL "}";
3826 return os.str();
3827 }
3828
3829 template <typename T>
GenFSMS(GLenum internalformat)3830 std::string GenFSMS(GLenum internalformat)
3831 {
3832 std::ostringstream os;
3833 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3834 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3835 << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3836 << TypePrefix<T>()
3837 << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3838 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
3839 " if (imageAtomicAdd(g_image_2dms, coord, 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3840 " if (imageAtomicMin(g_image_2dms, coord, 1, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3841 " if (imageAtomicMax(g_image_2dms, coord, 1, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3842 " if (imageAtomicAnd(g_image_2dms, coord, 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3843 " if (imageAtomicOr(g_image_2dms, coord, 1, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3844 " if (imageAtomicXor(g_image_2dms, coord, 1, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3845 " if (imageAtomicExchange(g_image_2dms, coord, 1, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3846 " if (imageAtomicCompSwap(g_image_2dms, coord, 1, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3847 " if (imageAtomicExchange(g_image_2dms, coord, 1, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL NL
3848 " if (imageAtomicAdd(g_image_2dms_array, ivec3(coord, 1), 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, "
3849 "1.0);" NL " if (imageAtomicMin(g_image_2dms_array, ivec3(coord, 1), 1, 3) != 2) o_color = vec4(1.0, "
3850 "0.0, 0.0, 1.0);" NL " if (imageAtomicMax(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 2) "
3851 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3852 " if (imageAtomicAnd(g_image_2dms_array, ivec3(coord, 1), 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, "
3853 "1.0);" NL " if (imageAtomicOr(g_image_2dms_array, ivec3(coord, 1), 1, 7) != 0) o_color = vec4(1.0, "
3854 "0.0, 0.0, 1.0);" NL " if (imageAtomicXor(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 7) "
3855 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3856 " if (imageAtomicExchange(g_image_2dms_array, ivec3(coord, 1), 1, 1) != 3) o_color = vec4(1.0, 0.0, "
3857 "0.0, 1.0);" NL " if (imageAtomicCompSwap(g_image_2dms_array, ivec3(coord, 1), 1, 1, 6) != 1) o_color = "
3858 "vec4(1.0, 0.0, 0.0, 1.0);" NL " if (imageAtomicExchange(g_image_2dms_array, "
3859 "ivec3(coord, 1), 1, 0) != 6) o_color = vec4(1.0, 0.0, "
3860 "0.0, 1.0);" NL "}";
3861 return os.str();
3862 }
3863 };
3864 //-----------------------------------------------------------------------------
3865 // LoadStoreMachine
3866 //-----------------------------------------------------------------------------
3867 class LoadStoreMachine : public ShaderImageLoadStoreBase
3868 {
3869 GLuint m_vao;
3870 int m_stage;
3871
Setup()3872 virtual long Setup()
3873 {
3874 glGenVertexArrays(1, &m_vao);
3875 return NO_ERROR;
3876 }
3877
Cleanup()3878 virtual long Cleanup()
3879 {
3880 glDisable(GL_RASTERIZER_DISCARD);
3881 glDeleteVertexArrays(1, &m_vao);
3882 return NO_ERROR;
3883 }
3884
3885 template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)3886 bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
3887 {
3888 const GLenum targets[] = { GL_TEXTURE_1D, GL_TEXTURE_2D,
3889 GL_TEXTURE_3D, GL_TEXTURE_RECTANGLE,
3890 GL_TEXTURE_CUBE_MAP, GL_TEXTURE_1D_ARRAY,
3891 GL_TEXTURE_2D_ARRAY, GL_TEXTURE_CUBE_MAP_ARRAY };
3892 const int kTargets = sizeof(targets) / sizeof(targets[0]);
3893 GLuint program_store = 0;
3894 GLuint program_load = 0;
3895 if (m_stage == 0)
3896 { // VS
3897 program_store =
3898 BuildProgram(GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL, NULL, NULL);
3899 program_load =
3900 BuildProgram(GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL, NULL, NULL);
3901 }
3902 else if (m_stage == 1)
3903 { // TCS
3904 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
3905 const char* const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
3906 program_store = BuildProgram(glsl_vs, GenStoreShader(m_stage, internalformat, write_value).c_str(),
3907 glsl_tes, NULL, NULL);
3908 program_load = BuildProgram(glsl_vs, GenLoadShader(m_stage, internalformat, expected_value).c_str(),
3909 glsl_tes, NULL, NULL);
3910 }
3911 else if (m_stage == 2)
3912 { // TES
3913 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
3914 program_store =
3915 BuildProgram(glsl_vs, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL);
3916 program_load =
3917 BuildProgram(glsl_vs, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL);
3918 }
3919 else if (m_stage == 3)
3920 { // GS
3921 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
3922 program_store =
3923 BuildProgram(glsl_vs, NULL, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL);
3924 program_load =
3925 BuildProgram(glsl_vs, NULL, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL);
3926 }
3927 else if (m_stage == 4)
3928 { // CS
3929 {
3930 std::string source = GenStoreShader(m_stage, internalformat, write_value);
3931 const char* const src = source.c_str();
3932 GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
3933 glShaderSource(sh, 1, &src, NULL);
3934 glCompileShader(sh);
3935 program_store = glCreateProgram();
3936 glAttachShader(program_store, sh);
3937 glLinkProgram(program_store);
3938 glDeleteShader(sh);
3939 }
3940 {
3941 std::string source = GenLoadShader(m_stage, internalformat, expected_value);
3942 const char* const src = source.c_str();
3943 GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
3944 glShaderSource(sh, 1, &src, NULL);
3945 glCompileShader(sh);
3946 program_load = glCreateProgram();
3947 glAttachShader(program_load, sh);
3948 glLinkProgram(program_load);
3949 glDeleteShader(sh);
3950 }
3951 }
3952 GLuint textures[kTargets], texture_result;
3953 glGenTextures(kTargets, textures);
3954 glGenTextures(1, &texture_result);
3955
3956 glBindTexture(GL_TEXTURE_2D, texture_result);
3957 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3958 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3959 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3960
3961 for (int i = 0; i < kTargets; ++i)
3962 {
3963 glBindTexture(targets[i], textures[i]);
3964 glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3965 glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3966
3967 if (targets[i] == GL_TEXTURE_1D)
3968 {
3969 glTexStorage1D(targets[i], 1, internalformat, 1);
3970 }
3971 else if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE)
3972 {
3973 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
3974 }
3975 else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
3976 {
3977 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2);
3978 }
3979 else if (targets[i] == GL_TEXTURE_CUBE_MAP)
3980 {
3981 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
3982 }
3983 else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY)
3984 {
3985 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 12);
3986 }
3987 else if (targets[i] == GL_TEXTURE_1D_ARRAY)
3988 {
3989 glTexStorage2D(targets[i], 1, internalformat, 1, 2);
3990 }
3991 }
3992 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3993 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3994 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3995 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3996 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3997 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3998 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3999 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
4000
4001 glUseProgram(program_store);
4002 glUniform1i(glGetUniformLocation(program_store, "g_image_1d"), 0);
4003 glUniform1i(glGetUniformLocation(program_store, "g_image_2d"), 1);
4004 glUniform1i(glGetUniformLocation(program_store, "g_image_3d"), 2);
4005 glUniform1i(glGetUniformLocation(program_store, "g_image_2drect"), 3);
4006 glUniform1i(glGetUniformLocation(program_store, "g_image_cube"), 4);
4007 glUniform1i(glGetUniformLocation(program_store, "g_image_1darray"), 5);
4008 glUniform1i(glGetUniformLocation(program_store, "g_image_2darray"), 6);
4009 glUniform1i(glGetUniformLocation(program_store, "g_image_cube_array"), 7);
4010
4011 glBindVertexArray(m_vao);
4012 if (m_stage == 1 || m_stage == 2)
4013 { // TCS or TES
4014 glPatchParameteri(GL_PATCH_VERTICES, 1);
4015 glDrawArrays(GL_PATCHES, 0, 1);
4016 glPatchParameteri(GL_PATCH_VERTICES, 3);
4017 }
4018 else if (m_stage == 4)
4019 { // CS
4020 glDispatchCompute(1, 1, 1);
4021 }
4022 else
4023 {
4024 glDrawArrays(GL_POINTS, 0, 1);
4025 }
4026
4027 bool status = true;
4028 for (int i = 0; i < kTargets; ++i)
4029 {
4030 glBindTexture(targets[i], textures[i]);
4031 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4032
4033 if (targets[i] == GL_TEXTURE_CUBE_MAP)
4034 {
4035 for (int face = 0; face < 6; ++face)
4036 {
4037 T data;
4038 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]);
4039 if (!Equal(data, expected_value, internalformat))
4040 {
4041 status = false;
4042 m_context.getTestContext().getLog()
4043 << tcu::TestLog::Message << "Value is: " << ToString(data)
4044 << ". Value should be: " << ToString(expected_value)
4045 << ". Format is: " << FormatEnumToString(internalformat)
4046 << ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage)
4047 << tcu::TestLog::EndMessage;
4048 }
4049 }
4050 }
4051 else
4052 {
4053 T data[12];
4054
4055 for (deUint32 ndx = 0; ndx < DE_LENGTH_OF_ARRAY(data); ndx++)
4056 data[ndx] = T(0);
4057
4058 glGetTexImage(targets[i], 0, Format<T>(), Type<T>(), &data[0]);
4059
4060 int count = 1;
4061 if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
4062 count = 2;
4063 else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY)
4064 count = 12;
4065 else if (targets[i] == GL_TEXTURE_1D_ARRAY)
4066 count = 2;
4067
4068 for (int j = 0; j < count; ++j)
4069 {
4070 if (!Equal(data[j], expected_value, internalformat))
4071 {
4072 status = false;
4073 m_context.getTestContext().getLog()
4074 << tcu::TestLog::Message << "Value is: " << ToString(data[j])
4075 << ". Value should be: " << ToString(expected_value)
4076 << ". Format is: " << FormatEnumToString(internalformat)
4077 << ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage)
4078 << tcu::TestLog::EndMessage;
4079 }
4080 }
4081 }
4082 }
4083 glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4084 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
4085 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4086 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
4087 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4088 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4089 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4090 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4091
4092 glUseProgram(program_load);
4093 glUniform1i(glGetUniformLocation(program_load, "g_image_result"), 0);
4094 glUniform1i(glGetUniformLocation(program_load, "g_image_2d"), 1);
4095 glUniform1i(glGetUniformLocation(program_load, "g_image_3d"), 2);
4096 glUniform1i(glGetUniformLocation(program_load, "g_image_2drect"), 3);
4097 glUniform1i(glGetUniformLocation(program_load, "g_image_cube"), 4);
4098 glUniform1i(glGetUniformLocation(program_load, "g_image_1darray"), 5);
4099 glUniform1i(glGetUniformLocation(program_load, "g_image_2darray"), 6);
4100 glUniform1i(glGetUniformLocation(program_load, "g_image_cube_array"), 7);
4101
4102 if (m_stage == 1 || m_stage == 2)
4103 { // TCS or TES
4104 glPatchParameteri(GL_PATCH_VERTICES, 1);
4105 glDrawArrays(GL_PATCHES, 0, 1);
4106 glPatchParameteri(GL_PATCH_VERTICES, 3);
4107 }
4108 else if (m_stage == 4)
4109 { // CS
4110 glDispatchCompute(1, 1, 1);
4111 }
4112 else
4113 {
4114 glDrawArrays(GL_POINTS, 0, 1);
4115 }
4116 {
4117 vec4 color;
4118 glBindTexture(GL_TEXTURE_2D, texture_result);
4119 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4120 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]);
4121 if (!tcu::allEqual(color, vec4(0, 1, 0, 1)))
4122 {
4123 status = false;
4124 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color)
4125 << ". Format is: " << FormatEnumToString(internalformat)
4126 << ". Stage is: " << StageName(m_stage) << tcu::TestLog::EndMessage;
4127 }
4128 }
4129 glUseProgram(0);
4130 glDeleteProgram(program_store);
4131 glDeleteProgram(program_load);
4132 glDeleteTextures(kTargets, textures);
4133 glDeleteTextures(1, &texture_result);
4134 return status;
4135 }
4136
4137 template <typename T>
GenStoreShader(int stage,GLenum internalformat,const T & write_value)4138 std::string GenStoreShader(int stage, GLenum internalformat, const T& write_value)
4139 {
4140 std::ostringstream os;
4141 os << "#version 420 core";
4142 if (stage == 4)
4143 { // CS
4144 os << NL "#extension GL_ARB_compute_shader : require";
4145 }
4146 os << NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4147 << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
4148 << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
4149 << ") writeonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
4150 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4151 << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
4152 << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat)
4153 << ") writeonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
4154 << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4155 << "image2DArray g_image_2darray;" NL "layout(" << FormatEnumToString(internalformat)
4156 << ") writeonly uniform " << TypePrefix<T>() << "imageCubeArray g_image_cube_array;" NL "uniform "
4157 << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << write_value
4158 << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);";
4159 if (stage == 0)
4160 { // VS
4161 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
4162 }
4163 else if (stage == 1)
4164 { // TCS
4165 os << NL "layout(vertices = 1) out;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL
4166 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL
4167 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL
4168 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4169 }
4170 else if (stage == 2)
4171 { // TES
4172 os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4173 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4174 }
4175 else if (stage == 3)
4176 { // GS
4177 os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4178 " ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);";
4179 }
4180 else if (stage == 4)
4181 { // CS
4182 os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4183 " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
4184 }
4185 os << NL " imageStore(g_image_1d, coord.x, g_value);" NL " imageStore(g_image_2d, coord, g_value);" NL
4186 " imageStore(g_image_3d, ivec3(coord.xy, g_index[0]), g_value);" NL
4187 " imageStore(g_image_3d, ivec3(coord.xy, g_index[1]), g_value);" NL
4188 " imageStore(g_image_2drect, coord, g_value);" NL " for (int i = 0; i < 6; ++i) {" NL
4189 " imageStore(g_image_cube, ivec3(coord, g_index[i]), g_value);" NL " }" NL
4190 " imageStore(g_image_1darray, ivec2(coord.x, g_index[0]), g_value);" NL
4191 " imageStore(g_image_1darray, ivec2(coord.x, g_index[1]), g_value);" NL
4192 " imageStore(g_image_2darray, ivec3(coord, g_index[0]), g_value);" NL
4193 " imageStore(g_image_2darray, ivec3(coord, g_index[1]), g_value);" NL
4194 " for (int i = 0; i < 6; ++i) {" NL
4195 " imageStore(g_image_cube_array, ivec3(coord, g_index[i]), g_value);" NL " }" NL
4196 " for (int i = 0; i < 6; ++i) {" NL
4197 " imageStore(g_image_cube_array, ivec3(coord, g_index[i] + 6), g_value);" NL " }" NL "}";
4198 return os.str();
4199 }
4200
4201 template <typename T>
GenLoadShader(int stage,GLenum internalformat,const T & expected_value)4202 std::string GenLoadShader(int stage, GLenum internalformat, const T& expected_value)
4203 {
4204 std::ostringstream os;
4205 os << "#version 420 core";
4206 if (stage == 4)
4207 { // CS
4208 os << NL "#extension GL_ARB_compute_shader : require";
4209 }
4210 os << NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4211 << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
4212 << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
4213 << ") readonly uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout("
4214 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4215 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
4216 << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat)
4217 << ") readonly uniform " << TypePrefix<T>() << "image2DArray g_image_2darray;" NL "layout("
4218 << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4219 << "imageCubeArray g_image_cube_array;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL
4220 "uniform "
4221 << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << expected_value
4222 << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);";
4223 if (stage == 0)
4224 { // VS
4225 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
4226 }
4227 else if (stage == 1)
4228 { // TCS
4229 os << NL "layout(vertices = 1) out;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL
4230 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL
4231 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL
4232 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4233 }
4234 else if (stage == 2)
4235 { // TES
4236 os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4237 " ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4238 }
4239 else if (stage == 3)
4240 { // GS
4241 os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4242 " ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);";
4243 }
4244 else if (stage == 4)
4245 { // CS
4246 os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4247 " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
4248 }
4249 os << NL " vec4 r = vec4(0, 1, 0, 1);" NL " " << TypePrefix<T>()
4250 << "vec4 v;" NL " v = imageLoad(g_image_2d, coord);" NL
4251 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4252 " v = imageLoad(g_image_3d, ivec3(coord, g_index[0]));" NL
4253 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL " v = imageLoad(g_image_2drect, coord);" NL
4254 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4255 " v = imageLoad(g_image_cube, ivec3(coord, g_index[0]));" NL
4256 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL " v = imageLoad(g_image_1darray, coord);" NL
4257 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4258 " v = imageLoad(g_image_2darray, ivec3(coord, g_index[0]));" NL
4259 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4260 " v = imageLoad(g_image_cube_array, ivec3(coord, g_index[0]));" NL
4261 " if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL " imageStore(g_image_result, coord, r);" NL "}";
4262 return os.str();
4263 }
4264
4265 protected:
RunStage(int stage)4266 long RunStage(int stage)
4267 {
4268 if (!SupportedInStage(stage, 8))
4269 return NOT_SUPPORTED;
4270
4271 glEnable(GL_RASTERIZER_DISCARD);
4272 m_stage = stage;
4273
4274 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
4275 return ERROR;
4276 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
4277 return ERROR;
4278 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4279 return ERROR;
4280
4281 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
4282 return ERROR;
4283 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
4284 return ERROR;
4285 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4286 return ERROR;
4287
4288 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4289 return ERROR;
4290 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4291 return ERROR;
4292 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4293 return ERROR;
4294
4295 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
4296 return ERROR;
4297
4298 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4299 return ERROR;
4300 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4301 return ERROR;
4302 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4303 return ERROR;
4304
4305 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4306 return ERROR;
4307 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4308 return ERROR;
4309 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4310 return ERROR;
4311
4312 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4313 return ERROR;
4314 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4315 return ERROR;
4316 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4317 return ERROR;
4318 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4319 return ERROR;
4320
4321 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4322 return ERROR;
4323 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4324 return ERROR;
4325 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4326 return ERROR;
4327
4328 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4329 return ERROR;
4330 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4331 return ERROR;
4332 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4333 return ERROR;
4334
4335 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
4336 return ERROR;
4337 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
4338 return ERROR;
4339 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
4340 return ERROR;
4341 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4342 return ERROR;
4343
4344 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
4345 return ERROR;
4346 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
4347 return ERROR;
4348 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4349 return ERROR;
4350
4351 //
4352 {
4353 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
4354 return ERROR;
4355 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
4356 return ERROR;
4357 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
4358 return ERROR;
4359
4360 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
4361 return ERROR;
4362 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
4363 return ERROR;
4364 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
4365 return ERROR;
4366 }
4367 return NO_ERROR;
4368 }
4369 };
4370 //-----------------------------------------------------------------------------
4371 // AtomicMachine
4372 //-----------------------------------------------------------------------------
4373 class AtomicMachine : public ShaderImageLoadStoreBase
4374 {
4375 GLuint m_vao;
4376
Setup()4377 virtual long Setup()
4378 {
4379 glEnable(GL_RASTERIZER_DISCARD);
4380 glGenVertexArrays(1, &m_vao);
4381 return NO_ERROR;
4382 }
4383
Cleanup()4384 virtual long Cleanup()
4385 {
4386 glDisable(GL_RASTERIZER_DISCARD);
4387 glDeleteVertexArrays(1, &m_vao);
4388 return NO_ERROR;
4389 }
4390
4391 template <typename T>
Atomic(int stage,GLenum internalformat)4392 bool Atomic(int stage, GLenum internalformat)
4393 {
4394 GLuint program = 0;
4395 if (stage == 0)
4396 { // VS
4397 program = BuildProgram(GenShader<T>(stage, internalformat).c_str(), NULL, NULL, NULL, NULL);
4398 }
4399 else if (stage == 1)
4400 { // TCS
4401 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
4402 const char* const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
4403 program = BuildProgram(glsl_vs, GenShader<T>(stage, internalformat).c_str(), glsl_tes, NULL, NULL);
4404 }
4405 else if (stage == 2)
4406 { // TES
4407 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
4408 program = BuildProgram(glsl_vs, NULL, GenShader<T>(stage, internalformat).c_str(), NULL, NULL);
4409 }
4410 else if (stage == 3)
4411 { // GS
4412 const char* const glsl_vs = "#version 420 core" NL "void main() {}";
4413 program = BuildProgram(glsl_vs, NULL, NULL, GenShader<T>(stage, internalformat).c_str(), NULL);
4414 }
4415 else if (stage == 4)
4416 { // CS
4417 std::string source = GenShader<T>(stage, internalformat);
4418 const char* const src = source.c_str();
4419 GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
4420 glShaderSource(sh, 1, &src, NULL);
4421 glCompileShader(sh);
4422 program = glCreateProgram();
4423 glAttachShader(program, sh);
4424 glLinkProgram(program);
4425 glDeleteShader(sh);
4426 }
4427 GLuint texture_result;
4428 glGenTextures(1, &texture_result);
4429 glBindTexture(GL_TEXTURE_2D, texture_result);
4430 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4431 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4432 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
4433
4434 const GLenum targets[] = { GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP,
4435 GL_TEXTURE_BUFFER, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY };
4436 const int kTargets = sizeof(targets) / sizeof(targets[0]);
4437
4438 GLuint textures[kTargets];
4439 GLuint buffer;
4440 glGenTextures(kTargets, textures);
4441 glGenBuffers(1, &buffer);
4442
4443 for (int i = 0; i < kTargets; ++i)
4444 {
4445 glBindTexture(targets[i], textures[i]);
4446 if (targets[i] != GL_TEXTURE_BUFFER)
4447 {
4448 glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4449 glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4450 }
4451 if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE)
4452 {
4453 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
4454 }
4455 else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
4456 {
4457 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2);
4458 }
4459 else if (targets[i] == GL_TEXTURE_CUBE_MAP)
4460 {
4461 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
4462 }
4463 else if (targets[i] == GL_TEXTURE_BUFFER)
4464 {
4465 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
4466 glBufferData(GL_TEXTURE_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
4467 glBindBuffer(GL_TEXTURE_BUFFER, 0);
4468 glTexBuffer(targets[i], internalformat, buffer);
4469 }
4470 else if (targets[i] == GL_TEXTURE_1D_ARRAY)
4471 {
4472 glTexStorage2D(targets[i], 1, internalformat, 1, 2);
4473 }
4474 }
4475 glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4476 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4477 glBindImageTexture(2, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4478 glBindImageTexture(3, textures[2], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4479 glBindImageTexture(4, textures[3], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4480 glBindImageTexture(5, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4481 glBindImageTexture(6, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4482 glBindImageTexture(7, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4483
4484 glUseProgram(program);
4485 glUniform1i(glGetUniformLocation(program, "g_image_result"), 0);
4486 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
4487 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
4488 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
4489 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4);
4490 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5);
4491 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6);
4492 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7);
4493
4494 glBindVertexArray(m_vao);
4495 if (stage == 1 || stage == 2)
4496 { // TCS or TES
4497 glPatchParameteri(GL_PATCH_VERTICES, 1);
4498 glDrawArrays(GL_PATCHES, 0, 1);
4499 glPatchParameteri(GL_PATCH_VERTICES, 3);
4500 }
4501 else if (stage == 4)
4502 { // CS
4503 glDispatchCompute(1, 1, 1);
4504 }
4505 else
4506 {
4507 glDrawArrays(GL_POINTS, 0, 1);
4508 }
4509
4510 bool status = true;
4511 {
4512 vec4 color;
4513 glBindTexture(GL_TEXTURE_2D, texture_result);
4514 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4515 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]);
4516 if (!tcu::allEqual(color, vec4(0, 1, 0, 1)))
4517 {
4518 status = false;
4519 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color)
4520 << ". Format is: " << FormatEnumToString(internalformat)
4521 << ". Stage is: " << StageName(stage) << tcu::TestLog::EndMessage;
4522 }
4523 }
4524 glUseProgram(0);
4525 glDeleteProgram(program);
4526 glDeleteTextures(7, textures);
4527 glDeleteTextures(1, &texture_result);
4528 glDeleteBuffers(1, &buffer);
4529 return status;
4530 }
4531
4532 template <typename T>
GenShader(int stage,GLenum internalformat)4533 std::string GenShader(int stage, GLenum internalformat)
4534 {
4535 std::ostringstream os;
4536 os << "#version 420 core";
4537 if (stage == 4)
4538 { // CS
4539 os << NL "#extension GL_ARB_compute_shader : require";
4540 }
4541 os << NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4542 << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
4543 << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
4544 << ") coherent uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout("
4545 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4546 << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
4547 << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
4548 << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
4549 << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4550 << "image2DArray g_image_2darray;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL
4551 "uniform int g_value[6] = int[](0, 1, 2, 3, 4, 5);";
4552 if (stage == 0)
4553 { // VS
4554 os << NL "void main() {" NL " ivec2 coord = ivec2(gl_VertexID, g_value[0]);";
4555 }
4556 else if (stage == 1)
4557 { // TCS
4558 os << NL "layout(vertices = 1) out;" NL "void main() {" NL " gl_TessLevelInner[0] = 1;" NL
4559 " gl_TessLevelInner[1] = 1;" NL " gl_TessLevelOuter[0] = 1;" NL " gl_TessLevelOuter[1] = 1;" NL
4560 " gl_TessLevelOuter[2] = 1;" NL " gl_TessLevelOuter[3] = 1;" NL
4561 " ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);";
4562 }
4563 else if (stage == 2)
4564 { // TES
4565 os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4566 " ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);";
4567 }
4568 else if (stage == 3)
4569 { // GS
4570 os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4571 " ivec2 coord = ivec2(gl_PrimitiveIDIn, g_value[0]);";
4572 }
4573 else if (stage == 4)
4574 { // CS
4575 os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4576 " ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_value[0]);";
4577 }
4578 os << NL
4579 " vec4 o_color = vec4(0, 1, 0, 1);" NL " imageAtomicExchange(g_image_2d, coord, 0);" NL
4580 " if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4581 " if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4582 " if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4583 " if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4584 " if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4585 " if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4586 " if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4587 " if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4588 " if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4589
4590 NL " imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0);" NL
4591 " if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4592 " if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4593 " if (imageAtomicMax(g_image_3d, ivec3(coord, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4594 " if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4595 " if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4596 " if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4597 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4598 " if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4599 " if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4600
4601 NL " imageAtomicExchange(g_image_2drect, coord, 0);" NL
4602 " if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4603 " if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4604 " if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4605 " if (imageAtomicAnd(g_image_2drect, coord, 0) != g_value[4]) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4606 " if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4607 " if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4608 " if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4609 " if (imageAtomicCompSwap(g_image_2drect, coord, g_value[1], 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
4610 "1.0);" NL " if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4611
4612 NL " imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0);" NL " if (imageAtomicAdd(g_image_cube, "
4613 "ivec3(coord, 0), g_value[2]) != 0) "
4614 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4615 " if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4616 " if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4617 " if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4618 " if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4619 " if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4620 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4621 " if (imageAtomicCompSwap(g_image_cube, ivec3(coord, g_value[0]), 1, 6) != 1) o_color = vec4(1.0, 0.0, "
4622 "0.0, 1.0);" NL
4623 " if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4624
4625 NL " imageAtomicExchange(g_image_buffer, coord.x, g_value[0]);" NL
4626 " if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4627 " if (imageAtomicMin(g_image_buffer, coord.x, g_value[3]) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4628 " if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4629 " if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4630 " if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4631 " if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4632 " if (imageAtomicExchange(g_image_buffer, coord.x, g_value[1]) != 3) o_color = vec4(1.0, 0.0, 0.0, "
4633 "1.0);" NL
4634 " if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4635 " if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4636
4637 NL " imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0);" NL
4638 " if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4639 " if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4640 " if (imageAtomicMax(g_image_1darray, ivec2(coord.x, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, "
4641 "1.0);" NL
4642 " if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4643 " if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4644 " if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4645 " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
4646 "1.0);" NL " if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = vec4(1.0, "
4647 "0.0, 0.0, 1.0);" NL
4648 " if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4649
4650 NL " imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0);" NL
4651 " if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4652 " if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4653 " if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4654 " if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4655 " if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4656 " if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), g_value[4]) != 7) o_color = vec4(1.0, 0.0, 0.0, "
4657 "1.0);" NL " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, "
4658 "0.0, 1.0);" NL " if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) "
4659 "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4660 " if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4661
4662 NL " imageStore(g_image_result, coord, o_color);" NL "}";
4663 return os.str();
4664 }
4665
4666 protected:
RunStage(int stage)4667 long RunStage(int stage)
4668 {
4669 if (!SupportedInStage(stage, 8))
4670 return NOT_SUPPORTED;
4671 if (!Atomic<GLint>(stage, GL_R32I))
4672 return ERROR;
4673 if (!Atomic<GLuint>(stage, GL_R32UI))
4674 return ERROR;
4675 return NO_ERROR;
4676 }
4677 };
4678 //-----------------------------------------------------------------------------
4679 // 1.3.4 BasicAllTargetsLoadStoreVS
4680 //-----------------------------------------------------------------------------
4681 class BasicAllTargetsLoadStoreVS : public LoadStoreMachine
4682 {
Run()4683 virtual long Run()
4684 {
4685 return RunStage(0);
4686 }
4687 };
4688 //-----------------------------------------------------------------------------
4689 // 1.3.5 BasicAllTargetsLoadStoreTCS
4690 //-----------------------------------------------------------------------------
4691 class BasicAllTargetsLoadStoreTCS : public LoadStoreMachine
4692 {
Run()4693 virtual long Run()
4694 {
4695 return RunStage(1);
4696 }
4697 };
4698 //-----------------------------------------------------------------------------
4699 // 1.3.6 BasicAllTargetsLoadStoreTES
4700 //-----------------------------------------------------------------------------
4701 class BasicAllTargetsLoadStoreTES : public LoadStoreMachine
4702 {
Run()4703 virtual long Run()
4704 {
4705 return RunStage(2);
4706 }
4707 };
4708 //-----------------------------------------------------------------------------
4709 // 1.3.7 BasicAllTargetsLoadStoreGS
4710 //-----------------------------------------------------------------------------
4711 class BasicAllTargetsLoadStoreGS : public LoadStoreMachine
4712 {
Run()4713 virtual long Run()
4714 {
4715 return RunStage(3);
4716 }
4717 };
4718 //-----------------------------------------------------------------------------
4719 // 1.3.8 BasicAllTargetsLoadStoreCS
4720 //-----------------------------------------------------------------------------
4721 class BasicAllTargetsLoadStoreCS : public LoadStoreMachine
4722 {
Run()4723 virtual long Run()
4724 {
4725 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
4726 {
4727 m_context.getTestContext().getLog()
4728 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
4729 << tcu::TestLog::EndMessage;
4730 return NO_ERROR;
4731 }
4732
4733 return RunStage(4);
4734 }
4735 };
4736 //-----------------------------------------------------------------------------
4737 // 1.3.9 BasicAllTargetsAtomicVS
4738 //-----------------------------------------------------------------------------
4739 class BasicAllTargetsAtomicVS : public AtomicMachine
4740 {
Run()4741 virtual long Run()
4742 {
4743 return RunStage(0);
4744 }
4745 };
4746 //-----------------------------------------------------------------------------
4747 // 1.3.10 BasicAllTargetsAtomicTCS
4748 //-----------------------------------------------------------------------------
4749 class BasicAllTargetsAtomicTCS : public AtomicMachine
4750 {
Run()4751 virtual long Run()
4752 {
4753 return RunStage(1);
4754 }
4755 };
4756 //-----------------------------------------------------------------------------
4757 // 1.3.11 BasicAllTargetsAtomicTES
4758 //-----------------------------------------------------------------------------
4759 class BasicAllTargetsAtomicTES : public AtomicMachine
4760 {
Run()4761 virtual long Run()
4762 {
4763 return RunStage(2);
4764 }
4765 };
4766 //-----------------------------------------------------------------------------
4767 // 1.3.12 BasicAllTargetsAtomicGS
4768 //-----------------------------------------------------------------------------
4769 class BasicAllTargetsAtomicGS : public AtomicMachine
4770 {
Run()4771 virtual long Run()
4772 {
4773 return RunStage(3);
4774 }
4775 };
4776 //-----------------------------------------------------------------------------
4777 // 1.3.13 BasicAllTargetsAtomicCS
4778 //-----------------------------------------------------------------------------
4779 class BasicAllTargetsAtomicCS : public AtomicMachine
4780 {
Run()4781 virtual long Run()
4782 {
4783 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
4784 {
4785 m_context.getTestContext().getLog()
4786 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
4787 << tcu::TestLog::EndMessage;
4788 return NO_ERROR;
4789 }
4790
4791 return RunStage(4);
4792 }
4793 };
4794 //-----------------------------------------------------------------------------
4795 // 1.4.1 BasicGLSLMisc
4796 //-----------------------------------------------------------------------------
4797 class BasicGLSLMisc : public ShaderImageLoadStoreBase
4798 {
4799 GLuint m_texture;
4800 GLuint m_program;
4801 GLuint m_vao, m_vbo;
4802
Setup()4803 virtual long Setup()
4804 {
4805 m_texture = 0;
4806 m_program = 0;
4807 m_vao = m_vbo = 0;
4808 return NO_ERROR;
4809 }
4810
Run()4811 virtual long Run()
4812 {
4813 const int kSize = 32;
4814 std::vector<vec4> data(kSize * kSize * 4, vec4(0.0f));
4815
4816 glGenTextures(1, &m_texture);
4817 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
4818 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4819 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, kSize, kSize, 4, 0, GL_RGBA, GL_FLOAT, &data[0]);
4820 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
4821
4822 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4823 " gl_Position = i_position;" NL "}";
4824 const char* src_fs =
4825 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
4826 "layout(rgba32f) coherent volatile restrict uniform image2D g_image_layer0;" NL
4827 "layout(rgba32f) volatile uniform image2D g_image_layer1;" NL
4828 "void main() {" NL " ivec2 coord = ivec2(gl_FragCoord.xy);" NL
4829 " imageStore(g_image_layer0, coord, vec4(1.0));" NL " memoryBarrier();" NL
4830 " imageStore(g_image_layer0, coord, vec4(2.0));" NL " memoryBarrier();" NL
4831 " imageStore(g_image_layer0, coord, vec4(0.0, 1.0, 0.0, 1.0));" NL " memoryBarrier();" NL
4832 " o_color = imageLoad(g_image_layer0, coord) + imageLoad(g_image_layer1, coord);" NL "}";
4833 m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs);
4834
4835 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4836
4837 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4838 glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_ONLY, GL_RGBA32F);
4839
4840 glClear(GL_COLOR_BUFFER_BIT);
4841 glViewport(0, 0, kSize, kSize);
4842
4843 glUseProgram(m_program);
4844 glUniform1i(glGetUniformLocation(m_program, "g_image_layer0"), 0);
4845 glUniform1i(glGetUniformLocation(m_program, "g_image_layer1"), 1);
4846
4847 glBindVertexArray(m_vao);
4848 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4849
4850 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
4851 {
4852 return ERROR;
4853 }
4854 return NO_ERROR;
4855 }
4856
Cleanup()4857 virtual long Cleanup()
4858 {
4859 glViewport(0, 0, getWindowWidth(), getWindowHeight());
4860 glDeleteTextures(1, &m_texture);
4861 glDeleteVertexArrays(1, &m_vao);
4862 glDeleteBuffers(1, &m_vbo);
4863 glUseProgram(0);
4864 glDeleteProgram(m_program);
4865 return NO_ERROR;
4866 }
4867 };
4868 //-----------------------------------------------------------------------------
4869 // 1.4.2 BasicGLSLEarlyFragTests
4870 //-----------------------------------------------------------------------------
4871 class BasicGLSLEarlyFragTests : public ShaderImageLoadStoreBase
4872 {
4873 GLuint m_texture[2];
4874 GLuint m_program[2];
4875 GLuint m_vao, m_vbo;
4876
Setup()4877 virtual long Setup()
4878 {
4879 m_texture[0] = m_texture[1] = 0;
4880 m_program[0] = m_program[1] = 0;
4881 m_vao = m_vbo = 0;
4882 return NO_ERROR;
4883 }
4884
Run()4885 virtual long Run()
4886 {
4887 int ds = m_context.getRenderContext().getRenderTarget().getDepthBits();
4888
4889 const int kSize = 32;
4890 std::vector<vec4> data(kSize * kSize);
4891
4892 glGenTextures(2, m_texture);
4893 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4894 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4895 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]);
4896 glBindTexture(GL_TEXTURE_2D, 0);
4897
4898 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4899 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4900 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]);
4901 glBindTexture(GL_TEXTURE_2D, 0);
4902
4903 const char* glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4904 " gl_Position = i_position;" NL "}";
4905 const char* glsl_early_frag_tests_fs =
4906 "#version 420 core" NL "layout(early_fragment_tests) in;" NL "layout(location = 0) out vec4 o_color;" NL
4907 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL
4908 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(1.0));" NL
4909 " o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
4910 const char* glsl_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
4911 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL
4912 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(1.0));" NL
4913 " o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
4914 m_program[0] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_early_frag_tests_fs);
4915 m_program[1] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
4916
4917 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4918
4919 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4920 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4921
4922 glViewport(0, 0, kSize, kSize);
4923 glBindVertexArray(m_vao);
4924
4925 glEnable(GL_DEPTH_TEST);
4926 glClearColor(0.0, 1.0f, 0.0, 1.0f);
4927 glClearDepthf(0.0f);
4928
4929 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4930 glUseProgram(m_program[0]);
4931 glUniform1i(glGetUniformLocation(m_program[0], "g_image"), 0);
4932
4933 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4934
4935 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4936 glUseProgram(m_program[1]);
4937 glUniform1i(glGetUniformLocation(m_program[1], "g_image"), 1);
4938 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4939
4940 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4941 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4942 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]);
4943 for (int i = 0; i < kSize * kSize; ++i)
4944 {
4945 if (IsEqual(data[i], vec4(1.0f)) && ds != 0)
4946 return ERROR;
4947 }
4948
4949 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4950 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4951 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]);
4952 for (int i = 0; i < kSize * kSize; ++i)
4953 {
4954 if (!IsEqual(data[i], vec4(1.0f)) && ds != 0)
4955 return ERROR;
4956 }
4957
4958 return NO_ERROR;
4959 }
4960
Cleanup()4961 virtual long Cleanup()
4962 {
4963 glDisable(GL_DEPTH_TEST);
4964 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
4965 glClearDepthf(1.0f);
4966 glViewport(0, 0, getWindowWidth(), getWindowHeight());
4967 glDeleteTextures(2, m_texture);
4968 glDeleteVertexArrays(1, &m_vao);
4969 glDeleteBuffers(1, &m_vbo);
4970 glUseProgram(0);
4971 glDeleteProgram(m_program[0]);
4972 glDeleteProgram(m_program[1]);
4973 return NO_ERROR;
4974 }
4975 };
4976 //-----------------------------------------------------------------------------
4977 // 1.4.3 BasicGLSLConst
4978 //-----------------------------------------------------------------------------
4979 class BasicGLSLConst : public ShaderImageLoadStoreBase
4980 {
4981 GLuint m_program;
4982 GLuint m_vao, m_vbo;
4983
Setup()4984 virtual long Setup()
4985 {
4986 m_program = 0;
4987 m_vao = m_vbo = 0;
4988 return NO_ERROR;
4989 }
4990
Run()4991 virtual long Run()
4992 {
4993 bool isAtLeast44Context =
4994 glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 4));
4995
4996 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4997 " gl_Position = i_position;" NL "}";
4998 std::ostringstream src_fs;
4999 src_fs << "#version " << (isAtLeast44Context ? "440" : "420") << " core";
5000 src_fs << NL "layout(location = 0) out vec4 o_color;" NL "uniform int MaxImageUnits;" NL
5001 "uniform int MaxCombinedShaderOutputResources;" NL "uniform int MaxImageSamples;" NL
5002 "uniform int MaxVertexImageUniforms;" NL "uniform int MaxTessControlImageUniforms;" NL
5003 "uniform int MaxTessEvaluationImageUniforms;" NL "uniform int MaxGeometryImageUniforms;" NL
5004 "uniform int MaxFragmentImageUniforms;" NL "uniform int MaxCombinedImageUniforms;" NL
5005 "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
5006 " if (gl_MaxImageUnits != MaxImageUnits) o_color = vec4(1.0, 0.0, 0.0, 0.1);";
5007 if (isAtLeast44Context)
5008 src_fs << NL " if (gl_MaxCombinedShaderOutputResources != MaxCombinedShaderOutputResources) o_color = "
5009 "vec4(0.2, 0.0, 0.0, 0.2);";
5010 else
5011 src_fs << NL " if (gl_MaxCombinedImageUnitsAndFragmentOutputs != MaxCombinedShaderOutputResources) "
5012 "o_color = vec4(0.2, 0.0, 0.0, 0.2);";
5013 src_fs << NL
5014 " if (gl_MaxImageSamples != MaxImageSamples) o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
5015 " if (gl_MaxVertexImageUniforms != MaxVertexImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL
5016 " if (gl_MaxTessControlImageUniforms != MaxTessControlImageUniforms) o_color = vec4(1.0, 0.0, 0.0, "
5017 "0.5);" NL " if (gl_MaxTessEvaluationImageUniforms != MaxTessEvaluationImageUniforms) o_color = vec4(1.0, "
5018 "0.0, 0.0, 0.6);" NL
5019 " if (gl_MaxGeometryImageUniforms != MaxGeometryImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL
5020 " if (gl_MaxFragmentImageUniforms != MaxFragmentImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL
5021 " if (gl_MaxCombinedImageUniforms != MaxCombinedImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.9);" NL "}";
5022
5023 m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs.str().c_str());
5024 glUseProgram(m_program);
5025
5026 GLint i;
5027 glGetIntegerv(GL_MAX_IMAGE_UNITS, &i);
5028 glUniform1i(glGetUniformLocation(m_program, "MaxImageUnits"), i);
5029
5030 glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &i);
5031 glUniform1i(glGetUniformLocation(m_program, "MaxCombinedShaderOutputResources"), i);
5032
5033 glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
5034 glUniform1i(glGetUniformLocation(m_program, "MaxImageSamples"), i);
5035
5036 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &i);
5037 glUniform1i(glGetUniformLocation(m_program, "MaxVertexImageUniforms"), i);
5038
5039 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &i);
5040 glUniform1i(glGetUniformLocation(m_program, "MaxTessControlImageUniforms"), i);
5041
5042 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &i);
5043 glUniform1i(glGetUniformLocation(m_program, "MaxTessEvaluationImageUniforms"), i);
5044
5045 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &i);
5046 glUniform1i(glGetUniformLocation(m_program, "MaxGeometryImageUniforms"), i);
5047
5048 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &i);
5049 glUniform1i(glGetUniformLocation(m_program, "MaxFragmentImageUniforms"), i);
5050
5051 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &i);
5052 glUniform1i(glGetUniformLocation(m_program, "MaxCombinedImageUniforms"), i);
5053
5054 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5055
5056 glClear(GL_COLOR_BUFFER_BIT);
5057 glBindVertexArray(m_vao);
5058 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5059
5060 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5061 {
5062 return ERROR;
5063 }
5064 return NO_ERROR;
5065 }
5066
Cleanup()5067 virtual long Cleanup()
5068 {
5069 glDeleteVertexArrays(1, &m_vao);
5070 glDeleteBuffers(1, &m_vbo);
5071 glUseProgram(0);
5072 glDeleteProgram(m_program);
5073 return NO_ERROR;
5074 }
5075 };
5076 //-----------------------------------------------------------------------------
5077 // 2.1.1 AdvancedSyncImageAccess
5078 //-----------------------------------------------------------------------------
5079 class AdvancedSyncImageAccess : public ShaderImageLoadStoreBase
5080 {
5081 GLuint m_buffer;
5082 GLuint m_buffer_tex;
5083 GLuint m_store_program;
5084 GLuint m_draw_program;
5085 GLuint m_attribless_vao;
5086
Setup()5087 virtual long Setup()
5088 {
5089 m_buffer = 0;
5090 m_buffer_tex = 0;
5091 m_store_program = 0;
5092 m_draw_program = 0;
5093 m_attribless_vao = 0;
5094 return NO_ERROR;
5095 }
5096
Run()5097 virtual long Run()
5098 {
5099 if (!SupportedInVS(1))
5100 return NOT_SUPPORTED;
5101 const char* const glsl_store_vs =
5102 "#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL
5103 " vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
5104 " imageStore(g_output_data, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL "}";
5105 const char* const glsl_draw_vs =
5106 "#version 420 core" NL "out vec4 vs_color;" NL "layout(rg32f) readonly uniform imageBuffer g_image;" NL
5107 "uniform samplerBuffer g_sampler;" NL "void main() {" NL " vec4 pi = imageLoad(g_image, gl_VertexID);" NL
5108 " vec4 ps = texelFetch(g_sampler, gl_VertexID);" NL
5109 " 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
5110 " gl_Position = pi;" NL "}";
5111 const char* const glsl_draw_fs =
5112 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
5113 " o_color = vs_color;" NL "}";
5114 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5115 m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5116
5117 glGenVertexArrays(1, &m_attribless_vao);
5118 glBindVertexArray(m_attribless_vao);
5119
5120 glGenBuffers(1, &m_buffer);
5121 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5122 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW);
5123 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5124
5125 glGenTextures(1, &m_buffer_tex);
5126 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5127 glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_buffer);
5128
5129 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG32F);
5130
5131 glEnable(GL_RASTERIZER_DISCARD);
5132 glUseProgram(m_store_program);
5133 glDrawArrays(GL_POINTS, 0, 4);
5134
5135 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT);
5136
5137 glDisable(GL_RASTERIZER_DISCARD);
5138 glClear(GL_COLOR_BUFFER_BIT);
5139 glUseProgram(m_draw_program);
5140 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5141
5142 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5143 {
5144 return ERROR;
5145 }
5146 return NO_ERROR;
5147 }
5148
Cleanup()5149 virtual long Cleanup()
5150 {
5151 glUseProgram(0);
5152 glDeleteBuffers(1, &m_buffer);
5153 glDeleteTextures(1, &m_buffer_tex);
5154 glDeleteProgram(m_store_program);
5155 glDeleteProgram(m_draw_program);
5156 glDeleteVertexArrays(1, &m_attribless_vao);
5157 return NO_ERROR;
5158 }
5159 };
5160 //-----------------------------------------------------------------------------
5161 // 2.1.2 AdvancedSyncVertexArray
5162 //-----------------------------------------------------------------------------
5163 class AdvancedSyncVertexArray : public ShaderImageLoadStoreBase
5164 {
5165 GLuint m_position_buffer;
5166 GLuint m_color_buffer;
5167 GLuint m_element_buffer;
5168 GLuint m_position_buffer_tex;
5169 GLuint m_color_buffer_tex;
5170 GLuint m_element_buffer_tex;
5171 GLuint m_store_program;
5172 GLuint m_draw_program;
5173 GLuint m_attribless_vao;
5174 GLuint m_draw_vao;
5175
Setup()5176 virtual long Setup()
5177 {
5178 m_position_buffer = 0;
5179 m_color_buffer = 0;
5180 m_element_buffer = 0;
5181 m_position_buffer_tex = 0;
5182 m_color_buffer_tex = 0;
5183 m_element_buffer_tex = 0;
5184 m_store_program = 0;
5185 m_draw_program = 0;
5186 m_attribless_vao = 0;
5187 m_draw_vao = 0;
5188 return NO_ERROR;
5189 }
5190
Run()5191 virtual long Run()
5192 {
5193 if (!SupportedInVS(3))
5194 return NOT_SUPPORTED;
5195 const char* const glsl_store_vs =
5196 "#version 420 core" NL "layout(rg32f) writeonly uniform imageBuffer g_position_buffer;" NL
5197 "layout(rgba32f) writeonly uniform imageBuffer g_color_buffer;" NL
5198 "layout(r32ui) writeonly uniform uimageBuffer g_element_buffer;" NL "uniform vec4 g_color;" NL
5199 "void main() {" NL " vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
5200 " imageStore(g_position_buffer, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL
5201 " imageStore(g_color_buffer, gl_VertexID, g_color);" NL
5202 " imageStore(g_element_buffer, gl_VertexID, uvec4(gl_VertexID));" NL "}";
5203 const char* const glsl_draw_vs =
5204 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5205 "layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL "void main() {" NL
5206 " gl_Position = i_position;" NL " vs_color = i_color;" NL "}";
5207 const char* const glsl_draw_fs =
5208 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
5209 " o_color = vs_color;" NL "}";
5210 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5211 glUseProgram(m_store_program);
5212 glUniform1i(glGetUniformLocation(m_store_program, "g_position_buffer"), 0);
5213 glUniform1i(glGetUniformLocation(m_store_program, "g_color_buffer"), 1);
5214 glUniform1i(glGetUniformLocation(m_store_program, "g_element_buffer"), 2);
5215 glUseProgram(0);
5216
5217 m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5218
5219 glGenBuffers(1, &m_position_buffer);
5220 glBindBuffer(GL_TEXTURE_BUFFER, m_position_buffer);
5221 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW);
5222 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5223
5224 glGenBuffers(1, &m_color_buffer);
5225 glBindBuffer(GL_TEXTURE_BUFFER, m_color_buffer);
5226 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_DYNAMIC_DRAW);
5227 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5228
5229 glGenBuffers(1, &m_element_buffer);
5230 glBindBuffer(GL_TEXTURE_BUFFER, m_element_buffer);
5231 glBufferData(GL_TEXTURE_BUFFER, sizeof(GLuint) * 4, NULL, GL_DYNAMIC_DRAW);
5232 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5233
5234 glGenTextures(1, &m_position_buffer_tex);
5235 glBindTexture(GL_TEXTURE_BUFFER, m_position_buffer_tex);
5236 glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_position_buffer);
5237 glBindTexture(GL_TEXTURE_BUFFER, 0);
5238
5239 glGenTextures(1, &m_color_buffer_tex);
5240 glBindTexture(GL_TEXTURE_BUFFER, m_color_buffer_tex);
5241 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_color_buffer);
5242 glBindTexture(GL_TEXTURE_BUFFER, 0);
5243
5244 glGenTextures(1, &m_element_buffer_tex);
5245 glBindTexture(GL_TEXTURE_BUFFER, m_element_buffer_tex);
5246 glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, m_element_buffer);
5247 glBindTexture(GL_TEXTURE_BUFFER, 0);
5248
5249 glGenVertexArrays(1, &m_attribless_vao);
5250
5251 glGenVertexArrays(1, &m_draw_vao);
5252 glBindVertexArray(m_draw_vao);
5253 glBindBuffer(GL_ARRAY_BUFFER, m_position_buffer);
5254 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
5255 glBindBuffer(GL_ARRAY_BUFFER, m_color_buffer);
5256 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
5257 glBindBuffer(GL_ARRAY_BUFFER, 0);
5258 glEnableVertexAttribArray(0);
5259 glEnableVertexAttribArray(1);
5260 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_element_buffer);
5261 glBindVertexArray(0);
5262
5263 glEnable(GL_RASTERIZER_DISCARD);
5264 glBindImageTexture(0, m_position_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RG32F);
5265 glBindImageTexture(1, m_color_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5266 glBindImageTexture(2, m_element_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
5267 glUseProgram(m_store_program);
5268 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
5269 glBindVertexArray(m_attribless_vao);
5270 glDrawArrays(GL_POINTS, 0, 4);
5271
5272 glDisable(GL_RASTERIZER_DISCARD);
5273 glClear(GL_COLOR_BUFFER_BIT);
5274 glUseProgram(m_draw_program);
5275 glBindVertexArray(m_draw_vao);
5276 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
5277 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
5278
5279 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5280 {
5281 return ERROR;
5282 }
5283
5284 glEnable(GL_RASTERIZER_DISCARD);
5285 glUseProgram(m_store_program);
5286 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 0.0f, 1.0f, 1.0f);
5287 glBindVertexArray(m_attribless_vao);
5288 glDrawArrays(GL_POINTS, 0, 4);
5289
5290 glDisable(GL_RASTERIZER_DISCARD);
5291 glClear(GL_COLOR_BUFFER_BIT);
5292 glUseProgram(m_draw_program);
5293 glBindVertexArray(m_draw_vao);
5294 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
5295 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
5296
5297 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 0, 1, 1)))
5298 {
5299 return ERROR;
5300 }
5301 return NO_ERROR;
5302 }
5303
Cleanup()5304 virtual long Cleanup()
5305 {
5306 glDisable(GL_RASTERIZER_DISCARD);
5307 glUseProgram(0);
5308 glDeleteBuffers(1, &m_position_buffer);
5309 glDeleteBuffers(1, &m_color_buffer);
5310 glDeleteBuffers(1, &m_element_buffer);
5311 glDeleteTextures(1, &m_position_buffer_tex);
5312 glDeleteTextures(1, &m_color_buffer_tex);
5313 glDeleteTextures(1, &m_element_buffer_tex);
5314 glDeleteProgram(m_store_program);
5315 glDeleteProgram(m_draw_program);
5316 glDeleteVertexArrays(1, &m_attribless_vao);
5317 glDeleteVertexArrays(1, &m_draw_vao);
5318 return NO_ERROR;
5319 }
5320 };
5321
5322 //-----------------------------------------------------------------------------
5323 // 2.1.4 AdvancedSyncDrawIndirect
5324 //-----------------------------------------------------------------------------
5325 class AdvancedSyncDrawIndirect : public ShaderImageLoadStoreBase
5326 {
5327 GLuint m_draw_command_buffer;
5328 GLuint m_draw_command_buffer_tex;
5329 GLuint m_store_program;
5330 GLuint m_draw_program;
5331 GLuint m_attribless_vao;
5332 GLuint m_draw_vao;
5333 GLuint m_draw_vbo;
5334
Setup()5335 virtual long Setup()
5336 {
5337 m_draw_command_buffer = 0;
5338 m_draw_command_buffer_tex = 0;
5339 m_store_program = 0;
5340 m_draw_program = 0;
5341 m_attribless_vao = 0;
5342 m_draw_vao = 0;
5343 m_draw_vbo = 0;
5344 return NO_ERROR;
5345 }
5346
Run()5347 virtual long Run()
5348 {
5349 if (!SupportedInVS(1))
5350 return NOT_SUPPORTED;
5351 const char* const glsl_store_vs =
5352 "#version 420 core" NL "writeonly uniform uimageBuffer g_draw_command_buffer;" NL "void main() {" NL
5353 " imageStore(g_draw_command_buffer, 0, uvec4(4, 1, 0, 0));" NL "}";
5354 const char* const glsl_draw_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5355 "void main() {" NL " gl_Position = i_position;" NL "}";
5356 const char* const glsl_draw_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
5357 "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
5358 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5359 m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5360
5361 glGenBuffers(1, &m_draw_command_buffer);
5362 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer);
5363 glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(uvec4), NULL, GL_DYNAMIC_DRAW);
5364 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
5365
5366 glGenTextures(1, &m_draw_command_buffer_tex);
5367 glBindTexture(GL_TEXTURE_BUFFER, m_draw_command_buffer_tex);
5368 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, m_draw_command_buffer);
5369 glBindTexture(GL_TEXTURE_BUFFER, 0);
5370
5371 glGenVertexArrays(1, &m_attribless_vao);
5372 CreateFullViewportQuad(&m_draw_vao, &m_draw_vbo, NULL);
5373
5374 glBindImageTexture(0, m_draw_command_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
5375
5376 glEnable(GL_RASTERIZER_DISCARD);
5377 glUseProgram(m_store_program);
5378 glBindVertexArray(m_attribless_vao);
5379 glDrawArrays(GL_POINTS, 0, 1);
5380
5381 glDisable(GL_RASTERIZER_DISCARD);
5382 glClear(GL_COLOR_BUFFER_BIT);
5383 glUseProgram(m_draw_program);
5384 glBindVertexArray(m_draw_vao);
5385 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer);
5386 glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
5387 glDrawArraysIndirect(GL_TRIANGLE_STRIP, 0);
5388
5389 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5390 {
5391 return ERROR;
5392 }
5393 return NO_ERROR;
5394 }
5395
Cleanup()5396 virtual long Cleanup()
5397 {
5398 glUseProgram(0);
5399 glDeleteBuffers(1, &m_draw_command_buffer);
5400 glDeleteTextures(1, &m_draw_command_buffer_tex);
5401 glDeleteProgram(m_store_program);
5402 glDeleteProgram(m_draw_program);
5403 glDeleteVertexArrays(1, &m_attribless_vao);
5404 glDeleteVertexArrays(1, &m_draw_vao);
5405 glDeleteBuffers(1, &m_draw_vbo);
5406 return NO_ERROR;
5407 }
5408 };
5409 //-----------------------------------------------------------------------------
5410 // 2.1.5 AdvancedSyncTextureUpdate
5411 //-----------------------------------------------------------------------------
5412 class AdvancedSyncTextureUpdate : public ShaderImageLoadStoreBase
5413 {
5414 GLuint m_texture;
5415 GLuint m_store_program;
5416 GLuint m_draw_program;
5417 GLuint m_vao;
5418 GLuint m_vbo;
5419 GLuint m_pbo;
5420
Setup()5421 virtual long Setup()
5422 {
5423 m_texture = 0;
5424 m_store_program = 0;
5425 m_draw_program = 0;
5426 m_vao = 0;
5427 m_vbo = 0;
5428 m_pbo = 0;
5429 return NO_ERROR;
5430 }
5431
Run()5432 virtual long Run()
5433 {
5434 const char* const glsl_vs =
5435 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL
5436 "void main() {" NL " gl_Position = i_position;" NL " vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}";
5437 const char* const glsl_store_fs =
5438 "#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL
5439 " imageStore(g_image, ivec2(gl_FragCoord.xy), gl_FragCoord);" NL " discard;" NL "}";
5440 const char* const glsl_draw_fs =
5441 "#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL
5442 "uniform sampler2D g_sampler;" NL "void main() {" NL " o_color = texture(g_sampler, vs_texcoord);" NL "}";
5443 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
5444 m_draw_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs);
5445
5446 std::vector<vec4> data(16 * 16, vec4(1.0f));
5447 glGenBuffers(1, &m_pbo);
5448 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
5449 glBufferData(GL_PIXEL_UNPACK_BUFFER, 16 * 16 * sizeof(vec4), &data[0], GL_DYNAMIC_READ);
5450 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
5451
5452 glGenTextures(1, &m_texture);
5453 glBindTexture(GL_TEXTURE_2D, m_texture);
5454 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5455 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
5456 glBindTexture(GL_TEXTURE_2D, 0);
5457
5458 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5459
5460 glViewport(0, 0, 16, 16);
5461 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5462 glUseProgram(m_store_program);
5463 glBindVertexArray(m_vao);
5464 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5465
5466 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
5467 glBindTexture(GL_TEXTURE_2D, m_texture);
5468 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
5469 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGBA, GL_FLOAT, 0);
5470 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
5471
5472 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5473 glClear(GL_COLOR_BUFFER_BIT);
5474 glUseProgram(m_draw_program);
5475 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5476
5477 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(1, 1, 1, 1)))
5478 {
5479 return ERROR;
5480 }
5481 return NO_ERROR;
5482 }
5483
Cleanup()5484 virtual long Cleanup()
5485 {
5486 glUseProgram(0);
5487 glDeleteBuffers(1, &m_vbo);
5488 glDeleteBuffers(1, &m_pbo);
5489 glDeleteTextures(1, &m_texture);
5490 glDeleteProgram(m_store_program);
5491 glDeleteProgram(m_draw_program);
5492 glDeleteVertexArrays(1, &m_vao);
5493 return NO_ERROR;
5494 }
5495 };
5496 //-----------------------------------------------------------------------------
5497 // 2.1.6 AdvancedSyncImageAccess2
5498 //-----------------------------------------------------------------------------
5499 class AdvancedSyncImageAccess2 : public ShaderImageLoadStoreBase
5500 {
5501 GLuint m_texture;
5502 GLuint m_store_program;
5503 GLuint m_draw_program;
5504 GLuint m_vao;
5505 GLuint m_vbo;
5506
Setup()5507 virtual long Setup()
5508 {
5509 m_texture = 0;
5510 m_store_program = 0;
5511 m_draw_program = 0;
5512 m_vao = 0;
5513 m_vbo = 0;
5514 return NO_ERROR;
5515 }
5516
Run()5517 virtual long Run()
5518 {
5519 const char* const glsl_vs =
5520 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL
5521 "void main() {" NL " gl_Position = i_position;" NL " vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}";
5522 const char* const glsl_store_fs =
5523 "#version 420 core" NL "writeonly uniform image2D g_image;" NL "uniform vec4 g_color;" NL "void main() {" NL
5524 " imageStore(g_image, ivec2(gl_FragCoord.xy), g_color);" NL " discard;" NL "}";
5525 const char* const glsl_draw_fs =
5526 "#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL
5527 "uniform sampler2D g_sampler;" NL "void main() {" NL " o_color = texture(g_sampler, vs_texcoord);" NL "}";
5528 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
5529 m_draw_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs);
5530
5531 int width = getWindowWidth();
5532 int height = getWindowHeight();
5533 scaleDimensionsToMemory(width, height, 1, 1, 16, 16);
5534
5535 glGenTextures(1, &m_texture);
5536 glBindTexture(GL_TEXTURE_2D, m_texture);
5537 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5538 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
5539 glBindTexture(GL_TEXTURE_2D, 0);
5540
5541 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5542
5543 glViewport(0, 0, width, height);
5544 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5545 glUseProgram(m_store_program);
5546 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 1.0f, 0.0f, 0.0f, 1.0f);
5547 glBindVertexArray(m_vao);
5548 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5549
5550 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5551
5552 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
5553 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5554
5555 glClear(GL_COLOR_BUFFER_BIT);
5556 glBindTexture(GL_TEXTURE_2D, m_texture);
5557 glUseProgram(m_draw_program);
5558 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5559
5560 if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
5561 {
5562 return ERROR;
5563 }
5564 return NO_ERROR;
5565 }
5566
Cleanup()5567 virtual long Cleanup()
5568 {
5569 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5570 glUseProgram(0);
5571 glDeleteBuffers(1, &m_vbo);
5572 glDeleteTextures(1, &m_texture);
5573 glDeleteProgram(m_store_program);
5574 glDeleteProgram(m_draw_program);
5575 glDeleteVertexArrays(1, &m_vao);
5576 return NO_ERROR;
5577 }
5578 };
5579 //-----------------------------------------------------------------------------
5580 // 2.1.7 AdvancedSyncBufferUpdate
5581 //-----------------------------------------------------------------------------
5582 class AdvancedSyncBufferUpdate : public ShaderImageLoadStoreBase
5583 {
5584 GLuint m_buffer;
5585 GLuint m_buffer_tex;
5586 GLuint m_store_program;
5587 GLuint m_attribless_vao;
5588
Setup()5589 virtual long Setup()
5590 {
5591 m_buffer = 0;
5592 m_buffer_tex = 0;
5593 m_store_program = 0;
5594 m_attribless_vao = 0;
5595 return NO_ERROR;
5596 }
5597
Run()5598 virtual long Run()
5599 {
5600 if (!SupportedInVS(1))
5601 return NOT_SUPPORTED;
5602 const char* const glsl_store_vs =
5603 "#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL
5604 " imageStore(g_output_data, gl_VertexID, vec4(gl_VertexID));" NL "}";
5605 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5606
5607 glGenVertexArrays(1, &m_attribless_vao);
5608 glBindVertexArray(m_attribless_vao);
5609
5610 glGenBuffers(1, &m_buffer);
5611 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5612 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 1000, NULL, GL_DYNAMIC_DRAW);
5613 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5614
5615 glGenTextures(1, &m_buffer_tex);
5616 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5617 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5618
5619 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5620
5621 glEnable(GL_RASTERIZER_DISCARD);
5622 glUseProgram(m_store_program);
5623 glDrawArrays(GL_POINTS, 0, 1000);
5624
5625 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5626
5627 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5628 vec4* ptr =
5629 reinterpret_cast<vec4*>(glMapBufferRange(GL_TEXTURE_BUFFER, 0, 1000 * sizeof(vec4), GL_MAP_READ_BIT));
5630 for (int i = 0; i < 1000; ++i)
5631 {
5632 if (!IsEqual(ptr[i], vec4(static_cast<float>(i))))
5633 {
5634 m_context.getTestContext().getLog()
5635 << tcu::TestLog::Message << "Bad buffer value found at index " << i << tcu::TestLog::EndMessage;
5636 return ERROR;
5637 }
5638 }
5639 return NO_ERROR;
5640 }
5641
Cleanup()5642 virtual long Cleanup()
5643 {
5644 glDisable(GL_RASTERIZER_DISCARD);
5645 glUseProgram(0);
5646 glDeleteBuffers(1, &m_buffer);
5647 glDeleteTextures(1, &m_buffer_tex);
5648 glDeleteProgram(m_store_program);
5649 glDeleteVertexArrays(1, &m_attribless_vao);
5650 return NO_ERROR;
5651 }
5652 };
5653 //-----------------------------------------------------------------------------
5654 // 2.2.1 AdvancedAllStagesOneImage
5655 //-----------------------------------------------------------------------------
5656 class AdvancedAllStagesOneImage : public ShaderImageLoadStoreBase
5657 {
5658 GLuint m_program;
5659 GLuint m_vao;
5660 GLuint m_vbo;
5661 GLuint m_ebo;
5662 GLuint m_buffer;
5663 GLuint m_buffer_tex;
5664 GLuint m_texture;
5665
Setup()5666 virtual long Setup()
5667 {
5668 m_program = 0;
5669 m_vao = 0;
5670 m_vbo = 0;
5671 m_ebo = 0;
5672 m_buffer = 0;
5673 m_buffer_tex = 0;
5674 m_texture = 0;
5675 return NO_ERROR;
5676 }
5677
Run()5678 virtual long Run()
5679 {
5680 if (!SupportedInGeomStages(2))
5681 return NOT_SUPPORTED;
5682 const char* const glsl_vs =
5683 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5684 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5685 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5686 " gl_Position = i_position + vec4(1.0, 1.0, 0.0, 0.0);" NL " imageAtomicAdd(g_buffer, 0, 1);" NL
5687 " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}";
5688 const char* const glsl_tcs =
5689 "#version 420 core" NL "layout(vertices = 1) out;" NL
5690 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5691 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5692 " gl_out[gl_InvocationID].gl_Position = gl_in[0].gl_Position;" NL " gl_TessLevelInner[0] = 1.0;" NL
5693 " gl_TessLevelInner[1] = 1.0;" NL " gl_TessLevelOuter[0] = 1.0;" NL " gl_TessLevelOuter[1] = 1.0;" NL
5694 " gl_TessLevelOuter[2] = 1.0;" NL " gl_TessLevelOuter[3] = 1.0;" NL " imageAtomicAdd(g_buffer, 0, 1);" NL
5695 " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}";
5696 const char* const glsl_tes =
5697 "#version 420 core" NL "layout(triangles, point_mode) in;" NL
5698 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5699 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5700 " imageAtomicAdd(g_buffer, 0, 1);" NL " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5701 " gl_Position = gl_in[0].gl_Position;" NL "}";
5702 const char* const glsl_gs =
5703 "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL
5704 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5705 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5706 " imageAtomicAdd(g_buffer, 0, 1);" NL " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5707 " gl_Position = gl_in[0].gl_Position;" NL " EmitVertex();" NL "}";
5708 const char* const glsl_fs =
5709 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
5710 "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5711 "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5712 " imageAtomicAdd(g_buffer, 0, 1);" NL " imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5713 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
5714 m_program = BuildProgram(glsl_vs, glsl_tcs, glsl_tes, glsl_gs, glsl_fs);
5715 glUseProgram(m_program);
5716 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5717 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5718
5719 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
5720
5721 GLint i32 = 0;
5722 glGenBuffers(1, &m_buffer);
5723 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5724 glBufferData(GL_TEXTURE_BUFFER, 4, &i32, GL_STATIC_DRAW);
5725 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5726
5727 glGenTextures(1, &m_buffer_tex);
5728 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5729 glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, m_buffer);
5730 glBindTexture(GL_TEXTURE_BUFFER, 0);
5731
5732 GLuint ui32 = 0;
5733 glGenTextures(1, &m_texture);
5734 glBindTexture(GL_TEXTURE_2D, m_texture);
5735 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5736 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5737 glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 1, 1, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32);
5738 glBindTexture(GL_TEXTURE_2D, 0);
5739
5740 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
5741 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
5742
5743 glBindVertexArray(m_vao);
5744 glPatchParameteri(GL_PATCH_VERTICES, 1);
5745
5746 glDrawElementsInstancedBaseVertex(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1, 0);
5747 glDrawElementsInstanced(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1);
5748
5749 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5750 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5751 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, 4, &i32);
5752 if (i32 < 20 || i32 > 50)
5753 {
5754 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Buffer value is " << i32
5755 << " should be in the range [20;50]" << tcu::TestLog::EndMessage;
5756 return ERROR;
5757 }
5758
5759 glBindTexture(GL_TEXTURE_2D, m_texture);
5760 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32);
5761 if (ui32 < 40 || ui32 != static_cast<GLuint>(2 * i32))
5762 {
5763 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texture value is " << ui32 << " should be "
5764 << (2 * i32) << tcu::TestLog::EndMessage;
5765 return ERROR;
5766 }
5767
5768 return NO_ERROR;
5769 }
5770
Cleanup()5771 virtual long Cleanup()
5772 {
5773 glPatchParameteri(GL_PATCH_VERTICES, 3);
5774 glUseProgram(0);
5775 glDeleteBuffers(1, &m_buffer);
5776 glDeleteBuffers(1, &m_vbo);
5777 glDeleteBuffers(1, &m_ebo);
5778 glDeleteTextures(1, &m_buffer_tex);
5779 glDeleteTextures(1, &m_texture);
5780 glDeleteProgram(m_program);
5781 glDeleteVertexArrays(1, &m_vao);
5782 return NO_ERROR;
5783 }
5784 };
5785 //-----------------------------------------------------------------------------
5786 // 2.3.1 AdvancedMemoryDependentInvocation
5787 //-----------------------------------------------------------------------------
5788 class AdvancedMemoryDependentInvocation : public ShaderImageLoadStoreBase
5789 {
5790 GLuint m_buffer;
5791 GLuint m_buffer_tex;
5792 GLuint m_texture;
5793 GLuint m_program;
5794 GLuint m_vao;
5795 GLuint m_vbo;
5796
Setup()5797 virtual long Setup()
5798 {
5799 m_buffer = 0;
5800 m_buffer_tex = 0;
5801 m_texture = 0;
5802 m_program = 0;
5803 m_vao = 0;
5804 m_vbo = 0;
5805 return NO_ERROR;
5806 }
5807
Run()5808 virtual long Run()
5809 {
5810 if (!SupportedInVS(2))
5811 return NOT_SUPPORTED;
5812 const char* const glsl_vs =
5813 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5814 "layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL
5815 "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL
5816 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL " gl_Position = i_position;" NL
5817 " vs_color = i_color;" NL " imageStore(g_buffer, 0, vec4(1.0));" NL
5818 " imageStore(g_image, ivec2(0, 0), vec4(2.0));" NL " memoryBarrier();" NL "}";
5819 const char* const glsl_fs =
5820 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
5821 "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL
5822 "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL " o_color = vs_color;" NL
5823 " if (imageLoad(g_buffer, 0) != vec4(1.0)) o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL
5824 " if (imageLoad(g_image, ivec2(0, 0)) != vec4(2.0)) o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "}";
5825 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
5826 glUseProgram(m_program);
5827 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5828 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5829
5830 vec4 zero(0);
5831 glGenBuffers(1, &m_buffer);
5832 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5833 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4), &zero, GL_STATIC_DRAW);
5834 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5835
5836 glGenTextures(1, &m_buffer_tex);
5837 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5838 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5839 glBindTexture(GL_TEXTURE_BUFFER, 0);
5840
5841 glGenTextures(1, &m_texture);
5842 glBindTexture(GL_TEXTURE_2D, m_texture);
5843 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5844 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, &zero);
5845 glBindTexture(GL_TEXTURE_2D, 0);
5846
5847 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5848 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5849
5850 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5851
5852 glClear(GL_COLOR_BUFFER_BIT);
5853 glBindVertexArray(m_vao);
5854 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5855
5856 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5857 {
5858 return ERROR;
5859 }
5860 return NO_ERROR;
5861 }
5862
Cleanup()5863 virtual long Cleanup()
5864 {
5865 glUseProgram(0);
5866 glDeleteBuffers(1, &m_vbo);
5867 glDeleteBuffers(1, &m_buffer);
5868 glDeleteTextures(1, &m_texture);
5869 glDeleteTextures(1, &m_buffer_tex);
5870 glDeleteProgram(m_program);
5871 glDeleteVertexArrays(1, &m_vao);
5872 return NO_ERROR;
5873 }
5874 };
5875 //-----------------------------------------------------------------------------
5876 // 2.3.2 AdvancedMemoryOrder
5877 //-----------------------------------------------------------------------------
5878 class AdvancedMemoryOrder : public ShaderImageLoadStoreBase
5879 {
5880 GLuint m_buffer;
5881 GLuint m_buffer_tex;
5882 GLuint m_texture;
5883 GLuint m_program;
5884 GLuint m_vao;
5885 GLuint m_vbo;
5886
Setup()5887 virtual long Setup()
5888 {
5889 m_buffer = 0;
5890 m_buffer_tex = 0;
5891 m_texture = 0;
5892 m_program = 0;
5893 m_vao = 0;
5894 m_vbo = 0;
5895 return NO_ERROR;
5896 }
5897
Run()5898 virtual long Run()
5899 {
5900 if (!SupportedInVS(1))
5901 return NOT_SUPPORTED;
5902 const char* const glsl_vs =
5903 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec4 vs_color;" NL
5904 "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL "void main() {" NL
5905 " gl_Position = i_position;" NL " vs_color = vec4(0, 1, 0, 1);" NL
5906 " imageStore(g_buffer, gl_VertexID, vec4(1.0));" NL " imageStore(g_buffer, gl_VertexID, vec4(2.0));" NL
5907 " imageStore(g_buffer, gl_VertexID, vec4(3.0));" NL
5908 " if (imageLoad(g_buffer, gl_VertexID) != vec4(3.0)) vs_color = vec4(1, 0, 0, 1);" NL "}";
5909 const char* const glsl_fs =
5910 "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
5911 "layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL " o_color = vs_color;" NL
5912 " ivec2 coord = ivec2(gl_FragCoord);" NL " for (int i = 0; i < 3; ++i) {" NL
5913 " imageStore(g_image, coord, vec4(i));" NL " vec4 v = imageLoad(g_image, coord);" NL
5914 " if (v != vec4(i)) {" NL " o_color = vec4(v.xyz, 0.0);" NL " break;" NL " }" NL " }" NL
5915 "}";
5916 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
5917 glUseProgram(m_program);
5918 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5919 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5920
5921 glGenBuffers(1, &m_buffer);
5922 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5923 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW);
5924 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5925
5926 glGenTextures(1, &m_buffer_tex);
5927 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5928 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5929 glBindTexture(GL_TEXTURE_BUFFER, 0);
5930
5931 int width = getWindowWidth();
5932 int height = getWindowHeight();
5933 scaleDimensionsToMemory(width, height, 1, 2, 16, 16);
5934
5935 std::vector<vec4> data(width * height);
5936 glGenTextures(1, &m_texture);
5937 glBindTexture(GL_TEXTURE_2D, m_texture);
5938 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5939 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &data[0]);
5940 glBindTexture(GL_TEXTURE_2D, 0);
5941
5942 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5943 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5944
5945 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5946
5947 glClear(GL_COLOR_BUFFER_BIT);
5948 glViewport(0, 0, width, height);
5949 glBindVertexArray(m_vao);
5950 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5951
5952 if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
5953 {
5954 return ERROR;
5955 }
5956 return NO_ERROR;
5957 }
5958
Cleanup()5959 virtual long Cleanup()
5960 {
5961 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5962 glUseProgram(0);
5963 glDeleteBuffers(1, &m_vbo);
5964 glDeleteBuffers(1, &m_buffer);
5965 glDeleteTextures(1, &m_texture);
5966 glDeleteTextures(1, &m_buffer_tex);
5967 glDeleteProgram(m_program);
5968 glDeleteVertexArrays(1, &m_vao);
5969 return NO_ERROR;
5970 }
5971 };
5972 //-----------------------------------------------------------------------------
5973 // 2.4.1 AdvancedSSOSimple
5974 //-----------------------------------------------------------------------------
5975 class AdvancedSSOSimple : public ShaderImageLoadStoreBase
5976 {
5977 GLuint m_texture;
5978 GLuint m_pipeline[2];
5979 GLuint m_vsp, m_fsp0, m_fsp1;
5980 GLuint m_vao, m_vbo;
5981
Setup()5982 virtual long Setup()
5983 {
5984 glGenTextures(1, &m_texture);
5985 glGenProgramPipelines(2, m_pipeline);
5986 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5987
5988 const char* const glsl_vs =
5989 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL
5990 " vec4 gl_Position;" NL "};" NL "void main() {" NL " gl_Position = i_position;" NL "}";
5991 const char* const glsl_fs0 =
5992 "#version 420 core" NL "layout(rgba32f) uniform image2D g_image[4];" NL "void main() {" NL
5993 " for (int i = 0; i < g_image.length(); ++i) {" NL
5994 " imageStore(g_image[i], ivec2(gl_FragCoord), vec4(1.0));" NL " }" NL " discard;" NL "}";
5995 const char* const glsl_fs1 =
5996 "#version 420 core" NL "writeonly uniform image2D g_image[4];" NL "void main() {" NL
5997 " for (int i = 0; i < g_image.length(); ++i) {" NL
5998 " imageStore(g_image[i], ivec2(gl_FragCoord), vec4(2.0));" NL " }" NL " discard;" NL "}";
5999 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6000 m_fsp0 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs0);
6001 m_fsp1 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs1);
6002
6003 return NO_ERROR;
6004 }
6005
Run()6006 virtual long Run()
6007 {
6008 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[0]"), 0);
6009 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[1]"), 2);
6010 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[2]"), 4);
6011 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[3]"), 6);
6012
6013 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[0]"), 1);
6014 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[1]"), 3);
6015 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[2]"), 5);
6016 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[3]"), 7);
6017
6018 glUseProgramStages(m_pipeline[0], GL_VERTEX_SHADER_BIT, m_vsp);
6019 glUseProgramStages(m_pipeline[0], GL_FRAGMENT_SHADER_BIT, m_fsp0);
6020
6021 glUseProgramStages(m_pipeline[1], GL_VERTEX_SHADER_BIT, m_vsp);
6022 glUseProgramStages(m_pipeline[1], GL_FRAGMENT_SHADER_BIT, m_fsp1);
6023
6024 int width = getWindowWidth();
6025 int height = getWindowHeight();
6026 scaleDimensionsToMemory(width, height, 8, 8, 16, 16);
6027
6028 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
6029 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6030 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, width, height, 8, 0, GL_RGBA, GL_FLOAT, NULL);
6031
6032 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6033 glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_RGBA32F);
6034 glBindImageTexture(2, m_texture, 0, GL_FALSE, 2, GL_READ_WRITE, GL_RGBA32F);
6035 glBindImageTexture(3, m_texture, 0, GL_FALSE, 3, GL_READ_WRITE, GL_RGBA32F);
6036 glBindImageTexture(4, m_texture, 0, GL_FALSE, 4, GL_READ_WRITE, GL_RGBA32F);
6037 glBindImageTexture(5, m_texture, 0, GL_FALSE, 5, GL_READ_WRITE, GL_RGBA32F);
6038 glBindImageTexture(6, m_texture, 0, GL_FALSE, 6, GL_READ_WRITE, GL_RGBA32F);
6039 glBindImageTexture(7, m_texture, 0, GL_FALSE, 7, GL_READ_WRITE, GL_RGBA32F);
6040
6041 glBindVertexArray(m_vao);
6042
6043 glViewport(0, 0, width, height);
6044 glBindProgramPipeline(m_pipeline[0]);
6045 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
6046
6047 glBindProgramPipeline(m_pipeline[1]);
6048 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6049
6050 std::vector<vec4> data(width * height * 8);
6051 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6052
6053 for (int layer = 0; layer < 8; ++layer)
6054 {
6055 for (int h = 0; h < height; ++h)
6056 {
6057 for (int w = 0; w < width; ++w)
6058 {
6059 const vec4 c = data[layer * width * height + h * width + w];
6060 if (layer % 2)
6061 {
6062 if (!IsEqual(c, vec4(2.0f)))
6063 {
6064 return ERROR;
6065 }
6066 }
6067 else
6068 {
6069 if (!IsEqual(c, vec4(1.0f)))
6070 {
6071 return ERROR;
6072 }
6073 }
6074 }
6075 }
6076 }
6077 return NO_ERROR;
6078 }
6079
Cleanup()6080 virtual long Cleanup()
6081 {
6082 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6083 glDeleteBuffers(1, &m_vbo);
6084 glDeleteTextures(1, &m_texture);
6085 glDeleteProgram(m_vsp);
6086 glDeleteProgram(m_fsp0);
6087 glDeleteProgram(m_fsp1);
6088 glDeleteVertexArrays(1, &m_vao);
6089 glDeleteProgramPipelines(2, m_pipeline);
6090 return NO_ERROR;
6091 }
6092 };
6093 //-----------------------------------------------------------------------------
6094 // 2.4.2 AdvancedSSOAtomicCounters
6095 //-----------------------------------------------------------------------------
6096 class AdvancedSSOAtomicCounters : public ShaderImageLoadStoreBase
6097 {
6098 GLuint m_buffer, m_buffer_tex;
6099 GLuint m_counter_buffer;
6100 GLuint m_transform_buffer;
6101 GLuint m_pipeline;
6102 GLuint m_vao, m_vbo;
6103 GLuint m_vsp, m_fsp;
6104
Setup()6105 virtual long Setup()
6106 {
6107 m_vao = 0;
6108 m_vbo = 0;
6109 m_vsp = 0;
6110 m_fsp = 0;
6111 glGenBuffers(1, &m_buffer);
6112 glGenTextures(1, &m_buffer_tex);
6113 glGenBuffers(1, &m_counter_buffer);
6114 glGenBuffers(1, &m_transform_buffer);
6115 glGenProgramPipelines(1, &m_pipeline);
6116 return NO_ERROR;
6117 }
6118
Run()6119 virtual long Run()
6120 {
6121 if (!SupportedInVS(1))
6122 return NOT_SUPPORTED;
6123
6124 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
6125 const char* const glsl_vs =
6126 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6127 "layout(location = 1) in vec4 i_color;" NL "layout(location = 3) out vec4 o_color;" NL
6128 "out gl_PerVertex {" NL " vec4 gl_Position;" NL "};" NL "layout(std140) uniform Transform {" NL
6129 " mat4 mvp;" NL "} g_transform;" NL "writeonly uniform imageBuffer g_buffer;" NL
6130 "layout(binding = 0, offset = 0) uniform atomic_uint g_counter;" NL "void main() {" NL
6131 " gl_Position = g_transform.mvp * i_position;" NL " o_color = i_color;" NL
6132 " const uint index = atomicCounterIncrement(g_counter);" NL
6133 " imageStore(g_buffer, int(index), gl_Position);" NL "}";
6134 const char* const glsl_fs =
6135 "#version 420 core" NL "layout(location = 3) in vec4 i_color;" NL
6136 "layout(location = 0) out vec4 o_color;" NL "void main() {" NL " o_color = i_color;" NL "}";
6137 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6138 m_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs);
6139
6140 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
6141 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_fsp);
6142
6143 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
6144 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW);
6145
6146 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
6147 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
6148
6149 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_counter_buffer);
6150 vec4 zero(0);
6151 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), &zero, GL_STATIC_DRAW);
6152
6153 glBindBuffer(GL_UNIFORM_BUFFER, m_transform_buffer);
6154 mat4 identity(1);
6155 glBufferData(GL_UNIFORM_BUFFER, sizeof(mat4), &identity, GL_STATIC_DRAW);
6156
6157 glClear(GL_COLOR_BUFFER_BIT);
6158 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_counter_buffer);
6159 glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_transform_buffer);
6160 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6161 glBindVertexArray(m_vao);
6162 glBindProgramPipeline(m_pipeline);
6163 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
6164
6165 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6166 {
6167 return ERROR;
6168 }
6169
6170 std::vector<vec4> data(4);
6171 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
6172 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(vec4) * 4, &data[0]);
6173
6174 for (int i = 0; i < 4; ++i)
6175 {
6176 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)) &&
6177 !IsEqual(data[i], vec4(-1.0f, 1.0f, 0.0f, 1.0f)) && !IsEqual(data[i], vec4(1.0f, 1.0f, 0.0f, 1.0f)))
6178 {
6179 return ERROR;
6180 }
6181 }
6182
6183 return NO_ERROR;
6184 }
6185
Cleanup()6186 virtual long Cleanup()
6187 {
6188 glDeleteBuffers(1, &m_buffer);
6189 glDeleteBuffers(1, &m_vbo);
6190 glDeleteBuffers(1, &m_counter_buffer);
6191 glDeleteBuffers(1, &m_transform_buffer);
6192 glDeleteTextures(1, &m_buffer_tex);
6193 glDeleteProgram(m_vsp);
6194 glDeleteProgram(m_fsp);
6195 glDeleteVertexArrays(1, &m_vao);
6196 glDeleteProgramPipelines(1, &m_pipeline);
6197 return NO_ERROR;
6198 }
6199 };
6200 //-----------------------------------------------------------------------------
6201 // 2.4.3 AdvancedSSOSubroutine
6202 //-----------------------------------------------------------------------------
6203 class AdvancedSSOSubroutine : public ShaderImageLoadStoreBase
6204 {
6205 GLuint m_texture;
6206 GLuint m_attribless_vao;
6207 GLuint m_program;
6208 GLint m_draw_buffer;
6209
Setup()6210 virtual long Setup()
6211 {
6212 glGenTextures(1, &m_texture);
6213 glGenVertexArrays(1, &m_attribless_vao);
6214
6215 const char* const glsl_vs = "#version 420 core" NL "const int kSize = 3;" NL
6216 "const vec2 g_triangle[kSize] = vec2[3](vec2(-1, -1), vec2(3, -1), vec2(-1, 3));" NL
6217 "void main() {" NL " gl_Position = vec4(g_triangle[gl_VertexID], 0, 1);" NL "}";
6218 const char* const glsl_fs =
6219 "#version 420 core" NL "writeonly uniform image2DArray g_image0;" NL
6220 "writeonly uniform image2DArray g_image1;" NL "subroutine void Brush(ivec2 coord);" NL
6221 "subroutine uniform Brush g_brush;" NL "subroutine(Brush) void Brush0(ivec2 coord) {" NL
6222 " imageStore(g_image0, ivec3(coord, 0), vec4(1.0, 0.0, 0.0, 1.0));" NL
6223 " imageStore(g_image0, ivec3(coord, 1), vec4(0.0, 1.0, 0.0, 1.0));" NL
6224 " imageStore(g_image0, ivec3(coord, 2), vec4(0.0, 0.0, 1.0, 1.0));" NL "}" NL
6225 "subroutine(Brush) void Brush1(ivec2 coord) {" NL
6226 " imageStore(g_image1, ivec3(coord, 0), vec4(0.0, 1.0, 0.0, 1.0));" NL
6227 " imageStore(g_image1, ivec3(coord, 1), vec4(0.0, 0.0, 1.0, 1.0));" NL
6228 " imageStore(g_image1, ivec3(coord, 2), vec4(1.0, 0.0, 0.0, 1.0));" NL "}" NL "void main() {" NL
6229 " g_brush(ivec2(gl_FragCoord));" NL "}";
6230 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6231
6232 return NO_ERROR;
6233 }
6234
Run()6235 virtual long Run()
6236 {
6237 int width = getWindowWidth();
6238 int height = getWindowHeight();
6239 scaleDimensionsToMemory(width, height, 3, 3, 16, 16);
6240
6241 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image0"), 1);
6242 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image1"), 1);
6243
6244 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
6245 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6246 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, width, height, 3, 0, GL_RGBA, GL_FLOAT, NULL);
6247
6248 glGetIntegerv(GL_DRAW_BUFFER, &m_draw_buffer);
6249
6250 glDrawBuffer(GL_NONE);
6251 glBindImageTexture(1, m_texture, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32F);
6252 glUseProgram(m_program);
6253 glBindVertexArray(m_attribless_vao);
6254
6255 const GLuint indices[2] = { glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush0"),
6256 glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush1") };
6257
6258 glViewport(0, 0, width, height);
6259 glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[0]);
6260 glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
6261
6262 std::vector<vec4> data(width * height * 3);
6263 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6264 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6265
6266 for (int layer = 0; layer < 3; ++layer)
6267 {
6268 for (int h = 0; h < height; ++h)
6269 {
6270 for (int w = 0; w < width; ++w)
6271 {
6272 const vec4 c = data[layer * width * height + h * width + w];
6273 if (layer == 0 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f)))
6274 {
6275 m_context.getTestContext().getLog()
6276 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6277 << ") should be (1 0 0 1)" << tcu::TestLog::EndMessage;
6278 return ERROR;
6279 }
6280 else if (layer == 1 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f)))
6281 {
6282 m_context.getTestContext().getLog()
6283 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6284 << ") should be (0 1 0 1)" << tcu::TestLog::EndMessage;
6285 return ERROR;
6286 }
6287 else if (layer == 2 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f)))
6288 {
6289 m_context.getTestContext().getLog()
6290 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6291 << ") should be (0 0 1 1)" << tcu::TestLog::EndMessage;
6292 return ERROR;
6293 }
6294 }
6295 }
6296 }
6297
6298 glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[1]);
6299 glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
6300
6301 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6302 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6303
6304 for (int layer = 0; layer < 3; ++layer)
6305 {
6306 for (int h = 0; h < height; ++h)
6307 {
6308 for (int w = 0; w < width; ++w)
6309 {
6310 const vec4 c = data[layer * width * height + h * width + w];
6311 if (layer == 0 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f)))
6312 {
6313 m_context.getTestContext().getLog()
6314 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6315 << ") should be (0 1 0 1)" << tcu::TestLog::EndMessage;
6316 return ERROR;
6317 }
6318 else if (layer == 1 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f)))
6319 {
6320 m_context.getTestContext().getLog()
6321 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6322 << ") should be (0 0 1 1)" << tcu::TestLog::EndMessage;
6323 return ERROR;
6324 }
6325 else if (layer == 2 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f)))
6326 {
6327 m_context.getTestContext().getLog()
6328 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6329 << ") should be (1 0 0 1)" << tcu::TestLog::EndMessage;
6330 return ERROR;
6331 }
6332 }
6333 }
6334 }
6335 return NO_ERROR;
6336 }
6337
Cleanup()6338 virtual long Cleanup()
6339 {
6340 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6341 glDrawBuffer(m_draw_buffer);
6342 glDeleteTextures(1, &m_texture);
6343 glUseProgram(0);
6344 glDeleteProgram(m_program);
6345 glDeleteVertexArrays(1, &m_attribless_vao);
6346 return NO_ERROR;
6347 }
6348 };
6349 //-----------------------------------------------------------------------------
6350 // 2.4.4 AdvancedSSOPerSample
6351 //-----------------------------------------------------------------------------
6352 class AdvancedSSOPerSample : public ShaderImageLoadStoreBase
6353 {
6354 GLuint m_texture;
6355 GLuint m_pipeline;
6356 GLuint m_vao, m_vbo, m_ebo;
6357 GLuint m_vsp, m_store_fsp, m_load_fsp;
6358
Setup()6359 virtual long Setup()
6360 {
6361 m_vao = 0;
6362 m_vbo = 0;
6363 m_ebo = 0;
6364 m_vsp = 0;
6365 m_store_fsp = 0;
6366 m_load_fsp = 0;
6367 glGenTextures(1, &m_texture);
6368 glGenProgramPipelines(1, &m_pipeline);
6369
6370 return NO_ERROR;
6371 }
6372
Run()6373 virtual long Run()
6374 {
6375 if (!SupportedSamples(4))
6376 return NOT_SUPPORTED;
6377
6378 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6379
6380 const char* const glsl_vs =
6381 "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL
6382 " vec4 gl_Position;" NL "};" NL "void main() {" NL " gl_Position = i_position;" NL "}";
6383 const char* const glsl_store_fs =
6384 "#version 420 core" NL "layout(rgba32f) writeonly uniform image2DMS g_image;" NL "void main() {" NL
6385 " imageStore(g_image, ivec2(gl_FragCoord), gl_SampleID, vec4(gl_SampleID+1));" NL "}";
6386 const char* const glsl_load_fs =
6387 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6388 "layout(rgba32f) readonly uniform image2DMS g_image;" NL "void main() {" NL
6389 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " if (imageLoad(g_image, ivec2(gl_FragCoord), gl_SampleID) != "
6390 "vec4(gl_SampleID+1)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
6391 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6392 m_store_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_store_fs);
6393 m_load_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_load_fs);
6394
6395 int width = getWindowWidth();
6396 int height = getWindowHeight();
6397 scaleDimensionsToMemory(width, height, 1, 1, /* bpp*samples */ 16 * 4, 16);
6398
6399 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texture);
6400 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA32F, width, height, GL_FALSE);
6401 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
6402
6403 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
6404 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_store_fsp);
6405
6406 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6407
6408 glClear(GL_COLOR_BUFFER_BIT);
6409 glViewport(0, 0, width, height);
6410 glBindVertexArray(m_vao);
6411 glBindProgramPipeline(m_pipeline);
6412 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6413
6414 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
6415
6416 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_load_fsp);
6417 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6418
6419 if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
6420 {
6421 return ERROR;
6422 }
6423 return NO_ERROR;
6424 }
6425
Cleanup()6426 virtual long Cleanup()
6427 {
6428 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6429 glDeleteBuffers(1, &m_vbo);
6430 glDeleteBuffers(1, &m_ebo);
6431 glDeleteTextures(1, &m_texture);
6432 glDeleteProgram(m_vsp);
6433 glDeleteProgram(m_store_fsp);
6434 glDeleteProgram(m_load_fsp);
6435 glDeleteVertexArrays(1, &m_vao);
6436 glDeleteProgramPipelines(1, &m_pipeline);
6437 return NO_ERROR;
6438 }
6439 };
6440
6441 //-----------------------------------------------------------------------------
6442 // 2.5 AdvancedCopyImage
6443 //-----------------------------------------------------------------------------
6444 class AdvancedCopyImage : public ShaderImageLoadStoreBase
6445 {
6446 GLuint m_texture[2];
6447 GLuint m_program;
6448 GLuint m_vao, m_vbo, m_ebo;
6449
Setup()6450 virtual long Setup()
6451 {
6452 glGenTextures(2, m_texture);
6453 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6454
6455 const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6456 "void main() {" NL " gl_Position = i_position;" NL "}";
6457 const char* const glsl_fs =
6458 "#version 420 core" NL "layout(rgba32f) readonly uniform image2D g_input_image;" NL
6459 "layout(rgba32f) writeonly uniform image2D g_output_image;" NL "void main() {" NL
6460 " ivec2 coord = ivec2(gl_FragCoord);" NL
6461 " imageStore(g_output_image, coord, imageLoad(g_input_image, coord));" NL " discard;" NL "}";
6462 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6463
6464 return NO_ERROR;
6465 }
6466
Run()6467 virtual long Run()
6468 {
6469 int width = getWindowWidth();
6470 int height = getWindowHeight();
6471 scaleDimensionsToMemory(width, height, 2, 2, 16, 16);
6472
6473 glUseProgram(m_program);
6474 glUniform1i(glGetUniformLocation(m_program, "g_input_image"), 0);
6475 glUniform1i(glGetUniformLocation(m_program, "g_output_image"), 1);
6476
6477 std::vector<vec4> data(width * height, vec4(7.0f));
6478 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6479 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6480 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &data[0]);
6481
6482 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6483 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6484 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
6485
6486 glBindTexture(GL_TEXTURE_2D, 0);
6487
6488 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
6489 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
6490
6491 glClear(GL_COLOR_BUFFER_BIT);
6492 glViewport(0, 0, width, height);
6493 glBindVertexArray(m_vao);
6494 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6495
6496 std::vector<vec4> rdata(width * height);
6497 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6498 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &rdata[0]);
6499
6500 for (int h = 0; h < height; ++h)
6501 {
6502 for (int w = 0; w < width; ++w)
6503 {
6504 if (!IsEqual(rdata[h * width + w], vec4(7.0f)))
6505 {
6506 return ERROR;
6507 }
6508 }
6509 }
6510 return NO_ERROR;
6511 }
6512
Cleanup()6513 virtual long Cleanup()
6514 {
6515 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6516 glUseProgram(0);
6517 glDeleteBuffers(1, &m_vbo);
6518 glDeleteBuffers(1, &m_ebo);
6519 glDeleteTextures(2, m_texture);
6520 glDeleteProgram(m_program);
6521 glDeleteVertexArrays(1, &m_vao);
6522 return NO_ERROR;
6523 }
6524 };
6525 //-----------------------------------------------------------------------------
6526 // 2.6 AdvancedAllMips
6527 //-----------------------------------------------------------------------------
6528 class AdvancedAllMips : public ShaderImageLoadStoreBase
6529 {
6530 GLuint m_texture;
6531 GLuint m_store_program, m_load_program;
6532 GLuint m_vao, m_vbo, m_ebo;
6533
Setup()6534 virtual long Setup()
6535 {
6536 glGenTextures(1, &m_texture);
6537 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6538
6539 const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6540 "void main() {" NL " gl_Position = i_position;" NL "}";
6541 const char* const glsl_store_fs =
6542 "#version 420 core" NL "layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL
6543 " for (int i = 0; i < 6; ++i) {" NL " imageStore(g_image[i], ivec2(gl_FragCoord), vec4(i));" NL " }" NL
6544 " discard;" NL "}";
6545 const char* const glsl_load_fs =
6546 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6547 "layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL
6548 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " for (int i = 0; i < 6; ++i) {" NL
6549 " const ivec2 coord = ivec2(gl_FragCoord);" NL " const vec4 c = imageLoad(g_image[i], coord);" NL
6550 " if (c != vec4(i) && c != vec4(0.0)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL " }" NL "}";
6551 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
6552 m_load_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_load_fs);
6553
6554 return NO_ERROR;
6555 }
6556
Run()6557 virtual long Run()
6558 {
6559 glUseProgram(m_store_program);
6560 glUniform1i(glGetUniformLocation(m_store_program, "g_image[0]"), 0);
6561 glUniform1i(glGetUniformLocation(m_store_program, "g_image[1]"), 1);
6562 glUniform1i(glGetUniformLocation(m_store_program, "g_image[2]"), 2);
6563 glUniform1i(glGetUniformLocation(m_store_program, "g_image[3]"), 3);
6564 glUniform1i(glGetUniformLocation(m_store_program, "g_image[4]"), 4);
6565 glUniform1i(glGetUniformLocation(m_store_program, "g_image[5]"), 5);
6566 glUseProgram(0);
6567
6568 glUseProgram(m_load_program);
6569 glUniform1i(glGetUniformLocation(m_load_program, "g_image[0]"), 0);
6570 glUniform1i(glGetUniformLocation(m_load_program, "g_image[1]"), 1);
6571 glUniform1i(glGetUniformLocation(m_load_program, "g_image[2]"), 2);
6572 glUniform1i(glGetUniformLocation(m_load_program, "g_image[3]"), 3);
6573 glUniform1i(glGetUniformLocation(m_load_program, "g_image[4]"), 4);
6574 glUniform1i(glGetUniformLocation(m_load_program, "g_image[5]"), 5);
6575 glUseProgram(0);
6576
6577 glBindTexture(GL_TEXTURE_2D, m_texture);
6578 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 32, 32, 0, GL_RGBA, GL_FLOAT, NULL);
6579 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
6580 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA32F, 8, 8, 0, GL_RGBA, GL_FLOAT, NULL);
6581 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA32F, 4, 4, 0, GL_RGBA, GL_FLOAT, NULL);
6582 glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA32F, 2, 2, 0, GL_RGBA, GL_FLOAT, NULL);
6583 glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, NULL);
6584 glBindTexture(GL_TEXTURE_2D, 0);
6585
6586 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6587 glBindImageTexture(1, m_texture, 1, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6588 glBindImageTexture(2, m_texture, 2, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6589 glBindImageTexture(3, m_texture, 3, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6590 glBindImageTexture(4, m_texture, 4, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6591 glBindImageTexture(5, m_texture, 5, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6592
6593 glViewport(0, 0, 32, 32);
6594 glBindVertexArray(m_vao);
6595
6596 glClear(GL_COLOR_BUFFER_BIT);
6597 glUseProgram(m_store_program);
6598 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6599
6600 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
6601
6602 glUseProgram(m_load_program);
6603 glDrawElementsInstancedBaseVertex(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6604
6605 if (!ValidateReadBuffer(0, 0, 32, 32, vec4(0, 1, 0, 1)))
6606 {
6607 return ERROR;
6608 }
6609 return NO_ERROR;
6610 }
6611
Cleanup()6612 virtual long Cleanup()
6613 {
6614 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6615 glUseProgram(0);
6616 glDeleteBuffers(1, &m_vbo);
6617 glDeleteBuffers(1, &m_ebo);
6618 glDeleteTextures(1, &m_texture);
6619 glDeleteProgram(m_store_program);
6620 glDeleteProgram(m_load_program);
6621 glDeleteVertexArrays(1, &m_vao);
6622 return NO_ERROR;
6623 }
6624 };
6625 //-----------------------------------------------------------------------------
6626 // 2.7 AdvancedCast
6627 //-----------------------------------------------------------------------------
6628 class AdvancedCast : public ShaderImageLoadStoreBase
6629 {
6630 GLuint m_texture[2];
6631 GLuint m_program;
6632 GLuint m_vao, m_vbo, m_ebo;
6633
Setup()6634 virtual long Setup()
6635 {
6636 glGenTextures(2, m_texture);
6637 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6638
6639 const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6640 "void main() {" NL " gl_Position = i_position;" NL "}";
6641 const char* const glsl_fs =
6642 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6643 "layout(r32i) coherent uniform iimage2D g_image0;" NL "layout(r32ui) coherent uniform uimage2D g_image1;" NL
6644 "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL " ivec2 coord = ivec2(gl_FragCoord);" NL
6645 " if (imageAtomicAdd(g_image0, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6646 " if (imageAtomicAdd(g_image0, coord, -1) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6647 " if (imageAtomicAdd(g_image1, coord, 1) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6648 " if (imageAtomicAdd(g_image1, coord, 2) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
6649 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6650
6651 return NO_ERROR;
6652 }
6653
Run()6654 virtual long Run()
6655 {
6656 glUseProgram(m_program);
6657 glUniform1i(glGetUniformLocation(m_program, "g_image0"), 0);
6658 glUniform1i(glGetUniformLocation(m_program, "g_image1"), 1);
6659
6660 {
6661 std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4);
6662 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6663 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6664 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
6665 &data[0]);
6666
6667 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6668 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6669 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
6670 &data[0]);
6671
6672 glBindTexture(GL_TEXTURE_2D, 0);
6673 }
6674
6675 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
6676 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
6677
6678 glClear(GL_COLOR_BUFFER_BIT);
6679 glBindVertexArray(m_vao);
6680 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6681
6682 std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4);
6683 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6684 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6685 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
6686
6687 for (int h = 0; h < getWindowHeight(); ++h)
6688 {
6689 for (int w = 0; w < getWindowWidth(); ++w)
6690 {
6691 const GLubyte c[4] = {
6692 data[h * (getWindowWidth() * 4) + w * 4 + 0], data[h * (getWindowWidth() * 4) + w * 4 + 1],
6693 data[h * (getWindowWidth() * 4) + w * 4 + 2], data[h * (getWindowWidth() * 4) + w * 4 + 3],
6694 };
6695 if (c[0] != 1 || c[1] != 0 || c[2] != 0 || c[3] != 0)
6696 {
6697 m_context.getTestContext().getLog()
6698 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6699 << ") should be (1 0 0 0)" << tcu::TestLog::EndMessage;
6700 return ERROR;
6701 }
6702 }
6703 }
6704
6705 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6706 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
6707
6708 for (int h = 0; h < getWindowHeight(); ++h)
6709 {
6710 for (int w = 0; w < getWindowWidth(); ++w)
6711 {
6712 const GLubyte c[4] = {
6713 data[h * (getWindowWidth() * 4) + w * 4 + 0], data[h * (getWindowWidth() * 4) + w * 4 + 1],
6714 data[h * (getWindowWidth() * 4) + w * 4 + 2], data[h * (getWindowWidth() * 4) + w * 4 + 3],
6715 };
6716 if (c[0] != 3 || c[1] != 0 || c[2] != 0 || c[3] != 0)
6717 {
6718 m_context.getTestContext().getLog()
6719 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6720 << ") should be (3 0 0 0)" << tcu::TestLog::EndMessage;
6721 return ERROR;
6722 }
6723 }
6724 }
6725
6726 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6727 {
6728 return ERROR;
6729 }
6730 return NO_ERROR;
6731 }
6732
Cleanup()6733 virtual long Cleanup()
6734 {
6735 glUseProgram(0);
6736 glDeleteBuffers(1, &m_vbo);
6737 glDeleteBuffers(1, &m_ebo);
6738 glDeleteTextures(2, m_texture);
6739 glDeleteProgram(m_program);
6740 glDeleteVertexArrays(1, &m_vao);
6741 return NO_ERROR;
6742 }
6743 };
6744
6745 /** Test "imageLoad() and imageStore() for single-byte data alignment" description follows.
6746 *
6747 * Steps:
6748 * - create two textures: "source" and "destination". Fill "source"
6749 * texture with unique values. Fill "destination" texture with zeros,
6750 * - prepare a program object that will read texel from "source" image at given
6751 * coordinates and write its value to "destination" image at same
6752 * coordinates,
6753 * - bind "source" and "destination" textures as "source" and "destination"
6754 * image uniforms,
6755 * - render "full screen" quad (left bottom corner at -1,-1 and right top
6756 * corner at 1,1),
6757 * - verify that texel values in "destination" texture match those in
6758 * "source" texture (use glGetTexImage).
6759 *
6760 * Test with 2D R8UI textures with following dimensions:
6761 * - 16x16,
6762 * - 16x17,
6763 * - 17x16,
6764 * - 17x17,
6765 * - 16x18,
6766 * - 18x16,
6767 * - 18x18,
6768 * - 19x16,
6769 * - 16x19,
6770 * - 19x19.
6771 *
6772 * Note that default data alignment should cause problems with packing/
6773 * /unpacking. Therefore GL_PACK_ALIGNMENT and GL_UNPACK_ALIGNMENT parameters
6774 * of pixel storage mode have to be changed to one byte alignment.
6775 *
6776 * Program should consist of vertex and fragment shader. Vertex shader should
6777 * pass vertex position through. Fragment shader should do imageLoad() and
6778 * imageStore() operations at coordinates gl_FragCoord.
6779 **/
6780 class ImageLoadStoreDataAlignmentTest : public ShaderImageLoadStoreBase
6781 {
6782 private:
6783 /* Structures */
6784 struct TextureDimensions
6785 {
6786 GLuint m_width;
6787 GLuint m_height;
6788
TextureDimensionsgl4cts::__anonb00615420111::ImageLoadStoreDataAlignmentTest::TextureDimensions6789 TextureDimensions(GLuint width, GLuint height) : m_width(width), m_height(height)
6790 {
6791 }
6792 };
6793
6794 /* Typedefs */
6795 typedef std::deque<TextureDimensions> TextureDimensionsList;
6796
6797 /* Fields */
6798 GLuint m_destination_texture_id;
6799 GLuint m_program_id;
6800 TextureDimensionsList m_texture_dimensions;
6801 GLuint m_source_texture_id;
6802 GLuint m_vertex_array_object_id;
6803 GLuint m_vertex_buffer_id;
6804
6805 public:
6806 /* Constructor */
ImageLoadStoreDataAlignmentTest()6807 ImageLoadStoreDataAlignmentTest()
6808 : m_destination_texture_id(0)
6809 , m_program_id(0)
6810 , m_source_texture_id(0)
6811 , m_vertex_array_object_id(0)
6812 , m_vertex_buffer_id(0)
6813 {
6814 /* Nothing to be done here */
6815 }
6816
6817 /* Methods inherited from SubcaseBase */
Setup()6818 virtual long Setup()
6819 {
6820 /* Shaders code */
6821 const char* const vertex_shader_code = "#version 400 core\n"
6822 "#extension GL_ARB_shader_image_load_store : require\n"
6823 "\n"
6824 "precision highp float;\n"
6825 "\n"
6826 "in vec4 vs_in_position;\n"
6827 "\n"
6828 "void main()\n"
6829 "{\n"
6830 " gl_Position = vs_in_position;\n"
6831 "}\n";
6832
6833 const char* const fragment_shader_code =
6834 "#version 400 core\n"
6835 "#extension GL_ARB_shader_image_load_store : require\n"
6836 "\n"
6837 "precision highp float;\n"
6838 "\n"
6839 "layout(r8ui) writeonly uniform uimage2D u_destination_image;\n"
6840 "layout(r8ui) readonly uniform uimage2D u_source_image;\n"
6841 "\n"
6842 "void main()\n"
6843 "{\n"
6844 " uvec4 loaded_color = imageLoad (u_source_image, ivec2(gl_FragCoord));\n"
6845 " imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n"
6846 "\n"
6847 " discard;\n"
6848 "}\n";
6849
6850 /* Vertex postions for "full screen" quad, made with triangle strip */
6851 static const GLfloat m_vertex_buffer_data[] = {
6852 -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
6853 -1.0f, 1.0f, 0.0f, 1.0f, /* left top */
6854 1.0f, -1.0f, 0.0f, 1.0f, /* right bottom */
6855 1.0f, 1.0f, 0.0f, 1.0f, /* right top */
6856 };
6857
6858 /* Result of BuildProgram operation */
6859 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
6860
6861 /* Add all tested texture dimensions */
6862 m_texture_dimensions.push_back(TextureDimensions(16, 16));
6863 m_texture_dimensions.push_back(TextureDimensions(16, 17));
6864 m_texture_dimensions.push_back(TextureDimensions(17, 16));
6865 m_texture_dimensions.push_back(TextureDimensions(17, 17));
6866 m_texture_dimensions.push_back(TextureDimensions(16, 18));
6867 m_texture_dimensions.push_back(TextureDimensions(18, 16));
6868 m_texture_dimensions.push_back(TextureDimensions(18, 18));
6869 m_texture_dimensions.push_back(TextureDimensions(16, 19));
6870 m_texture_dimensions.push_back(TextureDimensions(19, 16));
6871 m_texture_dimensions.push_back(TextureDimensions(19, 19));
6872
6873 /* Clean previous error */
6874 glGetError();
6875
6876 /* Set single-byte data alignment */
6877 glPixelStorei(GL_PACK_ALIGNMENT, 1);
6878 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
6879 GLU_EXPECT_NO_ERROR(glGetError(), "PixelStorei");
6880
6881 /* Prepare buffer with vertex positions of "full screen" quad" */
6882 glGenBuffers(1, &m_vertex_buffer_id);
6883 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
6884
6885 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
6886 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
6887
6888 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
6889 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
6890
6891 /* Generate vertex array object */
6892 glGenVertexArrays(1, &m_vertex_array_object_id);
6893 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
6894
6895 /* Prepare program object */
6896 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */,
6897 fragment_shader_code, &is_program_correct);
6898 if (false == is_program_correct)
6899 {
6900 return ERROR;
6901 }
6902
6903 /* Done */
6904 return NO_ERROR;
6905 }
6906
Cleanup()6907 virtual long Cleanup()
6908 {
6909 /* Reset OpenGL state */
6910 glBindBuffer(GL_ARRAY_BUFFER, 0);
6911 glBindTexture(GL_TEXTURE_2D, 0);
6912 glBindVertexArray(0);
6913 glUseProgram(0);
6914
6915 /* Delete program */
6916 if (0 != m_program_id)
6917 {
6918 glDeleteProgram(m_program_id);
6919 m_program_id = 0;
6920 }
6921
6922 /* Delete textures */
6923 if (0 != m_destination_texture_id)
6924 {
6925 glDeleteTextures(1, &m_destination_texture_id);
6926 m_destination_texture_id = 0;
6927 }
6928
6929 if (0 != m_source_texture_id)
6930 {
6931 glDeleteTextures(1, &m_source_texture_id);
6932 m_source_texture_id = 0;
6933 }
6934
6935 /* Delete vertex array object */
6936 if (0 != m_vertex_array_object_id)
6937 {
6938 glDeleteVertexArrays(1, &m_vertex_array_object_id);
6939 m_vertex_array_object_id = 0;
6940 }
6941
6942 /* Delete buffer */
6943 if (0 != m_vertex_buffer_id)
6944 {
6945 glDeleteBuffers(1, &m_vertex_buffer_id);
6946 m_vertex_buffer_id = 0;
6947 }
6948
6949 /* Done */
6950 return NO_ERROR;
6951 }
6952
Run()6953 virtual long Run()
6954 {
6955 bool result = true;
6956
6957 /* For each dimension */
6958 for (TextureDimensionsList::const_iterator it = m_texture_dimensions.begin(); m_texture_dimensions.end() != it;
6959 ++it)
6960 {
6961 /* Prepare "source" and "destination" textures */
6962 GLU_EXPECT_NO_ERROR(Create2DR8UIDestinationTexture(it->m_width, it->m_height, m_destination_texture_id),
6963 "Create2DR8UIDestinationTexture");
6964 GLU_EXPECT_NO_ERROR(Create2DR8UISourceTexture(it->m_width, it->m_height, m_source_texture_id),
6965 "Create2DR8UISourceTexture");
6966
6967 /* Copy texture data with imageLoad() and imageStore() operations */
6968 Copy2DR8UITexture(m_destination_texture_id, m_source_texture_id);
6969
6970 /* Compare "source" and "destination" textures */
6971 if (false ==
6972 Compare2DR8UITextures(m_destination_texture_id, m_source_texture_id, it->m_width, it->m_height))
6973 {
6974 m_context.getTestContext().getLog()
6975 << tcu::TestLog::Message
6976 << "Copy with imageLoad and imageStore failed for textures: " << it->m_width << "x" << it->m_height
6977 << ". Source and destination textures are different" << tcu::TestLog::EndMessage;
6978
6979 result = false;
6980 }
6981
6982 /* Destroy "source" and "destination" textures */
6983 glDeleteTextures(1, &m_destination_texture_id);
6984 glDeleteTextures(1, &m_source_texture_id);
6985
6986 m_destination_texture_id = 0;
6987 m_source_texture_id = 0;
6988 }
6989
6990 if (false == result)
6991 {
6992 return ERROR;
6993 }
6994
6995 /* Done */
6996 return NO_ERROR;
6997 }
6998
6999 private:
7000 /* Private methods */
7001
7002 /** Binds a texture to user-specified image unit and updates relevant sampler uniform
7003 *
7004 * @param program_id Program object id
7005 * @param texture_id Texture id
7006 * @param image_unit Index of image unit
7007 * @param uniform_name Name of image uniform
7008 **/
BindTextureToImage(GLuint program_id,GLuint texture_id,GLuint image_unit,const char * uniform_name)7009 void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, const char* uniform_name)
7010 {
7011 /* Uniform location and invalid value */
7012 static const GLint invalid_uniform_location = -1;
7013 GLint image_uniform_location = 0;
7014
7015 /* Get uniform location */
7016 image_uniform_location = glGetUniformLocation(program_id, uniform_name);
7017 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
7018 if (invalid_uniform_location == image_uniform_location)
7019 {
7020 throw tcu::InternalError("A required uniform is considered inactive", uniform_name, __FILE__, __LINE__);
7021 }
7022
7023 /* Bind texture to image unit */
7024 glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_R8UI);
7025 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
7026
7027 /* Set uniform to image unit */
7028 glUniform1i(image_uniform_location, image_unit);
7029 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
7030 }
7031
7032 /** Compare two 2D R8UI textures
7033 *
7034 * @param left_texture_id Id of "left" texture object
7035 * @param right_texture_id Id of "right" texture object
7036 * @param width Width of the textures
7037 * @param height Height of the textures
7038 *
7039 * @return true when texture data is identical, false otherwise
7040 **/
Compare2DR8UITextures(GLuint left_texture_id,GLuint right_texture_id,GLuint width,GLuint height)7041 bool Compare2DR8UITextures(GLuint left_texture_id, GLuint right_texture_id, GLuint width, GLuint height)
7042 {
7043 /* Size of textures */
7044 const GLuint texture_data_size = width * height;
7045
7046 /* Storage for texture data */
7047 std::vector<GLubyte> left_texture_data;
7048 std::vector<GLubyte> right_texture_data;
7049
7050 /* Alocate memory for texture data */
7051 left_texture_data.resize(texture_data_size);
7052 right_texture_data.resize(texture_data_size);
7053
7054 /* Get "left" texture data */
7055 glBindTexture(GL_TEXTURE_2D, left_texture_id);
7056 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7057
7058 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &left_texture_data[0]);
7059 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7060
7061 /* Get "right" texture data */
7062 glBindTexture(GL_TEXTURE_2D, right_texture_id);
7063 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7064
7065 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &right_texture_data[0]);
7066 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7067
7068 /* Compare texels */
7069 return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size));
7070 }
7071
7072 /** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations
7073 *
7074 * @param destination_texture_id Id of "destination" texture object
7075 * @param source_texture_id Id of "source" texture object
7076 **/
Copy2DR8UITexture(GLuint destination_texture_id,GLuint source_texture_id)7077 void Copy2DR8UITexture(GLuint destination_texture_id, GLuint source_texture_id)
7078 {
7079 /* Uniform names */
7080 static const char* const destination_image_uniform_name = "u_destination_image";
7081 static const char* const source_image_uniform_name = "u_source_image";
7082
7083 /* Attribute name */
7084 static const char* const position_attribute_name = "vs_in_position";
7085
7086 /* Attribute location and invalid value */
7087 static const GLint invalid_attribute_location = -1;
7088 GLint position_attribute_location = 0;
7089
7090 /* Set current program */
7091 glUseProgram(m_program_id);
7092 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
7093
7094 /* Bind vertex array object */
7095 glBindVertexArray(m_vertex_array_object_id);
7096 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
7097
7098 /* Bind buffer with quad vertex positions */
7099 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7100 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7101
7102 /* Set up position attribute */
7103 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
7104 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
7105 if (invalid_attribute_location == position_attribute_location)
7106 {
7107 throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
7108 __LINE__);
7109 }
7110
7111 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */,
7112 0 /* stride */, 0);
7113 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
7114
7115 glEnableVertexAttribArray(position_attribute_location);
7116 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
7117
7118 /* Set up textures as source and destination images */
7119 BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, destination_image_uniform_name);
7120 BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, source_image_uniform_name);
7121
7122 /* Execute draw */
7123 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
7124 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
7125 }
7126
7127 /** Create 2D R8UI texture and fills it with zeros
7128 *
7129 * @param width Width of created texture
7130 * @param height Height of created texture
7131 * @param out_texture_id Id of created texture, not modified if operation fails
7132 *
7133 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7134 **/
Create2DR8UIDestinationTexture(GLuint width,GLuint height,GLuint & out_texture_id)7135 GLenum Create2DR8UIDestinationTexture(GLuint width, GLuint height, GLuint& out_texture_id)
7136 {
7137 /* Texture size */
7138 const GLuint texture_size = width * height;
7139
7140 /* Prepare storage for texture data */
7141 std::vector<GLubyte> texture_data;
7142 texture_data.resize(texture_size);
7143
7144 /* Set all texels */
7145 for (GLuint i = 0; i < texture_size; ++i)
7146 {
7147 texture_data[i] = 0;
7148 }
7149
7150 /* Create texture */
7151 return Create2DR8UITexture(width, height, texture_data, out_texture_id);
7152 }
7153
7154 /** Create 2D R8UI texture and fills it with increasing values, starting from 0
7155 *
7156 * @param width Width of created texture
7157 * @param height Height of created texture
7158 * @param out_texture_id Id of created texture, not modified if operation fails
7159 *
7160 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7161 **/
Create2DR8UISourceTexture(GLuint width,GLuint height,GLuint & out_texture_id)7162 GLenum Create2DR8UISourceTexture(GLuint width, GLuint height, GLuint& out_texture_id)
7163 {
7164 /* Texture size */
7165 const GLuint texture_size = width * height;
7166
7167 /* Value of texel */
7168 GLubyte texel_value = 0;
7169
7170 /* Prepare storage for texture data */
7171 std::vector<GLubyte> texture_data;
7172 texture_data.resize(texture_size);
7173
7174 /* Set all texels */
7175 for (GLuint i = 0; i < texture_size; ++i)
7176 {
7177 texture_data[i] = texel_value++;
7178 }
7179
7180 /* Create texture */
7181 return Create2DR8UITexture(width, height, texture_data, out_texture_id);
7182 }
7183
7184 /** Create 2D R8UI texture and fills it with user-provided data
7185 *
7186 * @param width Width of created texture
7187 * @param height Height of created texture
7188 * @param texture_data Texture data
7189 * @param out_texture_id Id of created texture, not modified if operation fails
7190 *
7191 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7192 **/
Create2DR8UITexture(GLuint width,GLuint height,const std::vector<GLubyte> & texture_data,GLuint & out_texture_id)7193 GLenum Create2DR8UITexture(GLuint width, GLuint height, const std::vector<GLubyte>& texture_data,
7194 GLuint& out_texture_id)
7195 {
7196 GLenum err = 0;
7197 GLuint texture_id = 0;
7198
7199 /* Generate texture */
7200 glGenTextures(1, &texture_id);
7201 err = glGetError();
7202 if (GL_NO_ERROR != err)
7203 {
7204 return err;
7205 }
7206
7207 /* Bind texture */
7208 glBindTexture(GL_TEXTURE_2D, texture_id);
7209 err = glGetError();
7210 if (GL_NO_ERROR != err)
7211 {
7212 glDeleteTextures(1, &texture_id);
7213 return err;
7214 }
7215
7216 /* Allocate storage and fill texture */
7217 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R8UI, width, height, 0 /* border */, GL_RED_INTEGER,
7218 GL_UNSIGNED_BYTE, &texture_data[0]);
7219 err = glGetError();
7220 if (GL_NO_ERROR != err)
7221 {
7222 glDeleteTextures(1, &texture_id);
7223 return err;
7224 }
7225
7226 /* Make texture complete */
7227 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
7228 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
7229 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7230 err = glGetError();
7231 if (GL_NO_ERROR != err)
7232 {
7233 glDeleteTextures(1, &texture_id);
7234 return err;
7235 }
7236
7237 /* Set out_texture_id */
7238 out_texture_id = texture_id;
7239
7240 /* Done */
7241 return GL_NO_ERROR;
7242 }
7243 };
7244
7245 /** Test "imageLoad() and imageStore() for non-layered image bindings" description follows.
7246 *
7247 * Steps: same as in test 1 (ImageLoadStoreDataAlignmentTest).
7248 *
7249 * Test non-layered image bindings (BindImageTexture <layered>: false) with:
7250 * | Type | Dimensions |
7251 * | 2D_ARRAY | 64x64x6 |
7252 * | 3D | 64x64x6 |
7253 * | CUBE_MAP | 64 |
7254 * | CUBE_MAP_ARRAY | 64x3 |
7255 *
7256 * Use RGBA8 format. All layers shall be tested.
7257 *
7258 * Program should consist of vertex and fragment shader. Vertex shader should
7259 * pass vertex position through. Fragment shader should do imageLoad() and
7260 * imageStore() operations at coordinates gl_FragCoord. Fragment shader should
7261 * use image2D as image type.
7262 **/
7263 class ImageLoadStoreNonLayeredBindingTest : public ShaderImageLoadStoreBase
7264 {
7265 private:
7266 /* Structures */
7267 struct TextureShapeDefinition
7268 {
7269 GLuint m_edge;
7270 GLuint m_n_elements;
7271 GLenum m_type;
7272
TextureShapeDefinitiongl4cts::__anonb00615420111::ImageLoadStoreNonLayeredBindingTest::TextureShapeDefinition7273 TextureShapeDefinition(GLuint edge, GLuint n_elements, GLenum type)
7274 : m_edge(edge), m_n_elements(n_elements), m_type(type)
7275 {
7276 }
7277 };
7278
7279 /* Typedefs */
7280 typedef std::deque<TextureShapeDefinition> TextureShapeDefinitionList;
7281
7282 /* Fields */
7283 GLuint m_destination_texture_id;
7284 GLuint m_program_id;
7285 TextureShapeDefinitionList m_texture_shape_definitions;
7286 GLuint m_source_texture_id;
7287 GLuint m_vertex_array_object_id;
7288 GLuint m_vertex_buffer_id;
7289
7290 public:
7291 /* Constructor */
ImageLoadStoreNonLayeredBindingTest()7292 ImageLoadStoreNonLayeredBindingTest()
7293 : m_destination_texture_id(0)
7294 , m_program_id(0)
7295 , m_source_texture_id(0)
7296 , m_vertex_array_object_id(0)
7297 , m_vertex_buffer_id(0)
7298 {
7299 /* Nothing to be done here */
7300 }
7301
7302 /* Methods inherited from SubcaseBase */
Setup()7303 virtual long Setup()
7304 {
7305 /* Shaders code */
7306 const char* const vertex_shader_code = "#version 400 core\n"
7307 "#extension GL_ARB_shader_image_load_store : require\n"
7308 "\n"
7309 "precision highp float;\n"
7310 "\n"
7311 "in vec4 vs_in_position;\n"
7312 "\n"
7313 "void main()\n"
7314 "{\n"
7315 " gl_Position = vs_in_position;\n"
7316 "}\n";
7317
7318 const char* const fragment_shader_code =
7319 "#version 400 core\n"
7320 "#extension GL_ARB_shader_image_load_store : require\n"
7321 "\n"
7322 "precision highp float;\n"
7323 "\n"
7324 "layout(rgba8) writeonly uniform image2D u_destination_image;\n"
7325 "layout(rgba8) readonly uniform image2D u_source_image;\n"
7326 "\n"
7327 "void main()\n"
7328 "{\n"
7329 " vec4 loaded_color = imageLoad (u_source_image, ivec2(gl_FragCoord));\n"
7330 " imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n"
7331 "\n"
7332 " discard;\n"
7333 "}\n";
7334
7335 /* Vertex postions for "full screen" quad, defined as a triangle strip */
7336 static const GLfloat m_vertex_buffer_data[] = {
7337 -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
7338 -1.0f, 1.0f, 0.0f, 1.0f, /* left top */
7339 1.0f, -1.0f, 0.0f, 1.0f, /* right bottom */
7340 1.0f, 1.0f, 0.0f, 1.0f, /* right top */
7341 };
7342
7343 /* Result of BuildProgram operation */
7344 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
7345
7346 /* Add all tested texture shapes */
7347 int texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
7348 m_texture_shape_definitions.push_back(
7349 TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_2D_ARRAY));
7350 m_texture_shape_definitions.push_back(
7351 TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_3D));
7352 m_texture_shape_definitions.push_back(
7353 TextureShapeDefinition(texture_edge /* edge */, 1 /* n_elements */, GL_TEXTURE_CUBE_MAP));
7354 m_texture_shape_definitions.push_back(
7355 TextureShapeDefinition(texture_edge /* edge */, 3 /* n_elements */, GL_TEXTURE_CUBE_MAP_ARRAY));
7356
7357 /* Prepare buffer with vertex positions of "full screen" quad" */
7358 glGenBuffers(1, &m_vertex_buffer_id);
7359 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
7360
7361 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7362 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7363
7364 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
7365 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
7366
7367 /* Generate vertex array object */
7368 glGenVertexArrays(1, &m_vertex_array_object_id);
7369 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
7370
7371 /* Prepare program object */
7372 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /* src_gs */,
7373 fragment_shader_code, &is_program_correct);
7374 if (false == is_program_correct)
7375 {
7376 return ERROR;
7377 }
7378
7379 /* Done */
7380 return NO_ERROR;
7381 }
7382
Cleanup()7383 virtual long Cleanup()
7384 {
7385 /* Reset OpenGL state */
7386 glBindBuffer(GL_ARRAY_BUFFER, 0);
7387 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
7388 glBindTexture(GL_TEXTURE_3D, 0);
7389 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
7390 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
7391 glBindVertexArray(0);
7392 glUseProgram(0);
7393
7394 /* Delete program */
7395 if (0 != m_program_id)
7396 {
7397 glDeleteProgram(m_program_id);
7398 m_program_id = 0;
7399 }
7400
7401 /* Delete textures */
7402 if (0 != m_destination_texture_id)
7403 {
7404 glDeleteTextures(1, &m_destination_texture_id);
7405 m_destination_texture_id = 0;
7406 }
7407
7408 if (0 != m_source_texture_id)
7409 {
7410 glDeleteTextures(1, &m_source_texture_id);
7411 m_source_texture_id = 0;
7412 }
7413
7414 /* Delete vertex array object */
7415 if (0 != m_vertex_array_object_id)
7416 {
7417 glDeleteVertexArrays(1, &m_vertex_array_object_id);
7418 m_vertex_array_object_id = 0;
7419 }
7420
7421 /* Delete buffer */
7422 if (0 != m_vertex_buffer_id)
7423 {
7424 glDeleteBuffers(1, &m_vertex_buffer_id);
7425 m_vertex_buffer_id = 0;
7426 }
7427
7428 /* Done */
7429 return NO_ERROR;
7430 }
7431
Run()7432 virtual long Run()
7433 {
7434 bool result = true;
7435
7436 /* For each shape */
7437 for (TextureShapeDefinitionList::const_iterator it = m_texture_shape_definitions.begin();
7438 m_texture_shape_definitions.end() != it; ++it)
7439 {
7440 const GLuint n_layers = GetTotalNumberOfLayers(it->m_n_elements, it->m_type);
7441
7442 /* Prepare "source" and "destination" textures */
7443 GLU_EXPECT_NO_ERROR(
7444 CreateRGBA8DestinationTexture(it->m_edge, it->m_n_elements, it->m_type, m_destination_texture_id),
7445 "Create2DR8UIDestinationTexture");
7446 GLU_EXPECT_NO_ERROR(CreateRGBA8SourceTexture(it->m_edge, it->m_n_elements, it->m_type, m_source_texture_id),
7447 "Create2DR8UISourceTexture");
7448
7449 /* Copy texture data with imageLoad() and imageStore() operations */
7450 CopyRGBA8Texture(m_destination_texture_id, m_source_texture_id, n_layers);
7451
7452 /* Compare "source" and "destination" textures */
7453 if (false ==
7454 CompareRGBA8Textures(m_destination_texture_id, m_source_texture_id, it->m_edge, n_layers, it->m_type))
7455 {
7456 const char* texture_type = "";
7457 switch (it->m_type)
7458 {
7459 case GL_TEXTURE_2D_ARRAY:
7460 texture_type = "2d array";
7461 break;
7462 case GL_TEXTURE_3D:
7463 texture_type = "3d";
7464 break;
7465 case GL_TEXTURE_CUBE_MAP:
7466 texture_type = "Cube map";
7467 break;
7468 case GL_TEXTURE_CUBE_MAP_ARRAY:
7469 texture_type = "Cube map array";
7470 break;
7471 }
7472
7473 m_context.getTestContext().getLog()
7474 << tcu::TestLog::Message
7475 << "Copy with imageLoad and imageStore failed for texture type: " << texture_type
7476 << ". Source and destination textures are different" << tcu::TestLog::EndMessage;
7477
7478 result = false;
7479 }
7480
7481 /* Destroy "source" and "destination" textures */
7482 glDeleteTextures(1, &m_destination_texture_id);
7483 glDeleteTextures(1, &m_source_texture_id);
7484
7485 m_destination_texture_id = 0;
7486 m_source_texture_id = 0;
7487 }
7488
7489 if (false == result)
7490 {
7491 return ERROR;
7492 }
7493
7494 /* Done */
7495 return NO_ERROR;
7496 }
7497
7498 private:
7499 /* Private methods */
7500
7501 /** Binds a texture to user-specified image unit and update relevant sampler uniform
7502 *
7503 * @param program_id Program object id
7504 * @param texture_id Texture id
7505 * @param image_unit Index of image unit
7506 * @param layer Index of layer bound to unit
7507 * @param uniform_name Name of image uniform
7508 **/
BindTextureToImage(GLuint program_id,GLuint texture_id,GLuint image_unit,GLuint layer,const char * uniform_name)7509 void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, GLuint layer,
7510 const char* uniform_name)
7511 {
7512 static const GLint invalid_uniform_location = -1;
7513 GLint image_uniform_location = 0;
7514
7515 /* Get uniform location */
7516 image_uniform_location = glGetUniformLocation(program_id, uniform_name);
7517 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
7518 if (invalid_uniform_location == image_uniform_location)
7519 {
7520 throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__);
7521 }
7522
7523 /* Bind texture to image unit */
7524 glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE /* layered */, layer, GL_READ_WRITE,
7525 GL_RGBA8);
7526 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
7527
7528 /* Set uniform to image unit */
7529 glUniform1i(image_uniform_location, image_unit);
7530 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
7531 }
7532
7533 /** Compare two 2D R8UI textures
7534 *
7535 * @param left_texture_id Id of "left" texture object
7536 * @param right_texture_id Id of "right" texture object
7537 * @param edge Length of texture edge
7538 * @param n_layers Number of layers to compare
7539 * @param type Type of texture
7540 *
7541 * @return true when texture data is found identical, false otherwise
7542 **/
CompareRGBA8Textures(GLuint left_texture_id,GLuint right_texture_id,GLuint edge,GLuint n_layers,GLenum type)7543 bool CompareRGBA8Textures(GLuint left_texture_id, GLuint right_texture_id, GLuint edge, GLuint n_layers,
7544 GLenum type)
7545 {
7546 static const GLuint n_components = 4; /* RGBA */
7547 const GLuint texture_data_size = edge * edge * n_layers * n_components;
7548
7549 /* Storage for texture data */
7550 std::vector<GLubyte> left_texture_data;
7551 std::vector<GLubyte> right_texture_data;
7552
7553 ExtractTextureData(left_texture_id, edge, n_layers, type, left_texture_data);
7554 ExtractTextureData(right_texture_id, edge, n_layers, type, right_texture_data);
7555
7556 /* Compare texels */
7557 return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size));
7558 }
7559
7560 /** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations
7561 *
7562 * @param destination_texture_id Id of "destination" texture object
7563 * @param source_texture_id Id of "source" texture object
7564 * @param n_layers Number of layers
7565 **/
CopyRGBA8Texture(GLuint destination_texture_id,GLuint source_texture_id,GLuint n_layers)7566 void CopyRGBA8Texture(GLuint destination_texture_id, GLuint source_texture_id, GLuint n_layers)
7567 {
7568 for (GLuint layer = 0; layer < n_layers; ++layer)
7569 {
7570 CopyRGBA8TextureLayer(destination_texture_id, source_texture_id, layer);
7571 }
7572 }
7573
7574 /** Copy contents of layer from "source" texture to "destination" texture with imageLoad() and imageStore() operations
7575 *
7576 * @param destination_texture_id Id of "destination" texture object
7577 * @param source_texture_id Id of "source" texture object
7578 * @param layer Index of layer
7579 **/
CopyRGBA8TextureLayer(GLuint destination_texture_id,GLuint source_texture_id,GLuint layer)7580 void CopyRGBA8TextureLayer(GLuint destination_texture_id, GLuint source_texture_id, GLuint layer)
7581 {
7582 /* Uniform names */
7583 static const char* const destination_image_uniform_name = "u_destination_image";
7584 static const char* const source_image_uniform_name = "u_source_image";
7585
7586 /* Attribute name */
7587 static const char* const position_attribute_name = "vs_in_position";
7588
7589 /* Attribute location and invalid value */
7590 static const GLint invalid_attribute_location = -1;
7591 GLint position_attribute_location = 0;
7592
7593 /* Set current program */
7594 glUseProgram(m_program_id);
7595 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
7596
7597 /* Bind vertex array object */
7598 glBindVertexArray(m_vertex_array_object_id);
7599 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
7600
7601 /* Bind buffer with quad vertex positions */
7602 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7603 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7604
7605 /* Set up vertex attribute array for position attribute */
7606 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
7607 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
7608 if (invalid_attribute_location == position_attribute_location)
7609 {
7610 throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
7611 __LINE__);
7612 }
7613
7614 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */,
7615 0 /* stride */, 0 /* pointer */);
7616 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
7617
7618 glEnableVertexAttribArray(position_attribute_location);
7619 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
7620
7621 /* Set up textures as source and destination image samplers */
7622 BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, layer,
7623 destination_image_uniform_name);
7624 BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, layer, source_image_uniform_name);
7625
7626 /* Execute draw */
7627 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
7628 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
7629 }
7630
7631 /** Creates RGBA8 texture of given type and fills it with zeros
7632 *
7633 * @param edge Edge of created texture
7634 * @param n_elements Number of elements in texture array
7635 * @param target Target of created texture
7636 * @param out_texture_id Id of created texture, not modified if operation fails
7637 *
7638 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7639 **/
CreateRGBA8DestinationTexture(GLuint edge,GLuint n_elements,GLenum target,GLuint & out_texture_id)7640 GLenum CreateRGBA8DestinationTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint& out_texture_id)
7641 {
7642 /* Constasts to calculate texture size */
7643 static const GLuint n_components = 4; /* RGBA */
7644 const GLuint layer_size = edge * edge * n_components;
7645 const GLuint n_layers = GetTotalNumberOfLayers(n_elements, target);
7646 const GLuint texture_size = layer_size * n_layers;
7647
7648 /* Prepare storage for texture data */
7649 std::vector<GLubyte> texture_data;
7650 texture_data.resize(texture_size);
7651
7652 /* Set all texels */
7653 for (GLuint i = 0; i < texture_size; ++i)
7654 {
7655 texture_data[i] = 0;
7656 }
7657
7658 /* Create texture */
7659 return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id);
7660 }
7661
7662 /** Creates RGBA8 texture and fills it with [x, y, layer, 0xaa]
7663 *
7664 * @param edge Edge of created texture
7665 * @param n_elements Number of elements in texture array
7666 * @param target Target of created texture
7667 * @param out_texture_id Id of created texture, not modified if operation fails
7668 *
7669 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7670 **/
CreateRGBA8SourceTexture(GLuint edge,GLuint n_elements,GLenum target,GLuint & out_texture_id)7671 GLenum CreateRGBA8SourceTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint& out_texture_id)
7672 {
7673 /* Constants to calculate texture size */
7674 static const GLuint n_components = 4; /* RGBA */
7675 const GLuint layer_size = edge * edge * n_components;
7676 const GLuint n_layers = GetTotalNumberOfLayers(n_elements, target);
7677 const GLuint texture_size = layer_size * n_layers;
7678
7679 /* Value of texel */
7680 GLubyte texel[4] = { 0, 0, 0, 0xaa };
7681
7682 /* Prepare storage for texture data */
7683 std::vector<GLubyte> texture_data;
7684 texture_data.resize(texture_size);
7685
7686 /* Set all texels */
7687 for (GLuint layer = 0; layer < n_layers; ++layer)
7688 {
7689 const GLuint layer_offset = layer_size * layer;
7690
7691 texel[2] = static_cast<GLubyte>(layer);
7692
7693 for (GLuint y = 0; y < edge; ++y)
7694 {
7695 const GLuint line_offset = y * edge * n_components + layer_offset;
7696
7697 texel[1] = static_cast<GLubyte>(y);
7698
7699 for (GLuint x = 0; x < edge; ++x)
7700 {
7701 const GLuint texel_offset = x * n_components + line_offset;
7702 texel[0] = static_cast<GLubyte>(x);
7703
7704 for (GLuint component = 0; component < n_components; ++component)
7705 {
7706 texture_data[texel_offset + component] = texel[component];
7707 }
7708 }
7709 }
7710 }
7711
7712 /* Create texture */
7713 return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id);
7714 }
7715
7716 /** Creates RGBA8 texture of given type and fills it provided data
7717 *
7718 * @param edge Edge of created texture
7719 * @param n_elements Number of elements in texture array
7720 * @param target Target of created texture
7721 * @param texture_data Texture data
7722 * @param out_texture_id Id of created texture, not modified if operation fails
7723 *
7724 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7725 **/
CreateRGBA8Texture(GLuint edge,GLenum target,GLuint n_layers,const std::vector<GLubyte> & texture_data,GLuint & out_texture_id)7726 GLenum CreateRGBA8Texture(GLuint edge, GLenum target, GLuint n_layers, const std::vector<GLubyte>& texture_data,
7727 GLuint& out_texture_id)
7728 {
7729 GLenum err = 0;
7730 GLuint texture_id = 0;
7731
7732 /* Generate texture */
7733 glGenTextures(1, &texture_id);
7734 err = glGetError();
7735 if (GL_NO_ERROR != err)
7736 {
7737 return err;
7738 }
7739
7740 /* Bind texture */
7741 glBindTexture(target, texture_id);
7742 err = glGetError();
7743 if (GL_NO_ERROR != err)
7744 {
7745 glDeleteTextures(1, &texture_id);
7746 return err;
7747 }
7748
7749 /* Allocate storage and fill texture */
7750 if (GL_TEXTURE_CUBE_MAP != target)
7751 {
7752 glTexImage3D(target, 0 /* level */, GL_RGBA8, edge, edge, n_layers, 0 /* border */, GL_RGBA,
7753 GL_UNSIGNED_BYTE, &texture_data[0]);
7754 }
7755 else
7756 {
7757 const GLuint n_components = 4;
7758 const GLuint layer_size = edge * edge * n_components;
7759
7760 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7761 GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]);
7762 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7763 GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]);
7764 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7765 GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]);
7766 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7767 GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]);
7768 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7769 GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]);
7770 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7771 GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]);
7772 }
7773 err = glGetError();
7774 if (GL_NO_ERROR != err)
7775 {
7776 glDeleteTextures(1, &texture_id);
7777 return err;
7778 }
7779
7780 /* Make texture complete */
7781 glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0);
7782 glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 0);
7783 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7784 err = glGetError();
7785 if (GL_NO_ERROR != err)
7786 {
7787 glDeleteTextures(1, &texture_id);
7788 return err;
7789 }
7790
7791 /* Set out_texture_id */
7792 out_texture_id = texture_id;
7793
7794 /* Done */
7795 return GL_NO_ERROR;
7796 }
7797
7798 /** Extracts texture data
7799 *
7800 * @param texture_id Id of texture object
7801 * @param edge Length of texture edge
7802 * @param n_layers Number of layers
7803 * @param target Target of texture
7804 * @param texture_data Extracted texture data
7805 **/
ExtractTextureData(GLuint texture_id,GLuint edge,GLuint n_layers,GLenum target,std::vector<GLubyte> & texture_data)7806 void ExtractTextureData(GLuint texture_id, GLuint edge, GLuint n_layers, GLenum target,
7807 std::vector<GLubyte>& texture_data)
7808 {
7809 static const GLuint n_components = 4; /* RGBA */
7810 const GLuint texture_data_size = edge * edge * n_layers * n_components;
7811
7812 /* Alocate memory for texture data */
7813 texture_data.resize(texture_data_size);
7814
7815 /* Bind texture */
7816 glBindTexture(target, texture_id);
7817 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7818
7819 /* Get data */
7820 if (GL_TEXTURE_CUBE_MAP != target)
7821 {
7822 glGetTexImage(target, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
7823 }
7824 else
7825 {
7826 const GLuint layer_size = edge * edge * n_components;
7827
7828 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]);
7829 glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]);
7830 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]);
7831 glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]);
7832 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]);
7833 glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]);
7834 }
7835
7836 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7837 }
7838
7839 /** Get number of layers per single element for given type of texture
7840 *
7841 * @param target Target of texture
7842 *
7843 * @return Number of layers
7844 **/
GetLayersPerElement(GLenum target)7845 GLuint GetLayersPerElement(GLenum target)
7846 {
7847 switch (target)
7848 {
7849 case GL_TEXTURE_2D_ARRAY:
7850 case GL_TEXTURE_3D:
7851 return 1;
7852 break;
7853 case GL_TEXTURE_CUBE_MAP:
7854 case GL_TEXTURE_CUBE_MAP_ARRAY:
7855 return 6;
7856 break;
7857 default:
7858 throw tcu::InternalError("Not supported texture type", "", __FILE__, __LINE__);
7859 break;
7860 }
7861 }
7862
7863 /** Get total number of layers in texture of given type and number of array elements
7864 *
7865 * @param n_elements Number of elements in texture array
7866 * @param target Target of texture
7867 *
7868 * @return Number of layers
7869 **/
GetTotalNumberOfLayers(GLuint n_elements,GLenum target)7870 GLuint GetTotalNumberOfLayers(GLuint n_elements, GLenum target)
7871 {
7872 return GetLayersPerElement(target) * n_elements;
7873 }
7874 };
7875
7876 /** Test "imageLoad() and imageStore() for incomplete textures" description follows.
7877 *
7878 * Load from incomplete textures should return 0.
7879 * Store to incomplete textures should be ignored.
7880 *
7881 * Steps:
7882 * - create two incomplete textures: "incomplete_source" and
7883 * "incomplete_destination",
7884 * - create two complete textures: "complete_source" and
7885 * "complete_destination",
7886 * - fill all textures with unique values,
7887 * - prepare program that will:
7888 * * load texel from "incomplete_source" and store its value to
7889 * "complete_destination",
7890 * * load texel from "complete_source" and store its value to
7891 * "incomplete_destination".
7892 * - bind textures to corresponding image uniforms
7893 * - execute program for all texels,
7894 * - verify that "incomplete_destination" was not modified and
7895 * "complete_destination" is filled with zeros.
7896 *
7897 * Texture is considered incomplete when it has enabled mipmaping (see below)
7898 * and does not have all mipmap levels defined. But for the case of Image
7899 * accessing, it is considered invalid if it is mipmap-incomplete and the
7900 * level is different to the base level (base-incomplete).
7901 *
7902 * Creation of incomplete texture:
7903 * - generate and bind texture object id,
7904 * - call TexImage2D with <level>: 0,
7905 * - set GL_TEXTURE_MIN_FILTER? parameter to GL_NEAREST_MIPMAP_LINEAR, (to make
7906 * sure, it should be initial value),
7907 * - set GL_TEXTURE_BASE_LEVEL parameter to 0.
7908 * - set GL_TEXTURE_MAX_LEVEL parameter, for 64x64 set 7 (log2(min(width,
7909 * height)).
7910 *
7911 * Creation of complete texture:
7912 * - generate and bind texture object id,
7913 * - call TexImage2D with <level>: 0,
7914 * - set GL_TEXTURE_BASE_LEVEL parameter to 0.
7915 * - set GL_TEXTURE_MAX_LEVEL parameter to 0.
7916 *
7917 * Binding:
7918 * - Set level == base_level for complete destinations.
7919 * - Set level != base_level for incomplete destinations that are using
7920 * mipmap-incomplete textures.
7921 *
7922 * Test with 2D 64x64 RGBA8 textures.
7923 *
7924 * Program should consist of vertex and fragment shader. Vertex shader should
7925 * pass vertex position through. Fragment shader should do imageLoad() and
7926 * imageStore() operations at coordinates gl_FragCoord.
7927 **/
7928 class ImageLoadStoreIncompleteTexturesTest : public ShaderImageLoadStoreBase
7929 {
7930 private:
7931 /* Constants */
7932 /* Magic numbers that will identify textures, which will be used as their
7933 * texel value.
7934 */
7935 static const GLubyte m_complete_destination_magic_number = 0x11;
7936 static const GLubyte m_complete_source_magic_number = 0x22;
7937 static const GLubyte m_incomplete_destination_magic_number = 0x33;
7938 static const GLubyte m_incomplete_source_magic_number = 0x44;
7939
7940 /* Texture edge */
7941 GLuint m_texture_edge;
7942
7943 /* Fields */
7944 GLuint m_complete_destination_texture_id;
7945 GLuint m_complete_source_texture_id;
7946 GLuint m_incomplete_destination_texture_id;
7947 GLuint m_incomplete_source_texture_id;
7948 GLuint m_program_id;
7949 GLuint m_vertex_array_object_id;
7950 GLuint m_vertex_buffer_id;
7951
7952 public:
7953 /* Constructor */
ImageLoadStoreIncompleteTexturesTest()7954 ImageLoadStoreIncompleteTexturesTest()
7955 : m_texture_edge(0)
7956 , m_complete_destination_texture_id(0)
7957 , m_complete_source_texture_id(0)
7958 , m_incomplete_destination_texture_id(0)
7959 , m_incomplete_source_texture_id(0)
7960 , m_program_id(0)
7961 , m_vertex_array_object_id(0)
7962 , m_vertex_buffer_id(0)
7963 {
7964 /* Nothing to be done here */
7965 }
7966
7967 /* Methods inherited from SubcaseBase */
Setup()7968 virtual long Setup()
7969 {
7970 /* Shaders code */
7971 const char* const vertex_shader_code = "#version 400 core\n"
7972 "#extension GL_ARB_shader_image_load_store : require\n"
7973 "\n"
7974 "precision highp float;\n"
7975 "\n"
7976 "in vec4 vs_in_position;\n"
7977 "\n"
7978 "void main()\n"
7979 "{\n"
7980 " gl_Position = vs_in_position;\n"
7981 "}\n";
7982
7983 const char* const fragment_shader_code =
7984 "#version 400 core\n"
7985 "#extension GL_ARB_shader_image_load_store : require\n"
7986 "\n"
7987 "precision highp float;\n"
7988 "\n"
7989 "layout(rgba8) writeonly uniform image2D u_complete_destination_image;\n"
7990 "layout(rgba8) readonly uniform image2D u_complete_source_image;\n"
7991 "layout(rgba8) writeonly uniform image2D u_incomplete_destination_image;\n"
7992 "layout(rgba8) readonly uniform image2D u_incomplete_source_image;\n"
7993 "\n"
7994 "void main()\n"
7995 "{\n"
7996 " vec4 complete_loaded_color = imageLoad (u_complete_source_image, ivec2(gl_FragCoord));\n"
7997 " vec4 incomplete_loaded_color = imageLoad (u_incomplete_source_image, ivec2(gl_FragCoord));\n"
7998
7999 " imageStore(u_complete_destination_image,\n"
8000 " ivec2(gl_FragCoord),\n"
8001 " incomplete_loaded_color);\n"
8002 " imageStore(u_incomplete_destination_image,\n"
8003 " ivec2(gl_FragCoord),\n"
8004 " complete_loaded_color);\n"
8005 "\n"
8006 " discard;\n"
8007 "}\n";
8008
8009 /* Vertex postions for "full screen" quad, made with triangle strip */
8010 static const GLfloat m_vertex_buffer_data[] = {
8011 -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
8012 -1.0f, 1.0f, 0.0f, 1.0f, /* left top */
8013 1.0f, -1.0f, 0.0f, 1.0f, /* right bottom */
8014 1.0f, 1.0f, 0.0f, 1.0f, /* right top */
8015 };
8016
8017 /* Result of BuildProgram operation */
8018 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
8019
8020 /* Clean previous error */
8021 glGetError();
8022
8023 m_texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
8024
8025 /* Prepare textures */
8026 GLU_EXPECT_NO_ERROR(
8027 Create2DRGBA8CompleteTexture(m_complete_destination_magic_number, m_complete_destination_texture_id),
8028 "Create2DRGBA8CompleteTexture");
8029 GLU_EXPECT_NO_ERROR(Create2DRGBA8CompleteTexture(m_complete_source_magic_number, m_complete_source_texture_id),
8030 "Create2DRGBA8CompleteTexture");
8031 GLU_EXPECT_NO_ERROR(
8032 Create2DRGBA8IncompleteTexture(m_incomplete_destination_magic_number, m_incomplete_destination_texture_id),
8033 "Create2DRGBA8IncompleteTexture");
8034 GLU_EXPECT_NO_ERROR(
8035 Create2DRGBA8IncompleteTexture(m_incomplete_source_magic_number, m_incomplete_source_texture_id),
8036 "Create2DRGBA8IncompleteTexture");
8037
8038 /* Prepare buffer with vertex positions of "full screen" quad" */
8039 glGenBuffers(1, &m_vertex_buffer_id);
8040 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
8041
8042 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
8043 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
8044
8045 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
8046 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
8047
8048 /* Generate vertex array object */
8049 glGenVertexArrays(1, &m_vertex_array_object_id);
8050 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
8051
8052 /* Prepare program object */
8053 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */,
8054 fragment_shader_code, &is_program_correct);
8055
8056 if (false == is_program_correct)
8057 {
8058 return ERROR;
8059 }
8060
8061 /* Done */
8062 return NO_ERROR;
8063 }
8064
Cleanup()8065 virtual long Cleanup()
8066 {
8067 /* Reset OpenGL state */
8068 glBindBuffer(GL_ARRAY_BUFFER, 0);
8069 glBindTexture(GL_TEXTURE_2D, 0);
8070 glBindVertexArray(0);
8071 glUseProgram(0);
8072
8073 /* Delete program */
8074 if (0 != m_program_id)
8075 {
8076 glDeleteProgram(m_program_id);
8077 m_program_id = 0;
8078 }
8079
8080 /* Delete textures */
8081 if (0 != m_complete_destination_texture_id)
8082 {
8083 glDeleteTextures(1, &m_complete_destination_texture_id);
8084 m_complete_destination_texture_id = 0;
8085 }
8086
8087 if (0 != m_complete_source_texture_id)
8088 {
8089 glDeleteTextures(1, &m_complete_source_texture_id);
8090 m_complete_source_texture_id = 0;
8091 }
8092
8093 if (0 != m_incomplete_destination_texture_id)
8094 {
8095 glDeleteTextures(1, &m_incomplete_destination_texture_id);
8096 m_incomplete_destination_texture_id = 0;
8097 }
8098
8099 if (0 != m_incomplete_source_texture_id)
8100 {
8101 glDeleteTextures(1, &m_incomplete_source_texture_id);
8102 m_incomplete_source_texture_id = 0;
8103 }
8104
8105 /* Delete vertex array object */
8106 if (0 != m_vertex_array_object_id)
8107 {
8108 glDeleteVertexArrays(1, &m_vertex_array_object_id);
8109 m_vertex_array_object_id = 0;
8110 }
8111
8112 /* Delete buffer */
8113 if (0 != m_vertex_buffer_id)
8114 {
8115 glDeleteBuffers(1, &m_vertex_buffer_id);
8116 m_vertex_buffer_id = 0;
8117 }
8118
8119 /* Done */
8120 return NO_ERROR;
8121 }
8122
Run()8123 virtual long Run()
8124 {
8125 bool result = true;
8126
8127 /* Copy textures data with imageLoad() and imageStore() operations */
8128 Copy2DRGBA8Textures(m_complete_destination_texture_id, m_incomplete_destination_texture_id,
8129 m_complete_source_texture_id, m_incomplete_source_texture_id);
8130
8131 glMemoryBarrier(GL_ALL_BARRIER_BITS);
8132
8133 /* Verify that store to "incomplete destination" was ignored */
8134 if (true ==
8135 CheckIfTextureWasModified(m_incomplete_destination_texture_id, m_incomplete_destination_magic_number))
8136 {
8137 m_context.getTestContext().getLog()
8138 << tcu::TestLog::Message << "Problem with imageStore, operation modified contents of incomplete texture"
8139 << tcu::TestLog::EndMessage;
8140
8141 result = false;
8142 }
8143
8144 /* Verify that load from "incomplete source" returned 0 */
8145 if (false == CheckIfTextureIsBlack(m_complete_destination_texture_id))
8146 {
8147 m_context.getTestContext().getLog()
8148 << tcu::TestLog::Message
8149 << "Problem with imageLoad, operation returned non 0 result for incomplete texture"
8150 << tcu::TestLog::EndMessage;
8151
8152 result = false;
8153 }
8154
8155 if (false == result)
8156 {
8157 return ERROR;
8158 }
8159
8160 /* Done */
8161 return NO_ERROR;
8162 }
8163
8164 private:
8165 /* Private methods */
8166
8167 /** Bind texture to image unit and sets image uniform to that unit
8168 *
8169 * @param program_id Program object id
8170 * @param texture_id Texture id
8171 * @param level Texture level
8172 * @param image_unit Index of image unit
8173 * @param uniform_name Name of image uniform
8174 **/
BindTextureToImage(GLuint program_id,GLuint texture_id,GLint level,GLuint image_unit,const char * uniform_name)8175 void BindTextureToImage(GLuint program_id, GLuint texture_id, GLint level, GLuint image_unit, const char* uniform_name)
8176 {
8177 /* Uniform location and invalid value */
8178 static const GLint invalid_uniform_location = -1;
8179 GLint image_uniform_location = 0;
8180
8181 /* Get uniform location */
8182 image_uniform_location = glGetUniformLocation(program_id, uniform_name);
8183 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
8184 if (invalid_uniform_location == image_uniform_location)
8185 {
8186 throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__);
8187 }
8188
8189 /* Bind texture to image unit */
8190 glBindImageTexture(image_unit, texture_id, level, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_RGBA8);
8191 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
8192
8193 /* Set uniform to image unit */
8194 glUniform1i(image_uniform_location, image_unit);
8195 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
8196 }
8197
8198 /** Check if texture is filled with black color, zeros
8199 *
8200 * @param texture_id Id of texture object
8201 *
8202 * @return true when texture is fully black, false otherwise
8203 **/
CheckIfTextureIsBlack(GLuint texture_id)8204 bool CheckIfTextureIsBlack(GLuint texture_id)
8205 {
8206 /* Constants to calculate size of texture */
8207 static const GLuint n_components = 4; /* RGBA */
8208 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components;
8209
8210 /* Storage for texture data */
8211 std::vector<GLubyte> black_texture_data;
8212 std::vector<GLubyte> texture_data;
8213
8214 /* Allocate memory */
8215 black_texture_data.resize(texture_data_size);
8216 texture_data.resize(texture_data_size);
8217
8218 /* Set all texels to black */
8219 for (GLuint i = 0; i < texture_data_size; ++i)
8220 {
8221 black_texture_data[i] = 0;
8222 }
8223
8224 /* Bind texture */
8225 glBindTexture(GL_TEXTURE_2D, texture_id);
8226 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
8227
8228 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
8229 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
8230
8231 /* Compare texels */
8232 return (0 == memcmp(&texture_data[0], &black_texture_data[0], texture_data_size));
8233 }
8234
8235 /** Check if texture was modified
8236 *
8237 * @param texture_id Id of texture object
8238 * @param nagic_number Magic number that was to create texture
8239 *
8240 * @return true if texture contents match expected values, false otherwise
8241 **/
CheckIfTextureWasModified(GLuint texture_id,GLubyte magic_number)8242 bool CheckIfTextureWasModified(GLuint texture_id, GLubyte magic_number)
8243 {
8244 /* Constants to calculate size of texture */
8245 static const GLuint n_components = 4; /* RGBA */
8246 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components;
8247
8248 /* Storage for texture data */
8249 std::vector<GLubyte> expected_texture_data;
8250 std::vector<GLubyte> texture_data;
8251
8252 /* Allocate memory */
8253 expected_texture_data.resize(texture_data_size);
8254 texture_data.resize(texture_data_size);
8255
8256 /* Prepare expected texels */
8257 for (GLuint y = 0; y < m_texture_edge; ++y)
8258 {
8259 const GLuint line_offset = y * m_texture_edge * n_components;
8260
8261 for (GLuint x = 0; x < m_texture_edge; ++x)
8262 {
8263 const GLuint texel_offset = x * n_components + line_offset;
8264
8265 SetTexel(&expected_texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y),
8266 magic_number);
8267 }
8268 }
8269
8270 /* Bind texture */
8271 glBindTexture(GL_TEXTURE_2D, texture_id);
8272 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
8273
8274 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
8275 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
8276
8277 /* Compare texels, true when textures are different */
8278 return (0 != memcmp(&texture_data[0], &expected_texture_data[0], texture_data_size));
8279 }
8280
8281 /** Copy contents of "source" textures to "destination" textures with imageLoad() and imageStore() operations
8282 *
8283 * @param complete_destination_texture_id Id of "complete destination" texture object
8284 * @param incomplete_destination_texture_id Id of "incomplete destination" texture object
8285 * @param complete_source_texture_id Id of "complete source" texture object
8286 * @param incomplete_source_texture_id Id of "incomplete source" texture object
8287 **/
Copy2DRGBA8Textures(GLuint complete_destination_texture_id,GLuint incomplete_destination_texture_id,GLuint complete_source_texture_id,GLuint incomplete_source_texture_id)8288 void Copy2DRGBA8Textures(GLuint complete_destination_texture_id, GLuint incomplete_destination_texture_id,
8289 GLuint complete_source_texture_id, GLuint incomplete_source_texture_id)
8290 {
8291 /* Uniform names */
8292 static const char* const complete_destination_image_uniform_name = "u_complete_destination_image";
8293 static const char* const complete_source_image_uniform_name = "u_complete_source_image";
8294 static const char* const incomplete_destination_image_uniform_name = "u_incomplete_destination_image";
8295 static const char* const incomplete_source_image_uniform_name = "u_incomplete_source_image";
8296
8297 /* Attribute name */
8298 static const char* const position_attribute_name = "vs_in_position";
8299
8300 /* Attribute location and invalid value */
8301 static const GLint invalid_attribute_location = -1;
8302 GLint position_attribute_location = 0;
8303
8304 /* Set current program */
8305 glUseProgram(m_program_id);
8306 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
8307
8308 /* Bind vertex array object */
8309 glBindVertexArray(m_vertex_array_object_id);
8310 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
8311
8312 /* Bind buffer with quad vertex positions */
8313 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
8314 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
8315
8316 /* Setup position attribute */
8317 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
8318 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
8319 if (invalid_attribute_location == position_attribute_location)
8320 {
8321 throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
8322 __LINE__);
8323 }
8324
8325 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE, 0 /* stride */, 0);
8326 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
8327
8328 glEnableVertexAttribArray(position_attribute_location);
8329 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
8330
8331 /* Setup textures as source and destination images */
8332 BindTextureToImage(m_program_id, complete_destination_texture_id,
8333 0 /* texture level */, 0 /* image_unit */,
8334 complete_destination_image_uniform_name);
8335 BindTextureToImage(m_program_id, complete_source_texture_id,
8336 0 /* texture level */, 1 /* image_unit */,
8337 complete_source_image_uniform_name);
8338 BindTextureToImage(m_program_id, incomplete_destination_texture_id,
8339 2 /* texture level */, 2 /* image_unit */,
8340 incomplete_destination_image_uniform_name);
8341 BindTextureToImage(m_program_id, incomplete_source_texture_id,
8342 2 /* texture level */, 3 /* image_unit */,
8343 incomplete_source_image_uniform_name);
8344
8345 /* Execute draw */
8346 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
8347 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
8348 }
8349
8350 /** Create complete 2D RGBA8 texture.
8351 *
8352 * @param magic_number Magic number of texture
8353 * @param out_texture_id Id of created texture, not modified if operation fails
8354 *
8355 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
8356 **/
Create2DRGBA8CompleteTexture(GLubyte magic_number,GLuint & out_texture_id)8357 GLenum Create2DRGBA8CompleteTexture(GLubyte magic_number, GLuint& out_texture_id)
8358 {
8359 /* Constants to calculate size of texture */
8360 static const GLuint n_components = 4; /* RGBA */
8361 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components;
8362
8363 /* Error code */
8364 GLenum err = 0;
8365
8366 /* Texture id */
8367 GLuint texture_id = 0;
8368
8369 /* Prepare storage for texture data */
8370 std::vector<GLubyte> texture_data;
8371 texture_data.resize(texture_data_size);
8372
8373 /* Prepare texture data */
8374 for (GLuint y = 0; y < m_texture_edge; ++y)
8375 {
8376 const GLuint line_offset = y * m_texture_edge * n_components;
8377
8378 for (GLuint x = 0; x < m_texture_edge; ++x)
8379 {
8380 const GLuint texel_offset = x * n_components + line_offset;
8381
8382 SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number);
8383 }
8384 }
8385
8386 /* Generate texture */
8387 glGenTextures(1, &texture_id);
8388 err = glGetError();
8389 if (GL_NO_ERROR != err)
8390 {
8391 return err;
8392 }
8393
8394 /* Bind texture */
8395 glBindTexture(GL_TEXTURE_2D, texture_id);
8396 err = glGetError();
8397 if (GL_NO_ERROR != err)
8398 {
8399 glDeleteTextures(1, &texture_id);
8400 return err;
8401 }
8402
8403 /* Allocate storage and fill texture */
8404 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA,
8405 GL_UNSIGNED_BYTE, &texture_data[0]);
8406 err = glGetError();
8407 if (GL_NO_ERROR != err)
8408 {
8409 glDeleteTextures(1, &texture_id);
8410 return err;
8411 }
8412
8413 /* Make texture complete */
8414 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8415 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
8416 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8417 err = glGetError();
8418 if (GL_NO_ERROR != err)
8419 {
8420 glDeleteTextures(1, &texture_id);
8421 return err;
8422 }
8423
8424 /* Set out_texture_id */
8425 out_texture_id = texture_id;
8426
8427 /* Done */
8428 return GL_NO_ERROR;
8429 }
8430
8431 /** Create incomplete 2D RGBA8 texture
8432 *
8433 * @param magic_number Magic number of texture
8434 * @param out_texture_id Id of created texture, not modified if operation fails
8435 *
8436 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
8437 **/
Create2DRGBA8IncompleteTexture(GLubyte magic_number,GLuint & out_texture_id)8438 GLenum Create2DRGBA8IncompleteTexture(GLubyte magic_number, GLuint& out_texture_id)
8439 {
8440 /* Constants to calculate size of texture */
8441 static const GLuint n_components = 4; /* RGBA */
8442 const GLuint texture_data_size = m_texture_edge * m_texture_edge * n_components;
8443
8444 /* Error code */
8445 GLenum err = 0;
8446
8447 /* Texture id */
8448 GLuint texture_id = 0;
8449
8450 /* Prepare storage for texture data */
8451 std::vector<GLubyte> texture_data;
8452 texture_data.resize(texture_data_size);
8453
8454 /* Prepare texture data */
8455 for (GLuint y = 0; y < m_texture_edge; ++y)
8456 {
8457 const GLuint line_offset = y * m_texture_edge * n_components;
8458
8459 for (GLuint x = 0; x < m_texture_edge; ++x)
8460 {
8461 const GLuint texel_offset = x * n_components + line_offset;
8462
8463 SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number);
8464 }
8465 }
8466
8467 /* Generate texture */
8468 glGenTextures(1, &texture_id);
8469 err = glGetError();
8470 if (GL_NO_ERROR != err)
8471 {
8472 return err;
8473 }
8474
8475 /* Bind texture */
8476 glBindTexture(GL_TEXTURE_2D, texture_id);
8477 err = glGetError();
8478 if (GL_NO_ERROR != err)
8479 {
8480 glDeleteTextures(1, &texture_id);
8481 return err;
8482 }
8483
8484 /* Allocate storage and fill texture */
8485 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA,
8486 GL_UNSIGNED_BYTE, &texture_data[0]);
8487 err = glGetError();
8488 if (GL_NO_ERROR != err)
8489 {
8490 glDeleteTextures(1, &texture_id);
8491 return err;
8492 }
8493
8494 /* Make texture incomplete */
8495 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8496 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 7);
8497 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
8498 err = glGetError();
8499 if (GL_NO_ERROR != err)
8500 {
8501 glDeleteTextures(1, &texture_id);
8502 return err;
8503 }
8504
8505 /* Set out_texture_id */
8506 out_texture_id = texture_id;
8507
8508 /* Done */
8509 return GL_NO_ERROR;
8510 }
8511
8512 /** Prepare "unique" texels.
8513 * Texel is assigned with such values: [x_coordinate, y_coordinate, magic_number, 0xcc].
8514 *
8515 * @param texel Storage of texel
8516 * @param x_coordinate X coordiante of texel
8517 * @param y_coordinate Y coordinate of texel
8518 * @param magic_number Magic number of texture
8519 **/
SetTexel(GLubyte texel[4],GLubyte x_coordinate,GLubyte y_coordinate,GLubyte magic_number)8520 void SetTexel(GLubyte texel[4], GLubyte x_coordinate, GLubyte y_coordinate, GLubyte magic_number)
8521 {
8522 texel[0] = x_coordinate;
8523 texel[1] = y_coordinate;
8524 texel[2] = magic_number;
8525 texel[3] = 0xcc;
8526 }
8527 };
8528
8529 /** Test "Refer to the same image unit using multiple uniforms", description follows.
8530 *
8531 * Steps:
8532 * - prepare program object, see details below,
8533 * - prepare 2D R32I texture, width should be equal to the number of image
8534 * uniforms used by program object, height should be 2, fill first row with
8535 * unique values, fill second row with zeros,
8536 * - bind texture to first image unit,
8537 * - set all image uniforms to first image unit,
8538 * - execute program for a single vertex,
8539 * - verify that:
8540 * - values in first row were negated,
8541 * - values from first row were copied to second row,
8542 *
8543 * Repeat steps to test all shader stages that support at least 2 image
8544 * uniforms.
8545 *
8546 * Program has to contain all necessary shader stages. Use boilerplate shaders
8547 * for shader stages that are not important for the test.
8548 *
8549 * Tested shader stage should:
8550 * - Use as many different image formats as possible, image formats compatible
8551 * with R32I:
8552 * * rg16f
8553 * * r11f_g11f_b10f
8554 * * r32f
8555 * * rgb10_a2ui
8556 * * rgba8ui
8557 * * rg16ui
8558 * * r32ui
8559 * * rgba8i
8560 * * rg16i
8561 * * r32i
8562 * * rgb10_a2
8563 * * rgba8
8564 * * rg16
8565 * * rgba8_snorm
8566 * * rg16_snorm.
8567 * - Declare maximum allowed number of image uniforms,
8568 *
8569 * layout(format) uniform gimage2D u_image;
8570 *
8571 * where <format> is selected image format, <gimage2D> is type of 2D image
8572 * compatible with <format> and <u_image> is unique name of uniform.
8573 * Note that image uniforms cannot be declared as array, due to different image
8574 * formats. Therefore separate uniforms have to be used.
8575 * - Include following code snippet:
8576 * for (int i = 0; i < gl_Max*ImageUniforms; ++i)
8577 * {
8578 * vec row_1_coord(i,0);
8579 * vec row_2_coord(i,1);
8580 *
8581 * row_1_value = imageLoad(u_image[i], row_1_coord);
8582 * imageStore(u_image[i], row_1_coord, -row_1_value);
8583 * imageStore(u_image[i], row_2_coord, row_1_value);
8584 * }
8585 * where gl_Max*ImageUniforms is the constant corresponding to tested shader
8586 * stage.
8587 **/
8588 class ImageLoadStoreMultipleUniformsTest : public ShaderImageLoadStoreBase
8589 {
8590 private:
8591 /* Types */
8592 /** Details of image format
8593 *
8594 **/
8595 struct imageFormatDetails
8596 {
8597 typedef bool (*verificationRoutine)(GLint, GLint, GLint);
8598
8599 const char* m_image_format;
8600 const char* m_image_type;
8601 const char* m_color_type;
8602 GLenum m_image_unit_format;
8603 verificationRoutine m_verification_routine;
8604 };
8605
8606 template <typename T, GLuint SIZE, GLuint OFFSET, bool = (OFFSET < sizeof(T) * CHAR_BIT)>
8607 struct Masks
8608 {
8609 /** Get mask of bits used to store in bit-field
8610 *
8611 * @return Mask
8612 **/
RawMaskgl4cts::__anonb00615420111::ImageLoadStoreMultipleUniformsTest::Masks8613 static inline T RawMask()
8614 {
8615 static const T mask = ValueMask() << OFFSET;
8616
8617 return mask;
8618 }
8619
8620 /** Get mask of bits used to store value.
8621 *
8622 * @return Mask
8623 **/
ValueMaskgl4cts::__anonb00615420111::ImageLoadStoreMultipleUniformsTest::Masks8624 static inline T ValueMask()
8625 {
8626 static const T mask = (1 << SIZE) - 1;
8627
8628 return mask;
8629 }
8630
8631 /** Get offset.
8632 *
8633 * @return offset
8634 **/
Offsetgl4cts::__anonb00615420111::ImageLoadStoreMultipleUniformsTest::Masks8635 static inline T Offset()
8636 {
8637 return OFFSET;
8638 }
8639 };
8640
8641 template <typename T, GLuint SIZE, GLuint OFFSET>
8642 struct Masks<T, SIZE, OFFSET, false>
8643 {
8644 /** Get mask of bits used to store in bit-field
8645 *
8646 * @return Mask
8647 **/
RawMaskgl4cts::__anonb00615420111::ImageLoadStoreMultipleUniformsTest::Masks8648 static inline T RawMask()
8649 {
8650 DE_ASSERT(DE_FALSE && "Shouldn't be called");
8651 return 0;
8652 }
8653
8654 /** Get mask of bits used to store value.
8655 *
8656 * @return Mask
8657 **/
ValueMaskgl4cts::__anonb00615420111::ImageLoadStoreMultipleUniformsTest::Masks8658 static inline T ValueMask()
8659 {
8660 DE_ASSERT(DE_FALSE && "Shouldn't be called");
8661 return 0;
8662 }
8663
8664 /** Get offset.
8665 *
8666 * @return offset
8667 **/
Offsetgl4cts::__anonb00615420111::ImageLoadStoreMultipleUniformsTest::Masks8668 static inline T Offset()
8669 {
8670 DE_ASSERT(DE_FALSE && "Shouldn't be called");
8671 return 0;
8672 }
8673 };
8674
8675 /** Template class for accessing integer values stored in bit-fields
8676 *
8677 **/
8678 template <typename T, GLuint SIZE, GLuint OFFSET>
8679 class Integer
8680 {
8681 public:
8682 /** Constructor
8683 *
8684 **/
Integer(T raw)8685 Integer(T raw) : m_raw(raw)
8686 {
8687 }
8688
8689 /** Extract value from bit-field
8690 *
8691 * @return Value
8692 **/
Get() const8693 T Get() const
8694 {
8695 const T mask = Masks<T, SIZE, OFFSET>::RawMask();
8696
8697 const T bits = m_raw & mask;
8698 const T result = (unsigned)bits >> Masks<T, SIZE, OFFSET>::Offset();
8699
8700 return result;
8701 }
8702
8703 /** Extract value from bit-field and negate it
8704 *
8705 * @return Negated value
8706 **/
GetNegated() const8707 T GetNegated() const
8708 {
8709 const T mask = Masks<T, SIZE, OFFSET>::ValueMask();
8710 const T value = Get();
8711
8712 return Clamp((~value) + 1) & mask;
8713 }
8714
Clamp(T n) const8715 T Clamp(T n) const
8716 {
8717 const bool isUnsigned = (T(0) < T(-1));
8718 const T min = T(isUnsigned ? 0.L : -pow(2.L, int(SIZE - 1)));
8719 const T max = T(isUnsigned ? pow(2.L, int(SIZE)) - 1.L : pow(2.L, int(SIZE - 1)) - 1.L);
8720 const T x = n > max ? max : n;
8721 return x < min ? min : x;
8722 }
8723
8724 private:
8725 T m_raw;
8726 };
8727
8728 /* Enums */
8729 /** Shader stage identification
8730 *
8731 **/
8732 enum shaderStage
8733 {
8734 fragmentShaderStage = 2,
8735 geometryShaderStage = 4,
8736 tesselationControlShaderStage = 8,
8737 tesselationEvalutaionShaderStage = 16,
8738 vertexShaderStage = 32,
8739 };
8740
8741 /** Test result
8742 *
8743 **/
8744 enum testResult
8745 {
8746 testFailed = -1,
8747 testNotSupported = 1,
8748 testPassed = 0
8749 };
8750
8751 /* Constants */
8752 static const GLint m_min_required_image_uniforms = 2;
8753
8754 /* Fields */
8755 GLuint m_program_to_test_fs_stage_id;
8756 GLuint m_program_to_test_gs_stage_id;
8757 GLuint m_program_to_test_tcs_stage_id;
8758 GLuint m_program_to_test_tes_stage_id;
8759 GLuint m_program_to_test_vs_stage_id;
8760 GLuint m_texture_to_test_fs_stage_id;
8761 GLuint m_texture_to_test_gs_stage_id;
8762 GLuint m_texture_to_test_tcs_stage_id;
8763 GLuint m_texture_to_test_tes_stage_id;
8764 GLuint m_texture_to_test_vs_stage_id;
8765 GLuint m_vertex_array_object_id;
8766
8767 public:
8768 /* Constructor */
ImageLoadStoreMultipleUniformsTest()8769 ImageLoadStoreMultipleUniformsTest()
8770 : m_program_to_test_fs_stage_id(0)
8771 , m_program_to_test_gs_stage_id(0)
8772 , m_program_to_test_tcs_stage_id(0)
8773 , m_program_to_test_tes_stage_id(0)
8774 , m_program_to_test_vs_stage_id(0)
8775 , m_texture_to_test_fs_stage_id(0)
8776 , m_texture_to_test_gs_stage_id(0)
8777 , m_texture_to_test_tcs_stage_id(0)
8778 , m_texture_to_test_tes_stage_id(0)
8779 , m_texture_to_test_vs_stage_id(0)
8780 , m_vertex_array_object_id(0)
8781 {
8782 /* Nothing to be done here */
8783 }
8784
8785 /* Methods inherited from SubcaseBase */
Setup()8786 virtual long Setup()
8787 {
8788 /* Prepare programs */
8789 m_program_to_test_fs_stage_id = buildProgramToTestShaderStage(fragmentShaderStage);
8790 m_program_to_test_gs_stage_id = buildProgramToTestShaderStage(geometryShaderStage);
8791 m_program_to_test_tcs_stage_id = buildProgramToTestShaderStage(tesselationControlShaderStage);
8792 m_program_to_test_tes_stage_id = buildProgramToTestShaderStage(tesselationEvalutaionShaderStage);
8793 m_program_to_test_vs_stage_id = buildProgramToTestShaderStage(vertexShaderStage);
8794
8795 /* Prepare textures */
8796 m_texture_to_test_fs_stage_id = createTextureToTestShaderStage(fragmentShaderStage);
8797 m_texture_to_test_gs_stage_id = createTextureToTestShaderStage(geometryShaderStage);
8798 m_texture_to_test_tcs_stage_id = createTextureToTestShaderStage(tesselationControlShaderStage);
8799 m_texture_to_test_tes_stage_id = createTextureToTestShaderStage(tesselationEvalutaionShaderStage);
8800 m_texture_to_test_vs_stage_id = createTextureToTestShaderStage(vertexShaderStage);
8801
8802 /* Generate vertex array object */
8803 glGenVertexArrays(1, &m_vertex_array_object_id);
8804 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
8805
8806 /* Bind vertex array object */
8807 glBindVertexArray(m_vertex_array_object_id);
8808 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
8809
8810 /* Set vertices number for patches */
8811 glPatchParameteri(GL_PATCH_VERTICES, 1);
8812
8813 /* Done */
8814 return NO_ERROR;
8815 }
8816
Cleanup()8817 virtual long Cleanup()
8818 {
8819 glUseProgram(0);
8820
8821 /* Delete programs */
8822 if (0 != m_program_to_test_fs_stage_id)
8823 {
8824 glDeleteProgram(m_program_to_test_fs_stage_id);
8825 m_program_to_test_fs_stage_id = 0;
8826 }
8827
8828 if (0 != m_program_to_test_gs_stage_id)
8829 {
8830 glDeleteProgram(m_program_to_test_gs_stage_id);
8831 m_program_to_test_gs_stage_id = 0;
8832 }
8833
8834 if (0 != m_program_to_test_tcs_stage_id)
8835 {
8836 glDeleteProgram(m_program_to_test_tcs_stage_id);
8837 m_program_to_test_tcs_stage_id = 0;
8838 }
8839
8840 if (0 != m_program_to_test_tes_stage_id)
8841 {
8842 glDeleteProgram(m_program_to_test_tes_stage_id);
8843 m_program_to_test_tes_stage_id = 0;
8844 }
8845
8846 if (0 != m_program_to_test_vs_stage_id)
8847 {
8848 glDeleteProgram(m_program_to_test_vs_stage_id);
8849 m_program_to_test_vs_stage_id = 0;
8850 }
8851
8852 /* Delete textures */
8853 if (0 != m_texture_to_test_fs_stage_id)
8854 {
8855 glDeleteTextures(1, &m_texture_to_test_fs_stage_id);
8856 m_texture_to_test_fs_stage_id = 0;
8857 }
8858
8859 if (0 != m_texture_to_test_gs_stage_id)
8860 {
8861 glDeleteTextures(1, &m_texture_to_test_gs_stage_id);
8862 m_texture_to_test_gs_stage_id = 0;
8863 }
8864
8865 if (0 != m_texture_to_test_tcs_stage_id)
8866 {
8867 glDeleteTextures(1, &m_texture_to_test_tcs_stage_id);
8868 m_texture_to_test_tcs_stage_id = 0;
8869 }
8870
8871 if (0 != m_texture_to_test_tes_stage_id)
8872 {
8873 glDeleteTextures(1, &m_texture_to_test_tes_stage_id);
8874 m_texture_to_test_tes_stage_id = 0;
8875 }
8876
8877 if (0 != m_texture_to_test_vs_stage_id)
8878 {
8879 glDeleteTextures(1, &m_texture_to_test_vs_stage_id);
8880 m_texture_to_test_vs_stage_id = 0;
8881 }
8882
8883 /* Delete vertex array object id */
8884 if (0 != m_vertex_array_object_id)
8885 {
8886 glDeleteVertexArrays(1, &m_vertex_array_object_id);
8887 m_vertex_array_object_id = 0;
8888 }
8889
8890 /* Done */
8891 return NO_ERROR;
8892 }
8893
Run()8894 virtual long Run()
8895 {
8896 bool result = true;
8897
8898 if (testFailed == testShaderStage(fragmentShaderStage))
8899 {
8900 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with fragment shader stage!"
8901 << tcu::TestLog::EndMessage;
8902
8903 result = false;
8904 }
8905
8906 if (testFailed == testShaderStage(geometryShaderStage))
8907 {
8908 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with geometry shader stage!"
8909 << tcu::TestLog::EndMessage;
8910
8911 result = false;
8912 }
8913
8914 if (testFailed == testShaderStage(tesselationControlShaderStage))
8915 {
8916 m_context.getTestContext().getLog() << tcu::TestLog::Message
8917 << "Problems with tesselation control shader stage!"
8918 << tcu::TestLog::EndMessage;
8919
8920 result = false;
8921 }
8922
8923 if (testFailed == testShaderStage(tesselationEvalutaionShaderStage))
8924 {
8925 m_context.getTestContext().getLog() << tcu::TestLog::Message
8926 << "Problems with tesselation evaluation shader stage!"
8927 << tcu::TestLog::EndMessage;
8928
8929 result = false;
8930 }
8931
8932 if (testFailed == testShaderStage(vertexShaderStage))
8933 {
8934 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with vertex shader stage!"
8935 << tcu::TestLog::EndMessage;
8936
8937 result = false;
8938 }
8939
8940 if (false == result)
8941 {
8942 return ERROR;
8943 }
8944
8945 /* Done */
8946 return NO_ERROR;
8947 }
8948
8949 private:
8950 /* Static routines */
8951 /** Provide image format details for given index
8952 *
8953 * @param index Index
8954 * @param out_details Image format detail instance
8955 **/
getImageUniformDeclarationDetails(GLuint index,imageFormatDetails & out_details)8956 static void getImageUniformDeclarationDetails(GLuint index, imageFormatDetails& out_details)
8957 {
8958 static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails default_format_details = {
8959 "r32i", "iimage2D", "ivec4", GL_R32I, ImageLoadStoreMultipleUniformsTest::verifyInteger
8960 };
8961
8962 static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details[] = {
8963 { "rg16f", "image2D", "vec4", GL_RG16F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLushort> },
8964 { "r11f_g11f_b10f", "image2D", "vec4", GL_R11F_G11F_B10F,
8965 ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8966 { "r32f", "image2D", "vec4", GL_R32F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLuint> },
8967 { "rgb10_a2", "image2D", "vec4", GL_RGB10_A2,
8968 ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8969 { "rgba8", "image2D", "vec4", GL_RGBA8, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8970 { "rg16", "image2D", "vec4", GL_RG16, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8971 { "rgba8_snorm", "image2D", "vec4", GL_RGBA8_SNORM,
8972 ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLbyte> },
8973 { "rg16_snorm", "image2D", "vec4", GL_RG16_SNORM,
8974 ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLshort> },
8975 { "rgb10_a2ui", "uimage2D", "uvec4", GL_RGB10_A2UI,
8976 ImageLoadStoreMultipleUniformsTest::verifyInteger<10, 10, 10, 2, GLuint> },
8977 { "rgba8ui", "uimage2D", "uvec4", GL_RGBA8UI,
8978 ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLuint> },
8979 { "rg16ui", "uimage2D", "uvec4", GL_RG16UI,
8980 ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLuint> },
8981 { "r32ui", "uimage2D", "uvec4", GL_R32UI, ImageLoadStoreMultipleUniformsTest::verifyInteger },
8982 { "rgba8i", "iimage2D", "ivec4", GL_RGBA8I,
8983 ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLint> },
8984 { "rg16i", "iimage2D", "ivec4", GL_RG16I,
8985 ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLint> }
8986 };
8987
8988 static const GLuint n_imageUniformFormatDetails =
8989 sizeof(format_details) / sizeof(ImageLoadStoreMultipleUniformsTest::imageFormatDetails);
8990
8991 if (n_imageUniformFormatDetails <= index)
8992 {
8993 out_details = default_format_details;
8994 }
8995 else
8996 {
8997 out_details = format_details[index];
8998 }
8999 }
9000
9001 /** Write name of image uniform at given index to output stream
9002 *
9003 * @param stream Output stream
9004 * @param index Index
9005 **/
writeImageUniformNameToStream(std::ostream & stream,GLuint index)9006 static void writeImageUniformNameToStream(std::ostream& stream, GLuint index)
9007 {
9008 /* u_image_0 */
9009 stream << "u_image_" << index;
9010 }
9011
9012 /** Write name of variable used to store value loaded from image at given index to output stream
9013 *
9014 * @param stream Output stream
9015 * @param index Index
9016 **/
writeLoadedValueVariableNameToStream(std::ostream & stream,GLuint index)9017 static void writeLoadedValueVariableNameToStream(std::ostream& stream, GLuint index)
9018 {
9019 /* loaded_value_0 */
9020 stream << "loaded_value_" << index;
9021 }
9022
9023 /** Write name of variable used to store coordinate of texel at given row to output stream
9024 *
9025 * @param stream Output stream
9026 * @param index Index of image uniform
9027 * @param row Row of image
9028 **/
writeCoordinatesVariableNameToStream(std::ostream & stream,GLuint index,GLuint row)9029 static void writeCoordinatesVariableNameToStream(std::ostream& stream, GLuint index, GLuint row)
9030 {
9031 /* row_0_coordinates_0 */
9032 stream << "row_" << row << "_coordinates_" << index;
9033 }
9034
9035 struct imageUniformDeclaration
9036 {
imageUniformDeclarationgl4cts::__anonb00615420111::ImageLoadStoreMultipleUniformsTest::imageUniformDeclaration9037 imageUniformDeclaration(GLuint index) : m_index(index)
9038 {
9039 }
9040
9041 GLuint m_index;
9042 };
9043
9044 /** Write declaration of image uniform at given index to output stream
9045 *
9046 * @param stream Output stream
9047 * @param imageUniformDeclaration Declaration details
9048 *
9049 * @return stream
9050 **/
operator <<(std::ostream & stream,const imageUniformDeclaration & declaration)9051 friend std::ostream& operator<<(std::ostream& stream, const imageUniformDeclaration& declaration)
9052 {
9053 ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details;
9054 getImageUniformDeclarationDetails(declaration.m_index, format_details);
9055
9056 /* layout(r32f) uniform image2D u_image_0; */
9057 stream << "layout(" << format_details.m_image_format << ") uniform " << format_details.m_image_type << " ";
9058
9059 ImageLoadStoreMultipleUniformsTest::writeImageUniformNameToStream(stream, declaration.m_index);
9060
9061 stream << ";";
9062
9063 return stream;
9064 }
9065
9066 struct imageLoadCall
9067 {
imageLoadCallgl4cts::__anonb00615420111::ImageLoadStoreMultipleUniformsTest::imageLoadCall9068 imageLoadCall(GLuint index) : m_index(index)
9069 {
9070 }
9071
9072 GLuint m_index;
9073 };
9074
9075 /* Stream operators */
9076 /** Write code that execute imageLoad routine for image at given index to output stream
9077 *
9078 * @param stream Output stream
9079 * @param load imageLoad call details
9080 *
9081 * @return stream
9082 **/
operator <<(std::ostream & stream,const imageLoadCall & load)9083 friend std::ostream& operator<<(std::ostream& stream, const imageLoadCall& load)
9084 {
9085 ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details;
9086 getImageUniformDeclarationDetails(load.m_index, format_details);
9087
9088 /* vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates_0); */
9089 stream << format_details.m_color_type << " ";
9090
9091 writeLoadedValueVariableNameToStream(stream, load.m_index);
9092
9093 stream << " = imageLoad(";
9094
9095 writeImageUniformNameToStream(stream, load.m_index);
9096
9097 stream << ", ";
9098
9099 writeCoordinatesVariableNameToStream(stream, load.m_index, 0 /* row */);
9100
9101 stream << ");";
9102
9103 return stream;
9104 }
9105
9106 struct imageStoreCall
9107 {
imageStoreCallgl4cts::__anonb00615420111::ImageLoadStoreMultipleUniformsTest::imageStoreCall9108 imageStoreCall(GLuint index, GLuint row) : m_index(index), m_row(row)
9109 {
9110 }
9111
9112 GLuint m_index;
9113 GLuint m_row;
9114 };
9115
9116 /** Write code that execute imageStore to image at given index to output stream
9117 *
9118 * @param stream Output stream
9119 * @param store imageStore call details
9120 *
9121 * @return stream
9122 **/
operator <<(std::ostream & stream,const imageStoreCall & store)9123 friend std::ostream& operator<<(std::ostream& stream, const imageStoreCall& store)
9124 {
9125 /* imageStore(u_image_0, row_0_coordinates_0, -loaded_value_0); */
9126 stream << "imageStore(";
9127
9128 writeImageUniformNameToStream(stream, store.m_index);
9129
9130 stream << ", ";
9131
9132 writeCoordinatesVariableNameToStream(stream, store.m_index, store.m_row);
9133
9134 if (0 == store.m_row)
9135 {
9136 stream << ", -";
9137 }
9138 else
9139 {
9140 stream << ", ";
9141 }
9142
9143 writeLoadedValueVariableNameToStream(stream, store.m_index);
9144 stream << ");";
9145
9146 return stream;
9147 }
9148
9149 struct coordinatesVariableDeclaration
9150 {
coordinatesVariableDeclarationgl4cts::__anonb00615420111::ImageLoadStoreMultipleUniformsTest::coordinatesVariableDeclaration9151 coordinatesVariableDeclaration(GLuint index, GLuint row) : m_index(index), m_row(row)
9152 {
9153 }
9154 GLuint m_index;
9155 GLuint m_row;
9156 };
9157
9158 /** Write declaration of variable for coordinate at given row to output stream
9159 *
9160 * @param stream Output stream
9161 * @param declaration Declaration details
9162 *
9163 * @return stream
9164 **/
operator <<(std::ostream & stream,const coordinatesVariableDeclaration & declaration)9165 friend std::ostream& operator<<(std::ostream& stream, const coordinatesVariableDeclaration& declaration)
9166 {
9167 stream << "const ivec2 ";
9168
9169 writeCoordinatesVariableNameToStream(stream, declaration.m_index, declaration.m_row);
9170
9171 stream << " = ivec2(" << declaration.m_index << ", " << declaration.m_row << ");";
9172
9173 return stream;
9174 }
9175
9176 /* Methods */
9177 /** Build program to test specified shader stage
9178 *
9179 * Throws exception in case of any failure
9180 *
9181 * @param stage Stage id
9182 *
9183 * @return Program id
9184 **/
buildProgramToTestShaderStage(shaderStage stage)9185 GLuint buildProgramToTestShaderStage(shaderStage stage)
9186 {
9187 static const char* const boilerplate_fragment_shader_code =
9188 "#version 400 core\n"
9189 "#extension GL_ARB_shader_image_load_store : require\n"
9190 "\n"
9191 "precision highp float;\n"
9192 "\n"
9193 "void main()\n"
9194 "{\n"
9195 " discard;\n"
9196 "}\n";
9197
9198 static const char* const boilerplate_tesselation_evaluation_shader_code =
9199 "#version 400 core\n"
9200 "#extension GL_ARB_shader_image_load_store : require\n"
9201 "\n"
9202 "precision highp float;\n"
9203 "\n"
9204 "layout(quads, equal_spacing, ccw) in;\n"
9205 "\n"
9206 "void main()\n"
9207 "{\n"
9208 "\n"
9209 "}\n";
9210
9211 static const char* const boilerplate_vertex_shader_code =
9212 "#version 400 core\n"
9213 "#extension GL_ARB_shader_image_load_store : require\n"
9214 "\n"
9215 "precision highp float;\n"
9216 "\n"
9217 "layout(location = 0) in vec4 i_position;\n"
9218 "\n"
9219 "void main()\n"
9220 "{\n"
9221 " gl_Position = i_position;\n"
9222 "}\n";
9223
9224 const char* fragment_shader_code = boilerplate_fragment_shader_code;
9225 const char* geometry_shader_code = 0;
9226 bool is_program_built = true;
9227 GLuint program_object_id = 0;
9228 const char* tesselation_control_shader_code = 0;
9229 const char* tesselation_evaluation_shader_code = 0;
9230 std::string tested_shader_stage_code;
9231 const char* vertex_shader_code = boilerplate_vertex_shader_code;
9232
9233 /* Get source code for tested shader stage */
9234 prepareShaderForTestedShaderStage(stage, tested_shader_stage_code);
9235
9236 if (true == tested_shader_stage_code.empty())
9237 {
9238 return 0;
9239 }
9240
9241 /* Set up source code for all required stages */
9242 switch (stage)
9243 {
9244 case fragmentShaderStage:
9245 fragment_shader_code = tested_shader_stage_code.c_str();
9246 break;
9247
9248 case geometryShaderStage:
9249 geometry_shader_code = tested_shader_stage_code.c_str();
9250 break;
9251
9252 case tesselationControlShaderStage:
9253 tesselation_control_shader_code = tested_shader_stage_code.c_str();
9254 tesselation_evaluation_shader_code = boilerplate_tesselation_evaluation_shader_code;
9255 break;
9256
9257 case tesselationEvalutaionShaderStage:
9258 tesselation_evaluation_shader_code = tested_shader_stage_code.c_str();
9259 break;
9260
9261 case vertexShaderStage:
9262 vertex_shader_code = tested_shader_stage_code.c_str();
9263 break;
9264
9265 default:
9266 TCU_FAIL("Invalid shader stage");
9267 }
9268
9269 /* Build program */
9270 program_object_id =
9271 BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
9272 geometry_shader_code, fragment_shader_code, &is_program_built);
9273
9274 /* Check if program was built */
9275 if (false == is_program_built)
9276 {
9277 throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__);
9278 }
9279
9280 /* Done */
9281 return program_object_id;
9282 }
9283
9284 /** Create texture to test given shader stage
9285 *
9286 * Throws exception in case of any failure
9287 *
9288 * @param stage Stage id
9289 *
9290 * @return Texture id
9291 **/
createTextureToTestShaderStage(shaderStage stage)9292 GLuint createTextureToTestShaderStage(shaderStage stage)
9293 {
9294 GLenum error = glGetError();
9295 const GLint max_image_uniforms = getMaximumImageUniformsForStage(stage);
9296 GLuint texture_id = 0;
9297 std::vector<GLint> texture_data;
9298
9299 const GLsizei height = 2;
9300 const GLsizei width = max_image_uniforms;
9301
9302 if (m_min_required_image_uniforms > max_image_uniforms)
9303 {
9304 return 0;
9305 }
9306
9307 /* Generate texture id */
9308 glGenTextures(1, &texture_id);
9309 GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures");
9310
9311 /* Bind texture */
9312 glBindTexture(GL_TEXTURE_2D, texture_id);
9313 error = glGetError();
9314 if (GL_NO_ERROR != error)
9315 {
9316 glDeleteTextures(1, &texture_id);
9317 GLU_EXPECT_NO_ERROR(error, "BindTexture");
9318 }
9319
9320 /* Prepare storage for texture data */
9321 texture_data.resize(width * height);
9322 for (GLint i = 0; i < max_image_uniforms; ++i)
9323 {
9324 texture_data[i] = getExpectedValue(i);
9325 texture_data[i + width] = 0;
9326 }
9327
9328 /* Create first level of texture */
9329 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R32I, width, height, 0 /*border */, GL_RED_INTEGER, GL_INT,
9330 &texture_data[0]);
9331 error = glGetError();
9332 if (GL_NO_ERROR != error)
9333 {
9334 glDeleteTextures(1, &texture_id);
9335 GLU_EXPECT_NO_ERROR(error, "TexImage2D");
9336 }
9337
9338 /* Make texture complete */
9339 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
9340 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
9341 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9342 error = glGetError();
9343 if (GL_NO_ERROR != error)
9344 {
9345 glDeleteTextures(1, &texture_id);
9346 GLU_EXPECT_NO_ERROR(error, "TexParameteri");
9347 }
9348
9349 /* Done */
9350 return texture_id;
9351 }
9352
9353 /** Get value of texel for image at given index
9354 *
9355 * @param index Index of image uniform
9356 *
9357 * @return Value of texel
9358 **/
getExpectedValue(GLint index)9359 GLint getExpectedValue(GLint index)
9360 {
9361 // To fix denorm issues with r32f, rg16f and r11f_g11f_b10f
9362 // we set one bit in the exponent of each component of those pixel format
9363 return 0x40104200 + index;
9364 }
9365
9366 /** Get name of uniform at given index
9367 *
9368 * @param index Index of uniform
9369 * @param out_name Name of uniform
9370 **/
getImageUniformName(GLuint index,std::string & out_name)9371 void getImageUniformName(GLuint index, std::string& out_name)
9372 {
9373 std::stringstream stream;
9374
9375 writeImageUniformNameToStream(stream, index);
9376
9377 out_name = stream.str();
9378 }
9379
9380 /** Get maximum number of image uniforms allowed for given shader stage
9381 *
9382 * @param stage Stage id
9383 *
9384 * @return Maximum allowed image uniforms
9385 **/
getMaximumImageUniformsForStage(shaderStage stage)9386 GLint getMaximumImageUniformsForStage(shaderStage stage)
9387 {
9388 GLint max_image_uniforms = 0;
9389 GLenum pname = 0;
9390
9391 switch (stage)
9392 {
9393 case fragmentShaderStage:
9394 pname = GL_MAX_FRAGMENT_IMAGE_UNIFORMS;
9395 break;
9396
9397 case geometryShaderStage:
9398 pname = GL_MAX_GEOMETRY_IMAGE_UNIFORMS;
9399 break;
9400
9401 case tesselationControlShaderStage:
9402 pname = GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS;
9403 break;
9404
9405 case tesselationEvalutaionShaderStage:
9406 pname = GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS;
9407 break;
9408
9409 case vertexShaderStage:
9410 pname = GL_MAX_VERTEX_IMAGE_UNIFORMS;
9411 break;
9412
9413 default:
9414 TCU_FAIL("Invalid shader stage");
9415 }
9416
9417 glGetIntegerv(pname, &max_image_uniforms);
9418 GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv");
9419
9420 return max_image_uniforms;
9421 }
9422
9423 /** Prepare source for tested shader stage
9424 *
9425 * @param stage Stage id
9426 * @param out_code Source code
9427 **/
prepareShaderForTestedShaderStage(shaderStage stage,std::string & out_code)9428 void prepareShaderForTestedShaderStage(shaderStage stage, std::string& out_code)
9429 {
9430 GLint max_image_uniforms = getMaximumImageUniformsForStage(stage);
9431 const char* stage_specific_layout = "";
9432 const char* stage_specific_predicate = "true";
9433 std::stringstream stream;
9434
9435 if (m_min_required_image_uniforms > max_image_uniforms)
9436 {
9437 return;
9438 }
9439
9440 /* Expected result follows
9441 *
9442 * #version 400 core
9443 * #extension GL_ARB_shader_image_load_store : require
9444 *
9445 * precision highp float;
9446 *
9447 * stage_specific_layout goes here
9448 *
9449 * Uniform declarations go here
9450 *
9451 * void main()
9452 * {
9453 * const ivec2 row_0_coordinates(0, 0);
9454 * const ivec2 row_1_coordinates(0, 1);
9455 *
9456 * For each index <0, GL_MAX_*_IMAGE_UNIFORMS>
9457 *
9458 * vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates);
9459 *
9460 * imageStore(u_image_0, row_0_coordinates, -loaded_value_0);
9461 * imageStore(u_image_0, row_1_coordinates, loaded_value_0);
9462 * }
9463 */
9464
9465 /* Get piece of code specific for stage */
9466 switch (stage)
9467 {
9468 case fragmentShaderStage:
9469 break;
9470
9471 case geometryShaderStage:
9472 stage_specific_layout = "layout(points) in;\n"
9473 "layout(points, max_vertices = 1) out;\n"
9474 "\n";
9475 break;
9476
9477 case tesselationControlShaderStage:
9478 stage_specific_layout = "layout(vertices = 4) out;\n"
9479 "\n";
9480 stage_specific_predicate = "gl_InvocationID == 0";
9481 break;
9482
9483 case tesselationEvalutaionShaderStage:
9484 stage_specific_layout = "layout(quads, equal_spacing, ccw) in;\n"
9485 "\n";
9486 break;
9487
9488 case vertexShaderStage:
9489 break;
9490
9491 default:
9492 TCU_FAIL("Invalid shader stage");
9493 }
9494
9495 /* Preamble */
9496 stream << "#version 400 core\n"
9497 "#extension GL_ARB_shader_image_load_store : require\n"
9498 "\n"
9499 "precision highp float;\n"
9500 "\n"
9501 << stage_specific_layout;
9502
9503 /* Image uniforms declarations */
9504 for (GLint i = 0; i < max_image_uniforms; ++i)
9505 {
9506 stream << imageUniformDeclaration(i) << "\n";
9507 }
9508
9509 /* Main opening */
9510 stream << "\n"
9511 "void main()\n"
9512 "{\n";
9513
9514 stream << " if (" << stage_specific_predicate << ")\n";
9515 stream << " {\n";
9516
9517 /* imageLoad and imageStores for each uniform */
9518 for (GLint i = 0; i < max_image_uniforms; ++i)
9519 {
9520 stream << " " << coordinatesVariableDeclaration(i, 0) << "\n"
9521 << " " << coordinatesVariableDeclaration(i, 1) << "\n"
9522 << "\n"
9523 << " " << imageLoadCall(i) << "\n"
9524 << "\n"
9525 << " " << imageStoreCall(i, 0) << "\n"
9526 << " " << imageStoreCall(i, 1) << "\n";
9527
9528 if (max_image_uniforms > i + 1)
9529 {
9530 stream << "\n";
9531 }
9532 }
9533
9534 stream << " }\n";
9535
9536 /* Main closing */
9537 stream << "}\n\n";
9538
9539 /* Done */
9540 out_code = stream.str();
9541 }
9542
9543 /** Test given shader stage
9544 *
9545 * @param stage Stage id
9546 *
9547 * @return m_test_not_supported if shader stage does not support at least m_min_required_image_uniforms image uniforms;
9548 * testFailed when test result is negative;
9549 * m_test_passed when test result is positive;
9550 **/
testShaderStage(shaderStage stage)9551 testResult testShaderStage(shaderStage stage)
9552 {
9553 std::string image_uniform_name;
9554 static const GLint invalid_uniform_location = -1;
9555 const GLint max_image_uniforms = getMaximumImageUniformsForStage(stage);
9556 GLenum primitive_mode = GL_POINTS;
9557 GLuint program_id = 0;
9558 testResult result = testPassed;
9559 std::vector<GLint> texture_data;
9560 GLuint texture_id = 0;
9561
9562 static const GLuint height = 2;
9563 const GLuint width = max_image_uniforms;
9564
9565 const GLuint positive_value_index = width;
9566 static const GLuint negated_value_index = 0;
9567
9568 if (m_min_required_image_uniforms > max_image_uniforms)
9569 {
9570 return testNotSupported;
9571 }
9572
9573 /* Select program and texture ids for given stage */
9574 switch (stage)
9575 {
9576 case fragmentShaderStage:
9577 program_id = m_program_to_test_fs_stage_id;
9578 texture_id = m_texture_to_test_fs_stage_id;
9579 break;
9580
9581 case geometryShaderStage:
9582 program_id = m_program_to_test_gs_stage_id;
9583 texture_id = m_texture_to_test_gs_stage_id;
9584 break;
9585
9586 case tesselationControlShaderStage:
9587 primitive_mode = GL_PATCHES;
9588 program_id = m_program_to_test_tcs_stage_id;
9589 texture_id = m_texture_to_test_tcs_stage_id;
9590 break;
9591
9592 case tesselationEvalutaionShaderStage:
9593 primitive_mode = GL_PATCHES;
9594 program_id = m_program_to_test_tes_stage_id;
9595 texture_id = m_texture_to_test_tes_stage_id;
9596 break;
9597
9598 case vertexShaderStage:
9599 program_id = m_program_to_test_vs_stage_id;
9600 texture_id = m_texture_to_test_vs_stage_id;
9601 break;
9602
9603 default:
9604 TCU_FAIL("Invalid shader stage");
9605 }
9606
9607 /* Set program */
9608 glUseProgram(program_id);
9609 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
9610
9611 /* Bind texture to image units */
9612 for (GLint i = 0; i < max_image_uniforms; ++i)
9613 {
9614 imageFormatDetails format_details;
9615 getImageUniformDeclarationDetails(i, format_details);
9616
9617 glBindImageTexture(i /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
9618 GL_READ_WRITE, format_details.m_image_unit_format);
9619 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
9620 }
9621
9622 /* Set all image uniforms to corresponding image units */
9623 for (GLint i = 0; i < max_image_uniforms; ++i)
9624 {
9625 /* Get name */
9626 getImageUniformName(i, image_uniform_name);
9627
9628 /* Get location */
9629 GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name.c_str());
9630 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
9631
9632 if (invalid_uniform_location == image_uniform_location)
9633 {
9634 throw tcu::InternalError("Uniform location is not available", image_uniform_name.c_str(), __FILE__,
9635 __LINE__);
9636 }
9637
9638 /* Set uniform value */
9639 glUniform1i(image_uniform_location, i /* image_unit */);
9640 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
9641 }
9642
9643 /* Execute draw */
9644 glDrawArrays(primitive_mode, 0 /* first vertex */, 1 /* one vertex */);
9645 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
9646
9647 glMemoryBarrier(GL_ALL_BARRIER_BITS);
9648
9649 texture_data.resize(width * height);
9650
9651 /* Get texture data */
9652 glBindTexture(GL_TEXTURE_2D, texture_id);
9653 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
9654
9655 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_INT, &texture_data[0]);
9656 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
9657
9658 /* Verify each image uniform */
9659 for (GLint i = 0; i < max_image_uniforms; ++i)
9660 {
9661 imageFormatDetails format_details;
9662 getImageUniformDeclarationDetails(i, format_details);
9663
9664 if (false ==
9665 format_details.m_verification_routine(getExpectedValue(i), texture_data[positive_value_index + i],
9666 texture_data[negated_value_index + i]))
9667 {
9668 m_context.getTestContext().getLog()
9669 << tcu::TestLog::Message << "Invalid result!"
9670 << " Image format: " << format_details.m_image_format << " Original value: "
9671 << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16) << getExpectedValue(i)
9672 << " Copied value: "
9673 << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16)
9674 << texture_data[positive_value_index + i] << " Negated value: "
9675 << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16)
9676 << texture_data[negated_value_index + i] << tcu::TestLog::EndMessage;
9677
9678 result = testFailed;
9679 }
9680 }
9681
9682 /* Done */
9683 return result;
9684 }
9685
9686 /** Verifies if original_value, positive_value and negated_value match
9687 *
9688 * @tparam T Type used during verification process, it should match float values by size
9689 *
9690 * @param original_value Original value of texel, used when creating a texture
9691 * @param positive_value Value stored by shader as read
9692 * @param negated_value Value stored by shader after negation
9693 *
9694 * @return true if values match, false otherwise
9695 **/
9696 template <typename T>
verifyFloat(GLint original_value,GLint positive_value,GLint negated_value)9697 static bool verifyFloat(GLint original_value, GLint positive_value, GLint negated_value)
9698 {
9699 if (original_value != positive_value)
9700 {
9701 return false;
9702 }
9703
9704 static const GLuint n_elements = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */
9705 static const GLuint sign_bit_index = sizeof(T) * 8 - 1; /* 7, 15, 31 */
9706 static const T sign_bit_mask = 1 << sign_bit_index; /* 0x80.. */
9707 static const T sign_bit_inv_mask = (T)~sign_bit_mask; /* 0x7f.. */
9708
9709 const T* positive_elements = (T*)&positive_value;
9710 const T* negated_elements = (T*)&negated_value;
9711
9712 for (GLuint i = 0; i < n_elements; ++i)
9713 {
9714 const T positive_element = positive_elements[i];
9715 const T negated_element = negated_elements[i];
9716
9717 const T positive_sign_bit = positive_element & sign_bit_mask;
9718 const T negated_sign_bit = negated_element & sign_bit_mask;
9719
9720 const T positive_data = positive_element & sign_bit_inv_mask;
9721 const T negated_data = negated_element & sign_bit_inv_mask;
9722
9723 /* Compare data bits */
9724 if (positive_data != negated_data)
9725 {
9726 return false;
9727 }
9728
9729 /* Verify that sign bit is inverted */
9730 if (positive_sign_bit == negated_sign_bit)
9731 {
9732 return false;
9733 }
9734 }
9735
9736 return true;
9737 }
9738
9739 /** Verifies if original_value, positive_value and negated_value match
9740 *
9741 * @tparam T Type used during verification process, it should match float values by size
9742 *
9743 * @param original_value Original value of texel, used when creating a texture
9744 * @param positive_value Value stored by shader as read
9745 * @param negated_value Value stored by shader after negation
9746 *
9747 * @return true if values match, false otherwise
9748 **/
9749 template <typename T>
verifyFloatSignedNorm(GLint original_value,GLint positive_value,GLint negated_value)9750 static bool verifyFloatSignedNorm(GLint original_value, GLint positive_value, GLint negated_value)
9751 {
9752 if (original_value != positive_value)
9753 {
9754 return false;
9755 }
9756
9757 static const GLuint n_elements = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */
9758
9759 const T* positive_elements = (T*)&positive_value;
9760 const T* negated_elements = (T*)&negated_value;
9761
9762 for (GLuint i = 0; i < n_elements; ++i)
9763 {
9764 const T positive_element = positive_elements[i];
9765 const T negated_element = negated_elements[i];
9766
9767 /* Compare data bits */
9768 if (positive_element != -negated_element)
9769 {
9770 return false;
9771 }
9772 }
9773
9774 return true;
9775 }
9776
9777 /** Verifies if original_value, positive_value and negated_value match
9778 *
9779 * @tparam R Number of bits for red channel
9780 * @tparam G Number of bits for green channel
9781 * @tparam B Number of bits for blue channel
9782 * @tparam A Number of bits for alpha channel
9783 *
9784 * @param original_value Original value of texel, used when creating a texture
9785 * @param positive_value Value stored by shader as read
9786 * @param negated_value Value stored by shader after negation
9787 *
9788 * @return true if values match, false otherwise
9789 **/
9790 template <GLuint R, GLuint G, GLuint B, GLuint A, typename T>
verifyInteger(GLint original_value,GLint positive_value,GLint negated_value)9791 static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value)
9792 {
9793 if (original_value != positive_value)
9794 {
9795 return false;
9796 }
9797
9798 Integer<T, R, 0> positive_red(positive_value);
9799 Integer<T, R, 0> negated_red(negated_value);
9800
9801 Integer<T, G, R> positive_green(positive_value);
9802 Integer<T, G, R> negated_green(negated_value);
9803
9804 Integer<T, B, R + G> positive_blue(positive_value);
9805 Integer<T, B, R + G> negated_blue(negated_value);
9806
9807 Integer<T, A, R + G + B> positive_alpha(positive_value);
9808 Integer<T, A, R + G + B> negated_alpha(negated_value);
9809
9810 if (((0 != R) && (positive_red.GetNegated() != negated_red.Get())) ||
9811 ((0 != B) && (positive_blue.GetNegated() != negated_blue.Get())) ||
9812 ((0 != G) && (positive_green.GetNegated() != negated_green.Get())) ||
9813 ((0 != A) && (positive_alpha.GetNegated() != negated_alpha.Get())))
9814 {
9815 return false;
9816 }
9817
9818 return true;
9819 }
9820
9821 /** Verifies if original_value, positive_value and negated_value match
9822 *
9823 * @param original_value Original value of texel, used when creating a texture
9824 * @param positive_value Value stored by shader as read
9825 * @param negated_value Value stored by shader after negation
9826 *
9827 * @return true if values match, false otherwise
9828 **/
verifyInteger(GLint original_value,GLint positive_value,GLint negated_value)9829 static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value)
9830 {
9831 if (original_value != positive_value)
9832 {
9833 return false;
9834 }
9835
9836 if (positive_value != -negated_value)
9837 {
9838 return false;
9839 }
9840
9841 return true;
9842 }
9843
9844 /** Verifies if original_value, positive_value and negated_value match
9845 *
9846 * @param original_value Original value of texel, used when creating a texture
9847 * @param positive_value Value stored by shader as read
9848 * @param negated_value Value stored by shader after negation
9849 *
9850 * @return true if values match, false otherwise
9851 **/
9852 template <typename T>
verifyFloatUnsigned(GLint original_value,GLint positive_value,GLint negated_value)9853 static bool verifyFloatUnsigned(GLint original_value, GLint positive_value, GLint negated_value)
9854 {
9855 if (original_value != positive_value)
9856 {
9857 return false;
9858 }
9859
9860 if (0 != negated_value)
9861 {
9862 return false;
9863 }
9864
9865 return true;
9866 }
9867 };
9868
9869 /** Test "Early fragment tests" description follows.
9870 *
9871 * BasicGLSLEarlyFragTests verifies that:
9872 * - early z test is applied when enabled,
9873 * - early z test is not applied when disabled.
9874 *
9875 * Proposed modifications:
9876 * - verify that early z test does not discard all fragments when enabled,
9877 * - verify that early stencil test is applied when enabled,
9878 * - verify that early stencil test does not discard all fragments when
9879 * enabled,
9880 * - verify that early stencil test is not applied when disabled.
9881 *
9882 * Steps:
9883 * - prepare 2 programs that store 1.0 at red channel to image in fragment
9884 * shader stage:
9885 * a) one program should enable early fragment tests
9886 * ("layout(early_fragment_tests) in;"),
9887 * b) second program should disable early fragment tests,
9888 * - prepare frame buffer with 64x64 R32F color and GL_DEPTH_STENCIL
9889 * depth-stencil attachments,
9890 * - prepare 2D texture 64x64 R32F,
9891 * - enable depth test,
9892 * - verify that early z test is applied when enabled:
9893 * - use program enabling early fragment tests,
9894 * - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9895 * - fill texture with zeros,
9896 * - bind texture to image uniform,
9897 * - draw "full screen" quad (left bottom corner at -1,-1 and right top
9898 * corner at 1,1) at z: 0.75
9899 * - verify that texture is still filled with zeros,
9900 * - verify that early z test does not discard all fragments:
9901 * - use program enabling early fragment tests,
9902 * - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9903 * - fill texture with zeros,
9904 * - bind texture to image uniform,
9905 * - draw "full screen" quad at z: 0.25
9906 * - verify that texture is now filled with 1.0,
9907 * -verify that early z test is not applied when disabled:
9908 * - use program disabling early fragment tests,
9909 * - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9910 * - fill texture with zeros,
9911 * - bind texture to image uniform,
9912 * - draw "full screen" quad at z: 0.75
9913 * - verify that texture is now filled with 1.0.
9914 * - disable depth test
9915 * - enable stencil test
9916 * - verify that early stencil test is applied when enabled:
9917 * - use program enabling early fragment tests,
9918 * - clean frame buffer with color: 0, stencil: 0 and depth 1,
9919 * - fill texture with zeros,
9920 * - set stencil test to:
9921 * - <func> to GL_LESS,
9922 * - <ref> to 128,
9923 * - <mask> 0xffffffff,
9924 * - bind texture to image uniform,
9925 * - draw "full screen" quad at z: 0,
9926 * - verify that texture is still filled with zeros,
9927 * - verify that early stencil test does not discard all fragments:
9928 * - use program enabling early fragment tests,
9929 * - clean frame buffer with color: 0, stencil: 128 and depth 1,
9930 * - fill texture with zeros,
9931 * - set stencil test to:
9932 * - <func> to GL_LESS,
9933 * - <ref> to 0,
9934 * - <mask> 0xffffffff,
9935 * - bind texture to image uniform,
9936 * - draw "full screen" quad at z: 0,
9937 * - verify that texture is now filled with 1.0,
9938 * - verify that early stencil test is not applied when disabled:
9939 * - use program disabling early fragment tests,
9940 * - clean frame buffer with color: 0, stencil: 0 and depth 1,
9941 * - fill texture with zeros,
9942 * - set stencil test to:
9943 * - <func> to GL_LESS,
9944 * - <ref> to 128,
9945 * - <mask> 0xffffffff,
9946 * - bind texture to image uniform,
9947 * - draw "full screen" quad at z: 0,
9948 * - verify that texture is now filled with 1.0
9949 **/
9950 class ImageLoadStoreEarlyFragmentTestsTest : public ShaderImageLoadStoreBase
9951 {
9952 private:
9953 /* Constants */
9954 GLuint m_image_edge;
9955 static const GLint m_invalid_uniform_location = -1;
9956
9957 /* Types */
9958 /** Store id and uniform locations for a single program object
9959 *
9960 **/
9961 struct programDetails
9962 {
9963 GLint m_depth_uniform_location;
9964 GLint m_image_uniform_location;
9965 GLuint m_program_id;
9966
programDetailsgl4cts::__anonb00615420111::ImageLoadStoreEarlyFragmentTestsTest::programDetails9967 programDetails()
9968 : m_depth_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location)
9969 , m_image_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location)
9970 , m_program_id(0)
9971 {
9972 /* Nothing to be done here */
9973 }
9974 };
9975
9976 /* Fileds */
9977 /* Storage for texture data */
9978 std::vector<GLfloat> m_clean_texture_data;
9979 std::vector<GLfloat> m_extracted_texture_data;
9980
9981 /* Program details */
9982 programDetails m_disabled_early_tests;
9983 programDetails m_enabled_early_tests;
9984
9985 /* Ids of GL objects */
9986 GLuint m_color_renderbuffer_id;
9987 GLuint m_depth_stencil_renderbuffer_id;
9988 GLuint m_framebuffer_id;
9989 GLuint m_texture_id;
9990 GLuint m_vertex_array_object_id;
9991
9992 public:
9993 /* Constructor */
ImageLoadStoreEarlyFragmentTestsTest()9994 ImageLoadStoreEarlyFragmentTestsTest()
9995 : m_image_edge(0)
9996 , m_color_renderbuffer_id(0)
9997 , m_depth_stencil_renderbuffer_id(0)
9998 , m_framebuffer_id(0)
9999 , m_texture_id(0)
10000 , m_vertex_array_object_id(0)
10001 {
10002 /* Nothing to be done here */
10003 }
10004
10005 /* Methods inherited from SubcaseBase */
Cleanup()10006 virtual long Cleanup()
10007 {
10008 /* Restore defaults */
10009 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
10010 glBindRenderbuffer(GL_RENDERBUFFER, 0);
10011 glBindTexture(GL_TEXTURE_2D, 0);
10012 glBindVertexArray(0);
10013 glDisable(GL_DEPTH_TEST);
10014 glDisable(GL_STENCIL_TEST);
10015 glUseProgram(0);
10016
10017 /* Delete objects */
10018 if (0 != m_disabled_early_tests.m_program_id)
10019 {
10020 glDeleteProgram(m_disabled_early_tests.m_program_id);
10021 m_disabled_early_tests.m_program_id = 0;
10022 }
10023
10024 if (0 != m_enabled_early_tests.m_program_id)
10025 {
10026 glDeleteProgram(m_enabled_early_tests.m_program_id);
10027 m_enabled_early_tests.m_program_id = 0;
10028 }
10029
10030 if (0 != m_color_renderbuffer_id)
10031 {
10032 glDeleteRenderbuffers(1, &m_color_renderbuffer_id);
10033 m_color_renderbuffer_id = 0;
10034 }
10035
10036 if (0 != m_depth_stencil_renderbuffer_id)
10037 {
10038 glDeleteRenderbuffers(1, &m_depth_stencil_renderbuffer_id);
10039 m_depth_stencil_renderbuffer_id = 0;
10040 }
10041
10042 if (0 != m_framebuffer_id)
10043 {
10044 glDeleteFramebuffers(1, &m_framebuffer_id);
10045 m_framebuffer_id = 0;
10046 }
10047
10048 if (0 != m_texture_id)
10049 {
10050 glDeleteTextures(1, &m_texture_id);
10051 m_texture_id = 0;
10052 }
10053
10054 if (0 != m_vertex_array_object_id)
10055 {
10056 glDeleteVertexArrays(1, &m_vertex_array_object_id);
10057 m_vertex_array_object_id = 0;
10058 }
10059
10060 /* Done */
10061 return NO_ERROR;
10062 }
10063
Run()10064 virtual long Run()
10065 {
10066 bool result = true;
10067
10068 /* Bind texture to first image unit */
10069 glBindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
10070 GL_READ_WRITE, GL_R32F);
10071 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
10072
10073 /* Run tests for depth test */
10074 if (false == testEarlyZ())
10075 {
10076 result = false;
10077 }
10078
10079 /* Run tests for stencil test */
10080 if (false == testEarlyStencil())
10081 {
10082 result = false;
10083 }
10084
10085 /* Return ERROR if any problem was found */
10086 if (false == result)
10087 {
10088 return ERROR;
10089 }
10090
10091 /* Done */
10092 return NO_ERROR;
10093 }
10094
Setup()10095 virtual long Setup()
10096 {
10097 m_image_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
10098
10099 /* Prepare storage for texture data */
10100 m_clean_texture_data.resize(m_image_edge * m_image_edge);
10101 m_extracted_texture_data.resize(m_image_edge * m_image_edge);
10102
10103 /* Prepare programs, framebuffer and texture */
10104 buildPrograms();
10105 createFramebuffer();
10106 createTexture();
10107
10108 /* Generate vertex array object */
10109 glGenVertexArrays(1, &m_vertex_array_object_id);
10110 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
10111
10112 /* Bind vertex array object */
10113 glBindVertexArray(m_vertex_array_object_id);
10114 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
10115
10116 /* Set clear color */
10117 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
10118 GLU_EXPECT_NO_ERROR(glGetError(), "ClearColor");
10119
10120 /* Done */
10121 return NO_ERROR;
10122 }
10123
10124 private:
10125 /** Build two programs: with enabled and disabled early fragment tests
10126 *
10127 **/
buildPrograms()10128 void buildPrograms()
10129 {
10130 static const char* const fragment_shader_with_disabled_early_tests =
10131 "#version 400 core\n"
10132 "#extension GL_ARB_shader_image_load_store : require\n"
10133 "\n"
10134 "precision highp float;\n"
10135 "\n"
10136 "layout(r32f) uniform image2D u_image;\n"
10137 "\n"
10138 "void main()\n"
10139 "{\n"
10140 " vec4 color = vec4(1.0, 0, 0, 0);\n"
10141 "\n"
10142 " imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n"
10143 "\n"
10144 " discard;\n"
10145 "}\n\n";
10146
10147 static const char* const fragment_shader_with_enabled_early_tests =
10148 "#version 400 core\n"
10149 "#extension GL_ARB_shader_image_load_store : require\n"
10150 "\n"
10151 "precision highp float;\n"
10152 "\n"
10153 "layout(early_fragment_tests) in;\n"
10154 "\n"
10155 "layout(r32f) uniform image2D u_image;\n"
10156 "\n"
10157 "void main()\n"
10158 "{\n"
10159 " vec4 color = vec4(1.0, 0, 0, 0);\n"
10160 "\n"
10161 " imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n"
10162 "\n"
10163 " discard;\n"
10164 "}\n\n";
10165
10166 static const char* const geometry_shader_code = "#version 400 core\n"
10167 "#extension GL_ARB_shader_image_load_store : require\n"
10168 "\n"
10169 "precision highp float;\n"
10170 "\n"
10171 "layout(points) in;\n"
10172 "layout(triangle_strip, max_vertices = 4) out;\n"
10173 "\n"
10174 "uniform float u_depth;\n"
10175 "\n"
10176 "void main()\n"
10177 "{\n"
10178 " // Left-bottom\n"
10179 " gl_Position = vec4(-1, -1, u_depth, 1);\n"
10180 " EmitVertex();\n"
10181 "\n"
10182 " // Left-top\n"
10183 " gl_Position = vec4(-1, 1, u_depth, 1);\n"
10184 " EmitVertex();\n"
10185 "\n"
10186 " // Right-bottom\n"
10187 " gl_Position = vec4( 1, -1, u_depth, 1);\n"
10188 " EmitVertex();\n"
10189 "\n"
10190 " // Right-top\n"
10191 " gl_Position = vec4( 1, 1, u_depth, 1);\n"
10192 " EmitVertex();\n"
10193 "}\n\n";
10194
10195 static const char* const vertex_shader_code = "#version 400 core\n"
10196 "#extension GL_ARB_shader_image_load_store : require\n"
10197 "\n"
10198 "precision highp float;\n"
10199 "\n"
10200 "void main()\n"
10201 "{\n"
10202 "}\n\n";
10203
10204 prepareProgramDetails(fragment_shader_with_disabled_early_tests, geometry_shader_code, vertex_shader_code,
10205 m_disabled_early_tests);
10206
10207 prepareProgramDetails(fragment_shader_with_enabled_early_tests, geometry_shader_code, vertex_shader_code,
10208 m_enabled_early_tests);
10209 }
10210
10211 /** Fill texture with zeros
10212 *
10213 **/
cleanTexture()10214 void cleanTexture()
10215 {
10216 glTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, m_image_edge, m_image_edge,
10217 GL_RED, GL_FLOAT, &m_clean_texture_data[0]);
10218 GLU_EXPECT_NO_ERROR(glGetError(), "TexSubImage2D");
10219 }
10220
10221 /** Create and bind (draw) framebuffer with color and depth-stencil attachments
10222 *
10223 **/
createFramebuffer()10224 void createFramebuffer()
10225 {
10226 /* Generate render buffers */
10227 glGenRenderbuffers(1, &m_color_renderbuffer_id);
10228 GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers");
10229
10230 glGenRenderbuffers(1, &m_depth_stencil_renderbuffer_id);
10231 GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers");
10232
10233 /* Generate and bind framebuffer object */
10234 glGenFramebuffers(1, &m_framebuffer_id);
10235 GLU_EXPECT_NO_ERROR(glGetError(), "GenFramebuffers");
10236
10237 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
10238 GLU_EXPECT_NO_ERROR(glGetError(), "BindFramebuffer");
10239
10240 /* Prepare color render buffer */
10241 glBindRenderbuffer(GL_RENDERBUFFER, m_color_renderbuffer_id);
10242 GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer");
10243
10244 glRenderbufferStorage(GL_RENDERBUFFER, GL_R32F, m_image_edge, m_image_edge);
10245 GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage");
10246
10247 /* Set up color attachment */
10248 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_color_renderbuffer_id);
10249 GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer");
10250
10251 /* Prepare depth-stencil render buffer */
10252 glBindRenderbuffer(GL_RENDERBUFFER, m_depth_stencil_renderbuffer_id);
10253 GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer");
10254
10255 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_image_edge, m_image_edge);
10256 GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage");
10257
10258 /* Set up depth-stencil attachment */
10259 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
10260 m_depth_stencil_renderbuffer_id);
10261 GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer");
10262 }
10263
10264 /** Create 2D R32F texture
10265 *
10266 **/
createTexture()10267 void createTexture()
10268 {
10269 glGenTextures(1, &m_texture_id);
10270 GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures");
10271
10272 glBindTexture(GL_TEXTURE_2D, m_texture_id);
10273 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
10274
10275 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, m_image_edge, m_image_edge);
10276 GLU_EXPECT_NO_ERROR(glGetError(), "TexStorage2D");
10277 }
10278
10279 /** Extracts red channel from texture and verify if all texels are set to specified value
10280 *
10281 * @param value Expected value
10282 *
10283 * @return true if all texel match expected value, false otherwise
10284 **/
isTextureFilledWithValue(GLfloat value)10285 bool isTextureFilledWithValue(GLfloat value)
10286 {
10287 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED, GL_FLOAT, &m_extracted_texture_data[0]);
10288 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
10289
10290 for (GLuint i = 0; i < m_image_edge * m_image_edge; ++i)
10291 {
10292 if (value != m_extracted_texture_data[i])
10293 {
10294 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texel at location " << i
10295 << " has invalid value: " << m_extracted_texture_data[i]
10296 << " expected: " << value << tcu::TestLog::EndMessage;
10297
10298 return false;
10299 }
10300 }
10301
10302 return true;
10303 }
10304
10305 /** Build program, extract location of uniforms and store results in programDetails instance
10306 *
10307 * Throws tcu::InternalError if uniforms are inactive
10308 *
10309 * @param fragment_shader_code Source of fragment shader
10310 * @param geometry_shader_code Source of geometry shader
10311 * @param vertex_shader_code Source of vertex shader
10312 * @param out_program_details Instance of programDetails
10313 **/
prepareProgramDetails(const char * fragment_shader_code,const char * geometry_shader_code,const char * vertex_shader_code,programDetails & out_program_details)10314 void prepareProgramDetails(const char* fragment_shader_code, const char* geometry_shader_code,
10315 const char* vertex_shader_code, programDetails& out_program_details)
10316 {
10317 static const char* const depth_uniform_name = "u_depth";
10318 static const char* const image_uniform_name = "u_image";
10319 bool is_program_built = true;
10320
10321 GLuint program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, geometry_shader_code,
10322 fragment_shader_code, &is_program_built);
10323
10324 if (false == is_program_built)
10325 {
10326 throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__);
10327 }
10328
10329 /* Get depth uniform location */
10330 GLint depth_uniform_location = glGetUniformLocation(program_id, depth_uniform_name);
10331 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
10332
10333 if (m_invalid_uniform_location == depth_uniform_location)
10334 {
10335 throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__);
10336 }
10337
10338 /* Get image uniform location */
10339 GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name);
10340 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
10341
10342 if (m_invalid_uniform_location == image_uniform_location)
10343 {
10344 throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__);
10345 }
10346
10347 /* Store results */
10348 out_program_details.m_depth_uniform_location = depth_uniform_location;
10349 out_program_details.m_image_uniform_location = image_uniform_location;
10350 out_program_details.m_program_id = program_id;
10351 }
10352
10353 /** Test if early fragment stencil test works as expected.
10354 *
10355 * @return true if successful, false otherwise
10356 **/
testEarlyStencil()10357 bool testEarlyStencil()
10358 {
10359 bool result = true;
10360
10361 glEnable(GL_STENCIL_TEST);
10362 GLU_EXPECT_NO_ERROR(glGetError(), "glEnable");
10363
10364 glClearDepthf(1.0f);
10365 GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf");
10366
10367 /* verify that early stencil test is applied when enabled */
10368 {
10369 glUseProgram(m_enabled_early_tests.m_program_id);
10370 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10371
10372 glClearStencil(0);
10373 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10374
10375 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10376 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10377
10378 cleanTexture();
10379
10380 glStencilFunc(GL_LESS, 128, 0xffffffff);
10381 GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10382
10383 glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10384 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10385
10386 glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.0f /* depth */);
10387 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10388
10389 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10390 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10391
10392 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10393 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10394
10395 if (false == isTextureFilledWithValue(0.0f))
10396 {
10397 m_context.getTestContext().getLog() << tcu::TestLog::Message
10398 << "Problem with early stencil test. It is not applied"
10399 << tcu::TestLog::EndMessage;
10400
10401 result = false;
10402 }
10403 }
10404
10405 /* verify that early stencil test does not discard all fragments */
10406 {
10407 glClearStencil(128);
10408 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10409
10410 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10411 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10412
10413 cleanTexture();
10414
10415 glStencilFunc(GL_LESS, 0, 0xffffffff);
10416 GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10417
10418 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10419 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10420
10421 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10422 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10423
10424 if (false == isTextureFilledWithValue(1.0f))
10425 {
10426 m_context.getTestContext().getLog()
10427 << tcu::TestLog::Message
10428 << "Problem with early stencil test. It discards fragments, that shall be drawn"
10429 << tcu::TestLog::EndMessage;
10430
10431 result = false;
10432 }
10433 }
10434
10435 /* verify that early stencil test is not applied when disabled */
10436 {
10437 glUseProgram(m_disabled_early_tests.m_program_id);
10438 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10439
10440 glClearStencil(0);
10441 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10442
10443 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10444 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10445
10446 cleanTexture();
10447
10448 glStencilFunc(GL_LESS, 128, 0xffffffff);
10449 GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10450
10451 glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10452 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10453
10454 glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.0f /* depth */);
10455 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10456
10457 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10458 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10459
10460 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10461 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10462
10463 if (false == isTextureFilledWithValue(1.0f))
10464 {
10465 m_context.getTestContext().getLog() << tcu::TestLog::Message
10466 << "Problem with early stencil test. It is applied when disabled"
10467 << tcu::TestLog::EndMessage;
10468
10469 result = false;
10470 }
10471 }
10472
10473 glDisable(GL_STENCIL_TEST);
10474 GLU_EXPECT_NO_ERROR(glGetError(), "Disable");
10475
10476 /* Done */
10477 return result;
10478 }
10479
10480 /** Test if early fragment depth test works as expected.
10481 *
10482 * @return true if successful, false otherwise
10483 **/
testEarlyZ()10484 bool testEarlyZ()
10485 {
10486 bool result = true;
10487
10488 glEnable(GL_DEPTH_TEST);
10489 GLU_EXPECT_NO_ERROR(glGetError(), "glEnable");
10490
10491 glClearDepthf(0.5f);
10492 GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf");
10493
10494 glClearStencil(0);
10495 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10496
10497 /* verify that early z test is applied when enabled */
10498 {
10499 glUseProgram(m_enabled_early_tests.m_program_id);
10500 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10501
10502 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10503 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10504
10505 cleanTexture();
10506
10507 glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10508 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10509
10510 glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.5f /* depth */);
10511 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10512
10513 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10514 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10515
10516 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10517 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10518
10519 if (false == isTextureFilledWithValue(0.0f))
10520 {
10521 m_context.getTestContext().getLog() << tcu::TestLog::Message
10522 << "Problem with early z test. It is not applied"
10523 << tcu::TestLog::EndMessage;
10524
10525 result = false;
10526 }
10527 }
10528
10529 /* verify that early z test does not discard all fragments */
10530 {
10531 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10532 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10533
10534 cleanTexture();
10535
10536 glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10537 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10538
10539 glUniform1f(m_enabled_early_tests.m_depth_uniform_location, -0.5f /* depth */);
10540 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10541
10542 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10543 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10544
10545 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10546 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10547
10548 if (false == isTextureFilledWithValue(1.0f))
10549 {
10550 m_context.getTestContext().getLog()
10551 << tcu::TestLog::Message << "Problem with early z test. It discards fragments, that shall be drawn"
10552 << tcu::TestLog::EndMessage;
10553
10554 result = false;
10555 }
10556 }
10557
10558 /* verify that early z test is not applied when disabled */
10559 {
10560 glUseProgram(m_disabled_early_tests.m_program_id);
10561 GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10562
10563 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10564 GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10565
10566 cleanTexture();
10567
10568 glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10569 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10570
10571 glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.5f /* depth */);
10572 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10573
10574 glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10575 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10576
10577 glMemoryBarrier(GL_ALL_BARRIER_BITS);
10578 GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10579
10580 if (false == isTextureFilledWithValue(1.0f))
10581 {
10582 m_context.getTestContext().getLog() << tcu::TestLog::Message
10583 << "Problem with early z test. It is applied when disabled"
10584 << tcu::TestLog::EndMessage;
10585
10586 result = false;
10587 }
10588 }
10589
10590 glDisable(GL_DEPTH_TEST);
10591 GLU_EXPECT_NO_ERROR(glGetError(), "Disable");
10592
10593 /* Done */
10594 return result;
10595 }
10596 };
10597
10598 //-----------------------------------------------------------------------------
10599 // 4.1 NegativeUniform
10600 //-----------------------------------------------------------------------------
10601 class NegativeUniform : public ShaderImageLoadStoreBase
10602 {
10603 GLuint m_program;
10604
Setup()10605 virtual long Setup()
10606 {
10607 m_program = 0;
10608 return NO_ERROR;
10609 }
10610
Run()10611 virtual long Run()
10612 {
10613 const char* glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
10614 " gl_Position = i_position;" NL "}";
10615 const char* glsl_fs = "#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL
10616 " ivec2 coord = ivec2(gl_FragCoord.xy);" NL " imageStore(g_image, coord, vec4(0.0));" NL
10617 " discard;" NL "}";
10618 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
10619
10620 GLint max_image_units;
10621 glGetIntegerv(GL_MAX_IMAGE_UNITS, &max_image_units);
10622 glUseProgram(m_program);
10623
10624 glUniform1i(glGetUniformLocation(m_program, "g_image"), -1);
10625 if (glGetError() != GL_INVALID_VALUE)
10626 {
10627 m_context.getTestContext().getLog()
10628 << tcu::TestLog::Message << "glUniform1i should generate INVALID_VALUE when <value> is less than zero."
10629 << tcu::TestLog::EndMessage;
10630 return ERROR;
10631 }
10632 glUniform1i(glGetUniformLocation(m_program, "g_image"), max_image_units);
10633 if (glGetError() != GL_INVALID_VALUE)
10634 {
10635 m_context.getTestContext().getLog()
10636 << tcu::TestLog::Message
10637 << "glUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the value of "
10638 << "MAX_IMAGE_UNITS." << tcu::TestLog::EndMessage;
10639 return ERROR;
10640 }
10641
10642 GLint i = -3;
10643 glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
10644 if (glGetError() != GL_INVALID_VALUE)
10645 {
10646 m_context.getTestContext().getLog()
10647 << tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is less than zero."
10648 << tcu::TestLog::EndMessage;
10649 return ERROR;
10650 }
10651 i = max_image_units + 1;
10652 glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
10653 if (glGetError() != GL_INVALID_VALUE)
10654 {
10655 m_context.getTestContext().getLog()
10656 << tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is greater "
10657 "than or equal to the value of MAX_IMAGE_UNITS."
10658 << tcu::TestLog::EndMessage;
10659 return ERROR;
10660 }
10661
10662 glUniform1ui(glGetUniformLocation(m_program, "g_image"), 0);
10663 if (glGetError() != GL_INVALID_OPERATION)
10664 {
10665 m_context.getTestContext().getLog()
10666 << tcu::TestLog::Message
10667 << "glUniform1iv should generate INVALID_OPERATION if the location refers to an image variable."
10668 << tcu::TestLog::EndMessage;
10669 return ERROR;
10670 }
10671 glUniform2i(glGetUniformLocation(m_program, "g_image"), 0, 0);
10672 if (glGetError() != GL_INVALID_OPERATION)
10673 {
10674 m_context.getTestContext().getLog()
10675 << tcu::TestLog::Message
10676 << "glUniform2i should generate INVALID_OPERATION if the location refers to an image variable."
10677 << tcu::TestLog::EndMessage;
10678 return ERROR;
10679 }
10680
10681 {
10682 glUseProgram(0);
10683
10684 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), -1);
10685 if (glGetError() != GL_INVALID_VALUE)
10686 {
10687 m_context.getTestContext().getLog()
10688 << tcu::TestLog::Message
10689 << "glProgramUniform1i should generate INVALID_VALUE when <value> is less than zero."
10690 << tcu::TestLog::EndMessage;
10691 return ERROR;
10692 }
10693 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), max_image_units);
10694 if (glGetError() != GL_INVALID_VALUE)
10695 {
10696 m_context.getTestContext().getLog()
10697 << tcu::TestLog::Message
10698 << "glProgramUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the "
10699 "value of MAX_IMAGE_UNITS."
10700 << tcu::TestLog::EndMessage;
10701 return ERROR;
10702 }
10703
10704 GLint ii = -3;
10705 glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii);
10706 if (glGetError() != GL_INVALID_VALUE)
10707 {
10708 m_context.getTestContext().getLog()
10709 << tcu::TestLog::Message
10710 << "glProgramUniform1iv should generate INVALID_VALUE when <value> is less than zero."
10711 << tcu::TestLog::EndMessage;
10712 return ERROR;
10713 }
10714 ii = max_image_units + 1;
10715 glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii);
10716 if (glGetError() != GL_INVALID_VALUE)
10717 {
10718 m_context.getTestContext().getLog()
10719 << tcu::TestLog::Message << "glProgramUniform1iv should generate INVALID_VALUE when <value> "
10720 "is greater than or equal to the value of MAX_IMAGE_UNITS."
10721 << tcu::TestLog::EndMessage;
10722 return ERROR;
10723 }
10724
10725 glProgramUniform1ui(m_program, glGetUniformLocation(m_program, "g_image"), 0);
10726 if (glGetError() != GL_INVALID_OPERATION)
10727 {
10728 m_context.getTestContext().getLog()
10729 << tcu::TestLog::Message << "glProgramUniform1ui should generate INVALID_OPERATION if the "
10730 "location refers to an image variable."
10731 << tcu::TestLog::EndMessage;
10732 return ERROR;
10733 }
10734 glProgramUniform2i(m_program, glGetUniformLocation(m_program, "g_image"), 0, 0);
10735 if (glGetError() != GL_INVALID_OPERATION)
10736 {
10737 m_context.getTestContext().getLog()
10738 << tcu::TestLog::Message << "glProgramUniform2i should generate INVALID_OPERATION if the "
10739 "location refers to an image variable."
10740 << tcu::TestLog::EndMessage;
10741 return ERROR;
10742 }
10743 }
10744
10745 return NO_ERROR;
10746 }
10747
Cleanup()10748 virtual long Cleanup()
10749 {
10750 glUseProgram(0);
10751 glDeleteProgram(m_program);
10752 return NO_ERROR;
10753 }
10754 };
10755 //-----------------------------------------------------------------------------
10756 // 4.2 NegativeBind
10757 //-----------------------------------------------------------------------------
10758 class NegativeBind : public ShaderImageLoadStoreBase
10759 {
Setup()10760 virtual long Setup()
10761 {
10762 return NO_ERROR;
10763 }
10764
Run()10765 virtual long Run()
10766 {
10767 glBindImageTexture(100, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
10768 if (glGetError() != GL_INVALID_VALUE)
10769 {
10770 m_context.getTestContext().getLog()
10771 << tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <unit> is "
10772 "greater than or equal to the value of MAX_IMAGE_UNITS."
10773 << tcu::TestLog::EndMessage;
10774 return ERROR;
10775 }
10776
10777 glBindImageTexture(0, 123, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
10778 if (glGetError() != GL_INVALID_VALUE)
10779 {
10780 m_context.getTestContext().getLog()
10781 << tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <texture> is not "
10782 "the name of an existing texture object."
10783 << tcu::TestLog::EndMessage;
10784 return ERROR;
10785 }
10786
10787 glBindImageTexture(1, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA + 1234);
10788 if (glGetError() != GL_INVALID_VALUE)
10789 {
10790 m_context.getTestContext().getLog()
10791 << tcu::TestLog::Message
10792 << "BindImageTexture should generate INVALID_VALUE if <format> is not a legal format."
10793 << tcu::TestLog::EndMessage;
10794 return ERROR;
10795 }
10796 return NO_ERROR;
10797 }
10798
Cleanup()10799 virtual long Cleanup()
10800 {
10801 return NO_ERROR;
10802 }
10803 };
10804 //-----------------------------------------------------------------------------
10805 // 4.3 NegativeCompileErrors
10806 //-----------------------------------------------------------------------------
10807 class NegativeCompileErrors : public ShaderImageLoadStoreBase
10808 {
Run()10809 virtual long Run()
10810 {
10811 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10812 "layout(rgba32f) writeonly readonly uniform image2D g_image;" NL "void main() {" NL
10813 " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10814 return ERROR;
10815
10816 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10817 "layout(rgba32f) writeonly uniform image2D g_image;" NL "void main() {" NL
10818 " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10819 return ERROR;
10820
10821 if (!Compile("#version 420 core" NL "in vec4 i_color;" NL "layout(location = 0) out vec4 o_color;" NL
10822 "layout(rgba32f) readonly uniform image2D g_image;" NL "void main() {" NL
10823 " imageStore(g_image, ivec2(0), i_color);" NL " o_color = i_color;" NL "}"))
10824 return ERROR;
10825
10826 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform image2D g_image;" NL
10827 "void main() {" NL " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10828 return ERROR;
10829
10830 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10831 "readonly uniform image2D g_image;" NL "void main() {" NL
10832 " o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10833 return ERROR;
10834
10835 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10836 "layout(rg16i) uniform image1D 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(rg16) uniform iimage2D g_image;" NL "void main() {" NL " o_color = vec4(1.0);" NL "}"))
10841 return ERROR;
10842
10843 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10844 "layout(r32f) coherent uniform image2D g_image;" NL "void main() {" NL
10845 " imageAtomicAdd(g_image, ivec2(1), 10);" NL " o_color = vec4(1.0);" NL "}"))
10846 return ERROR;
10847
10848 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10849 "layout(r16i) coherent uniform iimage2D g_image;" NL "void main() {" NL
10850 " imageAtomicAdd(g_image, ivec2(1), 1u);" NL " o_color = vec4(1.0);" NL "}"))
10851 return ERROR;
10852
10853 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10854 "layout(r32ui) uniform iimage3D g_image;" NL "void main() {" NL
10855 " imageStore(g_image, ivec3(1), ivec4(1));" NL " o_color = vec4(1.0);" NL "}"))
10856 return ERROR;
10857
10858 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10859 "layout(rgba8) uniform uimage2DArray g_image;" NL "void main() {" NL
10860 " imageStore(g_image, ivec3(0), uvec4(1));" NL " o_color = vec4(1.0);" NL "}"))
10861 return ERROR;
10862
10863 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10864 "layout(rgba32f) coherent uniform image2D g_image;" NL "vec4 Load(image2D image) {" NL
10865 " return imageLoad(image, vec2(0));" NL "}" NL "void main() {" NL " o_color = Load(g_image);" NL
10866 "}"))
10867 return ERROR;
10868
10869 return NO_ERROR;
10870 }
10871
Compile(const std::string & source)10872 bool Compile(const std::string& source)
10873 {
10874 const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
10875
10876 const char* const src = source.c_str();
10877 glShaderSource(sh, 1, &src, NULL);
10878 glCompileShader(sh);
10879
10880 GLchar log[1024];
10881 glGetShaderInfoLog(sh, sizeof(log), NULL, log);
10882 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
10883 << log << tcu::TestLog::EndMessage;
10884
10885 GLint status;
10886 glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
10887 glDeleteShader(sh);
10888
10889 if (status == GL_TRUE)
10890 {
10891 m_context.getTestContext().getLog()
10892 << tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage;
10893 return false;
10894 }
10895
10896 return true;
10897 }
10898 };
10899 //-----------------------------------------------------------------------------
10900 // 4.4 NegativeLinkErrors
10901 //-----------------------------------------------------------------------------
10902 class NegativeLinkErrors : public ShaderImageLoadStoreBase
10903 {
Run()10904 virtual long Run()
10905 {
10906 if (!SupportedInVS(1))
10907 return NOT_SUPPORTED;
10908
10909 if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
10910 "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL
10911 " imageStore(g_image, gl_VertexID, vec4(0));" NL " gl_Position = i_position;" NL "}",
10912 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10913 "layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL
10914 " imageStore(g_image, ivec2(gl_FragCoord), vec4(1.0));" NL " o_color = vec4(1.0);" NL "}"))
10915 return ERROR;
10916
10917 if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
10918 "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL
10919 " imageStore(g_image, gl_VertexID, vec4(0));" NL " gl_Position = i_position;" NL "}",
10920 "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10921 "layout(rg32f) uniform image1D g_image;" NL "void main() {" NL
10922 " imageStore(g_image, int(gl_FragCoord.x), vec4(1.0));" NL " o_color = vec4(1.0);" NL "}"))
10923 return ERROR;
10924
10925 return NO_ERROR;
10926 }
10927
Link(const std::string & vs,const std::string & fs)10928 bool Link(const std::string& vs, const std::string& fs)
10929 {
10930 const GLuint p = glCreateProgram();
10931
10932 const GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
10933 glAttachShader(p, vsh);
10934 glDeleteShader(vsh);
10935 const char* const vssrc = vs.c_str();
10936 glShaderSource(vsh, 1, &vssrc, NULL);
10937 glCompileShader(vsh);
10938
10939 const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
10940 glAttachShader(p, fsh);
10941 glDeleteShader(fsh);
10942 const char* const fssrc = fs.c_str();
10943 glShaderSource(fsh, 1, &fssrc, NULL);
10944 glCompileShader(fsh);
10945
10946 GLint status;
10947 glGetShaderiv(vsh, GL_COMPILE_STATUS, &status);
10948 if (status == GL_FALSE)
10949 {
10950 glDeleteProgram(p);
10951 m_context.getTestContext().getLog()
10952 << tcu::TestLog::Message << "VS compilation should be ok." << tcu::TestLog::EndMessage;
10953 return false;
10954 }
10955 glGetShaderiv(fsh, GL_COMPILE_STATUS, &status);
10956 if (status == GL_FALSE)
10957 {
10958 glDeleteProgram(p);
10959 m_context.getTestContext().getLog()
10960 << tcu::TestLog::Message << "FS compilation should be ok." << tcu::TestLog::EndMessage;
10961 return false;
10962 }
10963
10964 glLinkProgram(p);
10965
10966 GLchar log[1024];
10967 glGetProgramInfoLog(p, sizeof(log), NULL, log);
10968 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
10969 << log << tcu::TestLog::EndMessage;
10970
10971 glGetProgramiv(p, GL_LINK_STATUS, &status);
10972 glDeleteProgram(p);
10973
10974 if (status == GL_TRUE)
10975 {
10976 m_context.getTestContext().getLog()
10977 << tcu::TestLog::Message << "Link operation should fail." << tcu::TestLog::EndMessage;
10978 return false;
10979 }
10980
10981 return true;
10982 }
10983 };
10984
10985 /** Negative Test "Active image uniform limits", description follows.
10986 *
10987 * Program that exceeds resource limits should not compile and/or link.
10988 *
10989 * Steps:
10990 * - try to compile and link a program that uses too many image uniforms in
10991 * fragment shader stage,
10992 * - try to compile and link a program that uses too many image uniforms in
10993 * vertex shader stage,
10994 * - try to compile and link a program that uses too many image uniforms in
10995 * tessellation control shader stage,
10996 * - try to compile and link a program that uses too many image uniforms in
10997 * tessellation evaluation shader stage,
10998 * - try to compile and link a program that uses too many image uniforms in
10999 * geometry shader stage,
11000 * - try to compile and link a program that uses too many image uniforms in all
11001 * shader stages combined, any single stage should not exceed its limits, this
11002 * step might be impossible to fulfill.
11003 *
11004 * Test should use the following declaration of image uniforms:
11005 * layout(r32i) uniform iimage2D u_image[N_UNIFORMS];
11006 *
11007 * For cases where limit for single stage is tested, N_UNIFORMS should be
11008 * defined as gl_Max*ImageUniforms + 1, where gl_Max*ImageUniforms is constant
11009 * corresponding to tested shader stage.
11010 *
11011 * For case where limit for combined stages is tested:
11012 * - u_image name should be appended with the name of shader stage, like
11013 * u_image_vertex,
11014 * - N_UNIFORMS should be defined as gl_Max*ImageUniforms, where
11015 * gl_Max*ImageUniforms is constant corresponding to tested shader stage,
11016 * - compilation and linking shall succeed, when sum of all
11017 * gl_Max*ImageUniforms corresponding to shader stages is equal (or less) to
11018 * gl_MaxCombinedImageUniforms.
11019 *
11020 * All defined image uniforms have to be active. Each shader stage that declare
11021 * image uniforms should include following code snippet:
11022 * value = 1;
11023 * for (int i = 0; i < N_UNIFORMS; ++i)
11024 * {
11025 * value = imageAtomicAdd(u_image[i], coord, value);
11026 * }
11027 **/
11028 class ImageLoadStoreUniformLimitsTest : public ShaderImageLoadStoreBase
11029 {
11030 private:
11031 /* Fields */
11032 /* Results */
11033 bool m_result_for_combined;
11034 bool m_result_for_fragment_shader;
11035 bool m_result_for_geometry_shader;
11036 bool m_result_for_tesselation_control_shader;
11037 bool m_result_for_tesselatioon_evaluation_shader;
11038 bool m_result_for_vertex_shader;
11039
11040 public:
11041 /* Constructor */
ImageLoadStoreUniformLimitsTest()11042 ImageLoadStoreUniformLimitsTest()
11043 : m_result_for_combined(false)
11044 , m_result_for_fragment_shader(false)
11045 , m_result_for_geometry_shader(false)
11046 , m_result_for_tesselation_control_shader(false)
11047 , m_result_for_tesselatioon_evaluation_shader(false)
11048 , m_result_for_vertex_shader(false)
11049 {
11050 /* Nothing to be done */
11051 }
11052
11053 /* Methods inherited from SubcaseBase */
Cleanup()11054 virtual long Cleanup()
11055 {
11056 /* Done */
11057 return NO_ERROR;
11058 }
11059
Run()11060 virtual long Run()
11061 {
11062 m_context.getTestContext().getLog() << tcu::TestLog::Message
11063 << "This test tries to build invalid programs, expect error messages about "
11064 "exceeded number of active image uniforms"
11065 << tcu::TestLog::EndMessage;
11066
11067 testFragmentShaderStage();
11068 testGeometryShaderStage();
11069 testTesselationControlShaderStage();
11070 testTesselationEvaluationShaderStage();
11071 testVertexShaderStage();
11072 testCombinedShaderStages();
11073
11074 /* Return error if any stage failed */
11075 if ((false == m_result_for_combined) || (false == m_result_for_fragment_shader) ||
11076 (false == m_result_for_geometry_shader) || (false == m_result_for_tesselation_control_shader) ||
11077 (false == m_result_for_tesselatioon_evaluation_shader) || (false == m_result_for_vertex_shader))
11078 {
11079 return ERROR;
11080 }
11081
11082 /* Done */
11083 return NO_ERROR;
11084 }
11085
Setup()11086 virtual long Setup()
11087 {
11088 /* Done */
11089 return NO_ERROR;
11090 }
11091
11092 private:
11093 /** Test fragment shader stage
11094 *
11095 **/
testFragmentShaderStage()11096 void testFragmentShaderStage()
11097 {
11098 static const char* const fragment_shader_code =
11099 "#version 400 core\n"
11100 "#extension GL_ARB_shader_image_load_store : require\n"
11101 "\n"
11102 "precision highp float;\n"
11103 "\n"
11104 "#define N_UNIFORMS gl_MaxFragmentImageUniforms + 1\n"
11105 "\n"
11106 "flat in ivec2 vs_fs_coord;\n"
11107 "\n"
11108 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11109 "\n"
11110 "void main()\n"
11111 "{\n"
11112 " int value = 1;\n"
11113 "\n"
11114 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11115 " {\n"
11116 " value = imageAtomicAdd(u_image[i], vs_fs_coord, value);\n"
11117 " }\n"
11118 "\n"
11119 " discard;\n"
11120 "}\n\n";
11121
11122 static const char* const vertex_shader_code = "#version 400 core\n"
11123 "#extension GL_ARB_shader_image_load_store : require\n"
11124 "\n"
11125 "precision highp float;\n"
11126 "\n"
11127 " in ivec2 vs_in_coord;\n"
11128 "flat out ivec2 vs_fs_coord;\n"
11129 "\n"
11130 "void main()\n"
11131 "{\n"
11132 " vs_fs_coord = vs_in_coord;\n"
11133 "}\n\n";
11134
11135 m_result_for_fragment_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */,
11136 0 /* tesselation_control_shader_code */,
11137 0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11138
11139 if (false == m_result_for_fragment_shader)
11140 {
11141 m_context.getTestContext().getLog()
11142 << tcu::TestLog::Message
11143 << "Program which exceeds limit of GL_MAX_FRAGMENT_IMAGE_UNIFORMS was linked successfully."
11144 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11145 << fragment_shader_code << tcu::TestLog::EndMessage;
11146 }
11147 }
11148
11149 /** Test geometry shader stage
11150 *
11151 **/
testGeometryShaderStage()11152 void testGeometryShaderStage()
11153 {
11154 static const char* const fragment_shader_code = "#version 400 core\n"
11155 "#extension GL_ARB_shader_image_load_store : require\n"
11156 "\n"
11157 "precision highp float;\n"
11158 "\n"
11159 "void main()\n"
11160 "{\n"
11161 " discard;\n"
11162 "}\n\n";
11163
11164 static const char* const geometry_shader_code =
11165 "#version 400 core\n"
11166 "#extension GL_ARB_shader_image_load_store : require\n"
11167 "\n"
11168 "precision highp float;\n"
11169 "\n"
11170 "layout(points) in;\n"
11171 "layout(points, max_vertices = 1) out;\n"
11172 "\n"
11173 "#define N_UNIFORMS gl_MaxGeometryImageUniforms + 1\n"
11174 "\n"
11175 "in ivec2 vs_gs_coord[];\n"
11176 "\n"
11177 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11178 "\n"
11179 "void main()\n"
11180 "{\n"
11181 " int value = 1;\n"
11182 "\n"
11183 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11184 " {\n"
11185 " value = imageAtomicAdd(u_image[i], vs_gs_coord[0], value);\n"
11186 " }\n"
11187 "}\n\n";
11188
11189 static const char* const vertex_shader_code = "#version 400 core\n"
11190 "#extension GL_ARB_shader_image_load_store : require\n"
11191 "\n"
11192 "precision highp float;\n"
11193 "\n"
11194 "in ivec2 vs_in_coord;\n"
11195 "out ivec2 vs_gs_coord;\n"
11196 "\n"
11197 "void main()\n"
11198 "{\n"
11199 " vs_gs_coord = vs_in_coord;\n"
11200 "}\n\n";
11201
11202 m_result_for_geometry_shader =
11203 !doesProgramLink(fragment_shader_code, geometry_shader_code, 0 /* tesselation_control_shader_code */,
11204 0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11205
11206 if (false == m_result_for_geometry_shader)
11207 {
11208 m_context.getTestContext().getLog()
11209 << tcu::TestLog::Message
11210 << "Program which exceeds limit of GL_MAX_GEOMETRY_IMAGE_UNIFORMS was linked successfully."
11211 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11212 << geometry_shader_code << tcu::TestLog::EndMessage;
11213 }
11214 }
11215
11216 /** Test tesselation control shader stage
11217 *
11218 **/
testTesselationControlShaderStage()11219 void testTesselationControlShaderStage()
11220 {
11221 static const char* const fragment_shader_code = "#version 400 core\n"
11222 "#extension GL_ARB_shader_image_load_store : require\n"
11223 "\n"
11224 "precision highp float;\n"
11225 "\n"
11226 "void main()\n"
11227 "{\n"
11228 " discard;\n"
11229 "}\n\n";
11230
11231 static const char* const tesselation_control_shader_code =
11232 "#version 400 core\n"
11233 "#extension GL_ARB_shader_image_load_store : require\n"
11234 "\n"
11235 "precision highp float;\n"
11236 "\n"
11237 "layout(vertices = 4) out;\n"
11238 "\n"
11239 "#define N_UNIFORMS gl_MaxTessControlImageUniforms + 1\n"
11240 "\n"
11241 "in ivec2 vs_tcs_coord[];\n"
11242 "\n"
11243 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11244 "\n"
11245 "void main()\n"
11246 "{\n"
11247 " int value = 1;\n"
11248 "\n"
11249 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11250 " {\n"
11251 " value = imageAtomicAdd(u_image[i], vs_tcs_coord[0], value);\n"
11252 " }\n"
11253 "}\n\n";
11254
11255 static const char* const tesselation_evaluation_shader_code =
11256 "#version 400 core\n"
11257 "#extension GL_ARB_shader_image_load_store : require\n"
11258 "\n"
11259 "precision highp float;\n"
11260 "\n"
11261 "layout(quads, equal_spacing, ccw) in;\n"
11262 "\n"
11263 "void main()\n"
11264 "{\n"
11265 "}\n";
11266
11267 static const char* const vertex_shader_code = "#version 400 core\n"
11268 "#extension GL_ARB_shader_image_load_store : require\n"
11269 "\n"
11270 "precision highp float;\n"
11271 "\n"
11272 "in ivec2 vs_in_coord;\n"
11273 "out ivec2 vs_tcs_coord;\n"
11274 "\n"
11275 "void main()\n"
11276 "{\n"
11277 " vs_tcs_coord = vs_in_coord;\n"
11278 "}\n\n";
11279
11280 m_result_for_tesselation_control_shader =
11281 !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */, tesselation_control_shader_code,
11282 tesselation_evaluation_shader_code, vertex_shader_code);
11283
11284 if (false == m_result_for_tesselation_control_shader)
11285 {
11286 m_context.getTestContext().getLog()
11287 << tcu::TestLog::Message
11288 << "Program which exceeds limit of GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS was linked successfully."
11289 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11290 << tesselation_control_shader_code << tcu::TestLog::EndMessage;
11291 }
11292 }
11293
11294 /** Test teselation evaluation shader stage
11295 *
11296 **/
testTesselationEvaluationShaderStage()11297 void testTesselationEvaluationShaderStage()
11298 {
11299 static const char* const fragment_shader_code = "#version 400 core\n"
11300 "#extension GL_ARB_shader_image_load_store : require\n"
11301 "\n"
11302 "precision highp float;\n"
11303 "\n"
11304 "void main()\n"
11305 "{\n"
11306 " discard;\n"
11307 "}\n\n";
11308
11309 static const char* const tesselation_evaluation_shader_code =
11310 "#version 400 core\n"
11311 "#extension GL_ARB_shader_image_load_store : require\n"
11312 "\n"
11313 "precision highp float;\n"
11314 "\n"
11315 "layout(quads, equal_spacing, ccw) in;\n"
11316 "\n"
11317 "#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms + 1\n"
11318 "\n"
11319 "in ivec2 vs_tes_coord[];\n"
11320 "\n"
11321 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11322 "\n"
11323 "void main()\n"
11324 "{\n"
11325 " int value = 1;\n"
11326 "\n"
11327 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11328 " {\n"
11329 " value = imageAtomicAdd(u_image[i], vs_tes_coord[0], value);\n"
11330 " }\n"
11331 "}\n\n";
11332
11333 static const char* const vertex_shader_code = "#version 400 core\n"
11334 "#extension GL_ARB_shader_image_load_store : require\n"
11335 "\n"
11336 "precision highp float;\n"
11337 "\n"
11338 "in ivec2 vs_in_coord;\n"
11339 "out ivec2 vs_tes_coord;\n"
11340 "\n"
11341 "void main()\n"
11342 "{\n"
11343 " vs_tes_coord = vs_in_coord;\n"
11344 "}\n\n";
11345
11346 m_result_for_tesselatioon_evaluation_shader = !doesProgramLink(
11347 fragment_shader_code, 0 /* geometry_shader_code */, 0 /* tesselation_control_shader_code */,
11348 tesselation_evaluation_shader_code, vertex_shader_code);
11349
11350 if (false == m_result_for_tesselatioon_evaluation_shader)
11351 {
11352 m_context.getTestContext().getLog()
11353 << tcu::TestLog::Message
11354 << "Program which exceeds limit of GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS was linked successfully."
11355 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11356 << tesselation_evaluation_shader_code << tcu::TestLog::EndMessage;
11357 }
11358 }
11359
11360 /** Test vertex shader stage
11361 *
11362 **/
testVertexShaderStage()11363 void testVertexShaderStage()
11364 {
11365 static const char* const fragment_shader_code = "#version 400 core\n"
11366 "#extension GL_ARB_shader_image_load_store : require\n"
11367 "\n"
11368 "precision highp float;\n"
11369 "\n"
11370 "void main()\n"
11371 "{\n"
11372 " discard;\n"
11373 "}\n\n";
11374
11375 static const char* const vertex_shader_code =
11376 "#version 400 core\n"
11377 "#extension GL_ARB_shader_image_load_store : require\n"
11378 "\n"
11379 "precision highp float;\n"
11380 "\n"
11381 "in ivec2 vs_in_coord;\n"
11382 "\n"
11383 "#define N_UNIFORMS gl_MaxVertexImageUniforms + 1\n"
11384 "\n"
11385 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11386 "\n"
11387 "void main()\n"
11388 "{\n"
11389 " int value = 1;\n"
11390 "\n"
11391 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11392 " {\n"
11393 " value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n"
11394 " }\n"
11395 "}\n\n";
11396
11397 m_result_for_vertex_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */,
11398 0 /* tesselation_control_shader_code */,
11399 0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11400
11401 if (false == m_result_for_vertex_shader)
11402 {
11403 m_context.getTestContext().getLog()
11404 << tcu::TestLog::Message
11405 << "Program which exceeds limit of GL_MAX_VERTEX_IMAGE_UNIFORMS was linked successfully."
11406 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11407 << vertex_shader_code << tcu::TestLog::EndMessage;
11408 }
11409 }
11410
11411 /** Test combined shader stages
11412 *
11413 **/
testCombinedShaderStages()11414 void testCombinedShaderStages()
11415 {
11416 std::string fragment_shader_code =
11417 "#version 400 core\n"
11418 "#extension GL_ARB_shader_image_load_store : require\n"
11419 "\n"
11420 "precision highp float;\n"
11421 "\n"
11422 "#define N_UNIFORMS gl_MaxFragmentImageUniforms\n"
11423 "\n"
11424 "flat in ivec2 gs_fs_coord;\n"
11425 "\n"
11426 "layout(r32i) uniform iimage2D u_image_fragment[N_UNIFORMS];\n"
11427 "\n"
11428 "void main()\n"
11429 "{\n"
11430 " int value = 1;\n"
11431 "\n"
11432 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11433 " {\n"
11434 " value = imageAtomicAdd(u_image_fragment[i], gs_fs_coord, value);\n"
11435 " }\n"
11436 "\n"
11437 " discard;\n"
11438 "}\n\n";
11439
11440 std::string geometry_shader_code =
11441 "#version 400 core\n"
11442 "#extension GL_ARB_shader_image_load_store : require\n"
11443 "\n"
11444 "precision highp float;\n"
11445 "\n"
11446 "layout(points) in;\n"
11447 "layout(points, max_vertices = 1) out;\n"
11448 "\n"
11449 "#define N_UNIFORMS gl_MaxGeometryImageUniforms\n"
11450 "\n"
11451 "flat in ivec2 tes_gs_coord[];\n"
11452 "flat out ivec2 gs_fs_coord;\n"
11453 "\n"
11454 "#ifdef IMAGES\n"
11455 "layout(r32i) uniform iimage2D u_image_geometry[N_UNIFORMS];\n"
11456 "#endif\n"
11457 "\n"
11458 "void main()\n"
11459 "{\n"
11460 "#ifdef IMAGES\n"
11461 " int value = 1;\n"
11462 "\n"
11463 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11464 " {\n"
11465 " value = imageAtomicAdd(u_image_geometry[i], tes_gs_coord[0], value);\n"
11466 " }\n"
11467 "\n"
11468 "#endif\n"
11469 " gs_fs_coord = tes_gs_coord[0];\n"
11470 " EmitVertex();\n"
11471 "}\n\n";
11472
11473 std::string tesselation_control_shader_code =
11474 "#version 400 core\n"
11475 "#extension GL_ARB_shader_image_load_store : require\n"
11476 "\n"
11477 "precision highp float;\n"
11478 "\n"
11479 "layout(vertices = 4) out;\n"
11480 "\n"
11481 "#define N_UNIFORMS gl_MaxTessControlImageUniforms\n"
11482 "\n"
11483 "flat in ivec2 vs_tcs_coord[];\n"
11484 "flat out ivec2 tcs_tes_coord[];\n"
11485 "\n"
11486 "#ifdef IMAGES\n"
11487 "layout(r32i) uniform iimage2D u_image_tess_control[N_UNIFORMS];\n"
11488 "#endif\n"
11489 "\n"
11490 "void main()\n"
11491 "{\n"
11492 "#ifdef IMAGES\n"
11493 " int value = 1;\n"
11494 "\n"
11495 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11496 " {\n"
11497 " value = imageAtomicAdd(u_image_tess_control[i], vs_tcs_coord[0], value);\n"
11498 " }\n"
11499 "\n"
11500 "#endif\n"
11501 " tcs_tes_coord[gl_InvocationID] = vs_tcs_coord[0];\n"
11502 "}\n\n";
11503
11504 std::string tesselation_evaluation_shader_code =
11505 "#version 400 core\n"
11506 "#extension GL_ARB_shader_image_load_store : require\n"
11507 "\n"
11508 "precision highp float;\n"
11509 "\n"
11510 "layout(quads, equal_spacing, ccw) in;\n"
11511 "\n"
11512 "#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms\n"
11513 "\n"
11514 "flat in ivec2 tcs_tes_coord[];\n"
11515 "flat out ivec2 tes_gs_coord;\n"
11516 "\n"
11517 "#ifdef IMAGES\n"
11518 "layout(r32i) uniform iimage2D u_image_tess_evaluation[N_UNIFORMS];\n"
11519 "#endif\n"
11520 "\n"
11521 "void main()\n"
11522 "{\n"
11523 "#ifdef IMAGES\n"
11524 " int value = 1;\n"
11525 "\n"
11526 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11527 " {\n"
11528 " value = imageAtomicAdd(u_image_tess_evaluation[i], tcs_tes_coord[0], value);\n"
11529 " }\n"
11530 "\n"
11531 "#endif\n"
11532 " tes_gs_coord = tcs_tes_coord[0];\n"
11533 "}\n\n";
11534
11535 std::string vertex_shader_code =
11536 "#version 400 core\n"
11537 "#extension GL_ARB_shader_image_load_store : require\n"
11538 "\n"
11539 "precision highp float;\n"
11540 "\n"
11541 " in ivec2 vs_in_coord;\n"
11542 "flat out ivec2 vs_tcs_coord;\n"
11543 "\n"
11544 "#define N_UNIFORMS gl_MaxVertexImageUniforms\n"
11545 "\n"
11546 "#ifdef IMAGES\n"
11547 "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11548 "#endif\n"
11549 "\n"
11550 "void main()\n"
11551 "{\n"
11552 "#ifdef IMAGES\n"
11553 " int value = 1;\n"
11554 "\n"
11555 " for (int i = 0; i < N_UNIFORMS; ++i)\n"
11556 " {\n"
11557 " value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n"
11558 " }\n"
11559 "\n"
11560 "#endif\n"
11561 " vs_tcs_coord = vs_tcs_coord;\n"
11562 "}\n\n";
11563
11564 /* Active image uniform limits */
11565 GLint max_combined_image_uniforms = 0;
11566 GLint max_fragment_image_uniforms = 0;
11567 GLint max_geometry_image_uniforms = 0;
11568 GLint max_tesselation_control_image_uniforms = 0;
11569 GLint max_tesselation_evaluation_image_uniforms = 0;
11570 GLint max_vertex_image_uniforms = 0;
11571
11572 /* Get limit values */
11573 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &max_combined_image_uniforms);
11574 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &max_fragment_image_uniforms);
11575 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &max_geometry_image_uniforms);
11576 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &max_tesselation_control_image_uniforms);
11577 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &max_tesselation_evaluation_image_uniforms);
11578 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &max_vertex_image_uniforms);
11579 GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv");
11580
11581 if (max_vertex_image_uniforms)
11582 vertex_shader_code.insert(18, "#define IMAGES\n");
11583 if (max_geometry_image_uniforms)
11584 geometry_shader_code.insert(18, "#define IMAGES\n");
11585 if (max_tesselation_control_image_uniforms)
11586 tesselation_control_shader_code.insert(18, "#define IMAGES\n");
11587 if (max_tesselation_evaluation_image_uniforms)
11588 tesselation_evaluation_shader_code.insert(18, "#define IMAGES\n");
11589
11590 /* Check if program builds */
11591 m_result_for_combined =
11592 !doesProgramLink(fragment_shader_code.c_str(),
11593 geometry_shader_code.c_str(),
11594 tesselation_control_shader_code.c_str(),
11595 tesselation_evaluation_shader_code.c_str(),
11596 vertex_shader_code.c_str());
11597
11598 /* Result depends on the limit values */
11599 if (max_combined_image_uniforms >=
11600 (max_fragment_image_uniforms + max_geometry_image_uniforms + max_tesselation_control_image_uniforms +
11601 max_tesselation_evaluation_image_uniforms + max_vertex_image_uniforms))
11602 {
11603 /* In this case, combined image uniforms limit cannot be exeeded, therefore successful linking is expected */
11604 m_result_for_combined = !m_result_for_combined;
11605
11606 if (false == m_result_for_combined)
11607 {
11608 m_context.getTestContext().getLog()
11609 << tcu::TestLog::Message << "There was an error while building a program."
11610 << " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n"
11611 << vertex_shader_code << "\nTesselation control shader code:\n"
11612 << tesselation_control_shader_code << "\nTesselation evaluation shader code:\n"
11613 << tesselation_evaluation_shader_code << "\nGeometry shader code:\n"
11614 << geometry_shader_code << "\nFragment shader code:\n"
11615 << fragment_shader_code << tcu::TestLog::EndMessage;
11616 }
11617 }
11618 else
11619 {
11620 /* In this case, combined image uniforms can be exceeded, therefore failed linking is expected */
11621 if (false == m_result_for_combined)
11622 {
11623 m_context.getTestContext().getLog()
11624 << tcu::TestLog::Message
11625 << "Program which exceeds limit of GL_MAX_COMBINED_IMAGE_UNIFORMS was linked successfully."
11626 << " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n"
11627 << vertex_shader_code << "\nTesselation control shader code:\n"
11628 << tesselation_control_shader_code << "\nTesselation evaluation shader code:\n"
11629 << tesselation_evaluation_shader_code << "\nGeometry shader code:\n"
11630 << geometry_shader_code << "\nFragment shader code:\n"
11631 << fragment_shader_code << tcu::TestLog::EndMessage;
11632 }
11633 }
11634 }
11635
11636 /** Check if program builds successfully
11637 *
11638 * @param fragment_shader_code Source code for fragment shader stage
11639 * @param geometry_shader_code Source code for geometry shader stage
11640 * @param tesselation_control_shader_code Source code for tesselation control shader stage
11641 * @param tesselation_evaluation_shader_code Source code for tesselation evaluation shader stage
11642 * @param vertex_shader_code Source code for vertex shader stage
11643 *
11644 * @return true if program was built without errors, false otherwise
11645 **/
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)11646 bool doesProgramLink(const char* fragment_shader_code, const char* geometry_shader_code,
11647 const char* tesselation_control_shader_code, const char* tesselation_evaluation_shader_code,
11648 const char* vertex_shader_code)
11649 {
11650 bool is_program_built = true;
11651 GLuint program_id = 0;
11652
11653 program_id =
11654 BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
11655 geometry_shader_code, fragment_shader_code, &is_program_built);
11656
11657 if (0 != program_id)
11658 {
11659 glDeleteProgram(program_id);
11660 }
11661
11662 return is_program_built;
11663 }
11664 };
11665 }
11666
ShaderImageLoadStoreTests(deqp::Context & context)11667 ShaderImageLoadStoreTests::ShaderImageLoadStoreTests(deqp::Context& context)
11668 : TestCaseGroup(context, "shader_image_load_store", "")
11669 {
11670 }
11671
~ShaderImageLoadStoreTests(void)11672 ShaderImageLoadStoreTests::~ShaderImageLoadStoreTests(void)
11673 {
11674 }
11675
init()11676 void ShaderImageLoadStoreTests::init()
11677 {
11678 using namespace deqp;
11679 addChild(new TestSubcase(m_context, "basic-api-get", TestSubcase::Create<BasicAPIGet>));
11680 addChild(new TestSubcase(m_context, "basic-api-bind", TestSubcase::Create<BasicAPIBind>));
11681 addChild(new TestSubcase(m_context, "basic-api-barrier", TestSubcase::Create<BasicAPIBarrier>));
11682 addChild(new TestSubcase(m_context, "basic-api-texParam", TestSubcase::Create<BasicAPITexParam>));
11683 addChild(new TestSubcase(m_context, "basic-allFormats-store", TestSubcase::Create<BasicAllFormatsStore>));
11684 addChild(new TestSubcase(m_context, "basic-allFormats-load", TestSubcase::Create<BasicAllFormatsLoad>));
11685 addChild(new TestSubcase(m_context, "basic-allFormats-storeGeometryStages",
11686 TestSubcase::Create<BasicAllFormatsStoreGeometryStages>));
11687 addChild(new TestSubcase(m_context, "basic-allFormats-loadGeometryStages",
11688 TestSubcase::Create<BasicAllFormatsLoadGeometryStages>));
11689 addChild(new TestSubcase(m_context, "basic-allFormats-loadStoreComputeStage",
11690 TestSubcase::Create<BasicAllFormatsLoadStoreComputeStage>));
11691 addChild(new TestSubcase(m_context, "basic-allTargets-store", TestSubcase::Create<BasicAllTargetsStore>));
11692 addChild(new TestSubcase(m_context, "basic-allTargets-load-nonMS", TestSubcase::Create<BasicAllTargetsLoadNonMS>));
11693 addChild(new TestSubcase(m_context, "basic-allTargets-load-ms", TestSubcase::Create<BasicAllTargetsLoadMS>));
11694 addChild(new TestSubcase(m_context, "basic-allTargets-atomic", TestSubcase::Create<BasicAllTargetsAtomic>));
11695 addChild(
11696 new TestSubcase(m_context, "basic-allTargets-loadStoreVS", TestSubcase::Create<BasicAllTargetsLoadStoreVS>));
11697 addChild(
11698 new TestSubcase(m_context, "basic-allTargets-loadStoreTCS", TestSubcase::Create<BasicAllTargetsLoadStoreTCS>));
11699 addChild(
11700 new TestSubcase(m_context, "basic-allTargets-loadStoreTES", TestSubcase::Create<BasicAllTargetsLoadStoreTES>));
11701 addChild(
11702 new TestSubcase(m_context, "basic-allTargets-loadStoreGS", TestSubcase::Create<BasicAllTargetsLoadStoreGS>));
11703 addChild(
11704 new TestSubcase(m_context, "basic-allTargets-loadStoreCS", TestSubcase::Create<BasicAllTargetsLoadStoreCS>));
11705 addChild(new TestSubcase(m_context, "basic-allTargets-atomicVS", TestSubcase::Create<BasicAllTargetsAtomicVS>));
11706 addChild(new TestSubcase(m_context, "basic-allTargets-atomicTCS", TestSubcase::Create<BasicAllTargetsAtomicTCS>));
11707 addChild(new TestSubcase(m_context, "basic-allTargets-atomicGS", TestSubcase::Create<BasicAllTargetsAtomicGS>));
11708 addChild(new TestSubcase(m_context, "basic-allTargets-atomicCS", TestSubcase::Create<BasicAllTargetsAtomicCS>));
11709 addChild(new TestSubcase(m_context, "basic-glsl-misc", TestSubcase::Create<BasicGLSLMisc>));
11710 addChild(new TestSubcase(m_context, "basic-glsl-earlyFragTests", TestSubcase::Create<BasicGLSLEarlyFragTests>));
11711 addChild(new TestSubcase(m_context, "basic-glsl-const", TestSubcase::Create<BasicGLSLConst>));
11712 addChild(new TestSubcase(m_context, "advanced-sync-imageAccess", TestSubcase::Create<AdvancedSyncImageAccess>));
11713 addChild(new TestSubcase(m_context, "advanced-sync-vertexArray", TestSubcase::Create<AdvancedSyncVertexArray>));
11714 addChild(new TestSubcase(m_context, "advanced-sync-drawIndirect", TestSubcase::Create<AdvancedSyncDrawIndirect>));
11715 addChild(new TestSubcase(m_context, "advanced-sync-textureUpdate", TestSubcase::Create<AdvancedSyncTextureUpdate>));
11716 addChild(new TestSubcase(m_context, "advanced-sync-imageAccess2", TestSubcase::Create<AdvancedSyncImageAccess2>));
11717 addChild(new TestSubcase(m_context, "advanced-sync-bufferUpdate", TestSubcase::Create<AdvancedSyncBufferUpdate>));
11718 addChild(new TestSubcase(m_context, "advanced-allStages-oneImage", TestSubcase::Create<AdvancedAllStagesOneImage>));
11719 addChild(new TestSubcase(m_context, "advanced-memory-dependentInvocation",
11720 TestSubcase::Create<AdvancedMemoryDependentInvocation>));
11721 addChild(new TestSubcase(m_context, "advanced-memory-order", TestSubcase::Create<AdvancedMemoryOrder>));
11722 addChild(new TestSubcase(m_context, "advanced-sso-simple", TestSubcase::Create<AdvancedSSOSimple>));
11723 addChild(new TestSubcase(m_context, "advanced-sso-atomicCounters", TestSubcase::Create<AdvancedSSOAtomicCounters>));
11724 addChild(new TestSubcase(m_context, "advanced-sso-subroutine", TestSubcase::Create<AdvancedSSOSubroutine>));
11725 addChild(new TestSubcase(m_context, "advanced-sso-perSample", TestSubcase::Create<AdvancedSSOPerSample>));
11726 addChild(new TestSubcase(m_context, "advanced-copyImage", TestSubcase::Create<AdvancedCopyImage>));
11727 addChild(new TestSubcase(m_context, "advanced-allMips", TestSubcase::Create<AdvancedAllMips>));
11728 addChild(new TestSubcase(m_context, "advanced-cast", TestSubcase::Create<AdvancedCast>));
11729 addChild(
11730 new TestSubcase(m_context, "single-byte_data_alignment", TestSubcase::Create<ImageLoadStoreDataAlignmentTest>));
11731 addChild(
11732 new TestSubcase(m_context, "non-layered_binding", TestSubcase::Create<ImageLoadStoreNonLayeredBindingTest>));
11733 addChild(
11734 new TestSubcase(m_context, "incomplete_textures", TestSubcase::Create<ImageLoadStoreIncompleteTexturesTest>));
11735 addChild(new TestSubcase(m_context, "multiple-uniforms", TestSubcase::Create<ImageLoadStoreMultipleUniformsTest>));
11736 addChild(
11737 new TestSubcase(m_context, "early-fragment-tests", TestSubcase::Create<ImageLoadStoreEarlyFragmentTestsTest>));
11738 addChild(new TestSubcase(m_context, "negative-uniform", TestSubcase::Create<NegativeUniform>));
11739 addChild(new TestSubcase(m_context, "negative-bind", TestSubcase::Create<NegativeBind>));
11740 addChild(new TestSubcase(m_context, "negative-compileErrors", TestSubcase::Create<NegativeCompileErrors>));
11741 addChild(new TestSubcase(m_context, "negative-linkErrors", TestSubcase::Create<NegativeLinkErrors>));
11742 addChild(new TestSubcase(m_context, "uniform-limits", TestSubcase::Create<ImageLoadStoreUniformLimitsTest>));
11743 }
11744 }
11745