• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23 
24 /*!
25  * \file esextcGPUShader5SSBOArrayIndexing.cpp
26  * \brief GPUShader5 SSBO Array Indexing (Test 5)
27  */ /*-------------------------------------------------------------------*/
28 
29 #include "esextcGPUShader5SSBOArrayIndexing.hpp"
30 #include "gluContextInfo.hpp"
31 #include "gluDefs.hpp"
32 #include "glwEnums.hpp"
33 #include "glwFunctions.hpp"
34 #include "tcuTestLog.hpp"
35 #include <cstring>
36 
37 namespace glcts
38 {
39 
40 /* Compute shader code */
41 const char* GPUShader5SSBOArrayIndexing::m_compute_shader_code =
42 	"${VERSION}\n"
43 	"\n"
44 	"${GPU_SHADER5_REQUIRE}\n"
45 	"\n"
46 	"#define LOCAL_SIZE_X 3u\n"
47 	"#define LOCAL_SIZE_Y 3u\n"
48 	"\n"
49 	"layout (local_size_x = LOCAL_SIZE_X, local_size_y = LOCAL_SIZE_Y) in;\n"
50 	"\n"
51 	"layout(binding = 0) buffer ComputeSSBO\n"
52 	"{\n"
53 	"    uint value;\n"
54 	"} computeSSBO[4];\n"
55 	"\n"
56 	"uniform uint index;\n"
57 	"\n"
58 	"void main(void)\n"
59 	"{\n"
60 	"    uint id = gl_LocalInvocationID.x * LOCAL_SIZE_Y + gl_LocalInvocationID.y;\n"
61 	"\n"
62 	"    for (uint i = 0u; i < LOCAL_SIZE_X * LOCAL_SIZE_Y; ++i)\n"
63 	"    {\n"
64 	"        if (id == i)\n"
65 	"        {\n"
66 	"            computeSSBO[index].value += id;\n"
67 	"        }\n"
68 	"\n"
69 	"        memoryBarrier();\n"
70 	"    }\n"
71 	"}\n";
72 
73 /* Size of the ssbo array */
74 const glw::GLuint GPUShader5SSBOArrayIndexing::m_n_arrays = 4;
75 
76 /** Constructor
77  *
78  *  @param context       Test context
79  *  @param name          Test case's name
80  *  @param description   Test case's description
81  **/
GPUShader5SSBOArrayIndexing(Context & context,const ExtParameters & extParams,const char * name,const char * description)82 GPUShader5SSBOArrayIndexing::GPUShader5SSBOArrayIndexing(Context& context, const ExtParameters& extParams,
83 														 const char* name, const char* description)
84 	: TestCaseBase(context, extParams, name, description)
85 	, m_compute_shader_id(0)
86 	, m_program_id(0)
87 	, m_ssbo_buffer_ids(DE_NULL)
88 {
89 	/* Nothing to be done here */
90 }
91 
92 /** Initializes GLES objects used during the test.
93  *
94  */
initTest(void)95 void GPUShader5SSBOArrayIndexing::initTest(void)
96 {
97 	/* Check if gpu_shader5 extension is supported */
98 	if (!m_is_gpu_shader5_supported)
99 	{
100 		throw tcu::NotSupportedError(GPU_SHADER5_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
101 	}
102 
103 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
104 
105 	m_program_id = gl.createProgram();
106 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create program object!");
107 
108 	m_compute_shader_id = gl.createShader(GL_COMPUTE_SHADER);
109 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object!");
110 
111 	if (!buildProgram(m_program_id, m_compute_shader_id, 1, &m_compute_shader_code))
112 	{
113 		TCU_FAIL("Could not build program from valid compute shader!");
114 	}
115 
116 	m_ssbo_buffer_ids = new glw::GLuint[m_n_arrays];
117 	memset(m_ssbo_buffer_ids, 0, m_n_arrays * sizeof(glw::GLuint));
118 
119 	gl.genBuffers(m_n_arrays, m_ssbo_buffer_ids);
120 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
121 
122 	for (glw::GLuint index = 0; index < m_n_arrays; ++index)
123 	{
124 		gl.bindBuffer(GL_ARRAY_BUFFER, m_ssbo_buffer_ids[index]);
125 		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind buffer object!");
126 
127 		const glw::GLuint ssbo_data = 0;
128 
129 		gl.bufferData(GL_ARRAY_BUFFER, sizeof(glw::GLuint), &ssbo_data, GL_DYNAMIC_COPY);
130 		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set buffer object data!");
131 
132 		gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, index, m_ssbo_buffer_ids[index]);
133 		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind buffer object to shader storage binding point!");
134 	}
135 }
136 
137 /** Executes the test.
138  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
139  *
140  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
141  *
142  *  Note the function throws exception should an error occur!
143  **/
iterate(void)144 tcu::TestNode::IterateResult GPUShader5SSBOArrayIndexing::iterate(void)
145 {
146 	initTest();
147 
148 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
149 
150 	/* Activate the program object and retrieve index uniform location */
151 	gl.useProgram(m_program_id);
152 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not use program!");
153 
154 	glw::GLint index_location = gl.getUniformLocation(m_program_id, "index");
155 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call failed!");
156 
157 	if (index_location == -1)
158 	{
159 		TCU_FAIL("Index uniform location is inactive which is invalid!");
160 	}
161 
162 	/* Issue a few compute operations */
163 	gl.uniform1ui(index_location, 1);
164 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set value of index uniform variable!");
165 
166 	gl.dispatchCompute(1,  /* num_groups_x */
167 					   1,  /* num_groups_y */
168 					   1); /* num_groups_z */
169 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not dispatch compute!");
170 
171 	gl.memoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
172 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set memory barrier!");
173 
174 	gl.uniform1ui(index_location, 3);
175 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set value to index uniform variable!");
176 
177 	gl.dispatchCompute(1,  /* num_groups_x */
178 					   1,  /* num_groups_y */
179 					   1); /* num_groups_z */
180 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not dispatch compute!");
181 
182 	gl.memoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
183 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set memory barrier!");
184 
185 	/* Validate the results */
186 	glw::GLuint expected_result[m_n_arrays] = { 0, 36, 0, 36 };
187 	bool		test_failed					= false;
188 
189 	for (glw::GLuint index = 0; index < m_n_arrays; ++index)
190 	{
191 		gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo_buffer_ids[index]);
192 		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind a buffer object!");
193 
194 		const glw::GLuint* compute_SSBO =
195 			(const glw::GLuint*)gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(glw::GLuint), GL_MAP_READ_BIT);
196 
197 		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not map buffer data to client memory");
198 
199 		if (compute_SSBO[0] != expected_result[index])
200 		{
201 			m_testCtx.getLog() << tcu::TestLog::Message << "Expected Data (" << expected_result[index] << ") "
202 							   << "Result Data (" << compute_SSBO[0] << ")" << tcu::TestLog::EndMessage;
203 
204 			test_failed = true;
205 		}
206 
207 		gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
208 		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not unmap buffer");
209 	}
210 
211 	if (test_failed)
212 	{
213 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
214 	}
215 	else
216 	{
217 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
218 	}
219 
220 	return STOP;
221 }
222 
223 /** Deinitializes GLES objects created during the test.
224  *
225  */
deinit(void)226 void GPUShader5SSBOArrayIndexing::deinit(void)
227 {
228 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
229 
230 	/* Reset OpenGL ES state */
231 	gl.useProgram(0);
232 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
233 	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
234 
235 	/* Delete program object and shaders */
236 	if (m_program_id != 0)
237 	{
238 		gl.deleteProgram(m_program_id);
239 
240 		m_program_id = 0;
241 	}
242 
243 	if (m_compute_shader_id != 0)
244 	{
245 		gl.deleteShader(m_compute_shader_id);
246 
247 		m_compute_shader_id = 0;
248 	}
249 
250 	if (m_ssbo_buffer_ids != DE_NULL)
251 	{
252 		gl.deleteBuffers(m_n_arrays, m_ssbo_buffer_ids);
253 
254 		delete[] m_ssbo_buffer_ids;
255 		m_ssbo_buffer_ids = DE_NULL;
256 	}
257 
258 	/* Call base class' deinit() */
259 	TestCaseBase::deinit();
260 }
261 
262 } // namespace glcts
263