1e5c31af7Sopenharmony_ci#ifndef _GL4CSPARSEBUFFERTESTS_HPP
2e5c31af7Sopenharmony_ci#define _GL4CSPARSEBUFFERTESTS_HPP
3e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
4e5c31af7Sopenharmony_ci * OpenGL Conformance Test Suite
5e5c31af7Sopenharmony_ci * -----------------------------
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Copyright (c) 2015-2016 The Khronos Group Inc.
8e5c31af7Sopenharmony_ci *
9e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
10e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
11e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
14e5c31af7Sopenharmony_ci *
15e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
16e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
17e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
19e5c31af7Sopenharmony_ci * limitations under the License.
20e5c31af7Sopenharmony_ci *
21e5c31af7Sopenharmony_ci */ /*!
22e5c31af7Sopenharmony_ci * \file
23e5c31af7Sopenharmony_ci * \brief
24e5c31af7Sopenharmony_ci */ /*-------------------------------------------------------------------*/
25e5c31af7Sopenharmony_ci
26e5c31af7Sopenharmony_ci/**
27e5c31af7Sopenharmony_ci */ /*!
28e5c31af7Sopenharmony_ci * \file  gl4cSparseBufferTests.hpp
29e5c31af7Sopenharmony_ci * \brief Conformance tests for the GL_ARB_sparse_buffer functionality.
30e5c31af7Sopenharmony_ci */ /*-------------------------------------------------------------------*/
31e5c31af7Sopenharmony_ci#include "glcTestCase.hpp"
32e5c31af7Sopenharmony_ci#include "glwDefs.hpp"
33e5c31af7Sopenharmony_ci#include "glwEnums.hpp"
34e5c31af7Sopenharmony_ci#include "tcuDefs.hpp"
35e5c31af7Sopenharmony_ci#include <vector>
36e5c31af7Sopenharmony_ci
37e5c31af7Sopenharmony_cinamespace gl4cts
38e5c31af7Sopenharmony_ci{
39e5c31af7Sopenharmony_ci/** Utility functions, used across many sparse buffer conformance test classes. */
40e5c31af7Sopenharmony_ciclass SparseBufferTestUtilities
41e5c31af7Sopenharmony_ci{
42e5c31af7Sopenharmony_cipublic:
43e5c31af7Sopenharmony_ci	/* Public methods */
44e5c31af7Sopenharmony_ci	static unsigned int alignOffset(const unsigned int& offset, const unsigned int& value);
45e5c31af7Sopenharmony_ci
46e5c31af7Sopenharmony_ci	static glw::GLuint createComputeProgram(const glw::Functions& gl, const char** cs_body_parts,
47e5c31af7Sopenharmony_ci											unsigned int n_cs_body_parts);
48e5c31af7Sopenharmony_ci
49e5c31af7Sopenharmony_ci	static glw::GLuint createProgram(const glw::Functions& gl, const char** fs_body_parts, unsigned int n_fs_body_parts,
50e5c31af7Sopenharmony_ci									 const char** vs_body_parts, unsigned int n_vs_body_parts,
51e5c31af7Sopenharmony_ci									 const char** attribute_names, const unsigned int* attribute_locations,
52e5c31af7Sopenharmony_ci									 unsigned int			   n_attribute_properties,
53e5c31af7Sopenharmony_ci									 const glw::GLchar* const* tf_varyings = DE_NULL, unsigned int n_tf_varyings = 0,
54e5c31af7Sopenharmony_ci									 glw::GLenum tf_varying_mode = GL_NONE);
55e5c31af7Sopenharmony_ci
56e5c31af7Sopenharmony_ci	static std::string getSparseBOFlagsString(glw::GLenum flags);
57e5c31af7Sopenharmony_ci};
58e5c31af7Sopenharmony_ci
59e5c31af7Sopenharmony_ci/** * Verify glBufferPageCommitmentARB() returns GL_INVALID_ENUM if <target> is
60e5c31af7Sopenharmony_ci *    set to GL_INTERLEAVED_ATTRIBS.
61e5c31af7Sopenharmony_ci *
62e5c31af7Sopenharmony_ci *  * Verify glBufferStorage() throws a GL_INVALID_VALUE error if <flags> is
63e5c31af7Sopenharmony_ci *    set to (GL_SPARSE_STORAGE_BIT_ARB | GL_MAP_READ_BIT) or
64e5c31af7Sopenharmony_ci *    (GL_SPARSE_STORAGE_BIT_ARB | GL_MAP_WRITE_BIT).
65e5c31af7Sopenharmony_ci *
66e5c31af7Sopenharmony_ci *  * Verify glBufferPageCommitmentARB() generates a GL_INVALID_OPERATION error if
67e5c31af7Sopenharmony_ci *    it is called for an immutable BO, which has not been initialized with the
68e5c31af7Sopenharmony_ci *    GL_SPARSE_STORAGE_BIT_ARB flag.
69e5c31af7Sopenharmony_ci *
70e5c31af7Sopenharmony_ci *  * Verify glBufferPageCommitmentARB() issues a GL_INVALID_VALUE error if <offset>
71e5c31af7Sopenharmony_ci *    is set to (0.5 * GL_SPARSE_BUFFER_PAGE_SIZE_ARB). Skip if the constant's value
72e5c31af7Sopenharmony_ci *    is equal to 1.
73e5c31af7Sopenharmony_ci *
74e5c31af7Sopenharmony_ci *  * Verify glBufferPageCommitmentARB() emits a GL_INVALID_VALUE error if <size>
75e5c31af7Sopenharmony_ci *    is set to (0.5 * GL_SPARSE_BUFFER_PAGE_SIZE_ARB). Skip if the constant's value
76e5c31af7Sopenharmony_ci *    is equal to 1.
77e5c31af7Sopenharmony_ci *
78e5c31af7Sopenharmony_ci *  * Verify glBufferPageCommitmentARB() returns GL_INVALID_VALUE if <offset> is
79e5c31af7Sopenharmony_ci *    set to -1, but all other arguments are valid.
80e5c31af7Sopenharmony_ci *
81e5c31af7Sopenharmony_ci *  * Verify glBufferPageCommitmentARB() returns GL_INVALID_VALUE if <size> is
82e5c31af7Sopenharmony_ci *    set to -1, but all other arguments are valid.
83e5c31af7Sopenharmony_ci *
84e5c31af7Sopenharmony_ci *  * Verify glBufferPageCommitmentARB() returns GL_INVALID_VALUE if BO's size is
85e5c31af7Sopenharmony_ci *    GL_SPARSE_BUFFER_PAGE_SIZE_ARB * 3, but the <offset> is set to 0 and <size>
86e5c31af7Sopenharmony_ci *    argument used for the call is set to GL_SPARSE_BUFFER_PAGE_SIZE_ARB * 4.
87e5c31af7Sopenharmony_ci *
88e5c31af7Sopenharmony_ci *  * Verify glBufferPageCommitmentARB() returns GL_INVALID_VALUE if BO's size is
89e5c31af7Sopenharmony_ci *    GL_SPARSE_BUFFER_PAGE_SIZE_ARB * 3, but the <offset> is set to
90e5c31af7Sopenharmony_ci *    GL_SPARSE_BUFFER_PAGE_SIZE_ARB * 1 and <size> argument used for the call
91e5c31af7Sopenharmony_ci *    is set to GL_SPARSE_BUFFER_PAGE_SIZE_ARB * 3.
92e5c31af7Sopenharmony_ci *
93e5c31af7Sopenharmony_ci *  * Verify that calling glMapBuffer() or glMapBufferRange() against a sparse
94e5c31af7Sopenharmony_ci *    buffer generates a GL_INVALID_OPERATION error.
95e5c31af7Sopenharmony_ci **/
96e5c31af7Sopenharmony_ciclass NegativeTests : public deqp::TestCase
97e5c31af7Sopenharmony_ci{
98e5c31af7Sopenharmony_cipublic:
99e5c31af7Sopenharmony_ci	/* Public methods */
100e5c31af7Sopenharmony_ci	NegativeTests(deqp::Context& context);
101e5c31af7Sopenharmony_ci
102e5c31af7Sopenharmony_ci	void						 deinit();
103e5c31af7Sopenharmony_ci	void						 init();
104e5c31af7Sopenharmony_ci	tcu::TestNode::IterateResult iterate();
105e5c31af7Sopenharmony_ci
106e5c31af7Sopenharmony_ciprivate:
107e5c31af7Sopenharmony_ci	/* Private methods */
108e5c31af7Sopenharmony_ci
109e5c31af7Sopenharmony_ci	/* Private members */
110e5c31af7Sopenharmony_ci	glw::GLuint		   m_helper_bo_id;	/* never allocated actual storage; bound to GL_ELEMENT_ARRAY_BUFFER */
111e5c31af7Sopenharmony_ci	glw::GLuint		   m_immutable_bo_id; /* bound to GL_COPY_READ_BUFFER */
112e5c31af7Sopenharmony_ci	const unsigned int m_immutable_bo_size;
113e5c31af7Sopenharmony_ci
114e5c31af7Sopenharmony_ci	glw::GLuint m_sparse_bo_id; /* bound to GL_ARRAY_BUFFER */
115e5c31af7Sopenharmony_ci};
116e5c31af7Sopenharmony_ci
117e5c31af7Sopenharmony_ci/** 1. Make sure glGetBooleanv(), glGetDoublev(), glGetFloatv(), glGetIntegerv()
118e5c31af7Sopenharmony_ci *     and glGetInteger64v() recognize the new GL_SPARSE_BUFFER_PAGE_SIZE_ARB
119e5c31af7Sopenharmony_ci *     pname and return a value equal to or larger than 1, but no bigger than 65536
120e5c31af7Sopenharmony_ci */
121e5c31af7Sopenharmony_ciclass PageSizeGetterTest : public deqp::TestCase
122e5c31af7Sopenharmony_ci{
123e5c31af7Sopenharmony_cipublic:
124e5c31af7Sopenharmony_ci	/* Public methods */
125e5c31af7Sopenharmony_ci	PageSizeGetterTest(deqp::Context& context);
126e5c31af7Sopenharmony_ci
127e5c31af7Sopenharmony_ci	void						 deinit();
128e5c31af7Sopenharmony_ci	void						 init();
129e5c31af7Sopenharmony_ci	tcu::TestNode::IterateResult iterate();
130e5c31af7Sopenharmony_ci};
131e5c31af7Sopenharmony_ci
132e5c31af7Sopenharmony_ci/** Interface class for test case implementation for the functional test 2. */
133e5c31af7Sopenharmony_ciclass BufferStorageTestCase
134e5c31af7Sopenharmony_ci{
135e5c31af7Sopenharmony_cipublic:
136e5c31af7Sopenharmony_ci	virtual ~BufferStorageTestCase()
137e5c31af7Sopenharmony_ci	{
138e5c31af7Sopenharmony_ci	}
139e5c31af7Sopenharmony_ci
140e5c31af7Sopenharmony_ci	/* Public methods */
141e5c31af7Sopenharmony_ci	virtual void deinitTestCaseGlobal()						  = 0;
142e5c31af7Sopenharmony_ci	virtual bool execute(glw::GLuint sparse_bo_storage_flags) = 0;
143e5c31af7Sopenharmony_ci	virtual const char* getName()							  = 0;
144e5c31af7Sopenharmony_ci	virtual bool		initTestCaseGlobal()				  = 0;
145e5c31af7Sopenharmony_ci	virtual bool initTestCaseIteration(glw::GLuint sparse_bo) = 0;
146e5c31af7Sopenharmony_ci
147e5c31af7Sopenharmony_ci	virtual void deinitTestCaseIteration()
148e5c31af7Sopenharmony_ci	{
149e5c31af7Sopenharmony_ci		/* Stub by default */
150e5c31af7Sopenharmony_ci	}
151e5c31af7Sopenharmony_ci};
152e5c31af7Sopenharmony_ci
153e5c31af7Sopenharmony_ci/** Implements the test case e for the test 2:
154e5c31af7Sopenharmony_ci *
155e5c31af7Sopenharmony_ci * e.  Use the committed sparse buffer storage to store atomic counter values.
156e5c31af7Sopenharmony_ci *     The vertex shader used for the test case should define as many ACs as
157e5c31af7Sopenharmony_ci *     supported by the platform (GL_MAX_VERTEX_ATOMIC_COUNTERS). The condition,
158e5c31af7Sopenharmony_ci *     under which each of the ACs should be incremented, can be based on
159e5c31af7Sopenharmony_ci *     gl_VertexID's value (eg. increment AC0 if gl_VertexID % 2 == 0, increment
160e5c31af7Sopenharmony_ci *     AC1 if gl_VertexID % 3 == 0, and so on).
161e5c31af7Sopenharmony_ci *
162e5c31af7Sopenharmony_ci *     Use regular draw calls, issued consecutively for three times, for the
163e5c31af7Sopenharmony_ci *     test.
164e5c31af7Sopenharmony_ci *     Verify that both atomic counter buffer binding commands (glBindBufferBase()
165e5c31af7Sopenharmony_ci *     and glBindBufferRange() ) work correctly.
166e5c31af7Sopenharmony_ci *
167e5c31af7Sopenharmony_ci *     The test passes if the result values are correct.
168e5c31af7Sopenharmony_ci *
169e5c31af7Sopenharmony_ci *     The test should run in two iterations:
170e5c31af7Sopenharmony_ci *     a) All required pages are committed.
171e5c31af7Sopenharmony_ci *     b) Only half of the pages are committed. If only a single page is needed,
172e5c31af7Sopenharmony_ci *        de-commit that page before issuing the draw call.
173e5c31af7Sopenharmony_ci */
174e5c31af7Sopenharmony_ciclass AtomicCounterBufferStorageTestCase : public BufferStorageTestCase
175e5c31af7Sopenharmony_ci{
176e5c31af7Sopenharmony_cipublic:
177e5c31af7Sopenharmony_ci	/* Public methods */
178e5c31af7Sopenharmony_ci	AtomicCounterBufferStorageTestCase(const glw::Functions& gl, tcu::TestContext& testContext, glw::GLint page_size,
179e5c31af7Sopenharmony_ci									   bool all_pages_committed);
180e5c31af7Sopenharmony_ci
181e5c31af7Sopenharmony_ci	/* BufferStorageTestCase implementation */
182e5c31af7Sopenharmony_ci	void deinitTestCaseGlobal();
183e5c31af7Sopenharmony_ci	void deinitTestCaseIteration();
184e5c31af7Sopenharmony_ci
185e5c31af7Sopenharmony_ci	bool execute(glw::GLuint sparse_bo_storage_flags);
186e5c31af7Sopenharmony_ci	bool initTestCaseGlobal();
187e5c31af7Sopenharmony_ci	bool initTestCaseIteration(glw::GLuint sparse_bo);
188e5c31af7Sopenharmony_ci
189e5c31af7Sopenharmony_ci	const char* getName()
190e5c31af7Sopenharmony_ci	{
191e5c31af7Sopenharmony_ci		return "case e";
192e5c31af7Sopenharmony_ci	}
193e5c31af7Sopenharmony_ci
194e5c31af7Sopenharmony_ciprivate:
195e5c31af7Sopenharmony_ci	/* Private fields */
196e5c31af7Sopenharmony_ci	bool				  m_all_pages_committed;
197e5c31af7Sopenharmony_ci	const glw::Functions& m_gl;
198e5c31af7Sopenharmony_ci	glw::GLint			  m_gl_atomic_counter_uniform_array_stride;
199e5c31af7Sopenharmony_ci	glw::GLint			  m_gl_max_vertex_atomic_counters_value;
200e5c31af7Sopenharmony_ci	glw::GLuint			  m_helper_bo;
201e5c31af7Sopenharmony_ci	unsigned int		  m_helper_bo_size;
202e5c31af7Sopenharmony_ci	unsigned int		  m_helper_bo_size_rounded;
203e5c31af7Sopenharmony_ci	const unsigned int	m_n_draw_calls;
204e5c31af7Sopenharmony_ci	glw::GLint			  m_page_size;
205e5c31af7Sopenharmony_ci	glw::GLuint			  m_po;
206e5c31af7Sopenharmony_ci	glw::GLuint			  m_sparse_bo;
207e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_data_size;
208e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_data_size_rounded; /* aligned to page size */
209e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_data_start_offset;
210e5c31af7Sopenharmony_ci	unsigned int m_sparse_bo_data_start_offset_rounded; /* <= m_sparse_bo_data_start_offset, aligned to page size */
211e5c31af7Sopenharmony_ci	tcu::TestContext& m_testCtx;
212e5c31af7Sopenharmony_ci	glw::GLuint		  m_vao;
213e5c31af7Sopenharmony_ci};
214e5c31af7Sopenharmony_ci
215e5c31af7Sopenharmony_ci/** Implements the test case f for the test 2:
216e5c31af7Sopenharmony_ci *
217e5c31af7Sopenharmony_ci * f.  Use the committed sparse buffer storage as a backing for a buffer texture
218e5c31af7Sopenharmony_ci *     object. A compute shader should inspect the contents of the texture and,
219e5c31af7Sopenharmony_ci *     for invocation-specific texels, write out 1 to a SSBO if the fetched texel
220e5c31af7Sopenharmony_ci *     was correct. Otherwise, it should write out 0.
221e5c31af7Sopenharmony_ci *
222e5c31af7Sopenharmony_ci *     The shader storage block needs not be backed by a sparse buffer.
223e5c31af7Sopenharmony_ci *
224e5c31af7Sopenharmony_ci *     As with previous cases, make sure both of the following scenarios are
225e5c31af7Sopenharmony_ci *     tested:
226e5c31af7Sopenharmony_ci *
227e5c31af7Sopenharmony_ci *     a) All required pages are committed.
228e5c31af7Sopenharmony_ci *     b) Only half of the pages are committed. If only a single page is needed,
229e5c31af7Sopenharmony_ci *        de-commit that page before issuing the dispatch call.
230e5c31af7Sopenharmony_ci *
231e5c31af7Sopenharmony_ci *     Both glTexBuffer() and glTexBufferRange() should be tested.
232e5c31af7Sopenharmony_ci *
233e5c31af7Sopenharmony_ci */
234e5c31af7Sopenharmony_ciclass BufferTextureStorageTestCase : public BufferStorageTestCase
235e5c31af7Sopenharmony_ci{
236e5c31af7Sopenharmony_cipublic:
237e5c31af7Sopenharmony_ci	/* Public methods */
238e5c31af7Sopenharmony_ci	BufferTextureStorageTestCase(const glw::Functions& gl, deqp::Context& context, tcu::TestContext& testContext,
239e5c31af7Sopenharmony_ci								 glw::GLint page_size);
240e5c31af7Sopenharmony_ci
241e5c31af7Sopenharmony_ci	/* BufferStorageTestCase implementation */
242e5c31af7Sopenharmony_ci	void deinitTestCaseGlobal();
243e5c31af7Sopenharmony_ci	void deinitTestCaseIteration();
244e5c31af7Sopenharmony_ci	bool execute(glw::GLuint sparse_bo_storage_flags);
245e5c31af7Sopenharmony_ci	bool initTestCaseGlobal();
246e5c31af7Sopenharmony_ci	bool initTestCaseIteration(glw::GLuint sparse_bo);
247e5c31af7Sopenharmony_ci
248e5c31af7Sopenharmony_ci	const char* getName()
249e5c31af7Sopenharmony_ci	{
250e5c31af7Sopenharmony_ci		return "case f";
251e5c31af7Sopenharmony_ci	}
252e5c31af7Sopenharmony_ci
253e5c31af7Sopenharmony_ciprivate:
254e5c31af7Sopenharmony_ci	/* Private fields */
255e5c31af7Sopenharmony_ci	const glw::Functions& m_gl;
256e5c31af7Sopenharmony_ci	glw::GLuint			  m_helper_bo;
257e5c31af7Sopenharmony_ci	unsigned char*		  m_helper_bo_data;
258e5c31af7Sopenharmony_ci	unsigned int		  m_helper_bo_data_size;
259e5c31af7Sopenharmony_ci	bool				  m_is_texture_buffer_range_supported;
260e5c31af7Sopenharmony_ci	glw::GLint			  m_page_size;
261e5c31af7Sopenharmony_ci	glw::GLuint			  m_po;
262e5c31af7Sopenharmony_ci	const unsigned int	m_po_local_wg_size;
263e5c31af7Sopenharmony_ci	glw::GLuint			  m_sparse_bo;
264e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_size;
265e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_size_rounded;
266e5c31af7Sopenharmony_ci	glw::GLuint			  m_ssbo;
267e5c31af7Sopenharmony_ci	unsigned char*		  m_ssbo_zero_data;
268e5c31af7Sopenharmony_ci	unsigned int		  m_ssbo_zero_data_size;
269e5c31af7Sopenharmony_ci	tcu::TestContext&	 m_testCtx;
270e5c31af7Sopenharmony_ci	glw::GLuint			  m_to;
271e5c31af7Sopenharmony_ci	const unsigned int	m_to_width;
272e5c31af7Sopenharmony_ci};
273e5c31af7Sopenharmony_ci
274e5c31af7Sopenharmony_ci/** Implements the test case c for the test 2:
275e5c31af7Sopenharmony_ci *
276e5c31af7Sopenharmony_ci * c.  Issue glClearBufferData() and glClearBufferSubData() calls
277e5c31af7Sopenharmony_ci *     over a sparse buffer. Make sure that all committed pages, which should
278e5c31af7Sopenharmony_ci *     have been affected by the calls, have been reset to the requested
279e5c31af7Sopenharmony_ci *     values.
280e5c31af7Sopenharmony_ci *     Try issuing glClearNamedBufferSubData() over a region, for which one
281e5c31af7Sopenharmony_ci *     of the halves is committed, and the other is not. Make sure the former
282e5c31af7Sopenharmony_ci *     has been touched, and that no crash has occurred.
283e5c31af7Sopenharmony_ci *
284e5c31af7Sopenharmony_ci */
285e5c31af7Sopenharmony_ciclass ClearOpsBufferStorageTestCase : public BufferStorageTestCase
286e5c31af7Sopenharmony_ci{
287e5c31af7Sopenharmony_cipublic:
288e5c31af7Sopenharmony_ci	/* Public methods */
289e5c31af7Sopenharmony_ci	ClearOpsBufferStorageTestCase(const glw::Functions& gl, tcu::TestContext& testContext, glw::GLint page_size);
290e5c31af7Sopenharmony_ci
291e5c31af7Sopenharmony_ci	/* BufferStorageTestCase implementation */
292e5c31af7Sopenharmony_ci	void deinitTestCaseGlobal();
293e5c31af7Sopenharmony_ci	void deinitTestCaseIteration();
294e5c31af7Sopenharmony_ci	bool execute(glw::GLuint sparse_bo_storage_flags);
295e5c31af7Sopenharmony_ci	bool initTestCaseGlobal();
296e5c31af7Sopenharmony_ci	bool initTestCaseIteration(glw::GLuint sparse_bo);
297e5c31af7Sopenharmony_ci
298e5c31af7Sopenharmony_ci	const char* getName()
299e5c31af7Sopenharmony_ci	{
300e5c31af7Sopenharmony_ci		return "case c";
301e5c31af7Sopenharmony_ci	}
302e5c31af7Sopenharmony_ci
303e5c31af7Sopenharmony_ciprivate:
304e5c31af7Sopenharmony_ci	/* Private fields */
305e5c31af7Sopenharmony_ci	const glw::Functions& m_gl;
306e5c31af7Sopenharmony_ci	glw::GLuint			  m_helper_bo;	/* holds m_sparse_bo_size_rounded bytes */
307e5c31af7Sopenharmony_ci	unsigned char*		  m_initial_data; /* holds m_sparse_bo_size_rounded bytes */
308e5c31af7Sopenharmony_ci	unsigned int		  m_n_pages_to_use;
309e5c31af7Sopenharmony_ci	glw::GLint			  m_page_size;
310e5c31af7Sopenharmony_ci	glw::GLuint			  m_sparse_bo;
311e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_size_rounded;
312e5c31af7Sopenharmony_ci	tcu::TestContext&	 m_testCtx;
313e5c31af7Sopenharmony_ci};
314e5c31af7Sopenharmony_ci
315e5c31af7Sopenharmony_ci/** Implements the test case g for the test 2:
316e5c31af7Sopenharmony_ci *
317e5c31af7Sopenharmony_ci * g.  Verify copy operations work correctly for cases where:
318e5c31af7Sopenharmony_ci *
319e5c31af7Sopenharmony_ci *     I)   Destination and source are different sparse BOs.
320e5c31af7Sopenharmony_ci *     II)  Destination is a sparse buffer object, source is an immutable BO.
321e5c31af7Sopenharmony_ci *     III) Destination is an immutable BO, source is a sparse BO.
322e5c31af7Sopenharmony_ci *     IV)  Destination and source are the same sparse BO, but refer to
323e5c31af7Sopenharmony_ci *          different, non-overlapping memory regions.
324e5c31af7Sopenharmony_ci *
325e5c31af7Sopenharmony_ci *     and
326e5c31af7Sopenharmony_ci *
327e5c31af7Sopenharmony_ci *     *)   All pages of the source region are not committed
328e5c31af7Sopenharmony_ci *     **)  Half of the pages of the source region is not committed
329e5c31af7Sopenharmony_ci *     ***) None of the pages of the source region are committed.
330e5c31af7Sopenharmony_ci *
331e5c31af7Sopenharmony_ci *     and
332e5c31af7Sopenharmony_ci *
333e5c31af7Sopenharmony_ci *     +)   All pages of the destination region are not committed
334e5c31af7Sopenharmony_ci *     ++)  Half of the pages of the destination region is not committed
335e5c31af7Sopenharmony_ci *     +++) None of the pages of the destination region are committed.
336e5c31af7Sopenharmony_ci *
337e5c31af7Sopenharmony_ci *     Test all combinations of I-IV, *-***, and +-+++ bearing in mind that:
338e5c31af7Sopenharmony_ci *
339e5c31af7Sopenharmony_ci *     a) reads executed on non-committed memory regions return meaningless
340e5c31af7Sopenharmony_ci *        values but MUST NOT crash GL
341e5c31af7Sopenharmony_ci *     b) writes performed on non-committed memory regions are silently
342e5c31af7Sopenharmony_ci *        ignored.
343e5c31af7Sopenharmony_ci */
344e5c31af7Sopenharmony_ciclass CopyOpsBufferStorageTestCase : public BufferStorageTestCase
345e5c31af7Sopenharmony_ci{
346e5c31af7Sopenharmony_cipublic:
347e5c31af7Sopenharmony_ci	/* Public methods */
348e5c31af7Sopenharmony_ci	CopyOpsBufferStorageTestCase(const glw::Functions& gl, tcu::TestContext& testContext, glw::GLint page_size);
349e5c31af7Sopenharmony_ci
350e5c31af7Sopenharmony_ci	/* BufferStorageTestCase implementation */
351e5c31af7Sopenharmony_ci	void deinitTestCaseGlobal();
352e5c31af7Sopenharmony_ci	void deinitTestCaseIteration();
353e5c31af7Sopenharmony_ci	bool execute(glw::GLuint sparse_bo_storage_flags);
354e5c31af7Sopenharmony_ci	bool initTestCaseGlobal();
355e5c31af7Sopenharmony_ci	bool initTestCaseIteration(glw::GLuint sparse_bo);
356e5c31af7Sopenharmony_ci
357e5c31af7Sopenharmony_ci	const char* getName()
358e5c31af7Sopenharmony_ci	{
359e5c31af7Sopenharmony_ci		return "case g";
360e5c31af7Sopenharmony_ci	}
361e5c31af7Sopenharmony_ci
362e5c31af7Sopenharmony_ciprivate:
363e5c31af7Sopenharmony_ci	/* Private type definitions */
364e5c31af7Sopenharmony_ci	typedef struct _test_case
365e5c31af7Sopenharmony_ci	{
366e5c31af7Sopenharmony_ci		glw::GLint		dst_bo_commit_size;
367e5c31af7Sopenharmony_ci		glw::GLint		dst_bo_commit_start_offset;
368e5c31af7Sopenharmony_ci		glw::GLuint		dst_bo_sparse_id;
369e5c31af7Sopenharmony_ci		bool			dst_bo_is_sparse;
370e5c31af7Sopenharmony_ci		unsigned short* dst_bo_ref_data;
371e5c31af7Sopenharmony_ci		glw::GLint		dst_bo_start_offset;
372e5c31af7Sopenharmony_ci
373e5c31af7Sopenharmony_ci		glw::GLint n_bytes_to_copy;
374e5c31af7Sopenharmony_ci
375e5c31af7Sopenharmony_ci		glw::GLint		src_bo_commit_size;
376e5c31af7Sopenharmony_ci		glw::GLint		src_bo_commit_start_offset;
377e5c31af7Sopenharmony_ci		glw::GLuint		src_bo_sparse_id;
378e5c31af7Sopenharmony_ci		bool			src_bo_is_sparse;
379e5c31af7Sopenharmony_ci		unsigned short* src_bo_ref_data;
380e5c31af7Sopenharmony_ci		glw::GLint		src_bo_start_offset;
381e5c31af7Sopenharmony_ci	} _test_case;
382e5c31af7Sopenharmony_ci
383e5c31af7Sopenharmony_ci	typedef std::vector<_test_case>		_test_cases;
384e5c31af7Sopenharmony_ci	typedef _test_cases::const_iterator _test_cases_const_iterator;
385e5c31af7Sopenharmony_ci	typedef _test_cases::iterator		_test_cases_iterator;
386e5c31af7Sopenharmony_ci
387e5c31af7Sopenharmony_ci	/* Private methods */
388e5c31af7Sopenharmony_ci	void initReferenceData();
389e5c31af7Sopenharmony_ci	void initTestCases();
390e5c31af7Sopenharmony_ci
391e5c31af7Sopenharmony_ci	/* Private fields */
392e5c31af7Sopenharmony_ci	const glw::Functions& m_gl;
393e5c31af7Sopenharmony_ci	glw::GLuint			  m_helper_bo;
394e5c31af7Sopenharmony_ci	glw::GLuint			  m_immutable_bo;
395e5c31af7Sopenharmony_ci	glw::GLint			  m_page_size;
396e5c31af7Sopenharmony_ci	unsigned short*		  m_ref_data[3];   /* [0] - immutable bo data, [1] - sparse bo[0] data, [2] - sparse bo[1] data.
397e5c31af7Sopenharmony_ci	 *
398e5c31af7Sopenharmony_ci	 * Each data buffer holds m_sparse_bo_size_rounded bytes.
399e5c31af7Sopenharmony_ci	 */
400e5c31af7Sopenharmony_ci	glw::GLuint			  m_sparse_bos[2]; /* [0] - provided by BufferStorageTest[0], [1] - managed by the test case */
401e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_size;
402e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_size_rounded;
403e5c31af7Sopenharmony_ci	_test_cases			  m_test_cases;
404e5c31af7Sopenharmony_ci	tcu::TestContext&	 m_testCtx;
405e5c31af7Sopenharmony_ci};
406e5c31af7Sopenharmony_ci
407e5c31af7Sopenharmony_ci/** Implements the test case h for the test 2:
408e5c31af7Sopenharmony_ci *
409e5c31af7Sopenharmony_ci *  h.  Verify indirect dispatch calls work correctly for the following cases:
410e5c31af7Sopenharmony_ci *
411e5c31af7Sopenharmony_ci *  a) The arguments are taken from a committed memory page.
412e5c31af7Sopenharmony_ci *  b) The arguments are taken from a de-committed memory page. We expect
413e5c31af7Sopenharmony_ci *     the dispatch request to be silently ignored in this case.
414e5c31af7Sopenharmony_ci *  c) Half of the arguments are taken from a committed memory page,
415e5c31af7Sopenharmony_ci *     and the other half come from a de-committed memory page. Anticipated
416e5c31af7Sopenharmony_ci *     result is as per b).
417e5c31af7Sopenharmony_ci *
418e5c31af7Sopenharmony_ci *  Each spawned compute shader invocation should increment an atomic
419e5c31af7Sopenharmony_ci *  counter.
420e5c31af7Sopenharmony_ci *
421e5c31af7Sopenharmony_ci */
422e5c31af7Sopenharmony_ciclass IndirectDispatchBufferStorageTestCase : public BufferStorageTestCase
423e5c31af7Sopenharmony_ci{
424e5c31af7Sopenharmony_cipublic:
425e5c31af7Sopenharmony_ci	/* Public methods */
426e5c31af7Sopenharmony_ci	IndirectDispatchBufferStorageTestCase(const glw::Functions& gl, tcu::TestContext& testContext,
427e5c31af7Sopenharmony_ci										  glw::GLint page_size);
428e5c31af7Sopenharmony_ci
429e5c31af7Sopenharmony_ci	/* BufferStorageTestCase implementation */
430e5c31af7Sopenharmony_ci	void deinitTestCaseGlobal();
431e5c31af7Sopenharmony_ci	void deinitTestCaseIteration();
432e5c31af7Sopenharmony_ci	bool execute(glw::GLuint sparse_bo_storage_flags);
433e5c31af7Sopenharmony_ci	bool initTestCaseGlobal();
434e5c31af7Sopenharmony_ci	bool initTestCaseIteration(glw::GLuint sparse_bo);
435e5c31af7Sopenharmony_ci
436e5c31af7Sopenharmony_ci	const char* getName()
437e5c31af7Sopenharmony_ci	{
438e5c31af7Sopenharmony_ci		return "case h";
439e5c31af7Sopenharmony_ci	}
440e5c31af7Sopenharmony_ci
441e5c31af7Sopenharmony_ciprivate:
442e5c31af7Sopenharmony_ci	/* Private fields */
443e5c31af7Sopenharmony_ci	unsigned int		  m_dispatch_draw_call_args_start_offset;
444e5c31af7Sopenharmony_ci	unsigned int		  m_expected_ac_value;
445e5c31af7Sopenharmony_ci	const glw::Functions& m_gl;
446e5c31af7Sopenharmony_ci	const unsigned int	m_global_wg_size_x;
447e5c31af7Sopenharmony_ci	glw::GLuint			  m_helper_bo; /* stores AC value + indirect dispatch call args */
448e5c31af7Sopenharmony_ci	const unsigned int	m_local_wg_size_x;
449e5c31af7Sopenharmony_ci	glw::GLint			  m_page_size;
450e5c31af7Sopenharmony_ci	glw::GLuint			  m_po;
451e5c31af7Sopenharmony_ci	glw::GLuint			  m_sparse_bo;
452e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_size;
453e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_size_rounded;
454e5c31af7Sopenharmony_ci	tcu::TestContext&	 m_testCtx;
455e5c31af7Sopenharmony_ci};
456e5c31af7Sopenharmony_ci
457e5c31af7Sopenharmony_ci/** Implements the test case d for the test 2:
458e5c31af7Sopenharmony_ci *
459e5c31af7Sopenharmony_ci * d.  Issue glInvalidateBufferData() and glInvalidateBufferSubData() calls for
460e5c31af7Sopenharmony_ci *     sparse buffers. For the *SubData() case, make sure you test both of
461e5c31af7Sopenharmony_ci *     cases:
462e5c31af7Sopenharmony_ci *
463e5c31af7Sopenharmony_ci *     * the whole touched region has been committed
464e5c31af7Sopenharmony_ci *     * only half of the pages have physical backing.
465e5c31af7Sopenharmony_ci */
466e5c31af7Sopenharmony_ciclass InvalidateBufferStorageTestCase : public BufferStorageTestCase
467e5c31af7Sopenharmony_ci{
468e5c31af7Sopenharmony_cipublic:
469e5c31af7Sopenharmony_ci	/* Public methods */
470e5c31af7Sopenharmony_ci	InvalidateBufferStorageTestCase(const glw::Functions& gl, tcu::TestContext& testContext, glw::GLint page_size);
471e5c31af7Sopenharmony_ci
472e5c31af7Sopenharmony_ci	/* BufferStorageTestCase implementation */
473e5c31af7Sopenharmony_ci	void deinitTestCaseGlobal();
474e5c31af7Sopenharmony_ci	void deinitTestCaseIteration();
475e5c31af7Sopenharmony_ci	bool execute(glw::GLuint sparse_bo_storage_flags);
476e5c31af7Sopenharmony_ci	bool initTestCaseGlobal();
477e5c31af7Sopenharmony_ci	bool initTestCaseIteration(glw::GLuint sparse_bo);
478e5c31af7Sopenharmony_ci
479e5c31af7Sopenharmony_ci	const char* getName()
480e5c31af7Sopenharmony_ci	{
481e5c31af7Sopenharmony_ci		return "case d";
482e5c31af7Sopenharmony_ci	}
483e5c31af7Sopenharmony_ci
484e5c31af7Sopenharmony_ciprivate:
485e5c31af7Sopenharmony_ci	/* Private fields */
486e5c31af7Sopenharmony_ci	const glw::Functions& m_gl;
487e5c31af7Sopenharmony_ci	unsigned int		  m_n_pages_to_use;
488e5c31af7Sopenharmony_ci	const glw::GLint	  m_page_size;
489e5c31af7Sopenharmony_ci	glw::GLuint			  m_sparse_bo;
490e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_size;
491e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_size_rounded;
492e5c31af7Sopenharmony_ci};
493e5c31af7Sopenharmony_ci
494e5c31af7Sopenharmony_ci/** Implement the test case k from CTS_ARB_sparse_buffer:
495e5c31af7Sopenharmony_ci *
496e5c31af7Sopenharmony_ci *  k. Verify pixel pack functionality works correctly, when a sparse buffer
497e5c31af7Sopenharmony_ci *     is bound to the pixel pack buffer binding point. Render a black-to-white
498e5c31af7Sopenharmony_ci *     RGBA8 gradient and use glReadPixels() to read & verify the rendered
499e5c31af7Sopenharmony_ci *     data. The color attachment should be of 1024x1024 resolution.
500e5c31af7Sopenharmony_ci *
501e5c31af7Sopenharmony_ci *     Consider three scenarios:
502e5c31af7Sopenharmony_ci *
503e5c31af7Sopenharmony_ci *     a) All pages, to which the data is to be written to, have been committed.
504e5c31af7Sopenharmony_ci *     b) Use the same memory page commitment layout as proposed in b2. The
505e5c31af7Sopenharmony_ci *        committed pages should contain correct data. Contents the pages
506e5c31af7Sopenharmony_ci *        without the physical backing should not be verified.
507e5c31af7Sopenharmony_ci *     c) No pages have been committed. The draw & read call should not crash
508e5c31af7Sopenharmony_ci *        the driver, but the actual contents is of no relevance.
509e5c31af7Sopenharmony_ci *
510e5c31af7Sopenharmony_ci **/
511e5c31af7Sopenharmony_ciclass PixelPackBufferStorageTestCase : public BufferStorageTestCase
512e5c31af7Sopenharmony_ci{
513e5c31af7Sopenharmony_cipublic:
514e5c31af7Sopenharmony_ci	/* Public methods */
515e5c31af7Sopenharmony_ci	PixelPackBufferStorageTestCase(const glw::Functions& gl, tcu::TestContext& testContext, glw::GLint page_size);
516e5c31af7Sopenharmony_ci
517e5c31af7Sopenharmony_ci	/* BufferStorageTestCase implementation */
518e5c31af7Sopenharmony_ci	void deinitTestCaseGlobal();
519e5c31af7Sopenharmony_ci	void deinitTestCaseIteration();
520e5c31af7Sopenharmony_ci	bool execute(glw::GLuint sparse_bo_storage_flags);
521e5c31af7Sopenharmony_ci	bool initTestCaseGlobal();
522e5c31af7Sopenharmony_ci	bool initTestCaseIteration(glw::GLuint sparse_bo);
523e5c31af7Sopenharmony_ci
524e5c31af7Sopenharmony_ci	const char* getName()
525e5c31af7Sopenharmony_ci	{
526e5c31af7Sopenharmony_ci		return "case k";
527e5c31af7Sopenharmony_ci	}
528e5c31af7Sopenharmony_ci
529e5c31af7Sopenharmony_ciprivate:
530e5c31af7Sopenharmony_ci	/* Private fields */
531e5c31af7Sopenharmony_ci	glw::GLuint			  m_color_rb;
532e5c31af7Sopenharmony_ci	const unsigned int	m_color_rb_height;
533e5c31af7Sopenharmony_ci	const unsigned int	m_color_rb_width;
534e5c31af7Sopenharmony_ci	glw::GLuint			  m_fbo;
535e5c31af7Sopenharmony_ci	const glw::Functions& m_gl;
536e5c31af7Sopenharmony_ci	glw::GLuint			  m_helper_bo;
537e5c31af7Sopenharmony_ci	glw::GLint			  m_page_size;
538e5c31af7Sopenharmony_ci	glw::GLuint			  m_po;
539e5c31af7Sopenharmony_ci	unsigned char*		  m_ref_data_ptr;
540e5c31af7Sopenharmony_ci	unsigned int		  m_ref_data_size;
541e5c31af7Sopenharmony_ci	glw::GLuint			  m_sparse_bo;
542e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_size;
543e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_size_rounded;
544e5c31af7Sopenharmony_ci	tcu::TestContext&	 m_testCtx;
545e5c31af7Sopenharmony_ci	glw::GLuint			  m_vao;
546e5c31af7Sopenharmony_ci};
547e5c31af7Sopenharmony_ci
548e5c31af7Sopenharmony_ci/** Implements the test case l for the test 2:
549e5c31af7Sopenharmony_ci *
550e5c31af7Sopenharmony_ci * l. Verify pixel unpack functionality works correctly, when a sparse buffer
551e5c31af7Sopenharmony_ci *     is bound to the pixel unpack buffer binding point. Use a black-to-white
552e5c31af7Sopenharmony_ci *     gradient texture data for a glTexSubImage2D() call applied against an
553e5c31af7Sopenharmony_ci *     immutable texture object's base mip-map. Read back the data with
554e5c31af7Sopenharmony_ci *     a glGetTexImage() call and verify the contents is valid.
555e5c31af7Sopenharmony_ci *
556e5c31af7Sopenharmony_ci *     Consider three scenarios:
557e5c31af7Sopenharmony_ci *
558e5c31af7Sopenharmony_ci *     a) All pages, from which the texture data were read from, have been
559e5c31af7Sopenharmony_ci *        committed at the glTexSubImage2D() call time.
560e5c31af7Sopenharmony_ci *     b) Use the same memory page commitment layout as proposed in b2. The
561e5c31af7Sopenharmony_ci *        test should only check contents of the committed memory pages.
562e5c31af7Sopenharmony_ci *     c) No pages have been committed at the glTexSubImage2D() call time.
563e5c31af7Sopenharmony_ci *        The upload & getter calls should not crash, but the returned
564e5c31af7Sopenharmony_ci *        contents are irrelevant in this case.
565e5c31af7Sopenharmony_ci */
566e5c31af7Sopenharmony_ciclass PixelUnpackBufferStorageTestCase : public BufferStorageTestCase
567e5c31af7Sopenharmony_ci{
568e5c31af7Sopenharmony_cipublic:
569e5c31af7Sopenharmony_ci	/* Public methods */
570e5c31af7Sopenharmony_ci	PixelUnpackBufferStorageTestCase(const glw::Functions& gl, tcu::TestContext& testContext, glw::GLint page_size);
571e5c31af7Sopenharmony_ci
572e5c31af7Sopenharmony_ci	/* BufferStorageTestCase implementation */
573e5c31af7Sopenharmony_ci	void deinitTestCaseGlobal();
574e5c31af7Sopenharmony_ci	void deinitTestCaseIteration();
575e5c31af7Sopenharmony_ci	bool execute(glw::GLuint sparse_bo_storage_flags);
576e5c31af7Sopenharmony_ci	bool initTestCaseGlobal();
577e5c31af7Sopenharmony_ci	bool initTestCaseIteration(glw::GLuint sparse_bo);
578e5c31af7Sopenharmony_ci
579e5c31af7Sopenharmony_ci	const char* getName()
580e5c31af7Sopenharmony_ci	{
581e5c31af7Sopenharmony_ci		return "case l";
582e5c31af7Sopenharmony_ci	}
583e5c31af7Sopenharmony_ci
584e5c31af7Sopenharmony_ciprivate:
585e5c31af7Sopenharmony_ci	/* Private fields */
586e5c31af7Sopenharmony_ci	const glw::Functions& m_gl;
587e5c31af7Sopenharmony_ci	glw::GLuint			  m_helper_bo;
588e5c31af7Sopenharmony_ci	glw::GLint			  m_page_size;
589e5c31af7Sopenharmony_ci	unsigned char*		  m_read_data_ptr;
590e5c31af7Sopenharmony_ci	glw::GLuint			  m_sparse_bo;
591e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_size;
592e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_size_rounded;
593e5c31af7Sopenharmony_ci	tcu::TestContext&	 m_testCtx;
594e5c31af7Sopenharmony_ci	unsigned char*		  m_texture_data_ptr;
595e5c31af7Sopenharmony_ci	unsigned int		  m_texture_data_size;
596e5c31af7Sopenharmony_ci	glw::GLuint			  m_to;
597e5c31af7Sopenharmony_ci	unsigned char*		  m_to_data_zero;
598e5c31af7Sopenharmony_ci	const unsigned int	m_to_height;
599e5c31af7Sopenharmony_ci	const unsigned int	m_to_width;
600e5c31af7Sopenharmony_ci};
601e5c31af7Sopenharmony_ci
602e5c31af7Sopenharmony_ci/** Implements test cases a1-a6 for the test 2:
603e5c31af7Sopenharmony_ci *
604e5c31af7Sopenharmony_ci * a1. Use the sparse buffer as a VBO.
605e5c31af7Sopenharmony_ci *
606e5c31af7Sopenharmony_ci *     The render-target should be drawn a total of 100 x 100 green quads
607e5c31af7Sopenharmony_ci *     (built of triangles). Fill the buffer with vertex data (use four
608e5c31af7Sopenharmony_ci *     components, even though we need the rectangles to be rendered in
609e5c31af7Sopenharmony_ci *     screen space, in order to assure that the data-set spans across
610e5c31af7Sopenharmony_ci *     multiple pages by exceeding the maximum permitted page size of 64KB).
611e5c31af7Sopenharmony_ci *
612e5c31af7Sopenharmony_ci *     The quads should be 5px in width & height, and be separated from each
613e5c31af7Sopenharmony_ci *     other by a delta of 5px.
614e5c31af7Sopenharmony_ci *
615e5c31af7Sopenharmony_ci *     Render the quads to a render-target of 1024x1024 resolution.
616e5c31af7Sopenharmony_ci *
617e5c31af7Sopenharmony_ci *     All the pages, to which the vertex data has been submitted, should
618e5c31af7Sopenharmony_ci *     be committed. The test case passes if the rendered data is correct.
619e5c31af7Sopenharmony_ci *
620e5c31af7Sopenharmony_ci * a2. Follow the same approach as described for a1. However, this time,
621e5c31af7Sopenharmony_ci *     after the vertex data is uploaded, the test should de-commit all the
622e5c31af7Sopenharmony_ci *     pages and attempt to do the draw call.
623e5c31af7Sopenharmony_ci *
624e5c31af7Sopenharmony_ci *     The test passes if the GL implementation does not crash. Do not
625e5c31af7Sopenharmony_ci *     validate the rendered data.
626e5c31af7Sopenharmony_ci *
627e5c31af7Sopenharmony_ci * a3. Follow the same approach as described for a1. However, this time,
628e5c31af7Sopenharmony_ci *     make sure to also provide an IBO and issue an indexed draw call
629e5c31af7Sopenharmony_ci *     (both ranged and non-ranged). All required VBO and IBO pages should
630e5c31af7Sopenharmony_ci *     be committed.
631e5c31af7Sopenharmony_ci *
632e5c31af7Sopenharmony_ci *     The pass condition described in a1 is not changed.
633e5c31af7Sopenharmony_ci *
634e5c31af7Sopenharmony_ci * a4. Follow the same approach as described for a2. However, this time,
635e5c31af7Sopenharmony_ci *     after the vertex and index data is uploaded, the test should de-commit
636e5c31af7Sopenharmony_ci *     pages storing both IBO and VBO data. Both draw calls should be issued
637e5c31af7Sopenharmony_ci *     then.
638e5c31af7Sopenharmony_ci *
639e5c31af7Sopenharmony_ci *     The pass condition described in a2 is not changed.
640e5c31af7Sopenharmony_ci *
641e5c31af7Sopenharmony_ci * a5. Follow the same approach as described for a1. Apply the following
642e5c31af7Sopenharmony_ci *     change:
643e5c31af7Sopenharmony_ci *
644e5c31af7Sopenharmony_ci *     - Each rectangle should now be assigned a color, exposed to the VS
645e5c31af7Sopenharmony_ci *       via a Vertex Attribute Array. The color data should come from committed
646e5c31af7Sopenharmony_ci *       sparse buffer pages.
647e5c31af7Sopenharmony_ci *
648e5c31af7Sopenharmony_ci * a6. Follow the same approach as described for a5. Apply the following
649e5c31af7Sopenharmony_ci *     change:
650e5c31af7Sopenharmony_ci *
651e5c31af7Sopenharmony_ci *     - De-commit color data, after it has been uploaded. Try to execute the
652e5c31af7Sopenharmony_ci *       draw call.
653e5c31af7Sopenharmony_ci *
654e5c31af7Sopenharmony_ci *     The test passes if the GL implementation does not crash. Do not
655e5c31af7Sopenharmony_ci *     validate the rendered data.
656e5c31af7Sopenharmony_ci */
657e5c31af7Sopenharmony_ciclass QuadsBufferStorageTestCase : public BufferStorageTestCase
658e5c31af7Sopenharmony_ci{
659e5c31af7Sopenharmony_cipublic:
660e5c31af7Sopenharmony_ci	/* Type definitions */
661e5c31af7Sopenharmony_ci	enum _ibo_usage
662e5c31af7Sopenharmony_ci	{
663e5c31af7Sopenharmony_ci		/* Use glDrawArrays() for the draw call */
664e5c31af7Sopenharmony_ci		IBO_USAGE_NONE,
665e5c31af7Sopenharmony_ci		/* Use glDrawElements() for the draw call */
666e5c31af7Sopenharmony_ci		IBO_USAGE_INDEXED_DRAW_CALL,
667e5c31af7Sopenharmony_ci		/* Use glDrawRangeElements() for the draw call */
668e5c31af7Sopenharmony_ci		IBO_USAGE_INDEXED_RANGED_DRAW_CALL
669e5c31af7Sopenharmony_ci	};
670e5c31af7Sopenharmony_ci
671e5c31af7Sopenharmony_ci	/* Public methods */
672e5c31af7Sopenharmony_ci	QuadsBufferStorageTestCase(const glw::Functions& gl, tcu::TestContext& testContext, glw::GLint page_size,
673e5c31af7Sopenharmony_ci							   _ibo_usage ibo_usage, bool use_color_data);
674e5c31af7Sopenharmony_ci
675e5c31af7Sopenharmony_ci	/* BufferStorageTestCase implementation */
676e5c31af7Sopenharmony_ci	void deinitTestCaseGlobal();
677e5c31af7Sopenharmony_ci	void deinitTestCaseIteration();
678e5c31af7Sopenharmony_ci	bool execute(glw::GLuint sparse_bo_storage_flags);
679e5c31af7Sopenharmony_ci	bool initTestCaseGlobal();
680e5c31af7Sopenharmony_ci	bool initTestCaseIteration(glw::GLuint sparse_bo);
681e5c31af7Sopenharmony_ci
682e5c31af7Sopenharmony_ci	const char* getName()
683e5c31af7Sopenharmony_ci	{
684e5c31af7Sopenharmony_ci		return (!m_use_color_data && m_ibo_usage == IBO_USAGE_NONE) ?
685e5c31af7Sopenharmony_ci				   "cases a1-a2" :
686e5c31af7Sopenharmony_ci				   (!m_use_color_data && m_ibo_usage != IBO_USAGE_NONE) ?
687e5c31af7Sopenharmony_ci				   "cases a3-a4" :
688e5c31af7Sopenharmony_ci				   (m_use_color_data && m_ibo_usage != IBO_USAGE_NONE) ? "casea a5-a6" : "?!";
689e5c31af7Sopenharmony_ci	}
690e5c31af7Sopenharmony_ci
691e5c31af7Sopenharmony_ciprivate:
692e5c31af7Sopenharmony_ci	/* Private methods */
693e5c31af7Sopenharmony_ci	void createTestData(unsigned char** out_data, unsigned int* out_vbo_data_offset, unsigned int* out_ibo_data_offset,
694e5c31af7Sopenharmony_ci						unsigned int* out_color_data_offset) const;
695e5c31af7Sopenharmony_ci
696e5c31af7Sopenharmony_ci	void initHelperBO();
697e5c31af7Sopenharmony_ci
698e5c31af7Sopenharmony_ci	void initSparseBO(bool decommit_data_pages_after_upload, bool is_dynamic_storage);
699e5c31af7Sopenharmony_ci
700e5c31af7Sopenharmony_ci	/* Private fields */
701e5c31af7Sopenharmony_ci	glw::GLuint			  m_attribute_color_location;
702e5c31af7Sopenharmony_ci	glw::GLuint			  m_attribute_position_location;
703e5c31af7Sopenharmony_ci	glw::GLuint			  m_color_data_offset;
704e5c31af7Sopenharmony_ci	unsigned char*		  m_data;
705e5c31af7Sopenharmony_ci	glw::GLuint			  m_data_size;		   /* ibo, vbo, color data  */
706e5c31af7Sopenharmony_ci	glw::GLuint			  m_data_size_rounded; /* rounded up to page size */
707e5c31af7Sopenharmony_ci	glw::GLuint			  m_fbo;
708e5c31af7Sopenharmony_ci	const glw::Functions& m_gl;
709e5c31af7Sopenharmony_ci	glw::GLuint			  m_helper_bo;
710e5c31af7Sopenharmony_ci	glw::GLuint			  m_ibo_data_offset;
711e5c31af7Sopenharmony_ci	_ibo_usage			  m_ibo_usage;
712e5c31af7Sopenharmony_ci	const unsigned int	m_n_quad_delta_x;
713e5c31af7Sopenharmony_ci	const unsigned int	m_n_quad_delta_y;
714e5c31af7Sopenharmony_ci	const unsigned int	m_n_quad_height;
715e5c31af7Sopenharmony_ci	const unsigned int	m_n_quad_width;
716e5c31af7Sopenharmony_ci	const unsigned int	m_n_quads_x;
717e5c31af7Sopenharmony_ci	const unsigned int	m_n_quads_y;
718e5c31af7Sopenharmony_ci	unsigned int		  m_n_vertices_to_draw;
719e5c31af7Sopenharmony_ci	bool				  m_pages_committed;
720e5c31af7Sopenharmony_ci	glw::GLuint			  m_po;
721e5c31af7Sopenharmony_ci	glw::GLuint			  m_sparse_bo;
722e5c31af7Sopenharmony_ci	tcu::TestContext&	 m_testCtx;
723e5c31af7Sopenharmony_ci	glw::GLuint			  m_to;
724e5c31af7Sopenharmony_ci	const unsigned int	m_to_height;
725e5c31af7Sopenharmony_ci	const unsigned int	m_to_width;
726e5c31af7Sopenharmony_ci	bool				  m_use_color_data;
727e5c31af7Sopenharmony_ci	glw::GLuint			  m_vao;
728e5c31af7Sopenharmony_ci	glw::GLuint			  m_vbo_data_offset;
729e5c31af7Sopenharmony_ci};
730e5c31af7Sopenharmony_ci
731e5c31af7Sopenharmony_ci/** Implements test case m for the test 2:
732e5c31af7Sopenharmony_ci *
733e5c31af7Sopenharmony_ci * m. Verify query functionality works correctly, when a sparse buffer is bound
734e5c31af7Sopenharmony_ci *    to the query buffer binding point. Render a number of triangles while
735e5c31af7Sopenharmony_ci *    a GL_PRIMITIVES_GENERATED query is enabled and the BO is bound to the
736e5c31af7Sopenharmony_ci *    GL_QUERY_BUFFER binding point. Read back the value of the query from
737e5c31af7Sopenharmony_ci *    the BO and verify it is correct using glGetQueryObjectiv(),
738e5c31af7Sopenharmony_ci *    glGetQueryObjectuiv(), glGetQueryObjecti64v() and glGetQueryObjectui64v()
739e5c31af7Sopenharmony_ci *    functions.
740e5c31af7Sopenharmony_ci *
741e5c31af7Sopenharmony_ci *    Consider two scenarios:
742e5c31af7Sopenharmony_ci *
743e5c31af7Sopenharmony_ci *    a) The page holding the result value is committed.
744e5c31af7Sopenharmony_ci *    b) The page holding the result value is NOT committed. In this case,
745e5c31af7Sopenharmony_ci *       the draw call glGetQueryObjectuiv() and all the getter functions should
746e5c31af7Sopenharmony_ci *       not crash, but the reported values are irrelevant.
747e5c31af7Sopenharmony_ci */
748e5c31af7Sopenharmony_ciclass QueryBufferStorageTestCase : public BufferStorageTestCase
749e5c31af7Sopenharmony_ci{
750e5c31af7Sopenharmony_cipublic:
751e5c31af7Sopenharmony_ci	/* Public methods */
752e5c31af7Sopenharmony_ci	QueryBufferStorageTestCase(const glw::Functions& gl, tcu::TestContext& testContext, glw::GLint page_size);
753e5c31af7Sopenharmony_ci
754e5c31af7Sopenharmony_ci	/* BufferStorageTestCase implementation */
755e5c31af7Sopenharmony_ci	void deinitTestCaseGlobal();
756e5c31af7Sopenharmony_ci	void deinitTestCaseIteration();
757e5c31af7Sopenharmony_ci	bool execute(glw::GLuint sparse_bo_storage_flags);
758e5c31af7Sopenharmony_ci	bool initTestCaseGlobal();
759e5c31af7Sopenharmony_ci	bool initTestCaseIteration(glw::GLuint sparse_bo);
760e5c31af7Sopenharmony_ci
761e5c31af7Sopenharmony_ci	const char* getName()
762e5c31af7Sopenharmony_ci	{
763e5c31af7Sopenharmony_ci		return "case m";
764e5c31af7Sopenharmony_ci	}
765e5c31af7Sopenharmony_ci
766e5c31af7Sopenharmony_ciprivate:
767e5c31af7Sopenharmony_ci	/* Private fields */
768e5c31af7Sopenharmony_ci	const glw::Functions& m_gl;
769e5c31af7Sopenharmony_ci	glw::GLuint			  m_helper_bo;
770e5c31af7Sopenharmony_ci	const unsigned int	m_n_triangles;
771e5c31af7Sopenharmony_ci	glw::GLint			  m_page_size;
772e5c31af7Sopenharmony_ci	glw::GLuint			  m_po;
773e5c31af7Sopenharmony_ci	glw::GLuint			  m_qo;
774e5c31af7Sopenharmony_ci	glw::GLuint			  m_sparse_bo;
775e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_size;
776e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_size_rounded;
777e5c31af7Sopenharmony_ci	tcu::TestContext&	 m_testCtx;
778e5c31af7Sopenharmony_ci	glw::GLuint			  m_vao;
779e5c31af7Sopenharmony_ci};
780e5c31af7Sopenharmony_ci
781e5c31af7Sopenharmony_ci/** Implements test case i for the test 2:
782e5c31af7Sopenharmony_ci *
783e5c31af7Sopenharmony_ci * i. Verify a SSBO, holding an unsized array, accessed from a compute shader,
784e5c31af7Sopenharmony_ci *    contains anticipated values. Each CS invocation should only fetch
785e5c31af7Sopenharmony_ci *    a single invocation-specific value. If the value is found correct, it
786e5c31af7Sopenharmony_ci *    should increment it.
787e5c31af7Sopenharmony_ci *
788e5c31af7Sopenharmony_ci *    The test passes if all values accessed by the CS invocations are found
789e5c31af7Sopenharmony_ci *    valid after the dispatch call.
790e5c31af7Sopenharmony_ci *
791e5c31af7Sopenharmony_ci *    Make sure to test three scenarios:
792e5c31af7Sopenharmony_ci *
793e5c31af7Sopenharmony_ci *    a) All values come from the committed memory pages.
794e5c31af7Sopenharmony_ci *    b) Use the same memory page commitment layout as proposed in b2. Verify
795e5c31af7Sopenharmony_ci *       only those values, which were available to the compute shader.
796e5c31af7Sopenharmony_ci *    c) None of the value exposed via SSBO are backed by physical memory.
797e5c31af7Sopenharmony_ci *       In this case, we do not really care about the outputs of the CS.
798e5c31af7Sopenharmony_ci *       We only need to ensure that GL (or the GPU) does not crash.
799e5c31af7Sopenharmony_ci */
800e5c31af7Sopenharmony_ciclass SSBOStorageTestCase : public BufferStorageTestCase
801e5c31af7Sopenharmony_ci{
802e5c31af7Sopenharmony_cipublic:
803e5c31af7Sopenharmony_ci	/* Public methods */
804e5c31af7Sopenharmony_ci	SSBOStorageTestCase(const glw::Functions& gl, tcu::TestContext& testContext, glw::GLint page_size);
805e5c31af7Sopenharmony_ci
806e5c31af7Sopenharmony_ci	/* BufferStorageTestCase implementation */
807e5c31af7Sopenharmony_ci	void deinitTestCaseGlobal();
808e5c31af7Sopenharmony_ci	void deinitTestCaseIteration();
809e5c31af7Sopenharmony_ci	bool execute(glw::GLuint sparse_bo_storage_flags);
810e5c31af7Sopenharmony_ci	bool initTestCaseGlobal();
811e5c31af7Sopenharmony_ci	bool initTestCaseIteration(glw::GLuint sparse_bo);
812e5c31af7Sopenharmony_ci
813e5c31af7Sopenharmony_ci	const char* getName()
814e5c31af7Sopenharmony_ci	{
815e5c31af7Sopenharmony_ci		return "case i";
816e5c31af7Sopenharmony_ci	}
817e5c31af7Sopenharmony_ci
818e5c31af7Sopenharmony_ciprivate:
819e5c31af7Sopenharmony_ci	/* Private fields */
820e5c31af7Sopenharmony_ci	const glw::Functions& m_gl;
821e5c31af7Sopenharmony_ci	glw::GLuint			  m_helper_bo; /* holds m_sparse_bo_size bytes */
822e5c31af7Sopenharmony_ci	glw::GLint			  m_page_size;
823e5c31af7Sopenharmony_ci	glw::GLuint			  m_po;
824e5c31af7Sopenharmony_ci	const unsigned int	m_po_local_wg_size;
825e5c31af7Sopenharmony_ci	glw::GLuint			  m_result_bo;
826e5c31af7Sopenharmony_ci	glw::GLuint			  m_sparse_bo;
827e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_size;
828e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_size_rounded;
829e5c31af7Sopenharmony_ci	unsigned int*		  m_ssbo_data; /* holds m_sparse_bo_size bytes */
830e5c31af7Sopenharmony_ci	tcu::TestContext&	 m_testCtx;
831e5c31af7Sopenharmony_ci};
832e5c31af7Sopenharmony_ci
833e5c31af7Sopenharmony_ci/** Implements test cases b1-b2 for the test 2:
834e5c31af7Sopenharmony_ci *
835e5c31af7Sopenharmony_ci * b1. Use a sparse buffer as a target for separate & interleaved transform
836e5c31af7Sopenharmony_ci *     feed-back (in separate iterations). A sufficient number of pages should
837e5c31af7Sopenharmony_ci *     have been committed prior to issuing any draw call.
838e5c31af7Sopenharmony_ci *
839e5c31af7Sopenharmony_ci *     The vertex shader should output vertex ID & instance ID data to two
840e5c31af7Sopenharmony_ci *     different output variables captured by the TF.
841e5c31af7Sopenharmony_ci *
842e5c31af7Sopenharmony_ci *     The test should only pass if the generated output is correct.
843e5c31af7Sopenharmony_ci *
844e5c31af7Sopenharmony_ci *     For the purpose of this test, use the following draw call types:
845e5c31af7Sopenharmony_ci *
846e5c31af7Sopenharmony_ci *     * regular
847e5c31af7Sopenharmony_ci *     * regular indirect
848e5c31af7Sopenharmony_ci *     * regular indirect multi
849e5c31af7Sopenharmony_ci *     * regular instanced
850e5c31af7Sopenharmony_ci *     * regular instanced + base instance
851e5c31af7Sopenharmony_ci *     * regular multi
852e5c31af7Sopenharmony_ci *     * indexed
853e5c31af7Sopenharmony_ci *     * indexed indirect
854e5c31af7Sopenharmony_ci *     * indexed indirect multi
855e5c31af7Sopenharmony_ci *     * indexed multi
856e5c31af7Sopenharmony_ci *     * indexed multi + base vertex
857e5c31af7Sopenharmony_ci *     * indexed + base vertex
858e5c31af7Sopenharmony_ci *     * indexed + base vertex + base instance
859e5c31af7Sopenharmony_ci *     * instanced indexed
860e5c31af7Sopenharmony_ci *     * instanced indexed + base vertex
861e5c31af7Sopenharmony_ci *     * instanced indexed + base vertex + base instance
862e5c31af7Sopenharmony_ci *
863e5c31af7Sopenharmony_ci *
864e5c31af7Sopenharmony_ci * b2. Follow the same approach as described for b1. However, the commitment
865e5c31af7Sopenharmony_ci *     state of memory pages used for the TF process should be laid out in
866e5c31af7Sopenharmony_ci *     the following order:
867e5c31af7Sopenharmony_ci *
868e5c31af7Sopenharmony_ci *     1st       page:     committed
869e5c31af7Sopenharmony_ci *     2nd       page: NOT committed
870e5c31af7Sopenharmony_ci *     ...
871e5c31af7Sopenharmony_ci *     (2N)  -th page:     committed
872e5c31af7Sopenharmony_ci *     (2N+1)-th page: NOT committed
873e5c31af7Sopenharmony_ci *
874e5c31af7Sopenharmony_ci *     Make sure to use at least 4 memory pages in this test case.
875e5c31af7Sopenharmony_ci *
876e5c31af7Sopenharmony_ci *     Execute the test as described in b1, and make sure the results stored
877e5c31af7Sopenharmony_ci *     in the committed pages used by the TF process holds valid result data.
878e5c31af7Sopenharmony_ci */
879e5c31af7Sopenharmony_ciclass TransformFeedbackBufferStorageTestCase : public BufferStorageTestCase
880e5c31af7Sopenharmony_ci{
881e5c31af7Sopenharmony_cipublic:
882e5c31af7Sopenharmony_ci	/* Type definitions */
883e5c31af7Sopenharmony_ci	enum _draw_call
884e5c31af7Sopenharmony_ci	{
885e5c31af7Sopenharmony_ci		/* glDrawElements() */
886e5c31af7Sopenharmony_ci		DRAW_CALL_INDEXED,
887e5c31af7Sopenharmony_ci		/* glDrawElementsBaseVertex() */
888e5c31af7Sopenharmony_ci		DRAW_CALL_INDEXED_BASE_VERTEX,
889e5c31af7Sopenharmony_ci		/* glDrawElementsIndirect() */
890e5c31af7Sopenharmony_ci		DRAW_CALL_INDEXED_INDIRECT,
891e5c31af7Sopenharmony_ci		/* glMultiDrawElementIndirect() */
892e5c31af7Sopenharmony_ci		DRAW_CALL_INDEXED_INDIRECT_MULTI,
893e5c31af7Sopenharmony_ci		/* glMultiDrawElements() */
894e5c31af7Sopenharmony_ci		DRAW_CALL_INDEXED_MULTI,
895e5c31af7Sopenharmony_ci		/* glMultiDrawElementsBaseVertex() */
896e5c31af7Sopenharmony_ci		DRAW_CALL_INDEXED_MULTI_BASE_VERTEX,
897e5c31af7Sopenharmony_ci		/* glDrawElementsInstanced() */
898e5c31af7Sopenharmony_ci		DRAW_CALL_INSTANCED_INDEXED,
899e5c31af7Sopenharmony_ci		/* glDrawElementsInstancedBaseVertex() */
900e5c31af7Sopenharmony_ci		DRAW_CALL_INSTANCED_INDEXED_BASE_VERTEX,
901e5c31af7Sopenharmony_ci		/* glDrawElementsInstancedBaseVertexBaseInstance() */
902e5c31af7Sopenharmony_ci		DRAW_CALL_INSTANCED_INDEXED_BASE_VERTEX_BASE_INSTANCE,
903e5c31af7Sopenharmony_ci		/* glDrawArrays() */
904e5c31af7Sopenharmony_ci		DRAW_CALL_REGULAR,
905e5c31af7Sopenharmony_ci		/* glDrawArraysIndirect() */
906e5c31af7Sopenharmony_ci		DRAW_CALL_REGULAR_INDIRECT,
907e5c31af7Sopenharmony_ci		/* glMultiDrawArraysIndirect() */
908e5c31af7Sopenharmony_ci		DRAW_CALL_REGULAR_INDIRECT_MULTI,
909e5c31af7Sopenharmony_ci		/* glDrawArraysInstanced() */
910e5c31af7Sopenharmony_ci		DRAW_CALL_REGULAR_INSTANCED,
911e5c31af7Sopenharmony_ci		/* glDrawArraysInstancedBaseInstance() */
912e5c31af7Sopenharmony_ci		DRAW_CALL_REGULAR_INSTANCED_BASE_INSTANCE,
913e5c31af7Sopenharmony_ci		/* glMultiDrawArrays() */
914e5c31af7Sopenharmony_ci		DRAW_CALL_REGULAR_MULTI,
915e5c31af7Sopenharmony_ci
916e5c31af7Sopenharmony_ci		/* Always last */
917e5c31af7Sopenharmony_ci		DRAW_CALL_COUNT
918e5c31af7Sopenharmony_ci	};
919e5c31af7Sopenharmony_ci
920e5c31af7Sopenharmony_ci	/* Public methods */
921e5c31af7Sopenharmony_ci	TransformFeedbackBufferStorageTestCase(const glw::Functions& gl, tcu::TestContext& testContext,
922e5c31af7Sopenharmony_ci										   glw::GLint page_size, bool all_pages_committed);
923e5c31af7Sopenharmony_ci
924e5c31af7Sopenharmony_ci	/* BufferStorageTestCase implementation */
925e5c31af7Sopenharmony_ci	void deinitTestCaseGlobal();
926e5c31af7Sopenharmony_ci	bool execute(glw::GLuint sparse_bo_storage_flags);
927e5c31af7Sopenharmony_ci	bool initTestCaseGlobal();
928e5c31af7Sopenharmony_ci	bool initTestCaseIteration(glw::GLuint sparse_bo);
929e5c31af7Sopenharmony_ci
930e5c31af7Sopenharmony_ci	const char* getName()
931e5c31af7Sopenharmony_ci	{
932e5c31af7Sopenharmony_ci		return (m_all_pages_committed) ? "case b1" : "case b2";
933e5c31af7Sopenharmony_ci	}
934e5c31af7Sopenharmony_ci
935e5c31af7Sopenharmony_ciprivate:
936e5c31af7Sopenharmony_ci	/* Private methods */
937e5c31af7Sopenharmony_ci	const char* getDrawCallTypeString(_draw_call draw_call);
938e5c31af7Sopenharmony_ci	void initDataBO();
939e5c31af7Sopenharmony_ci	void initTestData();
940e5c31af7Sopenharmony_ci
941e5c31af7Sopenharmony_ci	/* Private fields */
942e5c31af7Sopenharmony_ci	bool				  m_all_pages_committed;
943e5c31af7Sopenharmony_ci	glw::GLuint			  m_data_bo;
944e5c31af7Sopenharmony_ci	unsigned int		  m_data_bo_index_data_offset;
945e5c31af7Sopenharmony_ci	unsigned int		  m_data_bo_indexed_indirect_arg_offset;
946e5c31af7Sopenharmony_ci	unsigned int		  m_data_bo_indexed_mdi_arg_offset;
947e5c31af7Sopenharmony_ci	unsigned int		  m_data_bo_regular_indirect_arg_offset;
948e5c31af7Sopenharmony_ci	unsigned int		  m_data_bo_regular_mdi_arg_offset;
949e5c31af7Sopenharmony_ci	glw::GLuint			  m_data_bo_size;
950e5c31af7Sopenharmony_ci	const unsigned int	m_draw_call_baseInstance;
951e5c31af7Sopenharmony_ci	const unsigned int	m_draw_call_baseVertex;
952e5c31af7Sopenharmony_ci	const unsigned int	m_draw_call_first;
953e5c31af7Sopenharmony_ci	const unsigned int	m_draw_call_firstIndex;
954e5c31af7Sopenharmony_ci	const glw::Functions& m_gl;
955e5c31af7Sopenharmony_ci	glw::GLuint			  m_helper_bo; /* of m_result_bo_size size */
956e5c31af7Sopenharmony_ci	glw::GLuint*		  m_index_data;
957e5c31af7Sopenharmony_ci	glw::GLuint			  m_index_data_size;
958e5c31af7Sopenharmony_ci	glw::GLuint*		  m_indirect_arg_data;
959e5c31af7Sopenharmony_ci	glw::GLuint			  m_indirect_arg_data_size;
960e5c31af7Sopenharmony_ci	const unsigned int	m_min_memory_page_span;
961e5c31af7Sopenharmony_ci	glw::GLint			  m_multidrawcall_basevertex[2];
962e5c31af7Sopenharmony_ci	glw::GLsizei		  m_multidrawcall_count[2];
963e5c31af7Sopenharmony_ci	unsigned int		  m_multidrawcall_drawcount;
964e5c31af7Sopenharmony_ci	glw::GLint			  m_multidrawcall_first[2];
965e5c31af7Sopenharmony_ci	glw::GLvoid*		  m_multidrawcall_index[2];
966e5c31af7Sopenharmony_ci	unsigned int		  m_multidrawcall_primcount;
967e5c31af7Sopenharmony_ci	const unsigned int	m_n_instances_to_test;
968e5c31af7Sopenharmony_ci	unsigned int		  m_n_vertices_per_instance;
969e5c31af7Sopenharmony_ci	glw::GLint			  m_page_size;
970e5c31af7Sopenharmony_ci	glw::GLuint			  m_po_ia; /* interleave attribs TF */
971e5c31af7Sopenharmony_ci	glw::GLuint			  m_po_sa; /* separate attribs TF */
972e5c31af7Sopenharmony_ci	glw::GLuint			  m_result_bo;
973e5c31af7Sopenharmony_ci	glw::GLuint			  m_result_bo_size;
974e5c31af7Sopenharmony_ci	glw::GLuint			  m_result_bo_size_rounded;
975e5c31af7Sopenharmony_ci	tcu::TestContext&	 m_testCtx;
976e5c31af7Sopenharmony_ci	glw::GLuint			  m_vao;
977e5c31af7Sopenharmony_ci};
978e5c31af7Sopenharmony_ci
979e5c31af7Sopenharmony_ci/** Implements test case j for the test 2:
980e5c31af7Sopenharmony_ci *
981e5c31af7Sopenharmony_ci * j. Verify an UBO, backed by a sparse buffer, accessed from a vertex shader,
982e5c31af7Sopenharmony_ci *    holds values as expected. Each VS invocation should only check
983e5c31af7Sopenharmony_ci *    an invocation-specific arrayed member item and set gl_Position to
984e5c31af7Sopenharmony_ci *    vec4(1.0), if the retrieved value is valid.
985e5c31af7Sopenharmony_ci *
986e5c31af7Sopenharmony_ci *    Make sure to test three scenarios as described for case i).
987e5c31af7Sopenharmony_ci */
988e5c31af7Sopenharmony_ciclass UniformBufferStorageTestCase : public BufferStorageTestCase
989e5c31af7Sopenharmony_ci{
990e5c31af7Sopenharmony_cipublic:
991e5c31af7Sopenharmony_ci	/* Public methods */
992e5c31af7Sopenharmony_ci	UniformBufferStorageTestCase(const glw::Functions& gl, tcu::TestContext& testContext, glw::GLint page_size);
993e5c31af7Sopenharmony_ci
994e5c31af7Sopenharmony_ci	/* BufferStorageTestCase implementation */
995e5c31af7Sopenharmony_ci	void deinitTestCaseGlobal();
996e5c31af7Sopenharmony_ci	void deinitTestCaseIteration();
997e5c31af7Sopenharmony_ci	bool execute(glw::GLuint sparse_bo_storage_flags);
998e5c31af7Sopenharmony_ci	bool initTestCaseGlobal();
999e5c31af7Sopenharmony_ci	bool initTestCaseIteration(glw::GLuint sparse_bo);
1000e5c31af7Sopenharmony_ci
1001e5c31af7Sopenharmony_ci	const char* getName()
1002e5c31af7Sopenharmony_ci	{
1003e5c31af7Sopenharmony_ci		return "case j";
1004e5c31af7Sopenharmony_ci	}
1005e5c31af7Sopenharmony_ci
1006e5c31af7Sopenharmony_ciprivate:
1007e5c31af7Sopenharmony_ci	/* Private fields */
1008e5c31af7Sopenharmony_ci	const glw::Functions& m_gl;
1009e5c31af7Sopenharmony_ci	glw::GLint			  m_gl_uniform_buffer_offset_alignment_value;
1010e5c31af7Sopenharmony_ci	glw::GLuint			  m_helper_bo;
1011e5c31af7Sopenharmony_ci	const unsigned int	m_n_pages_to_use;
1012e5c31af7Sopenharmony_ci	unsigned int		  m_n_ubo_uints;
1013e5c31af7Sopenharmony_ci	glw::GLint			  m_page_size;
1014e5c31af7Sopenharmony_ci	glw::GLuint			  m_po;
1015e5c31af7Sopenharmony_ci	glw::GLuint			  m_sparse_bo;
1016e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_data_size;
1017e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_data_start_offset;
1018e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_size;
1019e5c31af7Sopenharmony_ci	unsigned int		  m_sparse_bo_size_rounded;
1020e5c31af7Sopenharmony_ci	tcu::TestContext&	 m_testCtx;
1021e5c31af7Sopenharmony_ci	glw::GLuint			  m_tf_bo;
1022e5c31af7Sopenharmony_ci	unsigned char*		  m_ubo_data;
1023e5c31af7Sopenharmony_ci	glw::GLuint			  m_vao;
1024e5c31af7Sopenharmony_ci};
1025e5c31af7Sopenharmony_ci
1026e5c31af7Sopenharmony_ci/** Implements conformance test 2 from the test specification:
1027e5c31af7Sopenharmony_ci *
1028e5c31af7Sopenharmony_ci * 2. Make sure glBufferStorage() accepts the new GL_SPARSE_STORAGE_BIT_ARB flag
1029e5c31af7Sopenharmony_ci *    in all valid flag combinations. For each such combination, allocate
1030e5c31af7Sopenharmony_ci *    a sparse buffer of 1GB size and verify the following test cases work as
1031e5c31af7Sopenharmony_ci *    expected. After all tests have been run for a particular flag combination,
1032e5c31af7Sopenharmony_ci *    the sparse buffer should be deleted, and a new sparse buffer should be
1033e5c31af7Sopenharmony_ci *    created, if there are any outstanding flag combinations.
1034e5c31af7Sopenharmony_ci *
1035e5c31af7Sopenharmony_ci *    Test cases, whose verification behavior is incompatible with
1036e5c31af7Sopenharmony_ci *    the requested flag combination should skip the validation part:
1037e5c31af7Sopenharmony_ci *
1038e5c31af7Sopenharmony_ci *    (for test case descriptions, please check test case class prototypes)
1039e5c31af7Sopenharmony_ci */
1040e5c31af7Sopenharmony_ciclass BufferStorageTest : public deqp::TestCase
1041e5c31af7Sopenharmony_ci{
1042e5c31af7Sopenharmony_cipublic:
1043e5c31af7Sopenharmony_ci	/* Public methods */
1044e5c31af7Sopenharmony_ci	BufferStorageTest(deqp::Context& context);
1045e5c31af7Sopenharmony_ci
1046e5c31af7Sopenharmony_ci	void						 deinit();
1047e5c31af7Sopenharmony_ci	void						 init();
1048e5c31af7Sopenharmony_ci	tcu::TestNode::IterateResult iterate();
1049e5c31af7Sopenharmony_ci
1050e5c31af7Sopenharmony_ciprivate:
1051e5c31af7Sopenharmony_ci	/* Private type definitions */
1052e5c31af7Sopenharmony_ci	typedef std::vector<BufferStorageTestCase*> TestCasesVector;
1053e5c31af7Sopenharmony_ci	typedef TestCasesVector::const_iterator		TestCasesVectorConstIterator;
1054e5c31af7Sopenharmony_ci	typedef TestCasesVector::iterator			TestCasesVectorIterator;
1055e5c31af7Sopenharmony_ci
1056e5c31af7Sopenharmony_ci	/* Private methods */
1057e5c31af7Sopenharmony_ci	void initTestCases();
1058e5c31af7Sopenharmony_ci
1059e5c31af7Sopenharmony_ci	/* Private members */
1060e5c31af7Sopenharmony_ci	glw::GLuint		m_sparse_bo;
1061e5c31af7Sopenharmony_ci	TestCasesVector m_testCases;
1062e5c31af7Sopenharmony_ci};
1063e5c31af7Sopenharmony_ci
1064e5c31af7Sopenharmony_ci/** Test group which encapsulates all sparse buffer conformance tests */
1065e5c31af7Sopenharmony_ciclass SparseBufferTests : public deqp::TestCaseGroup
1066e5c31af7Sopenharmony_ci{
1067e5c31af7Sopenharmony_cipublic:
1068e5c31af7Sopenharmony_ci	/* Public methods */
1069e5c31af7Sopenharmony_ci	SparseBufferTests(deqp::Context& context);
1070e5c31af7Sopenharmony_ci
1071e5c31af7Sopenharmony_ci	void init();
1072e5c31af7Sopenharmony_ci
1073e5c31af7Sopenharmony_ciprivate:
1074e5c31af7Sopenharmony_ci	SparseBufferTests(const SparseBufferTests& other);
1075e5c31af7Sopenharmony_ci	SparseBufferTests& operator=(const SparseBufferTests& other);
1076e5c31af7Sopenharmony_ci};
1077e5c31af7Sopenharmony_ci
1078e5c31af7Sopenharmony_ci} /* glcts namespace */
1079e5c31af7Sopenharmony_ci
1080e5c31af7Sopenharmony_ci#endif // _GL4CSPARSEBUFFERTESTS_HPP
1081