• 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  esextcTextureBufferAtomicFunctions.cpp
26  * \brief Texture Buffer Atomic Functions (Test 5)
27  */ /*-------------------------------------------------------------------*/
28 
29 #include "esextcTextureBufferAtomicFunctions.hpp"
30 #include "gluContextInfo.hpp"
31 #include "gluDefs.hpp"
32 #include "glwEnums.hpp"
33 #include "glwFunctions.hpp"
34 #include "tcuTestLog.hpp"
35 #include <vector>
36 
37 namespace glcts
38 {
39 
40 /** Constructor
41  *
42  *  @param context     Test context
43  *  @param name        Test case's name
44  *  @param description Test case's description
45  **/
TextureBufferAtomicFunctions(Context & context,const ExtParameters & extParams,const char * name,const char * description)46 TextureBufferAtomicFunctions::TextureBufferAtomicFunctions(Context& context, const ExtParameters& extParams,
47 														   const char* name, const char* description)
48 	: TestCaseBase(context, extParams, name, description)
49 	, m_cs_id(0)
50 	, m_po_id(0)
51 	, m_tbo_id(0)
52 	, m_tbo_tex_id(0)
53 	, m_n_texels_in_texture_buffer(0)
54 {
55 }
56 
57 /** Initializes GLES objects used during the test */
initTest(void)58 void TextureBufferAtomicFunctions::initTest(void)
59 {
60 	/* Check if required extensions are supported */
61 	if (!m_is_texture_buffer_supported)
62 	{
63 		throw tcu::NotSupportedError(TEXTURE_BUFFER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
64 	}
65 
66 	if (!m_is_shader_image_atomic_supported)
67 	{
68 		throw tcu::NotSupportedError(SHADER_IMAGE_ATOMIC_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
69 	}
70 
71 	/* Get GL entry points */
72 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
73 
74 	glw::GLint work_group_size = 0;
75 	gl.getIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, &work_group_size);
76 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error getting GL_MAX_COMPUTE_WORK_GROUP_SIZE parameter value!");
77 
78 	m_n_texels_in_texture_buffer = (glw::GLuint)work_group_size + 1;
79 	std::vector<glw::GLuint> data_buffer(m_n_texels_in_texture_buffer);
80 
81 	for (glw::GLuint i = 0; i < m_n_texels_in_texture_buffer; ++i)
82 	{
83 		data_buffer[i] = i;
84 	}
85 
86 	/* Create buffer object */
87 	gl.genBuffers(1, &m_tbo_id);
88 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating buffer object!");
89 
90 	gl.bindBuffer(m_glExtTokens.TEXTURE_BUFFER, m_tbo_id);
91 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!");
92 
93 	gl.bufferData(m_glExtTokens.TEXTURE_BUFFER, m_n_texels_in_texture_buffer * sizeof(glw::GLuint), &data_buffer[0],
94 				  GL_DYNAMIC_DRAW);
95 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating buffer object's data store!");
96 
97 	/* Initialize texture buffer */
98 	gl.genTextures(1, &m_tbo_tex_id);
99 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating texture object!");
100 
101 	gl.activeTexture(GL_TEXTURE0);
102 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active texture unit!");
103 
104 	gl.bindTexture(m_glExtTokens.TEXTURE_BUFFER, m_tbo_tex_id);
105 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object to GL_TEXTURE_BUFFER_EXT target!");
106 
107 	gl.texBuffer(m_glExtTokens.TEXTURE_BUFFER, GL_R32UI, m_tbo_id);
108 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting buffer object as texture buffer's data store!");
109 
110 	/* Create program object */
111 	m_po_id = gl.createProgram();
112 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program object!");
113 
114 	m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
115 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating shader object!");
116 
117 	std::string csSource = getComputeShaderCode(work_group_size);
118 	const char* csCode   = csSource.c_str();
119 
120 	if (!buildProgram(m_po_id, m_cs_id, 1, &csCode))
121 	{
122 		TCU_FAIL("Could not create a program object from valid compute shader object!");
123 	}
124 }
125 
126 /** Returns Compute shader Code
127  *
128  * @return pointer to literal with Compute Shader Code
129  */
getComputeShaderCode(glw::GLint work_group_size) const130 std::string TextureBufferAtomicFunctions::getComputeShaderCode(glw::GLint work_group_size) const
131 {
132 	std::stringstream strstream;
133 
134 	strstream << "${VERSION}\n"
135 				 "\n"
136 				 "${TEXTURE_BUFFER_REQUIRE}\n"
137 				 "${SHADER_IMAGE_ATOMIC_REQUIRE}\n"
138 				 "\n"
139 				 "precision highp float;\n"
140 				 "\n"
141 				 "layout (local_size_x = "
142 			  << work_group_size << " ) in;\n"
143 									"\n"
144 									"layout(r32ui, binding = 0) coherent uniform highp uimageBuffer uimage_buffer;\n"
145 									"\n"
146 									"void main(void)\n"
147 									"{\n"
148 									"   uint value = imageLoad( uimage_buffer, int(gl_LocalInvocationID.x) + 1 ).x;\n"
149 									"   imageAtomicAdd( uimage_buffer, 0 , value );\n"
150 									"\n"
151 									"   memoryBarrier();\n"
152 									"   barrier();\n"
153 									"\n"
154 									"   value = imageLoad( uimage_buffer, 0 ).x;\n"
155 									"   imageAtomicCompSwap( uimage_buffer, int(gl_LocalInvocationID.x) + 1, "
156 									"gl_LocalInvocationID.x + 1u, value );\n"
157 									"}\n";
158 
159 	return strstream.str();
160 }
161 
162 /** Executes the test.
163  *
164  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
165  *
166  *  Note the function throws exception should an error occur!
167  *
168  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
169  **/
iterate(void)170 tcu::TestNode::IterateResult TextureBufferAtomicFunctions::iterate(void)
171 {
172 	/* Initialize */
173 	initTest();
174 
175 	/* Get Gl entry points */
176 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
177 
178 	bool test_result = true;
179 
180 	gl.useProgram(m_po_id);
181 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active program object!");
182 
183 	gl.bindImageTexture(0, m_tbo_tex_id, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
184 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object to image unit 0!");
185 
186 	gl.dispatchCompute(1, 1, 1);
187 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error running compute shader!");
188 
189 	gl.memoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
190 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting memory barrier!");
191 
192 	/* Get result data */
193 	glw::GLuint* result = (glw::GLuint*)gl.mapBufferRange(
194 		m_glExtTokens.TEXTURE_BUFFER, 0, m_n_texels_in_texture_buffer * sizeof(glw::GLuint), GL_MAP_READ_BIT);
195 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error mapping buffer object's data store to client address space!");
196 
197 	glw::GLuint expected_value = (m_n_texels_in_texture_buffer * (m_n_texels_in_texture_buffer - 1)) / 2;
198 
199 	for (glw::GLuint i = 0; i < m_n_texels_in_texture_buffer; ++i)
200 	{
201 		/* Log error if expected data and result data are not equal */
202 		if (result[i] != expected_value)
203 		{
204 			m_testCtx.getLog() << tcu::TestLog::Message << "Result is different than expected at index: " << i << "\n"
205 							   << "Expected value: " << expected_value << "\n"
206 							   << "Result   value: " << result[i] << "\n"
207 							   << tcu::TestLog::EndMessage;
208 
209 			test_result = false;
210 			break;
211 		}
212 	}
213 
214 	gl.unmapBuffer(m_glExtTokens.TEXTURE_BUFFER);
215 
216 	if (test_result)
217 	{
218 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
219 	}
220 	else
221 	{
222 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
223 	}
224 
225 	return STOP;
226 }
227 
228 /** Deinitializes GLES objects created during the test */
deinit(void)229 void TextureBufferAtomicFunctions::deinit(void)
230 {
231 	/* Get Gl entry points */
232 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
233 
234 	/* Reset GLES state */
235 	gl.useProgram(0);
236 	gl.bindBuffer(m_glExtTokens.TEXTURE_BUFFER, 0);
237 	gl.bindTexture(m_glExtTokens.TEXTURE_BUFFER, 0);
238 
239 	/* Delete GLES objects */
240 	if (0 != m_po_id)
241 	{
242 		gl.deleteProgram(m_po_id);
243 		m_po_id = 0;
244 	}
245 
246 	if (0 != m_cs_id)
247 	{
248 		gl.deleteShader(m_cs_id);
249 		m_cs_id = 0;
250 	}
251 
252 	if (0 != m_tbo_tex_id)
253 	{
254 		gl.deleteTextures(1, &m_tbo_tex_id);
255 		m_tbo_tex_id = 0;
256 	}
257 
258 	if (0 != m_tbo_id)
259 	{
260 		gl.deleteBuffers(1, &m_tbo_id);
261 		m_tbo_id = 0;
262 	}
263 
264 	/* Deinitialize base class */
265 	TestCaseBase::deinit();
266 }
267 
268 } // namespace glcts
269