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