es31fShaderAtomicOpTests.cpp revision 75be7fae1949a801c080530de53bdf123abb517a
13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*------------------------------------------------------------------------- 23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 3.1 Module 33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ------------------------------------------------- 43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project 63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License"); 83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License. 93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at 103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * http://www.apache.org/licenses/LICENSE-2.0 123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software 143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS, 153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and 173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License. 183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*! 203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file 213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Shader atomic operation tests. 223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/ 233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es31fShaderAtomicOpTests.hpp" 253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderProgram.hpp" 263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderUtil.hpp" 273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluRenderContext.hpp" 283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluObjectWrapper.hpp" 293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluProgramInterfaceQuery.hpp" 303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuVector.hpp" 313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp" 323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuVectorUtil.hpp" 333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuFormatUtil.hpp" 343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp" 353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp" 363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp" 373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp" 383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <algorithm> 403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <set> 413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 423c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp 433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 443c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles31 453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional 473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string; 503c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector; 513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestLog; 523c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::UVec3; 533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::set; 543c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace glu; 553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 563c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T, int Size> 573c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline T product (const tcu::Vector<T, Size>& v) 583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry T res = v[0]; 603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 1; ndx < Size; ndx++) 613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry res *= v[ndx]; 623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return res; 633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ShaderAtomicOpCase : public TestCase 663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ShaderAtomicOpCase (Context& context, const char* name, const char* funcName, AtomicOperandType operandType, DataType type, Precision precision, const UVec3& workGroupSize); 693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ~ShaderAtomicOpCase (void); 703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void init (void); 723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void deinit (void); 733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IterateResult iterate (void); 743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected: 763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry virtual void getInputs (int numValues, int stride, void* inputs) const = 0; 773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry virtual bool verify (int numValues, int inputStride, const void* inputs, int outputStride, const void* outputs, int groupStride, const void* groupOutputs) const = 0; 783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string m_funcName; 803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const AtomicOperandType m_operandType; 813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const DataType m_type; 823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Precision m_precision; 833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const UVec3 m_workGroupSize; 853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const UVec3 m_numWorkGroups; 863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 m_initialValue; 883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 893c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ShaderAtomicOpCase (const ShaderAtomicOpCase& other); 913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ShaderAtomicOpCase& operator= (const ShaderAtomicOpCase& other); 923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ShaderProgram* m_program; 943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 963c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderAtomicOpCase::ShaderAtomicOpCase (Context& context, const char* name, const char* funcName, AtomicOperandType operandType, DataType type, Precision precision, const UVec3& workGroupSize) 973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : TestCase (context, name, funcName) 983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_funcName (funcName) 993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_operandType (operandType) 1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_type (type) 1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_precision (precision) 1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_workGroupSize (workGroupSize) 1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_numWorkGroups (4,4,4) 1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_initialValue (0) 1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_program (DE_NULL) 1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1093c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderAtomicOpCase::~ShaderAtomicOpCase (void) 1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ShaderAtomicOpCase::deinit(); 1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderAtomicOpCase::init (void) 1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isSSBO = m_operandType == ATOMIC_OPERAND_BUFFER_VARIABLE; 1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const char* precName = getPrecisionName(m_precision); 1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const char* typeName = getDataTypeName(m_type); 11975be7fae1949a801c080530de53bdf123abb517aPyry Haulos 12075be7fae1949a801c080530de53bdf123abb517aPyry Haulos const DataType outType = isSSBO ? m_type : glu::TYPE_UINT; 12175be7fae1949a801c080530de53bdf123abb517aPyry Haulos const char* outTypeName = getDataTypeName(outType); 12275be7fae1949a801c080530de53bdf123abb517aPyry Haulos 1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 numValues = product(m_workGroupSize)*product(m_numWorkGroups); 1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::ostringstream src; 1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "#version 310 es\n" 1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "layout(local_size_x = " << m_workGroupSize.x() 1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << ", local_size_y = " << m_workGroupSize.y() 1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << ", local_size_z = " << m_workGroupSize.z() << ") in;\n" 1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "layout(binding = 0) buffer InOut\n" 1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "{\n" 1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " " << precName << " " << typeName << " inputValues[" << numValues << "];\n" 13375be7fae1949a801c080530de53bdf123abb517aPyry Haulos << " " << precName << " " << outTypeName << " outputValues[" << numValues << "];\n" 13475be7fae1949a801c080530de53bdf123abb517aPyry Haulos << " " << (isSSBO ? "coherent " : "") << precName << " " << outTypeName << " groupValues[" << product(m_numWorkGroups) << "];\n" 1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "} sb_inout;\n"; 1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!isSSBO) 1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "shared " << precName << " " << typeName << " s_var;\n"; 1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\n" 1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "void main (void)\n" 1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "{\n" 1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " uint localSize = gl_WorkGroupSize.x*gl_WorkGroupSize.y*gl_WorkGroupSize.z;\n" 1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " uint globalNdx = gl_NumWorkGroups.x*gl_NumWorkGroups.y*gl_WorkGroupID.z + gl_NumWorkGroups.x*gl_WorkGroupID.y + gl_WorkGroupID.x;\n" 1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " uint globalOffs = localSize*globalNdx;\n" 1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " uint offset = globalOffs + gl_LocalInvocationIndex;\n" 1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\n"; 1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (isSSBO) 1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15175be7fae1949a801c080530de53bdf123abb517aPyry Haulos DE_ASSERT(outType == m_type); 1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << " sb_inout.outputValues[offset] = " << m_funcName << "(sb_inout.groupValues[globalNdx], sb_inout.inputValues[offset]);\n"; 1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15675be7fae1949a801c080530de53bdf123abb517aPyry Haulos const string castBeg = outType != m_type ? (string(outTypeName) + "(") : string(""); 15775be7fae1949a801c080530de53bdf123abb517aPyry Haulos const char* const castEnd = outType != m_type ? ")" : ""; 15875be7fae1949a801c080530de53bdf123abb517aPyry Haulos 1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << " if (gl_LocalInvocationIndex == 0u)\n" 1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " s_var = " << typeName << "(" << tcu::toHex(m_initialValue) << "u);\n" 1618852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry << " barrier();\n" 16275be7fae1949a801c080530de53bdf123abb517aPyry Haulos << " " << precName << " " << typeName << " res = " << m_funcName << "(s_var, sb_inout.inputValues[offset]);\n" 16375be7fae1949a801c080530de53bdf123abb517aPyry Haulos << " sb_inout.outputValues[offset] = " << castBeg << "res" << castEnd << ";\n" 1648852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry << " barrier();\n" 1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " if (gl_LocalInvocationIndex == 0u)\n" 16675be7fae1949a801c080530de53bdf123abb517aPyry Haulos << " sb_inout.groupValues[globalNdx] = " << castBeg << "s_var" << castEnd << ";\n"; 1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "}\n"; 1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(!m_program); 1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_program = new ShaderProgram(m_context.getRenderContext(), ProgramSources() << ComputeSource(src.str())); 1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << *m_program; 1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!m_program->isOk()) 1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry delete m_program; 1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_program = DE_NULL; 1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry throw tcu::TestError("Compile failed"); 1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderAtomicOpCase::deinit (void) 1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry delete m_program; 1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_program = DE_NULL; 1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1903c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderAtomicOpCase::IterateResult ShaderAtomicOpCase::iterate (void) 1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 program = m_program->getProgram(); 1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Buffer inoutBuffer (m_context.getRenderContext()); 1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 blockNdx = gl.getProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, "InOut"); 1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const InterfaceBlockInfo blockInfo = getProgramInterfaceBlockInfo(gl, program, GL_SHADER_STORAGE_BLOCK, blockNdx); 1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 inVarNdx = gl.getProgramResourceIndex(program, GL_BUFFER_VARIABLE, "InOut.inputValues[0]"); 1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const InterfaceVariableInfo inVarInfo = getProgramInterfaceVariableInfo(gl, program, GL_BUFFER_VARIABLE, inVarNdx); 1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 outVarNdx = gl.getProgramResourceIndex(program, GL_BUFFER_VARIABLE, "InOut.outputValues[0]"); 2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const InterfaceVariableInfo outVarInfo = getProgramInterfaceVariableInfo(gl, program, GL_BUFFER_VARIABLE, outVarNdx); 2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 groupVarNdx = gl.getProgramResourceIndex(program, GL_BUFFER_VARIABLE, "InOut.groupValues[0]"); 2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const InterfaceVariableInfo groupVarInfo = getProgramInterfaceVariableInfo(gl, program, GL_BUFFER_VARIABLE, groupVarNdx); 2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 numValues = product(m_workGroupSize)*product(m_numWorkGroups); 2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TCU_CHECK(inVarInfo.arraySize == numValues && 2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry outVarInfo.arraySize == numValues && 2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry groupVarInfo.arraySize == product(m_numWorkGroups)); 2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.useProgram(program); 2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup buffer. 2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<deUint8> bufData(blockInfo.dataSize); 2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::fill(bufData.begin(), bufData.end(), 0); 2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry getInputs((int)numValues, (int)inVarInfo.arrayStride, &bufData[0] + inVarInfo.offset); 2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_operandType == ATOMIC_OPERAND_BUFFER_VARIABLE) 2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (deUint32 valNdx = 0; valNdx < product(m_numWorkGroups); valNdx++) 2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *(deUint32*)(&bufData[0] + groupVarInfo.offset + groupVarInfo.arrayStride*valNdx) = m_initialValue; 2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, *inoutBuffer); 2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bufferData(GL_SHADER_STORAGE_BUFFER, blockInfo.dataSize, &bufData[0], GL_STATIC_READ); 2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, *inoutBuffer); 2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "Output buffer setup failed"); 2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.dispatchCompute(m_numWorkGroups.x(), m_numWorkGroups.y(), m_numWorkGroups.z()); 2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Read back and compare 2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const void* resPtr = gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, blockInfo.dataSize, GL_MAP_READ_BIT); 2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool isOk = true; 2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()"); 2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TCU_CHECK(resPtr); 2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry isOk = verify((int)numValues, 2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (int)inVarInfo.arrayStride, (const deUint8*)resPtr + inVarInfo.offset, 2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (int)outVarInfo.arrayStride, (const deUint8*)resPtr + outVarInfo.offset, 2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (int)groupVarInfo.arrayStride, (const deUint8*)resPtr + groupVarInfo.offset); 2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER); 2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer()"); 2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry isOk ? "Pass" : "Comparison failed"); 2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return STOP; 2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ShaderAtomicAddCase : public ShaderAtomicOpCase 2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ShaderAtomicAddCase (Context& context, const char* name, AtomicOperandType operandType, DataType type, Precision precision) 2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : ShaderAtomicOpCase(context, name, "atomicAdd", operandType, type, precision, UVec3(3,2,1)) 2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_initialValue = 1; 2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected: 2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputs (int numValues, int stride, void* inputs) const 2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName())); 2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int maxVal = m_precision == PRECISION_LOWP ? 2 : 32; 2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int minVal = 1; 2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \todo [2013-09-04 pyry] Negative values! 2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int valNdx = 0; valNdx < numValues; valNdx++) 2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *(int*)((deUint8*)inputs + stride*valNdx) = rnd.getInt(minVal, maxVal); 2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool verify (int numValues, int inputStride, const void* inputs, int outputStride, const void* outputs, int groupStride, const void* groupOutputs) const 2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int workGroupSize = (int)product(m_workGroupSize); 2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numWorkGroups = numValues/workGroupSize; 2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++) 2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int groupOffset = groupNdx*workGroupSize; 2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int groupOutput = *(const int*)((const deUint8*)groupOutputs + groupNdx*groupStride); 2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry set<int> outValues; 2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool maxFound = false; 2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int valueSum = (int)m_initialValue; 2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int localNdx = 0; localNdx < workGroupSize; localNdx++) 2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int inputValue = *(const int*)((const deUint8*)inputs + inputStride*(groupOffset+localNdx)); 2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry valueSum += inputValue; 2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (groupOutput != valueSum) 2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ": expected sum " << valueSum << ", got " << groupOutput << TestLog::EndMessage; 2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int localNdx = 0; localNdx < workGroupSize; localNdx++) 3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int inputValue = *(const int*)((const deUint8*)inputs + inputStride*(groupOffset+localNdx)); 3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int outputValue = *(const int*)((const deUint8*)outputs + outputStride*(groupOffset+localNdx)); 3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!de::inRange(outputValue, (int)m_initialValue, valueSum-inputValue)) 3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ", invocation " << localNdx 3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << ": expected value in range [" << m_initialValue << ", " << (valueSum-inputValue) 3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "], got " << outputValue 3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::EndMessage; 3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (outValues.find(outputValue) != outValues.end()) 3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ", invocation " << localNdx 3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << ": found duplicate value " << outputValue 3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::EndMessage; 3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry outValues.insert(outputValue); 3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (outputValue == valueSum-inputValue) 3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry maxFound = true; 3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!maxFound) 3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: could not find maximum expected value from group " << groupNdx << TestLog::EndMessage; 3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (outValues.find((int)m_initialValue) == outValues.end()) 3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: could not find initial value from group " << groupNdx << TestLog::EndMessage; 3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ShaderAtomicMinCase : public ShaderAtomicOpCase 3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ShaderAtomicMinCase (Context& context, const char* name, AtomicOperandType operandType, DataType type, Precision precision) 3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : ShaderAtomicOpCase(context, name, "atomicMin", operandType, type, precision, UVec3(3,2,1)) 3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_initialValue = m_precision == PRECISION_LOWP ? 100 : 1000; 3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected: 3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputs (int numValues, int stride, void* inputs) const 3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName())); 3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isSigned = m_type == TYPE_INT; 3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int maxVal = m_precision == PRECISION_LOWP ? 100 : 1000; 3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int minVal = isSigned ? -maxVal : 0; 3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int valNdx = 0; valNdx < numValues; valNdx++) 3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *(int*)((deUint8*)inputs + stride*valNdx) = rnd.getInt(minVal, maxVal); 3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool verify (int numValues, int inputStride, const void* inputs, int outputStride, const void* outputs, int groupStride, const void* groupOutputs) const 3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int workGroupSize = (int)product(m_workGroupSize); 3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numWorkGroups = numValues/workGroupSize; 3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++) 3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int groupOffset = groupNdx*workGroupSize; 3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int groupOutput = *(const int*)((const deUint8*)groupOutputs + groupNdx*groupStride); 3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry set<int> inValues; 3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry set<int> outValues; 3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int minValue = (int)m_initialValue; 3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int localNdx = 0; localNdx < workGroupSize; localNdx++) 3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int inputValue = *(const int*)((const deUint8*)inputs + inputStride*(groupOffset+localNdx)); 3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry inValues.insert(inputValue); 3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry minValue = de::min(inputValue, minValue); 3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (minValue != groupOutput) 3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ": expected minimum " << minValue << ", got " << groupOutput << TestLog::EndMessage; 3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int localNdx = 0; localNdx < workGroupSize; localNdx++) 3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int outputValue = *(const int*)((const deUint8*)outputs + outputStride*(groupOffset+localNdx)); 3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (inValues.find(outputValue) == inValues.end() && outputValue != (int)m_initialValue) 3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ", invocation " << localNdx 4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << ": found unexpected value " << outputValue 4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::EndMessage; 4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry outValues.insert(outputValue); 4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (outValues.find((int)m_initialValue) == outValues.end()) 4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: could not find initial value from group " << groupNdx << TestLog::EndMessage; 4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ShaderAtomicMaxCase : public ShaderAtomicOpCase 4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ShaderAtomicMaxCase (Context& context, const char* name, AtomicOperandType operandType, DataType type, Precision precision) 4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : ShaderAtomicOpCase(context, name, "atomicMax", operandType, type, precision, UVec3(3,2,1)) 4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isSigned = m_type == TYPE_INT; 4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_initialValue = isSigned ? (m_precision == PRECISION_LOWP ? -100 : -1000) : 0; 4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected: 4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputs (int numValues, int stride, void* inputs) const 4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName())); 4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isSigned = m_type == TYPE_INT; 4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int maxVal = m_precision == PRECISION_LOWP ? 100 : 1000; 4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int minVal = isSigned ? -maxVal : 0; 4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int valNdx = 0; valNdx < numValues; valNdx++) 4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *(int*)((deUint8*)inputs + stride*valNdx) = rnd.getInt(minVal, maxVal); 4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool verify (int numValues, int inputStride, const void* inputs, int outputStride, const void* outputs, int groupStride, const void* groupOutputs) const 4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int workGroupSize = (int)product(m_workGroupSize); 4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numWorkGroups = numValues/workGroupSize; 4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++) 4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int groupOffset = groupNdx*workGroupSize; 4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int groupOutput = *(const int*)((const deUint8*)groupOutputs + groupNdx*groupStride); 4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry set<int> inValues; 4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry set<int> outValues; 4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int maxValue = (int)m_initialValue; 4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int localNdx = 0; localNdx < workGroupSize; localNdx++) 4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int inputValue = *(const int*)((const deUint8*)inputs + inputStride*(groupOffset+localNdx)); 4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry inValues.insert(inputValue); 4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry maxValue = de::max(maxValue, inputValue); 4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (maxValue != groupOutput) 4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ": expected maximum " << maxValue << ", got " << groupOutput << TestLog::EndMessage; 4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int localNdx = 0; localNdx < workGroupSize; localNdx++) 4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int outputValue = *(const int*)((const deUint8*)outputs + outputStride*(groupOffset+localNdx)); 4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (inValues.find(outputValue) == inValues.end() && outputValue != (int)m_initialValue) 4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ", invocation " << localNdx 4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << ": found unexpected value " << outputValue 4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::EndMessage; 4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry outValues.insert(outputValue); 4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (outValues.find((int)m_initialValue) == outValues.end()) 4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: could not find initial value from group " << groupNdx << TestLog::EndMessage; 4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ShaderAtomicAndCase : public ShaderAtomicOpCase 4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ShaderAtomicAndCase (Context& context, const char* name, AtomicOperandType operandType, DataType type, Precision precision) 4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : ShaderAtomicOpCase(context, name, "atomicAnd", operandType, type, precision, UVec3(3,2,1)) 4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numBits = m_precision == PRECISION_HIGHP ? 32 : 5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_precision == PRECISION_MEDIUMP ? 16 : 8; 5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 valueMask = numBits == 32 ? ~0u : (1u<<numBits)-1u; 5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_initialValue = ~((1u<<(numBits-1u)) | 1u) & valueMask; // All bits except lowest and highest set. 5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected: 5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputs (int numValues, int stride, void* inputs) const 5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName())); 5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int workGroupSize = (int)product(m_workGroupSize); 5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numWorkGroups = numValues/workGroupSize; 5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numBits = m_precision == PRECISION_HIGHP ? 32 : 5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_precision == PRECISION_MEDIUMP ? 16 : 8; 5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 valueMask = numBits == 32 ? ~0u : (1u<<numBits)-1u; 5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++) 5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int groupOffset = groupNdx*workGroupSize; 5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 groupMask = 1<<rnd.getInt(0, numBits-2); // One bit is always set. 5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int localNdx = 0; localNdx < workGroupSize; localNdx++) 5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *(deUint32*)((deUint8*)inputs + stride*(groupOffset+localNdx)) = (rnd.getUint32() & valueMask) | groupMask; 5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool verify (int numValues, int inputStride, const void* inputs, int outputStride, const void* outputs, int groupStride, const void* groupOutputs) const 5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int workGroupSize = (int)product(m_workGroupSize); 5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numWorkGroups = numValues/workGroupSize; 5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++) 5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int groupOffset = groupNdx*workGroupSize; 5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 groupOutput = *(const deUint32*)((const deUint8*)groupOutputs + groupNdx*groupStride); 5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 expectedValue = m_initialValue; 5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int localNdx = 0; localNdx < workGroupSize; localNdx++) 5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 inputValue = *(const deUint32*)((const deUint8*)inputs + inputStride*(groupOffset+localNdx)); 5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry expectedValue &= inputValue; 5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (expectedValue != groupOutput) 5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ": expected " << tcu::toHex(expectedValue) << ", got " << tcu::toHex(groupOutput) << TestLog::EndMessage; 5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int localNdx = 0; localNdx < workGroupSize; localNdx++) 5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 outputValue = *(const deUint32*)((const deUint8*)outputs + outputStride*(groupOffset+localNdx)); 5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if ((outputValue & ~m_initialValue) != 0) 5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ", invocation " << localNdx 5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << ": found unexpected value " << tcu::toHex(outputValue) 5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::EndMessage; 5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ShaderAtomicOrCase : public ShaderAtomicOpCase 5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ShaderAtomicOrCase (Context& context, const char* name, AtomicOperandType operandType, DataType type, Precision precision) 5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : ShaderAtomicOpCase(context, name, "atomicOr", operandType, type, precision, UVec3(3,2,1)) 5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_initialValue = 1u; // Lowest bit set. 5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected: 5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputs (int numValues, int stride, void* inputs) const 5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName())); 5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int workGroupSize = (int)product(m_workGroupSize); 5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numWorkGroups = numValues/workGroupSize; 5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numBits = m_precision == PRECISION_HIGHP ? 32 : 5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_precision == PRECISION_MEDIUMP ? 16 : 8; 5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++) 5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int groupOffset = groupNdx*workGroupSize; 5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int localNdx = 0; localNdx < workGroupSize; localNdx++) 5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *(deUint32*)((deUint8*)inputs + stride*(groupOffset+localNdx)) = 1u<<rnd.getInt(0, numBits-1); 5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool verify (int numValues, int inputStride, const void* inputs, int outputStride, const void* outputs, int groupStride, const void* groupOutputs) const 5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int workGroupSize = (int)product(m_workGroupSize); 5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numWorkGroups = numValues/workGroupSize; 5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++) 5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int groupOffset = groupNdx*workGroupSize; 6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 groupOutput = *(const deUint32*)((const deUint8*)groupOutputs + groupNdx*groupStride); 6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 expectedValue = m_initialValue; 6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int localNdx = 0; localNdx < workGroupSize; localNdx++) 6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 inputValue = *(const deUint32*)((const deUint8*)inputs + inputStride*(groupOffset+localNdx)); 6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry expectedValue |= inputValue; 6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (expectedValue != groupOutput) 6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ": expected " << tcu::toHex(expectedValue) << ", got " << tcu::toHex(groupOutput) << TestLog::EndMessage; 6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int localNdx = 0; localNdx < workGroupSize; localNdx++) 6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 outputValue = *(const deUint32*)((const deUint8*)outputs + outputStride*(groupOffset+localNdx)); 6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if ((outputValue & m_initialValue) == 0) 6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ", invocation " << localNdx 6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << ": found unexpected value " << tcu::toHex(outputValue) 6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::EndMessage; 6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ShaderAtomicXorCase : public ShaderAtomicOpCase 6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ShaderAtomicXorCase (Context& context, const char* name, AtomicOperandType operandType, DataType type, Precision precision) 6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : ShaderAtomicOpCase(context, name, "atomicXor", operandType, type, precision, UVec3(3,2,1)) 6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_initialValue = 0; 6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected: 6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputs (int numValues, int stride, void* inputs) const 6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName())); 6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int workGroupSize = (int)product(m_workGroupSize); 6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numWorkGroups = numValues/workGroupSize; 6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++) 6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int groupOffset = groupNdx*workGroupSize; 6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // First uses random bit-pattern. 6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *(deUint32*)((deUint8*)inputs + stride*(groupOffset)) = rnd.getUint32(); 6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Rest have either all or no bits set. 6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int localNdx = 1; localNdx < workGroupSize; localNdx++) 6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *(deUint32*)((deUint8*)inputs + stride*(groupOffset+localNdx)) = rnd.getBool() ? ~0u : 0u; 6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool verify (int numValues, int inputStride, const void* inputs, int outputStride, const void* outputs, int groupStride, const void* groupOutputs) const 6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int workGroupSize = (int)product(m_workGroupSize); 6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numWorkGroups = numValues/workGroupSize; 6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numBits = m_precision == PRECISION_HIGHP ? 32 : 6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_precision == PRECISION_MEDIUMP ? 16 : 8; 6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 compareMask = numBits == 32 ? ~0u : (1u<<numBits)-1u; 6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++) 6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int groupOffset = groupNdx*workGroupSize; 6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 groupOutput = *(const deUint32*)((const deUint8*)groupOutputs + groupNdx*groupStride); 6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 randomValue = *(const int*)((const deUint8*)inputs + inputStride*groupOffset); 6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 expected0 = randomValue ^ 0u; 6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 expected1 = randomValue ^ ~0u; 6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int numXorZeros = (m_initialValue == 0) ? 1 : 0; 6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int localNdx = 1; localNdx < workGroupSize; localNdx++) 6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 inputValue = *(const deUint32*)((const deUint8*)inputs + inputStride*(groupOffset+localNdx)); 6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (inputValue == 0) 6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry numXorZeros += 1; 6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 expected = (numXorZeros%2 == 0) ? expected0 : expected1; 6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if ((groupOutput & compareMask) != (expected & compareMask)) 6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ": expected " << tcu::toHex(expected0) 6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " or " << tcu::toHex(expected1) << " (compare mask " << tcu::toHex(compareMask) 6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "), got " << tcu::toHex(groupOutput) << TestLog::EndMessage; 6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int localNdx = 0; localNdx < workGroupSize; localNdx++) 6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 outputValue = *(const deUint32*)((const deUint8*)outputs + outputStride*(groupOffset+localNdx)); 7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if ((outputValue&compareMask) != 0 && 7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (outputValue&compareMask) != compareMask && 7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (outputValue&compareMask) != (expected0&compareMask) && 7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (outputValue&compareMask) != (expected1&compareMask)) 7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ", invocation " << localNdx 7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << ": found unexpected value " << tcu::toHex(outputValue) 7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::EndMessage; 7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ShaderAtomicExchangeCase : public ShaderAtomicOpCase 7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ShaderAtomicExchangeCase (Context& context, const char* name, AtomicOperandType operandType, DataType type, Precision precision) 7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : ShaderAtomicOpCase(context, name, "atomicExchange", operandType, type, precision, UVec3(3,2,1)) 7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_initialValue = 0; 7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected: 7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputs (int numValues, int stride, void* inputs) const 7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int workGroupSize = (int)product(m_workGroupSize); 7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numWorkGroups = numValues/workGroupSize; 7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++) 7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int groupOffset = groupNdx*workGroupSize; 7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int localNdx = 0; localNdx < workGroupSize; localNdx++) 7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *(int*)((deUint8*)inputs + stride*(groupOffset+localNdx)) = localNdx+1; 7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool verify (int numValues, int inputStride, const void* inputs, int outputStride, const void* outputs, int groupStride, const void* groupOutputs) const 7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int workGroupSize = (int)product(m_workGroupSize); 7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numWorkGroups = numValues/workGroupSize; 7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_UNREF(inputStride && inputs); 7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++) 7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int groupOffset = groupNdx*workGroupSize; 7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int groupOutput = *(const int*)((const deUint8*)groupOutputs + groupNdx*groupStride); 7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry set<int> usedValues; 7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int localNdx = 0; localNdx < workGroupSize; localNdx++) 7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int outputValue = *(const int*)((const deUint8*)outputs + outputStride*(groupOffset+localNdx)); 7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!de::inRange(outputValue, 0, workGroupSize) || usedValues.find(outputValue) != usedValues.end()) 7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ", invocation " << localNdx 7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << ": found unexpected value " << outputValue 7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::EndMessage; 7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry usedValues.insert(outputValue); 7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!de::inRange(groupOutput, 0, workGroupSize) || usedValues.find(groupOutput) != usedValues.end()) 7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ": unexpected final value" << groupOutput << TestLog::EndMessage; 7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ShaderAtomicCompSwapCase : public TestCase 7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ShaderAtomicCompSwapCase (Context& context, const char* name, AtomicOperandType operandType, DataType type, Precision precision); 7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ~ShaderAtomicCompSwapCase (void); 7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void init (void); 7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void deinit (void); 7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IterateResult iterate (void); 7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected: 7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ShaderAtomicCompSwapCase (const ShaderAtomicCompSwapCase& other); 7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ShaderAtomicCompSwapCase& operator= (const ShaderAtomicCompSwapCase& other); 7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const AtomicOperandType m_operandType; 7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const DataType m_type; 7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Precision m_precision; 7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const UVec3 m_workGroupSize; 8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const UVec3 m_numWorkGroups; 8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ShaderProgram* m_program; 8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8063c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderAtomicCompSwapCase::ShaderAtomicCompSwapCase (Context& context, const char* name, AtomicOperandType operandType, DataType type, Precision precision) 8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : TestCase (context, name, "atomicCompSwap() Test") 8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_operandType (operandType) 8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_type (type) 8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_precision (precision) 8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_workGroupSize (3,2,1) 8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_numWorkGroups (4,4,4) 8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_program (DE_NULL) 8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8173c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderAtomicCompSwapCase::~ShaderAtomicCompSwapCase (void) 8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ShaderAtomicCompSwapCase::deinit(); 8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderAtomicCompSwapCase::init (void) 8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isSSBO = m_operandType == ATOMIC_OPERAND_BUFFER_VARIABLE; 8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const char* precName = getPrecisionName(m_precision); 8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const char* typeName = getDataTypeName(m_type); 8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 numValues = product(m_workGroupSize)*product(m_numWorkGroups); 8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::ostringstream src; 8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "#version 310 es\n" 8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "layout(local_size_x = " << m_workGroupSize.x() 8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << ", local_size_y = " << m_workGroupSize.y() 8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << ", local_size_z = " << m_workGroupSize.z() << ") in;\n" 8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "layout(binding = 0) buffer InOut\n" 8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "{\n" 8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " " << precName << " " << typeName << " compareValues[" << numValues << "];\n" 8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " " << precName << " " << typeName << " exchangeValues[" << numValues << "];\n" 8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " " << precName << " " << typeName << " outputValues[" << numValues << "];\n" 8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " " << (isSSBO ? "coherent " : "") << precName << " " << typeName << " groupValues[" << product(m_numWorkGroups) << "];\n" 8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "} sb_inout;\n"; 8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!isSSBO) 8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "shared " << precName << " " << typeName << " s_var;\n"; 8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "\n" 8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "void main (void)\n" 8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "{\n" 8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " uint localSize = gl_WorkGroupSize.x*gl_WorkGroupSize.y*gl_WorkGroupSize.z;\n" 8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " uint globalNdx = gl_NumWorkGroups.x*gl_NumWorkGroups.y*gl_WorkGroupID.z + gl_NumWorkGroups.x*gl_WorkGroupID.y + gl_WorkGroupID.x;\n" 8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " uint globalOffs = localSize*globalNdx;\n" 8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " uint offset = globalOffs + gl_LocalInvocationIndex;\n" 8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\n"; 8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!isSSBO) 8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << " if (gl_LocalInvocationIndex == 0u)\n" 8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " s_var = " << typeName << "(" << 0 << ");\n" 8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\n"; 8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << " " << precName << " " << typeName << " compare = sb_inout.compareValues[offset];\n" 8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " " << precName << " " << typeName << " exchange = sb_inout.exchangeValues[offset];\n" 8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " " << precName << " " << typeName << " result;\n" 8648852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry << " bool swapDone = false;\n" 8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\n" 8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " for (uint ndx = 0u; ndx < localSize; ndx++)\n" 8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " {\n" 8688852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry << " barrier();\n" 8698852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry << " if (!swapDone)\n" 8708852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry << " {\n" 8718852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry << " result = atomicCompSwap(" << (isSSBO ? "sb_inout.groupValues[globalNdx]" : "s_var") << ", compare, exchange);\n" 8728852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry << " if (result == compare)\n" 8738852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry << " swapDone = true;\n" 8748852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry << " }\n" 8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " }\n" 8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "\n" 8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " sb_inout.outputValues[offset] = result;\n"; 8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!isSSBO) 8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8818852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry src << " barrier();\n" 8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " if (gl_LocalInvocationIndex == 0u)\n" 8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << " sb_inout.groupValues[globalNdx] = s_var;\n"; 8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry src << "}\n"; 8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(!m_program); 8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_program = new ShaderProgram(m_context.getRenderContext(), ProgramSources() << ComputeSource(src.str())); 8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << *m_program; 8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!m_program->isOk()) 8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry delete m_program; 8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_program = DE_NULL; 8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry throw tcu::TestError("Compile failed"); 8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderAtomicCompSwapCase::deinit (void) 9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry delete m_program; 9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_program = DE_NULL; 9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9073c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderAtomicOpCase::IterateResult ShaderAtomicCompSwapCase::iterate (void) 9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 program = m_program->getProgram(); 9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Buffer inoutBuffer (m_context.getRenderContext()); 9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 blockNdx = gl.getProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, "InOut"); 9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const InterfaceBlockInfo blockInfo = getProgramInterfaceBlockInfo(gl, program, GL_SHADER_STORAGE_BLOCK, blockNdx); 9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 cmpVarNdx = gl.getProgramResourceIndex(program, GL_BUFFER_VARIABLE, "InOut.compareValues[0]"); 9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const InterfaceVariableInfo cmpVarInfo = getProgramInterfaceVariableInfo(gl, program, GL_BUFFER_VARIABLE, cmpVarNdx); 9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 exhVarNdx = gl.getProgramResourceIndex(program, GL_BUFFER_VARIABLE, "InOut.exchangeValues[0]"); 9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const InterfaceVariableInfo exhVarInfo = getProgramInterfaceVariableInfo(gl, program, GL_BUFFER_VARIABLE, exhVarNdx); 9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 outVarNdx = gl.getProgramResourceIndex(program, GL_BUFFER_VARIABLE, "InOut.outputValues[0]"); 9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const InterfaceVariableInfo outVarInfo = getProgramInterfaceVariableInfo(gl, program, GL_BUFFER_VARIABLE, outVarNdx); 9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 groupVarNdx = gl.getProgramResourceIndex(program, GL_BUFFER_VARIABLE, "InOut.groupValues[0]"); 9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const InterfaceVariableInfo groupVarInfo = getProgramInterfaceVariableInfo(gl, program, GL_BUFFER_VARIABLE, groupVarNdx); 9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 numValues = product(m_workGroupSize)*product(m_numWorkGroups); 9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TCU_CHECK(cmpVarInfo.arraySize == numValues && 9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry exhVarInfo.arraySize == numValues && 9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry outVarInfo.arraySize == numValues && 9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry groupVarInfo.arraySize == product(m_numWorkGroups)); 9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.useProgram(program); 9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \todo [2013-09-05 pyry] Use randomized input values! 9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Setup buffer. 9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 workGroupSize = product(m_workGroupSize); 9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<deUint8> bufData (blockInfo.dataSize); 9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::fill(bufData.begin(), bufData.end(), 0); 9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (deUint32 ndx = 0; ndx < numValues; ndx++) 9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *(deUint32*)(&bufData[0] + cmpVarInfo.offset + cmpVarInfo.arrayStride*ndx) = ndx%workGroupSize; 9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (deUint32 ndx = 0; ndx < numValues; ndx++) 9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *(deUint32*)(&bufData[0] + exhVarInfo.offset + exhVarInfo.arrayStride*ndx) = (ndx%workGroupSize)+1; 9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, *inoutBuffer); 9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bufferData(GL_SHADER_STORAGE_BUFFER, blockInfo.dataSize, &bufData[0], GL_STATIC_READ); 9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, *inoutBuffer); 9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "Output buffer setup failed"); 9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.dispatchCompute(m_numWorkGroups.x(), m_numWorkGroups.y(), m_numWorkGroups.z()); 9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Read back and compare 9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const void* resPtr = gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, blockInfo.dataSize, GL_MAP_READ_BIT); 9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numWorkGroups = (int)product(m_numWorkGroups); 9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int workGroupSize = (int)product(m_workGroupSize); 9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool isOk = true; 9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()"); 9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TCU_CHECK(resPtr); 9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int groupNdx = 0; groupNdx < numWorkGroups; groupNdx++) 9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int groupOffset = groupNdx*workGroupSize; 9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int groupOutput = *(const int*)((const deUint8*)resPtr + groupVarInfo.offset + groupNdx*groupVarInfo.arrayStride); 9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int localNdx = 0; localNdx < workGroupSize; localNdx++) 9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int refValue = localNdx; 9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int outputValue = *(const int*)((const deUint8*)resPtr + outVarInfo.offset + outVarInfo.arrayStride*(groupOffset+localNdx)); 9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (outputValue != refValue) 9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ", invocation " << localNdx 9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << ": expected " << refValue << ", got " << outputValue 9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::EndMessage; 9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry isOk = false; 9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (groupOutput != workGroupSize) 9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: at group " << groupNdx << ": expected" << workGroupSize << ", got " << groupOutput << TestLog::EndMessage; 9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry isOk = false; 9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER); 9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer()"); 9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry isOk ? "Pass" : "Comparison failed"); 9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return STOP; 10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10023c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderAtomicOpTests::ShaderAtomicOpTests (Context& context, const char* name, AtomicOperandType operandType) 10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : TestCaseGroup (context, name, "Atomic Operation Tests") 10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_operandType (operandType) 10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10083c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderAtomicOpTests::~ShaderAtomicOpTests (void) 10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T> 10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic tcu::TestCaseGroup* createAtomicOpGroup (Context& context, AtomicOperandType operandType, const char* groupName) 10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::TestCaseGroup *const group = new tcu::TestCaseGroup(context.getTestContext(), groupName, (string("Atomic ") + groupName).c_str()); 10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry try 10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int precNdx = 0; precNdx < PRECISION_LAST; precNdx++) 10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int typeNdx = 0; typeNdx < 2; typeNdx++) 10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Precision precision = Precision(precNdx); 10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const DataType type = typeNdx > 0 ? TYPE_INT : TYPE_UINT; 10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const string caseName = string(getPrecisionName(precision)) + "_" + getDataTypeName(type); 10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry group->addChild(new T(context, caseName.c_str(), operandType, type, precision)); 10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return group; 10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry catch (...) 10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry delete group; 10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry throw; 10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderAtomicOpTests::init (void) 10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addChild(createAtomicOpGroup<ShaderAtomicAddCase> (m_context, m_operandType, "add")); 10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addChild(createAtomicOpGroup<ShaderAtomicMinCase> (m_context, m_operandType, "min")); 10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addChild(createAtomicOpGroup<ShaderAtomicMaxCase> (m_context, m_operandType, "max")); 10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addChild(createAtomicOpGroup<ShaderAtomicAndCase> (m_context, m_operandType, "and")); 10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addChild(createAtomicOpGroup<ShaderAtomicOrCase> (m_context, m_operandType, "or")); 10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addChild(createAtomicOpGroup<ShaderAtomicXorCase> (m_context, m_operandType, "xor")); 10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addChild(createAtomicOpGroup<ShaderAtomicExchangeCase> (m_context, m_operandType, "exchange")); 10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addChild(createAtomicOpGroup<ShaderAtomicCompSwapCase> (m_context, m_operandType, "compswap")); 10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional 10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles31 10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp 1054