1 #ifndef _GL4CSHADERATOMICCOUNTEROPSTESTS_HPP
2 #define _GL4CSHADERATOMICCOUNTEROPSTESTS_HPP
3 /*-------------------------------------------------------------------------
4  * OpenGL Conformance Test Suite
5  * -----------------------------
6  *
7  * Copyright (c) 2017 The Khronos Group Inc.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */ /*!
22  * \file  gl4cShaderAtomicCounterOpsTests.hpp
23  * \brief Conformance tests for the ARB_shader_atomic_counter_ops functionality.
24  */ /*-------------------------------------------------------------------*/
25 
26 #include "deUniquePtr.hpp"
27 #include "glcTestCase.hpp"
28 #include "gluShaderProgram.hpp"
29 
30 #include <algorithm>
31 #include <map>
32 #include <string>
33 
34 namespace gl4cts
35 {
36 
37 class ShaderAtomicCounterOpsTestBase : public deqp::TestCase
38 {
39 public:
40 	class AtomicOperation
41 	{
42 	private:
43 		std::string m_function;
44 		glw::GLuint m_inputValue;
45 		glw::GLuint m_paramValue;
46 		glw::GLuint m_compareValue;
47 		bool		m_testReturnValue;
48 
49 	protected:
50 		virtual glw::GLuint iterate(glw::GLuint input, glw::GLuint param, glw::GLuint compare) const = 0;
51 
52 	public:
AtomicOperation(std::string function,glw::GLuint inputValue,glw::GLuint paramValue,glw::GLuint compareValue=0,bool testReturnValue=false)53 		AtomicOperation(std::string function, glw::GLuint inputValue, glw::GLuint paramValue,
54 						glw::GLuint compareValue = 0, bool testReturnValue = false)
55 			: m_function(function)
56 			, m_inputValue(inputValue)
57 			, m_paramValue(paramValue)
58 			, m_compareValue(compareValue)
59 			, m_testReturnValue(testReturnValue)
60 		{
61 		}
62 
~AtomicOperation()63 		virtual ~AtomicOperation()
64 		{
65 		}
66 
getResult(unsigned int iterations) const67 		glw::GLuint getResult(unsigned int iterations) const
68 		{
69 			glw::GLuint result = m_inputValue;
70 			for (unsigned int i = 0; i < iterations; ++i)
71 			{
72 				result = iterate(result, m_paramValue, m_compareValue);
73 			}
74 			return result;
75 		}
76 
getFunction() const77 		inline std::string getFunction() const
78 		{
79 			return m_function;
80 		}
getInputValue() const81 		inline glw::GLuint getInputValue() const
82 		{
83 			return m_inputValue;
84 		}
getParamValue() const85 		inline glw::GLuint getParamValue() const
86 		{
87 			return m_paramValue;
88 		}
getCompareValue() const89 		inline glw::GLuint getCompareValue() const
90 		{
91 			return m_compareValue;
92 		}
shouldTestReturnValue() const93 		inline bool shouldTestReturnValue() const
94 		{
95 			return m_testReturnValue;
96 		}
97 	};
98 
99 	class AtomicOperationAdd : public AtomicOperation
100 	{
101 	private:
iterate(glw::GLuint input,glw::GLuint param,glw::GLuint compare) const102 		glw::GLuint iterate(glw::GLuint input, glw::GLuint param, glw::GLuint compare) const
103 		{
104 			DE_UNREF(compare);
105 			return input + param;
106 		}
107 
108 	public:
AtomicOperationAdd(glw::GLuint inputValue,glw::GLuint paramValue)109 		AtomicOperationAdd(glw::GLuint inputValue, glw::GLuint paramValue)
110 			: AtomicOperation("atomicCounterAdd", inputValue, paramValue, 0U, true)
111 		{
112 		}
113 	};
114 
115 	class AtomicOperationSubtract : public AtomicOperation
116 	{
117 	private:
iterate(glw::GLuint input,glw::GLuint param,glw::GLuint compare) const118 		glw::GLuint iterate(glw::GLuint input, glw::GLuint param, glw::GLuint compare) const
119 		{
120 			DE_UNREF(compare);
121 			return input - param;
122 		}
123 
124 	public:
AtomicOperationSubtract(glw::GLuint inputValue,glw::GLuint paramValue)125 		AtomicOperationSubtract(glw::GLuint inputValue, glw::GLuint paramValue)
126 			: AtomicOperation("atomicCounterSubtract", inputValue, paramValue, 0U, true)
127 		{
128 		}
129 	};
130 
131 	class AtomicOperationMin : public AtomicOperation
132 	{
133 	private:
iterate(glw::GLuint input,glw::GLuint param,glw::GLuint compare) const134 		glw::GLuint iterate(glw::GLuint input, glw::GLuint param, glw::GLuint compare) const
135 		{
136 			DE_UNREF(compare);
137 			return std::min(input, param);
138 		}
139 
140 	public:
AtomicOperationMin(glw::GLuint inputValue,glw::GLuint paramValue)141 		AtomicOperationMin(glw::GLuint inputValue, glw::GLuint paramValue)
142 			: AtomicOperation("atomicCounterMin", inputValue, paramValue)
143 		{
144 		}
145 	};
146 
147 	class AtomicOperationMax : public AtomicOperation
148 	{
149 	private:
iterate(glw::GLuint input,glw::GLuint param,glw::GLuint compare) const150 		glw::GLuint iterate(glw::GLuint input, glw::GLuint param, glw::GLuint compare) const
151 		{
152 			DE_UNREF(compare);
153 			return std::max(input, param);
154 		}
155 
156 	public:
AtomicOperationMax(glw::GLuint inputValue,glw::GLuint paramValue)157 		AtomicOperationMax(glw::GLuint inputValue, glw::GLuint paramValue)
158 			: AtomicOperation("atomicCounterMax", inputValue, paramValue)
159 		{
160 		}
161 	};
162 
163 	class AtomicOperationAnd : public AtomicOperation
164 	{
165 	private:
iterate(glw::GLuint input,glw::GLuint param,glw::GLuint compare) const166 		glw::GLuint iterate(glw::GLuint input, glw::GLuint param, glw::GLuint compare) const
167 		{
168 			DE_UNREF(compare);
169 			return input & param;
170 		}
171 
172 	public:
AtomicOperationAnd(glw::GLuint inputValue,glw::GLuint paramValue)173 		AtomicOperationAnd(glw::GLuint inputValue, glw::GLuint paramValue)
174 			: AtomicOperation("atomicCounterAnd", inputValue, paramValue)
175 		{
176 		}
177 	};
178 
179 	class AtomicOperationOr : public AtomicOperation
180 	{
181 	private:
iterate(glw::GLuint input,glw::GLuint param,glw::GLuint compare) const182 		glw::GLuint iterate(glw::GLuint input, glw::GLuint param, glw::GLuint compare) const
183 		{
184 			DE_UNREF(compare);
185 			return input | param;
186 		}
187 
188 	public:
AtomicOperationOr(glw::GLuint inputValue,glw::GLuint paramValue)189 		AtomicOperationOr(glw::GLuint inputValue, glw::GLuint paramValue)
190 			: AtomicOperation("atomicCounterOr", inputValue, paramValue)
191 		{
192 		}
193 	};
194 
195 	class AtomicOperationXor : public AtomicOperation
196 	{
197 	private:
iterate(glw::GLuint input,glw::GLuint param,glw::GLuint compare) const198 		glw::GLuint iterate(glw::GLuint input, glw::GLuint param, glw::GLuint compare) const
199 		{
200 			DE_UNREF(compare);
201 			return input ^ param;
202 		}
203 
204 	public:
AtomicOperationXor(glw::GLuint inputValue,glw::GLuint paramValue)205 		AtomicOperationXor(glw::GLuint inputValue, glw::GLuint paramValue)
206 			: AtomicOperation("atomicCounterXor", inputValue, paramValue)
207 		{
208 		}
209 	};
210 
211 	class AtomicOperationExchange : public AtomicOperation
212 	{
213 	private:
iterate(glw::GLuint input,glw::GLuint param,glw::GLuint compare) const214 		glw::GLuint iterate(glw::GLuint input, glw::GLuint param, glw::GLuint compare) const
215 		{
216 			DE_UNREF(input);
217 			DE_UNREF(compare);
218 			return param;
219 		}
220 
221 	public:
AtomicOperationExchange(glw::GLuint inputValue,glw::GLuint paramValue)222 		AtomicOperationExchange(glw::GLuint inputValue, glw::GLuint paramValue)
223 			: AtomicOperation("atomicCounterExchange", inputValue, paramValue)
224 		{
225 		}
226 	};
227 
228 	class AtomicOperationCompSwap : public AtomicOperation
229 	{
230 	private:
iterate(glw::GLuint input,glw::GLuint param,glw::GLuint compare) const231 		glw::GLuint iterate(glw::GLuint input, glw::GLuint param, glw::GLuint compare) const
232 		{
233 			return input == compare ? param : input;
234 		}
235 
236 	public:
AtomicOperationCompSwap(glw::GLuint inputValue,glw::GLuint paramValue,glw::GLuint compareValue)237 		AtomicOperationCompSwap(glw::GLuint inputValue, glw::GLuint paramValue, glw::GLuint compareValue)
238 			: AtomicOperation("atomicCounterCompSwap", inputValue, paramValue, compareValue)
239 		{
240 		}
241 	};
242 
243 	class ShaderPipeline
244 	{
245 	private:
246 		glu::ShaderProgram* m_program;
247 		glu::ShaderProgram* m_programCompute;
248 		glu::ShaderType		m_testedShader;
249 		AtomicOperation*	m_atomicOp;
250 
251 		std::string m_shaders[glu::SHADERTYPE_LAST];
252 
253 		void renderQuad(deqp::Context& context);
254 		void executeComputeShader(deqp::Context& context);
255 
256 	public:
257 		ShaderPipeline(glu::ShaderType testedShader, AtomicOperation* newOp, bool contextGL46);
258 		~ShaderPipeline();
259 
260 		void prepareShader(std::string& shader, const std::string& tag, const std::string& replace);
261 
262 		void create(deqp::Context& context);
263 		void use(deqp::Context& context);
264 
getShaderProgram() const265 		inline glu::ShaderProgram* getShaderProgram() const
266 		{
267 			return m_program;
268 		}
269 
getAtomicOperation() const270 		inline AtomicOperation* getAtomicOperation() const
271 		{
272 			return m_atomicOp;
273 		}
274 
275 		void test(deqp::Context& context);
276 	};
277 
278 private:
279 	/* Private methods*/
280 	void fillAtomicCounterBuffer(AtomicOperation* atomicOp);
281 	bool checkAtomicCounterBuffer(AtomicOperation* atomicOp);
282 
283 	void bindBuffers();
284 	bool validateColor(tcu::Vec4 testedColor, tcu::Vec4 desiredColor);
285 	bool validateScreenPixels(tcu::Vec4 desiredColor, tcu::Vec4 ignoredColor);
286 
287 protected:
288 	/* Protected members */
289 	glw::GLuint					  m_atomicCounterBuffer;
290 	glw::GLuint					  m_atomicCounterCallsBuffer;
291 	bool						  m_contextSupportsGL46;
292 	std::vector<AtomicOperation*> m_operations;
293 	std::vector<ShaderPipeline>   m_shaderPipelines;
294 
295 	/* Protected methods */
addOperation(AtomicOperation * newOp)296 	inline void addOperation(AtomicOperation* newOp)
297 	{
298 		for (unsigned int i = 0; i < glu::SHADERTYPE_LAST; ++i)
299 		{
300 			m_shaderPipelines.push_back(ShaderPipeline((glu::ShaderType)i, newOp, m_contextSupportsGL46));
301 		}
302 	}
303 
304 	virtual void setOperations() = 0;
305 
306 public:
307 	/* Public methods */
308 	ShaderAtomicCounterOpsTestBase(deqp::Context& context, const char* name, const char* description);
309 
310 	void init();
311 	void deinit();
312 
313 	tcu::TestNode::IterateResult iterate();
314 
315 	typedef std::vector<ShaderPipeline>::iterator   ShaderPipelineIter;
316 	typedef std::vector<AtomicOperation*>::iterator AtomicOperationIter;
317 };
318 
319 /** Test verifies new built-in addition and substraction atomic counter operations
320 **/
321 class ShaderAtomicCounterOpsAdditionSubstractionTestCase : public ShaderAtomicCounterOpsTestBase
322 {
323 private:
324 	/* Private methods */
325 	void setOperations();
326 
327 public:
328 	/* Public methods */
329 	ShaderAtomicCounterOpsAdditionSubstractionTestCase(deqp::Context& context);
330 };
331 
332 /** Test verifies new built-in minimum and maximum atomic counter operations
333 **/
334 class ShaderAtomicCounterOpsMinMaxTestCase : public ShaderAtomicCounterOpsTestBase
335 {
336 private:
337 	/* Private methods */
338 	void setOperations();
339 
340 public:
341 	/* Public methods */
342 	ShaderAtomicCounterOpsMinMaxTestCase(deqp::Context& context);
343 };
344 
345 /** Test verifies new built-in bitwise atomic counter operations
346 **/
347 class ShaderAtomicCounterOpsBitwiseTestCase : public ShaderAtomicCounterOpsTestBase
348 {
349 private:
350 	/* Private methods */
351 	void setOperations();
352 
353 public:
354 	/* Public methods */
355 	ShaderAtomicCounterOpsBitwiseTestCase(deqp::Context& context);
356 };
357 
358 /** Test verifies new built-in exchange and swap atomic counter operations
359 **/
360 class ShaderAtomicCounterOpsExchangeTestCase : public ShaderAtomicCounterOpsTestBase
361 {
362 private:
363 	/* Private methods */
364 	void setOperations();
365 
366 public:
367 	/* Public methods */
368 	ShaderAtomicCounterOpsExchangeTestCase(deqp::Context& context);
369 };
370 
371 /** Test group which encapsulates all ARB_shader_atomic_counter_ops conformance tests */
372 class ShaderAtomicCounterOps : public deqp::TestCaseGroup
373 {
374 public:
375 	/* Public methods */
376 	ShaderAtomicCounterOps(deqp::Context& context);
377 
378 	void init();
379 
380 private:
381 	ShaderAtomicCounterOps(const ShaderAtomicCounterOps& other);
382 	ShaderAtomicCounterOps& operator=(const ShaderAtomicCounterOps& other);
383 };
384 
385 } /* glcts namespace */
386 
387 #endif // _GL4CSHADERATOMICCOUNTEROPSTESTS_HPP
388