1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2015-2016 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */ /*!
20 * \file
21 * \brief
22 */ /*-------------------------------------------------------------------*/
23
24 /**
25 * \file gl4cBufferStorageTests.cpp
26 * \brief Implements conformance tests for "Buffer storage" functionality.
27 */ /*-------------------------------------------------------------------*/
28
29 #include "gl4cBufferStorageTests.hpp"
30
31 #include "gluContextInfo.hpp"
32 #include "gluDefs.hpp"
33 #include "gluStrUtil.hpp"
34 #include "glwEnums.hpp"
35 #include "glwFunctions.hpp"
36 #include "tcuImageIO.hpp"
37 #include "tcuTestLog.hpp"
38 #include "tcuTexture.hpp"
39
40 #include <iomanip>
41 #include <string>
42
43 using namespace glw;
44
45 namespace gl4cts
46 {
47 namespace BufferStorage
48 {
49 /* Enums */
50
51 /* Represents how functionality is supported */
52 enum FUNCTIONALITY_SUPPORT
53 {
54 FUNCTIONALITY_SUPPORT_NONE = 0,
55 FUNCTIONALITY_SUPPORT_EXTENSION,
56 FUNCTIONALITY_SUPPORT_CORE,
57 FUNCTIONALITY_SUPPORT_NOT_DETERMINED,
58 };
59
60 /* Prototypes of functions */
61 FUNCTIONALITY_SUPPORT getDirectStateAccessSupport(deqp::Context &context);
62 bool isGLVersionAtLeast(const glw::Functions &gl, glw::GLint required_major, glw::GLint required_minor);
63
64 /* Classes */
65
66 /** Represents buffer instance
67 * Provides basic buffer functionality
68 **/
69 class Buffer
70 {
71 public:
72 // I don't quite understand how the old code *ever* worked...
73 // This is uglyish hack to make it actually compile on any sane
74 // compiler, and not crash.
75 struct MoveMapOwner
76 {
MoveMapOwnergl4cts::BufferStorage::Buffer::MoveMapOwner77 MoveMapOwner(Buffer *buffer_, glw::GLvoid *data_) : buffer(buffer_), data(data_)
78 {
79 }
80
81 Buffer *buffer;
82 glw::GLvoid *data;
83 };
84
85 /* Public classes */
86 class MapOwner
87 {
88 friend class Buffer;
89
90 public:
91 MapOwner(MapOwner &map_owner);
92 MapOwner(const MoveMapOwner &moveOwner);
93 ~MapOwner();
94
95 glw::GLvoid *m_data;
96
97 private:
98 MapOwner(Buffer &buffer, glw::GLvoid *data);
99
100 Buffer *m_buffer;
101 };
102
103 /* Public methods */
104 /* Ctr & Dtr */
105 Buffer(deqp::Context &context);
106 ~Buffer();
107
108 /* Init & Release */
109 void InitData(glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size, const glw::GLvoid *data);
110
111 void InitStorage(glw::GLenum target, glw::GLenum flags, glw::GLsizeiptr size, const glw::GLvoid *data);
112
113 void Release();
114
115 /* Functionality */
116 void Bind() const;
117 void BindBase(glw::GLuint index) const;
118
119 void BindRange(glw::GLuint index, glw::GLintptr offset, glw::GLsizeiptr size) const;
120
121 MoveMapOwner MapRange(glw::GLintptr offset, glw::GLsizeiptr length, glw::GLenum access);
122
123 void UnMap();
124
125 /* Public static routines */
126 /* Extensions */
127 static void LoadExtDirectStateAccess(deqp::Context &context);
128
129 /* Functionality */
130 static void Bind(const glw::Functions &gl, glw::GLuint id, glw::GLenum target);
131
132 static void BindBase(const glw::Functions &gl, glw::GLuint id, glw::GLenum target, glw::GLuint index);
133
134 static void BindRange(const glw::Functions &gl, glw::GLuint id, glw::GLenum target, glw::GLuint index,
135 glw::GLintptr offset, glw::GLsizeiptr size);
136
137 static void Data(const glw::Functions &gl, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size,
138 const glw::GLvoid *data);
139
140 static void Generate(const glw::Functions &gl, glw::GLuint &out_id);
141
142 static void GetNamedParameter(const glw::Functions &gl, glw::GLuint buffer, glw::GLenum pname, glw::GLint *data);
143
144 static void GetParameter(const glw::Functions &gl, glw::GLenum target, glw::GLenum value, glw::GLint *data);
145
146 static void GetSubData(const glw::Functions &gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size,
147 glw::GLvoid *data);
148
149 static void *Map(const glw::Functions &gl, glw::GLenum target, glw::GLenum access);
150
151 static void *MapRange(const glw::Functions &gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr length,
152 glw::GLenum access);
153
154 static void Storage(const glw::Functions &gl, glw::GLenum target, glw::GLenum flags, glw::GLsizeiptr size,
155 const glw::GLvoid *data);
156
157 static void SubData(const glw::Functions &gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size,
158 glw::GLvoid *data);
159
160 static void UnMap(const glw::Functions &gl, glw::GLenum target);
161
162 /* Public fields */
163 glw::GLuint m_id;
164
165 /* Public constants */
166 static const glw::GLuint m_invalid_id;
167 static const glw::GLuint m_n_targets = 13;
168 static const glw::GLenum m_targets[m_n_targets];
169
170 private:
171 /* Private enums */
172
173 /* Private fields */
174 deqp::Context &m_context;
175 glw::GLenum m_target;
176 };
177
178 /** Represents framebuffer
179 * Provides basic functionality
180 **/
181 class Framebuffer
182 {
183 public:
184 /* Public methods */
185 /* Ctr & Dtr */
186 Framebuffer(deqp::Context &context);
187 ~Framebuffer();
188
189 /* Init & Release */
190 void Release();
191
192 /* Public static routines */
193 static void AttachTexture(const glw::Functions &gl, glw::GLenum target, glw::GLenum attachment,
194 glw::GLuint texture_id, glw::GLuint width, glw::GLuint height);
195
196 static void Bind(const glw::Functions &gl, glw::GLenum target, glw::GLuint id);
197
198 static void Generate(const glw::Functions &gl, glw::GLuint &out_id);
199
200 /* Public fields */
201 glw::GLuint m_id;
202
203 /* Public constants */
204 static const glw::GLuint m_invalid_id;
205
206 private:
207 /* Private fields */
208 deqp::Context &m_context;
209 };
210
211 /** Represents shader instance.
212 * Provides basic functionality for shaders.
213 **/
214 class Shader
215 {
216 public:
217 /* Public methods */
218 /* Ctr & Dtr */
219 Shader(deqp::Context &context);
220 ~Shader();
221
222 /* Init & Realese */
223 void Init(glw::GLenum stage, const std::string &source);
224 void Release();
225
226 /* Public static routines */
227 /* Functionality */
228 static void Compile(const glw::Functions &gl, glw::GLuint id);
229
230 static void Create(const glw::Functions &gl, glw::GLenum stage, glw::GLuint &out_id);
231
232 static void Source(const glw::Functions &gl, glw::GLuint id, const std::string &source);
233
234 /* Public fields */
235 glw::GLuint m_id;
236
237 /* Public constants */
238 static const glw::GLuint m_invalid_id;
239
240 private:
241 /* Private fields */
242 deqp::Context &m_context;
243 };
244
245 /** Represents program instance.
246 * Provides basic functionality
247 **/
248 class Program
249 {
250 public:
251 /* Public methods */
252 /* Ctr & Dtr */
253 Program(deqp::Context &context);
254 ~Program();
255
256 /* Init & Release */
257 void Init(const std::string &compute_shader, const std::string &fragment_shader, const std::string &geometry_shader,
258 const std::string &tesselation_control_shader, const std::string &tesselation_evaluation_shader,
259 const std::string &vertex_shader);
260
261 void Release();
262
263 /* Public static routines */
264 /* Functionality */
265 static void Attach(const glw::Functions &gl, glw::GLuint program_id, glw::GLuint shader_id);
266
267 static void Create(const glw::Functions &gl, glw::GLuint &out_id);
268
269 static void Link(const glw::Functions &gl, glw::GLuint id);
270
271 static void Use(const glw::Functions &gl, glw::GLuint id);
272
273 /* Public fields */
274 glw::GLuint m_id;
275
276 Shader m_compute;
277 Shader m_fragment;
278 Shader m_geometry;
279 Shader m_tess_ctrl;
280 Shader m_tess_eval;
281 Shader m_vertex;
282
283 /* Public constants */
284 static const glw::GLuint m_invalid_id;
285
286 private:
287 /* Private fields */
288 deqp::Context &m_context;
289 };
290
291 /** Represents texture instance
292 **/
293 class Texture
294 {
295 public:
296 /* Public types */
297 /* Public methods */
298 /* Ctr & Dtr */
299 Texture(deqp::Context &context);
300 ~Texture();
301
302 /* Init & Release */
303 void Release();
304
305 /* Public static routines */
306 /* Extensions */
307 static void LoadExtDirectStateAccess(deqp::Context &context);
308
309 /* Functionality */
310 static void Bind(const glw::Functions &gl, glw::GLuint id, glw::GLenum target);
311
312 static void CompressedImage(const glw::Functions &gl, glw::GLenum target, glw::GLint level,
313 glw::GLenum internal_format, glw::GLuint width, glw::GLuint height, glw::GLuint depth,
314 glw::GLsizei image_size, const glw::GLvoid *data);
315
316 static void Generate(const glw::Functions &gl, glw::GLuint &out_id);
317
318 static void GetData(const glw::Functions &gl, glw::GLenum target, glw::GLenum format, glw::GLenum type,
319 glw::GLvoid *out_data);
320
321 static void GetLevelParameter(const glw::Functions &gl, glw::GLenum target, glw::GLint level, glw::GLenum pname,
322 glw::GLint *param);
323
324 static void Image(const glw::Functions &gl, glw::GLenum target, glw::GLint level, glw::GLenum internal_format,
325 glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type,
326 const glw::GLvoid *data);
327
328 static void Storage(const glw::Functions &gl, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format,
329 glw::GLuint width, glw::GLuint height, glw::GLuint depth);
330
331 static void SubImage(const glw::Functions &gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y,
332 glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format,
333 glw::GLenum type, const glw::GLvoid *pixels);
334
335 /* Public fields */
336 glw::GLuint m_id;
337
338 /* Public constants */
339 static const glw::GLuint m_invalid_id;
340
341 private:
342 /* Private fields */
343 deqp::Context &m_context;
344
345 /* Private static fields */
346 static FUNCTIONALITY_SUPPORT m_direct_state_access_support;
347 };
348
349 /** Represents Vertex array object
350 * Provides basic functionality
351 **/
352 class VertexArray
353 {
354 public:
355 /* Public methods */
356 /* Ctr & Dtr */
357 VertexArray(deqp::Context &Context);
358 ~VertexArray();
359
360 /* Init & Release */
361 void Release();
362
363 /* Public static methods */
364 static void Bind(const glw::Functions &gl, glw::GLuint id);
365 static void Generate(const glw::Functions &gl, glw::GLuint &out_id);
366
367 /* Public fields */
368 glw::GLuint m_id;
369
370 /* Public constants */
371 static const glw::GLuint m_invalid_id;
372
373 private:
374 /* Private fields */
375 deqp::Context &m_context;
376 };
377
378 /* Global variables */
379 static FUNCTIONALITY_SUPPORT m_direct_state_access_support = FUNCTIONALITY_SUPPORT_NOT_DETERMINED;
380
381 /* Implementations of functions */
382 /** Get support for direct state access
383 *
384 * @param context CTS context
385 **/
getDirectStateAccessSupport(deqp::Context & context)386 FUNCTIONALITY_SUPPORT getDirectStateAccessSupport(deqp::Context &context)
387 {
388 if (FUNCTIONALITY_SUPPORT_NOT_DETERMINED == m_direct_state_access_support)
389 {
390 const Functions &gl = context.getRenderContext().getFunctions();
391
392 if (true == isGLVersionAtLeast(gl, 4, 5))
393 {
394 m_direct_state_access_support = FUNCTIONALITY_SUPPORT_CORE;
395 }
396 else
397 {
398 bool is_supported = context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
399
400 if (true == is_supported)
401 {
402 m_direct_state_access_support = FUNCTIONALITY_SUPPORT_EXTENSION;
403 }
404 else
405 {
406 m_direct_state_access_support = FUNCTIONALITY_SUPPORT_NONE;
407 }
408 }
409 }
410
411 return m_direct_state_access_support;
412 }
413
414 /** Check if GL context meets version requirements
415 *
416 * @param gl Functions
417 * @param required_major Minimum required MAJOR_VERSION
418 * @param required_minor Minimum required MINOR_VERSION
419 *
420 * @return true if GL context version is at least as requested, false otherwise
421 **/
isGLVersionAtLeast(const glw::Functions & gl,glw::GLint required_major,glw::GLint required_minor)422 bool isGLVersionAtLeast(const glw::Functions &gl, glw::GLint required_major, glw::GLint required_minor)
423 {
424 glw::GLint major = 0;
425 glw::GLint minor = 0;
426
427 gl.getIntegerv(GL_MAJOR_VERSION, &major);
428 gl.getIntegerv(GL_MINOR_VERSION, &minor);
429
430 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
431
432 if (major > required_major)
433 {
434 /* Major is higher than required one */
435 return true;
436 }
437 else if (major == required_major)
438 {
439 if (minor >= required_minor)
440 {
441 /* Major is equal to required one */
442 /* Minor is higher than or equal to required one */
443 return true;
444 }
445 else
446 {
447 /* Major is equal to required one */
448 /* Minor is lower than required one */
449 return false;
450 }
451 }
452 else
453 {
454 /* Major is lower than required one */
455 return false;
456 }
457 }
458
459 /* Buffer constants */
460 const GLuint Buffer::m_invalid_id = -1;
461
462 const GLenum Buffer::m_targets[Buffer::m_n_targets] = {
463 GL_ARRAY_BUFFER, /* 0 */
464 GL_ATOMIC_COUNTER_BUFFER, /* 1 */
465 GL_COPY_READ_BUFFER, /* 2 */
466 GL_COPY_WRITE_BUFFER, /* 3 */
467 GL_DISPATCH_INDIRECT_BUFFER, /* 4 */
468 GL_DRAW_INDIRECT_BUFFER, /* 5 */
469 GL_ELEMENT_ARRAY_BUFFER, /* 6 */
470 GL_PIXEL_PACK_BUFFER, /* 7 */
471 GL_PIXEL_UNPACK_BUFFER, /* 8 */
472 GL_QUERY_BUFFER, /* 9 */
473 GL_SHADER_STORAGE_BUFFER, /* 10 */
474 GL_TRANSFORM_FEEDBACK_BUFFER, /* 11 */
475 GL_UNIFORM_BUFFER, /* 12 */
476 };
477
478 /** Constructor.
479 *
480 * @param context CTS context.
481 **/
Buffer(deqp::Context & context)482 Buffer::Buffer(deqp::Context &context) : m_id(m_invalid_id), m_context(context), m_target(GL_ARRAY_BUFFER)
483 {
484 }
485
486 /** Destructor
487 *
488 **/
~Buffer()489 Buffer::~Buffer()
490 {
491 Release();
492 }
493
494 /** Initialize buffer instance
495 *
496 * @param target Buffer target
497 * @param usage Buffer usage enum
498 * @param size <size> parameter
499 * @param data <data> parameter
500 **/
InitData(glw::GLenum target,glw::GLenum usage,glw::GLsizeiptr size,const glw::GLvoid * data)501 void Buffer::InitData(glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size, const glw::GLvoid *data)
502 {
503 /* Delete previous buffer instance */
504 Release();
505
506 m_target = target;
507
508 const Functions &gl = m_context.getRenderContext().getFunctions();
509
510 Generate(gl, m_id);
511 Bind(gl, m_id, m_target);
512 Data(gl, m_target, usage, size, data);
513 }
514
515 /** Initialize buffer instance
516 *
517 * @param target Buffer target
518 * @param usage Buffer usage enum
519 * @param size <size> parameter
520 * @param data <data> parameter
521 **/
InitStorage(glw::GLenum target,glw::GLenum flags,glw::GLsizeiptr size,const glw::GLvoid * data)522 void Buffer::InitStorage(glw::GLenum target, glw::GLenum flags, glw::GLsizeiptr size, const glw::GLvoid *data)
523 {
524 /* Delete previous buffer instance */
525 Release();
526
527 m_target = target;
528
529 const Functions &gl = m_context.getRenderContext().getFunctions();
530
531 Generate(gl, m_id);
532 Bind(gl, m_id, m_target);
533 Storage(gl, m_target, flags, size, data);
534 }
535
536 /** Release buffer instance
537 *
538 **/
Release()539 void Buffer::Release()
540 {
541 if (m_invalid_id != m_id)
542 {
543 const Functions &gl = m_context.getRenderContext().getFunctions();
544
545 gl.deleteBuffers(1, &m_id);
546 m_id = m_invalid_id;
547 }
548 }
549
550 /** Binds buffer to its target
551 *
552 **/
Bind() const553 void Buffer::Bind() const
554 {
555 const Functions &gl = m_context.getRenderContext().getFunctions();
556
557 Bind(gl, m_id, m_target);
558 }
559
560 /** Binds indexed buffer
561 *
562 * @param index <index> parameter
563 **/
BindBase(glw::GLuint index) const564 void Buffer::BindBase(glw::GLuint index) const
565 {
566 const Functions &gl = m_context.getRenderContext().getFunctions();
567
568 BindBase(gl, m_id, m_target, index);
569 }
570
571 /** Binds range of buffer
572 *
573 * @param index <index> parameter
574 * @param offset <offset> parameter
575 * @param size <size> parameter
576 **/
BindRange(glw::GLuint index,glw::GLintptr offset,glw::GLsizeiptr size) const577 void Buffer::BindRange(glw::GLuint index, glw::GLintptr offset, glw::GLsizeiptr size) const
578 {
579 const Functions &gl = m_context.getRenderContext().getFunctions();
580
581 BindRange(gl, m_id, m_target, index, offset, size);
582 }
583
584 /** Maps contents of buffer into CPU space
585 *
586 * @param access Requested access
587 *
588 * @return Pointer to memory region available for CPU
589 **/
MapRange(glw::GLintptr offset,glw::GLsizeiptr length,glw::GLenum access)590 Buffer::MoveMapOwner Buffer::MapRange(glw::GLintptr offset, glw::GLsizeiptr length, glw::GLenum access)
591 {
592 const Functions &gl = m_context.getRenderContext().getFunctions();
593
594 Bind(gl, m_id, m_target);
595
596 void *data = MapRange(gl, m_target, offset, length, access);
597
598 MoveMapOwner map(this, data);
599
600 return map;
601 }
602
603 /** Unmaps contents of buffer
604 *
605 **/
UnMap()606 void Buffer::UnMap()
607 {
608 const Functions &gl = m_context.getRenderContext().getFunctions();
609
610 UnMap(gl, m_target);
611 }
612
613 /** Loads entry points for direct state access extension
614 *
615 * @param context CTS context
616 **/
LoadExtDirectStateAccess(deqp::Context & context)617 void Buffer::LoadExtDirectStateAccess(deqp::Context &context)
618 {
619 FUNCTIONALITY_SUPPORT support = getDirectStateAccessSupport(context);
620
621 switch (support)
622 {
623 case FUNCTIONALITY_SUPPORT_NONE:
624 /* Nothing to be done */
625 break;
626 case FUNCTIONALITY_SUPPORT_CORE:
627 case FUNCTIONALITY_SUPPORT_EXTENSION:
628 break;
629 default:
630 TCU_FAIL("Invalid enum");
631 }
632 }
633
634 /** Bind buffer to given target
635 *
636 * @param gl GL functions
637 * @param id Id of buffer
638 * @param target Buffer target
639 **/
Bind(const glw::Functions & gl,glw::GLuint id,glw::GLenum target)640 void Buffer::Bind(const glw::Functions &gl, glw::GLuint id, glw::GLenum target)
641 {
642 gl.bindBuffer(target, id);
643 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
644 }
645
646 /** Binds indexed buffer
647 *
648 * @param gl GL functions
649 * @param id Id of buffer
650 * @param target Buffer target
651 * @param index <index> parameter
652 **/
BindBase(const glw::Functions & gl,glw::GLuint id,glw::GLenum target,glw::GLuint index)653 void Buffer::BindBase(const glw::Functions &gl, glw::GLuint id, glw::GLenum target, glw::GLuint index)
654 {
655 gl.bindBufferBase(target, index, id);
656 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
657 }
658
659 /** Binds buffer range
660 *
661 * @param gl GL functions
662 * @param id Id of buffer
663 * @param target Buffer target
664 * @param index <index> parameter
665 * @param offset <offset> parameter
666 * @param size <size> parameter
667 **/
BindRange(const glw::Functions & gl,glw::GLuint id,glw::GLenum target,glw::GLuint index,glw::GLintptr offset,glw::GLsizeiptr size)668 void Buffer::BindRange(const glw::Functions &gl, glw::GLuint id, glw::GLenum target, glw::GLuint index,
669 glw::GLintptr offset, glw::GLsizeiptr size)
670 {
671 gl.bindBufferRange(target, index, id, offset, size);
672 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
673 }
674
675 /** Allocate memory for buffer and sends initial content
676 *
677 * @param gl GL functions
678 * @param target Buffer target
679 * @param usage Buffer usage enum
680 * @param size <size> parameter
681 * @param data <data> parameter
682 **/
Data(const glw::Functions & gl,glw::GLenum target,glw::GLenum usage,glw::GLsizeiptr size,const glw::GLvoid * data)683 void Buffer::Data(const glw::Functions &gl, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size,
684 const glw::GLvoid *data)
685 {
686 gl.bufferData(target, size, data, usage);
687 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
688 }
689
690 /** Generate buffer
691 *
692 * @param gl GL functions
693 * @param out_id Id of buffer
694 **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)695 void Buffer::Generate(const glw::Functions &gl, glw::GLuint &out_id)
696 {
697 GLuint id = m_invalid_id;
698
699 gl.genBuffers(1, &id);
700 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
701
702 if (m_invalid_id == id)
703 {
704 TCU_FAIL("Got invalid id");
705 }
706
707 out_id = id;
708 }
709
710 /** Query parameter of named buffer
711 *
712 * @param gl GL functions
713 * @param buffer Buffer name
714 * @param pname Parameter name
715 * @param data Storage for queried results
716 **/
GetNamedParameter(const glw::Functions & gl,glw::GLuint buffer,glw::GLenum pname,glw::GLint * data)717 void Buffer::GetNamedParameter(const glw::Functions &gl, glw::GLuint buffer, glw::GLenum pname, glw::GLint *data)
718 {
719 gl.getNamedBufferParameteriv(buffer, pname, data);
720 GLU_EXPECT_NO_ERROR(gl.getError(), "GetNameBufferParameteriv");
721 }
722
723 /** Query parameter of bound buffer
724 *
725 * @param gl GL functions
726 * @param Target Buffer target
727 * @param pname Parameter name
728 * @param data Storage for queried results
729 **/
GetParameter(const glw::Functions & gl,glw::GLenum target,glw::GLenum value,glw::GLint * data)730 void Buffer::GetParameter(const glw::Functions &gl, glw::GLenum target, glw::GLenum value, glw::GLint *data)
731 {
732 gl.getBufferParameteriv(target, value, data);
733 GLU_EXPECT_NO_ERROR(gl.getError(), "GetBufferParameteriv");
734 }
735
736 /** Get contents of buffer's region
737 *
738 * @param gl GL functions
739 * @param target Buffer target
740 * @param offset Offset in buffer
741 * @param size <size> parameter
742 * @param data <data> parameter
743 **/
GetSubData(const glw::Functions & gl,glw::GLenum target,glw::GLintptr offset,glw::GLsizeiptr size,glw::GLvoid * data)744 void Buffer::GetSubData(const glw::Functions &gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size,
745 glw::GLvoid *data)
746 {
747 gl.getBufferSubData(target, offset, size, data);
748 GLU_EXPECT_NO_ERROR(gl.getError(), "GetBufferSubData");
749 }
750
751 /** Maps buffer content
752 *
753 * @param gl GL functions
754 * @param target Buffer target
755 * @param access Access rights for mapped region
756 *
757 * @return Mapped memory
758 **/
Map(const glw::Functions & gl,glw::GLenum target,glw::GLenum access)759 void *Buffer::Map(const glw::Functions &gl, glw::GLenum target, glw::GLenum access)
760 {
761 void *result = gl.mapBuffer(target, access);
762 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
763
764 return result;
765 }
766
767 /** Maps buffer content
768 *
769 * @param gl GL functions
770 * @param target Buffer target
771 * @param access Access rights for mapped region
772 *
773 * @return Mapped memory
774 **/
MapRange(const glw::Functions & gl,glw::GLenum target,glw::GLintptr offset,glw::GLsizeiptr length,glw::GLenum access)775 void *Buffer::MapRange(const glw::Functions &gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr length,
776 glw::GLenum access)
777 {
778 void *result = gl.mapBufferRange(target, offset, length, access);
779 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBufferRange");
780
781 return result;
782 }
783
784 /** Allocate immutable memory for buffer and sends initial content
785 *
786 * @param gl GL functions
787 * @param target Buffer target
788 * @param flags Buffer flags
789 * @param size <size> parameter
790 * @param data <data> parameter
791 **/
Storage(const glw::Functions & gl,glw::GLenum target,glw::GLenum flags,glw::GLsizeiptr size,const glw::GLvoid * data)792 void Buffer::Storage(const glw::Functions &gl, glw::GLenum target, glw::GLenum flags, glw::GLsizeiptr size,
793 const glw::GLvoid *data)
794 {
795 gl.bufferStorage(target, size, data, flags);
796 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferStorage");
797 }
798
799 /** Update range of buffer
800 *
801 * @param gl GL functions
802 * @param target Buffer target
803 * @param offset Offset in buffer
804 * @param size <size> parameter
805 * @param data <data> parameter
806 **/
SubData(const glw::Functions & gl,glw::GLenum target,glw::GLintptr offset,glw::GLsizeiptr size,glw::GLvoid * data)807 void Buffer::SubData(const glw::Functions &gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size,
808 glw::GLvoid *data)
809 {
810 gl.bufferSubData(target, offset, size, data);
811 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData");
812 }
813
814 /** Unmaps buffer
815 *
816 * @param gl GL functions
817 * @param target Buffer target
818 **/
UnMap(const glw::Functions & gl,glw::GLenum target)819 void Buffer::UnMap(const glw::Functions &gl, glw::GLenum target)
820 {
821 gl.unmapBuffer(target);
822 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
823 }
824
825 /** Constructor
826 * Takes ownership of mapped region
827 *
828 * @param buffer Mapped buffer
829 * @param data Mapped data
830 **/
MapOwner(Buffer & buffer,glw::GLvoid * data)831 Buffer::MapOwner::MapOwner(Buffer &buffer, glw::GLvoid *data) : m_data(data), m_buffer(&buffer)
832 {
833 /* Nothing to be done */
834 }
835
MapOwner(const Buffer::MoveMapOwner & moveOwner)836 Buffer::MapOwner::MapOwner(const Buffer::MoveMapOwner &moveOwner) : m_data(moveOwner.data), m_buffer(moveOwner.buffer)
837 {
838 }
839
840 /** Move constructor
841 * Transfer ownership of mapped region.
842 *
843 * @param map_owner Map owner
844 **/
MapOwner(MapOwner & map_owner)845 Buffer::MapOwner::MapOwner(MapOwner &map_owner) : m_data(map_owner.m_data), m_buffer(map_owner.m_buffer)
846 {
847 map_owner.m_data = 0;
848 map_owner.m_buffer = 0;
849 }
850
851 /** Destructor
852 * Unmaps buffer
853 **/
~MapOwner()854 Buffer::MapOwner::~MapOwner()
855 {
856 m_data = 0;
857 if (0 != m_buffer)
858 {
859 m_buffer->Bind();
860 m_buffer->UnMap();
861 m_buffer = 0;
862 }
863 }
864
865 /* Framebuffer constants */
866 const GLuint Framebuffer::m_invalid_id = -1;
867
868 /** Constructor.
869 *
870 * @param context CTS context.
871 **/
Framebuffer(deqp::Context & context)872 Framebuffer::Framebuffer(deqp::Context &context) : m_id(m_invalid_id), m_context(context)
873 {
874 /* Nothing to done here */
875 }
876
877 /** Destructor
878 *
879 **/
~Framebuffer()880 Framebuffer::~Framebuffer()
881 {
882 Release();
883 }
884
885 /** Release texture instance
886 *
887 **/
Release()888 void Framebuffer::Release()
889 {
890 if (m_invalid_id != m_id)
891 {
892 const Functions &gl = m_context.getRenderContext().getFunctions();
893
894 gl.deleteFramebuffers(1, &m_id);
895 m_id = m_invalid_id;
896 }
897 }
898
899 /** Attach texture to specified attachment
900 *
901 * @param gl GL functions
902 * @param target Framebuffer target
903 * @param attachment Attachment
904 * @param texture_id Texture id
905 * @param width Texture width
906 * @param height Texture height
907 **/
AttachTexture(const glw::Functions & gl,glw::GLenum target,glw::GLenum attachment,glw::GLuint texture_id,glw::GLuint width,glw::GLuint height)908 void Framebuffer::AttachTexture(const glw::Functions &gl, glw::GLenum target, glw::GLenum attachment,
909 glw::GLuint texture_id, glw::GLuint width, glw::GLuint height)
910 {
911 gl.framebufferTexture(target, attachment, texture_id, 0 /* level */);
912 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture");
913
914 gl.viewport(0 /* x */, 0 /* y */, width, height);
915 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
916 }
917
918 /** Binds framebuffer to DRAW_FRAMEBUFFER
919 *
920 * @param gl GL functions
921 * @param target Framebuffer target
922 * @param id ID of framebuffer
923 **/
Bind(const glw::Functions & gl,glw::GLenum target,glw::GLuint id)924 void Framebuffer::Bind(const glw::Functions &gl, glw::GLenum target, glw::GLuint id)
925 {
926 gl.bindFramebuffer(target, id);
927 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
928 }
929
930 /** Generate framebuffer
931 *
932 **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)933 void Framebuffer::Generate(const glw::Functions &gl, glw::GLuint &out_id)
934 {
935 GLuint id = m_invalid_id;
936
937 gl.genFramebuffers(1, &id);
938 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
939
940 if (m_invalid_id == id)
941 {
942 TCU_FAIL("Invalid id");
943 }
944
945 out_id = id;
946 }
947
948 /* Program constants */
949 const GLuint Program::m_invalid_id = 0;
950
951 /** Constructor.
952 *
953 * @param context CTS context.
954 **/
Program(deqp::Context & context)955 Program::Program(deqp::Context &context)
956 : m_id(m_invalid_id)
957 , m_compute(context)
958 , m_fragment(context)
959 , m_geometry(context)
960 , m_tess_ctrl(context)
961 , m_tess_eval(context)
962 , m_vertex(context)
963 , m_context(context)
964 {
965 /* Nothing to be done here */
966 }
967
968 /** Destructor
969 *
970 **/
~Program()971 Program::~Program()
972 {
973 Release();
974 }
975
976 /** Initialize program instance
977 *
978 * @param compute_shader Compute shader source code
979 * @param fragment_shader Fragment shader source code
980 * @param geometry_shader Geometry shader source code
981 * @param tesselation_control_shader Tesselation control shader source code
982 * @param tesselation_evaluation_shader Tesselation evaluation shader source code
983 * @param vertex_shader Vertex shader source code
984 **/
Init(const std::string & compute_shader,const std::string & fragment_shader,const std::string & geometry_shader,const std::string & tesselation_control_shader,const std::string & tesselation_evaluation_shader,const std::string & vertex_shader)985 void Program::Init(const std::string &compute_shader, const std::string &fragment_shader,
986 const std::string &geometry_shader, const std::string &tesselation_control_shader,
987 const std::string &tesselation_evaluation_shader, const std::string &vertex_shader)
988 {
989 /* Delete previous program */
990 Release();
991
992 /* GL entry points */
993 const Functions &gl = m_context.getRenderContext().getFunctions();
994
995 /* Initialize shaders */
996 m_compute.Init(GL_COMPUTE_SHADER, compute_shader);
997 m_fragment.Init(GL_FRAGMENT_SHADER, fragment_shader);
998 m_geometry.Init(GL_GEOMETRY_SHADER, geometry_shader);
999 m_tess_ctrl.Init(GL_TESS_CONTROL_SHADER, tesselation_control_shader);
1000 m_tess_eval.Init(GL_TESS_EVALUATION_SHADER, tesselation_evaluation_shader);
1001 m_vertex.Init(GL_VERTEX_SHADER, vertex_shader);
1002
1003 /* Create program, set up transform feedback and attach shaders */
1004 Create(gl, m_id);
1005 Attach(gl, m_id, m_compute.m_id);
1006 Attach(gl, m_id, m_fragment.m_id);
1007 Attach(gl, m_id, m_geometry.m_id);
1008 Attach(gl, m_id, m_tess_ctrl.m_id);
1009 Attach(gl, m_id, m_tess_eval.m_id);
1010 Attach(gl, m_id, m_vertex.m_id);
1011
1012 /* Link program */
1013 Link(gl, m_id);
1014 }
1015
1016 /** Release program instance
1017 *
1018 **/
Release()1019 void Program::Release()
1020 {
1021 const Functions &gl = m_context.getRenderContext().getFunctions();
1022
1023 if (m_invalid_id != m_id)
1024 {
1025 Use(gl, m_invalid_id);
1026
1027 gl.deleteProgram(m_id);
1028 m_id = m_invalid_id;
1029 }
1030
1031 m_compute.Release();
1032 m_fragment.Release();
1033 m_geometry.Release();
1034 m_tess_ctrl.Release();
1035 m_tess_eval.Release();
1036 m_vertex.Release();
1037 }
1038
1039 /** Attach shader to program
1040 *
1041 * @param gl GL functions
1042 * @param program_id Id of program
1043 * @param shader_id Id of shader
1044 **/
Attach(const glw::Functions & gl,glw::GLuint program_id,glw::GLuint shader_id)1045 void Program::Attach(const glw::Functions &gl, glw::GLuint program_id, glw::GLuint shader_id)
1046 {
1047 /* Quick checks */
1048 if ((m_invalid_id == program_id) || (Shader::m_invalid_id == shader_id))
1049 {
1050 return;
1051 }
1052
1053 gl.attachShader(program_id, shader_id);
1054 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
1055 }
1056
1057 /** Create program instance
1058 *
1059 * @param gl GL functions
1060 * @param out_id Id of program
1061 **/
Create(const glw::Functions & gl,glw::GLuint & out_id)1062 void Program::Create(const glw::Functions &gl, glw::GLuint &out_id)
1063 {
1064 const GLuint id = gl.createProgram();
1065 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
1066
1067 if (m_invalid_id == id)
1068 {
1069 TCU_FAIL("Failed to create program");
1070 }
1071
1072 out_id = id;
1073 }
1074
1075 /** Link program
1076 *
1077 * @param gl GL functions
1078 * @param id Id of program
1079 **/
Link(const glw::Functions & gl,glw::GLuint id)1080 void Program::Link(const glw::Functions &gl, glw::GLuint id)
1081 {
1082 GLint status = GL_FALSE;
1083
1084 gl.linkProgram(id);
1085 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
1086
1087 /* Get link status */
1088 gl.getProgramiv(id, GL_LINK_STATUS, &status);
1089 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
1090
1091 /* Log link error */
1092 if (GL_TRUE != status)
1093 {
1094 glw::GLint length = 0;
1095 std::string message;
1096
1097 /* Get error log length */
1098 gl.getProgramiv(id, GL_INFO_LOG_LENGTH, &length);
1099 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
1100
1101 message.resize(length, 0);
1102
1103 /* Get error log */
1104 gl.getProgramInfoLog(id, length, 0, &message[0]);
1105 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
1106
1107 TCU_FAIL(message.c_str());
1108 }
1109 }
1110
1111 /** Use program
1112 *
1113 * @param gl GL functions
1114 * @param id Id of program
1115 **/
Use(const glw::Functions & gl,glw::GLuint id)1116 void Program::Use(const glw::Functions &gl, glw::GLuint id)
1117 {
1118 gl.useProgram(id);
1119 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
1120 }
1121
1122 /* Shader's constants */
1123 const GLuint Shader::m_invalid_id = 0;
1124
1125 /** Constructor.
1126 *
1127 * @param context CTS context.
1128 **/
Shader(deqp::Context & context)1129 Shader::Shader(deqp::Context &context) : m_id(m_invalid_id), m_context(context)
1130 {
1131 /* Nothing to be done here */
1132 }
1133
1134 /** Destructor
1135 *
1136 **/
~Shader()1137 Shader::~Shader()
1138 {
1139 Release();
1140 }
1141
1142 /** Initialize shader instance
1143 *
1144 * @param stage Shader stage
1145 * @param source Source code
1146 **/
Init(glw::GLenum stage,const std::string & source)1147 void Shader::Init(glw::GLenum stage, const std::string &source)
1148 {
1149 if (true == source.empty())
1150 {
1151 /* No source == no shader */
1152 return;
1153 }
1154
1155 /* Delete any previous shader */
1156 Release();
1157
1158 /* Create, set source and compile */
1159 const Functions &gl = m_context.getRenderContext().getFunctions();
1160
1161 Create(gl, stage, m_id);
1162 Source(gl, m_id, source);
1163
1164 Compile(gl, m_id);
1165 }
1166
1167 /** Release shader instance
1168 *
1169 **/
Release()1170 void Shader::Release()
1171 {
1172 if (m_invalid_id != m_id)
1173 {
1174 const Functions &gl = m_context.getRenderContext().getFunctions();
1175
1176 gl.deleteShader(m_id);
1177 m_id = m_invalid_id;
1178 }
1179 }
1180
1181 /** Compile shader
1182 *
1183 * @param gl GL functions
1184 * @param id Shader id
1185 **/
Compile(const glw::Functions & gl,glw::GLuint id)1186 void Shader::Compile(const glw::Functions &gl, glw::GLuint id)
1187 {
1188 GLint status = GL_FALSE;
1189
1190 /* Compile */
1191 gl.compileShader(id);
1192 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
1193
1194 /* Get compilation status */
1195 gl.getShaderiv(id, GL_COMPILE_STATUS, &status);
1196 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
1197
1198 /* Log compilation error */
1199 if (GL_TRUE != status)
1200 {
1201 glw::GLint length = 0;
1202 std::string message;
1203
1204 /* Error log length */
1205 gl.getShaderiv(id, GL_INFO_LOG_LENGTH, &length);
1206 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
1207
1208 /* Prepare storage */
1209 message.resize(length, 0);
1210
1211 /* Get error log */
1212 gl.getShaderInfoLog(id, length, 0, &message[0]);
1213 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
1214
1215 TCU_FAIL(message.c_str());
1216 }
1217 }
1218
1219 /** Create shader
1220 *
1221 * @param gl GL functions
1222 * @param stage Shader stage
1223 * @param out_id Shader id
1224 **/
Create(const glw::Functions & gl,glw::GLenum stage,glw::GLuint & out_id)1225 void Shader::Create(const glw::Functions &gl, glw::GLenum stage, glw::GLuint &out_id)
1226 {
1227 const GLuint id = gl.createShader(stage);
1228 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
1229
1230 if (m_invalid_id == id)
1231 {
1232 TCU_FAIL("Failed to create shader");
1233 }
1234
1235 out_id = id;
1236 }
1237
1238 /** Set shader's source code
1239 *
1240 * @param gl GL functions
1241 * @param id Shader id
1242 * @param source Shader source code
1243 **/
Source(const glw::Functions & gl,glw::GLuint id,const std::string & source)1244 void Shader::Source(const glw::Functions &gl, glw::GLuint id, const std::string &source)
1245 {
1246 const GLchar *code = source.c_str();
1247
1248 gl.shaderSource(id, 1 /* count */, &code, 0 /* lengths */);
1249 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
1250 }
1251
1252 /* Texture static fields */
1253
1254 FUNCTIONALITY_SUPPORT Texture::m_direct_state_access_support = FUNCTIONALITY_SUPPORT_NOT_DETERMINED;
1255
1256 /* Texture constants */
1257 const GLuint Texture::m_invalid_id = -1;
1258
1259 /** Constructor.
1260 *
1261 * @param context CTS context.
1262 **/
Texture(deqp::Context & context)1263 Texture::Texture(deqp::Context &context) : m_id(m_invalid_id), m_context(context)
1264 {
1265 /* Nothing to done here */
1266 }
1267
1268 /** Destructor
1269 *
1270 **/
~Texture()1271 Texture::~Texture()
1272 {
1273 Release();
1274 }
1275
1276 /** Release texture instance
1277 *
1278 **/
Release()1279 void Texture::Release()
1280 {
1281 if (m_invalid_id != m_id)
1282 {
1283 const Functions &gl = m_context.getRenderContext().getFunctions();
1284
1285 gl.deleteTextures(1, &m_id);
1286 m_id = m_invalid_id;
1287 }
1288 }
1289
1290 /** Loads entry points for direct state access extension
1291 *
1292 * @param context CTS context
1293 **/
LoadExtDirectStateAccess(deqp::Context & context)1294 void Texture::LoadExtDirectStateAccess(deqp::Context &context)
1295 {
1296 FUNCTIONALITY_SUPPORT support = getDirectStateAccessSupport(context);
1297
1298 switch (support)
1299 {
1300 case FUNCTIONALITY_SUPPORT_NONE:
1301 /* Nothing to be done */
1302 break;
1303 case FUNCTIONALITY_SUPPORT_CORE:
1304 case FUNCTIONALITY_SUPPORT_EXTENSION:
1305 break;
1306 default:
1307 TCU_FAIL("Invalid enum");
1308 }
1309 }
1310
1311 /** Bind texture to target
1312 *
1313 * @param gl GL functions
1314 * @param id Id of texture
1315 * @param tex_type Type of texture
1316 **/
Bind(const glw::Functions & gl,glw::GLuint id,glw::GLenum target)1317 void Texture::Bind(const glw::Functions &gl, glw::GLuint id, glw::GLenum target)
1318 {
1319 gl.bindTexture(target, id);
1320 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
1321 }
1322
1323 /** Set contents of compressed texture
1324 *
1325 * @param gl GL functions
1326 * @param target Texture target
1327 * @param level Mipmap level
1328 * @param internal_format Format of data
1329 * @param width Width of texture
1330 * @param height Height of texture
1331 * @param depth Depth of texture
1332 * @param image_size Size of data
1333 * @param data Buffer with image data
1334 **/
CompressedImage(const glw::Functions & gl,glw::GLenum target,glw::GLint level,glw::GLenum internal_format,glw::GLuint width,glw::GLuint height,glw::GLuint depth,glw::GLsizei image_size,const glw::GLvoid * data)1335 void Texture::CompressedImage(const glw::Functions &gl, glw::GLenum target, glw::GLint level,
1336 glw::GLenum internal_format, glw::GLuint width, glw::GLuint height, glw::GLuint depth,
1337 glw::GLsizei image_size, const glw::GLvoid *data)
1338 {
1339 switch (target)
1340 {
1341 case GL_TEXTURE_1D:
1342 gl.compressedTexImage1D(target, level, internal_format, width, 0 /* border */, image_size, data);
1343 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage1D");
1344 break;
1345 case GL_TEXTURE_1D_ARRAY:
1346 case GL_TEXTURE_2D:
1347 case GL_TEXTURE_RECTANGLE:
1348 gl.compressedTexImage2D(target, level, internal_format, width, height, 0 /* border */, image_size, data);
1349 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D");
1350 break;
1351 case GL_TEXTURE_CUBE_MAP:
1352 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */,
1353 image_size, data);
1354 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */,
1355 image_size, data);
1356 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */,
1357 image_size, data);
1358 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */,
1359 image_size, data);
1360 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */,
1361 image_size, data);
1362 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */,
1363 image_size, data);
1364 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D");
1365 break;
1366 case GL_TEXTURE_3D:
1367 case GL_TEXTURE_2D_ARRAY:
1368 gl.compressedTexImage3D(target, level, internal_format, width, height, depth, 0 /* border */, image_size, data);
1369 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage3D");
1370 break;
1371 default:
1372 TCU_FAIL("Invliad enum");
1373 }
1374 }
1375
1376 /** Generate texture instance
1377 *
1378 * @param gl GL functions
1379 * @param out_id Id of texture
1380 **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)1381 void Texture::Generate(const glw::Functions &gl, glw::GLuint &out_id)
1382 {
1383 GLuint id = m_invalid_id;
1384
1385 gl.genTextures(1, &id);
1386 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
1387
1388 if (m_invalid_id == id)
1389 {
1390 TCU_FAIL("Invalid id");
1391 }
1392
1393 out_id = id;
1394 }
1395
1396 /** Get texture data
1397 *
1398 * @param gl GL functions
1399 * @param target Texture target
1400 * @param format Format of data
1401 * @param type Type of data
1402 * @param out_data Buffer for data
1403 **/
GetData(const glw::Functions & gl,glw::GLenum target,glw::GLenum format,glw::GLenum type,glw::GLvoid * out_data)1404 void Texture::GetData(const glw::Functions &gl, glw::GLenum target, glw::GLenum format, glw::GLenum type,
1405 glw::GLvoid *out_data)
1406 {
1407 gl.getTexImage(target, 0 /* level */, format, type, out_data);
1408 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
1409 }
1410
1411 /** Generate texture instance
1412 *
1413 * @param gl GL functions
1414 * @param target Texture target
1415 * @param level Mipmap level
1416 * @param pname Parameter to query
1417 * @param param Result of query
1418 **/
GetLevelParameter(const glw::Functions & gl,glw::GLenum target,glw::GLint level,glw::GLenum pname,glw::GLint * param)1419 void Texture::GetLevelParameter(const glw::Functions &gl, glw::GLenum target, glw::GLint level, glw::GLenum pname,
1420 glw::GLint *param)
1421 {
1422 gl.getTexLevelParameteriv(target, level, pname, param);
1423 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexLevelParameteriv");
1424 }
1425
1426 /** Set contents of texture
1427 *
1428 * @param gl GL functions
1429 * @param target Texture target
1430 * @param level Mipmap level
1431 * @param internal_format Format of data
1432 * @param width Width of texture
1433 * @param height Height of texture
1434 * @param depth Depth of texture
1435 * @param format Format of data
1436 * @param type Type of data
1437 * @param data Buffer with image data
1438 **/
Image(const glw::Functions & gl,glw::GLenum target,glw::GLint level,glw::GLenum internal_format,glw::GLuint width,glw::GLuint height,glw::GLuint depth,glw::GLenum format,glw::GLenum type,const glw::GLvoid * data)1439 void Texture::Image(const glw::Functions &gl, glw::GLenum target, glw::GLint level, glw::GLenum internal_format,
1440 glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type,
1441 const glw::GLvoid *data)
1442 {
1443 switch (target)
1444 {
1445 case GL_TEXTURE_1D:
1446 gl.texImage1D(target, level, internal_format, width, 0 /* border */, format, type, data);
1447 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage1D");
1448 break;
1449 case GL_TEXTURE_1D_ARRAY:
1450 case GL_TEXTURE_2D:
1451 case GL_TEXTURE_RECTANGLE:
1452 gl.texImage2D(target, level, internal_format, width, height, 0 /* border */, format, type, data);
1453 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
1454 break;
1455 case GL_TEXTURE_CUBE_MAP:
1456 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */, format,
1457 type, data);
1458 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */, format,
1459 type, data);
1460 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */, format,
1461 type, data);
1462 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */, format,
1463 type, data);
1464 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */, format,
1465 type, data);
1466 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */, format,
1467 type, data);
1468 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
1469 break;
1470 case GL_TEXTURE_3D:
1471 case GL_TEXTURE_2D_ARRAY:
1472 gl.texImage3D(target, level, internal_format, width, height, depth, 0 /* border */, format, type, data);
1473 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage3D");
1474 break;
1475 default:
1476 TCU_FAIL("Invliad enum");
1477 }
1478 }
1479
1480 /** Allocate storage for texture
1481 *
1482 * @param gl GL functions
1483 * @param target Texture target
1484 * @param levels Number of levels
1485 * @param internal_format Internal format of texture
1486 * @param width Width of texture
1487 * @param height Height of texture
1488 * @param depth Depth of texture
1489 **/
Storage(const glw::Functions & gl,glw::GLenum target,glw::GLsizei levels,glw::GLenum internal_format,glw::GLuint width,glw::GLuint height,glw::GLuint depth)1490 void Texture::Storage(const glw::Functions &gl, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format,
1491 glw::GLuint width, glw::GLuint height, glw::GLuint depth)
1492 {
1493 switch (target)
1494 {
1495 case GL_TEXTURE_1D:
1496 gl.texStorage1D(target, levels, internal_format, width);
1497 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage1D");
1498 break;
1499 case GL_TEXTURE_1D_ARRAY:
1500 case GL_TEXTURE_2D:
1501 case GL_TEXTURE_RECTANGLE:
1502 case GL_TEXTURE_CUBE_MAP:
1503 gl.texStorage2D(target, levels, internal_format, width, height);
1504 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
1505 break;
1506 case GL_TEXTURE_3D:
1507 case GL_TEXTURE_2D_ARRAY:
1508 gl.texStorage3D(target, levels, internal_format, width, height, depth);
1509 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D");
1510 break;
1511 default:
1512 TCU_FAIL("Invliad enum");
1513 }
1514 }
1515
1516 /** Set contents of texture
1517 *
1518 * @param gl GL functions
1519 * @param target Texture target
1520 * @param level Mipmap level
1521 * @param x X offset
1522 * @param y Y offset
1523 * @param z Z offset
1524 * @param width Width of texture
1525 * @param height Height of texture
1526 * @param depth Depth of texture
1527 * @param format Format of data
1528 * @param type Type of data
1529 * @param pixels Buffer with image data
1530 **/
SubImage(const glw::Functions & gl,glw::GLenum target,glw::GLint level,glw::GLint x,glw::GLint y,glw::GLint z,glw::GLsizei width,glw::GLsizei height,glw::GLsizei depth,glw::GLenum format,glw::GLenum type,const glw::GLvoid * pixels)1531 void Texture::SubImage(const glw::Functions &gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y,
1532 glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format,
1533 glw::GLenum type, const glw::GLvoid *pixels)
1534 {
1535 switch (target)
1536 {
1537 case GL_TEXTURE_1D:
1538 gl.texSubImage1D(target, level, x, width, format, type, pixels);
1539 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage1D");
1540 break;
1541 case GL_TEXTURE_1D_ARRAY:
1542 case GL_TEXTURE_2D:
1543 case GL_TEXTURE_RECTANGLE:
1544 gl.texSubImage2D(target, level, x, y, width, height, format, type, pixels);
1545 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
1546 break;
1547 case GL_TEXTURE_CUBE_MAP:
1548 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, x, y, width, height, format, type, pixels);
1549 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, x, y, width, height, format, type, pixels);
1550 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, x, y, width, height, format, type, pixels);
1551 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, x, y, width, height, format, type, pixels);
1552 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, x, y, width, height, format, type, pixels);
1553 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, x, y, width, height, format, type, pixels);
1554 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
1555 break;
1556 case GL_TEXTURE_3D:
1557 case GL_TEXTURE_2D_ARRAY:
1558 gl.texSubImage3D(target, level, x, y, z, width, height, depth, format, type, pixels);
1559 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage3D");
1560 break;
1561 default:
1562 TCU_FAIL("Invliad enum");
1563 }
1564 }
1565
1566 /* VertexArray constants */
1567 const GLuint VertexArray::m_invalid_id = -1;
1568
1569 /** Constructor.
1570 *
1571 * @param context CTS context.
1572 **/
VertexArray(deqp::Context & context)1573 VertexArray::VertexArray(deqp::Context &context) : m_id(m_invalid_id), m_context(context)
1574 {
1575 }
1576
1577 /** Destructor
1578 *
1579 **/
~VertexArray()1580 VertexArray::~VertexArray()
1581 {
1582 Release();
1583 }
1584
1585 /** Release vertex array object instance
1586 *
1587 **/
Release()1588 void VertexArray::Release()
1589 {
1590 if (m_invalid_id != m_id)
1591 {
1592 const Functions &gl = m_context.getRenderContext().getFunctions();
1593
1594 Bind(gl, 0);
1595
1596 gl.deleteVertexArrays(1, &m_id);
1597
1598 m_id = m_invalid_id;
1599 }
1600 }
1601
1602 /** Binds Vertex array object
1603 *
1604 * @param gl GL functions
1605 * @param id ID of vertex array object
1606 **/
Bind(const glw::Functions & gl,glw::GLuint id)1607 void VertexArray::Bind(const glw::Functions &gl, glw::GLuint id)
1608 {
1609 gl.bindVertexArray(id);
1610 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
1611 }
1612
1613 /** Generates Vertex array object
1614 *
1615 * @param gl GL functions
1616 * @param out_id ID of vertex array object
1617 **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)1618 void VertexArray::Generate(const glw::Functions &gl, glw::GLuint &out_id)
1619 {
1620 GLuint id = m_invalid_id;
1621
1622 gl.genVertexArrays(1, &id);
1623 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
1624
1625 if (m_invalid_id == id)
1626 {
1627 TCU_FAIL("Invalid id");
1628 }
1629
1630 out_id = id;
1631 }
1632
1633 /** Constructor
1634 *
1635 * @param context Test context
1636 **/
ErrorsTest(deqp::Context & context)1637 ErrorsTest::ErrorsTest(deqp::Context &context)
1638 : TestCase(context, "errors", "Test if errors are generated as specified")
1639 {
1640 /* Nothing to be done here */
1641 }
1642
1643 /** Execute test
1644 *
1645 * @return tcu::TestNode::STOP otherwise
1646 **/
iterate()1647 tcu::TestNode::IterateResult ErrorsTest::iterate()
1648 {
1649 const Functions &gl = m_context.getRenderContext().getFunctions();
1650
1651 bool test_result = true;
1652
1653 Buffer::LoadExtDirectStateAccess(m_context);
1654
1655 // No GL45 or GL_ARB_direct_state_access support
1656 if (m_direct_state_access_support == FUNCTIONALITY_SUPPORT_NONE)
1657 {
1658 m_context.getTestContext().setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Unsupported");
1659 return tcu::TestNode::STOP;
1660 }
1661
1662 /*
1663 * - INVALID_OPERATION is generated by BufferStorage when 0 is bound to
1664 * <target>; Check all targets;
1665 */
1666 for (GLuint i = 0; i < Buffer::m_n_targets; ++i)
1667 {
1668 const GLenum target = Buffer::m_targets[i];
1669 std::string message = "BufferStorage was executed for id 0, target: ";
1670
1671 message.append(glu::getBufferTargetStr(target).toString().c_str());
1672
1673 Buffer::Bind(gl, 0 /* id */, target);
1674 gl.bufferStorage(target, 0 /* size */, 0 /* data */, GL_DYNAMIC_STORAGE_BIT /* flags */);
1675
1676 verifyError(GL_INVALID_OPERATION, message.c_str(), test_result);
1677 }
1678
1679 /*
1680 * - INVLIAD_OPERATION is generated by BufferStorage, NamedBufferStorage and
1681 * BufferData if buffer already have immutable store;
1682 */
1683 {
1684 static const GLsizeiptr data_size = 32;
1685 static GLubyte data[data_size];
1686
1687 Buffer buffer(m_context);
1688 buffer.InitStorage(GL_ARRAY_BUFFER, GL_DYNAMIC_STORAGE_BIT, data_size, data);
1689
1690 /* NamedBufferStorage */
1691 if (0 != gl.namedBufferStorage)
1692 {
1693 gl.namedBufferStorage(buffer.m_id, data_size, data, GL_DYNAMIC_STORAGE_BIT);
1694 verifyError(GL_INVALID_OPERATION, "NamedBufferStorage was executed for id with immutable storage",
1695 test_result);
1696 }
1697
1698 /* BufferStorage */
1699 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1700
1701 gl.bufferStorage(GL_ARRAY_BUFFER, data_size, data, GL_DYNAMIC_STORAGE_BIT);
1702 verifyError(GL_INVALID_OPERATION, "BufferStorage was executed for target with immutable storage", test_result);
1703
1704 Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1705 }
1706
1707 /*
1708 * - INVALID_VALUE is generated by BufferStorage and NamedBufferStorage when
1709 * <size> is less or equal to zero;
1710 */
1711 {
1712 static const GLsizeiptr data_size = 32;
1713 static GLubyte data[data_size];
1714
1715 Buffer buffer(m_context);
1716 gl.createBuffers(1, &buffer.m_id);
1717
1718 /* NamedBufferStorage */
1719 if (0 != gl.namedBufferStorage)
1720 {
1721 gl.namedBufferStorage(buffer.m_id, 0 /* size */, data, GL_DYNAMIC_STORAGE_BIT);
1722 verifyError(GL_INVALID_VALUE, "NamedBufferStorage was executed with size == 0", test_result);
1723
1724 gl.namedBufferStorage(buffer.m_id, -16 /* size */, data, GL_DYNAMIC_STORAGE_BIT);
1725 verifyError(GL_INVALID_VALUE, "NamedBufferStorage was executed with size == -16", test_result);
1726 }
1727
1728 /* BufferStorage */
1729 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1730
1731 gl.bufferStorage(GL_ARRAY_BUFFER, 0 /* size */, data, GL_DYNAMIC_STORAGE_BIT);
1732 verifyError(GL_INVALID_VALUE, "BufferStorage was executed with size == 0", test_result);
1733
1734 gl.bufferStorage(GL_ARRAY_BUFFER, -16 /* size */, data, GL_DYNAMIC_STORAGE_BIT);
1735 verifyError(GL_INVALID_VALUE, "BufferStorage was executed with size == -16", test_result);
1736
1737 Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1738 }
1739
1740 /*
1741 * - INVLAID_VALUE is generated by BufferStorage and NamedBufferStorage when
1742 * <flags> contains MAP_PERSISTENT_BIT and neither MAP_READ_BIT nor
1743 * MAP_WRITE_BIT;
1744 */
1745 {
1746 static const GLsizeiptr data_size = 32;
1747 static GLubyte data[data_size];
1748
1749 Buffer buffer(m_context);
1750 gl.createBuffers(1, &buffer.m_id);
1751
1752 /* NamedBufferStorage */
1753 if (0 != gl.namedBufferStorage)
1754 {
1755 gl.namedBufferStorage(buffer.m_id, data_size, data, GL_MAP_PERSISTENT_BIT);
1756 verifyError(GL_INVALID_VALUE, "NamedBufferStorage was executed with flags == GL_MAP_PERSISTENT_BIT",
1757 test_result);
1758 }
1759
1760 /* BufferStorage */
1761 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1762
1763 gl.bufferStorage(GL_ARRAY_BUFFER, data_size, data, GL_MAP_PERSISTENT_BIT);
1764 verifyError(GL_INVALID_VALUE, "BufferStorage was executed with flags == GL_MAP_PERSISTENT_BIT", test_result);
1765
1766 Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1767 }
1768
1769 /*
1770 * - INVALID_VALUE is generated by BufferStorage and NamedBufferStorage when
1771 * <flags> contains MAP_COHERENT_BIT and no MAP_PERSISTENT_BIT;
1772 */
1773 {
1774 static const GLsizeiptr data_size = 32;
1775 static GLubyte data[data_size];
1776
1777 Buffer buffer(m_context);
1778 gl.createBuffers(1, &buffer.m_id);
1779
1780 /* NamedBufferStorage */
1781 if (0 != gl.namedBufferStorage)
1782 {
1783 gl.namedBufferStorage(buffer.m_id, data_size, data, GL_MAP_COHERENT_BIT);
1784 verifyError(GL_INVALID_VALUE, "NamedBufferStorage was executed with flags == GL_MAP_COHERENT_BIT",
1785 test_result);
1786 }
1787
1788 /* BufferStorage */
1789 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1790
1791 gl.bufferStorage(GL_ARRAY_BUFFER, data_size, data, GL_MAP_COHERENT_BIT);
1792 verifyError(GL_INVALID_VALUE, "BufferStorage was executed with flags == GL_MAP_COHERENT_BIT", test_result);
1793
1794 Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1795 }
1796
1797 /*
1798 * - INVALID_OPERATION is generated by MapBufferRange if any of:
1799 * * MAP_COHERENT_BIT,
1800 * * MAP_PERSISTENT_BIT,
1801 * * MAP_READ_BIT,
1802 * * MAP_WRITE_BIT
1803 * is included in <access> and not in buffer's storage flags;
1804 */
1805 {
1806 static const GLsizeiptr data_size = 32;
1807 static GLubyte data[data_size];
1808
1809 Buffer buffer(m_context);
1810 buffer.InitStorage(GL_ARRAY_BUFFER, GL_DYNAMIC_STORAGE_BIT, data_size, data);
1811
1812 /* MapNamedBufferRange */
1813 if (0 != gl.mapNamedBufferRange)
1814 {
1815 gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_READ_BIT);
1816 verifyError(GL_INVALID_OPERATION,
1817 "MapNamedBufferRange was executed with access == GL_MAP_READ_BIT, "
1818 "storage flags == GL_DYNAMIC_STORAGE_BIT",
1819 test_result);
1820
1821 gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_WRITE_BIT);
1822 verifyError(GL_INVALID_OPERATION,
1823 "MapNamedBufferRange was executed with access == GL_MAP_WRITE_BIT, "
1824 "storage flags == GL_DYNAMIC_STORAGE_BIT",
1825 test_result);
1826
1827 gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT);
1828 verifyError(GL_INVALID_OPERATION,
1829 "MapNamedBufferRange was executed with access == GL_MAP_PERSISTENT_BIT, "
1830 "storage flags == GL_DYNAMIC_STORAGE_BIT",
1831 test_result);
1832
1833 gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_COHERENT_BIT);
1834 verifyError(GL_INVALID_OPERATION,
1835 "MapNamedBufferRange was executed with access == GL_MAP_COHERENT_BIT, "
1836 "storage flags == GL_DYNAMIC_STORAGE_BIT",
1837 test_result);
1838 }
1839
1840 /* BufferStorage */
1841 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1842
1843 gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_READ_BIT);
1844 verifyError(
1845 GL_INVALID_OPERATION,
1846 "MapBufferRange was executed with access == GL_MAP_READ_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT",
1847 test_result);
1848
1849 gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_WRITE_BIT);
1850 verifyError(
1851 GL_INVALID_OPERATION,
1852 "MapBufferRange was executed with access == GL_MAP_WRITE_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT",
1853 test_result);
1854
1855 gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT);
1856 verifyError(
1857 GL_INVALID_OPERATION,
1858 "MapBufferRange was executed with access == GL_MAP_PERSISTENT_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT",
1859 test_result);
1860
1861 gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_COHERENT_BIT);
1862 verifyError(
1863 GL_INVALID_OPERATION,
1864 "MapBufferRange was executed with access == GL_MAP_COHERENT_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT",
1865 test_result);
1866
1867 Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1868 }
1869
1870 /*
1871 * - INVALID_OPERATION is generated by BufferSubData and NamedBufferSubData
1872 * when buffer has immutable store but its flags does not include
1873 * DYNAMIC_STORAGE.
1874 */
1875 {
1876 static const GLsizeiptr data_size = 32;
1877 static GLubyte data[data_size];
1878
1879 Buffer buffer(m_context);
1880 buffer.InitStorage(GL_ARRAY_BUFFER, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT, data_size,
1881 data);
1882
1883 /* NamedBufferSubData */
1884 if (0 != gl.namedBufferSubData)
1885 {
1886 gl.namedBufferSubData(buffer.m_id, 0 /* offset */, data_size, data);
1887 verifyError(GL_INVALID_OPERATION,
1888 "NamedBufferSubData was executed for storage without GL_DYNAMIC_STORAGE_BIT", test_result);
1889 }
1890
1891 /* BufferStorage */
1892 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1893
1894 gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, data_size, data);
1895 verifyError(GL_INVALID_OPERATION, "BufferSubData was executed for storage without GL_DYNAMIC_STORAGE_BIT",
1896 test_result);
1897
1898 Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1899 }
1900
1901 /* Set result */
1902 if (true == test_result)
1903 {
1904 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1905 }
1906 else
1907 {
1908 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1909 }
1910
1911 /* Done */
1912 return tcu::TestNode::STOP;
1913 }
1914
1915 /** Verifies that expected error was generated
1916 *
1917 * @param expected_error Expected error
1918 * @param error_message Message that will be logged in case of wrong error
1919 * @param out_test_result Set to false if worng error was generated, not modified otherwise
1920 **/
verifyError(glw::GLenum expected_error,const glw::GLchar * error_message,bool & out_test_result)1921 void ErrorsTest::verifyError(glw::GLenum expected_error, const glw::GLchar *error_message, bool &out_test_result)
1922 {
1923 const Functions &gl = m_context.getRenderContext().getFunctions();
1924
1925 const GLenum error = gl.getError();
1926
1927 if (error != expected_error)
1928 {
1929 out_test_result = false;
1930
1931 m_context.getTestContext().getLog()
1932 << tcu::TestLog::Message << "Got invalid error: " << glu::getErrorName(error)
1933 << ", expected: " << glu::getErrorName(expected_error) << ". Message: " << error_message
1934 << tcu::TestLog::EndMessage;
1935 }
1936 }
1937
1938 /** Constructor
1939 *
1940 * @param context Test context
1941 **/
GetBufferParameterTest(deqp::Context & context)1942 GetBufferParameterTest::GetBufferParameterTest(deqp::Context &context)
1943 : TestCase(context, "get_buffer_parameter", "Test queries for parameters of buffers")
1944 {
1945 static const GLenum s_mapping_bits[] = {0, GL_MAP_PERSISTENT_BIT, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT};
1946 static const GLuint s_n_mapping_bits = sizeof(s_mapping_bits) / sizeof(s_mapping_bits[0]);
1947
1948 GLenum flags = 0;
1949
1950 for (GLuint dynamic = 0; dynamic < 2; ++dynamic)
1951 {
1952 flags = (0 == dynamic) ? 0 : GL_DYNAMIC_STORAGE_BIT;
1953
1954 for (GLuint client = 0; client < 2; ++client)
1955 {
1956 flags |= (0 == client) ? 0 : GL_CLIENT_STORAGE_BIT;
1957
1958 /* No "map" bits */
1959 if (0 != flags)
1960 {
1961 m_test_cases.push_back(testCase(flags, 0));
1962 }
1963
1964 for (GLuint flag_idx = 0; flag_idx < s_n_mapping_bits; ++flag_idx)
1965 {
1966 const GLenum flag_mapping_bits = s_mapping_bits[flag_idx];
1967 const GLenum flags_with_mapping = flags | flag_mapping_bits;
1968
1969 for (GLuint access_idx = 0; access_idx <= flag_idx; ++access_idx)
1970 {
1971 const GLenum access = s_mapping_bits[access_idx];
1972
1973 m_test_cases.push_back(testCase(flags_with_mapping | GL_MAP_READ_BIT, access | GL_MAP_READ_BIT));
1974 m_test_cases.push_back(testCase(flags_with_mapping | GL_MAP_WRITE_BIT, access | GL_MAP_WRITE_BIT));
1975 m_test_cases.push_back(
1976 testCase(flags_with_mapping | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, access | GL_MAP_READ_BIT));
1977 m_test_cases.push_back(
1978 testCase(flags_with_mapping | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, access | GL_MAP_WRITE_BIT));
1979 m_test_cases.push_back(testCase(flags_with_mapping | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
1980 access | GL_MAP_WRITE_BIT | GL_MAP_READ_BIT));
1981 }
1982 }
1983 }
1984 }
1985 }
1986
1987 /** Execute test
1988 *
1989 * @return tcu::TestNode::STOP otherwise
1990 **/
iterate()1991 tcu::TestNode::IterateResult GetBufferParameterTest::iterate()
1992 {
1993 static const GLsizeiptr data_size = 32;
1994 static GLubyte data[data_size];
1995
1996 Buffer::LoadExtDirectStateAccess(m_context);
1997
1998 // No GL45 or GL_ARB_direct_state_access support
1999 if (m_direct_state_access_support == FUNCTIONALITY_SUPPORT_NONE)
2000 {
2001 m_context.getTestContext().setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Unsupported");
2002 return tcu::TestNode::STOP;
2003 }
2004
2005 const Functions &gl = m_context.getRenderContext().getFunctions();
2006
2007 bool test_result = true;
2008
2009 for (GLuint i = 0; i < m_test_cases.size(); ++i)
2010 {
2011 const testCase &test_case = m_test_cases[i];
2012 const GLenum access = test_case.m_access;
2013 const GLenum flags = test_case.m_flags;
2014
2015 GLint queried_flags = -1;
2016 GLint queried_immutable = -1;
2017 GLint queried_size = -1;
2018
2019 Buffer buffer(m_context);
2020
2021 buffer.InitStorage(GL_ARRAY_BUFFER, flags, data_size, data);
2022 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
2023
2024 if (0 != gl.getNamedBufferParameteriv)
2025 {
2026 Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_STORAGE_FLAGS, &queried_flags);
2027 Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_IMMUTABLE_STORAGE, &queried_immutable);
2028 Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_SIZE, &queried_size);
2029
2030 if (queried_flags != (GLint)flags)
2031 {
2032 test_result = false;
2033 m_context.getTestContext().getLog()
2034 << tcu::TestLog::Message
2035 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_STORAGE_FLAGS: " << queried_flags
2036 << " expected: " << flags << tcu::TestLog::EndMessage;
2037 }
2038 }
2039
2040 if (queried_flags != (GLint)flags)
2041 {
2042 test_result = false;
2043 m_context.getTestContext().getLog()
2044 << tcu::TestLog::Message
2045 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_STORAGE_FLAGS: " << queried_flags
2046 << " expected: " << flags << tcu::TestLog::EndMessage;
2047 }
2048
2049 if (queried_immutable != GL_TRUE)
2050 {
2051 test_result = false;
2052 m_context.getTestContext().getLog()
2053 << tcu::TestLog::Message
2054 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_IMMUTABLE_STORAGE: "
2055 << queried_immutable << " expected: " << GL_TRUE << tcu::TestLog::EndMessage;
2056 }
2057
2058 if (queried_size != data_size)
2059 {
2060 test_result = false;
2061 m_context.getTestContext().getLog()
2062 << tcu::TestLog::Message
2063 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_SIZE: " << queried_size
2064 << " expected: " << data_size << tcu::TestLog::EndMessage;
2065 }
2066
2067 queried_flags = -1;
2068 queried_immutable = -1;
2069 queried_size = -1;
2070
2071 Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_STORAGE_FLAGS, &queried_flags);
2072 Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_IMMUTABLE_STORAGE, &queried_immutable);
2073 Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &queried_size);
2074
2075 if (queried_flags != (GLint)flags)
2076 {
2077 test_result = false;
2078 m_context.getTestContext().getLog()
2079 << tcu::TestLog::Message
2080 << "GetBufferParameteriv reported invalid state of GL_BUFFER_STORAGE_FLAGS: " << queried_flags
2081 << " expected: " << flags << tcu::TestLog::EndMessage;
2082 }
2083
2084 if (queried_immutable != GL_TRUE)
2085 {
2086 test_result = false;
2087 m_context.getTestContext().getLog()
2088 << tcu::TestLog::Message
2089 << "GetBufferParameteriv reported invalid state of GL_BUFFER_IMMUTABLE_STORAGE: " << queried_immutable
2090 << " expected: " << GL_TRUE << tcu::TestLog::EndMessage;
2091 }
2092
2093 if (queried_size != data_size)
2094 {
2095 test_result = false;
2096 m_context.getTestContext().getLog()
2097 << tcu::TestLog::Message
2098 << "GetBufferParameteriv reported invalid state of GL_BUFFER_SIZE: " << queried_size
2099 << " expected: " << data_size << tcu::TestLog::EndMessage;
2100 }
2101
2102 if (0 != access)
2103 {
2104 GLint queried_access = -1;
2105
2106 Buffer::MapOwner tmp(buffer.MapRange(0 /* offset */, data_size, access));
2107
2108 if (0 != gl.getNamedBufferParameteriv)
2109 {
2110 Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_ACCESS_FLAGS, &queried_access);
2111 }
2112
2113 if (queried_access != (GLint)access)
2114 {
2115 test_result = false;
2116 m_context.getTestContext().getLog()
2117 << tcu::TestLog::Message
2118 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_ACCESS_FLAGS: " << queried_access
2119 << " expected: " << access << tcu::TestLog::EndMessage;
2120 }
2121
2122 queried_access = -1;
2123
2124 Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_ACCESS_FLAGS, &queried_access);
2125
2126 if (queried_access != (GLint)access)
2127 {
2128 test_result = false;
2129 m_context.getTestContext().getLog()
2130 << tcu::TestLog::Message
2131 << "GetBufferParameteriv reported invalid state of GL_BUFFER_ACCESS_FLAGS: " << queried_access
2132 << " expected: " << access << tcu::TestLog::EndMessage;
2133 }
2134 }
2135
2136 Buffer::Bind(gl, 0 /* id */, GL_ARRAY_BUFFER);
2137 }
2138
2139 /* Set result */
2140 if (true == test_result)
2141 {
2142 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2143 }
2144 else
2145 {
2146 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2147 }
2148
2149 /* Done */
2150 return tcu::TestNode::STOP;
2151 }
2152
2153 /** Constructor
2154 *
2155 * @param context Test context
2156 **/
testCase(glw::GLenum flags,glw::GLenum access)2157 GetBufferParameterTest::testCase::testCase(glw::GLenum flags, glw::GLenum access) : m_flags(flags), m_access(access)
2158 {
2159 }
2160
2161 /** Constructor
2162 *
2163 * @param context Test context
2164 **/
DynamicStorageTest(deqp::Context & context)2165 DynamicStorageTest::DynamicStorageTest(deqp::Context &context)
2166 : TestCase(context, "dynamic_storage", "Test if DYNAMIC_STORAGE_BIT is respected")
2167 {
2168 /* Nothing to be done here */
2169 }
2170
2171 /** Execute test
2172 *
2173 * @return tcu::TestNode::STOP otherwise
2174 **/
iterate()2175 tcu::TestNode::IterateResult DynamicStorageTest::iterate()
2176 {
2177 static const size_t data_size = 64;
2178
2179 const Functions &gl = m_context.getRenderContext().getFunctions();
2180
2181 bool test_result = true;
2182
2183 /*
2184 * - prepare 64 bytes immutable buffer filled with value 1; Bind the buffer to
2185 * COPY_READ_BUFFER;
2186 * - prepare 64 bytes immutable buffer filled with value 2; Do not set
2187 * DYNAMIC_STORAGE_BIT for <flags>; Bind the buffer to COPY_WRITE_BUFFER;
2188 * - execute BufferSubData to update COPY_WRITE_BUFFER buffer with 64 bytes
2189 * filled with value 3; INVLIAD_OPERATION error should be generated;
2190 * - inspect contents of buffer to verify it is filled with 2;
2191 * - execute CopyBufferSubData to transfer data from COPY_READ_BUFFER to
2192 * COPY_WRITE_BUFFER; No error should be generated;
2193 * - inspect contents of buffer to verify it is filled with 1;
2194 */
2195 {
2196 /* Prepare buffers */
2197 GLubyte read_data[data_size];
2198 GLubyte temp_data[data_size];
2199 GLubyte update_data[data_size];
2200 GLubyte write_data[data_size];
2201
2202 for (size_t i = 0; i < data_size; ++i)
2203 {
2204 read_data[i] = 1;
2205 temp_data[i] = 0;
2206 update_data[i] = 3;
2207 write_data[i] = 2;
2208 }
2209
2210 Buffer read_buffer(m_context);
2211 Buffer write_buffer(m_context);
2212
2213 read_buffer.InitStorage(GL_COPY_READ_BUFFER, 0 /* flags */, data_size, read_data);
2214 write_buffer.InitStorage(GL_COPY_WRITE_BUFFER, 0 /* flags */, data_size, write_data);
2215
2216 /* Check bufferSubData */
2217 write_buffer.Bind();
2218 gl.bufferSubData(GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, update_data);
2219
2220 GLenum error = gl.getError();
2221 if (GL_INVALID_OPERATION != error)
2222 {
2223 test_result = false;
2224
2225 m_context.getTestContext().getLog()
2226 << tcu::TestLog::Message
2227 << "Invalid error was generated. BufferSubData was executed on store without "
2228 "DYNAMIC_STORAGE_BIT. Expected INVALID_OPERATION, got: "
2229 << glu::getErrorStr(error).toString().c_str() << tcu::TestLog::EndMessage;
2230 }
2231
2232 Buffer::GetSubData(gl, GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, temp_data);
2233
2234 if (0 != memcmp(temp_data, write_data, data_size))
2235 {
2236 test_result = false;
2237
2238 m_context.getTestContext().getLog()
2239 << tcu::TestLog::Message << "BufferSubData modified contents of store without DYNAMIC_STORAGE_BIT."
2240 << tcu::TestLog::EndMessage;
2241 }
2242
2243 /* Check copyBufferSubData */
2244 read_buffer.Bind();
2245 gl.copyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0 /* readOffset */, 0 /* writeOffset */,
2246 data_size);
2247 GLU_EXPECT_NO_ERROR(gl.getError(), "CopyBufferSubData");
2248
2249 Buffer::GetSubData(gl, GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, temp_data);
2250
2251 if (0 != memcmp(temp_data, read_data, data_size))
2252 {
2253 test_result = false;
2254
2255 m_context.getTestContext().getLog()
2256 << tcu::TestLog::Message << "CopyBufferSubData stored invalid contents in write target buffer."
2257 << tcu::TestLog::EndMessage;
2258 }
2259 }
2260
2261 /*
2262 * - delete buffer and create new one; This time <flags> should contain
2263 * DYNAMIC_STORAGE_BIT; Bind the buffer to COPY_WRITE_BUFFER;
2264 * - execute BufferSubData to update COPY_WRITE_BUFFER buffer with 64 bytes
2265 * filled with value 3; No error should be generated;
2266 * - inspect contents of buffer to verify it is filled with 3;
2267 */
2268 {
2269 /* Prepare buffers */
2270 GLubyte temp_data[data_size];
2271 GLubyte update_data[data_size];
2272 GLubyte write_data[data_size];
2273
2274 for (size_t i = 0; i < data_size; ++i)
2275 {
2276 temp_data[i] = 0;
2277 update_data[i] = 3;
2278 write_data[i] = 2;
2279 }
2280
2281 Buffer write_buffer(m_context);
2282
2283 write_buffer.InitStorage(GL_COPY_WRITE_BUFFER, GL_DYNAMIC_STORAGE_BIT, data_size, write_data);
2284
2285 /* Check bufferSubData */
2286 write_buffer.Bind();
2287 gl.bufferSubData(GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, update_data);
2288 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData");
2289
2290 Buffer::GetSubData(gl, GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, temp_data);
2291
2292 if (0 != memcmp(temp_data, update_data, data_size))
2293 {
2294 test_result = false;
2295
2296 m_context.getTestContext().getLog()
2297 << tcu::TestLog::Message << "BufferSubData stored invalid contents in write target buffer."
2298 << tcu::TestLog::EndMessage;
2299 }
2300 }
2301
2302 /* Set result */
2303 if (true == test_result)
2304 {
2305 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2306 }
2307 else
2308 {
2309 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2310 }
2311
2312 /* Done */
2313 return tcu::TestNode::STOP;
2314 }
2315
2316 /** Constructor
2317 *
2318 * @param context Test context
2319 **/
MapPersistentBufferSubDataTest(deqp::Context & context)2320 MapPersistentBufferSubDataTest::MapPersistentBufferSubDataTest(deqp::Context &context)
2321 : TestCase(context, "map_persistent_buffer_sub_data", "Test sub buffer operations against mapped buffer")
2322 {
2323 /* Nothing to be done here */
2324 }
2325
2326 /** Execute test
2327 *
2328 * @return tcu::TestNode::STOP otherwise
2329 **/
iterate()2330 tcu::TestNode::IterateResult MapPersistentBufferSubDataTest::iterate()
2331 {
2332 static const size_t data_size = 64;
2333 static const GLintptr mapped_region_offset = 16;
2334 static const GLsizeiptr mapped_region_size = 16;
2335 static const testCase test_cases[] = {
2336 {0, 16, false}, /* before mapped region */
2337 {32, 16, false}, /* after mapped region */
2338 {8, 16, true}, /* at the beginning */
2339 {24, 16, true}, /* at the end */
2340 {12, 8, true}, /* in the middle */
2341 };
2342 static const size_t n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
2343
2344 const Functions &gl = m_context.getRenderContext().getFunctions();
2345
2346 bool test_result = true;
2347
2348 /* Storage for data */
2349 GLubyte incrementing_data[data_size];
2350
2351 /* Prepare data */
2352 for (size_t i = 0; i < data_size; ++i)
2353 {
2354 incrementing_data[i] = (glw::GLubyte)i;
2355 }
2356
2357 /* Load DSA */
2358 Buffer::LoadExtDirectStateAccess(m_context);
2359
2360 // No GL45 or GL_ARB_direct_state_access support
2361 if (m_direct_state_access_support == FUNCTIONALITY_SUPPORT_NONE)
2362 {
2363 m_context.getTestContext().setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Unsupported");
2364 return tcu::TestNode::STOP;
2365 }
2366
2367 /* Prepare buffer */
2368 Buffer buffer(m_context);
2369 buffer.InitStorage(GL_ARRAY_BUFFER,
2370 GL_DYNAMIC_STORAGE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, data_size,
2371 0 /* data */);
2372 buffer.Bind();
2373
2374 /*
2375 * - execute tested operation, to update whole buffer with incrementing values
2376 * starting from 0; No error should be generated;
2377 */
2378 gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, data_size, incrementing_data);
2379 GLenum error = gl.getError();
2380
2381 if (GL_NO_ERROR != error)
2382 {
2383 test_result = false;
2384
2385 m_context.getTestContext().getLog() << tcu::TestLog::Message << "BufferSubData generated unexpected error: "
2386 << glu::getErrorStr(error).toString().c_str() << tcu::TestLog::EndMessage;
2387 }
2388
2389 if (0 != gl.namedBufferSubData)
2390 {
2391 gl.namedBufferSubData(buffer.m_id, 0 /* offset */, data_size, incrementing_data);
2392 error = gl.getError();
2393 }
2394
2395 gl.namedBufferSubData(buffer.m_id, 0 /* offset */, data_size, incrementing_data);
2396 error = gl.getError();
2397
2398 if (GL_NO_ERROR != error)
2399 {
2400 test_result = false;
2401
2402 m_context.getTestContext().getLog()
2403 << tcu::TestLog::Message
2404 << "NamedBufferSubData generated unexpected error: " << glu::getErrorStr(error).toString().c_str()
2405 << tcu::TestLog::EndMessage;
2406 }
2407
2408 /*
2409 * - map buffer contents with MapBufferRange; <access> should contain
2410 * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT; Provide 16 as <offset>
2411 * and <size>;
2412 * - mapped region should contain values from 16 to 31;
2413 * - execute tested operation, to update portions of buffer specified below;
2414 * No error should be generated;
2415 */
2416 {
2417 const Buffer::MapOwner map(buffer.MapRange(mapped_region_offset, mapped_region_size,
2418 GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2419
2420 if (0 != memcmp(map.m_data, incrementing_data + mapped_region_offset, mapped_region_size))
2421 {
2422 test_result = false;
2423
2424 m_context.getTestContext().getLog()
2425 << tcu::TestLog::Message << "Mapped region contains unexpected data" << tcu::TestLog::EndMessage;
2426 }
2427
2428 for (size_t i = 0; i < n_test_cases; ++i)
2429 {
2430 const GLintptr offset = test_cases[i].m_offset;
2431 const GLsizeiptr size = test_cases[i].m_size;
2432
2433 gl.bufferSubData(GL_ARRAY_BUFFER, offset, size, incrementing_data);
2434 error = gl.getError();
2435
2436 if (GL_NO_ERROR != error)
2437 {
2438 test_result = false;
2439
2440 m_context.getTestContext().getLog()
2441 << tcu::TestLog::Message
2442 << "BufferSubData generated unexpected error: " << glu::getErrorStr(error).toString().c_str()
2443 << tcu::TestLog::EndMessage;
2444 }
2445
2446 if (0 != gl.namedBufferSubData)
2447 {
2448 gl.namedBufferSubData(buffer.m_id, offset, size, incrementing_data);
2449 error = gl.getError();
2450 }
2451
2452 if (GL_NO_ERROR != error)
2453 {
2454 test_result = false;
2455
2456 m_context.getTestContext().getLog()
2457 << tcu::TestLog::Message
2458 << "NamedBufferSubData generated unexpected error: " << glu::getErrorStr(error).toString().c_str()
2459 << tcu::TestLog::EndMessage;
2460 }
2461 }
2462 }
2463
2464 /*
2465 * - unmap buffer;
2466 * - map buffer contents again, this time do not provide MAP_PERSISTENT_BIT;
2467 * - execute tested operation to update regions specified below; It is expected
2468 * that INVALID_OPERATION will be generated for cases that cross mapped region;
2469 * No error should be generated for other cases.
2470 */
2471 {
2472 Buffer::MapOwner tmp(
2473 buffer.MapRange(mapped_region_offset, mapped_region_size, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2474
2475 for (size_t i = 0; i < n_test_cases; ++i)
2476 {
2477 const GLintptr offset = test_cases[i].m_offset;
2478 const GLsizeiptr size = test_cases[i].m_size;
2479 const bool is_error_expected = test_cases[i].m_cross_mapped_region;
2480 const GLenum expected_error = (true == is_error_expected) ? GL_INVALID_OPERATION : GL_NO_ERROR;
2481
2482 gl.bufferSubData(GL_ARRAY_BUFFER, offset, size, incrementing_data);
2483 error = gl.getError();
2484
2485 if (expected_error != error)
2486 {
2487 test_result = false;
2488
2489 m_context.getTestContext().getLog()
2490 << tcu::TestLog::Message
2491 << "BufferSubData generated wrong error: " << glu::getErrorStr(error).toString().c_str()
2492 << ", expected: " << glu::getErrorStr(expected_error).toString().c_str()
2493 << ". Mapped region: offset: " << mapped_region_offset << ", size: " << mapped_region_size
2494 << ". Operation region: offset: " << offset << ", size: " << size << tcu::TestLog::EndMessage;
2495 }
2496
2497 if (0 != gl.namedBufferSubData)
2498 {
2499 gl.namedBufferSubData(buffer.m_id, offset, size, incrementing_data);
2500 error = gl.getError();
2501 }
2502
2503 if (expected_error != error)
2504 {
2505 test_result = false;
2506
2507 m_context.getTestContext().getLog()
2508 << tcu::TestLog::Message
2509 << "NamedBufferSubData generated wrong error: " << glu::getErrorStr(error).toString().c_str()
2510 << ", expected: " << glu::getErrorStr(expected_error).toString().c_str()
2511 << ". Mapped region: offset: " << mapped_region_offset << ", size: " << mapped_region_size
2512 << ". Operation region: offset: " << offset << ", size: " << size << tcu::TestLog::EndMessage;
2513 }
2514 }
2515 }
2516
2517 /* Set result */
2518 if (true == test_result)
2519 {
2520 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2521 }
2522 else
2523 {
2524 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2525 }
2526
2527 /* Done */
2528 return tcu::TestNode::STOP;
2529 }
2530
2531 /** Constructor
2532 *
2533 * @param context Test context
2534 **/
MapPersistentTextureTest(deqp::Context & context)2535 MapPersistentTextureTest::MapPersistentTextureTest(deqp::Context &context)
2536 : TestCase(context, "map_persistent_texture", "Test texture operations against mapped buffer")
2537 , m_compressed_image_size(0)
2538 , m_compressed_internal_format(0)
2539 {
2540 /* Nothing to be done here */
2541 }
2542
2543 /** Execute test
2544 *
2545 * @return tcu::TestNode::STOP otherwise
2546 **/
iterate()2547 tcu::TestNode::IterateResult MapPersistentTextureTest::iterate()
2548 {
2549 static const size_t data_size = 256;
2550
2551 const Functions &gl = m_context.getRenderContext().getFunctions();
2552
2553 bool test_result = true;
2554
2555 /* Storage for data */
2556 GLubyte data[data_size];
2557
2558 /* Prepare data */
2559 for (size_t i = 0; i < data_size; ++i)
2560 {
2561 data[i] = (glw::GLubyte)i;
2562 }
2563
2564 /* Load DSA */
2565 Buffer::LoadExtDirectStateAccess(m_context);
2566 Texture::LoadExtDirectStateAccess(m_context);
2567
2568 /* Get info about compressed image */
2569 getCompressedInfo();
2570
2571 /* Prepare buffer */
2572 Buffer buffer(m_context);
2573 buffer.InitStorage(GL_PIXEL_UNPACK_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, data_size,
2574 data);
2575 Buffer::Bind(gl, 0 /* id */, GL_PIXEL_UNPACK_BUFFER);
2576
2577 /*
2578 * - prepare texture in a way that is relevant for tested operation;
2579 * - execute tested operation, no error should be generated;
2580 * - delete texture and prepare next one;
2581 */
2582 for (GLuint i = 0; i < TESTED_OPERATION_MAX; ++i)
2583 {
2584 const TESTED_OPERATION operation = (TESTED_OPERATION)i;
2585
2586 bool result = verifyTestedOperation(operation, buffer, GL_NO_ERROR);
2587
2588 if (false == result)
2589 {
2590 test_result = false;
2591
2592 m_context.getTestContext().getLog()
2593 << tcu::TestLog::Message << "Buffer bound to PIXEL_UNPACK_BUFFER is not mapped"
2594 << tcu::TestLog::EndMessage;
2595 }
2596 }
2597
2598 /*
2599 * - map buffer contents with MapBufferRange, <access> should contain
2600 * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT;
2601 * - execute tested operation, no error should be generated;
2602 */
2603 for (GLuint i = 0; i < TESTED_OPERATION_MAX; ++i)
2604 {
2605 const TESTED_OPERATION operation = (TESTED_OPERATION)i;
2606
2607 {
2608 Buffer::MapOwner tmp(
2609 buffer.MapRange(0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2610 }
2611 Buffer::Bind(gl, 0 /* id */, GL_PIXEL_UNPACK_BUFFER);
2612
2613 bool result = verifyTestedOperation(operation, buffer, GL_NO_ERROR);
2614
2615 if (false == result)
2616 {
2617 test_result = false;
2618
2619 m_context.getTestContext().getLog()
2620 << tcu::TestLog::Message << "Buffer bound to PIXEL_UNPACK_BUFFER is persistently mapped"
2621 << tcu::TestLog::EndMessage;
2622 }
2623 }
2624
2625 /* Set result */
2626 if (true == test_result)
2627 {
2628 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2629 }
2630 else
2631 {
2632 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2633 }
2634
2635 /* Done */
2636 return tcu::TestNode::STOP;
2637 }
2638
2639 /** Return name of operation
2640 *
2641 * @param operation Operation which name will be returned
2642 *
2643 * @return Name of operation or 0 in case of invalid enum
2644 **/
getOperationName(TESTED_OPERATION operation)2645 const char *MapPersistentTextureTest::getOperationName(TESTED_OPERATION operation)
2646 {
2647 const char *name = 0;
2648
2649 switch (operation)
2650 {
2651 case OP_COMPRESSED_TEX_IMAGE:
2652 name = "CompressedTexImage";
2653 break;
2654 case OP_COMPRESSED_TEX_SUB_IMAGE:
2655 name = "CompressedTexSubImage";
2656 break;
2657 case OP_COMPRESSED_TEXTURE_SUB_IMAGE:
2658 name = "CompressedTextureSubImage";
2659 break;
2660 case OP_TEX_IMAGE:
2661 name = "TexImage";
2662 break;
2663 case OP_TEX_SUB_IMAGE:
2664 name = "TexSubImage";
2665 break;
2666 default:
2667 TCU_FAIL("Invalid enum");
2668 }
2669
2670 return name;
2671 }
2672
2673 /** Check format and size of compressed image
2674 *
2675 **/
getCompressedInfo()2676 void MapPersistentTextureTest::getCompressedInfo()
2677 {
2678 const Functions &gl = m_context.getRenderContext().getFunctions();
2679
2680 /* Texture creation */
2681 Texture texture(m_context);
2682 Texture::Generate(gl, texture.m_id);
2683 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
2684 Texture::Image(gl, GL_TEXTURE_2D, 0, GL_COMPRESSED_RED_RGTC1, 8, 8, 1, GL_RED, GL_UNSIGNED_BYTE,
2685 0); // glspec 4.5 pg 216
2686
2687 /* Queries */
2688 Texture::GetLevelParameter(gl, GL_TEXTURE_2D, 0 /* level */, GL_TEXTURE_COMPRESSED_IMAGE_SIZE,
2689 &m_compressed_image_size);
2690 Texture::GetLevelParameter(gl, GL_TEXTURE_2D, 0 /* level */, GL_TEXTURE_INTERNAL_FORMAT,
2691 &m_compressed_internal_format);
2692 }
2693
2694 /** Verifies results of tested operation
2695 *
2696 * @param operation Operation to be tested
2697 * @param buffer Buffer that will be used as GL_PIXEL_UNPACK_BUFFER
2698 * @param expected_error Expected error
2699 *
2700 * @return false in case of any error, true otherwise
2701 **/
verifyTestedOperation(TESTED_OPERATION operation,Buffer & buffer,glw::GLenum expected_error)2702 bool MapPersistentTextureTest::verifyTestedOperation(TESTED_OPERATION operation, Buffer &buffer,
2703 glw::GLenum expected_error)
2704 {
2705 const Functions &gl = m_context.getRenderContext().getFunctions();
2706
2707 bool result = true;
2708
2709 GLenum error = GL_NO_ERROR;
2710 Texture texture(m_context);
2711
2712 /* Prepare texture */
2713 Texture::Generate(gl, texture.m_id);
2714 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
2715
2716 switch (operation)
2717 {
2718 case OP_COMPRESSED_TEX_IMAGE:
2719 case OP_TEX_IMAGE:
2720 break;
2721 case OP_COMPRESSED_TEX_SUB_IMAGE:
2722 case OP_COMPRESSED_TEXTURE_SUB_IMAGE:
2723 Texture::CompressedImage(gl, GL_TEXTURE_2D, 0 /* level */, m_compressed_internal_format, 8 /* width */,
2724 8 /* height */, 0 /* depth */, m_compressed_image_size /* imageSize */,
2725 0 /* empty image */);
2726 break;
2727 case OP_TEX_SUB_IMAGE:
2728 Texture::Image(gl, GL_TEXTURE_2D, 0 /* level */, GL_R8, 8 /* width */, 8 /* height */, 0 /* depth */, GL_RED,
2729 GL_UNSIGNED_BYTE, 0 /* empty image */);
2730 break;
2731 default:
2732 TCU_FAIL("Invalid enum");
2733 }
2734
2735 /* Bind buffer to PIXEL_UNPACK */
2736 Buffer::Bind(gl, buffer.m_id, GL_PIXEL_UNPACK_BUFFER);
2737
2738 /* Execute operation */
2739 switch (operation)
2740 {
2741 case OP_COMPRESSED_TEX_IMAGE:
2742 gl.compressedTexImage2D(GL_TEXTURE_2D, 0 /* level */, m_compressed_internal_format, 8 /* width */,
2743 8 /* height */, 0 /* border */, m_compressed_image_size /* imageSize */,
2744 0 /* offset to pixel unpack buffer */);
2745 error = gl.getError();
2746 break;
2747 case OP_COMPRESSED_TEX_SUB_IMAGE:
2748 gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 8 /* width */, 8 /* height */,
2749 m_compressed_internal_format, m_compressed_image_size,
2750 0 /* offset to pixel unpack buffer */);
2751 error = gl.getError();
2752 break;
2753 case OP_COMPRESSED_TEXTURE_SUB_IMAGE:
2754 if (0 != gl.compressedTextureSubImage2D)
2755 {
2756 gl.compressedTextureSubImage2D(texture.m_id, 0 /* level */, 0 /* x */, 0 /* y */, 8 /* width */,
2757 8 /* height */, m_compressed_internal_format, m_compressed_image_size,
2758 0 /* offset to pixel unpack buffer */);
2759 error = gl.getError();
2760 }
2761 else
2762 {
2763 /* Not supported, ignore */
2764 error = expected_error;
2765 }
2766 break;
2767 case OP_TEX_IMAGE:
2768 gl.texImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R8, 8 /* width */, 8 /* height */, 0 /* border */, GL_RED,
2769 GL_UNSIGNED_BYTE, 0 /* offset to pixel unpack buffer */);
2770 error = gl.getError();
2771 break;
2772 case OP_TEX_SUB_IMAGE:
2773 gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 8 /* width */, 8 /* height */, GL_RED,
2774 GL_UNSIGNED_BYTE, 0 /* offset to pixel unpack buffer */);
2775 error = gl.getError();
2776 break;
2777 default:
2778 TCU_FAIL("Invalid enum");
2779 }
2780
2781 /* Unbind buffer */
2782 Buffer::Bind(gl, 0 /* id */, GL_PIXEL_UNPACK_BUFFER);
2783
2784 /* Check result */
2785 if (expected_error != error)
2786 {
2787 result = false;
2788
2789 m_context.getTestContext().getLog()
2790 << tcu::TestLog::Message << getOperationName(operation)
2791 << " generated wrong error: " << glu::getErrorStr(error).toString().c_str()
2792 << ", expected: " << glu::getErrorStr(expected_error).toString().c_str() << tcu::TestLog::EndMessage;
2793 }
2794
2795 /* Done */
2796 return result;
2797 }
2798
2799 /** Constructor
2800 *
2801 * @param context Test context
2802 **/
MapPersistentReadPixelsTest(deqp::Context & context)2803 MapPersistentReadPixelsTest::MapPersistentReadPixelsTest(deqp::Context &context)
2804 : TestCase(context, "map_persistent_read_pixels", "Test read pixels operation against mapped buffer")
2805 {
2806 /* Nothing to be done here */
2807 }
2808
2809 /** Execute test
2810 *
2811 * @return tcu::TestNode::STOP otherwise
2812 **/
iterate()2813 tcu::TestNode::IterateResult MapPersistentReadPixelsTest::iterate()
2814 {
2815 static const GLuint height = 8;
2816 static const GLuint width = 8;
2817 static const size_t data_size = width * height;
2818
2819 const Functions &gl = m_context.getRenderContext().getFunctions();
2820
2821 bool test_result = true;
2822
2823 /* Prepare data */
2824 GLubyte initial_texture_data[data_size];
2825 GLubyte updated_texture_data[data_size];
2826
2827 for (size_t i = 0; i < data_size; ++i)
2828 {
2829 initial_texture_data[i] = (glw::GLubyte)i;
2830 updated_texture_data[i] = (glw::GLubyte)(data_size - i);
2831 }
2832
2833 /* Prepare GL objects */
2834 Buffer buffer(m_context);
2835 Framebuffer framebuffer(m_context);
2836 Texture texture(m_context);
2837
2838 buffer.InitStorage(GL_PIXEL_PACK_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, data_size,
2839 0 /* data */);
2840
2841 Texture::Generate(gl, texture.m_id);
2842 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
2843 Texture::Storage(gl, GL_TEXTURE_2D, 1 /* levels */, GL_R8UI, width, height, 0 /* depth */);
2844 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, 0 /* depth */,
2845 GL_RED_INTEGER, GL_UNSIGNED_BYTE, initial_texture_data);
2846
2847 Framebuffer::Generate(gl, framebuffer.m_id);
2848 Framebuffer::Bind(gl, GL_READ_FRAMEBUFFER, framebuffer.m_id);
2849 Framebuffer::AttachTexture(gl, GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.m_id, width, height);
2850
2851 /*
2852 * - execute ReadPixels to transfer texture contents to buffer, no error should
2853 * be generated;
2854 */
2855 buffer.Bind();
2856 gl.readPixels(0 /* x */, 0 /* y */, width, height, GL_RED_INTEGER, GL_UNSIGNED_BYTE,
2857 0 /* offset in PIXEL_PACK_BUFFER */);
2858 GLU_EXPECT_NO_ERROR(gl.getError(), "ReadPixels to not mapped PIXEL_PACK buffer");
2859
2860 /*
2861 * - update contents of texture with different image;
2862 * - map buffer contents with MapBufferRange, <access> should contain
2863 * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT;
2864 * - execute ReadPixels to transfer texture contents to buffer, no error should
2865 * be generated;
2866 * - execute MemoryBarrier with CLIENT_MAPPED_BUFFER_BARRIER_BIT and Finish;
2867 * - inspect contents of mapped buffer, to verify that latest data transfer was
2868 * successful;
2869 * - unmap buffer
2870 */
2871 {
2872 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height,
2873 0 /* depth */, GL_RED_INTEGER, GL_UNSIGNED_BYTE, updated_texture_data);
2874
2875 const Buffer::MapOwner map(
2876 buffer.MapRange(0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2877
2878 buffer.Bind();
2879 gl.readPixels(0 /* x */, 0 /* y */, width, height, GL_RED_INTEGER, GL_UNSIGNED_BYTE,
2880 0 /* offset in PIXEL_PACK_BUFFER */);
2881 GLU_EXPECT_NO_ERROR(gl.getError(), "ReadPixels to persistently mapped PIXEL_PACK buffer");
2882
2883 gl.memoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
2884 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
2885
2886 gl.finish();
2887 GLU_EXPECT_NO_ERROR(gl.getError(), "Finish");
2888
2889 if (0 != memcmp(updated_texture_data, map.m_data, data_size))
2890 {
2891 test_result = false;
2892
2893 m_context.getTestContext().getLog()
2894 << tcu::TestLog::Message << "Wrong contents of persistently mapped PIXEL_PACK buffer after ReadPixels"
2895 << tcu::TestLog::EndMessage;
2896 }
2897 }
2898
2899 /*
2900 * - map buffer contents again, this time do not provide MAP_PERSISTENT_BIT;
2901 * - execute ReadPixels to transfer texture contents to buffer,
2902 * INVALID_OPERATION error should be generated.
2903 */
2904 {
2905 Buffer::MapOwner tmp(buffer.MapRange(0 /* offset */, data_size, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2906
2907 buffer.Bind();
2908 gl.readPixels(0 /* x */, 0 /* y */, width, height, GL_RED_INTEGER, GL_UNSIGNED_BYTE,
2909 0 /* offset in PIXEL_PACK_BUFFER */);
2910 GLenum error = gl.getError();
2911
2912 if (GL_INVALID_OPERATION != error)
2913 {
2914 test_result = false;
2915
2916 m_context.getTestContext().getLog()
2917 << tcu::TestLog::Message
2918 << "Wrong error was generated by ReadPixels. Expected INVALID_OPERATION as "
2919 "PIXEL_PACK buffer is mapped. Got: "
2920 << glu::getErrorStr(error).toString().c_str() << tcu::TestLog::EndMessage;
2921 }
2922 }
2923
2924 /* Set result */
2925 if (true == test_result)
2926 {
2927 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2928 }
2929 else
2930 {
2931 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2932 }
2933
2934 /* Done */
2935 return tcu::TestNode::STOP;
2936 }
2937
2938 /** Constructor
2939 *
2940 * @param context Test context
2941 **/
MapPersistentDispatchTest(deqp::Context & context)2942 MapPersistentDispatchTest::MapPersistentDispatchTest(deqp::Context &context)
2943 : TestCase(context, "map_persistent_dispatch", "test dispatch operation against mapped buffer")
2944 {
2945 /* Nothing to be done here */
2946 }
2947
2948 /** Constructor
2949 *
2950 * @param context Test context
2951 * @param test_name Test name
2952 * @param test_description Test description
2953 **/
MapPersistentDispatchTest(deqp::Context & context,const GLchar * test_name,const GLchar * test_description)2954 MapPersistentDispatchTest::MapPersistentDispatchTest(deqp::Context &context, const GLchar *test_name,
2955 const GLchar *test_description)
2956 : TestCase(context, test_name, test_description)
2957 {
2958 /* Nothing to be done here */
2959 }
2960
2961 /** Execute test
2962 *
2963 * @return tcu::TestNode::STOP otherwise
2964 **/
iterate()2965 tcu::TestNode::IterateResult MapPersistentDispatchTest::iterate()
2966 {
2967 static const GLchar *compute_shader = "#version 430 core\n"
2968 "\n"
2969 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2970 "\n"
2971 "layout (binding = 0, std430) buffer DestinationData {\n"
2972 " uint values[];\n"
2973 "} destination;\n"
2974 "\n"
2975 "layout (binding = 1, std430) buffer SourceData {\n"
2976 " uint values[];\n"
2977 "} source;\n"
2978 "\n"
2979 "void main()\n"
2980 "{\n"
2981 " uint index = gl_GlobalInvocationID.x;\n"
2982 " uint sum = 0u;\n"
2983 "\n"
2984 " for (uint i = 0u; i <= index; ++i)\n"
2985 " {\n"
2986 " sum += source.values[i];\n"
2987 " }\n"
2988 "\n"
2989 " destination.values[index] = sum;\n"
2990 "}\n"
2991 "\n";
2992 static const GLuint data_size = 16;
2993 static const GLuint destination_binding = 0;
2994 static const GLuint source_binding = 1;
2995
2996 const Functions &gl = m_context.getRenderContext().getFunctions();
2997
2998 bool test_result = true;
2999
3000 /* Prepare data */
3001 GLuint destination_data[data_size];
3002 GLuint modified_source_data[data_size];
3003 GLuint modified_sum_data[data_size];
3004 GLuint source_data[data_size];
3005 GLuint sum_data[data_size];
3006
3007 GLuint modified_sum = 0;
3008 GLuint sum = 0;
3009
3010 for (GLuint i = 0; i < data_size; ++i)
3011 {
3012 destination_data[i] = 0;
3013 modified_source_data[i] = data_size - i;
3014 source_data[i] = i;
3015
3016 modified_sum += modified_source_data[i];
3017 sum += source_data[i];
3018
3019 modified_sum_data[i] = modified_sum;
3020 sum_data[i] = sum;
3021 }
3022
3023 /* Prepare buffers */
3024 Buffer destination(m_context);
3025 Buffer source(m_context);
3026
3027 destination.InitStorage(GL_SHADER_STORAGE_BUFFER, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT,
3028 data_size * sizeof(GLuint), destination_data);
3029
3030 source.InitStorage(GL_SHADER_STORAGE_BUFFER, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT,
3031 data_size * sizeof(GLuint), source_data);
3032
3033 /* Prepare program */
3034 Program program(m_context);
3035 program.Init(compute_shader, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3036
3037 /*
3038 * - bind buffers to SHADER_STORAGE_BUFFER;
3039 * - use MapBufferRange to map both buffers; <access> shall be set as follows:
3040 * * MAP_COHERENT_BIT and MAP_PERSISTENT_BIT flags set for both
3041 * * MAP_WRITE_BIT flag shall be set for source;
3042 * * MAP_READ_BIT flag shall be set for destination;
3043 * - dispatch program for 16x1x1 groups;
3044 * - modify contents of source buffer via mapped memory;
3045 * - execute Finish;
3046 * - inspect contents of destination buffer via mapped memory; It is expected
3047 * that it will contain results based on original content of source buffer;
3048 * - dispatch program for 16x1x1 groups;
3049 * - execute Finish;
3050 * - inspect contents of destination buffer via mapped memory; It is expected
3051 * that it will contain results based on modified content of source buffer.
3052 */
3053 {
3054 /* Set program */
3055 Program::Use(gl, program.m_id);
3056
3057 /* Map buffers */
3058 destination.Bind();
3059 const Buffer::MapOwner destination_map(destination.MapRange(
3060 0 /* offset */, data_size * sizeof(GLuint), GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT));
3061
3062 source.Bind();
3063 const Buffer::MapOwner source_map(
3064 source.MapRange(0 /* offset */, data_size * sizeof(GLuint),
3065 GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT));
3066
3067 /* Clear binding point */
3068 Buffer::Bind(gl, 0, GL_SHADER_STORAGE_BUFFER);
3069
3070 /* Bind buffers */
3071 Buffer::BindBase(gl, destination.m_id, GL_SHADER_STORAGE_BUFFER, destination_binding);
3072 Buffer::BindBase(gl, source.m_id, GL_SHADER_STORAGE_BUFFER, source_binding);
3073
3074 /* Execute program for 16x1x1 groups */
3075 gl.dispatchCompute(16, 1, 1);
3076 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute with persistently mapped buffers");
3077
3078 /* Make sure that program executed */
3079 gl.finish();
3080 GLU_EXPECT_NO_ERROR(gl.getError(), "Finish");
3081
3082 if (0 != memcmp(destination_map.m_data, sum_data, data_size * sizeof(GLuint)))
3083 {
3084 test_result = false;
3085
3086 m_context.getTestContext().getLog()
3087 << tcu::TestLog::Message << "Contents of mapped region does not correspond with expected results"
3088 << tcu::TestLog::EndMessage;
3089 }
3090
3091 /* Modify source buffer via mapped area */
3092 memcpy(source_map.m_data, modified_source_data, data_size * sizeof(GLuint));
3093
3094 /* Execute program for 16x1x1 groups */
3095 gl.dispatchCompute(16, 1, 1);
3096 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute with persistently mapped buffers");
3097
3098 /* Make sure that program executed */
3099 gl.finish();
3100 GLU_EXPECT_NO_ERROR(gl.getError(), "Finish");
3101
3102 if (0 != memcmp(destination_map.m_data, modified_sum_data, data_size * sizeof(GLuint)))
3103 {
3104 test_result = false;
3105
3106 m_context.getTestContext().getLog()
3107 << tcu::TestLog::Message << "Contents of mapped region does not correspond with expected results"
3108 << tcu::TestLog::EndMessage;
3109 }
3110 }
3111
3112 /* Set result */
3113 if (true == test_result)
3114 {
3115 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3116 }
3117 else
3118 {
3119 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3120 }
3121
3122 /* Done */
3123 return tcu::TestNode::STOP;
3124 }
3125
3126 /** Constructor
3127 *
3128 * @param context Test context
3129 **/
MapPersistentFlushTest(deqp::Context & context)3130 MapPersistentFlushTest::MapPersistentFlushTest(deqp::Context &context)
3131 : TestCase(context, "map_persistent_flush", "Test mapped buffer against flushing")
3132 {
3133 /* Nothing to be done here */
3134 }
3135
3136 /** Execute test
3137 *
3138 * @return tcu::TestNode::STOP otherwise
3139 **/
iterate()3140 tcu::TestNode::IterateResult MapPersistentFlushTest::iterate()
3141 {
3142 static const GLchar *compute_shader = "#version 430 core\n"
3143 "\n"
3144 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3145 "\n"
3146 "layout (binding = 0, std430) buffer DestinationData {\n"
3147 " uint values[];\n"
3148 "} destination;\n"
3149 "\n"
3150 "layout (binding = 1, std430) buffer SourceData {\n"
3151 " uint values[];\n"
3152 "} source;\n"
3153 "\n"
3154 "void main()\n"
3155 "{\n"
3156 " uint index = gl_GlobalInvocationID.x;\n"
3157 " uint sum = 0u;\n"
3158 "\n"
3159 " for (uint i = 0u; i <= index; ++i)\n"
3160 " {\n"
3161 " sum += source.values[i];\n"
3162 " }\n"
3163 "\n"
3164 " destination.values[index] = sum;\n"
3165 "}\n"
3166 "\n";
3167 static const GLuint data_size = 16;
3168 static const GLuint destination_binding = 0;
3169 static const GLuint source_binding = 1;
3170
3171 const Functions &gl = m_context.getRenderContext().getFunctions();
3172
3173 bool test_result = true;
3174
3175 /* Prepare data */
3176 GLuint destination_data[data_size];
3177 GLuint modified_source_data[data_size];
3178 GLuint modified_sum_data[data_size];
3179 GLuint source_data[data_size];
3180 GLuint sum_data[data_size];
3181
3182 GLuint modified_sum = 0;
3183 GLuint sum = 0;
3184
3185 for (GLuint i = 0; i < data_size; ++i)
3186 {
3187 destination_data[i] = 0;
3188 modified_source_data[i] = data_size - i;
3189 source_data[i] = i;
3190
3191 modified_sum += modified_source_data[i];
3192 sum += source_data[i];
3193
3194 modified_sum_data[i] = modified_sum;
3195 sum_data[i] = sum;
3196 }
3197
3198 /* Prepare buffers */
3199 Buffer destination(m_context);
3200 Buffer source(m_context);
3201
3202 destination.InitStorage(GL_SHADER_STORAGE_BUFFER, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT,
3203 data_size * sizeof(GLuint), destination_data);
3204
3205 source.InitStorage(GL_SHADER_STORAGE_BUFFER, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT,
3206 data_size * sizeof(GLuint), source_data);
3207
3208 /* Prepare program */
3209 Program program(m_context);
3210 program.Init(compute_shader, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3211
3212 /*
3213 * - bind buffers to SHADER_STORAGE_BUFFER;
3214 * - use MapBufferRange to map both buffers; <access> shall be set as follows:
3215 * * MAP_COHERENT_BIT and MAP_PERSISTENT_BIT flags set for both
3216 * * MAP_WRITE_BIT flag shall be set for source;
3217 * * MAP_READ_BIT flag shall be set for destination;
3218 * - dispatch program for 16x1x1 groups;
3219 * - modify contents of source buffer via mapped memory;
3220 * - execute Finish;
3221 * - inspect contents of destination buffer via mapped memory; It is expected
3222 * that it will contain results based on original content of source buffer;
3223 * - dispatch program for 16x1x1 groups;
3224 * - execute Finish;
3225 * - inspect contents of destination buffer via mapped memory; It is expected
3226 * that it will contain results based on modified content of source buffer.
3227 */
3228 {
3229 /* Set program */
3230 Program::Use(gl, program.m_id);
3231
3232 /* Map buffers */
3233 destination.Bind();
3234 const Buffer::MapOwner destination_map(destination.MapRange(
3235 0 /* offset */, data_size * sizeof(GLuint), GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT));
3236
3237 source.Bind();
3238 const Buffer::MapOwner source_map(
3239 source.MapRange(0 /* offset */, data_size * sizeof(GLuint),
3240 GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT));
3241
3242 /* Clear binding point */
3243 Buffer::Bind(gl, 0, GL_SHADER_STORAGE_BUFFER);
3244
3245 /* Bind buffers */
3246 Buffer::BindBase(gl, destination.m_id, GL_SHADER_STORAGE_BUFFER, destination_binding);
3247 Buffer::BindBase(gl, source.m_id, GL_SHADER_STORAGE_BUFFER, source_binding);
3248
3249 /* Execute program for 16x1x1 groups */
3250 gl.dispatchCompute(16, 1, 1);
3251 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute with persistently mapped buffers");
3252
3253 /* Make sure that program executed */
3254 gl.finish();
3255 GLU_EXPECT_NO_ERROR(gl.getError(), "Finish");
3256
3257 if (0 != memcmp(destination_map.m_data, sum_data, data_size * sizeof(GLuint)))
3258 {
3259 test_result = false;
3260
3261 m_context.getTestContext().getLog()
3262 << tcu::TestLog::Message << "Contents of mapped region does not correspond with expected results"
3263 << tcu::TestLog::EndMessage;
3264 }
3265
3266 /* Modify source buffer via mapped area */
3267 memcpy(source_map.m_data, modified_source_data, data_size * sizeof(GLuint));
3268
3269 /*
3270 * - apply FlushMappedBufferRange to ensure that modifications of source buffer
3271 * are visible to server.
3272 */
3273 source.Bind();
3274 gl.flushMappedBufferRange(GL_SHADER_STORAGE_BUFFER, 0 /* offset */, data_size * sizeof(GLuint));
3275 GLU_EXPECT_NO_ERROR(gl.getError(), "FlushMappedBufferRange");
3276
3277 /* Clear binding point */
3278 Buffer::Bind(gl, 0, GL_SHADER_STORAGE_BUFFER);
3279
3280 /* Execute program for 16x1x1 groups */
3281 gl.dispatchCompute(16, 1, 1);
3282 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute with persistently mapped buffers");
3283
3284 /* Make sure that program executed */
3285 gl.finish();
3286 GLU_EXPECT_NO_ERROR(gl.getError(), "Finish");
3287
3288 if (0 != memcmp(destination_map.m_data, modified_sum_data, data_size * sizeof(GLuint)))
3289 {
3290 test_result = false;
3291
3292 m_context.getTestContext().getLog()
3293 << tcu::TestLog::Message << "Contents of mapped region does not correspond with expected results"
3294 << tcu::TestLog::EndMessage;
3295 }
3296 }
3297
3298 /* Set result */
3299 if (true == test_result)
3300 {
3301 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3302 }
3303 else
3304 {
3305 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3306 }
3307
3308 /* Done */
3309 return tcu::TestNode::STOP;
3310 }
3311
3312 /** Constructor
3313 *
3314 * @param context Test context
3315 **/
MapPersistentDrawTest(deqp::Context & context)3316 MapPersistentDrawTest::MapPersistentDrawTest(deqp::Context &context)
3317 : TestCase(context, "map_persistent_draw", "Test draw operation against mapped buffer")
3318 {
3319 /* Nothing to be done here */
3320 }
3321
3322 /** Execute test
3323 *
3324 * @return tcu::TestNode::STOP otherwise
3325 **/
iterate()3326 tcu::TestNode::IterateResult MapPersistentDrawTest::iterate()
3327 {
3328 /*
3329 * * fragment shader should pass value of "gs_fs_color" varying to red
3330 * channel of output color;
3331 */
3332 static const GLchar *fragment_shader = "#version 440 core\n"
3333 "\n"
3334 "in float gs_fs_color;\n"
3335 "out vec4 fs_out_color;\n"
3336 "\n"
3337 "void main()\n"
3338 "{\n"
3339 " fs_out_color = vec4(gs_fs_color, 0, 0, 1);\n"
3340 "}\n"
3341 "\n";
3342
3343 /*
3344 * * geometry shader should:
3345 * - define single uniform buffer array "rectangles" with unspecified size;
3346 * Rectangles should have two vec2 fields: position and size;
3347 * - define a separate atomic_uint "atom_color" per input point;
3348 * - increment "atom_color" once per input point;
3349 * - output a quad that is placed at rectangles[vs_gs_index].position and
3350 * has size equal rectangles[vs_gs_index].size;
3351 * - define output float varying "gs_fs_color" equal to "atom_color" / 255;
3352 */
3353 static const GLchar *geometry_shader =
3354 "#version 440 core\n"
3355 "\n"
3356 "layout(points) in;\n"
3357 "layout(triangle_strip, max_vertices = 4) out;\n"
3358 "\n"
3359 "struct Rectangle {\n"
3360 " vec2 position;\n"
3361 " vec2 size;\n"
3362 "};\n"
3363 "\n"
3364 "layout (std140, binding = 0) uniform Rectangles {\n"
3365 " Rectangle rectangle[2];\n"
3366 "} rectangles;\n"
3367 "\n"
3368 "layout (binding = 0) uniform atomic_uint atom_color[2];\n"
3369 "layout (binding = 0) uniform atomic_uint invocation_hit_count[2];\n"
3370 "\n"
3371 "in uint vs_gs_index[];\n"
3372 "out float gs_fs_color;\n"
3373 "\n"
3374 "void main()\n"
3375 "{\n"
3376 " if (atomicCounterIncrement(invocation_hit_count[gl_PrimitiveIDIn]) == 0)\n"
3377 " {\n"
3378 " atomicCounterIncrement(atom_color[gl_PrimitiveIDIn]);\n"
3379 " }\n"
3380 " memoryBarrierAtomicCounter();\n"
3381 " const uint atom_color_value = atomicCounter(atom_color[gl_PrimitiveIDIn]);"
3382 " //const uint atom_color_value = vs_gs_index[0];\n"
3383 " const float color = float(atom_color_value) / 255.0;\n"
3384 " //const float color = rectangles.rectangle[1].size.x;\n"
3385 "\n"
3386 " const float left = rectangles.rectangle[vs_gs_index[0]].position.x;\n"
3387 " const float bottom = rectangles.rectangle[vs_gs_index[0]].position.y;\n"
3388 " const float right = rectangles.rectangle[vs_gs_index[0]].size.x + left;\n"
3389 " const float top = rectangles.rectangle[vs_gs_index[0]].size.y + bottom;\n"
3390 "\n"
3391 " //const float left = rectangles.rectangle[0].position.x;\n"
3392 " //const float bottom = rectangles.rectangle[0].position.y;\n"
3393 " //const float right = rectangles.rectangle[0].size.x + left;\n"
3394 " //const float top = rectangles.rectangle[0].size.y + bottom;\n"
3395 "\n"
3396 " gs_fs_color = color;\n"
3397 " gl_Position = vec4(left, bottom, 0, 1);\n"
3398 " EmitVertex();\n"
3399 "\n"
3400 " gs_fs_color = color;\n"
3401 " gl_Position = vec4(left, top, 0, 1);\n"
3402 " EmitVertex();\n"
3403 "\n"
3404 " gs_fs_color = color;\n"
3405 " gl_Position = vec4(right, bottom, 0, 1);\n"
3406 " EmitVertex();\n"
3407 "\n"
3408 " gs_fs_color = color;\n"
3409 " gl_Position = vec4(right, top, 0, 1);\n"
3410 " EmitVertex();\n"
3411 "}\n"
3412 "\n";
3413
3414 /*
3415 * * vertex shader should output single varying "vs_gs_index" of type uint,
3416 * equal to gl_VertexID;
3417 */
3418 static const GLchar *vertex_shader = "#version 440 core\n"
3419 "\n"
3420 "out uint vs_gs_index;\n"
3421 "\n"
3422 "void main()\n"
3423 "{\n"
3424 " vs_gs_index = gl_VertexID;\n"
3425 "}\n"
3426 "\n";
3427
3428 static const GLuint atom_binding = 0;
3429 static const size_t atom_data_size = 4 * sizeof(GLuint);
3430 static const GLuint expected_atom_first = 2;
3431 static const GLuint expected_atom_second = 6;
3432 static const GLuint expected_pixel = 0xff000004;
3433 static const GLuint height = 16;
3434 static const GLuint n_rectangles = 2;
3435 static const GLuint pixel_size = 4 * sizeof(GLubyte);
3436 static const GLuint rectangles_binding = 0;
3437 static const size_t rectangle_size = 2 * 2 * sizeof(GLfloat); /* 2 * vec2 */
3438 static const size_t rectangles_data_size = n_rectangles * rectangle_size;
3439 static const GLuint width = 16;
3440 static const GLuint line_size = width * pixel_size;
3441 static const GLuint pixel_offset = 8 * line_size + 7 * pixel_size;
3442 static const size_t texture_data_size = height * line_size;
3443
3444 const Functions &gl = m_context.getRenderContext().getFunctions();
3445
3446 bool test_result = true;
3447
3448 /* Prepare data */
3449 GLuint atom_first_data[4] = {1, 1, 0, 0};
3450 GLuint atom_second_data[4] = {5, 5, 0, 0};
3451 GLubyte rectangles_first_data[rectangles_data_size];
3452 GLubyte rectangles_second_data[rectangles_data_size];
3453 GLubyte texture_data[texture_data_size];
3454
3455 {
3456 GLfloat *ptr = (GLfloat *)rectangles_first_data;
3457
3458 /* First.position*/
3459 ptr[0] = -0.5f;
3460 ptr[1] = -0.5f;
3461
3462 /* First.size*/
3463 ptr[2] = 1.0f;
3464 ptr[3] = 1.0f;
3465
3466 /* Second.position*/
3467 ptr[4 + 0] = -0.75f;
3468 ptr[4 + 1] = -0.75f;
3469
3470 /* Second.size*/
3471 ptr[4 + 2] = 1.5f;
3472 ptr[4 + 3] = 1.5f;
3473 }
3474
3475 {
3476 GLfloat *ptr = (GLfloat *)rectangles_second_data;
3477
3478 /* First.position*/
3479 ptr[0] = -1.0f;
3480 ptr[1] = -1.0f;
3481
3482 /* First.size*/
3483 ptr[2] = 0.5f;
3484 ptr[3] = 0.5f;
3485
3486 /* Second.position*/
3487 ptr[4 + 0] = 0.5f;
3488 ptr[4 + 1] = 0.5f;
3489
3490 /* Second.size*/
3491 ptr[4 + 2] = 0.5f;
3492 ptr[4 + 3] = 0.5f;
3493 }
3494
3495 /* Prepare buffers */
3496 Buffer atom(m_context);
3497 Buffer rectangles(m_context);
3498
3499 atom.InitStorage(GL_ATOMIC_COUNTER_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
3500 atom_data_size, 0);
3501
3502 rectangles.InitStorage(GL_UNIFORM_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT, rectangles_data_size, 0);
3503
3504 /* Prepare framebuffer */
3505 Framebuffer framebuffer(m_context);
3506 Texture texture(m_context);
3507
3508 Texture::Generate(gl, texture.m_id);
3509 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
3510 Texture::Storage(gl, GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, width, height, 0 /* depth */);
3511
3512 Framebuffer::Generate(gl, framebuffer.m_id);
3513 Framebuffer::Bind(gl, GL_DRAW_FRAMEBUFFER, framebuffer.m_id);
3514 Framebuffer::AttachTexture(gl, GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.m_id, width, height);
3515
3516 /* Prepare VAO */
3517 VertexArray vao(m_context);
3518
3519 VertexArray::Generate(gl, vao.m_id);
3520 VertexArray::Bind(gl, vao.m_id);
3521
3522 /* Prepare program */
3523 Program program(m_context);
3524 program.Init("" /* cs */, fragment_shader, geometry_shader, "" /* tcs */, "" /* tes */, vertex_shader);
3525 Program::Use(gl, program.m_id);
3526
3527 /*
3528 * - make persistent mapping of both buffers for reads and writes;
3529 * - modify "rectangles" buffer via mapped memory with the following two sets
3530 * * position [-0.5,-0.5], size [1.0,1.0],
3531 * * position [-0.25,-0.25], size [1.5,1.5];
3532 * - modify "atom_color" buffer via mapped memory to value 1;
3533 * - execute MemoryBarrier for CLIENT_MAPPED_BUFFER_BARRIER_BIT;
3534 * - enable blending with functions ONE for both source and destination;
3535 * - execute DrawArrays for two vertices;
3536 * - execute MemoryBarrier for ALL_BARRIER_BITS and Finish;
3537 * - inspect contents of:
3538 * * texture - to verify that pixel at 8,8 is filled with RGBA8(4,0,0,0),
3539 * * "atom_color" - to verify that it is equal to 2;
3540 * - modify "rectangles" buffer via mapped memory with the following two sets
3541 * * position [-1.0,-1.0], size [0.5,0.5],
3542 * * position [0.5,0.5], size [0.5,0.5];
3543 * - modify "atom_color" buffer via mapped memory to value 5;
3544 * - execute MemoryBarrier for CLIENT_MAPPED_BUFFER_BARRIER_BIT;
3545 * - execute DrawArrays for two vertices;
3546 * - execute MemoryBarrier for ALL_BARRIER_BITS and Finish;
3547 * - inspect contents of:
3548 * * texture - to verify that pixel at 8,8 is filled with RGBA8(4,0,0,0),
3549 * * "atom_color" - to verify that it is equal to 6;
3550 *
3551 * Additionally: change MemoryBarrier to FlushMapped*BufferRange if context supports OpenGL 4.5 Core Profile.
3552 */
3553 {
3554 /* Choose specification */
3555 const bool is_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
3556
3557 /* Map buffers */
3558 atom.Bind();
3559 const Buffer::MapOwner atom_map(atom.MapRange(0 /* offset */, atom_data_size,
3560 GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT |
3561 (is_gl_45 ? GL_MAP_FLUSH_EXPLICIT_BIT : 0)));
3562
3563 rectangles.Bind();
3564 const Buffer::MapOwner rectangles_map(
3565 rectangles.MapRange(0 /* offset */, rectangles_data_size,
3566 GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT | (is_gl_45 ? GL_MAP_FLUSH_EXPLICIT_BIT : 0)));
3567
3568 /* Clear binding points */
3569 Buffer::Bind(gl, 0, GL_ATOMIC_COUNTER_BUFFER);
3570 Buffer::Bind(gl, 0, GL_UNIFORM_BUFFER);
3571
3572 /* Bind buffers */
3573 Buffer::BindBase(gl, atom.m_id, GL_ATOMIC_COUNTER_BUFFER, atom_binding);
3574 Buffer::BindBase(gl, rectangles.m_id, GL_UNIFORM_BUFFER, rectangles_binding);
3575
3576 /* Set up blending */
3577 gl.enable(GL_BLEND);
3578 gl.blendFunc(GL_ONE, GL_ONE);
3579
3580 /* Modify buffers */
3581 memcpy(atom_map.m_data, atom_first_data, atom_data_size);
3582 memcpy(rectangles_map.m_data, rectangles_first_data, rectangles_data_size);
3583
3584 /* Execute barrier or flush content. */
3585 if (is_gl_45)
3586 {
3587 gl.flushMappedBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, atom_data_size);
3588 GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");
3589
3590 gl.flushMappedBufferRange(GL_UNIFORM_BUFFER, 0, rectangles_data_size);
3591 GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");
3592 }
3593 else
3594 {
3595 gl.memoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
3596 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3597 }
3598
3599 /* Clear drawbuffer */
3600 GLint clear_color[4] = {0, 0, 0, 0};
3601 gl.clearBufferiv(GL_COLOR, 0, clear_color);
3602
3603 /* Execute program for 2 vertices */
3604 gl.drawArrays(GL_POINTS, 0, 2);
3605 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays with persistently mapped buffers");
3606
3607 /* Execute barrier */
3608 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3609 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3610
3611 /* Inspect texture */
3612 Texture::GetData(gl, GL_TEXTURE_2D, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
3613 if (0 != memcmp(texture_data + pixel_offset, &expected_pixel, pixel_size))
3614 {
3615 test_result = false;
3616
3617 m_context.getTestContext().getLog()
3618 << tcu::TestLog::Message << "Contents of framebuffer does not correspond with expected results"
3619 << tcu::TestLog::EndMessage;
3620 tcu::ConstPixelBufferAccess img(
3621 tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), width, height,
3622 1 /* depth */, texture_data);
3623 m_context.getTestContext().getLog()
3624 << tcu::TestLog::Image("Framebuffer", "Framebuffer contents using initial buffer data", img);
3625 }
3626
3627 /* Inspect atom */
3628 if (0 != memcmp(atom_map.m_data, &expected_atom_first, sizeof(GLuint)))
3629 {
3630 test_result = false;
3631
3632 m_context.getTestContext().getLog()
3633 << tcu::TestLog::Message << "Contents of ATOMIC_COUNTER buffer are invalid."
3634 << tcu::TestLog::EndMessage;
3635 }
3636
3637 /* Modify buffers */
3638 memcpy(atom_map.m_data, atom_second_data, atom_data_size);
3639 memcpy(rectangles_map.m_data, rectangles_second_data, rectangles_data_size);
3640
3641 /* Execute barrier or flush content. */
3642 if (is_gl_45)
3643 {
3644 gl.flushMappedBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, atom_data_size);
3645 GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");
3646
3647 gl.flushMappedBufferRange(GL_UNIFORM_BUFFER, 0, rectangles_data_size);
3648 GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");
3649 }
3650 else
3651 {
3652 gl.memoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
3653 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3654 }
3655
3656 /* Execute program for 2 vertices */
3657 gl.drawArrays(GL_POINTS, 0, 2);
3658 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays with persistently mapped buffers");
3659
3660 /* Execute barrier */
3661 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3662 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3663
3664 /* Inspect texture */
3665 Texture::GetData(gl, GL_TEXTURE_2D, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
3666 if (0 != memcmp(texture_data + pixel_offset, &expected_pixel, pixel_size))
3667 {
3668 test_result = false;
3669
3670 m_context.getTestContext().getLog()
3671 << tcu::TestLog::Message << "Contents of framebuffer does not correspond with expected results"
3672 << tcu::TestLog::EndMessage;
3673 tcu::ConstPixelBufferAccess img(
3674 tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), width, height,
3675 1 /* depth */, texture_data);
3676 m_context.getTestContext().getLog()
3677 << tcu::TestLog::Image("Framebuffer", "Framebuffer contents using updated buffer data", img);
3678 }
3679
3680 /* Inspect atom */
3681 if (0 != memcmp(atom_map.m_data, &expected_atom_second, sizeof(GLuint)))
3682 {
3683 test_result = false;
3684
3685 m_context.getTestContext().getLog()
3686 << tcu::TestLog::Message << "Contents of ATOMIC_COUNTER buffer are invalid."
3687 << tcu::TestLog::EndMessage;
3688 }
3689 }
3690
3691 /* Set result */
3692 if (true == test_result)
3693 {
3694 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3695 }
3696 else
3697 {
3698 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3699 }
3700
3701 /* Done */
3702 return tcu::TestNode::STOP;
3703 }
3704 } // namespace BufferStorage
3705
3706 /** Constructor.
3707 *
3708 * @param context Rendering context.
3709 **/
BufferStorageTests(deqp::Context & context)3710 BufferStorageTests::BufferStorageTests(deqp::Context &context)
3711 : TestCaseGroup(context, "buffer_storage", "Verifies \"buffer storage\" functionality")
3712 {
3713 /* Left blank on purpose */
3714 }
3715
3716 /** Initializes a texture_storage_multisample test group.
3717 *
3718 **/
init(void)3719 void BufferStorageTests::init(void)
3720 {
3721 addChild(new BufferStorage::ErrorsTest(m_context));
3722 addChild(new BufferStorage::GetBufferParameterTest(m_context));
3723 addChild(new BufferStorage::DynamicStorageTest(m_context));
3724 addChild(new BufferStorage::MapPersistentBufferSubDataTest(m_context));
3725 addChild(new BufferStorage::MapPersistentTextureTest(m_context));
3726 addChild(new BufferStorage::MapPersistentReadPixelsTest(m_context));
3727 addChild(new BufferStorage::MapPersistentDispatchTest(m_context));
3728 addChild(new BufferStorage::MapPersistentFlushTest(m_context));
3729 addChild(new BufferStorage::MapPersistentDrawTest(m_context));
3730 }
3731 } // namespace gl4cts
3732