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 /* Sanity 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, "MapNamedBufferRange was executed with access == GL_MAP_READ_BIT, "
1817 "storage flags == GL_DYNAMIC_STORAGE_BIT",
1818 test_result);
1819
1820 gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_WRITE_BIT);
1821 verifyError(GL_INVALID_OPERATION, "MapNamedBufferRange was executed with access == GL_MAP_WRITE_BIT, "
1822 "storage flags == GL_DYNAMIC_STORAGE_BIT",
1823 test_result);
1824
1825 gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT);
1826 verifyError(GL_INVALID_OPERATION, "MapNamedBufferRange was executed with access == GL_MAP_PERSISTENT_BIT, "
1827 "storage flags == GL_DYNAMIC_STORAGE_BIT",
1828 test_result);
1829
1830 gl.mapNamedBufferRange(buffer.m_id, 0 /* offset */, data_size, GL_MAP_COHERENT_BIT);
1831 verifyError(GL_INVALID_OPERATION, "MapNamedBufferRange was executed with access == GL_MAP_COHERENT_BIT, "
1832 "storage flags == GL_DYNAMIC_STORAGE_BIT",
1833 test_result);
1834 }
1835
1836 /* BufferStorage */
1837 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1838
1839 gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_READ_BIT);
1840 verifyError(
1841 GL_INVALID_OPERATION,
1842 "MapBufferRange was executed with access == GL_MAP_READ_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT",
1843 test_result);
1844
1845 gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_WRITE_BIT);
1846 verifyError(
1847 GL_INVALID_OPERATION,
1848 "MapBufferRange was executed with access == GL_MAP_WRITE_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT",
1849 test_result);
1850
1851 gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT);
1852 verifyError(
1853 GL_INVALID_OPERATION,
1854 "MapBufferRange was executed with access == GL_MAP_PERSISTENT_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT",
1855 test_result);
1856
1857 gl.mapBufferRange(GL_ARRAY_BUFFER, 0 /* offset */, data_size, GL_MAP_COHERENT_BIT);
1858 verifyError(
1859 GL_INVALID_OPERATION,
1860 "MapBufferRange was executed with access == GL_MAP_COHERENT_BIT, storage flags == GL_DYNAMIC_STORAGE_BIT",
1861 test_result);
1862
1863 Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1864 }
1865
1866 /*
1867 * - INVALID_OPERATION is generated by BufferSubData and NamedBufferSubData
1868 * when buffer has immutable store but its flags does not include
1869 * DYNAMIC_STORAGE.
1870 */
1871 {
1872 static const GLsizeiptr data_size = 32;
1873 static GLubyte data[data_size];
1874
1875 Buffer buffer(m_context);
1876 buffer.InitStorage(GL_ARRAY_BUFFER, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT, data_size,
1877 data);
1878
1879 /* NamedBufferSubData */
1880 if (0 != gl.namedBufferSubData)
1881 {
1882 gl.namedBufferSubData(buffer.m_id, 0 /* offset */, data_size, data);
1883 verifyError(GL_INVALID_OPERATION,
1884 "NamedBufferSubData was executed for storage without GL_DYNAMIC_STORAGE_BIT", test_result);
1885 }
1886
1887 /* BufferStorage */
1888 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
1889
1890 gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, data_size, data);
1891 verifyError(GL_INVALID_OPERATION, "BufferSubData was executed for storage without GL_DYNAMIC_STORAGE_BIT",
1892 test_result);
1893
1894 Buffer::Bind(gl, 0, GL_ARRAY_BUFFER);
1895 }
1896
1897 /* Set result */
1898 if (true == test_result)
1899 {
1900 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1901 }
1902 else
1903 {
1904 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1905 }
1906
1907 /* Done */
1908 return tcu::TestNode::STOP;
1909 }
1910
1911 /** Verifies that expected error was generated
1912 *
1913 * @param expected_error Expected error
1914 * @param error_message Message that will be logged in case of wrong error
1915 * @param out_test_result Set to false if worng error was generated, not modified otherwise
1916 **/
verifyError(glw::GLenum expected_error,const glw::GLchar * error_message,bool & out_test_result)1917 void ErrorsTest::verifyError(glw::GLenum expected_error, const glw::GLchar* error_message, bool& out_test_result)
1918 {
1919 const Functions& gl = m_context.getRenderContext().getFunctions();
1920
1921 const GLenum error = gl.getError();
1922
1923 if (error != expected_error)
1924 {
1925 out_test_result = false;
1926
1927 m_context.getTestContext().getLog()
1928 << tcu::TestLog::Message << "Got invalid error: " << glu::getErrorName(error)
1929 << ", expected: " << glu::getErrorName(expected_error) << ". Message: " << error_message
1930 << tcu::TestLog::EndMessage;
1931 }
1932 }
1933
1934 /** Constructor
1935 *
1936 * @param context Test context
1937 **/
GetBufferParameterTest(deqp::Context & context)1938 GetBufferParameterTest::GetBufferParameterTest(deqp::Context& context)
1939 : TestCase(context, "get_buffer_parameter", "Test queries for parameters of buffers")
1940 {
1941 static const GLenum s_mapping_bits[] = { 0, GL_MAP_PERSISTENT_BIT, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT };
1942 static const GLuint s_n_mapping_bits = sizeof(s_mapping_bits) / sizeof(s_mapping_bits[0]);
1943
1944 GLenum flags = 0;
1945
1946 for (GLuint dynamic = 0; dynamic < 2; ++dynamic)
1947 {
1948 flags = (0 == dynamic) ? 0 : GL_DYNAMIC_STORAGE_BIT;
1949
1950 for (GLuint client = 0; client < 2; ++client)
1951 {
1952 flags |= (0 == client) ? 0 : GL_CLIENT_STORAGE_BIT;
1953
1954 /* No "map" bits */
1955 if (0 != flags)
1956 {
1957 m_test_cases.push_back(testCase(flags, 0));
1958 }
1959
1960 for (GLuint flag_idx = 0; flag_idx < s_n_mapping_bits; ++flag_idx)
1961 {
1962 const GLenum flag_mapping_bits = s_mapping_bits[flag_idx];
1963 const GLenum flags_with_mapping = flags | flag_mapping_bits;
1964
1965 for (GLuint access_idx = 0; access_idx <= flag_idx; ++access_idx)
1966 {
1967 const GLenum access = s_mapping_bits[access_idx];
1968
1969 m_test_cases.push_back(testCase(flags_with_mapping | GL_MAP_READ_BIT, access | GL_MAP_READ_BIT));
1970 m_test_cases.push_back(testCase(flags_with_mapping | GL_MAP_WRITE_BIT, access | GL_MAP_WRITE_BIT));
1971 m_test_cases.push_back(
1972 testCase(flags_with_mapping | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, access | GL_MAP_READ_BIT));
1973 m_test_cases.push_back(
1974 testCase(flags_with_mapping | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, access | GL_MAP_WRITE_BIT));
1975 m_test_cases.push_back(testCase(flags_with_mapping | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
1976 access | GL_MAP_WRITE_BIT | GL_MAP_READ_BIT));
1977 }
1978 }
1979 }
1980 }
1981 }
1982
1983 /** Execute test
1984 *
1985 * @return tcu::TestNode::STOP otherwise
1986 **/
iterate()1987 tcu::TestNode::IterateResult GetBufferParameterTest::iterate()
1988 {
1989 static const GLsizeiptr data_size = 32;
1990 static GLubyte data[data_size];
1991
1992 Buffer::LoadExtDirectStateAccess(m_context);
1993
1994 // No GL45 or GL_ARB_direct_state_access support
1995 if (m_direct_state_access_support == FUNCTIONALITY_SUPPORT_NONE)
1996 {
1997 m_context.getTestContext().setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Unsupported");
1998 return tcu::TestNode::STOP;
1999 }
2000
2001 const Functions& gl = m_context.getRenderContext().getFunctions();
2002
2003 bool test_result = true;
2004
2005 for (GLuint i = 0; i < m_test_cases.size(); ++i)
2006 {
2007 const testCase& test_case = m_test_cases[i];
2008 const GLenum access = test_case.m_access;
2009 const GLenum flags = test_case.m_flags;
2010
2011 GLint queried_flags = -1;
2012 GLint queried_immutable = -1;
2013 GLint queried_size = -1;
2014
2015 Buffer buffer(m_context);
2016
2017 buffer.InitStorage(GL_ARRAY_BUFFER, flags, data_size, data);
2018 Buffer::Bind(gl, buffer.m_id, GL_ARRAY_BUFFER);
2019
2020 if (0 != gl.getNamedBufferParameteriv)
2021 {
2022 Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_STORAGE_FLAGS, &queried_flags);
2023 Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_IMMUTABLE_STORAGE, &queried_immutable);
2024 Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_SIZE, &queried_size);
2025
2026 if (queried_flags != (GLint)flags)
2027 {
2028 test_result = false;
2029 m_context.getTestContext().getLog()
2030 << tcu::TestLog::Message
2031 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_STORAGE_FLAGS: " << queried_flags
2032 << " expected: " << flags << tcu::TestLog::EndMessage;
2033 }
2034 }
2035
2036 if (queried_flags != (GLint)flags)
2037 {
2038 test_result = false;
2039 m_context.getTestContext().getLog()
2040 << tcu::TestLog::Message
2041 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_STORAGE_FLAGS: " << queried_flags
2042 << " expected: " << flags << tcu::TestLog::EndMessage;
2043 }
2044
2045 if (queried_immutable != GL_TRUE)
2046 {
2047 test_result = false;
2048 m_context.getTestContext().getLog()
2049 << tcu::TestLog::Message
2050 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_IMMUTABLE_STORAGE: "
2051 << queried_immutable << " expected: " << GL_TRUE << tcu::TestLog::EndMessage;
2052 }
2053
2054 if (queried_size != data_size)
2055 {
2056 test_result = false;
2057 m_context.getTestContext().getLog()
2058 << tcu::TestLog::Message
2059 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_SIZE: " << queried_size
2060 << " expected: " << data_size << tcu::TestLog::EndMessage;
2061 }
2062
2063 queried_flags = -1;
2064 queried_immutable = -1;
2065 queried_size = -1;
2066
2067 Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_STORAGE_FLAGS, &queried_flags);
2068 Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_IMMUTABLE_STORAGE, &queried_immutable);
2069 Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &queried_size);
2070
2071 if (queried_flags != (GLint)flags)
2072 {
2073 test_result = false;
2074 m_context.getTestContext().getLog()
2075 << tcu::TestLog::Message
2076 << "GetBufferParameteriv reported invalid state of GL_BUFFER_STORAGE_FLAGS: " << queried_flags
2077 << " expected: " << flags << tcu::TestLog::EndMessage;
2078 }
2079
2080 if (queried_immutable != GL_TRUE)
2081 {
2082 test_result = false;
2083 m_context.getTestContext().getLog()
2084 << tcu::TestLog::Message
2085 << "GetBufferParameteriv reported invalid state of GL_BUFFER_IMMUTABLE_STORAGE: " << queried_immutable
2086 << " expected: " << GL_TRUE << tcu::TestLog::EndMessage;
2087 }
2088
2089 if (queried_size != data_size)
2090 {
2091 test_result = false;
2092 m_context.getTestContext().getLog()
2093 << tcu::TestLog::Message
2094 << "GetBufferParameteriv reported invalid state of GL_BUFFER_SIZE: " << queried_size
2095 << " expected: " << data_size << tcu::TestLog::EndMessage;
2096 }
2097
2098 if (0 != access)
2099 {
2100 GLint queried_access = -1;
2101
2102 Buffer::MapOwner tmp(buffer.MapRange(0 /* offset */, data_size, access));
2103
2104 if (0 != gl.getNamedBufferParameteriv)
2105 {
2106 Buffer::GetNamedParameter(gl, buffer.m_id, GL_BUFFER_ACCESS_FLAGS, &queried_access);
2107 }
2108
2109 if (queried_access != (GLint)access)
2110 {
2111 test_result = false;
2112 m_context.getTestContext().getLog()
2113 << tcu::TestLog::Message
2114 << "GetNamedBufferParameteriv reported invalid state of GL_BUFFER_ACCESS_FLAGS: " << queried_access
2115 << " expected: " << access << tcu::TestLog::EndMessage;
2116 }
2117
2118 queried_access = -1;
2119
2120 Buffer::GetParameter(gl, GL_ARRAY_BUFFER, GL_BUFFER_ACCESS_FLAGS, &queried_access);
2121
2122 if (queried_access != (GLint)access)
2123 {
2124 test_result = false;
2125 m_context.getTestContext().getLog()
2126 << tcu::TestLog::Message
2127 << "GetBufferParameteriv reported invalid state of GL_BUFFER_ACCESS_FLAGS: " << queried_access
2128 << " expected: " << access << tcu::TestLog::EndMessage;
2129 }
2130 }
2131
2132 Buffer::Bind(gl, 0 /* id */, GL_ARRAY_BUFFER);
2133 }
2134
2135 /* Set result */
2136 if (true == test_result)
2137 {
2138 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2139 }
2140 else
2141 {
2142 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2143 }
2144
2145 /* Done */
2146 return tcu::TestNode::STOP;
2147 }
2148
2149 /** Constructor
2150 *
2151 * @param context Test context
2152 **/
testCase(glw::GLenum flags,glw::GLenum access)2153 GetBufferParameterTest::testCase::testCase(glw::GLenum flags, glw::GLenum access) : m_flags(flags), m_access(access)
2154 {
2155 }
2156
2157 /** Constructor
2158 *
2159 * @param context Test context
2160 **/
DynamicStorageTest(deqp::Context & context)2161 DynamicStorageTest::DynamicStorageTest(deqp::Context& context)
2162 : TestCase(context, "dynamic_storage", "Test if DYNAMIC_STORAGE_BIT is respected")
2163 {
2164 /* Nothing to be done here */
2165 }
2166
2167 /** Execute test
2168 *
2169 * @return tcu::TestNode::STOP otherwise
2170 **/
iterate()2171 tcu::TestNode::IterateResult DynamicStorageTest::iterate()
2172 {
2173 static const size_t data_size = 64;
2174
2175 const Functions& gl = m_context.getRenderContext().getFunctions();
2176
2177 bool test_result = true;
2178
2179 /*
2180 * - prepare 64 bytes immutable buffer filled with value 1; Bind the buffer to
2181 * COPY_READ_BUFFER;
2182 * - prepare 64 bytes immutable buffer filled with value 2; Do not set
2183 * DYNAMIC_STORAGE_BIT for <flags>; Bind the buffer to COPY_WRITE_BUFFER;
2184 * - execute BufferSubData to update COPY_WRITE_BUFFER buffer with 64 bytes
2185 * filled with value 3; INVLIAD_OPERATION error should be generated;
2186 * - inspect contents of buffer to verify it is filled with 2;
2187 * - execute CopyBufferSubData to transfer data from COPY_READ_BUFFER to
2188 * COPY_WRITE_BUFFER; No error should be generated;
2189 * - inspect contents of buffer to verify it is filled with 1;
2190 */
2191 {
2192 /* Prepare buffers */
2193 GLubyte read_data[data_size];
2194 GLubyte temp_data[data_size];
2195 GLubyte update_data[data_size];
2196 GLubyte write_data[data_size];
2197
2198 for (size_t i = 0; i < data_size; ++i)
2199 {
2200 read_data[i] = 1;
2201 temp_data[i] = 0;
2202 update_data[i] = 3;
2203 write_data[i] = 2;
2204 }
2205
2206 Buffer read_buffer(m_context);
2207 Buffer write_buffer(m_context);
2208
2209 read_buffer.InitStorage(GL_COPY_READ_BUFFER, 0 /* flags */, data_size, read_data);
2210 write_buffer.InitStorage(GL_COPY_WRITE_BUFFER, 0 /* flags */, data_size, write_data);
2211
2212 /* Check bufferSubData */
2213 write_buffer.Bind();
2214 gl.bufferSubData(GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, update_data);
2215
2216 GLenum error = gl.getError();
2217 if (GL_INVALID_OPERATION != error)
2218 {
2219 test_result = false;
2220
2221 m_context.getTestContext().getLog()
2222 << tcu::TestLog::Message << "Invalid error was generated. BufferSubData was executed on store without "
2223 "DYNAMIC_STORAGE_BIT. Expected INVALID_OPERATION, got: "
2224 << glu::getErrorStr(error).toString().c_str() << tcu::TestLog::EndMessage;
2225 }
2226
2227 Buffer::GetSubData(gl, GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, temp_data);
2228
2229 if (0 != memcmp(temp_data, write_data, data_size))
2230 {
2231 test_result = false;
2232
2233 m_context.getTestContext().getLog()
2234 << tcu::TestLog::Message << "BufferSubData modified contents of store without DYNAMIC_STORAGE_BIT."
2235 << tcu::TestLog::EndMessage;
2236 }
2237
2238 /* Check copyBufferSubData */
2239 read_buffer.Bind();
2240 gl.copyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0 /* readOffset */, 0 /* writeOffset */,
2241 data_size);
2242 GLU_EXPECT_NO_ERROR(gl.getError(), "CopyBufferSubData");
2243
2244 Buffer::GetSubData(gl, GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, temp_data);
2245
2246 if (0 != memcmp(temp_data, read_data, data_size))
2247 {
2248 test_result = false;
2249
2250 m_context.getTestContext().getLog() << tcu::TestLog::Message
2251 << "CopyBufferSubData stored invalid contents in write target buffer."
2252 << tcu::TestLog::EndMessage;
2253 }
2254 }
2255
2256 /*
2257 * - delete buffer and create new one; This time <flags> should contain
2258 * DYNAMIC_STORAGE_BIT; Bind the buffer to COPY_WRITE_BUFFER;
2259 * - execute BufferSubData to update COPY_WRITE_BUFFER buffer with 64 bytes
2260 * filled with value 3; No error should be generated;
2261 * - inspect contents of buffer to verify it is filled with 3;
2262 */
2263 {
2264 /* Prepare buffers */
2265 GLubyte temp_data[data_size];
2266 GLubyte update_data[data_size];
2267 GLubyte write_data[data_size];
2268
2269 for (size_t i = 0; i < data_size; ++i)
2270 {
2271 temp_data[i] = 0;
2272 update_data[i] = 3;
2273 write_data[i] = 2;
2274 }
2275
2276 Buffer write_buffer(m_context);
2277
2278 write_buffer.InitStorage(GL_COPY_WRITE_BUFFER, GL_DYNAMIC_STORAGE_BIT, data_size, write_data);
2279
2280 /* Check bufferSubData */
2281 write_buffer.Bind();
2282 gl.bufferSubData(GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, update_data);
2283 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData");
2284
2285 Buffer::GetSubData(gl, GL_COPY_WRITE_BUFFER, 0 /* offset */, data_size, temp_data);
2286
2287 if (0 != memcmp(temp_data, update_data, data_size))
2288 {
2289 test_result = false;
2290
2291 m_context.getTestContext().getLog() << tcu::TestLog::Message
2292 << "BufferSubData stored invalid contents in write target buffer."
2293 << tcu::TestLog::EndMessage;
2294 }
2295 }
2296
2297 /* Set result */
2298 if (true == test_result)
2299 {
2300 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2301 }
2302 else
2303 {
2304 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2305 }
2306
2307 /* Done */
2308 return tcu::TestNode::STOP;
2309 }
2310
2311 /** Constructor
2312 *
2313 * @param context Test context
2314 **/
MapPersistentBufferSubDataTest(deqp::Context & context)2315 MapPersistentBufferSubDataTest::MapPersistentBufferSubDataTest(deqp::Context& context)
2316 : TestCase(context, "map_persistent_buffer_sub_data", "Test sub buffer operations against mapped buffer")
2317 {
2318 /* Nothing to be done here */
2319 }
2320
2321 /** Execute test
2322 *
2323 * @return tcu::TestNode::STOP otherwise
2324 **/
iterate()2325 tcu::TestNode::IterateResult MapPersistentBufferSubDataTest::iterate()
2326 {
2327 static const size_t data_size = 64;
2328 static const GLintptr mapped_region_offset = 16;
2329 static const GLsizeiptr mapped_region_size = 16;
2330 static const testCase test_cases[] = {
2331 { 0, 16, false }, /* before mapped region */
2332 { 32, 16, false }, /* after mapped region */
2333 { 8, 16, true }, /* at the beginning */
2334 { 24, 16, true }, /* at the end */
2335 { 12, 8, true }, /* in the middle */
2336 };
2337 static const size_t n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
2338
2339 const Functions& gl = m_context.getRenderContext().getFunctions();
2340
2341 bool test_result = true;
2342
2343 /* Storage for data */
2344 GLubyte incrementing_data[data_size];
2345
2346 /* Prepare data */
2347 for (size_t i = 0; i < data_size; ++i)
2348 {
2349 incrementing_data[i] = (glw::GLubyte)i;
2350 }
2351
2352 /* Load DSA */
2353 Buffer::LoadExtDirectStateAccess(m_context);
2354
2355 // No GL45 or GL_ARB_direct_state_access support
2356 if (m_direct_state_access_support == FUNCTIONALITY_SUPPORT_NONE)
2357 {
2358 m_context.getTestContext().setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Unsupported");
2359 return tcu::TestNode::STOP;
2360 }
2361
2362 /* Prepare buffer */
2363 Buffer buffer(m_context);
2364 buffer.InitStorage(GL_ARRAY_BUFFER,
2365 GL_DYNAMIC_STORAGE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, data_size,
2366 0 /* data */);
2367 buffer.Bind();
2368
2369 /*
2370 * - execute tested operation, to update whole buffer with incrementing values
2371 * starting from 0; No error should be generated;
2372 */
2373 gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, data_size, incrementing_data);
2374 GLenum error = gl.getError();
2375
2376 if (GL_NO_ERROR != error)
2377 {
2378 test_result = false;
2379
2380 m_context.getTestContext().getLog() << tcu::TestLog::Message << "BufferSubData generated unexpected error: "
2381 << glu::getErrorStr(error).toString().c_str() << tcu::TestLog::EndMessage;
2382 }
2383
2384 if (0 != gl.namedBufferSubData)
2385 {
2386 gl.namedBufferSubData(buffer.m_id, 0 /* offset */, data_size, incrementing_data);
2387 error = gl.getError();
2388 }
2389
2390 gl.namedBufferSubData(buffer.m_id, 0 /* offset */, data_size, incrementing_data);
2391 error = gl.getError();
2392
2393 if (GL_NO_ERROR != error)
2394 {
2395 test_result = false;
2396
2397 m_context.getTestContext().getLog()
2398 << tcu::TestLog::Message
2399 << "NamedBufferSubData generated unexpected error: " << glu::getErrorStr(error).toString().c_str()
2400 << tcu::TestLog::EndMessage;
2401 }
2402
2403 /*
2404 * - map buffer contents with MapBufferRange; <access> should contain
2405 * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT; Provide 16 as <offset>
2406 * and <size>;
2407 * - mapped region should contain values from 16 to 31;
2408 * - execute tested operation, to update portions of buffer specified below;
2409 * No error should be generated;
2410 */
2411 {
2412 const Buffer::MapOwner map(buffer.MapRange(mapped_region_offset, mapped_region_size,
2413 GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2414
2415 if (0 != memcmp(map.m_data, incrementing_data + mapped_region_offset, mapped_region_size))
2416 {
2417 test_result = false;
2418
2419 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Mapped region contains unexpected data"
2420 << tcu::TestLog::EndMessage;
2421 }
2422
2423 for (size_t i = 0; i < n_test_cases; ++i)
2424 {
2425 const GLintptr offset = test_cases[i].m_offset;
2426 const GLsizeiptr size = test_cases[i].m_size;
2427
2428 gl.bufferSubData(GL_ARRAY_BUFFER, offset, size, incrementing_data);
2429 error = gl.getError();
2430
2431 if (GL_NO_ERROR != error)
2432 {
2433 test_result = false;
2434
2435 m_context.getTestContext().getLog()
2436 << tcu::TestLog::Message
2437 << "BufferSubData generated unexpected error: " << glu::getErrorStr(error).toString().c_str()
2438 << tcu::TestLog::EndMessage;
2439 }
2440
2441 if (0 != gl.namedBufferSubData)
2442 {
2443 gl.namedBufferSubData(buffer.m_id, offset, size, incrementing_data);
2444 error = gl.getError();
2445 }
2446
2447 if (GL_NO_ERROR != error)
2448 {
2449 test_result = false;
2450
2451 m_context.getTestContext().getLog()
2452 << tcu::TestLog::Message
2453 << "NamedBufferSubData generated unexpected error: " << glu::getErrorStr(error).toString().c_str()
2454 << tcu::TestLog::EndMessage;
2455 }
2456 }
2457 }
2458
2459 /*
2460 * - unmap buffer;
2461 * - map buffer contents again, this time do not provide MAP_PERSISTENT_BIT;
2462 * - execute tested operation to update regions specified below; It is expected
2463 * that INVALID_OPERATION will be generated for cases that cross mapped region;
2464 * No error should be generated for other cases.
2465 */
2466 {
2467 Buffer::MapOwner tmp(
2468 buffer.MapRange(mapped_region_offset, mapped_region_size, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2469
2470 for (size_t i = 0; i < n_test_cases; ++i)
2471 {
2472 const GLintptr offset = test_cases[i].m_offset;
2473 const GLsizeiptr size = test_cases[i].m_size;
2474 const bool is_error_expected = test_cases[i].m_cross_mapped_region;
2475 const GLenum expected_error = (true == is_error_expected) ? GL_INVALID_OPERATION : GL_NO_ERROR;
2476
2477 gl.bufferSubData(GL_ARRAY_BUFFER, offset, size, incrementing_data);
2478 error = gl.getError();
2479
2480 if (expected_error != error)
2481 {
2482 test_result = false;
2483
2484 m_context.getTestContext().getLog()
2485 << tcu::TestLog::Message
2486 << "BufferSubData generated wrong error: " << glu::getErrorStr(error).toString().c_str()
2487 << ", expected: " << glu::getErrorStr(expected_error).toString().c_str()
2488 << ". Mapped region: offset: " << mapped_region_offset << ", size: " << mapped_region_size
2489 << ". Operation region: offset: " << offset << ", size: " << size << tcu::TestLog::EndMessage;
2490 }
2491
2492 if (0 != gl.namedBufferSubData)
2493 {
2494 gl.namedBufferSubData(buffer.m_id, offset, size, incrementing_data);
2495 error = gl.getError();
2496 }
2497
2498 if (expected_error != error)
2499 {
2500 test_result = false;
2501
2502 m_context.getTestContext().getLog()
2503 << tcu::TestLog::Message
2504 << "NamedBufferSubData generated wrong error: " << glu::getErrorStr(error).toString().c_str()
2505 << ", expected: " << glu::getErrorStr(expected_error).toString().c_str()
2506 << ". Mapped region: offset: " << mapped_region_offset << ", size: " << mapped_region_size
2507 << ". Operation region: offset: " << offset << ", size: " << size << tcu::TestLog::EndMessage;
2508 }
2509 }
2510 }
2511
2512 /* Set result */
2513 if (true == test_result)
2514 {
2515 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2516 }
2517 else
2518 {
2519 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2520 }
2521
2522 /* Done */
2523 return tcu::TestNode::STOP;
2524 }
2525
2526 /** Constructor
2527 *
2528 * @param context Test context
2529 **/
MapPersistentTextureTest(deqp::Context & context)2530 MapPersistentTextureTest::MapPersistentTextureTest(deqp::Context& context)
2531 : TestCase(context, "map_persistent_texture", "Test texture operations against mapped buffer")
2532 , m_compressed_image_size(0)
2533 , m_compressed_internal_format(0)
2534 {
2535 /* Nothing to be done here */
2536 }
2537
2538 /** Execute test
2539 *
2540 * @return tcu::TestNode::STOP otherwise
2541 **/
iterate()2542 tcu::TestNode::IterateResult MapPersistentTextureTest::iterate()
2543 {
2544 static const size_t data_size = 256;
2545
2546 const Functions& gl = m_context.getRenderContext().getFunctions();
2547
2548 bool test_result = true;
2549
2550 /* Storage for data */
2551 GLubyte data[data_size];
2552
2553 /* Prepare data */
2554 for (size_t i = 0; i < data_size; ++i)
2555 {
2556 data[i] = (glw::GLubyte)i;
2557 }
2558
2559 /* Load DSA */
2560 Buffer::LoadExtDirectStateAccess(m_context);
2561 Texture::LoadExtDirectStateAccess(m_context);
2562
2563 /* Get info about compressed image */
2564 getCompressedInfo();
2565
2566 /* Prepare buffer */
2567 Buffer buffer(m_context);
2568 buffer.InitStorage(GL_PIXEL_UNPACK_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, data_size,
2569 data);
2570 Buffer::Bind(gl, 0 /* id */, GL_PIXEL_UNPACK_BUFFER);
2571
2572 /*
2573 * - prepare texture in a way that is relevant for tested operation;
2574 * - execute tested operation, no error should be generated;
2575 * - delete texture and prepare next one;
2576 */
2577 for (GLuint i = 0; i < TESTED_OPERATION_MAX; ++i)
2578 {
2579 const TESTED_OPERATION operation = (TESTED_OPERATION)i;
2580
2581 bool result = verifyTestedOperation(operation, buffer, GL_NO_ERROR);
2582
2583 if (false == result)
2584 {
2585 test_result = false;
2586
2587 m_context.getTestContext().getLog() << tcu::TestLog::Message
2588 << "Buffer bound to PIXEL_UNPACK_BUFFER is not mapped"
2589 << tcu::TestLog::EndMessage;
2590 }
2591 }
2592
2593 /*
2594 * - map buffer contents with MapBufferRange, <access> should contain
2595 * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT;
2596 * - execute tested operation, no error should be generated;
2597 */
2598 for (GLuint i = 0; i < TESTED_OPERATION_MAX; ++i)
2599 {
2600 const TESTED_OPERATION operation = (TESTED_OPERATION)i;
2601
2602 {
2603 Buffer::MapOwner tmp(
2604 buffer.MapRange(0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2605 }
2606 Buffer::Bind(gl, 0 /* id */, GL_PIXEL_UNPACK_BUFFER);
2607
2608 bool result = verifyTestedOperation(operation, buffer, GL_NO_ERROR);
2609
2610 if (false == result)
2611 {
2612 test_result = false;
2613
2614 m_context.getTestContext().getLog() << tcu::TestLog::Message
2615 << "Buffer bound to PIXEL_UNPACK_BUFFER is persistently mapped"
2616 << tcu::TestLog::EndMessage;
2617 }
2618 }
2619
2620 /* Set result */
2621 if (true == test_result)
2622 {
2623 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2624 }
2625 else
2626 {
2627 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2628 }
2629
2630 /* Done */
2631 return tcu::TestNode::STOP;
2632 }
2633
2634 /** Return name of operation
2635 *
2636 * @param operation Operation which name will be returned
2637 *
2638 * @return Name of operation or 0 in case of invalid enum
2639 **/
getOperationName(TESTED_OPERATION operation)2640 const char* MapPersistentTextureTest::getOperationName(TESTED_OPERATION operation)
2641 {
2642 const char* name = 0;
2643
2644 switch (operation)
2645 {
2646 case OP_COMPRESSED_TEX_IMAGE:
2647 name = "CompressedTexImage";
2648 break;
2649 case OP_COMPRESSED_TEX_SUB_IMAGE:
2650 name = "CompressedTexSubImage";
2651 break;
2652 case OP_COMPRESSED_TEXTURE_SUB_IMAGE:
2653 name = "CompressedTextureSubImage";
2654 break;
2655 case OP_TEX_IMAGE:
2656 name = "TexImage";
2657 break;
2658 case OP_TEX_SUB_IMAGE:
2659 name = "TexSubImage";
2660 break;
2661 default:
2662 TCU_FAIL("Invalid enum");
2663 }
2664
2665 return name;
2666 }
2667
2668 /** Check format and size of compressed image
2669 *
2670 **/
getCompressedInfo()2671 void MapPersistentTextureTest::getCompressedInfo()
2672 {
2673 const Functions& gl = m_context.getRenderContext().getFunctions();
2674
2675 /* Texture creation */
2676 Texture texture(m_context);
2677 Texture::Generate(gl, texture.m_id);
2678 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
2679 Texture::Image(gl, GL_TEXTURE_2D, 0, GL_COMPRESSED_RED_RGTC1, 8, 8, 1, GL_RED, GL_UNSIGNED_BYTE,
2680 0); // glspec 4.5 pg 216
2681
2682 /* Queries */
2683 Texture::GetLevelParameter(gl, GL_TEXTURE_2D, 0 /* level */, GL_TEXTURE_COMPRESSED_IMAGE_SIZE,
2684 &m_compressed_image_size);
2685 Texture::GetLevelParameter(gl, GL_TEXTURE_2D, 0 /* level */, GL_TEXTURE_INTERNAL_FORMAT,
2686 &m_compressed_internal_format);
2687 }
2688
2689 /** Verifies results of tested operation
2690 *
2691 * @param operation Operation to be tested
2692 * @param buffer Buffer that will be used as GL_PIXEL_UNPACK_BUFFER
2693 * @param expected_error Expected error
2694 *
2695 * @return false in case of any error, true otherwise
2696 **/
verifyTestedOperation(TESTED_OPERATION operation,Buffer & buffer,glw::GLenum expected_error)2697 bool MapPersistentTextureTest::verifyTestedOperation(TESTED_OPERATION operation, Buffer& buffer,
2698 glw::GLenum expected_error)
2699 {
2700 const Functions& gl = m_context.getRenderContext().getFunctions();
2701
2702 bool result = true;
2703
2704 GLenum error = GL_NO_ERROR;
2705 Texture texture(m_context);
2706
2707 /* Prepare texture */
2708 Texture::Generate(gl, texture.m_id);
2709 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
2710
2711 switch (operation)
2712 {
2713 case OP_COMPRESSED_TEX_IMAGE:
2714 case OP_TEX_IMAGE:
2715 break;
2716 case OP_COMPRESSED_TEX_SUB_IMAGE:
2717 case OP_COMPRESSED_TEXTURE_SUB_IMAGE:
2718 Texture::CompressedImage(gl, GL_TEXTURE_2D, 0 /* level */, m_compressed_internal_format, 8 /* width */,
2719 8 /* height */, 0 /* depth */, m_compressed_image_size /* imageSize */,
2720 0 /* empty image */);
2721 break;
2722 case OP_TEX_SUB_IMAGE:
2723 Texture::Image(gl, GL_TEXTURE_2D, 0 /* level */, GL_R8, 8 /* width */, 8 /* height */, 0 /* depth */, GL_RED,
2724 GL_UNSIGNED_BYTE, 0 /* empty image */);
2725 break;
2726 default:
2727 TCU_FAIL("Invalid enum");
2728 }
2729
2730 /* Bind buffer to PIXEL_UNPACK */
2731 Buffer::Bind(gl, buffer.m_id, GL_PIXEL_UNPACK_BUFFER);
2732
2733 /* Execute operation */
2734 switch (operation)
2735 {
2736 case OP_COMPRESSED_TEX_IMAGE:
2737 gl.compressedTexImage2D(GL_TEXTURE_2D, 0 /* level */, m_compressed_internal_format, 8 /* width */,
2738 8 /* height */, 0 /* border */, m_compressed_image_size /* imageSize */,
2739 0 /* offset to pixel unpack buffer */);
2740 error = gl.getError();
2741 break;
2742 case OP_COMPRESSED_TEX_SUB_IMAGE:
2743 gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 8 /* width */, 8 /* height */,
2744 m_compressed_internal_format, m_compressed_image_size,
2745 0 /* offset to pixel unpack buffer */);
2746 error = gl.getError();
2747 break;
2748 case OP_COMPRESSED_TEXTURE_SUB_IMAGE:
2749 if (0 != gl.compressedTextureSubImage2D)
2750 {
2751 gl.compressedTextureSubImage2D(texture.m_id, 0 /* level */, 0 /* x */, 0 /* y */, 8 /* width */,
2752 8 /* height */, m_compressed_internal_format, m_compressed_image_size,
2753 0 /* offset to pixel unpack buffer */);
2754 error = gl.getError();
2755 }
2756 else
2757 {
2758 /* Not supported, ignore */
2759 error = expected_error;
2760 }
2761 break;
2762 case OP_TEX_IMAGE:
2763 gl.texImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R8, 8 /* width */, 8 /* height */, 0 /* border */, GL_RED,
2764 GL_UNSIGNED_BYTE, 0 /* offset to pixel unpack buffer */);
2765 error = gl.getError();
2766 break;
2767 case OP_TEX_SUB_IMAGE:
2768 gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 8 /* width */, 8 /* height */, GL_RED,
2769 GL_UNSIGNED_BYTE, 0 /* offset to pixel unpack buffer */);
2770 error = gl.getError();
2771 break;
2772 default:
2773 TCU_FAIL("Invalid enum");
2774 }
2775
2776 /* Unbind buffer */
2777 Buffer::Bind(gl, 0 /* id */, GL_PIXEL_UNPACK_BUFFER);
2778
2779 /* Check result */
2780 if (expected_error != error)
2781 {
2782 result = false;
2783
2784 m_context.getTestContext().getLog() << tcu::TestLog::Message << getOperationName(operation)
2785 << " generated wrong error: " << glu::getErrorStr(error).toString().c_str()
2786 << ", expected: " << glu::getErrorStr(expected_error).toString().c_str()
2787 << tcu::TestLog::EndMessage;
2788 }
2789
2790 /* Done */
2791 return result;
2792 }
2793
2794 /** Constructor
2795 *
2796 * @param context Test context
2797 **/
MapPersistentReadPixelsTest(deqp::Context & context)2798 MapPersistentReadPixelsTest::MapPersistentReadPixelsTest(deqp::Context& context)
2799 : TestCase(context, "map_persistent_read_pixels", "Test read pixels operation against mapped buffer")
2800 {
2801 /* Nothing to be done here */
2802 }
2803
2804 /** Execute test
2805 *
2806 * @return tcu::TestNode::STOP otherwise
2807 **/
iterate()2808 tcu::TestNode::IterateResult MapPersistentReadPixelsTest::iterate()
2809 {
2810 static const GLuint height = 8;
2811 static const GLuint width = 8;
2812 static const size_t data_size = width * height;
2813
2814 const Functions& gl = m_context.getRenderContext().getFunctions();
2815
2816 bool test_result = true;
2817
2818 /* Prepare data */
2819 GLubyte initial_texture_data[data_size];
2820 GLubyte updated_texture_data[data_size];
2821
2822 for (size_t i = 0; i < data_size; ++i)
2823 {
2824 initial_texture_data[i] = (glw::GLubyte)i;
2825 updated_texture_data[i] = (glw::GLubyte)(data_size - i);
2826 }
2827
2828 /* Prepare GL objects */
2829 Buffer buffer(m_context);
2830 Framebuffer framebuffer(m_context);
2831 Texture texture(m_context);
2832
2833 buffer.InitStorage(GL_PIXEL_PACK_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, data_size,
2834 0 /* data */);
2835
2836 Texture::Generate(gl, texture.m_id);
2837 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
2838 Texture::Storage(gl, GL_TEXTURE_2D, 1 /* levels */, GL_R8UI, width, height, 0 /* depth */);
2839 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, 0 /* depth */,
2840 GL_RED_INTEGER, GL_UNSIGNED_BYTE, initial_texture_data);
2841
2842 Framebuffer::Generate(gl, framebuffer.m_id);
2843 Framebuffer::Bind(gl, GL_READ_FRAMEBUFFER, framebuffer.m_id);
2844 Framebuffer::AttachTexture(gl, GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.m_id, width, height);
2845
2846 /*
2847 * - execute ReadPixels to transfer texture contents to buffer, no error should
2848 * be generated;
2849 */
2850 buffer.Bind();
2851 gl.readPixels(0 /* x */, 0 /* y */, width, height, GL_RED_INTEGER, GL_UNSIGNED_BYTE,
2852 0 /* offset in PIXEL_PACK_BUFFER */);
2853 GLU_EXPECT_NO_ERROR(gl.getError(), "ReadPixels to not mapped PIXEL_PACK buffer");
2854
2855 /*
2856 * - update contents of texture with different image;
2857 * - map buffer contents with MapBufferRange, <access> should contain
2858 * MAP_PERSISTENT_BIT, MAP_READ_BIT and MAP_WRITE_BIT;
2859 * - execute ReadPixels to transfer texture contents to buffer, no error should
2860 * be generated;
2861 * - execute MemoryBarrier with CLIENT_MAPPED_BUFFER_BARRIER_BIT and Finish;
2862 * - inspect contents of mapped buffer, to verify that latest data transfer was
2863 * successful;
2864 * - unmap buffer
2865 */
2866 {
2867 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height,
2868 0 /* depth */, GL_RED_INTEGER, GL_UNSIGNED_BYTE, updated_texture_data);
2869
2870 const Buffer::MapOwner map(
2871 buffer.MapRange(0 /* offset */, data_size, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2872
2873 buffer.Bind();
2874 gl.readPixels(0 /* x */, 0 /* y */, width, height, GL_RED_INTEGER, GL_UNSIGNED_BYTE,
2875 0 /* offset in PIXEL_PACK_BUFFER */);
2876 GLU_EXPECT_NO_ERROR(gl.getError(), "ReadPixels to persistently mapped PIXEL_PACK buffer");
2877
2878 gl.memoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
2879 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
2880
2881 gl.finish();
2882 GLU_EXPECT_NO_ERROR(gl.getError(), "Finish");
2883
2884 if (0 != memcmp(updated_texture_data, map.m_data, data_size))
2885 {
2886 test_result = false;
2887
2888 m_context.getTestContext().getLog()
2889 << tcu::TestLog::Message << "Wrong contents of persistently mapped PIXEL_PACK buffer after ReadPixels"
2890 << tcu::TestLog::EndMessage;
2891 }
2892 }
2893
2894 /*
2895 * - map buffer contents again, this time do not provide MAP_PERSISTENT_BIT;
2896 * - execute ReadPixels to transfer texture contents to buffer,
2897 * INVALID_OPERATION error should be generated.
2898 */
2899 {
2900 Buffer::MapOwner tmp(buffer.MapRange(0 /* offset */, data_size, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
2901
2902 buffer.Bind();
2903 gl.readPixels(0 /* x */, 0 /* y */, width, height, GL_RED_INTEGER, GL_UNSIGNED_BYTE,
2904 0 /* offset in PIXEL_PACK_BUFFER */);
2905 GLenum error = gl.getError();
2906
2907 if (GL_INVALID_OPERATION != error)
2908 {
2909 test_result = false;
2910
2911 m_context.getTestContext().getLog()
2912 << tcu::TestLog::Message << "Wrong error was generated by ReadPixels. Expected INVALID_OPERATION as "
2913 "PIXEL_PACK buffer is mapped. Got: "
2914 << glu::getErrorStr(error).toString().c_str() << tcu::TestLog::EndMessage;
2915 }
2916 }
2917
2918 /* Set result */
2919 if (true == test_result)
2920 {
2921 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2922 }
2923 else
2924 {
2925 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2926 }
2927
2928 /* Done */
2929 return tcu::TestNode::STOP;
2930 }
2931
2932 /** Constructor
2933 *
2934 * @param context Test context
2935 **/
MapPersistentDispatchTest(deqp::Context & context)2936 MapPersistentDispatchTest::MapPersistentDispatchTest(deqp::Context& context)
2937 : TestCase(context, "map_persistent_dispatch", "test dispatch operation against mapped buffer")
2938 {
2939 /* Nothing to be done here */
2940 }
2941
2942 /** Constructor
2943 *
2944 * @param context Test context
2945 * @param test_name Test name
2946 * @param test_description Test description
2947 **/
MapPersistentDispatchTest(deqp::Context & context,const GLchar * test_name,const GLchar * test_description)2948 MapPersistentDispatchTest::MapPersistentDispatchTest(deqp::Context& context, const GLchar* test_name,
2949 const GLchar* test_description)
2950 : TestCase(context, test_name, test_description)
2951 {
2952 /* Nothing to be done here */
2953 }
2954
2955 /** Execute test
2956 *
2957 * @return tcu::TestNode::STOP otherwise
2958 **/
iterate()2959 tcu::TestNode::IterateResult MapPersistentDispatchTest::iterate()
2960 {
2961 static const GLchar* compute_shader = "#version 430 core\n"
2962 "\n"
2963 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2964 "\n"
2965 "layout (binding = 0, std430) buffer DestinationData {\n"
2966 " uint values[];\n"
2967 "} destination;\n"
2968 "\n"
2969 "layout (binding = 1, std430) buffer SourceData {\n"
2970 " uint values[];\n"
2971 "} source;\n"
2972 "\n"
2973 "void main()\n"
2974 "{\n"
2975 " uint index = gl_GlobalInvocationID.x;\n"
2976 " uint sum = 0u;\n"
2977 "\n"
2978 " for (uint i = 0u; i <= index; ++i)\n"
2979 " {\n"
2980 " sum += source.values[i];\n"
2981 " }\n"
2982 "\n"
2983 " destination.values[index] = sum;\n"
2984 "}\n"
2985 "\n";
2986 static const GLuint data_size = 16;
2987 static const GLuint destination_binding = 0;
2988 static const GLuint source_binding = 1;
2989
2990 const Functions& gl = m_context.getRenderContext().getFunctions();
2991
2992 bool test_result = true;
2993
2994 /* Prepare data */
2995 GLuint destination_data[data_size];
2996 GLuint modified_source_data[data_size];
2997 GLuint modified_sum_data[data_size];
2998 GLuint source_data[data_size];
2999 GLuint sum_data[data_size];
3000
3001 GLuint modified_sum = 0;
3002 GLuint sum = 0;
3003
3004 for (GLuint i = 0; i < data_size; ++i)
3005 {
3006 destination_data[i] = 0;
3007 modified_source_data[i] = data_size - i;
3008 source_data[i] = i;
3009
3010 modified_sum += modified_source_data[i];
3011 sum += source_data[i];
3012
3013 modified_sum_data[i] = modified_sum;
3014 sum_data[i] = sum;
3015 }
3016
3017 /* Prepare buffers */
3018 Buffer destination(m_context);
3019 Buffer source(m_context);
3020
3021 destination.InitStorage(GL_SHADER_STORAGE_BUFFER, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT,
3022 data_size * sizeof(GLuint), destination_data);
3023
3024 source.InitStorage(GL_SHADER_STORAGE_BUFFER, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT,
3025 data_size * sizeof(GLuint), source_data);
3026
3027 /* Prepare program */
3028 Program program(m_context);
3029 program.Init(compute_shader, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3030
3031 /*
3032 * - bind buffers to SHADER_STORAGE_BUFFER;
3033 * - use MapBufferRange to map both buffers; <access> shall be set as follows:
3034 * * MAP_COHERENT_BIT and MAP_PERSISTENT_BIT flags set for both
3035 * * MAP_WRITE_BIT flag shall be set for source;
3036 * * MAP_READ_BIT flag shall be set for destination;
3037 * - dispatch program for 16x1x1 groups;
3038 * - modify contents of source buffer via mapped memory;
3039 * - execute Finish;
3040 * - inspect contents of destination buffer via mapped memory; It is expected
3041 * that it will contain results based on original content of source buffer;
3042 * - dispatch program for 16x1x1 groups;
3043 * - execute Finish;
3044 * - inspect contents of destination buffer via mapped memory; It is expected
3045 * that it will contain results based on modified content of source buffer.
3046 */
3047 {
3048 /* Set program */
3049 Program::Use(gl, program.m_id);
3050
3051 /* Map buffers */
3052 destination.Bind();
3053 const Buffer::MapOwner destination_map(destination.MapRange(
3054 0 /* offset */, data_size * sizeof(GLuint), GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT));
3055
3056 source.Bind();
3057 const Buffer::MapOwner source_map(
3058 source.MapRange(0 /* offset */, data_size * sizeof(GLuint),
3059 GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT));
3060
3061 /* Clear binding point */
3062 Buffer::Bind(gl, 0, GL_SHADER_STORAGE_BUFFER);
3063
3064 /* Bind buffers */
3065 Buffer::BindBase(gl, destination.m_id, GL_SHADER_STORAGE_BUFFER, destination_binding);
3066 Buffer::BindBase(gl, source.m_id, GL_SHADER_STORAGE_BUFFER, source_binding);
3067
3068 /* Execute program for 16x1x1 groups */
3069 gl.dispatchCompute(16, 1, 1);
3070 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute with persistently mapped buffers");
3071
3072 /* Make sure that program executed */
3073 gl.finish();
3074 GLU_EXPECT_NO_ERROR(gl.getError(), "Finish");
3075
3076 if (0 != memcmp(destination_map.m_data, sum_data, data_size * sizeof(GLuint)))
3077 {
3078 test_result = false;
3079
3080 m_context.getTestContext().getLog() << tcu::TestLog::Message
3081 << "Contents of mapped region does not correspond with expected results"
3082 << tcu::TestLog::EndMessage;
3083 }
3084
3085 /* Modify source buffer via mapped area */
3086 memcpy(source_map.m_data, modified_source_data, data_size * sizeof(GLuint));
3087
3088 /* Execute program for 16x1x1 groups */
3089 gl.dispatchCompute(16, 1, 1);
3090 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute with persistently mapped buffers");
3091
3092 /* Make sure that program executed */
3093 gl.finish();
3094 GLU_EXPECT_NO_ERROR(gl.getError(), "Finish");
3095
3096 if (0 != memcmp(destination_map.m_data, modified_sum_data, data_size * sizeof(GLuint)))
3097 {
3098 test_result = false;
3099
3100 m_context.getTestContext().getLog() << tcu::TestLog::Message
3101 << "Contents of mapped region does not correspond with expected results"
3102 << tcu::TestLog::EndMessage;
3103 }
3104 }
3105
3106 /* Set result */
3107 if (true == test_result)
3108 {
3109 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3110 }
3111 else
3112 {
3113 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3114 }
3115
3116 /* Done */
3117 return tcu::TestNode::STOP;
3118 }
3119
3120 /** Constructor
3121 *
3122 * @param context Test context
3123 **/
MapPersistentFlushTest(deqp::Context & context)3124 MapPersistentFlushTest::MapPersistentFlushTest(deqp::Context& context)
3125 : TestCase(context, "map_persistent_flush", "Test mapped buffer against flushing")
3126 {
3127 /* Nothing to be done here */
3128 }
3129
3130 /** Execute test
3131 *
3132 * @return tcu::TestNode::STOP otherwise
3133 **/
iterate()3134 tcu::TestNode::IterateResult MapPersistentFlushTest::iterate()
3135 {
3136 static const GLchar* compute_shader = "#version 430 core\n"
3137 "\n"
3138 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3139 "\n"
3140 "layout (binding = 0, std430) buffer DestinationData {\n"
3141 " uint values[];\n"
3142 "} destination;\n"
3143 "\n"
3144 "layout (binding = 1, std430) buffer SourceData {\n"
3145 " uint values[];\n"
3146 "} source;\n"
3147 "\n"
3148 "void main()\n"
3149 "{\n"
3150 " uint index = gl_GlobalInvocationID.x;\n"
3151 " uint sum = 0u;\n"
3152 "\n"
3153 " for (uint i = 0u; i <= index; ++i)\n"
3154 " {\n"
3155 " sum += source.values[i];\n"
3156 " }\n"
3157 "\n"
3158 " destination.values[index] = sum;\n"
3159 "}\n"
3160 "\n";
3161 static const GLuint data_size = 16;
3162 static const GLuint destination_binding = 0;
3163 static const GLuint source_binding = 1;
3164
3165 const Functions& gl = m_context.getRenderContext().getFunctions();
3166
3167 bool test_result = true;
3168
3169 /* Prepare data */
3170 GLuint destination_data[data_size];
3171 GLuint modified_source_data[data_size];
3172 GLuint modified_sum_data[data_size];
3173 GLuint source_data[data_size];
3174 GLuint sum_data[data_size];
3175
3176 GLuint modified_sum = 0;
3177 GLuint sum = 0;
3178
3179 for (GLuint i = 0; i < data_size; ++i)
3180 {
3181 destination_data[i] = 0;
3182 modified_source_data[i] = data_size - i;
3183 source_data[i] = i;
3184
3185 modified_sum += modified_source_data[i];
3186 sum += source_data[i];
3187
3188 modified_sum_data[i] = modified_sum;
3189 sum_data[i] = sum;
3190 }
3191
3192 /* Prepare buffers */
3193 Buffer destination(m_context);
3194 Buffer source(m_context);
3195
3196 destination.InitStorage(GL_SHADER_STORAGE_BUFFER, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT,
3197 data_size * sizeof(GLuint), destination_data);
3198
3199 source.InitStorage(GL_SHADER_STORAGE_BUFFER, GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT,
3200 data_size * sizeof(GLuint), source_data);
3201
3202 /* Prepare program */
3203 Program program(m_context);
3204 program.Init(compute_shader, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3205
3206 /*
3207 * - bind buffers to SHADER_STORAGE_BUFFER;
3208 * - use MapBufferRange to map both buffers; <access> shall be set as follows:
3209 * * MAP_COHERENT_BIT and MAP_PERSISTENT_BIT flags set for both
3210 * * MAP_WRITE_BIT flag shall be set for source;
3211 * * MAP_READ_BIT flag shall be set for destination;
3212 * - dispatch program for 16x1x1 groups;
3213 * - modify contents of source buffer via mapped memory;
3214 * - execute Finish;
3215 * - inspect contents of destination buffer via mapped memory; It is expected
3216 * that it will contain results based on original content of source buffer;
3217 * - dispatch program for 16x1x1 groups;
3218 * - execute Finish;
3219 * - inspect contents of destination buffer via mapped memory; It is expected
3220 * that it will contain results based on modified content of source buffer.
3221 */
3222 {
3223 /* Set program */
3224 Program::Use(gl, program.m_id);
3225
3226 /* Map buffers */
3227 destination.Bind();
3228 const Buffer::MapOwner destination_map(destination.MapRange(
3229 0 /* offset */, data_size * sizeof(GLuint), GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT));
3230
3231 source.Bind();
3232 const Buffer::MapOwner source_map(
3233 source.MapRange(0 /* offset */, data_size * sizeof(GLuint),
3234 GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT));
3235
3236 /* Clear binding point */
3237 Buffer::Bind(gl, 0, GL_SHADER_STORAGE_BUFFER);
3238
3239 /* Bind buffers */
3240 Buffer::BindBase(gl, destination.m_id, GL_SHADER_STORAGE_BUFFER, destination_binding);
3241 Buffer::BindBase(gl, source.m_id, GL_SHADER_STORAGE_BUFFER, source_binding);
3242
3243 /* Execute program for 16x1x1 groups */
3244 gl.dispatchCompute(16, 1, 1);
3245 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute with persistently mapped buffers");
3246
3247 /* Make sure that program executed */
3248 gl.finish();
3249 GLU_EXPECT_NO_ERROR(gl.getError(), "Finish");
3250
3251 if (0 != memcmp(destination_map.m_data, sum_data, data_size * sizeof(GLuint)))
3252 {
3253 test_result = false;
3254
3255 m_context.getTestContext().getLog() << tcu::TestLog::Message
3256 << "Contents of mapped region does not correspond with expected results"
3257 << tcu::TestLog::EndMessage;
3258 }
3259
3260 /* Modify source buffer via mapped area */
3261 memcpy(source_map.m_data, modified_source_data, data_size * sizeof(GLuint));
3262
3263 /*
3264 * - apply FlushMappedBufferRange to ensure that modifications of source buffer
3265 * are visible to server.
3266 */
3267 source.Bind();
3268 gl.flushMappedBufferRange(GL_SHADER_STORAGE_BUFFER, 0 /* offset */, data_size * sizeof(GLuint));
3269 GLU_EXPECT_NO_ERROR(gl.getError(), "FlushMappedBufferRange");
3270
3271 /* Clear binding point */
3272 Buffer::Bind(gl, 0, GL_SHADER_STORAGE_BUFFER);
3273
3274 /* Execute program for 16x1x1 groups */
3275 gl.dispatchCompute(16, 1, 1);
3276 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute with persistently mapped buffers");
3277
3278 /* Make sure that program executed */
3279 gl.finish();
3280 GLU_EXPECT_NO_ERROR(gl.getError(), "Finish");
3281
3282 if (0 != memcmp(destination_map.m_data, modified_sum_data, data_size * sizeof(GLuint)))
3283 {
3284 test_result = false;
3285
3286 m_context.getTestContext().getLog() << tcu::TestLog::Message
3287 << "Contents of mapped region does not correspond with expected results"
3288 << tcu::TestLog::EndMessage;
3289 }
3290 }
3291
3292 /* Set result */
3293 if (true == test_result)
3294 {
3295 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3296 }
3297 else
3298 {
3299 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3300 }
3301
3302 /* Done */
3303 return tcu::TestNode::STOP;
3304 }
3305
3306 /** Constructor
3307 *
3308 * @param context Test context
3309 **/
MapPersistentDrawTest(deqp::Context & context)3310 MapPersistentDrawTest::MapPersistentDrawTest(deqp::Context& context)
3311 : TestCase(context, "map_persistent_draw", "Test draw operation against mapped buffer")
3312 {
3313 /* Nothing to be done here */
3314 }
3315
3316 /** Execute test
3317 *
3318 * @return tcu::TestNode::STOP otherwise
3319 **/
iterate()3320 tcu::TestNode::IterateResult MapPersistentDrawTest::iterate()
3321 {
3322 /*
3323 * * fragment shader should pass value of "gs_fs_color" varying to red
3324 * channel of output color;
3325 */
3326 static const GLchar* fragment_shader = "#version 440 core\n"
3327 "\n"
3328 "in float gs_fs_color;\n"
3329 "out vec4 fs_out_color;\n"
3330 "\n"
3331 "void main()\n"
3332 "{\n"
3333 " fs_out_color = vec4(gs_fs_color, 0, 0, 1);\n"
3334 "}\n"
3335 "\n";
3336
3337 /*
3338 * * geometry shader should:
3339 * - define single uniform buffer array "rectangles" with unspecified size;
3340 * Rectangles should have two vec2 fields: position and size;
3341 * - define single atomic_uint "atom_color";
3342 * - increment "atom_color" once per execution;
3343 * - output a quad that is placed at rectangles[vs_gs_index].position and
3344 * has size equal rectangles[vs_gs_index].size;
3345 * - define output float varying "gs_fs_color" equal to "atom_color" / 255;
3346 */
3347 static const GLchar* geometry_shader =
3348 "#version 440 core\n"
3349 "\n"
3350 "layout(points) in;\n"
3351 "layout(triangle_strip, max_vertices = 4) out;\n"
3352 "\n"
3353 "struct Rectangle {\n"
3354 " vec2 position;\n"
3355 " vec2 size;\n"
3356 "};\n"
3357 "\n"
3358 "layout (std140, binding = 0) uniform Rectangles {\n"
3359 " Rectangle rectangle[2];\n"
3360 "} rectangles;\n"
3361 "\n"
3362 "layout (binding = 0) uniform atomic_uint atom_color;\n"
3363 "\n"
3364 "in uint vs_gs_index[];\n"
3365 "out float gs_fs_color;\n"
3366 "\n"
3367 "void main()\n"
3368 "{\n"
3369 " const uint atom_color_value = atomicCounterIncrement(atom_color);\n"
3370 " //const uint atom_color_value = vs_gs_index[0];\n"
3371 " const float color = float(atom_color_value) / 255.0;\n"
3372 " //const float color = rectangles.rectangle[1].size.x;\n"
3373 "\n"
3374 " const float left = rectangles.rectangle[vs_gs_index[0]].position.x;\n"
3375 " const float bottom = rectangles.rectangle[vs_gs_index[0]].position.y;\n"
3376 " const float right = rectangles.rectangle[vs_gs_index[0]].size.x + left;\n"
3377 " const float top = rectangles.rectangle[vs_gs_index[0]].size.y + bottom;\n"
3378 "\n"
3379 " //const float left = rectangles.rectangle[0].position.x;\n"
3380 " //const float bottom = rectangles.rectangle[0].position.y;\n"
3381 " //const float right = rectangles.rectangle[0].size.x + left;\n"
3382 " //const float top = rectangles.rectangle[0].size.y + bottom;\n"
3383 "\n"
3384 " gs_fs_color = color;\n"
3385 " gl_Position = vec4(left, bottom, 0, 1);\n"
3386 " EmitVertex();\n"
3387 "\n"
3388 " gs_fs_color = color;\n"
3389 " gl_Position = vec4(left, top, 0, 1);\n"
3390 " EmitVertex();\n"
3391 "\n"
3392 " gs_fs_color = color;\n"
3393 " gl_Position = vec4(right, bottom, 0, 1);\n"
3394 " EmitVertex();\n"
3395 "\n"
3396 " gs_fs_color = color;\n"
3397 " gl_Position = vec4(right, top, 0, 1);\n"
3398 " EmitVertex();\n"
3399 "}\n"
3400 "\n";
3401
3402 /*
3403 * * vertex shader should output single varying "vs_gs_index" of type uint,
3404 * equal to gl_VertexID;
3405 */
3406 static const GLchar* vertex_shader = "#version 440 core\n"
3407 "\n"
3408 "out uint vs_gs_index;\n"
3409 "\n"
3410 "void main()\n"
3411 "{\n"
3412 " vs_gs_index = gl_VertexID;\n"
3413 "}\n"
3414 "\n";
3415
3416 static const GLuint atom_binding = 0;
3417 static const size_t atom_data_size = 1 * sizeof(GLuint);
3418 static const GLuint expected_atom_first = 3;
3419 static const GLuint expected_atom_second = 7;
3420 static const GLuint expected_pixel = 0xff000003;
3421 static const GLuint height = 16;
3422 static const GLuint n_rectangles = 2;
3423 static const GLuint pixel_size = 4 * sizeof(GLubyte);
3424 static const GLuint rectangles_binding = 0;
3425 static const size_t rectangle_size = 2 * 2 * sizeof(GLfloat); /* 2 * vec2 */
3426 static const size_t rectangles_data_size = n_rectangles * rectangle_size;
3427 static const GLuint width = 16;
3428 static const GLuint line_size = width * pixel_size;
3429 static const GLuint pixel_offset = 8 * line_size + 7 * pixel_size;
3430 static const size_t texture_data_size = height * line_size;
3431
3432 const Functions& gl = m_context.getRenderContext().getFunctions();
3433
3434 bool test_result = true;
3435
3436 /* Prepare data */
3437 GLuint atom_first_data[1];
3438 GLuint atom_second_data[1];
3439 GLubyte rectangles_first_data[rectangles_data_size];
3440 GLubyte rectangles_second_data[rectangles_data_size];
3441 GLubyte texture_data[texture_data_size];
3442
3443 atom_first_data[0] = 1;
3444 atom_second_data[0] = 5;
3445
3446 {
3447 GLfloat* ptr = (GLfloat*)rectangles_first_data;
3448
3449 /* First.position*/
3450 ptr[0] = -0.5f;
3451 ptr[1] = -0.5f;
3452
3453 /* First.size*/
3454 ptr[2] = 1.0f;
3455 ptr[3] = 1.0f;
3456
3457 /* Second.position*/
3458 ptr[4 + 0] = -0.75f;
3459 ptr[4 + 1] = -0.75f;
3460
3461 /* Second.size*/
3462 ptr[4 + 2] = 1.5f;
3463 ptr[4 + 3] = 1.5f;
3464 }
3465
3466 {
3467 GLfloat* ptr = (GLfloat*)rectangles_second_data;
3468
3469 /* First.position*/
3470 ptr[0] = -1.0f;
3471 ptr[1] = -1.0f;
3472
3473 /* First.size*/
3474 ptr[2] = 0.5f;
3475 ptr[3] = 0.5f;
3476
3477 /* Second.position*/
3478 ptr[4 + 0] = 0.5f;
3479 ptr[4 + 1] = 0.5f;
3480
3481 /* Second.size*/
3482 ptr[4 + 2] = 0.5f;
3483 ptr[4 + 3] = 0.5f;
3484 }
3485
3486 /* Prepare buffers */
3487 Buffer atom(m_context);
3488 Buffer rectangles(m_context);
3489
3490 atom.InitStorage(GL_ATOMIC_COUNTER_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
3491 atom_data_size, 0);
3492
3493 rectangles.InitStorage(GL_UNIFORM_BUFFER, GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT, rectangles_data_size, 0);
3494
3495 /* Prepare framebuffer */
3496 Framebuffer framebuffer(m_context);
3497 Texture texture(m_context);
3498
3499 Texture::Generate(gl, texture.m_id);
3500 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
3501 Texture::Storage(gl, GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, width, height, 0 /* depth */);
3502
3503 Framebuffer::Generate(gl, framebuffer.m_id);
3504 Framebuffer::Bind(gl, GL_DRAW_FRAMEBUFFER, framebuffer.m_id);
3505 Framebuffer::AttachTexture(gl, GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.m_id, width, height);
3506
3507 /* Prepare VAO */
3508 VertexArray vao(m_context);
3509
3510 VertexArray::Generate(gl, vao.m_id);
3511 VertexArray::Bind(gl, vao.m_id);
3512
3513 /* Prepare program */
3514 Program program(m_context);
3515 program.Init("" /* cs */, fragment_shader, geometry_shader, "" /* tcs */, "" /* tes */, vertex_shader);
3516 Program::Use(gl, program.m_id);
3517
3518 /*
3519 * - make persistent mapping of both buffers for reads and writes;
3520 * - modify "rectangles" buffer via mapped memory with the following two sets
3521 * * position [-0.5,-0.5], size [1.0,1.0],
3522 * * position [-0.25,-0.25], size [1.5,1.5];
3523 * - modify "atom_color" buffer via mapped memory to value 1;
3524 * - execute MemoryBarrier for CLIENT_MAPPED_BUFFER_BARRIER_BIT;
3525 * - enable blending with functions ONE for both source and destination;
3526 * - execute DrawArrays for two vertices;
3527 * - execute MemoryBarrier for ALL_BARRIER_BITS and Finish;
3528 * - inspect contents of:
3529 * * texture - to verify that pixel at 8,8 is filled with RGBA8(3,0,0,0),
3530 * * "atom_color" - to verify that it is equal to 3;
3531 * - modify "rectangles" buffer via mapped memory with the following two sets
3532 * * position [-1.0,-1.0], size [0.5,0.5],
3533 * * position [0.5,0.5], size [0.5,0.5];
3534 * - modify "atom_color" buffer via mapped memory to value 5;
3535 * - execute MemoryBarrier for CLIENT_MAPPED_BUFFER_BARRIER_BIT;
3536 * - execute DrawArrays for two vertices;
3537 * - execute MemoryBarrier for ALL_BARRIER_BITS and Finish;
3538 * - inspect contents of:
3539 * * texture - to verify that pixel at 8,8 is filled with RGBA8(3,0,0,0),
3540 * * "atom_color" - to verify that it is equal to 7;
3541 *
3542 * Additionally: change MemoryBarrier to FlushMapped*BufferRange if context supports OpenGL 4.5 Core Profile.
3543 */
3544 {
3545 /* Choose specification */
3546 const bool is_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
3547
3548 /* Map buffers */
3549 atom.Bind();
3550 const Buffer::MapOwner atom_map(atom.MapRange(0 /* offset */, atom_data_size,
3551 GL_MAP_PERSISTENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT |
3552 (is_gl_45 ? GL_MAP_FLUSH_EXPLICIT_BIT : 0)));
3553
3554 rectangles.Bind();
3555 const Buffer::MapOwner rectangles_map(
3556 rectangles.MapRange(0 /* offset */, rectangles_data_size,
3557 GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT | (is_gl_45 ? GL_MAP_FLUSH_EXPLICIT_BIT : 0)));
3558
3559 /* Clear binding points */
3560 Buffer::Bind(gl, 0, GL_ATOMIC_COUNTER_BUFFER);
3561 Buffer::Bind(gl, 0, GL_UNIFORM_BUFFER);
3562
3563 /* Bind buffers */
3564 Buffer::BindBase(gl, atom.m_id, GL_ATOMIC_COUNTER_BUFFER, atom_binding);
3565 Buffer::BindBase(gl, rectangles.m_id, GL_UNIFORM_BUFFER, rectangles_binding);
3566
3567 /* Set up blending */
3568 gl.enable(GL_BLEND);
3569 gl.blendFunc(GL_ONE, GL_ONE);
3570
3571 /* Modify buffers */
3572 memcpy(atom_map.m_data, atom_first_data, atom_data_size);
3573 memcpy(rectangles_map.m_data, rectangles_first_data, rectangles_data_size);
3574
3575 /* Execute barrier or flush content. */
3576 if (is_gl_45)
3577 {
3578 gl.flushMappedBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, atom_data_size);
3579 GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");
3580
3581 gl.flushMappedBufferRange(GL_UNIFORM_BUFFER, 0, rectangles_data_size);
3582 GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");
3583 }
3584 else
3585 {
3586 gl.memoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
3587 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3588 }
3589
3590 /* Clear drawbuffer */
3591 GLint clear_color[4] = { 0, 0, 0, 0 };
3592 gl.clearBufferiv(GL_COLOR, 0, clear_color);
3593
3594 /* Execute program for 2 vertices */
3595 gl.drawArrays(GL_POINTS, 0, 2);
3596 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays with persistently mapped buffers");
3597
3598 /* Execute barrier */
3599 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3600 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3601
3602 /* Inspect texture */
3603 Texture::GetData(gl, GL_TEXTURE_2D, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
3604 if (0 != memcmp(texture_data + pixel_offset, &expected_pixel, pixel_size))
3605 {
3606 test_result = false;
3607
3608 m_context.getTestContext().getLog() << tcu::TestLog::Message
3609 << "Contents of framebuffer does not correspond with expected results"
3610 << tcu::TestLog::EndMessage;
3611 tcu::ConstPixelBufferAccess img(
3612 tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), width, height,
3613 1 /* depth */, texture_data);
3614 m_context.getTestContext().getLog()
3615 << tcu::TestLog::Image("Framebuffer", "Framebuffer contents using initial buffer data", img);
3616 }
3617
3618 /* Inspect atom */
3619 if (0 != memcmp(atom_map.m_data, &expected_atom_first, sizeof(GLuint)))
3620 {
3621 test_result = false;
3622
3623 m_context.getTestContext().getLog() << tcu::TestLog::Message
3624 << "Contents of ATOMIC_COUNTER buffer are invalid."
3625 << tcu::TestLog::EndMessage;
3626 }
3627
3628 /* Modify buffers */
3629 memcpy(atom_map.m_data, atom_second_data, atom_data_size);
3630 memcpy(rectangles_map.m_data, rectangles_second_data, rectangles_data_size);
3631
3632 /* Execute barrier or flush content. */
3633 if (is_gl_45)
3634 {
3635 gl.flushMappedBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, atom_data_size);
3636 GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");
3637
3638 gl.flushMappedBufferRange(GL_UNIFORM_BUFFER, 0, rectangles_data_size);
3639 GLU_EXPECT_NO_ERROR(gl.getError(), "glFlushMappedBufferRange");
3640 }
3641 else
3642 {
3643 gl.memoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
3644 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3645 }
3646
3647 /* Execute program for 2 vertices */
3648 gl.drawArrays(GL_POINTS, 0, 2);
3649 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays with persistently mapped buffers");
3650
3651 /* Execute barrier */
3652 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3653 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3654
3655 /* Inspect texture */
3656 Texture::GetData(gl, GL_TEXTURE_2D, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
3657 if (0 != memcmp(texture_data + pixel_offset, &expected_pixel, pixel_size))
3658 {
3659 test_result = false;
3660
3661 m_context.getTestContext().getLog() << tcu::TestLog::Message
3662 << "Contents of framebuffer does not correspond with expected results"
3663 << tcu::TestLog::EndMessage;
3664 tcu::ConstPixelBufferAccess img(
3665 tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), width, height,
3666 1 /* depth */, texture_data);
3667 m_context.getTestContext().getLog()
3668 << tcu::TestLog::Image("Framebuffer", "Framebuffer contents using updated buffer data", img);
3669 }
3670
3671 /* Inspect atom */
3672 if (0 != memcmp(atom_map.m_data, &expected_atom_second, sizeof(GLuint)))
3673 {
3674 test_result = false;
3675
3676 m_context.getTestContext().getLog() << tcu::TestLog::Message
3677 << "Contents of ATOMIC_COUNTER buffer are invalid."
3678 << tcu::TestLog::EndMessage;
3679 }
3680 }
3681
3682 /* Set result */
3683 if (true == test_result)
3684 {
3685 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3686 }
3687 else
3688 {
3689 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3690 }
3691
3692 /* Done */
3693 return tcu::TestNode::STOP;
3694 }
3695 } /* BufferStorage */
3696
3697 /** Constructor.
3698 *
3699 * @param context Rendering context.
3700 **/
BufferStorageTests(deqp::Context & context)3701 BufferStorageTests::BufferStorageTests(deqp::Context& context)
3702 : TestCaseGroup(context, "buffer_storage", "Verifies \"buffer storage\" functionality")
3703 {
3704 /* Left blank on purpose */
3705 }
3706
3707 /** Initializes a texture_storage_multisample test group.
3708 *
3709 **/
init(void)3710 void BufferStorageTests::init(void)
3711 {
3712 addChild(new BufferStorage::ErrorsTest(m_context));
3713 addChild(new BufferStorage::GetBufferParameterTest(m_context));
3714 addChild(new BufferStorage::DynamicStorageTest(m_context));
3715 addChild(new BufferStorage::MapPersistentBufferSubDataTest(m_context));
3716 addChild(new BufferStorage::MapPersistentTextureTest(m_context));
3717 addChild(new BufferStorage::MapPersistentReadPixelsTest(m_context));
3718 addChild(new BufferStorage::MapPersistentDispatchTest(m_context));
3719 addChild(new BufferStorage::MapPersistentFlushTest(m_context));
3720 addChild(new BufferStorage::MapPersistentDrawTest(m_context));
3721 }
3722 } /* gl4cts namespace */
3723