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